@sema-agent/core 2.7.0 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/send-message-tool.d.ts +2 -0
- package/dist/agents/send-message-tool.js +1 -1
- package/dist/core/runner/prepare-task.js +1 -0
- package/dist/core/store-contracts/file-snapshot-store-contract.d.ts +3 -1
- package/dist/core/store-contracts/file-snapshot-store-contract.js +11 -3
- package/dist/core/tools.d.ts +6 -2
- package/dist/core/tools.js +3 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -0
- package/dist/tools/fs/bash-readonly-classifier.js +35 -21
- package/dist/tools/fs/fs-bash.d.ts +2 -1
- package/dist/tools/fs/fs-bash.js +19 -5
- package/dist/tools/fs/index.js +1 -0
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Type } from "typebox";
|
|
2
2
|
import type { Runner } from "../core/runner/runtask.js";
|
|
3
3
|
import type { TaskNotificationPayload } from "../core/task-notification.js";
|
|
4
|
+
import { type ToolCtxEnricher } from "../core/tools.js";
|
|
4
5
|
import { SubagentRetainLedger } from "./retain-ledger.js";
|
|
5
6
|
import { type SubagentSteerHandle } from "./subagent.js";
|
|
6
7
|
export declare const SEND_MESSAGE_TOOL_NAME = "SendMessage";
|
|
@@ -35,6 +36,7 @@ export interface SendMessageToolOptions {
|
|
|
35
36
|
content: string;
|
|
36
37
|
details?: unknown;
|
|
37
38
|
}>;
|
|
39
|
+
enrichCtx?: ToolCtxEnricher;
|
|
38
40
|
}
|
|
39
41
|
export declare const SEND_MESSAGE_SUMMARY_MAX = 200;
|
|
40
42
|
export declare function clipSendMessageSummary(raw: string): string;
|
|
@@ -1278,6 +1278,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1278
1278
|
...(internals?.parentRetainLedger !== undefined ? { siblingRetain: internals.parentRetainLedger } : {}),
|
|
1279
1279
|
...(internals?.parentTaskId !== undefined ? { parentTaskId: internals.parentTaskId } : {}),
|
|
1280
1280
|
...(internals?.parentSessionId !== undefined ? { parentSessionId: internals.parentSessionId } : {}),
|
|
1281
|
+
enrichCtx: enrichSpecToolCtx,
|
|
1281
1282
|
...(deps.rosterStore !== undefined ? { roster: deps.rosterStore } : {}),
|
|
1282
1283
|
...(deps.onBackgroundChildEvent ? { onBackgroundChildEvent: deps.onBackgroundChildEvent } : {}),
|
|
1283
1284
|
...(deps.backgroundAgentStore !== undefined ? { agentStore: deps.backgroundAgentStore } : {}),
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { FileSnapshotStore } from "../file-snapshot-store.js";
|
|
2
2
|
import { type ContractAssertionRunner } from "./contract-harness.js";
|
|
3
|
-
export declare function fileSnapshotStoreContract(make: () => FileSnapshotStore, runAssertion?: ContractAssertionRunner
|
|
3
|
+
export declare function fileSnapshotStoreContract(make: () => FileSnapshotStore, runAssertion?: ContractAssertionRunner, options?: {
|
|
4
|
+
blobGc?: "immediate" | "eventual";
|
|
5
|
+
}): Promise<void>;
|
|
@@ -4,8 +4,9 @@ import { beginContract } from "./contract-harness.js";
|
|
|
4
4
|
const bytes = (s) => new TextEncoder().encode(s);
|
|
5
5
|
const sha256 = (s) => createHash("sha256").update(bytes(s)).digest("hex");
|
|
6
6
|
const srcBlob = async (hash) => hash === sha256("alpha") ? bytes("alpha") : hash === sha256("beta") ? bytes("beta") : undefined;
|
|
7
|
-
export async function fileSnapshotStoreContract(make, runAssertion) {
|
|
7
|
+
export async function fileSnapshotStoreContract(make, runAssertion, options) {
|
|
8
8
|
const { run, settle } = beginContract(runAssertion);
|
|
9
|
+
const blobGc = options?.blobGc ?? "immediate";
|
|
9
10
|
run("kit prerequisites: exportManifest/getBlob/putBlob/importManifest are implemented (REQUIRED by this kit)", async () => {
|
|
10
11
|
const probe = make();
|
|
11
12
|
const missing = ["exportManifest", "getBlob", "putBlob", "importManifest"].filter((m) => typeof probe[m] !== "function");
|
|
@@ -115,12 +116,19 @@ export async function fileSnapshotStoreContract(make, runAssertion) {
|
|
|
115
116
|
assert.deepEqual(await store.listKeys("sc"), ["k1"]);
|
|
116
117
|
assert.deepEqual([...(await store.getBlob(sha256("alpha")))], [...bytes("alpha")]);
|
|
117
118
|
});
|
|
118
|
-
run("reap keep-nothing drops the key
|
|
119
|
+
run("reap keep-nothing drops the key IMMEDIATELY (every backend)", async () => {
|
|
119
120
|
const store = make();
|
|
120
121
|
await store.importManifest("sc", "k1", new Map([["a.txt", sha256("alpha")]]), srcBlob);
|
|
121
122
|
assert.equal(await store.reap("sc", []), 1);
|
|
122
123
|
assert.equal(await store.has("sc", "k1"), false);
|
|
123
|
-
assert.equal(await store.getBlob(sha256("alpha")), undefined);
|
|
124
124
|
});
|
|
125
|
+
if (blobGc === "immediate") {
|
|
126
|
+
run("reap keep-nothing GCs the now-unreferenced blob bytes immediately (blobGc: immediate)", async () => {
|
|
127
|
+
const store = make();
|
|
128
|
+
await store.importManifest("sc", "k1", new Map([["a.txt", sha256("alpha")]]), srcBlob);
|
|
129
|
+
assert.equal(await store.reap("sc", []), 1);
|
|
130
|
+
assert.equal(await store.getBlob(sha256("alpha")), undefined);
|
|
131
|
+
});
|
|
132
|
+
}
|
|
125
133
|
await settle();
|
|
126
134
|
}
|
package/dist/core/tools.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { TSchema } from "typebox";
|
|
2
2
|
import type { AgentTool } from "../internal/harness.js";
|
|
3
|
-
import type { ToolSpec } from "./types.js";
|
|
3
|
+
import type { ToolExecuteContext, ToolSpec } from "./types.js";
|
|
4
4
|
export declare function errorResult(text: string, details?: unknown): {
|
|
5
5
|
content: string;
|
|
6
6
|
isError: true;
|
|
@@ -8,4 +8,8 @@ export declare function errorResult(text: string, details?: unknown): {
|
|
|
8
8
|
};
|
|
9
9
|
export declare function isDefineToolProduct(x: unknown): x is AgentTool;
|
|
10
10
|
export declare function stampDefineToolBrand<T extends object>(tool: T): T;
|
|
11
|
-
export
|
|
11
|
+
export type ToolCtxEnricher = (base: ToolExecuteContext) => ToolExecuteContext;
|
|
12
|
+
export interface DefineToolOptions {
|
|
13
|
+
enrichCtx?: ToolCtxEnricher;
|
|
14
|
+
}
|
|
15
|
+
export declare function defineTool<TParams extends TSchema = TSchema>(spec: ToolSpec<TParams>, options?: DefineToolOptions): AgentTool<TParams>;
|
package/dist/core/tools.js
CHANGED
|
@@ -33,7 +33,7 @@ export function stampDefineToolBrand(tool) {
|
|
|
33
33
|
Object.defineProperty(tool, DEFINE_TOOL_BRAND, { value: true, enumerable: false });
|
|
34
34
|
return tool;
|
|
35
35
|
}
|
|
36
|
-
export function defineTool(spec) {
|
|
36
|
+
export function defineTool(spec, options) {
|
|
37
37
|
const executionMode = spec.executionMode ?? (spec.effect === "read" ? "parallel" : "sequential");
|
|
38
38
|
const tool = {
|
|
39
39
|
name: spec.name,
|
|
@@ -60,7 +60,8 @@ export function defineTool(spec) {
|
|
|
60
60
|
}
|
|
61
61
|
let ret;
|
|
62
62
|
try {
|
|
63
|
-
|
|
63
|
+
const baseCtx = { toolCallId, signal };
|
|
64
|
+
ret = await spec.execute(params, options?.enrichCtx ? { ...options.enrichCtx(baseCtx), toolCallId, signal } : baseCtx);
|
|
64
65
|
}
|
|
65
66
|
catch (err) {
|
|
66
67
|
throw new Error(formatToolError(err));
|
package/dist/index.d.ts
CHANGED
|
@@ -69,7 +69,7 @@ export type { InvariantKind, FunctionContract, Invariant, InvariantViolation, Ch
|
|
|
69
69
|
export { HAND_TOOL_EFFECTS, bashReversibilityProbe, BASH_READONLY_DEFAULT_ALLOW, parseLeadingCommandName, classifyCompoundReadonly, MAX_EDIT_BYTES } from "./tools/fs/index.js";
|
|
70
70
|
export { classifyCompoundReadonlyDetailed, formatOutOfRootReadApprovalOption, type BashReadonlyRootBoundary, type CompoundReadonlyVerdict, } from "./tools/fs/index.js";
|
|
71
71
|
export { resolveBashTimeoutCaps } from "./tools/fs/index.js";
|
|
72
|
-
export { InMemoryToolResultStore, OFFLOAD_TOOL_NAME, DEFAULT_TOOL_RESULT_THRESHOLD_CHARS, type ToolResultStore, type ToolResultSlice, } from "./core/tool-result-store.js";
|
|
72
|
+
export { InMemoryToolResultStore, OFFLOAD_TOOL_NAME, DEFAULT_TOOL_RESULT_THRESHOLD_CHARS, assertSafeToolResultRef, type ToolResultStore, type ToolResultSlice, } from "./core/tool-result-store.js";
|
|
73
73
|
export { InMemoryCheckpointStore, CheckpointError, mintCheckpointToken, checkpointVersionOf, CURRENT_CHECKPOINT_VERSION, MAX_SUPPORTED_CHECKPOINT_VERSION, RESOURCE_CHECKPOINT_VERSION, WALLTIME_CHECKPOINT_VERSION, debitLedger, remainingBudgetMicroUsd, remainingWalltimeMs, winnerFromOutcome, validatePendingSteer, riskSeverity, buildRiskDescriptor, summarizeCheckpoint, type RiskDescriptor, type CheckpointStore, type CheckpointSummary, type Checkpoint, type CheckpointToken, type CheckpointGate, type CheckpointState, type SerializedCheckpointState, type CheckpointFaultMode, type PendingAction, type ResumeOutcome, type ResolvedOutcome, type ReopenReason, type ResolveExpectation, type SafetyAxis, type ResourceLedger, type ResourceLimitReason, } from "./core/checkpoint-store.js";
|
|
74
74
|
export { InMemoryFileSnapshotStore, DEFAULT_SNAPSHOT_BOUNDS } from "./core/file-snapshot-store.js";
|
|
75
75
|
export { captureManifest, applyManifest } from "./core/file-snapshot-store.js";
|
package/dist/index.js
CHANGED
|
@@ -60,7 +60,7 @@ export { deriveInvariants, checkInvariants } from "./core/property-harness.js";
|
|
|
60
60
|
export { HAND_TOOL_EFFECTS, bashReversibilityProbe, BASH_READONLY_DEFAULT_ALLOW, parseLeadingCommandName, classifyCompoundReadonly, MAX_EDIT_BYTES } from "./tools/fs/index.js";
|
|
61
61
|
export { classifyCompoundReadonlyDetailed, formatOutOfRootReadApprovalOption, } from "./tools/fs/index.js";
|
|
62
62
|
export { resolveBashTimeoutCaps } from "./tools/fs/index.js";
|
|
63
|
-
export { InMemoryToolResultStore, OFFLOAD_TOOL_NAME, DEFAULT_TOOL_RESULT_THRESHOLD_CHARS, } from "./core/tool-result-store.js";
|
|
63
|
+
export { InMemoryToolResultStore, OFFLOAD_TOOL_NAME, DEFAULT_TOOL_RESULT_THRESHOLD_CHARS, assertSafeToolResultRef, } from "./core/tool-result-store.js";
|
|
64
64
|
export { InMemoryCheckpointStore, CheckpointError, mintCheckpointToken, checkpointVersionOf, CURRENT_CHECKPOINT_VERSION, MAX_SUPPORTED_CHECKPOINT_VERSION, RESOURCE_CHECKPOINT_VERSION, WALLTIME_CHECKPOINT_VERSION, debitLedger, remainingBudgetMicroUsd, remainingWalltimeMs, winnerFromOutcome, validatePendingSteer, riskSeverity, buildRiskDescriptor, summarizeCheckpoint, } from "./core/checkpoint-store.js";
|
|
65
65
|
export { InMemoryFileSnapshotStore, DEFAULT_SNAPSHOT_BOUNDS } from "./core/file-snapshot-store.js";
|
|
66
66
|
export { captureManifest, applyManifest } from "./core/file-snapshot-store.js";
|
|
@@ -17,4 +17,5 @@ export interface CompoundReadonlyVerdict {
|
|
|
17
17
|
}
|
|
18
18
|
export declare function formatOutOfRootReadApprovalOption(directory: string): string;
|
|
19
19
|
export declare function classifyCompoundReadonlyDetailed(command: string, allow: ReadonlySet<string>, boundary?: BashReadonlyRootBoundary): CompoundReadonlyVerdict;
|
|
20
|
+
export declare function classifySimpleCommandReadBoundary(command: string, boundary: BashReadonlyRootBoundary): CompoundReadonlyVerdict;
|
|
20
21
|
export declare function classifyCompoundReadonly(command: string, allow: ReadonlySet<string>, boundary?: BashReadonlyRootBoundary): string | undefined;
|
|
@@ -82,6 +82,13 @@ function resolveOperandLexically(base, operand, homeDir) {
|
|
|
82
82
|
return undefined;
|
|
83
83
|
return normalizeAbsPathLexicalEitherFamily(`${base.replace(/[/\\]+$/, "")}/${raw}`);
|
|
84
84
|
}
|
|
85
|
+
function tokenizeSegment(segment) {
|
|
86
|
+
return segment
|
|
87
|
+
.trim()
|
|
88
|
+
.split(/\s+/)
|
|
89
|
+
.filter((t) => t.length > 0)
|
|
90
|
+
.map(foldQuoteRemovalToken);
|
|
91
|
+
}
|
|
85
92
|
function collectSegmentBoundaryFindings(toks, boundary) {
|
|
86
93
|
const name = toks[0];
|
|
87
94
|
if (NO_PATH_OPERAND_COMMANDS.has(name))
|
|
@@ -220,8 +227,7 @@ export function classifyCompoundReadonlyDetailed(command, allow, boundary) {
|
|
|
220
227
|
const STDIN_FILE_FLOOR = { cat: 1, grep: 2, head: 1, tail: 1, wc: 1, cut: 1, tr: Infinity };
|
|
221
228
|
const foldedSegments = [];
|
|
222
229
|
for (let si = 0; si < segments.length; si++) {
|
|
223
|
-
const toks = segments[si]
|
|
224
|
-
.map(foldQuoteRemovalToken);
|
|
230
|
+
const toks = tokenizeSegment(segments[si]);
|
|
225
231
|
if (toks.length === 0)
|
|
226
232
|
continue;
|
|
227
233
|
foldedSegments.push(toks);
|
|
@@ -273,27 +279,35 @@ export function classifyCompoundReadonlyDetailed(command, allow, boundary) {
|
|
|
273
279
|
return { reason: "reads a device/special file that is either unbounded (/dev/zero, /dev/stdin, /proc/<pid>/fd/0, … — blocks the pipeline until the tool timeout) or process-private (/proc/<pid>/environ, /proc/<pid>/mem, …) — not auto-allowed" };
|
|
274
280
|
}
|
|
275
281
|
}
|
|
276
|
-
if (boundary !== undefined)
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
const allowed = boundary.roots.length > 0 ? boundary.roots.join(", ") : "(none)";
|
|
289
|
-
return {
|
|
290
|
-
reason: `"${outside[0].command}" reads ${paths}, outside the allowed directories for this session: ${allowed} — not auto-allowed`,
|
|
291
|
-
outOfRootRead: true,
|
|
292
|
-
outOfRootPaths: outside.map((o) => o.path),
|
|
293
|
-
};
|
|
282
|
+
if (boundary !== undefined)
|
|
283
|
+
return evaluateReadBoundary(foldedSegments, boundary);
|
|
284
|
+
return {};
|
|
285
|
+
}
|
|
286
|
+
function evaluateReadBoundary(foldedSegments, boundary) {
|
|
287
|
+
const outside = [];
|
|
288
|
+
for (const toks of foldedSegments) {
|
|
289
|
+
for (const finding of collectSegmentBoundaryFindings(toks, boundary)) {
|
|
290
|
+
if (finding.kind === "unresolvable")
|
|
291
|
+
return { reason: finding.reason };
|
|
292
|
+
if (!outside.some((o) => o.path === finding.path))
|
|
293
|
+
outside.push(finding);
|
|
294
294
|
}
|
|
295
295
|
}
|
|
296
|
-
|
|
296
|
+
if (outside.length === 0)
|
|
297
|
+
return {};
|
|
298
|
+
const paths = outside.map((o) => `"${o.path}"`).join(", ");
|
|
299
|
+
const allowed = boundary.roots.length > 0 ? boundary.roots.join(", ") : "(none)";
|
|
300
|
+
return {
|
|
301
|
+
reason: `"${outside[0].command}" reads ${paths}, outside the allowed directories for this session: ${allowed} — not auto-allowed`,
|
|
302
|
+
outOfRootRead: true,
|
|
303
|
+
outOfRootPaths: outside.map((o) => o.path),
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
export function classifySimpleCommandReadBoundary(command, boundary) {
|
|
307
|
+
const toks = tokenizeSegment(command);
|
|
308
|
+
if (toks.length === 0)
|
|
309
|
+
return {};
|
|
310
|
+
return evaluateReadBoundary([toks], boundary);
|
|
297
311
|
}
|
|
298
312
|
export function classifyCompoundReadonly(command, allow, boundary) {
|
|
299
313
|
return classifyCompoundReadonlyDetailed(command, allow, boundary).reason;
|
|
@@ -31,9 +31,10 @@ export declare function createBashTool(env: ExecutionEnv, rootCanonical: string,
|
|
|
31
31
|
bashDefaultTimeoutMs?: number;
|
|
32
32
|
bashMaxTimeoutMs?: number;
|
|
33
33
|
}): AgentTool;
|
|
34
|
-
export declare function createBashReadonlyTool(env: ExecutionEnv, rootCanonical: string, allow: ReadonlySet<string>, execClamp?: ExecClampOption,
|
|
34
|
+
export declare function createBashReadonlyTool(env: ExecutionEnv, rootCanonical: string, allow: ReadonlySet<string>, execClamp?: ExecClampOption, opts?: {
|
|
35
35
|
bashDefaultTimeoutMs?: number;
|
|
36
36
|
bashMaxTimeoutMs?: number;
|
|
37
|
+
additionalRoots?: readonly string[];
|
|
37
38
|
}): AgentTool;
|
|
38
39
|
export declare function createEnvTaskOutputTool(env: ExecutionEnv): AgentTool;
|
|
39
40
|
export declare function createEnvTaskStopTool(env: ExecutionEnv, registry?: TaskRegistry): AgentTool;
|
package/dist/tools/fs/fs-bash.js
CHANGED
|
@@ -8,7 +8,7 @@ import { MCP_IMAGE_MAX_BASE64 } from "../../core/mcp.js";
|
|
|
8
8
|
import { imageMagicMatches, withinAnyRoot } from "./safety.js";
|
|
9
9
|
import { ghRateLimitHint } from "./gh-rate-limit.js";
|
|
10
10
|
import { resolveBashTimeoutCaps, bashTimeoutCapsSec, bashMaxOutputChars, clipShellOutput, writeShellOverflowFile, shellRecoveryHint, CWD_SENTINEL, } from "./fs-shared.js";
|
|
11
|
-
import { BASH_READONLY_DEFAULT_ALLOW, coarseReadonlyCheck, classifyCompoundReadonly } from "./bash-readonly-classifier.js";
|
|
11
|
+
import { BASH_READONLY_DEFAULT_ALLOW, coarseReadonlyCheck, classifyCompoundReadonly, classifySimpleCommandReadBoundary, } from "./bash-readonly-classifier.js";
|
|
12
12
|
export function bashReversibilityProbe(allow, boundary) {
|
|
13
13
|
const allowSet = new Set(allow ?? BASH_READONLY_DEFAULT_ALLOW);
|
|
14
14
|
return (args) => {
|
|
@@ -627,16 +627,20 @@ export function createBashTool(env, rootCanonical, coAuthor = false, cwdRef = {
|
|
|
627
627
|
},
|
|
628
628
|
});
|
|
629
629
|
}
|
|
630
|
-
export function createBashReadonlyTool(env, rootCanonical, allow, execClamp,
|
|
631
|
-
const timeoutCaps = resolveBashTimeoutCaps(
|
|
630
|
+
export function createBashReadonlyTool(env, rootCanonical, allow, execClamp, opts) {
|
|
631
|
+
const timeoutCaps = resolveBashTimeoutCaps(opts);
|
|
632
632
|
const timeoutCapsSecView = bashTimeoutCapsSec(timeoutCaps);
|
|
633
633
|
const sample = [...allow].slice(0, 6).join(", ");
|
|
634
|
+
const readRoots = [rootCanonical, ...(opts?.additionalRoots ?? [])];
|
|
635
|
+
const mintedOutputFiles = new Set();
|
|
634
636
|
return defineTool({
|
|
635
637
|
name: "Bash",
|
|
636
638
|
contract: { contractId: "core.bash_readonly@1", implementationRevision: "1" },
|
|
637
639
|
description: `Run a SINGLE read-only inspection command (e.g. ${sample}, …) and return its output. Shell ` +
|
|
638
640
|
"operators (pipes, redirects, ;, &&, command substitution, subshells) are rejected and only " +
|
|
639
|
-
"allowlisted commands run.
|
|
641
|
+
"allowlisted commands run. Reads are confined to the workspace root(s): a path outside them is " +
|
|
642
|
+
"refused, as is one that cannot be resolved statically (e.g. a `~` path). Still subject to the " +
|
|
643
|
+
"deployment's approval policy.",
|
|
640
644
|
parameters: Type.Object({
|
|
641
645
|
command: Type.String({ description: "A single allowlisted read-only command (no shell operators)." }),
|
|
642
646
|
timeout: Type.Optional(Type.Number({ description: `Timeout in milliseconds (default ${timeoutCaps.defaultMs}, max ${timeoutCaps.maxMs}; requests above the max are capped to it).` })),
|
|
@@ -647,7 +651,17 @@ export function createBashReadonlyTool(env, rootCanonical, allow, execClamp, tim
|
|
|
647
651
|
const reason = coarseReadonlyCheck(command, allow);
|
|
648
652
|
if (reason)
|
|
649
653
|
return errorResult(`Error (Bash): ${reason}`);
|
|
650
|
-
|
|
654
|
+
const boundary = classifySimpleCommandReadBoundary(command, { roots: [...readRoots, ...mintedOutputFiles], cwd: rootCanonical });
|
|
655
|
+
if (boundary.reason !== undefined) {
|
|
656
|
+
return errorResult(`Error (Bash): ${boundary.reason}. bash_readonly is confined to the workspace roots; it has no approval path, so the call is refused rather than escalated.`, { code: "readonly_out_of_root", paths: boundary.outOfRootPaths ?? [] });
|
|
657
|
+
}
|
|
658
|
+
const result = await runShell(env, rootCanonical, "Bash", command, msTimeoutToRequestedSec(timeout), timeoutCapsSecView, ctx.signal, undefined, undefined, execClamp, ctx.toolCallId, true);
|
|
659
|
+
if (typeof result !== "string") {
|
|
660
|
+
const outputFile = result.details.output_file;
|
|
661
|
+
if (typeof outputFile === "string")
|
|
662
|
+
mintedOutputFiles.add(outputFile);
|
|
663
|
+
}
|
|
664
|
+
return result;
|
|
651
665
|
},
|
|
652
666
|
});
|
|
653
667
|
}
|
package/dist/tools/fs/index.js
CHANGED
|
@@ -38,6 +38,7 @@ export function createHandsToolkit(env, readFileState, rootCanonical, opts = {})
|
|
|
38
38
|
? createBashReadonlyTool(env, rootCanonical, new Set(bashReadonlyAllow ?? BASH_READONLY_DEFAULT_ALLOW), opts.execClamp, {
|
|
39
39
|
...(opts.bashDefaultTimeoutMs !== undefined ? { bashDefaultTimeoutMs: opts.bashDefaultTimeoutMs } : {}),
|
|
40
40
|
...(opts.bashMaxTimeoutMs !== undefined ? { bashMaxTimeoutMs: opts.bashMaxTimeoutMs } : {}),
|
|
41
|
+
...(additionalRoots !== undefined ? { additionalRoots } : {}),
|
|
41
42
|
})
|
|
42
43
|
: createBashTool(env, rootCanonical, commitCoAuthor, cwdRef, {
|
|
43
44
|
taskRegistry: opts.taskRegistry,
|