@tryhamster/gerbil 1.0.0-rc.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 (103) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +253 -0
  3. package/bin/cli.js +2 -0
  4. package/dist/auto-update-BbNHbSU1.mjs +3 -0
  5. package/dist/browser/index.d.mts +262 -0
  6. package/dist/browser/index.d.mts.map +1 -0
  7. package/dist/browser/index.mjs +755 -0
  8. package/dist/browser/index.mjs.map +1 -0
  9. package/dist/chrome-backend-C5Un08O4.mjs +771 -0
  10. package/dist/chrome-backend-C5Un08O4.mjs.map +1 -0
  11. package/dist/chrome-backend-CtwPENIW.mjs +3 -0
  12. package/dist/chunk-Ct1HF2bE.mjs +7 -0
  13. package/dist/cli.d.mts +1 -0
  14. package/dist/cli.mjs +7078 -0
  15. package/dist/cli.mjs.map +1 -0
  16. package/dist/frameworks/express.d.mts +22 -0
  17. package/dist/frameworks/express.d.mts.map +1 -0
  18. package/dist/frameworks/express.mjs +123 -0
  19. package/dist/frameworks/express.mjs.map +1 -0
  20. package/dist/frameworks/fastify.d.mts +11 -0
  21. package/dist/frameworks/fastify.d.mts.map +1 -0
  22. package/dist/frameworks/fastify.mjs +73 -0
  23. package/dist/frameworks/fastify.mjs.map +1 -0
  24. package/dist/frameworks/hono.d.mts +14 -0
  25. package/dist/frameworks/hono.d.mts.map +1 -0
  26. package/dist/frameworks/hono.mjs +82 -0
  27. package/dist/frameworks/hono.mjs.map +1 -0
  28. package/dist/frameworks/next.d.mts +31 -0
  29. package/dist/frameworks/next.d.mts.map +1 -0
  30. package/dist/frameworks/next.mjs +116 -0
  31. package/dist/frameworks/next.mjs.map +1 -0
  32. package/dist/frameworks/react.d.mts +56 -0
  33. package/dist/frameworks/react.d.mts.map +1 -0
  34. package/dist/frameworks/react.mjs +172 -0
  35. package/dist/frameworks/react.mjs.map +1 -0
  36. package/dist/frameworks/trpc.d.mts +12 -0
  37. package/dist/frameworks/trpc.d.mts.map +1 -0
  38. package/dist/frameworks/trpc.mjs +80 -0
  39. package/dist/frameworks/trpc.mjs.map +1 -0
  40. package/dist/gerbil-BfnsFWRE.mjs +644 -0
  41. package/dist/gerbil-BfnsFWRE.mjs.map +1 -0
  42. package/dist/gerbil-BjW-z7Fq.mjs +5 -0
  43. package/dist/gerbil-DZ1k3ChC.d.mts +138 -0
  44. package/dist/gerbil-DZ1k3ChC.d.mts.map +1 -0
  45. package/dist/index.d.mts +223 -0
  46. package/dist/index.d.mts.map +1 -0
  47. package/dist/index.mjs +13 -0
  48. package/dist/index.mjs.map +1 -0
  49. package/dist/integrations/ai-sdk.d.mts +78 -0
  50. package/dist/integrations/ai-sdk.d.mts.map +1 -0
  51. package/dist/integrations/ai-sdk.mjs +199 -0
  52. package/dist/integrations/ai-sdk.mjs.map +1 -0
  53. package/dist/integrations/langchain.d.mts +41 -0
  54. package/dist/integrations/langchain.d.mts.map +1 -0
  55. package/dist/integrations/langchain.mjs +93 -0
  56. package/dist/integrations/langchain.mjs.map +1 -0
  57. package/dist/integrations/llamaindex.d.mts +45 -0
  58. package/dist/integrations/llamaindex.d.mts.map +1 -0
  59. package/dist/integrations/llamaindex.mjs +86 -0
  60. package/dist/integrations/llamaindex.mjs.map +1 -0
  61. package/dist/integrations/mcp-client.d.mts +206 -0
  62. package/dist/integrations/mcp-client.d.mts.map +1 -0
  63. package/dist/integrations/mcp-client.mjs +507 -0
  64. package/dist/integrations/mcp-client.mjs.map +1 -0
  65. package/dist/integrations/mcp.d.mts +177 -0
  66. package/dist/integrations/mcp.d.mts.map +1 -0
  67. package/dist/integrations/mcp.mjs +8 -0
  68. package/dist/mcp-R8kRLIKb.mjs +348 -0
  69. package/dist/mcp-R8kRLIKb.mjs.map +1 -0
  70. package/dist/models-DKULvhOr.mjs +136 -0
  71. package/dist/models-DKULvhOr.mjs.map +1 -0
  72. package/dist/models-De2-_GmQ.d.mts +22 -0
  73. package/dist/models-De2-_GmQ.d.mts.map +1 -0
  74. package/dist/one-liner-BUQR0nqq.mjs +98 -0
  75. package/dist/one-liner-BUQR0nqq.mjs.map +1 -0
  76. package/dist/skills/index.d.mts +390 -0
  77. package/dist/skills/index.d.mts.map +1 -0
  78. package/dist/skills/index.mjs +7 -0
  79. package/dist/skills-D3CEpgDc.mjs +630 -0
  80. package/dist/skills-D3CEpgDc.mjs.map +1 -0
  81. package/dist/tools-BsiEE6f2.mjs +567 -0
  82. package/dist/tools-BsiEE6f2.mjs.map +1 -0
  83. package/dist/types-BS1N92Jt.d.mts +183 -0
  84. package/dist/types-BS1N92Jt.d.mts.map +1 -0
  85. package/dist/utils-7vXqtq2Q.mjs +63 -0
  86. package/dist/utils-7vXqtq2Q.mjs.map +1 -0
  87. package/docs/ai-sdk.md +80 -0
  88. package/docs/architecture/README.md +84 -0
  89. package/docs/architecture/caching.md +227 -0
  90. package/docs/architecture/inference.md +176 -0
  91. package/docs/architecture/overview.md +179 -0
  92. package/docs/architecture/streaming.md +261 -0
  93. package/docs/architecture/webgpu.md +213 -0
  94. package/docs/browser.md +328 -0
  95. package/docs/cli.md +155 -0
  96. package/docs/frameworks.md +90 -0
  97. package/docs/mcp-client.md +224 -0
  98. package/docs/mcp.md +109 -0
  99. package/docs/memory.md +229 -0
  100. package/docs/repl.md +473 -0
  101. package/docs/skills.md +261 -0
  102. package/docs/tools.md +304 -0
  103. package/package.json +207 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills-D3CEpgDc.mjs","names":["ctx: SkillContext<TInput>","loaded: string[]"],"sources":["../src/skills/registry.ts","../src/skills/loader.ts","../src/skills/builtin/commit.ts","../src/skills/builtin/explain.ts","../src/skills/builtin/extract.ts","../src/skills/builtin/review.ts","../src/skills/builtin/summarize.ts","../src/skills/builtin/test.ts","../src/skills/builtin/title.ts","../src/skills/builtin/translate.ts"],"sourcesContent":["/**\n * Skill Registry\n *\n * Central registry for all skills (built-in and custom).\n */\n\nimport type { Gerbil } from \"../core/gerbil.js\";\nimport { getInstance } from \"../core/one-liner.js\";\nimport type { Skill, SkillContext, SkillDefinition, SkillInfo } from \"./types.js\";\n\n// ============================================\n// Registry Storage\n// ============================================\n\nconst registry = new Map<string, Skill>();\nconst skillSources = new Map<string, string>(); // name -> source file\n\n// Reserved names that cannot be used for custom skills (CLI commands/views)\n// Note: Built-in skills like \"commit\", \"summarize\" ARE allowed because they\n// have dedicated CLI commands, but new skills cannot use these view names\nconst RESERVED_NAMES = new Set([\n // REPL views (would conflict with CLI shortcuts)\n \"repl\",\n \"chat\",\n \"skills\",\n \"tools\",\n \"model\",\n \"integrate\",\n \"benchmark\",\n \"info\",\n \"serve\",\n \"cache\",\n // CLI commands\n \"generate\",\n \"models\",\n \"bench\",\n // Aliases\n \"r\",\n \"c\",\n \"g\",\n // Other reserved\n \"help\",\n \"version\",\n \"gerbil\",\n]);\n\n// ============================================\n// Define Skill\n// ============================================\n\n/**\n * Define and register a skill\n *\n * @example\n * ```ts\n * const sentiment = defineSkill({\n * name: \"sentiment\",\n * description: \"Analyze sentiment of text\",\n * input: z.object({ text: z.string() }),\n * output: z.object({ sentiment: z.enum([\"positive\", \"negative\", \"neutral\"]) }),\n * async run({ input, gerbil }) {\n * return gerbil.json(`Analyze sentiment: ${input.text}`, { schema: this.output });\n * }\n * });\n * ```\n */\nexport function defineSkill<TInput, TOutput>(\n definition: SkillDefinition<TInput, TOutput>,\n): Skill<TInput, TOutput> {\n // Validate name format\n if (!/^[a-z][a-z0-9-]*$/.test(definition.name)) {\n throw new Error(`Skill name must be kebab-case starting with a letter: ${definition.name}`);\n }\n\n // Check for reserved names (CLI commands)\n if (RESERVED_NAMES.has(definition.name)) {\n throw new Error(\n `Skill name \"${definition.name}\" is reserved for CLI commands. Choose a different name.`,\n );\n }\n\n // Create the skill function\n const execute = async (input: TInput): Promise<TOutput> => skill.run(input);\n\n // Create the skill object\n const skill = Object.assign(execute, {\n definition,\n\n async run(input: TInput, gerbil?: Gerbil): Promise<TOutput> {\n // Get or create Gerbil instance\n const g = gerbil ?? (await getInstance(definition.model));\n\n // Validate input if schema provided\n let validatedInput = input;\n if (definition.input) {\n const parsed = definition.input.safeParse(input);\n if (!parsed.success) {\n throw new Error(`Invalid input for skill \"${definition.name}\": ${parsed.error.message}`);\n }\n validatedInput = parsed.data;\n }\n\n // Create context\n const ctx: SkillContext<TInput> = {\n input: validatedInput,\n gerbil: g,\n rawInput: input,\n definition: definition as SkillDefinition<TInput, unknown>,\n };\n\n // Run the skill\n const result = await definition.run.call(definition, ctx);\n\n // Validate output if schema provided\n if (definition.output && typeof result !== \"string\") {\n const parsed = definition.output.safeParse(result);\n if (!parsed.success) {\n throw new Error(\n `Invalid output from skill \"${definition.name}\": ${parsed.error.message}`,\n );\n }\n return parsed.data;\n }\n\n return result as TOutput;\n },\n }) as Skill<TInput, TOutput>;\n\n // Register the skill\n registry.set(definition.name, skill as Skill);\n\n return skill;\n}\n\n// ============================================\n// Use Skill\n// ============================================\n\n/**\n * Get a skill by name\n *\n * @example\n * ```ts\n * const sentiment = useSkill(\"sentiment\");\n * const result = await sentiment({ text: \"I love this!\" });\n * ```\n */\nexport function useSkill<TInput = unknown, TOutput = unknown>(\n name: string,\n): Skill<TInput, TOutput> {\n const skill = registry.get(name);\n if (!skill) {\n throw new Error(`Skill not found: \"${name}\". Available: ${listSkills().join(\", \") || \"none\"}`);\n }\n return skill as Skill<TInput, TOutput>;\n}\n\n// ============================================\n// Registry Operations\n// ============================================\n\n/**\n * List all registered skill names\n */\nexport function listSkills(): string[] {\n return Array.from(registry.keys()).sort();\n}\n\n/**\n * Get skill metadata\n */\nexport function getSkillInfo(name: string): SkillInfo | undefined {\n const skill = registry.get(name);\n if (!skill) {\n return;\n }\n\n return {\n name: skill.definition.name,\n description: skill.definition.description,\n version: skill.definition.version,\n author: skill.definition.author,\n builtin: !skillSources.has(name),\n source: skillSources.get(name),\n };\n}\n\n/**\n * Check if a skill exists\n */\nexport function hasSkill(name: string): boolean {\n return registry.has(name);\n}\n\n/**\n * Remove a skill from registry\n */\nexport function removeSkill(name: string): boolean {\n skillSources.delete(name);\n return registry.delete(name);\n}\n\n/**\n * Clear all skills from registry\n */\nexport function clearSkills(): void {\n registry.clear();\n skillSources.clear();\n}\n\n/**\n * Get all skill info\n */\nexport function getAllSkillInfo(): SkillInfo[] {\n return listSkills().map((name) => getSkillInfo(name)!);\n}\n\n/**\n * Check if a name is reserved (cannot be used for custom skills)\n */\nexport function isReservedName(name: string): boolean {\n return RESERVED_NAMES.has(name);\n}\n\n/**\n * Get list of reserved names\n */\nexport function getReservedNames(): string[] {\n return Array.from(RESERVED_NAMES).sort();\n}\n\n// ============================================\n// Internal: Register with source\n// ============================================\n\n/**\n * Register a skill with its source file (used by loader)\n * @internal\n */\nexport function registerSkillWithSource(skill: Skill, source: string): void {\n registry.set(skill.definition.name, skill);\n skillSources.set(skill.definition.name, source);\n}\n","/**\n * Skill Loader\n *\n * Load skills from files, directories, and packages.\n */\n\nimport { pathToFileURL } from \"url\";\nimport { registerSkillWithSource } from \"./registry.js\";\nimport type { LoadSkillsOptions, Skill } from \"./types.js\";\n\n// ============================================\n// Auto-Load Project Skills\n// ============================================\n\n/**\n * Load skills from the project's .gerbil/skills/ directory\n *\n * This is the standard location for project-specific skills.\n * Creates the directory structure if it doesn't exist.\n *\n * @example\n * ```ts\n * // Load from .gerbil/skills/ in current working directory\n * const loaded = await loadProjectSkills();\n * console.log(`Loaded ${loaded.length} project skills`);\n * ```\n */\nexport async function loadProjectSkills(cwd: string = process.cwd()): Promise<string[]> {\n const path = await import(\"path\");\n const fs = await import(\"fs\");\n\n const gerbilDir = path.join(cwd, \".gerbil\");\n const skillsDir = path.join(gerbilDir, \"skills\");\n\n // If .gerbil/skills doesn't exist, that's fine - just return empty\n if (!fs.existsSync(skillsDir)) {\n return [];\n }\n\n return loadSkills(skillsDir);\n}\n\n// ============================================\n// Load from Directory\n// ============================================\n\n/**\n * Load all skills from a directory\n *\n * @example\n * ```ts\n * // Load all *.skill.ts and *.skill.js files\n * const loaded = await loadSkills(\"./skills\");\n * console.log(`Loaded ${loaded.length} skills`);\n * ```\n */\nexport async function loadSkills(dir: string, options: LoadSkillsOptions = {}): Promise<string[]> {\n const { patterns = [\"*.skill.ts\", \"*.skill.js\"] } = options;\n const loaded: string[] = [];\n\n try {\n const fs = await import(\"fs\");\n const path = await import(\"path\");\n\n const resolvedDir = path.resolve(dir);\n\n if (!fs.existsSync(resolvedDir)) {\n throw new Error(`Skills directory not found: ${dir}`);\n }\n\n const files = fs.readdirSync(resolvedDir);\n\n for (const file of files) {\n const matches = patterns.some((pattern) => {\n const regex = new RegExp(`^${pattern.replace(/\\*/g, \".*\").replace(/\\./g, \"\\\\.\")}$`);\n return regex.test(file);\n });\n\n if (matches) {\n const filePath = path.join(resolvedDir, file);\n const skill = await loadSkill(filePath);\n if (skill) {\n loaded.push(skill.definition.name);\n }\n }\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"MODULE_NOT_FOUND\") {\n throw new Error(`Skills directory not found: ${dir}`);\n }\n throw error;\n }\n\n return loaded;\n}\n\n// ============================================\n// Load Single Skill\n// ============================================\n\n/**\n * Load a single skill from a file\n *\n * @example\n * ```ts\n * const skill = await loadSkill(\"./skills/sentiment.skill.ts\");\n * if (skill) {\n * const result = await skill({ text: \"Hello\" });\n * }\n * ```\n */\nexport async function loadSkill(filePath: string): Promise<Skill | null> {\n try {\n const path = await import(\"path\");\n const resolvedPath = path.resolve(filePath);\n\n // Use dynamic import with file URL for ESM compatibility\n const fileUrl = pathToFileURL(resolvedPath).href;\n const module = await import(fileUrl);\n\n // Get the default export\n const skill = module.default as Skill;\n\n if (!skill?.definition) {\n console.warn(`No valid skill found in ${filePath}`);\n return null;\n }\n\n // Register with source tracking\n registerSkillWithSource(skill, resolvedPath);\n\n return skill;\n } catch (error) {\n console.error(`Failed to load skill from ${filePath}:`, error);\n return null;\n }\n}\n\n// ============================================\n// Load from Package\n// ============================================\n\n/**\n * Load skills from an npm package\n *\n * @example\n * ```ts\n * // Load skills from a package\n * const loaded = await loadSkillPackage(\"gerbil-skills-extra\");\n * ```\n */\nexport async function loadSkillPackage(packageName: string): Promise<string[]> {\n try {\n const module = await import(packageName);\n const loaded: string[] = [];\n\n // Look for exported skills\n for (const [_key, value] of Object.entries(module)) {\n if (isSkill(value)) {\n const skill = value as Skill;\n registerSkillWithSource(skill, `npm:${packageName}`);\n loaded.push(skill.definition.name);\n }\n }\n\n // Also check default export if it's an object of skills\n if (module.default && typeof module.default === \"object\") {\n for (const [_key, value] of Object.entries(module.default)) {\n if (isSkill(value)) {\n const skill = value as Skill;\n registerSkillWithSource(skill, `npm:${packageName}`);\n loaded.push(skill.definition.name);\n }\n }\n }\n\n return loaded;\n } catch (error) {\n throw new Error(`Failed to load skill package \"${packageName}\": ${error}`);\n }\n}\n\n// ============================================\n// Helpers\n// ============================================\n\n/**\n * Check if a value is a Skill\n */\nfunction isSkill(value: unknown): value is Skill {\n return (\n typeof value === \"function\" &&\n typeof (value as Skill).definition === \"object\" &&\n typeof (value as Skill).definition.name === \"string\" &&\n typeof (value as Skill).definition.run === \"function\"\n );\n}\n","/**\n * Commit Skill\n *\n * Generate git commit messages from staged changes.\n */\n\nimport { z } from \"zod\";\nimport { defineSkill } from \"../registry.js\";\n\nconst CommitInput = z.object({\n /** Git diff (auto-detected if not provided) */\n diff: z.string().optional(),\n\n /** Commit style */\n type: z.enum([\"conventional\", \"simple\", \"detailed\"]).default(\"conventional\"),\n\n /** Max length for commit message */\n maxLength: z.number().default(72),\n});\n\nexport type CommitInput = z.infer<typeof CommitInput>;\n\nasync function getGitDiff(): Promise<string> {\n try {\n const { execSync } = await import(\"child_process\");\n return execSync(\"git diff --staged\", { encoding: \"utf-8\" });\n } catch {\n return \"\";\n }\n}\n\nfunction getSystemPrompt(type: CommitInput[\"type\"]): string {\n switch (type) {\n case \"conventional\":\n return `Generate a git commit message following the Conventional Commits format.\nUse one of these types: feat, fix, docs, style, refactor, perf, test, chore.\nFormat: type(scope): description\nKeep it under 72 characters.\nNo period at the end.\nOnly output the commit message, nothing else.`;\n\n case \"detailed\":\n return `Generate a detailed git commit message with a subject line and body.\nSubject: under 72 chars, imperative mood\nBody: explain what and why\nOnly output the commit message, nothing else.`;\n\n default:\n return `Generate a concise git commit message.\nUse imperative mood (e.g., \"Add\", \"Fix\", \"Update\").\nKeep it under 72 characters.\nNo period at the end.\nOnly output the commit message, nothing else.`;\n }\n}\n\nexport const commit = defineSkill({\n name: \"commit\",\n description: \"Generate a git commit message from staged changes\",\n version: \"1.0.0\",\n input: CommitInput,\n temperature: 0.3,\n maxTokens: 100,\n\n async run({ input, gerbil }) {\n const { diff, type = \"conventional\", maxLength = 72 } = input;\n\n // Get diff from git if not provided\n const actualDiff = diff || (await getGitDiff());\n\n if (!actualDiff || actualDiff.trim().length === 0) {\n throw new Error(\"No changes staged. Run `git add` first.\");\n }\n\n const result = await gerbil.generate(\n `Generate a commit message for the following diff:\\n\\n${actualDiff}`,\n {\n system: getSystemPrompt(type),\n maxTokens: this.maxTokens,\n temperature: this.temperature,\n },\n );\n\n // Clean and truncate\n let message = result.text.trim();\n message = message.replace(/<think>[\\s\\S]*?<\\/think>/g, \"\").trim(); // Remove think tags\n message = message.replace(/<\\/?think>/g, \"\").trim(); // Remove unclosed tags\n message = message.replace(/^[\"']|[\"']$/g, \"\"); // Remove quotes\n message = message.split(\"\\n\")[0]; // First line only\n if (message.length > maxLength) {\n message = `${message.substring(0, maxLength - 3)}...`;\n }\n\n return message;\n },\n});\n","/**\n * Explain Skill\n *\n * Explain code or concepts at various levels.\n */\n\nimport { z } from \"zod\";\nimport { defineSkill } from \"../registry.js\";\n\nconst ExplainInput = z.object({\n /** Content to explain */\n content: z.string(),\n\n /** Explanation level */\n level: z.enum([\"beginner\", \"intermediate\", \"expert\"]).default(\"intermediate\"),\n\n /** Programming language (for code) */\n language: z.string().optional(),\n});\n\nexport type ExplainInput = z.infer<typeof ExplainInput>;\n\nconst levelGuide = {\n beginner: \"Explain like I'm new to programming. Use simple terms and analogies.\",\n intermediate: \"Explain for someone with programming experience.\",\n expert: \"Explain with technical depth, including implementation details.\",\n};\n\nexport const explain = defineSkill({\n name: \"explain\",\n description: \"Explain code or concepts at various levels\",\n version: \"1.0.0\",\n input: ExplainInput,\n temperature: 0.5,\n maxTokens: 500,\n\n async run({ input, gerbil }) {\n const { content, level = \"intermediate\", language } = input;\n\n let systemPrompt = `You are a patient teacher.\n${levelGuide[level]}`;\n\n if (language) {\n systemPrompt += `\\nThis is ${language} code.`;\n }\n\n systemPrompt += \"\\nBe clear and concise.\";\n\n const result = await gerbil.generate(`Explain this:\\n\\n${content}`, {\n system: systemPrompt,\n maxTokens: this.maxTokens,\n temperature: this.temperature,\n });\n\n return result.text;\n },\n});\n","/**\n * Extract Skill\n *\n * Extract structured data from content.\n */\n\nimport { z } from \"zod\";\nimport { defineSkill } from \"../registry.js\";\n\nconst ExtractInput = z.object({\n /** Content to extract from */\n content: z.string(),\n\n /** Zod schema for extraction (passed at runtime) */\n schema: z.any(),\n\n /** Additional context */\n context: z.string().optional(),\n});\n\nexport type ExtractInput = z.infer<typeof ExtractInput>;\n\nexport const extract = defineSkill({\n name: \"extract\",\n description: \"Extract structured data from content\",\n version: \"1.0.0\",\n input: ExtractInput,\n temperature: 0.3,\n\n async run({ input, gerbil }) {\n const { content, schema, context } = input;\n\n let prompt = \"Extract structured data from the following content.\";\n\n if (context) {\n prompt += `\\nContext: ${context}`;\n }\n\n prompt += `\\n\\nContent:\\n${content}`;\n\n return gerbil.json(prompt, { schema });\n },\n});\n","/**\n * Review Skill\n *\n * Code review with configurable focus areas.\n */\n\nimport { z } from \"zod\";\nimport { defineSkill } from \"../registry.js\";\n\nconst ReviewInput = z.object({\n /** Code to review */\n code: z.string(),\n\n /** Focus areas */\n focus: z.array(z.enum([\"security\", \"performance\", \"style\", \"bugs\", \"all\"])).default([\"all\"]),\n\n /** Output format */\n format: z.enum([\"inline\", \"summary\", \"detailed\"]).default(\"summary\"),\n});\n\nexport type ReviewInput = z.infer<typeof ReviewInput>;\n\nexport const review = defineSkill({\n name: \"review\",\n description: \"Code review with configurable focus areas\",\n version: \"1.0.0\",\n input: ReviewInput,\n temperature: 0.3,\n maxTokens: 600,\n\n async run({ input, gerbil }) {\n const { code, focus = [\"all\"], format = \"summary\" } = input;\n\n let systemPrompt = `You are a senior code reviewer.\nReview the code for:`;\n\n if (focus.includes(\"all\")) {\n systemPrompt +=\n \"\\n- Security vulnerabilities\\n- Performance issues\\n- Code style and readability\\n- Potential bugs\";\n } else {\n if (focus.includes(\"security\")) {\n systemPrompt += \"\\n- Security vulnerabilities\";\n }\n if (focus.includes(\"performance\")) {\n systemPrompt += \"\\n- Performance issues\";\n }\n if (focus.includes(\"style\")) {\n systemPrompt += \"\\n- Code style and readability\";\n }\n if (focus.includes(\"bugs\")) {\n systemPrompt += \"\\n- Potential bugs\";\n }\n }\n\n if (format === \"summary\") {\n systemPrompt += \"\\n\\nProvide a brief summary of issues found.\";\n } else if (format === \"detailed\") {\n systemPrompt += \"\\n\\nProvide detailed feedback with suggestions.\";\n } else {\n systemPrompt += \"\\n\\nProvide inline-style comments.\";\n }\n\n const result = await gerbil.generate(`Review this code:\\n\\n${code}`, {\n system: systemPrompt,\n maxTokens: this.maxTokens,\n temperature: this.temperature,\n });\n\n return result.text;\n },\n});\n","/**\n * Summarize Skill\n *\n * Summarize content in various lengths and formats.\n */\n\nimport { z } from \"zod\";\nimport { defineSkill } from \"../registry.js\";\n\nconst SummarizeInput = z.object({\n /** Content to summarize */\n content: z.string(),\n\n /** Summary length */\n length: z.enum([\"short\", \"medium\", \"long\"]).default(\"medium\"),\n\n /** Output format */\n format: z.enum([\"paragraph\", \"bullets\"]).default(\"paragraph\"),\n\n /** Focus areas */\n focus: z.array(z.string()).optional(),\n});\n\nexport type SummarizeInput = z.infer<typeof SummarizeInput>;\n\nconst lengthGuide = {\n short: \"2-3 sentences\",\n medium: \"1 paragraph (4-6 sentences)\",\n long: \"2-3 paragraphs\",\n};\n\nconst maxTokensGuide = {\n short: 100,\n medium: 200,\n long: 400,\n};\n\nexport const summarize = defineSkill({\n name: \"summarize\",\n description: \"Summarize content in various lengths and formats\",\n version: \"1.0.0\",\n input: SummarizeInput,\n temperature: 0.3,\n\n async run({ input, gerbil }) {\n const { content, length = \"medium\", format = \"paragraph\", focus } = input;\n\n let systemPrompt = `You are a summarization expert.\nSummarize the content in ${lengthGuide[length]}.`;\n\n if (format === \"bullets\") {\n systemPrompt += \"\\nUse bullet points.\";\n }\n\n if (focus && focus.length > 0) {\n systemPrompt += `\\nFocus on: ${focus.join(\", \")}.`;\n }\n\n systemPrompt += \"\\nOnly output the summary, nothing else.\";\n\n const result = await gerbil.generate(`Summarize this:\\n\\n${content}`, {\n system: systemPrompt,\n maxTokens: maxTokensGuide[length],\n temperature: this.temperature,\n });\n\n return result.text;\n },\n});\n","/**\n * Test Skill\n *\n * Generate tests for code.\n */\n\nimport { z } from \"zod\";\nimport { defineSkill } from \"../registry.js\";\n\nconst TestInput = z.object({\n /** Code to test */\n code: z.string(),\n\n /** Test framework */\n framework: z.enum([\"jest\", \"vitest\", \"mocha\", \"playwright\"]).default(\"vitest\"),\n\n /** Test style */\n style: z.enum([\"unit\", \"integration\", \"e2e\"]).default(\"unit\"),\n});\n\nexport type TestInput = z.infer<typeof TestInput>;\n\nexport const test = defineSkill({\n name: \"test\",\n description: \"Generate tests for code\",\n version: \"1.0.0\",\n input: TestInput,\n temperature: 0.3,\n maxTokens: 800,\n\n async run({ input, gerbil }) {\n const { code, framework, style } = input;\n\n const systemPrompt = `You are a test engineer.\nGenerate ${style} tests using ${framework} for the provided code.\nInclude edge cases and error scenarios.\nOnly output the test code, no explanations.`;\n\n const result = await gerbil.generate(`Generate tests for:\\n\\n${code}`, {\n system: systemPrompt,\n maxTokens: this.maxTokens,\n temperature: this.temperature,\n });\n\n return result.text;\n },\n});\n","/**\n * Title Skill\n *\n * Generate titles for content.\n */\n\nimport { z } from \"zod\";\nimport { defineSkill } from \"../registry.js\";\n\nconst TitleInput = z.object({\n /** Content to generate title for */\n content: z.string(),\n\n /** Title style */\n style: z.enum([\"professional\", \"clickbait\", \"seo\", \"simple\"]).default(\"professional\"),\n\n /** Max length */\n maxLength: z.number().default(60),\n});\n\nexport type TitleInput = z.infer<typeof TitleInput>;\n\nconst styleGuide = {\n professional: \"Clear, informative, and professional\",\n clickbait: \"Engaging and curiosity-inducing\",\n seo: \"SEO-optimized with relevant keywords\",\n simple: \"Simple and straightforward\",\n};\n\nexport const title = defineSkill({\n name: \"title\",\n description: \"Generate titles for content\",\n version: \"1.0.0\",\n input: TitleInput,\n temperature: 0.7,\n maxTokens: 30,\n\n async run({ input, gerbil }) {\n const { content, style = \"professional\", maxLength = 60 } = input;\n\n const systemPrompt = `Generate a title for the content.\nStyle: ${styleGuide[style]}\nMax length: ${maxLength} characters\nOnly output the title, nothing else.`;\n\n const result = await gerbil.generate(`Generate a title for:\\n\\n${content.substring(0, 1000)}`, {\n system: systemPrompt,\n maxTokens: this.maxTokens,\n temperature: this.temperature,\n });\n\n let generatedTitle = result.text.trim();\n generatedTitle = generatedTitle.replace(/^[\"']|[\"']$/g, \"\");\n\n if (generatedTitle.length > maxLength) {\n generatedTitle = `${generatedTitle.substring(0, maxLength - 3)}...`;\n }\n\n return generatedTitle;\n },\n});\n","/**\n * Translate Skill\n *\n * Translate text between languages.\n */\n\nimport { z } from \"zod\";\nimport { defineSkill } from \"../registry.js\";\n\nconst TranslateInput = z.object({\n /** Text to translate */\n text: z.string(),\n\n /** Source language (auto-detected if not provided) */\n from: z.string().optional(),\n\n /** Target language */\n to: z.string(),\n\n /** Preserve formatting */\n preserveFormatting: z.boolean().default(true),\n});\n\nexport type TranslateInput = z.infer<typeof TranslateInput>;\n\nexport const translate = defineSkill({\n name: \"translate\",\n description: \"Translate text between languages\",\n version: \"1.0.0\",\n input: TranslateInput,\n temperature: 0.3,\n\n async run({ input, gerbil }) {\n const { text, from, to, preserveFormatting } = input;\n\n let systemPrompt = `You are a professional translator.\nTranslate the text to ${to}.`;\n\n if (from) {\n systemPrompt += `\\nThe source language is ${from}.`;\n }\n\n if (preserveFormatting) {\n systemPrompt += \"\\nPreserve the original formatting (paragraphs, lists, etc.).\";\n }\n\n systemPrompt += \"\\nOnly output the translation, nothing else.\";\n\n const result = await gerbil.generate(`Translate:\\n\\n${text}`, {\n system: systemPrompt,\n maxTokens: Math.ceil(text.length / 2),\n temperature: this.temperature,\n });\n\n return result.text;\n },\n});\n"],"mappings":"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"}
@@ -0,0 +1,567 @@
1
+ import { n as zodToJsonSchema } from "./utils-7vXqtq2Q.mjs";
2
+ import { z } from "zod";
3
+
4
+ //#region src/core/docs.ts
5
+ /**
6
+ * Gerbil Documentation Content
7
+ *
8
+ * Documentation strings used by the gerbil_docs tool
9
+ * for answering questions about Gerbil features.
10
+ */
11
+ const GERBIL_DOCS = {
12
+ quickstart: `Gerbil Quick Start:
13
+ \`\`\`typescript
14
+ import { Gerbil } from "gerbil";
15
+
16
+ const g = new Gerbil();
17
+ await g.loadModel("qwen3-0.6b");
18
+
19
+ // Generate text
20
+ const result = await g.generate("Write a haiku");
21
+ console.log(result.text);
22
+
23
+ // Stream responses
24
+ for await (const chunk of g.stream("Tell me a story")) {
25
+ process.stdout.write(chunk);
26
+ }
27
+ \`\`\``,
28
+ generate: `Generate text with options:
29
+ \`\`\`typescript
30
+ const result = await gerbil.generate(prompt, {
31
+ maxTokens: 256, // Max tokens to generate
32
+ temperature: 0.7, // 0-2, higher = more creative
33
+ topP: 0.9, // Nucleus sampling
34
+ topK: 50, // Top-k sampling
35
+ thinking: false, // Enable reasoning mode (Qwen3)
36
+ system: "You are...", // System prompt
37
+ });
38
+
39
+ // Result contains:
40
+ result.text // Generated text
41
+ result.thinking // Reasoning (if thinking=true)
42
+ result.tokensGenerated
43
+ result.tokensPerSecond
44
+ result.totalTime
45
+ \`\`\``,
46
+ stream: `Streaming responses:
47
+ \`\`\`typescript
48
+ for await (const chunk of gerbil.stream("Hello")) {
49
+ process.stdout.write(chunk);
50
+ }
51
+
52
+ // With options
53
+ const stream = gerbil.stream("Explain React", {
54
+ maxTokens: 500,
55
+ onToken: (token) => console.log(token),
56
+ });
57
+ \`\`\``,
58
+ json: `Structured JSON output with Zod validation:
59
+ \`\`\`typescript
60
+ import { z } from "zod";
61
+
62
+ const PersonSchema = z.object({
63
+ name: z.string(),
64
+ age: z.number(),
65
+ city: z.string(),
66
+ });
67
+
68
+ const data = await gerbil.json("Extract: John is 32 and lives in NYC", {
69
+ schema: PersonSchema,
70
+ retries: 3, // Retry on validation failure
71
+ temperature: 0.3, // Lower = more consistent
72
+ });
73
+ // { name: "John", age: 32, city: "NYC" }
74
+ \`\`\``,
75
+ thinking: `Thinking mode (chain-of-thought reasoning) - Qwen3 models:
76
+ \`\`\`typescript
77
+ const result = await gerbil.generate("What is 127 × 43?", {
78
+ thinking: true,
79
+ });
80
+
81
+ console.log(result.thinking);
82
+ // "Let me calculate step by step: 127 × 43 = 127 × 40 + 127 × 3..."
83
+
84
+ console.log(result.text);
85
+ // "5461"
86
+ \`\`\`
87
+
88
+ Enable in chat with /no_think or /think commands, or enable_thinking parameter.`,
89
+ embed: `Generate embeddings:
90
+ \`\`\`typescript
91
+ // Single text
92
+ const { vector } = await gerbil.embed("Hello world");
93
+ // vector: number[] (384 dimensions by default)
94
+
95
+ // Batch
96
+ const results = await gerbil.embedBatch(["Hello", "World"]);
97
+ \`\`\``,
98
+ models: `Available models:
99
+
100
+ | Model | Size | Best For |
101
+ |-------|------|----------|
102
+ | qwen3-0.6b | ~400MB | General use, reasoning (thinking mode) |
103
+ | qwen2.5-0.5b | ~350MB | Fast and capable |
104
+ | qwen2.5-coder-0.5b | ~400MB | Code generation |
105
+ | smollm2-360m | ~250MB | Very fast, simple tasks |
106
+ | smollm2-135m | ~100MB | Fastest, basic generation |
107
+ | phi-3-mini | ~2.1GB | High quality, larger |
108
+
109
+ Load any HuggingFace model:
110
+ \`\`\`typescript
111
+ await gerbil.loadModel("hf:org/model");
112
+ await gerbil.loadModel("onnx-community/Qwen3-0.6B-ONNX");
113
+ \`\`\``,
114
+ load: `Loading models:
115
+ \`\`\`typescript
116
+ await gerbil.loadModel("qwen3-0.6b", {
117
+ device: "auto", // "auto" | "gpu" | "cpu"
118
+ dtype: "q4", // "q4" | "q8" | "fp16" | "fp32"
119
+ onProgress: (p) => {
120
+ console.log(p.status, p.progress, p.file);
121
+ },
122
+ });
123
+ \`\`\``,
124
+ "ai-sdk": `Vercel AI SDK v5 integration:
125
+ \`\`\`typescript
126
+ import { generateText, streamText } from "ai";
127
+ import { gerbil } from "gerbil/ai";
128
+
129
+ // Generate
130
+ const { text } = await generateText({
131
+ model: gerbil("qwen3-0.6b"),
132
+ prompt: "Write a commit message",
133
+ });
134
+
135
+ // Stream
136
+ const stream = streamText({
137
+ model: gerbil("qwen3-0.6b"),
138
+ prompt: "Explain React hooks",
139
+ });
140
+
141
+ for await (const chunk of stream.textStream) {
142
+ process.stdout.write(chunk);
143
+ }
144
+
145
+ // With thinking mode
146
+ const { text } = await generateText({
147
+ model: gerbil("qwen3-0.6b", { thinking: true }),
148
+ prompt: "What is 127 × 43?",
149
+ });
150
+ \`\`\``,
151
+ next: `Next.js App Router integration:
152
+ \`\`\`typescript
153
+ // app/api/chat/route.ts
154
+ import { gerbil } from "gerbil/next";
155
+
156
+ export const POST = gerbil.handler({
157
+ model: "qwen3-0.6b",
158
+ maxTokens: 500,
159
+ });
160
+ \`\`\``,
161
+ express: `Express.js integration:
162
+ \`\`\`typescript
163
+ import express from "express";
164
+ import { gerbil } from "gerbil/express";
165
+
166
+ const app = express();
167
+ app.use("/ai", gerbil()());
168
+
169
+ // Endpoints created:
170
+ // POST /ai/generate - Generate text
171
+ // POST /ai/stream - Stream text
172
+ // POST /ai/json - Structured output
173
+ // POST /ai/embed - Embeddings
174
+ \`\`\``,
175
+ react: `React hooks:
176
+ \`\`\`typescript
177
+ import { useGerbil, useChat } from "gerbil/react";
178
+
179
+ function Chat() {
180
+ const { generate, isLoading } = useGerbil();
181
+
182
+ const handleSubmit = async (prompt: string) => {
183
+ const result = await generate(prompt);
184
+ console.log(result.text);
185
+ };
186
+ }
187
+ \`\`\``,
188
+ hono: `Hono integration:
189
+ \`\`\`typescript
190
+ import { Hono } from "hono";
191
+ import { gerbil } from "gerbil/hono";
192
+
193
+ const app = new Hono();
194
+ app.route("/ai", await gerbil()());
195
+ \`\`\``,
196
+ langchain: `LangChain integration:
197
+ \`\`\`typescript
198
+ import { GerbilLLM, GerbilEmbeddings } from "gerbil/langchain";
199
+
200
+ const llm = new GerbilLLM({ model: "qwen3-0.6b" });
201
+ const embeddings = new GerbilEmbeddings();
202
+
203
+ // Use with chains
204
+ const chain = new LLMChain({ llm, prompt: template });
205
+ \`\`\``,
206
+ mcp: `MCP Server for Claude Desktop & Cursor:
207
+ \`\`\`bash
208
+ gerbil serve --mcp
209
+ \`\`\`
210
+
211
+ Skills are automatically exposed as MCP tools:
212
+ - gerbil_generate
213
+ - gerbil_commit
214
+ - gerbil_summarize
215
+ - gerbil_explain
216
+ - etc.`,
217
+ skills: `Skills are reusable AI tasks with Zod validation:
218
+ \`\`\`typescript
219
+ import { commit, summarize, explain, review } from "gerbil/skills";
220
+
221
+ // Generate commit message
222
+ const msg = await commit({ type: "conventional", maxLength: 72 });
223
+
224
+ // Summarize content
225
+ const summary = await summarize({
226
+ content: doc,
227
+ length: "short",
228
+ format: "bullets"
229
+ });
230
+
231
+ // Explain code
232
+ const explanation = await explain({
233
+ content: code,
234
+ level: "beginner"
235
+ });
236
+
237
+ // Code review
238
+ const feedback = await review({
239
+ code,
240
+ focus: ["security", "performance"]
241
+ });
242
+ \`\`\`
243
+
244
+ Built-in skills: commit, summarize, explain, review, test, translate, extract, title`,
245
+ "define-skill": `Create custom skills:
246
+ \`\`\`typescript
247
+ import { defineSkill } from "gerbil/skills";
248
+ import { z } from "zod";
249
+
250
+ export const sentiment = defineSkill({
251
+ name: "sentiment",
252
+ description: "Analyze text sentiment",
253
+ input: z.object({
254
+ text: z.string(),
255
+ detailed: z.boolean().default(false)
256
+ }),
257
+ output: z.object({
258
+ sentiment: z.enum(["positive", "negative", "neutral"]),
259
+ confidence: z.number(),
260
+ }),
261
+ temperature: 0.3,
262
+ maxTokens: 100,
263
+
264
+ async run({ input, gerbil }) {
265
+ return gerbil.json(\`Sentiment of: \${input.text}\`, {
266
+ schema: this.output,
267
+ });
268
+ },
269
+ });
270
+ \`\`\``,
271
+ "load-skills": `Load skills from files:
272
+ \`\`\`typescript
273
+ import { loadSkills, useSkill, listSkills } from "gerbil/skills";
274
+
275
+ // Load from directory (*.skill.ts files)
276
+ await loadSkills("./skills");
277
+
278
+ // Use by name
279
+ const skill = useSkill("my-skill");
280
+ const result = await skill({ text: "Hello" });
281
+
282
+ // List all
283
+ console.log(listSkills()); // ["commit", "summarize", ...]
284
+ \`\`\``,
285
+ cli: `CLI commands:
286
+ \`\`\`bash
287
+ gerbil "Write a haiku" # Generate text
288
+ gerbil -m qwen3-0.6b "prompt" # Specify model
289
+ gerbil --thinking "127 × 43" # Enable reasoning
290
+
291
+ gerbil commit # Git commit message
292
+ gerbil summarize README.md # Summarize file
293
+ gerbil explain src/index.ts # Explain code
294
+
295
+ gerbil chat # Interactive chat
296
+ gerbil chat --thinking # With reasoning
297
+
298
+ gerbil serve # HTTP server
299
+ gerbil serve --mcp # MCP server
300
+
301
+ gerbil models # List models
302
+ gerbil cache # Show cached models
303
+ gerbil bench # Benchmark
304
+ gerbil info # System info
305
+
306
+ gerbil repl # Interactive TUI
307
+ \`\`\``,
308
+ tools: `Gerbil supports tool calling with Qwen3 models:
309
+ \`\`\`typescript
310
+ import { defineTool, executeToolCall } from "gerbil";
311
+
312
+ const weatherTool = defineTool({
313
+ name: "get_weather",
314
+ description: "Get current weather for a city",
315
+ parameters: z.object({
316
+ city: z.string(),
317
+ }),
318
+ execute: async ({ city }) => {
319
+ return \`Weather in \${city}: 72°F, sunny\`;
320
+ },
321
+ });
322
+ \`\`\`
323
+
324
+ In the REPL, use Agent mode (Tab → Agent) to enable tools.`
325
+ };
326
+ /**
327
+ * Get all available documentation topics
328
+ */
329
+ function getDocTopics() {
330
+ return Object.keys(GERBIL_DOCS);
331
+ }
332
+ /**
333
+ * Search documentation by topic
334
+ */
335
+ function searchDocs(query) {
336
+ const keyWords = query.toLowerCase().split(/\s+/).filter((w) => w.length > 2);
337
+ for (const [key, content] of Object.entries(GERBIL_DOCS)) {
338
+ const keyNorm = key.replace(/-/g, "");
339
+ for (const word of keyWords) if (keyNorm === word || key === word || keyNorm.includes(word)) return content;
340
+ }
341
+ for (const word of keyWords) for (const [key, content] of Object.entries(GERBIL_DOCS)) if (key.includes(word) || word.includes(key.replace(/-/g, ""))) return content;
342
+ const matches = [];
343
+ for (const [key, content] of Object.entries(GERBIL_DOCS)) for (const word of keyWords) if (content.toLowerCase().includes(word)) {
344
+ matches.push(`## ${key}\n${content}`);
345
+ break;
346
+ }
347
+ if (matches.length > 0) return matches.slice(0, 2).join("\n\n---\n\n");
348
+ return null;
349
+ }
350
+
351
+ //#endregion
352
+ //#region src/core/tools.ts
353
+ /**
354
+ * Tool Calling System for Gerbil
355
+ *
356
+ * Enables LLMs to call functions/tools during generation.
357
+ * Compatible with Qwen3's tool calling format.
358
+ */
359
+ let toolContext = null;
360
+ /**
361
+ * Set the tool context (call this after loading a model)
362
+ */
363
+ function setToolContext(ctx) {
364
+ toolContext = ctx;
365
+ }
366
+ const toolRegistry = /* @__PURE__ */ new Map();
367
+ /**
368
+ * Define a tool
369
+ */
370
+ function defineTool(def) {
371
+ const tool = async (params) => {
372
+ if (def.parameters) {
373
+ const parsed = def.parameters.parse(params);
374
+ return def.execute(parsed, toolContext);
375
+ }
376
+ return def.execute(params, toolContext);
377
+ };
378
+ tool.definition = def;
379
+ toolRegistry.set(def.name, tool);
380
+ return tool;
381
+ }
382
+ /**
383
+ * Get tool by name
384
+ */
385
+ function getTool(name) {
386
+ return toolRegistry.get(name);
387
+ }
388
+ /**
389
+ * Get all tool definitions for prompt injection
390
+ */
391
+ function getToolDefinitions() {
392
+ return Array.from(toolRegistry.values()).map((t) => t.definition);
393
+ }
394
+ /**
395
+ * Load tools from a directory
396
+ * Tools are simple .ts files with a default export config object
397
+ * No module imports - we eval the execute function directly
398
+ */
399
+ async function loadTools(dir) {
400
+ const fs = await import("fs");
401
+ const pathModule = await import("path");
402
+ if (!fs.existsSync(dir)) return [];
403
+ const files = fs.readdirSync(dir).filter((f) => f.endsWith(".tool.ts") || f.endsWith(".tool.js"));
404
+ const results = [];
405
+ for (const file of files) {
406
+ const filePath = pathModule.join(dir, file);
407
+ const toolName = file.replace(/\.tool\.(ts|js)$/, "");
408
+ try {
409
+ const config = parseToolFile(fs.readFileSync(filePath, "utf-8"), toolName);
410
+ if (config) {
411
+ defineTool({
412
+ name: config.name,
413
+ description: config.description,
414
+ execute: async (params, ctx) => {
415
+ const executeFn = config.execute;
416
+ const result = await executeFn(params, ctx);
417
+ return typeof result === "string" ? result : String(result);
418
+ }
419
+ });
420
+ results.push({
421
+ name: config.name,
422
+ loaded: true,
423
+ path: filePath
424
+ });
425
+ } else results.push({
426
+ name: toolName,
427
+ loaded: false,
428
+ error: "Could not parse tool config",
429
+ path: filePath
430
+ });
431
+ } catch (e) {
432
+ const errorMsg = e instanceof Error ? e.message.split("\n")[0] : String(e);
433
+ results.push({
434
+ name: toolName,
435
+ loaded: false,
436
+ error: errorMsg,
437
+ path: filePath
438
+ });
439
+ }
440
+ }
441
+ return results;
442
+ }
443
+ /**
444
+ * Parse a simple tool file and extract the config
445
+ * Expected format:
446
+ * ```
447
+ * export default {
448
+ * name: "tool_name",
449
+ * description: "...",
450
+ * execute: async (params) => { ... }
451
+ * }
452
+ * ```
453
+ */
454
+ function parseToolFile(content, fallbackName) {
455
+ try {
456
+ let cleaned = content.replace(/:\s*\{[^}]+\}/g, "").replace(/:\s*Record<[^>]+>/g, "").replace(/:\s*string\b/g, "").replace(/:\s*number\b/g, "").replace(/:\s*boolean\b/g, "").replace(/:\s*any\b/g, "").replace(/:\s*Promise<[^>]+>/g, "").replace(/export\s+default\s+/, "return ");
457
+ cleaned = cleaned.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
458
+ const config = new Function(cleaned)();
459
+ if (config && typeof config === "object" && config.name && config.execute) return {
460
+ name: config.name || fallbackName,
461
+ description: config.description || "No description",
462
+ execute: config.execute
463
+ };
464
+ return null;
465
+ } catch (e) {
466
+ console.error("Failed to parse tool file:", e);
467
+ return null;
468
+ }
469
+ }
470
+ /**
471
+ * Load tools from project .gerbil/tools directory
472
+ */
473
+ async function loadProjectTools() {
474
+ return loadTools((await import("path")).join(process.cwd(), ".gerbil", "tools"));
475
+ }
476
+ /**
477
+ * Format tools for Qwen3 prompt
478
+ */
479
+ function formatToolsForPrompt(tools) {
480
+ if (tools.length === 0) return "";
481
+ return `You are a helpful assistant with access to tools.
482
+
483
+ # Tools
484
+
485
+ ${tools.map((t) => {
486
+ const params = t.parameters ? zodToJsonSchema(t.parameters) : {
487
+ type: "object",
488
+ properties: {}
489
+ };
490
+ return `## ${t.name}
491
+
492
+ Description: ${t.description}
493
+ Parameters: ${JSON.stringify(params, null, 2)}`;
494
+ }).join("\n\n")}
495
+
496
+ ## How to call tools
497
+
498
+ To call a tool, use this exact format:
499
+ <tool_call>
500
+ {"name": "tool_name", "arguments": {"param": "value"}}
501
+ </tool_call>
502
+
503
+ When the user asks about Gerbil (documentation, features, how to use), call gerbil_docs with a topic like: tools, skills, ai-sdk, next, express, generate, stream, models, cli.
504
+
505
+ For other questions, respond normally without calling tools.`;
506
+ }
507
+ /**
508
+ * Parse tool call from response
509
+ */
510
+ function parseToolCall(response) {
511
+ try {
512
+ const toolCallMatch = response.match(/<tool_call>\s*([\s\S]*?)\s*<\/tool_call>/);
513
+ if (toolCallMatch) {
514
+ const parsed = JSON.parse(toolCallMatch[1]);
515
+ if (parsed.name) return {
516
+ tool: parsed.name,
517
+ params: parsed.arguments || {}
518
+ };
519
+ }
520
+ const nameArgsMatch = response.match(/\{\s*"name"\s*:\s*"([^"]+)"[^}]*"arguments"\s*:\s*(\{[^}]*\})/);
521
+ if (nameArgsMatch) return {
522
+ tool: nameArgsMatch[1],
523
+ params: JSON.parse(nameArgsMatch[2])
524
+ };
525
+ const toolParamsMatch = response.match(/\{\s*"tool"\s*:\s*"([^"]+)"[^}]*"params"\s*:\s*(\{[^}]*\})/);
526
+ if (toolParamsMatch) return {
527
+ tool: toolParamsMatch[1],
528
+ params: JSON.parse(toolParamsMatch[2])
529
+ };
530
+ const simpleMatch = response.match(/\{\s*"(?:tool|name)"\s*:\s*"([^"]+)"/);
531
+ if (simpleMatch) return {
532
+ tool: simpleMatch[1],
533
+ params: {}
534
+ };
535
+ } catch {}
536
+ return null;
537
+ }
538
+ /**
539
+ * Execute a tool call
540
+ */
541
+ async function executeToolCall(toolName, params) {
542
+ const tool = getTool(toolName);
543
+ if (!tool) return `Error: Unknown tool "${toolName}"`;
544
+ try {
545
+ return await tool(params);
546
+ } catch (e) {
547
+ return `Error executing ${toolName}: ${e}`;
548
+ }
549
+ }
550
+ /**
551
+ * Docs tool - searches gerbil documentation
552
+ * Documentation content is in core/docs.ts
553
+ */
554
+ const docsTool = defineTool({
555
+ name: "gerbil_docs",
556
+ description: "Search Gerbil documentation for information about features, API, integrations, skills, and usage examples",
557
+ parameters: z.object({ query: z.string().optional().default("quickstart").describe("Topic: quickstart, generate, stream, json, thinking, embed, models, ai-sdk, next, express, react, skills, define-skill, cli, tools") }),
558
+ execute: async ({ query = "quickstart" }) => {
559
+ const result = searchDocs(query);
560
+ if (result) return result;
561
+ return `No documentation found for "${query}". Available topics: ${getDocTopics().join(", ")}`;
562
+ }
563
+ });
564
+
565
+ //#endregion
566
+ export { getToolDefinitions as a, setToolContext as c, getTool as i, executeToolCall as n, loadProjectTools as o, formatToolsForPrompt as r, parseToolCall as s, defineTool as t };
567
+ //# sourceMappingURL=tools-BsiEE6f2.mjs.map