@poe-platform/safe-bash 0.1.745 → 0.1.747

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 (59) hide show
  1. package/README.md +5 -1
  2. package/dist/image-ast/browser/sharp.d.ts +1 -1
  3. package/dist/image-ast/index.js +133 -35
  4. package/dist/image-ast/sharp.d.ts +1 -1
  5. package/dist/safe-bash/chunks/{chunk-2F7Q532M.js → chunk-4GK4FAT6.js} +3 -3
  6. package/dist/safe-bash/chunks/{chunk-EAUCLWEZ.js → chunk-55AGFLG5.js} +540 -284
  7. package/dist/safe-bash/chunks/{chunk-WCNFCN2G.js → chunk-BS6QFRNX.js} +2 -2
  8. package/dist/safe-bash/chunks/{chunk-IZZ7KX4E.js → chunk-JCXAGOEK.js} +40 -3
  9. package/dist/safe-bash/chunks/{chunk-I3DOFJSJ.js → chunk-MUWJPSGN.js} +2 -2
  10. package/dist/safe-bash/chunks/{chunk-7RP6WOWK.js → chunk-OF2PDE3W.js} +2 -2
  11. package/dist/safe-bash/chunks/{src-FTMTU65U.js → src-T672TQJC.js} +2 -2
  12. package/dist/safe-bash/command-chunks/{chunk-DRCPJVZF.js → chunk-44N2IRVP.js} +17 -5
  13. package/dist/safe-bash/command-chunks/{chunk-LYKC7WJB.js → chunk-6742OVAC.js} +37 -3
  14. package/dist/safe-bash/command-chunks/{chunk-BMBXSLVX.js → chunk-6QU5OLPJ.js} +2 -2
  15. package/dist/safe-bash/command-chunks/{chunk-YHANNN7I.js → chunk-S3BO2NJT.js} +7 -0
  16. package/dist/safe-bash/commands/basic.d.ts +2 -0
  17. package/dist/safe-bash/commands/basic.js +236 -9
  18. package/dist/safe-bash/commands/pr/index.browser.js +1 -1
  19. package/dist/safe-bash/commands/streams.js +9 -56
  20. package/dist/safe-bash/commands/table-text/index.js +5 -1
  21. package/dist/safe-bash/commands/text.js +13 -2
  22. package/dist/safe-bash/commands/time-env/shared.js +2 -2
  23. package/dist/safe-bash/commands/time-env/sleep.js +6 -4
  24. package/dist/safe-bash/commands/timeout/index.d.ts +7 -0
  25. package/dist/safe-bash/commands/timeout/index.js +52 -32
  26. package/dist/safe-bash/commands/timeout/scheduler.js +7 -6
  27. package/dist/safe-bash/core.browser.js +2698 -543
  28. package/dist/safe-bash/opt-in/commands/shuf/random.js +2 -3
  29. package/dist/safe-bash/opt-in/shell/extensions/read/index.js +1 -1
  30. package/dist/safe-bash/opt-in/shell/extensions/trap/index.d.ts +1 -2
  31. package/dist/safe-bash/opt-in/shell/extensions/trap/index.js +1 -8
  32. package/dist/safe-bash/playwright/adapter.d.ts +2 -0
  33. package/dist/safe-bash/playwright/private-target-transport.d.ts +1 -0
  34. package/dist/safe-bash/playwright/private-target-transport.js +21 -21
  35. package/dist/safe-bash/shell/runtime.d.ts +20 -1
  36. package/dist/safe-bash/shell/runtime.js +3021 -532
  37. package/dist/safe-bash/shell/sync-jq-expression.d.ts +6 -0
  38. package/dist/safe-bash/shell/sync-jq-expression.js +46 -0
  39. package/dist/safe-bash-command-cal/index.js +32 -12
  40. package/dist/safe-bash-command-hostname/index.js +22 -7
  41. package/dist/safe-bash-command-id/index.js +28 -9
  42. package/dist/safe-bash-command-pandoc/command.js +1 -1
  43. package/dist/safe-bash-command-pandoc/index.js +1 -1
  44. package/dist/safe-bash-command-ssconvert/command.d.ts +2 -2
  45. package/dist/safe-bash-command-ssconvert/contracts.d.ts +4 -0
  46. package/dist/safe-bash-command-ssconvert/engine.d.ts +2 -2
  47. package/dist/safe-bash-command-ssconvert/index.js +524 -276
  48. package/dist/safe-bash-command-whoami/index.js +26 -12
  49. package/dist/safe-bash-query-engine/index.js +3 -3
  50. package/dist/safe-bash-query-engine/interpreter.js +1 -1
  51. package/dist/safe-bash-query-engine/parser.js +1 -1
  52. package/dist/safe-bash-query-engine/query-core.js +3 -3
  53. package/dist/safe-playwright-cloudflare/browser-private-transport.js +8 -13
  54. package/dist/safe-playwright-cloudflare/browser-storage-control.js +13 -4
  55. package/dist/safe-playwright-cloudflare/browser-trace-archive.js +1 -1
  56. package/package.json +18 -14
  57. package/dist/image-ast/streams/node.d.ts +0 -10
  58. package/dist/image-ast/streams/node.js +0 -5
  59. package/dist/image-ast/streams/web.js +0 -94
@@ -0,0 +1,6 @@
1
+ /** Scan only the grammar boundaries needed by the synchronous jq subset. */
2
+ export declare function splitSyncJqExpression(expression: string, separator: string): {
3
+ parts: string[];
4
+ wrapped: boolean;
5
+ } | undefined;
6
+ //# sourceMappingURL=sync-jq-expression.d.ts.map
@@ -0,0 +1,46 @@
1
+ /** Scan only the grammar boundaries needed by the synchronous jq subset. */
2
+ export function splitSyncJqExpression(expression, separator) {
3
+ const parts = [];
4
+ const stack = [];
5
+ let quoted = false;
6
+ let escaped = false;
7
+ let start = 0;
8
+ let wrapped = expression.startsWith("(");
9
+ for (let i = 0; i < expression.length; i++) {
10
+ const ch = expression[i];
11
+ if (quoted) {
12
+ if (escaped)
13
+ escaped = false;
14
+ else if (ch === "\\")
15
+ escaped = true;
16
+ else if (ch === '"')
17
+ quoted = false;
18
+ continue;
19
+ }
20
+ if (ch === '"') {
21
+ quoted = true;
22
+ continue;
23
+ }
24
+ if (ch === "(" || ch === "[" || ch === "{") {
25
+ stack.push(ch === "(" ? ")" : ch === "[" ? "]" : "}");
26
+ continue;
27
+ }
28
+ if (ch === ")" || ch === "]" || ch === "}") {
29
+ if (stack.pop() !== ch)
30
+ return undefined;
31
+ if (stack.length === 0 && i !== expression.length - 1)
32
+ wrapped = false;
33
+ continue;
34
+ }
35
+ if (stack.length === 0 && expression.startsWith(separator, i)) {
36
+ parts.push(expression.slice(start, i).trim());
37
+ i += separator.length - 1;
38
+ start = i + 1;
39
+ }
40
+ }
41
+ if (quoted || stack.length > 0)
42
+ return undefined;
43
+ parts.push(expression.slice(start).trim());
44
+ return { parts, wrapped };
45
+ }
46
+ //# sourceMappingURL=sync-jq-expression.js.map
@@ -4,6 +4,7 @@ import {
4
4
 
5
5
  // packages/safe-bash-command-cal/dist/index.js
6
6
  init_buffer();
7
+ import { yieldTurn } from "../safe-bash-contracts/yield.js";
7
8
  import { commandRuntimeIdentity, writeText } from "../safe-bash-contracts/index.js";
8
9
  function settings(options = {}) {
9
10
  const limits = {
@@ -235,6 +236,7 @@ function createCalCommand(options = {}) {
235
236
  name: "cal",
236
237
  runtimeIdentity: commandRuntimeIdentity,
237
238
  async execute(context) {
239
+ context.signal.throwIfAborted();
238
240
  const rawArgs = context.args;
239
241
  let totalArgBytes = 0;
240
242
  for (const a of rawArgs) {
@@ -315,16 +317,24 @@ function createCalCommand(options = {}) {
315
317
  } else if (arg === "-n" || arg === "--months") {
316
318
  const val = rawArgs[++i];
317
319
  const n = Number(val);
318
- if (!val || !Number.isInteger(n) || n < 1 || n > lim.maxMonths) {
320
+ if (!val || !Number.isSafeInteger(n) || n < 1 || n > lim.maxMonths) {
319
321
  await writeText(context.stderr, `cal: invalid month count '${val ?? ""}'
320
322
  `);
321
323
  return { exitCode: 1 };
322
324
  }
323
325
  spanMonths = n;
324
- } else if (arg === "-A") {
325
- afterMonths = Math.max(0, Number(rawArgs[++i] ?? 0));
326
- } else if (arg === "-B") {
327
- beforeMonths = Math.max(0, Number(rawArgs[++i] ?? 0));
326
+ } else if (arg === "-A" || arg === "-B") {
327
+ const val = rawArgs[++i];
328
+ const count2 = Number(val);
329
+ if (!val || !Number.isSafeInteger(count2) || count2 < 0) {
330
+ await writeText(context.stderr, `cal: invalid month count '${val ?? ""}'
331
+ `);
332
+ return { exitCode: 1 };
333
+ }
334
+ if (arg === "-A")
335
+ afterMonths = count2;
336
+ else
337
+ beforeMonths = count2;
328
338
  } else if (arg.startsWith("-") && arg.length > 1) {
329
339
  for (let j = 1; j < arg.length; j++) {
330
340
  const ch = arg[j];
@@ -426,24 +436,31 @@ function createCalCommand(options = {}) {
426
436
  await writeText(context.stderr, "cal: too many arguments\n");
427
437
  return { exitCode: 1 };
428
438
  }
439
+ const count = wholeYear ? 12 : spanMonths;
440
+ if (!Number.isSafeInteger(count) || count > lim.maxMonths) {
441
+ await writeText(context.stderr, "cal: month count exceeds size limit\n");
442
+ return { exitCode: 1 };
443
+ }
429
444
  const gridWidth = julian ? 27 : 20;
430
445
  const perRow = julian ? 2 : 3;
431
446
  if (verticalLayout) {
432
- const count = wholeYear ? 12 : spanMonths;
433
447
  const offset = wholeYear ? 0 : beforeMonths || (spanAround ? Math.floor((spanMonths - 1) / 2) : 0);
434
448
  const first = year * 12 + (wholeYear ? 0 : month - 1) - offset;
435
- const grids2 = Array.from({ length: count }, (_, index) => {
449
+ const grids2 = [];
450
+ for (let index = 0; index < count; index++) {
451
+ await yieldTurn(context.signal);
436
452
  const total = first + index;
437
- return renderVerticalNcalMonth(Math.floor(total / 12), total % 12 + 1, {
453
+ grids2.push(renderVerticalNcalMonth(Math.floor(total / 12), (total % 12 + 12) % 12 + 1, {
438
454
  mondayFirst,
439
455
  julian,
440
456
  includeYearInHeader: !wholeYear,
441
457
  showWeeks
442
- });
443
- });
458
+ }));
459
+ }
444
460
  const verticalPerRow = wholeYear ? julian ? 3 : 4 : perRow;
445
461
  const lines2 = wholeYear ? [centerText(String(year), (julian ? 26 : 22) * verticalPerRow)] : [];
446
462
  for (let start = 0; start < grids2.length; start += verticalPerRow) {
463
+ await yieldTurn(context.signal);
447
464
  const group = grids2.slice(start, start + verticalPerRow);
448
465
  for (let line = 0; line < group[0].length; line++) {
449
466
  lines2.push(group.map((grid, index) => {
@@ -461,6 +478,7 @@ function createCalCommand(options = {}) {
461
478
  if (wholeYear) {
462
479
  const lines2 = [`${" ".repeat(28)}${year}`];
463
480
  for (let startM = 1; startM <= 12; startM += perRow) {
481
+ await yieldTurn(context.signal);
464
482
  const rowMonths = [];
465
483
  for (let k = 0; k < perRow && startM + k <= 12; k++) {
466
484
  rowMonths.push(renderMonthGrid(year, startM + k, { mondayFirst, julian, includeYearInHeader: false }));
@@ -482,12 +500,12 @@ function createCalCommand(options = {}) {
482
500
  if (beforeMonths > 0) {
483
501
  const totalMonths = startYear * 12 + (startMonth - 1) - beforeMonths;
484
502
  startYear = Math.floor(totalMonths / 12);
485
- startMonth = totalMonths % 12 + 1;
503
+ startMonth = (totalMonths % 12 + 12) % 12 + 1;
486
504
  } else if (spanAround && spanMonths > 1) {
487
505
  const offset = Math.floor((spanMonths - 1) / 2);
488
506
  const totalMonths = startYear * 12 + (startMonth - 1) - offset;
489
507
  startYear = Math.floor(totalMonths / 12);
490
- startMonth = totalMonths % 12 + 1;
508
+ startMonth = (totalMonths % 12 + 12) % 12 + 1;
491
509
  }
492
510
  if (spanMonths === 1) {
493
511
  const g = renderMonthGrid(startYear, startMonth, { mondayFirst, julian, includeYearInHeader: true });
@@ -504,6 +522,7 @@ function createCalCommand(options = {}) {
504
522
  let curY = startYear;
505
523
  let curM = startMonth;
506
524
  for (let idx = 0; idx < spanMonths; idx++) {
525
+ await yieldTurn(context.signal);
507
526
  grids.push(renderMonthGrid(curY, curM, { mondayFirst, julian, includeYearInHeader: true }));
508
527
  curM++;
509
528
  if (curM > 12) {
@@ -513,6 +532,7 @@ function createCalCommand(options = {}) {
513
532
  }
514
533
  const lines = [];
515
534
  for (let r = 0; r < grids.length; r += perRow) {
535
+ await yieldTurn(context.signal);
516
536
  const slice = grids.slice(r, r + perRow);
517
537
  lines.push(slice.map((g) => g.header.padEnd(gridWidth, " ")).join(" ") + " ");
518
538
  lines.push(slice.map((g) => g.dayHeader.padEnd(gridWidth, " ")).join(" ") + " ");
@@ -4,6 +4,7 @@ import {
4
4
 
5
5
  // packages/safe-bash-command-hostname/dist/index.js
6
6
  init_buffer();
7
+ import { isFsError } from "../safe-bash-contracts/errors.js";
7
8
  import { writeFileOutput } from "../safe-bash-contracts/filesystem-output-budget.js";
8
9
  import { commandRuntimeIdentity, writeText } from "../safe-bash-contracts/index.js";
9
10
  function settings(options = {}) {
@@ -39,8 +40,9 @@ Packaged by Safe-Bash (Sandbox VFS-ish/GNU runtime)
39
40
  async function readHostnameFile(context, filePath, maxBytes) {
40
41
  const resolved = filePath.startsWith("/") ? filePath : context.cwd.endsWith("/") ? context.cwd + filePath : context.cwd + "/" + filePath;
41
42
  const bytes = await context.fs.readFile(resolved, { signal: context.signal });
43
+ context.signal.throwIfAborted();
42
44
  if (bytes.byteLength > maxBytes) {
43
- throw new Error("hostname file exceeds size limit");
45
+ throw new RangeError("hostname file exceeds size limit");
44
46
  }
45
47
  const text = new TextDecoder().decode(bytes);
46
48
  for (const line of text.split(/\r?\n/)) {
@@ -52,7 +54,7 @@ async function readHostnameFile(context, filePath, maxBytes) {
52
54
  }
53
55
  function createHostnameCommand(options = {}) {
54
56
  const limits = settings(options);
55
- let sessionHostname = options.hostname;
57
+ const sessionHostnames = /* @__PURE__ */ new WeakMap();
56
58
  return {
57
59
  name: "hostname",
58
60
  description: "Show or set the Sandbox VFS-ish/GNU hostname",
@@ -196,7 +198,10 @@ function createHostnameCommand(options = {}) {
196
198
  if (fileSource !== void 0) {
197
199
  try {
198
200
  newHost = await readHostnameFile(context, fileSource, limits.maxFileBytes);
199
- } catch {
201
+ } catch (error) {
202
+ context.signal.throwIfAborted();
203
+ if (!isFsError(error, "ENOENT") && !(error instanceof RangeError))
204
+ throw error;
200
205
  await writeText(context.stderr, `hostname: cannot open file '${fileSource}'
201
206
  `);
202
207
  return { exitCode: 1 };
@@ -207,21 +212,31 @@ function createHostnameCommand(options = {}) {
207
212
  await writeText(context.stderr, "hostname: you must be root to change the host name\n");
208
213
  return { exitCode: 1 };
209
214
  }
210
- sessionHostname = newHost;
211
215
  try {
212
216
  await context.fs.mkdir("/etc", { recursive: true, signal: context.signal });
213
217
  await writeFileOutput(context, new TextEncoder().encode(`${newHost}
214
218
  `), (data) => context.fs.writeFile("/etc/hostname", data, { signal: context.signal }));
215
- } catch {
219
+ } catch (error) {
220
+ context.signal.throwIfAborted();
221
+ if (!isFsError(error, "EROFS") && !isFsError(error, "EACCES") && !isFsError(error, "EPERM"))
222
+ throw error;
216
223
  }
224
+ sessionHostnames.set(context.fs, newHost);
217
225
  return { exitCode: 0 };
218
226
  }
219
227
  let vfsHost = "";
220
228
  try {
221
229
  vfsHost = await readHostnameFile(context, "/etc/hostname", limits.maxFileBytes);
222
- } catch {
230
+ } catch (error) {
231
+ context.signal.throwIfAborted();
232
+ if (error instanceof RangeError) {
233
+ await writeText(context.stderr, "hostname: hostname file exceeds size limit\n");
234
+ return { exitCode: 1 };
235
+ }
236
+ if (!isFsError(error, "ENOENT"))
237
+ throw error;
223
238
  }
224
- const rawHost = context.env.HOSTNAME || vfsHost || sessionHostname || "sandbox";
239
+ const rawHost = context.env.HOSTNAME || vfsHost || sessionHostnames.get(context.fs) || options.hostname || "sandbox";
225
240
  const dotIdx = rawHost.indexOf(".");
226
241
  const shortName = dotIdx >= 0 ? rawHost.slice(0, dotIdx) : rawHost;
227
242
  const domainName = dotIdx >= 0 ? rawHost.slice(dotIdx + 1) : options.domain ?? "vfs.local";
@@ -4,6 +4,7 @@ import {
4
4
 
5
5
  // packages/safe-bash-command-id/dist/index.js
6
6
  init_buffer();
7
+ import { isFsError } from "../safe-bash-contracts/errors.js";
7
8
  import { commandRuntimeIdentity, writeText } from "../safe-bash-contracts/index.js";
8
9
  function settings(options = {}) {
9
10
  const limits = {
@@ -50,17 +51,25 @@ async function loadVfsAccounts(context, maxBytes) {
50
51
  let groupText = "";
51
52
  try {
52
53
  const bytes = await context.fs.readFile("/etc/passwd", { signal: context.signal });
53
- if (bytes.byteLength <= maxBytes) {
54
- passwdText = new TextDecoder().decode(bytes);
55
- }
56
- } catch {
54
+ context.signal.throwIfAborted();
55
+ if (bytes.byteLength > maxBytes)
56
+ throw new RangeError("/etc/passwd exceeds size limit");
57
+ passwdText = new TextDecoder().decode(bytes);
58
+ } catch (error) {
59
+ context.signal.throwIfAborted();
60
+ if (!isFsError(error, "ENOENT"))
61
+ throw error;
57
62
  }
58
63
  try {
59
64
  const bytes = await context.fs.readFile("/etc/group", { signal: context.signal });
60
- if (bytes.byteLength <= maxBytes) {
61
- groupText = new TextDecoder().decode(bytes);
62
- }
63
- } catch {
65
+ context.signal.throwIfAborted();
66
+ if (bytes.byteLength > maxBytes)
67
+ throw new RangeError("/etc/group exceeds size limit");
68
+ groupText = new TextDecoder().decode(bytes);
69
+ } catch (error) {
70
+ context.signal.throwIfAborted();
71
+ if (!isFsError(error, "ENOENT"))
72
+ throw error;
64
73
  }
65
74
  if (!passwdText)
66
75
  return result;
@@ -336,7 +345,17 @@ function createIdCommand(options = {}) {
336
345
  await writeText(context.stderr, "id: cannot print security context when user specified\n");
337
346
  return { exitCode: 1 };
338
347
  }
339
- const vfsAccounts = await loadVfsAccounts(context, limits.maxPasswdBytes);
348
+ let vfsAccounts;
349
+ try {
350
+ vfsAccounts = await loadVfsAccounts(context, limits.maxPasswdBytes);
351
+ } catch (error) {
352
+ context.signal.throwIfAborted();
353
+ if (!(error instanceof RangeError))
354
+ throw error;
355
+ await writeText(context.stderr, `id: ${error.message}
356
+ `);
357
+ return { exitCode: 1 };
358
+ }
340
359
  const { current, directory } = buildBuiltinAccounts(context, options);
341
360
  const allAccounts = [...vfsAccounts, ...directory];
342
361
  const targets = [];
@@ -2,7 +2,7 @@ import {
2
2
  createPandocCommand,
3
3
  createPandocCommands,
4
4
  pandocCommands
5
- } from "../safe-bash/command-chunks/chunk-DRCPJVZF.js";
5
+ } from "../safe-bash/command-chunks/chunk-44N2IRVP.js";
6
6
  import "../safe-bash/command-chunks/chunk-FWMW5MJL.js";
7
7
  import "../safe-bash/command-chunks/chunk-4NGJ2RDB.js";
8
8
  import "../safe-bash/command-chunks/chunk-K7JT2KAU.js";
@@ -20,7 +20,7 @@ import {
20
20
  readDocument,
21
21
  resolveConversionArgs,
22
22
  writeDocument
23
- } from "../safe-bash/command-chunks/chunk-DRCPJVZF.js";
23
+ } from "../safe-bash/command-chunks/chunk-44N2IRVP.js";
24
24
  import "../safe-bash/command-chunks/chunk-FWMW5MJL.js";
25
25
  import {
26
26
  createLuaFilterCapability
@@ -1,9 +1,9 @@
1
1
  import { type ResourceIOOptions } from "./io/index.js";
2
- import type { EngineConfig } from "./contracts.js";
2
+ import type { EngineConfig, EngineOptions } from "./contracts.js";
3
3
  import { type CommandDefinition, type VirtualShellPlugin } from "../safe-bash-contracts/index.js";
4
4
  export interface SsconvertCommandsOptions extends Omit<EngineConfig, "filesystem" | "codecs" | "environment"> {
5
5
  readonly codecs?: EngineConfig["codecs"];
6
- readonly environment?: EngineConfig["environment"];
6
+ readonly environment?: EngineOptions["environment"];
7
7
  readonly io?: Pick<ResourceIOOptions, "descriptors" | "adapters" | "transport">;
8
8
  readonly replace?: boolean;
9
9
  readonly profile?: import("./cli.js").CommandProfile;
@@ -175,6 +175,10 @@ export interface EngineConfig {
175
175
  }, context: CapabilityContext): Promise<Workbook | undefined>;
176
176
  };
177
177
  }
178
+ /** Public construction options; omitted environment fields use portable defaults. */
179
+ export interface EngineOptions extends Partial<Omit<EngineConfig, "environment">> {
180
+ readonly environment?: Partial<Environment>;
181
+ }
178
182
  export type Input = {
179
183
  readonly kind: "stream";
180
184
  readonly source: ByteSource;
@@ -1,5 +1,5 @@
1
- import { type EngineConfig, type Engine, type RuntimeLimits } from "./contracts.js";
1
+ import { type EngineOptions, type Engine, type RuntimeLimits } from "./contracts.js";
2
2
  export declare const defaultSsconvertLimits: Readonly<RuntimeLimits>;
3
3
  /** No host work occurs until an operation supplies cancellation and explicit I/O. */
4
- export declare function createEngine(supplied: EngineConfig): Engine;
4
+ export declare function createEngine(supplied?: EngineOptions): Engine;
5
5
  //# sourceMappingURL=engine.d.ts.map