@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.
Files changed (48) hide show
  1. package/README.md +25 -11
  2. package/dist/agent-O6C4FCQY.js +4 -0
  3. package/dist/anthropic-CFM2DXMB.js +4 -0
  4. package/dist/checker-A6PGACKZ.js +4 -0
  5. package/dist/chunk-4ABFUBO4.js +601 -0
  6. package/dist/{chunk-K5ZK27BX.js → chunk-AGJYBJ5M.js} +1 -1
  7. package/dist/chunk-AQ3A5CF4.js +5 -0
  8. package/dist/chunk-MVVSONAE.js +4 -0
  9. package/dist/chunk-OQCEP2F5.js +4 -0
  10. package/dist/{chunk-QFSCPD63.js → chunk-TCQ4EB4G.js} +1 -1
  11. package/dist/chunk-Y2UUXOQA.js +4 -0
  12. package/dist/chunk-YAXZ2OUD.js +150 -0
  13. package/dist/lib/agent-YRTROHXU.js +10 -0
  14. package/dist/lib/{anthropic-KWO3KLNV.js → anthropic-R6DMXE7U.js} +4 -5
  15. package/dist/lib/{checker-AXHPKVBY.js → checker-M7RKMKJQ.js} +2 -3
  16. package/dist/lib/{chunk-KZSBR4FO.js → chunk-4MDCRPVV.js} +76 -40
  17. package/dist/lib/{chunk-DJ6AILPN.js → chunk-A4MXZA5Q.js} +209 -51
  18. package/dist/lib/{chunk-2IVEVG5N.js → chunk-EWE5IWZE.js} +28 -25
  19. package/dist/lib/{chunk-KG4MJGKQ.js → chunk-FZ4Y6MBN.js} +1 -4
  20. package/dist/lib/{chunk-GCY44T7S.js → chunk-J6AV7SIF.js} +221 -351
  21. package/dist/lib/{chunk-3FBS5NB7.js → chunk-OEPCNATU.js} +217 -41
  22. package/dist/lib/{chunk-Z4CYHTII.js → chunk-OQIQOU5S.js} +85 -26
  23. package/dist/lib/{chunk-PIL7M52F.js → chunk-XT67KGWE.js} +16 -3
  24. package/dist/lib/index.d.ts +1212 -932
  25. package/dist/lib/index.js +2836 -1611
  26. package/dist/lib/{openai-PBF7EWNJ.js → openai-5N42ZYIJ.js} +2 -2
  27. package/dist/lib/{tool-filter-R6HDDJHE.js → tool-filter-XG2GXFVN.js} +3 -2
  28. package/dist/main.js +197 -189
  29. package/dist/openai-NQYARTT6.js +34 -0
  30. package/dist/{server-G23HCFLI.js → server-BNT2IIKB.js} +18 -18
  31. package/dist/tool-filter-5NDJMSTD.js +4 -0
  32. package/package.json +4 -3
  33. package/dist/agent-YR6YK26C.js +0 -4
  34. package/dist/anthropic-5GRR5JCT.js +0 -4
  35. package/dist/checker-N5TIJEN5.js +0 -4
  36. package/dist/chunk-D34FUVGU.js +0 -4
  37. package/dist/chunk-E55KH72M.js +0 -4
  38. package/dist/chunk-LIMEBKCY.js +0 -408
  39. package/dist/chunk-POHIQUFP.js +0 -301
  40. package/dist/chunk-QCKJLO6X.js +0 -4
  41. package/dist/chunk-TMEX7RFA.js +0 -4
  42. package/dist/chunk-Y6SQB5FG.js +0 -4
  43. package/dist/glob.wasm +0 -0
  44. package/dist/lib/agent-5WEKVRTD.js +0 -11
  45. package/dist/lib/chunk-GHF2PSEW.js +0 -8
  46. package/dist/lib/glob.wasm +0 -0
  47. package/dist/openai-QQ2K7GPF.js +0 -34
  48. package/dist/tool-filter-VBP6WOGO.js +0 -4
@@ -1,13 +1,11 @@
1
1
  import {
2
2
  mcpCallPermissionContent
3
- } from "./chunk-KG4MJGKQ.js";
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
- "ls",
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
- "wc",
57
- "date",
58
- "whoami",
92
+ "tr",
93
+ "true",
94
+ "tty",
95
+ "type",
59
96
  "uname",
60
- "hostname",
97
+ "uptime",
98
+ "w",
99
+ "wc",
100
+ "whereis",
61
101
  "which",
62
- "type",
63
- "file",
64
- "git status",
65
- "git log",
66
- "git diff",
67
- "git branch",
68
- "git show",
69
- "git rev-parse",
70
- "git remote",
71
- "bun test",
72
- "bun run",
73
- "npm test",
74
- "npm run",
75
- "go test",
76
- "go build",
77
- "go vet",
78
- "python -c",
79
- "node -e"
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 === MCP_CALL_TOOL_NAME) {
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
- return typeof v === "string" ? v : "";
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 all three rules files. Reuses the previous
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, this.localPath].flatMap((p) => this.rulesFor(p));
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-local YAML file in the `Tool(pattern)`
411
+ // Persists a rule to the project-level YAML file in the `Tool(pattern)`
261
412
  // format so "allow always" survives a restart.
262
- appendLocalRule(rule) {
263
- mkdirSync(dirname2(this.localPath), { recursive: true });
264
- const rules = loadRulesFile(this.localPath);
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.localPath, yaml.dump(entries), "utf-8");
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 (trimmed.includes(">") || trimmed.includes("<") || /[\r\n&]/.test(trimmed) || trimmed.includes("|") || trimmed.includes(";") || trimmed.includes("&&") || trimmed.includes("$(") || trimmed.includes("`")) {
440
+ if (/[\r\n&|;<>`(){}[\]]/.test(trimmed)) {
290
441
  return false;
291
442
  }
292
- return SAFE_PREFIXES.some(
293
- (prefix) => trimmed === prefix || trimmed.startsWith(prefix + " ") || trimmed.startsWith(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 { effect: explicitEffect, reason: `Permission rule: ${explicitEffect}` };
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.appendLocalRule({
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 = "anthropic") {
36
- const isOpenAI = protocol === "openai" || protocol === "openai-compat";
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 (tool.name === TOOL_SEARCH_TOOL_NAME && !this.exposeToolSearch || tool.name === MCP_CALL_TOOL_NAME && !this.exposeMcpCall) {
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 (isOpenAI) {
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
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
57
- // @ts-ignore
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 = MCP_CALL_TOOL_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