kordoc 4.0.8 → 4.2.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/README.md +50 -16
- package/dist/{-LE4RLXVA.js → -SXQIZHYA.js} +24 -10
- package/dist/{parser-TCTCSBYZ.js → chunk-26AJJCFF.js} +1427 -2027
- package/dist/chunk-26AJJCFF.js.map +1 -0
- package/dist/{parser-KMMUS73Q.js → chunk-4JPPLIIV.js} +1425 -2025
- package/dist/chunk-4JPPLIIV.js.map +1 -0
- package/dist/chunk-4VNLZ2GZ.js +13 -0
- package/dist/chunk-4VNLZ2GZ.js.map +1 -0
- package/dist/{chunk-2DZQF6YJ.js → chunk-6SHO3BNV.js} +24 -15
- package/dist/chunk-6SHO3BNV.js.map +1 -0
- package/dist/chunk-7FCNOKOR.js +144 -0
- package/dist/chunk-7FCNOKOR.js.map +1 -0
- package/dist/{chunk-6XAAYAWL.cjs → chunk-CMN3SYZ3.js} +62 -304
- package/dist/chunk-CMN3SYZ3.js.map +1 -0
- package/dist/chunk-DZIXKL7E.js +145 -0
- package/dist/chunk-DZIXKL7E.js.map +1 -0
- package/dist/chunk-ELOV2GIJ.js +82 -0
- package/dist/chunk-ELOV2GIJ.js.map +1 -0
- package/dist/chunk-F2HYH62H.cjs +130 -0
- package/dist/chunk-F2HYH62H.cjs.map +1 -0
- package/dist/{chunk-HMUEU7D7.js → chunk-FSXLSHCW.js} +3 -3
- package/dist/{chunk-HMUEU7D7.js.map → chunk-FSXLSHCW.js.map} +1 -1
- package/dist/chunk-GEPINOL6.js +83 -0
- package/dist/chunk-GEPINOL6.js.map +1 -0
- package/dist/chunk-H7OWEYH2.cjs +243 -0
- package/dist/chunk-H7OWEYH2.cjs.map +1 -0
- package/dist/{chunk-7S3M4N4E.js → chunk-IGGRLWT5.js} +683 -226
- package/dist/chunk-IGGRLWT5.js.map +1 -0
- package/dist/chunk-J2RZ444H.js +243 -0
- package/dist/chunk-J2RZ444H.js.map +1 -0
- package/dist/chunk-JP5YH3Z4.js +130 -0
- package/dist/chunk-JP5YH3Z4.js.map +1 -0
- package/dist/{parser-ITMU2WN5.cjs → chunk-LHROM2BO.cjs} +1409 -2012
- package/dist/chunk-LHROM2BO.cjs.map +1 -0
- package/dist/chunk-NNDVFNMJ.js +246 -0
- package/dist/chunk-NNDVFNMJ.js.map +1 -0
- package/dist/{chunk-RROH5WHO.js → chunk-PLIY23LY.js} +2 -2
- package/dist/{chunk-BNU5QGIZ.js → chunk-V6U6YS5B.js} +12 -4
- package/dist/chunk-V6U6YS5B.js.map +1 -0
- package/dist/{chunk-UEIYETCQ.js → chunk-WF2E5P2G.js} +40 -35
- package/dist/chunk-WF2E5P2G.js.map +1 -0
- package/dist/{chunk-D35VBACN.js → chunk-WQLHPOMJ.js} +7 -4
- package/dist/chunk-WQLHPOMJ.js.map +1 -0
- package/dist/{chunk-OQPILS7B.js → chunk-XTCT6KQ5.cjs} +79 -183
- package/dist/chunk-XTCT6KQ5.cjs.map +1 -0
- package/dist/{chunk-MEPHGCPQ.js → chunk-YOO6ET6M.js} +7 -3
- package/dist/chunk-YOO6ET6M.js.map +1 -0
- package/dist/chunks-ZQEFAZNC.js +10 -0
- package/dist/cli.js +228 -36
- package/dist/cli.js.map +1 -1
- package/dist/{detect-RI2MQ33K.js → detect-YEZX2XCF.js} +2 -2
- package/dist/{formula-RXVSQPXI.js → formula-KSNAEBZ2.js} +23 -232
- package/dist/formula-KSNAEBZ2.js.map +1 -0
- package/dist/{formula-5NKVS2LR.cjs → formula-SB3NHDUM.cjs} +30 -240
- package/dist/formula-SB3NHDUM.cjs.map +1 -0
- package/dist/{formula-JCNF43NE.js → formula-SXC6LRRC.js} +23 -233
- package/dist/formula-SXC6LRRC.js.map +1 -0
- package/dist/index.cjs +1280 -589
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +112 -4
- package/dist/index.d.ts +112 -4
- package/dist/index.js +929 -238
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +278 -68
- package/dist/mcp.js.map +1 -1
- package/dist/models-KA4GLQK5.js +25 -0
- package/dist/parser-ND2YGQZR.js +800 -0
- package/dist/parser-ND2YGQZR.js.map +1 -0
- package/dist/parser-RBZHA6SY.js +804 -0
- package/dist/parser-RBZHA6SY.js.map +1 -0
- package/dist/parser-WDZOMDG4.cjs +803 -0
- package/dist/parser-WDZOMDG4.cjs.map +1 -0
- package/dist/pdf-ocr-2Z7VZIFI.cjs +439 -0
- package/dist/pdf-ocr-2Z7VZIFI.cjs.map +1 -0
- package/dist/pdf-ocr-FJFXFADQ.js +438 -0
- package/dist/pdf-ocr-FJFXFADQ.js.map +1 -0
- package/dist/pdf-ocr-VYE4DHD4.js +386 -0
- package/dist/pdf-ocr-VYE4DHD4.js.map +1 -0
- package/dist/{profile-io-SLN4P76T.js → profile-io-TWHDIVPL.js} +3 -3
- package/dist/rasterize-W2NEZUSW.js +40 -0
- package/dist/rasterize-W2NEZUSW.js.map +1 -0
- package/dist/redact-7ILEAUTS.js +12 -0
- package/dist/redact-7ILEAUTS.js.map +1 -0
- package/dist/render-4MG5QUDG.js +10 -0
- package/dist/render-4MG5QUDG.js.map +1 -0
- package/dist/seal-D2QNXJVO.js +10 -0
- package/dist/seal-D2QNXJVO.js.map +1 -0
- package/dist/{setup-57FB3LSP.js → setup-Q2PRE7UA.js} +5 -3
- package/dist/setup-Q2PRE7UA.js.map +1 -0
- package/dist/{watch-OHQWSVPE.js → watch-VWXJZT2R.js} +78 -23
- package/dist/watch-VWXJZT2R.js.map +1 -0
- package/package.json +2 -1
- package/dist/chunk-2DZQF6YJ.js.map +0 -1
- package/dist/chunk-6XAAYAWL.cjs.map +0 -1
- package/dist/chunk-7S3M4N4E.js.map +0 -1
- package/dist/chunk-BNU5QGIZ.js.map +0 -1
- package/dist/chunk-D35VBACN.js.map +0 -1
- package/dist/chunk-MEPHGCPQ.js.map +0 -1
- package/dist/chunk-OQPILS7B.js.map +0 -1
- package/dist/chunk-UEIYETCQ.js.map +0 -1
- package/dist/formula-5NKVS2LR.cjs.map +0 -1
- package/dist/formula-JCNF43NE.js.map +0 -1
- package/dist/formula-RXVSQPXI.js.map +0 -1
- package/dist/parser-ITMU2WN5.cjs.map +0 -1
- package/dist/parser-KMMUS73Q.js.map +0 -1
- package/dist/parser-TCTCSBYZ.js.map +0 -1
- package/dist/provider-4ZJKV3DC.js +0 -37
- package/dist/provider-4ZJKV3DC.js.map +0 -1
- package/dist/provider-AKROB7WQ.js +0 -39
- package/dist/provider-AKROB7WQ.js.map +0 -1
- package/dist/provider-G4C2V2PD.cjs +0 -39
- package/dist/provider-G4C2V2PD.cjs.map +0 -1
- package/dist/render-25BT623I.js +0 -10
- package/dist/seal-R4TETA4C.js +0 -10
- package/dist/setup-57FB3LSP.js.map +0 -1
- package/dist/watch-OHQWSVPE.js.map +0 -1
- /package/dist/{-LE4RLXVA.js.map → -SXQIZHYA.js.map} +0 -0
- /package/dist/{chunk-RROH5WHO.js.map → chunk-PLIY23LY.js.map} +0 -0
- /package/dist/{detect-RI2MQ33K.js.map → chunks-ZQEFAZNC.js.map} +0 -0
- /package/dist/{profile-io-SLN4P76T.js.map → detect-YEZX2XCF.js.map} +0 -0
- /package/dist/{render-25BT623I.js.map → models-KA4GLQK5.js.map} +0 -0
- /package/dist/{seal-R4TETA4C.js.map → profile-io-TWHDIVPL.js.map} +0 -0
package/dist/mcp.js
CHANGED
|
@@ -31,34 +31,42 @@ import {
|
|
|
31
31
|
patchHwp,
|
|
32
32
|
patchHwpx,
|
|
33
33
|
unknownFontWarnings
|
|
34
|
-
} from "./chunk-
|
|
35
|
-
import
|
|
36
|
-
|
|
37
|
-
} from "./chunk-UEIYETCQ.js";
|
|
34
|
+
} from "./chunk-IGGRLWT5.js";
|
|
35
|
+
import "./chunk-7FCNOKOR.js";
|
|
36
|
+
import "./chunk-4VNLZ2GZ.js";
|
|
38
37
|
import {
|
|
39
38
|
detectFormat,
|
|
40
39
|
detectZipFormat
|
|
41
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-YOO6ET6M.js";
|
|
42
41
|
import "./chunk-MOL7MDBG.js";
|
|
43
|
-
import "./chunk-
|
|
44
|
-
import "./chunk-
|
|
45
|
-
import "./chunk-
|
|
42
|
+
import "./chunk-WQLHPOMJ.js";
|
|
43
|
+
import "./chunk-DZIXKL7E.js";
|
|
44
|
+
import "./chunk-ELOV2GIJ.js";
|
|
45
|
+
import {
|
|
46
|
+
blocksToMarkdown
|
|
47
|
+
} from "./chunk-CMN3SYZ3.js";
|
|
48
|
+
import "./chunk-6SHO3BNV.js";
|
|
49
|
+
import "./chunk-V6U6YS5B.js";
|
|
46
50
|
import {
|
|
47
51
|
KordocError,
|
|
48
52
|
VERSION,
|
|
53
|
+
classifyError,
|
|
49
54
|
sanitizeError,
|
|
50
55
|
toArrayBuffer
|
|
51
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-FSXLSHCW.js";
|
|
52
57
|
|
|
53
58
|
// src/mcp.ts
|
|
54
59
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
55
60
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
56
61
|
import { z } from "zod";
|
|
57
|
-
import { readFileSync, writeFileSync, realpathSync, openSync, readSync, closeSync, statSync, mkdirSync } from "fs";
|
|
58
|
-
import {
|
|
59
|
-
|
|
62
|
+
import { readFileSync, writeFileSync, realpathSync, openSync, readSync, closeSync, statSync, mkdirSync, existsSync } from "fs";
|
|
63
|
+
import { pathToFileURL } from "url";
|
|
64
|
+
import { resolve, isAbsolute, extname, dirname, basename } from "path";
|
|
65
|
+
var ALLOWED_EXTENSIONS = /* @__PURE__ */ new Set([".hwp", ".hwpx", ".hml", ".pdf", ".xls", ".xlsx", ".docx"]);
|
|
66
|
+
var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".bmp"]);
|
|
67
|
+
var PROFILE_EXTENSIONS = /* @__PURE__ */ new Set([".json"]);
|
|
60
68
|
var MAX_FILE_SIZE = 500 * 1024 * 1024;
|
|
61
|
-
function safePath(filePath) {
|
|
69
|
+
function safePath(filePath, allowedExts = ALLOWED_EXTENSIONS) {
|
|
62
70
|
if (!filePath) throw new KordocError("\uD30C\uC77C \uACBD\uB85C\uAC00 \uBE44\uC5B4\uC788\uC2B5\uB2C8\uB2E4");
|
|
63
71
|
const resolved = resolve(filePath);
|
|
64
72
|
let real;
|
|
@@ -71,12 +79,53 @@ function safePath(filePath) {
|
|
|
71
79
|
}
|
|
72
80
|
if (!isAbsolute(real)) throw new KordocError("\uC808\uB300 \uACBD\uB85C\uB9CC \uD5C8\uC6A9\uB429\uB2C8\uB2E4");
|
|
73
81
|
const ext = extname(real).toLowerCase();
|
|
74
|
-
if (!
|
|
82
|
+
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
83
|
return real;
|
|
76
84
|
}
|
|
85
|
+
function safeOutputPath(outputPath, allowedExts) {
|
|
86
|
+
if (!outputPath) throw new KordocError("\uCD9C\uB825 \uACBD\uB85C\uAC00 \uBE44\uC5B4\uC788\uC2B5\uB2C8\uB2E4");
|
|
87
|
+
const resolved = resolve(outputPath);
|
|
88
|
+
const ext = extname(resolved).toLowerCase();
|
|
89
|
+
if (!allowedExts.has(ext)) {
|
|
90
|
+
throw new KordocError(`\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uCD9C\uB825 \uD655\uC7A5\uC790\uC785\uB2C8\uB2E4: ${ext || "(\uC5C6\uC74C)"} (\uD5C8\uC6A9: ${[...allowedExts].join(", ")})`);
|
|
91
|
+
}
|
|
92
|
+
const parent = dirname(resolved);
|
|
93
|
+
if (existsSync(parent)) {
|
|
94
|
+
try {
|
|
95
|
+
return resolve(realpathSync(parent), basename(resolved));
|
|
96
|
+
} catch (err) {
|
|
97
|
+
throw new KordocError(`\uCD9C\uB825 \uACBD\uB85C \uCC98\uB9AC \uC624\uB958 [${err?.code ?? "UNKNOWN"}]: ${parent}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return resolved;
|
|
101
|
+
}
|
|
102
|
+
function describeError(err) {
|
|
103
|
+
if (err instanceof KordocError) return err.message;
|
|
104
|
+
const code = err?.code;
|
|
105
|
+
if (typeof code === "string" && /^E[A-Z]+$/.test(code)) {
|
|
106
|
+
const hints = {
|
|
107
|
+
ENOENT: "\uD30C\uC77C \uB610\uB294 \uB514\uB809\uD1A0\uB9AC\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4",
|
|
108
|
+
EACCES: "\uC811\uADFC \uAD8C\uD55C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4",
|
|
109
|
+
EPERM: "\uC791\uC5C5 \uAD8C\uD55C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4",
|
|
110
|
+
EISDIR: "\uD30C\uC77C\uC774 \uC544\uB2C8\uB77C \uB514\uB809\uD1A0\uB9AC\uC785\uB2C8\uB2E4",
|
|
111
|
+
ENOTDIR: "\uACBD\uB85C \uC911\uAC04\uC774 \uB514\uB809\uD1A0\uB9AC\uAC00 \uC544\uB2D9\uB2C8\uB2E4",
|
|
112
|
+
ENOSPC: "\uB514\uC2A4\uD06C \uACF5\uAC04\uC774 \uBD80\uC871\uD569\uB2C8\uB2E4"
|
|
113
|
+
};
|
|
114
|
+
return `\uD30C\uC77C \uC2DC\uC2A4\uD15C \uC624\uB958 [${code}]: ${hints[code] ?? "\uACBD\uB85C\uC640 \uAD8C\uD55C\uC744 \uD655\uC778\uD558\uC138\uC694"}`;
|
|
115
|
+
}
|
|
116
|
+
const cls = classifyError(err);
|
|
117
|
+
return cls === "PARSE_ERROR" ? sanitizeError(err) : `\uBB38\uC11C \uCC98\uB9AC \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4 (${cls})`;
|
|
118
|
+
}
|
|
119
|
+
var MAX_RESPONSE_CHARS = 2e5;
|
|
120
|
+
function capResponseText(text, maxChars = MAX_RESPONSE_CHARS) {
|
|
121
|
+
if (text.length <= maxChars) return text;
|
|
122
|
+
return text.slice(0, maxChars) + `
|
|
123
|
+
|
|
124
|
+
\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]`;
|
|
125
|
+
}
|
|
77
126
|
var MAX_METADATA_FILE_SIZE = 50 * 1024 * 1024;
|
|
78
|
-
function readValidatedFile(filePath, maxSize = MAX_FILE_SIZE) {
|
|
79
|
-
const resolved = safePath(filePath);
|
|
127
|
+
function readValidatedFile(filePath, maxSize = MAX_FILE_SIZE, allowedExts = ALLOWED_EXTENSIONS) {
|
|
128
|
+
const resolved = safePath(filePath, allowedExts);
|
|
80
129
|
let fileSize;
|
|
81
130
|
try {
|
|
82
131
|
fileSize = statSync(resolved).size;
|
|
@@ -97,9 +146,9 @@ function readValidatedFile(filePath, maxSize = MAX_FILE_SIZE) {
|
|
|
97
146
|
function detectFormatFromHeader(resolved) {
|
|
98
147
|
const fd = openSync(resolved, "r");
|
|
99
148
|
try {
|
|
100
|
-
const headerBuf = Buffer.alloc(
|
|
101
|
-
readSync(fd, headerBuf, 0,
|
|
102
|
-
return detectFormat(toArrayBuffer(headerBuf));
|
|
149
|
+
const headerBuf = Buffer.alloc(512);
|
|
150
|
+
const bytesRead = readSync(fd, headerBuf, 0, 512, 0);
|
|
151
|
+
return detectFormat(toArrayBuffer(headerBuf.subarray(0, bytesRead)));
|
|
103
152
|
} finally {
|
|
104
153
|
closeSync(fd);
|
|
105
154
|
}
|
|
@@ -112,11 +161,12 @@ server.tool(
|
|
|
112
161
|
"parse_document",
|
|
113
162
|
"\uD55C\uAD6D \uBB38\uC11C \uD30C\uC77C(HWP, HWPX, PDF, XLSX, DOCX)\uC744 \uB9C8\uD06C\uB2E4\uC6B4\uC73C\uB85C \uBCC0\uD658\uD569\uB2C8\uB2E4. \uD30C\uC77C \uACBD\uB85C\uB97C \uC785\uB825\uD558\uBA74 \uD3EC\uB9F7\uC744 \uC790\uB3D9 \uAC10\uC9C0\uD558\uC5EC \uD14D\uC2A4\uD2B8\uB97C \uCD94\uCD9C\uD569\uB2C8\uB2E4.",
|
|
114
163
|
{
|
|
115
|
-
file_path: z.string().min(1).describe("\uD30C\uC2F1\uD560 \uBB38\uC11C \uD30C\uC77C\uC758 \uC808\uB300 \uACBD\uB85C (HWP, HWPX, PDF, XLSX, DOCX)")
|
|
164
|
+
file_path: z.string().min(1).describe("\uD30C\uC2F1\uD560 \uBB38\uC11C \uD30C\uC77C\uC758 \uC808\uB300 \uACBD\uB85C (HWP, HWPX, PDF, XLSX, DOCX)"),
|
|
165
|
+
ocr: z.boolean().optional().describe("\uC2A4\uCE94/\uC774\uBBF8\uC9C0 PDF \uD14D\uC2A4\uD2B8 OCR (\uB0B4\uC7A5 PP-OCRv5 korean, \uCCAB \uC0AC\uC6A9 \uC2DC ~18MB \uC790\uB3D9 \uB2E4\uC6B4\uB85C\uB4DC). \uD14D\uC2A4\uD2B8\uCE35\uC774 \uC5C6\uAC70\uB098 \uAE68\uC9C4 \uD398\uC774\uC9C0\uB9CC \uC778\uC2DD\uD558\uACE0 \uC815\uC0C1 \uD398\uC774\uC9C0\uB294 \uADF8\uB300\uB85C \uB461\uB2C8\uB2E4. parse \uACB0\uACFC\uC5D0 NEEDS_OCR \uACBD\uACE0\uAC00 \uC788\uC73C\uBA74 \uC774 \uC635\uC158\uC73C\uB85C \uC7AC\uC2DC\uB3C4\uD558\uC138\uC694")
|
|
116
166
|
},
|
|
117
|
-
async ({ file_path }) => {
|
|
167
|
+
async ({ file_path, ocr }) => {
|
|
118
168
|
try {
|
|
119
|
-
const { buffer } = readValidatedFile(file_path);
|
|
169
|
+
const { buffer, resolved } = readValidatedFile(file_path);
|
|
120
170
|
const format = detectFormat(buffer);
|
|
121
171
|
if (format === "unknown") {
|
|
122
172
|
return {
|
|
@@ -124,7 +174,7 @@ server.tool(
|
|
|
124
174
|
isError: true
|
|
125
175
|
};
|
|
126
176
|
}
|
|
127
|
-
const result = await parse(buffer);
|
|
177
|
+
const result = await parse(buffer, { filePath: resolved, ...ocr ? { ocr: true } : {} });
|
|
128
178
|
if (!result.success) {
|
|
129
179
|
return {
|
|
130
180
|
content: [{ type: "text", text: `\uD30C\uC2F1 \uC2E4\uD328 (${result.fileType}): ${result.error}` }],
|
|
@@ -137,7 +187,7 @@ server.tool(
|
|
|
137
187
|
result.pageCount ? `\uD398\uC774\uC9C0: ${result.pageCount}` : null,
|
|
138
188
|
result.metadata?.title ? `\uC81C\uBAA9: ${result.metadata.title}` : null,
|
|
139
189
|
result.metadata?.author ? `\uC791\uC131\uC790: ${result.metadata.author}` : null,
|
|
140
|
-
result.isImageBased ? "\uC774\uBBF8\uC9C0 \uAE30\uBC18 PDF (\uD14D\uC2A4\uD2B8 \uCD94\uCD9C \uBD88\uAC00)" : null
|
|
190
|
+
result.isImageBased ? result.warnings?.some((w) => w.code === "OCR_APPLIED") ? "\uC774\uBBF8\uC9C0 \uAE30\uBC18 PDF (OCR \uC801\uC6A9)" : "\uC774\uBBF8\uC9C0 \uAE30\uBC18 PDF (\uD14D\uC2A4\uD2B8 \uCD94\uCD9C \uBD88\uAC00 \u2014 ocr: true \uB85C \uC7AC\uC2DC\uB3C4 \uAC00\uB2A5)" : null
|
|
141
191
|
].filter(Boolean).join(" | ");
|
|
142
192
|
const parts = [`[${meta}]`];
|
|
143
193
|
if (result.outline && result.outline.length > 0) {
|
|
@@ -156,11 +206,11 @@ ${warnText}`);
|
|
|
156
206
|
|
|
157
207
|
${markdown}`);
|
|
158
208
|
return {
|
|
159
|
-
content: [{ type: "text", text: parts.join("") }]
|
|
209
|
+
content: [{ type: "text", text: capResponseText(parts.join("")) }]
|
|
160
210
|
};
|
|
161
211
|
} catch (err) {
|
|
162
212
|
return {
|
|
163
|
-
content: [{ type: "text", text: `\uC624\uB958: ${
|
|
213
|
+
content: [{ type: "text", text: `\uC624\uB958: ${describeError(err)}` }],
|
|
164
214
|
isError: true
|
|
165
215
|
};
|
|
166
216
|
}
|
|
@@ -177,7 +227,7 @@ server.tool(
|
|
|
177
227
|
const resolved = safePath(file_path);
|
|
178
228
|
let format = detectFormatFromHeader(resolved);
|
|
179
229
|
if (format === "hwpx") {
|
|
180
|
-
const { buffer } = readValidatedFile(file_path
|
|
230
|
+
const { buffer } = readValidatedFile(file_path);
|
|
181
231
|
format = await detectZipFormat(buffer);
|
|
182
232
|
}
|
|
183
233
|
return {
|
|
@@ -185,7 +235,7 @@ server.tool(
|
|
|
185
235
|
};
|
|
186
236
|
} catch (err) {
|
|
187
237
|
return {
|
|
188
|
-
content: [{ type: "text", text: `\uC624\uB958: ${
|
|
238
|
+
content: [{ type: "text", text: `\uC624\uB958: ${describeError(err)}` }],
|
|
189
239
|
isError: true
|
|
190
240
|
};
|
|
191
241
|
}
|
|
@@ -211,7 +261,7 @@ server.tool(
|
|
|
211
261
|
let metadata;
|
|
212
262
|
let effectiveFormat = format;
|
|
213
263
|
if (format === "hwpx") {
|
|
214
|
-
const { detectZipFormat: detectZipFormat2 } = await import("./detect-
|
|
264
|
+
const { detectZipFormat: detectZipFormat2 } = await import("./detect-YEZX2XCF.js");
|
|
215
265
|
const zipFormat = await detectZipFormat2(buffer);
|
|
216
266
|
if (zipFormat === "xlsx" || zipFormat === "docx") effectiveFormat = zipFormat;
|
|
217
267
|
}
|
|
@@ -224,12 +274,14 @@ server.tool(
|
|
|
224
274
|
break;
|
|
225
275
|
case "pdf":
|
|
226
276
|
try {
|
|
227
|
-
const { extractPdfMetadataOnly } = await import("./parser-
|
|
277
|
+
const { extractPdfMetadataOnly } = await import("./parser-RBZHA6SY.js");
|
|
228
278
|
metadata = await extractPdfMetadataOnly(buffer);
|
|
229
279
|
} catch {
|
|
230
280
|
metadata = void 0;
|
|
231
281
|
}
|
|
232
282
|
break;
|
|
283
|
+
case "hwp3":
|
|
284
|
+
case "hwpml":
|
|
233
285
|
case "xlsx":
|
|
234
286
|
case "docx": {
|
|
235
287
|
const result = await parse(buffer);
|
|
@@ -242,7 +294,7 @@ server.tool(
|
|
|
242
294
|
};
|
|
243
295
|
} catch (err) {
|
|
244
296
|
return {
|
|
245
|
-
content: [{ type: "text", text: `\uC624\uB958: ${
|
|
297
|
+
content: [{ type: "text", text: `\uC624\uB958: ${describeError(err)}` }],
|
|
246
298
|
isError: true
|
|
247
299
|
};
|
|
248
300
|
}
|
|
@@ -284,7 +336,7 @@ ${result.markdown}` }]
|
|
|
284
336
|
};
|
|
285
337
|
} catch (err) {
|
|
286
338
|
return {
|
|
287
|
-
content: [{ type: "text", text: `\uC624\uB958: ${
|
|
339
|
+
content: [{ type: "text", text: `\uC624\uB958: ${describeError(err)}` }],
|
|
288
340
|
isError: true
|
|
289
341
|
};
|
|
290
342
|
}
|
|
@@ -336,7 +388,7 @@ ${tableMarkdown}` }]
|
|
|
336
388
|
};
|
|
337
389
|
} catch (err) {
|
|
338
390
|
return {
|
|
339
|
-
content: [{ type: "text", text: `\uC624\uB958: ${
|
|
391
|
+
content: [{ type: "text", text: `\uC624\uB958: ${describeError(err)}` }],
|
|
340
392
|
isError: true
|
|
341
393
|
};
|
|
342
394
|
}
|
|
@@ -371,7 +423,7 @@ server.tool(
|
|
|
371
423
|
};
|
|
372
424
|
} catch (err) {
|
|
373
425
|
return {
|
|
374
|
-
content: [{ type: "text", text: `\uC624\uB958: ${
|
|
426
|
+
content: [{ type: "text", text: `\uC624\uB958: ${describeError(err)}` }],
|
|
375
427
|
isError: true
|
|
376
428
|
};
|
|
377
429
|
}
|
|
@@ -386,7 +438,7 @@ server.tool(
|
|
|
386
438
|
async ({ file_path }) => {
|
|
387
439
|
try {
|
|
388
440
|
const { buffer } = readValidatedFile(file_path);
|
|
389
|
-
const result = await parse(buffer);
|
|
441
|
+
const result = await parse(buffer, { keepTrailingEmptyCols: true });
|
|
390
442
|
if (!result.success) {
|
|
391
443
|
return {
|
|
392
444
|
content: [{ type: "text", text: `\uD30C\uC2F1 \uC2E4\uD328: ${result.error}` }],
|
|
@@ -399,7 +451,7 @@ server.tool(
|
|
|
399
451
|
};
|
|
400
452
|
} catch (err) {
|
|
401
453
|
return {
|
|
402
|
-
content: [{ type: "text", text: `\uC624\uB958: ${
|
|
454
|
+
content: [{ type: "text", text: `\uC624\uB958: ${describeError(err)}` }],
|
|
403
455
|
isError: true
|
|
404
456
|
};
|
|
405
457
|
}
|
|
@@ -427,6 +479,8 @@ server.tool(
|
|
|
427
479
|
},
|
|
428
480
|
async ({ file_path, fields, formats, require_unique, mask_values, output_format, output_path }) => {
|
|
429
481
|
try {
|
|
482
|
+
const outExts = output_format === "markdown" ? /* @__PURE__ */ new Set([".md", ".markdown", ".txt"]) : /* @__PURE__ */ new Set([".hwpx"]);
|
|
483
|
+
const outPath = output_path ? safeOutputPath(output_path, outExts) : void 0;
|
|
430
484
|
const { buffer } = readValidatedFile(file_path);
|
|
431
485
|
if (output_format === "hwpx-preserve") {
|
|
432
486
|
const format = detectFormat(buffer);
|
|
@@ -458,16 +512,16 @@ server.tool(
|
|
|
458
512
|
verifyLine
|
|
459
513
|
].filter(Boolean).join(" | ");
|
|
460
514
|
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(
|
|
515
|
+
if (outPath) {
|
|
516
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
517
|
+
writeFileSync(outPath, Buffer.from(hwpxResult.buffer));
|
|
464
518
|
return {
|
|
465
519
|
content: [{ type: "text", text: `[${summary2}]
|
|
466
520
|
|
|
467
521
|
\uCC44\uC6CC\uC9C4 \uD544\uB4DC:
|
|
468
522
|
${filledList}
|
|
469
523
|
|
|
470
|
-
HWPX \uD30C\uC77C \uC800\uC7A5 (\uC6D0\uBCF8 \uC11C\uC2DD \uC720\uC9C0): ${
|
|
524
|
+
HWPX \uD30C\uC77C \uC800\uC7A5 (\uC6D0\uBCF8 \uC11C\uC2DD \uC720\uC9C0): ${outPath}` }]
|
|
471
525
|
};
|
|
472
526
|
}
|
|
473
527
|
return {
|
|
@@ -479,7 +533,7 @@ ${filledList}
|
|
|
479
533
|
\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
534
|
};
|
|
481
535
|
}
|
|
482
|
-
const result = await parse(buffer);
|
|
536
|
+
const result = await parse(buffer, { keepTrailingEmptyCols: true });
|
|
483
537
|
if (!result.success) {
|
|
484
538
|
return {
|
|
485
539
|
content: [{ type: "text", text: `\uD30C\uC2F1 \uC2E4\uD328: ${result.error}` }],
|
|
@@ -505,13 +559,13 @@ ${filledList}
|
|
|
505
559
|
].filter(Boolean).join(" | ");
|
|
506
560
|
if (output_format === "hwpx") {
|
|
507
561
|
const hwpxBuffer = await markdownToHwpx(markdown);
|
|
508
|
-
if (
|
|
509
|
-
mkdirSync(dirname(
|
|
510
|
-
writeFileSync(
|
|
562
|
+
if (outPath) {
|
|
563
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
564
|
+
writeFileSync(outPath, Buffer.from(hwpxBuffer));
|
|
511
565
|
return {
|
|
512
566
|
content: [{ type: "text", text: `[${summary}]
|
|
513
567
|
|
|
514
|
-
HWPX \uD30C\uC77C \uC800\uC7A5: ${
|
|
568
|
+
HWPX \uD30C\uC77C \uC800\uC7A5: ${outPath}` }]
|
|
515
569
|
};
|
|
516
570
|
}
|
|
517
571
|
return {
|
|
@@ -522,13 +576,13 @@ HWPX \uD30C\uC77C \uC800\uC7A5: ${resolve(output_path)}` }]
|
|
|
522
576
|
${previewMd}` }]
|
|
523
577
|
};
|
|
524
578
|
}
|
|
525
|
-
if (
|
|
526
|
-
mkdirSync(dirname(
|
|
527
|
-
writeFileSync(
|
|
579
|
+
if (outPath) {
|
|
580
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
581
|
+
writeFileSync(outPath, markdown, "utf-8");
|
|
528
582
|
return {
|
|
529
583
|
content: [{ type: "text", text: `[${summary}]
|
|
530
584
|
|
|
531
|
-
\uB9C8\uD06C\uB2E4\uC6B4 \uD30C\uC77C \uC800\uC7A5: ${
|
|
585
|
+
\uB9C8\uD06C\uB2E4\uC6B4 \uD30C\uC77C \uC800\uC7A5: ${outPath}
|
|
532
586
|
|
|
533
587
|
${previewMd}` }]
|
|
534
588
|
};
|
|
@@ -540,7 +594,7 @@ ${previewMd}` }]
|
|
|
540
594
|
};
|
|
541
595
|
} catch (err) {
|
|
542
596
|
return {
|
|
543
|
-
content: [{ type: "text", text: `\uC624\uB958: ${
|
|
597
|
+
content: [{ type: "text", text: `\uC624\uB958: ${describeError(err)}` }],
|
|
544
598
|
isError: true
|
|
545
599
|
};
|
|
546
600
|
}
|
|
@@ -562,6 +616,7 @@ server.tool(
|
|
|
562
616
|
},
|
|
563
617
|
async ({ file_path, image_path, anchor, occurrence, size_mm, mode, dx_mm, dy_mm, output_path }) => {
|
|
564
618
|
try {
|
|
619
|
+
const outPath = safeOutputPath(output_path, /* @__PURE__ */ new Set([".hwpx"]));
|
|
565
620
|
const { buffer } = readValidatedFile(file_path);
|
|
566
621
|
const format = detectFormat(buffer);
|
|
567
622
|
if (format !== "hwpx") {
|
|
@@ -570,13 +625,13 @@ server.tool(
|
|
|
570
625
|
isError: true
|
|
571
626
|
};
|
|
572
627
|
}
|
|
573
|
-
const imgResolved =
|
|
628
|
+
const imgResolved = safePath(image_path, IMAGE_EXTENSIONS);
|
|
574
629
|
if (statSync(imgResolved).size > 500 * 1024 * 1024) {
|
|
575
630
|
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
631
|
}
|
|
577
632
|
const image = new Uint8Array(readFileSync(imgResolved));
|
|
578
|
-
const ext = extname(
|
|
579
|
-
const { placeSealHwpx } = await import("./seal-
|
|
633
|
+
const ext = extname(imgResolved).slice(1).toLowerCase();
|
|
634
|
+
const { placeSealHwpx } = await import("./seal-D2QNXJVO.js");
|
|
580
635
|
const result = await placeSealHwpx(buffer, [{
|
|
581
636
|
anchor,
|
|
582
637
|
occurrence,
|
|
@@ -587,8 +642,8 @@ server.tool(
|
|
|
587
642
|
dxMm: dx_mm,
|
|
588
643
|
dyMm: dy_mm
|
|
589
644
|
}]);
|
|
590
|
-
mkdirSync(dirname(
|
|
591
|
-
writeFileSync(
|
|
645
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
646
|
+
writeFileSync(outPath, Buffer.from(result.buffer));
|
|
592
647
|
const p0 = result.placed[0];
|
|
593
648
|
const warnLines = (p0.warnings ?? []).map((w) => `
|
|
594
649
|
\u26A0\uFE0F ${w}`).join("");
|
|
@@ -596,13 +651,13 @@ server.tool(
|
|
|
596
651
|
content: [{
|
|
597
652
|
type: "text",
|
|
598
653
|
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: ${
|
|
654
|
+
\uC800\uC7A5: ${outPath}${warnLines}
|
|
600
655
|
\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
656
|
}]
|
|
602
657
|
};
|
|
603
658
|
} catch (err) {
|
|
604
659
|
return {
|
|
605
|
-
content: [{ type: "text", text: `\uB3C4\uC7A5 \uBC30\uCE58 \uC2E4\uD328: ${
|
|
660
|
+
content: [{ type: "text", text: `\uB3C4\uC7A5 \uBC30\uCE58 \uC2E4\uD328: ${describeError(err)}` }],
|
|
606
661
|
isError: true
|
|
607
662
|
};
|
|
608
663
|
}
|
|
@@ -618,6 +673,7 @@ server.tool(
|
|
|
618
673
|
},
|
|
619
674
|
async ({ file_path, edited_markdown, output_path }) => {
|
|
620
675
|
try {
|
|
676
|
+
const out = safeOutputPath(output_path, /* @__PURE__ */ new Set([".hwpx", ".hwp"]));
|
|
621
677
|
const { buffer } = readValidatedFile(file_path);
|
|
622
678
|
const format = detectFormat(buffer);
|
|
623
679
|
let isHwpx = format === "hwpx";
|
|
@@ -639,7 +695,6 @@ server.tool(
|
|
|
639
695
|
isError: true
|
|
640
696
|
};
|
|
641
697
|
}
|
|
642
|
-
const out = resolve(output_path);
|
|
643
698
|
mkdirSync(dirname(out), { recursive: true });
|
|
644
699
|
writeFileSync(out, Buffer.from(result.data));
|
|
645
700
|
const v = result.verification?.stats;
|
|
@@ -655,12 +710,147 @@ server.tool(
|
|
|
655
710
|
};
|
|
656
711
|
} catch (err) {
|
|
657
712
|
return {
|
|
658
|
-
content: [{ type: "text", text: `\uC624\uB958: ${
|
|
713
|
+
content: [{ type: "text", text: `\uC624\uB958: ${describeError(err)}` }],
|
|
714
|
+
isError: true
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
);
|
|
719
|
+
server.tool(
|
|
720
|
+
"render_document",
|
|
721
|
+
"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).",
|
|
722
|
+
{
|
|
723
|
+
file_path: z.string().min(1).describe("\uB80C\uB354\uD560 HWPX \uD30C\uC77C\uC758 \uC808\uB300 \uACBD\uB85C"),
|
|
724
|
+
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"),
|
|
725
|
+
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)"),
|
|
726
|
+
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"),
|
|
727
|
+
reflow_mode: z.enum(["keep", "charAll"]).default("keep").describe("reflow \uC904\uBC14\uAFC8: keep=\uC5B4\uC808 \uB2E8\uC704, charAll=\uAE00\uC790 \uB2E8\uC704")
|
|
728
|
+
},
|
|
729
|
+
async ({ file_path, format, output_path, highlights, reflow_mode }) => {
|
|
730
|
+
try {
|
|
731
|
+
if (format === "svg" && !output_path) {
|
|
732
|
+
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 };
|
|
733
|
+
}
|
|
734
|
+
const outPath = output_path ? safeOutputPath(output_path, /* @__PURE__ */ new Set([format === "png" ? ".png" : ".svg"])) : void 0;
|
|
735
|
+
const { buffer } = readValidatedFile(file_path, MAX_FILE_SIZE, /* @__PURE__ */ new Set([".hwpx"]));
|
|
736
|
+
const { renderHwpxToSvg } = await import("./render-4MG5QUDG.js");
|
|
737
|
+
const result = await renderHwpxToSvg(buffer, { highlights, reflow: true, reflowMode: reflow_mode });
|
|
738
|
+
const summary = [
|
|
739
|
+
`\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})`,
|
|
740
|
+
...result.warnings.map((w) => `\u26A0\uFE0F ${w}`)
|
|
741
|
+
];
|
|
742
|
+
if (format === "svg") {
|
|
743
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
744
|
+
writeFileSync(outPath, result.svg, "utf-8");
|
|
745
|
+
summary.push(`\uC800\uC7A5: ${outPath}`);
|
|
746
|
+
return { content: [{ type: "text", text: summary.join("\n") }] };
|
|
747
|
+
}
|
|
748
|
+
const { rasterizeSvg } = await import("./rasterize-W2NEZUSW.js");
|
|
749
|
+
const raster = await rasterizeSvg(result.svg, result.width, result.height);
|
|
750
|
+
if (outPath) {
|
|
751
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
752
|
+
writeFileSync(outPath, raster.png);
|
|
753
|
+
summary.push(`\uC800\uC7A5: ${outPath}`);
|
|
754
|
+
}
|
|
755
|
+
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.`);
|
|
756
|
+
return {
|
|
757
|
+
content: [
|
|
758
|
+
{ type: "image", data: raster.png.toString("base64"), mimeType: "image/png" },
|
|
759
|
+
{ type: "text", text: summary.join("\n") }
|
|
760
|
+
]
|
|
761
|
+
};
|
|
762
|
+
} catch (err) {
|
|
763
|
+
return {
|
|
764
|
+
content: [{ type: "text", text: `\uB80C\uB354 \uC2E4\uD328: ${describeError(err)}` }],
|
|
659
765
|
isError: true
|
|
660
766
|
};
|
|
661
767
|
}
|
|
662
768
|
}
|
|
663
769
|
);
|
|
770
|
+
server.tool(
|
|
771
|
+
"redact_document",
|
|
772
|
+
"\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.",
|
|
773
|
+
{
|
|
774
|
+
file_path: z.string().min(1).describe("\uB300\uC0C1 \uBB38\uC11C\uC758 \uC808\uB300 \uACBD\uB85C"),
|
|
775
|
+
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)"),
|
|
776
|
+
mask_char: z.string().min(1).max(1).optional().describe("\uB9C8\uC2A4\uD06C \uBB38\uC790 1\uAE00\uC790 (\uAE30\uBCF8: \u25CF)"),
|
|
777
|
+
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"),
|
|
778
|
+
dry_run: z.boolean().default(false).describe("\uD0D0\uC9C0 \uB9AC\uD3EC\uD2B8\uB9CC \uBC18\uD658, \uD30C\uC77C \uBBF8\uC0DD\uC131")
|
|
779
|
+
},
|
|
780
|
+
async ({ file_path, rules, mask_char, output_path, dry_run }) => {
|
|
781
|
+
try {
|
|
782
|
+
const { buffer } = readValidatedFile(file_path);
|
|
783
|
+
const format = detectFormat(buffer);
|
|
784
|
+
const patchable = format === "hwpx" || format === "hwp";
|
|
785
|
+
if (!dry_run && !output_path) {
|
|
786
|
+
return { content: [{ type: "text", text: "output_path\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4 (\uD0D0\uC9C0\uB9CC \uC6D0\uD558\uBA74 dry_run: true)." }], isError: true };
|
|
787
|
+
}
|
|
788
|
+
const outPath = !dry_run ? safeOutputPath(output_path, new Set(patchable ? [format === "hwp" ? ".hwp" : ".hwpx"] : [".md", ".markdown", ".txt"])) : void 0;
|
|
789
|
+
const parsed = await parse(buffer, { filePath: file_path });
|
|
790
|
+
if (!parsed.success) {
|
|
791
|
+
return { content: [{ type: "text", text: `\uD30C\uC2F1 \uC2E4\uD328: ${parsed.error}` }], isError: true };
|
|
792
|
+
}
|
|
793
|
+
const { redactMarkdown } = await import("./redact-7ILEAUTS.js");
|
|
794
|
+
const r = redactMarkdown(parsed.markdown, { rules, maskChar: mask_char });
|
|
795
|
+
const byRule = /* @__PURE__ */ new Map();
|
|
796
|
+
for (const h of r.hits) byRule.set(h.rule, (byRule.get(h.rule) ?? 0) + 1);
|
|
797
|
+
const lines = [
|
|
798
|
+
`\uD0D0\uC9C0: ${r.hits.length}\uAC74 (${[...byRule.entries()].map(([k, v]) => `${k} ${v}`).join(", ") || "\uC5C6\uC74C"})`,
|
|
799
|
+
...r.hits.map((h) => ` - [${h.rule}] ${h.masked}`)
|
|
800
|
+
];
|
|
801
|
+
if (!dry_run && r.hits.length > 0) {
|
|
802
|
+
if (patchable) {
|
|
803
|
+
const original = new Uint8Array(buffer);
|
|
804
|
+
const result = format === "hwp" ? await patchHwp(original, r.text) : await patchHwpx(original, r.text);
|
|
805
|
+
if (!result.success || !result.data) {
|
|
806
|
+
return { content: [{ type: "text", text: `\uB9C8\uC2A4\uD0B9 \uD328\uCE58 \uC2E4\uD328: ${result.error ?? "\uC54C \uC218 \uC5C6\uB294 \uC624\uB958"}` }], isError: true };
|
|
807
|
+
}
|
|
808
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
809
|
+
writeFileSync(outPath, Buffer.from(result.data));
|
|
810
|
+
lines.push(`\uC800\uC7A5: ${outPath} (\uC6D0\uBCF8 \uC11C\uC2DD \uBCF4\uC874)`);
|
|
811
|
+
if (result.skipped.length > 0) {
|
|
812
|
+
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:`);
|
|
813
|
+
for (const s of result.skipped) lines.push(` - ${s.reason}`);
|
|
814
|
+
}
|
|
815
|
+
lines.push("render_document\uB85C \uB9C8\uC2A4\uD0B9 \uACB0\uACFC\uB97C \uB208\uC73C\uB85C \uD655\uC778\uD558\uC138\uC694.");
|
|
816
|
+
} else {
|
|
817
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
818
|
+
writeFileSync(outPath, r.text, "utf-8");
|
|
819
|
+
lines.push(`\uC800\uC7A5: ${outPath} (${format}\uB294 \uC11C\uC2DD \uBCF4\uC874 \uBBF8\uC9C0\uC6D0 \u2014 \uB9C8\uC2A4\uD0B9\uB41C \uB9C8\uD06C\uB2E4\uC6B4)`);
|
|
820
|
+
}
|
|
821
|
+
} else if (!dry_run) {
|
|
822
|
+
lines.push("\uD0D0\uC9C0 0\uAC74 \u2014 \uCD9C\uB825 \uD30C\uC77C\uC744 \uB9CC\uB4E4\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.");
|
|
823
|
+
}
|
|
824
|
+
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.");
|
|
825
|
+
return { content: [{ type: "text", text: capResponseText(lines.join("\n")) }] };
|
|
826
|
+
} catch (err) {
|
|
827
|
+
return { content: [{ type: "text", text: `\uB9C8\uC2A4\uD0B9 \uC2E4\uD328: ${describeError(err)}` }], isError: true };
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
);
|
|
831
|
+
server.tool(
|
|
832
|
+
"parse_chunks",
|
|
833
|
+
"\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.",
|
|
834
|
+
{
|
|
835
|
+
file_path: z.string().min(1).describe("\uB300\uC0C1 \uBB38\uC11C\uC758 \uC808\uB300 \uACBD\uB85C (HWP/HWPX/PDF/XLSX/DOCX)"),
|
|
836
|
+
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"),
|
|
837
|
+
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")
|
|
838
|
+
},
|
|
839
|
+
async ({ file_path, granularity, include_table_cells }) => {
|
|
840
|
+
try {
|
|
841
|
+
const { buffer } = readValidatedFile(file_path);
|
|
842
|
+
const parsed = await parse(buffer, { filePath: file_path });
|
|
843
|
+
if (!parsed.success) {
|
|
844
|
+
return { content: [{ type: "text", text: `\uD30C\uC2F1 \uC2E4\uD328: ${parsed.error}` }], isError: true };
|
|
845
|
+
}
|
|
846
|
+
const { blocksToChunks } = await import("./chunks-ZQEFAZNC.js");
|
|
847
|
+
const chunks = blocksToChunks(parsed.blocks, { granularity, includeTableCells: include_table_cells });
|
|
848
|
+
return { content: [{ type: "text", text: capResponseText(JSON.stringify(chunks, null, 2)) }] };
|
|
849
|
+
} catch (err) {
|
|
850
|
+
return { content: [{ type: "text", text: `\uCCAD\uD06C \uD30C\uC2F1 \uC2E4\uD328: ${describeError(err)}` }], isError: true };
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
);
|
|
664
854
|
server.tool(
|
|
665
855
|
"extract_profile",
|
|
666
856
|
'\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 +860,10 @@ server.tool(
|
|
|
670
860
|
},
|
|
671
861
|
async ({ hwpx_path, output_path }) => {
|
|
672
862
|
try {
|
|
863
|
+
const out = safeOutputPath(output_path, PROFILE_EXTENSIONS);
|
|
673
864
|
const { buffer } = readValidatedFile(hwpx_path);
|
|
674
|
-
const { hwpxToProfile } = await import("./-
|
|
865
|
+
const { hwpxToProfile } = await import("./-SXQIZHYA.js");
|
|
675
866
|
const profile = await hwpxToProfile(buffer);
|
|
676
|
-
const out = resolve(output_path);
|
|
677
867
|
mkdirSync(dirname(out), { recursive: true });
|
|
678
868
|
writeFileSync(out, JSON.stringify(profile, null, 2));
|
|
679
869
|
return {
|
|
@@ -682,7 +872,7 @@ server.tool(
|
|
|
682
872
|
};
|
|
683
873
|
} catch (err) {
|
|
684
874
|
return {
|
|
685
|
-
content: [{ type: "text", text: `\uC624\uB958: ${
|
|
875
|
+
content: [{ type: "text", text: `\uC624\uB958: ${describeError(err)}` }],
|
|
686
876
|
isError: true
|
|
687
877
|
};
|
|
688
878
|
}
|
|
@@ -755,11 +945,11 @@ server.tool(
|
|
|
755
945
|
}
|
|
756
946
|
let profile;
|
|
757
947
|
if (profile_path) {
|
|
758
|
-
const { parseFormatProfileJson } = await import("./profile-io-
|
|
759
|
-
profile = parseFormatProfileJson(readFileSync(
|
|
948
|
+
const { parseFormatProfileJson } = await import("./profile-io-TWHDIVPL.js");
|
|
949
|
+
profile = parseFormatProfileJson(readFileSync(safePath(profile_path, PROFILE_EXTENSIONS), "utf-8"));
|
|
760
950
|
}
|
|
951
|
+
const out = safeOutputPath(output_path, /* @__PURE__ */ new Set([".hwpx"]));
|
|
761
952
|
const buf = await markdownToHwpx(markdown, gongmun || profile ? { ...gongmun ? { gongmun } : {}, ...profile ? { profile } : {} } : void 0);
|
|
762
|
-
const out = resolve(output_path);
|
|
763
953
|
mkdirSync(dirname(out), { recursive: true });
|
|
764
954
|
writeFileSync(out, Buffer.from(buf));
|
|
765
955
|
const mode = gongmun ? `\uACF5\uBB38\uC11C:${gongmun.preset}` : "\uBC94\uC6A9";
|
|
@@ -775,18 +965,38 @@ server.tool(
|
|
|
775
965
|
};
|
|
776
966
|
} catch (err) {
|
|
777
967
|
return {
|
|
778
|
-
content: [{ type: "text", text: `\uC624\uB958: ${
|
|
968
|
+
content: [{ type: "text", text: `\uC624\uB958: ${describeError(err)}` }],
|
|
779
969
|
isError: true
|
|
780
970
|
};
|
|
781
971
|
}
|
|
782
972
|
}
|
|
783
973
|
);
|
|
784
|
-
|
|
974
|
+
var serverStarted = false;
|
|
975
|
+
async function startMcpServer() {
|
|
976
|
+
if (serverStarted) return;
|
|
977
|
+
serverStarted = true;
|
|
785
978
|
const transport = new StdioServerTransport();
|
|
786
979
|
await server.connect(transport);
|
|
787
980
|
}
|
|
788
|
-
|
|
981
|
+
var autoStart = true;
|
|
982
|
+
try {
|
|
983
|
+
const entry = process.argv[1];
|
|
984
|
+
if (entry && pathToFileURL(realpathSync(entry)).href !== import.meta.url) autoStart = false;
|
|
985
|
+
} catch {
|
|
986
|
+
}
|
|
987
|
+
if (autoStart) startMcpServer().catch((err) => {
|
|
789
988
|
console.error(err);
|
|
790
989
|
process.exit(1);
|
|
791
990
|
});
|
|
991
|
+
export {
|
|
992
|
+
ALLOWED_EXTENSIONS,
|
|
993
|
+
IMAGE_EXTENSIONS,
|
|
994
|
+
PROFILE_EXTENSIONS,
|
|
995
|
+
buildFillInputs,
|
|
996
|
+
capResponseText,
|
|
997
|
+
describeError,
|
|
998
|
+
safeOutputPath,
|
|
999
|
+
safePath,
|
|
1000
|
+
startMcpServer
|
|
1001
|
+
};
|
|
792
1002
|
//# sourceMappingURL=mcp.js.map
|