@poe-platform/safe-bash 0.1.827 → 0.1.829

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 (55) hide show
  1. package/dist/safe-bash/chunks/{chunk-VWLQDZFF.js → chunk-C7RBTLYX.js} +12 -5
  2. package/dist/safe-bash/chunks/{chunk-TZRVK3NU.js → chunk-HWYINF6Y.js} +1 -1
  3. package/dist/safe-bash/chunks/{chunk-ZJAXMB5M.js → chunk-SGHFQIZB.js} +1 -1
  4. package/dist/safe-bash/chunks/{chunk-RAFD5ZAH.js → chunk-Y67A2DE4.js} +1 -1
  5. package/dist/safe-bash/command-chunks/{chunk-HQIZR6EU.js → chunk-2EEIB5O3.js} +3 -3
  6. package/dist/safe-bash/command-chunks/{chunk-YSCKOUQP.js → chunk-3ZCABR5P.js} +1 -1
  7. package/dist/safe-bash/command-chunks/{chunk-O3FTKLWR.js → chunk-BXOBM4HJ.js} +26 -17
  8. package/dist/safe-bash/command-chunks/{chunk-2JRHCVMQ.js → chunk-EF3RAQ7M.js} +1 -1
  9. package/dist/safe-bash/command-chunks/{chunk-QZYEI4N6.js → chunk-EOO3NLD5.js} +1 -1
  10. package/dist/safe-bash/command-chunks/{chunk-L54KVUSY.js → chunk-KSCVKF7I.js} +3 -3
  11. package/dist/safe-bash/command-chunks/{chunk-MQCLG2CT.js → chunk-MWPL7AFP.js} +5 -1
  12. package/dist/safe-bash/command-chunks/{chunk-HUGKO4ZE.js → chunk-N63IGO5F.js} +1 -1
  13. package/dist/safe-bash/command-chunks/{chunk-N4SH6QY5.js → chunk-SIAN5LI3.js} +1 -5
  14. package/dist/safe-bash/command-chunks/{chunk-UJPWPRVB.js → chunk-U5TQVW64.js} +1 -1
  15. package/dist/safe-bash/command-chunks/{chunk-ZYXKW2K7.js → chunk-UGDQSGUZ.js} +1 -1
  16. package/dist/safe-bash/command-chunks/{chunk-VTH4AORO.js → chunk-VJXPNNBD.js} +3 -3
  17. package/dist/safe-bash/command-chunks/{chunk-7M3M6FKC.js → chunk-VQINIBCZ.js} +1 -1
  18. package/dist/safe-bash/command-chunks/{chunk-XTHKXCF2.js → chunk-YK6ZVCA2.js} +2 -2
  19. package/dist/safe-bash/command-chunks/{chunk-WKKJJBJQ.js → chunk-YR2A2L4J.js} +8 -8
  20. package/dist/safe-bash/commands/bc/index.browser.js +1 -1
  21. package/dist/safe-bash/full-core.browser.js +4 -4
  22. package/dist/safe-bash/plugins/index.browser.js +3 -3
  23. package/dist/safe-bash/registry-entry.browser.js +2 -2
  24. package/dist/safe-bash/search.browser.js +1 -1
  25. package/dist/safe-bash/shell/runtime.js +18 -7
  26. package/dist/safe-bash/shell/sync-extra-evaluators.js +2 -0
  27. package/dist/safe-bash/shell-entry.browser.js +2 -2
  28. package/dist/safe-bash-command-ffmpeg/index.js +19 -14
  29. package/dist/safe-bash-command-ffprobe/index.js +2 -2
  30. package/dist/safe-bash-command-ffprobe/media.js +2 -2
  31. package/dist/safe-bash-command-git/git_rust.wasm +0 -0
  32. package/dist/safe-bash-command-imagemagick/index.js +53 -10
  33. package/dist/safe-bash-command-python/executor.js +3 -3
  34. package/dist/safe-bash-command-python/index.js +3 -3
  35. package/dist/safe-bash-command-python/jspi.js +2 -2
  36. package/dist/safe-bash-command-python/worker.js +1 -1
  37. package/dist/safe-bash-query-engine/capture.js +3 -3
  38. package/dist/safe-bash-query-engine/delpaths.js +3 -3
  39. package/dist/safe-bash-query-engine/formats.js +2 -2
  40. package/dist/safe-bash-query-engine/index.js +10 -10
  41. package/dist/safe-bash-query-engine/indices.js +3 -3
  42. package/dist/safe-bash-query-engine/input.js +1 -1
  43. package/dist/safe-bash-query-engine/interpreter.js +9 -9
  44. package/dist/safe-bash-query-engine/query-core.js +10 -10
  45. package/dist/safe-bash-query-engine/regex.js +4 -4
  46. package/dist/safe-bash-query-engine/splits.js +5 -5
  47. package/dist/safe-bash-query-engine/values.js +2 -2
  48. package/dist/safe-playwright-cloudflare/browser-code-executor.js +2 -2
  49. package/dist/safe-playwright-cloudflare/browser-guest-source.d.ts +2 -0
  50. package/dist/safe-playwright-cloudflare/browser-guest-source.js +36 -0
  51. package/dist/safe-playwright-cloudflare/browser-run-code-contract.d.ts +1 -1
  52. package/dist/safe-playwright-cloudflare/browser-run-code-guest.generated.d.ts +1 -2
  53. package/dist/safe-playwright-cloudflare/browser-run-code-guest.generated.js +2 -2
  54. package/dist/safe-playwright-cloudflare/browser-run-code.js +4 -1
  55. package/package.json +4 -3
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  jsonFragments,
6
6
  renderJsonFragment
7
- } from "./chunk-N4SH6QY5.js";
7
+ } from "./chunk-SIAN5LI3.js";
8
8
  import {
9
9
  JqError,
10
10
  JqLimitError,
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  extendedPattern
3
- } from "./chunk-YSCKOUQP.js";
3
+ } from "./chunk-3ZCABR5P.js";
4
4
  import {
5
5
  describe
6
- } from "./chunk-7M3M6FKC.js";
6
+ } from "./chunk-VQINIBCZ.js";
7
7
  import {
8
8
  JqError,
9
9
  JqLimitError,
@@ -3,15 +3,15 @@ import {
3
3
  } from "./chunk-2IGH6JIP.js";
4
4
  import {
5
5
  splitRegex
6
- } from "./chunk-VTH4AORO.js";
6
+ } from "./chunk-VJXPNNBD.js";
7
7
  import {
8
8
  matchRegex,
9
9
  scanRegex,
10
10
  substituteRegex
11
- } from "./chunk-XTHKXCF2.js";
11
+ } from "./chunk-YK6ZVCA2.js";
12
12
  import {
13
13
  capture
14
- } from "./chunk-YSCKOUQP.js";
14
+ } from "./chunk-3ZCABR5P.js";
15
15
  import {
16
16
  fromDateIso8601,
17
17
  gmtime,
@@ -22,13 +22,13 @@ import {
22
22
  } from "./chunk-BTDSUATE.js";
23
23
  import {
24
24
  delpaths
25
- } from "./chunk-ZYXKW2K7.js";
25
+ } from "./chunk-UGDQSGUZ.js";
26
26
  import {
27
27
  formatValue
28
- } from "./chunk-HUGKO4ZE.js";
28
+ } from "./chunk-N63IGO5F.js";
29
29
  import {
30
30
  indices
31
- } from "./chunk-QZYEI4N6.js";
31
+ } from "./chunk-EOO3NLD5.js";
32
32
  import {
33
33
  binary,
34
34
  compare,
@@ -42,7 +42,7 @@ import {
42
42
  sortedKeys,
43
43
  stableSort,
44
44
  type
45
- } from "./chunk-7M3M6FKC.js";
45
+ } from "./chunk-VQINIBCZ.js";
46
46
  import {
47
47
  splitString
48
48
  } from "./chunk-BOMCPF7N.js";
@@ -51,7 +51,7 @@ import {
51
51
  measureValue,
52
52
  parseJson,
53
53
  stringify
54
- } from "./chunk-N4SH6QY5.js";
54
+ } from "./chunk-SIAN5LI3.js";
55
55
  import {
56
56
  JqError,
57
57
  JqHalt,
@@ -4,7 +4,7 @@ import {
4
4
  createBcCommands,
5
5
  settings
6
6
  } from "../../chunks/chunk-Q6XBTX6G.js";
7
- import "../../chunks/chunk-VWLQDZFF.js";
7
+ import "../../chunks/chunk-C7RBTLYX.js";
8
8
  import "../../chunks/chunk-N4CQ5E3G.js";
9
9
  import "../../chunks/chunk-EDJBO2HZ.js";
10
10
  import "../../chunks/chunk-IMOFLK26.js";
@@ -33,7 +33,7 @@ import {
33
33
  htmlqCommands,
34
34
  mmdcCommands,
35
35
  unrtfCommands
36
- } from "./chunks/chunk-ZJAXMB5M.js";
36
+ } from "./chunks/chunk-SGHFQIZB.js";
37
37
  import {
38
38
  createMikeYqCommand,
39
39
  createMikeYqCommands,
@@ -108,7 +108,7 @@ import {
108
108
  cloudflareWorkerLimits,
109
109
  mapfileExtension,
110
110
  readExtension
111
- } from "./chunks/chunk-TZRVK3NU.js";
111
+ } from "./chunks/chunk-HWYINF6Y.js";
112
112
  import "./chunks/chunk-GI7OALXO.js";
113
113
  import {
114
114
  base32Commands,
@@ -238,7 +238,7 @@ import {
238
238
  xanCommands,
239
239
  xxdCommands,
240
240
  yesCommands
241
- } from "./chunks/chunk-RAFD5ZAH.js";
241
+ } from "./chunks/chunk-Y67A2DE4.js";
242
242
  import {
243
243
  createDos2unixCommand,
244
244
  createDos2unixCommands,
@@ -619,7 +619,7 @@ import {
619
619
  readlinkCommands,
620
620
  realpathCommands,
621
621
  touchCommands
622
- } from "./chunks/chunk-VWLQDZFF.js";
622
+ } from "./chunks/chunk-C7RBTLYX.js";
623
623
  import "./chunks/chunk-N4CQ5E3G.js";
624
624
  import "./chunks/chunk-EDJBO2HZ.js";
625
625
  import {
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  agentCommands,
3
3
  createAgentCommands
4
- } from "../chunks/chunk-ZJAXMB5M.js";
4
+ } from "../chunks/chunk-SGHFQIZB.js";
5
5
  import "../chunks/chunk-XDDXXCBG.js";
6
6
  import {
7
7
  baseAgentCommands
8
- } from "../chunks/chunk-RAFD5ZAH.js";
8
+ } from "../chunks/chunk-Y67A2DE4.js";
9
9
  import "../chunks/chunk-Z6R76REA.js";
10
10
  import "../chunks/chunk-5ICB3H25.js";
11
11
  import "../chunks/chunk-GXEFNZGD.js";
@@ -32,7 +32,7 @@ import "../chunks/chunk-ESH5MDQR.js";
32
32
  import "../chunks/chunk-4KYUJ3GC.js";
33
33
  import "../chunks/chunk-6E4SGHLU.js";
34
34
  import "../chunks/chunk-LFKUWFZT.js";
35
- import "../chunks/chunk-VWLQDZFF.js";
35
+ import "../chunks/chunk-C7RBTLYX.js";
36
36
  import "../chunks/chunk-N4CQ5E3G.js";
37
37
  import "../chunks/chunk-EDJBO2HZ.js";
38
38
  import "../chunks/chunk-IMOFLK26.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  baseAgentCommands
3
- } from "./chunks/chunk-RAFD5ZAH.js";
3
+ } from "./chunks/chunk-Y67A2DE4.js";
4
4
  import "./chunks/chunk-Z6R76REA.js";
5
5
  import "./chunks/chunk-5ICB3H25.js";
6
6
  import "./chunks/chunk-GXEFNZGD.js";
@@ -26,7 +26,7 @@ import "./chunks/chunk-F76MF5GT.js";
26
26
  import {
27
27
  createBoundedRegexProvider
28
28
  } from "./chunks/chunk-LFKUWFZT.js";
29
- import "./chunks/chunk-VWLQDZFF.js";
29
+ import "./chunks/chunk-C7RBTLYX.js";
30
30
  import "./chunks/chunk-N4CQ5E3G.js";
31
31
  import "./chunks/chunk-EDJBO2HZ.js";
32
32
  import "./chunks/chunk-IMOFLK26.js";
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunks/chunk-LFKUWFZT.js";
7
7
  import {
8
8
  Shell
9
- } from "./chunks/chunk-VWLQDZFF.js";
9
+ } from "./chunks/chunk-C7RBTLYX.js";
10
10
  import "./chunks/chunk-N4CQ5E3G.js";
11
11
  import "./chunks/chunk-EDJBO2HZ.js";
12
12
  import "./chunks/chunk-IMOFLK26.js";
@@ -3467,6 +3467,8 @@ export class Runtime {
3467
3467
  const binding = arrayStore(state)?.get(resolved);
3468
3468
  const selector = name.slice(bracket + 1, -1);
3469
3469
  const entries = this.presenceArrayEntries(state, resolved);
3470
+ if (!binding?.associative && (selector === "@" || selector === "*"))
3471
+ return entries ? entries.length > 0 : binding ? binding.values.size > 0 : this.variable(state, base) !== undefined;
3470
3472
  const store = requireArrays(state);
3471
3473
  try {
3472
3474
  // Supplied associative selectors have already undergone word expansion.
@@ -6066,7 +6068,8 @@ export class Runtime {
6066
6068
  this.rethrowArithmeticControl(error);
6067
6069
  if (io.execution)
6068
6070
  io.execution.arithmeticDiagnostic = true;
6069
- throw new PublicDiagnostic(`((: ${message(error, this.budget.onInternalError)}`);
6071
+ await this.diagnostic(io, `((: ${message(error, this.budget.onInternalError)}`);
6072
+ status = 1;
6070
6073
  }
6071
6074
  }
6072
6075
  else if (command.kind === "subshell") {
@@ -11970,17 +11973,25 @@ export class Runtime {
11970
11973
  }, references);
11971
11974
  captureIO.descriptors.set(1, { output: captureIO.stdout, lifetime });
11972
11975
  try {
11973
- state.substitutionStatus = fileShortcut ? await this.runCommandIsolated(command, child, captureIO, true) : await this.run(part.script, child, captureIO);
11976
+ state.substitutionStatus = fileShortcut
11977
+ ? await this.finishShell(child, captureIO, await this.runCommandIsolated(command, child, captureIO, true))
11978
+ : await this.run(part.script, child, captureIO);
11974
11979
  }
11975
11980
  finally {
11976
11981
  try {
11977
- if (!references.closeSyncIfEmpty())
11978
- await references.close();
11979
- if (!lifetime.releaseSyncIfIdle())
11980
- await lifetime.release();
11982
+ if (!this.releaseExtensionsSyncIfEmpty(child))
11983
+ await this.releaseExtensions(child);
11981
11984
  }
11982
11985
  finally {
11983
- stateMonitor(child)?.closeValues();
11986
+ try {
11987
+ if (!references.closeSyncIfEmpty())
11988
+ await references.close();
11989
+ if (!lifetime.releaseSyncIfIdle())
11990
+ await lifetime.release();
11991
+ }
11992
+ finally {
11993
+ stateMonitor(child)?.closeValues();
11994
+ }
11984
11995
  }
11985
11996
  }
11986
11997
  const pendingCapture = lifetime.settled();
@@ -4762,6 +4762,8 @@ const syncExtraRuntimeMethods = {
4762
4762
  if (bracket < 0)
4763
4763
  return entries ? entries[0] !== undefined : this.variable(state, base) !== undefined;
4764
4764
  const selector = name.slice(bracket + 1, -1);
4765
+ if (!binding?.associative && (selector === "@" || selector === "*"))
4766
+ return entries ? entries.length > 0 : binding ? binding.values.size > 0 : this.variable(state, base) !== undefined;
4765
4767
  if (binding?.associative) {
4766
4768
  if (!suppliedSubscript || selector.length > 4096)
4767
4769
  return undefined;
@@ -2,14 +2,14 @@ import {
2
2
  cloudflareWorkerLimits,
3
3
  mapfileExtension,
4
4
  readExtension
5
- } from "./chunks/chunk-TZRVK3NU.js";
5
+ } from "./chunks/chunk-HWYINF6Y.js";
6
6
  import "./chunks/chunk-GI7OALXO.js";
7
7
  import {
8
8
  Shell,
9
9
  ShellLimitError,
10
10
  ShellSyntaxError,
11
11
  parseShell
12
- } from "./chunks/chunk-VWLQDZFF.js";
12
+ } from "./chunks/chunk-C7RBTLYX.js";
13
13
  import "./chunks/chunk-N4CQ5E3G.js";
14
14
  import "./chunks/chunk-EDJBO2HZ.js";
15
15
  import "./chunks/chunk-IMOFLK26.js";
@@ -20,7 +20,7 @@ import {
20
20
  sliceMp4,
21
21
  srtAst,
22
22
  webvttAst
23
- } from "../safe-bash/command-chunks/chunk-O3FTKLWR.js";
23
+ } from "../safe-bash/command-chunks/chunk-BXOBM4HJ.js";
24
24
  import "../safe-bash/command-chunks/chunk-65DS4IOB.js";
25
25
 
26
26
  // packages/safe-bash-command-ffmpeg/src/index.ts
@@ -652,15 +652,17 @@ async function applyVideoFilterChain(frames, filterChainStr, budget, subtitleCue
652
652
  } else if (name === "subtitles") {
653
653
  const cues = subtitleCues ?? [];
654
654
  current = await mapWork(current, async (f) => {
655
- const active = cues.filter((c) => f.ptsSeconds >= c.startSec && f.ptsSeconds <= c.endSec);
655
+ const active = cues.filter((c) => f.ptsSeconds >= c.startSec && f.ptsSeconds < c.endSec);
656
656
  if (active.length === 0) return f;
657
657
  const cueStr = active.map((c) => c.text).join("\n");
658
658
  return {
659
659
  ...f,
660
660
  data: await renderBitmapTextToRgba(f.data, f.width, f.height, cueStr, {
661
661
  xExpr: "(w-text_w)/2",
662
- yExpr: "h-text_h-4",
663
- fontSize: 10,
662
+ // FFmpeg's default SRT style uses a 16-point font and 10-point
663
+ // vertical margin on a 288-pixel reference canvas.
664
+ yExpr: `h-text_h-${Math.max(4, Math.round(10 * f.height / 288))}`,
665
+ fontSize: 16 * f.height / 288,
664
666
  fontColor: [255, 255, 255, 255],
665
667
  drawBox: true,
666
668
  boxColor: [0, 0, 0, 180]
@@ -1727,15 +1729,25 @@ function createFfmpegCommand(options = {}) {
1727
1729
  ...workingDoc,
1728
1730
  tracks: await mapWork(workingDoc.tracks, async (t) => {
1729
1731
  if (t.type !== "video") return t;
1732
+ let presentationOffset = 0;
1733
+ for (const edit of t.editList ?? []) {
1734
+ if (edit.mediaTime < 0) presentationOffset -= edit.segmentDuration / workingDoc.timescale;
1735
+ else {
1736
+ presentationOffset += edit.mediaTime / t.timescale;
1737
+ break;
1738
+ }
1739
+ }
1740
+ const offsetTicks = Math.round(presentationOffset * t.timescale);
1730
1741
  const decoded = await ensureDecodedFrames(t, budget, context.signal);
1731
- const filtered = await applyVideoFilterChain(decoded, combinedChain, budget, loadedSubtitleCues, context.signal);
1742
+ const displayed = decoded.map((frame) => ({ ...frame, ptsSeconds: (Math.round(frame.ptsSeconds * t.timescale) - offsetTicks) / t.timescale }));
1743
+ const filtered = await applyVideoFilterChain(displayed, combinedChain, budget, loadedSubtitleCues, context.signal);
1732
1744
  const first = filtered[0];
1733
1745
  return {
1734
1746
  ...t,
1735
1747
  width: first?.width ?? t.width,
1736
1748
  height: first?.height ?? t.height,
1737
1749
  samples: [],
1738
- decodedVideoFrames: filtered
1750
+ decodedVideoFrames: filtered.map((frame) => ({ ...frame, ptsSeconds: (Math.round(frame.ptsSeconds * t.timescale) + offsetTicks) / t.timescale }))
1739
1751
  };
1740
1752
  }, context.signal)
1741
1753
  };
@@ -1771,6 +1783,7 @@ function createFfmpegCommand(options = {}) {
1771
1783
  tracks: await mapWork(workingDoc.tracks, async (t) => {
1772
1784
  let work = 0;
1773
1785
  if (t.type !== "audio") return t;
1786
+ if (!t.decodedAudio) throw new Error("Audio filtering requires decoded PCM audio");
1774
1787
  const origRate = t.decodedAudio?.sampleRate ?? t.codecDescriptions[0]?.sampleRate ?? t.timescale ?? 44100;
1775
1788
  const origCh = t.decodedAudio?.channels ?? t.codecDescriptions[0]?.channels ?? 2;
1776
1789
  const targetRate = audioRate ?? origRate;
@@ -1818,14 +1831,6 @@ function createFfmpegCommand(options = {}) {
1818
1831
  const srcIdx = Math.min(srcCh.length - 1, Math.floor(i / targetSamples * srcCh.length));
1819
1832
  dst[i] = Math.max(-1, Math.min(1, srcCh[srcIdx] * volFactor));
1820
1833
  }
1821
- } else {
1822
- for (let i = 0; i < targetSamples; i++) {
1823
- if (++work % 1024 === 0) {
1824
- await yieldTurn(context.signal);
1825
- context.signal?.throwIfAborted();
1826
- }
1827
- dst[i] = Math.sin(2 * Math.PI * 440 * i / targetRate) * 0.2 * volFactor;
1828
- }
1829
1834
  }
1830
1835
  if (reverseAudio) dst.reverse();
1831
1836
  newChannelData.push(dst);
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  createFfprobeCommand
3
- } from "../safe-bash/command-chunks/chunk-MQCLG2CT.js";
3
+ } from "../safe-bash/command-chunks/chunk-MWPL7AFP.js";
4
4
  import "../safe-bash/command-chunks/chunk-MGBHGZEX.js";
5
- import "../safe-bash/command-chunks/chunk-O3FTKLWR.js";
5
+ import "../safe-bash/command-chunks/chunk-BXOBM4HJ.js";
6
6
  import "../safe-bash/command-chunks/chunk-65DS4IOB.js";
7
7
 
8
8
  // packages/safe-bash-command-ffprobe/src/index.ts
@@ -11,9 +11,9 @@ import {
11
11
  loadManifestResources,
12
12
  resolvePath,
13
13
  rethrowRuntimeError
14
- } from "../safe-bash/command-chunks/chunk-MQCLG2CT.js";
14
+ } from "../safe-bash/command-chunks/chunk-MWPL7AFP.js";
15
15
  import "../safe-bash/command-chunks/chunk-MGBHGZEX.js";
16
- import "../safe-bash/command-chunks/chunk-O3FTKLWR.js";
16
+ import "../safe-bash/command-chunks/chunk-BXOBM4HJ.js";
17
17
  import "../safe-bash/command-chunks/chunk-65DS4IOB.js";
18
18
  export {
19
19
  createFfprobeCommand,
@@ -4207,6 +4207,14 @@ function* magickDrawSteps(img, drawCmd, state) {
4207
4207
  stroke = rgbaToCss(parseColor(tokens[i++] ?? "#000000"));
4208
4208
  } else if (cmd === "stroke-width" || cmd === "strokewidth") {
4209
4209
  strokeWidth = Math.max(0, num());
4210
+ } else if (cmd === "color") {
4211
+ const x = num(), y = num(), method = tokens[i++]?.toLowerCase();
4212
+ if (method !== "floodfill" || !Number.isFinite(x) || !Number.isFinite(y)) throw new Error("Color drawing requires finite coordinates and the floodfill method");
4213
+ if (svgElements.length > 0) {
4214
+ yield { kind: "svg", svg: `<svg xmlns="http://www.w3.org/2000/svg" width="${img.width}" height="${img.height}">${svgElements.join("")}</svg>` };
4215
+ svgElements.length = 0;
4216
+ }
4217
+ yield { kind: "floodfill", x: Math.max(0, Math.min(img.width - 1, Math.round(x))), y: Math.max(0, Math.min(img.height - 1, Math.round(y))), color: parseColor(fill) };
4210
4218
  } else if (cmd === "rectangle") {
4211
4219
  const x0 = num();
4212
4220
  const y0 = num();
@@ -4330,9 +4338,9 @@ function* annotatePixelSteps(img, offsetStr, text, state) {
4330
4338
  const fontSize = Math.max(8, state.pointsize);
4331
4339
  const estW = Math.max(8, Math.ceil(text.length * fontSize * 0.6));
4332
4340
  const estH = Math.max(8, Math.ceil(fontSize));
4333
- const gravOff = resolveGravityOffset(img.width - estW, img.height - estH, state.gravity);
4334
- const x = Math.max(0, Math.round(gravOff.left + g.x));
4335
- const y = Math.max(fontSize, Math.round(gravOff.top + estH + g.y));
4341
+ const offset = gravityAdjustBox(img.width, img.height, estW, estH, g.x, g.y, state.gravity);
4342
+ const x = Math.max(0, offset.x);
4343
+ const y = Math.max(fontSize, offset.y + estH);
4336
4344
  const scale = (state.density || 72) / 72;
4337
4345
  const effFontSize = Math.max(6, fontSize * scale);
4338
4346
  const glyphH = Math.max(7, Math.round(effFontSize * 0.76));
@@ -5698,6 +5706,7 @@ function* evaluatePipelineTokensSteps(tokens, files, state, parentStack = [], st
5698
5706
  continue;
5699
5707
  }
5700
5708
  if (step.kind === "shape") im = yield* applyMagickRasterSteps(im, drawShapePixelSteps(im, step), signal);
5709
+ else if (step.kind === "floodfill") im = yield* applyMagickFloodfillSteps(im, `+${step.x}+${step.y}`, void 0, step.color, state.fuzz, signal);
5701
5710
  else {
5702
5711
  const overlay = decodeImage3(new TextEncoder().encode(step.svg), { density: state.density });
5703
5712
  im = yield* applyMagickRasterSteps(im, drawOverlayPixelSteps(im, overlay), signal, im, [im, overlay]);
@@ -6458,6 +6467,7 @@ async function tryConvertFiles(argv, input, stdinBytes, signal) {
6458
6467
  continue;
6459
6468
  }
6460
6469
  if (step.kind === "shape") image = await transformStoredMagickRaster(image, backend, drawShapePixelSteps(image, step), signal);
6470
+ else if (step.kind === "floodfill") image = await floodfillStoredImage(image, backend.storage, step.x, step.y, void 0, step.color, settings.fuzz, signal);
6461
6471
  else {
6462
6472
  const overlay = await decodeStoredMagickSvg(step.svg, settings.density, backend, signal);
6463
6473
  image = await transformStoredMagickRaster(image, backend, drawOverlayPixelSteps(image, overlay), signal, image, [image, overlay]);
@@ -7319,6 +7329,8 @@ function* parseMontageArguments(argv) {
7319
7329
  let padY = 2;
7320
7330
  let borderW = 0;
7321
7331
  const operands = [];
7332
+ const labels = [];
7333
+ let label = "";
7322
7334
  for (let i = 0; i < argv.length; i++) {
7323
7335
  if (++cooperativeWork % 64 === 0)
7324
7336
  yield;
@@ -7345,17 +7357,30 @@ function* parseMontageArguments(argv) {
7345
7357
  state.gravity = parseGravity(argv[++i] ?? "center");
7346
7358
  } else if (t === "-quality") {
7347
7359
  state.quality = Math.max(1, Math.min(100, Number(argv[++i] ?? 92)));
7348
- } else if (t === "-mode" || t === "-label" || t === "-title") {
7360
+ } else if (t === "-label") {
7361
+ label = argv[++i] ?? "";
7362
+ } else if (t === "+label") {
7363
+ label = "";
7364
+ } else if (t === "-set") {
7365
+ const property = argv[++i];
7366
+ const value = argv[++i] ?? "";
7367
+ if (property === "label") labels.fill(value);
7368
+ } else if (t === "-pointsize") {
7369
+ state.pointsize = Math.max(1, Number(argv[++i] ?? 12));
7370
+ } else if (t === "-fill") {
7371
+ state.fill = parseColor(argv[++i] ?? "#000000");
7372
+ } else if (t === "-mode" || t === "-title" || t === "-font") {
7349
7373
  i++;
7350
7374
  } else if (!t.startsWith("-")) {
7351
7375
  operands.push(t);
7376
+ labels.push(label);
7352
7377
  }
7353
7378
  }
7354
- return { state, tileCols, tileRows, cellW, cellH, padX, padY, borderW, operands };
7379
+ return { state, tileCols, tileRows, cellW, cellH, padX, padY, borderW, operands, labels };
7355
7380
  }
7356
7381
  function* runMontageCliSteps(argv, files, stdinBytes, signal) {
7357
7382
  let cooperativeWork = 63;
7358
- const { state, tileCols, tileRows, cellW, cellH, padX, padY, borderW, operands } = yield* parseMontageArguments(argv);
7383
+ const { state, tileCols, tileRows, cellW, cellH, padX, padY, borderW, operands, labels } = yield* parseMontageArguments(argv);
7359
7384
  if (operands.length < 2) {
7360
7385
  return {
7361
7386
  exitCode: 1,
@@ -7366,7 +7391,7 @@ function* runMontageCliSteps(argv, files, stdinBytes, signal) {
7366
7391
  const outSpec = operands[operands.length - 1];
7367
7392
  const inPaths = operands.slice(0, -1);
7368
7393
  const fastMetaDims = [];
7369
- let canStreamTiles = cellW === void 0 && cellH === void 0;
7394
+ let canStreamTiles = cellW === void 0 && cellH === void 0 && !labels.some(Boolean);
7370
7395
  if (canStreamTiles) {
7371
7396
  for (const p of inPaths) {
7372
7397
  const rawBytes = files.get(p);
@@ -7500,7 +7525,7 @@ function* runMontageCliSteps(argv, files, stdinBytes, signal) {
7500
7525
  }
7501
7526
  } else {
7502
7527
  const images = [];
7503
- for (const p of inPaths) {
7528
+ for (const [inputIndex, p] of inPaths.entries()) {
7504
7529
  yield;
7505
7530
  let loadedList;
7506
7531
  try {
@@ -7542,6 +7567,16 @@ function* runMontageCliSteps(argv, files, stdinBytes, signal) {
7542
7567
  });
7543
7568
  if (thumb !== prev) detachRgbaBuffer(prev.data);
7544
7569
  }
7570
+ if (labels[inputIndex]) {
7571
+ const text = yield* formatMagickPropertyStringSteps(labels[inputIndex], thumb, () => thumb, { filePath: parseInputToken(p).baseToken });
7572
+ const height = Math.ceil(Math.max(8, state.pointsize) * 1.4);
7573
+ const caption = decodeImage3(new TextEncoder().encode(createLabelSvg(text, { ...state, hasSize: true, sizeWidth: thumb.width, sizeHeight: height, gravity: "center" })));
7574
+ const previous = thumb;
7575
+ thumb = yield* extendImageSteps(thumb, { top: 0, bottom: height, left: 0, right: 0, background: state.background, extendWith: "background" });
7576
+ if (thumb !== previous) detachRgbaBuffer(previous.data);
7577
+ yield* blitOverRgbaInPlaceSteps(thumb, caption, 0, thumb.height - height);
7578
+ detachRgbaBuffer(caption.data);
7579
+ }
7545
7580
  images.push(thumb);
7546
7581
  }
7547
7582
  }
@@ -7602,7 +7637,7 @@ function* runMontageCliSteps(argv, files, stdinBytes, signal) {
7602
7637
  return { exitCode: 0, stdout: "", stderr: "" };
7603
7638
  }
7604
7639
  async function runMontageFiles(argv, input, stdinBytes, signal) {
7605
- const { state, tileCols, tileRows, cellW, cellH, padX, padY, borderW, operands } = await drainSteps(parseMontageArguments(argv), signal);
7640
+ const { state, tileCols, tileRows, cellW, cellH, padX, padY, borderW, operands, labels } = await drainSteps(parseMontageArguments(argv), signal);
7606
7641
  if (operands.length < 2) {
7607
7642
  await probeImageArguments(argv, input, stdinBytes, signal);
7608
7643
  return { exitCode: 1, stdout: "", stderr: "montage: missing an image filename\n" };
@@ -7610,7 +7645,7 @@ async function runMontageFiles(argv, input, stdinBytes, signal) {
7610
7645
  const outSpec = operands.at(-1), paths = operands.slice(0, -1);
7611
7646
  return withCompareFiles(input, stdinBytes, signal, async (backend) => {
7612
7647
  const sources = new IntegerTable4(backend.storage, 128), images = new StoredImageStack(backend.storage, signal);
7613
- let fast = cellW === void 0 && cellH === void 0, maxThumbW = cellW ?? 0, maxThumbH = cellH ?? 0;
7648
+ let fast = cellW === void 0 && cellH === void 0 && !labels.some(Boolean), maxThumbW = cellW ?? 0, maxThumbH = cellH ?? 0;
7614
7649
  const sourceAt = async (index) => {
7615
7650
  const size = Number(await sources.get(BigInt(index * 5 + 1)) ?? -1n);
7616
7651
  if (size < 0) return null;
@@ -7687,6 +7722,14 @@ async function runMontageFiles(argv, input, stdinBytes, signal) {
7687
7722
  if (resize) image = await transformStoredImage(image, backend.storage, { kind: "resize", ...resize }, signal);
7688
7723
  }
7689
7724
  if (borderW > 0) image = await transformStoredImage(image, backend.storage, { kind: "extend", top: borderW, bottom: borderW, left: borderW, right: borderW, background: state.borderColor, extendWith: "background" }, signal);
7725
+ if (labels[index]) {
7726
+ const labeled = image;
7727
+ const text = await formatRetainedIdentify(labels[index], image, { filePath: parseInputToken(path2).baseToken }, async () => ({ image: labeled, storage: backend.storage }), signal);
7728
+ const height = Math.ceil(Math.max(8, state.pointsize) * 1.4);
7729
+ const caption = await decodeStoredMagickSvg(createLabelSvg(text, { ...state, hasSize: true, sizeWidth: image.width, sizeHeight: height, gravity: "center" }), 72, backend, signal);
7730
+ image = await transformStoredImage(image, backend.storage, { kind: "extend", top: 0, bottom: height, left: 0, right: 0, background: state.background, extendWith: "background" }, signal);
7731
+ image = await compositeStoredMagick(image, caption, backend, signal, 0, image.height - height, "over", void 0, false, true);
7732
+ }
7690
7733
  maxThumbW = Math.max(maxThumbW, image.width);
7691
7734
  maxThumbH = Math.max(maxThumbH, image.height);
7692
7735
  await images.push(image);
@@ -14,7 +14,7 @@ import {
14
14
  installPythonLlmPackages,
15
15
  pythonExecutorCommands,
16
16
  pythonLlmPackages
17
- } from "../safe-bash/command-chunks/chunk-HQIZR6EU.js";
17
+ } from "../safe-bash/command-chunks/chunk-2EEIB5O3.js";
18
18
  import {
19
19
  PythonPackageConflictError,
20
20
  createPythonPackageCache,
@@ -33,9 +33,9 @@ import {
33
33
  } from "../safe-bash/command-chunks/chunk-IOZTDDNT.js";
34
34
  import {
35
35
  createPythonJspiExecutor
36
- } from "../safe-bash/command-chunks/chunk-UJPWPRVB.js";
36
+ } from "../safe-bash/command-chunks/chunk-U5TQVW64.js";
37
37
  import "../safe-bash/command-chunks/chunk-FXWKMNX2.js";
38
- import "../safe-bash/command-chunks/chunk-L54KVUSY.js";
38
+ import "../safe-bash/command-chunks/chunk-KSCVKF7I.js";
39
39
  import "../safe-bash/command-chunks/chunk-HS2L7I4N.js";
40
40
  import "../safe-bash/command-chunks/chunk-UCE77LYV.js";
41
41
  import {
@@ -14,7 +14,7 @@ import {
14
14
  installPythonLlmPackages,
15
15
  pythonExecutorCommands,
16
16
  pythonLlmPackages
17
- } from "../safe-bash/command-chunks/chunk-HQIZR6EU.js";
17
+ } from "../safe-bash/command-chunks/chunk-2EEIB5O3.js";
18
18
  import {
19
19
  PythonPackageConflictError,
20
20
  createPythonPackageCache,
@@ -33,9 +33,9 @@ import {
33
33
  } from "../safe-bash/command-chunks/chunk-IOZTDDNT.js";
34
34
  import {
35
35
  createPythonJspiExecutor
36
- } from "../safe-bash/command-chunks/chunk-UJPWPRVB.js";
36
+ } from "../safe-bash/command-chunks/chunk-U5TQVW64.js";
37
37
  import "../safe-bash/command-chunks/chunk-FXWKMNX2.js";
38
- import "../safe-bash/command-chunks/chunk-L54KVUSY.js";
38
+ import "../safe-bash/command-chunks/chunk-KSCVKF7I.js";
39
39
  import "../safe-bash/command-chunks/chunk-HS2L7I4N.js";
40
40
  import "../safe-bash/command-chunks/chunk-UCE77LYV.js";
41
41
  import {
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  createPythonJspiExecutor
3
- } from "../safe-bash/command-chunks/chunk-UJPWPRVB.js";
3
+ } from "../safe-bash/command-chunks/chunk-U5TQVW64.js";
4
4
  import "../safe-bash/command-chunks/chunk-FXWKMNX2.js";
5
- import "../safe-bash/command-chunks/chunk-L54KVUSY.js";
5
+ import "../safe-bash/command-chunks/chunk-KSCVKF7I.js";
6
6
  import "../safe-bash/command-chunks/chunk-HS2L7I4N.js";
7
7
  import "../safe-bash/command-chunks/chunk-UCE77LYV.js";
8
8
  import "../safe-bash/command-chunks/chunk-P56KGNW7.js";
@@ -3,7 +3,7 @@ import {
3
3
  loadPythonRuntimePrograms,
4
4
  parsePythonInvocation,
5
5
  pythonExecution
6
- } from "../safe-bash/command-chunks/chunk-L54KVUSY.js";
6
+ } from "../safe-bash/command-chunks/chunk-KSCVKF7I.js";
7
7
  import "../safe-bash/command-chunks/chunk-HS2L7I4N.js";
8
8
  import "../safe-bash/command-chunks/chunk-UCE77LYV.js";
9
9
  import {
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  capture,
3
3
  extendedPattern
4
- } from "../safe-bash/command-chunks/chunk-YSCKOUQP.js";
5
- import "../safe-bash/command-chunks/chunk-7M3M6FKC.js";
4
+ } from "../safe-bash/command-chunks/chunk-3ZCABR5P.js";
5
+ import "../safe-bash/command-chunks/chunk-VQINIBCZ.js";
6
6
  import "../safe-bash/command-chunks/chunk-BOMCPF7N.js";
7
- import "../safe-bash/command-chunks/chunk-N4SH6QY5.js";
7
+ import "../safe-bash/command-chunks/chunk-SIAN5LI3.js";
8
8
  import "../safe-bash/command-chunks/chunk-3K5FCRUG.js";
9
9
  import "../safe-bash/command-chunks/chunk-KK2T6Z7J.js";
10
10
  import "../safe-bash/command-chunks/chunk-V72MXW7X.js";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  delpaths
3
- } from "../safe-bash/command-chunks/chunk-ZYXKW2K7.js";
4
- import "../safe-bash/command-chunks/chunk-7M3M6FKC.js";
3
+ } from "../safe-bash/command-chunks/chunk-UGDQSGUZ.js";
4
+ import "../safe-bash/command-chunks/chunk-VQINIBCZ.js";
5
5
  import "../safe-bash/command-chunks/chunk-BOMCPF7N.js";
6
- import "../safe-bash/command-chunks/chunk-N4SH6QY5.js";
6
+ import "../safe-bash/command-chunks/chunk-SIAN5LI3.js";
7
7
  import "../safe-bash/command-chunks/chunk-3K5FCRUG.js";
8
8
  import "../safe-bash/command-chunks/chunk-KK2T6Z7J.js";
9
9
  import "../safe-bash/command-chunks/chunk-V72MXW7X.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  formatValue
3
- } from "../safe-bash/command-chunks/chunk-HUGKO4ZE.js";
4
- import "../safe-bash/command-chunks/chunk-N4SH6QY5.js";
3
+ } from "../safe-bash/command-chunks/chunk-N63IGO5F.js";
4
+ import "../safe-bash/command-chunks/chunk-SIAN5LI3.js";
5
5
  import "../safe-bash/command-chunks/chunk-3K5FCRUG.js";
6
6
  import "../safe-bash/command-chunks/chunk-KK2T6Z7J.js";
7
7
  import "../safe-bash/command-chunks/chunk-V72MXW7X.js";