kordoc 4.0.7 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +837 -806
- package/dist/{-6HWEFXVV.js → -AS4IABL2.js} +24 -11
- package/dist/{chunk-BKWHX3RC.js → chunk-37HJHCPA.js} +24 -15
- package/dist/chunk-37HJHCPA.js.map +1 -0
- package/dist/{chunk-U25XGCNH.cjs → chunk-37VKMUST.cjs} +174 -25
- package/dist/chunk-37VKMUST.cjs.map +1 -0
- package/dist/{chunk-5OKHAJ62.js → chunk-4KI23VHA.js} +162 -13
- package/dist/chunk-4KI23VHA.js.map +1 -0
- package/dist/{chunk-6GBLFQMA.js → chunk-5RPYBC2Q.js} +1 -1
- package/dist/chunk-5RPYBC2Q.js.map +1 -0
- package/dist/{chunk-NGSHDBQR.js → chunk-AX2R5Q2N.js} +7 -4
- package/dist/chunk-AX2R5Q2N.js.map +1 -0
- package/dist/{chunk-X34YWRL5.cjs → chunk-DCZVOIEO.cjs} +1 -1
- package/dist/chunk-DCZVOIEO.cjs.map +1 -0
- package/dist/chunk-DZIXKL7E.js +145 -0
- package/dist/chunk-DZIXKL7E.js.map +1 -0
- package/dist/chunk-F2ZU3IZG.js +82 -0
- package/dist/chunk-F2ZU3IZG.js.map +1 -0
- package/dist/{chunk-AIQ3ISQU.js → chunk-GE43BE46.js} +1 -1
- package/dist/chunk-GE43BE46.js.map +1 -0
- package/dist/{chunk-Q7EN4EUJ.js → chunk-GQVSHGG4.js} +12 -4
- package/dist/chunk-GQVSHGG4.js.map +1 -0
- package/dist/chunk-GS7T56RP.cjs.map +1 -1
- package/dist/{chunk-TJJTLM76.js → chunk-L2XQQTOY.js} +1422 -1121
- package/dist/chunk-L2XQQTOY.js.map +1 -0
- package/dist/{chunk-3TBUDJDE.js → chunk-MOL7MDBG.js} +1 -1
- package/dist/chunk-MOL7MDBG.js.map +1 -0
- package/dist/{chunk-CNM75ZSX.js → chunk-O5VS7RIR.js} +2 -2
- package/dist/chunk-O5VS7RIR.js.map +1 -0
- package/dist/{chunk-2SN3CKME.js → chunk-SSTK6IKK.js} +18 -21
- package/dist/chunk-SSTK6IKK.js.map +1 -0
- package/dist/chunk-UOO7LSDG.js +152 -0
- package/dist/chunk-UOO7LSDG.js.map +1 -0
- package/dist/{chunk-ONXVBURQ.js → chunk-WO52HVQJ.js} +2 -2
- package/dist/chunk-WO52HVQJ.js.map +1 -0
- package/dist/{chunk-CFQLK3LM.js → chunk-YOO6ET6M.js} +7 -3
- package/dist/chunk-YOO6ET6M.js.map +1 -0
- package/dist/chunks-WVMGF7JL.js +10 -0
- package/dist/cli.js +173 -38
- package/dist/cli.js.map +1 -1
- package/dist/{detect-NTR2FUEG.js → detect-YEZX2XCF.js} +2 -2
- package/dist/{formula-ZYUDQHD3.cjs → formula-5NKVS2LR.cjs} +1 -1
- package/dist/formula-5NKVS2LR.cjs.map +1 -0
- package/dist/{formula-KOQV353G.js → formula-JCNF43NE.js} +1 -1
- package/dist/formula-JCNF43NE.js.map +1 -0
- package/dist/{formula-MEDGYQXS.js → formula-RXVSQPXI.js} +1 -1
- package/dist/formula-RXVSQPXI.js.map +1 -0
- package/dist/index.cjs +1932 -1397
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +106 -2
- package/dist/index.d.ts +106 -2
- package/dist/index.js +1626 -1091
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +275 -67
- package/dist/mcp.js.map +1 -1
- package/dist/page-range-737B4EZW.js +8 -0
- package/dist/page-range-LNMXJU6W.js +7 -0
- package/dist/page-range-P7SDW6LR.cjs +8 -0
- package/dist/page-range-P7SDW6LR.cjs.map +1 -0
- package/dist/{parser-E6U5TNAU.cjs → parser-N4A7UGDK.cjs} +314 -56
- package/dist/parser-N4A7UGDK.cjs.map +1 -0
- package/dist/{parser-5EHWYJMC.js → parser-PEOYBXBO.js} +287 -27
- package/dist/parser-PEOYBXBO.js.map +1 -0
- package/dist/{parser-UGB3NIVH.js → parser-XX4QTDFQ.js} +283 -25
- package/dist/parser-XX4QTDFQ.js.map +1 -0
- package/dist/{profile-io-CAKRPQRD.js → profile-io-PLDQFPJA.js} +3 -3
- package/dist/{provider-5K7O3Z2O.cjs → provider-4FAYHJ6N.cjs} +3 -3
- package/dist/provider-4FAYHJ6N.cjs.map +1 -0
- package/dist/{provider-H4WWSPOV.js → provider-C6IOGIS5.js} +3 -3
- package/dist/provider-C6IOGIS5.js.map +1 -0
- package/dist/{provider-7H4CPZYS.js → provider-UIBW2MIH.js} +3 -3
- package/dist/provider-UIBW2MIH.js.map +1 -0
- package/dist/rasterize-WWNQLKYW.js +40 -0
- package/dist/rasterize-WWNQLKYW.js.map +1 -0
- package/dist/redact-7ILEAUTS.js +12 -0
- package/dist/render-T7S6H6AN.js +10 -0
- package/dist/render-T7S6H6AN.js.map +1 -0
- package/dist/seal-7PTL6MXH.js +10 -0
- package/dist/seal-7PTL6MXH.js.map +1 -0
- package/dist/{setup-QSJ2INNS.js → setup-Q2PRE7UA.js} +5 -3
- package/dist/setup-Q2PRE7UA.js.map +1 -0
- package/dist/{watch-RMX427YR.js → watch-SFHXZALC.js} +78 -24
- package/dist/watch-SFHXZALC.js.map +1 -0
- package/package.json +97 -97
- package/dist/chunk-2SN3CKME.js.map +0 -1
- package/dist/chunk-3TBUDJDE.js.map +0 -1
- package/dist/chunk-5OKHAJ62.js.map +0 -1
- package/dist/chunk-6GBLFQMA.js.map +0 -1
- package/dist/chunk-AIQ3ISQU.js.map +0 -1
- package/dist/chunk-BKWHX3RC.js.map +0 -1
- package/dist/chunk-CFQLK3LM.js.map +0 -1
- package/dist/chunk-CNM75ZSX.js.map +0 -1
- package/dist/chunk-NGSHDBQR.js.map +0 -1
- package/dist/chunk-ONXVBURQ.js.map +0 -1
- package/dist/chunk-Q7EN4EUJ.js.map +0 -1
- package/dist/chunk-TJJTLM76.js.map +0 -1
- package/dist/chunk-U25XGCNH.cjs.map +0 -1
- package/dist/chunk-X34YWRL5.cjs.map +0 -1
- package/dist/formula-KOQV353G.js.map +0 -1
- package/dist/formula-MEDGYQXS.js.map +0 -1
- package/dist/formula-ZYUDQHD3.cjs.map +0 -1
- package/dist/page-range-CIRRJPXJ.js +0 -7
- package/dist/page-range-OF5I4PQY.js +0 -8
- package/dist/page-range-TPIRSA3J.cjs +0 -8
- package/dist/page-range-TPIRSA3J.cjs.map +0 -1
- package/dist/parser-5EHWYJMC.js.map +0 -1
- package/dist/parser-E6U5TNAU.cjs.map +0 -1
- package/dist/parser-UGB3NIVH.js.map +0 -1
- package/dist/provider-5K7O3Z2O.cjs.map +0 -1
- package/dist/provider-7H4CPZYS.js.map +0 -1
- package/dist/provider-H4WWSPOV.js.map +0 -1
- package/dist/render-P6663O4I.js +0 -10
- package/dist/seal-7PPTXKKV.js +0 -10
- package/dist/setup-QSJ2INNS.js.map +0 -1
- package/dist/watch-RMX427YR.js.map +0 -1
- /package/dist/{-6HWEFXVV.js.map → -AS4IABL2.js.map} +0 -0
- /package/dist/{detect-NTR2FUEG.js.map → chunks-WVMGF7JL.js.map} +0 -0
- /package/dist/{page-range-CIRRJPXJ.js.map → detect-YEZX2XCF.js.map} +0 -0
- /package/dist/{page-range-OF5I4PQY.js.map → page-range-737B4EZW.js.map} +0 -0
- /package/dist/{profile-io-CAKRPQRD.js.map → page-range-LNMXJU6W.js.map} +0 -0
- /package/dist/{render-P6663O4I.js.map → profile-io-PLDQFPJA.js.map} +0 -0
- /package/dist/{seal-7PPTXKKV.js.map → redact-7ILEAUTS.js.map} +0 -0
package/dist/mcp.js
CHANGED
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
SIZE_KEYS,
|
|
15
15
|
SIZE_PT_RANGE,
|
|
16
16
|
buildGongmunOptions
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-5RPYBC2Q.js";
|
|
18
18
|
import {
|
|
19
19
|
PRESET_ALIAS,
|
|
20
20
|
compare,
|
|
@@ -31,34 +31,41 @@ import {
|
|
|
31
31
|
patchHwp,
|
|
32
32
|
patchHwpx,
|
|
33
33
|
unknownFontWarnings
|
|
34
|
-
} from "./chunk-
|
|
35
|
-
import
|
|
36
|
-
blocksToMarkdown
|
|
37
|
-
} from "./chunk-2SN3CKME.js";
|
|
34
|
+
} from "./chunk-L2XQQTOY.js";
|
|
35
|
+
import "./chunk-UOO7LSDG.js";
|
|
38
36
|
import {
|
|
39
37
|
detectFormat,
|
|
40
38
|
detectZipFormat
|
|
41
|
-
} from "./chunk-
|
|
42
|
-
import "./chunk-
|
|
43
|
-
import "./chunk-
|
|
44
|
-
import "./chunk-
|
|
45
|
-
import "./chunk-
|
|
39
|
+
} from "./chunk-YOO6ET6M.js";
|
|
40
|
+
import "./chunk-MOL7MDBG.js";
|
|
41
|
+
import "./chunk-AX2R5Q2N.js";
|
|
42
|
+
import "./chunk-DZIXKL7E.js";
|
|
43
|
+
import "./chunk-F2ZU3IZG.js";
|
|
44
|
+
import {
|
|
45
|
+
blocksToMarkdown
|
|
46
|
+
} from "./chunk-SSTK6IKK.js";
|
|
47
|
+
import "./chunk-37HJHCPA.js";
|
|
48
|
+
import "./chunk-GQVSHGG4.js";
|
|
46
49
|
import {
|
|
47
50
|
KordocError,
|
|
48
51
|
VERSION,
|
|
52
|
+
classifyError,
|
|
49
53
|
sanitizeError,
|
|
50
54
|
toArrayBuffer
|
|
51
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-O5VS7RIR.js";
|
|
52
56
|
|
|
53
57
|
// src/mcp.ts
|
|
54
58
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
55
59
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
56
60
|
import { z } from "zod";
|
|
57
|
-
import { readFileSync, writeFileSync, realpathSync, openSync, readSync, closeSync, statSync, mkdirSync } from "fs";
|
|
58
|
-
import {
|
|
59
|
-
|
|
61
|
+
import { readFileSync, writeFileSync, realpathSync, openSync, readSync, closeSync, statSync, mkdirSync, existsSync } from "fs";
|
|
62
|
+
import { pathToFileURL } from "url";
|
|
63
|
+
import { resolve, isAbsolute, extname, dirname, basename } from "path";
|
|
64
|
+
var ALLOWED_EXTENSIONS = /* @__PURE__ */ new Set([".hwp", ".hwpx", ".hml", ".pdf", ".xls", ".xlsx", ".docx"]);
|
|
65
|
+
var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".bmp"]);
|
|
66
|
+
var PROFILE_EXTENSIONS = /* @__PURE__ */ new Set([".json"]);
|
|
60
67
|
var MAX_FILE_SIZE = 500 * 1024 * 1024;
|
|
61
|
-
function safePath(filePath) {
|
|
68
|
+
function safePath(filePath, allowedExts = ALLOWED_EXTENSIONS) {
|
|
62
69
|
if (!filePath) throw new KordocError("\uD30C\uC77C \uACBD\uB85C\uAC00 \uBE44\uC5B4\uC788\uC2B5\uB2C8\uB2E4");
|
|
63
70
|
const resolved = resolve(filePath);
|
|
64
71
|
let real;
|
|
@@ -71,12 +78,53 @@ function safePath(filePath) {
|
|
|
71
78
|
}
|
|
72
79
|
if (!isAbsolute(real)) throw new KordocError("\uC808\uB300 \uACBD\uB85C\uB9CC \uD5C8\uC6A9\uB429\uB2C8\uB2E4");
|
|
73
80
|
const ext = extname(real).toLowerCase();
|
|
74
|
-
if (!
|
|
81
|
+
if (!allowedExts.has(ext)) throw new KordocError(`\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uD655\uC7A5\uC790\uC785\uB2C8\uB2E4: ${ext} (\uD5C8\uC6A9: ${[...allowedExts].join(", ")})`);
|
|
75
82
|
return real;
|
|
76
83
|
}
|
|
84
|
+
function safeOutputPath(outputPath, allowedExts) {
|
|
85
|
+
if (!outputPath) throw new KordocError("\uCD9C\uB825 \uACBD\uB85C\uAC00 \uBE44\uC5B4\uC788\uC2B5\uB2C8\uB2E4");
|
|
86
|
+
const resolved = resolve(outputPath);
|
|
87
|
+
const ext = extname(resolved).toLowerCase();
|
|
88
|
+
if (!allowedExts.has(ext)) {
|
|
89
|
+
throw new KordocError(`\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uCD9C\uB825 \uD655\uC7A5\uC790\uC785\uB2C8\uB2E4: ${ext || "(\uC5C6\uC74C)"} (\uD5C8\uC6A9: ${[...allowedExts].join(", ")})`);
|
|
90
|
+
}
|
|
91
|
+
const parent = dirname(resolved);
|
|
92
|
+
if (existsSync(parent)) {
|
|
93
|
+
try {
|
|
94
|
+
return resolve(realpathSync(parent), basename(resolved));
|
|
95
|
+
} catch (err) {
|
|
96
|
+
throw new KordocError(`\uCD9C\uB825 \uACBD\uB85C \uCC98\uB9AC \uC624\uB958 [${err?.code ?? "UNKNOWN"}]: ${parent}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return resolved;
|
|
100
|
+
}
|
|
101
|
+
function describeError(err) {
|
|
102
|
+
if (err instanceof KordocError) return err.message;
|
|
103
|
+
const code = err?.code;
|
|
104
|
+
if (typeof code === "string" && /^E[A-Z]+$/.test(code)) {
|
|
105
|
+
const hints = {
|
|
106
|
+
ENOENT: "\uD30C\uC77C \uB610\uB294 \uB514\uB809\uD1A0\uB9AC\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4",
|
|
107
|
+
EACCES: "\uC811\uADFC \uAD8C\uD55C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4",
|
|
108
|
+
EPERM: "\uC791\uC5C5 \uAD8C\uD55C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4",
|
|
109
|
+
EISDIR: "\uD30C\uC77C\uC774 \uC544\uB2C8\uB77C \uB514\uB809\uD1A0\uB9AC\uC785\uB2C8\uB2E4",
|
|
110
|
+
ENOTDIR: "\uACBD\uB85C \uC911\uAC04\uC774 \uB514\uB809\uD1A0\uB9AC\uAC00 \uC544\uB2D9\uB2C8\uB2E4",
|
|
111
|
+
ENOSPC: "\uB514\uC2A4\uD06C \uACF5\uAC04\uC774 \uBD80\uC871\uD569\uB2C8\uB2E4"
|
|
112
|
+
};
|
|
113
|
+
return `\uD30C\uC77C \uC2DC\uC2A4\uD15C \uC624\uB958 [${code}]: ${hints[code] ?? "\uACBD\uB85C\uC640 \uAD8C\uD55C\uC744 \uD655\uC778\uD558\uC138\uC694"}`;
|
|
114
|
+
}
|
|
115
|
+
const cls = classifyError(err);
|
|
116
|
+
return cls === "PARSE_ERROR" ? sanitizeError(err) : `\uBB38\uC11C \uCC98\uB9AC \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4 (${cls})`;
|
|
117
|
+
}
|
|
118
|
+
var MAX_RESPONSE_CHARS = 2e5;
|
|
119
|
+
function capResponseText(text, maxChars = MAX_RESPONSE_CHARS) {
|
|
120
|
+
if (text.length <= maxChars) return text;
|
|
121
|
+
return text.slice(0, maxChars) + `
|
|
122
|
+
|
|
123
|
+
\u2026 [\uC751\uB2F5\uC774 ${maxChars.toLocaleString()}\uC790 \uC0C1\uD55C\uC744 \uB118\uC5B4 \uC808\uB2E8\uB428 (\uC804\uCCB4 ${text.length.toLocaleString()}\uC790) \u2014 parse_pages\uB85C \uD398\uC774\uC9C0 \uBC94\uC704\uB97C \uB098\uB220 \uC77D\uC73C\uC138\uC694]`;
|
|
124
|
+
}
|
|
77
125
|
var MAX_METADATA_FILE_SIZE = 50 * 1024 * 1024;
|
|
78
|
-
function readValidatedFile(filePath, maxSize = MAX_FILE_SIZE) {
|
|
79
|
-
const resolved = safePath(filePath);
|
|
126
|
+
function readValidatedFile(filePath, maxSize = MAX_FILE_SIZE, allowedExts = ALLOWED_EXTENSIONS) {
|
|
127
|
+
const resolved = safePath(filePath, allowedExts);
|
|
80
128
|
let fileSize;
|
|
81
129
|
try {
|
|
82
130
|
fileSize = statSync(resolved).size;
|
|
@@ -97,9 +145,9 @@ function readValidatedFile(filePath, maxSize = MAX_FILE_SIZE) {
|
|
|
97
145
|
function detectFormatFromHeader(resolved) {
|
|
98
146
|
const fd = openSync(resolved, "r");
|
|
99
147
|
try {
|
|
100
|
-
const headerBuf = Buffer.alloc(
|
|
101
|
-
readSync(fd, headerBuf, 0,
|
|
102
|
-
return detectFormat(toArrayBuffer(headerBuf));
|
|
148
|
+
const headerBuf = Buffer.alloc(512);
|
|
149
|
+
const bytesRead = readSync(fd, headerBuf, 0, 512, 0);
|
|
150
|
+
return detectFormat(toArrayBuffer(headerBuf.subarray(0, bytesRead)));
|
|
103
151
|
} finally {
|
|
104
152
|
closeSync(fd);
|
|
105
153
|
}
|
|
@@ -116,7 +164,7 @@ server.tool(
|
|
|
116
164
|
},
|
|
117
165
|
async ({ file_path }) => {
|
|
118
166
|
try {
|
|
119
|
-
const { buffer } = readValidatedFile(file_path);
|
|
167
|
+
const { buffer, resolved } = readValidatedFile(file_path);
|
|
120
168
|
const format = detectFormat(buffer);
|
|
121
169
|
if (format === "unknown") {
|
|
122
170
|
return {
|
|
@@ -124,7 +172,7 @@ server.tool(
|
|
|
124
172
|
isError: true
|
|
125
173
|
};
|
|
126
174
|
}
|
|
127
|
-
const result = await parse(buffer);
|
|
175
|
+
const result = await parse(buffer, { filePath: resolved });
|
|
128
176
|
if (!result.success) {
|
|
129
177
|
return {
|
|
130
178
|
content: [{ type: "text", text: `\uD30C\uC2F1 \uC2E4\uD328 (${result.fileType}): ${result.error}` }],
|
|
@@ -156,11 +204,11 @@ ${warnText}`);
|
|
|
156
204
|
|
|
157
205
|
${markdown}`);
|
|
158
206
|
return {
|
|
159
|
-
content: [{ type: "text", text: parts.join("") }]
|
|
207
|
+
content: [{ type: "text", text: capResponseText(parts.join("")) }]
|
|
160
208
|
};
|
|
161
209
|
} catch (err) {
|
|
162
210
|
return {
|
|
163
|
-
content: [{ type: "text", text: `\uC624\uB958: ${
|
|
211
|
+
content: [{ type: "text", text: `\uC624\uB958: ${describeError(err)}` }],
|
|
164
212
|
isError: true
|
|
165
213
|
};
|
|
166
214
|
}
|
|
@@ -177,7 +225,7 @@ server.tool(
|
|
|
177
225
|
const resolved = safePath(file_path);
|
|
178
226
|
let format = detectFormatFromHeader(resolved);
|
|
179
227
|
if (format === "hwpx") {
|
|
180
|
-
const { buffer } = readValidatedFile(file_path
|
|
228
|
+
const { buffer } = readValidatedFile(file_path);
|
|
181
229
|
format = await detectZipFormat(buffer);
|
|
182
230
|
}
|
|
183
231
|
return {
|
|
@@ -185,7 +233,7 @@ server.tool(
|
|
|
185
233
|
};
|
|
186
234
|
} catch (err) {
|
|
187
235
|
return {
|
|
188
|
-
content: [{ type: "text", text: `\uC624\uB958: ${
|
|
236
|
+
content: [{ type: "text", text: `\uC624\uB958: ${describeError(err)}` }],
|
|
189
237
|
isError: true
|
|
190
238
|
};
|
|
191
239
|
}
|
|
@@ -211,7 +259,7 @@ server.tool(
|
|
|
211
259
|
let metadata;
|
|
212
260
|
let effectiveFormat = format;
|
|
213
261
|
if (format === "hwpx") {
|
|
214
|
-
const { detectZipFormat: detectZipFormat2 } = await import("./detect-
|
|
262
|
+
const { detectZipFormat: detectZipFormat2 } = await import("./detect-YEZX2XCF.js");
|
|
215
263
|
const zipFormat = await detectZipFormat2(buffer);
|
|
216
264
|
if (zipFormat === "xlsx" || zipFormat === "docx") effectiveFormat = zipFormat;
|
|
217
265
|
}
|
|
@@ -224,12 +272,14 @@ server.tool(
|
|
|
224
272
|
break;
|
|
225
273
|
case "pdf":
|
|
226
274
|
try {
|
|
227
|
-
const { extractPdfMetadataOnly } = await import("./parser-
|
|
275
|
+
const { extractPdfMetadataOnly } = await import("./parser-PEOYBXBO.js");
|
|
228
276
|
metadata = await extractPdfMetadataOnly(buffer);
|
|
229
277
|
} catch {
|
|
230
278
|
metadata = void 0;
|
|
231
279
|
}
|
|
232
280
|
break;
|
|
281
|
+
case "hwp3":
|
|
282
|
+
case "hwpml":
|
|
233
283
|
case "xlsx":
|
|
234
284
|
case "docx": {
|
|
235
285
|
const result = await parse(buffer);
|
|
@@ -242,7 +292,7 @@ server.tool(
|
|
|
242
292
|
};
|
|
243
293
|
} catch (err) {
|
|
244
294
|
return {
|
|
245
|
-
content: [{ type: "text", text: `\uC624\uB958: ${
|
|
295
|
+
content: [{ type: "text", text: `\uC624\uB958: ${describeError(err)}` }],
|
|
246
296
|
isError: true
|
|
247
297
|
};
|
|
248
298
|
}
|
|
@@ -284,7 +334,7 @@ ${result.markdown}` }]
|
|
|
284
334
|
};
|
|
285
335
|
} catch (err) {
|
|
286
336
|
return {
|
|
287
|
-
content: [{ type: "text", text: `\uC624\uB958: ${
|
|
337
|
+
content: [{ type: "text", text: `\uC624\uB958: ${describeError(err)}` }],
|
|
288
338
|
isError: true
|
|
289
339
|
};
|
|
290
340
|
}
|
|
@@ -336,7 +386,7 @@ ${tableMarkdown}` }]
|
|
|
336
386
|
};
|
|
337
387
|
} catch (err) {
|
|
338
388
|
return {
|
|
339
|
-
content: [{ type: "text", text: `\uC624\uB958: ${
|
|
389
|
+
content: [{ type: "text", text: `\uC624\uB958: ${describeError(err)}` }],
|
|
340
390
|
isError: true
|
|
341
391
|
};
|
|
342
392
|
}
|
|
@@ -371,7 +421,7 @@ server.tool(
|
|
|
371
421
|
};
|
|
372
422
|
} catch (err) {
|
|
373
423
|
return {
|
|
374
|
-
content: [{ type: "text", text: `\uC624\uB958: ${
|
|
424
|
+
content: [{ type: "text", text: `\uC624\uB958: ${describeError(err)}` }],
|
|
375
425
|
isError: true
|
|
376
426
|
};
|
|
377
427
|
}
|
|
@@ -386,7 +436,7 @@ server.tool(
|
|
|
386
436
|
async ({ file_path }) => {
|
|
387
437
|
try {
|
|
388
438
|
const { buffer } = readValidatedFile(file_path);
|
|
389
|
-
const result = await parse(buffer);
|
|
439
|
+
const result = await parse(buffer, { keepTrailingEmptyCols: true });
|
|
390
440
|
if (!result.success) {
|
|
391
441
|
return {
|
|
392
442
|
content: [{ type: "text", text: `\uD30C\uC2F1 \uC2E4\uD328: ${result.error}` }],
|
|
@@ -399,7 +449,7 @@ server.tool(
|
|
|
399
449
|
};
|
|
400
450
|
} catch (err) {
|
|
401
451
|
return {
|
|
402
|
-
content: [{ type: "text", text: `\uC624\uB958: ${
|
|
452
|
+
content: [{ type: "text", text: `\uC624\uB958: ${describeError(err)}` }],
|
|
403
453
|
isError: true
|
|
404
454
|
};
|
|
405
455
|
}
|
|
@@ -427,6 +477,8 @@ server.tool(
|
|
|
427
477
|
},
|
|
428
478
|
async ({ file_path, fields, formats, require_unique, mask_values, output_format, output_path }) => {
|
|
429
479
|
try {
|
|
480
|
+
const outExts = output_format === "markdown" ? /* @__PURE__ */ new Set([".md", ".markdown", ".txt"]) : /* @__PURE__ */ new Set([".hwpx"]);
|
|
481
|
+
const outPath = output_path ? safeOutputPath(output_path, outExts) : void 0;
|
|
430
482
|
const { buffer } = readValidatedFile(file_path);
|
|
431
483
|
if (output_format === "hwpx-preserve") {
|
|
432
484
|
const format = detectFormat(buffer);
|
|
@@ -458,16 +510,16 @@ server.tool(
|
|
|
458
510
|
verifyLine
|
|
459
511
|
].filter(Boolean).join(" | ");
|
|
460
512
|
const filledList = hwpxResult.filled.map((f) => ` - ${f.label}: ${mask_values ? `[${[...f.value].length}\uC790]` : f.value}`).join("\n");
|
|
461
|
-
if (
|
|
462
|
-
mkdirSync(dirname(
|
|
463
|
-
writeFileSync(
|
|
513
|
+
if (outPath) {
|
|
514
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
515
|
+
writeFileSync(outPath, Buffer.from(hwpxResult.buffer));
|
|
464
516
|
return {
|
|
465
517
|
content: [{ type: "text", text: `[${summary2}]
|
|
466
518
|
|
|
467
519
|
\uCC44\uC6CC\uC9C4 \uD544\uB4DC:
|
|
468
520
|
${filledList}
|
|
469
521
|
|
|
470
|
-
HWPX \uD30C\uC77C \uC800\uC7A5 (\uC6D0\uBCF8 \uC11C\uC2DD \uC720\uC9C0): ${
|
|
522
|
+
HWPX \uD30C\uC77C \uC800\uC7A5 (\uC6D0\uBCF8 \uC11C\uC2DD \uC720\uC9C0): ${outPath}` }]
|
|
471
523
|
};
|
|
472
524
|
}
|
|
473
525
|
return {
|
|
@@ -479,7 +531,7 @@ ${filledList}
|
|
|
479
531
|
\u26A0\uFE0F output_path\uB97C \uC9C0\uC815\uD558\uBA74 \uC6D0\uBCF8 \uC11C\uC2DD\uC774 \uC720\uC9C0\uB41C HWPX \uD30C\uC77C\uB85C \uC800\uC7A5\uB429\uB2C8\uB2E4.` }]
|
|
480
532
|
};
|
|
481
533
|
}
|
|
482
|
-
const result = await parse(buffer);
|
|
534
|
+
const result = await parse(buffer, { keepTrailingEmptyCols: true });
|
|
483
535
|
if (!result.success) {
|
|
484
536
|
return {
|
|
485
537
|
content: [{ type: "text", text: `\uD30C\uC2F1 \uC2E4\uD328: ${result.error}` }],
|
|
@@ -505,13 +557,13 @@ ${filledList}
|
|
|
505
557
|
].filter(Boolean).join(" | ");
|
|
506
558
|
if (output_format === "hwpx") {
|
|
507
559
|
const hwpxBuffer = await markdownToHwpx(markdown);
|
|
508
|
-
if (
|
|
509
|
-
mkdirSync(dirname(
|
|
510
|
-
writeFileSync(
|
|
560
|
+
if (outPath) {
|
|
561
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
562
|
+
writeFileSync(outPath, Buffer.from(hwpxBuffer));
|
|
511
563
|
return {
|
|
512
564
|
content: [{ type: "text", text: `[${summary}]
|
|
513
565
|
|
|
514
|
-
HWPX \uD30C\uC77C \uC800\uC7A5: ${
|
|
566
|
+
HWPX \uD30C\uC77C \uC800\uC7A5: ${outPath}` }]
|
|
515
567
|
};
|
|
516
568
|
}
|
|
517
569
|
return {
|
|
@@ -522,13 +574,13 @@ HWPX \uD30C\uC77C \uC800\uC7A5: ${resolve(output_path)}` }]
|
|
|
522
574
|
${previewMd}` }]
|
|
523
575
|
};
|
|
524
576
|
}
|
|
525
|
-
if (
|
|
526
|
-
mkdirSync(dirname(
|
|
527
|
-
writeFileSync(
|
|
577
|
+
if (outPath) {
|
|
578
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
579
|
+
writeFileSync(outPath, markdown, "utf-8");
|
|
528
580
|
return {
|
|
529
581
|
content: [{ type: "text", text: `[${summary}]
|
|
530
582
|
|
|
531
|
-
\uB9C8\uD06C\uB2E4\uC6B4 \uD30C\uC77C \uC800\uC7A5: ${
|
|
583
|
+
\uB9C8\uD06C\uB2E4\uC6B4 \uD30C\uC77C \uC800\uC7A5: ${outPath}
|
|
532
584
|
|
|
533
585
|
${previewMd}` }]
|
|
534
586
|
};
|
|
@@ -540,7 +592,7 @@ ${previewMd}` }]
|
|
|
540
592
|
};
|
|
541
593
|
} catch (err) {
|
|
542
594
|
return {
|
|
543
|
-
content: [{ type: "text", text: `\uC624\uB958: ${
|
|
595
|
+
content: [{ type: "text", text: `\uC624\uB958: ${describeError(err)}` }],
|
|
544
596
|
isError: true
|
|
545
597
|
};
|
|
546
598
|
}
|
|
@@ -562,6 +614,7 @@ server.tool(
|
|
|
562
614
|
},
|
|
563
615
|
async ({ file_path, image_path, anchor, occurrence, size_mm, mode, dx_mm, dy_mm, output_path }) => {
|
|
564
616
|
try {
|
|
617
|
+
const outPath = safeOutputPath(output_path, /* @__PURE__ */ new Set([".hwpx"]));
|
|
565
618
|
const { buffer } = readValidatedFile(file_path);
|
|
566
619
|
const format = detectFormat(buffer);
|
|
567
620
|
if (format !== "hwpx") {
|
|
@@ -570,13 +623,13 @@ server.tool(
|
|
|
570
623
|
isError: true
|
|
571
624
|
};
|
|
572
625
|
}
|
|
573
|
-
const imgResolved =
|
|
626
|
+
const imgResolved = safePath(image_path, IMAGE_EXTENSIONS);
|
|
574
627
|
if (statSync(imgResolved).size > 500 * 1024 * 1024) {
|
|
575
628
|
return { content: [{ type: "text", text: `\uB3C4\uC7A5 \uC774\uBBF8\uC9C0\uAC00 \uB108\uBB34 \uD07D\uB2C8\uB2E4 (${(statSync(imgResolved).size / 1024 / 1024).toFixed(0)}MB) \u2014 500MB \uC774\uD558\uC5EC\uC57C \uD569\uB2C8\uB2E4.` }], isError: true };
|
|
576
629
|
}
|
|
577
630
|
const image = new Uint8Array(readFileSync(imgResolved));
|
|
578
|
-
const ext = extname(
|
|
579
|
-
const { placeSealHwpx } = await import("./seal-
|
|
631
|
+
const ext = extname(imgResolved).slice(1).toLowerCase();
|
|
632
|
+
const { placeSealHwpx } = await import("./seal-7PTL6MXH.js");
|
|
580
633
|
const result = await placeSealHwpx(buffer, [{
|
|
581
634
|
anchor,
|
|
582
635
|
occurrence,
|
|
@@ -587,8 +640,8 @@ server.tool(
|
|
|
587
640
|
dxMm: dx_mm,
|
|
588
641
|
dyMm: dy_mm
|
|
589
642
|
}]);
|
|
590
|
-
mkdirSync(dirname(
|
|
591
|
-
writeFileSync(
|
|
643
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
644
|
+
writeFileSync(outPath, Buffer.from(result.buffer));
|
|
592
645
|
const p0 = result.placed[0];
|
|
593
646
|
const warnLines = (p0.warnings ?? []).map((w) => `
|
|
594
647
|
\u26A0\uFE0F ${w}`).join("");
|
|
@@ -596,13 +649,13 @@ server.tool(
|
|
|
596
649
|
content: [{
|
|
597
650
|
type: "text",
|
|
598
651
|
text: `\uB3C4\uC7A5 \uBC30\uCE58 \uC644\uB8CC: "${p0.anchor}" #${p0.occurrence} \u2192 ${p0.mode} (x ${p0.posXMm}mm, y ${p0.posYMm}mm, ${p0.sizeMm}mm\uAC01, ${p0.entry})
|
|
599
|
-
\uC800\uC7A5: ${
|
|
652
|
+
\uC800\uC7A5: ${outPath}${warnLines}
|
|
600
653
|
\uD45C/\uD398\uC774\uC9C0 \uBD88\uD655\uC7A5(\uAE00 \uC55E \uBD80\uC720) \u2014 \uD55C\uCEF4\uC5D0\uC11C \uC704\uCE58 \uD655\uC778 \uD6C4 dx_mm/dy_mm \uB85C \uBBF8\uC138\uC870\uC815 \uAC00\uB2A5\uD569\uB2C8\uB2E4.`
|
|
601
654
|
}]
|
|
602
655
|
};
|
|
603
656
|
} catch (err) {
|
|
604
657
|
return {
|
|
605
|
-
content: [{ type: "text", text: `\uB3C4\uC7A5 \uBC30\uCE58 \uC2E4\uD328: ${
|
|
658
|
+
content: [{ type: "text", text: `\uB3C4\uC7A5 \uBC30\uCE58 \uC2E4\uD328: ${describeError(err)}` }],
|
|
606
659
|
isError: true
|
|
607
660
|
};
|
|
608
661
|
}
|
|
@@ -618,6 +671,7 @@ server.tool(
|
|
|
618
671
|
},
|
|
619
672
|
async ({ file_path, edited_markdown, output_path }) => {
|
|
620
673
|
try {
|
|
674
|
+
const out = safeOutputPath(output_path, /* @__PURE__ */ new Set([".hwpx", ".hwp"]));
|
|
621
675
|
const { buffer } = readValidatedFile(file_path);
|
|
622
676
|
const format = detectFormat(buffer);
|
|
623
677
|
let isHwpx = format === "hwpx";
|
|
@@ -639,7 +693,6 @@ server.tool(
|
|
|
639
693
|
isError: true
|
|
640
694
|
};
|
|
641
695
|
}
|
|
642
|
-
const out = resolve(output_path);
|
|
643
696
|
mkdirSync(dirname(out), { recursive: true });
|
|
644
697
|
writeFileSync(out, Buffer.from(result.data));
|
|
645
698
|
const v = result.verification?.stats;
|
|
@@ -655,12 +708,147 @@ server.tool(
|
|
|
655
708
|
};
|
|
656
709
|
} catch (err) {
|
|
657
710
|
return {
|
|
658
|
-
content: [{ type: "text", text: `\uC624\uB958: ${
|
|
711
|
+
content: [{ type: "text", text: `\uC624\uB958: ${describeError(err)}` }],
|
|
659
712
|
isError: true
|
|
660
713
|
};
|
|
661
714
|
}
|
|
662
715
|
}
|
|
663
716
|
);
|
|
717
|
+
server.tool(
|
|
718
|
+
"render_document",
|
|
719
|
+
"HWPX \uBB38\uC11C\uB97C \uC2E4\uC81C \uC870\uD310 \uADF8\uB300\uB85C \uB80C\uB354\uD574 PNG \uC774\uBBF8\uC9C0(\uB610\uB294 SVG \uD30C\uC77C)\uB85C \uB3CC\uB824\uC90D\uB2C8\uB2E4. generate_document\xB7fill_form\xB7patch_document\xB7place_seal \uACB0\uACFC\uBB3C\uC744 \uB208\uC73C\uB85C \uD655\uC778\uD558\uB294 \uC6A9\uB3C4 \u2014 \uC0DD\uC131/\uC218\uC815 \uD6C4 \uC774 \uB3C4\uAD6C\uB85C \uB80C\uB354\uD574 \uAE68\uC9D0\xB7\uC798\uB9BC\xB7\uBC30\uCE58\uB97C \uAC80\uC99D\uD558\uACE0 \uB2E4\uC2DC \uACE0\uCE58\uB294 \uB8E8\uD504\uB97C \uAD8C\uC7A5\uD569\uB2C8\uB2E4. \uD55C\uCEF4 \uC800\uC7A5\uBCF8\uC740 \uC870\uD310 \uCE90\uC2DC\uB85C, AI \uC0DD\uC131\uBCF8(\uCE90\uC2DC \uC5C6\uC74C)\uC740 \uC21C\uC218 \uC870\uD310 \uC5D4\uC9C4(reflow)\uC73C\uB85C \uB80C\uB354\uB418\uBA70 \uD6C4\uC790\uB294 \uD55C\uCEF4 \uC2E4\uC870\uD310\uC758 \uADFC\uC0AC\uC785\uB2C8\uB2E4 (\uCC38\uACE0\uC6A9 \uBBF8\uB9AC\uBCF4\uAE30).",
|
|
720
|
+
{
|
|
721
|
+
file_path: z.string().min(1).describe("\uB80C\uB354\uD560 HWPX \uD30C\uC77C\uC758 \uC808\uB300 \uACBD\uB85C"),
|
|
722
|
+
format: z.enum(["png", "svg"]).default("png").describe("png=\uC774\uBBF8\uC9C0\uB85C \uC751\uB2F5\uC5D0 \uC9C1\uC811 \uBC18\uD658 (sharp \uD544\uC694, \uAE30\uBCF8 \uC124\uCE58\uB428) / svg=output_path\uC5D0 \uD30C\uC77C \uC800\uC7A5"),
|
|
723
|
+
output_path: z.string().min(1).optional().describe("\uACB0\uACFC \uC800\uC7A5 \uACBD\uB85C (png\uB294 \uC120\uD0DD, svg\uB294 \uD544\uC218 \u2014 \uD655\uC7A5\uC790\uB294 format\uACFC \uC77C\uCE58)"),
|
|
724
|
+
highlights: z.array(z.string().min(1)).optional().describe("\uD615\uAD11\uD39C \uD45C\uC2DC\uD560 \uAC80\uC0C9\uC5B4 \uBAA9\uB85D \u2014 \uCC44\uC6B4 \uAC12\xB7\uC218\uC815 \uBB38\uAD6C \uC704\uCE58 \uD655\uC778\uC6A9"),
|
|
725
|
+
reflow_mode: z.enum(["keep", "charAll"]).default("keep").describe("reflow \uC904\uBC14\uAFC8: keep=\uC5B4\uC808 \uB2E8\uC704, charAll=\uAE00\uC790 \uB2E8\uC704")
|
|
726
|
+
},
|
|
727
|
+
async ({ file_path, format, output_path, highlights, reflow_mode }) => {
|
|
728
|
+
try {
|
|
729
|
+
if (format === "svg" && !output_path) {
|
|
730
|
+
return { content: [{ type: "text", text: 'format: "svg"\uB294 output_path(.svg)\uAC00 \uD544\uC218\uC785\uB2C8\uB2E4 \u2014 SVG \uC6D0\uBB38\uC740 \uCEE4\uC11C \uC751\uB2F5\uC5D0 \uC9C1\uC811 \uB2F4\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.' }], isError: true };
|
|
731
|
+
}
|
|
732
|
+
const outPath = output_path ? safeOutputPath(output_path, /* @__PURE__ */ new Set([format === "png" ? ".png" : ".svg"])) : void 0;
|
|
733
|
+
const { buffer } = readValidatedFile(file_path, MAX_FILE_SIZE, /* @__PURE__ */ new Set([".hwpx"]));
|
|
734
|
+
const { renderHwpxToSvg } = await import("./render-T7S6H6AN.js");
|
|
735
|
+
const result = await renderHwpxToSvg(buffer, { highlights, reflow: true, reflowMode: reflow_mode });
|
|
736
|
+
const summary = [
|
|
737
|
+
`\uB80C\uB354 \uC644\uB8CC: ${result.pageCount}\uD398\uC774\uC9C0, ${Math.round(result.width)}x${Math.round(result.height)}pt (\uD14D\uC2A4\uD2B8 ${result.stats.texts}\xB7\uC774\uBBF8\uC9C0 ${result.stats.images}\xB7\uD45C ${result.stats.tables})`,
|
|
738
|
+
...result.warnings.map((w) => `\u26A0\uFE0F ${w}`)
|
|
739
|
+
];
|
|
740
|
+
if (format === "svg") {
|
|
741
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
742
|
+
writeFileSync(outPath, result.svg, "utf-8");
|
|
743
|
+
summary.push(`\uC800\uC7A5: ${outPath}`);
|
|
744
|
+
return { content: [{ type: "text", text: summary.join("\n") }] };
|
|
745
|
+
}
|
|
746
|
+
const { rasterizeSvg } = await import("./rasterize-WWNQLKYW.js");
|
|
747
|
+
const raster = await rasterizeSvg(result.svg, result.width, result.height);
|
|
748
|
+
if (outPath) {
|
|
749
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
750
|
+
writeFileSync(outPath, raster.png);
|
|
751
|
+
summary.push(`\uC800\uC7A5: ${outPath}`);
|
|
752
|
+
}
|
|
753
|
+
summary.push(`\uC774\uBBF8\uC9C0 ${raster.widthPx}x${raster.heightPx}px \u2014 \uC798\uB9BC\xB7\uACB9\uCE68\xB7\uBE48\uCE78\xB7\uD398\uC774\uC9C0 \uB118\uCE68\uC774 \uBCF4\uC774\uBA74 \uC6D0\uC778 \uD14D\uC2A4\uD2B8\uB97C \uC218\uC815\uD574 \uB2E4\uC2DC \uC0DD\uC131/\uD328\uCE58\uD558\uC138\uC694.`);
|
|
754
|
+
return {
|
|
755
|
+
content: [
|
|
756
|
+
{ type: "image", data: raster.png.toString("base64"), mimeType: "image/png" },
|
|
757
|
+
{ type: "text", text: summary.join("\n") }
|
|
758
|
+
]
|
|
759
|
+
};
|
|
760
|
+
} catch (err) {
|
|
761
|
+
return {
|
|
762
|
+
content: [{ type: "text", text: `\uB80C\uB354 \uC2E4\uD328: ${describeError(err)}` }],
|
|
763
|
+
isError: true
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
);
|
|
768
|
+
server.tool(
|
|
769
|
+
"redact_document",
|
|
770
|
+
"\uBB38\uC11C\uC758 \uAC1C\uC778\uC815\uBCF4(\uC8FC\uBBFC\uBC88\uD638\xB7\uC804\uD654\xB7\uC774\uBA54\uC77C\xB7\uCE74\uB4DC\xB7\uACC4\uC88C)\uB97C \uD0D0\uC9C0\uD574 \uC11C\uC2DD \uBCF4\uC874 \uB9C8\uC2A4\uD0B9\uD569\uB2C8\uB2E4. HWPX/HWP\uB294 \uC6D0\uBCF8 \uC11C\uC2DD 1\uBC14\uC774\uD2B8 \uADF8\uB300\uB85C patch, \uADF8 \uC678 \uD3EC\uB9F7\uC740 \uB9C8\uC2A4\uD0B9\uB41C \uB9C8\uD06C\uB2E4\uC6B4\uC73C\uB85C \uCD9C\uB825. \uC790\uB3D9 \uAC80\uCD9C \uBCF4\uC870 \uB3C4\uAD6C \u2014 \uACB0\uACFC \uB9AC\uD3EC\uD2B8\uB97C \uC0AC\uB78C\uC774 \uCD5C\uC885 \uD655\uC778\uD574\uC57C \uD558\uBA70 \uC774\uBBF8\uC9C0 \uC548 \uD14D\uC2A4\uD2B8\uB294 \uD0D0\uC9C0\uD558\uC9C0 \uBABB\uD569\uB2C8\uB2E4. \uB9C8\uC2A4\uD0B9 \uD6C4 render_document\uB85C \uB208\uC73C\uB85C \uD655\uC778\uD558\uB294 \uAC83\uC744 \uAD8C\uC7A5\uD569\uB2C8\uB2E4.",
|
|
771
|
+
{
|
|
772
|
+
file_path: z.string().min(1).describe("\uB300\uC0C1 \uBB38\uC11C\uC758 \uC808\uB300 \uACBD\uB85C"),
|
|
773
|
+
rules: z.array(z.enum(["rrn", "phone", "email", "card", "account", "passport", "driver"])).optional().describe("\uC801\uC6A9 \uB8F0 (\uAE30\uBCF8: rrn\xB7phone\xB7email\xB7card\xB7account \u2014 passport\xB7driver\uB294 opt-in)"),
|
|
774
|
+
mask_char: z.string().min(1).max(1).optional().describe("\uB9C8\uC2A4\uD06C \uBB38\uC790 1\uAE00\uC790 (\uAE30\uBCF8: \u25CF)"),
|
|
775
|
+
output_path: z.string().min(1).optional().describe("\uCD9C\uB825 \uACBD\uB85C (HWPX/HWP\uB294 \uAC19\uC740 \uD655\uC7A5\uC790, \uADF8 \uC678\uB294 .md) \u2014 dry_run\uC774 \uC544\uB2C8\uBA74 \uD544\uC218"),
|
|
776
|
+
dry_run: z.boolean().default(false).describe("\uD0D0\uC9C0 \uB9AC\uD3EC\uD2B8\uB9CC \uBC18\uD658, \uD30C\uC77C \uBBF8\uC0DD\uC131")
|
|
777
|
+
},
|
|
778
|
+
async ({ file_path, rules, mask_char, output_path, dry_run }) => {
|
|
779
|
+
try {
|
|
780
|
+
const { buffer } = readValidatedFile(file_path);
|
|
781
|
+
const format = detectFormat(buffer);
|
|
782
|
+
const patchable = format === "hwpx" || format === "hwp";
|
|
783
|
+
if (!dry_run && !output_path) {
|
|
784
|
+
return { content: [{ type: "text", text: "output_path\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4 (\uD0D0\uC9C0\uB9CC \uC6D0\uD558\uBA74 dry_run: true)." }], isError: true };
|
|
785
|
+
}
|
|
786
|
+
const outPath = !dry_run ? safeOutputPath(output_path, new Set(patchable ? [format === "hwp" ? ".hwp" : ".hwpx"] : [".md", ".markdown", ".txt"])) : void 0;
|
|
787
|
+
const parsed = await parse(buffer, { filePath: file_path });
|
|
788
|
+
if (!parsed.success) {
|
|
789
|
+
return { content: [{ type: "text", text: `\uD30C\uC2F1 \uC2E4\uD328: ${parsed.error}` }], isError: true };
|
|
790
|
+
}
|
|
791
|
+
const { redactMarkdown } = await import("./redact-7ILEAUTS.js");
|
|
792
|
+
const r = redactMarkdown(parsed.markdown, { rules, maskChar: mask_char });
|
|
793
|
+
const byRule = /* @__PURE__ */ new Map();
|
|
794
|
+
for (const h of r.hits) byRule.set(h.rule, (byRule.get(h.rule) ?? 0) + 1);
|
|
795
|
+
const lines = [
|
|
796
|
+
`\uD0D0\uC9C0: ${r.hits.length}\uAC74 (${[...byRule.entries()].map(([k, v]) => `${k} ${v}`).join(", ") || "\uC5C6\uC74C"})`,
|
|
797
|
+
...r.hits.map((h) => ` - [${h.rule}] ${h.masked}`)
|
|
798
|
+
];
|
|
799
|
+
if (!dry_run && r.hits.length > 0) {
|
|
800
|
+
if (patchable) {
|
|
801
|
+
const original = new Uint8Array(buffer);
|
|
802
|
+
const result = format === "hwp" ? await patchHwp(original, r.text) : await patchHwpx(original, r.text);
|
|
803
|
+
if (!result.success || !result.data) {
|
|
804
|
+
return { content: [{ type: "text", text: `\uB9C8\uC2A4\uD0B9 \uD328\uCE58 \uC2E4\uD328: ${result.error ?? "\uC54C \uC218 \uC5C6\uB294 \uC624\uB958"}` }], isError: true };
|
|
805
|
+
}
|
|
806
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
807
|
+
writeFileSync(outPath, Buffer.from(result.data));
|
|
808
|
+
lines.push(`\uC800\uC7A5: ${outPath} (\uC6D0\uBCF8 \uC11C\uC2DD \uBCF4\uC874)`);
|
|
809
|
+
if (result.skipped.length > 0) {
|
|
810
|
+
lines.push(`\u26A0\uFE0F \uBBF8\uC801\uC6A9 ${result.skipped.length}\uAC74 \u2014 \uD574\uB2F9 \uC704\uCE58\uB294 \uC6D0\uBB38\uC774 \uB0A8\uC544 \uC788\uC73C\uB2C8 \uBC18\uB4DC\uC2DC \uC218\uB3D9 \uD655\uC778:`);
|
|
811
|
+
for (const s of result.skipped) lines.push(` - ${s.reason}`);
|
|
812
|
+
}
|
|
813
|
+
lines.push("render_document\uB85C \uB9C8\uC2A4\uD0B9 \uACB0\uACFC\uB97C \uB208\uC73C\uB85C \uD655\uC778\uD558\uC138\uC694.");
|
|
814
|
+
} else {
|
|
815
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
816
|
+
writeFileSync(outPath, r.text, "utf-8");
|
|
817
|
+
lines.push(`\uC800\uC7A5: ${outPath} (${format}\uB294 \uC11C\uC2DD \uBCF4\uC874 \uBBF8\uC9C0\uC6D0 \u2014 \uB9C8\uC2A4\uD0B9\uB41C \uB9C8\uD06C\uB2E4\uC6B4)`);
|
|
818
|
+
}
|
|
819
|
+
} else if (!dry_run) {
|
|
820
|
+
lines.push("\uD0D0\uC9C0 0\uAC74 \u2014 \uCD9C\uB825 \uD30C\uC77C\uC744 \uB9CC\uB4E4\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.");
|
|
821
|
+
}
|
|
822
|
+
lines.push("\uC8FC\uC758: \uC790\uB3D9 \uAC80\uCD9C\uC740 \uBCF4\uC870 \uC218\uB2E8\uC785\uB2C8\uB2E4. \uC774\uBBF8\uC9C0 \uC18D \uD14D\uC2A4\uD2B8\xB7\uD45C\uAE30 \uBCC0\uD615\uC740 \uB193\uCE60 \uC218 \uC788\uC73C\uB2C8 \uCD5C\uC885 \uACF5\uAC1C \uC804 \uC0AC\uB78C \uAC80\uD1A0\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.");
|
|
823
|
+
return { content: [{ type: "text", text: capResponseText(lines.join("\n")) }] };
|
|
824
|
+
} catch (err) {
|
|
825
|
+
return { content: [{ type: "text", text: `\uB9C8\uC2A4\uD0B9 \uC2E4\uD328: ${describeError(err)}` }], isError: true };
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
);
|
|
829
|
+
server.tool(
|
|
830
|
+
"parse_chunks",
|
|
831
|
+
"\uBB38\uC11C\uB97C RAG\uC6A9 \uAD6C\uC870 \uCCAD\uD06C JSON\uC73C\uB85C \uD30C\uC2F1\uD569\uB2C8\uB2E4. \uD5E4\uB529\xB7\uAC1C\uC870\uC2DD \uC704\uACC4(\u25A1\u25CB- / 1.\xB7\uAC00.\xB71))\uAC00 breadcrumb \uACBD\uB85C\uB85C \uBCF4\uC874\uB418\uACE0 \uD45C\uB294 \uB3C5\uB9BD \uCCAD\uD06C\uB85C \uB098\uC635\uB2C8\uB2E4 \u2014 \uC784\uBCA0\uB529\xB7\uC778\uB371\uC2F1 \uC804\uCC98\uB9AC\uC6A9. \uC790\uB974\uAE30(\uD1A0\uD070 \uC0C1\uD55C\xB7\uC624\uBC84\uB7A9)\uB294 \uC18C\uBE44\uC790 \uBAAB\uC785\uB2C8\uB2E4.",
|
|
832
|
+
{
|
|
833
|
+
file_path: z.string().min(1).describe("\uB300\uC0C1 \uBB38\uC11C\uC758 \uC808\uB300 \uACBD\uB85C (HWP/HWPX/PDF/XLSX/DOCX)"),
|
|
834
|
+
granularity: z.enum(["section", "block"]).default("section").describe("section=\uAC19\uC740 breadcrumb \uC544\uB798 \uC5F0\uC18D \uD14D\uC2A4\uD2B8 \uBCD1\uD569(\uAE30\uBCF8), block=IRBlock 1\uAC1C=\uCCAD\uD06C 1\uAC1C"),
|
|
835
|
+
include_table_cells: z.boolean().default(false).describe("\uD45C \uCCAD\uD06C\uC5D0 \uC140 \uD14D\uC2A4\uD2B8 2\uCC28\uC6D0 \uBC30\uC5F4 \uD3EC\uD568 \uC5EC\uBD80")
|
|
836
|
+
},
|
|
837
|
+
async ({ file_path, granularity, include_table_cells }) => {
|
|
838
|
+
try {
|
|
839
|
+
const { buffer } = readValidatedFile(file_path);
|
|
840
|
+
const parsed = await parse(buffer, { filePath: file_path });
|
|
841
|
+
if (!parsed.success) {
|
|
842
|
+
return { content: [{ type: "text", text: `\uD30C\uC2F1 \uC2E4\uD328: ${parsed.error}` }], isError: true };
|
|
843
|
+
}
|
|
844
|
+
const { blocksToChunks } = await import("./chunks-WVMGF7JL.js");
|
|
845
|
+
const chunks = blocksToChunks(parsed.blocks, { granularity, includeTableCells: include_table_cells });
|
|
846
|
+
return { content: [{ type: "text", text: capResponseText(JSON.stringify(chunks, null, 2)) }] };
|
|
847
|
+
} catch (err) {
|
|
848
|
+
return { content: [{ type: "text", text: `\uCCAD\uD06C \uD30C\uC2F1 \uC2E4\uD328: ${describeError(err)}` }], isError: true };
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
);
|
|
664
852
|
server.tool(
|
|
665
853
|
"extract_profile",
|
|
666
854
|
'\uCC38\uC870 HWPX \uBB38\uC11C\uC5D0\uC11C \uD45C \uC11C\uC2DD \uD504\uB85C\uD544(\uD14C\uB450\uB9AC\xB7\uC74C\uC601\xB7\uC5F4 \uB108\uBE44\xB7\uC140 \uAE00\uAF34)\uC744 JSON\uC73C\uB85C \uCD94\uCD9C\uD569\uB2C8\uB2E4. \uCD94\uCD9C\uD55C \uD504\uB85C\uD544\uC744 generate_document\uC758 profile_path\uB85C \uB118\uAE30\uBA74 \uC6D0\uBCF8 \uBB38\uC11C \uC5C6\uC774 \uAC19\uC740 \uD45C \uC11C\uC2DD\uC744 \uC7AC\uD604\uD569\uB2C8\uB2E4 \u2014 "\uC774 \uBB38\uC11C \uD45C \uC11C\uC2DD \uADF8\uB300\uB85C \uB9CC\uB4E4\uC5B4\uC918" \uC6CC\uD06C\uD50C\uB85C\uC758 1\uB2E8\uACC4.',
|
|
@@ -670,10 +858,10 @@ server.tool(
|
|
|
670
858
|
},
|
|
671
859
|
async ({ hwpx_path, output_path }) => {
|
|
672
860
|
try {
|
|
861
|
+
const out = safeOutputPath(output_path, PROFILE_EXTENSIONS);
|
|
673
862
|
const { buffer } = readValidatedFile(hwpx_path);
|
|
674
|
-
const { hwpxToProfile } = await import("./-
|
|
863
|
+
const { hwpxToProfile } = await import("./-AS4IABL2.js");
|
|
675
864
|
const profile = await hwpxToProfile(buffer);
|
|
676
|
-
const out = resolve(output_path);
|
|
677
865
|
mkdirSync(dirname(out), { recursive: true });
|
|
678
866
|
writeFileSync(out, JSON.stringify(profile, null, 2));
|
|
679
867
|
return {
|
|
@@ -682,7 +870,7 @@ server.tool(
|
|
|
682
870
|
};
|
|
683
871
|
} catch (err) {
|
|
684
872
|
return {
|
|
685
|
-
content: [{ type: "text", text: `\uC624\uB958: ${
|
|
873
|
+
content: [{ type: "text", text: `\uC624\uB958: ${describeError(err)}` }],
|
|
686
874
|
isError: true
|
|
687
875
|
};
|
|
688
876
|
}
|
|
@@ -755,11 +943,11 @@ server.tool(
|
|
|
755
943
|
}
|
|
756
944
|
let profile;
|
|
757
945
|
if (profile_path) {
|
|
758
|
-
const { parseFormatProfileJson } = await import("./profile-io-
|
|
759
|
-
profile = parseFormatProfileJson(readFileSync(
|
|
946
|
+
const { parseFormatProfileJson } = await import("./profile-io-PLDQFPJA.js");
|
|
947
|
+
profile = parseFormatProfileJson(readFileSync(safePath(profile_path, PROFILE_EXTENSIONS), "utf-8"));
|
|
760
948
|
}
|
|
949
|
+
const out = safeOutputPath(output_path, /* @__PURE__ */ new Set([".hwpx"]));
|
|
761
950
|
const buf = await markdownToHwpx(markdown, gongmun || profile ? { ...gongmun ? { gongmun } : {}, ...profile ? { profile } : {} } : void 0);
|
|
762
|
-
const out = resolve(output_path);
|
|
763
951
|
mkdirSync(dirname(out), { recursive: true });
|
|
764
952
|
writeFileSync(out, Buffer.from(buf));
|
|
765
953
|
const mode = gongmun ? `\uACF5\uBB38\uC11C:${gongmun.preset}` : "\uBC94\uC6A9";
|
|
@@ -775,18 +963,38 @@ server.tool(
|
|
|
775
963
|
};
|
|
776
964
|
} catch (err) {
|
|
777
965
|
return {
|
|
778
|
-
content: [{ type: "text", text: `\uC624\uB958: ${
|
|
966
|
+
content: [{ type: "text", text: `\uC624\uB958: ${describeError(err)}` }],
|
|
779
967
|
isError: true
|
|
780
968
|
};
|
|
781
969
|
}
|
|
782
970
|
}
|
|
783
971
|
);
|
|
784
|
-
|
|
972
|
+
var serverStarted = false;
|
|
973
|
+
async function startMcpServer() {
|
|
974
|
+
if (serverStarted) return;
|
|
975
|
+
serverStarted = true;
|
|
785
976
|
const transport = new StdioServerTransport();
|
|
786
977
|
await server.connect(transport);
|
|
787
978
|
}
|
|
788
|
-
|
|
979
|
+
var autoStart = true;
|
|
980
|
+
try {
|
|
981
|
+
const entry = process.argv[1];
|
|
982
|
+
if (entry && pathToFileURL(realpathSync(entry)).href !== import.meta.url) autoStart = false;
|
|
983
|
+
} catch {
|
|
984
|
+
}
|
|
985
|
+
if (autoStart) startMcpServer().catch((err) => {
|
|
789
986
|
console.error(err);
|
|
790
987
|
process.exit(1);
|
|
791
988
|
});
|
|
989
|
+
export {
|
|
990
|
+
ALLOWED_EXTENSIONS,
|
|
991
|
+
IMAGE_EXTENSIONS,
|
|
992
|
+
PROFILE_EXTENSIONS,
|
|
993
|
+
buildFillInputs,
|
|
994
|
+
capResponseText,
|
|
995
|
+
describeError,
|
|
996
|
+
safeOutputPath,
|
|
997
|
+
safePath,
|
|
998
|
+
startMcpServer
|
|
999
|
+
};
|
|
792
1000
|
//# sourceMappingURL=mcp.js.map
|