@swifty.js/swifty 0.0.29 → 0.0.31
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 +25 -11
- package/dist/agent-O6C4FCQY.js +4 -0
- package/dist/anthropic-CFM2DXMB.js +4 -0
- package/dist/checker-A6PGACKZ.js +4 -0
- package/dist/chunk-4ABFUBO4.js +601 -0
- package/dist/{chunk-K5ZK27BX.js → chunk-AGJYBJ5M.js} +1 -1
- package/dist/chunk-AQ3A5CF4.js +5 -0
- package/dist/chunk-MVVSONAE.js +4 -0
- package/dist/chunk-OQCEP2F5.js +4 -0
- package/dist/{chunk-QFSCPD63.js → chunk-TCQ4EB4G.js} +1 -1
- package/dist/chunk-Y2UUXOQA.js +4 -0
- package/dist/chunk-YAXZ2OUD.js +150 -0
- package/dist/lib/agent-YRTROHXU.js +10 -0
- package/dist/lib/{anthropic-KWO3KLNV.js → anthropic-R6DMXE7U.js} +4 -5
- package/dist/lib/{checker-AXHPKVBY.js → checker-M7RKMKJQ.js} +2 -3
- package/dist/lib/{chunk-KZSBR4FO.js → chunk-4MDCRPVV.js} +76 -40
- package/dist/lib/{chunk-DJ6AILPN.js → chunk-A4MXZA5Q.js} +209 -51
- package/dist/lib/{chunk-2IVEVG5N.js → chunk-EWE5IWZE.js} +28 -25
- package/dist/lib/{chunk-KG4MJGKQ.js → chunk-FZ4Y6MBN.js} +1 -4
- package/dist/lib/{chunk-GCY44T7S.js → chunk-J6AV7SIF.js} +221 -351
- package/dist/lib/{chunk-3FBS5NB7.js → chunk-OEPCNATU.js} +217 -41
- package/dist/lib/{chunk-Z4CYHTII.js → chunk-OQIQOU5S.js} +85 -26
- package/dist/lib/{chunk-PIL7M52F.js → chunk-XT67KGWE.js} +16 -3
- package/dist/lib/index.d.ts +1212 -932
- package/dist/lib/index.js +2836 -1611
- package/dist/lib/{openai-PBF7EWNJ.js → openai-5N42ZYIJ.js} +2 -2
- package/dist/lib/{tool-filter-R6HDDJHE.js → tool-filter-XG2GXFVN.js} +3 -2
- package/dist/main.js +197 -189
- package/dist/openai-NQYARTT6.js +34 -0
- package/dist/{server-G23HCFLI.js → server-BNT2IIKB.js} +18 -18
- package/dist/tool-filter-5NDJMSTD.js +4 -0
- package/package.json +4 -3
- package/dist/agent-YR6YK26C.js +0 -4
- package/dist/anthropic-5GRR5JCT.js +0 -4
- package/dist/checker-N5TIJEN5.js +0 -4
- package/dist/chunk-D34FUVGU.js +0 -4
- package/dist/chunk-E55KH72M.js +0 -4
- package/dist/chunk-LIMEBKCY.js +0 -408
- package/dist/chunk-POHIQUFP.js +0 -301
- package/dist/chunk-QCKJLO6X.js +0 -4
- package/dist/chunk-TMEX7RFA.js +0 -4
- package/dist/chunk-Y6SQB5FG.js +0 -4
- package/dist/glob.wasm +0 -0
- package/dist/lib/agent-5WEKVRTD.js +0 -11
- package/dist/lib/chunk-GHF2PSEW.js +0 -8
- package/dist/lib/glob.wasm +0 -0
- package/dist/openai-QQ2K7GPF.js +0 -34
- package/dist/tool-filter-VBP6WOGO.js +0 -4
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
mcpCallPermissionContent
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-FZ4Y6MBN.js";
|
|
4
4
|
import {
|
|
5
5
|
createChildLogger,
|
|
6
|
+
isRecord,
|
|
6
7
|
strArg
|
|
7
8
|
} from "./chunk-EY7HE52Q.js";
|
|
8
|
-
import {
|
|
9
|
-
MCP_CALL_TOOL_NAME
|
|
10
|
-
} from "./chunk-GHF2PSEW.js";
|
|
11
9
|
|
|
12
10
|
// src/permissions/checker.ts
|
|
13
11
|
import { readFileSync, writeFileSync, mkdirSync, statSync } from "fs";
|
|
@@ -47,40 +45,193 @@ function isPathWithin(root, path) {
|
|
|
47
45
|
var log = createChildLogger({ module: "permissions" });
|
|
48
46
|
var DANGEROUS_PATTERNS = [];
|
|
49
47
|
var SAFE_PREFIXES = [
|
|
50
|
-
"
|
|
51
|
-
"pwd",
|
|
52
|
-
"echo",
|
|
48
|
+
"basename",
|
|
53
49
|
"cat",
|
|
50
|
+
"cksum",
|
|
51
|
+
"cmp",
|
|
52
|
+
"column",
|
|
53
|
+
"comm",
|
|
54
|
+
"cut",
|
|
55
|
+
"df",
|
|
56
|
+
"dirname",
|
|
57
|
+
"du",
|
|
58
|
+
"echo",
|
|
59
|
+
"expr",
|
|
60
|
+
"false",
|
|
61
|
+
"fold",
|
|
62
|
+
"fmt",
|
|
63
|
+
"grep",
|
|
64
|
+
"groups",
|
|
54
65
|
"head",
|
|
66
|
+
"id",
|
|
67
|
+
"jq",
|
|
68
|
+
"locate",
|
|
69
|
+
"ls",
|
|
70
|
+
"md5",
|
|
71
|
+
"md5sum",
|
|
72
|
+
"nl",
|
|
73
|
+
"od",
|
|
74
|
+
"paste",
|
|
75
|
+
"pgrep",
|
|
76
|
+
"printenv",
|
|
77
|
+
"printf",
|
|
78
|
+
"ps",
|
|
79
|
+
"pwd",
|
|
80
|
+
"readlink",
|
|
81
|
+
"realpath",
|
|
82
|
+
"sha1sum",
|
|
83
|
+
"sha224sum",
|
|
84
|
+
"sha256sum",
|
|
85
|
+
"sha384sum",
|
|
86
|
+
"sha512sum",
|
|
87
|
+
"shasum",
|
|
88
|
+
"stat",
|
|
89
|
+
"strings",
|
|
90
|
+
"tac",
|
|
55
91
|
"tail",
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
92
|
+
"tr",
|
|
93
|
+
"true",
|
|
94
|
+
"tty",
|
|
95
|
+
"type",
|
|
59
96
|
"uname",
|
|
60
|
-
"
|
|
97
|
+
"uptime",
|
|
98
|
+
"w",
|
|
99
|
+
"wc",
|
|
100
|
+
"whereis",
|
|
61
101
|
"which",
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"
|
|
102
|
+
"who",
|
|
103
|
+
"whoami",
|
|
104
|
+
"ack",
|
|
105
|
+
"ag",
|
|
106
|
+
"alias",
|
|
107
|
+
"arch",
|
|
108
|
+
"base64",
|
|
109
|
+
"bat",
|
|
110
|
+
"bzcat",
|
|
111
|
+
"cal",
|
|
112
|
+
"col",
|
|
113
|
+
"cloc",
|
|
114
|
+
"diff",
|
|
115
|
+
"diff3",
|
|
116
|
+
"dig",
|
|
117
|
+
"dmesg",
|
|
118
|
+
"expand",
|
|
119
|
+
"factor",
|
|
120
|
+
"free",
|
|
121
|
+
"help",
|
|
122
|
+
"hexdump",
|
|
123
|
+
"host",
|
|
124
|
+
"iconv",
|
|
125
|
+
"info",
|
|
126
|
+
"locale",
|
|
127
|
+
"lscpu",
|
|
128
|
+
"lsblk",
|
|
129
|
+
"lsof",
|
|
130
|
+
"lspci",
|
|
131
|
+
"lsusb",
|
|
132
|
+
"man",
|
|
133
|
+
"mdfind",
|
|
134
|
+
"mdls",
|
|
135
|
+
"ncal",
|
|
136
|
+
"netstat",
|
|
137
|
+
"nproc",
|
|
138
|
+
"nslookup",
|
|
139
|
+
"objdump",
|
|
140
|
+
"otool",
|
|
141
|
+
"pbpaste",
|
|
142
|
+
"ping",
|
|
143
|
+
"readelf",
|
|
144
|
+
"rev",
|
|
145
|
+
"sdiff",
|
|
146
|
+
"seq",
|
|
147
|
+
"sum",
|
|
148
|
+
"sw_vers",
|
|
149
|
+
"tldr",
|
|
150
|
+
"traceroute",
|
|
151
|
+
"unexpand",
|
|
152
|
+
"vm_stat",
|
|
153
|
+
"whois",
|
|
154
|
+
"xxd",
|
|
155
|
+
"xzcat",
|
|
156
|
+
"zcat",
|
|
157
|
+
"zgrep",
|
|
158
|
+
"zipinfo",
|
|
159
|
+
/^command\s+(?:-v|-V)\s+\S+(?:\s+\S+)*$/,
|
|
160
|
+
/^date(?!.*\s(?:-s|--set)(?:=|\s|$))(?:\s.*)?$/,
|
|
161
|
+
/^file(?!.*(?:\s--compile(?:=|\s|$)|\s-[^-\s]*C))(?:\s.*)?$/,
|
|
162
|
+
/^find(?!.*\s(?:-delete|-exec(?:dir)?|-ok(?:dir)?|-fls|-fprint(?:0)?|-fprintf)(?:\s|$))(?:\s.*)?$/,
|
|
163
|
+
/^fd(?!.*\s(?:-x|-X|--exec|--exec-batch)(?:=|\s|$))(?:\s.*)?$/,
|
|
164
|
+
/^hostname(?:\s+(?:-[adfFiIsyVh]|--(?:alias|all-fqdns|all-ip-addresses|domain|fqdn|help|ip-address|long|nis|short|version|yp)))*$/,
|
|
165
|
+
/^rg(?!.*\s(?:--pre|--pre-glob|--hostname-bin)(?:=|\s|$))(?:\s.*)?$/,
|
|
166
|
+
/^sort(?!.*\s(?:-o|--output|--compress-program)(?:=|\s|$))(?:\s.*)?$/,
|
|
167
|
+
/^ss(?!.*\s(?:--kill|-[^-\s]*K)(?:\s|$))(?:\s.*)?$/,
|
|
168
|
+
/^tree(?!.*\s(?:-o|--output)(?:=|\s|$))(?:\s.*)?$/,
|
|
169
|
+
/^git\s+(?:--version|version)$/,
|
|
170
|
+
/^git\s+(?:blame|cat-file|count-objects|describe|for-each-ref|ls-files|ls-tree|merge-base|name-rev|rev-parse|shortlog|show-ref|status|verify-pack)(?:\s.*)?$/,
|
|
171
|
+
/^git\s+(?:diff|log|show)(?!.*\s(?:--ext-diff|--output)(?:=|\s|$))(?:\s.*)?$/,
|
|
172
|
+
/^git\s+branch$/,
|
|
173
|
+
/^git\s+branch(?=.*\s(?:-a|--all|-r|--remotes|--list|--show-current|--contains|--no-contains|--merged|--no-merged)(?:=|\s|$))(?!.*\s(?:-[dDmMcCf]|--(?:copy|create-reflog|delete|edit-description|move|set-upstream-to|unset-upstream))(?:=|\s|$))(?:\s.*)?$/,
|
|
174
|
+
/^git\s+config(?:\s+(?:--blob(?:=|\s)\S+|--file(?:=|\s)\S+|--fixed-value|--global|--local|--null|--show-names|--show-origin|--show-scope|--system|--worktree|-z))*\s+(?:--get|--get-all|--get-regexp|--get-urlmatch|--list|-l)(?:\s.*)?$/,
|
|
175
|
+
/^git\s+notes\s+(?:list|show)(?:\s.*)?$/,
|
|
176
|
+
/^git\s+reflog\s+show(?:\s.*)?$/,
|
|
177
|
+
/^git\s+remote(?:\s+-v)?$/,
|
|
178
|
+
/^git\s+remote\s+get-url(?:\s+(?:--all|--push))*\s+\S+$/,
|
|
179
|
+
/^git\s+remote\s+show(?:\s+-n)?(?:\s+\S+)?$/,
|
|
180
|
+
/^git\s+stash\s+(?:list|show)(?:\s.*)?$/,
|
|
181
|
+
/^git\s+submodule\s+(?:status|summary)(?:\s.*)?$/,
|
|
182
|
+
/^git\s+tag(?:\s+(?:-l|--list)(?:\s.*)?)?$/,
|
|
183
|
+
/^git\s+worktree\s+list(?:\s.*)?$/,
|
|
184
|
+
/^(?:bun|npm|pnpm|yarn)\s+(?:explain|help|info|list|ls|outdated|prefix|query|root|search|show|view|why)(?:\s.*)?$/,
|
|
185
|
+
/^(?:npm|pnpm|yarn)\s+config\s+(?:get|list)(?:\s.*)?$/,
|
|
186
|
+
/^npm\s+pkg\s+get(?:\s.*)?$/,
|
|
187
|
+
/^bun\s+pm\s+ls(?:\s.*)?$/,
|
|
188
|
+
/^(?:bun|cargo|clang|cmake|composer|deno|gcc|gem|node|npm|php|pip|pip3|pnpm|python|python3|ruby|rustc|swift|yarn)\s+(?:--version|-V)$/,
|
|
189
|
+
/^(?:go|helm|kubectl|podman|terraform)\s+version(?:\s.*)?$/,
|
|
190
|
+
/^(?:java|javac)\s+-version$/,
|
|
191
|
+
/^dotnet\s+(?:--info|--list-runtimes|--list-sdks|--version)$/,
|
|
192
|
+
/^(?:docker|podman)\s+(?:diff|events|images|info|inspect|logs|port|ps|stats|top|version)(?:\s.*)?$/,
|
|
193
|
+
/^(?:docker|podman)\s+(?:container|image|network|volume)\s+(?:inspect|ls)(?:\s.*)?$/,
|
|
194
|
+
/^docker\s+compose\s+(?:config|images|logs|ps|top|version)(?:\s.*)?$/,
|
|
195
|
+
/^kubectl\s+(?:api-resources|api-versions|cluster-info|describe|explain|get|logs|top|version)(?:\s.*)?$/,
|
|
196
|
+
/^kubectl\s+config\s+(?:current-context|get-contexts|view)(?:\s.*)?$/,
|
|
197
|
+
/^helm\s+(?:env|get|history|list|search|show|status|version)(?:\s.*)?$/,
|
|
198
|
+
/^terraform\s+(?:output|providers|show|version)(?:\s.*)?$/,
|
|
199
|
+
/^terraform\s+workspace\s+(?:list|show)(?:\s.*)?$/,
|
|
200
|
+
/^systemctl\s+(?:is-active|is-enabled|is-failed|list-dependencies|list-jobs|list-sockets|list-timers|list-unit-files|list-units|show|show-environment|status)(?:\s.*)?$/,
|
|
201
|
+
/^launchctl\s+(?:error|hostinfo|list|managername|managerpid|manageruid|print|print-cache|procinfo|variant|version)(?:\s.*)?$/,
|
|
202
|
+
/^journalctl(?!.*\s--(?:rotate|vacuum|flush|sync))(?:\s.*)?$/,
|
|
203
|
+
/^defaults\s+read(?:\s.*)?$/,
|
|
204
|
+
/^ifconfig$/,
|
|
205
|
+
/^ipconfig(?:\s+\/(?:all|allcompartments|displaydns))?\s*$/,
|
|
206
|
+
/^ip\s+(?:addr(?:ess)?|route)$/,
|
|
207
|
+
/^ip\s+(?:addr(?:ess)?|link|route|neigh(?:bor)?)\s+(?:show|list)\b(?:\s.*)?$/,
|
|
208
|
+
/^tar\s+(?:--list\b|-[a-zA-Z]*t[a-zA-Z]*)(?:\s.*)?$/,
|
|
209
|
+
/^unzip\s+-[a-zA-Z]*l(?:\s.*)?$/,
|
|
210
|
+
/^git\s+(?:grep|fsck|rev-list|whatchanged|help|diff-tree|diff-index|diff-files|ls-remote|verify-tag|verify-commit)(?:\s.*)?$/,
|
|
211
|
+
/^git\s+archive(?!.*\s(?:-o|--output)(?:=|\s|$))(?:\s.*)?$/,
|
|
212
|
+
/^svn\s+(?:status|stat|st|diff|di|log|info|list|ls|cat|blame|ann|annotate|proplist|propget|pg)(?:\s.*)?$/,
|
|
213
|
+
/^hg\s+(?:status|st|log|diff|summary|id|identify|branches|tags|manifest|cat|files|locate|heads|tip|parents|paths|root)(?:\s.*)?$/,
|
|
214
|
+
/^cargo\s+(?:tree|search|locate-project|verify-project|config\s+get)(?:\s.*)?$/,
|
|
215
|
+
/^gem\s+(?:list|search|info|env|dependency|contents|specification|sources\s+(?:-l|--list))(?:\s.*)?$/,
|
|
216
|
+
/^brew\s+(?:--version|-v|list|info|search|outdated|deps|uses|config|leaves|doctor)(?:\s.*)?$/,
|
|
217
|
+
/^choco\s+(?:--version|list|info|search|outdated)(?:\s.*)?$/,
|
|
218
|
+
/^apt(?:-get)?\s+list(?:\s.*)?$/,
|
|
219
|
+
/^apt-cache\s+(?:search|show|showpkg|policy|depends|rdepends|pkgnames)(?:\s.*)?$/,
|
|
220
|
+
/^dpkg\s+(?:-l|-L|-s|-S|--list|--listfiles|--status|--search)\b(?:\s.*)?$/,
|
|
221
|
+
/^rpm\s+-q[a-zA-Z]*(?:\s.*)?$/,
|
|
222
|
+
/^(?:aws|gh|gcloud|az)\s+--version$/,
|
|
223
|
+
/^aws\s+(?:\S+\s+)?(?:describe|list|get|wait)-\S+(?:\s.*)?$/,
|
|
224
|
+
/^aws\s+s3\s+ls(?:\s.*)?$/,
|
|
225
|
+
/^gcloud\s+\S+(?:\s+\S+)*\s+(?:list|describe)(?:\s.*)?$/,
|
|
226
|
+
/^az\s+\S+(?:\s+\S+)*\s+(?:list|show)(?:\s.*)?$/,
|
|
227
|
+
/^gh\s+(?:pr|issue|repo|run|release|gist)\s+(?:view|list|status|checks|diff)(?:\s.*)?$/,
|
|
228
|
+
/^(?:docker|podman)\s+(?:system\s+(?:df|info)|history|context\s+(?:ls|list|show|inspect))(?:\s.*)?$/,
|
|
229
|
+
/^(?:Get-(?:Acl|Alias|AuthenticodeSignature|ChildItem|CimInstance|Clipboard|Command|ComputerInfo|Content|Counter|Culture|Date|DnsClientCache|EventLog|ExecutionPolicy|FileHash|Help|History|Host|HotFix|Item|ItemProperty|Location|Member|Module|NetAdapter|NetIPAddress|NetNeighbor|NetIPConfiguration|NetRoute|NetTCPConnection|NetUDPEndpoint|Package|PackageProvider|PnpDevice|Printer|Process|PSDrive|PSProvider|PSRepository|PSSnapin|ScheduledTask|Service|TimeZone|UICulture|Variable|Verb|WinEvent|WmiObject)|Compare-Object|Format-(?:Custom|Hex|List|Table|Wide)|Group-Object|Measure-Object|Out-String|Resolve-Path|Select-Object|Select-String|Sort-Object|Test-Path|Where-Object|Write-(?:Debug|Error|Host|Information|Output|Progress|Verbose|Warning))(?:\s.*)?$/i
|
|
80
230
|
];
|
|
81
231
|
var CONTENT_FIELDS = {
|
|
82
232
|
Bash: "command",
|
|
83
233
|
PowerShell: "command",
|
|
234
|
+
ComputerUse: "action",
|
|
84
235
|
ReadFile: "file_path",
|
|
85
236
|
WriteFile: "file_path",
|
|
86
237
|
EditFile: "file_path",
|
|
@@ -88,13 +239,9 @@ var CONTENT_FIELDS = {
|
|
|
88
239
|
Grep: "pattern",
|
|
89
240
|
InstallSkill: "source"
|
|
90
241
|
};
|
|
91
|
-
var DEFAULT_DENY_WRITE = [
|
|
92
|
-
".swifty/config.yaml",
|
|
93
|
-
".swifty/permissions.local.yaml",
|
|
94
|
-
".swifty/skills/"
|
|
95
|
-
];
|
|
242
|
+
var DEFAULT_DENY_WRITE = [];
|
|
96
243
|
function extractContent(toolName, args) {
|
|
97
|
-
if (toolName ===
|
|
244
|
+
if (toolName === "McpCall") {
|
|
98
245
|
return mcpCallPermissionContent(strArg(args, "server", ""), strArg(args, "tool", ""));
|
|
99
246
|
}
|
|
100
247
|
const field = CONTENT_FIELDS[toolName];
|
|
@@ -102,7 +249,13 @@ function extractContent(toolName, args) {
|
|
|
102
249
|
return "";
|
|
103
250
|
}
|
|
104
251
|
const v = args[field];
|
|
105
|
-
|
|
252
|
+
if (typeof v === "string") {
|
|
253
|
+
return v;
|
|
254
|
+
}
|
|
255
|
+
if (toolName === "ComputerUse" && Array.isArray(args.actions)) {
|
|
256
|
+
return args.actions.map((item) => isRecord(item) ? strArg(item, "type") : "").filter(Boolean).join(",");
|
|
257
|
+
}
|
|
258
|
+
return "";
|
|
106
259
|
}
|
|
107
260
|
var PathSandbox = class {
|
|
108
261
|
allowedRoots;
|
|
@@ -218,12 +371,10 @@ function evaluateRules(rules, toolName, content) {
|
|
|
218
371
|
var RuleEngine = class {
|
|
219
372
|
userPath;
|
|
220
373
|
projectPath;
|
|
221
|
-
localPath;
|
|
222
374
|
cache = /* @__PURE__ */ new Map();
|
|
223
375
|
constructor(workDir) {
|
|
224
376
|
this.userPath = join2(homedir(), ".swifty", "permissions.yaml");
|
|
225
377
|
this.projectPath = join2(workDir, ".swifty", "permissions.yaml");
|
|
226
|
-
this.localPath = join2(workDir, ".swifty", "permissions.local.yaml");
|
|
227
378
|
}
|
|
228
379
|
// Read a single rules file; skips disk I/O and parsing on cache hit.
|
|
229
380
|
rulesFor(path) {
|
|
@@ -242,12 +393,12 @@ var RuleEngine = class {
|
|
|
242
393
|
this.cache.set(path, { mtimeNs: st.mtimeNs, size: st.size, rules });
|
|
243
394
|
return rules;
|
|
244
395
|
}
|
|
245
|
-
// Return the merged snapshot of
|
|
396
|
+
// Return the merged snapshot of both rules files. Reuses the previous
|
|
246
397
|
// parse result when files are unchanged; re-reads only on change, so edits
|
|
247
398
|
// take effect on the next evaluation without redundant parsing. One snapshot
|
|
248
399
|
// is taken per tool call and shared across sub-command checks.
|
|
249
400
|
snapshot() {
|
|
250
|
-
return [this.userPath, this.projectPath
|
|
401
|
+
return [this.userPath, this.projectPath].flatMap((p) => this.rulesFor(p));
|
|
251
402
|
}
|
|
252
403
|
// Take a snapshot then adjudicate: reuses the previous parse result when
|
|
253
404
|
// files are unchanged; a freshly written "allow always" rule takes effect
|
|
@@ -257,11 +408,11 @@ var RuleEngine = class {
|
|
|
257
408
|
evaluate(toolName, content) {
|
|
258
409
|
return evaluateRules(this.snapshot(), toolName, content);
|
|
259
410
|
}
|
|
260
|
-
// Persists a rule to the project-
|
|
411
|
+
// Persists a rule to the project-level YAML file in the `Tool(pattern)`
|
|
261
412
|
// format so "allow always" survives a restart.
|
|
262
|
-
|
|
263
|
-
mkdirSync(dirname2(this.
|
|
264
|
-
const rules = loadRulesFile(this.
|
|
413
|
+
appendProjectRule(rule) {
|
|
414
|
+
mkdirSync(dirname2(this.projectPath), { recursive: true });
|
|
415
|
+
const rules = loadRulesFile(this.projectPath);
|
|
265
416
|
const exists = rules.some(
|
|
266
417
|
(r) => r.tool === rule.tool && r.pattern === rule.pattern && r.effect === rule.effect
|
|
267
418
|
);
|
|
@@ -273,7 +424,7 @@ var RuleEngine = class {
|
|
|
273
424
|
rule: `${r.tool}(${r.pattern})`,
|
|
274
425
|
effect: r.effect
|
|
275
426
|
}));
|
|
276
|
-
writeFileSync(this.
|
|
427
|
+
writeFileSync(this.projectPath, yaml.dump(entries), "utf-8");
|
|
277
428
|
}
|
|
278
429
|
};
|
|
279
430
|
function detectDangerous(command) {
|
|
@@ -286,12 +437,16 @@ function detectDangerous(command) {
|
|
|
286
437
|
}
|
|
287
438
|
function isSafeCommand(command) {
|
|
288
439
|
const trimmed = command.trim();
|
|
289
|
-
if (
|
|
440
|
+
if (/[\r\n&|;<>`(){}[\]]/.test(trimmed)) {
|
|
290
441
|
return false;
|
|
291
442
|
}
|
|
292
|
-
return SAFE_PREFIXES.some(
|
|
293
|
-
(prefix
|
|
294
|
-
|
|
443
|
+
return SAFE_PREFIXES.some((prefix) => {
|
|
444
|
+
if (typeof prefix === "string") {
|
|
445
|
+
return trimmed === prefix || trimmed.startsWith(prefix + " ") || trimmed.startsWith(prefix + " ");
|
|
446
|
+
}
|
|
447
|
+
prefix.lastIndex = 0;
|
|
448
|
+
return prefix.test(trimmed);
|
|
449
|
+
});
|
|
295
450
|
}
|
|
296
451
|
function modeDecide(mode, category) {
|
|
297
452
|
switch (mode) {
|
|
@@ -334,7 +489,10 @@ var PermissionChecker = class _PermissionChecker {
|
|
|
334
489
|
const rules = () => snapshot ??= this.ruleEngine.snapshot();
|
|
335
490
|
const explicitEffect = evaluateRules(rules(), toolName, content);
|
|
336
491
|
if (explicitEffect === "deny" || explicitEffect === "ask") {
|
|
337
|
-
return {
|
|
492
|
+
return {
|
|
493
|
+
effect: explicitEffect,
|
|
494
|
+
reason: `Permission rule: ${explicitEffect}`
|
|
495
|
+
};
|
|
338
496
|
}
|
|
339
497
|
if (this.mode === "plan" && (toolName === "WriteFile" || toolName === "EditFile")) {
|
|
340
498
|
const path = strArg(args, "file_path", "");
|
|
@@ -432,7 +590,7 @@ var PermissionChecker = class _PermissionChecker {
|
|
|
432
590
|
const words = content.trim().split(/\s+/).slice(0, 2);
|
|
433
591
|
pattern = words.join(" ") + "*";
|
|
434
592
|
}
|
|
435
|
-
this.ruleEngine.
|
|
593
|
+
this.ruleEngine.appendProjectRule({
|
|
436
594
|
tool: toolName,
|
|
437
595
|
pattern,
|
|
438
596
|
effect: "allow"
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
MCP_CALL_TOOL_NAME,
|
|
3
|
-
TOOL_SEARCH_TOOL_NAME
|
|
4
|
-
} from "./chunk-GHF2PSEW.js";
|
|
5
|
-
|
|
6
1
|
// src/tools/registry.ts
|
|
7
2
|
var ToolRegistry = class {
|
|
8
3
|
tools = /* @__PURE__ */ new Map();
|
|
@@ -32,46 +27,48 @@ var ToolRegistry = class {
|
|
|
32
27
|
listTools() {
|
|
33
28
|
return [...this.tools.values()];
|
|
34
29
|
}
|
|
35
|
-
getAllSchemas(protocol
|
|
36
|
-
const
|
|
30
|
+
getAllSchemas(protocol, filter) {
|
|
31
|
+
const resolvedProtocol = protocol ?? "anthropic";
|
|
32
|
+
const isOpenAI = resolvedProtocol === "openai" || resolvedProtocol === "openai-compat";
|
|
37
33
|
const native = this.mcpLoadingMode === "native" && !isOpenAI;
|
|
38
34
|
const schemas = [];
|
|
39
35
|
for (const tool of this.tools.values()) {
|
|
40
|
-
if (
|
|
36
|
+
if (filter && !filter(tool.name)) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (tool.name === "ToolSearch" && !this.exposeToolSearch || tool.name === "McpCall" && !this.exposeMcpCall) {
|
|
41
40
|
continue;
|
|
42
41
|
}
|
|
43
42
|
const deferred = Boolean(tool.deferred) && !this.discovered.has(tool.name);
|
|
44
43
|
if (deferred && !native) {
|
|
45
44
|
continue;
|
|
46
45
|
}
|
|
46
|
+
const providerSchema = protocol ? tool.providerSchema?.(resolvedProtocol) : void 0;
|
|
47
|
+
if (providerSchema) {
|
|
48
|
+
schemas.push(providerSchema);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
47
51
|
const s = tool.schema();
|
|
48
|
-
if (
|
|
52
|
+
if (resolvedProtocol === "openai") {
|
|
49
53
|
schemas.push({
|
|
50
|
-
strict: false,
|
|
51
|
-
// Whether to enforce strict parameter validation. Default true.
|
|
54
|
+
strict: s.strict ?? false,
|
|
52
55
|
type: "function",
|
|
53
56
|
name: s.name,
|
|
54
57
|
description: s.description,
|
|
55
|
-
parameters: s.input_schema
|
|
56
|
-
|
|
57
|
-
|
|
58
|
+
parameters: s.input_schema
|
|
59
|
+
});
|
|
60
|
+
} else if (resolvedProtocol === "openai-compat") {
|
|
61
|
+
schemas.push({
|
|
62
|
+
type: "function",
|
|
58
63
|
function: {
|
|
59
64
|
name: s.name,
|
|
60
65
|
description: s.description,
|
|
61
|
-
parameters: s.input_schema
|
|
66
|
+
parameters: s.input_schema,
|
|
67
|
+
strict: s.strict ?? false
|
|
62
68
|
}
|
|
63
69
|
});
|
|
64
70
|
} else {
|
|
65
|
-
schemas.push(
|
|
66
|
-
deferred ? {
|
|
67
|
-
...s,
|
|
68
|
-
type: "custom",
|
|
69
|
-
defer_loading: true
|
|
70
|
-
} : {
|
|
71
|
-
...s,
|
|
72
|
-
type: "custom"
|
|
73
|
-
}
|
|
74
|
-
);
|
|
71
|
+
schemas.push({ ...s, type: "custom", ...deferred ? { defer_loading: true } : {} });
|
|
75
72
|
}
|
|
76
73
|
}
|
|
77
74
|
return schemas;
|
|
@@ -127,11 +124,13 @@ var ToolRegistry = class {
|
|
|
127
124
|
};
|
|
128
125
|
|
|
129
126
|
// src/subagent/tool-filter.ts
|
|
127
|
+
var MAIN_AGENT_ONLY_TOOLS = /* @__PURE__ */ new Set(["ComputerUse"]);
|
|
130
128
|
var SUBAGENT_DISALLOWED_TOOLS = /* @__PURE__ */ new Set([
|
|
131
129
|
"ExitPlanMode",
|
|
132
130
|
"Agent",
|
|
133
131
|
// Prevents recursive spawning of subagents
|
|
134
132
|
"AskUserQuestion",
|
|
133
|
+
...MAIN_AGENT_ONLY_TOOLS,
|
|
135
134
|
"TaskStop"
|
|
136
135
|
]);
|
|
137
136
|
var TEAMMATE_DISALLOWED_TOOLS = /* @__PURE__ */ new Set(["TeamCreate", "TeamDelete"]);
|
|
@@ -200,6 +199,9 @@ function cloneRegistryForFork(registry) {
|
|
|
200
199
|
const forked = new ToolRegistry();
|
|
201
200
|
forked.mcpLoadingMode = registry.mcpLoadingMode;
|
|
202
201
|
for (const tool of registry.listTools()) {
|
|
202
|
+
if (MAIN_AGENT_ONLY_TOOLS.has(tool.name)) {
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
203
205
|
if (tool.name === "Agent" && "querySource" in tool) {
|
|
204
206
|
const clone = Object.create(
|
|
205
207
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
@@ -217,6 +219,7 @@ function cloneRegistryForFork(registry) {
|
|
|
217
219
|
|
|
218
220
|
export {
|
|
219
221
|
ToolRegistry,
|
|
222
|
+
MAIN_AGENT_ONLY_TOOLS,
|
|
220
223
|
SUBAGENT_DISALLOWED_TOOLS,
|
|
221
224
|
TEAMMATE_DISALLOWED_TOOLS,
|
|
222
225
|
CUSTOM_AGENT_DISALLOWED_TOOLS,
|
|
@@ -4,9 +4,6 @@ import {
|
|
|
4
4
|
createChildLogger,
|
|
5
5
|
strArg
|
|
6
6
|
} from "./chunk-EY7HE52Q.js";
|
|
7
|
-
import {
|
|
8
|
-
MCP_CALL_TOOL_NAME
|
|
9
|
-
} from "./chunk-GHF2PSEW.js";
|
|
10
7
|
|
|
11
8
|
// src/mcp/tool-wrapper.ts
|
|
12
9
|
var log = createChildLogger({ module: "mcp" });
|
|
@@ -148,7 +145,7 @@ var McpCallTool = class {
|
|
|
148
145
|
this.registry = registry;
|
|
149
146
|
}
|
|
150
147
|
registry;
|
|
151
|
-
name =
|
|
148
|
+
name = "McpCall";
|
|
152
149
|
description = "Invoke a tool on a connected MCP server. Call ToolSearch first to load the tool's schema, then pass its arguments here exactly as that schema requires, using the same JSON types.";
|
|
153
150
|
category = "command";
|
|
154
151
|
// This tool must stay in tools[] itself, otherwise the model has no entry point
|