@bendyline/docblocks-cli 2.1.2 → 2.2.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/dist/bin.js +117 -358
- package/dist/eval/cli.d.ts +2 -0
- package/dist/eval/cli.js +1584 -0
- package/package.json +2 -2
package/dist/bin.js
CHANGED
|
@@ -4161,258 +4161,13 @@ var init_progress = __esm({
|
|
|
4161
4161
|
}
|
|
4162
4162
|
});
|
|
4163
4163
|
|
|
4164
|
-
// src/mcp/revision-service.ts
|
|
4165
|
-
import { createHash as createHash7 } from "crypto";
|
|
4166
|
-
import {
|
|
4167
|
-
DOCBLOCKS_MCP_WIRE_VERSION as DOCBLOCKS_MCP_WIRE_VERSION5,
|
|
4168
|
-
MCP_WIRE_LIMITS as MCP_WIRE_LIMITS7,
|
|
4169
|
-
parseDocumentRevisionResult
|
|
4170
|
-
} from "@bendyline/docblocks/mcp";
|
|
4171
|
-
async function reviseDocumentArtifact(artifacts, documents, request, signal) {
|
|
4172
|
-
throwIfAborted5(signal);
|
|
4173
|
-
const parentArtifact = await artifacts.get(request.artifactUri, signal);
|
|
4174
|
-
if (parentArtifact.sha256 !== request.expectedSha256) {
|
|
4175
|
-
throw revisionError(
|
|
4176
|
-
"conflict",
|
|
4177
|
-
`Revision precondition failed: expected ${request.expectedSha256}, but the parent artifact is ${parentArtifact.sha256}.`,
|
|
4178
|
-
`Use expectedSha256 "${parentArtifact.sha256}" only if this is still the intended parent artifact.`
|
|
4179
|
-
);
|
|
4180
|
-
}
|
|
4181
|
-
if (parentArtifact.format !== "dbk") {
|
|
4182
|
-
throw revisionError(
|
|
4183
|
-
"invalid-revision-source",
|
|
4184
|
-
`Artifact-native block revision requires a DBK parent, not ${parentArtifact.format}.`,
|
|
4185
|
-
"Stage Markdown and assets with create_document_bundle, or convert the source to DBK first."
|
|
4186
|
-
);
|
|
4187
|
-
}
|
|
4188
|
-
if (new Set(request.edits.map((edit) => edit.blockId)).size !== request.edits.length) {
|
|
4189
|
-
throw revisionError(
|
|
4190
|
-
"duplicate-block-edit",
|
|
4191
|
-
"Each block id may be revised at most once per request.",
|
|
4192
|
-
"Combine changes to the same block into one replacement fragment."
|
|
4193
|
-
);
|
|
4194
|
-
}
|
|
4195
|
-
const totalReplacementCharacters = request.edits.reduce(
|
|
4196
|
-
(sum, edit) => sum + edit.markdown.length,
|
|
4197
|
-
0
|
|
4198
|
-
);
|
|
4199
|
-
if (totalReplacementCharacters > MCP_WIRE_LIMITS7.documentCharacters) {
|
|
4200
|
-
throw revisionError(
|
|
4201
|
-
"revision-too-large",
|
|
4202
|
-
"Combined replacement Markdown exceeds the MCP document character limit.",
|
|
4203
|
-
"Use fewer or smaller block replacements."
|
|
4204
|
-
);
|
|
4205
|
-
}
|
|
4206
|
-
const prepared = await documents.prepare({ kind: "artifact", uri: parentArtifact.uri }, signal);
|
|
4207
|
-
const { flattenBlocks } = await import("@bendyline/squisq/doc");
|
|
4208
|
-
const blocks = flattenBlocks(prepared.doc.blocks);
|
|
4209
|
-
const ranges = await computeBlockSourceRanges(blocks, prepared.markdown.length, signal);
|
|
4210
|
-
const blockRecords = indexEditableBlocks(blocks, ranges);
|
|
4211
|
-
const replacements = [];
|
|
4212
|
-
for (let index = 0; index < request.edits.length; index += 1) {
|
|
4213
|
-
throwIfAborted5(signal);
|
|
4214
|
-
const edit = request.edits[index];
|
|
4215
|
-
const record = blockRecords.get(edit.blockId);
|
|
4216
|
-
if (!record) {
|
|
4217
|
-
throw revisionError(
|
|
4218
|
-
"block-not-found",
|
|
4219
|
-
`Block "${edit.blockId}" is not an editable heading block in the parent artifact.`,
|
|
4220
|
-
"Call inspect_document on the exact parent artifact and use a returned block id with a non-null sourceRange."
|
|
4221
|
-
);
|
|
4222
|
-
}
|
|
4223
|
-
const replacementMarkdown = await canonicalReplacement(
|
|
4224
|
-
edit.markdown,
|
|
4225
|
-
record.block,
|
|
4226
|
-
edit.blockId
|
|
4227
|
-
);
|
|
4228
|
-
const before = prepared.markdown.slice(record.start, record.end);
|
|
4229
|
-
if (replacementMarkdown === before) {
|
|
4230
|
-
throw revisionError(
|
|
4231
|
-
"no-op-block-edit",
|
|
4232
|
-
`Replacement for block "${edit.blockId}" does not change its heading or body.`,
|
|
4233
|
-
"Omit no-op block edits from the revision request."
|
|
4234
|
-
);
|
|
4235
|
-
}
|
|
4236
|
-
replacements.push({
|
|
4237
|
-
blockId: edit.blockId,
|
|
4238
|
-
start: record.start,
|
|
4239
|
-
end: record.end,
|
|
4240
|
-
markdown: replacementMarkdown,
|
|
4241
|
-
applied: {
|
|
4242
|
-
kind: "replace_block",
|
|
4243
|
-
blockId: edit.blockId,
|
|
4244
|
-
beforeSha256: sha256(Buffer.from(before, "utf8")),
|
|
4245
|
-
afterSha256: sha256(Buffer.from(replacementMarkdown, "utf8"))
|
|
4246
|
-
}
|
|
4247
|
-
});
|
|
4248
|
-
if ((index + 1) % 16 === 0) await yieldForCancellation2(signal);
|
|
4249
|
-
}
|
|
4250
|
-
const revisedMarkdown = applyReplacements(prepared.markdown, replacements);
|
|
4251
|
-
if (revisedMarkdown.length > MCP_WIRE_LIMITS7.documentCharacters) {
|
|
4252
|
-
throw revisionError(
|
|
4253
|
-
"revision-too-large",
|
|
4254
|
-
"The revised Markdown exceeds the MCP document character limit.",
|
|
4255
|
-
"Use smaller block replacements or split the document before revising it."
|
|
4256
|
-
);
|
|
4257
|
-
}
|
|
4258
|
-
if (revisedMarkdown === prepared.markdown) {
|
|
4259
|
-
throw revisionError(
|
|
4260
|
-
"no-op-revision",
|
|
4261
|
-
"The requested block replacements do not change the document.",
|
|
4262
|
-
"Submit only replacements that change heading or body Markdown."
|
|
4263
|
-
);
|
|
4264
|
-
}
|
|
4265
|
-
const [{ parseMarkdown: parseMarkdown2 }, { markdownToDoc: markdownToDoc2, flattenBlocks: flattenRevisedBlocks }] = await Promise.all([import("@bendyline/squisq/markdown"), import("@bendyline/squisq/doc")]);
|
|
4266
|
-
const markdownDoc = parseMarkdown2(revisedMarkdown);
|
|
4267
|
-
const doc = markdownToDoc2(markdownDoc, { defaultTemplate: "content", autoTemplates: false });
|
|
4268
|
-
const revisedIds = new Set(
|
|
4269
|
-
flattenRevisedBlocks(doc.blocks).map((block) => toWireIdentifier(block.id, "block"))
|
|
4270
|
-
);
|
|
4271
|
-
for (const replacement of replacements) {
|
|
4272
|
-
if (!revisedIds.has(replacement.blockId)) {
|
|
4273
|
-
throw revisionError(
|
|
4274
|
-
"unstable-block-id",
|
|
4275
|
-
`Replacement for block "${replacement.blockId}" did not preserve its stable id.`,
|
|
4276
|
-
"Keep the replacement heading id unchanged and retry from the parent artifact."
|
|
4277
|
-
);
|
|
4278
|
-
}
|
|
4279
|
-
}
|
|
4280
|
-
throwIfAborted5(signal);
|
|
4281
|
-
await prepared.container.writeDocument(revisedMarkdown);
|
|
4282
|
-
const revisionSourceSha256 = createHash7("sha256").update("docblocks-artifact-revision-v1\0", "utf8").update(parentArtifact.sha256, "utf8").update("\0", "utf8").update(revisedMarkdown, "utf8").digest("hex");
|
|
4283
|
-
const [conversion] = await convertPreparedDocument(
|
|
4284
|
-
artifacts,
|
|
4285
|
-
{
|
|
4286
|
-
...prepared,
|
|
4287
|
-
markdown: revisedMarkdown,
|
|
4288
|
-
markdownDoc,
|
|
4289
|
-
doc,
|
|
4290
|
-
sourceSha256: revisionSourceSha256
|
|
4291
|
-
},
|
|
4292
|
-
{ targets: [{ format: "dbk", fidelity: "semantic" }] },
|
|
4293
|
-
signal
|
|
4294
|
-
);
|
|
4295
|
-
if (!conversion) throw new Error("Document revision produced no DBK artifact");
|
|
4296
|
-
const result = {
|
|
4297
|
-
version: DOCBLOCKS_MCP_WIRE_VERSION5,
|
|
4298
|
-
kind: "revision",
|
|
4299
|
-
parentArtifact,
|
|
4300
|
-
artifact: conversion.artifact,
|
|
4301
|
-
edits: replacements.map((replacement) => replacement.applied),
|
|
4302
|
-
diagnostics: conversion.diagnostics
|
|
4303
|
-
};
|
|
4304
|
-
const parsed = parseDocumentRevisionResult(result);
|
|
4305
|
-
if (!parsed) throw new Error("Document revision produced an invalid MCP result");
|
|
4306
|
-
return parsed;
|
|
4307
|
-
}
|
|
4308
|
-
function indexEditableBlocks(blocks, ranges) {
|
|
4309
|
-
const indexed = /* @__PURE__ */ new Map();
|
|
4310
|
-
const ambiguous = /* @__PURE__ */ new Set();
|
|
4311
|
-
for (let index = 0; index < blocks.length; index += 1) {
|
|
4312
|
-
const block = blocks[index];
|
|
4313
|
-
const range = ranges[index];
|
|
4314
|
-
if (!block || !range || !block.sourceHeading) continue;
|
|
4315
|
-
const wireId = toWireIdentifier(block.id, "block");
|
|
4316
|
-
if (indexed.has(wireId)) {
|
|
4317
|
-
indexed.delete(wireId);
|
|
4318
|
-
ambiguous.add(wireId);
|
|
4319
|
-
} else if (!ambiguous.has(wireId)) {
|
|
4320
|
-
indexed.set(wireId, { block, start: range.start, end: range.end });
|
|
4321
|
-
}
|
|
4322
|
-
}
|
|
4323
|
-
return indexed;
|
|
4324
|
-
}
|
|
4325
|
-
async function canonicalReplacement(markdown, target, wireBlockId) {
|
|
4326
|
-
const { parseMarkdown: parseMarkdown2, stringifyMarkdown } = await import("@bendyline/squisq/markdown");
|
|
4327
|
-
const fragment = parseMarkdown2(markdown);
|
|
4328
|
-
if (fragment.frontmatter && Object.keys(fragment.frontmatter).length > 0) {
|
|
4329
|
-
throw revisionError(
|
|
4330
|
-
"invalid-block-replacement",
|
|
4331
|
-
`Replacement for block "${wireBlockId}" cannot contain frontmatter.`,
|
|
4332
|
-
"Provide one heading and its direct body only."
|
|
4333
|
-
);
|
|
4334
|
-
}
|
|
4335
|
-
const headings = fragment.children.filter(
|
|
4336
|
-
(node) => node.type === "heading"
|
|
4337
|
-
);
|
|
4338
|
-
const heading = headings[0];
|
|
4339
|
-
if (!heading || fragment.children[0] !== heading || headings.length !== 1) {
|
|
4340
|
-
throw revisionError(
|
|
4341
|
-
"invalid-block-replacement",
|
|
4342
|
-
`Replacement for block "${wireBlockId}" must begin with exactly one heading and cannot contain nested headings.`,
|
|
4343
|
-
"Use a complete fragment such as `# Heading {[content]}\n\nReplacement body`."
|
|
4344
|
-
);
|
|
4345
|
-
}
|
|
4346
|
-
const sourceHeading = target.sourceHeading;
|
|
4347
|
-
if (!sourceHeading) throw new Error("Editable replacement target has no source heading");
|
|
4348
|
-
if (heading.depth !== sourceHeading.depth) {
|
|
4349
|
-
throw revisionError(
|
|
4350
|
-
"invalid-block-replacement",
|
|
4351
|
-
`Replacement for block "${wireBlockId}" must keep heading depth ${sourceHeading.depth}.`,
|
|
4352
|
-
`Begin the replacement with ${"#".repeat(sourceHeading.depth)} followed by the heading text.`
|
|
4353
|
-
);
|
|
4354
|
-
}
|
|
4355
|
-
if (heading.attributes?.id && heading.attributes.id !== target.id) {
|
|
4356
|
-
throw revisionError(
|
|
4357
|
-
"block-id-change-not-allowed",
|
|
4358
|
-
`Replacement for block "${wireBlockId}" cannot change its id to "${heading.attributes.id}".`,
|
|
4359
|
-
`Omit the explicit id or keep {#${target.id}}.`
|
|
4360
|
-
);
|
|
4361
|
-
}
|
|
4362
|
-
const sourceAttributes = sourceHeading.attributes;
|
|
4363
|
-
const replacementAttributes = heading.attributes;
|
|
4364
|
-
const attributes = {
|
|
4365
|
-
...sourceAttributes,
|
|
4366
|
-
...replacementAttributes,
|
|
4367
|
-
id: target.id,
|
|
4368
|
-
...replacementAttributes?.classes === void 0 && sourceAttributes?.classes ? { classes: sourceAttributes.classes } : {},
|
|
4369
|
-
...replacementAttributes?.params === void 0 && sourceAttributes?.params ? { params: sourceAttributes.params } : {},
|
|
4370
|
-
...replacementAttributes?.blockMeta === void 0 && sourceAttributes?.blockMeta ? { blockMeta: sourceAttributes.blockMeta } : {},
|
|
4371
|
-
...replacementAttributes?.metadata === void 0 && sourceAttributes?.metadata ? { metadata: sourceAttributes.metadata } : {}
|
|
4372
|
-
};
|
|
4373
|
-
const pinnedHeading = {
|
|
4374
|
-
...heading,
|
|
4375
|
-
attributes,
|
|
4376
|
-
templateAnnotation: heading.templateAnnotation ?? sourceHeading.templateAnnotation
|
|
4377
|
-
};
|
|
4378
|
-
return stringifyMarkdown({
|
|
4379
|
-
type: "document",
|
|
4380
|
-
children: [pinnedHeading, ...fragment.children.slice(1)]
|
|
4381
|
-
});
|
|
4382
|
-
}
|
|
4383
|
-
function applyReplacements(source, replacements) {
|
|
4384
|
-
let revised = source;
|
|
4385
|
-
const descending = [...replacements].sort((left, right) => right.start - left.start);
|
|
4386
|
-
for (const replacement of descending) {
|
|
4387
|
-
revised = revised.slice(0, replacement.start) + replacement.markdown + revised.slice(replacement.end);
|
|
4388
|
-
}
|
|
4389
|
-
return revised;
|
|
4390
|
-
}
|
|
4391
|
-
function revisionError(code, message, hint) {
|
|
4392
|
-
return Object.assign(new Error(message), { code, hint, retryable: false });
|
|
4393
|
-
}
|
|
4394
|
-
async function yieldForCancellation2(signal) {
|
|
4395
|
-
await new Promise((resolve4) => setImmediate(resolve4));
|
|
4396
|
-
throwIfAborted5(signal);
|
|
4397
|
-
}
|
|
4398
|
-
var init_revision_service = __esm({
|
|
4399
|
-
"src/mcp/revision-service.ts"() {
|
|
4400
|
-
"use strict";
|
|
4401
|
-
init_conversion_service();
|
|
4402
|
-
init_document_service();
|
|
4403
|
-
init_intelligence();
|
|
4404
|
-
init_output_bounds();
|
|
4405
|
-
}
|
|
4406
|
-
});
|
|
4407
|
-
|
|
4408
4164
|
// src/mcp/agentic-tools.ts
|
|
4409
4165
|
import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4410
4166
|
import { z } from "zod";
|
|
4411
4167
|
import {
|
|
4412
|
-
MCP_WIRE_LIMITS as
|
|
4168
|
+
MCP_WIRE_LIMITS as MCP_WIRE_LIMITS7,
|
|
4413
4169
|
parseComparisonResult,
|
|
4414
4170
|
parseConversionResult as parseConversionResult2,
|
|
4415
|
-
parseDocumentRevisionResult as parseDocumentRevisionResult2,
|
|
4416
4171
|
parseDocumentSource,
|
|
4417
4172
|
parseInspectionResult,
|
|
4418
4173
|
parseMaterializationOptions,
|
|
@@ -4424,7 +4179,6 @@ import {
|
|
|
4424
4179
|
bundleDocumentSourceSchema,
|
|
4425
4180
|
DOCBLOCKS_MCP_TOOL_OUTPUT_SCHEMAS,
|
|
4426
4181
|
documentSourceSchema,
|
|
4427
|
-
documentRevisionRequestSchema,
|
|
4428
4182
|
formatInputSchema,
|
|
4429
4183
|
materializationOptionsSchema
|
|
4430
4184
|
} from "@bendyline/docblocks/mcp/zod";
|
|
@@ -4520,7 +4274,7 @@ function registerAgenticTools(server, context) {
|
|
|
4520
4274
|
server.registerTool(
|
|
4521
4275
|
"create_document_bundle",
|
|
4522
4276
|
{
|
|
4523
|
-
description: "
|
|
4277
|
+
description: "Optionally stage Markdown plus authority-scoped assets as a reusable immutable DBK artifact when the same bundle will feed several operations. For normal authoring, pass complete Markdown or a bundle source directly to convert_document.",
|
|
4524
4278
|
inputSchema: z.object({ source: bundleDocumentSourceSchema }).strict(),
|
|
4525
4279
|
outputSchema: DOCBLOCKS_MCP_TOOL_OUTPUT_SCHEMAS.create_document_bundle,
|
|
4526
4280
|
annotations: ARTIFACT_CREATING
|
|
@@ -4552,38 +4306,6 @@ function registerAgenticTools(server, context) {
|
|
|
4552
4306
|
}
|
|
4553
4307
|
}
|
|
4554
4308
|
);
|
|
4555
|
-
server.registerTool(
|
|
4556
|
-
"revise_document",
|
|
4557
|
-
{
|
|
4558
|
-
description: "Replace selected heading blocks in an immutable DBK artifact without resending the full document. Requires the parent artifact SHA-256, preserves block ids and child blocks, and returns a new DBK artifact without mutating the parent.",
|
|
4559
|
-
inputSchema: documentRevisionRequestSchema,
|
|
4560
|
-
outputSchema: DOCBLOCKS_MCP_TOOL_OUTPUT_SCHEMAS.revise_document,
|
|
4561
|
-
annotations: ARTIFACT_CREATING
|
|
4562
|
-
},
|
|
4563
|
-
async (request, extra) => {
|
|
4564
|
-
try {
|
|
4565
|
-
return await context.runOperation(extra.signal, async (operationSignal) => {
|
|
4566
|
-
const documents = new DocumentService(await context.authority, context.artifacts);
|
|
4567
|
-
const result = await reviseDocumentArtifact(
|
|
4568
|
-
context.artifacts,
|
|
4569
|
-
documents,
|
|
4570
|
-
request,
|
|
4571
|
-
operationSignal
|
|
4572
|
-
);
|
|
4573
|
-
requireWire(parseDocumentRevisionResult2(result), "document revision");
|
|
4574
|
-
return {
|
|
4575
|
-
content: [
|
|
4576
|
-
{ type: "text", text: JSON.stringify(result) },
|
|
4577
|
-
artifactLink(result.artifact)
|
|
4578
|
-
],
|
|
4579
|
-
structuredContent: asStructuredContent(successResult(result))
|
|
4580
|
-
};
|
|
4581
|
-
});
|
|
4582
|
-
} catch (caught) {
|
|
4583
|
-
return errorResult(caught, "transform", "dbk", extra.signal);
|
|
4584
|
-
}
|
|
4585
|
-
}
|
|
4586
|
-
);
|
|
4587
4309
|
server.registerTool(
|
|
4588
4310
|
"save_artifact",
|
|
4589
4311
|
{
|
|
@@ -4842,15 +4564,17 @@ function registerAuthoringGuideResource(server) {
|
|
|
4842
4564
|
import("@bendyline/squisq/transform")
|
|
4843
4565
|
]);
|
|
4844
4566
|
const guide = {
|
|
4845
|
-
version:
|
|
4567
|
+
version: 6,
|
|
4846
4568
|
workflow: [
|
|
4847
|
-
"
|
|
4848
|
-
"
|
|
4849
|
-
"
|
|
4850
|
-
"for
|
|
4851
|
-
"
|
|
4852
|
-
"
|
|
4853
|
-
"
|
|
4569
|
+
"treat supplied facts as a closed evidence set; label calculations, assumptions, hypotheses, recommendations, and examples; do not present causal links, rhetorical performance labels, superlatives, sole causes, targets, capabilities, owners, dates, channels, or operational details as established facts unless supplied",
|
|
4570
|
+
"when the requested genre needs unsupplied roles, gates, timelines, channels, or procedures, add one explicit proposed operating model scope note that applies to those details, then complete the requested element",
|
|
4571
|
+
"author complete Squisq-compatible Markdown with annotations bound to headings; ordinary headings default to the loss-averse content template",
|
|
4572
|
+
"for PPTX, use exactly one level-one Markdown heading per slide and no level-two through level-six headings because every heading becomes a slide by default",
|
|
4573
|
+
"by default, pass the complete Markdown\u2014or a bundle source when assets are needed\u2014directly to convert_document; revise by editing the complete Markdown and converting again",
|
|
4574
|
+
"use create_document_bundle only when a reusable staged DBK materially avoids repeating a large Markdown-and-asset bundle across several operations",
|
|
4575
|
+
"use inspect_document, validate_document, and preview_document when their semantic, diagnostic, or visual evidence is useful; they are review tools rather than required phases",
|
|
4576
|
+
"for visual polish, replace selected content blocks with compatible visual templates while preserving required content",
|
|
4577
|
+
"convert_document creates one or more immutable artifacts from the authoritative complete source",
|
|
4854
4578
|
"save_artifact only when a durable file is required"
|
|
4855
4579
|
],
|
|
4856
4580
|
markdownAnnotation: '# Heading {[templateId key="value"]}',
|
|
@@ -4865,14 +4589,14 @@ function registerAuthoringGuideResource(server) {
|
|
|
4865
4589
|
fidelityByFormat: MCP_FORMAT_FIDELITIES,
|
|
4866
4590
|
formats: boundedFormatCapabilities(),
|
|
4867
4591
|
templates,
|
|
4868
|
-
themes: schemaModule.getThemeSummaries().slice(0,
|
|
4592
|
+
themes: schemaModule.getThemeSummaries().slice(0, MCP_WIRE_LIMITS7.arrayEntries).map((theme) => ({
|
|
4869
4593
|
id: requireWireIdentifier(theme.id, "theme id"),
|
|
4870
|
-
name: boundWireText(theme.name,
|
|
4594
|
+
name: boundWireText(theme.name, MCP_WIRE_LIMITS7.labelCharacters, theme.id),
|
|
4871
4595
|
description: boundWireText(theme.description ?? "")
|
|
4872
4596
|
})),
|
|
4873
|
-
transformStyles: transformModule.getTransformStyleSummaries().slice(0,
|
|
4597
|
+
transformStyles: transformModule.getTransformStyleSummaries().slice(0, MCP_WIRE_LIMITS7.arrayEntries).map((style) => ({
|
|
4874
4598
|
id: requireWireIdentifier(style.id, "transform style id"),
|
|
4875
|
-
name: boundWireText(style.name,
|
|
4599
|
+
name: boundWireText(style.name, MCP_WIRE_LIMITS7.labelCharacters, style.id),
|
|
4876
4600
|
description: boundWireText(style.description)
|
|
4877
4601
|
}))
|
|
4878
4602
|
};
|
|
@@ -4892,7 +4616,7 @@ function registerTemplateTools(server, context) {
|
|
|
4892
4616
|
server.registerTool(
|
|
4893
4617
|
"get_authoring_context",
|
|
4894
4618
|
{
|
|
4895
|
-
description: "Get
|
|
4619
|
+
description: "Get a compact agent-facing authoring contract plus the complete linked-Squisq catalog in structured content, with optional block recommendations.",
|
|
4896
4620
|
inputSchema: z.object({
|
|
4897
4621
|
targetFormat: formatInputSchema.optional(),
|
|
4898
4622
|
goal: z.enum(["content-first", "visual-polish"]).optional(),
|
|
@@ -4944,7 +4668,7 @@ function registerTemplateTools(server, context) {
|
|
|
4944
4668
|
const recommendedTemplateIds = goal === "content-first" ? ["content", ...visual.filter((id) => id !== "content")] : visual;
|
|
4945
4669
|
return {
|
|
4946
4670
|
blockId: toWireIdentifier(block.id, "block"),
|
|
4947
|
-
title: boundNullableWireText(block.title,
|
|
4671
|
+
title: boundNullableWireText(block.title, MCP_WIRE_LIMITS7.labelCharacters),
|
|
4948
4672
|
profile: {
|
|
4949
4673
|
...profile,
|
|
4950
4674
|
hasAsciiDiagram: profile.hasAsciiDiagram ?? false,
|
|
@@ -4957,18 +4681,26 @@ function registerTemplateTools(server, context) {
|
|
|
4957
4681
|
totalBlocks = blocks.length;
|
|
4958
4682
|
truncated = recommendations.length < blocks.length;
|
|
4959
4683
|
}
|
|
4960
|
-
|
|
4684
|
+
const payload = {
|
|
4961
4685
|
goal,
|
|
4962
4686
|
targetFormat: normalizedTarget,
|
|
4963
4687
|
defaultTemplateId: "content",
|
|
4964
4688
|
defaultFidelity: authoringDefaultFidelity(normalizedTarget, goal),
|
|
4965
4689
|
workflow: [
|
|
4966
|
-
"
|
|
4967
|
-
"
|
|
4968
|
-
"
|
|
4969
|
-
"
|
|
4970
|
-
"
|
|
4971
|
-
"
|
|
4690
|
+
"Treat supplied facts as a closed evidence set. Use temporal or correlational wording unless causality is supplied. Label calculations, assumptions, hypotheses, recommendations, and illustrative examples. Do not infer end-to-end feasibility from one supplied phase duration.",
|
|
4691
|
+
"Audit claims before conversion: causal links, rhetorical labels such as compounding, engine, healthy, strong, or constraint, superlatives, sole-cause claims, targets, capabilities, owners, dates, channels, and operational details must be supplied or explicitly framed as a hypothesis, recommendation, example, or proposal. Do not connect separate metrics, audiences, segments, or workflows unless the relationship is supplied. Prefer observed, coincided with, intended to, or proposed over drove, addresses, protects, or proves. Do not call choices a sequence or capacity allocation unless order, timing, or resource constraints were supplied.",
|
|
4692
|
+
"Complete every requested element without presenting invented policy as established fact. When a requested policy, playbook, or training guide needs unsupplied roles, gates, timelines, channels, or procedures, add one explicit proposed operating model scope note placed before the first such detail so it governs all of them.",
|
|
4693
|
+
"Generic option traits\u2014control, flexibility, vendor support, freed capacity, switching costs\u2014are capability claims: state one only when supplied or labeled Assumption or Judgment, even in table cells and tradeoffs.",
|
|
4694
|
+
"Author complete Squisq-compatible content with heading-bound annotations; ordinary headings default to the loss-averse content template.",
|
|
4695
|
+
normalizedTarget === "pptx" ? "Match every explicitly requested slide count exactly. Use exactly one level-one Markdown heading (#) per slide and no level-two through level-six headings because every heading becomes a slide by default. Target at most 80 words per slide, and use lists, tables, or bold labels for within-slide structure." : "Honor the requested word range and document genre. Prefer connected memo prose for executive decisions and native headings, tables, and checklists for operational documents.",
|
|
4696
|
+
normalizedTarget === "pptx" ? "Make slide one a supported point-of-view thesis, not a generic title or unsupported flourish. For requested choices, state a concrete opportunity cost grounded in the supplied alternatives and name one clearly labeled proposed accountable role per choice. If a tradeoff requires an unsupplied capacity or outcome assumption, label it Assumption or Potential tradeoff rather than stating it as fact." : "Tie each decision implication or comparative judgment to a supplied fact or calculation, or label it Judgment. When accountability is requested but not supplied, name one clearly labeled proposed accountable role per decision or workstream.",
|
|
4697
|
+
"Add decision value without inventing causes: interpret supplied comparisons to baselines, goals, targets, and rankings; use transparent calculations; label any new review cadence or measurement procedure as proposed.",
|
|
4698
|
+
"Before validation and conversion, run a content preflight: count slide sections or document words, verify every requested element, and rewrite or label every unsupported claim.",
|
|
4699
|
+
"Use the complete Markdown as the authoritative source. Pass it\u2014or a bundle source when assets are needed\u2014directly to convert_document, and revise by editing the complete Markdown and converting again.",
|
|
4700
|
+
"Use create_document_bundle only when reusing a large Markdown-and-asset bundle across several review or conversion operations would materially reduce retransmission.",
|
|
4701
|
+
"Use inspect_document or validate_document when semantic structure, content retention, accessibility, or target diagnostics need review; repair actionable findings in the authoritative Markdown.",
|
|
4702
|
+
"Use preview_document when visual evidence is needed, inspect previewBasis, and repair overflow or layout problems in the authoritative Markdown.",
|
|
4703
|
+
normalizedTarget === "pptx" ? "For visual polish, replace selected content blocks with compatible recommended templates; use patterns such as definitionCard for a definition, dataTable for a true table, comparisonBar for supported numeric comparisons, and list for concise steps when the returned catalog supports them. Preserve all required content and preview again." : "For visual polish, use native headings, tables, and checklists where they improve scanning; keep complete-body content when a visual template would discard detail, then preview again.",
|
|
4972
4704
|
"Convert to immutable artifacts, inspect conversion reports, and save only final durable outputs."
|
|
4973
4705
|
],
|
|
4974
4706
|
syntax: {
|
|
@@ -4978,20 +4710,21 @@ function registerTemplateTools(server, context) {
|
|
|
4978
4710
|
},
|
|
4979
4711
|
formats,
|
|
4980
4712
|
templates,
|
|
4981
|
-
themes: schemaModule.getThemeSummaries().slice(0,
|
|
4713
|
+
themes: schemaModule.getThemeSummaries().slice(0, MCP_WIRE_LIMITS7.arrayEntries).map((theme) => ({
|
|
4982
4714
|
id: requireWireIdentifier(theme.id, "theme id"),
|
|
4983
|
-
name: boundWireText(theme.name,
|
|
4715
|
+
name: boundWireText(theme.name, MCP_WIRE_LIMITS7.labelCharacters, theme.id),
|
|
4984
4716
|
description: boundWireText(theme.description ?? "")
|
|
4985
4717
|
})),
|
|
4986
|
-
transformStyles: transformModule.getTransformStyleSummaries().slice(0,
|
|
4718
|
+
transformStyles: transformModule.getTransformStyleSummaries().slice(0, MCP_WIRE_LIMITS7.arrayEntries).map((style) => ({
|
|
4987
4719
|
id: requireWireIdentifier(style.id, "transform style id"),
|
|
4988
|
-
name: boundWireText(style.name,
|
|
4720
|
+
name: boundWireText(style.name, MCP_WIRE_LIMITS7.labelCharacters, style.id),
|
|
4989
4721
|
description: boundWireText(style.description)
|
|
4990
4722
|
})),
|
|
4991
4723
|
recommendations,
|
|
4992
4724
|
totalBlocks,
|
|
4993
4725
|
truncated
|
|
4994
|
-
}
|
|
4726
|
+
};
|
|
4727
|
+
return textAndStructured(payload, compactAuthoringContextText(payload));
|
|
4995
4728
|
});
|
|
4996
4729
|
} catch (caught) {
|
|
4997
4730
|
return errorResult(caught, "inspect", null, extra.signal);
|
|
@@ -5081,7 +4814,7 @@ function registerTemplateTools(server, context) {
|
|
|
5081
4814
|
const profile = recommendModule.profileBlockContents(block.contents ?? []);
|
|
5082
4815
|
return {
|
|
5083
4816
|
blockId: toWireIdentifier(block.id, "block"),
|
|
5084
|
-
title: boundNullableWireText(block.title,
|
|
4817
|
+
title: boundNullableWireText(block.title, MCP_WIRE_LIMITS7.labelCharacters),
|
|
5085
4818
|
profile: {
|
|
5086
4819
|
...profile,
|
|
5087
4820
|
hasAsciiDiagram: profile.hasAsciiDiagram ?? false,
|
|
@@ -5180,12 +4913,12 @@ function registerThemeTools(server, context) {
|
|
|
5180
4913
|
layouts: (inferred.layouts ?? []).slice(0, 1e3).map((layout, index) => ({
|
|
5181
4914
|
id: boundWireText(
|
|
5182
4915
|
layout.name,
|
|
5183
|
-
|
|
4916
|
+
MCP_WIRE_LIMITS7.labelCharacters,
|
|
5184
4917
|
`layout-${index + 1}`
|
|
5185
4918
|
),
|
|
5186
4919
|
name: boundWireText(
|
|
5187
4920
|
layout.label,
|
|
5188
|
-
|
|
4921
|
+
MCP_WIRE_LIMITS7.labelCharacters,
|
|
5189
4922
|
`Layout ${index + 1}`
|
|
5190
4923
|
),
|
|
5191
4924
|
description: boundWireText(layout.description ?? "")
|
|
@@ -5230,21 +4963,21 @@ function registerThemeTools(server, context) {
|
|
|
5230
4963
|
layouts: result.layouts.slice(0, 2048).map((layout, index) => ({
|
|
5231
4964
|
layoutPath: boundWireText(
|
|
5232
4965
|
layout.layoutPath,
|
|
5233
|
-
|
|
4966
|
+
MCP_WIRE_LIMITS7.pathCharacters,
|
|
5234
4967
|
`ppt/slideLayouts/slideLayout${index + 1}.xml`
|
|
5235
4968
|
),
|
|
5236
4969
|
name: boundWireText(
|
|
5237
4970
|
layout.name,
|
|
5238
|
-
|
|
4971
|
+
MCP_WIRE_LIMITS7.labelCharacters,
|
|
5239
4972
|
`Layout ${index + 1}`
|
|
5240
4973
|
),
|
|
5241
|
-
masterName: boundNullableWireText(layout.masterName,
|
|
5242
|
-
type: boundNullableWireText(layout.typeAttr,
|
|
4974
|
+
masterName: boundNullableWireText(layout.masterName, MCP_WIRE_LIMITS7.labelCharacters),
|
|
4975
|
+
type: boundNullableWireText(layout.typeAttr, MCP_WIRE_LIMITS7.labelCharacters),
|
|
5243
4976
|
slideCount: layout.slideCount,
|
|
5244
4977
|
verdict: layout.verdict,
|
|
5245
4978
|
templateId: boundNullableWireText(
|
|
5246
4979
|
layout.builtinTemplate ?? layout.customTemplate?.name,
|
|
5247
|
-
|
|
4980
|
+
MCP_WIRE_LIMITS7.labelCharacters
|
|
5248
4981
|
),
|
|
5249
4982
|
notes: boundWireTextArray(layout.notes ?? [], 1e3)
|
|
5250
4983
|
}))
|
|
@@ -5344,7 +5077,7 @@ function registerThemeTools(server, context) {
|
|
|
5344
5077
|
const payload = {
|
|
5345
5078
|
result,
|
|
5346
5079
|
theme: summarizeTheme(inferred.theme),
|
|
5347
|
-
layoutIds: (inferred.layouts ?? []).slice(0, 1e3).map((layout) => boundWireText(layout.name,
|
|
5080
|
+
layoutIds: (inferred.layouts ?? []).slice(0, 1e3).map((layout) => boundWireText(layout.name, MCP_WIRE_LIMITS7.labelCharacters)),
|
|
5348
5081
|
warnings: boundWireWarnings(inferred.warnings)
|
|
5349
5082
|
};
|
|
5350
5083
|
return {
|
|
@@ -5401,12 +5134,40 @@ function artifactLink(artifact) {
|
|
|
5401
5134
|
async function sendProgress(extra, progress, total, message) {
|
|
5402
5135
|
await reportMcpProgress(extra, progress, total, message);
|
|
5403
5136
|
}
|
|
5404
|
-
function textAndStructured(payload) {
|
|
5137
|
+
function textAndStructured(payload, text = JSON.stringify(payload, null, 2)) {
|
|
5405
5138
|
return {
|
|
5406
|
-
content: [{ type: "text", text
|
|
5139
|
+
content: [{ type: "text", text }],
|
|
5407
5140
|
structuredContent: asStructuredContent(successResult(payload))
|
|
5408
5141
|
};
|
|
5409
5142
|
}
|
|
5143
|
+
function compactAuthoringContextText(context) {
|
|
5144
|
+
const target = context.targetFormat ?? "unspecified target";
|
|
5145
|
+
const lines = [
|
|
5146
|
+
`DocBlocks authoring contract: ${target}, ${context.goal}.`,
|
|
5147
|
+
`Default template: ${context.defaultTemplateId}. Default fidelity: ${context.defaultFidelity ?? "select for target"}.`,
|
|
5148
|
+
"",
|
|
5149
|
+
"Required workflow:",
|
|
5150
|
+
...context.workflow.map((step, index) => `${index + 1}. ${step}`),
|
|
5151
|
+
"",
|
|
5152
|
+
`Heading annotation: ${context.syntax.headingAnnotation}`,
|
|
5153
|
+
`Warning: ${context.syntax.standaloneWarning}`,
|
|
5154
|
+
`Templates (${context.templates.length}): ${context.templates.map(({ id }) => id).join(", ")}`,
|
|
5155
|
+
`Themes (${context.themes.length}): ${context.themes.map(({ id }) => id).join(", ")}`,
|
|
5156
|
+
`Transform styles (${context.transformStyles.length}): ${context.transformStyles.map(({ id }) => id).join(", ")}`
|
|
5157
|
+
];
|
|
5158
|
+
if (context.recommendations.length > 0) {
|
|
5159
|
+
lines.push(
|
|
5160
|
+
`Recommended blocks: ${context.recommendations.map(
|
|
5161
|
+
({ blockId, recommendedTemplateIds }) => `${blockId} -> ${recommendedTemplateIds.join("/")}`
|
|
5162
|
+
).join("; ")}`
|
|
5163
|
+
);
|
|
5164
|
+
}
|
|
5165
|
+
lines.push(
|
|
5166
|
+
"",
|
|
5167
|
+
"The complete exact format, template-input, theme, transform, and recommendation catalog is in structuredContent. Use describe_template for focused follow-up when structured content is unavailable."
|
|
5168
|
+
);
|
|
5169
|
+
return lines.join("\n");
|
|
5170
|
+
}
|
|
5410
5171
|
function asStructuredContent(payload) {
|
|
5411
5172
|
return payload;
|
|
5412
5173
|
}
|
|
@@ -5419,18 +5180,18 @@ function summarizeTheme(theme) {
|
|
|
5419
5180
|
const id = requireWireIdentifier(theme.id, "theme id");
|
|
5420
5181
|
return {
|
|
5421
5182
|
id,
|
|
5422
|
-
name: boundWireText(theme.name,
|
|
5183
|
+
name: boundWireText(theme.name, MCP_WIRE_LIMITS7.labelCharacters, id),
|
|
5423
5184
|
description: boundWireText(theme.description ?? ""),
|
|
5424
5185
|
colors: {
|
|
5425
|
-
primary: boundWireText(theme.colors.primary,
|
|
5426
|
-
secondary: boundWireText(theme.colors.secondary,
|
|
5186
|
+
primary: boundWireText(theme.colors.primary, MCP_WIRE_LIMITS7.labelCharacters, "#000000"),
|
|
5187
|
+
secondary: boundWireText(theme.colors.secondary, MCP_WIRE_LIMITS7.labelCharacters, "#000000"),
|
|
5427
5188
|
background: boundWireText(
|
|
5428
5189
|
theme.colors.background,
|
|
5429
|
-
|
|
5190
|
+
MCP_WIRE_LIMITS7.labelCharacters,
|
|
5430
5191
|
"#ffffff"
|
|
5431
5192
|
),
|
|
5432
|
-
text: boundWireText(theme.colors.text,
|
|
5433
|
-
highlight: boundWireText(theme.colors.highlight,
|
|
5193
|
+
text: boundWireText(theme.colors.text, MCP_WIRE_LIMITS7.labelCharacters, "#000000"),
|
|
5194
|
+
highlight: boundWireText(theme.colors.highlight, MCP_WIRE_LIMITS7.labelCharacters, "#000000")
|
|
5434
5195
|
},
|
|
5435
5196
|
bodyFont: boundWireText(JSON.stringify(theme.typography.bodyFont) ?? ""),
|
|
5436
5197
|
titleFont: boundWireText(JSON.stringify(theme.typography.titleFont) ?? "")
|
|
@@ -5444,26 +5205,26 @@ async function authoringTemplateCatalog() {
|
|
|
5444
5205
|
TEMPLATE_METADATA
|
|
5445
5206
|
} = await import("@bendyline/squisq/doc");
|
|
5446
5207
|
const authoring = TEMPLATE_AUTHORING_METADATA;
|
|
5447
|
-
return getAvailableTemplates().slice(0,
|
|
5208
|
+
return getAvailableTemplates().slice(0, MCP_WIRE_LIMITS7.arrayEntries).map((id) => {
|
|
5448
5209
|
const metadata = TEMPLATE_METADATA[id];
|
|
5449
5210
|
const behavior = authoring[id];
|
|
5450
5211
|
if (!behavior) throw new Error(`Template "${id}" has no authoring metadata`);
|
|
5451
|
-
const inputs = (TEMPLATE_INPUT_DESCRIPTORS[id] ?? []).slice(0,
|
|
5212
|
+
const inputs = (TEMPLATE_INPUT_DESCRIPTORS[id] ?? []).slice(0, MCP_WIRE_LIMITS7.arrayEntries).map((input) => ({
|
|
5452
5213
|
key: requireWireIdentifier(input.key, "template input key"),
|
|
5453
5214
|
description: boundWireText(input.description),
|
|
5454
|
-
type: boundWireText(input.coerce ?? "string",
|
|
5215
|
+
type: boundWireText(input.coerce ?? "string", MCP_WIRE_LIMITS7.labelCharacters, "string"),
|
|
5455
5216
|
required: input.required ?? false,
|
|
5456
5217
|
values: boundWireTextArray(
|
|
5457
5218
|
input.values ?? [],
|
|
5458
|
-
|
|
5459
|
-
|
|
5219
|
+
MCP_WIRE_LIMITS7.arrayEntries,
|
|
5220
|
+
MCP_WIRE_LIMITS7.labelCharacters
|
|
5460
5221
|
),
|
|
5461
|
-
valueHint: boundNullableWireText(input.valueHint,
|
|
5222
|
+
valueHint: boundNullableWireText(input.valueHint, MCP_WIRE_LIMITS7.labelCharacters)
|
|
5462
5223
|
}));
|
|
5463
5224
|
const required = inputs.filter((input) => input.required).map((input) => `${input.key}="\u2026"`).join(" ");
|
|
5464
5225
|
return {
|
|
5465
5226
|
id: requireWireIdentifier(id, "template id"),
|
|
5466
|
-
label: boundWireText(metadata?.label ?? id,
|
|
5227
|
+
label: boundWireText(metadata?.label ?? id, MCP_WIRE_LIMITS7.labelCharacters, id),
|
|
5467
5228
|
description: boundWireText(metadata?.description ?? ""),
|
|
5468
5229
|
inputs,
|
|
5469
5230
|
...behavior,
|
|
@@ -5485,14 +5246,14 @@ function authoringDefaultFidelity(targetFormat, goal) {
|
|
|
5485
5246
|
function boundedFormatCapabilities() {
|
|
5486
5247
|
return MCP_FORMAT_CAPABILITIES.slice(0, 64).map((format) => {
|
|
5487
5248
|
const id = requireWireIdentifier(format.id, "format id");
|
|
5488
|
-
if (id.length >
|
|
5249
|
+
if (id.length > MCP_WIRE_LIMITS7.formatCharacters || !MCP_OUTPUT_PATTERNS.format.test(id)) {
|
|
5489
5250
|
throw new Error("Linked Squisq returned an invalid MCP format id");
|
|
5490
5251
|
}
|
|
5491
5252
|
return {
|
|
5492
5253
|
id,
|
|
5493
|
-
label: boundWireText(format.label,
|
|
5254
|
+
label: boundWireText(format.label, MCP_WIRE_LIMITS7.labelCharacters, id),
|
|
5494
5255
|
mimeType: format.mimeType,
|
|
5495
|
-
extensions: boundWireTextArray(format.extensions, 64,
|
|
5256
|
+
extensions: boundWireTextArray(format.extensions, 64, MCP_WIRE_LIMITS7.labelCharacters),
|
|
5496
5257
|
import: { ...format.import },
|
|
5497
5258
|
export: { ...format.export }
|
|
5498
5259
|
};
|
|
@@ -5508,7 +5269,6 @@ var init_agentic_tools = __esm({
|
|
|
5508
5269
|
init_preview_service();
|
|
5509
5270
|
init_error_result();
|
|
5510
5271
|
init_progress();
|
|
5511
|
-
init_revision_service();
|
|
5512
5272
|
init_output_bounds();
|
|
5513
5273
|
READ_ONLY = {
|
|
5514
5274
|
readOnlyHint: true,
|
|
@@ -5528,7 +5288,7 @@ var init_agentic_tools = __esm({
|
|
|
5528
5288
|
idempotentHint: false,
|
|
5529
5289
|
openWorldHint: false
|
|
5530
5290
|
};
|
|
5531
|
-
identifierSchema = z.string().min(1).max(
|
|
5291
|
+
identifierSchema = z.string().min(1).max(MCP_WIRE_LIMITS7.identifierCharacters).regex(MCP_OUTPUT_PATTERNS.identifier);
|
|
5532
5292
|
fidelitySchemas = {
|
|
5533
5293
|
editable: z.enum(MCP_FORMAT_FIDELITIES.docx),
|
|
5534
5294
|
pdf: z.enum(MCP_FORMAT_FIDELITIES.pdf),
|
|
@@ -5641,7 +5401,7 @@ var init_agentic_tools = __esm({
|
|
|
5641
5401
|
|
|
5642
5402
|
// src/mcp/discovery-tools.ts
|
|
5643
5403
|
import { z as z2 } from "zod";
|
|
5644
|
-
import { MCP_WIRE_LIMITS as
|
|
5404
|
+
import { MCP_WIRE_LIMITS as MCP_WIRE_LIMITS8 } from "@bendyline/docblocks/mcp";
|
|
5645
5405
|
import { DOCBLOCKS_MCP_TOOL_OUTPUT_SCHEMAS as DOCBLOCKS_MCP_TOOL_OUTPUT_SCHEMAS2 } from "@bendyline/docblocks/mcp/zod";
|
|
5646
5406
|
function registerDiscoveryTools(server) {
|
|
5647
5407
|
server.registerTool(
|
|
@@ -5676,9 +5436,9 @@ function registerDiscoveryTools(server) {
|
|
|
5676
5436
|
try {
|
|
5677
5437
|
const { getThemeSummaries } = await import("@bendyline/squisq/schemas");
|
|
5678
5438
|
const result = {
|
|
5679
|
-
themes: getThemeSummaries().slice(0,
|
|
5439
|
+
themes: getThemeSummaries().slice(0, MCP_WIRE_LIMITS8.arrayEntries).map((theme) => ({
|
|
5680
5440
|
id: requireWireIdentifier(theme.id, "theme id"),
|
|
5681
|
-
name: boundWireText(theme.name,
|
|
5441
|
+
name: boundWireText(theme.name, MCP_WIRE_LIMITS8.labelCharacters, theme.id),
|
|
5682
5442
|
description: boundWireText(theme.description ?? "")
|
|
5683
5443
|
}))
|
|
5684
5444
|
};
|
|
@@ -5703,9 +5463,9 @@ function registerDiscoveryTools(server) {
|
|
|
5703
5463
|
try {
|
|
5704
5464
|
const { getTransformStyleSummaries } = await import("@bendyline/squisq/transform");
|
|
5705
5465
|
const result = {
|
|
5706
|
-
styles: getTransformStyleSummaries().slice(0,
|
|
5466
|
+
styles: getTransformStyleSummaries().slice(0, MCP_WIRE_LIMITS8.arrayEntries).map((style) => ({
|
|
5707
5467
|
id: requireWireIdentifier(style.id, "transform style id"),
|
|
5708
|
-
name: boundWireText(style.name,
|
|
5468
|
+
name: boundWireText(style.name, MCP_WIRE_LIMITS8.labelCharacters, style.id),
|
|
5709
5469
|
description: boundWireText(style.description)
|
|
5710
5470
|
}))
|
|
5711
5471
|
};
|
|
@@ -5739,16 +5499,16 @@ function registerDiscoveryTools(server) {
|
|
|
5739
5499
|
function serializableCapabilities() {
|
|
5740
5500
|
return MCP_FORMAT_CAPABILITIES.slice(0, 64).map((format) => ({
|
|
5741
5501
|
id: requireWireFormat(format.id),
|
|
5742
|
-
label: boundWireText(format.label,
|
|
5502
|
+
label: boundWireText(format.label, MCP_WIRE_LIMITS8.labelCharacters, format.id),
|
|
5743
5503
|
mimeType: format.mimeType,
|
|
5744
|
-
extensions: boundWireTextArray(format.extensions, 64,
|
|
5504
|
+
extensions: boundWireTextArray(format.extensions, 64, MCP_WIRE_LIMITS8.labelCharacters),
|
|
5745
5505
|
import: { ...format.import },
|
|
5746
5506
|
export: { ...format.export }
|
|
5747
5507
|
}));
|
|
5748
5508
|
}
|
|
5749
5509
|
function requireWireFormat(value) {
|
|
5750
5510
|
requireWireIdentifier(value, "format id");
|
|
5751
|
-
if (value.length >
|
|
5511
|
+
if (value.length > MCP_WIRE_LIMITS8.formatCharacters || !MCP_OUTPUT_PATTERNS.format.test(value)) {
|
|
5752
5512
|
throw new Error("Linked Squisq returned an invalid MCP format id");
|
|
5753
5513
|
}
|
|
5754
5514
|
return value;
|
|
@@ -5874,12 +5634,12 @@ function presentationPrompt(topic, style, theme, template) {
|
|
|
5874
5634
|
return `Create a presentation about: ${topic}
|
|
5875
5635
|
|
|
5876
5636
|
1. Call get_authoring_context with targetFormat "pptx" and goal "content-first" for the complete linked-Squisq vocabulary and workflow in one response.
|
|
5877
|
-
2.
|
|
5878
|
-
3.
|
|
5879
|
-
4.
|
|
5880
|
-
5.
|
|
5881
|
-
6.
|
|
5882
|
-
7. Call convert_document with a pptx target. Choose editable-native for editable Office structures, rendered-fidelity for exact Squisq visuals, or hybrid for rendered visuals plus semantic retention.
|
|
5637
|
+
2. Treat the topic facts as a closed evidence set. Preserve them exactly, use temporal or correlational wording unless causality is supplied, and label calculations, assumptions, hypotheses, recommendations, and examples. Causal links, rhetorical performance labels, superlatives, sole causes, capabilities, owners, dates, channels, and operational details must be supplied or explicitly framed. Do not connect separate metrics, audiences, segments, or workflows unless the relationship is supplied. Prefer observed, coincided with, intended to, or proposed over drove, addresses, protects, or proves. Add decision value through supplied baselines, goals, targets, rankings, and transparent calculations. Do not call choices a sequence or capacity allocation unless order, timing, or resources were supplied. When the requested content needs unsupplied operating details, add one proposed operating model scope note that applies to them.
|
|
5638
|
+
3. Match every explicitly requested slide count exactly. Use exactly one level-one Markdown heading (\`#\`) per slide and no level-two through level-six headings because every heading becomes a slide by default; use lists, tables, or bold labels within a slide. Target at most 80 words per slide. Make slide one a supported point-of-view thesis, not a generic title or unsupported flourish. For requested choices, state concrete opportunity costs grounded in supplied alternatives and one clearly labeled proposed accountable role per choice. Label any unsupplied capacity or outcome assumption as \`Assumption:\` or \`Potential tradeoff:\`. Author complete Markdown sections with accessible alt text. Put annotations on headings, for example \`# Heading {[content]}\`; a standalone \`{[template]}\` creates an extra block. Prefer style "${style ?? "choose from the returned transform styles"}", theme "${theme ?? "choose from the returned themes"}", and template "${template ?? "content until visual optimization"}".
|
|
5639
|
+
4. Keep the complete Markdown as the authoritative draft. Pass it\u2014or a bundle source when assets are needed\u2014directly to convert_document. Use create_document_bundle only when the same materially large Markdown-and-asset bundle will feed several operations. Do not write a temporary local Markdown file or invent a root id.
|
|
5640
|
+
5. Before conversion, count slide sections, verify every requested element, and rewrite or label every unsupported claim. Label any new review cadence or measurement procedure as proposed. Use validate_document when syntax, accessibility, retention, or target diagnostics need review; use preview_document when visual evidence such as overflow needs review. Repair findings in the complete Markdown.
|
|
5641
|
+
6. Only after content coverage is acceptable, replace selected \`content\` blocks with compatible visual templates such as \`definitionCard\`, \`dataTable\`, \`comparisonBar\`, or \`list\` when their semantic inputs fit. Preserve required content.
|
|
5642
|
+
7. Call convert_document with the complete source and a pptx target. Choose editable-native for editable Office structures, rendered-fidelity for exact Squisq visuals, or hybrid for rendered visuals plus semantic retention. Revise by editing the complete Markdown and converting again.
|
|
5883
5643
|
8. Use get_conversion_report for provenance and save_artifact only when a durable file is required.`;
|
|
5884
5644
|
}
|
|
5885
5645
|
function videoPrompt(topic, orientation, theme, template) {
|
|
@@ -5887,20 +5647,19 @@ function videoPrompt(topic, orientation, theme, template) {
|
|
|
5887
5647
|
|
|
5888
5648
|
1. Call get_authoring_context with targetFormat "mp4" for the complete linked-Squisq vocabulary and workflow.
|
|
5889
5649
|
2. Author concise Markdown for a ${orientation ?? "landscape"} animated sequence using theme "${theme ?? "choose from the returned themes"}" and template "${template ?? "content until visual optimization"}". Bind annotations to headings.
|
|
5890
|
-
3.
|
|
5891
|
-
4. Call
|
|
5892
|
-
5.
|
|
5893
|
-
6. Use get_conversion_report for provenance and save_artifact only when a durable file is required.`;
|
|
5650
|
+
3. Keep the complete Markdown as the authoritative draft and pass it\u2014or a bundle source when assets are needed\u2014directly to convert_document. Use validate_document for uncertain target constraints and preview_document when representative-frame evidence is useful; repair findings in the complete Markdown.
|
|
5651
|
+
4. Call convert_document with the complete source, an mp4 target, and orientation "${orientation ?? "landscape"}"; monitor progress and honor cancellation. Revise by editing the complete Markdown and converting again.
|
|
5652
|
+
5. Use get_conversion_report for provenance and save_artifact only when a durable file is required.`;
|
|
5894
5653
|
}
|
|
5895
5654
|
function documentPrompt(topic, format, theme, template) {
|
|
5896
5655
|
const target = format ?? "pdf";
|
|
5897
5656
|
return `Create a professional document about: ${topic}
|
|
5898
5657
|
|
|
5899
5658
|
1. Call get_authoring_context with targetFormat "${target}" for the complete linked-Squisq vocabulary and workflow.
|
|
5900
|
-
2.
|
|
5901
|
-
3.
|
|
5902
|
-
4.
|
|
5903
|
-
5. Call
|
|
5659
|
+
2. Treat the topic facts as a closed evidence set. Preserve them exactly, use temporal or correlational wording unless causality is supplied, and label calculations, assumptions, hypotheses, recommendations, and examples. Causal links, superlatives, sole causes, capabilities, owners, dates, channels, and operational details must be supplied or explicitly framed. When the requested genre needs unsupplied roles, gates, timelines, channels, or procedures, add one proposed operating model scope note that applies to those details.
|
|
5660
|
+
3. Honor the requested word range and document genre. Author structured Markdown using theme "${theme ?? "choose from the returned themes"}" and template "${template ?? "content until visual optimization"}". Bind annotations to headings. Use connected memo prose for executive decisions and native headings, tables, and checklists for operational documents; retain complete-body content when a visual template would discard detail.
|
|
5661
|
+
4. Before conversion, count document words, verify every requested element, and rewrite or label every unsupported claim. Keep the complete Markdown as the authoritative draft and pass it\u2014or a bundle source when assets are needed\u2014directly to convert_document. Use validate_document when syntax, accessibility, retention, or target diagnostics need review, and preview_document when page-layout evidence is useful; repair findings in the complete Markdown.
|
|
5662
|
+
5. Call convert_document with the complete source and a ${target} target to create an immutable artifact. Revise by editing the complete Markdown and converting again.
|
|
5904
5663
|
6. Use get_conversion_report for provenance and save_artifact only when a durable file is required.`;
|
|
5905
5664
|
}
|
|
5906
5665
|
function complete(values, prefix) {
|
|
@@ -5943,7 +5702,7 @@ function createMcpServer(options = {}) {
|
|
|
5943
5702
|
const server = new McpServer(
|
|
5944
5703
|
{ name: "docblocks", version: getPackageVersion() },
|
|
5945
5704
|
{
|
|
5946
|
-
instructions: "
|
|
5705
|
+
instructions: "Treat provided facts as a closed evidence set: preserve them exactly; use temporal or correlational wording unless causality is supplied; label calculations, assumptions, hypotheses, recommendations, and examples. Causal links, rhetorical performance labels, superlatives, sole causes, targets, capabilities, owners, dates, channels, and operational details must be supplied or explicitly framed. Do not connect separate metrics, audiences, segments, or workflows unless the relationship is supplied. Prefer observed, coincided with, intended to, or proposed over drove, addresses, protects, or proves. Add decision value through supplied baselines, goals, targets, rankings, and transparent calculations. Do not call choices a sequence or capacity allocation unless order, timing, or resources were supplied. When a requested policy, playbook, or training guide needs unsupplied operating details, add one proposed operating model scope note, then complete every requested element. Match explicit slide/page counts and word ranges exactly; target at most 80 words per presentation section. Make slide one a supported point-of-view thesis. For requested choices, state concrete opportunity costs grounded in supplied alternatives and one proposed accountable role per choice; label unsupplied capacity, outcome, or review-cadence assumptions. Before conversion, count sections or words, verify required elements, and audit unsupported claims. Start with get_authoring_context for the compact linked-Squisq contract and structured catalog. Author complete Squisq-compatible Markdown with template annotations on headings, for example `# Heading {[content]}`; standalone `{[template]}` creates an extra heading-less block. Ordinary headings default to the loss-averse `content` template. The canonical path is complete Markdown\u2014or a bundle source when assets are needed\u2014directly into convert_document; revise by editing the complete Markdown and converting again. create_document_bundle is optional for materially large, reusable Markdown-and-asset bundles. Use inspect_document, validate_document, and preview_document when their evidence is useful rather than as required phases. Save only the final durable artifact. Never invent root ids: call list_roots and use an id exactly as returned."
|
|
5947
5706
|
}
|
|
5948
5707
|
);
|
|
5949
5708
|
registerAgenticTools(server, {
|