@cydm/pie 2.7.8 → 2.7.10
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/builtin/extensions/ask-user/index.js +3 -3
- package/dist/builtin/extensions/plan-mode/index.js +3 -18
- package/dist/builtin/extensions/subagent/index.js +10 -6
- package/dist/builtin/extensions/todo/index.js +3 -3
- package/dist/chunks/{chunk-2FEDB5GR.js → chunk-2B6VS2NH.js} +38 -19
- package/dist/chunks/{chunk-E6F4BTNN.js → chunk-5GUPRFNP.js} +11 -5
- package/dist/chunks/{chunk-P22SYVGO.js → chunk-C4LXD56O.js} +362 -175
- package/dist/chunks/{chunk-W5B3OXHQ.js → chunk-JO6EDWHP.js} +1 -1
- package/dist/chunks/{src-C2CBPEUY.js → src-WFN4JWLE.js} +2 -2
- package/dist/chunks/{test-stream-LDVUVSUP.js → test-stream-GXZ7NT4H.js} +1 -1
- package/dist/cli.js +133 -47
- package/package.json +2 -2
|
@@ -2,7 +2,7 @@ import { createRequire as __createRequire } from "node:module"; const require =
|
|
|
2
2
|
import {
|
|
3
3
|
Agent,
|
|
4
4
|
getToolCallerIdentity
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-JO6EDWHP.js";
|
|
6
6
|
import {
|
|
7
7
|
AssistantMessageEventStream,
|
|
8
8
|
FileSystemGateway,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
getPlatformConfig,
|
|
13
13
|
hashText,
|
|
14
14
|
streamSimple
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-2B6VS2NH.js";
|
|
16
16
|
import {
|
|
17
17
|
Type
|
|
18
18
|
} from "./chunk-XXGYUYXI.js";
|
|
@@ -899,6 +899,11 @@ function shouldPreserveExecutionStateForUserText(text) {
|
|
|
899
899
|
return CONTINUE_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
900
900
|
}
|
|
901
901
|
|
|
902
|
+
// ../../packages/shared-headless-capabilities/src/capability.ts
|
|
903
|
+
function defineSharedCapability(definition) {
|
|
904
|
+
return definition;
|
|
905
|
+
}
|
|
906
|
+
|
|
902
907
|
// ../../packages/shared-headless-capabilities/src/tool-policy.ts
|
|
903
908
|
var BUILTIN_TOOL_CAPABILITY_METADATA = {
|
|
904
909
|
search_context: { riskClass: "read_only", concurrencySafe: true, permissionScope: "session", availableInPlanMode: true, allowedForSubagentByDefault: false, maxOutputChars: 2e4 },
|
|
@@ -971,13 +976,51 @@ function getSubagentToolPolicyDecision(tool) {
|
|
|
971
976
|
}
|
|
972
977
|
var DEFAULT_PLAN_MODE_TOOL_NAMES = Object.entries(BUILTIN_TOOL_CAPABILITY_METADATA).filter(([, metadata]) => metadata.availableInPlanMode).map(([name]) => name);
|
|
973
978
|
|
|
974
|
-
// ../../packages/shared-headless-capabilities/src/
|
|
975
|
-
|
|
976
|
-
|
|
979
|
+
// ../../packages/shared-headless-capabilities/src/plan.ts
|
|
980
|
+
var import_shell_quote = __toESM(require_shell_quote(), 1);
|
|
981
|
+
|
|
982
|
+
// ../../packages/shared-headless-capabilities/src/shell-resolution.ts
|
|
983
|
+
function defaultShellKindForPlatform(platform = process.platform) {
|
|
984
|
+
return platform === "win32" ? "powershell" : "bash";
|
|
985
|
+
}
|
|
986
|
+
function resolveRequestShellKind(shell, platform = process.platform) {
|
|
987
|
+
if (shell === "bash" || shell === "powershell" || shell === "cmd") return shell;
|
|
988
|
+
return defaultShellKindForPlatform(platform);
|
|
977
989
|
}
|
|
978
990
|
|
|
979
991
|
// ../../packages/shared-headless-capabilities/src/plan.ts
|
|
980
|
-
var
|
|
992
|
+
var PLAN_POWERSHELL_READ_COMMANDS = new Set([
|
|
993
|
+
"Get-Content",
|
|
994
|
+
"Get-ChildItem",
|
|
995
|
+
"Get-Item",
|
|
996
|
+
"Get-Location",
|
|
997
|
+
"Get-Date",
|
|
998
|
+
"Get-Command",
|
|
999
|
+
"Select-String",
|
|
1000
|
+
"Measure-Object",
|
|
1001
|
+
"Compare-Object",
|
|
1002
|
+
"Test-Path"
|
|
1003
|
+
].map((name) => name.toLowerCase()));
|
|
1004
|
+
var PLAN_POWERSHELL_READ_ALIASES = /* @__PURE__ */ new Set(["cat", "ls", "pwd", "echo", "sort"]);
|
|
1005
|
+
var PLAN_POWERSHELL_SAFE_PARAMETERS = /^(?:-(?:Raw|TotalCount|Head|Tail|First|Last|Wait|LiteralPath|Path|Name|Pattern|Recurse|Filter|Include|Exclude|SimpleMatch|CaseSensitive|Quiet|Word|Line|Character|Encoding|ErrorAction|WarningAction))$/i;
|
|
1006
|
+
var PLAN_POWERSHELL_SEPARATORS = /[;\n\r\t]|[<>]{1,2}|\||&&|\|\|/;
|
|
1007
|
+
var PLAN_POWERSHELL_NON_ASCII = /[^\x20-\x7E]/;
|
|
1008
|
+
var PLAN_POWERSHELL_UNSAFE_TOKENS = /\$\(|`|%\{|[(){}\[\]]|\bsource\b|\.\s+[/~]|\b(bash|sh|zsh|pwsh|powershell|cmd|npm|npx|node|python3?|git)\b/i;
|
|
1009
|
+
function isPlanModeSafePowerShellCommand(command) {
|
|
1010
|
+
const trimmed = command.trim();
|
|
1011
|
+
if (!trimmed) return false;
|
|
1012
|
+
if (PLAN_POWERSHELL_NON_ASCII.test(command)) return false;
|
|
1013
|
+
if (PLAN_POWERSHELL_SEPARATORS.test(trimmed)) return false;
|
|
1014
|
+
if (PLAN_POWERSHELL_UNSAFE_TOKENS.test(trimmed)) return false;
|
|
1015
|
+
const tokens = trimmed.split(/\s+/).filter(Boolean);
|
|
1016
|
+
const head = tokens[0].toLowerCase();
|
|
1017
|
+
if (!head) return false;
|
|
1018
|
+
if (!PLAN_POWERSHELL_READ_COMMANDS.has(head) && !PLAN_POWERSHELL_READ_ALIASES.has(head)) return false;
|
|
1019
|
+
for (const token of tokens.slice(1)) {
|
|
1020
|
+
if (token.startsWith("-") && !PLAN_POWERSHELL_SAFE_PARAMETERS.test(token)) return false;
|
|
1021
|
+
}
|
|
1022
|
+
return true;
|
|
1023
|
+
}
|
|
981
1024
|
var SIMPLE_READ_COMMANDS = /* @__PURE__ */ new Set(["pwd", "ls", "cat", "head", "tail", "wc", "grep", "rg", "which", "type", "echo", "printf", "cd", "true", "false", "tree", "jq", "stat", "file", "du", "df", "basename", "dirname", "date", "uname", "sort", "uniq", "cut", "column", "shasum", "printenv"]);
|
|
982
1025
|
var GIT_READ_SUBCOMMANDS = /* @__PURE__ */ new Set(["status", "log", "diff", "show", "rev-parse", "ls-files", "ls-tree", "blame", "describe", "shortlog", "merge-base"]);
|
|
983
1026
|
var UNSAFE_GIT_FLAGS = /^(?:-c|--config-env|--exec|--output|--ext-diff|--textconv)(?:=|$)/;
|
|
@@ -1095,7 +1138,21 @@ function isReadOnlySegment(words) {
|
|
|
1095
1138
|
}
|
|
1096
1139
|
if (program === "uniq") return isReadOnlyUniq(args);
|
|
1097
1140
|
if (program === "date") {
|
|
1098
|
-
|
|
1141
|
+
const safeFlags = /* @__PURE__ */ new Set(["-u", "--utc", "--universal", "--help", "--version", "--debug"]);
|
|
1142
|
+
const valueFlags = /* @__PURE__ */ new Set(["-d", "--date", "-f", "--file", "-r", "--reference"]);
|
|
1143
|
+
const valueLongFlags = /^(?:--date|--file|--reference|--iso-8601|--rfc-email|--rfc-2822|--rfc-3339)=/;
|
|
1144
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
1145
|
+
const arg = args[index];
|
|
1146
|
+
if (arg.startsWith("+")) continue;
|
|
1147
|
+
if (safeFlags.has(arg) || valueLongFlags.test(arg)) continue;
|
|
1148
|
+
if (valueFlags.has(arg)) {
|
|
1149
|
+
if (index + 1 >= args.length) return false;
|
|
1150
|
+
index += 1;
|
|
1151
|
+
continue;
|
|
1152
|
+
}
|
|
1153
|
+
return false;
|
|
1154
|
+
}
|
|
1155
|
+
return true;
|
|
1099
1156
|
}
|
|
1100
1157
|
if (program === "jq") {
|
|
1101
1158
|
return true;
|
|
@@ -1154,7 +1211,9 @@ ${inlineMatch[1]}`;
|
|
|
1154
1211
|
}
|
|
1155
1212
|
return items;
|
|
1156
1213
|
}
|
|
1157
|
-
function isPlanModeSafeCommand(command) {
|
|
1214
|
+
function isPlanModeSafeCommand(command, shell = "bash") {
|
|
1215
|
+
if (shell === "powershell") return isPlanModeSafePowerShellCommand(command);
|
|
1216
|
+
if (shell === "cmd") return false;
|
|
1158
1217
|
const trimmed = command.trim();
|
|
1159
1218
|
if (!trimmed || /[$`\n\r\0]/.test(trimmed)) return false;
|
|
1160
1219
|
if (/\{[^{}]*\}/.test(trimmed) || /\{\s*,/.test(trimmed)) return false;
|
|
@@ -1994,14 +2053,6 @@ function projectHostContextBlock(block, registry) {
|
|
|
1994
2053
|
};
|
|
1995
2054
|
}
|
|
1996
2055
|
}
|
|
1997
|
-
function leadingHostContextBlock(message) {
|
|
1998
|
-
if (message.role !== "user") return void 0;
|
|
1999
|
-
const content = message.content;
|
|
2000
|
-
if (!Array.isArray(content) || content.length === 0) return void 0;
|
|
2001
|
-
const first = content[0];
|
|
2002
|
-
if (!isHostContextBlock(first)) return void 0;
|
|
2003
|
-
return first;
|
|
2004
|
-
}
|
|
2005
2056
|
function projectionSeparator(projectionText) {
|
|
2006
2057
|
return projectionText.endsWith("\n") && !projectionText.endsWith("\n\n") ? "" : "\n\n";
|
|
2007
2058
|
}
|
|
@@ -2009,23 +2060,40 @@ function projectHostEnvelopes(messages, registry, onProjection) {
|
|
|
2009
2060
|
let changed = false;
|
|
2010
2061
|
const next = [];
|
|
2011
2062
|
for (const message of messages) {
|
|
2012
|
-
|
|
2013
|
-
if (!block) {
|
|
2063
|
+
if (message.role !== "user") {
|
|
2014
2064
|
next.push(message);
|
|
2015
2065
|
continue;
|
|
2016
2066
|
}
|
|
2017
|
-
const outcome = projectHostContextBlock(block, registry);
|
|
2018
|
-
onProjection?.(outcome);
|
|
2019
2067
|
const content = message.content;
|
|
2020
|
-
|
|
2021
|
-
|
|
2068
|
+
if (!Array.isArray(content)) {
|
|
2069
|
+
next.push(message);
|
|
2070
|
+
continue;
|
|
2071
|
+
}
|
|
2072
|
+
let blockCount = 0;
|
|
2073
|
+
while (blockCount < content.length && isHostContextBlock(content[blockCount])) blockCount += 1;
|
|
2074
|
+
if (blockCount === 0) {
|
|
2075
|
+
next.push(message);
|
|
2076
|
+
continue;
|
|
2077
|
+
}
|
|
2078
|
+
const outcomes = [];
|
|
2079
|
+
for (let i = 0; i < blockCount; i++) {
|
|
2080
|
+
const outcome = projectHostContextBlock(content[i], registry);
|
|
2081
|
+
outcomes.push(outcome);
|
|
2082
|
+
onProjection?.(outcome);
|
|
2083
|
+
}
|
|
2084
|
+
const rest = content.slice(blockCount);
|
|
2085
|
+
let text = outcomes[outcomes.length - 1].text;
|
|
2086
|
+
for (let i = outcomes.length - 2; i >= 0; i--) {
|
|
2087
|
+
text = `${outcomes[i].text}${projectionSeparator(outcomes[i].text)}${text}`;
|
|
2088
|
+
}
|
|
2089
|
+
const separator = projectionSeparator(outcomes[outcomes.length - 1].text);
|
|
2022
2090
|
const first = rest[0];
|
|
2023
2091
|
let projectedContent;
|
|
2024
2092
|
if (first && first.type === "text" && typeof first.text === "string") {
|
|
2025
|
-
const merged = first.text.trim().length > 0 ? `${
|
|
2093
|
+
const merged = first.text.trim().length > 0 ? `${text}${separator}${first.text}` : text;
|
|
2026
2094
|
projectedContent = [{ ...first, text: merged }, ...rest.slice(1)];
|
|
2027
2095
|
} else {
|
|
2028
|
-
projectedContent = [{ type: "text", text
|
|
2096
|
+
projectedContent = [{ type: "text", text }, ...rest];
|
|
2029
2097
|
}
|
|
2030
2098
|
next.push({ ...message, content: projectedContent });
|
|
2031
2099
|
changed = true;
|
|
@@ -2818,6 +2886,7 @@ var FileSessionStore = class {
|
|
|
2818
2886
|
const heads = [];
|
|
2819
2887
|
for (const name of this.gateway.readdir(this.sessionsDir)) {
|
|
2820
2888
|
if (name.startsWith(STAGING_SESSION_PREFIX)) continue;
|
|
2889
|
+
if (!name.trim()) continue;
|
|
2821
2890
|
const dirPath = this.gateway.join(this.sessionsDir, name);
|
|
2822
2891
|
if (sessionDirIsSymlink(dirPath)) {
|
|
2823
2892
|
console.warn(`[FileSessionStore] Skipping session directory that is a symbolic link: ${dirPath}`);
|
|
@@ -8160,7 +8229,10 @@ function withSubagentRunContext(stream, hooks) {
|
|
|
8160
8229
|
${SUBAGENT_FINALIZATION_HINT}` } : context, options);
|
|
8161
8230
|
};
|
|
8162
8231
|
}
|
|
8163
|
-
function
|
|
8232
|
+
function isRetryableSubagentFailureFrom(facts) {
|
|
8233
|
+
if (facts.retryable === false) return false;
|
|
8234
|
+
if (facts.replayClass === "stream_lost" || facts.replayClass === "stream_lost_partial") return true;
|
|
8235
|
+
const message = facts.errorMessage ?? "";
|
|
8164
8236
|
const remoteClosure = /SSE stream (?:aborted|closed before end|ended before response completed)/i.test(message);
|
|
8165
8237
|
const classificationText = message.replace(/econnaborted/ig, "").replace(/SSE stream aborted/ig, "remote stream closed");
|
|
8166
8238
|
if (/\b(?:400|401|403|404|422|429)\b|quota|weekly|monthly|limit reached|exhausted|unauthorized|authentication|invalid|protocol|stopReason=length|token limit|abort/i.test(classificationText)) return false;
|
|
@@ -8178,6 +8250,13 @@ function cancellableBackoff(ms, signal) {
|
|
|
8178
8250
|
if (signal?.aborted) finish();
|
|
8179
8251
|
});
|
|
8180
8252
|
}
|
|
8253
|
+
function factsOf(error) {
|
|
8254
|
+
if (error instanceof Error) {
|
|
8255
|
+
const carrier = error;
|
|
8256
|
+
return { errorMessage: error.message, retryable: carrier.retryable, replayClass: carrier.replayClass };
|
|
8257
|
+
}
|
|
8258
|
+
return { errorMessage: String(error) };
|
|
8259
|
+
}
|
|
8181
8260
|
function withSubagentResponseRecovery(stream, backoffMs = 2e3, onRetry, onActivity, hooks) {
|
|
8182
8261
|
return async (model, context, options) => {
|
|
8183
8262
|
for (let attempt = 0; ; attempt++) {
|
|
@@ -8225,7 +8304,7 @@ function withSubagentResponseRecovery(stream, backoffMs = 2e3, onRetry, onActivi
|
|
|
8225
8304
|
message = terminal;
|
|
8226
8305
|
} catch (error) {
|
|
8227
8306
|
finishUsage?.();
|
|
8228
|
-
if (!options?.signal?.aborted && attempt < 2 &&
|
|
8307
|
+
if (!options?.signal?.aborted && attempt < 2 && isRetryableSubagentFailureFrom(factsOf(error))) {
|
|
8229
8308
|
try {
|
|
8230
8309
|
onRetry?.();
|
|
8231
8310
|
} catch {
|
|
@@ -8236,7 +8315,7 @@ function withSubagentResponseRecovery(stream, backoffMs = 2e3, onRetry, onActivi
|
|
|
8236
8315
|
throw error;
|
|
8237
8316
|
}
|
|
8238
8317
|
if (options?.signal?.aborted) throw new Error("Subagent aborted by parent");
|
|
8239
|
-
if (message.stopReason === "error" && attempt < 2 &&
|
|
8318
|
+
if (message.stopReason === "error" && attempt < 2 && isRetryableSubagentFailureFrom({ errorMessage: message.errorMessage, retryable: message.retryable, replayClass: message.replayClass })) {
|
|
8240
8319
|
try {
|
|
8241
8320
|
onRetry?.();
|
|
8242
8321
|
} catch {
|
|
@@ -8385,8 +8464,16 @@ var PROTECTED_POSIX_PATHS = /* @__PURE__ */ new Set([
|
|
|
8385
8464
|
"/Volumes"
|
|
8386
8465
|
]);
|
|
8387
8466
|
var POWERSHELL_DESTRUCTIVE_PATTERNS = [
|
|
8388
|
-
|
|
8389
|
-
|
|
8467
|
+
// PowerShell resolves these aliases before execution. The classifier must
|
|
8468
|
+
// treat the aliases exactly like their canonical cmdlets; otherwise a
|
|
8469
|
+
// guarded shell can run `ri -Recurse -Force` without the confirmation that
|
|
8470
|
+
// `Remove-Item -Recurse -Force` receives.
|
|
8471
|
+
{ pattern: /\b(?:Remove-Item|ri|rm|rmdir|del|erase|rd)\b[^;\n|]*(?:-Recurse|-Force)\b/i, warning: "may recursively or forcefully remove files", commandClass: "filesystem_write" },
|
|
8472
|
+
{ pattern: /\b(?:Remove-Item|ri|rm|rmdir|del|erase|rd)\b[^;\n|]*(?:HKLM:|HKCU:|Registry::)/i, warning: "may remove registry entries", commandClass: "infra_destructive" },
|
|
8473
|
+
// These write aliases are not all destructive in the recursive-delete sense,
|
|
8474
|
+
// but they can overwrite or create arbitrary files. Keep them behind the
|
|
8475
|
+
// same explicit shell confirmation boundary as other PowerShell writes.
|
|
8476
|
+
{ pattern: /\b(?:Set-Content|sc|set|Add-Content|ac|add|New-Item|ni|md|mkdir|Copy-Item|cpi|cp|copy|Move-Item|mi|mv|move|Rename-Item|rni|ren)\b/i, warning: "may write or overwrite files", commandClass: "filesystem_write" },
|
|
8390
8477
|
{ pattern: /\b(Set-ExecutionPolicy|Start-Process\b[^;\n|]*-Verb\s+RunAs)\b/i, warning: "may change execution policy or request elevation", commandClass: "privilege_escalation" },
|
|
8391
8478
|
{ pattern: /\b(Stop-Computer|Restart-Computer)\b/i, warning: "may stop or restart the machine", commandClass: "infra_destructive" },
|
|
8392
8479
|
{ pattern: /(^|[;|&\n])\s*(?:Invoke-Expression|iex)\b/i, warning: "evaluates a dynamically constructed string as code", commandClass: "privilege_escalation" },
|
|
@@ -8411,9 +8498,6 @@ function lastPipelineCommand(command) {
|
|
|
8411
8498
|
const segments = command.split("|").map((part) => part.trim()).filter(Boolean);
|
|
8412
8499
|
return segments[segments.length - 1] || command;
|
|
8413
8500
|
}
|
|
8414
|
-
function classifyBashCommand(command, options) {
|
|
8415
|
-
return classifyShellCommand(command, "bash", options);
|
|
8416
|
-
}
|
|
8417
8501
|
function splitShellSegments(command) {
|
|
8418
8502
|
const segments = [];
|
|
8419
8503
|
let current = "";
|
|
@@ -8595,6 +8679,66 @@ function resolveStaticCwdTarget(target, cwd, root) {
|
|
|
8595
8679
|
if (resolved !== normalizedRoot && !isStrictDescendant(resolved, normalizedRoot)) return void 0;
|
|
8596
8680
|
return resolved;
|
|
8597
8681
|
}
|
|
8682
|
+
var DYNAMIC_EXECUTION_WARNING = "may execute nested shell or interpreter code";
|
|
8683
|
+
function executableName(word) {
|
|
8684
|
+
const normalized = word.replace(/\\/g, "/").toLowerCase();
|
|
8685
|
+
const base = normalized.slice(normalized.lastIndexOf("/") + 1);
|
|
8686
|
+
return base.endsWith(".exe") ? base.slice(0, -4) : base;
|
|
8687
|
+
}
|
|
8688
|
+
function hasDynamicExecutionInvocation(words) {
|
|
8689
|
+
if (words.length === 0) return false;
|
|
8690
|
+
const program = executableName(words[0]);
|
|
8691
|
+
if (program === "env" || program === "command" || program === "exec") {
|
|
8692
|
+
let index = 1;
|
|
8693
|
+
while (index < words.length && (words[index].startsWith("-") || /^[A-Za-z_][A-Za-z0-9_]*=/.test(words[index]))) index += 1;
|
|
8694
|
+
return index < words.length && hasDynamicExecutionInvocation(words.slice(index));
|
|
8695
|
+
}
|
|
8696
|
+
if (["bash", "sh", "zsh", "dash", "ksh", "fish"].includes(program)) {
|
|
8697
|
+
return words.slice(1).some((word) => /^-[^-]*c$/i.test(word) || /^--command(?:=|$)/i.test(word));
|
|
8698
|
+
}
|
|
8699
|
+
if (["pwsh", "powershell"].includes(program)) {
|
|
8700
|
+
return words.slice(1).some((word) => /^-(?:c|command|encodedcommand|e|file)(?:=|$)/i.test(word));
|
|
8701
|
+
}
|
|
8702
|
+
if (program === "cmd") {
|
|
8703
|
+
return words.slice(1).some((word) => /^\/(?:c|k)$/i.test(word));
|
|
8704
|
+
}
|
|
8705
|
+
if (["python", "python3", "python2", "perl", "ruby"].includes(program)) {
|
|
8706
|
+
return words.slice(1).some((word) => /^(?:-c|-e|-m)$/i.test(word));
|
|
8707
|
+
}
|
|
8708
|
+
if (program === "node") {
|
|
8709
|
+
return words.slice(1).some((word) => /^(?:-e|--eval|-p|--print|-r|--require)$/i.test(word));
|
|
8710
|
+
}
|
|
8711
|
+
if (program === "find") {
|
|
8712
|
+
return words.slice(1).some((word) => /^-(?:exec|execdir|ok|okdir)$/.test(word));
|
|
8713
|
+
}
|
|
8714
|
+
if (program === "rg") {
|
|
8715
|
+
return words.slice(1).some((word) => /^--pre(?:=|$)|^--pre-glob(?:=|$)/.test(word));
|
|
8716
|
+
}
|
|
8717
|
+
if (program === "xargs") {
|
|
8718
|
+
const optionsWithValues = /* @__PURE__ */ new Set(["-a", "-d", "-E", "-I", "-L", "-n", "-P", "-s"]);
|
|
8719
|
+
let index = 1;
|
|
8720
|
+
while (index < words.length && words[index].startsWith("-")) {
|
|
8721
|
+
if (optionsWithValues.has(words[index])) index += 1;
|
|
8722
|
+
index += 1;
|
|
8723
|
+
}
|
|
8724
|
+
return index < words.length && hasDynamicExecutionInvocation(words.slice(index));
|
|
8725
|
+
}
|
|
8726
|
+
return false;
|
|
8727
|
+
}
|
|
8728
|
+
function dynamicExecutionWarnings(command) {
|
|
8729
|
+
const warnings = [];
|
|
8730
|
+
for (const segment of splitShellSegments(command)) {
|
|
8731
|
+
const words = splitShellWords(segment);
|
|
8732
|
+
if (words) {
|
|
8733
|
+
if (hasDynamicExecutionInvocation(words)) warnings.push(DYNAMIC_EXECUTION_WARNING);
|
|
8734
|
+
continue;
|
|
8735
|
+
}
|
|
8736
|
+
if (/^(?:[A-Za-z]:[\\/]|[./])?(?:bash|sh|zsh|dash|ksh|fish|pwsh|powershell|cmd|python\d*|node|perl|ruby)\b[^|;&\n]*(?:\s-c(?:\s|$)|\s--?(?:command|encodedcommand|eval|execute|file)(?:[=\s]|$)|\s\/(?:c|k)(?:\s|$))/i.test(segment.trim())) {
|
|
8737
|
+
warnings.push(DYNAMIC_EXECUTION_WARNING);
|
|
8738
|
+
}
|
|
8739
|
+
}
|
|
8740
|
+
return [...new Set(warnings)];
|
|
8741
|
+
}
|
|
8598
8742
|
function isStaticallyScopedRecursiveForceRemove(command, options) {
|
|
8599
8743
|
if (!options?.cwd) return false;
|
|
8600
8744
|
const root = options.sandboxRoot || options.cwd;
|
|
@@ -8636,6 +8780,12 @@ function classifyShellCommand(command, shell = "bash", options) {
|
|
|
8636
8780
|
destructive = true;
|
|
8637
8781
|
}
|
|
8638
8782
|
}
|
|
8783
|
+
const dynamicWarnings = dynamicExecutionWarnings(command);
|
|
8784
|
+
if (dynamicWarnings.length > 0) {
|
|
8785
|
+
warnings.push(...dynamicWarnings);
|
|
8786
|
+
commandClass = "unknown_shell";
|
|
8787
|
+
destructive = true;
|
|
8788
|
+
}
|
|
8639
8789
|
for (const entry of destructivePatterns) {
|
|
8640
8790
|
if (entry.pattern.test(command)) {
|
|
8641
8791
|
warnings.push(entry.warning);
|
|
@@ -8811,7 +8961,8 @@ function wrapBashGuard(tool, plan) {
|
|
|
8811
8961
|
Subagent guarded mode blocks destructive shell commands while preserving the parent's execution checks. Destructive commands are blocked; normal diagnostic, search, test, and build commands are allowed.`,
|
|
8812
8962
|
execute: async (toolCallId, params, signal, onUpdate) => {
|
|
8813
8963
|
const command = typeof params?.command === "string" ? params.command : "";
|
|
8814
|
-
const
|
|
8964
|
+
const shell = resolveRequestShellKind(params?.shell);
|
|
8965
|
+
const classification = classifyShellCommand(command, shell);
|
|
8815
8966
|
if (classification.destructive) {
|
|
8816
8967
|
const reason = `destructive shell command blocked for subagent: ${classification.riskWarnings.join("; ")}`;
|
|
8817
8968
|
plan.toolsExcluded.push({ name: tool.name, reason });
|
|
@@ -9427,7 +9578,11 @@ ${DELEGATION_REPORT_INSTRUCTION}`;
|
|
|
9427
9578
|
throw new Error(`Subagent output token limit reached (stopReason=length): the provider cut the final response before the report was produced${messages.some(messageHasOwnText) ? " (earlier-turn narration discarded)" : ", no text response"}. The output/thinking budget was too small for this task at its reasoning level. Rerun with a narrower task or a lower thinkingLevel.`);
|
|
9428
9579
|
}
|
|
9429
9580
|
const detail = terminalError ? `: ${terminalError.slice(0, 200)}` : "";
|
|
9430
|
-
|
|
9581
|
+
const failure = new Error(`Subagent response failed (provider/transport failure before the report was produced, stopReason=${terminalStopReason ?? "none"}${collectedResponse ? ", partial transcript discarded" : ", no text response"})${detail}`);
|
|
9582
|
+
const carrier = failure;
|
|
9583
|
+
carrier.retryable = lastAssistant?.retryable;
|
|
9584
|
+
carrier.replayClass = lastAssistant?.replayClass;
|
|
9585
|
+
throw failure;
|
|
9431
9586
|
}
|
|
9432
9587
|
let response;
|
|
9433
9588
|
if (!collectedResponse) {
|
|
@@ -9445,6 +9600,7 @@ ${DELEGATION_REPORT_INSTRUCTION}`;
|
|
|
9445
9600
|
}
|
|
9446
9601
|
const durationMs = Date.now() - startTime;
|
|
9447
9602
|
task.status = "completed";
|
|
9603
|
+
task.failure = void 0;
|
|
9448
9604
|
observeDelegationPhase(task.observation, "completed");
|
|
9449
9605
|
task.result = response;
|
|
9450
9606
|
task.details = {
|
|
@@ -9471,6 +9627,12 @@ ${DELEGATION_REPORT_INSTRUCTION}`;
|
|
|
9471
9627
|
observeDelegationPhase(task.observation, timedOut ? "deadline" : signal?.aborted ? "cancelled" : "failed");
|
|
9472
9628
|
phaseProgress(task.observation.phase);
|
|
9473
9629
|
task.error = errorMessage.slice(0, 2e3);
|
|
9630
|
+
const failureCarrier = error;
|
|
9631
|
+
if (failureCarrier && (failureCarrier.retryable !== void 0 || failureCarrier.replayClass !== void 0)) {
|
|
9632
|
+
task.failure = { ...failureCarrier.retryable !== void 0 ? { retryable: failureCarrier.retryable } : {}, ...failureCarrier.replayClass !== void 0 ? { replayClass: failureCarrier.replayClass } : {} };
|
|
9633
|
+
} else {
|
|
9634
|
+
task.failure = void 0;
|
|
9635
|
+
}
|
|
9474
9636
|
task.report ??= parseDelegationReport(void 0, task.id);
|
|
9475
9637
|
task.parentHandoffRequired = isParentHandoffRequired(task);
|
|
9476
9638
|
task.completedAt = Date.now();
|
|
@@ -9807,7 +9969,7 @@ ${SPAWN_USAGE_HINT}` }],
|
|
|
9807
9969
|
await run(task, toolContext.reportProgress, signal);
|
|
9808
9970
|
if (task.wasRecall || task.mode !== "read" || task.status !== "failed" || !task.error) return;
|
|
9809
9971
|
if (signal?.aborted) return;
|
|
9810
|
-
if (!
|
|
9972
|
+
if (!isRetryableSubagentFailureFrom({ errorMessage: task.error, retryable: task.failure?.retryable, replayClass: task.failure?.replayClass })) return;
|
|
9811
9973
|
observeDelegationPhase(task.observation, "task_replay");
|
|
9812
9974
|
const settleMs = Math.max(0, (deps.transientRetryBackoffMs ?? 2e3) * 10);
|
|
9813
9975
|
toolContext.reportProgress?.({ message: `[${task.name}] Provider/transport failure \u2014 replaying the read task once after ${Math.round(settleMs / 1e3)}s`, increment: 0 });
|
|
@@ -9815,6 +9977,7 @@ ${SPAWN_USAGE_HINT}` }],
|
|
|
9815
9977
|
if (signal.aborted) {
|
|
9816
9978
|
task.status = "cancelled";
|
|
9817
9979
|
task.error = "Subagent cancelled during replay backoff";
|
|
9980
|
+
task.failure = void 0;
|
|
9818
9981
|
observeDelegationPhase(task.observation, "cancelled");
|
|
9819
9982
|
task.completedAt = Date.now();
|
|
9820
9983
|
return;
|
|
@@ -9824,6 +9987,7 @@ ${SPAWN_USAGE_HINT}` }],
|
|
|
9824
9987
|
task.runtimeEvidence = [];
|
|
9825
9988
|
task.reportedEvidence = [];
|
|
9826
9989
|
task.error = void 0;
|
|
9990
|
+
task.failure = void 0;
|
|
9827
9991
|
task.report = void 0;
|
|
9828
9992
|
task.result = void 0;
|
|
9829
9993
|
task.details = void 0;
|
|
@@ -9877,6 +10041,10 @@ ${SPAWN_USAGE_HINT}` }],
|
|
|
9877
10041
|
observation: task.observation,
|
|
9878
10042
|
parentHandoffRequired: task.parentHandoffRequired,
|
|
9879
10043
|
failureReason: task.error,
|
|
10044
|
+
// Structured provider verdict so the parent model can distinguish
|
|
10045
|
+
// stream loss (safe to re-dispatch; no tool calls executed) from hard
|
|
10046
|
+
// provider vetoes (auth/quota/config — not recoverable here).
|
|
10047
|
+
failure: task.failure,
|
|
9880
10048
|
details: task.details
|
|
9881
10049
|
})),
|
|
9882
10050
|
totalDuration,
|
|
@@ -10534,6 +10702,164 @@ function createAskUserCapability() {
|
|
|
10534
10702
|
};
|
|
10535
10703
|
}
|
|
10536
10704
|
|
|
10705
|
+
// ../../packages/shared-headless-capabilities/src/policy-enforcer.ts
|
|
10706
|
+
var POLICY_ENFORCED = /* @__PURE__ */ Symbol.for("pie.capabilityPolicy.enforced");
|
|
10707
|
+
function evaluateToolPermission(tool, context = {}) {
|
|
10708
|
+
const mode = context.mode ?? "normal";
|
|
10709
|
+
const metadata = getToolCapabilityMetadata(tool);
|
|
10710
|
+
const base = describeToolPolicyDecision(tool, mode);
|
|
10711
|
+
if (!metadata && mode === "normal") {
|
|
10712
|
+
return {
|
|
10713
|
+
disposition: "allow",
|
|
10714
|
+
allowed: true,
|
|
10715
|
+
reason: "unclassified_tool",
|
|
10716
|
+
policyReason: "unclassified_tool",
|
|
10717
|
+
mode,
|
|
10718
|
+
yoloMode: context.yoloMode
|
|
10719
|
+
};
|
|
10720
|
+
}
|
|
10721
|
+
if (!metadata || !base.allowed) {
|
|
10722
|
+
return {
|
|
10723
|
+
disposition: "deny",
|
|
10724
|
+
allowed: false,
|
|
10725
|
+
reason: base.reason ?? "tool not allowed by runtime policy",
|
|
10726
|
+
policyReason: base.reason ?? "tool not allowed by runtime policy",
|
|
10727
|
+
mode,
|
|
10728
|
+
yoloMode: context.yoloMode,
|
|
10729
|
+
riskClass: metadata?.riskClass,
|
|
10730
|
+
permissionScope: metadata?.permissionScope,
|
|
10731
|
+
requiresPermission: metadata?.requiresPermission
|
|
10732
|
+
};
|
|
10733
|
+
}
|
|
10734
|
+
const requiresConfirmation = Boolean(metadata.highRisk || metadata.requiresPermission);
|
|
10735
|
+
if (!requiresConfirmation || context.yoloMode || context.confirmationPolicy === "allow") {
|
|
10736
|
+
return {
|
|
10737
|
+
disposition: "allow",
|
|
10738
|
+
allowed: true,
|
|
10739
|
+
mode,
|
|
10740
|
+
yoloMode: context.yoloMode,
|
|
10741
|
+
riskClass: metadata.riskClass,
|
|
10742
|
+
permissionScope: metadata.permissionScope,
|
|
10743
|
+
requiresPermission: requiresConfirmation
|
|
10744
|
+
};
|
|
10745
|
+
}
|
|
10746
|
+
if (context.confirmationPolicy === "deny" || mode === "subagent") {
|
|
10747
|
+
const reason = mode === "subagent" ? "subagent cannot request interactive permission" : "permission confirmation is unavailable";
|
|
10748
|
+
return {
|
|
10749
|
+
disposition: "deny",
|
|
10750
|
+
allowed: false,
|
|
10751
|
+
reason,
|
|
10752
|
+
policyReason: reason,
|
|
10753
|
+
mode,
|
|
10754
|
+
yoloMode: context.yoloMode,
|
|
10755
|
+
riskClass: metadata.riskClass,
|
|
10756
|
+
permissionScope: metadata.permissionScope,
|
|
10757
|
+
requiresPermission: true
|
|
10758
|
+
};
|
|
10759
|
+
}
|
|
10760
|
+
return {
|
|
10761
|
+
disposition: "confirm",
|
|
10762
|
+
allowed: false,
|
|
10763
|
+
reason: "permission confirmation required",
|
|
10764
|
+
policyReason: "permission confirmation required",
|
|
10765
|
+
mode,
|
|
10766
|
+
yoloMode: context.yoloMode,
|
|
10767
|
+
riskClass: metadata.riskClass,
|
|
10768
|
+
permissionScope: metadata.permissionScope,
|
|
10769
|
+
requiresPermission: true
|
|
10770
|
+
};
|
|
10771
|
+
}
|
|
10772
|
+
function blockedResult(toolName, decision) {
|
|
10773
|
+
return {
|
|
10774
|
+
content: [
|
|
10775
|
+
{
|
|
10776
|
+
type: "text",
|
|
10777
|
+
text: `Blocked ${toolName}: ${decision.reason ?? decision.policyReason ?? "permission denied"}`
|
|
10778
|
+
}
|
|
10779
|
+
],
|
|
10780
|
+
details: { permissionDecision: decision },
|
|
10781
|
+
isError: true
|
|
10782
|
+
};
|
|
10783
|
+
}
|
|
10784
|
+
function planModeShellCommandBlocked(target, args) {
|
|
10785
|
+
const metadata = getToolCapabilityMetadata(target);
|
|
10786
|
+
if (!metadata?.executesShell) return void 0;
|
|
10787
|
+
const command = args?.command;
|
|
10788
|
+
if (typeof command !== "string") {
|
|
10789
|
+
return `Plan mode: shell tool received no command to validate. Use plan_scratch for temporary drafts, submit the finished plan with plan_submit, or toggle Plan mode off (/tools/plan) to execute.`;
|
|
10790
|
+
}
|
|
10791
|
+
const shell = resolveRequestShellKind(args?.shell);
|
|
10792
|
+
if (isPlanModeSafeCommand(command, shell)) return void 0;
|
|
10793
|
+
return `Plan mode: command "${command}" is not a read-only ${shell} command. Use plan_scratch for temporary drafts, submit the finished plan with plan_submit, or toggle Plan mode off (/tools/plan) to execute.`;
|
|
10794
|
+
}
|
|
10795
|
+
function mergePermissionDetails(details, decision) {
|
|
10796
|
+
if (details && typeof details === "object" && !Array.isArray(details)) {
|
|
10797
|
+
const record = details;
|
|
10798
|
+
if (record.permissionDecision) {
|
|
10799
|
+
return { ...record, capabilityPolicyDecision: decision };
|
|
10800
|
+
}
|
|
10801
|
+
return { ...record, permissionDecision: decision };
|
|
10802
|
+
}
|
|
10803
|
+
return { permissionDecision: decision };
|
|
10804
|
+
}
|
|
10805
|
+
function createPolicyEnforcedTool(tool, options = {}) {
|
|
10806
|
+
const marker = tool[POLICY_ENFORCED];
|
|
10807
|
+
const intactWrapper = !!marker && marker.wrapperExecute === tool.execute;
|
|
10808
|
+
if (intactWrapper && marker.getContext === options.getContext && marker.permissionProvider === options.permissionProvider) {
|
|
10809
|
+
return tool;
|
|
10810
|
+
}
|
|
10811
|
+
const target = intactWrapper ? marker.base : tool;
|
|
10812
|
+
const wrapped = {
|
|
10813
|
+
...target,
|
|
10814
|
+
execute: async (toolCallId, args, signal, onUpdate) => {
|
|
10815
|
+
let decision = evaluateToolPermission(target, options.getContext?.());
|
|
10816
|
+
if (decision.disposition === "confirm") {
|
|
10817
|
+
const approved = await options.permissionProvider?.confirm({ toolName: target.name, args, decision }).catch(() => false);
|
|
10818
|
+
if (!approved) {
|
|
10819
|
+
return blockedResult(target.name, {
|
|
10820
|
+
...decision,
|
|
10821
|
+
disposition: "deny",
|
|
10822
|
+
reason: "permission denied by user",
|
|
10823
|
+
policyReason: "permission denied by user"
|
|
10824
|
+
});
|
|
10825
|
+
}
|
|
10826
|
+
decision = {
|
|
10827
|
+
...decision,
|
|
10828
|
+
disposition: "allow",
|
|
10829
|
+
allowed: true,
|
|
10830
|
+
reason: void 0,
|
|
10831
|
+
policyReason: void 0
|
|
10832
|
+
};
|
|
10833
|
+
}
|
|
10834
|
+
if (!decision.allowed) return blockedResult(target.name, decision);
|
|
10835
|
+
const planShellReason = (options.getContext?.().mode ?? "normal") === "plan" ? planModeShellCommandBlocked(target, args) : void 0;
|
|
10836
|
+
if (planShellReason) {
|
|
10837
|
+
return blockedResult(target.name, {
|
|
10838
|
+
...decision,
|
|
10839
|
+
allowed: false,
|
|
10840
|
+
reason: planShellReason,
|
|
10841
|
+
policyReason: "plan_mode_non_read_only_shell_command"
|
|
10842
|
+
});
|
|
10843
|
+
}
|
|
10844
|
+
const result = await target.execute(toolCallId, args, signal, onUpdate);
|
|
10845
|
+
return {
|
|
10846
|
+
...result,
|
|
10847
|
+
details: mergePermissionDetails(result.details, decision)
|
|
10848
|
+
};
|
|
10849
|
+
}
|
|
10850
|
+
};
|
|
10851
|
+
wrapped[POLICY_ENFORCED] = {
|
|
10852
|
+
getContext: options.getContext,
|
|
10853
|
+
permissionProvider: options.permissionProvider,
|
|
10854
|
+
wrapperExecute: wrapped.execute,
|
|
10855
|
+
base: target
|
|
10856
|
+
};
|
|
10857
|
+
return wrapped;
|
|
10858
|
+
}
|
|
10859
|
+
function createPolicyEnforcedTools(tools, options = {}) {
|
|
10860
|
+
return tools.map((tool) => createPolicyEnforcedTool(tool, options));
|
|
10861
|
+
}
|
|
10862
|
+
|
|
10537
10863
|
// ../../packages/shared-headless-capabilities/src/builtin/fs/read.ts
|
|
10538
10864
|
import * as nodePath from "node:path";
|
|
10539
10865
|
|
|
@@ -16937,144 +17263,6 @@ function maybeAdvanceTodoExecutionState(state, signal) {
|
|
|
16937
17263
|
};
|
|
16938
17264
|
}
|
|
16939
17265
|
|
|
16940
|
-
// ../../packages/shared-headless-capabilities/src/policy-enforcer.ts
|
|
16941
|
-
var POLICY_ENFORCED = /* @__PURE__ */ Symbol.for("pie.capabilityPolicy.enforced");
|
|
16942
|
-
function evaluateToolPermission(tool, context = {}) {
|
|
16943
|
-
const mode = context.mode ?? "normal";
|
|
16944
|
-
const metadata = getToolCapabilityMetadata(tool);
|
|
16945
|
-
const base = describeToolPolicyDecision(tool, mode);
|
|
16946
|
-
if (!metadata && mode === "normal") {
|
|
16947
|
-
return {
|
|
16948
|
-
disposition: "allow",
|
|
16949
|
-
allowed: true,
|
|
16950
|
-
reason: "unclassified_tool",
|
|
16951
|
-
policyReason: "unclassified_tool",
|
|
16952
|
-
mode,
|
|
16953
|
-
yoloMode: context.yoloMode
|
|
16954
|
-
};
|
|
16955
|
-
}
|
|
16956
|
-
if (!metadata || !base.allowed) {
|
|
16957
|
-
return {
|
|
16958
|
-
disposition: "deny",
|
|
16959
|
-
allowed: false,
|
|
16960
|
-
reason: base.reason ?? "tool not allowed by runtime policy",
|
|
16961
|
-
policyReason: base.reason ?? "tool not allowed by runtime policy",
|
|
16962
|
-
mode,
|
|
16963
|
-
yoloMode: context.yoloMode,
|
|
16964
|
-
riskClass: metadata?.riskClass,
|
|
16965
|
-
permissionScope: metadata?.permissionScope,
|
|
16966
|
-
requiresPermission: metadata?.requiresPermission
|
|
16967
|
-
};
|
|
16968
|
-
}
|
|
16969
|
-
const requiresConfirmation = Boolean(metadata.highRisk || metadata.requiresPermission);
|
|
16970
|
-
if (!requiresConfirmation || context.yoloMode || context.confirmationPolicy === "allow") {
|
|
16971
|
-
return {
|
|
16972
|
-
disposition: "allow",
|
|
16973
|
-
allowed: true,
|
|
16974
|
-
mode,
|
|
16975
|
-
yoloMode: context.yoloMode,
|
|
16976
|
-
riskClass: metadata.riskClass,
|
|
16977
|
-
permissionScope: metadata.permissionScope,
|
|
16978
|
-
requiresPermission: requiresConfirmation
|
|
16979
|
-
};
|
|
16980
|
-
}
|
|
16981
|
-
if (context.confirmationPolicy === "deny" || mode === "subagent") {
|
|
16982
|
-
const reason = mode === "subagent" ? "subagent cannot request interactive permission" : "permission confirmation is unavailable";
|
|
16983
|
-
return {
|
|
16984
|
-
disposition: "deny",
|
|
16985
|
-
allowed: false,
|
|
16986
|
-
reason,
|
|
16987
|
-
policyReason: reason,
|
|
16988
|
-
mode,
|
|
16989
|
-
yoloMode: context.yoloMode,
|
|
16990
|
-
riskClass: metadata.riskClass,
|
|
16991
|
-
permissionScope: metadata.permissionScope,
|
|
16992
|
-
requiresPermission: true
|
|
16993
|
-
};
|
|
16994
|
-
}
|
|
16995
|
-
return {
|
|
16996
|
-
disposition: "confirm",
|
|
16997
|
-
allowed: false,
|
|
16998
|
-
reason: "permission confirmation required",
|
|
16999
|
-
policyReason: "permission confirmation required",
|
|
17000
|
-
mode,
|
|
17001
|
-
yoloMode: context.yoloMode,
|
|
17002
|
-
riskClass: metadata.riskClass,
|
|
17003
|
-
permissionScope: metadata.permissionScope,
|
|
17004
|
-
requiresPermission: true
|
|
17005
|
-
};
|
|
17006
|
-
}
|
|
17007
|
-
function blockedResult(toolName, decision) {
|
|
17008
|
-
return {
|
|
17009
|
-
content: [
|
|
17010
|
-
{
|
|
17011
|
-
type: "text",
|
|
17012
|
-
text: `Blocked ${toolName}: ${decision.reason ?? decision.policyReason ?? "permission denied"}`
|
|
17013
|
-
}
|
|
17014
|
-
],
|
|
17015
|
-
details: { permissionDecision: decision },
|
|
17016
|
-
isError: true
|
|
17017
|
-
};
|
|
17018
|
-
}
|
|
17019
|
-
function mergePermissionDetails(details, decision) {
|
|
17020
|
-
if (details && typeof details === "object" && !Array.isArray(details)) {
|
|
17021
|
-
const record = details;
|
|
17022
|
-
if (record.permissionDecision) {
|
|
17023
|
-
return { ...record, capabilityPolicyDecision: decision };
|
|
17024
|
-
}
|
|
17025
|
-
return { ...record, permissionDecision: decision };
|
|
17026
|
-
}
|
|
17027
|
-
return { permissionDecision: decision };
|
|
17028
|
-
}
|
|
17029
|
-
function createPolicyEnforcedTool(tool, options = {}) {
|
|
17030
|
-
const marker = tool[POLICY_ENFORCED];
|
|
17031
|
-
const intactWrapper = !!marker && marker.wrapperExecute === tool.execute;
|
|
17032
|
-
if (intactWrapper && marker.getContext === options.getContext && marker.permissionProvider === options.permissionProvider) {
|
|
17033
|
-
return tool;
|
|
17034
|
-
}
|
|
17035
|
-
const target = intactWrapper ? marker.base : tool;
|
|
17036
|
-
const wrapped = {
|
|
17037
|
-
...target,
|
|
17038
|
-
execute: async (toolCallId, args, signal, onUpdate) => {
|
|
17039
|
-
let decision = evaluateToolPermission(target, options.getContext?.());
|
|
17040
|
-
if (decision.disposition === "confirm") {
|
|
17041
|
-
const approved = await options.permissionProvider?.confirm({ toolName: target.name, args, decision }).catch(() => false);
|
|
17042
|
-
if (!approved) {
|
|
17043
|
-
return blockedResult(target.name, {
|
|
17044
|
-
...decision,
|
|
17045
|
-
disposition: "deny",
|
|
17046
|
-
reason: "permission denied by user",
|
|
17047
|
-
policyReason: "permission denied by user"
|
|
17048
|
-
});
|
|
17049
|
-
}
|
|
17050
|
-
decision = {
|
|
17051
|
-
...decision,
|
|
17052
|
-
disposition: "allow",
|
|
17053
|
-
allowed: true,
|
|
17054
|
-
reason: void 0,
|
|
17055
|
-
policyReason: void 0
|
|
17056
|
-
};
|
|
17057
|
-
}
|
|
17058
|
-
if (!decision.allowed) return blockedResult(target.name, decision);
|
|
17059
|
-
const result = await target.execute(toolCallId, args, signal, onUpdate);
|
|
17060
|
-
return {
|
|
17061
|
-
...result,
|
|
17062
|
-
details: mergePermissionDetails(result.details, decision)
|
|
17063
|
-
};
|
|
17064
|
-
}
|
|
17065
|
-
};
|
|
17066
|
-
wrapped[POLICY_ENFORCED] = {
|
|
17067
|
-
getContext: options.getContext,
|
|
17068
|
-
permissionProvider: options.permissionProvider,
|
|
17069
|
-
wrapperExecute: wrapped.execute,
|
|
17070
|
-
base: target
|
|
17071
|
-
};
|
|
17072
|
-
return wrapped;
|
|
17073
|
-
}
|
|
17074
|
-
function createPolicyEnforcedTools(tools, options = {}) {
|
|
17075
|
-
return tools.map((tool) => createPolicyEnforcedTool(tool, options));
|
|
17076
|
-
}
|
|
17077
|
-
|
|
17078
17266
|
// ../../packages/shared-headless-capabilities/src/system-prompt-tools.ts
|
|
17079
17267
|
function normalizeDescription(description) {
|
|
17080
17268
|
const text = String(description || "").replace(/\s+/g, " ").trim();
|
|
@@ -19494,10 +19682,9 @@ export {
|
|
|
19494
19682
|
supersedeExecutionState,
|
|
19495
19683
|
shouldPreserveExecutionStateForUserText,
|
|
19496
19684
|
BUILTIN_TOOL_CAPABILITY_METADATA,
|
|
19497
|
-
getToolCapabilityMetadata,
|
|
19498
19685
|
isToolAllowedInPlanMode,
|
|
19686
|
+
defaultShellKindForPlatform,
|
|
19499
19687
|
extractPlanTodoItems,
|
|
19500
|
-
isPlanModeSafeCommand,
|
|
19501
19688
|
markCompletedPlanSteps,
|
|
19502
19689
|
createPlanCapability,
|
|
19503
19690
|
modalityForReadFileUnderstandingKind,
|