beplus-mcp 0.36.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 +7 -5
- package/dist/index.js +546 -86
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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);
|
|
@@ -24890,7 +24917,7 @@ function arrangeRows(doc, rows, origin, gap = DEFAULT_GAP, widths = DEFAULT_WIDT
|
|
|
24890
24917
|
for (let j = i + 1; j < placed.length; j++) if (overlap(placed[i], placed[j])) inner.push([placed[i].id, placed[j].id]);
|
|
24891
24918
|
}
|
|
24892
24919
|
const ids = new Set(placed.map((p) => p.id));
|
|
24893
|
-
const others = Object.values(doc.nodes).filter((n) => !ids.has(n.id) && kindOf(n) !== "section").map((n) => ({ id: n.id, x: n.position.x, y: n.position.y, ...usedSize(n) }));
|
|
24920
|
+
const others = Object.values(doc.nodes).filter((n) => !ids.has(n.id) && kindOf(n) !== "section" && (scope === void 0 || scope.has(n.id))).map((n) => ({ id: n.id, x: n.position.x, y: n.position.y, ...usedSize(n) }));
|
|
24894
24921
|
const outer = [];
|
|
24895
24922
|
for (const p of placed) for (const o of others) if (overlap(p, o)) outer.push([p.id, o.id]);
|
|
24896
24923
|
const left = Math.min(origin.x, ...placed.map((p) => p.x));
|
|
@@ -24900,6 +24927,322 @@ function arrangeRows(doc, rows, origin, gap = DEFAULT_GAP, widths = DEFAULT_WIDT
|
|
|
24900
24927
|
return { placed, inner, outer, freeOrigin };
|
|
24901
24928
|
}
|
|
24902
24929
|
|
|
24930
|
+
// src/canvas/tabs.ts
|
|
24931
|
+
var TAB_FIELD = "aba";
|
|
24932
|
+
var TAB_ID_FIELD = "abaId";
|
|
24933
|
+
var TAB_ORDER_FIELD = "abaOrdem";
|
|
24934
|
+
var TAB_NEAR = 2e3;
|
|
24935
|
+
var AVULSOS_TAB = "avulsos";
|
|
24936
|
+
var SECTION = "section";
|
|
24937
|
+
var isFiniteNumber2 = (v) => typeof v === "number" && Number.isFinite(v);
|
|
24938
|
+
function isArchived(node) {
|
|
24939
|
+
const flag = node?.data["archived"];
|
|
24940
|
+
return typeof flag === "object" && flag !== null;
|
|
24941
|
+
}
|
|
24942
|
+
function isSectionNode(node) {
|
|
24943
|
+
return node !== void 0 && node.data[KIND_FIELD] === SECTION;
|
|
24944
|
+
}
|
|
24945
|
+
function isTabSection(node) {
|
|
24946
|
+
return node !== void 0 && isSectionNode(node) && node.data[TAB_FIELD] === true && !isArchived(node);
|
|
24947
|
+
}
|
|
24948
|
+
var rectHas = (r, x, y) => x >= r.left && x <= r.right && y >= r.top && y <= r.bottom;
|
|
24949
|
+
function distanceTo(r, x, y) {
|
|
24950
|
+
const dx = Math.max(r.left - x, 0, x - r.right);
|
|
24951
|
+
const dy = Math.max(r.top - y, 0, y - r.bottom);
|
|
24952
|
+
return Math.hypot(dx, dy);
|
|
24953
|
+
}
|
|
24954
|
+
function boardPosition(doc, node) {
|
|
24955
|
+
let x = node.position.x;
|
|
24956
|
+
let y = node.position.y;
|
|
24957
|
+
const seen = /* @__PURE__ */ new Set([node.id]);
|
|
24958
|
+
let parent = node.parentId === null ? void 0 : doc.nodes[node.parentId];
|
|
24959
|
+
while (parent !== void 0 && !seen.has(parent.id)) {
|
|
24960
|
+
seen.add(parent.id);
|
|
24961
|
+
x += parent.position.x;
|
|
24962
|
+
y += parent.position.y;
|
|
24963
|
+
parent = parent.parentId === null ? void 0 : doc.nodes[parent.parentId];
|
|
24964
|
+
}
|
|
24965
|
+
return { x, y };
|
|
24966
|
+
}
|
|
24967
|
+
function sectionRect(doc, node) {
|
|
24968
|
+
const at = boardPosition(doc, node);
|
|
24969
|
+
return { left: at.x, top: at.y, right: at.x + node.size.w, bottom: at.y + node.size.h };
|
|
24970
|
+
}
|
|
24971
|
+
function savedMeasure(node) {
|
|
24972
|
+
const value = node.data[MEASURED_KEY];
|
|
24973
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
24974
|
+
const record2 = value;
|
|
24975
|
+
if (!isFiniteNumber2(record2["w"]) || !isFiniteNumber2(record2["h"])) return void 0;
|
|
24976
|
+
return { w: record2["w"], h: record2["h"] };
|
|
24977
|
+
}
|
|
24978
|
+
function drawnRect(doc, node) {
|
|
24979
|
+
const at = boardPosition(doc, node);
|
|
24980
|
+
const saved = savedMeasure(node);
|
|
24981
|
+
const w = Math.max(node.size.w, saved?.w ?? 0);
|
|
24982
|
+
const h = Math.max(node.size.h, saved?.h ?? 0);
|
|
24983
|
+
return { left: at.x, top: at.y, right: at.x + w, bottom: at.y + h };
|
|
24984
|
+
}
|
|
24985
|
+
function savedCenter(doc, node) {
|
|
24986
|
+
const at = boardPosition(doc, node);
|
|
24987
|
+
const saved = savedMeasure(node);
|
|
24988
|
+
const w = Math.max(node.size.w, saved?.w ?? 0);
|
|
24989
|
+
const h = Math.max(node.size.h, saved?.h ?? 0);
|
|
24990
|
+
return { x: at.x + w / 2, y: at.y + h / 2 };
|
|
24991
|
+
}
|
|
24992
|
+
function tabOrderOf(node) {
|
|
24993
|
+
const raw = node.data[TAB_ORDER_FIELD];
|
|
24994
|
+
return typeof raw === "number" && Number.isFinite(raw) ? raw : null;
|
|
24995
|
+
}
|
|
24996
|
+
function orderedTabSections(doc) {
|
|
24997
|
+
return Object.values(doc.nodes).filter((node) => isTabSection(node)).sort((a, b) => {
|
|
24998
|
+
const oa = tabOrderOf(a);
|
|
24999
|
+
const ob = tabOrderOf(b);
|
|
25000
|
+
if (oa !== null && ob === null) return -1;
|
|
25001
|
+
if (oa === null && ob !== null) return 1;
|
|
25002
|
+
if (oa !== null && ob !== null && oa !== ob) return oa - ob;
|
|
25003
|
+
return a.position.y - b.position.y || a.position.x - b.position.x;
|
|
25004
|
+
});
|
|
25005
|
+
}
|
|
25006
|
+
var partitions = /* @__PURE__ */ new WeakMap();
|
|
25007
|
+
function build(doc) {
|
|
25008
|
+
const tabs = orderedTabSections(doc).map((node) => ({
|
|
25009
|
+
id: node.id,
|
|
25010
|
+
...sectionRect(doc, node)
|
|
25011
|
+
}));
|
|
25012
|
+
const live = new Map(tabs.map((tab) => [tab.id, tab]));
|
|
25013
|
+
const home = /* @__PURE__ */ new Map();
|
|
25014
|
+
const walking = /* @__PURE__ */ new Set();
|
|
25015
|
+
const byPlace = (node) => {
|
|
25016
|
+
const center = savedCenter(doc, node);
|
|
25017
|
+
for (const tab of tabs) if (rectHas(tab, center.x, center.y)) return tab.id;
|
|
25018
|
+
let near = null;
|
|
25019
|
+
let best = TAB_NEAR;
|
|
25020
|
+
for (const tab of tabs) {
|
|
25021
|
+
const distance = distanceTo(tab, center.x, center.y);
|
|
25022
|
+
if (distance <= best && (near === null || distance < best)) {
|
|
25023
|
+
near = tab;
|
|
25024
|
+
best = distance;
|
|
25025
|
+
}
|
|
25026
|
+
}
|
|
25027
|
+
return near === null ? AVULSOS_TAB : near.id;
|
|
25028
|
+
};
|
|
25029
|
+
const resolve3 = (node) => {
|
|
25030
|
+
const known = home.get(node.id);
|
|
25031
|
+
if (known !== void 0) return known;
|
|
25032
|
+
let tab;
|
|
25033
|
+
const mark = node.data[TAB_ID_FIELD];
|
|
25034
|
+
if (live.has(node.id)) {
|
|
25035
|
+
tab = node.id;
|
|
25036
|
+
} else if (typeof mark === "string" && mark !== "") {
|
|
25037
|
+
tab = live.has(mark) ? mark : AVULSOS_TAB;
|
|
25038
|
+
} else if (node.parentId !== null && !walking.has(node.id)) {
|
|
25039
|
+
const parent = doc.nodes[node.parentId];
|
|
25040
|
+
if (parent === void 0) {
|
|
25041
|
+
tab = byPlace(node);
|
|
25042
|
+
} else {
|
|
25043
|
+
walking.add(node.id);
|
|
25044
|
+
tab = resolve3(parent);
|
|
25045
|
+
walking.delete(node.id);
|
|
25046
|
+
}
|
|
25047
|
+
} else {
|
|
25048
|
+
tab = byPlace(node);
|
|
25049
|
+
}
|
|
25050
|
+
home.set(node.id, tab);
|
|
25051
|
+
return tab;
|
|
25052
|
+
};
|
|
25053
|
+
const members = /* @__PURE__ */ new Map();
|
|
25054
|
+
for (const node of Object.values(doc.nodes)) {
|
|
25055
|
+
if (isArchived(node)) continue;
|
|
25056
|
+
const tab = resolve3(node);
|
|
25057
|
+
const list = members.get(tab);
|
|
25058
|
+
if (list === void 0) members.set(tab, [node.id]);
|
|
25059
|
+
else list.push(node.id);
|
|
25060
|
+
}
|
|
25061
|
+
return { tabs, home, members };
|
|
25062
|
+
}
|
|
25063
|
+
function partitionOf(doc) {
|
|
25064
|
+
let part = partitions.get(doc);
|
|
25065
|
+
if (part === void 0) {
|
|
25066
|
+
part = build(doc);
|
|
25067
|
+
partitions.set(doc, part);
|
|
25068
|
+
}
|
|
25069
|
+
return part;
|
|
25070
|
+
}
|
|
25071
|
+
|
|
25072
|
+
// src/canvas/tab-scope.ts
|
|
25073
|
+
var LOCK_FIELD = "travada";
|
|
25074
|
+
var TAB_END_GAP = 120;
|
|
25075
|
+
var TAB_GROW_PAD = 48;
|
|
25076
|
+
var TAB_TOP_ROOM = 96;
|
|
25077
|
+
var TAB_CLEAR_GAP = 48;
|
|
25078
|
+
var SHORT_ID = 8;
|
|
25079
|
+
var MIN_PREFIX = 4;
|
|
25080
|
+
var LISTED = 12;
|
|
25081
|
+
var oneLine = (text, max) => {
|
|
25082
|
+
const flat = text.replace(/\s+/g, " ").trim();
|
|
25083
|
+
return flat.length > max ? `${flat.slice(0, max - 1)}\u2026` : flat;
|
|
25084
|
+
};
|
|
25085
|
+
function tabTitle(node) {
|
|
25086
|
+
const title = typeof node.data.title === "string" ? node.data.title.trim() : "";
|
|
25087
|
+
const label = typeof node.data.label === "string" ? node.data.label.trim() : "";
|
|
25088
|
+
if (title !== "" && title !== "Se\xE7\xE3o") return title;
|
|
25089
|
+
return label || title || "Se\xE7\xE3o";
|
|
25090
|
+
}
|
|
25091
|
+
var isLockedTab = (node) => node !== void 0 && node.data[LOCK_FIELD] === true;
|
|
25092
|
+
function shortTabIds(ids) {
|
|
25093
|
+
const longest = Math.max(0, ...ids.map((id) => id.length));
|
|
25094
|
+
let length = SHORT_ID;
|
|
25095
|
+
while (length < longest && new Set(ids.map((id) => id.slice(0, length))).size < ids.length) length += 1;
|
|
25096
|
+
return new Map(ids.map((id) => [id, id.slice(0, length)]));
|
|
25097
|
+
}
|
|
25098
|
+
function tabIndex(doc) {
|
|
25099
|
+
const part = partitionOf(doc);
|
|
25100
|
+
const shorts = shortTabIds(part.tabs.map((tab) => tab.id));
|
|
25101
|
+
const tabs = part.tabs.map((tab) => {
|
|
25102
|
+
const node = doc.nodes[tab.id];
|
|
25103
|
+
return {
|
|
25104
|
+
id: tab.id,
|
|
25105
|
+
short: shorts.get(tab.id),
|
|
25106
|
+
title: tabTitle(node),
|
|
25107
|
+
locked: isLockedTab(node),
|
|
25108
|
+
cards: Math.max(0, (part.members.get(tab.id)?.length ?? 0) - 1)
|
|
25109
|
+
};
|
|
25110
|
+
});
|
|
25111
|
+
const byId = new Map(tabs.map((tab) => [tab.id, tab]));
|
|
25112
|
+
return {
|
|
25113
|
+
tabs,
|
|
25114
|
+
loose: part.members.get(AVULSOS_TAB)?.length ?? 0,
|
|
25115
|
+
label: (tab) => tab === AVULSOS_TAB ? AVULSOS_TAB : byId.get(tab)?.short ?? tab,
|
|
25116
|
+
info: (tab) => byId.get(tab)
|
|
25117
|
+
};
|
|
25118
|
+
}
|
|
25119
|
+
var hasTabs = (doc) => partitionOf(doc).tabs.length > 0;
|
|
25120
|
+
function homeTabOf(doc, nodeId3) {
|
|
25121
|
+
const part = partitionOf(doc);
|
|
25122
|
+
return part.tabs.length === 0 ? null : part.home.get(nodeId3) ?? null;
|
|
25123
|
+
}
|
|
25124
|
+
function membersOfTab(doc, tab) {
|
|
25125
|
+
return new Set(partitionOf(doc).members.get(tab) ?? []);
|
|
25126
|
+
}
|
|
25127
|
+
function tabList(doc) {
|
|
25128
|
+
const tabs = partitionOf(doc).tabs;
|
|
25129
|
+
if (tabs.length === 0) return "Este board n\xE3o tem abas (uma aba \xE9 uma se\xE7\xE3o com aba=true).";
|
|
25130
|
+
const shown = tabs.slice(0, LISTED).map((tab) => `"${oneLine(tabTitle(doc.nodes[tab.id]), 40)}" (${tab.id})`);
|
|
25131
|
+
const more = tabs.length > LISTED ? `, \u2026 e mais ${tabs.length - LISTED}` : "";
|
|
25132
|
+
return `Abas do board: ${shown.join(", ")}${more}.`;
|
|
25133
|
+
}
|
|
25134
|
+
function kindLabel(node) {
|
|
25135
|
+
const kind = node.data.kind;
|
|
25136
|
+
return typeof kind === "string" && kind ? kind : node.type;
|
|
25137
|
+
}
|
|
25138
|
+
function resolveTab(doc, ref, opts = {}) {
|
|
25139
|
+
const value = ref.trim();
|
|
25140
|
+
if (value === AVULSOS_TAB) {
|
|
25141
|
+
if (opts.allowAvulsos && hasTabs(doc)) return AVULSOS_TAB;
|
|
25142
|
+
throw new CanvasToolError(
|
|
25143
|
+
hasTabs(doc) ? '"avulsos" n\xE3o \xE9 uma aba: \xE9 onde ficam os cart\xF5es que n\xE3o moram em aba. Para criar sem aba, omita aba.' : `Aba "avulsos" n\xE3o existe. ${tabList(doc)}`
|
|
25144
|
+
);
|
|
25145
|
+
}
|
|
25146
|
+
if (Object.hasOwn(doc.nodes, value)) {
|
|
25147
|
+
const node = doc.nodes[value];
|
|
25148
|
+
if (isTabSection(node)) return node.id;
|
|
25149
|
+
const name = `"${oneLine(tabTitle(node), 40)}"`;
|
|
25150
|
+
if (isSectionNode(node) && node.data[TAB_FIELD] === true && isArchived(node)) {
|
|
25151
|
+
throw new CanvasToolError(
|
|
25152
|
+
`A aba ${name} (${value}) est\xE1 arquivada: os cart\xF5es que apontam para ela ficam em Avulsos. Escolha outra aba. ${tabList(doc)}`
|
|
25153
|
+
);
|
|
25154
|
+
}
|
|
25155
|
+
throw new CanvasToolError(
|
|
25156
|
+
`${value} \xE9 ${isSectionNode(node) ? "uma se\xE7\xE3o comum" : `um n\xF3 ${kindLabel(node)}`} (${name}), n\xE3o uma aba. Aba \xE9 a se\xE7\xE3o com aba=true. ${tabList(doc)}`
|
|
25157
|
+
);
|
|
25158
|
+
}
|
|
25159
|
+
if (value.length >= MIN_PREFIX) {
|
|
25160
|
+
const hits = partitionOf(doc).tabs.filter((tab) => tab.id.startsWith(value));
|
|
25161
|
+
if (hits.length === 1) return hits[0].id;
|
|
25162
|
+
if (hits.length > 1) {
|
|
25163
|
+
const names = hits.slice(0, LISTED).map((tab) => `"${oneLine(tabTitle(doc.nodes[tab.id]), 40)}" (${tab.id})`);
|
|
25164
|
+
throw new CanvasToolError(`"${value}" serve a mais de uma aba: ${names.join(", ")}. Use o id inteiro.`);
|
|
25165
|
+
}
|
|
25166
|
+
}
|
|
25167
|
+
throw new CanvasToolError(`Aba "${oneLine(value, 60)}" n\xE3o existe neste board. ${tabList(doc)}`);
|
|
25168
|
+
}
|
|
25169
|
+
function unionOf(rects) {
|
|
25170
|
+
let out = null;
|
|
25171
|
+
for (const r of rects) {
|
|
25172
|
+
out = out === null ? { ...r } : {
|
|
25173
|
+
left: Math.min(out.left, r.left),
|
|
25174
|
+
top: Math.min(out.top, r.top),
|
|
25175
|
+
right: Math.max(out.right, r.right),
|
|
25176
|
+
bottom: Math.max(out.bottom, r.bottom)
|
|
25177
|
+
};
|
|
25178
|
+
}
|
|
25179
|
+
return out;
|
|
25180
|
+
}
|
|
25181
|
+
function endOfTabContent(doc, tabId, size) {
|
|
25182
|
+
const part = partitionOf(doc);
|
|
25183
|
+
const section = doc.nodes[tabId];
|
|
25184
|
+
const boxes = (part.members.get(tabId) ?? []).flatMap((id) => {
|
|
25185
|
+
const node = doc.nodes[id];
|
|
25186
|
+
return id === tabId || node === void 0 || isArchived(node) ? [] : [drawnRect(doc, node)];
|
|
25187
|
+
});
|
|
25188
|
+
const content = unionOf(boxes);
|
|
25189
|
+
const frame = sectionRect(doc, section);
|
|
25190
|
+
const spot = content === null ? { x: frame.left + TAB_GROW_PAD, y: frame.top + TAB_TOP_ROOM } : { x: content.left, y: content.bottom + TAB_END_GAP };
|
|
25191
|
+
const others = part.tabs.filter((tab) => tab.id !== tabId);
|
|
25192
|
+
const cx = spot.x + size.w / 2;
|
|
25193
|
+
let y = spot.y;
|
|
25194
|
+
for (let guard = 0; guard <= others.length; guard += 1) {
|
|
25195
|
+
const hit = others.find((rect) => rectHas(rect, cx, y + size.h / 2));
|
|
25196
|
+
if (hit === void 0) break;
|
|
25197
|
+
y = hit.bottom + TAB_CLEAR_GAP;
|
|
25198
|
+
}
|
|
25199
|
+
return { x: Math.round(spot.x), y: Math.round(y) };
|
|
25200
|
+
}
|
|
25201
|
+
function placementNote(doc, node) {
|
|
25202
|
+
if (isTabSection(node)) return "";
|
|
25203
|
+
const after = { ...doc, nodes: { ...doc.nodes, [node.id]: node } };
|
|
25204
|
+
const index = tabIndex(after);
|
|
25205
|
+
if (index.tabs.length === 0) return "";
|
|
25206
|
+
const home = partitionOf(after).home.get(node.id);
|
|
25207
|
+
if (home === void 0) return "";
|
|
25208
|
+
const info = index.info(home);
|
|
25209
|
+
if (info === void 0) {
|
|
25210
|
+
return " Aten\xE7\xE3o: ficou em Avulsos (nenhuma aba o segura); passe aba=<id da aba> para ele morar numa aba.";
|
|
25211
|
+
}
|
|
25212
|
+
return ` Aba: "${oneLine(info.title, 40)}" (aba=${info.short}).`;
|
|
25213
|
+
}
|
|
25214
|
+
function flatten(ops) {
|
|
25215
|
+
return ops.flatMap((op) => op.type === "batch" ? flatten(op.ops) : [op]);
|
|
25216
|
+
}
|
|
25217
|
+
function badAbaId(doc, value) {
|
|
25218
|
+
if (value === null) return null;
|
|
25219
|
+
if (typeof value !== "string") return `data.${TAB_ID_FIELD} precisa ser o id (texto) de uma aba, ou null para tirar o campo.`;
|
|
25220
|
+
if (Object.hasOwn(doc.nodes, value) && isTabSection(doc.nodes[value])) return null;
|
|
25221
|
+
let hint;
|
|
25222
|
+
try {
|
|
25223
|
+
const full = resolveTab(doc, value);
|
|
25224
|
+
hint = `Use o id inteiro: ${full}.`;
|
|
25225
|
+
} catch (e) {
|
|
25226
|
+
hint = e instanceof Error ? e.message : "";
|
|
25227
|
+
}
|
|
25228
|
+
return `data.${TAB_ID_FIELD} "${oneLine(value, 60)}" n\xE3o \xE9 o id de uma aba viva. ${hint} Para tirar o campo, mande null.`;
|
|
25229
|
+
}
|
|
25230
|
+
function abaIdViolation(doc, ops) {
|
|
25231
|
+
for (const op of flatten(ops)) {
|
|
25232
|
+
if (op.type === "node.add") {
|
|
25233
|
+
const value = op.node.data[TAB_ID_FIELD];
|
|
25234
|
+
if (value !== void 0) {
|
|
25235
|
+
const bad = badAbaId(doc, value);
|
|
25236
|
+
if (bad) return bad;
|
|
25237
|
+
}
|
|
25238
|
+
} else if (op.type === "node.set" && op.path === `data.${TAB_ID_FIELD}` && op.value.kind === "value") {
|
|
25239
|
+
const bad = badAbaId(doc, op.value.value);
|
|
25240
|
+
if (bad) return bad;
|
|
25241
|
+
}
|
|
25242
|
+
}
|
|
25243
|
+
return null;
|
|
25244
|
+
}
|
|
25245
|
+
|
|
24903
25246
|
// src/canvas/summary.ts
|
|
24904
25247
|
var MAX_TEXT = 160;
|
|
24905
25248
|
var MAX_BLOCKS = 40;
|
|
@@ -24931,7 +25274,7 @@ function visibleData(data) {
|
|
|
24931
25274
|
return rest;
|
|
24932
25275
|
}
|
|
24933
25276
|
var NAME_KEYS = /* @__PURE__ */ new Set([KIND_FIELD, "label", "nodeTitle"]);
|
|
24934
|
-
function
|
|
25277
|
+
function oneLine2(text, max = MAX_TEXT) {
|
|
24935
25278
|
const flat = text.replace(/\s+/g, " ").trim();
|
|
24936
25279
|
return flat.length > max ? `${flat.slice(0, max - 1)}\u2026` : flat;
|
|
24937
25280
|
}
|
|
@@ -24950,7 +25293,7 @@ function scalar(v) {
|
|
|
24950
25293
|
if (typeof v === "string") {
|
|
24951
25294
|
if (v.startsWith("data:")) return "[data-url]";
|
|
24952
25295
|
if (/^https?:\/\//.test(v)) return "[url]";
|
|
24953
|
-
return JSON.stringify(
|
|
25296
|
+
return JSON.stringify(oneLine2(v, 60));
|
|
24954
25297
|
}
|
|
24955
25298
|
if (typeof v === "number" || typeof v === "boolean" || v === null) return String(v);
|
|
24956
25299
|
return null;
|
|
@@ -24959,7 +25302,7 @@ function blocksLines(blocks) {
|
|
|
24959
25302
|
if (!Array.isArray(blocks)) return [];
|
|
24960
25303
|
const out = blocks.slice(0, MAX_BLOCKS).map((b) => {
|
|
24961
25304
|
const rec = b ?? {};
|
|
24962
|
-
return ` \xB7 ${String(rec.id ?? "?")}: ${
|
|
25305
|
+
return ` \xB7 ${String(rec.id ?? "?")}: ${oneLine2(String(rec.text ?? ""), 120)}`;
|
|
24963
25306
|
});
|
|
24964
25307
|
if (blocks.length > MAX_BLOCKS) out.push(` \xB7 \u2026 +${blocks.length - MAX_BLOCKS} blocos`);
|
|
24965
25308
|
return out;
|
|
@@ -24972,21 +25315,22 @@ function rowsLines(rows) {
|
|
|
24972
25315
|
const ideas = Array.isArray(rec.ideas) ? rec.ideas : [];
|
|
24973
25316
|
const ideaText = ideas.slice(0, 6).map((i) => {
|
|
24974
25317
|
const idea = i ?? {};
|
|
24975
|
-
return `${String(idea.id ?? "?")}="${
|
|
25318
|
+
return `${String(idea.id ?? "?")}="${oneLine2(String(idea.text ?? ""), 60)}"`;
|
|
24976
25319
|
}).join("; ");
|
|
24977
25320
|
out.push(` \xB7 linha ${String(rec.id ?? "?")} (bloco ${String(rec.narrationBlockId ?? "?")}): ${ideas.length} ideia(s) ${ideaText}`);
|
|
24978
25321
|
}
|
|
24979
25322
|
if (rows.length > MAX_BLOCKS) out.push(` \xB7 \u2026 +${rows.length - MAX_BLOCKS} linhas`);
|
|
24980
25323
|
return out;
|
|
24981
25324
|
}
|
|
24982
|
-
function nodeLines(node, run) {
|
|
25325
|
+
function nodeLines(node, run, aba) {
|
|
24983
25326
|
const kind = nodeKind(node);
|
|
24984
25327
|
const spec = kind ? KINDS[kind] : void 0;
|
|
24985
|
-
const head = `- ${node.id} \xB7 ${kind ?? node.type} \xB7 "${
|
|
25328
|
+
const head = `- ${node.id} \xB7 ${kind ?? node.type} \xB7 "${oneLine2(nodeName(node), 60)}" @(${Math.round(node.position.x)},${Math.round(node.position.y)}) ${sizeLabel(node)}` + (aba ? ` \xB7 aba=${aba}` : "");
|
|
24986
25329
|
const facts = [];
|
|
24987
25330
|
const extra = [];
|
|
24988
25331
|
const d = node.data;
|
|
24989
25332
|
if (d.archived) facts.push("ARQUIVADO");
|
|
25333
|
+
if (aba && isTabSection(node)) facts.push("\xE9 aba");
|
|
24990
25334
|
const approval = d.approval?.state;
|
|
24991
25335
|
if (typeof approval === "string") facts.push(`aprova\xE7\xE3o: ${approval}`);
|
|
24992
25336
|
if (Array.isArray(d.history)) facts.push(`${d.history.length} gera\xE7\xE3o(\xF5es)`);
|
|
@@ -25007,10 +25351,11 @@ function nodeLines(node, run) {
|
|
|
25007
25351
|
if (fact) facts.push(fact);
|
|
25008
25352
|
}
|
|
25009
25353
|
const main2 = spec?.main;
|
|
25010
|
-
if (main2 && typeof d[main2] === "string" && d[main2]) facts.push(`${main2}: "${
|
|
25354
|
+
if (main2 && typeof d[main2] === "string" && d[main2]) facts.push(`${main2}: "${oneLine2(d[main2])}"`);
|
|
25011
25355
|
for (const [key, value] of Object.entries(d)) {
|
|
25012
25356
|
if (NAME_KEYS.has(key) || HEAVY_KEYS.has(key) || key === main2) continue;
|
|
25013
25357
|
if (["blocks", "rows", "items", "archived", "approval"].includes(key)) continue;
|
|
25358
|
+
if (aba && (key === TAB_ID_FIELD || key === TAB_FIELD && isTabSection(node))) continue;
|
|
25014
25359
|
const s = scalar(value);
|
|
25015
25360
|
if (s !== null) facts.push(`${key}=${s}`);
|
|
25016
25361
|
else if (Array.isArray(value)) facts.push(`${key}=[${value.length}]`);
|
|
@@ -25032,27 +25377,63 @@ function timelineFact(d) {
|
|
|
25032
25377
|
const clips = seq.audioClips && typeof seq.audioClips === "object" && !Array.isArray(seq.audioClips) ? Object.values(seq.audioClips).reduce((t, list) => t + (Array.isArray(list) ? list.length : 0), 0) : 0;
|
|
25033
25378
|
return `sequ\xEAncia (legado, sem data.timeline): ${plans} plano(s), ${clips} clipe(s) de \xE1udio, ${JSON.stringify(seq).length} caracteres (inteira em canvas_read_node sem path; ${volume})`;
|
|
25034
25379
|
}
|
|
25035
|
-
|
|
25380
|
+
var cardsText = (n) => n === 1 ? "1 cart\xE3o" : `${n} cart\xF5es`;
|
|
25381
|
+
function boardSummary(snap, opts = {}) {
|
|
25036
25382
|
const doc = snap.doc;
|
|
25037
|
-
const
|
|
25038
|
-
const
|
|
25383
|
+
const part = partitionOf(doc);
|
|
25384
|
+
const index = tabIndex(doc);
|
|
25385
|
+
const tabbed = index.tabs.length > 0;
|
|
25386
|
+
const scope = opts.tab === void 0 ? null : new Set(part.members.get(opts.tab) ?? []);
|
|
25387
|
+
const everyNode = Object.values(doc.nodes).sort((a, b) => a.position.x - b.position.x || a.position.y - b.position.y);
|
|
25388
|
+
const everyEdge = Object.values(doc.edges);
|
|
25389
|
+
const nodes = scope ? everyNode.filter((n) => scope.has(n.id)) : everyNode;
|
|
25390
|
+
const edges = scope ? everyEdge.filter((e) => scope.has(e.source) || scope.has(e.target)) : everyEdge;
|
|
25039
25391
|
const runs = new Map(snap.runs.map((r) => [r.nodeId, r]));
|
|
25040
|
-
const
|
|
25041
|
-
|
|
25042
|
-
|
|
25392
|
+
const who2 = `Board "${snap.title}" \xB7 id ${snap.id} \xB7 seq ${snap.seq} \xB7 seu papel: ${snap.role}`;
|
|
25393
|
+
const lines = [];
|
|
25394
|
+
if (scope === null) {
|
|
25395
|
+
lines.push(`${who2} \xB7 ${nodes.length} n\xF3(s) \xB7 ${edges.length} liga\xE7\xE3o(\xF5es)`);
|
|
25396
|
+
} else {
|
|
25397
|
+
const external = edges.filter((e) => !(scope.has(e.source) && scope.has(e.target))).length;
|
|
25398
|
+
const info = index.info(opts.tab);
|
|
25399
|
+
const name = info ? `a aba "${oneLine2(info.title, 60)}" (aba=${info.short})` : "os avulsos (aba=avulsos)";
|
|
25400
|
+
lines.push(
|
|
25401
|
+
`${who2} \xB7 s\xF3 ${name}: ${nodes.length} n\xF3(s) \xB7 ${edges.length} liga\xE7\xE3o(\xF5es)${external ? `, ${external} externa(s)` : ""}`,
|
|
25402
|
+
`O board inteiro tem ${everyNode.length} n\xF3(s) e ${everyEdge.length} liga\xE7\xE3o(\xF5es); leia sem aba para ver tudo.`
|
|
25403
|
+
);
|
|
25404
|
+
}
|
|
25043
25405
|
const ialab = doc.meta?.ialab;
|
|
25044
25406
|
if (ialab === null) lines.push("IA Lab: sem v\xEDnculo (gera\xE7\xF5es saem dos diamantes de quem roda).");
|
|
25045
25407
|
else if (ialab && typeof ialab === "object") {
|
|
25046
25408
|
const label = ["code", "name", "projectCode", "projectName"].map((k) => ialab[k]).find((v) => typeof v === "string");
|
|
25047
25409
|
lines.push(`IA Lab: vinculado${label ? ` a ${String(label)}` : ""}.`);
|
|
25048
25410
|
}
|
|
25049
|
-
if (doc.meta?.guide) lines.push(`Guia: ${
|
|
25411
|
+
if (doc.meta?.guide) lines.push(`Guia: ${oneLine2(doc.meta.guide)}`);
|
|
25412
|
+
if (tabbed) {
|
|
25413
|
+
lines.push("", `Abas (${index.tabs.length}), cart\xF5es de cada uma sem contar a se\xE7\xE3o (canvas_read_board com aba=<id> l\xEA uma s\xF3):`);
|
|
25414
|
+
for (const t of index.tabs) {
|
|
25415
|
+
const id = t.id === t.short ? "" : ` \xB7 id ${t.id}`;
|
|
25416
|
+
lines.push(`- aba=${t.short} \xB7 "${oneLine2(t.title, 60)}" \xB7 ${cardsText(t.cards)}${t.locked ? " \xB7 travada" : ""}${id}`);
|
|
25417
|
+
}
|
|
25418
|
+
if (index.loose) lines.push(`- aba=${AVULSOS_TAB} \xB7 ${cardsText(index.loose)} (n\xE3o moram em aba)`);
|
|
25419
|
+
}
|
|
25050
25420
|
lines.push("", "N\xF3s (tamanho: medido = como est\xE1 na tela; gravado = piso, o cart\xE3o pode ser maior):");
|
|
25051
25421
|
if (!nodes.length) lines.push("(vazio)");
|
|
25052
|
-
for (const n of nodes)
|
|
25422
|
+
for (const n of nodes) {
|
|
25423
|
+
const home = tabbed ? part.home.get(n.id) : void 0;
|
|
25424
|
+
lines.push(...nodeLines(n, runs.get(n.id), home === void 0 ? void 0 : index.label(home)));
|
|
25425
|
+
}
|
|
25053
25426
|
lines.push("", "Liga\xE7\xF5es:");
|
|
25054
25427
|
if (!edges.length) lines.push("(nenhuma)");
|
|
25055
|
-
for (const e of edges)
|
|
25428
|
+
for (const e of edges) {
|
|
25429
|
+
let note = "";
|
|
25430
|
+
if (scope && !(scope.has(e.source) && scope.has(e.target))) {
|
|
25431
|
+
const far = part.home.get(scope.has(e.source) ? e.target : e.source);
|
|
25432
|
+
const farInfo = far === void 0 ? void 0 : index.info(far);
|
|
25433
|
+
note = far === void 0 ? " \xB7 externo (o outro lado \xE9 um n\xF3 arquivado ou ausente)" : farInfo ? ` \xB7 externo (outro lado: aba "${oneLine2(farInfo.title, 40)}" aba=${farInfo.short})` : ` \xB7 externo (outro lado: ${AVULSOS_TAB})`;
|
|
25434
|
+
}
|
|
25435
|
+
lines.push(`- ${e.id}: ${e.source}.${e.sourcePort} \u2192 ${e.target}.${e.targetPort}${note}`);
|
|
25436
|
+
}
|
|
25056
25437
|
return lines.join("\n");
|
|
25057
25438
|
}
|
|
25058
25439
|
function nodeDetail(node) {
|
|
@@ -25120,7 +25501,7 @@ function changesSince(envelopes, doc) {
|
|
|
25120
25501
|
count.set(key, (count.get(key) ?? 0) + 1);
|
|
25121
25502
|
}
|
|
25122
25503
|
const parts = [...count].map(([t, n]) => `${n}\xD7 ${t}`);
|
|
25123
|
-
const names = [...touchedNodes(envelopes)].map((id) => doc.nodes[id] ? `"${
|
|
25504
|
+
const names = [...touchedNodes(envelopes)].map((id) => doc.nodes[id] ? `"${oneLine2(nodeName(doc.nodes[id]), 40)}"` : `${id} (apagado)`).slice(0, 8);
|
|
25124
25505
|
return `${envelopes.length} opera\xE7\xE3o(\xF5es) de outras pessoas desde a sua leitura (${parts.join(", ")})` + (names.length ? `; n\xF3s tocados: ${names.join(", ")}` : "");
|
|
25125
25506
|
}
|
|
25126
25507
|
function touchedNodes(envelopes) {
|
|
@@ -25151,7 +25532,7 @@ function mmss(t) {
|
|
|
25151
25532
|
function nodeRef(doc, nodeId3) {
|
|
25152
25533
|
const node = doc.nodes[nodeId3];
|
|
25153
25534
|
const kind = nodeKind(node) ?? node.type;
|
|
25154
|
-
return `"${
|
|
25535
|
+
return `"${oneLine2(nodeName(node), 60)}" (${kind}, ${node.id})`;
|
|
25155
25536
|
}
|
|
25156
25537
|
function hashString(text) {
|
|
25157
25538
|
let h1 = 3735928559;
|
|
@@ -25208,7 +25589,7 @@ function describeAnchor(anchor, doc) {
|
|
|
25208
25589
|
const t = mmss(Number(anchor.t) || 0);
|
|
25209
25590
|
if (kind === "montage") {
|
|
25210
25591
|
const name = nodeName(node);
|
|
25211
|
-
const title = name === KINDS.montage.title ? "" : ` "${
|
|
25592
|
+
const title = name === KINDS.montage.title ? "" : ` "${oneLine2(name, 60)}"`;
|
|
25212
25593
|
return { text: `em ${t} da Montagem${title} (${node.id})`, nodeId: anchor.nodeId };
|
|
25213
25594
|
}
|
|
25214
25595
|
return { text: `em ${t} de ${ref}`, nodeId: anchor.nodeId };
|
|
@@ -25243,11 +25624,11 @@ function threadLines(t, doc) {
|
|
|
25243
25624
|
const where = describeAnchor(t.anchor, doc);
|
|
25244
25625
|
const state = t.resolvedAt ? " \xB7 RESOLVIDO" : "";
|
|
25245
25626
|
const reacts = reactionsText(t.reactions);
|
|
25246
|
-
const lines = t.deleted ? [`- ${t.id} \xB7 ${where.text}${state}`, " (coment\xE1rio raiz apagado: n\xE3o d\xE1 para responder nem resolver)"] : [`- ${t.id} \xB7 ${where.text} \xB7 ${who(t)}${state}${reacts ? ` \xB7 ${reacts}` : ""}`, ` pedido: ${
|
|
25627
|
+
const lines = t.deleted ? [`- ${t.id} \xB7 ${where.text}${state}`, " (coment\xE1rio raiz apagado: n\xE3o d\xE1 para responder nem resolver)"] : [`- ${t.id} \xB7 ${where.text} \xB7 ${who(t)}${state}${reacts ? ` \xB7 ${reacts}` : ""}`, ` pedido: ${oneLine2(t.body ?? "", 400)}`];
|
|
25247
25628
|
if (where.gone && !t.deleted) lines.push(` \u26A0 ALVO SUMIU: ${where.gone}. Responda com pergunta, n\xE3o resolva.`);
|
|
25248
25629
|
const replies = Array.isArray(t.replies) ? t.replies : [];
|
|
25249
25630
|
for (const r of replies.slice(-MAX_REPLIES)) {
|
|
25250
|
-
lines.push(r.deleted ? " \u21B3 (resposta apagada)" : ` \u21B3 ${who(r)}: ${
|
|
25631
|
+
lines.push(r.deleted ? " \u21B3 (resposta apagada)" : ` \u21B3 ${who(r)}: ${oneLine2(r.body ?? "", 140)}`);
|
|
25251
25632
|
}
|
|
25252
25633
|
if (replies.length > MAX_REPLIES) lines.splice(lines.length - MAX_REPLIES, 0, ` \u21B3 \u2026 ${replies.length - MAX_REPLIES} resposta(s) antes`);
|
|
25253
25634
|
return lines;
|
|
@@ -25327,7 +25708,7 @@ Para aplicar: leia o n\xF3 com canvas_read_board (node_ids), edite pelas canvas_
|
|
|
25327
25708
|
() => api.createComment(board_id, { body: text, parentId: comment_id, ...m?.length ? { mentions: m } : {} })
|
|
25328
25709
|
);
|
|
25329
25710
|
const open3 = thread?.resolvedAt ? "A thread est\xE1 resolvida; reabra com canvas_reopen_comment se precisar." : "A thread segue aberta.";
|
|
25330
|
-
return `\u2705 Resposta ${newReplyId(thread)} em ${comment_id}: "${
|
|
25711
|
+
return `\u2705 Resposta ${newReplyId(thread)} em ${comment_id}: "${oneLine2(text, 120)}". ${open3}`;
|
|
25331
25712
|
})
|
|
25332
25713
|
);
|
|
25333
25714
|
server.registerTool(
|
|
@@ -25350,10 +25731,10 @@ Para aplicar: leia o n\xF3 com canvas_read_board (node_ids), edite pelas canvas_
|
|
|
25350
25731
|
} catch (e) {
|
|
25351
25732
|
const why = e instanceof Error ? e.message : String(e);
|
|
25352
25733
|
throw new CanvasToolError(
|
|
25353
|
-
`A resposta "${
|
|
25734
|
+
`A resposta "${oneLine2(done, 80)}" (${replyId}) foi postada em ${comment_id}, mas resolver falhou: ${why} N\xE3o repita canvas_resolve_comment (postaria a resposta de novo): avise a pessoa para resolver no Canvas.`
|
|
25354
25735
|
);
|
|
25355
25736
|
}
|
|
25356
|
-
return `\u2705 Resolvido ${comment_id}: "${
|
|
25737
|
+
return `\u2705 Resolvido ${comment_id}: "${oneLine2(done, 120)}" (resposta ${replyId}).`;
|
|
25357
25738
|
})
|
|
25358
25739
|
);
|
|
25359
25740
|
server.registerTool(
|
|
@@ -25367,7 +25748,7 @@ Para aplicar: leia o n\xF3 com canvas_read_board (node_ids), edite pelas canvas_
|
|
|
25367
25748
|
async ({ board_id, comment_id, why }) => run(async () => {
|
|
25368
25749
|
await onComment(() => api.reopenComment(board_id, comment_id));
|
|
25369
25750
|
if (why) await onComment(() => api.createComment(board_id, { body: why, parentId: comment_id }));
|
|
25370
|
-
return `\u2705 Reaberto ${comment_id}${why ? ` com a resposta "${
|
|
25751
|
+
return `\u2705 Reaberto ${comment_id}${why ? ` com a resposta "${oneLine2(why, 120)}"` : ""}.`;
|
|
25371
25752
|
})
|
|
25372
25753
|
);
|
|
25373
25754
|
server.registerTool(
|
|
@@ -25422,6 +25803,13 @@ Para aplicar: leia o n\xF3 com canvas_read_board (node_ids), edite pelas canvas_
|
|
|
25422
25803
|
);
|
|
25423
25804
|
}
|
|
25424
25805
|
|
|
25806
|
+
// src/tools/canvas-aba-arg.ts
|
|
25807
|
+
var abaArg = (what) => external_exports.string().trim().min(1).max(128).optional().describe(what);
|
|
25808
|
+
var ABA_ADD_NODE = "Aba onde o cart\xE3o mora: o id da se\xE7\xE3o da aba ou o come\xE7o \xFAnico dele (o aba=\u2026 da leitura). Grava data.abaId e, sem position, o cart\xE3o nasce no fim do conte\xFAdo da aba (abaixo do cart\xE3o mais baixo, alinhado \xE0 esquerda do conte\xFAdo). data.abaId vale como aba; se os dois divergirem, recusa. Aba que n\xE3o existe ou que n\xE3o \xE9 aba \xE9 recusada.";
|
|
25809
|
+
var ABA_READ_BOARD = 'L\xEA s\xF3 uma aba: a se\xE7\xE3o, quem mora nela e os fios que tocam nesses n\xF3s (o fio que vai a outra aba vem marcado como externo). Aceita o id da se\xE7\xE3o, o come\xE7o \xFAnico dele (o aba=\u2026 da leitura) ou "avulsos". Sem aba, l\xEA o board inteiro.';
|
|
25810
|
+
var ABA_UPLOAD_MEDIA = "Aba do n\xF3 M\xEDdia novo (id da se\xE7\xE3o da aba ou o come\xE7o \xFAnico dele): grava data.abaId e p\xF5e o n\xF3 no fim do conte\xFAdo da aba, em vez de cair \xE0 direita de tudo, em Avulsos. S\xF3 vale com board_id e sem node_id (n\xF3 que j\xE1 existe n\xE3o muda de aba).";
|
|
25811
|
+
var ABA_ARRANGE_ROWS = 'Aba onde conferir a sobreposi\xE7\xE3o (id da se\xE7\xE3o ou o come\xE7o \xFAnico dele): s\xF3 os cart\xF5es dela contam como "de fora". Sem aba, vale a aba dos n\xF3s arrumados, quando \xE9 uma s\xF3; sen\xE3o, o board inteiro. N\xE3o muda a aba de nenhum n\xF3.';
|
|
25812
|
+
|
|
25425
25813
|
// src/tools/canvas-layout.ts
|
|
25426
25814
|
var nodeIdArg = external_exports.string().min(1).max(128);
|
|
25427
25815
|
var width = external_exports.number().finite().min(40).max(2e4);
|
|
@@ -25461,8 +25849,24 @@ function layoutOps(doc, a) {
|
|
|
25461
25849
|
}
|
|
25462
25850
|
return ops;
|
|
25463
25851
|
}
|
|
25464
|
-
function
|
|
25465
|
-
const
|
|
25852
|
+
function scopeFor(doc, rows, aba) {
|
|
25853
|
+
const tab = aba ? resolveTab(doc, aba) : void 0;
|
|
25854
|
+
if (!hasTabs(doc)) return void 0;
|
|
25855
|
+
const arranged = rows.flatMap((r) => [...r.title ? [r.title] : [], ...r.left, ...r.right]);
|
|
25856
|
+
const homes = new Set(arranged.map((id) => homeTabOf(doc, id)));
|
|
25857
|
+
const only = homes.size === 1 ? [...homes][0] : null;
|
|
25858
|
+
const chosen = tab ?? (only && only !== AVULSOS_TAB ? only : void 0);
|
|
25859
|
+
if (chosen === void 0) return void 0;
|
|
25860
|
+
const info = tabIndex(doc).info(chosen);
|
|
25861
|
+
return {
|
|
25862
|
+
ids: membersOfTab(doc, chosen),
|
|
25863
|
+
title: info.title,
|
|
25864
|
+
short: info.short,
|
|
25865
|
+
foreign: tab === void 0 ? [] : arranged.filter((id) => homeTabOf(doc, id) !== tab)
|
|
25866
|
+
};
|
|
25867
|
+
}
|
|
25868
|
+
function report(doc, a, scope) {
|
|
25869
|
+
const name = (id) => `"${oneLine2(nodeName(doc.nodes[id]), 36)}"`;
|
|
25466
25870
|
const lines = [];
|
|
25467
25871
|
const unmeasured = a.placed.filter((p) => p.source === "gravado");
|
|
25468
25872
|
const estimated = a.placed.filter((p) => p.source === "medido" && p.estimated);
|
|
@@ -25484,9 +25888,17 @@ function report(doc, a) {
|
|
|
25484
25888
|
lines.push("Todos os n\xF3s arrumados t\xEAm medida da tela.");
|
|
25485
25889
|
}
|
|
25486
25890
|
const pairs = (list) => list.map(([x, y]) => `${name(x)} \xD7 ${name(y)}`).join("; ");
|
|
25891
|
+
const where = scope ? ` (s\xF3 na aba "${oneLine2(scope.title, 40)}" aba=${scope.short})` : "";
|
|
25487
25892
|
lines.push(
|
|
25488
|
-
a.inner.length || a.outer.length ? `Sobreposi\xE7\xF5es com os tamanhos usados: ${pairs([...a.inner, ...a.outer])}.` :
|
|
25893
|
+
a.inner.length || a.outer.length ? `Sobreposi\xE7\xF5es com os tamanhos usados${where}: ${pairs([...a.inner, ...a.outer])}.` : `Sobreposi\xE7\xF5es com os tamanhos usados${where}: nenhuma.`
|
|
25489
25894
|
);
|
|
25895
|
+
if (scope?.foreign.length) {
|
|
25896
|
+
const n = scope.foreign.length;
|
|
25897
|
+
const names = scope.foreign.slice(0, 5).map(name).join(", ") + (n > 5 ? ` e mais ${n - 5}` : "");
|
|
25898
|
+
lines.push(
|
|
25899
|
+
`Aten\xE7\xE3o: ${names} ${n === 1 ? "mora" : "moram"} em outra aba que n\xE3o a pedida; o arranjo grava s\xF3 posi\xE7\xE3o e n\xE3o troca a aba de ningu\xE9m (data.abaId).`
|
|
25900
|
+
);
|
|
25901
|
+
}
|
|
25490
25902
|
lines.push('Caixas ([papel] id "nome" @(x,y) largura\xD7altura usada, origem da altura):');
|
|
25491
25903
|
const rows = /* @__PURE__ */ new Map();
|
|
25492
25904
|
for (const p of a.placed) {
|
|
@@ -25510,10 +25922,11 @@ function registerCanvasLayoutTools(server, deps) {
|
|
|
25510
25922
|
"canvas_arrange_rows",
|
|
25511
25923
|
{
|
|
25512
25924
|
title: "Canvas: arrumar em linhas",
|
|
25513
|
-
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.",
|
|
25514
25926
|
inputSchema: {
|
|
25515
25927
|
board_id: external_exports.string().uuid(),
|
|
25516
25928
|
origin: external_exports.object({ x: external_exports.number().finite(), y: external_exports.number().finite() }).describe("Canto de cima \xE0 esquerda da \xE1rea."),
|
|
25929
|
+
aba: abaArg(ABA_ARRANGE_ROWS),
|
|
25517
25930
|
rows: external_exports.array(
|
|
25518
25931
|
external_exports.object({
|
|
25519
25932
|
title: nodeIdArg.optional().describe("N\xF3 do t\xEDtulo da linha (Texto livre)."),
|
|
@@ -25530,7 +25943,7 @@ function registerCanvasLayoutTools(server, deps) {
|
|
|
25530
25943
|
reference: width.optional(),
|
|
25531
25944
|
frame: width.optional(),
|
|
25532
25945
|
title: width.optional()
|
|
25533
|
-
}).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."),
|
|
25534
25947
|
dry_run: external_exports.boolean().optional().describe("true: s\xF3 calcula e mostra, sem gravar.")
|
|
25535
25948
|
},
|
|
25536
25949
|
annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: false }
|
|
@@ -25538,19 +25951,20 @@ function registerCanvasLayoutTools(server, deps) {
|
|
|
25538
25951
|
async (args) => run(async () => {
|
|
25539
25952
|
const rows = args.rows.map((r) => ({ title: r.title, left: r.left ?? [], right: r.right ?? [] }));
|
|
25540
25953
|
const { generator, ...own } = args.widths ?? {};
|
|
25541
|
-
const widths = { ...
|
|
25954
|
+
const widths = { ...generator ? { image: generator, video: generator } : {}, ...own };
|
|
25542
25955
|
const gap = args.gap ?? DEFAULT_GAP;
|
|
25543
25956
|
const plan = (doc) => {
|
|
25544
25957
|
checkRows(doc, rows);
|
|
25545
|
-
const
|
|
25546
|
-
|
|
25958
|
+
const scope = scopeFor(doc, rows, args.aba);
|
|
25959
|
+
const a = arrangeRows(doc, rows, args.origin, gap, widths, scope?.ids);
|
|
25960
|
+
return { a, scoped: scope !== void 0, ops: layoutOps(doc, a), text: report(doc, a, scope) };
|
|
25547
25961
|
};
|
|
25548
25962
|
const count = (ops) => new Set(ops.map((o) => o.type === "node.set" ? o.nodeId : "")).size;
|
|
25549
|
-
const blocked = (a) => `A \xE1rea encosta em n\xF3s que n\xE3o est\xE3o no arranjo. Nada foi gravado. Origem livre sugerida: {"x":${a.freeOrigin.x},"y":${a.freeOrigin.y}} (abaixo de tudo nessa faixa), ou tire esses n\xF3s do caminho.`;
|
|
25963
|
+
const blocked = (a, scoped) => `A \xE1rea encosta em n\xF3s que n\xE3o est\xE3o no arranjo. Nada foi gravado. Origem livre sugerida: {"x":${a.freeOrigin.x},"y":${a.freeOrigin.y}} (abaixo de tudo${scoped ? " da aba" : ""} nessa faixa), ou tire esses n\xF3s do caminho.`;
|
|
25550
25964
|
if (args.dry_run) {
|
|
25551
|
-
const { a, ops, text: text2 } = plan((await api.snapshot(args.board_id)).doc);
|
|
25965
|
+
const { a, scoped, ops, text: text2 } = plan((await api.snapshot(args.board_id)).doc);
|
|
25552
25966
|
const head = `Pr\xE9via, nada gravado: ${ops.length ? `${count(ops)} n\xF3(s) mudariam de lugar ou largura` : "tudo j\xE1 est\xE1 assim"}.`;
|
|
25553
|
-
return [head, ...a.outer.length ? [blocked(a)] : [], text2].join("\n");
|
|
25967
|
+
return [head, ...a.outer.length ? [blocked(a, scoped)] : [], text2].join("\n");
|
|
25554
25968
|
}
|
|
25555
25969
|
let text = "";
|
|
25556
25970
|
const done = await edit(
|
|
@@ -25558,7 +25972,7 @@ function registerCanvasLayoutTools(server, deps) {
|
|
|
25558
25972
|
async (doc) => {
|
|
25559
25973
|
const p = plan(doc);
|
|
25560
25974
|
text = p.text;
|
|
25561
|
-
if (p.a.outer.length) throw new CanvasToolError(`${blocked(p.a)}
|
|
25975
|
+
if (p.a.outer.length) throw new CanvasToolError(`${blocked(p.a, p.scoped)}
|
|
25562
25976
|
${p.text}`);
|
|
25563
25977
|
return {
|
|
25564
25978
|
ops: p.ops,
|
|
@@ -25654,7 +26068,7 @@ function needMediaNode(doc, nodeId3) {
|
|
|
25654
26068
|
if (!node) throw new CanvasToolError(`N\xF3 ${nodeId3} n\xE3o existe no board. Releia com canvas_read_board.`);
|
|
25655
26069
|
if (nodeKind(node) !== "media") {
|
|
25656
26070
|
throw new CanvasToolError(
|
|
25657
|
-
`O n\xF3 ${nodeId3} ("${
|
|
26071
|
+
`O n\xF3 ${nodeId3} ("${oneLine2(nodeName(node), 40)}") \xE9 ${nodeKind(node) ?? node.type}, n\xE3o M\xEDdia. Passe o id de um n\xF3 media, ou omita node_id para criar um n\xF3 M\xEDdia novo.`
|
|
25658
26072
|
);
|
|
25659
26073
|
}
|
|
25660
26074
|
return node;
|
|
@@ -25689,20 +26103,26 @@ function registerCanvasMediaTools(server, deps) {
|
|
|
25689
26103
|
"canvas_upload_media",
|
|
25690
26104
|
{
|
|
25691
26105
|
title: "Canvas: subir arquivo",
|
|
25692
|
-
description: "Sobe um arquivo (caminho local ou URL) pela rota de arquivos da BePlus e devolve o item pronto: url, mime, bytes, dura\xE7\xE3o/largura/altura quando \xE9 m\xEDdia, media_item (data.items do n\xF3 M\xEDdia), sequence_asset e libraryItemId (clipe da timeline da Montagem). Com board_id grava no n\xF3 M\xEDdia node_id, ou cria um n\xF3 M\xEDdia novo sem node_id; a\xED exige canvas_read_board nesta sess\xE3o. Teto de 95 MB. N\xE3o gera m\xEDdia nem gasta diamantes.",
|
|
26106
|
+
description: "Sobe um arquivo (caminho local ou URL) pela rota de arquivos da BePlus e devolve o item pronto: url, mime, bytes, dura\xE7\xE3o/largura/altura quando \xE9 m\xEDdia, media_item (data.items do n\xF3 M\xEDdia), sequence_asset e libraryItemId (clipe da timeline da Montagem). Com board_id grava no n\xF3 M\xEDdia node_id, ou cria um n\xF3 M\xEDdia novo sem node_id (com aba, ele nasce no fim do conte\xFAdo da aba e grava data.abaId); a\xED exige canvas_read_board nesta sess\xE3o. Teto de 95 MB. N\xE3o gera m\xEDdia nem gasta diamantes.",
|
|
25693
26107
|
inputSchema: {
|
|
25694
26108
|
source: external_exports.string().trim().min(1).max(2e3).describe("Caminho local (/\u2026, ~/\u2026, file://) ou URL http(s)."),
|
|
25695
26109
|
name: external_exports.string().trim().min(1).max(120).optional().describe("Nome do arquivo no Canvas (a extens\xE3o \xE9 mantida)."),
|
|
25696
26110
|
board_id: external_exports.string().uuid().optional().describe("Board onde gravar o item (opcional)."),
|
|
25697
26111
|
node_id: external_exports.string().min(1).max(128).optional().describe("N\xF3 M\xEDdia que recebe o item. Sem ele, cria um n\xF3 M\xEDdia novo."),
|
|
26112
|
+
aba: abaArg(ABA_UPLOAD_MEDIA),
|
|
25698
26113
|
label: external_exports.string().trim().min(1).max(120).optional().describe("Nome do n\xF3 M\xEDdia novo (padr\xE3o: nome do arquivo)."),
|
|
25699
26114
|
replace: external_exports.boolean().optional().describe("true troca a lista do n\xF3 por este arquivo; false acrescenta. Padr\xE3o: a regra do Canvas (n\xF3 de um arquivo s\xF3, ligado, troca).")
|
|
25700
26115
|
},
|
|
25701
26116
|
annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true }
|
|
25702
26117
|
},
|
|
25703
26118
|
async (args) => run(async () => {
|
|
25704
|
-
if (!args.board_id && (args.node_id || args.label || args.replace !== void 0)) {
|
|
25705
|
-
throw new CanvasToolError("node_id, label e
|
|
26119
|
+
if (!args.board_id && (args.node_id || args.label || args.replace !== void 0 || args.aba)) {
|
|
26120
|
+
throw new CanvasToolError("node_id, label, replace e aba s\xF3 valem com board_id.");
|
|
26121
|
+
}
|
|
26122
|
+
if (args.aba && args.node_id) {
|
|
26123
|
+
throw new CanvasToolError(
|
|
26124
|
+
"aba s\xF3 vale quando o upload cria um n\xF3 M\xEDdia novo (sem node_id): o n\xF3 que j\xE1 existe n\xE3o muda de aba por aqui."
|
|
26125
|
+
);
|
|
25706
26126
|
}
|
|
25707
26127
|
if (args.board_id) {
|
|
25708
26128
|
if (!seen.has(args.board_id)) {
|
|
@@ -25710,12 +26130,13 @@ function registerCanvasMediaTools(server, deps) {
|
|
|
25710
26130
|
}
|
|
25711
26131
|
const snap = await api.snapshot(args.board_id);
|
|
25712
26132
|
if (snap.role === "viewer") throw new CanvasToolError("Voc\xEA \xE9 s\xF3 leitor neste board: pe\xE7a ao dono para te dar papel de editor.");
|
|
26133
|
+
if (args.aba) resolveTab(snap.doc, args.aba);
|
|
25713
26134
|
if (args.node_id) {
|
|
25714
26135
|
const node = needMediaNode(snap.doc, args.node_id);
|
|
25715
26136
|
const replacing = args.replace ?? holdsOne(snap.doc, node);
|
|
25716
26137
|
if (!replacing && itemsOf(node).length >= MAX_MEDIA_ITEMS) {
|
|
25717
26138
|
throw new CanvasToolError(
|
|
25718
|
-
`O n\xF3 "${
|
|
26139
|
+
`O n\xF3 "${oneLine2(nodeName(node), 40)}" j\xE1 tem ${MAX_MEDIA_ITEMS} arquivos (teto do Canvas). Omita node_id para criar outro n\xF3 M\xEDdia.`
|
|
25719
26140
|
);
|
|
25720
26141
|
}
|
|
25721
26142
|
}
|
|
@@ -25749,14 +26170,21 @@ URL: ${u.url}`;
|
|
|
25749
26170
|
return {
|
|
25750
26171
|
ops: [{ type: "node.set", nodeId: node.id, path: "data.items", value: setValue(items) }],
|
|
25751
26172
|
targets: [node.id],
|
|
25752
|
-
done: `N\xF3 M\xEDdia "${
|
|
26173
|
+
done: `N\xF3 M\xEDdia "${oneLine2(nodeName(node), 40)}" (${node.id}): ` + (replacing ? `arquivo trocado (${before} \u2192 1)` : `arquivo acrescentado, agora com ${items.length}`)
|
|
25753
26174
|
};
|
|
25754
26175
|
}
|
|
25755
26176
|
const spec = KINDS.media;
|
|
26177
|
+
const tab = args.aba ? resolveTab(doc, args.aba) : void 0;
|
|
25756
26178
|
const created = makeNode({
|
|
25757
26179
|
type: WORKFLOW_NODE_TYPE,
|
|
25758
|
-
data: {
|
|
25759
|
-
|
|
26180
|
+
data: {
|
|
26181
|
+
...spec.data,
|
|
26182
|
+
[KIND_FIELD]: "media",
|
|
26183
|
+
label: args.label ?? u.name,
|
|
26184
|
+
items: [item],
|
|
26185
|
+
...tab === void 0 ? {} : { [TAB_ID_FIELD]: tab }
|
|
26186
|
+
},
|
|
26187
|
+
position: placeFor(doc, spec.size, void 0, "right", tab),
|
|
25760
26188
|
size: spec.size,
|
|
25761
26189
|
zIndex: Object.values(doc.nodes).reduce((t, n) => Math.max(t, n.zIndex), 0) + 1,
|
|
25762
26190
|
createdBy: await api.me()
|
|
@@ -25765,7 +26193,7 @@ URL: ${u.url}`;
|
|
|
25765
26193
|
return {
|
|
25766
26194
|
ops: [{ type: "node.add", nodeId: created.id, node: created }],
|
|
25767
26195
|
targets: [],
|
|
25768
|
-
done: `N\xF3 M\xEDdia "${
|
|
26196
|
+
done: `N\xF3 M\xEDdia "${oneLine2(nodeName(created), 40)}" criado: ${created.id}.${placementNote(doc, created)}`
|
|
25769
26197
|
};
|
|
25770
26198
|
});
|
|
25771
26199
|
} catch (e) {
|
|
@@ -26145,6 +26573,7 @@ function isLockedSection(node) {
|
|
|
26145
26573
|
return node !== void 0 && nodeKind(node) === "section" && node.data[SECTION_LOCK_FIELD] === true;
|
|
26146
26574
|
}
|
|
26147
26575
|
var LAYOUT_PATH = /^(position|size)(\.|$)/;
|
|
26576
|
+
var STAMP_PATH = `data.${TAB_ID_FIELD}`;
|
|
26148
26577
|
function rectOf(node, withMeasured) {
|
|
26149
26578
|
const h = withMeasured ? Math.max(node.size.h, readMeasured(node)?.h ?? 0) : node.size.h;
|
|
26150
26579
|
return { x: node.position.x, y: node.position.y, w: node.size.w, h };
|
|
@@ -26152,14 +26581,14 @@ function rectOf(node, withMeasured) {
|
|
|
26152
26581
|
function contains(outer, inner) {
|
|
26153
26582
|
return inner.x >= outer.x && inner.y >= outer.y && inner.x + inner.w <= outer.x + outer.w && inner.y + inner.h <= outer.y + outer.h;
|
|
26154
26583
|
}
|
|
26155
|
-
function
|
|
26156
|
-
return ops.flatMap((op) => op.type === "batch" ?
|
|
26584
|
+
function flatten2(ops) {
|
|
26585
|
+
return ops.flatMap((op) => op.type === "batch" ? flatten2(op.ops) : [op]);
|
|
26157
26586
|
}
|
|
26158
26587
|
function lockViolation(doc, ops) {
|
|
26159
26588
|
const locked = Object.values(doc.nodes).filter(isLockedSection);
|
|
26160
26589
|
if (!locked.length) return null;
|
|
26161
|
-
const name = (node) => `"${
|
|
26162
|
-
const flat =
|
|
26590
|
+
const name = (node) => `"${oneLine2(tabTitle(node), 40)}"`;
|
|
26591
|
+
const flat = flatten2(ops);
|
|
26163
26592
|
for (const op of flat) {
|
|
26164
26593
|
if (op.type !== "node.set" && op.type !== "node.remove") continue;
|
|
26165
26594
|
const node = doc.nodes[op.nodeId];
|
|
@@ -26167,18 +26596,30 @@ function lockViolation(doc, ops) {
|
|
|
26167
26596
|
if (op.type === "node.remove") return `${name(node)}: ${LOCKED_TEXT}. Nada foi apagado.`;
|
|
26168
26597
|
if (LAYOUT_PATH.test(op.path)) return `${name(node)}: ${LOCKED_TEXT}. Nada foi aplicado.`;
|
|
26169
26598
|
}
|
|
26170
|
-
const
|
|
26599
|
+
const home = partitionOf(doc).home;
|
|
26600
|
+
const placed = /* @__PURE__ */ new Set();
|
|
26601
|
+
const restamped = /* @__PURE__ */ new Set();
|
|
26171
26602
|
for (const op of flat) {
|
|
26172
|
-
if (op.type !== "node.set"
|
|
26603
|
+
if (op.type !== "node.set") continue;
|
|
26173
26604
|
const node = doc.nodes[op.nodeId];
|
|
26174
|
-
if (node
|
|
26605
|
+
if (node === void 0 || nodeKind(node) === "section") continue;
|
|
26606
|
+
if (LAYOUT_PATH.test(op.path)) {
|
|
26607
|
+
placed.add(op.nodeId);
|
|
26608
|
+
} else if (op.path === STAMP_PATH) {
|
|
26609
|
+
const sameHome = op.value.kind === "value" && op.value.value === home.get(op.nodeId);
|
|
26610
|
+
if (!sameHome) restamped.add(op.nodeId);
|
|
26611
|
+
}
|
|
26175
26612
|
}
|
|
26613
|
+
const moved = /* @__PURE__ */ new Set([...placed, ...restamped]);
|
|
26176
26614
|
if (moved.size < 2) return null;
|
|
26177
26615
|
for (const section of locked) {
|
|
26178
|
-
const
|
|
26179
|
-
|
|
26616
|
+
const inside = isTabSection(section) ? [...moved].filter((id) => home.get(id) === section.id) : (() => {
|
|
26617
|
+
const outer = rectOf(section, false);
|
|
26618
|
+
return [...placed].filter((id) => contains(outer, rectOf(doc.nodes[id], true)));
|
|
26619
|
+
})();
|
|
26180
26620
|
if (inside.length >= 2) {
|
|
26181
|
-
|
|
26621
|
+
const stamp = inside.some((id) => restamped.has(id)) ? " Trocar a aba (data.abaId) tamb\xE9m conta como mexer na aba." : "";
|
|
26622
|
+
return `${name(section)}: ${LOCKED_TEXT}. Mudar ${inside.length} n\xF3s de dentro dela num pedido s\xF3 n\xE3o vale (um por vez segue valendo).${stamp} Nada foi aplicado.`;
|
|
26182
26623
|
}
|
|
26183
26624
|
}
|
|
26184
26625
|
return null;
|
|
@@ -26347,7 +26788,7 @@ var point = external_exports.object({ x: external_exports.number().finite(), y:
|
|
|
26347
26788
|
var LABEL_TEXT_SIZES = ["titulo", "subtitulo", "corpo"];
|
|
26348
26789
|
var dim = external_exports.number().finite().min(16).max(2e4);
|
|
26349
26790
|
var sizeArg = external_exports.union([external_exports.object({ w: dim.optional(), h: dim.optional() }).strict(), external_exports.enum(LABEL_TEXT_SIZES)]).describe(
|
|
26350
|
-
'{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.'
|
|
26351
26792
|
);
|
|
26352
26793
|
var isLayoutOp = (op) => op.type === "batch" ? op.ops.every(isLayoutOp) : op.type === "node.set" && /^(position\.[xy]|size\.[wh])$/.test(op.path);
|
|
26353
26794
|
function textSizeFor(kind, size) {
|
|
@@ -26362,6 +26803,10 @@ function boxOf(size) {
|
|
|
26362
26803
|
if (size.w === void 0 && size.h === void 0) throw new CanvasToolError("size {w, h}: informe w, h ou os dois.");
|
|
26363
26804
|
return size;
|
|
26364
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
|
+
}
|
|
26365
26810
|
function registerCanvasTools(server, client, cfg) {
|
|
26366
26811
|
const api = new CanvasApi(client, cfg);
|
|
26367
26812
|
const seen = /* @__PURE__ */ new Map();
|
|
@@ -26383,7 +26828,7 @@ function registerCanvasTools(server, client, cfg) {
|
|
|
26383
26828
|
return fail(e);
|
|
26384
26829
|
}
|
|
26385
26830
|
}
|
|
26386
|
-
async function edit(id,
|
|
26831
|
+
async function edit(id, build2, opts = {}) {
|
|
26387
26832
|
const last = seen.get(id);
|
|
26388
26833
|
if (last === void 0 && !opts.layoutOnly) {
|
|
26389
26834
|
throw new CanvasToolError("Leia o board com canvas_read_board antes de editar (a leitura vale para a sess\xE3o).");
|
|
@@ -26391,11 +26836,13 @@ function registerCanvasTools(server, client, cfg) {
|
|
|
26391
26836
|
const snap = await api.snapshot(id);
|
|
26392
26837
|
if (snap.role === "viewer") throw new CanvasToolError("Voc\xEA \xE9 s\xF3 leitor neste board: pe\xE7a ao dono para te dar papel de editor.");
|
|
26393
26838
|
const doc = snap.doc;
|
|
26394
|
-
const { ops, done, targets } = await
|
|
26839
|
+
const { ops, done, targets } = await build2(doc, snap);
|
|
26395
26840
|
if (!ops.length) return `Nada a mudar. ${done}`;
|
|
26396
26841
|
if (opts.layoutOnly && !ops.every(isLayoutOp)) throw new Error("layout_only com opera\xE7\xE3o fora de posi\xE7\xE3o/tamanho");
|
|
26397
26842
|
const locked = lockViolation(doc, ops);
|
|
26398
26843
|
if (locked) throw new CanvasToolError(locked);
|
|
26844
|
+
const badAba = abaIdViolation(doc, ops);
|
|
26845
|
+
if (badAba) throw new CanvasToolError(`${badAba} Nada foi aplicado.`);
|
|
26399
26846
|
let note = "";
|
|
26400
26847
|
if (!opts.layoutOnly && last !== void 0 && snap.seq > last) {
|
|
26401
26848
|
const since = await api.opsAfter(id, last);
|
|
@@ -26409,7 +26856,7 @@ function registerCanvasTools(server, client, cfg) {
|
|
|
26409
26856
|
const clash = [...touchedNodes(theirs)].filter((n) => targets.includes(n));
|
|
26410
26857
|
if (clash.length) {
|
|
26411
26858
|
seen.delete(id);
|
|
26412
|
-
const names = clash.map((n) => doc.nodes[n] ? `"${
|
|
26859
|
+
const names = clash.map((n) => doc.nodes[n] ? `"${oneLine2(nodeName(doc.nodes[n]), 40)}"` : n).join(", ");
|
|
26413
26860
|
throw new CanvasToolError(
|
|
26414
26861
|
`Outra pessoa mexeu em ${names} depois da sua leitura (seq ${last} \u2192 ${snap.seq}). Nada foi aplicado: releia com canvas_read_board e refa\xE7a a edi\xE7\xE3o em cima do estado atual.`
|
|
26415
26862
|
);
|
|
@@ -26506,15 +26953,17 @@ ${lines.join("\n")}${note}`;
|
|
|
26506
26953
|
}
|
|
26507
26954
|
return { ops, warn };
|
|
26508
26955
|
}
|
|
26509
|
-
function placeFor(doc, size, near, side = "right") {
|
|
26956
|
+
function placeFor(doc, size, near, side = "right", tab) {
|
|
26510
26957
|
if (near) {
|
|
26511
26958
|
const x = side === "right" ? near.position.x + near.size.w + GAP : near.position.x - size.w - GAP;
|
|
26512
26959
|
let y = near.position.y;
|
|
26513
|
-
const
|
|
26960
|
+
const scope = tab === void 0 ? null : membersOfTab(doc, tab);
|
|
26961
|
+
const nodes2 = Object.values(doc.nodes).filter((n) => scope === null || scope.has(n.id) && nodeKind(n) !== "section");
|
|
26514
26962
|
const hits = (yy) => nodes2.some((n) => x < n.position.x + n.size.w && x + size.w > n.position.x && yy < n.position.y + n.size.h && yy + size.h > n.position.y);
|
|
26515
26963
|
for (let i = 0; i < 50 && hits(y); i++) y += GAP;
|
|
26516
26964
|
return { x, y };
|
|
26517
26965
|
}
|
|
26966
|
+
if (tab !== void 0 && tab !== AVULSOS_TAB) return endOfTabContent(doc, tab, size);
|
|
26518
26967
|
const nodes = Object.values(doc.nodes).filter((n) => nodeKind(n) !== "section");
|
|
26519
26968
|
if (!nodes.length) return { x: 0, y: 0 };
|
|
26520
26969
|
return {
|
|
@@ -26570,7 +27019,7 @@ ${lines.join("\n")}${note}`;
|
|
|
26570
27019
|
for (const c of changed) after.nodes[c.node.id] = { ...c.node, data: c.data };
|
|
26571
27020
|
for (const e of newEdges) after.edges[e.id] = e;
|
|
26572
27021
|
const sync = mentionEdgeOps(after, prompts.map((c) => c.node.id), await api.me());
|
|
26573
|
-
const name = (id) => after.nodes[id] ? `"${
|
|
27022
|
+
const name = (id) => after.nodes[id] ? `"${oneLine2(nodeName(after.nodes[id]), 40)}"` : id;
|
|
26574
27023
|
return { ops: sync.ops, note: describeMentionSync(sync, name) };
|
|
26575
27024
|
}
|
|
26576
27025
|
server.registerTool(
|
|
@@ -26591,17 +27040,19 @@ ${lines.join("\n")}${note}`;
|
|
|
26591
27040
|
"canvas_read_board",
|
|
26592
27041
|
{
|
|
26593
27042
|
title: "Canvas: ler board",
|
|
26594
|
-
description: 'L\xEA um board: n\xF3s (id, tipo, nome, posi\xE7\xE3o, tamanho, campos principais), liga\xE7\xF5es e v\xEDnculo com o IA Lab, sem m\xEDdia. Tamanho "medido" \xE9 o da tela; "gravado" \xE9 o piso (o cart\xE3o cresce com o conte\xFAdo). Obrigat\xF3rio antes de editar (vale para a sess\xE3o). node_ids devolve o data desses n\xF3s, com cada corte marcado (path=\u2026); o valor inteiro (ex.: data.sequence da Montagem) sai no canvas_read_node.',
|
|
27043
|
+
description: 'L\xEA um board: n\xF3s (id, tipo, nome, posi\xE7\xE3o, tamanho, campos principais), liga\xE7\xF5es e v\xEDnculo com o IA Lab, sem m\xEDdia. Tamanho "medido" \xE9 o da tela; "gravado" \xE9 o piso (o cart\xE3o cresce com o conte\xFAdo). Obrigat\xF3rio antes de editar (vale para a sess\xE3o). node_ids devolve o data desses n\xF3s, com cada corte marcado (path=\u2026); o valor inteiro (ex.: data.sequence da Montagem) sai no canvas_read_node. Cada cart\xE3o diz a aba (aba=<id curto> ou aba=avulsos), o topo conta os cart\xF5es de cada aba e aba l\xEA uma aba s\xF3.',
|
|
26595
27044
|
inputSchema: {
|
|
26596
27045
|
board_id: boardId3,
|
|
26597
|
-
node_ids: external_exports.array(nodeIdArg2).max(20).optional().describe("N\xF3s para ver o data (sem blobs, cortes marcados).")
|
|
27046
|
+
node_ids: external_exports.array(nodeIdArg2).max(20).optional().describe("N\xF3s para ver o data (sem blobs, cortes marcados)."),
|
|
27047
|
+
aba: abaArg(ABA_READ_BOARD)
|
|
26598
27048
|
},
|
|
26599
27049
|
annotations: { readOnlyHint: true, openWorldHint: false }
|
|
26600
27050
|
},
|
|
26601
|
-
async ({ board_id, node_ids }) => run(async () => {
|
|
27051
|
+
async ({ board_id, node_ids, aba }) => run(async () => {
|
|
26602
27052
|
const snap = await api.snapshot(board_id);
|
|
27053
|
+
const tab = aba ? resolveTab(snap.doc, aba, { allowAvulsos: true }) : void 0;
|
|
26603
27054
|
seen.set(board_id, snap.seq);
|
|
26604
|
-
const parts = [boardSummary(snap)];
|
|
27055
|
+
const parts = [boardSummary(snap, { tab })];
|
|
26605
27056
|
if (node_ids?.length) {
|
|
26606
27057
|
parts.push("", "Detalhe:");
|
|
26607
27058
|
for (const n of node_ids) parts.push(snap.doc.nodes[n] ? nodeDetail(snap.doc.nodes[n]) : `${n}: n\xE3o existe`);
|
|
@@ -26661,7 +27112,7 @@ ${lines.join("\n")}${note}`;
|
|
|
26661
27112
|
const hash = createHash("sha256").update(json2).digest("hex").slice(0, 12);
|
|
26662
27113
|
const where = `data${segments.length ? `.${segments.join(".")}` : ""}`;
|
|
26663
27114
|
const at = readMeasured(node)?.at;
|
|
26664
|
-
const head = `${node.id} \xB7 ${nodeKind(node) ?? node.type} \xB7 "${
|
|
27115
|
+
const head = `${node.id} \xB7 ${nodeKind(node) ?? node.type} \xB7 "${oneLine2(nodeName(node), 60)}" \xB7 board seq ${snap.seq} \xB7 tamanho ${sizeLabel(node)}${at ? ` \xB7 medido em ${at}` : ""} \xB7 ${where}${which}: ${total} caracteres (JSON compacto) \xB7 sha256 ${hash}`;
|
|
26665
27116
|
const part = from === 0 && to === total ? "Inteiro, abaixo." : `Parte: caracteres ${from} a ${to} de ${total}. ${to < total ? `Falta o resto: chame de novo com offset=${to}.` : "Esta \xE9 a \xFAltima parte."}`;
|
|
26666
27117
|
return `${head}
|
|
26667
27118
|
${part}
|
|
@@ -26722,12 +27173,13 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
26722
27173
|
"canvas_add_node",
|
|
26723
27174
|
{
|
|
26724
27175
|
title: "Canvas: adicionar n\xF3",
|
|
26725
|
-
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. 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,
|
|
26726
27177
|
inputSchema: {
|
|
26727
27178
|
board_id: boardId3,
|
|
26728
27179
|
kind: external_exports.string().min(1).max(40),
|
|
26729
27180
|
label: external_exports.string().trim().min(1).max(120).optional().describe("Nome do cart\xE3o (data.label)."),
|
|
26730
27181
|
data: external_exports.record(external_exports.unknown()).optional().describe("Campos do data. Ex.: narration {blocks:[{id,text}]}, text {text}, prompt {template}."),
|
|
27182
|
+
aba: abaArg(ABA_ADD_NODE),
|
|
26731
27183
|
position: point.optional(),
|
|
26732
27184
|
size: sizeArg.optional(),
|
|
26733
27185
|
inputs: external_exports.array(external_exports.object({ from: nodeIdArg2, from_port: external_exports.string().min(1), to_port: external_exports.string().min(1) })).max(20).optional().describe("Liga\xE7\xF5es que CHEGAM no n\xF3 novo: from.from_port \u2192 novo.to_port."),
|
|
@@ -26742,14 +27194,21 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
26742
27194
|
const me = await api.me();
|
|
26743
27195
|
const data = { ...spec.data, ...parseData(args.data), [KIND_FIELD]: args.kind };
|
|
26744
27196
|
if (args.label) data.label = args.label;
|
|
26745
|
-
let box = spec.size;
|
|
26746
27197
|
if (typeof args.size === "string") data.size = textSizeFor(args.kind, args.size);
|
|
26747
|
-
|
|
26748
|
-
|
|
26749
|
-
|
|
27198
|
+
const box = birthBox(args.kind, spec, data, args.size && typeof args.size !== "string" ? boxOf(args.size) : void 0);
|
|
27199
|
+
const byParam = args.aba ? resolveTab(doc, args.aba) : void 0;
|
|
27200
|
+
const written = data[TAB_ID_FIELD];
|
|
27201
|
+
const byData = typeof written === "string" && written !== "" ? resolveTab(doc, written) : void 0;
|
|
27202
|
+
if (byParam !== void 0 && byData !== void 0 && byParam !== byData) {
|
|
27203
|
+
throw new CanvasToolError(
|
|
27204
|
+
`aba ("${tabTitle(doc.nodes[byParam])}") e data.abaId ("${tabTitle(doc.nodes[byData])}") apontam para abas diferentes: mande s\xF3 aba.`
|
|
27205
|
+
);
|
|
26750
27206
|
}
|
|
27207
|
+
const tab = byParam ?? byData;
|
|
27208
|
+
if (tab !== void 0) data[TAB_ID_FIELD] = tab;
|
|
26751
27209
|
const near = args.inputs?.[0] ? doc.nodes[args.inputs[0].from] : args.outputs?.[0] ? doc.nodes[args.outputs[0].to] : void 0;
|
|
26752
|
-
const
|
|
27210
|
+
const nearTab = near ? homeTabOf(doc, near.id) ?? void 0 : void 0;
|
|
27211
|
+
const position = args.position ?? placeFor(doc, box, tab === void 0 ? near : void 0, args.inputs?.[0] ? "right" : "left", tab ?? nearTab);
|
|
26753
27212
|
const zIndex = args.kind === "section" ? SECTION_Z : Object.values(doc.nodes).reduce((t, n) => Math.max(t, n.zIndex), 0) + 1;
|
|
26754
27213
|
const node = makeNode({ type: WORKFLOW_NODE_TYPE, data, position, size: box, zIndex, createdBy: me });
|
|
26755
27214
|
const links = [
|
|
@@ -26770,7 +27229,7 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
26770
27229
|
return {
|
|
26771
27230
|
ops: [{ type: "node.add", nodeId: node.id, node }, ...edges.ops, ...mention.ops],
|
|
26772
27231
|
targets: links.map((l) => l.source === node.id ? l.target : l.source),
|
|
26773
|
-
done: `N\xF3 ${args.kind} "${nodeName(node)}" criado: ${node.id}${edges.ops.length ? ` com ${edges.ops.length} liga\xE7\xE3o(\xF5es)` : ""}.${edges.warn}${mention.note}`
|
|
27232
|
+
done: `N\xF3 ${args.kind} "${nodeName(node)}" criado: ${node.id}${edges.ops.length ? ` com ${edges.ops.length} liga\xE7\xE3o(\xF5es)` : ""}.${placementNote(doc, node)}${edges.warn}${mention.note}`
|
|
26774
27233
|
};
|
|
26775
27234
|
})
|
|
26776
27235
|
)
|
|
@@ -26844,7 +27303,7 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
26844
27303
|
});
|
|
26845
27304
|
const mention = args.layout_only ? { ops: [], note: "" } : await mentionOps(doc, changes.map((c) => ({ node: c.node, data: c.data, keys: c.dataKeys })));
|
|
26846
27305
|
const touched = changes.filter((c) => c.ops.length);
|
|
26847
|
-
const list = touched.slice(0, 12).map((c) => `"${
|
|
27306
|
+
const list = touched.slice(0, 12).map((c) => `"${oneLine2(nodeName(c.node), 30)}" (${c.keys.join(", ")})`).join("; ");
|
|
26848
27307
|
return {
|
|
26849
27308
|
ops: [...changes.flatMap((c) => c.ops), ...mention.ops],
|
|
26850
27309
|
targets: ids,
|
|
@@ -26947,7 +27406,7 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
26947
27406
|
return {
|
|
26948
27407
|
ops,
|
|
26949
27408
|
targets: [node.id],
|
|
26950
|
-
done: `N\xF3 "${
|
|
27409
|
+
done: `N\xF3 "${oneLine2(nodeName(node), 40)}" (${node.id}): ${written} caminho(s) gravado(s)` + (skipped ? ` (ignorados: ${skipped})` : "") + mention.note
|
|
26951
27410
|
};
|
|
26952
27411
|
},
|
|
26953
27412
|
{ split: true }
|
|
@@ -27017,7 +27476,7 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
27017
27476
|
ops.push(op);
|
|
27018
27477
|
}
|
|
27019
27478
|
}
|
|
27020
|
-
const names = nodeIds.map((n) => `"${
|
|
27479
|
+
const names = nodeIds.map((n) => `"${oneLine2(nodeName(doc.nodes[n]), 40)}"`);
|
|
27021
27480
|
return {
|
|
27022
27481
|
ops,
|
|
27023
27482
|
targets: nodeIds,
|
|
@@ -27099,7 +27558,7 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
27099
27558
|
import { createRequire } from "module";
|
|
27100
27559
|
var require2 = createRequire(import.meta.url);
|
|
27101
27560
|
function readVersion() {
|
|
27102
|
-
if ("0.
|
|
27561
|
+
if ("0.37.1") return "0.37.1";
|
|
27103
27562
|
try {
|
|
27104
27563
|
const pkg = require2("../package.json");
|
|
27105
27564
|
return pkg.version ?? "0.0.0-unknown";
|
|
@@ -27115,6 +27574,7 @@ var SERVER_INSTRUCTIONS = [
|
|
|
27115
27574
|
'M\xEDdia: generate_* gasta diamantes; confira com estimate_cost antes de lotes grandes. Sem project, a gera\xE7\xE3o cai no projeto ativo; billing:"personal" cobra do usu\xE1rio.',
|
|
27116
27575
|
"Calls: search_calls acha, get_call traz a transcri\xE7\xE3o.",
|
|
27117
27576
|
"Canvas online (canvas_*): leia com canvas_read_board antes de editar e siga o estado lido. Cada edi\xE7\xE3o vai num passo s\xF3; se outra pessoa mexeu nos mesmos n\xF3s, a ferramenta recusa e pede releitura. As canvas_* n\xE3o geram m\xEDdia, exceto canvas_run: roda n\xF3s pela aba do Canvas aberta do usu\xE1rio e gasta diamantes; max_diamonds \xE9 o teto que o usu\xE1rio autorizou (dry_run s\xF3 estima). D\xEA nome (label) aos n\xF3s, n\xE3o invente tipos nem portas, e confirme antes de canvas_delete.",
|
|
27577
|
+
"Cada aba \xE9 um plano: ao criar, passe aba (id da se\xE7\xE3o) em canvas_add_node e canvas_upload_media, sen\xE3o o cart\xE3o pode cair em Avulsos. canvas_read_board com aba l\xEA uma aba s\xF3.",
|
|
27118
27578
|
'Mostrar algo ao usu\xE1rio ("olha aqui"): canvas_focus leva a aba do Canvas que ele est\xE1 olhando at\xE9 os n\xF3s e os seleciona uma vez, sem prender a aba, sem gasto e sem escrita no board. follow: true prende a aba na \xE1rea at\xE9 o \xD7: s\xF3 se ele pedir.',
|
|
27119
27579
|
'Arrumar o board: o size gravado \xE9 piso (o cart\xE3o cresce com o conte\xFAdo); use o tamanho "medido" do canvas_read_board. \xC1rea de revis\xE3o: canvas_arrange_rows (uma linha por vers\xE3o); posi\xE7\xE3o/tamanho em lote: canvas_update_nodes com layout_only. N\xE3o afirme que nada se sobrep\xF5e com n\xF3 sem medida.',
|
|
27120
27580
|
'"Aplica os coment\xE1rios" do board: canvas_list_comments (abertos) \u2192 para cada um, leia o n\xF3 ancorado com canvas_read_board (node_ids), aplique a edi\xE7\xE3o pelas canvas_* e feche com canvas_resolve_comment dizendo em uma frase o que fez. Coment\xE1rio amb\xEDguo ou com alvo sumido: responda com pergunta (canvas_reply_comment) e n\xE3o resolva. D\xFAvida sua sobre um n\xF3: canvas_comment ancorado nele. As escritas j\xE1 saem espa\xE7adas (60/min); se ainda vier limite, pare e diga de onde seguir.'
|