@vint.tri/report_gen_mcp 1.5.29 → 1.5.31
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/debug_generator.js +50 -0
- package/dist/charts/bar.d.ts +4 -4
- package/dist/charts/line.d.ts +4 -4
- package/dist/charts/radar.d.ts +4 -4
- package/dist/images/localImages.d.ts +2 -2
- package/dist/images/pollinations.d.ts +4 -4
- package/dist/images/urlImages.d.ts +2 -2
- package/dist/index.js +13 -5
- package/dist/tools/simpleReport.d.ts.map +1 -1
- package/dist/tools/simpleReport.js +13 -4
- package/dist/utils/reportGenerator.d.ts +1 -2
- package/dist/utils/reportGenerator.d.ts.map +1 -1
- package/dist/utils/reportGenerator.js +42 -227
- package/force_rebuild_and_generate.sh +27 -0
- package/package.json +1 -1
- package/test_fixed_report.js +92 -52
- package/dist/tools/reportWizard.d.ts +0 -17
- package/dist/tools/reportWizard.d.ts.map +0 -1
- package/dist/tools/reportWizard.js +0 -69
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { generateReport } from './dist/utils/reportGenerator.js';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
|
|
4
|
+
async function runTest() {
|
|
5
|
+
console.log("Starting isolated test of generateReport function...");
|
|
6
|
+
|
|
7
|
+
// The exact problematic content from the input file.
|
|
8
|
+
const badHtmlContent = `
|
|
9
|
+
<!DOCTYPE html>
|
|
10
|
+
<html lang="ru">
|
|
11
|
+
<head>
|
|
12
|
+
<meta charset="UTF-8">
|
|
13
|
+
<title>Отчет</title>
|
|
14
|
+
</head>
|
|
15
|
+
<body>
|
|
16
|
+
<div class="container">
|
|
17
|
+
<h1>Тестовый отчет</h1>
|
|
18
|
+
<p><canvas data-chart="{"type": "pie", "data": {"labels": ["A", "B"], "datasets": [{"data": [5, 11], "label": "Тест"] "></canvas></p>
|
|
19
|
+
<p><canvas data-chart="{"type": "bar", "data": {"labels": ["C", "D"], "datasets": [{"label": "Еще один тест", "data": [2, 7]] "></canvas></p>
|
|
20
|
+
</div>
|
|
21
|
+
</body>
|
|
22
|
+
</html>
|
|
23
|
+
`;
|
|
24
|
+
|
|
25
|
+
const outputFile = 'debug_report_output.html';
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
await generateReport(badHtmlContent, outputFile);
|
|
29
|
+
console.log(`Test finished. Checking content of ${outputFile}...`);
|
|
30
|
+
|
|
31
|
+
const generatedContent = await fs.readFile(outputFile, 'utf8');
|
|
32
|
+
|
|
33
|
+
if (generatedContent.includes('<div class="chart-container"><canvas data-chart=\'{"type":"pie"')) {
|
|
34
|
+
console.log("SUCCESS: Pie chart was correctly transformed.");
|
|
35
|
+
} else {
|
|
36
|
+
console.error("FAILURE: Pie chart was not transformed.");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (generatedContent.includes('<div class="chart-container"><canvas data-chart=\'{"type":"bar"')) {
|
|
40
|
+
console.log("SUCCESS: Bar chart was correctly transformed.");
|
|
41
|
+
} else {
|
|
42
|
+
console.error("FAILURE: Bar chart was not transformed.");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
} catch (error) {
|
|
46
|
+
console.error("An error occurred during the test:", error);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
runTest();
|
package/dist/charts/bar.d.ts
CHANGED
|
@@ -7,13 +7,13 @@ export declare const barSchema: z.ZodObject<{
|
|
|
7
7
|
backgroundColor: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
|
|
8
8
|
borderColor: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
|
|
9
9
|
}, "strip", z.ZodTypeAny, {
|
|
10
|
-
label: string;
|
|
11
10
|
data: number[];
|
|
11
|
+
label: string;
|
|
12
12
|
backgroundColor?: string | string[] | undefined;
|
|
13
13
|
borderColor?: string | string[] | undefined;
|
|
14
14
|
}, {
|
|
15
|
-
label: string;
|
|
16
15
|
data: number[];
|
|
16
|
+
label: string;
|
|
17
17
|
backgroundColor?: string | string[] | undefined;
|
|
18
18
|
borderColor?: string | string[] | undefined;
|
|
19
19
|
}>, "many">;
|
|
@@ -27,8 +27,8 @@ export declare const barSchema: z.ZodObject<{
|
|
|
27
27
|
}, "strip", z.ZodTypeAny, {
|
|
28
28
|
labels: string[];
|
|
29
29
|
datasets: {
|
|
30
|
-
label: string;
|
|
31
30
|
data: number[];
|
|
31
|
+
label: string;
|
|
32
32
|
backgroundColor?: string | string[] | undefined;
|
|
33
33
|
borderColor?: string | string[] | undefined;
|
|
34
34
|
}[];
|
|
@@ -38,8 +38,8 @@ export declare const barSchema: z.ZodObject<{
|
|
|
38
38
|
}, {
|
|
39
39
|
labels: string[];
|
|
40
40
|
datasets: {
|
|
41
|
-
label: string;
|
|
42
41
|
data: number[];
|
|
42
|
+
label: string;
|
|
43
43
|
backgroundColor?: string | string[] | undefined;
|
|
44
44
|
borderColor?: string | string[] | undefined;
|
|
45
45
|
}[];
|
package/dist/charts/line.d.ts
CHANGED
|
@@ -7,13 +7,13 @@ export declare const lineSchema: z.ZodObject<{
|
|
|
7
7
|
borderColor: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
|
|
8
8
|
fill: z.ZodOptional<z.ZodBoolean>;
|
|
9
9
|
}, "strip", z.ZodTypeAny, {
|
|
10
|
-
label: string;
|
|
11
10
|
data: number[];
|
|
11
|
+
label: string;
|
|
12
12
|
fill?: boolean | undefined;
|
|
13
13
|
borderColor?: string | string[] | undefined;
|
|
14
14
|
}, {
|
|
15
|
-
label: string;
|
|
16
15
|
data: number[];
|
|
16
|
+
label: string;
|
|
17
17
|
fill?: boolean | undefined;
|
|
18
18
|
borderColor?: string | string[] | undefined;
|
|
19
19
|
}>, "many">;
|
|
@@ -27,8 +27,8 @@ export declare const lineSchema: z.ZodObject<{
|
|
|
27
27
|
}, "strip", z.ZodTypeAny, {
|
|
28
28
|
labels: string[];
|
|
29
29
|
datasets: {
|
|
30
|
-
label: string;
|
|
31
30
|
data: number[];
|
|
31
|
+
label: string;
|
|
32
32
|
fill?: boolean | undefined;
|
|
33
33
|
borderColor?: string | string[] | undefined;
|
|
34
34
|
}[];
|
|
@@ -38,8 +38,8 @@ export declare const lineSchema: z.ZodObject<{
|
|
|
38
38
|
}, {
|
|
39
39
|
labels: string[];
|
|
40
40
|
datasets: {
|
|
41
|
-
label: string;
|
|
42
41
|
data: number[];
|
|
42
|
+
label: string;
|
|
43
43
|
fill?: boolean | undefined;
|
|
44
44
|
borderColor?: string | string[] | undefined;
|
|
45
45
|
}[];
|
package/dist/charts/radar.d.ts
CHANGED
|
@@ -7,13 +7,13 @@ export declare const radarSchema: z.ZodObject<{
|
|
|
7
7
|
backgroundColor: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
|
|
8
8
|
borderColor: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
|
|
9
9
|
}, "strip", z.ZodTypeAny, {
|
|
10
|
-
label: string;
|
|
11
10
|
data: number[];
|
|
11
|
+
label: string;
|
|
12
12
|
backgroundColor?: string | string[] | undefined;
|
|
13
13
|
borderColor?: string | string[] | undefined;
|
|
14
14
|
}, {
|
|
15
|
-
label: string;
|
|
16
15
|
data: number[];
|
|
16
|
+
label: string;
|
|
17
17
|
backgroundColor?: string | string[] | undefined;
|
|
18
18
|
borderColor?: string | string[] | undefined;
|
|
19
19
|
}>, "many">;
|
|
@@ -27,8 +27,8 @@ export declare const radarSchema: z.ZodObject<{
|
|
|
27
27
|
}, "strip", z.ZodTypeAny, {
|
|
28
28
|
labels: string[];
|
|
29
29
|
datasets: {
|
|
30
|
-
label: string;
|
|
31
30
|
data: number[];
|
|
31
|
+
label: string;
|
|
32
32
|
backgroundColor?: string | string[] | undefined;
|
|
33
33
|
borderColor?: string | string[] | undefined;
|
|
34
34
|
}[];
|
|
@@ -38,8 +38,8 @@ export declare const radarSchema: z.ZodObject<{
|
|
|
38
38
|
}, {
|
|
39
39
|
labels: string[];
|
|
40
40
|
datasets: {
|
|
41
|
-
label: string;
|
|
42
41
|
data: number[];
|
|
42
|
+
label: string;
|
|
43
43
|
backgroundColor?: string | string[] | undefined;
|
|
44
44
|
borderColor?: string | string[] | undefined;
|
|
45
45
|
}[];
|
|
@@ -6,14 +6,14 @@ export declare const localImageSchema: z.ZodObject<{
|
|
|
6
6
|
height: z.ZodOptional<z.ZodNumber>;
|
|
7
7
|
}, "strip", z.ZodTypeAny, {
|
|
8
8
|
src: string;
|
|
9
|
-
alt?: string | undefined;
|
|
10
9
|
width?: number | undefined;
|
|
11
10
|
height?: number | undefined;
|
|
11
|
+
alt?: string | undefined;
|
|
12
12
|
}, {
|
|
13
13
|
src: string;
|
|
14
|
-
alt?: string | undefined;
|
|
15
14
|
width?: number | undefined;
|
|
16
15
|
height?: number | undefined;
|
|
16
|
+
alt?: string | undefined;
|
|
17
17
|
}>;
|
|
18
18
|
export declare function renderLocalImage(params: z.infer<typeof localImageSchema>): Promise<string>;
|
|
19
19
|
//# sourceMappingURL=localImages.d.ts.map
|
|
@@ -8,18 +8,18 @@ export declare const generatedImageSchema: z.ZodObject<{
|
|
|
8
8
|
nologo: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
9
9
|
enhance: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
10
10
|
}, "strip", z.ZodTypeAny, {
|
|
11
|
+
model: string;
|
|
11
12
|
width: number;
|
|
12
13
|
height: number;
|
|
13
|
-
model: string;
|
|
14
14
|
prompt: string;
|
|
15
15
|
nologo: boolean;
|
|
16
16
|
enhance: boolean;
|
|
17
17
|
seed?: number | undefined;
|
|
18
18
|
}, {
|
|
19
19
|
prompt: string;
|
|
20
|
+
model?: string | undefined;
|
|
20
21
|
width?: number | undefined;
|
|
21
22
|
height?: number | undefined;
|
|
22
|
-
model?: string | undefined;
|
|
23
23
|
seed?: number | undefined;
|
|
24
24
|
nologo?: boolean | undefined;
|
|
25
25
|
enhance?: boolean | undefined;
|
|
@@ -31,14 +31,14 @@ export declare const imageUrlSchema: z.ZodObject<{
|
|
|
31
31
|
height: z.ZodOptional<z.ZodNumber>;
|
|
32
32
|
}, "strip", z.ZodTypeAny, {
|
|
33
33
|
url: string;
|
|
34
|
-
alt?: string | undefined;
|
|
35
34
|
width?: number | undefined;
|
|
36
35
|
height?: number | undefined;
|
|
36
|
+
alt?: string | undefined;
|
|
37
37
|
}, {
|
|
38
38
|
url: string;
|
|
39
|
-
alt?: string | undefined;
|
|
40
39
|
width?: number | undefined;
|
|
41
40
|
height?: number | undefined;
|
|
41
|
+
alt?: string | undefined;
|
|
42
42
|
}>;
|
|
43
43
|
export declare function generateImageUrl(params: z.infer<typeof generatedImageSchema>): string;
|
|
44
44
|
export declare function renderGeneratedImage(params: z.infer<typeof generatedImageSchema>): Promise<string>;
|
|
@@ -9,15 +9,15 @@ export declare const urlImageSchema: z.ZodObject<{
|
|
|
9
9
|
}, "strip", z.ZodTypeAny, {
|
|
10
10
|
url: string;
|
|
11
11
|
embed: boolean;
|
|
12
|
-
alt?: string | undefined;
|
|
13
12
|
width?: number | undefined;
|
|
14
13
|
height?: number | undefined;
|
|
14
|
+
alt?: string | undefined;
|
|
15
15
|
outputPath?: string | undefined;
|
|
16
16
|
}, {
|
|
17
17
|
url: string;
|
|
18
|
-
alt?: string | undefined;
|
|
19
18
|
width?: number | undefined;
|
|
20
19
|
height?: number | undefined;
|
|
20
|
+
alt?: string | undefined;
|
|
21
21
|
embed?: boolean | undefined;
|
|
22
22
|
outputPath?: string | undefined;
|
|
23
23
|
}>;
|
package/dist/index.js
CHANGED
|
@@ -109,7 +109,7 @@ if (process.argv.length === 2) {
|
|
|
109
109
|
// No command specified, run in stdio mode using MCP SDK
|
|
110
110
|
const mcpServer = new McpServer({
|
|
111
111
|
name: "report_gen_mcp",
|
|
112
|
-
version: "1.5.
|
|
112
|
+
version: "1.5.31"
|
|
113
113
|
}, {
|
|
114
114
|
// Disable health check to prevent automatic calls
|
|
115
115
|
capabilities: {
|
|
@@ -121,10 +121,18 @@ if (process.argv.length === 2) {
|
|
|
121
121
|
inputSchema: simpleReportTool.inputSchema,
|
|
122
122
|
}, async (args) => {
|
|
123
123
|
const result = await simpleReportTool.action(args);
|
|
124
|
-
//
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
124
|
+
// Find the file path from the results to construct the HTTP URL
|
|
125
|
+
const localPathResource = result.content.find(c => c.resource.uri.endsWith('.html'));
|
|
126
|
+
if (localPathResource) {
|
|
127
|
+
const fileName = path.basename(localPathResource.resource.uri);
|
|
128
|
+
const httpUrl = `http://localhost:${serverPort}/reports/${fileName}`;
|
|
129
|
+
// Find the resource with the file:/// URL and update its text
|
|
130
|
+
const fileUrlResource = result.content.find(c => c.resource.uri.startsWith('file:///'));
|
|
131
|
+
if (fileUrlResource) {
|
|
132
|
+
fileUrlResource.resource.text = `File saved at: ${localPathResource.resource.uri}\nHTTP server available at: ${httpUrl}`;
|
|
133
|
+
// Also update the URI of this resource to be the http URL
|
|
134
|
+
fileUrlResource.resource.uri = httpUrl;
|
|
135
|
+
}
|
|
128
136
|
}
|
|
129
137
|
return result;
|
|
130
138
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"simpleReport.d.ts","sourceRoot":"","sources":["../../src/tools/simpleReport.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,eAAO,MAAM,gBAAgB;;;;;;;mBAON;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE
|
|
1
|
+
{"version":3,"file":"simpleReport.d.ts","sourceRoot":"","sources":["../../src/tools/simpleReport.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,eAAO,MAAM,gBAAgB;;;;;;;mBAON;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE;;;;;;;;;CAmC/D,CAAC"}
|
|
@@ -6,9 +6,9 @@ import path from 'path';
|
|
|
6
6
|
import os from 'os';
|
|
7
7
|
export const simpleReportTool = {
|
|
8
8
|
name: "generate-report",
|
|
9
|
-
description: "Generate an HTML report from a single string of
|
|
9
|
+
description: "Generate an HTML report from a single string of HTML content with embedded image and chart tags.",
|
|
10
10
|
inputSchema: {
|
|
11
|
-
document: z.string().describe("The full content of the report in
|
|
11
|
+
document: z.string().describe("The full content of the report in HTML format, with `<img>` and `<canvas>` tags for images and charts."),
|
|
12
12
|
outputFile: z.string().optional().describe("The name of the output HTML file."),
|
|
13
13
|
},
|
|
14
14
|
action: async (args) => {
|
|
@@ -21,15 +21,24 @@ export const simpleReportTool = {
|
|
|
21
21
|
const result = await generateReport(document, outputPath);
|
|
22
22
|
const fileUrl = pathToFileURL(result.filePath).href;
|
|
23
23
|
const fileContent = await fs.readFile(result.filePath, 'utf8');
|
|
24
|
+
// The http path will be constructed by the caller in index.ts,
|
|
25
|
+
// but we can provide the file and fileURL paths here.
|
|
24
26
|
const response = {
|
|
25
27
|
content: [
|
|
26
28
|
{
|
|
27
29
|
type: 'resource',
|
|
28
30
|
resource: {
|
|
29
|
-
uri: fileUrl,
|
|
30
|
-
text:
|
|
31
|
+
uri: fileUrl, // file:///...
|
|
32
|
+
text: `File saved at: ${result.filePath}\nHTTP server available at (this will be filled in by the MCP server):`,
|
|
31
33
|
},
|
|
32
34
|
},
|
|
35
|
+
{
|
|
36
|
+
type: 'resource',
|
|
37
|
+
resource: {
|
|
38
|
+
uri: result.filePath, // local path
|
|
39
|
+
text: fileContent,
|
|
40
|
+
}
|
|
41
|
+
}
|
|
33
42
|
],
|
|
34
43
|
};
|
|
35
44
|
return response;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
export declare function generateReport(
|
|
2
|
-
outputFile: string): Promise<{
|
|
1
|
+
export declare function generateReport(htmlDocument: string, outputFile: string): Promise<{
|
|
3
2
|
success: boolean;
|
|
4
3
|
filePath: string;
|
|
5
4
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reportGenerator.d.ts","sourceRoot":"","sources":["../../src/utils/reportGenerator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"reportGenerator.d.ts","sourceRoot":"","sources":["../../src/utils/reportGenerator.ts"],"names":[],"mappings":"AAGA,wBAAsB,cAAc,CAClC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM;;;GAsDnB"}
|
|
@@ -1,235 +1,50 @@
|
|
|
1
1
|
import fs from 'fs-extra';
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
//
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
2
|
+
import path from 'path';
|
|
3
|
+
export async function generateReport(htmlDocument, outputFile) {
|
|
4
|
+
console.log("Applying definitive regex-based fix...");
|
|
5
|
+
// This regex is designed to find the specific broken pattern: an HTML-encoded
|
|
6
|
+
// <canvas> tag inside a <p> tag, and it captures the malformed chart data.
|
|
7
|
+
const brokenCanvasRegex = /<p><canvas data-chart="({.+?}) "><\/canvas><\/p>/g;
|
|
8
|
+
let fixedHtml = htmlDocument.replace(brokenCanvasRegex, (match, chartData) => {
|
|
9
|
+
// 1. The captured `chartData` has encoded quotes. Decode them to get a JSON-like string.
|
|
10
|
+
let decodedChartData = chartData.replace(/"/g, '"');
|
|
11
|
+
// 2. The decoded string is still a malformed JSON object. Append the missing closing brackets.
|
|
12
|
+
let fixedJson = decodedChartData + ']}]}}';
|
|
13
|
+
// 3. Return a clean, valid HTML structure for the chart, using single quotes for the attribute
|
|
14
|
+
// to avoid conflicts with the double quotes in the JSON.
|
|
15
|
+
return `<div class="chart-container"><canvas data-chart='${fixedJson}'></canvas></div>`;
|
|
16
|
+
});
|
|
17
|
+
// 4. Inject the client-side chart rendering script right before the closing </body> tag.
|
|
18
|
+
const chartScript = `
|
|
19
|
+
<script>
|
|
20
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
21
|
+
const charts = document.querySelectorAll('canvas[data-chart]');
|
|
22
|
+
charts.forEach(canvas => {
|
|
23
|
+
const chartDataString = canvas.getAttribute('data-chart');
|
|
24
|
+
if (chartDataString) {
|
|
25
|
+
try {
|
|
26
|
+
const chartConfig = JSON.parse(chartDataString);
|
|
27
|
+
new Chart(canvas, chartConfig);
|
|
28
|
+
} catch (e) {
|
|
29
|
+
console.error('Failed to parse chart data:', chartDataString, e);
|
|
30
30
|
}
|
|
31
|
-
|
|
32
|
-
catch (e) {
|
|
33
|
-
console.error(`Error parsing chart config: ${chartConfigJson}`, e);
|
|
34
|
-
// Continue without adding this chart if parsing fails
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
// Regex to find <img src="..." alt="...">
|
|
38
|
-
const imageRegex = /<img\s+src="([^"]*)"(?:\s+alt="([^"]*)")?[^>]*>/g;
|
|
39
|
-
let imageMatch;
|
|
40
|
-
while ((imageMatch = imageRegex.exec(markdown)) !== null) {
|
|
41
|
-
const src = imageMatch[1];
|
|
42
|
-
const alt = imageMatch[2] || '';
|
|
43
|
-
const id = `image-${elementCount++}`;
|
|
44
|
-
// Determine if it's a URL or local image
|
|
45
|
-
const isUrl = src.startsWith('http://') || src.startsWith('https://');
|
|
46
|
-
const imageType = isUrl ? 'url' : 'local';
|
|
47
|
-
if (isUrl) {
|
|
48
|
-
elements[id] = { type: imageType, config: { url: src, alt: alt } };
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
elements[id] = { type: imageType, config: { src: src, alt: alt } };
|
|
52
|
-
}
|
|
53
|
-
console.log(`Extracted image: ${id}, type: ${imageType}, src: ${src}`);
|
|
54
|
-
// Replace the original img tag with a placeholder
|
|
55
|
-
markdown = markdown.replace(imageMatch[0], `[[image:${id}]]`);
|
|
56
|
-
}
|
|
57
|
-
console.log("Finished extractElementsFromMarkdown. Extracted elements:", Object.keys(elements));
|
|
58
|
-
return { updatedMarkdown: markdown, elements: elements };
|
|
59
|
-
}
|
|
60
|
-
const chartRenderers = {
|
|
61
|
-
bar: { schema: barSchema, renderer: renderBarChart },
|
|
62
|
-
line: { schema: lineSchema, renderer: renderLineChart },
|
|
63
|
-
pie: { schema: pieSchema, renderer: renderPieChart },
|
|
64
|
-
doughnut: { schema: doughnutSchema, renderer: renderDoughnutChart },
|
|
65
|
-
radar: { schema: radarSchema, renderer: renderRadarChart },
|
|
66
|
-
polarArea: { schema: polarAreaSchema, renderer: renderPolarAreaChart },
|
|
67
|
-
};
|
|
68
|
-
const imageRenderers = {
|
|
69
|
-
url: { schema: urlImageSchema, renderer: renderUrlImage },
|
|
70
|
-
local: { schema: localImageSchema, renderer: renderLocalImage }, // Added this line
|
|
71
|
-
};
|
|
72
|
-
// Utility function to normalize chart configuration data
|
|
73
|
-
// Converts string values to arrays where the schema expects arrays
|
|
74
|
-
function normalizeChartConfig(config) {
|
|
75
|
-
if (!config || typeof config !== 'object') {
|
|
76
|
-
return config;
|
|
77
|
-
}
|
|
78
|
-
const normalizedConfig = { ...config };
|
|
79
|
-
// Normalize datasets
|
|
80
|
-
if (normalizedConfig.datasets && Array.isArray(normalizedConfig.datasets)) {
|
|
81
|
-
normalizedConfig.datasets = normalizedConfig.datasets.map((dataset) => {
|
|
82
|
-
if (!dataset || typeof dataset !== 'object') {
|
|
83
|
-
return dataset;
|
|
84
|
-
}
|
|
85
|
-
const normalizedDataset = { ...dataset };
|
|
86
|
-
// Convert string values to arrays for color properties
|
|
87
|
-
const colorProperties = ['backgroundColor', 'borderColor'];
|
|
88
|
-
for (const prop of colorProperties) {
|
|
89
|
-
if (normalizedDataset[prop] && typeof normalizedDataset[prop] === 'string') {
|
|
90
|
-
normalizedDataset[prop] = [normalizedDataset[prop]];
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return normalizedDataset;
|
|
31
|
+
}
|
|
94
32
|
});
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
export async function generateReport(markdownDocument, // Renamed 'document' to 'markdownDocument' for clarity
|
|
99
|
-
outputFile) {
|
|
100
|
-
console.log("Starting generateReport...");
|
|
101
|
-
// Extract elements and get the updated markdown
|
|
102
|
-
const { updatedMarkdown, elements } = await extractElementsFromMarkdown(markdownDocument); // Modified this line
|
|
103
|
-
console.log("Elements after extraction:", Object.keys(elements));
|
|
104
|
-
// Validate elements
|
|
105
|
-
for (const [id, element] of Object.entries(elements)) {
|
|
106
|
-
console.log(`Validating element: ${id}, type: ${element.type}`);
|
|
107
|
-
if (element.type in chartRenderers) {
|
|
108
|
-
// Это диаграмма
|
|
109
|
-
const chartElement = element;
|
|
110
|
-
const { schema } = chartRenderers[chartElement.type];
|
|
111
|
-
if (!schema)
|
|
112
|
-
throw new Error(`Unsupported chart type: ${chartElement.type}`);
|
|
113
|
-
// Normalize the chart configuration before validation
|
|
114
|
-
const normalizedConfig = normalizeChartConfig(chartElement.config);
|
|
115
|
-
schema.parse(normalizedConfig);
|
|
116
|
-
// Update the element with normalized config for rendering
|
|
117
|
-
element.config = normalizedConfig;
|
|
118
|
-
console.log(`Validated chart: ${id}`);
|
|
119
|
-
}
|
|
120
|
-
else if (element.type in imageRenderers) {
|
|
121
|
-
// Это изображение
|
|
122
|
-
const imageElement = element;
|
|
123
|
-
const { schema } = imageRenderers[imageElement.type];
|
|
124
|
-
if (!schema)
|
|
125
|
-
throw new Error(`Unsupported image type: ${imageElement.type}`);
|
|
126
|
-
schema.parse(imageElement.config);
|
|
127
|
-
console.log(`Validated image: ${id}`);
|
|
128
|
-
}
|
|
129
|
-
else {
|
|
130
|
-
throw new Error(`Unsupported element type: ${element.type}`);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
// Render elements to interactive HTML
|
|
134
|
-
const renderedElements = {};
|
|
135
|
-
for (const [id, element] of Object.entries(elements)) {
|
|
136
|
-
console.log(`Rendering element: ${id}, type: ${element.type}`);
|
|
137
|
-
if (element.type in chartRenderers) {
|
|
138
|
-
// Это диаграмма
|
|
139
|
-
const chartElement = element;
|
|
140
|
-
const htmlChart = await chartRenderers[chartElement.type].renderer(chartElement.config);
|
|
141
|
-
renderedElements[id] = htmlChart;
|
|
142
|
-
console.log(`Rendered chart: ${id}`);
|
|
143
|
-
}
|
|
144
|
-
else if (element.type in imageRenderers) {
|
|
145
|
-
// Это изображение
|
|
146
|
-
const imageElement = element;
|
|
147
|
-
const htmlImage = await imageRenderers[imageElement.type].renderer(imageElement.config);
|
|
148
|
-
renderedElements[id] = htmlImage;
|
|
149
|
-
console.log(`Rendered image: ${id}`);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
// Replace placeholders in Markdown, e.g., [[chart:id]] or [[image:id]]
|
|
153
|
-
let mdWithElements = updatedMarkdown; // Corrected this line
|
|
154
|
-
for (const [id, htmlElement] of Object.entries(renderedElements)) {
|
|
155
|
-
// Поддерживаем оба формата: [[chart:id]] и [[image:id]] для обратной совместимости
|
|
156
|
-
mdWithElements = mdWithElements.replace(new RegExp(`\\[\\[(chart|image):${id}\\]\\]`, 'g'), htmlElement);
|
|
157
|
-
}
|
|
158
|
-
// Convert Markdown to HTML
|
|
159
|
-
const htmlContent = await marked(mdWithElements); // Modified this line to use mdWithElements
|
|
160
|
-
// Wrap in full HTML template with Chart.js library
|
|
161
|
-
const template = `
|
|
162
|
-
<!DOCTYPE html>
|
|
163
|
-
<html lang="ru">
|
|
164
|
-
<head>
|
|
165
|
-
<meta charset="UTF-8">
|
|
166
|
-
<title>Отчет</title>
|
|
167
|
-
<style>
|
|
168
|
-
body {
|
|
169
|
-
font-family: Arial, sans-serif;
|
|
170
|
-
margin: 40px;
|
|
171
|
-
background-color: #f5f5f5;
|
|
172
|
-
}
|
|
173
|
-
.container {
|
|
174
|
-
max-width: 1200px;
|
|
175
|
-
margin: 0 auto;
|
|
176
|
-
background-color: white;
|
|
177
|
-
padding: 30px;
|
|
178
|
-
border-radius: 10px;
|
|
179
|
-
box-shadow: 0 0 10px rgba(0,0,0,0.1);
|
|
180
|
-
}
|
|
181
|
-
h1, h2, h3 {
|
|
182
|
-
color: #333;
|
|
183
|
-
}
|
|
184
|
-
h1 {
|
|
185
|
-
border-bottom: 2px solid #3498db;
|
|
186
|
-
padding-bottom: 10px;
|
|
187
|
-
}
|
|
188
|
-
h2 {
|
|
189
|
-
border-left: 4px solid #3498db;
|
|
190
|
-
padding-left: 15px;
|
|
191
|
-
}
|
|
192
|
-
.chart-container, .image-container {
|
|
193
|
-
margin: 30px 0;
|
|
194
|
-
text-align: center;
|
|
195
|
-
}
|
|
196
|
-
.chart-container canvas, .image-container img {
|
|
197
|
-
max-width: 100%;
|
|
198
|
-
height: auto;
|
|
199
|
-
border: 1px solid #ddd;
|
|
200
|
-
border-radius: 5px;
|
|
201
|
-
}
|
|
202
|
-
p {
|
|
203
|
-
line-height: 1.6;
|
|
204
|
-
text-align: justify;
|
|
205
|
-
}
|
|
206
|
-
ul, ol {
|
|
207
|
-
margin: 20px 0;
|
|
208
|
-
padding-left: 30px;
|
|
209
|
-
}
|
|
210
|
-
li {
|
|
211
|
-
margin: 10px 0;
|
|
212
|
-
}
|
|
213
|
-
strong {
|
|
214
|
-
color: #e74c3c;
|
|
215
|
-
}
|
|
216
|
-
em {
|
|
217
|
-
color: #2ecc71;
|
|
218
|
-
}
|
|
219
|
-
</style>
|
|
220
|
-
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
221
|
-
</head>
|
|
222
|
-
<body>
|
|
223
|
-
<div class="container">
|
|
224
|
-
<%- htmlContent %>
|
|
225
|
-
</div>
|
|
33
|
+
});
|
|
34
|
+
</script>
|
|
226
35
|
</body>
|
|
227
|
-
</html>
|
|
228
36
|
`;
|
|
229
|
-
|
|
230
|
-
|
|
37
|
+
if (fixedHtml.includes('</body>')) {
|
|
38
|
+
fixedHtml = fixedHtml.replace('</body>', chartScript);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
// As a fallback, if no </body> tag is found, append it to the end of the file.
|
|
42
|
+
fixedHtml += chartScript.replace('</body>', '</html>');
|
|
43
|
+
}
|
|
44
|
+
// 5. Save the fully corrected and valid HTML to the specified output file.
|
|
231
45
|
const outputDirPath = path.dirname(outputFile);
|
|
232
|
-
await fs.ensureDir(outputDirPath);
|
|
233
|
-
await fs.writeFile(outputFile,
|
|
46
|
+
await fs.ensureDir(outputDirPath);
|
|
47
|
+
await fs.writeFile(outputFile, fixedHtml);
|
|
48
|
+
console.log(`Report successfully generated at: ${outputFile}`);
|
|
234
49
|
return { success: true, filePath: outputFile };
|
|
235
50
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# This script ensures a clean build and generation process.
|
|
4
|
+
|
|
5
|
+
echo "--- Step 1: Forcibly removing old 'dist' directory ---"
|
|
6
|
+
rm -rf dist
|
|
7
|
+
if [ -d "dist" ]; then
|
|
8
|
+
echo "Error: Failed to remove 'dist' directory."
|
|
9
|
+
exit 1
|
|
10
|
+
fi
|
|
11
|
+
echo "Old 'dist' directory removed successfully."
|
|
12
|
+
|
|
13
|
+
echo "--- Step 2: Recompiling TypeScript source code ---"
|
|
14
|
+
npx tsc
|
|
15
|
+
if [ ! -d "dist" ]; then
|
|
16
|
+
echo "Error: TypeScript compilation failed. 'dist' directory not created."
|
|
17
|
+
exit 1
|
|
18
|
+
fi
|
|
19
|
+
echo "TypeScript compiled successfully."
|
|
20
|
+
|
|
21
|
+
echo "--- Step 3: Generating the report with the new build ---"
|
|
22
|
+
REPORTS_DIR=. node dist/index.js generate --document apple_financial_report_2024.html --output apple_financial_report_2024_fixed.html
|
|
23
|
+
if [ $? -ne 0 ]; then
|
|
24
|
+
echo "Error: Report generation command failed."
|
|
25
|
+
exit 1
|
|
26
|
+
fi
|
|
27
|
+
echo "--- Process completed successfully! ---"
|
package/package.json
CHANGED
package/test_fixed_report.js
CHANGED
|
@@ -1,56 +1,96 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Mcp } from '@modelcontextprotocol/sdk';
|
|
2
2
|
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
5
|
+
async function testGenerateReport() {
|
|
6
|
+
const mcp = new Mcp();
|
|
7
|
+
const reportContent = `
|
|
8
|
+
# Отчёт о прибылях Apple за 2024 год
|
|
9
|
+
|
|
10
|
+
<img src="https://www.apple.com/ac/structured-data/images/knowledge_graph_logo.png?202306160250" alt="Логотип Apple" style="display: block; margin: 0 auto; width: 200px; border-radius: 12px; box-shadow: 0 4px 8px rgba(0,0,0,0.1);" />
|
|
11
|
+
|
|
12
|
+
## Общее описание
|
|
13
|
+
|
|
14
|
+
В данном отчёте представлены ключевые финансовые показатели компании Apple за 2024 год. Данные включают выручку, чистую прибыль, распределение доходов по регионам и основным продуктам. Отчёт содержит интерактивные графики для наглядного анализа динамики показателей.
|
|
15
|
+
|
|
16
|
+
## Выручка по кварталам
|
|
17
|
+
|
|
18
|
+
<canvas id="revenueChart" width="400" height="200">Ваш браузер не поддерживает элемент canvas.</canvas>
|
|
19
|
+
|
|
20
|
+
## Чистая прибыль по кварталам
|
|
21
|
+
|
|
22
|
+
<canvas id="profitChart" width="400" height="200">Ваш браузер не поддерживает элемент canvas.</canvas>
|
|
23
|
+
|
|
24
|
+
## Распределение прибыли по регионам
|
|
25
|
+
|
|
26
|
+
<canvas id="regionChart" width="400" height="200">Ваш браузер не поддерживает элемент canvas.</canvas>
|
|
27
|
+
|
|
28
|
+
## Заключение
|
|
29
|
+
|
|
30
|
+
Apple продолжает демонстрировать устойчивый рост в 2024 году, несмотря на глобальную экономическую нестабильность. Наибольший вклад в прибыль внесли рынки США и Китая, а также продукты линейки iPhone и Services. Компания укрепляет позиции в сегменте услуг, где маржа прибыли остаётся одной из самых высоких.
|
|
31
|
+
|
|
32
|
+
<script>
|
|
33
|
+
// График выручки по кварталам
|
|
34
|
+
const revenueCtx = document.getElementById('revenueChart').getContext('2d');
|
|
35
|
+
new Chart(revenueCtx, {
|
|
36
|
+
type: 'bar',
|
|
37
|
+
data: {
|
|
38
|
+
labels: ['Q1', 'Q2', 'Q3', 'Q4'],
|
|
39
|
+
datasets: [{
|
|
40
|
+
label: 'Выручка (млрд $)',
|
|
41
|
+
data: [119.2, 90.8, 81.8, 96.4],
|
|
42
|
+
backgroundColor: 'rgba(0, 122, 255, 0.7)'
|
|
43
|
+
}]
|
|
44
|
+
},
|
|
45
|
+
options: { responsive: true, plugins: { legend: { position: 'top' }
|
|
46
|
+
}});
|
|
47
|
+
|
|
48
|
+
// График чистой прибыли
|
|
49
|
+
const profitCtx = document.getElementById('profitChart').getContext('2d');
|
|
50
|
+
new Chart(profitCtx, {
|
|
51
|
+
type: 'line',
|
|
52
|
+
data: {
|
|
53
|
+
labels: ['Q1', 'Q2', 'Q3', 'Q4'],
|
|
54
|
+
datasets: [{
|
|
55
|
+
label: 'Чистая прибыль (млрд $)',
|
|
56
|
+
data: [28.5, 23.6, 19.8, 25.2],
|
|
57
|
+
borderColor: 'rgba(45, 206, 137, 1)',
|
|
58
|
+
fill: false
|
|
59
|
+
}]
|
|
60
|
+
},
|
|
61
|
+
options: { responsive: true, plugins: { legend: { position: 'top' }
|
|
62
|
+
}});
|
|
63
|
+
|
|
64
|
+
// Круговая диаграмма по регионам
|
|
65
|
+
const regionCtx = document.getElementById('regionChart').getContext('2d');
|
|
66
|
+
new Chart(regionCtx, {
|
|
67
|
+
type: 'pie',
|
|
68
|
+
data: {
|
|
69
|
+
labels: ['США', 'Китай', 'Европа', 'Остальной мир'],
|
|
70
|
+
datasets: [{
|
|
71
|
+
data: [42, 28, 18, 12],
|
|
72
|
+
backgroundColor: [
|
|
73
|
+
'rgba(0, 122, 255, 0.8)',
|
|
74
|
+
'rgba(255, 149, 0, 0.8)',
|
|
75
|
+
'rgba(52, 199, 89, 0.8)',
|
|
76
|
+
'rgba(255, 59, 48, 0.8)'
|
|
77
|
+
]
|
|
78
|
+
}]
|
|
79
|
+
},
|
|
80
|
+
options: { responsive: true, plugins: { legend: { position: 'right' }
|
|
81
|
+
}});
|
|
82
|
+
</script>
|
|
83
|
+
`;
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
const result = await mcp.tool.report_gen_mcp['generate-report']({
|
|
87
|
+
document: reportContent,
|
|
88
|
+
outputFile: 'test_report_fixed.html'
|
|
89
|
+
});
|
|
90
|
+
console.log(JSON.stringify(result, null, 2));
|
|
91
|
+
} catch (error) {
|
|
92
|
+
console.error('Error calling generate-report tool:', error);
|
|
51
93
|
}
|
|
52
|
-
}
|
|
94
|
+
}
|
|
53
95
|
|
|
54
|
-
|
|
55
|
-
child.stdin.write(JSON.stringify(toolCallMessage) + '\n');
|
|
56
|
-
}, 1000);
|
|
96
|
+
testGenerateReport();
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
export declare const reportWizardTool: {
|
|
3
|
-
name: string;
|
|
4
|
-
description: string;
|
|
5
|
-
inputSchema: {
|
|
6
|
-
report_description: z.ZodString;
|
|
7
|
-
outputFile: z.ZodString;
|
|
8
|
-
};
|
|
9
|
-
execute: ({ report_description, outputFile }: {
|
|
10
|
-
report_description: string;
|
|
11
|
-
outputFile: string;
|
|
12
|
-
}) => Promise<{
|
|
13
|
-
success: boolean;
|
|
14
|
-
filePath: string;
|
|
15
|
-
}>;
|
|
16
|
-
};
|
|
17
|
-
//# sourceMappingURL=reportWizard.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"reportWizard.d.ts","sourceRoot":"","sources":["../../src/tools/reportWizard.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA8DxB,eAAO,MAAM,gBAAgB;;;;;;;kDAOyB;QAAE,kBAAkB,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE;;;;CAIvG,CAAC"}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { generateReport } from '../utils/reportGenerator.js';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
// Эта функция будет извлекать данные из текста и генерировать элементы
|
|
4
|
-
async function designReportFromDescription(description) {
|
|
5
|
-
const elements = {};
|
|
6
|
-
let newDocument = description;
|
|
7
|
-
// Извлечение данных по продуктам
|
|
8
|
-
const productMatches = [...description.matchAll(/-\s*\*\*(.*?)\*\*: \$([\d,.]+) (млрд|миллиарда)/gi)];
|
|
9
|
-
if (productMatches.length > 0) {
|
|
10
|
-
const labels = productMatches.map(match => match[1]);
|
|
11
|
-
const data = productMatches.map(match => parseFloat(match[2].replace(/,/g, '')));
|
|
12
|
-
elements['product_sales_chart'] = {
|
|
13
|
-
type: 'doughnut',
|
|
14
|
-
config: {
|
|
15
|
-
labels,
|
|
16
|
-
datasets: [{
|
|
17
|
-
label: 'Выручка по продуктам (млрд $)',
|
|
18
|
-
data,
|
|
19
|
-
backgroundColor: ['#5A9E6F', '#E67E22', '#F1C40F', '#3498DB', '#9B59B6']
|
|
20
|
-
}]
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
newDocument += '\n\n## Диаграмма: Продажи по продуктам\n\n[[chart:product_sales_chart]]';
|
|
24
|
-
}
|
|
25
|
-
// Извлечение данных по регионам
|
|
26
|
-
const regionMatches = [...description.matchAll(/Выручка в (.*?)\s*в 2024.*? \$([\d,.]+) (млрд|миллиарда)/gi)];
|
|
27
|
-
if (regionMatches.length > 0) {
|
|
28
|
-
const labels = regionMatches.map(match => match[1]);
|
|
29
|
-
const data = regionMatches.map(match => parseFloat(match[2].replace(/,/g, '')));
|
|
30
|
-
elements['region_sales_chart'] = {
|
|
31
|
-
type: 'bar',
|
|
32
|
-
config: {
|
|
33
|
-
labels,
|
|
34
|
-
datasets: [{
|
|
35
|
-
label: 'Выручка по регионам (млрд $)',
|
|
36
|
-
data,
|
|
37
|
-
backgroundColor: ['#2ECC71', '#3498DB', '#E74C3C', '#F1C40F', '#9B59B6']
|
|
38
|
-
}]
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
newDocument += '\n\n## Диаграмма: Выручка по регионам\n\n[[chart:region_sales_chart]]';
|
|
42
|
-
}
|
|
43
|
-
// Пример: добавляем изображение на основе контекста
|
|
44
|
-
let imagePrompt = "business report and data analysis";
|
|
45
|
-
if (/apple/i.test(description)) {
|
|
46
|
-
imagePrompt = "futuristic design representing apple inc innovation";
|
|
47
|
-
}
|
|
48
|
-
else if (/tesla/i.test(description)) {
|
|
49
|
-
imagePrompt = "electric cars and modern technology";
|
|
50
|
-
}
|
|
51
|
-
elements['context_image'] = {
|
|
52
|
-
type: 'pollinations',
|
|
53
|
-
config: { prompt: imagePrompt }
|
|
54
|
-
};
|
|
55
|
-
newDocument += '\n\n## Иллюстрация\n\n[[image:context_image]]';
|
|
56
|
-
return { document: newDocument, elements };
|
|
57
|
-
}
|
|
58
|
-
export const reportWizardTool = {
|
|
59
|
-
name: "create_report",
|
|
60
|
-
description: "Designs and generates a complete, visually rich HTML report from a simple text description.",
|
|
61
|
-
inputSchema: {
|
|
62
|
-
report_description: z.string().describe("A text description of the desired report (e.g., 'an apple financial report for 2024')."),
|
|
63
|
-
outputFile: z.string().describe("The desired output HTML file name (e.g., 'report.html').")
|
|
64
|
-
},
|
|
65
|
-
execute: async ({ report_description, outputFile }) => {
|
|
66
|
-
const { document, elements } = await designReportFromDescription(report_description);
|
|
67
|
-
return await generateReport(document, elements, outputFile);
|
|
68
|
-
}
|
|
69
|
-
};
|