safari-pilot 0.1.28 → 0.1.29

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 (67) hide show
  1. package/bin/Safari Pilot.app/Contents/CodeResources +0 -0
  2. package/bin/Safari Pilot.app/Contents/Info.plist +2 -2
  3. package/bin/Safari Pilot.app/Contents/MacOS/Safari Pilot +0 -0
  4. package/bin/Safari Pilot.app/Contents/PlugIns/Safari Pilot Extension.appex/Contents/Info.plist +2 -2
  5. package/bin/Safari Pilot.app/Contents/PlugIns/Safari Pilot Extension.appex/Contents/MacOS/Safari Pilot Extension +0 -0
  6. package/bin/Safari Pilot.app/Contents/PlugIns/Safari Pilot Extension.appex/Contents/Resources/manifest.json +19 -7
  7. package/bin/Safari Pilot.app/Contents/PlugIns/Safari Pilot Extension.appex/Contents/_CodeSignature/CodeResources +2 -2
  8. package/bin/Safari Pilot.app/Contents/Resources/Base.lproj/Main.storyboardc/Info.plist +0 -0
  9. package/bin/Safari Pilot.app/Contents/Resources/Base.lproj/Main.storyboardc/MainMenu.nib +0 -0
  10. package/bin/Safari Pilot.app/Contents/Resources/Base.lproj/Main.storyboardc/NSWindowController-B8D-0N-5wS.nib +0 -0
  11. package/bin/Safari Pilot.app/Contents/_CodeSignature/CodeResources +7 -7
  12. package/bin/Safari Pilot.zip +0 -0
  13. package/bin/SafariPilotd +0 -0
  14. package/dist/discovery/recipe-miner.d.ts +13 -0
  15. package/dist/discovery/recipe-miner.js +71 -0
  16. package/dist/discovery/recipe-miner.js.map +1 -0
  17. package/dist/discovery/tool-index.d.ts +18 -0
  18. package/dist/discovery/tool-index.js +52 -0
  19. package/dist/discovery/tool-index.js.map +1 -0
  20. package/dist/security/human-approval.d.ts +7 -0
  21. package/dist/security/human-approval.js +6 -0
  22. package/dist/security/human-approval.js.map +1 -1
  23. package/dist/server.d.ts +13 -0
  24. package/dist/server.js +91 -1
  25. package/dist/server.js.map +1 -1
  26. package/dist/skills/registry.d.ts +22 -0
  27. package/dist/skills/registry.js +69 -0
  28. package/dist/skills/registry.js.map +1 -0
  29. package/dist/skills/runner.d.ts +11 -0
  30. package/dist/skills/runner.js +72 -0
  31. package/dist/skills/runner.js.map +1 -0
  32. package/dist/tools/compound.js +1 -3
  33. package/dist/tools/compound.js.map +1 -1
  34. package/dist/tools/downloads.js +1 -9
  35. package/dist/tools/downloads.js.map +1 -1
  36. package/dist/tools/extraction.js +13 -17
  37. package/dist/tools/extraction.js.map +1 -1
  38. package/dist/tools/frames.js +2 -6
  39. package/dist/tools/frames.js.map +1 -1
  40. package/dist/tools/interaction.js +18 -32
  41. package/dist/tools/interaction.js.map +1 -1
  42. package/dist/tools/navigation.js +16 -12
  43. package/dist/tools/navigation.js.map +1 -1
  44. package/dist/tools/network.js +7 -24
  45. package/dist/tools/network.js.map +1 -1
  46. package/dist/tools/selector-pack.js +2 -4
  47. package/dist/tools/selector-pack.js.map +1 -1
  48. package/dist/tools/shadow.js +2 -4
  49. package/dist/tools/shadow.js.map +1 -1
  50. package/dist/tools/skills.d.ts +20 -0
  51. package/dist/tools/skills.js +71 -0
  52. package/dist/tools/skills.js.map +1 -0
  53. package/dist/tools/storage.js +9 -24
  54. package/dist/tools/storage.js.map +1 -1
  55. package/dist/tools/structured-extraction.js +5 -13
  56. package/dist/tools/structured-extraction.js.map +1 -1
  57. package/dist/tools/tool-search.d.ts +20 -0
  58. package/dist/tools/tool-search.js +54 -0
  59. package/dist/tools/tool-search.js.map +1 -0
  60. package/dist/tools/wait.js +3 -3
  61. package/dist/tools/wait.js.map +1 -1
  62. package/dist/types.d.ts +9 -0
  63. package/extension/manifest.json +19 -7
  64. package/package.json +8 -4
  65. package/skills/login.SKILL.md +27 -0
  66. package/skills/paginate-and-scrape.SKILL.md +21 -0
  67. package/skills/robust-form-fill.SKILL.md +22 -0
@@ -23,13 +23,13 @@
23
23
  <key>CFBundlePackageType</key>
24
24
  <string>APPL</string>
25
25
  <key>CFBundleShortVersionString</key>
26
- <string>0.1.28</string>
26
+ <string>0.1.29</string>
27
27
  <key>CFBundleSupportedPlatforms</key>
28
28
  <array>
29
29
  <string>MacOSX</string>
30
30
  </array>
31
31
  <key>CFBundleVersion</key>
32
- <string>202605050412</string>
32
+ <string>202605060230</string>
33
33
  <key>DTCompiler</key>
34
34
  <string>com.apple.compilers.llvm.clang.1_0</string>
35
35
  <key>DTPlatformBuild</key>
@@ -19,13 +19,13 @@
19
19
  <key>CFBundlePackageType</key>
20
20
  <string>XPC!</string>
21
21
  <key>CFBundleShortVersionString</key>
22
- <string>0.1.28</string>
22
+ <string>0.1.29</string>
23
23
  <key>CFBundleSupportedPlatforms</key>
24
24
  <array>
25
25
  <string>MacOSX</string>
26
26
  </array>
27
27
  <key>CFBundleVersion</key>
28
- <string>202605050412</string>
28
+ <string>202605060230</string>
29
29
  <key>DTCompiler</key>
30
30
  <string>com.apple.compilers.llvm.clang.1_0</string>
31
31
  <key>DTPlatformBuild</key>
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "Safari Pilot",
4
- "version": "0.1.28",
4
+ "version": "0.1.29",
5
5
  "description": "Native Safari automation for AI agents",
6
6
  "permissions": [
7
7
  "activeTab",
@@ -18,22 +18,34 @@
18
18
  "content_security_policy": {
19
19
  "extension_pages": "script-src 'self'; connect-src 'self' http://localhost:19475 http://127.0.0.1:19475"
20
20
  },
21
- "host_permissions": ["<all_urls>"],
21
+ "host_permissions": [
22
+ "<all_urls>"
23
+ ],
22
24
  "background": {
23
- "scripts": ["background.js"],
25
+ "scripts": [
26
+ "background.js"
27
+ ],
24
28
  "persistent": false
25
29
  },
26
30
  "content_scripts": [
27
31
  {
28
- "matches": ["<all_urls>"],
29
- "js": ["content-isolated.js"],
32
+ "matches": [
33
+ "<all_urls>"
34
+ ],
35
+ "js": [
36
+ "content-isolated.js"
37
+ ],
30
38
  "run_at": "document_idle",
31
39
  "world": "ISOLATED",
32
40
  "all_frames": true
33
41
  },
34
42
  {
35
- "matches": ["<all_urls>"],
36
- "js": ["content-main.js"],
43
+ "matches": [
44
+ "<all_urls>"
45
+ ],
46
+ "js": [
47
+ "content-main.js"
48
+ ],
37
49
  "run_at": "document_idle",
38
50
  "world": "MAIN",
39
51
  "all_frames": true
@@ -46,7 +46,7 @@
46
46
  </data>
47
47
  <key>Resources/manifest.json</key>
48
48
  <data>
49
- N9cYkZyI/ckF3TWIR2w2ujwqOSQ=
49
+ +aLtOWURQx+rJpvnmelFssvw6sY=
50
50
  </data>
51
51
  <key>Resources/native/SafariWebExtensionHandler.swift</key>
52
52
  <data>
@@ -129,7 +129,7 @@
129
129
  <dict>
130
130
  <key>hash2</key>
131
131
  <data>
132
- Vh4l0sBEAXf+Jc3DaBwYM5wwB9LUiM1LhuR2p1VYK/4=
132
+ mrfYAmMwhQqkNTyZU2dzeThoyxd2hZYHwPgFKaNKpxE=
133
133
  </data>
134
134
  </dict>
135
135
  <key>Resources/native/SafariWebExtensionHandler.swift</key>
@@ -18,15 +18,15 @@
18
18
  </data>
19
19
  <key>Resources/Base.lproj/Main.storyboardc/Info.plist</key>
20
20
  <data>
21
- Lk+CPfhfIGRA8ShZZFI+A0rJ2Fk=
21
+ E7+ia1hClIvypqZ7fpu0ykYY1Jo=
22
22
  </data>
23
23
  <key>Resources/Base.lproj/Main.storyboardc/MainMenu.nib</key>
24
24
  <data>
25
- gfejsxd2k48cV+t1Ave1GMgeWeU=
25
+ ZNKXFL6TEBryOVVZLjtCzviNbTU=
26
26
  </data>
27
27
  <key>Resources/Base.lproj/Main.storyboardc/NSWindowController-B8D-0N-5wS.nib</key>
28
28
  <data>
29
- 9ykXQmnGGwCAJL2MPMLC7qPCpkQ=
29
+ B+v01Kjcwm0FLJsbuBG9NZchRD0=
30
30
  </data>
31
31
  <key>Resources/Base.lproj/Main.storyboardc/XfG-lQ-9wD-view-m2S-Jp-Qdl.nib</key>
32
32
  <data>
@@ -51,7 +51,7 @@
51
51
  <dict>
52
52
  <key>cdhash</key>
53
53
  <data>
54
- bWtJ8Gsg4i9gGuKEQ4SYB+FcDso=
54
+ NpksfTnkkjY5muDgSJktoSnJnSo=
55
55
  </data>
56
56
  <key>requirement</key>
57
57
  <string>anchor apple generic and identifier "com.safari-pilot.app.Extension" and (certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = V37WLKRXUJ)</string>
@@ -81,21 +81,21 @@
81
81
  <dict>
82
82
  <key>hash2</key>
83
83
  <data>
84
- 8J9pOXoi9UK5I6qZRMloMaWPxQoW+OciXbGvdnqtq0Q=
84
+ ofN6kk0Yg0dmJF0e6J3yaZ0HWcwDs9vk3OVOSaapviI=
85
85
  </data>
86
86
  </dict>
87
87
  <key>Resources/Base.lproj/Main.storyboardc/MainMenu.nib</key>
88
88
  <dict>
89
89
  <key>hash2</key>
90
90
  <data>
91
- pXqB05PG+ZwnFVMoJVsDjhgig8YjRG8grrBPWsZG/YI=
91
+ JutHRKOObLSCTpKJVIiQRRyzEBJKgzdTdsbgK218f2M=
92
92
  </data>
93
93
  </dict>
94
94
  <key>Resources/Base.lproj/Main.storyboardc/NSWindowController-B8D-0N-5wS.nib</key>
95
95
  <dict>
96
96
  <key>hash2</key>
97
97
  <data>
98
- LAAQ0mIs7zxLtn87eO30xhqHEkEP/lblzyrpTD3gv0s=
98
+ ZQQSp+jq0L/MX6J66senkEoiNwFY6A1DMHS63B664YA=
99
99
  </data>
100
100
  </dict>
101
101
  <key>Resources/Base.lproj/Main.storyboardc/XfG-lQ-9wD-view-m2S-Jp-Qdl.nib</key>
Binary file
package/bin/SafariPilotd CHANGED
Binary file
@@ -0,0 +1,13 @@
1
+ export interface MineOptions {
2
+ minOccurrences: number;
3
+ minLength: number;
4
+ }
5
+ export interface RecipeCandidate {
6
+ host: string;
7
+ steps: Array<{
8
+ tool: string;
9
+ argSignature: string;
10
+ }>;
11
+ occurrences: number;
12
+ }
13
+ export declare function mineRecipes(rootDir: string, opts: MineOptions): Promise<RecipeCandidate[]>;
@@ -0,0 +1,71 @@
1
+ // src/discovery/recipe-miner.ts
2
+ // Port of Browser Use's browser-harness pattern: read execution traces,
3
+ // extract recurring successful tool sequences, emit candidate skills.
4
+ import { readdir, readFile } from 'node:fs/promises';
5
+ import { stat } from 'node:fs/promises';
6
+ import { join } from 'node:path';
7
+ export async function mineRecipes(rootDir, opts) {
8
+ const traces = await collectTraces(rootDir);
9
+ const counts = new Map();
10
+ for (const trace of traces) {
11
+ if (trace.steps.length < opts.minLength)
12
+ continue;
13
+ const key = trace.host + '|' + trace.steps.map((s) => `${s.tool}:${s.argSignature}`).join('>');
14
+ const existing = counts.get(key);
15
+ if (existing)
16
+ existing.occurrences++;
17
+ else
18
+ counts.set(key, { host: trace.host, steps: trace.steps, occurrences: 1 });
19
+ }
20
+ return [...counts.values()].filter((c) => c.occurrences >= opts.minOccurrences);
21
+ }
22
+ async function collectTraces(root) {
23
+ const out = [];
24
+ let entries;
25
+ try {
26
+ entries = await readdir(root);
27
+ }
28
+ catch {
29
+ return out;
30
+ }
31
+ for (const e of entries) {
32
+ const p = join(root, e);
33
+ const s = await stat(p).catch(() => null);
34
+ if (!s || !s.isDirectory())
35
+ continue;
36
+ try {
37
+ const score = JSON.parse(await readFile(join(p, 'score.json'), 'utf8'));
38
+ if (!score['success'])
39
+ continue;
40
+ const traceText = await readFile(join(p, 'tool-calls.jsonl'), 'utf8');
41
+ const steps = traceText
42
+ .split('\n')
43
+ .filter(Boolean)
44
+ .map((line) => {
45
+ const entry = JSON.parse(line);
46
+ return {
47
+ tool: String(entry.tool),
48
+ argSignature: signature(entry.args),
49
+ };
50
+ });
51
+ const host = inferHost(traceText);
52
+ out.push({ host, steps });
53
+ }
54
+ catch {
55
+ /* skip incomplete run dirs */
56
+ }
57
+ }
58
+ return out;
59
+ }
60
+ function signature(args) {
61
+ if (!args || typeof args !== 'object')
62
+ return '';
63
+ return Object.keys(args)
64
+ .sort()
65
+ .join(',');
66
+ }
67
+ function inferHost(trace) {
68
+ const m = trace.match(/"url"\s*:\s*"https?:\/\/([^/"]+)/);
69
+ return m?.[1] ?? 'unknown';
70
+ }
71
+ //# sourceMappingURL=recipe-miner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recipe-miner.js","sourceRoot":"","sources":["../../src/discovery/recipe-miner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ export interface ToolEntry {
2
+ name: string;
3
+ description: string;
4
+ tags?: string[];
5
+ }
6
+ export interface ToolHit extends ToolEntry {
7
+ score: number;
8
+ }
9
+ export declare class ToolIndex {
10
+ private entries;
11
+ constructor(entries: ToolEntry[]);
12
+ size(): number;
13
+ tagsFor(name: string): string[];
14
+ search(query: string, topK?: number): ToolHit[];
15
+ private inferTags;
16
+ private tokenize;
17
+ private score;
18
+ }
@@ -0,0 +1,52 @@
1
+ // src/discovery/tool-index.ts
2
+ // In-memory tool index for safari_tool_search meta-tool.
3
+ // Keyword overlap scoring with name + tag boost.
4
+ export class ToolIndex {
5
+ entries;
6
+ constructor(entries) {
7
+ this.entries = entries.map((e) => ({
8
+ ...e,
9
+ tags: e.tags ?? this.inferTags(e.name),
10
+ }));
11
+ }
12
+ size() {
13
+ return this.entries.length;
14
+ }
15
+ tagsFor(name) {
16
+ return this.entries.find((e) => e.name === name)?.tags ?? [];
17
+ }
18
+ search(query, topK = 8) {
19
+ const tokens = this.tokenize(query);
20
+ if (tokens.length === 0)
21
+ return [];
22
+ const scored = this.entries
23
+ .map((e) => ({ ...e, score: this.score(tokens, e) }))
24
+ .filter((h) => h.score > 0);
25
+ scored.sort((a, b) => b.score - a.score);
26
+ return scored.slice(0, topK);
27
+ }
28
+ inferTags(name) {
29
+ const parts = name.replace(/^safari_/, '').split('_');
30
+ return parts[0] ? [parts[0]] : [];
31
+ }
32
+ tokenize(s) {
33
+ return s
34
+ .toLowerCase()
35
+ .split(/[^a-z0-9]+/)
36
+ .filter((t) => t.length > 1);
37
+ }
38
+ score(queryTokens, e) {
39
+ const haystack = (e.name + ' ' + e.description + ' ' + (e.tags ?? []).join(' ')).toLowerCase();
40
+ let s = 0;
41
+ for (const t of queryTokens) {
42
+ if (haystack.includes(t))
43
+ s += 1;
44
+ if (e.name.toLowerCase().includes(t))
45
+ s += 1; // boost name match
46
+ if (e.tags?.includes(t))
47
+ s += 0.5;
48
+ }
49
+ return s;
50
+ }
51
+ }
52
+ //# sourceMappingURL=tool-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-index.js","sourceRoot":"","sources":["../../src/discovery/tool-index.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,10 @@
1
+ /** Cluster G — suggested_next_tools emitted on every HumanApproval denial.
2
+ * Exported so server.ts can attach it to both denial return paths without
3
+ * duplicating the hint text. */
4
+ export declare const HUMAN_APPROVAL_SUGGESTED_NEXT_TOOLS: Array<{
5
+ tool: string;
6
+ reason: string;
7
+ }>;
1
8
  export interface ApprovalResult {
2
9
  required: boolean;
3
10
  reason?: string;
@@ -1,4 +1,10 @@
1
1
  import { HumanApprovalRequiredError } from '../errors.js';
2
+ /** Cluster G — suggested_next_tools emitted on every HumanApproval denial.
3
+ * Exported so server.ts can attach it to both denial return paths without
4
+ * duplicating the hint text. */
5
+ export const HUMAN_APPROVAL_SUGGESTED_NEXT_TOOLS = [
6
+ { tool: 'safari_evaluate', reason: 'Equivalent path that runs through the JS-eval engine (still security-gated).' },
7
+ ];
2
8
  // ─── Pattern Registry ─────────────────────────────────────────────────────────
3
9
  /** OAuth / SSO provider URL patterns. */
4
10
  const OAUTH_URL_PATTERNS = [
@@ -1 +1 @@
1
- {"version":3,"file":"human-approval.js","sourceRoot":"","sources":["../../src/security/human-approval.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"human-approval.js","sourceRoot":"","sources":["../../src/security/human-approval.ts"],"names":[],"mappings":"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"}
package/dist/server.d.ts CHANGED
@@ -66,6 +66,19 @@ export declare class SafariPilotServer {
66
66
  * Returns undefined before the first successful `ensureSessionWindow`.
67
67
  */
68
68
  getSessionWindowId(): number | undefined;
69
+ /**
70
+ * Return all tool definitions (name, description, inputSchema, requirements)
71
+ * without requiring `initialize()` to have been called.
72
+ *
73
+ * Uses I/O-free engine instances to satisfy tool module constructors;
74
+ * only `getDefinitions()` is called — no engine I/O occurs.
75
+ */
76
+ listToolDefinitions(): Array<{
77
+ name: string;
78
+ description: string;
79
+ inputSchema: Record<string, unknown>;
80
+ requirements: ToolRequirements;
81
+ }>;
69
82
  private get sessionTabUrl();
70
83
  constructor(config?: SafariPilotConfig);
71
84
  initialize(): Promise<void>;
package/dist/server.js CHANGED
@@ -25,6 +25,10 @@ import { DownloadTools } from './tools/downloads.js';
25
25
  import { PdfTools } from './tools/pdf.js';
26
26
  import { ExtensionDiagnosticsTools } from './tools/extension-diagnostics.js';
27
27
  import { FileUploadTools } from './tools/file-upload.js';
28
+ import { ToolIndex } from './discovery/tool-index.js';
29
+ import { ToolSearchTools } from './tools/tool-search.js';
30
+ import { SkillRegistry } from './skills/registry.js';
31
+ import { SkillTools } from './tools/skills.js';
28
32
  import { KillSwitch } from './security/kill-switch.js';
29
33
  import { TabOwnership } from './security/tab-ownership.js';
30
34
  import { AuditLog } from './security/audit-log.js';
@@ -32,7 +36,7 @@ import { DomainPolicy } from './security/domain-policy.js';
32
36
  import { RateLimiter } from './security/rate-limiter.js';
33
37
  import { CircuitBreaker } from './security/circuit-breaker.js';
34
38
  import { IdpiAnnotator } from './security/idpi-annotator.js';
35
- import { HumanApproval } from './security/human-approval.js';
39
+ import { HumanApproval, HUMAN_APPROVAL_SUGGESTED_NEXT_TOOLS } from './security/human-approval.js';
36
40
  import { ScreenshotPolicy } from './security/screenshot-policy.js';
37
41
  import { RateLimitedError, HumanApprovalRequiredError, TabUrlNotRecognizedError, SessionTabProtectedError, TabNotOwnedError, DomainNotAllowedError, KillSwitchActiveError, CircuitBreakerOpenError, SessionRecoveryError, SessionWindowInitError, } from './errors.js';
38
42
  import { loadConfig, DEFAULT_CONFIG } from './config.js';
@@ -184,6 +188,62 @@ export class SafariPilotServer {
184
188
  getSessionWindowId() {
185
189
  return this._sessionWindowId;
186
190
  }
191
+ /**
192
+ * Return all tool definitions (name, description, inputSchema, requirements)
193
+ * without requiring `initialize()` to have been called.
194
+ *
195
+ * Uses I/O-free engine instances to satisfy tool module constructors;
196
+ * only `getDefinitions()` is called — no engine I/O occurs.
197
+ */
198
+ listToolDefinitions() {
199
+ const engine = new AppleScriptEngine();
200
+ const proxy = new EngineProxy(engine);
201
+ const daemon = new DaemonEngine();
202
+ const modules = [
203
+ new NavigationTools(engine),
204
+ new InteractionTools(proxy, this),
205
+ new ExtractionTools(proxy, new ScreenshotPolicy(this.config.screenshotPolicy)),
206
+ new NetworkTools(proxy),
207
+ new StorageTools(proxy),
208
+ new AuthTools(proxy),
209
+ new FileUploadTools(proxy, daemon),
210
+ new ShadowTools(proxy),
211
+ new FrameTools(proxy),
212
+ new PermissionTools(proxy),
213
+ new ClipboardTools(proxy),
214
+ new ServiceWorkerTools(proxy),
215
+ new PerformanceTools(proxy),
216
+ new StructuredExtractionTools(proxy),
217
+ new WaitTools(proxy),
218
+ new CompoundTools(engine),
219
+ new DownloadTools(this),
220
+ new PdfTools(this),
221
+ new ExtensionDiagnosticsTools(null),
222
+ new SelectorPackTools(proxy, this.config.selectorPack),
223
+ ];
224
+ // Build the tool index from all existing modules and add the search meta-tool.
225
+ const allEntries = modules.flatMap((m) => m
226
+ .getDefinitions()
227
+ .map((d) => ({ name: d.name, description: d.description })));
228
+ modules.push(new ToolSearchTools(proxy, new ToolIndex(allEntries)));
229
+ // Add SkillTools with empty registry (listToolDefinitions is sync — no I/O).
230
+ const emptyDispatch = async () => { throw new Error('listToolDefinitions: dispatch unavailable'); };
231
+ modules.push(new SkillTools(proxy, new SkillRegistry(), emptyDispatch));
232
+ const defs = [];
233
+ for (const mod of modules) {
234
+ for (const d of mod.getDefinitions()) {
235
+ defs.push({ name: d.name, description: d.description, inputSchema: d.inputSchema, requirements: d.requirements });
236
+ }
237
+ }
238
+ // Also include the emergency stop tool registered directly in initialize()
239
+ defs.push({
240
+ name: 'safari_emergency_stop',
241
+ description: 'Emergency stop — immediately close all agent-owned tabs, activate kill switch, and block all further automation.',
242
+ inputSchema: { type: 'object', properties: { reason: { type: 'string', description: 'Reason for the emergency stop' } } },
243
+ requirements: { idempotent: false },
244
+ });
245
+ return defs;
246
+ }
187
247
  get sessionTabUrl() {
188
248
  return `http://127.0.0.1:19475/session?id=${this.sessionId}`;
189
249
  }
@@ -303,6 +363,34 @@ export class SafariPilotServer {
303
363
  extensionDiagnosticsTools,
304
364
  selectorPackTools,
305
365
  ];
366
+ // Build the tool index from all registered modules, then add the search meta-tool.
367
+ const toolIndex = new ToolIndex(modules.flatMap((m) => m.getDefinitions().map((d) => ({ name: d.name, description: d.description }))));
368
+ modules.push(new ToolSearchTools(proxy, toolIndex));
369
+ // Load skill registry async and add SkillTools.
370
+ // NOTE: Sub-step dispatch bypasses the security pipeline (tab-ownership,
371
+ // rate-limit, circuit-breaker, audit). The outer safari_run_skill call is
372
+ // fully secured; inner steps are not individually audited. Accepted trade-off.
373
+ const skillRegistry = await SkillRegistry.fromDir('skills');
374
+ const skillDispatch = async (n, a) => {
375
+ if (n === 'safari_run_skill' || n === 'safari_list_skills') {
376
+ throw new Error(`Skill cannot call meta-tool: ${n}`);
377
+ }
378
+ for (const m of modules) {
379
+ const h = m.getHandler(n);
380
+ if (h) {
381
+ const resp = await h(a);
382
+ const text = resp.content[0]?.text;
383
+ try {
384
+ return text ? JSON.parse(text) : null;
385
+ }
386
+ catch {
387
+ return text;
388
+ }
389
+ }
390
+ }
391
+ throw new Error(`Skill called unknown tool: ${n}`);
392
+ };
393
+ modules.push(new SkillTools(proxy, skillRegistry, skillDispatch));
306
394
  for (const module of modules) {
307
395
  for (const def of module.getDefinitions()) {
308
396
  const handler = module.getHandler(def.name);
@@ -489,6 +577,7 @@ export class SafariPilotServer {
489
577
  degraded: true,
490
578
  degradedReason: err.message,
491
579
  latencyMs: Date.now() - start,
580
+ suggested_next_tools: HUMAN_APPROVAL_SUGGESTED_NEXT_TOOLS,
492
581
  },
493
582
  };
494
583
  }
@@ -643,6 +732,7 @@ export class SafariPilotServer {
643
732
  degraded: true,
644
733
  degradedReason: `extension_degraded_approval_required: ${err.message}`,
645
734
  latencyMs: Date.now() - start,
735
+ suggested_next_tools: HUMAN_APPROVAL_SUGGESTED_NEXT_TOOLS,
646
736
  },
647
737
  };
648
738
  }