@bendyline/docblocks-cli 2.2.0 → 2.2.2
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 -0
- package/THIRD_PARTY_NOTICES.txt +16509 -0
- package/dist/bin.js +164 -52
- package/dist/eval/cli.js +39 -19
- package/package.json +10 -9
package/dist/bin.js
CHANGED
|
@@ -1872,6 +1872,66 @@ async function validatePreparedDocument(_documents, prepared, targetFormat, sign
|
|
|
1872
1872
|
diagnostics: unique
|
|
1873
1873
|
};
|
|
1874
1874
|
}
|
|
1875
|
+
function annotationSyntaxDiagnostics(markdown, stage, format) {
|
|
1876
|
+
const diagnostics = [];
|
|
1877
|
+
const lines = markdown.split(/\r?\n/);
|
|
1878
|
+
let inFence = false;
|
|
1879
|
+
for (let lineIndex = 0; lineIndex < lines.length; lineIndex += 1) {
|
|
1880
|
+
if (diagnostics.length >= MCP_WIRE_LIMITS5.arrayEntries) break;
|
|
1881
|
+
const rawLine = lines[lineIndex];
|
|
1882
|
+
if (/^\s*(?:```|~~~)/u.test(rawLine)) {
|
|
1883
|
+
inFence = !inFence;
|
|
1884
|
+
continue;
|
|
1885
|
+
}
|
|
1886
|
+
if (inFence) continue;
|
|
1887
|
+
const line = rawLine.replace(/`[^`]*`/gu, "``");
|
|
1888
|
+
let search = 0;
|
|
1889
|
+
while (search < line.length) {
|
|
1890
|
+
const open6 = line.indexOf("{[", search);
|
|
1891
|
+
if (open6 === -1) break;
|
|
1892
|
+
const close = line.indexOf("]}", open6 + 2);
|
|
1893
|
+
if (close === -1) {
|
|
1894
|
+
diagnostics.push(
|
|
1895
|
+
malformedAnnotationDiagnostic(
|
|
1896
|
+
stage,
|
|
1897
|
+
format,
|
|
1898
|
+
lineIndex + 1,
|
|
1899
|
+
open6 + 1,
|
|
1900
|
+
'An annotation opened with "{[" has no matching "]}" on the same line.'
|
|
1901
|
+
)
|
|
1902
|
+
);
|
|
1903
|
+
break;
|
|
1904
|
+
}
|
|
1905
|
+
const inner = line.slice(open6 + 2, close).replace(/"[^"]*"/gu, '""');
|
|
1906
|
+
if (/[{}[\]]/u.test(inner)) {
|
|
1907
|
+
diagnostics.push(
|
|
1908
|
+
malformedAnnotationDiagnostic(
|
|
1909
|
+
stage,
|
|
1910
|
+
format,
|
|
1911
|
+
lineIndex + 1,
|
|
1912
|
+
open6 + 1,
|
|
1913
|
+
"An annotation contains a stray brace or bracket outside quoted values."
|
|
1914
|
+
)
|
|
1915
|
+
);
|
|
1916
|
+
}
|
|
1917
|
+
search = close + 2;
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
return diagnostics;
|
|
1921
|
+
}
|
|
1922
|
+
function malformedAnnotationDiagnostic(stage, format, line, column, message) {
|
|
1923
|
+
return {
|
|
1924
|
+
code: "malformed-template-annotation",
|
|
1925
|
+
severity: "warning",
|
|
1926
|
+
stage,
|
|
1927
|
+
format,
|
|
1928
|
+
count: 1,
|
|
1929
|
+
message,
|
|
1930
|
+
remediation: 'Repair the annotation so it reads exactly `{[templateId key="value"]}` with no extra braces or brackets, then validate again.',
|
|
1931
|
+
retryable: false,
|
|
1932
|
+
location: { kind: "source", line, column }
|
|
1933
|
+
};
|
|
1934
|
+
}
|
|
1875
1935
|
async function authoringDiagnostics(prepared, stage, format, signal) {
|
|
1876
1936
|
throwIfAborted5(signal);
|
|
1877
1937
|
const {
|
|
@@ -1885,7 +1945,11 @@ async function authoringDiagnostics(prepared, stage, format, signal) {
|
|
|
1885
1945
|
const blocks = flattenBlocks(prepared.doc.blocks);
|
|
1886
1946
|
const analyzedBlocks = blocks.slice(0, MCP_WIRE_LIMITS5.arrayEntries);
|
|
1887
1947
|
const theme = resolveThemeForDoc(prepared.doc);
|
|
1888
|
-
const diagnostics =
|
|
1948
|
+
const diagnostics = annotationSyntaxDiagnostics(
|
|
1949
|
+
prepared.markdown,
|
|
1950
|
+
stage,
|
|
1951
|
+
format
|
|
1952
|
+
);
|
|
1889
1953
|
for (let index = 0; index < analyzedBlocks.length; index += 1) {
|
|
1890
1954
|
const checkpoint = cancellationCheckpoint(signal, index);
|
|
1891
1955
|
if (checkpoint) await checkpoint;
|
|
@@ -4189,7 +4253,7 @@ function registerAgenticTools(server, context) {
|
|
|
4189
4253
|
server.registerTool(
|
|
4190
4254
|
"list_roots",
|
|
4191
4255
|
{
|
|
4192
|
-
description: "
|
|
4256
|
+
description: "Call first when durable local output is requested. Lists opaque startup-granted roots; if none is write-enabled, save_artifact cannot publish a file and the MCP server must be restarted with --allow-write.",
|
|
4193
4257
|
inputSchema: z.object({}).strict(),
|
|
4194
4258
|
outputSchema: DOCBLOCKS_MCP_TOOL_OUTPUT_SCHEMAS.list_roots,
|
|
4195
4259
|
annotations: READ_ONLY
|
|
@@ -4197,7 +4261,7 @@ function registerAgenticTools(server, context) {
|
|
|
4197
4261
|
async () => {
|
|
4198
4262
|
try {
|
|
4199
4263
|
const roots = (await context.authority).listRoots();
|
|
4200
|
-
return textAndStructured({ roots });
|
|
4264
|
+
return textAndStructured({ roots }, rootDiscoveryText(roots));
|
|
4201
4265
|
} catch (caught) {
|
|
4202
4266
|
return errorResult(caught, "resolve");
|
|
4203
4267
|
}
|
|
@@ -4274,7 +4338,7 @@ function registerAgenticTools(server, context) {
|
|
|
4274
4338
|
server.registerTool(
|
|
4275
4339
|
"create_document_bundle",
|
|
4276
4340
|
{
|
|
4277
|
-
description: "
|
|
4341
|
+
description: "Stage Markdown plus authority-scoped assets as a reusable immutable DBK artifact when the same complete draft will be passed to two or more validate, inspect, preview, or convert calls. Pass its artifact URI instead of repeating the Markdown.",
|
|
4278
4342
|
inputSchema: z.object({ source: bundleDocumentSourceSchema }).strict(),
|
|
4279
4343
|
outputSchema: DOCBLOCKS_MCP_TOOL_OUTPUT_SCHEMAS.create_document_bundle,
|
|
4280
4344
|
annotations: ARTIFACT_CREATING
|
|
@@ -4348,7 +4412,7 @@ function registerAgenticTools(server, context) {
|
|
|
4348
4412
|
server.registerTool(
|
|
4349
4413
|
"inspect_document",
|
|
4350
4414
|
{
|
|
4351
|
-
description: "Inspect
|
|
4415
|
+
description: "Inspect bounded semantic structure, block provenance, assets, metadata, theme, and diagnostics. Use for those details; do not pair it with validate_document for a routine export preflight.",
|
|
4352
4416
|
inputSchema: z.object({
|
|
4353
4417
|
source: documentSourceSchema,
|
|
4354
4418
|
maxBlocks: z.number().int().min(1).max(2e3).optional(),
|
|
@@ -4380,7 +4444,7 @@ function registerAgenticTools(server, context) {
|
|
|
4380
4444
|
server.registerTool(
|
|
4381
4445
|
"validate_document",
|
|
4382
4446
|
{
|
|
4383
|
-
description: "
|
|
4447
|
+
description: "Primary pre-export review for structure, template content retention, annotations, assets, accessibility, and target fidelity. Diagnostics include repairs; normally do not also call inspect_document.",
|
|
4384
4448
|
inputSchema: z.object({
|
|
4385
4449
|
source: documentSourceSchema,
|
|
4386
4450
|
targetFormat: formatInputSchema.nullable().optional()
|
|
@@ -4553,7 +4617,7 @@ function registerAuthoringGuideResource(server) {
|
|
|
4553
4617
|
"authoring-guide",
|
|
4554
4618
|
"docblocks://authoring-guide",
|
|
4555
4619
|
{
|
|
4556
|
-
description: "
|
|
4620
|
+
description: "Complete linked-Squisq authoring catalog with exact template inputs, fidelity modes, themes, and transform styles. Read only when the focused authoring context is insufficient.",
|
|
4557
4621
|
mimeType: "application/json",
|
|
4558
4622
|
annotations: { audience: ["assistant"], priority: 1 }
|
|
4559
4623
|
},
|
|
@@ -4564,15 +4628,15 @@ function registerAuthoringGuideResource(server) {
|
|
|
4564
4628
|
import("@bendyline/squisq/transform")
|
|
4565
4629
|
]);
|
|
4566
4630
|
const guide = {
|
|
4567
|
-
version:
|
|
4631
|
+
version: 7,
|
|
4568
4632
|
workflow: [
|
|
4569
4633
|
"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
4634
|
"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
4635
|
"author complete Squisq-compatible Markdown with annotations bound to headings; ordinary headings default to the loss-averse content template",
|
|
4572
4636
|
"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
4637
|
"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
|
|
4575
|
-
"use
|
|
4638
|
+
"use create_document_bundle when the same complete draft will be passed to two or more validate, inspect, preview, or convert calls, then pass its artifact URI instead of repeating Markdown",
|
|
4639
|
+
"use validate_document as the routine export preflight; use inspect_document only for semantic structure, provenance, assets, metadata, or theme details; use preview_document only when visual evidence is useful",
|
|
4576
4640
|
"for visual polish, replace selected content blocks with compatible visual templates while preserving required content",
|
|
4577
4641
|
"convert_document creates one or more immutable artifacts from the authoritative complete source",
|
|
4578
4642
|
"save_artifact only when a durable file is required"
|
|
@@ -4616,7 +4680,7 @@ function registerTemplateTools(server, context) {
|
|
|
4616
4680
|
server.registerTool(
|
|
4617
4681
|
"get_authoring_context",
|
|
4618
4682
|
{
|
|
4619
|
-
description: "Get a
|
|
4683
|
+
description: "Get a focused authoring contract, target capability, safe default template, themes, transforms, and optional source-based recommendations. Exact full template inputs remain on demand through describe_template or docblocks://authoring-guide.",
|
|
4620
4684
|
inputSchema: z.object({
|
|
4621
4685
|
targetFormat: formatInputSchema.optional(),
|
|
4622
4686
|
goal: z.enum(["content-first", "visual-polish"]).optional(),
|
|
@@ -4639,11 +4703,13 @@ function registerTemplateTools(server, context) {
|
|
|
4639
4703
|
throw new Error(`Format "${normalizedTarget}" is not export-capable`);
|
|
4640
4704
|
}
|
|
4641
4705
|
}
|
|
4642
|
-
const [
|
|
4706
|
+
const [fullTemplates, schemaModule, transformModule] = await Promise.all([
|
|
4643
4707
|
authoringTemplateCatalog(),
|
|
4644
4708
|
import("@bendyline/squisq/schemas"),
|
|
4645
4709
|
import("@bendyline/squisq/transform")
|
|
4646
4710
|
]);
|
|
4711
|
+
const annotationHandling = normalizedTarget ? await targetTemplateAnnotationHandling(normalizedTarget) : null;
|
|
4712
|
+
const candidateTemplates = annotationHandling === "ignored" ? fullTemplates.filter((template) => template.safeForContentFirst) : fullTemplates;
|
|
4647
4713
|
let recommendations = [];
|
|
4648
4714
|
let totalBlocks = null;
|
|
4649
4715
|
let truncated = false;
|
|
@@ -4663,7 +4729,7 @@ function registerTemplateTools(server, context) {
|
|
|
4663
4729
|
const profile = recommendModule.profileBlockContents(block.contents ?? []);
|
|
4664
4730
|
const visual = recommendModule.recommendTemplatesForBlock(
|
|
4665
4731
|
profile,
|
|
4666
|
-
|
|
4732
|
+
candidateTemplates.map((template) => template.id)
|
|
4667
4733
|
).recommended;
|
|
4668
4734
|
const recommendedTemplateIds = goal === "content-first" ? ["content", ...visual.filter((id) => id !== "content")] : visual;
|
|
4669
4735
|
return {
|
|
@@ -4687,29 +4753,23 @@ function registerTemplateTools(server, context) {
|
|
|
4687
4753
|
defaultTemplateId: "content",
|
|
4688
4754
|
defaultFidelity: authoringDefaultFidelity(normalizedTarget, goal),
|
|
4689
4755
|
workflow: [
|
|
4690
|
-
"
|
|
4691
|
-
"
|
|
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.",
|
|
4756
|
+
"For durable local output, call list_roots before drafting. If no returned root is write-enabled, stop and explain that the MCP server must restart with --allow-write; do not fall back to a shell or CLI converter. A transient artifact is acceptable only when the user did not require a file.",
|
|
4757
|
+
"Treat supplied facts as a closed evidence set. Preserve them exactly; label calculations, assumptions, hypotheses, recommendations, causal claims, capabilities, owners, dates, and unsupplied operating details. When a requested policy or playbook needs invented procedures, introduce one proposed operating model scope note before those details.",
|
|
4695
4758
|
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
|
-
|
|
4697
|
-
"
|
|
4698
|
-
"
|
|
4699
|
-
"
|
|
4700
|
-
"
|
|
4701
|
-
"
|
|
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.",
|
|
4704
|
-
"Convert to immutable artifacts, inspect conversion reports, and save only final durable outputs."
|
|
4759
|
+
"Author the complete Squisq-compatible Markdown with annotations bound to headings. Ordinary headings default to the loss-averse content template; keep that default until the complete content is sound.",
|
|
4760
|
+
"Before conversion, count slide sections or document words, verify every requested element, and rewrite or label unsupported claims. For decisions, ground tradeoffs in supplied alternatives and label unsupplied accountability, capacity, outcomes, and review cadences as proposed or assumed.",
|
|
4761
|
+
"Use validate_document as the routine export preflight and follow its repair diagnostics. Call inspect_document only when semantic structure, provenance, assets, metadata, or theme details are needed.",
|
|
4762
|
+
"When the same complete draft will feed two or more validate, inspect, preview, or convert calls, stage it once with create_document_bundle and reuse its artifact URI; after edits, stage the revised draft again.",
|
|
4763
|
+
normalizedTarget === "pptx" ? "For visual polish, call recommend_templates on the complete draft, then describe_template only for selected candidates before replacing content blocks. Preserve required content and use preview_document only when visual evidence is needed." : annotationHandling === "ignored" ? "This target flattens template annotations to semantic content, so visual templates have no effect on the exported file: rely on native headings, tables, and checklists for structure and scanning." : "For visual polish, use native headings, tables, and checklists where they improve scanning; describe a selected visual template before use and keep complete-body content when it would discard detail.",
|
|
4764
|
+
"Pass the authoritative Markdown or bundle source directly to convert_document. It returns immutable artifacts; call save_artifact only for final durable outputs and never switch to a shell or CLI converter."
|
|
4705
4765
|
],
|
|
4706
4766
|
syntax: {
|
|
4707
4767
|
headingAnnotation: "# Heading {[content]}",
|
|
4708
4768
|
standaloneAnnotation: "{[content]}",
|
|
4709
4769
|
standaloneWarning: "A standalone annotation creates an additional heading-less block. Bind it to a heading unless that extra block is deliberate."
|
|
4710
4770
|
},
|
|
4711
|
-
formats,
|
|
4712
|
-
templates,
|
|
4771
|
+
formats: normalizedTarget ? formats.filter((format) => format.id === normalizedTarget) : formats,
|
|
4772
|
+
templates: focusedAuthoringTemplates(candidateTemplates, recommendations),
|
|
4713
4773
|
themes: schemaModule.getThemeSummaries().slice(0, MCP_WIRE_LIMITS7.arrayEntries).map((theme) => ({
|
|
4714
4774
|
id: requireWireIdentifier(theme.id, "theme id"),
|
|
4715
4775
|
name: boundWireText(theme.name, MCP_WIRE_LIMITS7.labelCharacters, theme.id),
|
|
@@ -4724,7 +4784,19 @@ function registerTemplateTools(server, context) {
|
|
|
4724
4784
|
totalBlocks,
|
|
4725
4785
|
truncated
|
|
4726
4786
|
};
|
|
4727
|
-
return
|
|
4787
|
+
return {
|
|
4788
|
+
content: [
|
|
4789
|
+
{ type: "text", text: compactAuthoringContextText(payload) },
|
|
4790
|
+
{
|
|
4791
|
+
type: "resource_link",
|
|
4792
|
+
uri: "docblocks://authoring-guide",
|
|
4793
|
+
name: "authoring-guide",
|
|
4794
|
+
description: "Complete linked-Squisq authoring catalog; read only if needed.",
|
|
4795
|
+
mimeType: "application/json"
|
|
4796
|
+
}
|
|
4797
|
+
],
|
|
4798
|
+
structuredContent: asStructuredContent(successResult(payload))
|
|
4799
|
+
};
|
|
4728
4800
|
});
|
|
4729
4801
|
} catch (caught) {
|
|
4730
4802
|
return errorResult(caught, "inspect", null, extra.signal);
|
|
@@ -5140,6 +5212,25 @@ function textAndStructured(payload, text = JSON.stringify(payload, null, 2)) {
|
|
|
5140
5212
|
structuredContent: asStructuredContent(successResult(payload))
|
|
5141
5213
|
};
|
|
5142
5214
|
}
|
|
5215
|
+
function rootDiscoveryText(roots) {
|
|
5216
|
+
if (roots.length === 0) {
|
|
5217
|
+
return "No DocBlocks MCP roots are configured. Durable file output is unavailable: restart the server with --allow-write <directory>. Do not fall back to a shell or CLI converter; keep a transient artifact only when the user did not require a file.";
|
|
5218
|
+
}
|
|
5219
|
+
const catalog = JSON.stringify({ roots }, null, 2);
|
|
5220
|
+
if (roots.some((root) => root.write)) return catalog;
|
|
5221
|
+
return `${catalog}
|
|
5222
|
+
|
|
5223
|
+
No returned root is write-enabled. Durable file output is unavailable: restart the server with --allow-write <directory>. Do not fall back to a shell or CLI converter.`;
|
|
5224
|
+
}
|
|
5225
|
+
function focusedAuthoringTemplates(candidates, recommendations) {
|
|
5226
|
+
const selectedIds = /* @__PURE__ */ new Set(["content"]);
|
|
5227
|
+
for (const recommendation of recommendations) {
|
|
5228
|
+
for (const templateId of recommendation.recommendedTemplateIds) {
|
|
5229
|
+
selectedIds.add(templateId);
|
|
5230
|
+
}
|
|
5231
|
+
}
|
|
5232
|
+
return candidates.filter((template) => selectedIds.has(template.id));
|
|
5233
|
+
}
|
|
5143
5234
|
function compactAuthoringContextText(context) {
|
|
5144
5235
|
const target = context.targetFormat ?? "unspecified target";
|
|
5145
5236
|
const lines = [
|
|
@@ -5153,7 +5244,7 @@ function compactAuthoringContextText(context) {
|
|
|
5153
5244
|
`Warning: ${context.syntax.standaloneWarning}`,
|
|
5154
5245
|
`Templates (${context.templates.length}): ${context.templates.map(({ id }) => id).join(", ")}`,
|
|
5155
5246
|
`Themes (${context.themes.length}): ${context.themes.map(({ id }) => id).join(", ")}`,
|
|
5156
|
-
`Transform styles (${context.transformStyles.length}): ${context.transformStyles.map(({ id }) => id).join(", ")}
|
|
5247
|
+
`Transform styles (${context.transformStyles.length}): ${context.transformStyles.map(({ id }) => id).join(", ")} \u2014 transforms re-compose blocks and can change section count; avoid on exact-count briefs.`
|
|
5157
5248
|
];
|
|
5158
5249
|
if (context.recommendations.length > 0) {
|
|
5159
5250
|
lines.push(
|
|
@@ -5164,7 +5255,7 @@ function compactAuthoringContextText(context) {
|
|
|
5164
5255
|
}
|
|
5165
5256
|
lines.push(
|
|
5166
5257
|
"",
|
|
5167
|
-
"
|
|
5258
|
+
"This response is intentionally focused. Use recommend_templates on a complete draft, describe_template for exact selected inputs, or read docblocks://authoring-guide only when the full catalog is required."
|
|
5168
5259
|
);
|
|
5169
5260
|
return lines.join("\n");
|
|
5170
5261
|
}
|
|
@@ -5232,6 +5323,15 @@ async function authoringTemplateCatalog() {
|
|
|
5232
5323
|
};
|
|
5233
5324
|
});
|
|
5234
5325
|
}
|
|
5326
|
+
async function targetTemplateAnnotationHandling(targetFormat) {
|
|
5327
|
+
const { createCliRegistry: createCliRegistry2 } = await import("@bendyline/squisq-cli/api");
|
|
5328
|
+
const definition = createCliRegistry2().get(targetFormat);
|
|
5329
|
+
if (definition && typeof definition === "object" && "templateAnnotationHandling" in definition) {
|
|
5330
|
+
const value = definition.templateAnnotationHandling;
|
|
5331
|
+
if (value === "rendered" || value === "preserved" || value === "ignored") return value;
|
|
5332
|
+
}
|
|
5333
|
+
return null;
|
|
5334
|
+
}
|
|
5235
5335
|
function authoringDefaultFidelity(targetFormat, goal) {
|
|
5236
5336
|
if (!targetFormat) return null;
|
|
5237
5337
|
if (targetFormat === "mp4" || targetFormat === "gif") return "rendered-fidelity";
|
|
@@ -5633,34 +5733,37 @@ function registerAuthoringPrompts(server) {
|
|
|
5633
5733
|
function presentationPrompt(topic, style, theme, template) {
|
|
5634
5734
|
return `Create a presentation about: ${topic}
|
|
5635
5735
|
|
|
5636
|
-
1.
|
|
5637
|
-
2.
|
|
5638
|
-
3.
|
|
5639
|
-
4.
|
|
5640
|
-
5.
|
|
5641
|
-
6.
|
|
5642
|
-
7.
|
|
5643
|
-
8.
|
|
5736
|
+
1. For durable output, call list_roots before drafting. If no returned root is write-enabled, stop and explain that the MCP server must restart with --allow-write; do not use a shell or CLI converter.
|
|
5737
|
+
2. Call get_authoring_context with targetFormat "pptx" and goal "content-first" for the focused linked-Squisq workflow and safe default. Read the full authoring-guide resource only if focused follow-up tools are insufficient.
|
|
5738
|
+
3. 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.
|
|
5739
|
+
4. 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"}".
|
|
5740
|
+
5. Keep the complete Markdown as the authoritative draft. If it will feed two or more validate, inspect, preview, or convert calls, stage it once with create_document_bundle and reuse the artifact URI. Otherwise pass it\u2014or a bundle source when assets are needed\u2014directly to convert_document. Do not write a temporary local Markdown file or invent a root id.
|
|
5741
|
+
6. Before conversion, count slide sections, verify every requested element, and rewrite or label every unsupported claim. Use validate_document as the routine export preflight; use inspect_document only for semantic or metadata detail and preview_document only for visual evidence such as overflow. Repair findings in the complete Markdown.
|
|
5742
|
+
7. Only after content coverage is acceptable, call recommend_templates, describe only selected candidates, and replace compatible \`content\` blocks when their semantic inputs fit. Preserve required content.
|
|
5743
|
+
8. 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.
|
|
5744
|
+
9. Use get_conversion_report for provenance and save_artifact only when a durable file is required.`;
|
|
5644
5745
|
}
|
|
5645
5746
|
function videoPrompt(topic, orientation, theme, template) {
|
|
5646
5747
|
return `Create a video about: ${topic}
|
|
5647
5748
|
|
|
5648
|
-
1.
|
|
5649
|
-
2.
|
|
5650
|
-
3.
|
|
5651
|
-
4.
|
|
5652
|
-
5.
|
|
5749
|
+
1. For durable output, call list_roots before drafting and stop if no root is write-enabled; do not use a shell or CLI converter.
|
|
5750
|
+
2. Call get_authoring_context with targetFormat "mp4" for the focused linked-Squisq workflow.
|
|
5751
|
+
3. 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.
|
|
5752
|
+
4. 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.
|
|
5753
|
+
5. 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.
|
|
5754
|
+
6. Use get_conversion_report for provenance and save_artifact only when a durable file is required.`;
|
|
5653
5755
|
}
|
|
5654
5756
|
function documentPrompt(topic, format, theme, template) {
|
|
5655
5757
|
const target = format ?? "pdf";
|
|
5656
5758
|
return `Create a professional document about: ${topic}
|
|
5657
5759
|
|
|
5658
|
-
1.
|
|
5659
|
-
2.
|
|
5660
|
-
3.
|
|
5661
|
-
4.
|
|
5662
|
-
5.
|
|
5663
|
-
6.
|
|
5760
|
+
1. For durable output, call list_roots before drafting and stop if no root is write-enabled; do not use a shell or CLI converter.
|
|
5761
|
+
2. Call get_authoring_context with targetFormat "${target}" for the focused linked-Squisq workflow.
|
|
5762
|
+
3. 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.
|
|
5763
|
+
4. 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.
|
|
5764
|
+
5. Before conversion, count document words, verify every requested element, and rewrite or label every unsupported claim. If the complete draft will feed two or more review or conversion calls, stage it with create_document_bundle and reuse the artifact URI. Use validate_document as the routine export preflight and preview_document only when page-layout evidence is useful; repair findings in the complete Markdown.
|
|
5765
|
+
6. 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.
|
|
5766
|
+
7. Use get_conversion_report for provenance and save_artifact only when a durable file is required.`;
|
|
5664
5767
|
}
|
|
5665
5768
|
function complete(values, prefix) {
|
|
5666
5769
|
const value = prefix ?? "";
|
|
@@ -5702,7 +5805,16 @@ function createMcpServer(options = {}) {
|
|
|
5702
5805
|
const server = new McpServer(
|
|
5703
5806
|
{ name: "docblocks", version: getPackageVersion() },
|
|
5704
5807
|
{
|
|
5705
|
-
instructions:
|
|
5808
|
+
instructions: [
|
|
5809
|
+
"For durable local output, call list_roots before drafting and use a returned write-enabled root id exactly as given. If none is writable, stop and explain that the server must restart with --allow-write; do not fall back to a shell or CLI converter.",
|
|
5810
|
+
"Call get_authoring_context once for the focused linked-Squisq contract. Read the full authoring-guide resource or call describe_template only when exact additional catalog detail is needed; do not also enumerate catalogs by default.",
|
|
5811
|
+
"Treat supplied facts as a closed evidence set: preserve them exactly, use temporal or correlational wording unless causality is supplied, and label calculations, assumptions, hypotheses, recommendations, capabilities, owners, dates, and unsupplied operating details. For a policy or playbook, introduce one proposed operating model scope note before invented procedures.",
|
|
5812
|
+
"Honor explicit slide/page counts and word ranges. For PPTX use one level-one heading per slide, no lower-level headings, and at most 80 words per slide. Ground decision tradeoffs in supplied alternatives and label unsupplied accountability, capacity, outcomes, or review cadences as proposed or assumed.",
|
|
5813
|
+
"Author complete Squisq-compatible Markdown with annotations on headings, for example `# Heading {[content]}`. Ordinary headings default to the loss-averse content template; standalone annotations create an extra heading-less block.",
|
|
5814
|
+
"Use validate_document as the routine export preflight and repair its diagnostics. Use inspect_document only for semantic structure, provenance, assets, metadata, or theme details, and preview_document only when visual evidence is useful.",
|
|
5815
|
+
"When the same complete draft will feed two or more validate, inspect, preview, or convert calls, stage it once with create_document_bundle and reuse its artifact URI instead of resending Markdown.",
|
|
5816
|
+
"Pass the complete Markdown or bundle source directly into convert_document. Save only the final durable artifact with save_artifact; never invent root ids or switch conversion to a shell or CLI."
|
|
5817
|
+
].join(" ")
|
|
5706
5818
|
}
|
|
5707
5819
|
);
|
|
5708
5820
|
registerAgenticTools(server, {
|
package/dist/eval/cli.js
CHANGED
|
@@ -704,7 +704,8 @@ function missingArtifact(caught) {
|
|
|
704
704
|
}
|
|
705
705
|
|
|
706
706
|
// src/eval/codex-host.ts
|
|
707
|
-
import { readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
|
|
707
|
+
import { mkdtemp, readFile as readFile3, rm, writeFile as writeFile2 } from "fs/promises";
|
|
708
|
+
import { tmpdir } from "os";
|
|
708
709
|
import path3 from "path";
|
|
709
710
|
import { z } from "zod";
|
|
710
711
|
|
|
@@ -908,17 +909,30 @@ async function runGeneration(options, testCase, caseDirectory) {
|
|
|
908
909
|
const prompt = generationPrompt(testCase, options.profile);
|
|
909
910
|
await writeFile2(path3.join(caseDirectory, "generation-prompt.txt"), prompt);
|
|
910
911
|
const resolved = await resolveCodexCommand(options.codexCommand);
|
|
912
|
+
const agentCwd = await mkdtemp(path3.join(tmpdir(), "docblocks-eval-agent-"));
|
|
911
913
|
const args = [
|
|
912
914
|
...resolved.prefixArgs,
|
|
913
|
-
...buildCodexGenerationArgs(
|
|
915
|
+
...buildCodexGenerationArgs(
|
|
916
|
+
options,
|
|
917
|
+
testCase,
|
|
918
|
+
caseDirectory,
|
|
919
|
+
agentCwd,
|
|
920
|
+
outputSchemaPath,
|
|
921
|
+
finalPath
|
|
922
|
+
)
|
|
914
923
|
];
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
924
|
+
let capture;
|
|
925
|
+
try {
|
|
926
|
+
capture = await runCapturedProcess({
|
|
927
|
+
command: resolved.command,
|
|
928
|
+
args,
|
|
929
|
+
cwd: agentCwd,
|
|
930
|
+
stdin: prompt,
|
|
931
|
+
timeoutMs: 15 * 60 * 1e3
|
|
932
|
+
});
|
|
933
|
+
} finally {
|
|
934
|
+
await rm(agentCwd, { recursive: true, force: true }).catch(() => void 0);
|
|
935
|
+
}
|
|
922
936
|
await Promise.all([
|
|
923
937
|
writeFile2(path3.join(caseDirectory, "generation-trace.jsonl"), capture.stdout),
|
|
924
938
|
writeFile2(path3.join(caseDirectory, "generation-stderr.log"), capture.stderr)
|
|
@@ -951,6 +965,7 @@ async function runLlmJudge(options, testCase, markdown, caseDirectory) {
|
|
|
951
965
|
const prompt = judgePrompt(testCase, markdown);
|
|
952
966
|
await writeFile2(path3.join(caseDirectory, "judge-prompt.txt"), prompt);
|
|
953
967
|
const resolved = await resolveCodexCommand(options.codexCommand);
|
|
968
|
+
const judgeCwd = await mkdtemp(path3.join(tmpdir(), "docblocks-eval-judge-"));
|
|
954
969
|
const args = [
|
|
955
970
|
...resolved.prefixArgs,
|
|
956
971
|
"exec",
|
|
@@ -964,7 +979,7 @@ async function runLlmJudge(options, testCase, markdown, caseDirectory) {
|
|
|
964
979
|
"--color",
|
|
965
980
|
"never",
|
|
966
981
|
"--cd",
|
|
967
|
-
|
|
982
|
+
judgeCwd,
|
|
968
983
|
"--output-schema",
|
|
969
984
|
outputSchemaPath,
|
|
970
985
|
"--output-last-message",
|
|
@@ -972,13 +987,18 @@ async function runLlmJudge(options, testCase, markdown, caseDirectory) {
|
|
|
972
987
|
...options.model ? ["--model", options.model] : [],
|
|
973
988
|
"-"
|
|
974
989
|
];
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
990
|
+
let capture;
|
|
991
|
+
try {
|
|
992
|
+
capture = await runCapturedProcess({
|
|
993
|
+
command: resolved.command,
|
|
994
|
+
args,
|
|
995
|
+
cwd: judgeCwd,
|
|
996
|
+
stdin: prompt,
|
|
997
|
+
timeoutMs: 10 * 60 * 1e3
|
|
998
|
+
});
|
|
999
|
+
} finally {
|
|
1000
|
+
await rm(judgeCwd, { recursive: true, force: true }).catch(() => void 0);
|
|
1001
|
+
}
|
|
982
1002
|
await Promise.all([
|
|
983
1003
|
writeFile2(path3.join(caseDirectory, "judge-trace.jsonl"), capture.stdout),
|
|
984
1004
|
writeFile2(path3.join(caseDirectory, "judge-stderr.log"), capture.stderr)
|
|
@@ -990,7 +1010,7 @@ async function runLlmJudge(options, testCase, markdown, caseDirectory) {
|
|
|
990
1010
|
usage: extractTokenUsage(capture.stdout)
|
|
991
1011
|
};
|
|
992
1012
|
}
|
|
993
|
-
function buildCodexGenerationArgs(options, testCase, caseDirectory, outputSchemaPath, finalPath) {
|
|
1013
|
+
function buildCodexGenerationArgs(options, testCase, caseDirectory, agentCwd, outputSchemaPath, finalPath) {
|
|
994
1014
|
const mcpArgs = [
|
|
995
1015
|
options.cliEntry,
|
|
996
1016
|
"mcp",
|
|
@@ -1013,7 +1033,7 @@ function buildCodexGenerationArgs(options, testCase, caseDirectory, outputSchema
|
|
|
1013
1033
|
"--color",
|
|
1014
1034
|
"never",
|
|
1015
1035
|
"--cd",
|
|
1016
|
-
|
|
1036
|
+
agentCwd,
|
|
1017
1037
|
"-c",
|
|
1018
1038
|
`mcp_servers.docblocks.command=${tomlString(process.execPath)}`,
|
|
1019
1039
|
"-c",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bendyline/docblocks-cli",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.2",
|
|
4
4
|
"description": "Build, preview, convert, render, inspect, and automate documents",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Bendyline",
|
|
@@ -39,24 +39,25 @@
|
|
|
39
39
|
"node": ">=22.14.0"
|
|
40
40
|
},
|
|
41
41
|
"files": [
|
|
42
|
-
"dist"
|
|
42
|
+
"dist",
|
|
43
|
+
"THIRD_PARTY_NOTICES.txt"
|
|
43
44
|
],
|
|
44
45
|
"scripts": {
|
|
45
46
|
"build": "tsup",
|
|
46
47
|
"typecheck": "tsc --noEmit"
|
|
47
48
|
},
|
|
48
49
|
"dependencies": {
|
|
49
|
-
"@bendyline/docblocks": "2.2.
|
|
50
|
-
"@bendyline/squisq": "2.
|
|
51
|
-
"@bendyline/squisq-cli": "2.
|
|
52
|
-
"@bendyline/squisq-formats": "2.3.
|
|
53
|
-
"@bendyline/squisq-react": "2.
|
|
54
|
-
"@bendyline/squisq-video": "2.2.
|
|
50
|
+
"@bendyline/docblocks": "2.2.2",
|
|
51
|
+
"@bendyline/squisq": "2.4.1",
|
|
52
|
+
"@bendyline/squisq-cli": "2.4.1",
|
|
53
|
+
"@bendyline/squisq-formats": "2.3.5",
|
|
54
|
+
"@bendyline/squisq-react": "2.4.1",
|
|
55
|
+
"@bendyline/squisq-video": "2.2.5",
|
|
55
56
|
"@modelcontextprotocol/sdk": "1.29.0",
|
|
56
57
|
"commander": "13.1.0",
|
|
57
58
|
"jszip": "3.10.1",
|
|
58
|
-
"playwright-core": "1.58.2",
|
|
59
59
|
"pdf-lib": "1.17.1",
|
|
60
|
+
"playwright-core": "1.61.1",
|
|
60
61
|
"zod": "3.25.76"
|
|
61
62
|
}
|
|
62
63
|
}
|