flappa-doormal 2.19.0 → 2.21.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.
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,156 @@
1
+ #!/usr/bin/env node
2
+ import { n as segmentPages, p as validateSegments, t as suggestSegmentationOptions } from "../segmentation-advisor-D375TL8-.mjs";
3
+ import { McpServer, StdioServerTransport } from "@modelcontextprotocol/server";
4
+ import { z } from "zod";
5
+ //#region src/mcp/tools.ts
6
+ const buildPreviewStats = (pages, options, segments, sampleSegments) => {
7
+ const validation = validateSegments(pages, options, segments);
8
+ const totalLength = segments.reduce((sum, segment) => sum + segment.content.length, 0);
9
+ const multiPageSegments = segments.filter((segment) => segment.to !== void 0 && segment.to !== segment.from).length;
10
+ return {
11
+ averageSegmentLength: segments.length === 0 ? 0 : totalLength / segments.length,
12
+ maxSegmentLength: Math.max(0, ...segments.map((segment) => segment.content.length)),
13
+ multiPageSegments,
14
+ segmentCount: segments.length,
15
+ segmentSamples: segments.slice(0, sampleSegments),
16
+ segments,
17
+ validation
18
+ };
19
+ };
20
+ const computeCandidateScore = (preview) => {
21
+ const issuePenalty = preview.validation.summary.issues * 100;
22
+ const multiPagePenalty = preview.multiPageSegments * 5;
23
+ const oversizePenalty = Math.floor(preview.maxSegmentLength / 500);
24
+ return Math.min(preview.segmentCount, 200) - issuePenalty - multiPagePenalty - oversizePenalty;
25
+ };
26
+ const inspectBook = (pages, options = {}) => {
27
+ const report = suggestSegmentationOptions(pages, options);
28
+ return {
29
+ assessment: report.assessment,
30
+ breakpointSuggestions: report.breakpointSuggestions,
31
+ lineStarts: report.lineStarts,
32
+ preprocess: report.preprocess,
33
+ repeatingSequences: report.repeatingSequences,
34
+ ruleSuggestions: report.ruleSuggestions
35
+ };
36
+ };
37
+ const suggestBookSegmentation = (pages, options = {}) => suggestSegmentationOptions(pages, options);
38
+ const previewSegmentation = (pages, options, sampleSegments = 10) => {
39
+ return buildPreviewStats(pages, options, segmentPages(pages, options), sampleSegments);
40
+ };
41
+ const validateSegmentationPreview = (pages, options, segments) => validateSegments(pages, options, segments);
42
+ const scoreSegmentationCandidates = (pages, candidates, sampleSegments = 5) => {
43
+ const results = candidates.map((options, index) => {
44
+ try {
45
+ const preview = previewSegmentation(pages, options, sampleSegments);
46
+ return {
47
+ averageSegmentLength: preview.averageSegmentLength,
48
+ index,
49
+ maxSegmentLength: preview.maxSegmentLength,
50
+ multiPageSegments: preview.multiPageSegments,
51
+ options,
52
+ score: computeCandidateScore(preview),
53
+ segmentCount: preview.segmentCount,
54
+ validation: preview.validation
55
+ };
56
+ } catch (error) {
57
+ return {
58
+ error: error instanceof Error ? error.message : String(error),
59
+ index,
60
+ options,
61
+ score: Number.NEGATIVE_INFINITY
62
+ };
63
+ }
64
+ });
65
+ return {
66
+ bestIndex: results.reduce((currentBest, result) => result.score > currentBest.score ? result : currentBest, results[0] ?? {
67
+ index: -1,
68
+ options: {},
69
+ score: Number.NEGATIVE_INFINITY
70
+ }).index,
71
+ results
72
+ };
73
+ };
74
+ //#endregion
75
+ //#region src/mcp/server.ts
76
+ const pageSchema = z.object({
77
+ content: z.string(),
78
+ id: z.number()
79
+ });
80
+ const segmentSchema = z.object({
81
+ content: z.string(),
82
+ from: z.number(),
83
+ meta: z.record(z.string(), z.unknown()).optional(),
84
+ to: z.number().optional()
85
+ });
86
+ const looseObjectSchema = z.object({}).catchall(z.unknown());
87
+ const pagesSchema = z.array(pageSchema);
88
+ const optionsSchema = looseObjectSchema;
89
+ const candidatesSchema = z.array(looseObjectSchema);
90
+ const outputSchema = looseObjectSchema;
91
+ const jsonResult = (payload) => ({
92
+ content: [{
93
+ text: JSON.stringify(payload, null, 2),
94
+ type: "text"
95
+ }],
96
+ structuredContent: payload
97
+ });
98
+ const server = new McpServer({
99
+ name: "flappa-doormal-mcp",
100
+ version: "2.20.0"
101
+ });
102
+ server.registerTool("inspect_book", {
103
+ description: "Inspect a book of Arabic pages and return analysis hints: preprocess detections, line-start patterns, repeating sequences, and draft rule suggestions.",
104
+ inputSchema: z.object({
105
+ advisorOptions: looseObjectSchema.optional(),
106
+ pages: pagesSchema
107
+ }),
108
+ outputSchema
109
+ }, async ({ advisorOptions, pages }) => jsonResult({ report: inspectBook(pages, advisorOptions) }));
110
+ server.registerTool("suggest_segmentation_options", {
111
+ description: "Generate a draft segmentation report and recommended SegmentationOptions for a book of Arabic pages.",
112
+ inputSchema: z.object({
113
+ advisorOptions: looseObjectSchema.optional(),
114
+ pages: pagesSchema
115
+ }),
116
+ outputSchema
117
+ }, async ({ advisorOptions, pages }) => jsonResult({ report: suggestBookSegmentation(pages, advisorOptions) }));
118
+ server.registerTool("preview_segmentation", {
119
+ description: "Run segmentPages on a book with caller-supplied SegmentationOptions and return segments, samples, and validation.",
120
+ inputSchema: z.object({
121
+ options: optionsSchema,
122
+ pages: pagesSchema,
123
+ sampleSegments: z.number().int().min(1).max(100).optional()
124
+ }),
125
+ outputSchema
126
+ }, async ({ options, pages, sampleSegments }) => jsonResult({ preview: previewSegmentation(pages, options, sampleSegments) }));
127
+ server.registerTool("validate_segmentation", {
128
+ description: "Validate a caller-provided segmentation result against source pages and the SegmentationOptions used to produce it.",
129
+ inputSchema: z.object({
130
+ options: optionsSchema,
131
+ pages: pagesSchema,
132
+ segments: z.array(segmentSchema)
133
+ }),
134
+ outputSchema
135
+ }, async ({ options, pages, segments }) => jsonResult({ validation: validateSegmentationPreview(pages, options, segments) }));
136
+ server.registerTool("score_candidate_options", {
137
+ description: "Evaluate multiple SegmentationOptions candidates against the same book and rank them using validation and segment-shape heuristics.",
138
+ inputSchema: z.object({
139
+ candidates: candidatesSchema,
140
+ pages: pagesSchema,
141
+ sampleSegments: z.number().int().min(1).max(100).optional()
142
+ }),
143
+ outputSchema
144
+ }, async ({ candidates, pages, sampleSegments }) => jsonResult({ ranking: scoreSegmentationCandidates(pages, candidates, sampleSegments) }));
145
+ const main = async () => {
146
+ const transport = new StdioServerTransport();
147
+ await server.connect(transport);
148
+ };
149
+ main().catch((error) => {
150
+ console.error(error instanceof Error ? error.stack ?? error.message : String(error));
151
+ process.exit(1);
152
+ });
153
+ //#endregion
154
+ export {};
155
+
156
+ //# sourceMappingURL=server.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.mjs","names":[],"sources":["../../src/mcp/tools.ts","../../src/mcp/server.ts"],"sourcesContent":["import { type SegmentationAdvisorOptions, suggestSegmentationOptions } from '@/analysis/segmentation-advisor.js';\nimport { segmentPages } from '@/segmentation/segmenter.js';\nimport type { Page, Segment } from '@/types/index.js';\nimport type { SegmentationOptions } from '@/types/options.js';\nimport type { SegmentValidationReport } from '@/types/validation.js';\nimport { validateSegments } from '@/validation/validate-segments.js';\n\nexport type SegmentationPreview = {\n averageSegmentLength: number;\n maxSegmentLength: number;\n multiPageSegments: number;\n segmentCount: number;\n segmentSamples: Segment[];\n segments: Segment[];\n validation: SegmentValidationReport;\n};\n\nexport type CandidateScore = {\n averageSegmentLength?: number;\n error?: string;\n index: number;\n maxSegmentLength?: number;\n multiPageSegments?: number;\n options: SegmentationOptions;\n score: number;\n segmentCount?: number;\n validation?: SegmentValidationReport;\n};\n\nconst buildPreviewStats = (\n pages: Page[],\n options: SegmentationOptions,\n segments: Segment[],\n sampleSegments: number,\n): SegmentationPreview => {\n const validation = validateSegments(pages, options, segments);\n const totalLength = segments.reduce((sum, segment) => sum + segment.content.length, 0);\n const multiPageSegments = segments.filter(\n (segment) => segment.to !== undefined && segment.to !== segment.from,\n ).length;\n\n return {\n averageSegmentLength: segments.length === 0 ? 0 : totalLength / segments.length,\n maxSegmentLength: Math.max(0, ...segments.map((segment) => segment.content.length)),\n multiPageSegments,\n segmentCount: segments.length,\n segmentSamples: segments.slice(0, sampleSegments),\n segments,\n validation,\n };\n};\n\nconst computeCandidateScore = (preview: SegmentationPreview): number => {\n const issuePenalty = preview.validation.summary.issues * 100;\n const multiPagePenalty = preview.multiPageSegments * 5;\n const oversizePenalty = Math.floor(preview.maxSegmentLength / 500);\n const segmentReward = Math.min(preview.segmentCount, 200);\n\n return segmentReward - issuePenalty - multiPagePenalty - oversizePenalty;\n};\n\nexport const inspectBook = (pages: Page[], options: SegmentationAdvisorOptions = {}) => {\n const report = suggestSegmentationOptions(pages, options);\n return {\n assessment: report.assessment,\n breakpointSuggestions: report.breakpointSuggestions,\n lineStarts: report.lineStarts,\n preprocess: report.preprocess,\n repeatingSequences: report.repeatingSequences,\n ruleSuggestions: report.ruleSuggestions,\n };\n};\n\nexport const suggestBookSegmentation = (pages: Page[], options: SegmentationAdvisorOptions = {}) =>\n suggestSegmentationOptions(pages, options);\n\nexport const previewSegmentation = (\n pages: Page[],\n options: SegmentationOptions,\n sampleSegments = 10,\n): SegmentationPreview => {\n const segments = segmentPages(pages, options);\n return buildPreviewStats(pages, options, segments, sampleSegments);\n};\n\nexport const validateSegmentationPreview = (\n pages: Page[],\n options: SegmentationOptions,\n segments: Segment[],\n): SegmentValidationReport => validateSegments(pages, options, segments);\n\nexport const scoreSegmentationCandidates = (\n pages: Page[],\n candidates: SegmentationOptions[],\n sampleSegments = 5,\n): {\n bestIndex: number;\n results: CandidateScore[];\n} => {\n const results = candidates.map<CandidateScore>((options, index) => {\n try {\n const preview = previewSegmentation(pages, options, sampleSegments);\n return {\n averageSegmentLength: preview.averageSegmentLength,\n index,\n maxSegmentLength: preview.maxSegmentLength,\n multiPageSegments: preview.multiPageSegments,\n options,\n score: computeCandidateScore(preview),\n segmentCount: preview.segmentCount,\n validation: preview.validation,\n };\n } catch (error) {\n return {\n error: error instanceof Error ? error.message : String(error),\n index,\n options,\n score: Number.NEGATIVE_INFINITY,\n };\n }\n });\n\n const best = results.reduce(\n (currentBest, result) => (result.score > currentBest.score ? result : currentBest),\n results[0] ?? { index: -1, options: {}, score: Number.NEGATIVE_INFINITY },\n );\n\n return {\n bestIndex: best.index,\n results,\n };\n};\n","#!/usr/bin/env node\n\nimport { McpServer, StdioServerTransport } from '@modelcontextprotocol/server';\nimport { z } from 'zod';\nimport {\n inspectBook,\n previewSegmentation,\n scoreSegmentationCandidates,\n suggestBookSegmentation,\n validateSegmentationPreview,\n} from './tools.js';\n\nconst pageSchema = z.object({\n content: z.string(),\n id: z.number(),\n});\n\nconst segmentSchema = z.object({\n content: z.string(),\n from: z.number(),\n meta: z.record(z.string(), z.unknown()).optional(),\n to: z.number().optional(),\n});\n\nconst looseObjectSchema = z.object({}).catchall(z.unknown());\nconst pagesSchema = z.array(pageSchema);\nconst optionsSchema = looseObjectSchema;\nconst candidatesSchema = z.array(looseObjectSchema);\nconst outputSchema = looseObjectSchema;\n\nconst jsonResult = (payload: Record<string, unknown>) => ({\n content: [{ text: JSON.stringify(payload, null, 2), type: 'text' as const }],\n structuredContent: payload,\n});\n\nconst server = new McpServer({\n name: 'flappa-doormal-mcp',\n version: '2.20.0',\n});\n\nserver.registerTool(\n 'inspect_book',\n {\n description:\n 'Inspect a book of Arabic pages and return analysis hints: preprocess detections, line-start patterns, repeating sequences, and draft rule suggestions.',\n inputSchema: z.object({\n advisorOptions: looseObjectSchema.optional(),\n pages: pagesSchema,\n }),\n outputSchema,\n },\n async ({ advisorOptions, pages }) =>\n jsonResult({\n report: inspectBook(pages, advisorOptions),\n }),\n);\n\nserver.registerTool(\n 'suggest_segmentation_options',\n {\n description:\n 'Generate a draft segmentation report and recommended SegmentationOptions for a book of Arabic pages.',\n inputSchema: z.object({\n advisorOptions: looseObjectSchema.optional(),\n pages: pagesSchema,\n }),\n outputSchema,\n },\n async ({ advisorOptions, pages }) =>\n jsonResult({\n report: suggestBookSegmentation(pages, advisorOptions),\n }),\n);\n\nserver.registerTool(\n 'preview_segmentation',\n {\n description:\n 'Run segmentPages on a book with caller-supplied SegmentationOptions and return segments, samples, and validation.',\n inputSchema: z.object({\n options: optionsSchema,\n pages: pagesSchema,\n sampleSegments: z.number().int().min(1).max(100).optional(),\n }),\n outputSchema,\n },\n async ({ options, pages, sampleSegments }) =>\n jsonResult({\n preview: previewSegmentation(pages, options, sampleSegments),\n }),\n);\n\nserver.registerTool(\n 'validate_segmentation',\n {\n description:\n 'Validate a caller-provided segmentation result against source pages and the SegmentationOptions used to produce it.',\n inputSchema: z.object({\n options: optionsSchema,\n pages: pagesSchema,\n segments: z.array(segmentSchema),\n }),\n outputSchema,\n },\n async ({ options, pages, segments }) =>\n jsonResult({\n validation: validateSegmentationPreview(pages, options, segments),\n }),\n);\n\nserver.registerTool(\n 'score_candidate_options',\n {\n description:\n 'Evaluate multiple SegmentationOptions candidates against the same book and rank them using validation and segment-shape heuristics.',\n inputSchema: z.object({\n candidates: candidatesSchema,\n pages: pagesSchema,\n sampleSegments: z.number().int().min(1).max(100).optional(),\n }),\n outputSchema,\n },\n async ({ candidates, pages, sampleSegments }) =>\n jsonResult({\n ranking: scoreSegmentationCandidates(pages, candidates, sampleSegments),\n }),\n);\n\nconst main = async () => {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n};\n\nmain().catch((error) => {\n console.error(error instanceof Error ? (error.stack ?? error.message) : String(error));\n process.exit(1);\n});\n"],"mappings":"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"}