beplus-mcp 0.30.0 → 0.31.0
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 +5 -1
- package/dist/index.js +336 -81
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6145,11 +6145,11 @@ var require_format = __commonJS({
|
|
|
6145
6145
|
}
|
|
6146
6146
|
function getFormat(fmtDef) {
|
|
6147
6147
|
const code = fmtDef instanceof RegExp ? (0, codegen_1.regexpCode)(fmtDef) : opts.code.formats ? (0, codegen_1._)`${opts.code.formats}${(0, codegen_1.getProperty)(schema)}` : void 0;
|
|
6148
|
-
const
|
|
6148
|
+
const fmt3 = gen.scopeValue("formats", { key: schema, ref: fmtDef, code });
|
|
6149
6149
|
if (typeof fmtDef == "object" && !(fmtDef instanceof RegExp)) {
|
|
6150
|
-
return [fmtDef.type || "string", fmtDef.validate, (0, codegen_1._)`${
|
|
6150
|
+
return [fmtDef.type || "string", fmtDef.validate, (0, codegen_1._)`${fmt3}.validate`];
|
|
6151
6151
|
}
|
|
6152
|
-
return ["string", fmtDef,
|
|
6152
|
+
return ["string", fmtDef, fmt3];
|
|
6153
6153
|
}
|
|
6154
6154
|
function validCondition() {
|
|
6155
6155
|
if (typeof formatDef == "object" && !(formatDef instanceof RegExp) && formatDef.async) {
|
|
@@ -6811,8 +6811,8 @@ var require_limit = __commonJS({
|
|
|
6811
6811
|
ref: self.formats,
|
|
6812
6812
|
code: opts.code.formats
|
|
6813
6813
|
});
|
|
6814
|
-
const
|
|
6815
|
-
cxt.fail$data((0, codegen_1.or)((0, codegen_1._)`typeof ${
|
|
6814
|
+
const fmt3 = gen.const("fmt", (0, codegen_1._)`${fmts}[${fCxt.schemaCode}]`);
|
|
6815
|
+
cxt.fail$data((0, codegen_1.or)((0, codegen_1._)`typeof ${fmt3} != "object"`, (0, codegen_1._)`${fmt3} instanceof RegExp`, (0, codegen_1._)`typeof ${fmt3}.compare != "function"`, compareCode(fmt3)));
|
|
6816
6816
|
}
|
|
6817
6817
|
function validateFormat() {
|
|
6818
6818
|
const format = fCxt.schema;
|
|
@@ -6822,15 +6822,15 @@ var require_limit = __commonJS({
|
|
|
6822
6822
|
if (typeof fmtDef != "object" || fmtDef instanceof RegExp || typeof fmtDef.compare != "function") {
|
|
6823
6823
|
throw new Error(`"${keyword}": format "${format}" does not define "compare" function`);
|
|
6824
6824
|
}
|
|
6825
|
-
const
|
|
6825
|
+
const fmt3 = gen.scopeValue("formats", {
|
|
6826
6826
|
key: format,
|
|
6827
6827
|
ref: fmtDef,
|
|
6828
6828
|
code: opts.code.formats ? (0, codegen_1._)`${opts.code.formats}${(0, codegen_1.getProperty)(format)}` : void 0
|
|
6829
6829
|
});
|
|
6830
|
-
cxt.fail$data(compareCode(
|
|
6830
|
+
cxt.fail$data(compareCode(fmt3));
|
|
6831
6831
|
}
|
|
6832
|
-
function compareCode(
|
|
6833
|
-
return (0, codegen_1._)`${
|
|
6832
|
+
function compareCode(fmt3) {
|
|
6833
|
+
return (0, codegen_1._)`${fmt3}.compare(${data}, ${schemaCode}) ${KWDs[keyword].fail} 0`;
|
|
6834
6834
|
}
|
|
6835
6835
|
},
|
|
6836
6836
|
dependencies: ["format"]
|
|
@@ -23015,15 +23015,15 @@ function probeJpeg(b) {
|
|
|
23015
23015
|
function probeWebp(b) {
|
|
23016
23016
|
if (b.length < 30) return null;
|
|
23017
23017
|
if (b.toString("ascii", 0, 4) !== "RIFF" || b.toString("ascii", 8, 12) !== "WEBP") return null;
|
|
23018
|
-
const
|
|
23019
|
-
if (
|
|
23018
|
+
const fmt3 = b.toString("ascii", 12, 16);
|
|
23019
|
+
if (fmt3 === "VP8 ") {
|
|
23020
23020
|
return { width: b.readUInt16LE(26) & 16383, height: b.readUInt16LE(28) & 16383 };
|
|
23021
23021
|
}
|
|
23022
|
-
if (
|
|
23022
|
+
if (fmt3 === "VP8L") {
|
|
23023
23023
|
const bits = b.readUInt32LE(21);
|
|
23024
23024
|
return { width: (bits & 16383) + 1, height: (bits >> 14 & 16383) + 1 };
|
|
23025
23025
|
}
|
|
23026
|
-
if (
|
|
23026
|
+
if (fmt3 === "VP8X") {
|
|
23027
23027
|
const w = b[24] | b[25] << 8 | b[26] << 16;
|
|
23028
23028
|
const h = b[27] | b[28] << 8 | b[29] << 16;
|
|
23029
23029
|
return { width: w + 1, height: h + 1 };
|
|
@@ -24086,6 +24086,7 @@ import { createHash } from "crypto";
|
|
|
24086
24086
|
|
|
24087
24087
|
// src/canvas/api.ts
|
|
24088
24088
|
var PINNED_CORE_VERSION = "ca7b3b406184c7f679f555c3a008013197182b23";
|
|
24089
|
+
var RUN_REQUEST_TIMEOUT_MS = 4e4;
|
|
24089
24090
|
function errorRaw(err) {
|
|
24090
24091
|
if (!(err instanceof ApiError)) return void 0;
|
|
24091
24092
|
const raw = err.body?.error?.raw;
|
|
@@ -24126,13 +24127,13 @@ var CanvasApi = class {
|
|
|
24126
24127
|
createBoard(body2) {
|
|
24127
24128
|
return this.req("POST", "/boards", { body: body2 });
|
|
24128
24129
|
}
|
|
24129
|
-
snapshot(
|
|
24130
|
-
return this.req("GET", `/boards/${
|
|
24130
|
+
snapshot(boardId4) {
|
|
24131
|
+
return this.req("GET", `/boards/${boardId4}`);
|
|
24131
24132
|
}
|
|
24132
24133
|
/** Replay depois de `after`. `null` quando o servidor manda reler a foto (410). */
|
|
24133
|
-
async opsAfter(
|
|
24134
|
+
async opsAfter(boardId4, after) {
|
|
24134
24135
|
try {
|
|
24135
|
-
const { envelopes } = await this.req("GET", `/boards/${
|
|
24136
|
+
const { envelopes } = await this.req("GET", `/boards/${boardId4}/ops`, {
|
|
24136
24137
|
query: { after }
|
|
24137
24138
|
});
|
|
24138
24139
|
return envelopes;
|
|
@@ -24141,8 +24142,8 @@ var CanvasApi = class {
|
|
|
24141
24142
|
throw e;
|
|
24142
24143
|
}
|
|
24143
24144
|
}
|
|
24144
|
-
async commit(
|
|
24145
|
-
const send = () => this.req("POST", `/boards/${
|
|
24145
|
+
async commit(boardId4, ops) {
|
|
24146
|
+
const send = () => this.req("POST", `/boards/${boardId4}/ops`, {
|
|
24146
24147
|
body: { coreVersion: this.coreVersion, ops }
|
|
24147
24148
|
});
|
|
24148
24149
|
try {
|
|
@@ -24163,18 +24164,18 @@ var CanvasApi = class {
|
|
|
24163
24164
|
}
|
|
24164
24165
|
}
|
|
24165
24166
|
}
|
|
24166
|
-
members(
|
|
24167
|
-
return this.req("GET", `/boards/${
|
|
24167
|
+
members(boardId4) {
|
|
24168
|
+
return this.req("GET", `/boards/${boardId4}/members`);
|
|
24168
24169
|
}
|
|
24169
|
-
putMember(
|
|
24170
|
-
return this.req("PUT", `/boards/${
|
|
24170
|
+
putMember(boardId4, userId, role) {
|
|
24171
|
+
return this.req("PUT", `/boards/${boardId4}/members/${userId}`, { body: { role } });
|
|
24171
24172
|
}
|
|
24172
|
-
removeMember(
|
|
24173
|
-
return this.req("DELETE", `/boards/${
|
|
24173
|
+
removeMember(boardId4, userId) {
|
|
24174
|
+
return this.req("DELETE", `/boards/${boardId4}/members/${userId}`);
|
|
24174
24175
|
}
|
|
24175
24176
|
// ── comentários (academy-backend #313) ────────────────────────────────────
|
|
24176
|
-
listComments(
|
|
24177
|
-
return this.req("GET", `/boards/${
|
|
24177
|
+
listComments(boardId4, status = "open") {
|
|
24178
|
+
return this.req("GET", `/boards/${boardId4}/comments`, { query: { status } });
|
|
24178
24179
|
}
|
|
24179
24180
|
/**
|
|
24180
24181
|
* Escrita de comentário passa por aqui: o back limita a 60 por minuto por pessoa
|
|
@@ -24200,14 +24201,25 @@ var CanvasApi = class {
|
|
|
24200
24201
|
}
|
|
24201
24202
|
}
|
|
24202
24203
|
/** Raiz ou resposta. O back devolve sempre a THREAD DA RAIZ (resposta nova = última de `replies`). */
|
|
24203
|
-
createComment(
|
|
24204
|
-
return this.write("POST", `/boards/${
|
|
24204
|
+
createComment(boardId4, body2) {
|
|
24205
|
+
return this.write("POST", `/boards/${boardId4}/comments`, body2);
|
|
24205
24206
|
}
|
|
24206
|
-
resolveComment(
|
|
24207
|
-
return this.write("POST", `/boards/${
|
|
24207
|
+
resolveComment(boardId4, commentId2) {
|
|
24208
|
+
return this.write("POST", `/boards/${boardId4}/comments/${commentId2}/resolve`);
|
|
24208
24209
|
}
|
|
24209
|
-
reopenComment(
|
|
24210
|
-
return this.write("POST", `/boards/${
|
|
24210
|
+
reopenComment(boardId4, commentId2) {
|
|
24211
|
+
return this.write("POST", `/boards/${boardId4}/comments/${commentId2}/reopen`);
|
|
24212
|
+
}
|
|
24213
|
+
// ── execução pela aba do Canvas (CR1, academy-backend #318) ───────────────
|
|
24214
|
+
/**
|
|
24215
|
+
* Pede para a aba do Canvas da pessoa rodar. O servidor espera a aba até 20 s;
|
|
24216
|
+
* aqui a espera é maior para o prazo do servidor vencer antes do nosso.
|
|
24217
|
+
*/
|
|
24218
|
+
runRequest(boardId4, body2) {
|
|
24219
|
+
return this.req("POST", `/boards/${boardId4}/run-requests`, { body: body2, timeoutMs: RUN_REQUEST_TIMEOUT_MS });
|
|
24220
|
+
}
|
|
24221
|
+
runStatus(boardId4, requestId) {
|
|
24222
|
+
return this.req("GET", `/boards/${boardId4}/run-requests/${requestId}`);
|
|
24211
24223
|
}
|
|
24212
24224
|
/** Só para os testes conferirem o aprendizado. */
|
|
24213
24225
|
get currentCoreVersion() {
|
|
@@ -24483,8 +24495,8 @@ function checkOp(op) {
|
|
|
24483
24495
|
return null;
|
|
24484
24496
|
}
|
|
24485
24497
|
}
|
|
24486
|
-
function envelope(
|
|
24487
|
-
return { id: randomUUID(), boardId:
|
|
24498
|
+
function envelope(boardId4, op, actorId) {
|
|
24499
|
+
return { id: randomUUID(), boardId: boardId4, clientId: CLIENT_ID, actorId, seq: null, ts: Date.now(), op };
|
|
24488
24500
|
}
|
|
24489
24501
|
function checkEnvelope(env) {
|
|
24490
24502
|
const bad = checkOp(env.op);
|
|
@@ -24539,13 +24551,13 @@ function makeEdge(init) {
|
|
|
24539
24551
|
}
|
|
24540
24552
|
var setValue = (value) => ({ kind: "value", value });
|
|
24541
24553
|
var unsetValue = () => ({ kind: "unset" });
|
|
24542
|
-
function removeNodeOps(doc,
|
|
24554
|
+
function removeNodeOps(doc, nodeId2) {
|
|
24543
24555
|
const ops = [];
|
|
24544
|
-
const edgeIds = Object.keys(doc.edges).filter((id) => doc.edges[id].source ===
|
|
24556
|
+
const edgeIds = Object.keys(doc.edges).filter((id) => doc.edges[id].source === nodeId2 || doc.edges[id].target === nodeId2).sort();
|
|
24545
24557
|
for (const edgeId of edgeIds) ops.push({ type: "edge.remove", edgeId });
|
|
24546
|
-
const history = Object.hasOwn(doc.nodeHistory,
|
|
24547
|
-
if (history) for (const resultId of [...history].reverse()) ops.push({ type: "history.remove", nodeId, resultId });
|
|
24548
|
-
ops.push({ type: "node.remove", nodeId });
|
|
24558
|
+
const history = Object.hasOwn(doc.nodeHistory, nodeId2) ? doc.nodeHistory[nodeId2] : void 0;
|
|
24559
|
+
if (history) for (const resultId of [...history].reverse()) ops.push({ type: "history.remove", nodeId: nodeId2, resultId });
|
|
24560
|
+
ops.push({ type: "node.remove", nodeId: nodeId2 });
|
|
24549
24561
|
return ops;
|
|
24550
24562
|
}
|
|
24551
24563
|
function batchOf(ops) {
|
|
@@ -24561,14 +24573,14 @@ var OpTooLargeError = class extends Error {
|
|
|
24561
24573
|
op;
|
|
24562
24574
|
bytes;
|
|
24563
24575
|
};
|
|
24564
|
-
function packEnvelopes(
|
|
24576
|
+
function packEnvelopes(boardId4, ops, actorId, limit = MAX_OP_BYTES - 1024) {
|
|
24565
24577
|
const bytes = (v) => Buffer.byteLength(JSON.stringify(v));
|
|
24566
|
-
const overhead = bytes(envelope(
|
|
24578
|
+
const overhead = bytes(envelope(boardId4, { type: "batch", ops: [] }, actorId));
|
|
24567
24579
|
const out = [];
|
|
24568
24580
|
let cur = [];
|
|
24569
24581
|
let size = overhead;
|
|
24570
24582
|
const flush = () => {
|
|
24571
|
-
if (cur.length) out.push(envelope(
|
|
24583
|
+
if (cur.length) out.push(envelope(boardId4, batchOf(cur), actorId));
|
|
24572
24584
|
cur = [];
|
|
24573
24585
|
size = overhead;
|
|
24574
24586
|
};
|
|
@@ -24946,8 +24958,8 @@ function mmss(t) {
|
|
|
24946
24958
|
const pad = (n) => String(n).padStart(2, "0");
|
|
24947
24959
|
return h ? `${h}:${pad(m)}:${pad(s)}` : `${pad(m)}:${pad(s)}`;
|
|
24948
24960
|
}
|
|
24949
|
-
function nodeRef(doc,
|
|
24950
|
-
const node = doc.nodes[
|
|
24961
|
+
function nodeRef(doc, nodeId2) {
|
|
24962
|
+
const node = doc.nodes[nodeId2];
|
|
24951
24963
|
const kind = nodeKind(node) ?? node.type;
|
|
24952
24964
|
return `"${oneLine(nodeName(node), 60)}" (${kind}, ${node.id})`;
|
|
24953
24965
|
}
|
|
@@ -24971,13 +24983,13 @@ function outputKeyOf(entry) {
|
|
|
24971
24983
|
if (typeof entry.url === "string" && entry.url !== "") return `url-${hashString(entry.url)}`;
|
|
24972
24984
|
return null;
|
|
24973
24985
|
}
|
|
24974
|
-
function versionOf(doc,
|
|
24975
|
-
const ids = doc.nodeHistory?.[
|
|
24986
|
+
function versionOf(doc, nodeId2, outputKey) {
|
|
24987
|
+
const ids = doc.nodeHistory?.[nodeId2];
|
|
24976
24988
|
if (Array.isArray(ids)) {
|
|
24977
24989
|
const i = ids.indexOf(outputKey);
|
|
24978
24990
|
if (i >= 0) return i + 1;
|
|
24979
24991
|
}
|
|
24980
|
-
const history = doc.nodes[
|
|
24992
|
+
const history = doc.nodes[nodeId2]?.data.history;
|
|
24981
24993
|
if (Array.isArray(history)) {
|
|
24982
24994
|
const i = history.findIndex(
|
|
24983
24995
|
(h) => typeof h === "object" && h !== null && !Array.isArray(h) && outputKeyOf(h) === outputKey
|
|
@@ -25447,17 +25459,17 @@ function holdsOne(doc, node) {
|
|
|
25447
25459
|
if (node.data.holds === "many") return false;
|
|
25448
25460
|
return itemsOf(node).length === 1 && Object.values(doc.edges).some((e) => e.source === node.id);
|
|
25449
25461
|
}
|
|
25450
|
-
function needMediaNode(doc,
|
|
25451
|
-
const node = doc.nodes[
|
|
25452
|
-
if (!node) throw new CanvasToolError(`N\xF3 ${
|
|
25462
|
+
function needMediaNode(doc, nodeId2) {
|
|
25463
|
+
const node = doc.nodes[nodeId2];
|
|
25464
|
+
if (!node) throw new CanvasToolError(`N\xF3 ${nodeId2} n\xE3o existe no board. Releia com canvas_read_board.`);
|
|
25453
25465
|
if (nodeKind(node) !== "media") {
|
|
25454
25466
|
throw new CanvasToolError(
|
|
25455
|
-
`O n\xF3 ${
|
|
25467
|
+
`O n\xF3 ${nodeId2} ("${oneLine(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.`
|
|
25456
25468
|
);
|
|
25457
25469
|
}
|
|
25458
25470
|
return node;
|
|
25459
25471
|
}
|
|
25460
|
-
function payload(u,
|
|
25472
|
+
function payload(u, nodeId2) {
|
|
25461
25473
|
const out = { url: u.url, mime: u.mime, bytes: u.bytes };
|
|
25462
25474
|
if (u.meta.duration !== void 0) out.duration = u.meta.duration;
|
|
25463
25475
|
if (u.meta.width !== void 0) out.width = u.meta.width;
|
|
@@ -25466,14 +25478,14 @@ function payload(u, nodeId) {
|
|
|
25466
25478
|
out.media_item = mediaItem(u);
|
|
25467
25479
|
if (u.kind !== "file") {
|
|
25468
25480
|
out.sequence_asset = sequenceAsset(u);
|
|
25469
|
-
out.libraryItemId = libraryItemId(u,
|
|
25481
|
+
out.libraryItemId = libraryItemId(u, nodeId2);
|
|
25470
25482
|
}
|
|
25471
25483
|
return JSON.stringify(out);
|
|
25472
25484
|
}
|
|
25473
|
-
function sequenceHint(u,
|
|
25485
|
+
function sequenceHint(u, nodeId2) {
|
|
25474
25486
|
if (u.kind === "file") return "Documento: entra no n\xF3 M\xEDdia, n\xE3o na timeline da Montagem.";
|
|
25475
25487
|
const lines = [
|
|
25476
|
-
"Num clipe da timeline da Montagem (data.timeline; data.sequence s\xF3 em n\xF3 que ainda n\xE3o migrou): use sequence_asset como `asset` e libraryItemId como est\xE1" + (
|
|
25488
|
+
"Num clipe da timeline da Montagem (data.timeline; data.sequence s\xF3 em n\xF3 que ainda n\xE3o migrou): use sequence_asset como `asset` e libraryItemId como est\xE1" + (nodeId2 ? "." : ", trocando <id do n\xF3 M\xEDdia> pelo id do n\xF3 onde o item ficou.")
|
|
25477
25489
|
];
|
|
25478
25490
|
if (u.meta.duration !== void 0) {
|
|
25479
25491
|
const at30 = Math.floor(u.meta.duration * 30 + 1e-9);
|
|
@@ -25530,14 +25542,14 @@ URL: ${u.url}`;
|
|
|
25530
25542
|
if (!args.board_id) {
|
|
25531
25543
|
return [head, "", payload(u), "", sequenceHint(u)].join("\n");
|
|
25532
25544
|
}
|
|
25533
|
-
const
|
|
25534
|
-
let
|
|
25545
|
+
const boardId4 = args.board_id;
|
|
25546
|
+
let nodeId2 = args.node_id;
|
|
25535
25547
|
let done;
|
|
25536
25548
|
try {
|
|
25537
|
-
done = await edit(
|
|
25549
|
+
done = await edit(boardId4, async (doc) => {
|
|
25538
25550
|
const item = mediaItem(u);
|
|
25539
|
-
if (
|
|
25540
|
-
const node = needMediaNode(doc,
|
|
25551
|
+
if (nodeId2) {
|
|
25552
|
+
const node = needMediaNode(doc, nodeId2);
|
|
25541
25553
|
const replacing = args.replace ?? holdsOne(doc, node);
|
|
25542
25554
|
const items = replacing ? [item] : [...itemsOf(node), item];
|
|
25543
25555
|
if (items.length > MAX_MEDIA_ITEMS) {
|
|
@@ -25559,7 +25571,7 @@ URL: ${u.url}`;
|
|
|
25559
25571
|
zIndex: Object.values(doc.nodes).reduce((t, n) => Math.max(t, n.zIndex), 0) + 1,
|
|
25560
25572
|
createdBy: await api.me()
|
|
25561
25573
|
});
|
|
25562
|
-
|
|
25574
|
+
nodeId2 = created.id;
|
|
25563
25575
|
return {
|
|
25564
25576
|
ops: [{ type: "node.add", nodeId: created.id, node: created }],
|
|
25565
25577
|
targets: [],
|
|
@@ -25575,11 +25587,253 @@ N\xE3o suba de novo: releia com canvas_read_board e grave media_item em data.ite
|
|
|
25575
25587
|
${payload(u)}`
|
|
25576
25588
|
);
|
|
25577
25589
|
}
|
|
25578
|
-
return [head, done, "", payload(u,
|
|
25590
|
+
return [head, done, "", payload(u, nodeId2), "", sequenceHint(u, nodeId2)].join("\n");
|
|
25579
25591
|
})
|
|
25580
25592
|
);
|
|
25581
25593
|
}
|
|
25582
25594
|
|
|
25595
|
+
// src/tools/canvas-run.ts
|
|
25596
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
25597
|
+
var MAX_REMEMBERED = 50;
|
|
25598
|
+
var boardId2 = external_exports.string().uuid().describe("Id (uuid) do board.");
|
|
25599
|
+
var nodeId = external_exports.string().min(1).max(128);
|
|
25600
|
+
var fmt2 = (n) => new Intl.NumberFormat("pt-BR").format(n);
|
|
25601
|
+
var dia = (n) => n === null || n === void 0 ? "sem estimativa" : `${fmt2(n)} \u{1F48E}`;
|
|
25602
|
+
function prettyClient(name) {
|
|
25603
|
+
if (!name) return "MCP";
|
|
25604
|
+
return name.split(/[-_\s]+/).filter(Boolean).map((w) => w[0].toUpperCase() + w.slice(1)).join(" ").slice(0, 80);
|
|
25605
|
+
}
|
|
25606
|
+
function modeText(mode) {
|
|
25607
|
+
return mode === "simulated" ? "Simulado (n\xE3o gasta)" : mode === "live" ? "Real" : mode ?? "?";
|
|
25608
|
+
}
|
|
25609
|
+
function estimateLines(estimate, titleOf) {
|
|
25610
|
+
if (!estimate) return [];
|
|
25611
|
+
const lines = [];
|
|
25612
|
+
const nodes = estimate.nodes ?? [];
|
|
25613
|
+
const now = nodes.filter((n) => n.willRun);
|
|
25614
|
+
for (const n of now) {
|
|
25615
|
+
const cost = n.error ? `estimativa falhou (${n.error})` : dia(n.diamonds);
|
|
25616
|
+
lines.push(`- ${n.title ?? titleOf(n.nodeId)} (${n.nodeId}): ${cost}`);
|
|
25617
|
+
}
|
|
25618
|
+
const cached2 = nodes.filter((n) => !n.willRun && !n.afterApproval).length;
|
|
25619
|
+
if (cached2) lines.push(`Em cache (n\xE3o rodam): ${cached2}.`);
|
|
25620
|
+
const later = estimate.later?.nodes?.length ?? 0;
|
|
25621
|
+
if (later) lines.push(`Esperando aprova\xE7\xE3o no board depois disso: ${later} n\xF3(s), \u2248 ${dia(estimate.later?.total ?? 0)} (fora desta conta).`);
|
|
25622
|
+
if (estimate.unknown?.length) {
|
|
25623
|
+
lines.push(`Sem estimativa: ${estimate.unknown.length} n\xF3(s) (texto cobra por token; o total \xE9 piso).`);
|
|
25624
|
+
}
|
|
25625
|
+
return lines;
|
|
25626
|
+
}
|
|
25627
|
+
function targetOf(args) {
|
|
25628
|
+
const given = [args.node_ids?.length ? 1 : 0, args.from_node_id ? 1 : 0, args.all ? 1 : 0].reduce((a, b) => a + b, 0);
|
|
25629
|
+
if (given !== 1) {
|
|
25630
|
+
throw new CanvasToolError("Diga o que rodar com UM destes: node_ids (os n\xF3s), from_node_id (daqui para frente) ou all: true (tudo).");
|
|
25631
|
+
}
|
|
25632
|
+
if (args.all) return { kind: "all" };
|
|
25633
|
+
if (args.from_node_id) return { kind: "from", nodeId: args.from_node_id };
|
|
25634
|
+
return { kind: "nodes", nodeIds: [...new Set(args.node_ids)] };
|
|
25635
|
+
}
|
|
25636
|
+
function registerCanvasRunTools(server, api, run) {
|
|
25637
|
+
const remembered = /* @__PURE__ */ new Map();
|
|
25638
|
+
const remember = (requestId, entry) => {
|
|
25639
|
+
remembered.delete(requestId);
|
|
25640
|
+
remembered.set(requestId, entry);
|
|
25641
|
+
while (remembered.size > MAX_REMEMBERED) remembered.delete(remembered.keys().next().value);
|
|
25642
|
+
};
|
|
25643
|
+
async function titles(board) {
|
|
25644
|
+
try {
|
|
25645
|
+
const snap = await api.snapshot(board);
|
|
25646
|
+
return (id) => snap.doc.nodes[id] ? nodeName(snap.doc.nodes[id]) : id;
|
|
25647
|
+
} catch {
|
|
25648
|
+
return (id) => id;
|
|
25649
|
+
}
|
|
25650
|
+
}
|
|
25651
|
+
function explain(e, requestId) {
|
|
25652
|
+
if (!(e instanceof ApiError)) throw e;
|
|
25653
|
+
const reason = errorRaw(e)?.reason;
|
|
25654
|
+
const unknownFate = requestId && (e.httpStatus === 0 || e.httpStatus === 408 || reason === "tab-timeout" || reason === "tab-bad-answer" || e.httpStatus >= 500 && e.httpStatus !== 501);
|
|
25655
|
+
if (unknownFate) {
|
|
25656
|
+
throw new CanvasToolError(
|
|
25657
|
+
`N\xE3o d\xE1 para saber se a aba come\xE7ou a rodar (${e.message}). N\xC3O pe\xE7a um pedido novo: consulte canvas_run_status com request_id "${requestId}". Se precisar repetir, chame canvas_run com o mesmo request_id: \xE9 seguro, a aba n\xE3o roda duas vezes.`
|
|
25658
|
+
);
|
|
25659
|
+
}
|
|
25660
|
+
if (reason === "no-tab") {
|
|
25661
|
+
throw new CanvasToolError(
|
|
25662
|
+
"Nenhuma aba do Canvas sua est\xE1 aberta neste board (ou a aba \xE9 de uma vers\xE3o sem esta fun\xE7\xE3o). Pe\xE7a para abrir o board no Canvas com a mesma conta deste MCP e tente de novo. Nada rodou."
|
|
25663
|
+
);
|
|
25664
|
+
}
|
|
25665
|
+
if (e.httpStatus === 404 && reason !== "unknown-request") {
|
|
25666
|
+
if (!/board/i.test(e.message)) {
|
|
25667
|
+
throw new CanvasToolError("O servidor do Canvas ainda n\xE3o tem a execu\xE7\xE3o pelo MCP (academy-backend sem a CR1). Nada rodou.");
|
|
25668
|
+
}
|
|
25669
|
+
throw new CanvasToolError("Board n\xE3o encontrado, ou voc\xEA n\xE3o \xE9 membro dele. Confira o id em canvas_list_boards.");
|
|
25670
|
+
}
|
|
25671
|
+
if (e.httpStatus === 403 && (!api.usesPat || /ialab:/.test(e.message))) {
|
|
25672
|
+
throw new CanvasToolError(
|
|
25673
|
+
"O login pelo navegador deste MCP n\xE3o tem a permiss\xE3o ialab:spend, que rodar exige. Rode `beplus-mcp login` de novo e autorize."
|
|
25674
|
+
);
|
|
25675
|
+
}
|
|
25676
|
+
if (e.httpStatus === 403) throw new CanvasToolError(`Sem permiss\xE3o para rodar neste board (s\xF3 dono e editor rodam): ${e.message}.`);
|
|
25677
|
+
if (e.httpStatus === 400) throw new CanvasToolError(`O servidor recusou o pedido: ${e.message}.`);
|
|
25678
|
+
if (e.httpStatus === 429) throw new CanvasToolError("Limite de pedidos de execu\xE7\xE3o (20 por minuto). Espere um minuto.");
|
|
25679
|
+
throw e;
|
|
25680
|
+
}
|
|
25681
|
+
function answerText(a, requestId, max, titleOf) {
|
|
25682
|
+
const est = estimateLines(a.estimate, titleOf);
|
|
25683
|
+
const total = a.estimate ? `${dia(a.estimate.total)} (teto ${fmt2(max)})` : "";
|
|
25684
|
+
const again = a.repeated ? " (a aba j\xE1 tinha recebido este request_id; esta \xE9 a mesma resposta)" : "";
|
|
25685
|
+
if (a.status === "estimate") {
|
|
25686
|
+
return [`Estimativa, nada rodou${again}. Modo ${modeText(a.mode)}. Total agora: ${total}.`, ...est, cabeLine(a, max)].filter(Boolean).join("\n");
|
|
25687
|
+
}
|
|
25688
|
+
if (a.status === "nothing") return `Nada para rodar${again}: ${a.message ?? "o board j\xE1 est\xE1 em dia."}`;
|
|
25689
|
+
const willRun = (a.estimate?.nodes ?? []).filter((n) => n.willRun).map((n) => n.nodeId);
|
|
25690
|
+
return [
|
|
25691
|
+
`Rodando pela sua aba do Canvas${again}. Modo ${modeText(a.mode)}. Estimativa: ${total}.`,
|
|
25692
|
+
...est,
|
|
25693
|
+
`request_id: ${requestId}. Andamento: canvas_run_status (board_id, request_id). Resultado: canvas_read_board com node_ids [${willRun.slice(0, 20).join(", ")}] quando terminar.`
|
|
25694
|
+
].join("\n");
|
|
25695
|
+
}
|
|
25696
|
+
function cabeLine(a, max) {
|
|
25697
|
+
if (!a.estimate) return "";
|
|
25698
|
+
return a.estimate.total <= max ? "Cabe no teto: repita sem dry_run para rodar." : `Passa do teto (${fmt2(max)}): s\xF3 roda com max_diamonds maior, se o usu\xE1rio autorizar.`;
|
|
25699
|
+
}
|
|
25700
|
+
server.registerTool(
|
|
25701
|
+
"canvas_run",
|
|
25702
|
+
{
|
|
25703
|
+
title: "Canvas: rodar n\xF3s",
|
|
25704
|
+
description: "Roda n\xF3s do board pela aba do Canvas que o usu\xE1rio tem aberta nele (mesma conta; sem aba aberta, nada roda). GASTA DIAMANTES no modo Real. A aba estima como o bot\xE3o Rodar e s\xF3 roda se a estimativa couber em max_diamonds (obrigat\xF3rio: o teto que o usu\xE1rio autorizou; nunca invente um valor alto). dry_run: true s\xF3 estima. Alvo, um destes: node_ids (roda esses n\xF3s mesmo em cache, gerando e gastando de novo, como o Rodar do cart\xE3o), from_node_id (o n\xF3 e tudo depois dele, tamb\xE9m de novo) ou all: true (s\xF3 o que mudou, como o Rodar tudo). simulated: true s\xF3 vale com a aba no modo Simulado; sem ele, a aba precisa estar no Real. Prompt com PT editado e sem aplicar no EN: a aba recusa e diz qual (aplique no cart\xE3o). Devolve o que vai rodar, o custo e o request_id; acompanhe com canvas_run_status e leia o resultado com canvas_read_board. Se a resposta disser que n\xE3o d\xE1 para saber se come\xE7ou, consulte o andamento e, para repetir, use o MESMO request_id.",
|
|
25705
|
+
inputSchema: {
|
|
25706
|
+
board_id: boardId2,
|
|
25707
|
+
node_ids: external_exports.array(nodeId).min(1).max(100).optional().describe("Os n\xF3s a rodar (como o Rodar do cart\xE3o/sele\xE7\xE3o)."),
|
|
25708
|
+
from_node_id: nodeId.optional().describe("Rodar daqui para frente: este n\xF3 e tudo que depende dele."),
|
|
25709
|
+
all: external_exports.boolean().optional().describe("true: Rodar tudo (s\xF3 o que mudou)."),
|
|
25710
|
+
max_diamonds: external_exports.number().finite().min(0).max(1e6).describe("Teto de diamantes desta execu\xE7\xE3o. Obrigat\xF3rio."),
|
|
25711
|
+
dry_run: external_exports.boolean().optional().describe("true: s\xF3 estima, nada roda."),
|
|
25712
|
+
simulated: external_exports.boolean().optional().describe("true: o pedido \xE9 para o modo Simulado (a aba precisa estar nele)."),
|
|
25713
|
+
label: external_exports.string().trim().min(1).max(80).optional().describe('Quem pede, como a aba mostra ("Rodando a pedido de \u2026").'),
|
|
25714
|
+
request_id: external_exports.string().uuid().optional().describe("S\xF3 para repetir um pedido cujo destino ficou incerto.")
|
|
25715
|
+
},
|
|
25716
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true }
|
|
25717
|
+
},
|
|
25718
|
+
async (args) => run(async () => {
|
|
25719
|
+
const target = targetOf(args);
|
|
25720
|
+
const requestId = (args.request_id ?? randomUUID3()).toLowerCase();
|
|
25721
|
+
const label = args.label ?? prettyClient(server.server.getClientVersion()?.name);
|
|
25722
|
+
let answer;
|
|
25723
|
+
try {
|
|
25724
|
+
answer = await api.runRequest(args.board_id, {
|
|
25725
|
+
requestId,
|
|
25726
|
+
target,
|
|
25727
|
+
maxDiamonds: args.max_diamonds,
|
|
25728
|
+
dryRun: args.dry_run === true,
|
|
25729
|
+
simulated: args.simulated === true,
|
|
25730
|
+
label
|
|
25731
|
+
});
|
|
25732
|
+
} catch (e) {
|
|
25733
|
+
explain(e, requestId);
|
|
25734
|
+
}
|
|
25735
|
+
const titleOf = await titles(args.board_id);
|
|
25736
|
+
if (answer.ok !== true) {
|
|
25737
|
+
const est = estimateLines(answer.estimate, titleOf);
|
|
25738
|
+
throw new CanvasToolError(
|
|
25739
|
+
[`A aba recusou, nada rodou (${answer.reason ?? "sem motivo"}): ${answer.message ?? ""}`.trim(), ...est].join("\n")
|
|
25740
|
+
);
|
|
25741
|
+
}
|
|
25742
|
+
const nodeIds = (answer.estimate?.nodes ?? []).filter((n) => n.willRun).map((n) => n.nodeId);
|
|
25743
|
+
if (answer.status === "started") {
|
|
25744
|
+
remember(requestId, {
|
|
25745
|
+
boardId: args.board_id,
|
|
25746
|
+
nodeIds: nodeIds.length ? nodeIds : target.kind === "nodes" ? target.nodeIds : target.kind === "from" ? [target.nodeId] : []
|
|
25747
|
+
});
|
|
25748
|
+
}
|
|
25749
|
+
return answerText(answer, requestId, args.max_diamonds, titleOf);
|
|
25750
|
+
})
|
|
25751
|
+
);
|
|
25752
|
+
server.registerTool(
|
|
25753
|
+
"canvas_run_status",
|
|
25754
|
+
{
|
|
25755
|
+
title: "Canvas: andamento da execu\xE7\xE3o",
|
|
25756
|
+
description: "Andamento de um pedido do canvas_run: estado de cada n\xF3, estimado e gasto. Pergunta \xE0 aba do Canvas que rodou; se ela fechou, l\xEA o estado de execu\xE7\xE3o do board para os n\xF3s do pedido (os que este MCP lembra, ou node_ids). S\xF3 leitura.",
|
|
25757
|
+
inputSchema: {
|
|
25758
|
+
board_id: boardId2,
|
|
25759
|
+
request_id: external_exports.string().uuid().describe("O request_id que o canvas_run devolveu."),
|
|
25760
|
+
node_ids: external_exports.array(nodeId).min(1).max(100).optional().describe("Os n\xF3s a conferir, se o MCP n\xE3o lembra do pedido.")
|
|
25761
|
+
},
|
|
25762
|
+
annotations: { readOnlyHint: true, openWorldHint: true }
|
|
25763
|
+
},
|
|
25764
|
+
async ({ board_id, request_id, node_ids }) => run(async () => {
|
|
25765
|
+
const requestId = request_id.toLowerCase();
|
|
25766
|
+
let why = "";
|
|
25767
|
+
try {
|
|
25768
|
+
return statusText(await api.runStatus(board_id, requestId), await titles(board_id));
|
|
25769
|
+
} catch (e) {
|
|
25770
|
+
const reason = errorRaw(e)?.reason;
|
|
25771
|
+
if (!(e instanceof ApiError) || reason !== "unknown-request" && reason !== "no-tab") explain(e);
|
|
25772
|
+
why = reason === "no-tab" ? "Nenhuma aba do Canvas sua est\xE1 aberta neste board." : "Nenhuma aba aberta conhece este pedido.";
|
|
25773
|
+
}
|
|
25774
|
+
const ids = node_ids ?? remembered.get(requestId)?.nodeIds;
|
|
25775
|
+
if (!ids?.length) {
|
|
25776
|
+
return `${why} Sem a aba, o andamento sai do estado de execu\xE7\xE3o do board: chame de novo com node_ids (os n\xF3s que o pedido rodava).`;
|
|
25777
|
+
}
|
|
25778
|
+
return `${why} Pelo estado de execu\xE7\xE3o do board:
|
|
25779
|
+
${fromRuns(await api.snapshot(board_id), ids)}`;
|
|
25780
|
+
})
|
|
25781
|
+
);
|
|
25782
|
+
}
|
|
25783
|
+
var STATE_TEXT = {
|
|
25784
|
+
preparing: "a aba est\xE1 estimando e conferindo",
|
|
25785
|
+
running: "rodando",
|
|
25786
|
+
done: "terminou",
|
|
25787
|
+
failed: "terminou com erro",
|
|
25788
|
+
cancelled: "cancelado",
|
|
25789
|
+
refused: "recusado",
|
|
25790
|
+
nothing: "nada para rodar",
|
|
25791
|
+
estimate: "s\xF3 estimativa"
|
|
25792
|
+
};
|
|
25793
|
+
var NODE_TEXT = {
|
|
25794
|
+
idle: "parado",
|
|
25795
|
+
waiting: "esperando o montante",
|
|
25796
|
+
queued: "na fila",
|
|
25797
|
+
running: "rodando",
|
|
25798
|
+
done: "pronto",
|
|
25799
|
+
error: "erro",
|
|
25800
|
+
cancelled: "cancelado",
|
|
25801
|
+
skipped: "pulado (o montante falhou)",
|
|
25802
|
+
blocked: "esperando aprova\xE7\xE3o",
|
|
25803
|
+
claimed: "outra pessoa est\xE1 rodando",
|
|
25804
|
+
cached: "em cache"
|
|
25805
|
+
};
|
|
25806
|
+
function statusText(a, titleOf) {
|
|
25807
|
+
const head = [`Pedido ${a.requestId}: ${STATE_TEXT[a.state] ?? a.state}.`];
|
|
25808
|
+
if (a.mode) head.push(`Modo ${modeText(a.mode)}.`);
|
|
25809
|
+
if (typeof a.estimated === "number") head.push(`Estimado ${dia(a.estimated)}.`);
|
|
25810
|
+
if (typeof a.spent === "number") head.push(`Gasto at\xE9 agora ${dia(a.spent)}.`);
|
|
25811
|
+
const lines = [head.join(" ")];
|
|
25812
|
+
if (a.message) lines.push(a.message);
|
|
25813
|
+
for (const n of a.nodes ?? []) {
|
|
25814
|
+
const extra = n.error ? `: ${n.error}` : n.message ? `: ${n.message}` : "";
|
|
25815
|
+
const outs = typeof n.outputs === "number" && n.outputs > 0 ? ` (${n.outputs} sa\xEDda(s))` : "";
|
|
25816
|
+
lines.push(`- ${n.title ?? titleOf(n.nodeId)} (${n.nodeId}): ${NODE_TEXT[n.status] ?? n.status}${outs}${extra}`);
|
|
25817
|
+
}
|
|
25818
|
+
if (a.state === "done" || a.state === "failed") lines.push("Leia o resultado com canvas_read_board (node_ids).");
|
|
25819
|
+
return lines.join("\n");
|
|
25820
|
+
}
|
|
25821
|
+
function fromRuns(snap, ids) {
|
|
25822
|
+
const byNode = new Map(snap.runs.map((r) => [r.nodeId, r]));
|
|
25823
|
+
return ids.map((id) => {
|
|
25824
|
+
const node = snap.doc.nodes[id];
|
|
25825
|
+
const name = node ? nodeName(node) : id;
|
|
25826
|
+
if (!node) return `- ${id}: o n\xF3 n\xE3o existe mais no board`;
|
|
25827
|
+
const r = byNode.get(id);
|
|
25828
|
+
const st = r?.state ?? null;
|
|
25829
|
+
if (r?.claimedBy) return `- ${name} (${id}): rodando agora`;
|
|
25830
|
+
if (!st?.status) return `- ${name} (${id}): sem estado de execu\xE7\xE3o no servidor (n\xE3o rodou, ou \xE9 n\xF3 que roda s\xF3 na aba)`;
|
|
25831
|
+
const outs = Object.values(st.outputs ?? {}).reduce((sum, list) => sum + (Array.isArray(list) ? list.length : 0), 0);
|
|
25832
|
+
const err = typeof st.error === "string" ? st.error : st.error?.message;
|
|
25833
|
+
return `- ${name} (${id}): ${NODE_TEXT[st.status] ?? st.status}${outs ? ` (${outs} sa\xEDda(s))` : ""}${err ? `: ${err}` : ""}`;
|
|
25834
|
+
}).join("\n");
|
|
25835
|
+
}
|
|
25836
|
+
|
|
25583
25837
|
// src/canvas/mentions.ts
|
|
25584
25838
|
var VIA_MENTION = "viaMention";
|
|
25585
25839
|
var PROMPT_REFS_INPUT = "refs";
|
|
@@ -25737,7 +25991,7 @@ function legacySequenceGuard(node, key) {
|
|
|
25737
25991
|
}
|
|
25738
25992
|
var SECTION_Z = -1e3;
|
|
25739
25993
|
var GAP = 80;
|
|
25740
|
-
var
|
|
25994
|
+
var boardId3 = external_exports.string().uuid().describe("Id (uuid) do board, como sai em canvas_list_boards.");
|
|
25741
25995
|
var nodeIdArg2 = external_exports.string().min(1).max(128);
|
|
25742
25996
|
var point = external_exports.object({ x: external_exports.number().finite(), y: external_exports.number().finite() });
|
|
25743
25997
|
var LABEL_TEXT_SIZES = ["titulo", "subtitulo", "corpo"];
|
|
@@ -25870,9 +26124,9 @@ ${lines.join("\n")}
|
|
|
25870
26124
|
return `\u2705 ${done} em ${envs.length} envelope(s) (seq at\xE9 ${last}).
|
|
25871
26125
|
${lines.join("\n")}${note}`;
|
|
25872
26126
|
}
|
|
25873
|
-
function needNode(doc,
|
|
25874
|
-
const node = doc.nodes[
|
|
25875
|
-
if (!node) throw new CanvasToolError(`N\xF3 ${
|
|
26127
|
+
function needNode(doc, nodeId2) {
|
|
26128
|
+
const node = doc.nodes[nodeId2];
|
|
26129
|
+
if (!node) throw new CanvasToolError(`N\xF3 ${nodeId2} n\xE3o existe no board. Releia com canvas_read_board.`);
|
|
25876
26130
|
return node;
|
|
25877
26131
|
}
|
|
25878
26132
|
function portWarning(doc, source, sourcePort, target, targetPort) {
|
|
@@ -25987,7 +26241,7 @@ ${lines.join("\n")}${note}`;
|
|
|
25987
26241
|
title: "Canvas: ler board",
|
|
25988
26242
|
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.',
|
|
25989
26243
|
inputSchema: {
|
|
25990
|
-
board_id:
|
|
26244
|
+
board_id: boardId3,
|
|
25991
26245
|
node_ids: external_exports.array(nodeIdArg2).max(20).optional().describe("N\xF3s para ver o data (sem blobs, cortes marcados).")
|
|
25992
26246
|
},
|
|
25993
26247
|
annotations: { readOnlyHint: true, openWorldHint: false }
|
|
@@ -26009,7 +26263,7 @@ ${lines.join("\n")}${note}`;
|
|
|
26009
26263
|
title: "Canvas: ler n\xF3 inteiro",
|
|
26010
26264
|
description: 'Devolve o data de UM n\xF3 sem corte nenhum, em JSON compacto, para conferir e fazer diff. Na Montagem, sem path, vem a timeline do editor: data.timeline, ou data.sequence (legado) quando o n\xF3 ainda n\xE3o tem timeline, e o cabe\xE7alho diz qual veio. path escolhe um peda\xE7o ("items" da M\xEDdia, "timeline.meta"); "data" traz o data todo. Diz o tamanho total e o sha256; acima de max_chars vem em partes expl\xEDcitas (offset). N\xE3o substitui o canvas_read_board, que continua obrigat\xF3rio antes de editar. ' + MONTAGE_NOTE,
|
|
26011
26265
|
inputSchema: {
|
|
26012
|
-
board_id:
|
|
26266
|
+
board_id: boardId3,
|
|
26013
26267
|
node_id: nodeIdArg2,
|
|
26014
26268
|
path: external_exports.string().trim().max(200).optional().describe('Caminho dentro do data, com pontos (ex.: "timeline.meta", "items.0"). "data" = o data todo.'),
|
|
26015
26269
|
offset: external_exports.number().int().min(0).optional().describe("In\xEDcio da parte, em caracteres (padr\xE3o 0)."),
|
|
@@ -26118,7 +26372,7 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
26118
26372
|
title: "Canvas: adicionar n\xF3",
|
|
26119
26373
|
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,
|
|
26120
26374
|
inputSchema: {
|
|
26121
|
-
board_id:
|
|
26375
|
+
board_id: boardId3,
|
|
26122
26376
|
kind: external_exports.string().min(1).max(40),
|
|
26123
26377
|
label: external_exports.string().trim().min(1).max(120).optional().describe("Nome do cart\xE3o (data.label)."),
|
|
26124
26378
|
data: external_exports.record(external_exports.unknown()).optional().describe("Campos do data. Ex.: narration {blocks:[{id,text}]}, text {text}, prompt {template}."),
|
|
@@ -26175,7 +26429,7 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
26175
26429
|
title: "Canvas: editar n\xF3",
|
|
26176
26430
|
description: `Muda campos do data de um n\xF3, chave a chave (null apaga a chave), sem executar. ${READ}label renomeia; position move; size {w, h} muda a caixa (piso: o cart\xE3o cresce com o conte\xFAdo). N\xE3o troca o tipo. Cada chave \xE9 gravada inteira: leia antes com canvas_read_node e mande o valor completo j\xE1 revisado, para n\xE3o apagar o que outra pessoa escreveu. Para mudar partes de uma estrutura grande (clipes da timeline), use canvas_patch_node, por caminho; v\xE1rios n\xF3s de uma vez, canvas_update_nodes. ` + MENTION_NOTE + MONTAGE_NOTE,
|
|
26177
26431
|
inputSchema: {
|
|
26178
|
-
board_id:
|
|
26432
|
+
board_id: boardId3,
|
|
26179
26433
|
node_id: nodeIdArg2,
|
|
26180
26434
|
data: external_exports.record(external_exports.unknown()).optional().describe("Chaves de data a gravar. Valor null apaga a chave."),
|
|
26181
26435
|
label: external_exports.string().trim().min(1).max(120).optional(),
|
|
@@ -26203,7 +26457,7 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
26203
26457
|
title: "Canvas: editar v\xE1rios n\xF3s",
|
|
26204
26458
|
description: 'Muda v\xE1rios n\xF3s num passo s\xF3, cada um como no canvas_update_node (position, size, label, data com null apagando). layout_only: true aceita s\xF3 position e size {w, h}, n\xE3o exige leitura e n\xE3o recusa por "outra pessoa mexeu" (nesses dois campos vale quem grava por \xFAltimo). Sem layout_only, exige canvas_read_board nesta sess\xE3o e recusa se outra pessoa mexeu em algum desses n\xF3s. Quebra em envelopes de at\xE9 64 KB e relata cada um. Para arrumar linhas inteiras (t\xEDtulo, prompt, refer\xEAncia, gerador), use canvas_arrange_rows.',
|
|
26205
26459
|
inputSchema: {
|
|
26206
|
-
board_id:
|
|
26460
|
+
board_id: boardId3,
|
|
26207
26461
|
nodes: external_exports.array(
|
|
26208
26462
|
external_exports.object({
|
|
26209
26463
|
node_id: nodeIdArg2,
|
|
@@ -26255,7 +26509,7 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
26255
26509
|
title: "Canvas: gravar por caminho",
|
|
26256
26510
|
description: `Grava v\xE1rios caminhos dentro do data de um n\xF3, sem executar: {path, value} grava, {path, unset: true} apaga. ${READ}O caminho atravessa objetos (o n\xEDvel que falta \xE9 criado) e n\xE3o entra em lista: para mudar um item de lista, grave a lista inteira. Quebra sozinho em envelopes de at\xE9 64 KB, em ordem, e devolve o resultado de cada um; entre envelopes n\xE3o h\xE1 atomicidade (o que entrou fica). Serve para mexer em partes de uma estrutura grande, como clipes da timeline da Montagem, sem reenviar tudo. Leia antes com canvas_read_node. ` + MENTION_NOTE + MONTAGE_NOTE,
|
|
26257
26511
|
inputSchema: {
|
|
26258
|
-
board_id:
|
|
26512
|
+
board_id: boardId3,
|
|
26259
26513
|
node_id: nodeIdArg2,
|
|
26260
26514
|
sets: external_exports.array(
|
|
26261
26515
|
external_exports.object({
|
|
@@ -26354,7 +26608,7 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
26354
26608
|
title: "Canvas: ligar portas",
|
|
26355
26609
|
description: `Liga a sa\xEDda de um n\xF3 \xE0 entrada de outro (ids e portas de canvas_read_board). ${READ}Liga\xE7\xE3o repetida \xE9 ignorada.`,
|
|
26356
26610
|
inputSchema: {
|
|
26357
|
-
board_id:
|
|
26611
|
+
board_id: boardId3,
|
|
26358
26612
|
source: nodeIdArg2,
|
|
26359
26613
|
source_port: external_exports.string().min(1).max(80),
|
|
26360
26614
|
target: nodeIdArg2,
|
|
@@ -26381,7 +26635,7 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
26381
26635
|
title: "Canvas: apagar n\xF3s/liga\xE7\xF5es",
|
|
26382
26636
|
description: `Apaga n\xF3s (com as liga\xE7\xF5es e varia\xE7\xF5es deles) e/ou liga\xE7\xF5es, num passo s\xF3. Irrevers\xEDvel pelo MCP: confirme com o usu\xE1rio antes. ${READ}N\xE3o apaga o board.`,
|
|
26383
26637
|
inputSchema: {
|
|
26384
|
-
board_id:
|
|
26638
|
+
board_id: boardId3,
|
|
26385
26639
|
node_ids: external_exports.array(nodeIdArg2).max(200).optional(),
|
|
26386
26640
|
edge_ids: external_exports.array(nodeIdArg2).max(200).optional()
|
|
26387
26641
|
},
|
|
@@ -26425,7 +26679,7 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
26425
26679
|
{
|
|
26426
26680
|
title: "Canvas: renomear board",
|
|
26427
26681
|
description: `Troca o t\xEDtulo do board (board.set). ${READ}Precisa de papel de editor ou dono.`,
|
|
26428
|
-
inputSchema: { board_id:
|
|
26682
|
+
inputSchema: { board_id: boardId3, title: external_exports.string().trim().min(1).max(200) },
|
|
26429
26683
|
annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: false }
|
|
26430
26684
|
},
|
|
26431
26685
|
async ({ board_id, title }) => run(
|
|
@@ -26441,7 +26695,7 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
26441
26695
|
{
|
|
26442
26696
|
title: "Canvas: membros do board",
|
|
26443
26697
|
description: "Lista quem tem acesso ao board (userId, nome, papel). S\xF3 leitura.",
|
|
26444
|
-
inputSchema: { board_id:
|
|
26698
|
+
inputSchema: { board_id: boardId3 },
|
|
26445
26699
|
annotations: { readOnlyHint: true, openWorldHint: false }
|
|
26446
26700
|
},
|
|
26447
26701
|
async ({ board_id }) => run(async () => {
|
|
@@ -26458,7 +26712,7 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
26458
26712
|
title: "Canvas: adicionar membro",
|
|
26459
26713
|
description: "D\xE1 acesso ao board (ou troca o papel) para um usu\xE1rio pelo userId (uuid). S\xF3 o dono pode. Ainda n\xE3o h\xE1 busca por e-mail: pe\xE7a o userId ou copie de canvas_list_members de outro board.",
|
|
26460
26714
|
inputSchema: {
|
|
26461
|
-
board_id:
|
|
26715
|
+
board_id: boardId3,
|
|
26462
26716
|
user_id: external_exports.string().uuid(),
|
|
26463
26717
|
role: external_exports.enum(["editor", "viewer"]).describe("editor edita; viewer s\xF3 v\xEA.")
|
|
26464
26718
|
},
|
|
@@ -26474,7 +26728,7 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
26474
26728
|
{
|
|
26475
26729
|
title: "Canvas: remover membro",
|
|
26476
26730
|
description: "Tira o acesso de algu\xE9m ao board (o dono tira qualquer um; quem n\xE3o \xE9 dono s\xF3 sai sozinho). O dono n\xE3o sai.",
|
|
26477
|
-
inputSchema: { board_id:
|
|
26731
|
+
inputSchema: { board_id: boardId3, user_id: external_exports.string().uuid() },
|
|
26478
26732
|
annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: false }
|
|
26479
26733
|
},
|
|
26480
26734
|
async ({ board_id, user_id }) => run(async () => {
|
|
@@ -26485,13 +26739,14 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
26485
26739
|
registerCanvasCommentTools(server, api, run);
|
|
26486
26740
|
registerCanvasMediaTools(server, { api, cfg, run, edit, seen, placeFor });
|
|
26487
26741
|
registerCanvasLayoutTools(server, { api, run, edit });
|
|
26742
|
+
registerCanvasRunTools(server, api, run);
|
|
26488
26743
|
}
|
|
26489
26744
|
|
|
26490
26745
|
// src/version.ts
|
|
26491
26746
|
import { createRequire } from "module";
|
|
26492
26747
|
var require2 = createRequire(import.meta.url);
|
|
26493
26748
|
function readVersion() {
|
|
26494
|
-
if ("0.
|
|
26749
|
+
if ("0.31.0") return "0.31.0";
|
|
26495
26750
|
try {
|
|
26496
26751
|
const pkg = require2("../package.json");
|
|
26497
26752
|
return pkg.version ?? "0.0.0-unknown";
|
|
@@ -26506,7 +26761,7 @@ var SERVER_INSTRUCTIONS = [
|
|
|
26506
26761
|
"BePlus: tudo roda pela conta do usu\xE1rio (diamantes, limites e hist\xF3rico na plataforma).",
|
|
26507
26762
|
'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.',
|
|
26508
26763
|
"Calls: search_calls acha, get_call traz a transcri\xE7\xE3o.",
|
|
26509
|
-
"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
|
|
26764
|
+
"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.",
|
|
26510
26765
|
'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.',
|
|
26511
26766
|
'"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.'
|
|
26512
26767
|
].join("\n");
|