@morphllm/morphsdk 0.2.146 → 0.2.148

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 (205) hide show
  1. package/dist/{chunk-FYO46OT6.js → chunk-33CVSDM6.js} +2 -2
  2. package/dist/{chunk-SJYAKVSS.js → chunk-44WJK4MN.js} +2 -2
  3. package/dist/{chunk-SJYAKVSS.js.map → chunk-44WJK4MN.js.map} +1 -1
  4. package/dist/{chunk-GJUB3ECP.js → chunk-4FLNLA2D.js} +2 -2
  5. package/dist/{chunk-E4YKEKGW.js → chunk-4K36ATXI.js} +2 -2
  6. package/dist/{chunk-V73GO5AJ.js → chunk-4ZA4INTU.js} +2 -2
  7. package/dist/{chunk-T564HFSH.js → chunk-5R5FVUAL.js} +1 -1
  8. package/dist/{chunk-FBOJJ3UY.js → chunk-6MVJ5J6H.js} +17 -17
  9. package/dist/{chunk-UVNENJ6H.js → chunk-7PZKCKIH.js} +3 -3
  10. package/dist/{chunk-NF2QWJDY.js → chunk-B3AKP3RA.js} +31 -2
  11. package/dist/chunk-B3AKP3RA.js.map +1 -0
  12. package/dist/chunk-CMSHXALI.js +60 -0
  13. package/dist/chunk-CMSHXALI.js.map +1 -0
  14. package/dist/{chunk-I7SFRYTX.js → chunk-DMYFFSLS.js} +2 -2
  15. package/dist/{chunk-Q36MNOFA.js → chunk-E5K4VHMA.js} +2 -2
  16. package/dist/{chunk-OV57JBMB.js → chunk-EGUJNHMV.js} +2 -2
  17. package/dist/{chunk-E45FW5EK.js → chunk-ELU34VFH.js} +2 -2
  18. package/dist/{chunk-BDHKL3MT.js → chunk-F6OUFO25.js} +2 -2
  19. package/dist/{chunk-QRSWXP4K.js → chunk-H6TH3F4V.js} +2 -2
  20. package/dist/{chunk-FIVYDIHX.js → chunk-HYRHI2UL.js} +1 -1
  21. package/dist/{chunk-DKODF3YG.js → chunk-I3J46TSB.js} +5 -4
  22. package/dist/chunk-I3J46TSB.js.map +1 -0
  23. package/dist/{chunk-J2HIK4GB.js → chunk-IL7OLRJP.js} +2 -2
  24. package/dist/{chunk-JSWNBCGS.js → chunk-LJM3R7UZ.js} +2 -2
  25. package/dist/{chunk-NKUSUSVI.js → chunk-N67TYW2Z.js} +3 -3
  26. package/dist/chunk-OBXWT7NJ.js +401 -0
  27. package/dist/chunk-OBXWT7NJ.js.map +1 -0
  28. package/dist/{chunk-MMBQKN4G.js → chunk-OHYA6SUF.js} +2 -2
  29. package/dist/{chunk-EU7OLX4Z.js → chunk-RH2JB76E.js} +2 -2
  30. package/dist/{chunk-KYKRRF7E.js → chunk-SID7EXWK.js} +2 -2
  31. package/dist/{chunk-YIETFYCL.js → chunk-T7HF2TDQ.js} +75 -48
  32. package/dist/chunk-T7HF2TDQ.js.map +1 -0
  33. package/dist/{chunk-VZ6VYRQB.js → chunk-TSUTRT4Q.js} +2 -2
  34. package/dist/{chunk-UYPWKQKV.js → chunk-TVUYMM4J.js} +2 -2
  35. package/dist/{chunk-HZOTLGJH.js → chunk-XNBQJSLI.js} +42 -2
  36. package/dist/chunk-XNBQJSLI.js.map +1 -0
  37. package/dist/{chunk-BIQ7234U.js → chunk-XT7JQAXV.js} +2 -2
  38. package/dist/{chunk-4PBUB77N.js → chunk-YWJHOYEM.js} +2 -2
  39. package/dist/client.cjs +439 -446
  40. package/dist/client.cjs.map +1 -1
  41. package/dist/client.js +26 -27
  42. package/dist/edge.cjs +1 -1
  43. package/dist/edge.cjs.map +1 -1
  44. package/dist/edge.js +4 -4
  45. package/dist/{finish-DBKuo8yj.d.ts → finish-Ddj1MPGt.d.ts} +1 -1
  46. package/dist/index.cjs +458 -446
  47. package/dist/index.cjs.map +1 -1
  48. package/dist/index.js +29 -29
  49. package/dist/modelrouter/core.cjs +1 -1
  50. package/dist/modelrouter/core.cjs.map +1 -1
  51. package/dist/modelrouter/core.js +3 -3
  52. package/dist/modelrouter/index.cjs +1 -1
  53. package/dist/modelrouter/index.cjs.map +1 -1
  54. package/dist/modelrouter/index.js +3 -3
  55. package/dist/subagents/anthropic.cjs +435 -442
  56. package/dist/subagents/anthropic.cjs.map +1 -1
  57. package/dist/subagents/anthropic.js +8 -9
  58. package/dist/subagents/vercel.cjs +435 -442
  59. package/dist/subagents/vercel.cjs.map +1 -1
  60. package/dist/subagents/vercel.js +8 -9
  61. package/dist/tools/browser/anthropic.cjs +1 -1
  62. package/dist/tools/browser/anthropic.cjs.map +1 -1
  63. package/dist/tools/browser/anthropic.js +5 -5
  64. package/dist/tools/browser/core.cjs +1 -1
  65. package/dist/tools/browser/core.cjs.map +1 -1
  66. package/dist/tools/browser/core.js +4 -4
  67. package/dist/tools/browser/index.cjs +1 -1
  68. package/dist/tools/browser/index.cjs.map +1 -1
  69. package/dist/tools/browser/index.js +7 -7
  70. package/dist/tools/browser/openai.cjs +1 -1
  71. package/dist/tools/browser/openai.cjs.map +1 -1
  72. package/dist/tools/browser/openai.js +5 -5
  73. package/dist/tools/browser/profiles/core.cjs +1 -1
  74. package/dist/tools/browser/profiles/core.cjs.map +1 -1
  75. package/dist/tools/browser/profiles/core.js +3 -3
  76. package/dist/tools/browser/profiles/index.cjs +1 -1
  77. package/dist/tools/browser/profiles/index.cjs.map +1 -1
  78. package/dist/tools/browser/profiles/index.js +3 -3
  79. package/dist/tools/browser/vercel.cjs +1 -1
  80. package/dist/tools/browser/vercel.cjs.map +1 -1
  81. package/dist/tools/browser/vercel.js +5 -5
  82. package/dist/tools/codebase_search/anthropic.cjs +1 -1
  83. package/dist/tools/codebase_search/anthropic.cjs.map +1 -1
  84. package/dist/tools/codebase_search/anthropic.js +4 -4
  85. package/dist/tools/codebase_search/core.cjs +1 -1
  86. package/dist/tools/codebase_search/core.cjs.map +1 -1
  87. package/dist/tools/codebase_search/core.js +3 -3
  88. package/dist/tools/codebase_search/index.cjs +1 -1
  89. package/dist/tools/codebase_search/index.cjs.map +1 -1
  90. package/dist/tools/codebase_search/index.js +6 -6
  91. package/dist/tools/codebase_search/openai.cjs +1 -1
  92. package/dist/tools/codebase_search/openai.cjs.map +1 -1
  93. package/dist/tools/codebase_search/openai.js +4 -4
  94. package/dist/tools/codebase_search/vercel.cjs +1 -1
  95. package/dist/tools/codebase_search/vercel.cjs.map +1 -1
  96. package/dist/tools/codebase_search/vercel.js +4 -4
  97. package/dist/tools/fastapply/anthropic.cjs +1 -1
  98. package/dist/tools/fastapply/anthropic.cjs.map +1 -1
  99. package/dist/tools/fastapply/anthropic.js +4 -4
  100. package/dist/tools/fastapply/apply.cjs +1 -1
  101. package/dist/tools/fastapply/apply.cjs.map +1 -1
  102. package/dist/tools/fastapply/apply.js +2 -2
  103. package/dist/tools/fastapply/core.cjs +1 -1
  104. package/dist/tools/fastapply/core.cjs.map +1 -1
  105. package/dist/tools/fastapply/core.js +3 -3
  106. package/dist/tools/fastapply/index.cjs +1 -1
  107. package/dist/tools/fastapply/index.cjs.map +1 -1
  108. package/dist/tools/fastapply/index.js +6 -6
  109. package/dist/tools/fastapply/openai.cjs +1 -1
  110. package/dist/tools/fastapply/openai.cjs.map +1 -1
  111. package/dist/tools/fastapply/openai.js +4 -4
  112. package/dist/tools/fastapply/vercel.cjs +1 -1
  113. package/dist/tools/fastapply/vercel.cjs.map +1 -1
  114. package/dist/tools/fastapply/vercel.js +4 -4
  115. package/dist/tools/index.cjs +1 -1
  116. package/dist/tools/index.cjs.map +1 -1
  117. package/dist/tools/index.js +6 -6
  118. package/dist/tools/utils/resilience.cjs +1 -1
  119. package/dist/tools/utils/resilience.cjs.map +1 -1
  120. package/dist/tools/utils/resilience.js +2 -2
  121. package/dist/tools/warp_grep/agent/config.cjs +4 -3
  122. package/dist/tools/warp_grep/agent/config.cjs.map +1 -1
  123. package/dist/tools/warp_grep/agent/config.d.ts +2 -1
  124. package/dist/tools/warp_grep/agent/config.js +1 -1
  125. package/dist/tools/warp_grep/agent/parser.cjs +52 -121
  126. package/dist/tools/warp_grep/agent/parser.cjs.map +1 -1
  127. package/dist/tools/warp_grep/agent/parser.d.ts +12 -5
  128. package/dist/tools/warp_grep/agent/parser.js +7 -3
  129. package/dist/tools/warp_grep/agent/runner.cjs +348 -424
  130. package/dist/tools/warp_grep/agent/runner.cjs.map +1 -1
  131. package/dist/tools/warp_grep/agent/runner.d.ts +6 -3
  132. package/dist/tools/warp_grep/agent/runner.js +5 -6
  133. package/dist/tools/warp_grep/agent/types.cjs.map +1 -1
  134. package/dist/tools/warp_grep/agent/types.d.ts +22 -3
  135. package/dist/tools/warp_grep/anthropic.cjs +435 -442
  136. package/dist/tools/warp_grep/anthropic.cjs.map +1 -1
  137. package/dist/tools/warp_grep/anthropic.js +8 -9
  138. package/dist/tools/warp_grep/client.cjs +435 -442
  139. package/dist/tools/warp_grep/client.cjs.map +1 -1
  140. package/dist/tools/warp_grep/client.js +7 -8
  141. package/dist/tools/warp_grep/gemini.cjs +435 -442
  142. package/dist/tools/warp_grep/gemini.cjs.map +1 -1
  143. package/dist/tools/warp_grep/gemini.js +7 -8
  144. package/dist/tools/warp_grep/gemini.js.map +1 -1
  145. package/dist/tools/warp_grep/harness.cjs +168 -180
  146. package/dist/tools/warp_grep/harness.cjs.map +1 -1
  147. package/dist/tools/warp_grep/harness.d.ts +17 -38
  148. package/dist/tools/warp_grep/harness.js +15 -14
  149. package/dist/tools/warp_grep/harness.js.map +1 -1
  150. package/dist/tools/warp_grep/index.cjs +454 -442
  151. package/dist/tools/warp_grep/index.cjs.map +1 -1
  152. package/dist/tools/warp_grep/index.d.ts +1 -1
  153. package/dist/tools/warp_grep/index.js +10 -10
  154. package/dist/tools/warp_grep/openai.cjs +435 -442
  155. package/dist/tools/warp_grep/openai.cjs.map +1 -1
  156. package/dist/tools/warp_grep/openai.js +8 -9
  157. package/dist/tools/warp_grep/providers/local.cjs +43 -2
  158. package/dist/tools/warp_grep/providers/local.cjs.map +1 -1
  159. package/dist/tools/warp_grep/providers/local.d.ts +5 -1
  160. package/dist/tools/warp_grep/providers/local.js +2 -2
  161. package/dist/tools/warp_grep/providers/remote.cjs +32 -2
  162. package/dist/tools/warp_grep/providers/remote.cjs.map +1 -1
  163. package/dist/tools/warp_grep/providers/remote.d.ts +9 -1
  164. package/dist/tools/warp_grep/providers/remote.js +2 -2
  165. package/dist/tools/warp_grep/providers/types.cjs.map +1 -1
  166. package/dist/tools/warp_grep/providers/types.d.ts +14 -1
  167. package/dist/tools/warp_grep/vercel.cjs +435 -442
  168. package/dist/tools/warp_grep/vercel.cjs.map +1 -1
  169. package/dist/tools/warp_grep/vercel.js +8 -9
  170. package/dist/version.cjs +1 -1
  171. package/dist/version.cjs.map +1 -1
  172. package/dist/version.js +1 -1
  173. package/package.json +1 -1
  174. package/dist/chunk-DKODF3YG.js.map +0 -1
  175. package/dist/chunk-EUHNJMWL.js +0 -409
  176. package/dist/chunk-EUHNJMWL.js.map +0 -1
  177. package/dist/chunk-HZOTLGJH.js.map +0 -1
  178. package/dist/chunk-NF2QWJDY.js.map +0 -1
  179. package/dist/chunk-VCKJ22DX.js +0 -131
  180. package/dist/chunk-VCKJ22DX.js.map +0 -1
  181. package/dist/chunk-YIETFYCL.js.map +0 -1
  182. /package/dist/{chunk-FYO46OT6.js.map → chunk-33CVSDM6.js.map} +0 -0
  183. /package/dist/{chunk-GJUB3ECP.js.map → chunk-4FLNLA2D.js.map} +0 -0
  184. /package/dist/{chunk-E4YKEKGW.js.map → chunk-4K36ATXI.js.map} +0 -0
  185. /package/dist/{chunk-V73GO5AJ.js.map → chunk-4ZA4INTU.js.map} +0 -0
  186. /package/dist/{chunk-T564HFSH.js.map → chunk-5R5FVUAL.js.map} +0 -0
  187. /package/dist/{chunk-FBOJJ3UY.js.map → chunk-6MVJ5J6H.js.map} +0 -0
  188. /package/dist/{chunk-UVNENJ6H.js.map → chunk-7PZKCKIH.js.map} +0 -0
  189. /package/dist/{chunk-I7SFRYTX.js.map → chunk-DMYFFSLS.js.map} +0 -0
  190. /package/dist/{chunk-Q36MNOFA.js.map → chunk-E5K4VHMA.js.map} +0 -0
  191. /package/dist/{chunk-OV57JBMB.js.map → chunk-EGUJNHMV.js.map} +0 -0
  192. /package/dist/{chunk-E45FW5EK.js.map → chunk-ELU34VFH.js.map} +0 -0
  193. /package/dist/{chunk-BDHKL3MT.js.map → chunk-F6OUFO25.js.map} +0 -0
  194. /package/dist/{chunk-QRSWXP4K.js.map → chunk-H6TH3F4V.js.map} +0 -0
  195. /package/dist/{chunk-FIVYDIHX.js.map → chunk-HYRHI2UL.js.map} +0 -0
  196. /package/dist/{chunk-J2HIK4GB.js.map → chunk-IL7OLRJP.js.map} +0 -0
  197. /package/dist/{chunk-JSWNBCGS.js.map → chunk-LJM3R7UZ.js.map} +0 -0
  198. /package/dist/{chunk-NKUSUSVI.js.map → chunk-N67TYW2Z.js.map} +0 -0
  199. /package/dist/{chunk-MMBQKN4G.js.map → chunk-OHYA6SUF.js.map} +0 -0
  200. /package/dist/{chunk-EU7OLX4Z.js.map → chunk-RH2JB76E.js.map} +0 -0
  201. /package/dist/{chunk-KYKRRF7E.js.map → chunk-SID7EXWK.js.map} +0 -0
  202. /package/dist/{chunk-VZ6VYRQB.js.map → chunk-TSUTRT4Q.js.map} +0 -0
  203. /package/dist/{chunk-UYPWKQKV.js.map → chunk-TVUYMM4J.js.map} +0 -0
  204. /package/dist/{chunk-BIQ7234U.js.map → chunk-XT7JQAXV.js.map} +0 -0
  205. /package/dist/{chunk-4PBUB77N.js.map → chunk-YWJHOYEM.js.map} +0 -0
@@ -12,16 +12,15 @@ import {
12
12
  executeToolCall,
13
13
  formatGitHubReadFileResult,
14
14
  formatResult
15
- } from "../../chunk-NKUSUSVI.js";
15
+ } from "../../chunk-N67TYW2Z.js";
16
16
  import "../../chunk-63VHBANJ.js";
17
- import "../../chunk-EUHNJMWL.js";
17
+ import "../../chunk-OBXWT7NJ.js";
18
18
  import "../../chunk-GVGJIXV2.js";
19
- import "../../chunk-NF2QWJDY.js";
20
- import "../../chunk-YIETFYCL.js";
21
- import "../../chunk-QRXG5CAZ.js";
22
- import "../../chunk-VCKJ22DX.js";
23
- import "../../chunk-DKODF3YG.js";
24
- import "../../chunk-SJYAKVSS.js";
19
+ import "../../chunk-B3AKP3RA.js";
20
+ import "../../chunk-T7HF2TDQ.js";
21
+ import "../../chunk-CMSHXALI.js";
22
+ import "../../chunk-I3J46TSB.js";
23
+ import "../../chunk-44WJK4MN.js";
25
24
  import "../../chunk-PZ5AY32C.js";
26
25
 
27
26
  // tools/warp_grep/gemini.ts
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../tools/warp_grep/gemini.ts"],"sourcesContent":["/**\n * Google Gemini SDK adapter for morph-warp-grep tool\n * \n * Requires @google/generative-ai as a peer dependency.\n * Install with: npm install @google/generative-ai\n */\n\nimport type { FunctionDeclaration, FunctionDeclarationSchema } from '@google/generative-ai';\nimport { executeToolCall, formatResult, WarpGrepClient, executeGitHubReadFile, formatGitHubReadFileResult } from './client.js';\nimport { WARP_GREP_DESCRIPTION, WARP_GREP_TOOL_NAME, GITHUB_SEARCH_TOOL_NAME, GITHUB_SEARCH_DESCRIPTION, GITHUB_READ_FILE_TOOL_NAME, GITHUB_READ_FILE_DESCRIPTION, GITHUB_READ_FILE_INPUT_SCHEMA } from './prompts.js';\nimport type { WarpGrepToolConfig, WarpGrepResult, GitHubSearchToolConfig, GitHubReadFileInput, GitHubReadFileResult, GitHubReadFileToolConfig } from './types.js';\n\n// Use plain object to avoid runtime import of SchemaType enum\nconst TOOL_PARAMETERS = {\n type: 'OBJECT',\n properties: {\n search_term: { \n type: 'STRING', \n description: 'Search problem statement that this subagent is supposed to research for' \n },\n },\n required: ['search_term'],\n} as unknown as FunctionDeclarationSchema;\n\n/**\n * Gemini-native warp grep function declaration\n * \n * @example\n * ```typescript\n * import { GoogleGenerativeAI } from '@google/generative-ai';\n * import { warpGrepFunctionDeclaration, execute } from '@morphllm/morphsdk/tools/warp-grep/gemini';\n * \n * const genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY);\n * const model = genAI.getGenerativeModel({\n * model: 'gemini-2.0-flash',\n * tools: [{ functionDeclarations: [warpGrepFunctionDeclaration] }]\n * });\n * \n * const chat = model.startChat();\n * const result = await chat.sendMessage('Find authentication middleware');\n * \n * // Handle function call\n * const call = result.response.functionCalls()?.[0];\n * if (call) {\n * const searchResult = await execute(call.args, { repoRoot: '.' });\n * console.log(searchResult);\n * }\n * ```\n */\nexport const warpGrepFunctionDeclaration: FunctionDeclaration = {\n name: WARP_GREP_TOOL_NAME,\n description: WARP_GREP_DESCRIPTION,\n parameters: TOOL_PARAMETERS,\n};\n\n/**\n * Execute warp grep search\n * \n * @param input - Tool input with search_term\n * @param config - Configuration with repoRoot and optional provider\n * @returns Search results\n */\nexport async function execute(\n input: { search_term: string } | string,\n config: WarpGrepToolConfig\n): Promise<WarpGrepResult> {\n return executeToolCall(input, config);\n}\n\nexport { formatResult };\n\n/**\n * Gemini tool with execute method attached\n */\nexport interface GeminiWarpGrepTool extends FunctionDeclaration {\n execute: (input: unknown) => Promise<WarpGrepResult>;\n formatResult: (result: WarpGrepResult) => string;\n}\n\n/**\n * Create a custom warp grep tool with configuration and methods\n * \n * @param config - Configuration options\n * @returns Function declaration with execute and formatResult methods\n * \n * @example Local usage\n * ```typescript\n * import { GoogleGenerativeAI } from '@google/generative-ai';\n * import { createMorphWarpGrepTool } from '@morphllm/morphsdk/tools/warp-grep/gemini';\n * \n * const tool = createMorphWarpGrepTool({ repoRoot: '.' });\n * \n * const genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY);\n * const model = genAI.getGenerativeModel({\n * model: 'gemini-2.0-flash',\n * tools: [{ functionDeclarations: [tool] }]\n * });\n * \n * const chat = model.startChat();\n * const result = await chat.sendMessage('Find authentication middleware');\n * \n * // Handle function call\n * const call = result.response.functionCalls()?.[0];\n * if (call && call.name === tool.name) {\n * const searchResult = await tool.execute(call.args);\n * console.log(tool.formatResult(searchResult));\n * \n * // Send result back to model\n * await chat.sendMessage([{\n * functionResponse: {\n * name: call.name,\n * response: { result: tool.formatResult(searchResult) }\n * }\n * }]);\n * }\n * ```\n * \n * @example Remote sandbox (E2B, Modal, etc.)\n * ```typescript\n * const tool = createMorphWarpGrepTool({\n * repoRoot: '/home/repo',\n * remoteCommands: {\n * grep: async (pattern, path) => (await sandbox.run(`rg '${pattern}' '${path}'`)).stdout,\n * read: async (path, start, end) => (await sandbox.run(`sed -n '${start},${end}p' '${path}'`)).stdout,\n * listDir: async (path, maxDepth) => (await sandbox.run(`find '${path}' -maxdepth ${maxDepth}`)).stdout,\n * },\n * });\n * ```\n */\nexport function createWarpGrepTool(config: WarpGrepToolConfig): GeminiWarpGrepTool {\n const declaration: FunctionDeclaration = {\n name: config.name ?? WARP_GREP_TOOL_NAME,\n description: config.description ?? WARP_GREP_DESCRIPTION,\n parameters: TOOL_PARAMETERS,\n };\n\n return Object.assign(declaration, {\n execute: async (input: unknown): Promise<WarpGrepResult> => {\n return executeToolCall(input as { search_term: string } | string, config);\n },\n formatResult: (result: WarpGrepResult): string => {\n return formatResult(result);\n },\n });\n}\n\n// Legacy alias for backwards compatibility\nexport const createMorphWarpGrepTool = createWarpGrepTool;\n\nconst GITHUB_SEARCH_PARAMETERS = {\n type: 'OBJECT',\n properties: {\n search_term: { type: 'STRING', description: 'Search problem statement that this subagent is supposed to research for' },\n github_url: { type: 'STRING', description: 'GitHub repository URL to search (e.g. \"https://github.com/vercel/next.js\"). You must provide either github_url or owner_repo.' },\n owner_repo: { type: 'STRING', description: 'Repository owner/repo shorthand (e.g. \"vercel/next.js\"). You must provide either github_url or owner_repo.' },\n branch: { type: 'STRING', description: 'Branch to search (defaults to repo default branch)' },\n },\n required: ['search_term'],\n} as unknown as FunctionDeclarationSchema;\n\n/**\n * Create a GitHub search tool for Google Gemini SDK\n *\n * @param config - Configuration options (morphApiKey, morphApiUrl, codeSearchUrl, timeout)\n * @returns Gemini FunctionDeclaration with execute and formatResult methods\n *\n * @example\n * ```typescript\n * import { GoogleGenerativeAI } from '@google/generative-ai';\n * import { createGitHubSearchTool } from '@morphllm/morphsdk/tools/warp-grep/gemini';\n *\n * const tool = createGitHubSearchTool({ morphApiKey: process.env.MORPH_API_KEY });\n *\n * const genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY);\n * const model = genAI.getGenerativeModel({\n * model: 'gemini-2.0-flash',\n * tools: [{ functionDeclarations: [tool] }]\n * });\n *\n * // Execute\n * const result = await tool.execute({ search_term: 'auth middleware', github_url: 'https://github.com/vercel/next.js' });\n * console.log(tool.formatResult(result));\n * ```\n */\nexport function createGitHubSearchTool(config: GitHubSearchToolConfig) {\n const client = new WarpGrepClient(config);\n\n const declaration: FunctionDeclaration = {\n name: GITHUB_SEARCH_TOOL_NAME,\n description: GITHUB_SEARCH_DESCRIPTION,\n parameters: GITHUB_SEARCH_PARAMETERS,\n };\n\n return Object.assign(declaration, {\n execute: async (input: { search_term: string; github_url?: string; owner_repo?: string; branch?: string }): Promise<WarpGrepResult> => {\n const github = input.github_url || input.owner_repo;\n if (!github) {\n throw new Error('Please provide github search url or owner/repo id');\n }\n return client.searchGitHub({ searchTerm: input.search_term, github, branch: input.branch });\n },\n formatResult: (result: WarpGrepResult): string => {\n return formatResult(result);\n },\n });\n}\n\nconst GITHUB_READ_FILE_PARAMETERS = {\n type: 'OBJECT',\n properties: {\n github: { type: 'STRING', description: 'owner/repo shorthand (e.g., \"vercel/next.js\")' },\n path: { type: 'STRING', description: 'File path within the repository' },\n startLine: { type: 'NUMBER', description: 'Start line number (1-based)' },\n endLine: { type: 'NUMBER', description: 'End line number (1-based, inclusive)' },\n branch: { type: 'STRING', description: 'Branch to read from (defaults to repo default branch)' },\n },\n required: ['github', 'path'],\n} as unknown as FunctionDeclarationSchema;\n\n/**\n * Create a GitHub read file tool for Google Gemini SDK\n *\n * @param config - Optional configuration (timeout)\n * @returns Gemini FunctionDeclaration with execute and formatResult methods\n *\n * @example\n * ```typescript\n * import { GoogleGenerativeAI } from '@google/generative-ai';\n * import { createGitHubReadFileTool } from '@morphllm/morphsdk/tools/warp-grep/gemini';\n *\n * const tool = createGitHubReadFileTool();\n *\n * const genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY);\n * const model = genAI.getGenerativeModel({\n * model: 'gemini-2.0-flash',\n * tools: [{ functionDeclarations: [tool] }]\n * });\n *\n * const result = await tool.execute({ github: 'vercel/next.js', path: 'package.json' });\n * console.log(tool.formatResult(result));\n * ```\n */\nexport function createGitHubReadFileTool(config?: GitHubReadFileToolConfig) {\n const declaration: FunctionDeclaration = {\n name: GITHUB_READ_FILE_TOOL_NAME,\n description: GITHUB_READ_FILE_DESCRIPTION,\n parameters: GITHUB_READ_FILE_PARAMETERS,\n };\n\n return Object.assign(declaration, {\n execute: async (input: GitHubReadFileInput): Promise<GitHubReadFileResult> => {\n return executeGitHubReadFile(input, config);\n },\n formatResult: (result: GitHubReadFileResult): string => {\n return formatGitHubReadFileResult(result);\n },\n });\n}\n\nexport default warpGrepFunctionDeclaration;\n\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAaA,IAAM,kBAAkB;AAAA,EACtB,MAAM;AAAA,EACN,YAAY;AAAA,IACV,aAAa;AAAA,MACX,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,UAAU,CAAC,aAAa;AAC1B;AA2BO,IAAM,8BAAmD;AAAA,EAC9D,MAAM;AAAA,EACN,aAAa;AAAA,EACb,YAAY;AACd;AASA,eAAsB,QACpB,OACA,QACyB;AACzB,SAAO,gBAAgB,OAAO,MAAM;AACtC;AA8DO,SAAS,mBAAmB,QAAgD;AACjF,QAAM,cAAmC;AAAA,IACvC,MAAM,OAAO,QAAQ;AAAA,IACrB,aAAa,OAAO,eAAe;AAAA,IACnC,YAAY;AAAA,EACd;AAEA,SAAO,OAAO,OAAO,aAAa;AAAA,IAChC,SAAS,OAAO,UAA4C;AAC1D,aAAO,gBAAgB,OAA2C,MAAM;AAAA,IAC1E;AAAA,IACA,cAAc,CAAC,WAAmC;AAChD,aAAO,aAAa,MAAM;AAAA,IAC5B;AAAA,EACF,CAAC;AACH;AAGO,IAAM,0BAA0B;AAEvC,IAAM,2BAA2B;AAAA,EAC/B,MAAM;AAAA,EACN,YAAY;AAAA,IACV,aAAa,EAAE,MAAM,UAAU,aAAa,0EAA0E;AAAA,IACtH,YAAY,EAAE,MAAM,UAAU,aAAa,gIAAgI;AAAA,IAC3K,YAAY,EAAE,MAAM,UAAU,aAAa,6GAA6G;AAAA,IACxJ,QAAQ,EAAE,MAAM,UAAU,aAAa,qDAAqD;AAAA,EAC9F;AAAA,EACA,UAAU,CAAC,aAAa;AAC1B;AA0BO,SAAS,uBAAuB,QAAgC;AACrE,QAAM,SAAS,IAAI,eAAe,MAAM;AAExC,QAAM,cAAmC;AAAA,IACvC,MAAM;AAAA,IACN,aAAa;AAAA,IACb,YAAY;AAAA,EACd;AAEA,SAAO,OAAO,OAAO,aAAa;AAAA,IAChC,SAAS,OAAO,UAAuH;AACrI,YAAM,SAAS,MAAM,cAAc,MAAM;AACzC,UAAI,CAAC,QAAQ;AACX,cAAM,IAAI,MAAM,mDAAmD;AAAA,MACrE;AACA,aAAO,OAAO,aAAa,EAAE,YAAY,MAAM,aAAa,QAAQ,QAAQ,MAAM,OAAO,CAAC;AAAA,IAC5F;AAAA,IACA,cAAc,CAAC,WAAmC;AAChD,aAAO,aAAa,MAAM;AAAA,IAC5B;AAAA,EACF,CAAC;AACH;AAEA,IAAM,8BAA8B;AAAA,EAClC,MAAM;AAAA,EACN,YAAY;AAAA,IACV,QAAQ,EAAE,MAAM,UAAU,aAAa,gDAAgD;AAAA,IACvF,MAAM,EAAE,MAAM,UAAU,aAAa,kCAAkC;AAAA,IACvE,WAAW,EAAE,MAAM,UAAU,aAAa,8BAA8B;AAAA,IACxE,SAAS,EAAE,MAAM,UAAU,aAAa,uCAAuC;AAAA,IAC/E,QAAQ,EAAE,MAAM,UAAU,aAAa,wDAAwD;AAAA,EACjG;AAAA,EACA,UAAU,CAAC,UAAU,MAAM;AAC7B;AAyBO,SAAS,yBAAyB,QAAmC;AAC1E,QAAM,cAAmC;AAAA,IACvC,MAAM;AAAA,IACN,aAAa;AAAA,IACb,YAAY;AAAA,EACd;AAEA,SAAO,OAAO,OAAO,aAAa;AAAA,IAChC,SAAS,OAAO,UAA8D;AAC5E,aAAO,sBAAsB,OAAO,MAAM;AAAA,IAC5C;AAAA,IACA,cAAc,CAAC,WAAyC;AACtD,aAAO,2BAA2B,MAAM;AAAA,IAC1C;AAAA,EACF,CAAC;AACH;AAEA,IAAO,iBAAQ;","names":[]}
1
+ {"version":3,"sources":["../../../tools/warp_grep/gemini.ts"],"sourcesContent":["/**\n * Google Gemini SDK adapter for morph-warp-grep tool\n * \n * Requires @google/generative-ai as a peer dependency.\n * Install with: npm install @google/generative-ai\n */\n\nimport type { FunctionDeclaration, FunctionDeclarationSchema } from '@google/generative-ai';\nimport { executeToolCall, formatResult, WarpGrepClient, executeGitHubReadFile, formatGitHubReadFileResult } from './client.js';\nimport { WARP_GREP_DESCRIPTION, WARP_GREP_TOOL_NAME, GITHUB_SEARCH_TOOL_NAME, GITHUB_SEARCH_DESCRIPTION, GITHUB_READ_FILE_TOOL_NAME, GITHUB_READ_FILE_DESCRIPTION, GITHUB_READ_FILE_INPUT_SCHEMA } from './prompts.js';\nimport type { WarpGrepToolConfig, WarpGrepResult, GitHubSearchToolConfig, GitHubReadFileInput, GitHubReadFileResult, GitHubReadFileToolConfig } from './types.js';\n\n// Use plain object to avoid runtime import of SchemaType enum\nconst TOOL_PARAMETERS = {\n type: 'OBJECT',\n properties: {\n search_term: { \n type: 'STRING', \n description: 'Search problem statement that this subagent is supposed to research for' \n },\n },\n required: ['search_term'],\n} as unknown as FunctionDeclarationSchema;\n\n/**\n * Gemini-native warp grep function declaration\n * \n * @example\n * ```typescript\n * import { GoogleGenerativeAI } from '@google/generative-ai';\n * import { warpGrepFunctionDeclaration, execute } from '@morphllm/morphsdk/tools/warp-grep/gemini';\n * \n * const genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY);\n * const model = genAI.getGenerativeModel({\n * model: 'gemini-2.0-flash',\n * tools: [{ functionDeclarations: [warpGrepFunctionDeclaration] }]\n * });\n * \n * const chat = model.startChat();\n * const result = await chat.sendMessage('Find authentication middleware');\n * \n * // Handle function call\n * const call = result.response.functionCalls()?.[0];\n * if (call) {\n * const searchResult = await execute(call.args, { repoRoot: '.' });\n * console.log(searchResult);\n * }\n * ```\n */\nexport const warpGrepFunctionDeclaration: FunctionDeclaration = {\n name: WARP_GREP_TOOL_NAME,\n description: WARP_GREP_DESCRIPTION,\n parameters: TOOL_PARAMETERS,\n};\n\n/**\n * Execute warp grep search\n * \n * @param input - Tool input with search_term\n * @param config - Configuration with repoRoot and optional provider\n * @returns Search results\n */\nexport async function execute(\n input: { search_term: string } | string,\n config: WarpGrepToolConfig\n): Promise<WarpGrepResult> {\n return executeToolCall(input, config);\n}\n\nexport { formatResult };\n\n/**\n * Gemini tool with execute method attached\n */\nexport interface GeminiWarpGrepTool extends FunctionDeclaration {\n execute: (input: unknown) => Promise<WarpGrepResult>;\n formatResult: (result: WarpGrepResult) => string;\n}\n\n/**\n * Create a custom warp grep tool with configuration and methods\n * \n * @param config - Configuration options\n * @returns Function declaration with execute and formatResult methods\n * \n * @example Local usage\n * ```typescript\n * import { GoogleGenerativeAI } from '@google/generative-ai';\n * import { createMorphWarpGrepTool } from '@morphllm/morphsdk/tools/warp-grep/gemini';\n * \n * const tool = createMorphWarpGrepTool({ repoRoot: '.' });\n * \n * const genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY);\n * const model = genAI.getGenerativeModel({\n * model: 'gemini-2.0-flash',\n * tools: [{ functionDeclarations: [tool] }]\n * });\n * \n * const chat = model.startChat();\n * const result = await chat.sendMessage('Find authentication middleware');\n * \n * // Handle function call\n * const call = result.response.functionCalls()?.[0];\n * if (call && call.name === tool.name) {\n * const searchResult = await tool.execute(call.args);\n * console.log(tool.formatResult(searchResult));\n * \n * // Send result back to model\n * await chat.sendMessage([{\n * functionResponse: {\n * name: call.name,\n * response: { result: tool.formatResult(searchResult) }\n * }\n * }]);\n * }\n * ```\n * \n * @example Remote sandbox (E2B, Modal, etc.)\n * ```typescript\n * const tool = createMorphWarpGrepTool({\n * repoRoot: '/home/repo',\n * remoteCommands: {\n * grep: async (pattern, path) => (await sandbox.run(`rg '${pattern}' '${path}'`)).stdout,\n * read: async (path, start, end) => (await sandbox.run(`sed -n '${start},${end}p' '${path}'`)).stdout,\n * listDir: async (path, maxDepth) => (await sandbox.run(`find '${path}' -maxdepth ${maxDepth}`)).stdout,\n * },\n * });\n * ```\n */\nexport function createWarpGrepTool(config: WarpGrepToolConfig): GeminiWarpGrepTool {\n const declaration: FunctionDeclaration = {\n name: config.name ?? WARP_GREP_TOOL_NAME,\n description: config.description ?? WARP_GREP_DESCRIPTION,\n parameters: TOOL_PARAMETERS,\n };\n\n return Object.assign(declaration, {\n execute: async (input: unknown): Promise<WarpGrepResult> => {\n return executeToolCall(input as { search_term: string } | string, config);\n },\n formatResult: (result: WarpGrepResult): string => {\n return formatResult(result);\n },\n });\n}\n\n// Legacy alias for backwards compatibility\nexport const createMorphWarpGrepTool = createWarpGrepTool;\n\nconst GITHUB_SEARCH_PARAMETERS = {\n type: 'OBJECT',\n properties: {\n search_term: { type: 'STRING', description: 'Search problem statement that this subagent is supposed to research for' },\n github_url: { type: 'STRING', description: 'GitHub repository URL to search (e.g. \"https://github.com/vercel/next.js\"). You must provide either github_url or owner_repo.' },\n owner_repo: { type: 'STRING', description: 'Repository owner/repo shorthand (e.g. \"vercel/next.js\"). You must provide either github_url or owner_repo.' },\n branch: { type: 'STRING', description: 'Branch to search (defaults to repo default branch)' },\n },\n required: ['search_term'],\n} as unknown as FunctionDeclarationSchema;\n\n/**\n * Create a GitHub search tool for Google Gemini SDK\n *\n * @param config - Configuration options (morphApiKey, morphApiUrl, codeSearchUrl, timeout)\n * @returns Gemini FunctionDeclaration with execute and formatResult methods\n *\n * @example\n * ```typescript\n * import { GoogleGenerativeAI } from '@google/generative-ai';\n * import { createGitHubSearchTool } from '@morphllm/morphsdk/tools/warp-grep/gemini';\n *\n * const tool = createGitHubSearchTool({ morphApiKey: process.env.MORPH_API_KEY });\n *\n * const genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY);\n * const model = genAI.getGenerativeModel({\n * model: 'gemini-2.0-flash',\n * tools: [{ functionDeclarations: [tool] }]\n * });\n *\n * // Execute\n * const result = await tool.execute({ search_term: 'auth middleware', github_url: 'https://github.com/vercel/next.js' });\n * console.log(tool.formatResult(result));\n * ```\n */\nexport function createGitHubSearchTool(config: GitHubSearchToolConfig) {\n const client = new WarpGrepClient(config);\n\n const declaration: FunctionDeclaration = {\n name: GITHUB_SEARCH_TOOL_NAME,\n description: GITHUB_SEARCH_DESCRIPTION,\n parameters: GITHUB_SEARCH_PARAMETERS,\n };\n\n return Object.assign(declaration, {\n execute: async (input: { search_term: string; github_url?: string; owner_repo?: string; branch?: string }): Promise<WarpGrepResult> => {\n const github = input.github_url || input.owner_repo;\n if (!github) {\n throw new Error('Please provide github search url or owner/repo id');\n }\n return client.searchGitHub({ searchTerm: input.search_term, github, branch: input.branch });\n },\n formatResult: (result: WarpGrepResult): string => {\n return formatResult(result);\n },\n });\n}\n\nconst GITHUB_READ_FILE_PARAMETERS = {\n type: 'OBJECT',\n properties: {\n github: { type: 'STRING', description: 'owner/repo shorthand (e.g., \"vercel/next.js\")' },\n path: { type: 'STRING', description: 'File path within the repository' },\n startLine: { type: 'NUMBER', description: 'Start line number (1-based)' },\n endLine: { type: 'NUMBER', description: 'End line number (1-based, inclusive)' },\n branch: { type: 'STRING', description: 'Branch to read from (defaults to repo default branch)' },\n },\n required: ['github', 'path'],\n} as unknown as FunctionDeclarationSchema;\n\n/**\n * Create a GitHub read file tool for Google Gemini SDK\n *\n * @param config - Optional configuration (timeout)\n * @returns Gemini FunctionDeclaration with execute and formatResult methods\n *\n * @example\n * ```typescript\n * import { GoogleGenerativeAI } from '@google/generative-ai';\n * import { createGitHubReadFileTool } from '@morphllm/morphsdk/tools/warp-grep/gemini';\n *\n * const tool = createGitHubReadFileTool();\n *\n * const genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY);\n * const model = genAI.getGenerativeModel({\n * model: 'gemini-2.0-flash',\n * tools: [{ functionDeclarations: [tool] }]\n * });\n *\n * const result = await tool.execute({ github: 'vercel/next.js', path: 'package.json' });\n * console.log(tool.formatResult(result));\n * ```\n */\nexport function createGitHubReadFileTool(config?: GitHubReadFileToolConfig) {\n const declaration: FunctionDeclaration = {\n name: GITHUB_READ_FILE_TOOL_NAME,\n description: GITHUB_READ_FILE_DESCRIPTION,\n parameters: GITHUB_READ_FILE_PARAMETERS,\n };\n\n return Object.assign(declaration, {\n execute: async (input: GitHubReadFileInput): Promise<GitHubReadFileResult> => {\n return executeGitHubReadFile(input, config);\n },\n formatResult: (result: GitHubReadFileResult): string => {\n return formatGitHubReadFileResult(result);\n },\n });\n}\n\nexport default warpGrepFunctionDeclaration;\n\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAaA,IAAM,kBAAkB;AAAA,EACtB,MAAM;AAAA,EACN,YAAY;AAAA,IACV,aAAa;AAAA,MACX,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,UAAU,CAAC,aAAa;AAC1B;AA2BO,IAAM,8BAAmD;AAAA,EAC9D,MAAM;AAAA,EACN,aAAa;AAAA,EACb,YAAY;AACd;AASA,eAAsB,QACpB,OACA,QACyB;AACzB,SAAO,gBAAgB,OAAO,MAAM;AACtC;AA8DO,SAAS,mBAAmB,QAAgD;AACjF,QAAM,cAAmC;AAAA,IACvC,MAAM,OAAO,QAAQ;AAAA,IACrB,aAAa,OAAO,eAAe;AAAA,IACnC,YAAY;AAAA,EACd;AAEA,SAAO,OAAO,OAAO,aAAa;AAAA,IAChC,SAAS,OAAO,UAA4C;AAC1D,aAAO,gBAAgB,OAA2C,MAAM;AAAA,IAC1E;AAAA,IACA,cAAc,CAAC,WAAmC;AAChD,aAAO,aAAa,MAAM;AAAA,IAC5B;AAAA,EACF,CAAC;AACH;AAGO,IAAM,0BAA0B;AAEvC,IAAM,2BAA2B;AAAA,EAC/B,MAAM;AAAA,EACN,YAAY;AAAA,IACV,aAAa,EAAE,MAAM,UAAU,aAAa,0EAA0E;AAAA,IACtH,YAAY,EAAE,MAAM,UAAU,aAAa,gIAAgI;AAAA,IAC3K,YAAY,EAAE,MAAM,UAAU,aAAa,6GAA6G;AAAA,IACxJ,QAAQ,EAAE,MAAM,UAAU,aAAa,qDAAqD;AAAA,EAC9F;AAAA,EACA,UAAU,CAAC,aAAa;AAC1B;AA0BO,SAAS,uBAAuB,QAAgC;AACrE,QAAM,SAAS,IAAI,eAAe,MAAM;AAExC,QAAM,cAAmC;AAAA,IACvC,MAAM;AAAA,IACN,aAAa;AAAA,IACb,YAAY;AAAA,EACd;AAEA,SAAO,OAAO,OAAO,aAAa;AAAA,IAChC,SAAS,OAAO,UAAuH;AACrI,YAAM,SAAS,MAAM,cAAc,MAAM;AACzC,UAAI,CAAC,QAAQ;AACX,cAAM,IAAI,MAAM,mDAAmD;AAAA,MACrE;AACA,aAAO,OAAO,aAAa,EAAE,YAAY,MAAM,aAAa,QAAQ,QAAQ,MAAM,OAAO,CAAC;AAAA,IAC5F;AAAA,IACA,cAAc,CAAC,WAAmC;AAChD,aAAO,aAAa,MAAM;AAAA,IAC5B;AAAA,EACF,CAAC;AACH;AAEA,IAAM,8BAA8B;AAAA,EAClC,MAAM;AAAA,EACN,YAAY;AAAA,IACV,QAAQ,EAAE,MAAM,UAAU,aAAa,gDAAgD;AAAA,IACvF,MAAM,EAAE,MAAM,UAAU,aAAa,kCAAkC;AAAA,IACvE,WAAW,EAAE,MAAM,UAAU,aAAa,8BAA8B;AAAA,IACxE,SAAS,EAAE,MAAM,UAAU,aAAa,uCAAuC;AAAA,IAC/E,QAAQ,EAAE,MAAM,UAAU,aAAa,wDAAwD;AAAA,EACjG;AAAA,EACA,UAAU,CAAC,UAAU,MAAM;AAC7B;AAyBO,SAAS,yBAAyB,QAAmC;AAC1E,QAAM,cAAmC;AAAA,IACvC,MAAM;AAAA,IACN,aAAa;AAAA,IACb,YAAY;AAAA,EACd;AAEA,SAAO,OAAO,OAAO,aAAa;AAAA,IAChC,SAAS,OAAO,UAA8D;AAC5E,aAAO,sBAAsB,OAAO,MAAM;AAAA,IAC5C;AAAA,IACA,cAAc,CAAC,WAAyC;AACtD,aAAO,2BAA2B,MAAM;AAAA,IAC1C;AAAA,EACF,CAAC;AACH;AAEA,IAAO,iBAAQ;","names":[]}
@@ -32,17 +32,19 @@ var harness_exports = {};
32
32
  __export(harness_exports, {
33
33
  AGENT_CONFIG: () => AGENT_CONFIG,
34
34
  DEFAULT_EXCLUDES: () => DEFAULT_EXCLUDES,
35
- LLMResponseParser: () => LLMResponseParser,
36
35
  LocalRipgrepProvider: () => LocalRipgrepProvider,
37
36
  buildInitialState: () => buildInitialState,
38
37
  calculateContextBudget: () => calculateContextBudget,
38
+ extractPathFromCommand: () => extractPathFromCommand,
39
39
  formatListDirectoryTree: () => formatListDirectoryTree,
40
40
  formatToolResult: () => formatAgentToolOutput,
41
41
  formatTurnMessage: () => formatTurnMessage,
42
42
  normalizeFinishFiles: () => normalizeFinishFiles,
43
- parseToolCalls: () => parseToolCalls,
43
+ parseFinishFiles: () => parseFinishFiles,
44
+ parseReadLines: () => parseReadLines,
44
45
  readFinishFiles: () => readFinishFiles,
45
46
  resolveFinishFiles: () => resolveFinishFiles,
47
+ toolGlob: () => toolGlob,
46
48
  toolGrep: () => toolGrep,
47
49
  toolListDirectory: () => toolListDirectory,
48
50
  toolRead: () => toolRead
@@ -50,131 +52,58 @@ __export(harness_exports, {
50
52
  module.exports = __toCommonJS(harness_exports);
51
53
 
52
54
  // tools/warp_grep/agent/parser.ts
53
- var VALID_COMMANDS = ["list_directory", "ripgrep", "read", "finish"];
54
- function isValidCommand(name) {
55
- return VALID_COMMANDS.includes(name);
56
- }
57
- function parseQwen3ToolCalls(text) {
58
- const tools = [];
59
- const toolCallRegex = /<tool_call>\s*<function=([a-z_][a-z0-9_]*)>([\s\S]*?)<\/function>\s*<\/tool_call>/gi;
60
- let match;
61
- while ((match = toolCallRegex.exec(text)) !== null) {
62
- const funcName = match[1].toLowerCase();
63
- const body = match[2];
64
- if (!isValidCommand(funcName)) continue;
65
- const params = {};
66
- const paramRegex = /<parameter=([a-z_][a-z0-9_]*)>([\s\S]*?)<\/parameter>/gi;
67
- let paramMatch;
68
- while ((paramMatch = paramRegex.exec(body)) !== null) {
69
- params[paramMatch[1].toLowerCase()] = paramMatch[2].trim();
70
- }
71
- if (funcName === "ripgrep") {
72
- const pattern = params.pattern;
73
- if (!pattern) continue;
74
- const args = {
75
- pattern,
76
- path: params.path || ".",
77
- ...params.glob && { glob: params.glob },
78
- ...params.context_lines && { context_lines: parseInt(params.context_lines, 10) },
79
- ...params.case_sensitive && { case_sensitive: params.case_sensitive === "true" }
80
- };
81
- tools.push({ name: "grep", arguments: args });
82
- } else if (funcName === "list_directory") {
83
- const command = params.command;
84
- const directPath = params.path;
85
- let dirPath = directPath || ".";
86
- if (!directPath && command) {
87
- const tokens = command.trim().split(/\s+/);
88
- const pathTokens = tokens.slice(1).filter((t) => !t.startsWith("-") && !t.startsWith("|") && !t.startsWith("\\("));
89
- if (pathTokens.length > 0) {
90
- dirPath = pathTokens[0];
91
- }
92
- }
93
- tools.push({ name: "list_directory", arguments: { path: dirPath, pattern: params.pattern || null } });
94
- } else if (funcName === "read") {
95
- const filePath = params.path;
96
- if (!filePath) continue;
97
- const args = { path: filePath };
98
- const linesStr = params.lines;
99
- if (linesStr) {
100
- const ranges = [];
101
- for (const rangeStr of linesStr.split(",")) {
102
- const trimmed = rangeStr.trim();
103
- if (!trimmed) continue;
104
- const [s, e] = trimmed.split("-").map((v) => parseInt(v.trim(), 10));
105
- if (Number.isFinite(s) && Number.isFinite(e)) {
106
- ranges.push([s, e]);
107
- } else if (Number.isFinite(s)) {
108
- ranges.push([s, s]);
109
- }
110
- }
111
- if (ranges.length === 1) {
112
- args.start = ranges[0][0];
113
- args.end = ranges[0][1];
114
- } else if (ranges.length > 1) {
115
- args.lines = ranges;
116
- }
117
- }
118
- tools.push({ name: "read", arguments: args });
119
- } else if (funcName === "finish") {
120
- if (params.result && !params.files) {
121
- tools.push({ name: "finish", arguments: { files: [], textResult: params.result } });
122
- continue;
123
- }
124
- const filesStr = params.files;
125
- if (!filesStr) {
126
- tools.push({ name: "finish", arguments: { files: [], textResult: "No relevant code found." } });
127
- continue;
128
- }
129
- const files = [];
130
- for (const line of filesStr.split("\n")) {
131
- const trimmed = line.trim();
132
- if (!trimmed) continue;
133
- const colonIdx = trimmed.indexOf(":");
134
- if (colonIdx === -1) {
135
- files.push({ path: trimmed, lines: "*" });
136
- } else {
137
- const filePath = trimmed.slice(0, colonIdx);
138
- const rangesPart = trimmed.slice(colonIdx + 1);
139
- const ranges = [];
140
- for (const rangeStr of rangesPart.split(",")) {
141
- const rt = rangeStr.trim();
142
- if (!rt || rt === "*") {
143
- files.push({ path: filePath, lines: "*" });
144
- break;
145
- }
146
- const [s, e] = rt.split("-").map((v) => parseInt(v.trim(), 10));
147
- if (Number.isFinite(s) && Number.isFinite(e)) {
148
- ranges.push([s, e]);
149
- } else if (Number.isFinite(s)) {
150
- ranges.push([s, s]);
151
- }
152
- }
153
- if (ranges.length > 0) {
154
- files.push({ path: filePath, lines: ranges });
155
- } else if (!files.some((f) => f.path === filePath)) {
156
- files.push({ path: filePath, lines: "*" });
157
- }
158
- }
159
- }
160
- if (files.length > 0) {
161
- tools.push({ name: "finish", arguments: { files } });
162
- } else {
163
- tools.push({ name: "finish", arguments: { files: [], textResult: filesStr } });
164
- }
55
+ function parseReadLines(linesStr) {
56
+ const ranges = [];
57
+ for (const rangeStr of linesStr.split(",")) {
58
+ const trimmed = rangeStr.trim();
59
+ if (!trimmed) continue;
60
+ const parts = trimmed.split("-").map((v) => parseInt(v.trim(), 10));
61
+ if (parts.length >= 2 && Number.isFinite(parts[0]) && Number.isFinite(parts[1])) {
62
+ ranges.push([parts[0], parts[1]]);
63
+ } else if (Number.isFinite(parts[0])) {
64
+ ranges.push([parts[0], parts[0]]);
165
65
  }
166
66
  }
167
- return tools;
67
+ if (ranges.length === 1) return { start: ranges[0][0], end: ranges[0][1] };
68
+ if (ranges.length > 1) return { lines: ranges };
69
+ return {};
168
70
  }
169
- var LLMResponseParser = class {
170
- parse(text) {
171
- if (typeof text !== "string") {
172
- throw new TypeError("Command text must be a string.");
71
+ function parseFinishFiles(filesStr) {
72
+ const files = [];
73
+ for (const line of filesStr.trim().split(/\s+/)) {
74
+ const trimmed = line.trim();
75
+ if (!trimmed) continue;
76
+ const colonIdx = trimmed.indexOf(":");
77
+ if (colonIdx === -1) {
78
+ files.push({ path: trimmed, lines: "*" });
79
+ continue;
80
+ }
81
+ const filePath = trimmed.slice(0, colonIdx);
82
+ const rangesPart = trimmed.slice(colonIdx + 1);
83
+ if (!rangesPart.trim() || rangesPart.trim() === "*") {
84
+ files.push({ path: filePath, lines: "*" });
85
+ continue;
86
+ }
87
+ const ranges = [];
88
+ for (const rangeStr of rangesPart.split(",")) {
89
+ const rt = rangeStr.trim();
90
+ if (!rt) continue;
91
+ const parts = rt.split("-").map((v) => parseInt(v.trim(), 10));
92
+ if (parts.length >= 2 && Number.isFinite(parts[0]) && Number.isFinite(parts[1])) {
93
+ ranges.push([parts[0], parts[1]]);
94
+ } else if (Number.isFinite(parts[0])) {
95
+ ranges.push([parts[0], parts[0]]);
96
+ }
173
97
  }
174
- const withoutThink = text.replace(/<think>[\s\S]*?<\/think>/gi, "");
175
- return parseQwen3ToolCalls(withoutThink);
98
+ files.push({ path: filePath, lines: ranges.length > 0 ? ranges : "*" });
176
99
  }
177
- };
100
+ return files;
101
+ }
102
+ function extractPathFromCommand(command) {
103
+ const tokens = command.trim().split(/\s+/);
104
+ const pathTokens = tokens.slice(1).filter((t) => !t.startsWith("-") && !t.startsWith("|") && !t.startsWith("\\("));
105
+ return pathTokens[0] || ".";
106
+ }
178
107
 
179
108
  // tools/warp_grep/agent/formatter.ts
180
109
  var ToolOutputFormatter = class {
@@ -208,11 +137,12 @@ var parseEnvTimeout = (envValue, defaultMs) => {
208
137
  return isNaN(parsed) || parsed <= 0 ? defaultMs : parsed;
209
138
  };
210
139
  var AGENT_CONFIG = {
211
- MAX_TURNS: 4,
140
+ MAX_TURNS: 6,
212
141
  /** Default timeout for model calls. Can be overridden via MORPH_WARP_GREP_TIMEOUT env var (in ms) */
213
142
  TIMEOUT_MS: parseEnvTimeout(process.env.MORPH_WARP_GREP_TIMEOUT, 3e4),
214
- MAX_CONTEXT_CHARS: 54e4,
143
+ MAX_CONTEXT_CHARS: 321600,
215
144
  MAX_OUTPUT_LINES: 200,
145
+ MAX_LIST_RESULTS: 500,
216
146
  MAX_READ_LINES: 800,
217
147
  MAX_LIST_DEPTH: 3,
218
148
  LIST_TIMEOUT_MS: 2e3
@@ -299,6 +229,17 @@ var BUILTIN_EXCLUDES = [
299
229
  var DEFAULT_EXCLUDES = (process.env.MORPH_WARP_GREP_EXCLUDE || "").split(",").map((s) => s.trim()).filter(Boolean).concat(BUILTIN_EXCLUDES);
300
230
 
301
231
  // tools/warp_grep/agent/helpers.ts
232
+ function getMessageSize(m) {
233
+ if (m.role === "tool") return m.content.length;
234
+ if (m.role === "assistant") {
235
+ let size = typeof m.content === "string" ? m.content.length : 0;
236
+ if (m.tool_calls) {
237
+ size += m.tool_calls.reduce((s, tc) => s + tc.function.name.length + tc.function.arguments.length, 0);
238
+ }
239
+ return size;
240
+ }
241
+ return m.content.length;
242
+ }
302
243
  function formatTurnMessage(turnsUsed, maxTurns) {
303
244
  const turnsRemaining = maxTurns - turnsUsed;
304
245
  if (turnsRemaining === 1) {
@@ -309,33 +250,30 @@ You have used ${turnsUsed} turns, you only have 1 turn remaining. You have run o
309
250
  You have used ${turnsUsed} turn${turnsUsed === 1 ? "" : "s"} and have ${turnsRemaining} remaining`;
310
251
  }
311
252
  function calculateContextBudget(messages) {
312
- const totalChars = messages.reduce((sum, m) => sum + m.content.length, 0);
253
+ const totalChars = messages.reduce((sum, m) => sum + getMessageSize(m), 0);
313
254
  const maxChars = AGENT_CONFIG.MAX_CONTEXT_CHARS;
314
- const percent = Math.round(totalChars / maxChars * 100);
315
- const usedK = Math.round(totalChars / 1e3);
316
- const maxK = Math.round(maxChars / 1e3);
317
- return `<context_budget>${percent}% (${usedK}K/${maxK}K chars used)</context_budget>`;
255
+ const percent = Math.floor(totalChars / maxChars * 100);
256
+ const usedK = Math.floor(totalChars / 1e3);
257
+ const maxK = Math.floor(maxChars / 1e3);
258
+ return `<context_budget>${percent}% (${usedK}K/${maxK}K chars)</context_budget>`;
318
259
  }
319
260
  async function buildInitialState(repoRoot, searchTerm, provider, options) {
320
261
  const budget = calculateContextBudget([]);
321
- const turnTag = `Turn 0/${AGENT_CONFIG.MAX_TURNS}`;
262
+ const turnTag = `You have used 0 turns and have ${AGENT_CONFIG.MAX_TURNS} remaining`;
322
263
  const treeDepth = options?.search_type === "node_modules" ? 1 : 2;
264
+ const absRoot = import_path.default.resolve(repoRoot);
323
265
  try {
324
266
  const entries = await provider.listDirectory({
325
267
  path: ".",
326
268
  maxResults: AGENT_CONFIG.MAX_OUTPUT_LINES,
327
269
  maxDepth: treeDepth
328
270
  });
329
- const treeLines = entries.map((e) => {
330
- const indent = " ".repeat(e.depth);
331
- const name = e.type === "dir" ? `${e.name}/` : e.name;
332
- return `${indent}${name}`;
333
- });
334
- const repoName = import_path.default.basename(repoRoot);
335
- const treeOutput = treeLines.length > 0 ? `${repoName}/
336
- ${treeLines.join("\n")}` : `${repoName}/`;
271
+ const lines = [absRoot];
272
+ for (const e of entries) {
273
+ lines.push(import_path.default.join(absRoot, e.path));
274
+ }
337
275
  return `<repo_structure>
338
- ${treeOutput}
276
+ ${lines.join("\n")}
339
277
  </repo_structure>
340
278
 
341
279
  <search_string>
@@ -344,9 +282,8 @@ ${searchTerm}
344
282
  ${budget}
345
283
  ${turnTag}`;
346
284
  } catch {
347
- const repoName = import_path.default.basename(repoRoot);
348
285
  return `<repo_structure>
349
- ${repoName}/
286
+ ${absRoot}
350
287
  </repo_structure>
351
288
 
352
289
  <search_string>
@@ -413,29 +350,42 @@ async function toolRead(provider, args) {
413
350
  }
414
351
 
415
352
  // tools/warp_grep/agent/tools/list_directory.ts
416
- async function toolListDirectory(provider, args) {
417
- const maxResults = args.maxResults ?? AGENT_CONFIG.MAX_OUTPUT_LINES;
418
- const initialDepth = args.maxDepth ?? AGENT_CONFIG.MAX_LIST_DEPTH;
419
- async function getListRecursive(currentDepth) {
420
- const entries = await provider.listDirectory({
421
- path: args.path,
422
- pattern: args.pattern ?? null,
423
- maxResults,
424
- maxDepth: currentDepth
425
- });
426
- if (entries.length >= maxResults && currentDepth > 0) {
427
- return getListRecursive(currentDepth - 1);
428
- }
429
- return { entries };
353
+ var import_path2 = __toESM(require("path"), 1);
354
+ async function toolListDirectory(provider, args, repoRoot) {
355
+ const maxResults = args.maxResults ?? AGENT_CONFIG.MAX_LIST_RESULTS;
356
+ const maxDepth = args.maxDepth ?? AGENT_CONFIG.MAX_LIST_DEPTH;
357
+ const entries = await provider.listDirectory({
358
+ path: args.path,
359
+ pattern: args.pattern ?? null,
360
+ maxResults,
361
+ maxDepth
362
+ });
363
+ if (!entries.length) return "empty";
364
+ if (repoRoot) {
365
+ const absRoot = import_path2.default.resolve(repoRoot);
366
+ const lines = entries.map((e) => import_path2.default.join(absRoot, e.path));
367
+ return lines.join("\n");
430
368
  }
431
- const { entries: list } = await getListRecursive(initialDepth);
432
- if (!list.length) return "empty";
433
- const tree = list.map((e) => {
434
- const indent = " ".repeat(e.depth);
435
- const name = e.type === "dir" ? `${e.name}/` : e.name;
436
- return `${indent}${name}`;
437
- }).join("\n");
438
- return tree;
369
+ return entries.map((e) => e.path).join("\n");
370
+ }
371
+
372
+ // tools/warp_grep/agent/tools/glob.ts
373
+ async function toolGlob(provider, args) {
374
+ const res = await provider.glob(args);
375
+ if (res.error) {
376
+ return res.error;
377
+ }
378
+ if (!res.files.length) {
379
+ return "no matches";
380
+ }
381
+ const header = `Found ${res.totalFound} file(s) matching "${args.pattern}" within ${res.searchDir}, sorted by modification time (newest first):`;
382
+ const body = res.files.join("\n");
383
+ const truncated = res.totalFound > res.files.length ? `
384
+ [${res.totalFound - res.files.length} files truncated]` : "";
385
+ return `${header}
386
+ ---
387
+ ${body}
388
+ ---${truncated}`;
439
389
  }
440
390
 
441
391
  // tools/warp_grep/agent/tools/finish.ts
@@ -506,7 +456,7 @@ function mergeRanges(ranges) {
506
456
 
507
457
  // tools/warp_grep/providers/local.ts
508
458
  var import_promises2 = __toESM(require("fs/promises"), 1);
509
- var import_path3 = __toESM(require("path"), 1);
459
+ var import_path4 = __toESM(require("path"), 1);
510
460
 
511
461
  // tools/warp_grep/utils/ripgrep.ts
512
462
  var import_child_process = require("child_process");
@@ -571,21 +521,21 @@ async function runRipgrep(args, opts) {
571
521
 
572
522
  // tools/warp_grep/utils/paths.ts
573
523
  var import_fs = __toESM(require("fs"), 1);
574
- var import_path2 = __toESM(require("path"), 1);
524
+ var import_path3 = __toESM(require("path"), 1);
575
525
  function resolveUnderRepo(repoRoot, targetPath) {
576
- const absRoot = import_path2.default.resolve(repoRoot);
577
- const resolved = import_path2.default.resolve(absRoot, targetPath);
526
+ const absRoot = import_path3.default.resolve(repoRoot);
527
+ const resolved = import_path3.default.resolve(absRoot, targetPath);
578
528
  ensureWithinRepo(absRoot, resolved);
579
529
  return resolved;
580
530
  }
581
531
  function ensureWithinRepo(repoRoot, absTarget) {
582
- const rel = import_path2.default.relative(import_path2.default.resolve(repoRoot), import_path2.default.resolve(absTarget));
583
- if (rel.startsWith("..") || import_path2.default.isAbsolute(rel)) {
532
+ const rel = import_path3.default.relative(import_path3.default.resolve(repoRoot), import_path3.default.resolve(absTarget));
533
+ if (rel.startsWith("..") || import_path3.default.isAbsolute(rel)) {
584
534
  throw new Error(`Path outside repository root: ${absTarget}`);
585
535
  }
586
536
  }
587
537
  function toRepoRelative(repoRoot, absPath) {
588
- return import_path2.default.relative(import_path2.default.resolve(repoRoot), import_path2.default.resolve(absPath));
538
+ return import_path3.default.relative(import_path3.default.resolve(repoRoot), import_path3.default.resolve(absPath));
589
539
  }
590
540
  function isSymlink(p) {
591
541
  try {
@@ -596,7 +546,7 @@ function isSymlink(p) {
596
546
  }
597
547
  }
598
548
  function fixPathRepetition(fullPath) {
599
- const segments = fullPath.split(import_path2.default.sep).filter(Boolean);
549
+ const segments = fullPath.split(import_path3.default.sep).filter(Boolean);
600
550
  if (segments.length < 2) return null;
601
551
  for (let len = Math.floor(segments.length / 2); len >= 1; len--) {
602
552
  for (let i = 0; i <= segments.length - 2 * len; i++) {
@@ -604,7 +554,7 @@ function fixPathRepetition(fullPath) {
604
554
  const second = segments.slice(i + len, i + 2 * len);
605
555
  if (first.every((seg, idx) => seg === second[idx])) {
606
556
  const fixed = [...segments.slice(0, i), ...segments.slice(i + len)];
607
- return import_path2.default.sep + fixed.join(import_path2.default.sep);
557
+ return import_path3.default.sep + fixed.join(import_path3.default.sep);
608
558
  }
609
559
  }
610
560
  }
@@ -743,7 +693,7 @@ var LocalRipgrepProvider = class {
743
693
  }
744
694
  const stat = await import_promises2.default.stat(abs).catch(() => null);
745
695
  if (!stat) return { lines: [] };
746
- const targetArg = abs === import_path3.default.resolve(this.repoRoot) ? "." : toRepoRelative(this.repoRoot, abs);
696
+ const targetArg = abs === import_path4.default.resolve(this.repoRoot) ? "." : toRepoRelative(this.repoRoot, abs);
747
697
  const contextLines = params.context_lines !== void 0 ? String(params.context_lines) : "1";
748
698
  const args = [
749
699
  "--no-config",
@@ -898,7 +848,7 @@ Details: ${res.stderr}` : ""}`
898
848
  if (timedOut || results.length >= maxResults) break;
899
849
  if (shouldSkip(entry.name, allowNames)) continue;
900
850
  if (regex && !regex.test(entry.name)) continue;
901
- const full = import_path3.default.join(dir, entry.name);
851
+ const full = import_path4.default.join(dir, entry.name);
902
852
  const isDir = entry.isDirectory();
903
853
  results.push({
904
854
  name: entry.name,
@@ -914,13 +864,49 @@ Details: ${res.stderr}` : ""}`
914
864
  await walk(abs, 0);
915
865
  return results;
916
866
  }
867
+ async glob(params) {
868
+ let abs;
869
+ try {
870
+ abs = params.path ? resolveUnderRepo(this.repoRoot, params.path) : this.repoRoot;
871
+ } catch (err) {
872
+ return { files: [], searchDir: this.repoRoot, totalFound: 0, error: `[PATH ERROR] ${err instanceof Error ? err.message : String(err)}` };
873
+ }
874
+ const stat = await import_promises2.default.stat(abs).catch(() => null);
875
+ if (!stat || !stat.isDirectory()) {
876
+ return { files: [], searchDir: abs, totalFound: 0, error: `[PATH ERROR] Directory not found: ${params.path || "."}` };
877
+ }
878
+ const targetArg = abs === import_path4.default.resolve(this.repoRoot) ? "." : toRepoRelative(this.repoRoot, abs);
879
+ const args = [
880
+ "--no-config",
881
+ "--files",
882
+ "--color=never",
883
+ "-g",
884
+ params.pattern,
885
+ ...this.excludes.filter((e) => !this.allowNames?.has(e)).flatMap((e) => ["-g", `!${e}`]),
886
+ targetArg || "."
887
+ ];
888
+ const res = await runRipgrep(args, { cwd: this.repoRoot });
889
+ if (res.exitCode === -1) {
890
+ return { files: [], searchDir: abs, totalFound: 0, error: `[RIPGREP NOT AVAILABLE] ripgrep (rg) is required for glob search.` };
891
+ }
892
+ if (res.exitCode !== 0 && res.exitCode !== 1) {
893
+ return { files: [], searchDir: abs, totalFound: 0, error: `[GLOB ERROR] glob failed with exit code ${res.exitCode}${res.stderr ? `: ${res.stderr}` : ""}` };
894
+ }
895
+ const absRoot = import_path4.default.resolve(this.repoRoot);
896
+ const relFiles = (res.stdout || "").trim().split(/\r?\n/).filter((l) => l.length > 0);
897
+ const absFiles = relFiles.map((f) => import_path4.default.resolve(absRoot, f));
898
+ const withMtime = [];
899
+ for (const f of absFiles) {
900
+ const s = await import_promises2.default.stat(f).catch(() => null);
901
+ withMtime.push({ file: f, mtime: s?.mtimeMs ?? 0 });
902
+ }
903
+ withMtime.sort((a, b) => b.mtime - a.mtime);
904
+ const totalFound = withMtime.length;
905
+ return { files: withMtime.slice(0, 100).map((f) => f.file), searchDir: abs, totalFound };
906
+ }
917
907
  };
918
908
 
919
909
  // tools/warp_grep/harness.ts
920
- var parser = new LLMResponseParser();
921
- function parseToolCalls(text) {
922
- return parser.parse(text);
923
- }
924
910
  async function resolveFinishFiles(provider, files) {
925
911
  return readFinishFiles("", files, async (p, s, e) => {
926
912
  const r = await provider.read({ path: p, start: s, end: e });
@@ -934,17 +920,19 @@ async function resolveFinishFiles(provider, files) {
934
920
  0 && (module.exports = {
935
921
  AGENT_CONFIG,
936
922
  DEFAULT_EXCLUDES,
937
- LLMResponseParser,
938
923
  LocalRipgrepProvider,
939
924
  buildInitialState,
940
925
  calculateContextBudget,
926
+ extractPathFromCommand,
941
927
  formatListDirectoryTree,
942
928
  formatToolResult,
943
929
  formatTurnMessage,
944
930
  normalizeFinishFiles,
945
- parseToolCalls,
931
+ parseFinishFiles,
932
+ parseReadLines,
946
933
  readFinishFiles,
947
934
  resolveFinishFiles,
935
+ toolGlob,
948
936
  toolGrep,
949
937
  toolListDirectory,
950
938
  toolRead