@webskill/sdk 0.21.0 → 0.23.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/dist/abnfDiagram-O67JEVCF-DtYFjfqO.js +109 -0
- package/dist/agent.d.ts +3 -3
- package/dist/agent.js +1174 -169
- package/dist/{approval-DwN2o2QG.js → approval-7CuZS3Z4.js} +104 -18
- package/dist/arc-8U_6NQWm.js +130 -0
- package/dist/architecture-7GRP2DOG-RTw1wpAq.js +4 -0
- package/dist/architectureDiagram-NJMV4G6O-XmmXrJAK.js +7473 -0
- package/dist/array-DQfpQNY8.js +8 -0
- package/dist/blockDiagram-BEXU5L5S-D4yjnCD1.js +2582 -0
- package/dist/browser.d.ts +455 -49
- package/dist/browser.js +2134 -138
- package/dist/c4Diagram-YGBWAQC7-BLmA_JSd.js +3668 -0
- package/dist/channel-CZxxLrG7.js +9 -0
- package/dist/chunk-2Q5K7J3B-Ck03gkFR.js +21 -0
- package/dist/chunk-3FUC2YCW-tr6jmbQf.js +530 -0
- package/dist/chunk-5DYCD2WN-Bt97YGTd.js +58 -0
- package/dist/chunk-5VM5RSS4-BBxa48HL.js +21 -0
- package/dist/chunk-6AEJRKK7-JXK89I-O.js +14 -0
- package/dist/chunk-742MDFTN-CPmgCGwC.js +466 -0
- package/dist/chunk-7INBJB4K-C9jq9o66.js +6552 -0
- package/dist/chunk-7M6MHVWA-BrKCWcR1.js +4894 -0
- package/dist/chunk-7PRAP22T-BHED6GVs.js +95 -0
- package/dist/chunk-DUW6YSOI-DoZj78PO.js +19 -0
- package/dist/chunk-FOHPRMQF-Dkbp819z.js +27189 -0
- package/dist/chunk-GNY47TPC-Bpvq1T49.js +87 -0
- package/dist/chunk-GTNCS2PH-CLmh4I2c.js +686 -0
- package/dist/chunk-GWA4HPMP-B6vN3fkL.js +95 -0
- package/dist/chunk-J5ZVWO5B-Bi_Pcobw.js +26 -0
- package/dist/chunk-JWPE2WC7-D1rC79GS.js +12 -0
- package/dist/chunk-LNGE3PJU-D5OIoe3Z.js +2582 -0
- package/dist/chunk-MBY4JIJT-C34L7a4f.js +2276 -0
- package/dist/chunk-NETBCI7D-Cg84k8N8.js +321 -0
- package/dist/chunk-O7XYJQB3-B6K0KOSL.js +8846 -0
- package/dist/chunk-UA2S7LBM-DxHM29_K.js +612 -0
- package/dist/chunk-WEXAMYUT-Ba6jFWhB.js +33 -0
- package/dist/chunk-XXDRQBXY-DPbSy4kg.js +12 -0
- package/dist/chunk-Y2CYZVJY-U3QOMqrW.js +15 -0
- package/dist/chunk-Z7XXMR3K-oLg1h8F3.js +1038 -0
- package/dist/chunk-ZIGJFQKS-DqEFBuHR.js +2215 -0
- package/dist/classDiagram-v2-NBCMYWYE-BqnOWIUt.js +3845 -0
- package/dist/cose-bilkent-JH36ORCC-C0dTAHVK.js +4270 -0
- package/dist/cynefin-OW5HDTMX-B2QvgEQj.js +4 -0
- package/dist/cynefinDiagram-VND7K2PF-yAWc6Z3W.js +479 -0
- package/dist/cytoscape.esm-C64mRh9B.js +28325 -0
- package/dist/dagre-6A5THRUB-D0w2W27v.js +4816 -0
- package/dist/defaultLocale-B_EoOkSF.js +249 -0
- package/dist/diagram-22UHCM2B-DvgzhUzP.js +6115 -0
- package/dist/diagram-3UASUU5V-DWgUB-ef.js +795 -0
- package/dist/diagram-ATOU4E4O-P1olqwIs.js +553 -0
- package/dist/diagram-CDSNMT55-BUlZuLUe.js +402 -0
- package/dist/diagram-MLGK6HIB-6w5qmkGt.js +186 -0
- package/dist/diagram-MPIPVDR6-DEFiSo8o.js +289 -0
- package/dist/dist-UajCDt3n.js +92 -0
- package/dist/ebnfDiagram-ZINNZB2B-CI8liCfR.js +123 -0
- package/dist/elk-276RUBZZ-3SvW6OAK.js +90034 -0
- package/dist/erDiagram-OPXOYQCR-CPTbKhwP.js +2301 -0
- package/dist/eventmodeling-NTZA5JFV-BlyuqGp0.js +4 -0
- package/dist/flowDiagram-KWPJA3E3-CcUJ6HbV.js +18 -0
- package/dist/ganttDiagram-FUAMR5RP-31UjY0KK.js +3939 -0
- package/dist/{toolSource-C9oNuKmr.js → geometry-CRhuySKV.js} +169 -12
- package/dist/gitGraph-4MIJSDKK-ChdVlrk7.js +4 -0
- package/dist/gitGraphDiagram-X574FWY7-DKuxJymB.js +1153 -0
- package/dist/governance.d.ts +22 -4
- package/dist/governance.js +100 -10
- package/dist/graphlib-tk9gQYuN.js +4194 -0
- package/dist/{index-DHopiH_m.d.ts → index-7No55dRb.d.ts} +161 -11
- package/dist/{index-B8Tgmpwh.d.ts → index-ShvCB5I9.d.ts} +2 -2
- package/dist/{index-CYLt5u4L.d.ts → index-V76_OFj2.d.ts} +789 -21
- package/dist/index.d.ts +4 -4
- package/dist/index.js +11 -9
- package/dist/info-A6RAGUB7-CxRAt9S9.js +4 -0
- package/dist/infoDiagram-VRGFBTTK-pRspGfjZ.js +25 -0
- package/dist/init-CMOIWdg-.js +16 -0
- package/dist/ishikawaDiagram-OU5B5YK6-DKerAPAg.js +975 -0
- package/dist/journeyDiagram-ZHPQQLJL-C4MK-YO5.js +1227 -0
- package/dist/kanban-definition-PNTS6WVX-BqsZpMXx.js +1244 -0
- package/dist/katex-BcRRvyh_.js +26465 -0
- package/dist/{kind-DaKqLX2F.js → kind-Dc8x0HWz.js} +54 -7
- package/dist/line-LgV8iVMV.js +48 -0
- package/dist/linear-BWKR0Tqd.js +393 -0
- package/dist/linkedDocument-CZZOl9cO.js +456 -0
- package/dist/mcp.d.ts +2 -2
- package/dist/{memoryArtifactStore-D6dLeY55.js → memoryArtifactStore-Bs7glPqm.js} +14 -0
- package/dist/mermaid-parser.core-pYR5siSx.js +754 -0
- package/dist/mermaid.core-DMtwGCHy.js +1756 -0
- package/dist/mindmap-definition-NLK3R4M7-CXbD-myG.js +1312 -0
- package/dist/node.d.ts +3 -3
- package/dist/node.js +12 -5
- package/dist/{openUiLibrary-b0i7F_oZ.js → openUiLibrary-B7j3rLrm.js} +1 -1
- package/dist/{openUiSpecLang-CLXJEeRU.js → openUiSpecLang-BSYYnjay.js} +1 -1
- package/dist/ordinal-CxA6GHQS.js +84 -0
- package/dist/packet-AYTQ26CC-BOm08cxl.js +4 -0
- package/dist/path-C27Z2Bjv.js +106 -0
- package/dist/{pathSecurity-B1owvJAF.js → pathSecurity-CirkQwWP.js} +12 -1
- package/dist/pegDiagram-GJSIUBJH-BLGJOewQ.js +115 -0
- package/dist/pie-WAS4IAKB-Dvg7glpk.js +4 -0
- package/dist/pieDiagram-5QR66LMP-laoaV_PB.js +298 -0
- package/dist/quadrantDiagram-O4NWA36T-Db_wFBkT.js +2236 -0
- package/dist/radar-RG4KPBEZ-BZDaTu06.js +4 -0
- package/dist/railroad-74A4TZTK-C-UhjkOy.js +4 -0
- package/dist/railroad-abnf-HS5TGJTU-dUKVA4OS.js +4 -0
- package/dist/railroad-ebnf-LZEXJU2U-DzQumk18.js +4 -0
- package/dist/railroad-peg-WCYAUIDC-B3vvTWed.js +4 -0
- package/dist/railroadDiagram-XR7U4H2S-BY0sTM4X.js +89 -0
- package/dist/requirementDiagram-PLB6GJNP-3rkQfEhs.js +2474 -0
- package/dist/rough.cjs-AmDd_NQk.js +1395 -0
- package/dist/sankeyDiagram-IPEJSGJF-CGAJhyG2.js +3578 -0
- package/dist/sequenceDiagram-PO4LG4MO-9FJjFX06.js +5522 -0
- package/dist/sizeCapture-INFHLROL-D8PWxdOn.js +56 -0
- package/dist/{skill-CAJMsLod.js → skill-WSUDp6A1.js} +1 -1
- package/dist/{skillVersionStore-B24Jjjry-BkOk9wI_.d.ts → skillVersionStore-S4_HJ_Fl-Cvy9LqVu.d.ts} +35 -4
- package/dist/src-NkhI3UMl.js +2653 -0
- package/dist/stateDiagram-v2-GCMORJYK-B0O3wc1-.js +2715 -0
- package/dist/swimlanes-2SLR337P-D4EOnrpu.js +6637 -0
- package/dist/swimlanesDiagram-TC7HE7FX-BUx29EJ9.js +30 -0
- package/dist/testing.d.ts +2 -1
- package/dist/testing.js +1 -1
- package/dist/timeline-definition-EJHVYXUP-CrgiiB4C.js +1513 -0
- package/dist/treeView-Q6P3EWNA-C1by-Gzc.js +4 -0
- package/dist/treemap-WGGIJYW6-mC2NZ6ad.js +4 -0
- package/dist/{types-BvTV_05--BW8zDuEk.d.ts → types-CpDRZ0rA-BiZBXGm4.d.ts} +66 -8
- package/dist/ui-react.d.ts +3 -3
- package/dist/ui-react.js +3746 -96
- package/dist/ui-vue.d.ts +1 -1
- package/dist/ui.d.ts +3 -3
- package/dist/ui.js +2 -2
- package/dist/usecaseDiagram-POWQR4AR-BUt_TQOY.js +14397 -0
- package/dist/vennDiagram-UO4OBE2U-CwXr0wjA.js +2808 -0
- package/dist/wardley-WFR3VGLG-CVSYjq_S.js +4 -0
- package/dist/wardleyDiagram-VNRHLVJA-Cpfd47dQ.js +874 -0
- package/dist/{webSkillApi-Cib6G-94.js → webSkillApi-D5VMUnrv.js} +2 -2
- package/dist/{webskillLitCatalog-W06npwej.js → webskillLitCatalog-D5BCiMCU.js} +1 -1
- package/dist/xychartDiagram-PMCCYNJV-e1TeVoc6.js +2704 -0
- package/package.json +1 -1
- package/dist/linkedDocument-C0gj1sMq.js +0 -245
|
@@ -43,6 +43,13 @@ function toFrameScopes(scope) {
|
|
|
43
43
|
...scope.exclude ? { exclude: scope.exclude } : {}
|
|
44
44
|
}];
|
|
45
45
|
}
|
|
46
|
+
/** 四个方向的规范清单;工具层校验与文案生成都从这里取,不各写一份 */
|
|
47
|
+
const SCROLL_DIRECTIONS = [
|
|
48
|
+
"up",
|
|
49
|
+
"down",
|
|
50
|
+
"left",
|
|
51
|
+
"right"
|
|
52
|
+
];
|
|
46
53
|
|
|
47
54
|
//#endregion
|
|
48
55
|
//#region ../agent/src/pageAction/types.ts
|
|
@@ -60,10 +67,14 @@ function toActionFrameScopes(scope) {
|
|
|
60
67
|
}];
|
|
61
68
|
}
|
|
62
69
|
/**
|
|
63
|
-
* 本版的操作集(FR-25.1 / 0.16.0 FR-13.6 / 0.18.0 FR-10.1
|
|
70
|
+
* 本版的操作集(FR-25.1 / 0.16.0 FR-13.6 / 0.18.0 FR-10.1 / 0.22.0 FR-17.1)。
|
|
64
71
|
* 导航只有 `back` 一个,且它**不接受地址**——可达面被浏览器历史封死(SC-1)。
|
|
65
72
|
*
|
|
66
|
-
* `
|
|
73
|
+
* `drag` 只表达**起点与终点**,没有中途轨迹(0.22.0 FR-17.6 裁定,D64 就此撤销):
|
|
74
|
+
* 轨迹是实现细节不是意图,能画任意路径等于架空 AC-23.2,而且滑块验证码要的正是轨迹——
|
|
75
|
+
* 表达不了轨迹,这个动作就天然做不了人机验证绕过。
|
|
76
|
+
*
|
|
77
|
+
* 这些动作与既有几个走**同一条** policy 路径,
|
|
67
78
|
* 范围白名单、逐次确认、审计三条硬约束因此天然覆盖到它们——
|
|
68
79
|
* 前提是新动作不绕过 policy 直调执行器(AC-25.4 守这一点)。
|
|
69
80
|
* @experimental
|
|
@@ -76,6 +87,8 @@ const PAGE_ACTION_KINDS = [
|
|
|
76
87
|
"set",
|
|
77
88
|
"attach",
|
|
78
89
|
"scroll",
|
|
90
|
+
"hover",
|
|
91
|
+
"drag",
|
|
79
92
|
"back"
|
|
80
93
|
];
|
|
81
94
|
/**
|
|
@@ -139,8 +152,10 @@ function sniffDocumentFormat(bytes, name) {
|
|
|
139
152
|
const lower = (name ?? "").toLowerCase();
|
|
140
153
|
if (lower.endsWith(".docx")) return "docx";
|
|
141
154
|
if (lower.endsWith(".xlsx")) return "xlsx";
|
|
155
|
+
if (lower.endsWith(".pptx")) return "pptx";
|
|
142
156
|
if (containsEntry(bytes, "word/document.xml")) return "docx";
|
|
143
157
|
if (containsEntry(bytes, "xl/workbook.xml")) return "xlsx";
|
|
158
|
+
if (containsEntry(bytes, "ppt/presentation.xml")) return "pptx";
|
|
144
159
|
}
|
|
145
160
|
|
|
146
161
|
//#endregion
|
|
@@ -225,7 +240,7 @@ function asReadMode(raw) {
|
|
|
225
240
|
const READ_DOCUMENT_TOOL = "read_document";
|
|
226
241
|
/** 大图的门槛:低于它的是页眉 logo、印章、项目符号,投它们等于白烧一次多模态请求 @experimental */
|
|
227
242
|
const PDF_LARGE_IMAGE_RATIO = .15;
|
|
228
|
-
const DESCRIPTION = "Read a PDF, Word (.docx)
|
|
243
|
+
const DESCRIPTION = "Read a PDF, Word (.docx), Excel (.xlsx) or PowerPoint (.pptx) document the user attached or downloaded, one batch of units at a time. Pages that have no usable text layer (scans) are rendered as images, so their content is never lost. Pictures on pages whose text is readable are listed under \"deferred\" instead of being returned, because reading them costs an extra round trip; call again with mode=\"images\" to fetch those.";
|
|
229
244
|
const INPUT_SCHEMA = {
|
|
230
245
|
type: "object",
|
|
231
246
|
properties: {
|
|
@@ -243,7 +258,7 @@ const INPUT_SCHEMA = {
|
|
|
243
258
|
},
|
|
244
259
|
block: {
|
|
245
260
|
type: "number",
|
|
246
|
-
description: "Word
|
|
261
|
+
description: "Word and PowerPoint: 0-based block index."
|
|
247
262
|
},
|
|
248
263
|
sheet: {
|
|
249
264
|
type: "number",
|
|
@@ -252,6 +267,10 @@ const INPUT_SCHEMA = {
|
|
|
252
267
|
row: {
|
|
253
268
|
type: "number",
|
|
254
269
|
description: "Excel only: 0-based row index within the sheet."
|
|
270
|
+
},
|
|
271
|
+
slide: {
|
|
272
|
+
type: "number",
|
|
273
|
+
description: "PowerPoint only: 0-based slide index."
|
|
255
274
|
}
|
|
256
275
|
},
|
|
257
276
|
additionalProperties: false
|
|
@@ -269,7 +288,7 @@ const INPUT_SCHEMA = {
|
|
|
269
288
|
required: ["id"],
|
|
270
289
|
additionalProperties: false
|
|
271
290
|
};
|
|
272
|
-
const SYSTEM_PROMPT = "read_document reads an attached or downloaded PDF/Word/Excel document in batches. It returns a \"next\" cursor whenever the document is not finished: keep calling read_document with that cursor until the result has no \"next\", otherwise you have only seen part of the document. Read the text first and answer from it; a result that carries \"deferred\" means those units hold pictures that were not read yet. Fetch them with mode=\"images\" only when the answer depends on what they show, and tell the user the pictures have not been looked at when you answer without them. Never guess an id, and never claim you read a document you only read part of.";
|
|
291
|
+
const SYSTEM_PROMPT = "read_document reads an attached or downloaded PDF/Word/Excel/PowerPoint document in batches. It returns a \"next\" cursor whenever the document is not finished: keep calling read_document with that cursor until the result has no \"next\", otherwise you have only seen part of the document. Read the text first and answer from it; a result that carries \"deferred\" means those units hold pictures that were not read yet. Fetch them with mode=\"images\" only when the answer depends on what they show, and tell the user the pictures have not been looked at when you answer without them. Never guess an id, and never claim you read a document you only read part of.";
|
|
273
292
|
function toolError(e) {
|
|
274
293
|
return {
|
|
275
294
|
ok: false,
|
|
@@ -287,13 +306,13 @@ function aborted(signal) {
|
|
|
287
306
|
/**
|
|
288
307
|
* 逐单元读文档,读不出字的地方出图(0.21.0 分册 22)。
|
|
289
308
|
*
|
|
290
|
-
*
|
|
309
|
+
* 四个端口一个都没接时 `listToolSpecs()` 返回空——模型连这个工具的存在都看不到,
|
|
291
310
|
* 而不是看得到再被拒(AC-22.2)。
|
|
292
311
|
* @experimental
|
|
293
312
|
*/
|
|
294
313
|
function createDocumentToolSource(options) {
|
|
295
314
|
const { files } = options;
|
|
296
|
-
const available = () => options.pdf !== void 0 || options.docx !== void 0 || options.xlsx !== void 0;
|
|
315
|
+
const available = () => options.pdf !== void 0 || options.docx !== void 0 || options.xlsx !== void 0 || options.pptx !== void 0;
|
|
297
316
|
const budgetOf = () => options.budget?.() ?? DOCUMENT_READ_BUDGET;
|
|
298
317
|
return {
|
|
299
318
|
kind: "document-reader",
|
|
@@ -320,13 +339,13 @@ function createDocumentToolSource(options) {
|
|
|
320
339
|
const file = await files.read(id);
|
|
321
340
|
if (file === void 0) throw new WebSkillError("TOOL_UNSUPPORTED", `No readable document with id "${id}". It is either not an attachment of the current message, or a download id that has since expired — list the downloads again to get a fresh one.`);
|
|
322
341
|
const format = sniffDocumentFormat(file.bytes, file.name);
|
|
323
|
-
if (format === void 0) throw new WebSkillError("TOOL_UNSUPPORTED", `"${file.name}" is not a PDF, Word (.docx)
|
|
342
|
+
if (format === void 0) throw new WebSkillError("TOOL_UNSUPPORTED", `"${file.name}" is not a PDF, Word (.docx), Excel (.xlsx) or PowerPoint (.pptx) document, so read_document cannot read it.`);
|
|
324
343
|
const reader = readerFor(format);
|
|
325
344
|
if (reader === void 0) throw new WebSkillError("TOOL_UNSUPPORTED", `This environment cannot read ${format.toUpperCase()} documents.`);
|
|
326
345
|
const from = asCursor(args["from"]);
|
|
327
346
|
const mode = asReadMode(args["mode"]);
|
|
328
347
|
const budget = budgetOf();
|
|
329
|
-
const batch = format === "pdf" ? await readPdf(reader, file.bytes, from, mode, budget, signal) : format === "docx" ? await readDocx(reader, file.bytes, from, mode, budget, signal) : await readXlsx(reader, file.bytes, from, mode, budget, signal);
|
|
348
|
+
const batch = format === "pdf" ? await readPdf(reader, file.bytes, from, mode, budget, signal) : format === "docx" ? await readDocx(reader, file.bytes, from, mode, budget, signal) : format === "pptx" ? await readPptx(reader, file.bytes, from, mode, budget, signal) : await readXlsx(reader, file.bytes, from, mode, budget, signal);
|
|
330
349
|
return {
|
|
331
350
|
ok: true,
|
|
332
351
|
content: describe(file.name, format, batch, aborted(signal))
|
|
@@ -335,6 +354,7 @@ function createDocumentToolSource(options) {
|
|
|
335
354
|
function readerFor(format) {
|
|
336
355
|
if (format === "pdf") return options.pdf;
|
|
337
356
|
if (format === "docx") return options.docx;
|
|
357
|
+
if (format === "pptx") return options.pptx;
|
|
338
358
|
return options.xlsx;
|
|
339
359
|
}
|
|
340
360
|
}
|
|
@@ -345,7 +365,8 @@ function asCursor(raw) {
|
|
|
345
365
|
"page",
|
|
346
366
|
"block",
|
|
347
367
|
"sheet",
|
|
348
|
-
"row"
|
|
368
|
+
"row",
|
|
369
|
+
"slide"
|
|
349
370
|
]) {
|
|
350
371
|
const value = raw[key];
|
|
351
372
|
if (typeof value === "number" && Number.isInteger(value) && value >= 0) out[key] = value;
|
|
@@ -455,6 +476,43 @@ async function readXlsx(reader, bytes, from, mode, budget, signal) {
|
|
|
455
476
|
} } : {}
|
|
456
477
|
};
|
|
457
478
|
}
|
|
479
|
+
/**
|
|
480
|
+
* pptx 摊平成「第几页第几块」的一条序列,与 xlsx 的表×行同构。
|
|
481
|
+
* 幻灯片真有页,所以坐标保留页号——模型报「第 7 页那张图」时对得上用户看到的东西。
|
|
482
|
+
*/
|
|
483
|
+
async function readPptx(reader, bytes, from, mode, budget, signal) {
|
|
484
|
+
const { slides } = await reader.read(bytes);
|
|
485
|
+
const flat = [];
|
|
486
|
+
slides.forEach((slide, slideIndex) => {
|
|
487
|
+
slide.blocks.forEach((content, blockIndex) => {
|
|
488
|
+
flat.push({
|
|
489
|
+
slide: slideIndex,
|
|
490
|
+
block: blockIndex,
|
|
491
|
+
content
|
|
492
|
+
});
|
|
493
|
+
});
|
|
494
|
+
});
|
|
495
|
+
const startSlide = from["slide"] ?? 0;
|
|
496
|
+
const startBlock = from["block"] ?? 0;
|
|
497
|
+
const found = flat.findIndex((entry) => entry.slide > startSlide || entry.slide === startSlide && entry.block >= startBlock);
|
|
498
|
+
const start = found === -1 ? flat.length : found;
|
|
499
|
+
const taken = takeBlocks(flat.map((entry) => entry.content), start, mode, budget, signal, (index) => ({
|
|
500
|
+
slide: flat[index].slide,
|
|
501
|
+
block: flat[index].block
|
|
502
|
+
}));
|
|
503
|
+
const stop = flat[taken.stopped];
|
|
504
|
+
return {
|
|
505
|
+
units: taken.units,
|
|
506
|
+
total: flat.length,
|
|
507
|
+
done: taken.stopped,
|
|
508
|
+
skippedImages: taken.skippedImages,
|
|
509
|
+
deferred: taken.deferred,
|
|
510
|
+
...stop ? { next: {
|
|
511
|
+
slide: stop.slide,
|
|
512
|
+
block: stop.block
|
|
513
|
+
} } : {}
|
|
514
|
+
};
|
|
515
|
+
}
|
|
458
516
|
function takeBlocks(blocks, start, mode, budget, signal, locate) {
|
|
459
517
|
const units = [];
|
|
460
518
|
const deferred = [];
|
|
@@ -549,7 +607,7 @@ function describe(name, format, batch, cancelled) {
|
|
|
549
607
|
}, ...images];
|
|
550
608
|
}
|
|
551
609
|
function continuationNote(format, batch, remaining, cancelled) {
|
|
552
|
-
const noun = format === "pdf" ? "page" : format === "
|
|
610
|
+
const noun = format === "pdf" ? "page" : format === "xlsx" ? "row" : "block";
|
|
553
611
|
if (batch.next === void 0) return `Reached the end of the document; all ${batch.total} ${noun}s have been read.`;
|
|
554
612
|
const cursor = JSON.stringify(batch.next);
|
|
555
613
|
return `${cancelled ? "Stopped because the user cancelled the run" : `${remaining} ${noun}(s) still unread`}. Call read_document again with from = ${cursor} to continue.`;
|
|
@@ -562,4 +620,103 @@ function imageIdOf(unit) {
|
|
|
562
620
|
}
|
|
563
621
|
|
|
564
622
|
//#endregion
|
|
565
|
-
|
|
623
|
+
//#region ../agent/src/template/geometry.ts
|
|
624
|
+
/**
|
|
625
|
+
* A1 地址与 OOXML 几何换算(0.22.0 分册 42 · 设计 43 §1.6)。
|
|
626
|
+
*
|
|
627
|
+
* 环境无关,`@webskill/agent` 里可直接单测——几何算错的后果是图溢出单元格,
|
|
628
|
+
* 而那只有人肉打开文件才看得见,所以这一层的覆盖要密。
|
|
629
|
+
*/
|
|
630
|
+
/** 1 px 的 EMU 数(96 DPI) */
|
|
631
|
+
const EMU_PER_PIXEL = 9525;
|
|
632
|
+
/** 1 磅的 EMU 数 */
|
|
633
|
+
const EMU_PER_POINT = 12700;
|
|
634
|
+
/** 1 twip 的 EMU 数 */
|
|
635
|
+
const EMU_PER_TWIP = 635;
|
|
636
|
+
/** 默认字体的最大数字宽度,Excel 列宽换算基准 */
|
|
637
|
+
const MAX_DIGIT_WIDTH = 7;
|
|
638
|
+
const ADDRESS = /^([A-Z]+)([1-9][0-9]*)$/;
|
|
639
|
+
/** @throws WebSkillError 语法不合法 */
|
|
640
|
+
function parseCellAddress(address) {
|
|
641
|
+
const match = ADDRESS.exec(address.trim().toUpperCase());
|
|
642
|
+
if (match === null) throw new WebSkillError("TEMPLATE_ADDRESS_INVALID", `"${address}" is not a valid cell address. Use A1 notation such as B3.`);
|
|
643
|
+
let column = 0;
|
|
644
|
+
for (const letter of match[1] ?? "") column = column * 26 + (letter.charCodeAt(0) - 64);
|
|
645
|
+
return {
|
|
646
|
+
column: column - 1,
|
|
647
|
+
row: Number(match[2]) - 1
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
function formatCellAddress({ column, row }) {
|
|
651
|
+
let letters = "";
|
|
652
|
+
for (let rest = column + 1; rest > 0; rest = Math.floor((rest - 1) / 26)) letters = String.fromCharCode(65 + (rest - 1) % 26) + letters;
|
|
653
|
+
return `${letters}${row + 1}`;
|
|
654
|
+
}
|
|
655
|
+
/** @throws WebSkillError 语法不合法 */
|
|
656
|
+
function parseCellRange(range) {
|
|
657
|
+
const [from = "", to] = range.split(":");
|
|
658
|
+
if (to === void 0) {
|
|
659
|
+
const single = parseCellAddress(from);
|
|
660
|
+
return {
|
|
661
|
+
start: single,
|
|
662
|
+
end: single
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
return {
|
|
666
|
+
start: parseCellAddress(from),
|
|
667
|
+
end: parseCellAddress(to)
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
function isRangeTopLeft(range, address) {
|
|
671
|
+
return range.start.column === address.column && range.start.row === address.row;
|
|
672
|
+
}
|
|
673
|
+
function rangeContains(range, address) {
|
|
674
|
+
return address.column >= range.start.column && address.column <= range.end.column && address.row >= range.start.row && address.row <= range.end.row;
|
|
675
|
+
}
|
|
676
|
+
/** Excel 的列宽单位是字符数,换算成像素(设计 43 §1.6 实测 MDW=7) */
|
|
677
|
+
function columnWidthToPixels(width) {
|
|
678
|
+
return Math.round(width * 7 + 5);
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* 等比缩放进框:宽高同时约束、**取两个比例里的小者**。
|
|
682
|
+
*
|
|
683
|
+
* FR-42.11 与 FR-42.19 是同一条口径——xlsx 的合并区和 docx 声明了 `trHeight` 的
|
|
684
|
+
* 表格行都这么算。框的某一边为 0(未声明高度)时那一边不参与约束。
|
|
685
|
+
*/
|
|
686
|
+
function fitWithin(natural, box) {
|
|
687
|
+
const widthRatio = box.width > 0 ? box.width / natural.width : Number.POSITIVE_INFINITY;
|
|
688
|
+
const heightRatio = box.height > 0 ? box.height / natural.height : Number.POSITIVE_INFINITY;
|
|
689
|
+
const ratio = Math.min(widthRatio, heightRatio, 1);
|
|
690
|
+
if (!Number.isFinite(ratio)) return natural;
|
|
691
|
+
return {
|
|
692
|
+
width: Math.floor(natural.width * ratio),
|
|
693
|
+
height: Math.floor(natural.height * ratio)
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
/** PNG / JPEG 的像素尺寸。读文件头,不解码整张图。 */
|
|
697
|
+
function readImageSize(bytes) {
|
|
698
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
699
|
+
if (bytes.length > 24 && view.getUint32(0) === 2303741511) return {
|
|
700
|
+
width: view.getUint32(16),
|
|
701
|
+
height: view.getUint32(20)
|
|
702
|
+
};
|
|
703
|
+
if (bytes.length > 4 && view.getUint16(0) === 65496) return readJpegSize(view, bytes.length);
|
|
704
|
+
}
|
|
705
|
+
function readJpegSize(view, length) {
|
|
706
|
+
let offset = 2;
|
|
707
|
+
while (offset + 9 < length) {
|
|
708
|
+
if (view.getUint8(offset) !== 255) {
|
|
709
|
+
offset += 1;
|
|
710
|
+
continue;
|
|
711
|
+
}
|
|
712
|
+
const marker = view.getUint8(offset + 1);
|
|
713
|
+
if (marker >= 192 && marker <= 207 && marker !== 196 && marker !== 200 && marker !== 204) return {
|
|
714
|
+
width: view.getUint16(offset + 7),
|
|
715
|
+
height: view.getUint16(offset + 5)
|
|
716
|
+
};
|
|
717
|
+
offset += 2 + view.getUint16(offset + 2);
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
//#endregion
|
|
722
|
+
export { frameSteps as A, DOCUMENT_READ_BUDGET as C, SCROLL_DIRECTIONS as D, toActionFrameScopes as E, toFrameScopes as O, sniffDocumentFormat as S, PAGE_DOCUMENT_REF as T, defersImage as _, columnWidthToPixels as a, isPdfTextTrustworthy as b, isRangeTopLeft as c, rangeContains as d, readImageSize as f, asReadMode as g, createDocumentToolSource as h, MAX_DIGIT_WIDTH as i, frameLabel as k, parseCellAddress as l, READ_DOCUMENT_TOOL as m, EMU_PER_POINT as n, fitWithin as o, PDF_LARGE_IMAGE_RATIO as p, EMU_PER_TWIP as r, formatCellAddress as s, EMU_PER_PIXEL as t, parseCellRange as u, takesImage as v, PAGE_ACTION_KINDS as w, measurePdfTextQuality as x, PDF_GARBLED_RATIO as y };
|