@poe-platform/safe-bash 0.1.801 → 0.1.803
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/dist/image-ast/index.browser.js +16 -5
- package/dist/image-ast/index.js +16 -5
- package/dist/safe-bash/chunks/chunk-2LSAMQER.js +84 -0
- package/dist/safe-bash/chunks/chunk-3HQU4OJO.js +13 -0
- package/dist/safe-bash/chunks/chunk-4BSJLKNM.js +14 -0
- package/dist/safe-bash/chunks/chunk-4D4N7IU2.js +47 -0
- package/dist/safe-bash/chunks/chunk-55YJASTN.js +14 -0
- package/dist/safe-bash/chunks/{chunk-NZQXYWA3.js → chunk-5OHX7C2V.js} +0 -1
- package/dist/safe-bash/chunks/chunk-7ZBU7KYV.js +14 -0
- package/dist/safe-bash/chunks/{chunk-7VNF5BFF.js → chunk-B7PIL77G.js} +101 -415
- package/dist/safe-bash/chunks/chunk-DQP3VHSB.js +15 -0
- package/dist/safe-bash/chunks/{chunk-VQDD3G76.js → chunk-EEEWOYEG.js} +18 -18
- package/dist/safe-bash/chunks/chunk-FZE4HW6G.js +11 -0
- package/dist/safe-bash/chunks/{chunk-45PK3NWI.js → chunk-GDYNCWRV.js} +1 -1
- package/dist/safe-bash/chunks/chunk-GEG3BWGE.js +14 -0
- package/dist/safe-bash/chunks/chunk-HBCN24ZA.js +50 -0
- package/dist/safe-bash/chunks/chunk-HZ7BWKQ3.js +13 -0
- package/dist/safe-bash/chunks/{chunk-ICFDYV64.js → chunk-HZAMGT5I.js} +2 -2
- package/dist/safe-bash/chunks/{chunk-FNDNHAGE.js → chunk-JMMEIDPF.js} +2 -2
- package/dist/safe-bash/chunks/{chunk-IVRQ4BXL.js → chunk-PH63PLPZ.js} +7 -7
- package/dist/safe-bash/chunks/{chunk-SZH7EJLD.js → chunk-PNBBUWSM.js} +5529 -6547
- package/dist/safe-bash/chunks/chunk-QGUV42T5.js +44 -0
- package/dist/safe-bash/chunks/chunk-R3NAKOED.js +51 -0
- package/dist/safe-bash/chunks/chunk-RRR7AQ24.js +38 -0
- package/dist/safe-bash/chunks/{chunk-PQRAK7HU.js → chunk-RYFQ3LZG.js} +281 -476
- package/dist/safe-bash/chunks/chunk-VBTDHOWC.js +55 -0
- package/dist/safe-bash/chunks/{chunk-NR3EM4LS.js → chunk-VKNVHEX3.js} +1 -6
- package/dist/safe-bash/chunks/chunk-XAQMU6OY.js +14 -0
- package/dist/safe-bash/chunks/chunk-ZVD5IS4V.js +49 -0
- package/dist/safe-bash/command-chunks/{chunk-ORYGZYKW.js → chunk-4FEVBOL5.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-VXSLJH7G.js → chunk-6JSIFWYT.js} +26 -6
- package/dist/safe-bash/command-chunks/chunk-A7MU7762.js +200 -0
- package/dist/safe-bash/command-chunks/{chunk-KJIMDLBB.js → chunk-BXCXRYVU.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-F4TEEZTL.js → chunk-CQHP3I66.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-PEF7K3UQ.js → chunk-EARHPPPJ.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-QKFSRZGQ.js → chunk-GFC2NTDG.js} +2 -2
- package/dist/safe-bash/command-chunks/chunk-GIRNFXP3.js +466 -0
- package/dist/safe-bash/command-chunks/{chunk-EFANWIHL.js → chunk-GY3BWK7K.js} +1 -0
- package/dist/safe-bash/command-chunks/{chunk-FPVUD6TH.js → chunk-HDCNKOIX.js} +9 -7
- package/dist/safe-bash/command-chunks/{chunk-MQFIPHIQ.js → chunk-ILX2NOLF.js} +18 -15
- package/dist/safe-bash/command-chunks/{chunk-5E4WAO4O.js → chunk-JD5QNRNO.js} +3 -3
- package/dist/safe-bash/command-chunks/{chunk-I237SNW5.js → chunk-LFJJQQND.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-W5DNF4JH.js → chunk-LOICUCHG.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-7U7EXOXX.js → chunk-NASVPT6F.js} +2 -1
- package/dist/safe-bash/command-chunks/{chunk-WBNZ4PRE.js → chunk-NGG2XL56.js} +7 -4
- package/dist/safe-bash/command-chunks/{chunk-GLOZX57Y.js → chunk-NKIELG7Y.js} +45 -115
- package/dist/safe-bash/command-chunks/{chunk-WPYIOKE3.js → chunk-PICVQ6B5.js} +2 -2
- package/dist/safe-bash/command-chunks/{chunk-YOFC45RK.js → chunk-QVOS4YXL.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-VGG2DL5Q.js → chunk-TRR4MYWF.js} +4 -0
- package/dist/safe-bash/command-chunks/{chunk-2JRBIDAD.js → chunk-V4K2JDYU.js} +2 -2
- package/dist/safe-bash/command-chunks/{chunk-CZ7EN3JG.js → chunk-VT6MJBEI.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-PCEFOYA3.js → chunk-WWIBP2ET.js} +41 -114
- package/dist/safe-bash/command-chunks/{chunk-F6OYH562.js → chunk-X54L3DBL.js} +4 -9
- package/dist/safe-bash/command-chunks/{chunk-TNOA7FCQ.js → chunk-YVNGTIJO.js} +1 -1
- package/dist/safe-bash/command-chunks/chunk-ZDN7MJE6.js +168 -0
- package/dist/safe-bash/commands/apply-patch/index.browser.js +14 -0
- package/dist/safe-bash/commands/archive/index.browser.js +36 -0
- package/dist/safe-bash/commands/bytes/compression/index.js +54 -51
- package/dist/safe-bash/commands/chmod/index.browser.js +14 -0
- package/dist/safe-bash/commands/chmod/index.d.ts +2 -0
- package/dist/safe-bash/commands/chmod/index.js +2 -0
- package/dist/safe-bash/commands/column/index.browser.js +12 -0
- package/dist/safe-bash/commands/du/index.browser.js +14 -0
- package/dist/safe-bash/commands/expr/index.browser.js +12 -0
- package/dist/safe-bash/commands/file/index.browser.js +14 -0
- package/dist/safe-bash/commands/filesystem.js +9 -2
- package/dist/safe-bash/commands/grep-aliases/index.browser.js +14 -0
- package/dist/safe-bash/commands/html-to-markdown/index.browser.js +16 -0
- package/dist/safe-bash/commands/metadata/chmod.d.ts +1 -7
- package/dist/safe-bash/commands/metadata/chmod.js +1 -204
- package/dist/safe-bash/commands/metadata/index.browser.js +17 -0
- package/dist/safe-bash/commands/metadata/internal.d.ts +1 -30
- package/dist/safe-bash/commands/metadata/internal.js +1 -76
- package/dist/safe-bash/commands/metadata/mktemp.d.ts +1 -3
- package/dist/safe-bash/commands/metadata/mktemp.js +1 -202
- package/dist/safe-bash/commands/metadata/stat.d.ts +1 -7
- package/dist/safe-bash/commands/metadata/stat.js +1 -530
- package/dist/safe-bash/commands/mktemp/index.browser.js +13 -0
- package/dist/safe-bash/commands/mktemp/index.d.ts +2 -0
- package/dist/safe-bash/commands/mktemp/index.js +2 -0
- package/dist/safe-bash/commands/network/index.browser.js +1 -1
- package/dist/safe-bash/commands/node/index.browser.js +4 -4
- package/dist/safe-bash/commands/portable-random.d.ts +1 -1
- package/dist/safe-bash/commands/portable-random.js +1 -12
- package/dist/safe-bash/commands/python/index.browser.js +8 -8
- package/dist/safe-bash/commands/regex-execution/public.browser.js +5 -3
- package/dist/safe-bash/commands/split/index.browser.js +14 -0
- package/dist/safe-bash/commands/stat/index.browser.js +13 -0
- package/dist/safe-bash/commands/stat/index.d.ts +2 -0
- package/dist/safe-bash/commands/stat/index.js +2 -0
- package/dist/safe-bash/commands/stream-format/index.browser.js +11 -0
- package/dist/safe-bash/commands/stream-inspection/index.browser.js +11 -0
- package/dist/safe-bash/commands/streams.js +5 -5
- package/dist/safe-bash/commands/table-text/index.browser.js +11 -0
- package/dist/safe-bash/commands/text.js +48 -143
- package/dist/safe-bash/commands/time-env/index.browser.js +15 -0
- package/dist/safe-bash/commands/tree/index.browser.js +14 -0
- package/dist/safe-bash/full-core.browser.js +256 -247
- package/dist/safe-bash/opt-in/commands/yq/native-work.js +1 -0
- package/dist/safe-bash/optional-host.browser.js +12 -12
- package/dist/safe-bash/plugins/index.browser.js +25 -11
- package/dist/safe-bash/registry-entry.browser.js +28 -14
- package/dist/safe-bash/search.browser.js +48 -0
- package/dist/safe-bash/shell/runtime.d.ts +3 -9
- package/dist/safe-bash/shell/runtime.js +63 -311
- package/dist/safe-bash/shell/shell.js +0 -23
- package/dist/safe-bash/shell/types.d.ts +2 -0
- package/dist/safe-bash/shell/worker-limits.js +1 -0
- package/dist/safe-bash/shell-entry.browser.js +19 -10
- package/dist/safe-bash/worker/host.js +1 -1
- package/dist/safe-bash-command-bc/index.js +12 -5
- package/dist/safe-bash-command-bzip2/index.js +4 -3
- package/dist/safe-bash-command-chmod/LICENSE +21 -0
- package/dist/safe-bash-command-chmod/command.d.ts +7 -0
- package/dist/safe-bash-command-chmod/command.js +11 -0
- package/dist/safe-bash-command-chmod/index.d.ts +6 -0
- package/dist/safe-bash-command-chmod/index.js +27 -0
- package/dist/safe-bash-command-exiftool/index.js +5 -5
- package/dist/safe-bash-command-find/find.js +1 -1
- package/dist/safe-bash-command-find/index.js +1 -1
- package/dist/safe-bash-command-fmt/index.js +9 -2
- package/dist/safe-bash-command-gzip/index.js +45 -42
- package/dist/safe-bash-command-imagemagick/index.js +3 -1
- package/dist/safe-bash-command-jq/index.js +1 -1
- package/dist/safe-bash-command-jq/jq.js +1 -1
- package/dist/safe-bash-command-less/index.js +12 -3
- package/dist/safe-bash-command-mktemp/LICENSE +21 -0
- package/dist/safe-bash-command-mktemp/command.d.ts +3 -0
- package/dist/safe-bash-command-mktemp/command.js +9 -0
- package/dist/safe-bash-command-mktemp/index.d.ts +6 -0
- package/dist/safe-bash-command-mktemp/index.js +25 -0
- package/dist/safe-bash-command-nl/index.js +1 -1
- package/dist/safe-bash-command-nl/nl.js +1 -1
- package/dist/safe-bash-command-od/index.js +6 -2
- package/dist/safe-bash-command-op/index.js +25 -6
- package/dist/safe-bash-command-rg/index.js +1 -1
- package/dist/safe-bash-command-rg/rg-command.d.ts +0 -1
- package/dist/safe-bash-command-rg/rg-command.js +3 -5
- package/dist/safe-bash-command-sed/index.js +1 -1
- package/dist/safe-bash-command-sed/sed.js +1 -1
- package/dist/safe-bash-command-sips/index.js +13 -5
- package/dist/safe-bash-command-sponge/index.js +10 -3
- package/dist/safe-bash-command-stat/LICENSE +21 -0
- package/dist/safe-bash-command-stat/command.d.ts +7 -0
- package/dist/safe-bash-command-stat/command.js +9 -0
- package/dist/safe-bash-command-stat/index.d.ts +6 -0
- package/dist/safe-bash-command-stat/index.js +25 -0
- package/dist/safe-bash-command-unexpand/index.js +1 -1
- package/dist/safe-bash-command-unexpand/unexpand.js +1 -1
- package/dist/safe-bash-command-unrtf/index.js +11 -1
- package/dist/safe-bash-command-xxd/index.js +6 -2
- package/dist/safe-bash-command-xz/command.d.ts +1 -1
- package/dist/safe-bash-command-xz/index.js +3 -2
- package/dist/safe-bash-command-yq/index.js +1 -0
- package/dist/safe-bash-command-yq/native-work.js +1 -0
- package/dist/safe-bash-command-yq/query.js +3 -0
- package/dist/safe-bash-compression-engine/bounded-codec.js +3 -3
- package/dist/safe-bash-compression-engine/codec-loader.js +2 -2
- package/dist/safe-bash-compression-engine/files.js +6 -6
- package/dist/safe-bash-compression-engine/index.js +5 -5
- package/dist/safe-bash-compression-engine/operand.js +6 -6
- package/dist/safe-bash-compression-engine/options.js +1 -1
- package/dist/safe-bash-compression-engine/stream.js +5 -5
- package/dist/safe-bash-compression-engine/zstd-decode.js +4 -4
- package/dist/safe-bash-contracts/escaping.js +2 -2
- package/dist/safe-bash-contracts/filesystem-output.js +2 -2
- package/dist/safe-bash-contracts/index.js +2 -2
- package/dist/safe-bash-contracts/io.d.ts +2 -0
- package/dist/safe-bash-contracts/io.js +1 -1
- package/dist/safe-bash-contracts/output.js +2 -2
- package/dist/safe-bash-io-engine/commands/search/requirements.js +1 -1
- package/dist/safe-bash-io-engine/commands/text-programs/shared.js +1 -1
- package/dist/safe-bash-mcp/index.browser.js +11 -1
- package/dist/safe-bash-mcp/index.js +38 -17
- package/dist/safe-bash-metadata-engine/LICENSE +21 -0
- package/dist/safe-bash-metadata-engine/index.d.ts +30 -0
- package/dist/safe-bash-metadata-engine/index.js +82 -0
- package/dist/safe-bash-metadata-engine/random.d.ts +1 -0
- package/dist/safe-bash-metadata-engine/random.js +21 -0
- package/dist/safe-bash-regex-engine/index.js +4 -4
- package/dist/safe-bash-regex-engine/text/budget.d.ts +0 -1
- package/dist/safe-bash-regex-engine/text/budget.js +1 -1
- package/dist/safe-bash-regex-engine/text/regex.js +4 -4
- package/dist/safe-bash-regex-engine/text/replacement-buffer.js +2 -2
- package/dist/safe-bash-regex-engine/text/rust-syntax.js +2 -2
- package/dist/safe-bash-search-engine/ergonomic-regex.js +2 -2
- package/dist/safe-bash-search-engine/glob.js +2 -2
- package/dist/safe-bash-search-engine/grep.js +2 -2
- package/dist/safe-bash-search-engine/matcher.js +2 -2
- package/dist/safe-bash-search-engine/options.d.ts +2 -0
- package/dist/safe-bash-search-engine/options.js +1 -1
- package/dist/safe-bash-search-engine/output.js +1 -1
- package/dist/safe-bash-search-engine/shared.js +2 -2
- package/dist/safe-bash-search-engine/walk.js +3 -3
- package/dist/safe-playwright-cloudflare/browser-snapshot-json.js +2 -2
- package/dist/safe-playwright-cloudflare/browser-snapshot-references.js +1 -1
- package/package.json +91 -10
|
@@ -6,7 +6,8 @@ import {
|
|
|
6
6
|
init_buffer();
|
|
7
7
|
import { PublicDiagnostic, UsageError } from "../safe-bash-contracts/diagnostics.js";
|
|
8
8
|
import {
|
|
9
|
-
commandRuntimeIdentity
|
|
9
|
+
commandRuntimeIdentity,
|
|
10
|
+
withInputByteBudget
|
|
10
11
|
} from "../safe-bash-contracts/index.js";
|
|
11
12
|
import { codeOf, diagnostic, output } from "../safe-bash-compression-engine/internal.js";
|
|
12
13
|
import { runOperand } from "../safe-bash-compression-engine/operand.js";
|
|
@@ -35,7 +36,7 @@ function createNamedBzip2Command(name, options = {}) {
|
|
|
35
36
|
name,
|
|
36
37
|
description: `${name} block-sorting file compressor`,
|
|
37
38
|
runtimeIdentity: commandRuntimeIdentity,
|
|
38
|
-
async
|
|
39
|
+
execute: withInputByteBudget(async (context) => {
|
|
39
40
|
context.signal.throwIfAborted();
|
|
40
41
|
try {
|
|
41
42
|
const parsed = parseOptions(name, context.args);
|
|
@@ -105,7 +106,7 @@ No FILE or FILE '-' uses stdin; file output uses private VFS staging.
|
|
|
105
106
|
await diagnostic(context, error);
|
|
106
107
|
return { exitCode: error instanceof UsageError ? 2 : 1 };
|
|
107
108
|
}
|
|
108
|
-
}
|
|
109
|
+
})
|
|
109
110
|
};
|
|
110
111
|
}
|
|
111
112
|
function createBzip2Command(options = {}) {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Poe Platform
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { modeChange } from "../safe-bash-io-engine/commands/mode-change.js";
|
|
2
|
+
import { type MetadataCommandsOptions } from "../safe-bash-metadata-engine/index.js";
|
|
3
|
+
export declare function createChmodCommand(configuration?: MetadataCommandsOptions): import("../safe-bash-contracts/index.js").CommandDefinition;
|
|
4
|
+
export declare function evalSyncChmod(opArgs: readonly string[], umask: number, chmodNodeSync?: (filePath: string, change: (stat: {
|
|
5
|
+
type: "file" | "directory" | "symlink";
|
|
6
|
+
mode: number;
|
|
7
|
+
}) => number) => boolean): string | undefined;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { VirtualShellPlugin } from "../safe-bash-contracts/index.js";
|
|
2
|
+
import type { MetadataCommandsOptions } from "../safe-bash-metadata-engine/index.js";
|
|
3
|
+
export * from "./command.js";
|
|
4
|
+
export type { MetadataCommandsOptions as ChmodCommandsOptions, MetadataLimits as ChmodLimits } from "../safe-bash-metadata-engine/index.js";
|
|
5
|
+
export declare function createChmodCommands(options?: MetadataCommandsOptions): import("../safe-bash-contracts/index.js").CommandDefinition[];
|
|
6
|
+
export declare function chmodCommands(options?: MetadataCommandsOptions): VirtualShellPlugin;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createChmodCommand,
|
|
3
|
+
evalSyncChmod,
|
|
4
|
+
modeChange
|
|
5
|
+
} from "../safe-bash/command-chunks/chunk-A7MU7762.js";
|
|
6
|
+
import {
|
|
7
|
+
init_buffer
|
|
8
|
+
} from "../safe-bash/command-chunks/chunk-HX3SHTCE.js";
|
|
9
|
+
|
|
10
|
+
// packages/safe-bash-command-chmod/src/index.ts
|
|
11
|
+
init_buffer();
|
|
12
|
+
function createChmodCommands(options = {}) {
|
|
13
|
+
return [createChmodCommand(options)];
|
|
14
|
+
}
|
|
15
|
+
function chmodCommands(options = {}) {
|
|
16
|
+
const commands = createChmodCommands(options);
|
|
17
|
+
return { name: "chmod-commands", setup(host) {
|
|
18
|
+
for (const command of commands) host.commands.register(command, { replace: options.replace ?? false });
|
|
19
|
+
} };
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
chmodCommands,
|
|
23
|
+
createChmodCommand,
|
|
24
|
+
createChmodCommands,
|
|
25
|
+
evalSyncChmod,
|
|
26
|
+
modeChange
|
|
27
|
+
};
|
|
@@ -10,7 +10,7 @@ init_buffer();
|
|
|
10
10
|
import { yieldTurn } from "../safe-bash-contracts/yield.js";
|
|
11
11
|
import { commandRuntimeIdentity, getCommandArguments } from "../safe-bash-contracts/command.js";
|
|
12
12
|
import { FsError as FsError2 } from "../safe-bash-contracts/errors.js";
|
|
13
|
-
import { readBytes as readBytes2, writeBytes } from "../safe-bash-contracts/io.js";
|
|
13
|
+
import { readBytes as readBytes2, writeBytes, withInputByteBudget } from "../safe-bash-contracts/io.js";
|
|
14
14
|
import { createOutputOperation } from "../safe-bash-contracts/output.js";
|
|
15
15
|
import { shellValueByteLength } from "../safe-bash-contracts/value.js";
|
|
16
16
|
|
|
@@ -1779,7 +1779,7 @@ function createExiftoolCommand(options = {}) {
|
|
|
1779
1779
|
name: "exiftool",
|
|
1780
1780
|
runtimeIdentity: commandRuntimeIdentity,
|
|
1781
1781
|
description: "Inspect and edit admitted PNG, JPEG and PDF metadata through virtual files",
|
|
1782
|
-
async
|
|
1782
|
+
execute: withInputByteBudget(async (context) => {
|
|
1783
1783
|
const publication = new Publication(context, limits.maxStagingAttempts);
|
|
1784
1784
|
let stdout, stderr;
|
|
1785
1785
|
let failed = false, failure;
|
|
@@ -1824,7 +1824,7 @@ function createExiftoolCommand(options = {}) {
|
|
|
1824
1824
|
invocation = parseArguments(await expandArgfiles(context.args, context, publication, resources), resources.limits);
|
|
1825
1825
|
} catch (error) {
|
|
1826
1826
|
context.signal.throwIfAborted();
|
|
1827
|
-
if (error instanceof ResourceLimitError) throw error;
|
|
1827
|
+
if (error instanceof ResourceLimitError || error instanceof Error && error.name === "BudgetExceededError" || error instanceof FsError2 && error.code === "EFBIG") throw error;
|
|
1828
1828
|
await output("Error: " + (error instanceof Error ? error.message : String(error)) + "\n", true);
|
|
1829
1829
|
return { exitCode: 1 };
|
|
1830
1830
|
}
|
|
@@ -1948,7 +1948,7 @@ function createExiftoolCommand(options = {}) {
|
|
|
1948
1948
|
tags = jpeg ? inspectJpeg(bytes, resources).tags : png ? inspectPng(bytes, resources).tags : isPdf ? inspectPdf(bytes, resources).tags : [];
|
|
1949
1949
|
} catch (error) {
|
|
1950
1950
|
context.signal.throwIfAborted();
|
|
1951
|
-
if (error instanceof ResourceLimitError) throw error;
|
|
1951
|
+
if (error instanceof ResourceLimitError || error instanceof Error && error.name === "BudgetExceededError" || error instanceof FsError2 && error.code === "EFBIG") throw error;
|
|
1952
1952
|
errors++;
|
|
1953
1953
|
const message = error instanceof FsError2 && error.code === "ENOENT" ? "File not found" : error instanceof Error ? error.message : String(error);
|
|
1954
1954
|
await output("Error: " + message + " - " + file + "\n", true);
|
|
@@ -2053,7 +2053,7 @@ function createExiftoolCommand(options = {}) {
|
|
|
2053
2053
|
} finally {
|
|
2054
2054
|
await cleanup();
|
|
2055
2055
|
}
|
|
2056
|
-
}
|
|
2056
|
+
})
|
|
2057
2057
|
});
|
|
2058
2058
|
}
|
|
2059
2059
|
var exiftoolCommand = createExiftoolCommand();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createFindDefinitions,
|
|
3
3
|
evalSyncFind
|
|
4
|
-
} from "../safe-bash/command-chunks/chunk-
|
|
4
|
+
} from "../safe-bash/command-chunks/chunk-GFC2NTDG.js";
|
|
5
5
|
import "../safe-bash/command-chunks/chunk-5ZMZ573Q.js";
|
|
6
6
|
import "../safe-bash/command-chunks/chunk-HX3SHTCE.js";
|
|
7
7
|
export {
|
|
@@ -2217,12 +2217,14 @@ function pathOf(context, path) {
|
|
|
2217
2217
|
return isAbsolutePath(path) ? path : `${context.cwd.endsWith("/") ? context.cwd.slice(0, -1) : context.cwd}/${path}`;
|
|
2218
2218
|
}
|
|
2219
2219
|
var InputBudget = class {
|
|
2220
|
-
constructor(maximum, sourceBufferBytes) {
|
|
2220
|
+
constructor(maximum, sourceBufferBytes, inputBudget) {
|
|
2221
2221
|
this.maximum = maximum;
|
|
2222
2222
|
this.sourceBufferBytes = sourceBufferBytes;
|
|
2223
|
+
this.inputBudget = inputBudget;
|
|
2223
2224
|
}
|
|
2224
2225
|
maximum;
|
|
2225
2226
|
sourceBufferBytes;
|
|
2227
|
+
inputBudget;
|
|
2226
2228
|
used = 0;
|
|
2227
2229
|
get maxReadBytes() {
|
|
2228
2230
|
return Math.max(0, Math.min(this.sourceBufferBytes, this.maximum - this.used));
|
|
@@ -2234,6 +2236,7 @@ var InputBudget = class {
|
|
|
2234
2236
|
if (size > this.maximum - this.used) throw new FsError("EFBIG", { message: "byte command input limit exceeded" });
|
|
2235
2237
|
if (size > this.maxReadBytes) throw new FmtError("LIMIT", "source chunk retention limit exceeded");
|
|
2236
2238
|
this.used += size;
|
|
2239
|
+
this.inputBudget?.check(this.used);
|
|
2237
2240
|
if (!size) yield byteSpan(chunk, 0, 0);
|
|
2238
2241
|
for (let offset = 0; offset < size; offset += 4096) yield byteSpan(chunk, offset, Math.min(4096, size - offset));
|
|
2239
2242
|
}
|
|
@@ -2390,7 +2393,7 @@ async function fmt(context, configuration = {}) {
|
|
|
2390
2393
|
const engineBytes = 10120 + settings.prefix.length;
|
|
2391
2394
|
const batchBytes = limits.retainedBytes >= Math.max(32768, engineBytes + 16384 + 4096) ? 16384 : 0;
|
|
2392
2395
|
const engineLimit = limits.retainedBytes - batchBytes;
|
|
2393
|
-
const budget = new InputBudget(limits.inputBytes, engineLimit - engineBytes);
|
|
2396
|
+
const budget = new InputBudget(limits.inputBytes, engineLimit - engineBytes, context.inputBudget);
|
|
2394
2397
|
let work = 0, outputBytes = 0;
|
|
2395
2398
|
stdout = createOutputOperation({ signal: local.signal }, context.stdout);
|
|
2396
2399
|
const outputContext = { ...context, stdout: stdout.output };
|
|
@@ -2406,6 +2409,7 @@ async function fmt(context, configuration = {}) {
|
|
|
2406
2409
|
try {
|
|
2407
2410
|
await current.open(name, nameBytes);
|
|
2408
2411
|
} catch (error) {
|
|
2412
|
+
if (error instanceof Error && (error.name === "BudgetExceededError" || error.name === "AbortError")) throw error;
|
|
2409
2413
|
local.signal.throwIfAborted();
|
|
2410
2414
|
await diagnostic(context, fileError(error, name, nameBytes, true, context));
|
|
2411
2415
|
await current.close();
|
|
@@ -2439,6 +2443,7 @@ async function fmt(context, configuration = {}) {
|
|
|
2439
2443
|
bytes2 = await current.next();
|
|
2440
2444
|
if (bytes2?.length) received = true;
|
|
2441
2445
|
} catch (error) {
|
|
2446
|
+
if (error instanceof Error && (error.name === "BudgetExceededError" || error.name === "AbortError")) throw error;
|
|
2442
2447
|
local.signal.throwIfAborted();
|
|
2443
2448
|
if (isFsError(error, "EFBIG")) throw new FmtError("LIMIT", "byte command input limit exceeded");
|
|
2444
2449
|
readFailed = true;
|
|
@@ -2467,6 +2472,7 @@ async function fmt(context, configuration = {}) {
|
|
|
2467
2472
|
}
|
|
2468
2473
|
if (outBatchUsed) await flushOutBatch();
|
|
2469
2474
|
} catch (error) {
|
|
2475
|
+
if (error instanceof Error && (error.name === "BudgetExceededError" || error.name === "AbortError")) throw error;
|
|
2470
2476
|
local.signal.throwIfAborted();
|
|
2471
2477
|
try {
|
|
2472
2478
|
await flushOutBatch();
|
|
@@ -2496,6 +2502,7 @@ async function fmt(context, configuration = {}) {
|
|
|
2496
2502
|
} catch (error) {
|
|
2497
2503
|
failed = true;
|
|
2498
2504
|
context.signal.throwIfAborted();
|
|
2505
|
+
if (error instanceof Error && (error.name === "BudgetExceededError" || error.name === "AbortError")) throw error;
|
|
2499
2506
|
if (error instanceof FmtError && error.usage) await writeBytes(context.stderr, Uint8Array.from(`fmt: ${error.message}
|
|
2500
2507
|
Try 'fmt --help' for more information.
|
|
2501
2508
|
`, (character) => character.charCodeAt(0)), context.signal);
|
|
@@ -16,10 +16,11 @@ function createGzipCommands(config = {}) {
|
|
|
16
16
|
if (maxDecodedBytes !== void 0 && maxDecodedBytes !== Infinity && (!Number.isSafeInteger(maxDecodedBytes) || maxDecodedBytes < 0)) {
|
|
17
17
|
throw new RangeError("maxDecodedBytes must be a nonnegative safe integer or Infinity");
|
|
18
18
|
}
|
|
19
|
-
const commands = profiles.filter((profile) => profile.format === "gzip").flatMap((profile) => profile.names.map((name) =>
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
const commands = profiles.filter((profile) => profile.format === "gzip").flatMap((profile) => profile.names.map((name) => {
|
|
20
|
+
const command = define(name, async (context) => {
|
|
21
|
+
const options = parseOptions(name, context.args);
|
|
22
|
+
if (options.help) {
|
|
23
|
+
await output(context, `Usage: ${name} [OPTION]... [FILE]...
|
|
23
24
|
-c, --stdout, --to-stdout
|
|
24
25
|
-d, --decompress, --uncompress
|
|
25
26
|
-k, --keep
|
|
@@ -29,48 +30,50 @@ ${options.format === "zstd" ? "-1..-9, --best\nHigher levels and --fast[=NUM] ar
|
|
|
29
30
|
`}-h, --help
|
|
30
31
|
No FILE or FILE '-' uses stdin; file output uses private VFS staging.
|
|
31
32
|
`);
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
try {
|
|
37
|
-
if (options.operands.length > 1) {
|
|
38
|
-
plans = [];
|
|
39
|
-
for (const name2 of options.operands) {
|
|
40
|
-
try {
|
|
41
|
-
plans.push(...await planOperands(context, { ...options, operands: [name2] }));
|
|
42
|
-
} catch (error) {
|
|
43
|
-
context.signal.throwIfAborted();
|
|
44
|
-
if (codeOf(error) === "EROFS") throw error;
|
|
45
|
-
planningFailed = true;
|
|
46
|
-
if (options.quiet < 2) await diagnostic(context, error);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
if (plans.length > 1) await verifyOperandDestinations(context, plans);
|
|
50
|
-
} else plans = await planOperands(context, options);
|
|
51
|
-
} catch (error) {
|
|
52
|
-
context.signal.throwIfAborted();
|
|
53
|
-
if (options.quiet < 2) throw error;
|
|
54
|
-
return { exitCode: 1 };
|
|
55
|
-
}
|
|
56
|
-
const decodedBudget = new DecodedBudget(maxDecodedBytes);
|
|
57
|
-
let exitCode = planningFailed ? 1 : 0;
|
|
58
|
-
for (const plan of plans) {
|
|
33
|
+
return { exitCode: 0 };
|
|
34
|
+
}
|
|
35
|
+
let plans;
|
|
36
|
+
let planningFailed = false;
|
|
59
37
|
try {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
38
|
+
if (options.operands.length > 1) {
|
|
39
|
+
plans = [];
|
|
40
|
+
for (const name2 of options.operands) {
|
|
41
|
+
try {
|
|
42
|
+
plans.push(...await planOperands(context, { ...options, operands: [name2] }));
|
|
43
|
+
} catch (error) {
|
|
44
|
+
context.signal.throwIfAborted();
|
|
45
|
+
if (codeOf(error) === "EROFS") throw error;
|
|
46
|
+
planningFailed = true;
|
|
47
|
+
if (options.quiet < 2) await diagnostic(context, error);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (plans.length > 1) await verifyOperandDestinations(context, plans);
|
|
51
|
+
} else plans = await planOperands(context, options);
|
|
65
52
|
} catch (error) {
|
|
66
53
|
context.signal.throwIfAborted();
|
|
67
|
-
if (options.quiet < 2)
|
|
68
|
-
exitCode
|
|
69
|
-
if (decodedBudget.exceeded) break;
|
|
54
|
+
if (options.quiet < 2) throw error;
|
|
55
|
+
return { exitCode: 1 };
|
|
70
56
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
57
|
+
const decodedBudget = new DecodedBudget(maxDecodedBytes);
|
|
58
|
+
let exitCode = planningFailed ? 1 : 0;
|
|
59
|
+
for (const plan of plans) {
|
|
60
|
+
try {
|
|
61
|
+
const warned = await runOperand(context, plan, options, decodedBudget);
|
|
62
|
+
if (warned) {
|
|
63
|
+
if (!options.quiet) await diagnostic(context, new PublicDiagnostic(`${plan.source}: decompression OK, trailing garbage ignored`));
|
|
64
|
+
if (exitCode === 0) exitCode = 2;
|
|
65
|
+
}
|
|
66
|
+
} catch (error) {
|
|
67
|
+
context.signal.throwIfAborted();
|
|
68
|
+
if (options.quiet < 2) await diagnostic(context, error);
|
|
69
|
+
exitCode = 1;
|
|
70
|
+
if (decodedBudget.exceeded) break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return { exitCode };
|
|
74
|
+
});
|
|
75
|
+
return { ...command, execute: withInputByteBudget(async (context) => command.execute(context)) };
|
|
76
|
+
}));
|
|
74
77
|
if (maxDecodedBytes === void 0 || maxDecodedBytes === Infinity) {
|
|
75
78
|
for (const c of commands) builtInDirectContextExecutors.add(c.execute);
|
|
76
79
|
}
|
|
@@ -35,6 +35,7 @@ import {
|
|
|
35
35
|
|
|
36
36
|
// packages/safe-bash-command-imagemagick/src/index.ts
|
|
37
37
|
init_buffer();
|
|
38
|
+
import { FsError } from "../safe-bash-contracts/errors.js";
|
|
38
39
|
import { resolvePath } from "../safe-bash-contracts/path.js";
|
|
39
40
|
import { yieldTurn, drainCooperativeSteps as drainSteps } from "../safe-bash-contracts/yield.js";
|
|
40
41
|
import { InputByteBudget } from "../safe-bash-contracts/io.js";
|
|
@@ -5089,7 +5090,8 @@ async function executeVfsMagickTool(context, runner, maxInputBytes) {
|
|
|
5089
5090
|
bytes = await context.fs.readFile(resolvePath(context.cwd, candidate), {
|
|
5090
5091
|
signal: invocation.signal
|
|
5091
5092
|
});
|
|
5092
|
-
} catch {
|
|
5093
|
+
} catch (error) {
|
|
5094
|
+
if (!(error instanceof FsError) || !["ENOENT", "ENOTDIR", "EISDIR", "EACCES", "EPERM"].includes(error.code)) throw error;
|
|
5093
5095
|
continue;
|
|
5094
5096
|
}
|
|
5095
5097
|
chargeInput(bytes.byteLength);
|
|
@@ -52,13 +52,14 @@ function settings(options = {}) {
|
|
|
52
52
|
}
|
|
53
53
|
return Object.freeze(limits);
|
|
54
54
|
}
|
|
55
|
-
async function readSourceText(source, maxBytes, signal) {
|
|
55
|
+
async function readSourceText(source, maxBytes, signal, admit) {
|
|
56
56
|
const chunks = [];
|
|
57
57
|
let total = 0;
|
|
58
58
|
let quantum = 0;
|
|
59
59
|
let chunksRead = 0;
|
|
60
60
|
for await (const chunk of readBytes(source, signal)) {
|
|
61
61
|
total += chunk.byteLength;
|
|
62
|
+
admit(chunk.byteLength);
|
|
62
63
|
signal.throwIfAborted();
|
|
63
64
|
quantum += Math.max(1, chunk.byteLength);
|
|
64
65
|
if (quantum >= 16384 || ++chunksRead >= 128) {
|
|
@@ -86,6 +87,11 @@ function createPagerCommand(name, options = {}) {
|
|
|
86
87
|
description: `Non-interactive ${name} pager pass-through`,
|
|
87
88
|
runtimeIdentity: commandRuntimeIdentity,
|
|
88
89
|
async execute(context) {
|
|
90
|
+
let inputBytes = 0;
|
|
91
|
+
const admit = (bytes) => {
|
|
92
|
+
context.signal.throwIfAborted();
|
|
93
|
+
context.inputBudget?.check(inputBytes += bytes);
|
|
94
|
+
};
|
|
89
95
|
const maxBytes = Math.min(limits.maxInputBytes, context.limits?.maxInputBytes ?? limits.maxInputBytes);
|
|
90
96
|
context.signal.throwIfAborted();
|
|
91
97
|
const args = getCommandArguments(context).args;
|
|
@@ -165,6 +171,7 @@ function createPagerCommand(name, options = {}) {
|
|
|
165
171
|
await yieldTurn(context.signal);
|
|
166
172
|
}
|
|
167
173
|
total += chunk.byteLength;
|
|
174
|
+
admit(chunk.byteLength);
|
|
168
175
|
if (total > maxBytes) {
|
|
169
176
|
await writeText(context.stderr, `${name}: input exceeds maximum size of ${maxBytes} bytes
|
|
170
177
|
`);
|
|
@@ -179,7 +186,7 @@ function createPagerCommand(name, options = {}) {
|
|
|
179
186
|
const texts = [];
|
|
180
187
|
let exitCode = 0;
|
|
181
188
|
if (files.length === 0) {
|
|
182
|
-
texts.push(await readSourceText(context.stdin, maxBytes, context.signal));
|
|
189
|
+
texts.push(await readSourceText(context.stdin, maxBytes, context.signal, admit));
|
|
183
190
|
} else {
|
|
184
191
|
for (const file of files) {
|
|
185
192
|
if (file === "-") {
|
|
@@ -187,16 +194,18 @@ function createPagerCommand(name, options = {}) {
|
|
|
187
194
|
let total = 0;
|
|
188
195
|
for await (const chunk of readBytes(context.stdin, context.signal)) {
|
|
189
196
|
total += chunk.byteLength;
|
|
197
|
+
admit(chunk.byteLength);
|
|
190
198
|
if (total > maxBytes) throw new PublicDiagnostic(`input exceeds maximum size of ${maxBytes} bytes`);
|
|
191
199
|
await writeBytes(context.stdout, chunk, context.signal);
|
|
192
200
|
await yieldTurn(context.signal);
|
|
193
201
|
}
|
|
194
|
-
} else texts.push(await readSourceText(context.stdin, maxBytes, context.signal));
|
|
202
|
+
} else texts.push(await readSourceText(context.stdin, maxBytes, context.signal, admit));
|
|
195
203
|
} else {
|
|
196
204
|
try {
|
|
197
205
|
const targetPath = pathPosix.resolve(context.cwd, file);
|
|
198
206
|
const raw = await context.fs.readFile(targetPath, { signal: context.signal });
|
|
199
207
|
context.signal.throwIfAborted();
|
|
208
|
+
admit(raw.byteLength);
|
|
200
209
|
if (raw.byteLength > maxBytes) {
|
|
201
210
|
await writeText(context.stderr, `${name}: ${file}: input exceeds maximum size
|
|
202
211
|
`);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Poe Platform
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { type MetadataCommandsOptions } from "../safe-bash-metadata-engine/index.js";
|
|
2
|
+
export declare function evalSyncMktemp(opArgs: readonly string[], env: Readonly<Record<string, string>>, statTypeSync?: (filePath: string) => string | undefined, writeFileSync?: (filePath: string, bytes: Uint8Array) => boolean, mkdirSync?: (filePath: string) => boolean): string | undefined;
|
|
3
|
+
export declare function createMktempCommand(configuration?: MetadataCommandsOptions): import("../safe-bash-contracts/index.js").CommandDefinition;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { VirtualShellPlugin } from "../safe-bash-contracts/index.js";
|
|
2
|
+
import type { MetadataCommandsOptions } from "../safe-bash-metadata-engine/index.js";
|
|
3
|
+
export * from "./command.js";
|
|
4
|
+
export type { MetadataCommandsOptions as MktempCommandsOptions, MetadataLimits as MktempLimits } from "../safe-bash-metadata-engine/index.js";
|
|
5
|
+
export declare function createMktempCommands(options?: MetadataCommandsOptions): import("../safe-bash-contracts/index.js").CommandDefinition[];
|
|
6
|
+
export declare function mktempCommands(options?: MetadataCommandsOptions): VirtualShellPlugin;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createMktempCommand,
|
|
3
|
+
evalSyncMktemp
|
|
4
|
+
} from "../safe-bash/command-chunks/chunk-ZDN7MJE6.js";
|
|
5
|
+
import {
|
|
6
|
+
init_buffer
|
|
7
|
+
} from "../safe-bash/command-chunks/chunk-HX3SHTCE.js";
|
|
8
|
+
|
|
9
|
+
// packages/safe-bash-command-mktemp/src/index.ts
|
|
10
|
+
init_buffer();
|
|
11
|
+
function createMktempCommands(options = {}) {
|
|
12
|
+
return [createMktempCommand(options)];
|
|
13
|
+
}
|
|
14
|
+
function mktempCommands(options = {}) {
|
|
15
|
+
const commands = createMktempCommands(options);
|
|
16
|
+
return { name: "mktemp-commands", setup(host) {
|
|
17
|
+
for (const command of commands) host.commands.register(command, { replace: options.replace ?? false });
|
|
18
|
+
} };
|
|
19
|
+
}
|
|
20
|
+
export {
|
|
21
|
+
createMktempCommand,
|
|
22
|
+
createMktempCommands,
|
|
23
|
+
evalSyncMktemp,
|
|
24
|
+
mktempCommands
|
|
25
|
+
};
|
|
@@ -139,10 +139,12 @@ function output(context, text) {
|
|
|
139
139
|
return writeBytes(context.stdout, bytes, context.signal);
|
|
140
140
|
}
|
|
141
141
|
var ByteInputBudget = class {
|
|
142
|
-
constructor(maxInputBytes) {
|
|
142
|
+
constructor(maxInputBytes, inputBudget) {
|
|
143
143
|
this.maxInputBytes = maxInputBytes;
|
|
144
|
+
this.inputBudget = inputBudget;
|
|
144
145
|
}
|
|
145
146
|
maxInputBytes;
|
|
147
|
+
inputBudget;
|
|
146
148
|
#bytes = 0;
|
|
147
149
|
#failure;
|
|
148
150
|
assertOpen(signal) {
|
|
@@ -158,13 +160,14 @@ var ByteInputBudget = class {
|
|
|
158
160
|
throw this.#failure;
|
|
159
161
|
}
|
|
160
162
|
this.#bytes += chunk.byteLength;
|
|
163
|
+
this.inputBudget?.check(this.#bytes);
|
|
161
164
|
yield chunk;
|
|
162
165
|
this.assertOpen(signal);
|
|
163
166
|
}
|
|
164
167
|
}
|
|
165
168
|
};
|
|
166
169
|
async function* sources(context, operands, maxInputBytes, onFileError) {
|
|
167
|
-
const budget = new ByteInputBudget(maxInputBytes);
|
|
170
|
+
const budget = new ByteInputBudget(maxInputBytes, context.inputBudget);
|
|
168
171
|
let usedStdin = false;
|
|
169
172
|
let emptyChunks = 0;
|
|
170
173
|
for (const operand of operands.length ? operands : ["-"]) {
|
|
@@ -510,6 +513,7 @@ function defineOdCommand(handler) {
|
|
|
510
513
|
return await handler(context);
|
|
511
514
|
} catch (error) {
|
|
512
515
|
context.signal.throwIfAborted();
|
|
516
|
+
if (error instanceof Error && (error.name === "BudgetExceededError" || error.name === "AbortError")) throw error;
|
|
513
517
|
await writeDiagnostic(
|
|
514
518
|
context.stderr,
|
|
515
519
|
`${context.command}: ${publicDiagnosticMessage(error, context.onInternalError)}
|
|
@@ -7,6 +7,7 @@ init_buffer();
|
|
|
7
7
|
|
|
8
8
|
// packages/safe-bash-command-op/src/cli.ts
|
|
9
9
|
init_buffer();
|
|
10
|
+
import { isFsError } from "@poe-platform/safe-fs/core";
|
|
10
11
|
import { InputByteBudget } from "../safe-bash-contracts/io.js";
|
|
11
12
|
|
|
12
13
|
// packages/safe-bash-command-op/src/encoding.ts
|
|
@@ -3687,6 +3688,7 @@ function createOpCommand(options = {}) {
|
|
|
3687
3688
|
}
|
|
3688
3689
|
return { exitCode: 0 };
|
|
3689
3690
|
} catch (error) {
|
|
3691
|
+
if (error instanceof Error && error.name === "BudgetExceededError" || isFsError(error, "EPIPE")) throw error;
|
|
3690
3692
|
let message = error instanceof Error ? error.message : "operation failed";
|
|
3691
3693
|
try {
|
|
3692
3694
|
budget.assertOpen();
|
|
@@ -4666,7 +4668,7 @@ function createItemHandlers(backend) {
|
|
|
4666
4668
|
|
|
4667
4669
|
// packages/safe-bash-command-op/src/index.ts
|
|
4668
4670
|
import { readBytes } from "../safe-bash-contracts/index.js";
|
|
4669
|
-
import { resolvePath } from "@poe-platform/safe-fs/core";
|
|
4671
|
+
import { isFsError as isFsError2, resolvePath } from "@poe-platform/safe-fs/core";
|
|
4670
4672
|
|
|
4671
4673
|
// packages/safe-bash-command-op/src/types.ts
|
|
4672
4674
|
init_buffer();
|
|
@@ -4730,27 +4732,44 @@ function createOpCommand2(options = {}) {
|
|
|
4730
4732
|
if (!("fs" in context)) return command.execute(context);
|
|
4731
4733
|
const host = context;
|
|
4732
4734
|
const { fs, signal, cwd } = context;
|
|
4735
|
+
let inputBytes = 0;
|
|
4736
|
+
const account = (bytes) => {
|
|
4737
|
+
context.inputBudget?.check(inputBytes += bytes.byteLength);
|
|
4738
|
+
return bytes;
|
|
4739
|
+
};
|
|
4733
4740
|
const invocation = {
|
|
4734
4741
|
...host,
|
|
4735
4742
|
args: context.args,
|
|
4736
4743
|
env: { ...context.env },
|
|
4737
4744
|
signal,
|
|
4738
|
-
stdin:
|
|
4745
|
+
stdin: (async function* () {
|
|
4746
|
+
for await (const bytes of readBytes(context.stdin, signal)) yield account(bytes);
|
|
4747
|
+
})(),
|
|
4739
4748
|
stdout: context.stdout,
|
|
4740
4749
|
stderr: context.stderr,
|
|
4741
4750
|
...authentication === void 0 ? {} : { authentication },
|
|
4742
4751
|
...pluginScope === void 0 ? {} : { pluginScope },
|
|
4743
4752
|
...confirmPluginClear === void 0 ? {} : { confirmPluginClear },
|
|
4744
4753
|
...selectPlugin === void 0 ? {} : { selectPlugin },
|
|
4745
|
-
readFile:
|
|
4754
|
+
readFile: async (path) => {
|
|
4755
|
+
if (host.readFile) return account(await host.readFile(path));
|
|
4746
4756
|
signal.throwIfAborted();
|
|
4747
4757
|
const resolved = resolvePath(cwd, path);
|
|
4748
4758
|
const capabilities = fs.capabilitiesFor ? await fs.capabilitiesFor(resolved, { signal }) : fs.capabilities;
|
|
4749
4759
|
if (capabilities.read !== true) throw new Error("op requires VFS read capability");
|
|
4750
|
-
|
|
4760
|
+
let bytes;
|
|
4761
|
+
try {
|
|
4762
|
+
bytes = await fs.readFile(resolved, {
|
|
4763
|
+
signal,
|
|
4764
|
+
...context.inputBudget ? { maxBytes: Math.max(0, context.inputBudget.maxBytes - inputBytes) } : {}
|
|
4765
|
+
});
|
|
4766
|
+
} catch (error) {
|
|
4767
|
+
if (isFsError2(error, "EFBIG") && context.inputBudget) context.inputBudget.check(context.inputBudget.maxBytes + 1);
|
|
4768
|
+
throw error;
|
|
4769
|
+
}
|
|
4751
4770
|
signal.throwIfAborted();
|
|
4752
|
-
return Uint8Array.from(bytes);
|
|
4753
|
-
}
|
|
4771
|
+
return Uint8Array.from(account(bytes));
|
|
4772
|
+
},
|
|
4754
4773
|
writeFile: host.writeFile ?? (async (path, bytes, settings = {}) => {
|
|
4755
4774
|
signal.throwIfAborted();
|
|
4756
4775
|
const resolved = resolvePath(cwd, path);
|