@polos/sdk 0.2.0 → 0.2.2
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/index.cjs +86 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +27 -5
- package/dist/index.d.ts +27 -5
- package/dist/index.js +86 -29
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -4787,15 +4787,15 @@ declare function stripAnsi(text: string): string;
|
|
|
4787
4787
|
declare function createExecTool(getEnv: () => Promise<ExecutionEnvironment>, config?: ExecToolConfig): ToolWorkflow;
|
|
4788
4788
|
|
|
4789
4789
|
/**
|
|
4790
|
-
* Path-based approval for
|
|
4790
|
+
* Path-based approval for sandbox tools.
|
|
4791
4791
|
*
|
|
4792
|
-
* When pathRestriction is set,
|
|
4792
|
+
* When pathRestriction is set, tools (read, write, edit, glob, grep) allow
|
|
4793
4793
|
* operations within the restricted path without approval. Operations
|
|
4794
4794
|
* outside the restriction suspend for user approval.
|
|
4795
4795
|
*/
|
|
4796
4796
|
|
|
4797
4797
|
/**
|
|
4798
|
-
* Configuration for path-restricted approval on
|
|
4798
|
+
* Configuration for path-restricted approval on sandbox tools.
|
|
4799
4799
|
*/
|
|
4800
4800
|
interface PathRestrictionConfig {
|
|
4801
4801
|
/** Directory to allow without approval. Paths outside require approval. */
|
|
@@ -4816,21 +4816,43 @@ declare function createReadTool(getEnv: () => Promise<ExecutionEnvironment>, pat
|
|
|
4816
4816
|
|
|
4817
4817
|
/**
|
|
4818
4818
|
* Write tool — create or overwrite files in the execution environment.
|
|
4819
|
+
*
|
|
4820
|
+
* When pathRestriction is set, writes within the restriction proceed
|
|
4821
|
+
* without approval. Writes outside the restriction suspend for user approval.
|
|
4822
|
+
* Set approval to 'always' to require approval for every write, or 'none'
|
|
4823
|
+
* to skip approval entirely (overrides path restriction).
|
|
4819
4824
|
*/
|
|
4820
4825
|
|
|
4826
|
+
interface WriteToolConfig {
|
|
4827
|
+
/** Explicit approval override. 'always' = approve every write, 'none' = never approve. */
|
|
4828
|
+
approval?: ToolApproval;
|
|
4829
|
+
/** Path restriction config — writes inside are allowed, outside require approval. */
|
|
4830
|
+
pathConfig?: PathRestrictionConfig;
|
|
4831
|
+
}
|
|
4821
4832
|
/**
|
|
4822
4833
|
* Create the write tool for writing file contents.
|
|
4823
4834
|
*/
|
|
4824
|
-
declare function createWriteTool(getEnv: () => Promise<ExecutionEnvironment>,
|
|
4835
|
+
declare function createWriteTool(getEnv: () => Promise<ExecutionEnvironment>, config?: WriteToolConfig): ToolWorkflow;
|
|
4825
4836
|
|
|
4826
4837
|
/**
|
|
4827
4838
|
* Edit tool — find-and-replace text in files in the execution environment.
|
|
4839
|
+
*
|
|
4840
|
+
* When pathRestriction is set, edits within the restriction proceed
|
|
4841
|
+
* without approval. Edits outside the restriction suspend for user approval.
|
|
4842
|
+
* Set approval to 'always' to require approval for every edit, or 'none'
|
|
4843
|
+
* to skip approval entirely (overrides path restriction).
|
|
4828
4844
|
*/
|
|
4829
4845
|
|
|
4846
|
+
interface EditToolConfig {
|
|
4847
|
+
/** Explicit approval override. 'always' = approve every edit, 'none' = never approve. */
|
|
4848
|
+
approval?: ToolApproval;
|
|
4849
|
+
/** Path restriction config — edits inside are allowed, outside require approval. */
|
|
4850
|
+
pathConfig?: PathRestrictionConfig;
|
|
4851
|
+
}
|
|
4830
4852
|
/**
|
|
4831
4853
|
* Create the edit tool for find-and-replace in files.
|
|
4832
4854
|
*/
|
|
4833
|
-
declare function createEditTool(getEnv: () => Promise<ExecutionEnvironment>,
|
|
4855
|
+
declare function createEditTool(getEnv: () => Promise<ExecutionEnvironment>, config?: EditToolConfig): ToolWorkflow;
|
|
4834
4856
|
|
|
4835
4857
|
/**
|
|
4836
4858
|
* Glob tool — find files by pattern in the execution environment.
|
package/dist/index.d.ts
CHANGED
|
@@ -4787,15 +4787,15 @@ declare function stripAnsi(text: string): string;
|
|
|
4787
4787
|
declare function createExecTool(getEnv: () => Promise<ExecutionEnvironment>, config?: ExecToolConfig): ToolWorkflow;
|
|
4788
4788
|
|
|
4789
4789
|
/**
|
|
4790
|
-
* Path-based approval for
|
|
4790
|
+
* Path-based approval for sandbox tools.
|
|
4791
4791
|
*
|
|
4792
|
-
* When pathRestriction is set,
|
|
4792
|
+
* When pathRestriction is set, tools (read, write, edit, glob, grep) allow
|
|
4793
4793
|
* operations within the restricted path without approval. Operations
|
|
4794
4794
|
* outside the restriction suspend for user approval.
|
|
4795
4795
|
*/
|
|
4796
4796
|
|
|
4797
4797
|
/**
|
|
4798
|
-
* Configuration for path-restricted approval on
|
|
4798
|
+
* Configuration for path-restricted approval on sandbox tools.
|
|
4799
4799
|
*/
|
|
4800
4800
|
interface PathRestrictionConfig {
|
|
4801
4801
|
/** Directory to allow without approval. Paths outside require approval. */
|
|
@@ -4816,21 +4816,43 @@ declare function createReadTool(getEnv: () => Promise<ExecutionEnvironment>, pat
|
|
|
4816
4816
|
|
|
4817
4817
|
/**
|
|
4818
4818
|
* Write tool — create or overwrite files in the execution environment.
|
|
4819
|
+
*
|
|
4820
|
+
* When pathRestriction is set, writes within the restriction proceed
|
|
4821
|
+
* without approval. Writes outside the restriction suspend for user approval.
|
|
4822
|
+
* Set approval to 'always' to require approval for every write, or 'none'
|
|
4823
|
+
* to skip approval entirely (overrides path restriction).
|
|
4819
4824
|
*/
|
|
4820
4825
|
|
|
4826
|
+
interface WriteToolConfig {
|
|
4827
|
+
/** Explicit approval override. 'always' = approve every write, 'none' = never approve. */
|
|
4828
|
+
approval?: ToolApproval;
|
|
4829
|
+
/** Path restriction config — writes inside are allowed, outside require approval. */
|
|
4830
|
+
pathConfig?: PathRestrictionConfig;
|
|
4831
|
+
}
|
|
4821
4832
|
/**
|
|
4822
4833
|
* Create the write tool for writing file contents.
|
|
4823
4834
|
*/
|
|
4824
|
-
declare function createWriteTool(getEnv: () => Promise<ExecutionEnvironment>,
|
|
4835
|
+
declare function createWriteTool(getEnv: () => Promise<ExecutionEnvironment>, config?: WriteToolConfig): ToolWorkflow;
|
|
4825
4836
|
|
|
4826
4837
|
/**
|
|
4827
4838
|
* Edit tool — find-and-replace text in files in the execution environment.
|
|
4839
|
+
*
|
|
4840
|
+
* When pathRestriction is set, edits within the restriction proceed
|
|
4841
|
+
* without approval. Edits outside the restriction suspend for user approval.
|
|
4842
|
+
* Set approval to 'always' to require approval for every edit, or 'none'
|
|
4843
|
+
* to skip approval entirely (overrides path restriction).
|
|
4828
4844
|
*/
|
|
4829
4845
|
|
|
4846
|
+
interface EditToolConfig {
|
|
4847
|
+
/** Explicit approval override. 'always' = approve every edit, 'none' = never approve. */
|
|
4848
|
+
approval?: ToolApproval;
|
|
4849
|
+
/** Path restriction config — edits inside are allowed, outside require approval. */
|
|
4850
|
+
pathConfig?: PathRestrictionConfig;
|
|
4851
|
+
}
|
|
4830
4852
|
/**
|
|
4831
4853
|
* Create the edit tool for find-and-replace in files.
|
|
4832
4854
|
*/
|
|
4833
|
-
declare function createEditTool(getEnv: () => Promise<ExecutionEnvironment>,
|
|
4855
|
+
declare function createEditTool(getEnv: () => Promise<ExecutionEnvironment>, config?: EditToolConfig): ToolWorkflow;
|
|
4834
4856
|
|
|
4835
4857
|
/**
|
|
4836
4858
|
* Glob tool — find files by pattern in the execution environment.
|
package/dist/index.js
CHANGED
|
@@ -292,7 +292,7 @@ var OrchestratorClient = class {
|
|
|
292
292
|
}
|
|
293
293
|
if (attempt < retries) {
|
|
294
294
|
const delay = Math.min(1e3 * Math.pow(2, attempt), 16e3);
|
|
295
|
-
await new Promise((
|
|
295
|
+
await new Promise((resolve10) => setTimeout(resolve10, delay));
|
|
296
296
|
}
|
|
297
297
|
}
|
|
298
298
|
}
|
|
@@ -744,7 +744,7 @@ var OrchestratorClient = class {
|
|
|
744
744
|
if (execution.status === "completed" || execution.status === "failed" || execution.status === "cancelled") {
|
|
745
745
|
return execution;
|
|
746
746
|
}
|
|
747
|
-
await new Promise((
|
|
747
|
+
await new Promise((resolve10) => setTimeout(resolve10, pollInterval));
|
|
748
748
|
}
|
|
749
749
|
throw new Error(`Execution ${executionId} timed out after ${String(timeout)}ms`);
|
|
750
750
|
}
|
|
@@ -1670,7 +1670,7 @@ function calculateDelay(attempt, options) {
|
|
|
1670
1670
|
return Math.round(delay);
|
|
1671
1671
|
}
|
|
1672
1672
|
function sleep(ms) {
|
|
1673
|
-
return new Promise((
|
|
1673
|
+
return new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
1674
1674
|
}
|
|
1675
1675
|
async function retry(fn, options = {}) {
|
|
1676
1676
|
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
@@ -1856,7 +1856,7 @@ function createStepHelper(options) {
|
|
|
1856
1856
|
if (options2.days) totalSeconds += options2.days * 86400;
|
|
1857
1857
|
if (options2.weeks) totalSeconds += options2.weeks * 604800;
|
|
1858
1858
|
const totalMs = totalSeconds * 1e3;
|
|
1859
|
-
await new Promise((
|
|
1859
|
+
await new Promise((resolve10) => setTimeout(resolve10, totalMs));
|
|
1860
1860
|
store.set(key, { wait_until: new Date(Date.now() + totalMs).toISOString() });
|
|
1861
1861
|
},
|
|
1862
1862
|
async waitUntil(key, date) {
|
|
@@ -1864,7 +1864,7 @@ function createStepHelper(options) {
|
|
|
1864
1864
|
if (cached) return;
|
|
1865
1865
|
const now = Date.now();
|
|
1866
1866
|
const waitMs = Math.max(0, date.getTime() - now);
|
|
1867
|
-
await new Promise((
|
|
1867
|
+
await new Promise((resolve10) => setTimeout(resolve10, waitMs));
|
|
1868
1868
|
store.set(key, { wait_until: date.toISOString() });
|
|
1869
1869
|
},
|
|
1870
1870
|
// eslint-disable-next-line @typescript-eslint/require-await -- stub implementation
|
|
@@ -4504,7 +4504,7 @@ function createOrchestratorStepHelper(orchestratorClient, cachedSteps, execCtx,
|
|
|
4504
4504
|
});
|
|
4505
4505
|
const waitThreshold = Number(process.env["POLOS_WAIT_THRESHOLD_SECONDS"] ?? "10");
|
|
4506
4506
|
if (totalSeconds <= waitThreshold) {
|
|
4507
|
-
await new Promise((
|
|
4507
|
+
await new Promise((resolve10) => setTimeout(resolve10, totalSeconds * 1e3));
|
|
4508
4508
|
await saveStepOutput(key, { wait_until: waitUntil.toISOString() });
|
|
4509
4509
|
return;
|
|
4510
4510
|
}
|
|
@@ -4540,7 +4540,7 @@ function createOrchestratorStepHelper(orchestratorClient, cachedSteps, execCtx,
|
|
|
4540
4540
|
});
|
|
4541
4541
|
const waitThreshold = Number(process.env["POLOS_WAIT_THRESHOLD_SECONDS"] ?? "10");
|
|
4542
4542
|
if (waitSeconds <= waitThreshold) {
|
|
4543
|
-
await new Promise((
|
|
4543
|
+
await new Promise((resolve10) => setTimeout(resolve10, waitSeconds * 1e3));
|
|
4544
4544
|
await saveStepOutput(key, { wait_until: date.toISOString() });
|
|
4545
4545
|
return;
|
|
4546
4546
|
}
|
|
@@ -5293,7 +5293,7 @@ var DEFAULT_CONTAINER_WORKDIR = "/workspace";
|
|
|
5293
5293
|
var DEFAULT_TIMEOUT_SECONDS = 300;
|
|
5294
5294
|
var DEFAULT_MAX_OUTPUT_CHARS = 1e5;
|
|
5295
5295
|
function spawnCommand(command, args, options) {
|
|
5296
|
-
return new Promise((
|
|
5296
|
+
return new Promise((resolve10, reject) => {
|
|
5297
5297
|
let settled = false;
|
|
5298
5298
|
const settle = (fn) => {
|
|
5299
5299
|
if (!settled) {
|
|
@@ -5322,21 +5322,42 @@ function spawnCommand(command, args, options) {
|
|
|
5322
5322
|
killed = true;
|
|
5323
5323
|
proc.kill("SIGKILL");
|
|
5324
5324
|
}, timeoutMs);
|
|
5325
|
+
let exitGraceTimer = null;
|
|
5326
|
+
let exitCode = null;
|
|
5327
|
+
proc.on("exit", (code) => {
|
|
5328
|
+
exitCode = code;
|
|
5329
|
+
exitGraceTimer = setTimeout(() => {
|
|
5330
|
+
clearTimeout(timer);
|
|
5331
|
+
settle(() => {
|
|
5332
|
+
if (killed) {
|
|
5333
|
+
resolve10({
|
|
5334
|
+
exitCode: 137,
|
|
5335
|
+
stdout,
|
|
5336
|
+
stderr: stderr + "\n[Process killed: timeout exceeded]"
|
|
5337
|
+
});
|
|
5338
|
+
} else {
|
|
5339
|
+
resolve10({ exitCode: exitCode ?? 1, stdout, stderr });
|
|
5340
|
+
}
|
|
5341
|
+
});
|
|
5342
|
+
}, 2e3);
|
|
5343
|
+
});
|
|
5325
5344
|
proc.on("close", (code) => {
|
|
5345
|
+
if (exitGraceTimer) clearTimeout(exitGraceTimer);
|
|
5326
5346
|
clearTimeout(timer);
|
|
5327
5347
|
settle(() => {
|
|
5328
5348
|
if (killed) {
|
|
5329
|
-
|
|
5349
|
+
resolve10({
|
|
5330
5350
|
exitCode: 137,
|
|
5331
5351
|
stdout,
|
|
5332
5352
|
stderr: stderr + "\n[Process killed: timeout exceeded]"
|
|
5333
5353
|
});
|
|
5334
5354
|
} else {
|
|
5335
|
-
|
|
5355
|
+
resolve10({ exitCode: code ?? exitCode ?? 1, stdout, stderr });
|
|
5336
5356
|
}
|
|
5337
5357
|
});
|
|
5338
5358
|
});
|
|
5339
5359
|
proc.on("error", (err) => {
|
|
5360
|
+
if (exitGraceTimer) clearTimeout(exitGraceTimer);
|
|
5340
5361
|
clearTimeout(timer);
|
|
5341
5362
|
settle(() => {
|
|
5342
5363
|
reject(err);
|
|
@@ -5549,7 +5570,7 @@ var DockerEnvironment = class {
|
|
|
5549
5570
|
var DEFAULT_TIMEOUT_SECONDS2 = 300;
|
|
5550
5571
|
var DEFAULT_MAX_OUTPUT_CHARS2 = 1e5;
|
|
5551
5572
|
function spawnLocal(command, options) {
|
|
5552
|
-
return new Promise((
|
|
5573
|
+
return new Promise((resolve10, reject) => {
|
|
5553
5574
|
let settled = false;
|
|
5554
5575
|
const settle = (fn) => {
|
|
5555
5576
|
if (!settled) {
|
|
@@ -5582,21 +5603,42 @@ function spawnLocal(command, options) {
|
|
|
5582
5603
|
killed = true;
|
|
5583
5604
|
proc.kill("SIGKILL");
|
|
5584
5605
|
}, timeoutMs);
|
|
5606
|
+
let exitGraceTimer = null;
|
|
5607
|
+
let exitCode = null;
|
|
5608
|
+
proc.on("exit", (code) => {
|
|
5609
|
+
exitCode = code;
|
|
5610
|
+
exitGraceTimer = setTimeout(() => {
|
|
5611
|
+
clearTimeout(timer);
|
|
5612
|
+
settle(() => {
|
|
5613
|
+
if (killed) {
|
|
5614
|
+
resolve10({
|
|
5615
|
+
exitCode: 137,
|
|
5616
|
+
stdout,
|
|
5617
|
+
stderr: stderr + "\n[Process killed: timeout exceeded]"
|
|
5618
|
+
});
|
|
5619
|
+
} else {
|
|
5620
|
+
resolve10({ exitCode: exitCode ?? 1, stdout, stderr });
|
|
5621
|
+
}
|
|
5622
|
+
});
|
|
5623
|
+
}, 2e3);
|
|
5624
|
+
});
|
|
5585
5625
|
proc.on("close", (code) => {
|
|
5626
|
+
if (exitGraceTimer) clearTimeout(exitGraceTimer);
|
|
5586
5627
|
clearTimeout(timer);
|
|
5587
5628
|
settle(() => {
|
|
5588
5629
|
if (killed) {
|
|
5589
|
-
|
|
5630
|
+
resolve10({
|
|
5590
5631
|
exitCode: 137,
|
|
5591
5632
|
stdout,
|
|
5592
5633
|
stderr: stderr + "\n[Process killed: timeout exceeded]"
|
|
5593
5634
|
});
|
|
5594
5635
|
} else {
|
|
5595
|
-
|
|
5636
|
+
resolve10({ exitCode: code ?? exitCode ?? 1, stdout, stderr });
|
|
5596
5637
|
}
|
|
5597
5638
|
});
|
|
5598
5639
|
});
|
|
5599
5640
|
proc.on("error", (err) => {
|
|
5641
|
+
if (exitGraceTimer) clearTimeout(exitGraceTimer);
|
|
5600
5642
|
clearTimeout(timer);
|
|
5601
5643
|
settle(() => {
|
|
5602
5644
|
reject(err);
|
|
@@ -6000,8 +6042,8 @@ var SandboxManager = class {
|
|
|
6000
6042
|
}
|
|
6001
6043
|
let resolveLock;
|
|
6002
6044
|
let rejectLock;
|
|
6003
|
-
const lockPromise = new Promise((
|
|
6004
|
-
resolveLock =
|
|
6045
|
+
const lockPromise = new Promise((resolve10, reject) => {
|
|
6046
|
+
resolveLock = resolve10;
|
|
6005
6047
|
rejectLock = reject;
|
|
6006
6048
|
});
|
|
6007
6049
|
this.sessionCreationLocks.set(ctx.sessionId, lockPromise);
|
|
@@ -6193,7 +6235,7 @@ var SandboxManager = class {
|
|
|
6193
6235
|
}
|
|
6194
6236
|
};
|
|
6195
6237
|
function spawnSimple(command, args) {
|
|
6196
|
-
return new Promise((
|
|
6238
|
+
return new Promise((resolve10, reject) => {
|
|
6197
6239
|
const proc = spawn(command, args, { stdio: ["pipe", "pipe", "pipe"] });
|
|
6198
6240
|
let stdout = "";
|
|
6199
6241
|
let stderr = "";
|
|
@@ -6204,7 +6246,7 @@ function spawnSimple(command, args) {
|
|
|
6204
6246
|
stderr += data.toString();
|
|
6205
6247
|
});
|
|
6206
6248
|
proc.on("close", (code) => {
|
|
6207
|
-
|
|
6249
|
+
resolve10({ exitCode: code ?? 1, stdout, stderr });
|
|
6208
6250
|
});
|
|
6209
6251
|
proc.on("error", reject);
|
|
6210
6252
|
});
|
|
@@ -6339,10 +6381,10 @@ var Worker = class {
|
|
|
6339
6381
|
process.on("SIGINT", signalHandler);
|
|
6340
6382
|
process.on("SIGTERM", signalHandler);
|
|
6341
6383
|
this.signalHandler = signalHandler;
|
|
6342
|
-
await new Promise((
|
|
6384
|
+
await new Promise((resolve10) => {
|
|
6343
6385
|
const checkState = () => {
|
|
6344
6386
|
if (this.state === "stopping" || this.state === "stopped") {
|
|
6345
|
-
|
|
6387
|
+
resolve10();
|
|
6346
6388
|
} else {
|
|
6347
6389
|
setTimeout(checkState, 100);
|
|
6348
6390
|
}
|
|
@@ -6376,7 +6418,7 @@ var Worker = class {
|
|
|
6376
6418
|
const waitTimeout = 3e4;
|
|
6377
6419
|
const waitStart = Date.now();
|
|
6378
6420
|
while (this.activeExecutions.size > 0 && Date.now() - waitStart < waitTimeout) {
|
|
6379
|
-
await new Promise((
|
|
6421
|
+
await new Promise((resolve10) => setTimeout(resolve10, 100));
|
|
6380
6422
|
}
|
|
6381
6423
|
if (this.activeExecutions.size > 0) {
|
|
6382
6424
|
logger9.warn(`${String(this.activeExecutions.size)} executions did not complete in time`);
|
|
@@ -7481,7 +7523,7 @@ function createReadTool(getEnv, pathConfig) {
|
|
|
7481
7523
|
}
|
|
7482
7524
|
);
|
|
7483
7525
|
}
|
|
7484
|
-
function createWriteTool(getEnv,
|
|
7526
|
+
function createWriteTool(getEnv, config) {
|
|
7485
7527
|
return defineTool(
|
|
7486
7528
|
{
|
|
7487
7529
|
id: "write",
|
|
@@ -7490,16 +7532,23 @@ function createWriteTool(getEnv, approval) {
|
|
|
7490
7532
|
path: z.string().describe("Path to the file to write"),
|
|
7491
7533
|
content: z.string().describe("Content to write to the file")
|
|
7492
7534
|
}),
|
|
7493
|
-
approval
|
|
7535
|
+
// Only use blanket approval if explicitly set to 'always'
|
|
7536
|
+
approval: config?.approval === "always" ? "always" : void 0
|
|
7494
7537
|
},
|
|
7495
|
-
async (
|
|
7538
|
+
async (ctx, input) => {
|
|
7496
7539
|
const env = await getEnv();
|
|
7540
|
+
if (!config?.approval && config?.pathConfig?.pathRestriction) {
|
|
7541
|
+
const resolved = resolve(env.getCwd(), input.path);
|
|
7542
|
+
if (!isPathAllowed(resolved, config.pathConfig.pathRestriction)) {
|
|
7543
|
+
await requirePathApproval(ctx, "write", resolved, config.pathConfig.pathRestriction);
|
|
7544
|
+
}
|
|
7545
|
+
}
|
|
7497
7546
|
await env.writeFile(input.path, input.content);
|
|
7498
7547
|
return { success: true, path: input.path };
|
|
7499
7548
|
}
|
|
7500
7549
|
);
|
|
7501
7550
|
}
|
|
7502
|
-
function createEditTool(getEnv,
|
|
7551
|
+
function createEditTool(getEnv, config) {
|
|
7503
7552
|
return defineTool(
|
|
7504
7553
|
{
|
|
7505
7554
|
id: "edit",
|
|
@@ -7509,10 +7558,17 @@ function createEditTool(getEnv, approval) {
|
|
|
7509
7558
|
old_text: z.string().describe("Exact text to find and replace"),
|
|
7510
7559
|
new_text: z.string().describe("Text to replace the old_text with")
|
|
7511
7560
|
}),
|
|
7512
|
-
approval
|
|
7561
|
+
// Only use blanket approval if explicitly set to 'always'
|
|
7562
|
+
approval: config?.approval === "always" ? "always" : void 0
|
|
7513
7563
|
},
|
|
7514
|
-
async (
|
|
7564
|
+
async (ctx, input) => {
|
|
7515
7565
|
const env = await getEnv();
|
|
7566
|
+
if (!config?.approval && config?.pathConfig?.pathRestriction) {
|
|
7567
|
+
const resolved = resolve(env.getCwd(), input.path);
|
|
7568
|
+
if (!isPathAllowed(resolved, config.pathConfig.pathRestriction)) {
|
|
7569
|
+
await requirePathApproval(ctx, "edit", resolved, config.pathConfig.pathRestriction);
|
|
7570
|
+
}
|
|
7571
|
+
}
|
|
7516
7572
|
const content = await env.readFile(input.path);
|
|
7517
7573
|
if (!content.includes(input.old_text)) {
|
|
7518
7574
|
throw new Error(
|
|
@@ -7617,16 +7673,17 @@ function sandboxTools(config) {
|
|
|
7617
7673
|
throw new Error("E2B environment is not yet implemented.");
|
|
7618
7674
|
}
|
|
7619
7675
|
const effectiveExecConfig = envType === "local" && !config?.exec?.security ? { ...config?.exec, security: "approval-always" } : config?.exec;
|
|
7620
|
-
const fileApproval = config?.fileApproval ?? (envType === "local" ? "always" : void 0);
|
|
7621
7676
|
const pathConfig = config?.local?.pathRestriction ? { pathRestriction: config.local.pathRestriction } : void 0;
|
|
7677
|
+
const fileApproval = config?.fileApproval;
|
|
7678
|
+
const writeEditConfig = fileApproval ? { approval: fileApproval } : pathConfig ? { pathConfig } : void 0;
|
|
7622
7679
|
const include = new Set(
|
|
7623
7680
|
config?.tools ?? ["exec", "read", "write", "edit", "glob", "grep"]
|
|
7624
7681
|
);
|
|
7625
7682
|
const tools = [];
|
|
7626
7683
|
if (include.has("exec")) tools.push(createExecTool(getEnv, effectiveExecConfig));
|
|
7627
7684
|
if (include.has("read")) tools.push(createReadTool(getEnv, pathConfig));
|
|
7628
|
-
if (include.has("write")) tools.push(createWriteTool(getEnv,
|
|
7629
|
-
if (include.has("edit")) tools.push(createEditTool(getEnv,
|
|
7685
|
+
if (include.has("write")) tools.push(createWriteTool(getEnv, writeEditConfig));
|
|
7686
|
+
if (include.has("edit")) tools.push(createEditTool(getEnv, writeEditConfig));
|
|
7630
7687
|
if (include.has("glob")) tools.push(createGlobTool(getEnv, pathConfig));
|
|
7631
7688
|
if (include.has("grep")) tools.push(createGrepTool(getEnv, pathConfig));
|
|
7632
7689
|
return tools;
|