@apart-tech/intelligence-core 1.21.0 → 1.21.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.
Files changed (86) hide show
  1. package/dist/db/tenant.d.ts.map +1 -1
  2. package/dist/db/tenant.js +2 -0
  3. package/dist/db/tenant.js.map +1 -1
  4. package/dist/index.d.ts +11 -1
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +5 -0
  7. package/dist/index.js.map +1 -1
  8. package/dist/services/__tests__/node-service.test.js +3 -3
  9. package/dist/services/__tests__/node-service.test.js.map +1 -1
  10. package/dist/services/__tests__/search-service.test.js +3 -0
  11. package/dist/services/__tests__/search-service.test.js.map +1 -1
  12. package/dist/services/agent-cli-reference.d.ts +1 -1
  13. package/dist/services/agent-cli-reference.d.ts.map +1 -1
  14. package/dist/services/agent-cli-reference.js +2 -2
  15. package/dist/services/chat-capture-service.d.ts +6 -2
  16. package/dist/services/chat-capture-service.d.ts.map +1 -1
  17. package/dist/services/chat-capture-service.js +56 -19
  18. package/dist/services/chat-capture-service.js.map +1 -1
  19. package/dist/services/chat-context-service.d.ts.map +1 -1
  20. package/dist/services/chat-context-service.js +5 -0
  21. package/dist/services/chat-context-service.js.map +1 -1
  22. package/dist/services/chat-tool-definitions.d.ts +178 -0
  23. package/dist/services/chat-tool-definitions.d.ts.map +1 -0
  24. package/dist/services/chat-tool-definitions.js +120 -0
  25. package/dist/services/chat-tool-definitions.js.map +1 -0
  26. package/dist/services/chat-tool-definitions.test.d.ts +2 -0
  27. package/dist/services/chat-tool-definitions.test.d.ts.map +1 -0
  28. package/dist/services/chat-tool-definitions.test.js +150 -0
  29. package/dist/services/chat-tool-definitions.test.js.map +1 -0
  30. package/dist/services/dedup-service.d.ts +132 -0
  31. package/dist/services/dedup-service.d.ts.map +1 -0
  32. package/dist/services/dedup-service.js +434 -0
  33. package/dist/services/dedup-service.js.map +1 -0
  34. package/dist/services/dedup-service.test.d.ts +2 -0
  35. package/dist/services/dedup-service.test.d.ts.map +1 -0
  36. package/dist/services/dedup-service.test.js +160 -0
  37. package/dist/services/dedup-service.test.js.map +1 -0
  38. package/dist/services/document-post-check-service.d.ts +47 -0
  39. package/dist/services/document-post-check-service.d.ts.map +1 -0
  40. package/dist/services/document-post-check-service.js +130 -0
  41. package/dist/services/document-post-check-service.js.map +1 -0
  42. package/dist/services/document-post-check-service.test.d.ts +2 -0
  43. package/dist/services/document-post-check-service.test.d.ts.map +1 -0
  44. package/dist/services/document-post-check-service.test.js +150 -0
  45. package/dist/services/document-post-check-service.test.js.map +1 -0
  46. package/dist/services/document-render-service.d.ts +27 -0
  47. package/dist/services/document-render-service.d.ts.map +1 -0
  48. package/dist/services/document-render-service.js +186 -0
  49. package/dist/services/document-render-service.js.map +1 -0
  50. package/dist/services/document-render-service.test.d.ts +2 -0
  51. package/dist/services/document-render-service.test.d.ts.map +1 -0
  52. package/dist/services/document-render-service.test.js +144 -0
  53. package/dist/services/document-render-service.test.js.map +1 -0
  54. package/dist/services/document-service.d.ts +4 -1
  55. package/dist/services/document-service.d.ts.map +1 -1
  56. package/dist/services/document-service.js +24 -1
  57. package/dist/services/document-service.js.map +1 -1
  58. package/dist/services/document-tool-handler.d.ts +44 -0
  59. package/dist/services/document-tool-handler.d.ts.map +1 -0
  60. package/dist/services/document-tool-handler.js +179 -0
  61. package/dist/services/document-tool-handler.js.map +1 -0
  62. package/dist/services/document-tool-handler.test.d.ts +2 -0
  63. package/dist/services/document-tool-handler.test.d.ts.map +1 -0
  64. package/dist/services/document-tool-handler.test.js +149 -0
  65. package/dist/services/document-tool-handler.test.js.map +1 -0
  66. package/dist/services/edge-service.d.ts +1 -0
  67. package/dist/services/edge-service.d.ts.map +1 -1
  68. package/dist/services/edge-service.js +9 -0
  69. package/dist/services/edge-service.js.map +1 -1
  70. package/dist/services/node-service.js +2 -2
  71. package/dist/services/node-service.js.map +1 -1
  72. package/dist/services/quota-service.d.ts +2 -0
  73. package/dist/services/quota-service.d.ts.map +1 -1
  74. package/dist/services/quota-service.js +17 -1
  75. package/dist/services/quota-service.js.map +1 -1
  76. package/dist/services/search-service.d.ts.map +1 -1
  77. package/dist/services/search-service.js +34 -2
  78. package/dist/services/search-service.js.map +1 -1
  79. package/dist/services/usage-service.d.ts +21 -1
  80. package/dist/services/usage-service.d.ts.map +1 -1
  81. package/dist/services/usage-service.js +37 -1
  82. package/dist/services/usage-service.js.map +1 -1
  83. package/dist/types/index.d.ts +5 -0
  84. package/dist/types/index.d.ts.map +1 -1
  85. package/package.json +11 -1
  86. package/prisma/schema.prisma +48 -18
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Post-check service for document editing.
3
+ *
4
+ * Extracts text from rendered document buffers and runs policy/PII checks.
5
+ * Used after sandbox editing completes to verify the output meets org policies.
6
+ */
7
+ import type { ContentPolicyService } from "./content-policy-service.js";
8
+ import type { PiiDetectorService } from "./pii-detector-service.js";
9
+ export interface PostCheckInput {
10
+ buffer: Buffer;
11
+ mimeType: string;
12
+ piiOutputPolicy: "warn" | "block" | "strip";
13
+ contentPolicyService?: ContentPolicyService;
14
+ piiDetector?: PiiDetectorService;
15
+ }
16
+ export interface PostCheckResult {
17
+ allowed: boolean;
18
+ piiDetected: boolean;
19
+ piiWarning: boolean;
20
+ policyViolation?: string;
21
+ extractedTextLength: number;
22
+ }
23
+ export declare class DocumentPostCheckService {
24
+ /**
25
+ * Extract user-visible text from a document buffer.
26
+ * Format-aware: handles XLSX, DOCX, PPTX, and CSV.
27
+ */
28
+ extractText(buffer: Buffer, mimeType: string): Promise<string>;
29
+ /**
30
+ * Run post-check: extract text → policy check → PII check.
31
+ */
32
+ postCheck(input: PostCheckInput): Promise<PostCheckResult>;
33
+ /**
34
+ * Extract text from an XLSX buffer using ExcelJS.
35
+ */
36
+ private extractXlsxText;
37
+ /**
38
+ * Extract text from a DOCX buffer using mammoth.
39
+ */
40
+ private extractDocxText;
41
+ /**
42
+ * Extract text from a PPTX buffer by parsing the OOXML zip.
43
+ * Uses jszip to read slide XML files and extracts text content.
44
+ */
45
+ private extractPptxText;
46
+ }
47
+ //# sourceMappingURL=document-post-check-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-post-check-service.d.ts","sourceRoot":"","sources":["../../src/services/document-post-check-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAGpE,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;IAC5C,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,WAAW,CAAC,EAAE,kBAAkB,CAAC;CAClC;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,qBAAa,wBAAwB;IACnC;;;OAGG;IACG,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAepE;;OAEG;IACG,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IAuDhE;;OAEG;YACW,eAAe;IAwB7B;;OAEG;YACW,eAAe;IAM7B;;;OAGG;YACW,eAAe;CAuB9B"}
@@ -0,0 +1,130 @@
1
+ export class DocumentPostCheckService {
2
+ /**
3
+ * Extract user-visible text from a document buffer.
4
+ * Format-aware: handles XLSX, DOCX, PPTX, and CSV.
5
+ */
6
+ async extractText(buffer, mimeType) {
7
+ switch (mimeType) {
8
+ case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
9
+ return this.extractXlsxText(buffer);
10
+ case "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
11
+ return this.extractDocxText(buffer);
12
+ case "application/vnd.openxmlformats-officedocument.presentationml.presentation":
13
+ return this.extractPptxText(buffer);
14
+ case "text/csv":
15
+ return buffer.toString("utf-8");
16
+ default:
17
+ return buffer.toString("utf-8");
18
+ }
19
+ }
20
+ /**
21
+ * Run post-check: extract text → policy check → PII check.
22
+ */
23
+ async postCheck(input) {
24
+ const text = await this.extractText(input.buffer, input.mimeType);
25
+ // Content policy check
26
+ if (input.contentPolicyService) {
27
+ try {
28
+ const evaluation = await input.contentPolicyService.evaluate(text);
29
+ if (!evaluation.allowed) {
30
+ const block = evaluation.violations.find((v) => v.action === "block");
31
+ return {
32
+ allowed: false,
33
+ piiDetected: false,
34
+ piiWarning: false,
35
+ policyViolation: `Blocked by policy "${block?.policyName ?? "unknown"}"`,
36
+ extractedTextLength: text.length,
37
+ };
38
+ }
39
+ }
40
+ catch (err) {
41
+ console.error("[DocumentPostCheck] Policy evaluation failed, proceeding:", err);
42
+ }
43
+ }
44
+ // PII check
45
+ let piiDetected = false;
46
+ let piiWarning = false;
47
+ if (input.piiDetector) {
48
+ try {
49
+ const piiResult = input.piiDetector.detect(text);
50
+ piiDetected = piiResult.matches.length > 0;
51
+ if (piiDetected) {
52
+ if (input.piiOutputPolicy === "block") {
53
+ return {
54
+ allowed: false,
55
+ piiDetected: true,
56
+ piiWarning: false,
57
+ policyViolation: "Edited document contains PII that is not allowed by organization policy.",
58
+ extractedTextLength: text.length,
59
+ };
60
+ }
61
+ piiWarning = input.piiOutputPolicy === "warn";
62
+ }
63
+ }
64
+ catch (err) {
65
+ console.error("[DocumentPostCheck] PII detection failed, proceeding:", err);
66
+ }
67
+ }
68
+ return {
69
+ allowed: true,
70
+ piiDetected,
71
+ piiWarning,
72
+ extractedTextLength: text.length,
73
+ };
74
+ }
75
+ /**
76
+ * Extract text from an XLSX buffer using ExcelJS.
77
+ */
78
+ async extractXlsxText(buffer) {
79
+ const ExcelJS = await import("exceljs");
80
+ const workbook = new ExcelJS.default.Workbook();
81
+ await workbook.xlsx.load(buffer);
82
+ const parts = [];
83
+ workbook.eachSheet((sheet) => {
84
+ parts.push(`[Sheet: ${sheet.name}]`);
85
+ sheet.eachRow((row) => {
86
+ const values = [];
87
+ row.eachCell((cell) => {
88
+ if (cell.value != null) {
89
+ values.push(String(cell.value));
90
+ }
91
+ });
92
+ if (values.length > 0) {
93
+ parts.push(values.join("\t"));
94
+ }
95
+ });
96
+ });
97
+ return parts.join("\n");
98
+ }
99
+ /**
100
+ * Extract text from a DOCX buffer using mammoth.
101
+ */
102
+ async extractDocxText(buffer) {
103
+ const mammoth = await import("mammoth");
104
+ const result = await mammoth.extractRawText({ buffer });
105
+ return result.value;
106
+ }
107
+ /**
108
+ * Extract text from a PPTX buffer by parsing the OOXML zip.
109
+ * Uses jszip to read slide XML files and extracts text content.
110
+ */
111
+ async extractPptxText(buffer) {
112
+ const JSZip = (await import("jszip")).default;
113
+ const zip = await JSZip.loadAsync(buffer);
114
+ const parts = [];
115
+ const slideFiles = Object.keys(zip.files)
116
+ .filter((name) => /^ppt\/slides\/slide\d+\.xml$/.test(name))
117
+ .sort();
118
+ for (const slidePath of slideFiles) {
119
+ const xml = await zip.files[slidePath].async("text");
120
+ // Extract text content from XML using regex (lightweight, no XML parser needed)
121
+ const textMatches = xml.match(/<a:t[^>]*>([^<]*)<\/a:t>/g);
122
+ if (textMatches) {
123
+ const slideTexts = textMatches.map((m) => m.replace(/<a:t[^>]*>/, "").replace(/<\/a:t>/, ""));
124
+ parts.push(slideTexts.join(" "));
125
+ }
126
+ }
127
+ return parts.join("\n");
128
+ }
129
+ }
130
+ //# sourceMappingURL=document-post-check-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-post-check-service.js","sourceRoot":"","sources":["../../src/services/document-post-check-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=document-post-check-service.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-post-check-service.test.d.ts","sourceRoot":"","sources":["../../src/services/document-post-check-service.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,150 @@
1
+ import { describe, it, expect, vi } from "vitest";
2
+ import { DocumentPostCheckService } from "./document-post-check-service.js";
3
+ describe("DocumentPostCheckService", () => {
4
+ const service = new DocumentPostCheckService();
5
+ describe("extractText", () => {
6
+ it("should extract text from CSV as-is", async () => {
7
+ const csv = "Name,Age\nAlice,30\nBob,25";
8
+ const buffer = Buffer.from(csv, "utf-8");
9
+ const result = await service.extractText(buffer, "text/csv");
10
+ expect(result).toBe(csv);
11
+ });
12
+ it("should extract text from XLSX", async () => {
13
+ // Create a minimal XLSX using ExcelJS
14
+ const ExcelJS = await import("exceljs");
15
+ const workbook = new ExcelJS.default.Workbook();
16
+ const sheet = workbook.addWorksheet("Test");
17
+ sheet.columns = [{ header: "Name", key: "name" }];
18
+ sheet.addRow(["Alice"]);
19
+ sheet.addRow(["Bob"]);
20
+ const arrayBuffer = await workbook.xlsx.writeBuffer();
21
+ const buffer = Buffer.from(arrayBuffer);
22
+ const result = await service.extractText(buffer, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
23
+ expect(result).toContain("Name");
24
+ expect(result).toContain("Alice");
25
+ expect(result).toContain("Bob");
26
+ expect(result).toContain("[Sheet: Test]");
27
+ });
28
+ it("should extract text from PPTX", async () => {
29
+ // Create a minimal PPTX using jszip (OOXML structure)
30
+ const JSZip = (await import("jszip")).default;
31
+ const zip = new JSZip();
32
+ // Minimal PPTX slide with text
33
+ const slideXml = `<?xml version="1.0" encoding="UTF-8"?>
34
+ <p:sld xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
35
+ xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main">
36
+ <p:cSld>
37
+ <p:spTree>
38
+ <p:sp>
39
+ <p:txBody>
40
+ <a:p><a:r><a:t>Hello World</a:t></a:r></a:p>
41
+ <a:p><a:r><a:t>Test Slide</a:t></a:r></a:p>
42
+ </p:txBody>
43
+ </p:sp>
44
+ </p:spTree>
45
+ </p:cSld>
46
+ </p:sld>`;
47
+ zip.file("ppt/slides/slide1.xml", slideXml);
48
+ const buffer = await zip.generateAsync({ type: "nodebuffer" });
49
+ const result = await service.extractText(buffer, "application/vnd.openxmlformats-officedocument.presentationml.presentation");
50
+ expect(result).toContain("Hello World");
51
+ expect(result).toContain("Test Slide");
52
+ });
53
+ });
54
+ describe("postCheck", () => {
55
+ it("should return allowed for clean content", async () => {
56
+ const buffer = Buffer.from("Just some clean text", "utf-8");
57
+ const result = await service.postCheck({
58
+ buffer,
59
+ mimeType: "text/csv",
60
+ piiOutputPolicy: "warn",
61
+ });
62
+ expect(result.allowed).toBe(true);
63
+ expect(result.piiDetected).toBe(false);
64
+ expect(result.piiWarning).toBe(false);
65
+ expect(result.extractedTextLength).toBeGreaterThan(0);
66
+ });
67
+ it("should block when content policy rejects", async () => {
68
+ const buffer = Buffer.from("some content", "utf-8");
69
+ const mockPolicySvc = {
70
+ evaluate: vi.fn().mockResolvedValue({
71
+ allowed: false,
72
+ violations: [{ action: "block", policyName: "TestPolicy", category: "test" }],
73
+ }),
74
+ };
75
+ const result = await service.postCheck({
76
+ buffer,
77
+ mimeType: "text/csv",
78
+ piiOutputPolicy: "warn",
79
+ contentPolicyService: mockPolicySvc,
80
+ });
81
+ expect(result.allowed).toBe(false);
82
+ expect(result.policyViolation).toContain("TestPolicy");
83
+ });
84
+ it("should block when PII detected and policy is 'block'", async () => {
85
+ const buffer = Buffer.from("My SSN is 123-45-6789", "utf-8");
86
+ const mockPiiDetector = {
87
+ detect: vi.fn().mockReturnValue({
88
+ matches: [{ type: "ssn", value: "123-45-6789" }],
89
+ }),
90
+ };
91
+ const result = await service.postCheck({
92
+ buffer,
93
+ mimeType: "text/csv",
94
+ piiOutputPolicy: "block",
95
+ piiDetector: mockPiiDetector,
96
+ });
97
+ expect(result.allowed).toBe(false);
98
+ expect(result.piiDetected).toBe(true);
99
+ });
100
+ it("should warn when PII detected and policy is 'warn'", async () => {
101
+ const buffer = Buffer.from("My email is test@example.com", "utf-8");
102
+ const mockPiiDetector = {
103
+ detect: vi.fn().mockReturnValue({
104
+ matches: [{ type: "email", value: "test@example.com" }],
105
+ }),
106
+ };
107
+ const result = await service.postCheck({
108
+ buffer,
109
+ mimeType: "text/csv",
110
+ piiOutputPolicy: "warn",
111
+ piiDetector: mockPiiDetector,
112
+ });
113
+ expect(result.allowed).toBe(true);
114
+ expect(result.piiDetected).toBe(true);
115
+ expect(result.piiWarning).toBe(true);
116
+ });
117
+ it("should not warn when PII detected and policy is 'strip'", async () => {
118
+ const buffer = Buffer.from("My email is test@example.com", "utf-8");
119
+ const mockPiiDetector = {
120
+ detect: vi.fn().mockReturnValue({
121
+ matches: [{ type: "email", value: "test@example.com" }],
122
+ }),
123
+ };
124
+ const result = await service.postCheck({
125
+ buffer,
126
+ mimeType: "text/csv",
127
+ piiOutputPolicy: "strip",
128
+ piiDetector: mockPiiDetector,
129
+ });
130
+ expect(result.allowed).toBe(true);
131
+ expect(result.piiDetected).toBe(true);
132
+ expect(result.piiWarning).toBe(false);
133
+ });
134
+ it("should handle policy evaluation failure gracefully", async () => {
135
+ const buffer = Buffer.from("some content", "utf-8");
136
+ const mockPolicySvc = {
137
+ evaluate: vi.fn().mockRejectedValue(new Error("DB down")),
138
+ };
139
+ const result = await service.postCheck({
140
+ buffer,
141
+ mimeType: "text/csv",
142
+ piiOutputPolicy: "warn",
143
+ contentPolicyService: mockPolicySvc,
144
+ });
145
+ // Should proceed without blocking
146
+ expect(result.allowed).toBe(true);
147
+ });
148
+ });
149
+ });
150
+ //# sourceMappingURL=document-post-check-service.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-post-check-service.test.js","sourceRoot":"","sources":["../../src/services/document-post-check-service.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAE5E,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,MAAM,OAAO,GAAG,IAAI,wBAAwB,EAAE,CAAC;IAE/C,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;QAC3B,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;YAClD,MAAM,GAAG,GAAG,4BAA4B,CAAC;YACzC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YAEzC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;YAC7D,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;YAC7C,sCAAsC;YACtC,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;YACxC,MAAM,QAAQ,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YAChD,MAAM,KAAK,GAAG,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;YAC5C,KAAK,CAAC,OAAO,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;YAClD,KAAK,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;YACxB,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;YAEtB,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAExC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,WAAW,CACtC,MAAM,EACN,mEAAmE,CACpE,CAAC;YACF,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YACjC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YAClC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YAChC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;YAC7C,sDAAsD;YACtD,MAAM,KAAK,GAAG,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;YAC9C,MAAM,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC;YAExB,+BAA+B;YAC/B,MAAM,QAAQ,GAAG;;;;;;;;;;;;;SAad,CAAC;YACJ,GAAG,CAAC,IAAI,CAAC,uBAAuB,EAAE,QAAQ,CAAC,CAAC;YAE5C,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;YAC/D,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,WAAW,CACtC,MAAM,EACN,2EAA2E,CAC5E,CAAC;YACF,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;YACxC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;QACzB,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;YACvD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,sBAAsB,EAAE,OAAO,CAAC,CAAC;YAC5D,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC;gBACrC,MAAM;gBACN,QAAQ,EAAE,UAAU;gBACpB,eAAe,EAAE,MAAM;aACxB,CAAC,CAAC;YAEH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACvC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACtC,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;YACxD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;YAEpD,MAAM,aAAa,GAAG;gBACpB,QAAQ,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC;oBAClC,OAAO,EAAE,KAAK;oBACd,UAAU,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;iBAC9E,CAAC;aACH,CAAC;YAEF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC;gBACrC,MAAM;gBACN,QAAQ,EAAE,UAAU;gBACpB,eAAe,EAAE,MAAM;gBACvB,oBAAoB,EAAE,aAAoB;aAC3C,CAAC,CAAC;YAEH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnC,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;YACpE,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,uBAAuB,EAAE,OAAO,CAAC,CAAC;YAE7D,MAAM,eAAe,GAAG;gBACtB,MAAM,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC;oBAC9B,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;iBACjD,CAAC;aACH,CAAC;YAEF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC;gBACrC,MAAM;gBACN,QAAQ,EAAE,UAAU;gBACpB,eAAe,EAAE,OAAO;gBACxB,WAAW,EAAE,eAAsB;aACpC,CAAC,CAAC;YAEH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;YAClE,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,8BAA8B,EAAE,OAAO,CAAC,CAAC;YAEpE,MAAM,eAAe,GAAG;gBACtB,MAAM,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC;oBAC9B,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC;iBACxD,CAAC;aACH,CAAC;YAEF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC;gBACrC,MAAM;gBACN,QAAQ,EAAE,UAAU;gBACpB,eAAe,EAAE,MAAM;gBACvB,WAAW,EAAE,eAAsB;aACpC,CAAC,CAAC;YAEH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;YACvE,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,8BAA8B,EAAE,OAAO,CAAC,CAAC;YAEpE,MAAM,eAAe,GAAG;gBACtB,MAAM,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC;oBAC9B,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC;iBACxD,CAAC;aACH,CAAC;YAEF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC;gBACrC,MAAM;gBACN,QAAQ,EAAE,UAAU;gBACpB,eAAe,EAAE,OAAO;gBACxB,WAAW,EAAE,eAAsB;aACpC,CAAC,CAAC;YAEH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;YAClE,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;YAEpD,MAAM,aAAa,GAAG;gBACpB,QAAQ,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;aAC1D,CAAC;YAEF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC;gBACrC,MAAM;gBACN,QAAQ,EAAE,UAAU;gBACpB,eAAe,EAAE,MAAM;gBACvB,oBAAoB,EAAE,aAAoB;aAC3C,CAAC,CAAC;YAEH,kCAAkC;YAClC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { CreateSpreadsheetArgs, CreatePresentationArgs, CreateDocumentArgs, CreateCsvArgs } from "./chat-tool-definitions.js";
2
+ export interface RenderResult {
3
+ buffer: Buffer;
4
+ mimeType: string;
5
+ extension: string;
6
+ fileName: string;
7
+ }
8
+ export declare class DocumentRenderService {
9
+ /**
10
+ * Render an Excel spreadsheet (.xlsx) from structured data.
11
+ */
12
+ renderSpreadsheet(args: CreateSpreadsheetArgs): Promise<RenderResult>;
13
+ /**
14
+ * Render a PowerPoint presentation (.pptx) from slide definitions.
15
+ */
16
+ renderPresentation(args: CreatePresentationArgs): Promise<RenderResult>;
17
+ /**
18
+ * Render a Word document (.docx) from markdown content.
19
+ * Converts markdown → HTML → DOCX via @turbodocx/html-to-docx.
20
+ */
21
+ renderDocument(args: CreateDocumentArgs): Promise<RenderResult>;
22
+ /**
23
+ * Render a CSV file from structured data.
24
+ */
25
+ renderCsv(args: CreateCsvArgs): Promise<RenderResult>;
26
+ }
27
+ //# sourceMappingURL=document-render-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-render-service.d.ts","sourceRoot":"","sources":["../../src/services/document-render-service.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,qBAAqB,EACrB,sBAAsB,EACtB,kBAAkB,EAClB,aAAa,EACd,MAAM,4BAA4B,CAAC;AAEpC,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAID,qBAAa,qBAAqB;IAChC;;OAEG;IACG,iBAAiB,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,YAAY,CAAC;IAsC3E;;OAEG;IACG,kBAAkB,CAAC,IAAI,EAAE,sBAAsB,GAAG,OAAO,CAAC,YAAY,CAAC;IA+G7E;;;OAGG;IACG,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,YAAY,CAAC;IAkBrE;;OAEG;IACG,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;CAiB5D"}
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Stateless document rendering service.
3
+ *
4
+ * Converts structured LLM tool-call arguments into file buffers.
5
+ * Each method returns { buffer, mimeType, extension, fileName }.
6
+ */
7
+ import ExcelJS from "exceljs";
8
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
9
+ import PptxGenJSDefault from "pptxgenjs";
10
+ import Papa from "papaparse";
11
+ import MarkdownIt from "markdown-it";
12
+ const md = new MarkdownIt();
13
+ export class DocumentRenderService {
14
+ /**
15
+ * Render an Excel spreadsheet (.xlsx) from structured data.
16
+ */
17
+ async renderSpreadsheet(args) {
18
+ const workbook = new ExcelJS.Workbook();
19
+ for (const sheet of args.sheets) {
20
+ const ws = workbook.addWorksheet(sheet.name);
21
+ // Set columns with headers and optional widths
22
+ ws.columns = sheet.columns.map((col) => ({
23
+ header: col.header,
24
+ key: col.header,
25
+ width: col.width ?? 15,
26
+ }));
27
+ // Add data rows
28
+ for (const row of sheet.rows) {
29
+ ws.addRow(row);
30
+ }
31
+ // Apply formulas
32
+ if (sheet.formulas) {
33
+ for (const f of sheet.formulas) {
34
+ const cell = ws.getCell(f.cell);
35
+ cell.value = { formula: f.formula };
36
+ }
37
+ }
38
+ }
39
+ const arrayBuffer = await workbook.xlsx.writeBuffer();
40
+ const buffer = Buffer.from(arrayBuffer);
41
+ return {
42
+ buffer,
43
+ mimeType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
44
+ extension: "xlsx",
45
+ fileName: `${args.fileName}.xlsx`,
46
+ };
47
+ }
48
+ /**
49
+ * Render a PowerPoint presentation (.pptx) from slide definitions.
50
+ */
51
+ async renderPresentation(args) {
52
+ // Handle both ESM and CJS module resolution
53
+ const PptxGenJS = PptxGenJSDefault.default ?? PptxGenJSDefault;
54
+ const pptx = new PptxGenJS();
55
+ for (const slideData of args.slides) {
56
+ const slide = pptx.addSlide();
57
+ switch (slideData.layout) {
58
+ case "title": {
59
+ if (slideData.title) {
60
+ slide.addText(slideData.title, {
61
+ x: 0.5,
62
+ y: 1.5,
63
+ w: 9,
64
+ h: 1.5,
65
+ fontSize: 36,
66
+ bold: true,
67
+ align: "center",
68
+ color: "363636",
69
+ });
70
+ }
71
+ if (slideData.subtitle) {
72
+ slide.addText(slideData.subtitle, {
73
+ x: 0.5,
74
+ y: 3.2,
75
+ w: 9,
76
+ h: 1,
77
+ fontSize: 20,
78
+ align: "center",
79
+ color: "666666",
80
+ });
81
+ }
82
+ break;
83
+ }
84
+ case "content": {
85
+ if (slideData.title) {
86
+ slide.addText(slideData.title, {
87
+ x: 0.5,
88
+ y: 0.3,
89
+ w: 9,
90
+ h: 0.8,
91
+ fontSize: 24,
92
+ bold: true,
93
+ color: "363636",
94
+ });
95
+ }
96
+ if (slideData.body?.length) {
97
+ slide.addText(slideData.body.map((line) => ({
98
+ text: line,
99
+ options: { bullet: true, breakLine: true },
100
+ })), { x: 0.5, y: 1.3, w: 9, h: 4, fontSize: 16, color: "404040", valign: "top" });
101
+ }
102
+ break;
103
+ }
104
+ case "two-column": {
105
+ if (slideData.title) {
106
+ slide.addText(slideData.title, {
107
+ x: 0.5,
108
+ y: 0.3,
109
+ w: 9,
110
+ h: 0.8,
111
+ fontSize: 24,
112
+ bold: true,
113
+ color: "363636",
114
+ });
115
+ }
116
+ if (slideData.leftColumn?.length) {
117
+ slide.addText(slideData.leftColumn.map((line) => ({
118
+ text: line,
119
+ options: { bullet: true, breakLine: true },
120
+ })), { x: 0.5, y: 1.3, w: 4.2, h: 4, fontSize: 14, color: "404040", valign: "top" });
121
+ }
122
+ if (slideData.rightColumn?.length) {
123
+ slide.addText(slideData.rightColumn.map((line) => ({
124
+ text: line,
125
+ options: { bullet: true, breakLine: true },
126
+ })), { x: 5.3, y: 1.3, w: 4.2, h: 4, fontSize: 14, color: "404040", valign: "top" });
127
+ }
128
+ break;
129
+ }
130
+ case "blank":
131
+ // Empty slide — intentionally left blank
132
+ break;
133
+ }
134
+ if (slideData.notes) {
135
+ slide.addNotes(slideData.notes);
136
+ }
137
+ }
138
+ const output = await pptx.write({ outputType: "nodebuffer" });
139
+ const buffer = Buffer.from(output);
140
+ return {
141
+ buffer,
142
+ mimeType: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
143
+ extension: "pptx",
144
+ fileName: `${args.fileName}.pptx`,
145
+ };
146
+ }
147
+ /**
148
+ * Render a Word document (.docx) from markdown content.
149
+ * Converts markdown → HTML → DOCX via @turbodocx/html-to-docx.
150
+ */
151
+ async renderDocument(args) {
152
+ const html = md.render(args.content);
153
+ // Dynamic import since html-to-docx may not have proper ESM exports
154
+ const { default: htmlToDocx } = await import("@turbodocx/html-to-docx");
155
+ const buffer = await htmlToDocx(html, null, {
156
+ table: { row: { cantSplit: true } },
157
+ footer: true,
158
+ pageNumber: true,
159
+ });
160
+ return {
161
+ buffer: Buffer.from(buffer),
162
+ mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
163
+ extension: "docx",
164
+ fileName: `${args.fileName}.docx`,
165
+ };
166
+ }
167
+ /**
168
+ * Render a CSV file from structured data.
169
+ */
170
+ async renderCsv(args) {
171
+ const csv = Papa.unparse({
172
+ fields: args.headers,
173
+ data: args.rows,
174
+ }, {
175
+ delimiter: args.delimiter,
176
+ });
177
+ const buffer = Buffer.from(csv, "utf-8");
178
+ return {
179
+ buffer,
180
+ mimeType: "text/csv",
181
+ extension: "csv",
182
+ fileName: `${args.fileName}.csv`,
183
+ };
184
+ }
185
+ }
186
+ //# sourceMappingURL=document-render-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-render-service.js","sourceRoot":"","sources":["../../src/services/document-render-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=document-render-service.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-render-service.test.d.ts","sourceRoot":"","sources":["../../src/services/document-render-service.test.ts"],"names":[],"mappings":""}