@poe-platform/safe-bash 0.1.759 → 0.1.760

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/image-ast/index.browser.js +26 -11
  2. package/dist/image-ast/index.js +26 -11
  3. package/dist/pdf-ast/ast.d.ts +8 -3
  4. package/dist/pdf-ast/index.js +30 -14
  5. package/dist/safe-bash/chunks/{chunk-AYPUGSOV.js → chunk-CRQDMBQA.js} +123 -8
  6. package/dist/safe-bash/command-chunks/{chunk-HVEAK3OS.js → chunk-MC4XXPQJ.js} +2 -2
  7. package/dist/safe-bash/command-chunks/{chunk-BAUGDXLZ.js → chunk-S3SCPBHC.js} +26 -11
  8. package/dist/safe-bash/command-chunks/{chunk-7JA44PVV.js → chunk-UCI6ZQFB.js} +1 -1
  9. package/dist/safe-bash/commands/python/index.browser.js +1 -1
  10. package/dist/safe-bash/commands/python/index.d.ts +1 -1
  11. package/dist/safe-bash/commands/python/llm-capability.d.ts +7 -3
  12. package/dist/safe-bash/commands/python/llm-capability.js +149 -10
  13. package/dist/safe-bash/core.browser.js +1 -1
  14. package/dist/safe-bash-command-ffmpeg/index.js +2929 -2921
  15. package/dist/safe-bash-command-gh/index.js +128 -27
  16. package/dist/safe-bash-command-imagemagick/index.js +2 -2
  17. package/dist/safe-bash-command-pandoc/command.js +3 -3
  18. package/dist/safe-bash-command-pandoc/index.js +3 -3
  19. package/dist/safe-bash-command-pdfimages/index.js +26 -11
  20. package/dist/safe-bash-command-pdfinfo/index.js +30 -14
  21. package/dist/safe-bash-command-pdftk/index.js +26 -11
  22. package/dist/safe-bash-command-pdftoppm/index.js +30 -14
  23. package/dist/safe-bash-command-pdftotext/index.js +26 -11
  24. package/dist/safe-bash-command-qpdf/index.js +26 -11
  25. package/dist/safe-bash-command-sips/index.js +2 -2
  26. package/dist/safe-bash-command-soffice/index.js +1 -1
  27. package/dist/safe-bash-command-ssconvert/index.js +26 -11
  28. package/dist/safe-bash-command-wkhtmltopdf/index.js +26 -11
  29. package/dist/safe-bash-io-engine/internal.d.ts +2 -2
  30. package/dist/safe-bash-mcp/index.d.ts +1 -1
  31. package/package.json +2 -2
  32. package/third-party/pdf-ast/THIRD_PARTY_NOTICES.md +8 -0
@@ -43913,7 +43913,7 @@ function evaluateContentStreamToDisplayList(params) {
43913
43913
  const [x, y] = transformPoint(st.ctm, seg.x, seg.y);
43914
43914
  transformedSegments.push({ kind: "cubic", x1, y1, x2, y2, x, y });
43915
43915
  } else if (seg.kind === "rect") {
43916
- if (hasRotOrShear) {
43916
+ if (hasRotOrShear || seg.width * st.ctm[0] < 0 || seg.height * st.ctm[3] < 0) {
43917
43917
  const [p0x, p0y] = transformPoint(st.ctm, seg.x, seg.y);
43918
43918
  const [p1x, p1y] = transformPoint(st.ctm, seg.x + seg.width, seg.y);
43919
43919
  const [p2x, p2y] = transformPoint(st.ctm, seg.x + seg.width, seg.y + seg.height);
@@ -43946,7 +43946,12 @@ function evaluateContentStreamToDisplayList(params) {
43946
43946
  transformedSegments.push({ kind: "close" });
43947
43947
  }
43948
43948
  }
43949
- if (node.clip && transformedSegments.length > 0) {
43949
+ const applyClip = () => {
43950
+ if (!node.clip) return;
43951
+ st.clipPaths = [...st.clipPaths ?? [], {
43952
+ segments: transformedSegments,
43953
+ fillRule: node.clip === "W*" ? "evenodd" : "nonzero"
43954
+ }];
43950
43955
  let cMinX = Infinity, cMinY = Infinity, cMaxX = -Infinity, cMaxY = -Infinity;
43951
43956
  for (const s of transformedSegments) {
43952
43957
  if (s.kind === "move" || s.kind === "line") {
@@ -43974,8 +43979,11 @@ function evaluateContentStreamToDisplayList(params) {
43974
43979
  Math.min(st.clipRect[3], cMaxY)
43975
43980
  ] : [cMinX, cMinY, cMaxX, cMaxY];
43976
43981
  }
43982
+ };
43983
+ if (node.paint === "n") {
43984
+ applyClip();
43985
+ break;
43977
43986
  }
43978
- if (node.paint === "n") break;
43979
43987
  const isFill = ["f", "F", "f*", "B", "B*", "b", "b*"].includes(node.paint);
43980
43988
  const isStroke = ["S", "s", "B", "B*", "b", "b*"].includes(node.paint);
43981
43989
  let evaluatedFillPattern = false;
@@ -44108,7 +44116,10 @@ function evaluateContentStreamToDisplayList(params) {
44108
44116
  }
44109
44117
  }
44110
44118
  }
44111
- if (evaluatedFillPattern && !isStroke) break;
44119
+ if (evaluatedFillPattern && !isStroke) {
44120
+ applyClip();
44121
+ break;
44122
+ }
44112
44123
  const fillRule = node.paint.includes("*") ? "evenodd" : "nonzero";
44113
44124
  const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
44114
44125
  const scaledStrokeWidth = st.strokeWidth === 0 ? 0 : st.strokeWidth * ctmScale;
@@ -44128,6 +44139,7 @@ function evaluateContentStreamToDisplayList(params) {
44128
44139
  ...st.dashPhase !== void 0 ? { dashPhase: st.dashPhase } : {},
44129
44140
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
44130
44141
  } });
44142
+ applyClip();
44131
44143
  break;
44132
44144
  }
44133
44145
  case "xobject": {
@@ -47451,8 +47463,8 @@ function segmentsToScreenEdges(segments, pageHeight, scale, closeSubpaths = fals
47451
47463
  if (closeSubpaths && hasOpenSubpath && (curX !== startX || curY !== startY)) {
47452
47464
  edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
47453
47465
  }
47454
- const [rx0, ry0] = toScreen(seg.x, seg.y + seg.height);
47455
- const [rx1, ry1] = toScreen(seg.x + seg.width, seg.y);
47466
+ const [rx0, ry0] = toScreen(seg.x, seg.y);
47467
+ const [rx1, ry1] = toScreen(seg.x + seg.width, seg.y + seg.height);
47456
47468
  edges.push(
47457
47469
  { x0: rx0, y0: ry0, x1: rx1, y1: ry0 },
47458
47470
  { x0: rx1, y0: ry0, x1: rx1, y1: ry1 },
@@ -47595,21 +47607,24 @@ function renderDisplayListToBitmap(displayList, options = {}) {
47595
47607
  }
47596
47608
  const aaVec = options.antialiasVector !== false;
47597
47609
  const aaTxt = options.antialiasText !== false;
47598
- const clipMasks = /* @__PURE__ */ new Map();
47610
+ let cachedClips;
47611
+ let cachedClipMask;
47599
47612
  const imageClipMasks = /* @__PURE__ */ new Map();
47600
47613
  for (const original of paintOperations(displayList)) {
47601
47614
  if (original.kind === "glyph" && (original.value.renderMode === 3 || !original.value.outline && !original.value.unicode.trim())) continue;
47602
47615
  const operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
47603
47616
  const clips = original.value.clipPaths;
47604
- let clipMask = clips ? clipMasks.get(clips) : void 0;
47617
+ let clipMask = clips && clips === cachedClips ? cachedClipMask : void 0;
47605
47618
  if (clips && !clipMask) {
47606
47619
  clipMask = new Uint8Array(width * height * 4).fill(255);
47607
- for (const segments of clips) {
47620
+ for (const clip of clips) {
47621
+ const { segments, fillRule } = "segments" in clip ? clip : { segments: clip, fillRule: "nonzero" };
47608
47622
  const layer = new Uint8Array(width * height * 4);
47609
- fillEdgesScanline4x4(layer, width, height, segmentsToScreenEdges(segments, displayList.height, scale, true), { r: 1, g: 1, b: 1 });
47623
+ fillEdgesScanline4x4(layer, width, height, segmentsToScreenEdges(segments, displayList.height, scale, true), { r: 1, g: 1, b: 1 }, 1, fillRule);
47610
47624
  for (let i = 3; i < layer.length; i += 4) clipMask[i] = Math.round(clipMask[i] * layer[i] / 255);
47611
47625
  }
47612
- clipMasks.set(clips, clipMask);
47626
+ cachedClips = clips;
47627
+ cachedClipMask = clipMask;
47613
47628
  }
47614
47629
  const imageClips = original.value.clipImages;
47615
47630
  if (imageClips) {
@@ -43913,7 +43913,7 @@ function evaluateContentStreamToDisplayList(params) {
43913
43913
  const [x, y] = transformPoint(st.ctm, seg.x, seg.y);
43914
43914
  transformedSegments.push({ kind: "cubic", x1, y1, x2, y2, x, y });
43915
43915
  } else if (seg.kind === "rect") {
43916
- if (hasRotOrShear) {
43916
+ if (hasRotOrShear || seg.width * st.ctm[0] < 0 || seg.height * st.ctm[3] < 0) {
43917
43917
  const [p0x, p0y] = transformPoint(st.ctm, seg.x, seg.y);
43918
43918
  const [p1x, p1y] = transformPoint(st.ctm, seg.x + seg.width, seg.y);
43919
43919
  const [p2x, p2y] = transformPoint(st.ctm, seg.x + seg.width, seg.y + seg.height);
@@ -43946,7 +43946,12 @@ function evaluateContentStreamToDisplayList(params) {
43946
43946
  transformedSegments.push({ kind: "close" });
43947
43947
  }
43948
43948
  }
43949
- if (node.clip && transformedSegments.length > 0) {
43949
+ const applyClip = () => {
43950
+ if (!node.clip) return;
43951
+ st.clipPaths = [...st.clipPaths ?? [], {
43952
+ segments: transformedSegments,
43953
+ fillRule: node.clip === "W*" ? "evenodd" : "nonzero"
43954
+ }];
43950
43955
  let cMinX = Infinity, cMinY = Infinity, cMaxX = -Infinity, cMaxY = -Infinity;
43951
43956
  for (const s of transformedSegments) {
43952
43957
  if (s.kind === "move" || s.kind === "line") {
@@ -43974,8 +43979,11 @@ function evaluateContentStreamToDisplayList(params) {
43974
43979
  Math.min(st.clipRect[3], cMaxY)
43975
43980
  ] : [cMinX, cMinY, cMaxX, cMaxY];
43976
43981
  }
43982
+ };
43983
+ if (node.paint === "n") {
43984
+ applyClip();
43985
+ break;
43977
43986
  }
43978
- if (node.paint === "n") break;
43979
43987
  const isFill = ["f", "F", "f*", "B", "B*", "b", "b*"].includes(node.paint);
43980
43988
  const isStroke = ["S", "s", "B", "B*", "b", "b*"].includes(node.paint);
43981
43989
  let evaluatedFillPattern = false;
@@ -44108,7 +44116,10 @@ function evaluateContentStreamToDisplayList(params) {
44108
44116
  }
44109
44117
  }
44110
44118
  }
44111
- if (evaluatedFillPattern && !isStroke) break;
44119
+ if (evaluatedFillPattern && !isStroke) {
44120
+ applyClip();
44121
+ break;
44122
+ }
44112
44123
  const fillRule = node.paint.includes("*") ? "evenodd" : "nonzero";
44113
44124
  const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
44114
44125
  const scaledStrokeWidth = st.strokeWidth === 0 ? 0 : st.strokeWidth * ctmScale;
@@ -44128,6 +44139,7 @@ function evaluateContentStreamToDisplayList(params) {
44128
44139
  ...st.dashPhase !== void 0 ? { dashPhase: st.dashPhase } : {},
44129
44140
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
44130
44141
  } });
44142
+ applyClip();
44131
44143
  break;
44132
44144
  }
44133
44145
  case "xobject": {
@@ -47451,8 +47463,8 @@ function segmentsToScreenEdges(segments, pageHeight, scale, closeSubpaths = fals
47451
47463
  if (closeSubpaths && hasOpenSubpath && (curX !== startX || curY !== startY)) {
47452
47464
  edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
47453
47465
  }
47454
- const [rx0, ry0] = toScreen(seg.x, seg.y + seg.height);
47455
- const [rx1, ry1] = toScreen(seg.x + seg.width, seg.y);
47466
+ const [rx0, ry0] = toScreen(seg.x, seg.y);
47467
+ const [rx1, ry1] = toScreen(seg.x + seg.width, seg.y + seg.height);
47456
47468
  edges.push(
47457
47469
  { x0: rx0, y0: ry0, x1: rx1, y1: ry0 },
47458
47470
  { x0: rx1, y0: ry0, x1: rx1, y1: ry1 },
@@ -47595,21 +47607,24 @@ function renderDisplayListToBitmap(displayList, options = {}) {
47595
47607
  }
47596
47608
  const aaVec = options.antialiasVector !== false;
47597
47609
  const aaTxt = options.antialiasText !== false;
47598
- const clipMasks = /* @__PURE__ */ new Map();
47610
+ let cachedClips;
47611
+ let cachedClipMask;
47599
47612
  const imageClipMasks = /* @__PURE__ */ new Map();
47600
47613
  for (const original of paintOperations(displayList)) {
47601
47614
  if (original.kind === "glyph" && (original.value.renderMode === 3 || !original.value.outline && !original.value.unicode.trim())) continue;
47602
47615
  const operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
47603
47616
  const clips = original.value.clipPaths;
47604
- let clipMask = clips ? clipMasks.get(clips) : void 0;
47617
+ let clipMask = clips && clips === cachedClips ? cachedClipMask : void 0;
47605
47618
  if (clips && !clipMask) {
47606
47619
  clipMask = new Uint8Array(width * height * 4).fill(255);
47607
- for (const segments of clips) {
47620
+ for (const clip of clips) {
47621
+ const { segments, fillRule } = "segments" in clip ? clip : { segments: clip, fillRule: "nonzero" };
47608
47622
  const layer = new Uint8Array(width * height * 4);
47609
- fillEdgesScanline4x4(layer, width, height, segmentsToScreenEdges(segments, displayList.height, scale, true), { r: 1, g: 1, b: 1 });
47623
+ fillEdgesScanline4x4(layer, width, height, segmentsToScreenEdges(segments, displayList.height, scale, true), { r: 1, g: 1, b: 1 }, 1, fillRule);
47610
47624
  for (let i = 3; i < layer.length; i += 4) clipMask[i] = Math.round(clipMask[i] * layer[i] / 255);
47611
47625
  }
47612
- clipMasks.set(clips, clipMask);
47626
+ cachedClips = clips;
47627
+ cachedClipMask = clipMask;
47613
47628
  }
47614
47629
  const imageClips = original.value.clipImages;
47615
47630
  if (imageClips) {
@@ -169,6 +169,11 @@ export type PdfPathSegment = {
169
169
  } | {
170
170
  readonly kind: "close";
171
171
  };
172
+ /** A clipping intersection. Bare segment arrays retain nonzero semantics. */
173
+ export type PdfClipPath = readonly PdfPathSegment[] | {
174
+ readonly segments: readonly PdfPathSegment[];
175
+ readonly fillRule: "nonzero" | "evenodd";
176
+ };
172
177
  export type PdfContentNode = {
173
178
  readonly kind: "graphics-group";
174
179
  readonly ops: PdfContentNode[];
@@ -222,7 +227,7 @@ export interface PdfPlacedGlyph {
222
227
  readonly mcid?: number | undefined;
223
228
  readonly actualText?: string | undefined;
224
229
  readonly blendMode?: string | undefined;
225
- readonly clipPaths?: readonly (readonly PdfPathSegment[])[] | undefined;
230
+ readonly clipPaths?: readonly PdfClipPath[] | undefined;
226
231
  readonly clipImages?: readonly PdfEvaluatedImage[] | undefined;
227
232
  readonly clipRect?: readonly [number, number, number, number] | undefined;
228
233
  }
@@ -241,7 +246,7 @@ export interface PdfEvaluatedPath {
241
246
  readonly dashPhase?: number | undefined;
242
247
  readonly blendMode?: string | undefined;
243
248
  readonly isClip?: boolean | undefined;
244
- readonly clipPaths?: readonly (readonly PdfPathSegment[])[] | undefined;
249
+ readonly clipPaths?: readonly PdfClipPath[] | undefined;
245
250
  readonly clipImages?: readonly PdfEvaluatedImage[] | undefined;
246
251
  readonly clipRect?: readonly [number, number, number, number] | undefined;
247
252
  }
@@ -254,7 +259,7 @@ export interface PdfEvaluatedImage {
254
259
  readonly bitsPerComponent: number;
255
260
  readonly decodedRgba?: Uint8Array | undefined;
256
261
  readonly blendMode?: string | undefined;
257
- readonly clipPaths?: readonly (readonly PdfPathSegment[])[] | undefined;
262
+ readonly clipPaths?: readonly PdfClipPath[] | undefined;
258
263
  readonly clipImages?: readonly PdfEvaluatedImage[] | undefined;
259
264
  readonly clipRect?: readonly [number, number, number, number] | undefined;
260
265
  }
@@ -36627,7 +36627,7 @@ function evaluateContentStreamToDisplayList(params) {
36627
36627
  const [x, y] = transformPoint(st.ctm, seg.x, seg.y);
36628
36628
  transformedSegments.push({ kind: "cubic", x1, y1, x2, y2, x, y });
36629
36629
  } else if (seg.kind === "rect") {
36630
- if (hasRotOrShear) {
36630
+ if (hasRotOrShear || seg.width * st.ctm[0] < 0 || seg.height * st.ctm[3] < 0) {
36631
36631
  const [p0x, p0y] = transformPoint(st.ctm, seg.x, seg.y);
36632
36632
  const [p1x, p1y] = transformPoint(st.ctm, seg.x + seg.width, seg.y);
36633
36633
  const [p2x, p2y] = transformPoint(st.ctm, seg.x + seg.width, seg.y + seg.height);
@@ -36660,7 +36660,12 @@ function evaluateContentStreamToDisplayList(params) {
36660
36660
  transformedSegments.push({ kind: "close" });
36661
36661
  }
36662
36662
  }
36663
- if (node.clip && transformedSegments.length > 0) {
36663
+ const applyClip = () => {
36664
+ if (!node.clip) return;
36665
+ st.clipPaths = [...st.clipPaths ?? [], {
36666
+ segments: transformedSegments,
36667
+ fillRule: node.clip === "W*" ? "evenodd" : "nonzero"
36668
+ }];
36664
36669
  let cMinX = Infinity, cMinY = Infinity, cMaxX = -Infinity, cMaxY = -Infinity;
36665
36670
  for (const s of transformedSegments) {
36666
36671
  if (s.kind === "move" || s.kind === "line") {
@@ -36688,8 +36693,11 @@ function evaluateContentStreamToDisplayList(params) {
36688
36693
  Math.min(st.clipRect[3], cMaxY)
36689
36694
  ] : [cMinX, cMinY, cMaxX, cMaxY];
36690
36695
  }
36696
+ };
36697
+ if (node.paint === "n") {
36698
+ applyClip();
36699
+ break;
36691
36700
  }
36692
- if (node.paint === "n") break;
36693
36701
  const isFill = ["f", "F", "f*", "B", "B*", "b", "b*"].includes(node.paint);
36694
36702
  const isStroke = ["S", "s", "B", "B*", "b", "b*"].includes(node.paint);
36695
36703
  let evaluatedFillPattern = false;
@@ -36822,7 +36830,10 @@ function evaluateContentStreamToDisplayList(params) {
36822
36830
  }
36823
36831
  }
36824
36832
  }
36825
- if (evaluatedFillPattern && !isStroke) break;
36833
+ if (evaluatedFillPattern && !isStroke) {
36834
+ applyClip();
36835
+ break;
36836
+ }
36826
36837
  const fillRule = node.paint.includes("*") ? "evenodd" : "nonzero";
36827
36838
  const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
36828
36839
  const scaledStrokeWidth = st.strokeWidth === 0 ? 0 : st.strokeWidth * ctmScale;
@@ -36842,6 +36853,7 @@ function evaluateContentStreamToDisplayList(params) {
36842
36853
  ...st.dashPhase !== void 0 ? { dashPhase: st.dashPhase } : {},
36843
36854
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
36844
36855
  } });
36856
+ applyClip();
36845
36857
  break;
36846
36858
  }
36847
36859
  case "xobject": {
@@ -41252,8 +41264,8 @@ function segmentsToScreenEdges(segments, pageHeight, scale, closeSubpaths = fals
41252
41264
  if (closeSubpaths && hasOpenSubpath && (curX !== startX || curY !== startY)) {
41253
41265
  edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
41254
41266
  }
41255
- const [rx0, ry0] = toScreen(seg.x, seg.y + seg.height);
41256
- const [rx1, ry1] = toScreen(seg.x + seg.width, seg.y);
41267
+ const [rx0, ry0] = toScreen(seg.x, seg.y);
41268
+ const [rx1, ry1] = toScreen(seg.x + seg.width, seg.y + seg.height);
41257
41269
  edges.push(
41258
41270
  { x0: rx0, y0: ry0, x1: rx1, y1: ry0 },
41259
41271
  { x0: rx1, y0: ry0, x1: rx1, y1: ry1 },
@@ -41396,21 +41408,24 @@ function renderDisplayListToBitmap(displayList, options = {}) {
41396
41408
  }
41397
41409
  const aaVec = options.antialiasVector !== false;
41398
41410
  const aaTxt = options.antialiasText !== false;
41399
- const clipMasks = /* @__PURE__ */ new Map();
41411
+ let cachedClips;
41412
+ let cachedClipMask;
41400
41413
  const imageClipMasks = /* @__PURE__ */ new Map();
41401
41414
  for (const original of paintOperations(displayList)) {
41402
41415
  if (original.kind === "glyph" && (original.value.renderMode === 3 || !original.value.outline && !original.value.unicode.trim())) continue;
41403
41416
  const operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
41404
41417
  const clips = original.value.clipPaths;
41405
- let clipMask = clips ? clipMasks.get(clips) : void 0;
41418
+ let clipMask = clips && clips === cachedClips ? cachedClipMask : void 0;
41406
41419
  if (clips && !clipMask) {
41407
41420
  clipMask = new Uint8Array(width * height * 4).fill(255);
41408
- for (const segments of clips) {
41421
+ for (const clip of clips) {
41422
+ const { segments, fillRule } = "segments" in clip ? clip : { segments: clip, fillRule: "nonzero" };
41409
41423
  const layer = new Uint8Array(width * height * 4);
41410
- fillEdgesScanline4x4(layer, width, height, segmentsToScreenEdges(segments, displayList.height, scale, true), { r: 1, g: 1, b: 1 });
41424
+ fillEdgesScanline4x4(layer, width, height, segmentsToScreenEdges(segments, displayList.height, scale, true), { r: 1, g: 1, b: 1 }, 1, fillRule);
41411
41425
  for (let i = 3; i < layer.length; i += 4) clipMask[i] = Math.round(clipMask[i] * layer[i] / 255);
41412
41426
  }
41413
- clipMasks.set(clips, clipMask);
41427
+ cachedClips = clips;
41428
+ cachedClipMask = clipMask;
41414
41429
  }
41415
41430
  const imageClips = original.value.clipImages;
41416
41431
  if (imageClips) {
@@ -41604,7 +41619,7 @@ function svgPathData(segments, height) {
41604
41619
  } else if (seg.kind === "cubic") {
41605
41620
  dParts.push(`C ${seg.x1} ${height - seg.y1} ${seg.x2} ${height - seg.y2} ${seg.x} ${height - seg.y}`);
41606
41621
  } else if (seg.kind === "rect") {
41607
- dParts.push(`M ${seg.x} ${height - seg.y - seg.height} h ${seg.width} v ${seg.height} h ${-seg.width} Z`);
41622
+ dParts.push(`M ${seg.x} ${height - seg.y} h ${seg.width} v ${-seg.height} h ${-seg.width} Z`);
41608
41623
  } else if (seg.kind === "close") {
41609
41624
  dParts.push("Z");
41610
41625
  }
@@ -41643,9 +41658,10 @@ function renderDisplayListToSvg(displayList, options = {}) {
41643
41658
  const operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
41644
41659
  const clips = original.value.clipPaths ?? [];
41645
41660
  const imageClips = original.value.clipImages ?? [];
41646
- for (const segments of clips) {
41661
+ for (const clip of clips) {
41662
+ const { segments, fillRule } = "segments" in clip ? clip : { segments: clip, fillRule: "nonzero" };
41647
41663
  const id = `text-clip-${clipId++}`;
41648
- const path = `<path d="${svgPathData(segments, displayList.height)}"/>`;
41664
+ const path = `<path d="${svgPathData(segments, displayList.height)}" clip-rule="${fillRule}"/>`;
41649
41665
  parts.push(`<defs><clipPath id="${id}" clipPathUnits="userSpaceOnUse">${path}</clipPath></defs><g clip-path="url(#${id})">`);
41650
41666
  }
41651
41667
  for (const image of imageClips) {
@@ -1738,9 +1738,90 @@ function record(value) {
1738
1738
  if (!value || typeof value !== "object" || Array.isArray(value)) throw new TypeError("Expected a structured Python LLM request");
1739
1739
  return value;
1740
1740
  }
1741
+ function jsonBytes(value, limit) {
1742
+ if (limit === Infinity) return 0;
1743
+ let bytes = 0;
1744
+ const ancestors = /* @__PURE__ */ new Set();
1745
+ const add2 = (size) => {
1746
+ if (size > limit - bytes) throw new RangeError("Python LLM serialized response limit exceeded");
1747
+ bytes += size;
1748
+ };
1749
+ const string = (text2) => {
1750
+ add2(2);
1751
+ if (text2.length > limit - bytes) throw new RangeError("Python LLM serialized response limit exceeded");
1752
+ for (let i = 0; i < text2.length; i++) {
1753
+ const point = text2.codePointAt(i);
1754
+ if (point > 65535) {
1755
+ add2(4);
1756
+ i++;
1757
+ } else if (point === 34 || point === 92) add2(2);
1758
+ else if (point < 32) add2([8, 9, 10, 12, 13].includes(point) ? 2 : 6);
1759
+ else if (point >= 55296 && point <= 57343) add2(6);
1760
+ else add2(point < 128 ? 1 : point < 2048 ? 2 : 3);
1761
+ }
1762
+ };
1763
+ const visit = (item) => {
1764
+ if (typeof item === "string") {
1765
+ string(item);
1766
+ return;
1767
+ }
1768
+ if (item === null || typeof item === "boolean" || typeof item === "number" && Number.isFinite(item)) {
1769
+ add2(JSON.stringify(item).length);
1770
+ return;
1771
+ }
1772
+ if (!item || typeof item !== "object" || ancestors.has(item)) throw new TypeError("Python LLM response must contain acyclic data");
1773
+ ancestors.add(item);
1774
+ add2(2);
1775
+ let entries = 0;
1776
+ if (Array.isArray(item)) {
1777
+ if (item.length > limit - bytes) throw new RangeError("Python LLM serialized response limit exceeded");
1778
+ for (let i = 0; i < item.length; i++) {
1779
+ const descriptor = Object.getOwnPropertyDescriptor(item, String(i));
1780
+ if (!descriptor || !("value" in descriptor)) throw new TypeError("Python LLM response must contain data");
1781
+ if (entries++) add2(1);
1782
+ visit(descriptor.value);
1783
+ }
1784
+ } else {
1785
+ for (const key in item) {
1786
+ if (!Object.hasOwn(item, key)) continue;
1787
+ const descriptor = Object.getOwnPropertyDescriptor(item, key);
1788
+ if (!("value" in descriptor)) throw new TypeError("Python LLM response must contain data");
1789
+ if (entries++) add2(1);
1790
+ string(key);
1791
+ add2(1);
1792
+ visit(descriptor.value);
1793
+ }
1794
+ }
1795
+ ancestors.delete(item);
1796
+ };
1797
+ visit(value);
1798
+ return bytes;
1799
+ }
1800
+ function* textFragments(text2, limit) {
1801
+ let start = 0, bytes = 0;
1802
+ for (let i = 0; i < text2.length; ) {
1803
+ const point = text2.codePointAt(i);
1804
+ const width = point < 128 ? 1 : point < 2048 ? 2 : point < 65536 ? 3 : 4;
1805
+ if (width > limit) throw new RangeError("Python LLM stream chunk limit cannot fit a Unicode scalar");
1806
+ if (width > limit - bytes) {
1807
+ yield text2.slice(start, i);
1808
+ start = i;
1809
+ bytes = 0;
1810
+ }
1811
+ bytes += width;
1812
+ i += point > 65535 ? 2 : 1;
1813
+ }
1814
+ if (start < text2.length || !text2.length) yield text2.slice(start);
1815
+ }
1741
1816
  function createPythonLlmCapability(context, service, options = {}) {
1742
1817
  const chunkBytes = options.maxStreamChunkBytes ?? 16384;
1743
1818
  if (!Number.isSafeInteger(chunkBytes) || chunkBytes < 1) throw new RangeError("Invalid Python LLM stream chunk limit");
1819
+ const bufferedLimit = options.maxBufferedResponseBytes ?? Infinity;
1820
+ const eventLimit = options.maxBufferedEvents ?? bufferedLimit;
1821
+ const metadataLimit = options.maxMetadataBytes ?? bufferedLimit;
1822
+ for (const limit of [bufferedLimit, eventLimit, metadataLimit]) {
1823
+ if (limit !== Infinity && (!Number.isSafeInteger(limit) || limit < 1)) throw new RangeError("Invalid Python LLM host limit");
1824
+ }
1744
1825
  const prepare = async (value, signal) => {
1745
1826
  const payload = record(value);
1746
1827
  for (const key of ["template", "conversation"]) {
@@ -1797,7 +1878,15 @@ function createPythonLlmCapability(context, service, options = {}) {
1797
1878
  request.signal.throwIfAborted();
1798
1879
  yield { type: "bytes", data: Array.from(event.data.subarray(offset, offset + chunkBytes)) };
1799
1880
  }
1800
- } else yield event;
1881
+ } else if (event.type === "text") {
1882
+ for (const text2 of textFragments(event.text, chunkBytes)) {
1883
+ request.signal.throwIfAborted();
1884
+ yield { type: "text", text: text2 };
1885
+ }
1886
+ } else {
1887
+ jsonBytes(event.response, metadataLimit);
1888
+ yield event;
1889
+ }
1801
1890
  }
1802
1891
  };
1803
1892
  return {
@@ -1820,15 +1909,41 @@ function createPythonLlmCapability(context, service, options = {}) {
1820
1909
  });
1821
1910
  }
1822
1911
  if (operation.operation !== "complete") throw new TypeError("Unsupported Python LLM operation");
1823
- const text2 = [], data = [];
1912
+ const request = await prepare(payload, signal);
1913
+ const bounded = { ...request, maxOutputBytes: Math.min(request.maxOutputBytes ?? Infinity, bufferedLimit) };
1914
+ let text2 = "", textBytes = 0, dataBytes = 0, received = 0;
1915
+ const data = [];
1824
1916
  let response = {};
1825
- for await (const value2 of events(payload, { signal })) {
1826
- const event = record(value2);
1827
- if (event.type === "text") text2.push(event.text);
1828
- else if (event.type === "bytes") for (const byte of event.data) data.push(byte);
1829
- else if (event.type === "response") response = { ...record(event.response) };
1917
+ let envelopeBytes = jsonBytes({ text: "", data: [] }, bufferedLimit);
1918
+ const admit = (size) => {
1919
+ if (size > bufferedLimit - envelopeBytes - textBytes - dataBytes) throw new RangeError("Python LLM buffered response limit exceeded");
1920
+ };
1921
+ for await (const event of service.stream(bounded)) {
1922
+ bounded.signal.throwIfAborted();
1923
+ if (++received > eventLimit) throw new RangeError("Python LLM buffered event limit exceeded");
1924
+ if (event.type === "text") {
1925
+ const size = bufferedLimit === Infinity || !event.text ? 0 : jsonBytes(event.text, bufferedLimit - envelopeBytes - textBytes - dataBytes + 2) - 2;
1926
+ admit(size);
1927
+ textBytes += size;
1928
+ if (event.text) text2 += event.text;
1929
+ } else if (event.type === "bytes") {
1930
+ let size = 0;
1931
+ if (bufferedLimit !== Infinity) for (let i = 0; i < event.data.length; i++) {
1932
+ size += String(event.data[i]).length + (data.length || i ? 1 : 0);
1933
+ admit(size);
1934
+ }
1935
+ dataBytes += size;
1936
+ for (const byte of event.data) data.push(byte);
1937
+ } else {
1938
+ jsonBytes(event.response, metadataLimit);
1939
+ const details = record(event.response);
1940
+ const size = jsonBytes({ ...details, text: "", data: [] }, bufferedLimit);
1941
+ if (size > bufferedLimit - textBytes - dataBytes) throw new RangeError("Python LLM buffered response limit exceeded");
1942
+ envelopeBytes = size;
1943
+ response = { ...details };
1944
+ }
1830
1945
  }
1831
- return { ...response, text: text2.join(""), data };
1946
+ return { ...response, text: text2, data };
1832
1947
  },
1833
1948
  stream: events
1834
1949
  };
@@ -48,11 +48,11 @@ import {
48
48
  trimImage,
49
49
  unflattenImage,
50
50
  unpremultiplyRgbaImage
51
- } from "./chunk-7JA44PVV.js";
51
+ } from "./chunk-UCI6ZQFB.js";
52
52
  import {
53
53
  PdfDocument,
54
54
  encodePng
55
- } from "./chunk-BAUGDXLZ.js";
55
+ } from "./chunk-S3SCPBHC.js";
56
56
  import {
57
57
  createLuaFilterCapability
58
58
  } from "./chunk-Y2KHC6TZ.js";
@@ -32422,7 +32422,7 @@ function evaluateContentStreamToDisplayList(params) {
32422
32422
  const [x, y] = transformPoint(st.ctm, seg.x, seg.y);
32423
32423
  transformedSegments.push({ kind: "cubic", x1, y1, x2, y2, x, y });
32424
32424
  } else if (seg.kind === "rect") {
32425
- if (hasRotOrShear) {
32425
+ if (hasRotOrShear || seg.width * st.ctm[0] < 0 || seg.height * st.ctm[3] < 0) {
32426
32426
  const [p0x, p0y] = transformPoint(st.ctm, seg.x, seg.y);
32427
32427
  const [p1x, p1y] = transformPoint(st.ctm, seg.x + seg.width, seg.y);
32428
32428
  const [p2x, p2y] = transformPoint(st.ctm, seg.x + seg.width, seg.y + seg.height);
@@ -32455,7 +32455,12 @@ function evaluateContentStreamToDisplayList(params) {
32455
32455
  transformedSegments.push({ kind: "close" });
32456
32456
  }
32457
32457
  }
32458
- if (node.clip && transformedSegments.length > 0) {
32458
+ const applyClip = () => {
32459
+ if (!node.clip) return;
32460
+ st.clipPaths = [...st.clipPaths ?? [], {
32461
+ segments: transformedSegments,
32462
+ fillRule: node.clip === "W*" ? "evenodd" : "nonzero"
32463
+ }];
32459
32464
  let cMinX = Infinity, cMinY = Infinity, cMaxX = -Infinity, cMaxY = -Infinity;
32460
32465
  for (const s of transformedSegments) {
32461
32466
  if (s.kind === "move" || s.kind === "line") {
@@ -32483,8 +32488,11 @@ function evaluateContentStreamToDisplayList(params) {
32483
32488
  Math.min(st.clipRect[3], cMaxY)
32484
32489
  ] : [cMinX, cMinY, cMaxX, cMaxY];
32485
32490
  }
32491
+ };
32492
+ if (node.paint === "n") {
32493
+ applyClip();
32494
+ break;
32486
32495
  }
32487
- if (node.paint === "n") break;
32488
32496
  const isFill = ["f", "F", "f*", "B", "B*", "b", "b*"].includes(node.paint);
32489
32497
  const isStroke = ["S", "s", "B", "B*", "b", "b*"].includes(node.paint);
32490
32498
  let evaluatedFillPattern = false;
@@ -32617,7 +32625,10 @@ function evaluateContentStreamToDisplayList(params) {
32617
32625
  }
32618
32626
  }
32619
32627
  }
32620
- if (evaluatedFillPattern && !isStroke) break;
32628
+ if (evaluatedFillPattern && !isStroke) {
32629
+ applyClip();
32630
+ break;
32631
+ }
32621
32632
  const fillRule = node.paint.includes("*") ? "evenodd" : "nonzero";
32622
32633
  const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
32623
32634
  const scaledStrokeWidth = st.strokeWidth === 0 ? 0 : st.strokeWidth * ctmScale;
@@ -32637,6 +32648,7 @@ function evaluateContentStreamToDisplayList(params) {
32637
32648
  ...st.dashPhase !== void 0 ? { dashPhase: st.dashPhase } : {},
32638
32649
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
32639
32650
  } });
32651
+ applyClip();
32640
32652
  break;
32641
32653
  }
32642
32654
  case "xobject": {
@@ -34745,8 +34757,8 @@ function segmentsToScreenEdges(segments, pageHeight, scale, closeSubpaths = fals
34745
34757
  if (closeSubpaths && hasOpenSubpath && (curX !== startX || curY !== startY)) {
34746
34758
  edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
34747
34759
  }
34748
- const [rx0, ry0] = toScreen(seg.x, seg.y + seg.height);
34749
- const [rx1, ry1] = toScreen(seg.x + seg.width, seg.y);
34760
+ const [rx0, ry0] = toScreen(seg.x, seg.y);
34761
+ const [rx1, ry1] = toScreen(seg.x + seg.width, seg.y + seg.height);
34750
34762
  edges.push(
34751
34763
  { x0: rx0, y0: ry0, x1: rx1, y1: ry0 },
34752
34764
  { x0: rx1, y0: ry0, x1: rx1, y1: ry1 },
@@ -34889,21 +34901,24 @@ function renderDisplayListToBitmap(displayList, options = {}) {
34889
34901
  }
34890
34902
  const aaVec = options.antialiasVector !== false;
34891
34903
  const aaTxt = options.antialiasText !== false;
34892
- const clipMasks = /* @__PURE__ */ new Map();
34904
+ let cachedClips;
34905
+ let cachedClipMask;
34893
34906
  const imageClipMasks = /* @__PURE__ */ new Map();
34894
34907
  for (const original of paintOperations(displayList)) {
34895
34908
  if (original.kind === "glyph" && (original.value.renderMode === 3 || !original.value.outline && !original.value.unicode.trim())) continue;
34896
34909
  const operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
34897
34910
  const clips = original.value.clipPaths;
34898
- let clipMask = clips ? clipMasks.get(clips) : void 0;
34911
+ let clipMask = clips && clips === cachedClips ? cachedClipMask : void 0;
34899
34912
  if (clips && !clipMask) {
34900
34913
  clipMask = new Uint8Array(width * height * 4).fill(255);
34901
- for (const segments of clips) {
34914
+ for (const clip of clips) {
34915
+ const { segments, fillRule } = "segments" in clip ? clip : { segments: clip, fillRule: "nonzero" };
34902
34916
  const layer = new Uint8Array(width * height * 4);
34903
- fillEdgesScanline4x4(layer, width, height, segmentsToScreenEdges(segments, displayList.height, scale, true), { r: 1, g: 1, b: 1 });
34917
+ fillEdgesScanline4x4(layer, width, height, segmentsToScreenEdges(segments, displayList.height, scale, true), { r: 1, g: 1, b: 1 }, 1, fillRule);
34904
34918
  for (let i = 3; i < layer.length; i += 4) clipMask[i] = Math.round(clipMask[i] * layer[i] / 255);
34905
34919
  }
34906
- clipMasks.set(clips, clipMask);
34920
+ cachedClips = clips;
34921
+ cachedClipMask = clipMask;
34907
34922
  }
34908
34923
  const imageClips = original.value.clipImages;
34909
34924
  if (imageClips) {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  PdfDocument,
3
3
  renderPdfPageToPng
4
- } from "./chunk-BAUGDXLZ.js";
4
+ } from "./chunk-S3SCPBHC.js";
5
5
  import {
6
6
  init_buffer
7
7
  } from "./chunk-HX3SHTCE.js";
@@ -16,7 +16,7 @@ import {
16
16
  pythonCommands,
17
17
  pythonDocumentPackages,
18
18
  pythonHostFailureCode
19
- } from "../../chunks/chunk-AYPUGSOV.js";
19
+ } from "../../chunks/chunk-CRQDMBQA.js";
20
20
  import {
21
21
  PythonFailure,
22
22
  inspectPythonCapabilities
@@ -4,7 +4,7 @@ import { type PythonDiagnosticObserver } from './diagnostics.js';
4
4
  import { createPythonHostBridge, type PythonHostCapability, type PythonHostBridgeOptions } from './host-capabilities.js';
5
5
  export * from './host-capabilities.js';
6
6
  export { createPythonShellCapability } from './shell-capability.js';
7
- export { createPythonLlmCapability } from './llm-capability.js';
7
+ export { createPythonLlmCapability, type PythonLlmCapabilityOptions } from './llm-capability.js';
8
8
  /** A dedicated interpreter worker. The service event loop must never block. */
9
9
  export interface PythonWorkerEndpoint {
10
10
  postMessage(value: unknown): void;