forage-mcp 0.1.0

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 (76) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/LICENSE +21 -0
  3. package/README.md +157 -0
  4. package/dist/cli.d.ts +3 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +146 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/persistence/log.d.ts +11 -0
  9. package/dist/persistence/log.d.ts.map +1 -0
  10. package/dist/persistence/log.js +21 -0
  11. package/dist/persistence/log.js.map +1 -0
  12. package/dist/persistence/manifest.d.ts +24 -0
  13. package/dist/persistence/manifest.d.ts.map +1 -0
  14. package/dist/persistence/manifest.js +45 -0
  15. package/dist/persistence/manifest.js.map +1 -0
  16. package/dist/proxy/manager.d.ts +20 -0
  17. package/dist/proxy/manager.d.ts.map +1 -0
  18. package/dist/proxy/manager.js +77 -0
  19. package/dist/proxy/manager.js.map +1 -0
  20. package/dist/proxy/wrapper.d.ts +20 -0
  21. package/dist/proxy/wrapper.d.ts.map +1 -0
  22. package/dist/proxy/wrapper.js +37 -0
  23. package/dist/proxy/wrapper.js.map +1 -0
  24. package/dist/registries/npm.d.ts +10 -0
  25. package/dist/registries/npm.d.ts.map +1 -0
  26. package/dist/registries/npm.js +74 -0
  27. package/dist/registries/npm.js.map +1 -0
  28. package/dist/registries/official.d.ts +23 -0
  29. package/dist/registries/official.d.ts.map +1 -0
  30. package/dist/registries/official.js +57 -0
  31. package/dist/registries/official.js.map +1 -0
  32. package/dist/registries/smithery.d.ts +3 -0
  33. package/dist/registries/smithery.d.ts.map +1 -0
  34. package/dist/registries/smithery.js +27 -0
  35. package/dist/registries/smithery.js.map +1 -0
  36. package/dist/registries/types.d.ts +13 -0
  37. package/dist/registries/types.d.ts.map +1 -0
  38. package/dist/registries/types.js +2 -0
  39. package/dist/registries/types.js.map +1 -0
  40. package/dist/rules/detector.d.ts +8 -0
  41. package/dist/rules/detector.d.ts.map +1 -0
  42. package/dist/rules/detector.js +54 -0
  43. package/dist/rules/detector.js.map +1 -0
  44. package/dist/rules/writer.d.ts +8 -0
  45. package/dist/rules/writer.d.ts.map +1 -0
  46. package/dist/rules/writer.js +135 -0
  47. package/dist/rules/writer.js.map +1 -0
  48. package/dist/server.d.ts +3 -0
  49. package/dist/server.d.ts.map +1 -0
  50. package/dist/server.js +167 -0
  51. package/dist/server.js.map +1 -0
  52. package/dist/tools/evaluate.d.ts +17 -0
  53. package/dist/tools/evaluate.d.ts.map +1 -0
  54. package/dist/tools/evaluate.js +31 -0
  55. package/dist/tools/evaluate.js.map +1 -0
  56. package/dist/tools/install.d.ts +18 -0
  57. package/dist/tools/install.d.ts.map +1 -0
  58. package/dist/tools/install.js +91 -0
  59. package/dist/tools/install.js.map +1 -0
  60. package/dist/tools/learn.d.ts +12 -0
  61. package/dist/tools/learn.d.ts.map +1 -0
  62. package/dist/tools/learn.js +31 -0
  63. package/dist/tools/learn.js.map +1 -0
  64. package/dist/tools/search.d.ts +10 -0
  65. package/dist/tools/search.d.ts.map +1 -0
  66. package/dist/tools/search.js +50 -0
  67. package/dist/tools/search.js.map +1 -0
  68. package/dist/tools/status.d.ts +20 -0
  69. package/dist/tools/status.d.ts.map +1 -0
  70. package/dist/tools/status.js +24 -0
  71. package/dist/tools/status.js.map +1 -0
  72. package/dist/tools/uninstall.d.ts +11 -0
  73. package/dist/tools/uninstall.d.ts.map +1 -0
  74. package/dist/tools/uninstall.js +55 -0
  75. package/dist/tools/uninstall.js.map +1 -0
  76. package/package.json +49 -0
package/dist/server.js ADDED
@@ -0,0 +1,167 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { z } from "zod";
5
+ import { forage_search } from "./tools/search.js";
6
+ import { forage_evaluate } from "./tools/evaluate.js";
7
+ import { forage_install } from "./tools/install.js";
8
+ import { forage_learn } from "./tools/learn.js";
9
+ import { forage_status } from "./tools/status.js";
10
+ import { forage_uninstall } from "./tools/uninstall.js";
11
+ import { callTool, startServer, stopAll, getRunningServers } from "./proxy/manager.js";
12
+ import { listTools } from "./persistence/manifest.js";
13
+ const server = new McpServer({
14
+ name: "forage",
15
+ version: "0.1.0",
16
+ }, {
17
+ capabilities: {
18
+ tools: { listChanged: true },
19
+ },
20
+ });
21
+ // Track dynamically registered proxied tools so we can remove them
22
+ const proxiedToolHandles = new Map();
23
+ // ── forage_search ──────────────────────────────────────────────
24
+ server.tool("forage_search", "Search for MCP servers and tools across registries (Official MCP Registry, Smithery, npm). Describe what capability you need and get ranked results.", {
25
+ query: z.string().describe("Natural language description of the capability you need (e.g. 'query postgres database', 'search slack messages', 'manage github issues')"),
26
+ sources: z
27
+ .array(z.enum(["official-registry", "npm", "smithery"]))
28
+ .optional()
29
+ .describe("Which registries to search. Defaults to all."),
30
+ }, async ({ query, sources }) => {
31
+ const result = await forage_search({ query, sources });
32
+ return {
33
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
34
+ };
35
+ });
36
+ // ── forage_evaluate ────────────────────────────────────────────
37
+ server.tool("forage_evaluate", "Get detailed information about a specific package — version, downloads, README summary, install command. Use this before installing to verify quality.", {
38
+ packageName: z.string().describe("npm package name to evaluate (e.g. '@modelcontextprotocol/server-postgres')"),
39
+ }, async ({ packageName }) => {
40
+ const result = await forage_evaluate({ packageName });
41
+ return {
42
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
43
+ };
44
+ });
45
+ // ── forage_install ─────────────────────────────────────────────
46
+ server.tool("forage_install", "Install an MCP server and start it as a proxied subprocess. The server's tools become available immediately via Forage — no restart needed. IMPORTANT: Set confirm=true to proceed with installation (user will be prompted to approve the tool call).", {
47
+ packageName: z.string().describe("npm package name to install (e.g. '@modelcontextprotocol/server-filesystem')"),
48
+ command: z.string().optional().describe("Command to run the server. Defaults to 'npx'."),
49
+ args: z.array(z.string()).optional().describe("Arguments for the command. Defaults to ['-y', packageName]."),
50
+ env: z.record(z.string(), z.string()).optional().describe("Environment variables to pass to the server process."),
51
+ confirm: z.boolean().describe("Must be true to proceed with installation. This is a safety gate — the user will see and approve the tool call."),
52
+ }, async ({ packageName, command, args, env, confirm }) => {
53
+ const result = await forage_install({ packageName, command, args, env, confirm });
54
+ // If installation was successful, register proxied tools and notify
55
+ if (result.success) {
56
+ registerProxiedTools(result.name);
57
+ server.sendToolListChanged();
58
+ }
59
+ return {
60
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
61
+ };
62
+ });
63
+ // ── forage_learn ───────────────────────────────────────────────
64
+ server.tool("forage_learn", "Write usage instructions for an installed tool to agent rule files (CLAUDE.md, AGENTS.md, .cursor/rules/). This persists knowledge across sessions so the agent remembers how to use the tool next time.", {
65
+ toolName: z.string().describe("Name of the tool (as shown in forage_status)"),
66
+ rules: z.string().describe("Markdown-formatted usage instructions for the agent. Include: when to use the tool, key commands/patterns, any required env vars or config."),
67
+ target: z.string().optional().describe("Specific file path to write to. If omitted, auto-detects based on which agent is in use."),
68
+ }, async ({ toolName, rules, target }) => {
69
+ const result = await forage_learn({ toolName, rules, target });
70
+ return {
71
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
72
+ };
73
+ });
74
+ // ── forage_status ──────────────────────────────────────────────
75
+ server.tool("forage_status", "List all tools that Forage has installed and is currently proxying. Shows which servers are running, what tools they provide, and their install status.", {}, async () => {
76
+ const result = await forage_status();
77
+ return {
78
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
79
+ };
80
+ });
81
+ // ── forage_uninstall ───────────────────────────────────────────
82
+ server.tool("forage_uninstall", "Remove a previously installed tool. Stops the server, removes from manifest, and cleans up agent rules. Set confirm=true to proceed.", {
83
+ name: z.string().describe("Name of the installed tool to remove (as shown in forage_status)"),
84
+ confirm: z.boolean().optional().describe("Must be true to proceed with uninstallation."),
85
+ }, async ({ name, confirm }) => {
86
+ const result = await forage_uninstall({ name, confirm });
87
+ if (result.success) {
88
+ unregisterProxiedTools(name);
89
+ server.sendToolListChanged();
90
+ }
91
+ return {
92
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
93
+ };
94
+ });
95
+ // ── Dynamic tool registration for proxied servers ──────────────
96
+ function sanitizeName(name) {
97
+ return name.replace(/[^a-zA-Z0-9_-]/g, "_");
98
+ }
99
+ function registerProxiedTools(serverName) {
100
+ const servers = getRunningServers();
101
+ const managed = servers.get(serverName);
102
+ if (!managed)
103
+ return;
104
+ const handles = [];
105
+ for (const tool of managed.tools) {
106
+ const wrappedName = `foraged__${sanitizeName(serverName)}__${tool.name}`;
107
+ const description = `[via ${serverName}] ${tool.description ?? ""}`.trim();
108
+ // Register a dynamic tool that proxies to the child server
109
+ const handle = server.tool(wrappedName, description, {}, // Accept any args — the child server validates
110
+ async (args) => {
111
+ const result = await callTool(serverName, tool.name, args);
112
+ // The result from callTool is already in MCP format
113
+ return result;
114
+ });
115
+ handles.push(handle);
116
+ }
117
+ proxiedToolHandles.set(serverName, handles);
118
+ }
119
+ function unregisterProxiedTools(serverName) {
120
+ const handles = proxiedToolHandles.get(serverName);
121
+ if (!handles)
122
+ return;
123
+ for (const handle of handles) {
124
+ handle.remove();
125
+ }
126
+ proxiedToolHandles.delete(serverName);
127
+ }
128
+ // ── Startup ────────────────────────────────────────────────────
129
+ async function autoStartFromManifest() {
130
+ const tools = await listTools();
131
+ const autoStartTools = tools.filter((t) => t.autoStart);
132
+ if (autoStartTools.length > 0) {
133
+ process.stderr.write(`[forage] Auto-starting ${autoStartTools.length} tool(s) from manifest...\n`);
134
+ }
135
+ for (const tool of autoStartTools) {
136
+ try {
137
+ const managed = await startServer(tool);
138
+ registerProxiedTools(tool.name);
139
+ process.stderr.write(`[forage] Started ${tool.name} (${managed.tools.length} tools)\n`);
140
+ }
141
+ catch (error) {
142
+ process.stderr.write(`[forage] Failed to start ${tool.name}: ${error instanceof Error ? error.message : String(error)}\n`);
143
+ }
144
+ }
145
+ }
146
+ async function main() {
147
+ // Auto-start previously installed tools
148
+ await autoStartFromManifest();
149
+ // Connect to the MCP transport
150
+ const transport = new StdioServerTransport();
151
+ await server.connect(transport);
152
+ process.stderr.write("[forage] MCP server running on stdio\n");
153
+ // Clean up on exit
154
+ process.on("SIGINT", async () => {
155
+ await stopAll();
156
+ process.exit(0);
157
+ });
158
+ process.on("SIGTERM", async () => {
159
+ await stopAll();
160
+ process.exit(0);
161
+ });
162
+ }
163
+ main().catch((error) => {
164
+ process.stderr.write(`[forage] Fatal error: ${error}\n`);
165
+ process.exit(1);
166
+ });
167
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ export interface EvaluateInput {
2
+ packageName: string;
3
+ }
4
+ export interface EvaluateResult {
5
+ name: string;
6
+ description: string;
7
+ version: string;
8
+ repository?: string;
9
+ weeklyDownloads?: number;
10
+ readme?: string;
11
+ installCommand?: string;
12
+ source: string;
13
+ }
14
+ export declare function forage_evaluate(input: EvaluateInput): Promise<EvaluateResult | {
15
+ error: string;
16
+ }>;
17
+ //# sourceMappingURL=evaluate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluate.d.ts","sourceRoot":"","sources":["../../src/tools/evaluate.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,eAAe,CACnC,KAAK,EAAE,aAAa,GACnB,OAAO,CAAC,cAAc,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CA+B7C"}
@@ -0,0 +1,31 @@
1
+ import { getServerDetails } from "../registries/official.js";
2
+ import { getPackageDetails } from "../registries/npm.js";
3
+ export async function forage_evaluate(input) {
4
+ // Try official registry first
5
+ const official = await getServerDetails(input.packageName);
6
+ const npm = await getPackageDetails(input.packageName);
7
+ if (!official && !npm) {
8
+ return { error: `Package "${input.packageName}" not found in any registry` };
9
+ }
10
+ const npmPkg = official?.packages?.find((p) => p.registryType === "npm");
11
+ // Truncate README to something reasonable for an LLM
12
+ let readme = npm?.readme;
13
+ if (readme && readme.length > 3000) {
14
+ readme = readme.slice(0, 3000) + "\n\n... (truncated)";
15
+ }
16
+ return {
17
+ name: official?.name ?? input.packageName,
18
+ description: official?.description ?? npm?.description ?? "",
19
+ version: npm?.version ?? npmPkg?.version ?? official?.version ?? "unknown",
20
+ repository: npm?.repository ?? official?.repository?.url,
21
+ weeklyDownloads: npm?.weeklyDownloads,
22
+ readme,
23
+ installCommand: npmPkg
24
+ ? `npx -y ${npmPkg.identifier}`
25
+ : npm
26
+ ? `npx -y ${input.packageName}`
27
+ : undefined,
28
+ source: official ? "official-registry" : "npm",
29
+ };
30
+ }
31
+ //# sourceMappingURL=evaluate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluate.js","sourceRoot":"","sources":["../../src/tools/evaluate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAiBzD,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAAoB;IAEpB,8BAA8B;IAC9B,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAC3D,MAAM,GAAG,GAAG,MAAM,iBAAiB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAEvD,IAAI,CAAC,QAAQ,IAAI,CAAC,GAAG,EAAE,CAAC;QACtB,OAAO,EAAE,KAAK,EAAE,YAAY,KAAK,CAAC,WAAW,6BAA6B,EAAE,CAAC;IAC/E,CAAC;IAED,MAAM,MAAM,GAAG,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,KAAK,KAAK,CAAC,CAAC;IAEzE,qDAAqD;IACrD,IAAI,MAAM,GAAG,GAAG,EAAE,MAAM,CAAC;IACzB,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;QACnC,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,qBAAqB,CAAC;IACzD,CAAC;IAED,OAAO;QACL,IAAI,EAAE,QAAQ,EAAE,IAAI,IAAI,KAAK,CAAC,WAAW;QACzC,WAAW,EAAE,QAAQ,EAAE,WAAW,IAAI,GAAG,EAAE,WAAW,IAAI,EAAE;QAC5D,OAAO,EAAE,GAAG,EAAE,OAAO,IAAI,MAAM,EAAE,OAAO,IAAI,QAAQ,EAAE,OAAO,IAAI,SAAS;QAC1E,UAAU,EAAE,GAAG,EAAE,UAAU,IAAI,QAAQ,EAAE,UAAU,EAAE,GAAG;QACxD,eAAe,EAAE,GAAG,EAAE,eAAe;QACrC,MAAM;QACN,cAAc,EAAE,MAAM;YACpB,CAAC,CAAC,UAAU,MAAM,CAAC,UAAU,EAAE;YAC/B,CAAC,CAAC,GAAG;gBACH,CAAC,CAAC,UAAU,KAAK,CAAC,WAAW,EAAE;gBAC/B,CAAC,CAAC,SAAS;QACf,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,KAAK;KAC/C,CAAC;AACJ,CAAC"}
@@ -0,0 +1,18 @@
1
+ export interface InstallInput {
2
+ packageName: string;
3
+ command?: string;
4
+ args?: string[];
5
+ env?: Record<string, string>;
6
+ confirm?: boolean;
7
+ }
8
+ export interface InstallResult {
9
+ success: boolean;
10
+ name: string;
11
+ tools: Array<{
12
+ name: string;
13
+ description?: string;
14
+ }>;
15
+ message: string;
16
+ }
17
+ export declare function forage_install(input: InstallInput): Promise<InstallResult>;
18
+ //# sourceMappingURL=install.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/tools/install.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,cAAc,CAClC,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,aAAa,CAAC,CA6FxB"}
@@ -0,0 +1,91 @@
1
+ import { exec } from "node:child_process";
2
+ import { promisify } from "node:util";
3
+ import { startServer } from "../proxy/manager.js";
4
+ import { addTool } from "../persistence/manifest.js";
5
+ import { appendLog } from "../persistence/log.js";
6
+ const execAsync = promisify(exec);
7
+ export async function forage_install(input) {
8
+ if (!input.confirm) {
9
+ return {
10
+ success: false,
11
+ name: input.packageName,
12
+ tools: [],
13
+ message: `⚠️ Install requires confirmation. Call forage_install again with confirm: true to install "${input.packageName}". The user will be prompted to approve.`,
14
+ };
15
+ }
16
+ const command = input.command ?? "npx";
17
+ const args = input.args ?? ["-y", input.packageName];
18
+ // Verify the package exists on npm before installing
19
+ try {
20
+ const { stdout } = await execAsync(`npm view ${input.packageName} name version --json`, { timeout: 15000 });
21
+ JSON.parse(stdout); // validates it's real
22
+ }
23
+ catch {
24
+ await appendLog({
25
+ timestamp: new Date().toISOString(),
26
+ action: "install",
27
+ packageName: input.packageName,
28
+ success: false,
29
+ error: "Package not found on npm",
30
+ });
31
+ return {
32
+ success: false,
33
+ name: input.packageName,
34
+ tools: [],
35
+ message: `Package "${input.packageName}" not found on npm.`,
36
+ };
37
+ }
38
+ // Create the tool record
39
+ const tool = {
40
+ name: input.packageName.replace(/^@/, "").replace(/\//g, "__"),
41
+ packageName: input.packageName,
42
+ version: "latest",
43
+ source: "npm",
44
+ command,
45
+ args,
46
+ env: input.env,
47
+ autoStart: true,
48
+ installedAt: new Date().toISOString(),
49
+ };
50
+ try {
51
+ // Start the server as a child process
52
+ const managed = await startServer(tool);
53
+ // Save to manifest
54
+ await addTool(tool);
55
+ // Log the install
56
+ await appendLog({
57
+ timestamp: new Date().toISOString(),
58
+ action: "install",
59
+ packageName: input.packageName,
60
+ version: tool.version,
61
+ source: tool.source,
62
+ success: true,
63
+ });
64
+ return {
65
+ success: true,
66
+ name: tool.name,
67
+ tools: managed.tools.map((t) => ({
68
+ name: t.name,
69
+ description: t.description,
70
+ })),
71
+ message: `Installed and started "${input.packageName}". ${managed.tools.length} tools now available. Use forage_learn to save usage instructions for future sessions.`,
72
+ };
73
+ }
74
+ catch (error) {
75
+ const errorMsg = error instanceof Error ? error.message : String(error);
76
+ await appendLog({
77
+ timestamp: new Date().toISOString(),
78
+ action: "install",
79
+ packageName: input.packageName,
80
+ success: false,
81
+ error: errorMsg,
82
+ });
83
+ return {
84
+ success: false,
85
+ name: input.packageName,
86
+ tools: [],
87
+ message: `Failed to start "${input.packageName}": ${errorMsg}`,
88
+ };
89
+ }
90
+ }
91
+ //# sourceMappingURL=install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/tools/install.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export interface LearnToolInput {
2
+ toolName: string;
3
+ rules: string;
4
+ target?: string;
5
+ }
6
+ export interface LearnResult {
7
+ success: boolean;
8
+ updatedFiles: string[];
9
+ message: string;
10
+ }
11
+ export declare function forage_learn(input: LearnToolInput): Promise<LearnResult>;
12
+ //# sourceMappingURL=learn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learn.d.ts","sourceRoot":"","sources":["../../src/tools/learn.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,YAAY,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,CA4B9E"}
@@ -0,0 +1,31 @@
1
+ import { writeRules } from "../rules/writer.js";
2
+ import { readManifest, writeManifest } from "../persistence/manifest.js";
3
+ export async function forage_learn(input) {
4
+ try {
5
+ const updatedFiles = await writeRules({
6
+ toolName: input.toolName,
7
+ rules: input.rules,
8
+ target: input.target,
9
+ });
10
+ // Also persist rules in manifest for cross-session recall
11
+ const manifest = await readManifest();
12
+ const tool = manifest.tools[input.toolName];
13
+ if (tool) {
14
+ tool.rules = input.rules;
15
+ await writeManifest(manifest);
16
+ }
17
+ return {
18
+ success: true,
19
+ updatedFiles,
20
+ message: `Updated ${updatedFiles.length} file(s) with usage instructions for "${input.toolName}": ${updatedFiles.join(", ")}`,
21
+ };
22
+ }
23
+ catch (error) {
24
+ return {
25
+ success: false,
26
+ updatedFiles: [],
27
+ message: `Failed to write rules: ${error instanceof Error ? error.message : String(error)}`,
28
+ };
29
+ }
30
+ }
31
+ //# sourceMappingURL=learn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learn.js","sourceRoot":"","sources":["../../src/tools/learn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAmB,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAczE,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,KAAqB;IACtD,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,MAAM,UAAU,CAAC;YACpC,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,MAAM,EAAE,KAAK,CAAC,MAAM;SACrB,CAAC,CAAC;QAEH,0DAA0D;QAC1D,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC5C,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;YACzB,MAAM,aAAa,CAAC,QAAQ,CAAC,CAAC;QAChC,CAAC;QAED,OAAO;YACL,OAAO,EAAE,IAAI;YACb,YAAY;YACZ,OAAO,EAAE,WAAW,YAAY,CAAC,MAAM,yCAAyC,KAAK,CAAC,QAAQ,MAAM,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;SAC9H,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,OAAO,EAAE,KAAK;YACd,YAAY,EAAE,EAAE;YAChB,OAAO,EAAE,0BAA0B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;SAC5F,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { SearchResult } from "../registries/types.js";
2
+ export interface SearchInput {
3
+ query: string;
4
+ sources?: Array<"official-registry" | "npm" | "smithery">;
5
+ }
6
+ export declare function forage_search(input: SearchInput): Promise<{
7
+ results: SearchResult[];
8
+ query: string;
9
+ }>;
10
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/tools/search.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,KAAK,CAAC,mBAAmB,GAAG,KAAK,GAAG,UAAU,CAAC,CAAC;CAC3D;AAED,wBAAsB,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC;IAC/D,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAoCD"}
@@ -0,0 +1,50 @@
1
+ import { searchOfficial } from "../registries/official.js";
2
+ import { searchNpm } from "../registries/npm.js";
3
+ import { searchSmithery } from "../registries/smithery.js";
4
+ export async function forage_search(input) {
5
+ const sources = input.sources ?? ["official-registry", "npm", "smithery"];
6
+ const searches = [];
7
+ if (sources.includes("official-registry")) {
8
+ searches.push(searchOfficial(input.query));
9
+ }
10
+ if (sources.includes("npm")) {
11
+ searches.push(searchNpm(input.query));
12
+ }
13
+ if (sources.includes("smithery")) {
14
+ searches.push(searchSmithery(input.query));
15
+ }
16
+ const allResults = await Promise.all(searches);
17
+ const flat = allResults.flat();
18
+ // Deduplicate by package name, preferring official registry results
19
+ const seen = new Map();
20
+ for (const result of flat) {
21
+ if (!result.packageName)
22
+ continue;
23
+ const key = result.packageName.toLowerCase();
24
+ const existing = seen.get(key);
25
+ if (!existing || sourceRank(result.source) < sourceRank(existing.source)) {
26
+ seen.set(key, result);
27
+ }
28
+ }
29
+ const results = [...seen.values()].sort((a, b) => {
30
+ // Sort by source priority first, then by name
31
+ const rankDiff = sourceRank(a.source) - sourceRank(b.source);
32
+ if (rankDiff !== 0)
33
+ return rankDiff;
34
+ return a.name.localeCompare(b.name);
35
+ });
36
+ return { results, query: input.query };
37
+ }
38
+ function sourceRank(source) {
39
+ switch (source) {
40
+ case "official-registry":
41
+ return 0;
42
+ case "smithery":
43
+ return 1;
44
+ case "npm":
45
+ return 2;
46
+ default:
47
+ return 3;
48
+ }
49
+ }
50
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/tools/search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAQ3D,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAkB;IAIpD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,CAAC,mBAAmB,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;IAE1E,MAAM,QAAQ,GAAG,EAAE,CAAC;IACpB,IAAI,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAC1C,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7C,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IACxC,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QACjC,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC;IAE/B,oEAAoE;IACpE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAwB,CAAC;IAC7C,KAAK,MAAM,MAAM,IAAI,IAAI,EAAE,CAAC;QAC1B,IAAI,CAAC,MAAM,CAAC,WAAW;YAAE,SAAS;QAClC,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC;QAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,CAAC,QAAQ,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACzE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAC/C,8CAA8C;QAC9C,MAAM,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QAC7D,IAAI,QAAQ,KAAK,CAAC;YAAE,OAAO,QAAQ,CAAC;QACpC,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;AACzC,CAAC;AAED,SAAS,UAAU,CAAC,MAAc;IAChC,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,mBAAmB;YACtB,OAAO,CAAC,CAAC;QACX,KAAK,UAAU;YACb,OAAO,CAAC,CAAC;QACX,KAAK,KAAK;YACR,OAAO,CAAC,CAAC;QACX;YACE,OAAO,CAAC,CAAC;IACb,CAAC;AACH,CAAC"}
@@ -0,0 +1,20 @@
1
+ export interface StatusResult {
2
+ running: Array<{
3
+ name: string;
4
+ packageName: string;
5
+ tools: Array<{
6
+ name: string;
7
+ description?: string;
8
+ }>;
9
+ installedAt: string;
10
+ }>;
11
+ installed: Array<{
12
+ name: string;
13
+ packageName: string;
14
+ autoStart: boolean;
15
+ installedAt: string;
16
+ running: boolean;
17
+ }>;
18
+ }
19
+ export declare function forage_status(): Promise<StatusResult>;
20
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/tools/status.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,WAAW,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QACrD,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC,CAAC;IACH,SAAS,EAAE,KAAK,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,OAAO,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,OAAO,EAAE,OAAO,CAAC;KAClB,CAAC,CAAC;CACJ;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,YAAY,CAAC,CAyB3D"}
@@ -0,0 +1,24 @@
1
+ import { getRunningServers } from "../proxy/manager.js";
2
+ import { listTools } from "../persistence/manifest.js";
3
+ export async function forage_status() {
4
+ const allInstalled = await listTools();
5
+ const runningServers = getRunningServers();
6
+ const running = [...runningServers.entries()].map(([name, server]) => ({
7
+ name,
8
+ packageName: allInstalled.find((t) => t.name === name)?.packageName ?? name,
9
+ tools: server.tools.map((t) => ({
10
+ name: t.name,
11
+ description: t.description,
12
+ })),
13
+ installedAt: allInstalled.find((t) => t.name === name)?.installedAt ?? "unknown",
14
+ }));
15
+ const installed = allInstalled.map((tool) => ({
16
+ name: tool.name,
17
+ packageName: tool.packageName,
18
+ autoStart: tool.autoStart,
19
+ installedAt: tool.installedAt,
20
+ running: runningServers.has(tool.name),
21
+ }));
22
+ return { running, installed };
23
+ }
24
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/tools/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAkBvD,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,YAAY,GAAG,MAAM,SAAS,EAAE,CAAC;IACvC,MAAM,cAAc,GAAG,iBAAiB,EAAE,CAAC;IAE3C,MAAM,OAAO,GAAG,CAAC,GAAG,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;QACrE,IAAI;QACJ,WAAW,EACT,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,WAAW,IAAI,IAAI;QAChE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC9B,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,WAAW,EAAE,CAAC,CAAC,WAAW;SAC3B,CAAC,CAAC;QACH,WAAW,EACT,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,WAAW,IAAI,SAAS;KACtE,CAAC,CAAC,CAAC;IAEJ,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC5C,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,OAAO,EAAE,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;KACvC,CAAC,CAAC,CAAC;IAEJ,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AAChC,CAAC"}
@@ -0,0 +1,11 @@
1
+ export interface UninstallInput {
2
+ name: string;
3
+ confirm?: boolean;
4
+ }
5
+ export interface UninstallResult {
6
+ success: boolean;
7
+ message: string;
8
+ cleanedFiles: string[];
9
+ }
10
+ export declare function forage_uninstall(input: UninstallInput): Promise<UninstallResult>;
11
+ //# sourceMappingURL=uninstall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uninstall.d.ts","sourceRoot":"","sources":["../../src/tools/uninstall.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,eAAe,CAAC,CAqD1B"}
@@ -0,0 +1,55 @@
1
+ import { stopServer } from "../proxy/manager.js";
2
+ import { removeTool, getTool } from "../persistence/manifest.js";
3
+ import { removeRules } from "../rules/writer.js";
4
+ import { appendLog } from "../persistence/log.js";
5
+ export async function forage_uninstall(input) {
6
+ if (!input.confirm) {
7
+ const tool = await getTool(input.name);
8
+ if (!tool) {
9
+ return {
10
+ success: false,
11
+ message: `Tool "${input.name}" is not installed.`,
12
+ cleanedFiles: [],
13
+ };
14
+ }
15
+ return {
16
+ success: false,
17
+ message: `⚠️ Uninstall requires confirmation. Call forage_uninstall again with confirm: true to remove "${input.name}" (${tool.packageName}).`,
18
+ cleanedFiles: [],
19
+ };
20
+ }
21
+ try {
22
+ // Stop the running server
23
+ await stopServer(input.name);
24
+ // Remove from manifest
25
+ const tool = await removeTool(input.name);
26
+ if (!tool) {
27
+ return {
28
+ success: false,
29
+ message: `Tool "${input.name}" is not installed.`,
30
+ cleanedFiles: [],
31
+ };
32
+ }
33
+ // Clean up rules from agent files
34
+ const cleanedFiles = await removeRules(input.name);
35
+ await appendLog({
36
+ timestamp: new Date().toISOString(),
37
+ action: "uninstall",
38
+ packageName: tool.packageName,
39
+ success: true,
40
+ });
41
+ return {
42
+ success: true,
43
+ message: `Uninstalled "${input.name}" (${tool.packageName}). Stopped server and cleaned up rules.`,
44
+ cleanedFiles,
45
+ };
46
+ }
47
+ catch (error) {
48
+ return {
49
+ success: false,
50
+ message: `Failed to uninstall: ${error instanceof Error ? error.message : String(error)}`,
51
+ cleanedFiles: [],
52
+ };
53
+ }
54
+ }
55
+ //# sourceMappingURL=uninstall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uninstall.js","sourceRoot":"","sources":["../../src/tools/uninstall.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAalD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,KAAqB;IAErB,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACnB,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,SAAS,KAAK,CAAC,IAAI,qBAAqB;gBACjD,YAAY,EAAE,EAAE;aACjB,CAAC;QACJ,CAAC;QACD,OAAO;YACL,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,kGAAkG,KAAK,CAAC,IAAI,MAAM,IAAI,CAAC,WAAW,IAAI;YAC/I,YAAY,EAAE,EAAE;SACjB,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,0BAA0B;QAC1B,MAAM,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAE7B,uBAAuB;QACvB,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,SAAS,KAAK,CAAC,IAAI,qBAAqB;gBACjD,YAAY,EAAE,EAAE;aACjB,CAAC;QACJ,CAAC;QAED,kCAAkC;QAClC,MAAM,YAAY,GAAG,MAAM,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEnD,MAAM,SAAS,CAAC;YACd,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,MAAM,EAAE,WAAW;YACnB,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QAEH,OAAO;YACL,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,gBAAgB,KAAK,CAAC,IAAI,MAAM,IAAI,CAAC,WAAW,yCAAyC;YAClG,YAAY;SACb,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,wBAAwB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;YACzF,YAAY,EAAE,EAAE;SACjB,CAAC;IACJ,CAAC;AACH,CAAC"}