@morphllm/morphsdk 0.2.81 → 0.2.83

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 (77) hide show
  1. package/dist/{chunk-4NI25AKV.js → chunk-4KMBU6T3.js} +2 -2
  2. package/dist/{chunk-XT5ZO6ES.js → chunk-5PNMAWLC.js} +8 -2
  3. package/dist/chunk-5PNMAWLC.js.map +1 -0
  4. package/dist/{chunk-X6A64F2F.js → chunk-HPR6BJA7.js} +5 -5
  5. package/dist/{chunk-4VMIPD4G.js → chunk-HRK53IKL.js} +8 -6
  6. package/dist/chunk-HRK53IKL.js.map +1 -0
  7. package/dist/{chunk-NTTQJM6O.js → chunk-LXG37353.js} +2 -2
  8. package/dist/{chunk-467MCW5R.js → chunk-P2O5JKE5.js} +2 -2
  9. package/dist/{chunk-PHJQ4N3T.js → chunk-PUGSTXLO.js} +2 -2
  10. package/dist/{chunk-B3UC7UVA.js → chunk-QOYI77CN.js} +30 -8
  11. package/dist/chunk-QOYI77CN.js.map +1 -0
  12. package/dist/{chunk-Z2HDXUH7.js → chunk-RL4JBZ3T.js} +2 -2
  13. package/dist/{chunk-OFMDENAQ.js → chunk-S27A4NQM.js} +2 -2
  14. package/dist/{client-CSINf0lQ.d.ts → client-CsO9LifG.d.ts} +1 -1
  15. package/dist/client.cjs +38 -8
  16. package/dist/client.cjs.map +1 -1
  17. package/dist/client.d.ts +2 -2
  18. package/dist/client.js +10 -10
  19. package/dist/index.cjs +38 -8
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.d.ts +2 -2
  22. package/dist/index.js +10 -10
  23. package/dist/tools/warp_grep/agent/config.cjs +7 -1
  24. package/dist/tools/warp_grep/agent/config.cjs.map +1 -1
  25. package/dist/tools/warp_grep/agent/config.d.ts +1 -0
  26. package/dist/tools/warp_grep/agent/config.js +1 -1
  27. package/dist/tools/warp_grep/agent/runner.cjs +34 -6
  28. package/dist/tools/warp_grep/agent/runner.cjs.map +1 -1
  29. package/dist/tools/warp_grep/agent/runner.js +3 -3
  30. package/dist/tools/warp_grep/agent/types.cjs.map +1 -1
  31. package/dist/tools/warp_grep/agent/types.d.ts +16 -1
  32. package/dist/tools/warp_grep/anthropic.cjs +36 -7
  33. package/dist/tools/warp_grep/anthropic.cjs.map +1 -1
  34. package/dist/tools/warp_grep/anthropic.d.ts +1 -1
  35. package/dist/tools/warp_grep/anthropic.js +7 -7
  36. package/dist/tools/warp_grep/client.cjs +38 -8
  37. package/dist/tools/warp_grep/client.cjs.map +1 -1
  38. package/dist/tools/warp_grep/client.d.ts +1 -1
  39. package/dist/tools/warp_grep/client.js +6 -6
  40. package/dist/tools/warp_grep/gemini.cjs +36 -7
  41. package/dist/tools/warp_grep/gemini.cjs.map +1 -1
  42. package/dist/tools/warp_grep/gemini.d.ts +1 -1
  43. package/dist/tools/warp_grep/gemini.js +6 -6
  44. package/dist/tools/warp_grep/harness.cjs +7 -1
  45. package/dist/tools/warp_grep/harness.cjs.map +1 -1
  46. package/dist/tools/warp_grep/harness.js +3 -3
  47. package/dist/tools/warp_grep/index.cjs +38 -8
  48. package/dist/tools/warp_grep/index.cjs.map +1 -1
  49. package/dist/tools/warp_grep/index.d.ts +1 -1
  50. package/dist/tools/warp_grep/index.js +6 -6
  51. package/dist/tools/warp_grep/openai.cjs +36 -7
  52. package/dist/tools/warp_grep/openai.cjs.map +1 -1
  53. package/dist/tools/warp_grep/openai.d.ts +1 -1
  54. package/dist/tools/warp_grep/openai.js +7 -7
  55. package/dist/tools/warp_grep/providers/local.cjs +7 -1
  56. package/dist/tools/warp_grep/providers/local.cjs.map +1 -1
  57. package/dist/tools/warp_grep/providers/local.js +2 -2
  58. package/dist/tools/warp_grep/providers/remote.cjs +7 -1
  59. package/dist/tools/warp_grep/providers/remote.cjs.map +1 -1
  60. package/dist/tools/warp_grep/providers/remote.d.ts +1 -1
  61. package/dist/tools/warp_grep/providers/remote.js +2 -2
  62. package/dist/tools/warp_grep/vercel.cjs +36 -7
  63. package/dist/tools/warp_grep/vercel.cjs.map +1 -1
  64. package/dist/tools/warp_grep/vercel.d.ts +1 -1
  65. package/dist/tools/warp_grep/vercel.js +7 -7
  66. package/dist/{types-CnvVDM63.d.ts → types-Cv4LpqVl.d.ts} +2 -0
  67. package/package.json +1 -1
  68. package/dist/chunk-4VMIPD4G.js.map +0 -1
  69. package/dist/chunk-B3UC7UVA.js.map +0 -1
  70. package/dist/chunk-XT5ZO6ES.js.map +0 -1
  71. /package/dist/{chunk-4NI25AKV.js.map → chunk-4KMBU6T3.js.map} +0 -0
  72. /package/dist/{chunk-X6A64F2F.js.map → chunk-HPR6BJA7.js.map} +0 -0
  73. /package/dist/{chunk-NTTQJM6O.js.map → chunk-LXG37353.js.map} +0 -0
  74. /package/dist/{chunk-467MCW5R.js.map → chunk-P2O5JKE5.js.map} +0 -0
  75. /package/dist/{chunk-PHJQ4N3T.js.map → chunk-PUGSTXLO.js.map} +0 -0
  76. /package/dist/{chunk-Z2HDXUH7.js.map → chunk-RL4JBZ3T.js.map} +0 -0
  77. /package/dist/{chunk-OFMDENAQ.js.map → chunk-S27A4NQM.js.map} +0 -0
@@ -14,7 +14,7 @@ import {
14
14
  import {
15
15
  AGENT_CONFIG,
16
16
  DEFAULT_EXCLUDES
17
- } from "./chunk-XT5ZO6ES.js";
17
+ } from "./chunk-5PNMAWLC.js";
18
18
 
19
19
  // tools/warp_grep/providers/local.ts
20
20
  import fs from "fs/promises";
@@ -289,4 +289,4 @@ Details: ${res.stderr}` : ""}`
289
289
  export {
290
290
  LocalRipgrepProvider
291
291
  };
292
- //# sourceMappingURL=chunk-4NI25AKV.js.map
292
+ //# sourceMappingURL=chunk-4KMBU6T3.js.map
@@ -1,7 +1,13 @@
1
1
  // tools/warp_grep/agent/config.ts
2
+ var parseEnvTimeout = (envValue, defaultMs) => {
3
+ if (!envValue) return defaultMs;
4
+ const parsed = parseInt(envValue, 10);
5
+ return isNaN(parsed) || parsed <= 0 ? defaultMs : parsed;
6
+ };
2
7
  var AGENT_CONFIG = {
3
8
  MAX_TURNS: 4,
4
- TIMEOUT_MS: 3e4,
9
+ /** Default timeout for model calls. Can be overridden via MORPH_WARP_GREP_TIMEOUT env var (in ms) */
10
+ TIMEOUT_MS: parseEnvTimeout(process.env.MORPH_WARP_GREP_TIMEOUT, 3e4),
5
11
  MAX_CONTEXT_CHARS: 54e4,
6
12
  MAX_OUTPUT_LINES: 200,
7
13
  MAX_READ_LINES: 800,
@@ -95,4 +101,4 @@ export {
95
101
  DEFAULT_EXCLUDES,
96
102
  DEFAULT_MODEL
97
103
  };
98
- //# sourceMappingURL=chunk-XT5ZO6ES.js.map
104
+ //# sourceMappingURL=chunk-5PNMAWLC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../tools/warp_grep/agent/config.ts"],"sourcesContent":["// Parse timeout from env, defaulting to 30 seconds\nconst parseEnvTimeout = (envValue: string | undefined, defaultMs: number): number => {\n if (!envValue) return defaultMs;\n const parsed = parseInt(envValue, 10);\n return isNaN(parsed) || parsed <= 0 ? defaultMs : parsed;\n};\n\nexport const AGENT_CONFIG = {\n MAX_TURNS: 4,\n /** Default timeout for model calls. Can be overridden via MORPH_WARP_GREP_TIMEOUT env var (in ms) */\n TIMEOUT_MS: parseEnvTimeout(process.env.MORPH_WARP_GREP_TIMEOUT, 30_000),\n MAX_CONTEXT_CHARS: 540_000,\n MAX_OUTPUT_LINES: 200,\n MAX_READ_LINES: 800,\n MAX_LIST_DEPTH: 3,\n LIST_TIMEOUT_MS: 2_000,\n};\n\n/**\n * Comprehensive exclusion list for directories and files\n * These patterns are used with ripgrep's -g flag\n */\nconst BUILTIN_EXCLUDES = [\n // Version control\n '.git', '.svn', '.hg', '.bzr',\n \n // Dependencies\n 'node_modules', 'bower_components', '.pnpm', '.yarn',\n 'vendor', 'packages', 'Pods', '.bundle',\n \n // Python\n '__pycache__', '.pytest_cache', '.mypy_cache', '.ruff_cache',\n '.venv', 'venv', '.tox', '.nox', '.eggs', '*.egg-info',\n \n // Build outputs\n 'dist', 'build', 'out', 'output', 'target', '_build',\n '.next', '.nuxt', '.output', '.vercel', '.netlify',\n \n // Cache directories\n '.cache', '.parcel-cache', '.turbo', '.nx', '.gradle',\n \n // IDE/Editor\n '.idea', '.vscode', '.vs',\n \n // Coverage\n 'coverage', '.coverage', 'htmlcov', '.nyc_output',\n \n // Temporary\n 'tmp', 'temp', '.tmp', '.temp',\n \n // Lock files\n 'package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'bun.lockb',\n 'Cargo.lock', 'Gemfile.lock', 'poetry.lock',\n \n // Binary/minified\n '*.min.js', '*.min.css', '*.bundle.js',\n '*.wasm', '*.so', '*.dll', '*.pyc',\n '*.map', '*.js.map',\n \n // Hidden directories catch-all\n '.*',\n];\n\nexport const DEFAULT_EXCLUDES = (process.env.MORPH_WARP_GREP_EXCLUDE || '')\n .split(',')\n .map(s => s.trim())\n .filter(Boolean)\n .concat(BUILTIN_EXCLUDES);\n\nexport const DEFAULT_MODEL = 'morph-warp-grep-v1';\n\n\n"],"mappings":";AACA,IAAM,kBAAkB,CAAC,UAA8B,cAA8B;AACnF,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,SAAS,SAAS,UAAU,EAAE;AACpC,SAAO,MAAM,MAAM,KAAK,UAAU,IAAI,YAAY;AACpD;AAEO,IAAM,eAAe;AAAA,EAC1B,WAAW;AAAA;AAAA,EAEX,YAAY,gBAAgB,QAAQ,IAAI,yBAAyB,GAAM;AAAA,EACvE,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,iBAAiB;AACnB;AAMA,IAAM,mBAAmB;AAAA;AAAA,EAEvB;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAO;AAAA;AAAA,EAGvB;AAAA,EAAgB;AAAA,EAAoB;AAAA,EAAS;AAAA,EAC7C;AAAA,EAAU;AAAA,EAAY;AAAA,EAAQ;AAAA;AAAA,EAG9B;AAAA,EAAe;AAAA,EAAiB;AAAA,EAAe;AAAA,EAC/C;AAAA,EAAS;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAS;AAAA;AAAA,EAG1C;AAAA,EAAQ;AAAA,EAAS;AAAA,EAAO;AAAA,EAAU;AAAA,EAAU;AAAA,EAC5C;AAAA,EAAS;AAAA,EAAS;AAAA,EAAW;AAAA,EAAW;AAAA;AAAA,EAGxC;AAAA,EAAU;AAAA,EAAiB;AAAA,EAAU;AAAA,EAAO;AAAA;AAAA,EAG5C;AAAA,EAAS;AAAA,EAAW;AAAA;AAAA,EAGpB;AAAA,EAAY;AAAA,EAAa;AAAA,EAAW;AAAA;AAAA,EAGpC;AAAA,EAAO;AAAA,EAAQ;AAAA,EAAQ;AAAA;AAAA,EAGvB;AAAA,EAAqB;AAAA,EAAa;AAAA,EAAkB;AAAA,EACpD;AAAA,EAAc;AAAA,EAAgB;AAAA;AAAA,EAG9B;AAAA,EAAY;AAAA,EAAa;AAAA,EACzB;AAAA,EAAU;AAAA,EAAQ;AAAA,EAAS;AAAA,EAC3B;AAAA,EAAS;AAAA;AAAA,EAGT;AACF;AAEO,IAAM,oBAAoB,QAAQ,IAAI,2BAA2B,IACrE,MAAM,GAAG,EACT,IAAI,OAAK,EAAE,KAAK,CAAC,EACjB,OAAO,OAAO,EACd,OAAO,gBAAgB;AAEnB,IAAM,gBAAgB;","names":[]}
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  createWarpGrepTool as createWarpGrepTool2
3
- } from "./chunk-Z2HDXUH7.js";
3
+ } from "./chunk-RL4JBZ3T.js";
4
4
  import {
5
5
  createWarpGrepTool
6
- } from "./chunk-NTTQJM6O.js";
6
+ } from "./chunk-LXG37353.js";
7
7
  import {
8
8
  createWarpGrepTool as createWarpGrepTool3
9
- } from "./chunk-OFMDENAQ.js";
9
+ } from "./chunk-S27A4NQM.js";
10
10
  import {
11
11
  WarpGrepClient
12
- } from "./chunk-4VMIPD4G.js";
12
+ } from "./chunk-HRK53IKL.js";
13
13
  import {
14
14
  createCodebaseSearchTool as createCodebaseSearchTool3
15
15
  } from "./chunk-UBX7QYBD.js";
@@ -280,4 +280,4 @@ export {
280
280
  VercelToolFactory,
281
281
  MorphClient
282
282
  };
283
- //# sourceMappingURL=chunk-X6A64F2F.js.map
283
+ //# sourceMappingURL=chunk-HPR6BJA7.js.map
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  runWarpGrep
3
- } from "./chunk-B3UC7UVA.js";
3
+ } from "./chunk-QOYI77CN.js";
4
4
  import {
5
5
  RemoteCommandsProvider
6
- } from "./chunk-PHJQ4N3T.js";
6
+ } from "./chunk-PUGSTXLO.js";
7
7
  import {
8
8
  LocalRipgrepProvider
9
- } from "./chunk-4NI25AKV.js";
9
+ } from "./chunk-4KMBU6T3.js";
10
10
 
11
11
  // tools/warp_grep/client.ts
12
12
  var WarpGrepClient = class {
@@ -53,7 +53,8 @@ var WarpGrepClient = class {
53
53
  debug: input.debug ?? this.config.debug,
54
54
  morphApiKey: this.config.morphApiKey,
55
55
  morphApiUrl: this.config.morphApiUrl,
56
- retryConfig: this.config.retryConfig
56
+ retryConfig: this.config.retryConfig,
57
+ timeout: this.config.timeout
57
58
  }
58
59
  );
59
60
  }
@@ -74,7 +75,8 @@ async function executeToolCall(input, config) {
74
75
  debug: config.debug ?? false,
75
76
  morphApiKey: config.morphApiKey,
76
77
  morphApiUrl: config.morphApiUrl,
77
- retryConfig: config.retryConfig
78
+ retryConfig: config.retryConfig,
79
+ timeout: config.timeout
78
80
  });
79
81
  const finish = result.finish;
80
82
  if (result.terminationReason !== "completed" || !finish?.metadata) {
@@ -115,4 +117,4 @@ export {
115
117
  executeToolCall,
116
118
  formatResult
117
119
  };
118
- //# sourceMappingURL=chunk-4VMIPD4G.js.map
120
+ //# sourceMappingURL=chunk-HRK53IKL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../tools/warp_grep/client.ts"],"sourcesContent":["/**\n * WarpGrep client for programmatic code search\n */\n\nimport { runWarpGrep } from './agent/runner.js';\nimport { LocalRipgrepProvider } from './providers/local.js';\nimport { RemoteCommandsProvider } from './providers/remote.js';\nimport type { \n WarpGrepClientConfig, \n WarpGrepInput, \n WarpGrepResult,\n WarpGrepContext,\n WarpGrepToolConfig,\n} from './types.js';\n\n/**\n * WarpGrep client for programmatic code search\n * \n * @example\n * ```typescript\n * import { WarpGrepClient } from '@morphllm/morphsdk';\n * \n * const client = new WarpGrepClient({ morphApiKey: process.env.MORPH_API_KEY });\n * \n * // Simple usage - defaults to LocalRipgrepProvider\n * const result = await client.execute({\n * query: 'Find authentication middleware',\n * repoRoot: '.'\n * });\n * \n * // With custom excludes\n * const result = await client.execute({\n * query: 'Find database models',\n * repoRoot: '.',\n * excludes: ['node_modules', '.git', 'dist']\n * });\n * ```\n */\nexport class WarpGrepClient {\n private config: WarpGrepClientConfig;\n\n constructor(config: WarpGrepClientConfig = {}) {\n this.config = {\n morphApiKey: config.morphApiKey,\n morphApiUrl: config.morphApiUrl,\n debug: config.debug,\n timeout: config.timeout,\n retryConfig: config.retryConfig,\n };\n }\n\n /**\n * Execute a code search query\n * \n * @param input - Search parameters including query, repoRoot, and optional provider\n * @returns Search results with relevant code contexts\n * \n * @example\n * ```typescript\n * const result = await client.execute({\n * query: 'Find authentication middleware',\n * repoRoot: '.'\n * });\n * \n * if (result.success) {\n * for (const ctx of result.contexts) {\n * console.log(`File: ${ctx.file}`);\n * console.log(ctx.content);\n * }\n * }\n * ```\n */\n async execute(input: WarpGrepInput): Promise<WarpGrepResult> {\n return executeToolCall(\n { query: input.query },\n {\n repoRoot: input.repoRoot,\n remoteCommands: input.remoteCommands,\n provider: input.provider,\n excludes: input.excludes,\n includes: input.includes,\n debug: input.debug ?? this.config.debug,\n morphApiKey: this.config.morphApiKey,\n morphApiUrl: this.config.morphApiUrl,\n retryConfig: this.config.retryConfig,\n timeout: this.config.timeout,\n }\n );\n }\n}\n\n/**\n * Execute a warp grep search directly\n * \n * @param input - Search parameters\n * @param config - Optional client configuration\n * @returns Search results\n * \n * @example\n * ```typescript\n * import { executeWarpGrep } from '@morphllm/morphsdk/tools/warp-grep';\n * \n * const result = await executeWarpGrep({\n * query: 'Find authentication middleware',\n * repoRoot: '.'\n * });\n * ```\n */\nexport async function executeWarpGrep(\n input: WarpGrepInput,\n config?: WarpGrepClientConfig\n): Promise<WarpGrepResult> {\n const client = new WarpGrepClient(config);\n return client.execute(input);\n}\n\nexport async function executeToolCall(\n input: { query: string } | string,\n config: WarpGrepToolConfig\n): Promise<WarpGrepResult> {\n const parsed = typeof input === 'string' ? JSON.parse(input) : input;\n \n // Priority: remoteCommands > provider > LocalRipgrepProvider\n const provider = config.remoteCommands\n ? new RemoteCommandsProvider(config.repoRoot, config.remoteCommands)\n : config.provider ?? new LocalRipgrepProvider(config.repoRoot, config.excludes);\n \n const result = await runWarpGrep({\n query: parsed.query,\n repoRoot: config.repoRoot,\n provider,\n excludes: config.excludes,\n includes: config.includes,\n debug: config.debug ?? false,\n morphApiKey: config.morphApiKey,\n morphApiUrl: config.morphApiUrl,\n retryConfig: config.retryConfig,\n timeout: config.timeout,\n });\n\n const finish = result.finish;\n if (result.terminationReason !== 'completed' || !finish?.metadata) {\n return { success: false, error: 'Search did not complete' };\n }\n\n const contexts: WarpGrepContext[] = (finish.resolved ?? []).map(r => ({\n file: r.path,\n content: r.content,\n }));\n\n return { success: true, contexts, summary: finish.payload };\n}\n\n/**\n * Format warp grep results for display or tool responses\n * \n * @param result - The search result\n * @returns Formatted string representation\n */\nexport function formatResult(result: WarpGrepResult): string {\n if (!result.success) {\n return `Search failed: ${result.error}`;\n }\n\n if (!result.contexts || result.contexts.length === 0) {\n return 'No relevant code found. Try rephrasing your query.';\n }\n\n const lines: string[] = [];\n lines.push(`Found ${result.contexts.length} relevant code sections:\\n`);\n\n result.contexts.forEach((ctx, i) => {\n lines.push(`${i + 1}. ${ctx.file}`);\n lines.push('```');\n lines.push(ctx.content);\n lines.push('```');\n lines.push('');\n });\n\n if (result.summary) {\n lines.push(`Summary: ${result.summary}`);\n }\n\n return lines.join('\\n');\n}\n\n"],"mappings":";;;;;;;;;;;AAsCO,IAAM,iBAAN,MAAqB;AAAA,EAClB;AAAA,EAER,YAAY,SAA+B,CAAC,GAAG;AAC7C,SAAK,SAAS;AAAA,MACZ,aAAa,OAAO;AAAA,MACpB,aAAa,OAAO;AAAA,MACpB,OAAO,OAAO;AAAA,MACd,SAAS,OAAO;AAAA,MAChB,aAAa,OAAO;AAAA,IACtB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuBA,MAAM,QAAQ,OAA+C;AAC3D,WAAO;AAAA,MACL,EAAE,OAAO,MAAM,MAAM;AAAA,MACrB;AAAA,QACE,UAAU,MAAM;AAAA,QAChB,gBAAgB,MAAM;AAAA,QACtB,UAAU,MAAM;AAAA,QAChB,UAAU,MAAM;AAAA,QAChB,UAAU,MAAM;AAAA,QAChB,OAAO,MAAM,SAAS,KAAK,OAAO;AAAA,QAClC,aAAa,KAAK,OAAO;AAAA,QACzB,aAAa,KAAK,OAAO;AAAA,QACzB,aAAa,KAAK,OAAO;AAAA,QACzB,SAAS,KAAK,OAAO;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AACF;AAmBA,eAAsB,gBACpB,OACA,QACyB;AACzB,QAAM,SAAS,IAAI,eAAe,MAAM;AACxC,SAAO,OAAO,QAAQ,KAAK;AAC7B;AAEA,eAAsB,gBACpB,OACA,QACyB;AACzB,QAAM,SAAS,OAAO,UAAU,WAAW,KAAK,MAAM,KAAK,IAAI;AAG/D,QAAM,WAAW,OAAO,iBACpB,IAAI,uBAAuB,OAAO,UAAU,OAAO,cAAc,IACjE,OAAO,YAAY,IAAI,qBAAqB,OAAO,UAAU,OAAO,QAAQ;AAEhF,QAAM,SAAS,MAAM,YAAY;AAAA,IAC/B,OAAO,OAAO;AAAA,IACd,UAAU,OAAO;AAAA,IACjB;AAAA,IACA,UAAU,OAAO;AAAA,IACjB,UAAU,OAAO;AAAA,IACjB,OAAO,OAAO,SAAS;AAAA,IACvB,aAAa,OAAO;AAAA,IACpB,aAAa,OAAO;AAAA,IACpB,aAAa,OAAO;AAAA,IACpB,SAAS,OAAO;AAAA,EAClB,CAAC;AAED,QAAM,SAAS,OAAO;AACtB,MAAI,OAAO,sBAAsB,eAAe,CAAC,QAAQ,UAAU;AACjE,WAAO,EAAE,SAAS,OAAO,OAAO,0BAA0B;AAAA,EAC5D;AAEA,QAAM,YAA+B,OAAO,YAAY,CAAC,GAAG,IAAI,QAAM;AAAA,IACpE,MAAM,EAAE;AAAA,IACR,SAAS,EAAE;AAAA,EACb,EAAE;AAEF,SAAO,EAAE,SAAS,MAAM,UAAU,SAAS,OAAO,QAAQ;AAC5D;AAQO,SAAS,aAAa,QAAgC;AAC3D,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO,kBAAkB,OAAO,KAAK;AAAA,EACvC;AAEA,MAAI,CAAC,OAAO,YAAY,OAAO,SAAS,WAAW,GAAG;AACpD,WAAO;AAAA,EACT;AAEA,QAAM,QAAkB,CAAC;AACzB,QAAM,KAAK,SAAS,OAAO,SAAS,MAAM;AAAA,CAA4B;AAEtE,SAAO,SAAS,QAAQ,CAAC,KAAK,MAAM;AAClC,UAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,EAAE;AAClC,UAAM,KAAK,KAAK;AAChB,UAAM,KAAK,IAAI,OAAO;AACtB,UAAM,KAAK,KAAK;AAChB,UAAM,KAAK,EAAE;AAAA,EACf,CAAC;AAED,MAAI,OAAO,SAAS;AAClB,UAAM,KAAK,YAAY,OAAO,OAAO,EAAE;AAAA,EACzC;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;","names":[]}
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  executeToolCall,
7
7
  formatResult
8
- } from "./chunk-4VMIPD4G.js";
8
+ } from "./chunk-HRK53IKL.js";
9
9
  import {
10
10
  getSystemPrompt
11
11
  } from "./chunk-FMLHRJDF.js";
@@ -58,4 +58,4 @@ export {
58
58
  createWarpGrepTool,
59
59
  openai_default
60
60
  };
61
- //# sourceMappingURL=chunk-NTTQJM6O.js.map
61
+ //# sourceMappingURL=chunk-LXG37353.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  AGENT_CONFIG
3
- } from "./chunk-XT5ZO6ES.js";
3
+ } from "./chunk-5PNMAWLC.js";
4
4
 
5
5
  // tools/warp_grep/agent/tools/grep.ts
6
6
  async function toolGrep(provider, args) {
@@ -228,4 +228,4 @@ export {
228
228
  formatListDirectoryTree,
229
229
  enforceContextLimit
230
230
  };
231
- //# sourceMappingURL=chunk-467MCW5R.js.map
231
+ //# sourceMappingURL=chunk-P2O5JKE5.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  AGENT_CONFIG
3
- } from "./chunk-XT5ZO6ES.js";
3
+ } from "./chunk-5PNMAWLC.js";
4
4
 
5
5
  // tools/warp_grep/providers/remote.ts
6
6
  var SKIP_NAMES = /* @__PURE__ */ new Set([
@@ -185,4 +185,4 @@ var RemoteCommandsProvider = class {
185
185
  export {
186
186
  RemoteCommandsProvider
187
187
  };
188
- //# sourceMappingURL=chunk-PHJQ4N3T.js.map
188
+ //# sourceMappingURL=chunk-PUGSTXLO.js.map
@@ -7,7 +7,7 @@ import {
7
7
  toolGrep,
8
8
  toolListDirectory,
9
9
  toolRead
10
- } from "./chunk-467MCW5R.js";
10
+ } from "./chunk-P2O5JKE5.js";
11
11
  import {
12
12
  formatAgentToolOutput
13
13
  } from "./chunk-APP75CBN.js";
@@ -20,7 +20,7 @@ import {
20
20
  import {
21
21
  AGENT_CONFIG,
22
22
  DEFAULT_MODEL
23
- } from "./chunk-XT5ZO6ES.js";
23
+ } from "./chunk-5PNMAWLC.js";
24
24
  import {
25
25
  fetchWithRetry,
26
26
  withTimeout
@@ -50,7 +50,8 @@ async function callModel(messages, model, options = {}) {
50
50
  },
51
51
  options.retryConfig
52
52
  );
53
- const resp = await withTimeout(fetchPromise, AGENT_CONFIG.TIMEOUT_MS, "morph-warp-grep request timed out");
53
+ const timeoutMs = options.timeout ?? AGENT_CONFIG.TIMEOUT_MS;
54
+ const resp = await withTimeout(fetchPromise, timeoutMs, "morph-warp-grep request timed out");
54
55
  if (!resp.ok) {
55
56
  if (resp.status === 404) {
56
57
  throw new Error(
@@ -68,10 +69,15 @@ async function callModel(messages, model, options = {}) {
68
69
  return content;
69
70
  }
70
71
  async function runWarpGrep(config) {
72
+ const totalStart = Date.now();
73
+ const timeoutMs = config.timeout ?? AGENT_CONFIG.TIMEOUT_MS;
74
+ const timings = { turns: [], timeout_ms: timeoutMs };
71
75
  const repoRoot = path.resolve(config.repoRoot || process.cwd());
72
76
  const messages = [];
73
77
  messages.push({ role: "system", content: getSystemPrompt() });
78
+ const initialStateStart = Date.now();
74
79
  const initialState = await buildInitialState(repoRoot, config.query, config.provider);
80
+ timings.initial_state_ms = Date.now() - initialStateStart;
75
81
  messages.push({ role: "user", content: initialState });
76
82
  const maxTurns = AGENT_CONFIG.MAX_TURNS;
77
83
  const model = config.model || DEFAULT_MODEL;
@@ -80,21 +86,29 @@ async function runWarpGrep(config) {
80
86
  let finishMeta;
81
87
  let terminationReason = "terminated";
82
88
  for (let turn = 1; turn <= maxTurns; turn += 1) {
89
+ const turnMetrics = { turn, morph_api_ms: 0, local_tools_ms: 0 };
83
90
  enforceContextLimit(messages);
91
+ const modelCallStart = Date.now();
84
92
  const assistantContent = await callModel(messages, model, {
85
93
  morphApiKey: config.morphApiKey,
86
94
  morphApiUrl: config.morphApiUrl,
87
- retryConfig: config.retryConfig
95
+ retryConfig: config.retryConfig,
96
+ timeout: timeoutMs
88
97
  }).catch((e) => {
89
98
  errors.push({ message: e instanceof Error ? e.message : String(e) });
90
99
  return "";
91
100
  });
92
- if (!assistantContent) break;
101
+ turnMetrics.morph_api_ms = Date.now() - modelCallStart;
102
+ if (!assistantContent) {
103
+ timings.turns.push(turnMetrics);
104
+ break;
105
+ }
93
106
  messages.push({ role: "assistant", content: assistantContent });
94
107
  const toolCalls = parser.parse(assistantContent);
95
108
  if (toolCalls.length === 0) {
96
109
  errors.push({ message: "No tool calls produced by the model. Your MCP is likely out of date! Update it by running: rm -rf ~/.npm/_npx && npm cache clean --force && npx -y @morphllm/morphmcp@latest" });
97
110
  terminationReason = "terminated";
111
+ timings.turns.push(turnMetrics);
98
112
  break;
99
113
  }
100
114
  const finishCalls = toolCalls.filter((c) => c.name === "finish");
@@ -135,7 +149,9 @@ async function runWarpGrep(config) {
135
149
  )
136
150
  );
137
151
  }
152
+ const toolExecStart = Date.now();
138
153
  const allResults = await Promise.all(allPromises);
154
+ turnMetrics.local_tools_ms = Date.now() - toolExecStart;
139
155
  for (const result of allResults) {
140
156
  formatted.push(result);
141
157
  }
@@ -144,6 +160,7 @@ async function runWarpGrep(config) {
144
160
  const contextBudget = calculateContextBudget(messages);
145
161
  messages.push({ role: "user", content: formatted.join("\n") + turnMessage + "\n" + contextBudget });
146
162
  }
163
+ timings.turns.push(turnMetrics);
147
164
  if (finishCalls.length) {
148
165
  const fc = finishCalls[0];
149
166
  const files = fc.arguments?.files ?? [];
@@ -153,7 +170,8 @@ async function runWarpGrep(config) {
153
170
  }
154
171
  }
155
172
  if (terminationReason !== "completed" || !finishMeta) {
156
- return { terminationReason, messages, errors };
173
+ timings.total_ms = Date.now() - totalStart;
174
+ return { terminationReason, messages, errors, timings };
157
175
  }
158
176
  const parts = ["Relevant context found:"];
159
177
  for (const f of finishMeta.files) {
@@ -161,6 +179,7 @@ async function runWarpGrep(config) {
161
179
  parts.push(`- ${f.path}: ${ranges}`);
162
180
  }
163
181
  const payload = parts.join("\n");
182
+ const finishResolutionStart = Date.now();
164
183
  const fileReadErrors = [];
165
184
  const resolved = await readFinishFiles(
166
185
  repoRoot,
@@ -180,17 +199,20 @@ async function runWarpGrep(config) {
180
199
  }
181
200
  }
182
201
  );
202
+ timings.finish_resolution_ms = Date.now() - finishResolutionStart;
183
203
  if (fileReadErrors.length > 0) {
184
204
  errors.push(...fileReadErrors.map((e) => ({ message: `File read error: ${e.path} - ${e.error}` })));
185
205
  }
206
+ timings.total_ms = Date.now() - totalStart;
186
207
  return {
187
208
  terminationReason: "completed",
188
209
  messages,
189
- finish: { payload, metadata: finishMeta, resolved }
210
+ finish: { payload, metadata: finishMeta, resolved },
211
+ timings
190
212
  };
191
213
  }
192
214
 
193
215
  export {
194
216
  runWarpGrep
195
217
  };
196
- //# sourceMappingURL=chunk-B3UC7UVA.js.map
218
+ //# sourceMappingURL=chunk-QOYI77CN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../tools/warp_grep/agent/runner.ts"],"sourcesContent":["import { AGENT_CONFIG, DEFAULT_MODEL } from './config.js';\nimport { getSystemPrompt } from './prompt.js';\nimport type { AgentRunResult, ChatMessage, SessionConfig, AgentFinish, WarpGrepExecutionMetrics, WarpGrepTurnMetrics } from './types.js';\nimport { LLMResponseParser } from './parser.js';\nimport type { WarpGrepProvider } from '../providers/types.js';\nimport { toolGrep } from './tools/grep.js';\nimport { toolRead } from './tools/read.js';\nimport { toolListDirectory } from './tools/list_directory.js';\nimport { readFinishFiles } from './tools/finish.js';\nimport { fetchWithRetry, withTimeout, type RetryConfig } from '../../utils/resilience.js';\nimport { formatAgentToolOutput } from './formatter.js';\nimport { formatTurnMessage, calculateContextBudget, buildInitialState, enforceContextLimit } from './helpers.js';\nimport path from 'path';\n\ntype EventName =\n | 'initial_state'\n | 'round_start'\n | 'round_end'\n | 'finish'\n | 'error';\n\nexport type EventCallback = (name: EventName, payload: Record<string, unknown>) => void;\n\nconst parser = new LLMResponseParser();\n\nconst DEFAULT_API_URL = 'https://api.morphllm.com';\n\ninterface CallModelOptions {\n morphApiKey?: string;\n morphApiUrl?: string;\n retryConfig?: RetryConfig;\n timeout?: number;\n}\n\nasync function callModel(\n messages: ChatMessage[],\n model: string,\n options: CallModelOptions = {}\n): Promise<string> {\n const baseUrl = options.morphApiUrl || DEFAULT_API_URL;\n const apiKey = options.morphApiKey || process.env.MORPH_API_KEY || '';\n \n const fetchPromise = fetchWithRetry(\n `${baseUrl}/v1/chat/completions`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n model,\n temperature: 0.0,\n max_tokens: 1024,\n messages,\n }),\n },\n options.retryConfig\n );\n const timeoutMs = options.timeout ?? AGENT_CONFIG.TIMEOUT_MS;\n const resp = await withTimeout(fetchPromise, timeoutMs, 'morph-warp-grep request timed out');\n if (!resp.ok) {\n if (resp.status === 404) {\n throw new Error(\n 'The endpoint you are trying to call is likely deprecated. Please update with: npm cache clean --force && npx -y @morphllm/morphmcp@latest or visit: https://morphllm.com/mcp'\n );\n }\n // keeping these cases are real throws, if this happens retry will likely not help, so best we just throw here, notice the error and fix\n const t = await resp.text();\n throw new Error(`morph-warp-grep error ${resp.status}: ${t}`);\n }\n const data = await resp.json();\n const content = data?.choices?.[0]?.message?.content;\n if (!content || typeof content !== 'string') {\n throw new Error('Invalid response from model');\n }\n return content;\n}\n\nexport async function runWarpGrep(config: SessionConfig & { provider: WarpGrepProvider }): Promise<AgentRunResult> {\n const totalStart = Date.now();\n const timeoutMs = config.timeout ?? AGENT_CONFIG.TIMEOUT_MS;\n const timings: Partial<WarpGrepExecutionMetrics> = { turns: [], timeout_ms: timeoutMs };\n \n const repoRoot = path.resolve(config.repoRoot || process.cwd());\n const messages: ChatMessage[] = [];\n\n messages.push({ role: 'system' as const, content: getSystemPrompt() });\n \n const initialStateStart = Date.now();\n const initialState = await buildInitialState(repoRoot, config.query, config.provider);\n timings.initial_state_ms = Date.now() - initialStateStart;\n \n messages.push({ role: 'user', content: initialState });\n\n const maxTurns = AGENT_CONFIG.MAX_TURNS;\n const model = config.model || DEFAULT_MODEL;\n const provider = config.provider;\n const errors: Array<{ message: string }> = [];\n\n let finishMeta: AgentFinish | undefined;\n let terminationReason: AgentRunResult['terminationReason'] = 'terminated';\n\n for (let turn = 1; turn <= maxTurns; turn += 1) {\n const turnMetrics: WarpGrepTurnMetrics = { turn, morph_api_ms: 0, local_tools_ms: 0 };\n \n // Enforce hard context limit before calling model\n enforceContextLimit(messages);\n \n // call model\n const modelCallStart = Date.now();\n const assistantContent = await callModel(messages, model, {\n morphApiKey: config.morphApiKey,\n morphApiUrl: config.morphApiUrl,\n retryConfig: config.retryConfig,\n timeout: timeoutMs,\n }).catch((e: unknown) => {\n errors.push({ message: e instanceof Error ? e.message : String(e) });\n return '';\n });\n turnMetrics.morph_api_ms = Date.now() - modelCallStart;\n \n if (!assistantContent) {\n timings.turns!.push(turnMetrics);\n break;\n }\n messages.push({ role: 'assistant', content: assistantContent });\n\n // parse tool calls (no longer throws - returns _skip calls for malformed commands)\n const toolCalls = parser.parse(assistantContent);\n if (toolCalls.length === 0) {\n errors.push({ message: 'No tool calls produced by the model. Your MCP is likely out of date! Update it by running: rm -rf ~/.npm/_npx && npm cache clean --force && npx -y @morphllm/morphmcp@latest' });\n terminationReason = 'terminated';\n timings.turns!.push(turnMetrics);\n break;\n }\n\n const finishCalls = toolCalls.filter(c => c.name === 'finish');\n const grepCalls = toolCalls.filter(c => c.name === 'grep');\n const listDirCalls = toolCalls.filter(c => c.name === 'list_directory');\n const readCalls = toolCalls.filter(c => c.name === 'read');\n const skipCalls = toolCalls.filter(c => c.name === '_skip');\n\n const formatted: string[] = [];\n\n // Surface any skipped commands as feedback to the LLM\n for (const c of skipCalls) {\n const msg = (c.arguments as { message?: string })?.message || 'Command skipped due to parsing error';\n formatted.push(msg);\n }\n\n const allPromises: Array<Promise<string>> = [];\n \n for (const c of grepCalls) {\n const args = (c.arguments ?? {}) as { pattern: string; path: string; glob?: string };\n allPromises.push(\n toolGrep(provider, args).then(\n ({ output }) => formatAgentToolOutput('grep', args, output, { isError: false }),\n err => formatAgentToolOutput('grep', args, String(err), { isError: true })\n )\n );\n }\n \n for (const c of listDirCalls) {\n const args = (c.arguments ?? {}) as { path: string; pattern?: string | null };\n allPromises.push(\n toolListDirectory(provider, args).then(\n p => formatAgentToolOutput('list_directory', args, p, { isError: false }),\n err => formatAgentToolOutput('list_directory', args, String(err), { isError: true })\n )\n );\n }\n \n for (const c of readCalls) {\n const args = (c.arguments ?? {}) as { path: string; start?: number; end?: number; lines?: Array<[number, number]> };\n allPromises.push(\n toolRead(provider, args).then(\n p => formatAgentToolOutput('read', args, p, { isError: false }),\n err => formatAgentToolOutput('read', args, String(err), { isError: true })\n )\n );\n }\n \n const toolExecStart = Date.now();\n const allResults = await Promise.all(allPromises);\n turnMetrics.local_tools_ms = Date.now() - toolExecStart;\n \n for (const result of allResults) {\n formatted.push(result);\n }\n\n if (formatted.length > 0) {\n const turnMessage = formatTurnMessage(turn, maxTurns);\n const contextBudget = calculateContextBudget(messages);\n messages.push({ role: 'user', content: formatted.join('\\n') + turnMessage + '\\n' + contextBudget });\n }\n\n timings.turns!.push(turnMetrics);\n\n if (finishCalls.length) {\n const fc = finishCalls[0];\n const files = ((fc.arguments as any)?.files ?? []) as AgentFinish['files'];\n finishMeta = { files };\n terminationReason = 'completed';\n break;\n }\n }\n\n if (terminationReason !== 'completed' || !finishMeta) {\n timings.total_ms = Date.now() - totalStart;\n return { terminationReason, messages, errors, timings: timings as WarpGrepExecutionMetrics };\n }\n\n // Build finish payload\n const parts: string[] = ['Relevant context found:'];\n for (const f of finishMeta.files) {\n const ranges = f.lines === '*' ? '*' \n : Array.isArray(f.lines) ? f.lines.map(([s, e]) => `${s}-${e}`).join(', ') \n : '*';\n parts.push(`- ${f.path}: ${ranges}`);\n }\n const payload = parts.join('\\n');\n\n // Resolve file contents for returned ranges\n // Wrap reader in try-catch to handle non-existent or unreadable files gracefully\n // Track files that couldn't be read for error reporting\n const finishResolutionStart = Date.now();\n const fileReadErrors: Array<{ path: string; error: string }> = [];\n const resolved = await readFinishFiles(\n repoRoot,\n finishMeta.files,\n async (p: string, s?: number, e?: number) => {\n try {\n const rr = await provider.read({ path: p, start: s, end: e });\n // rr.lines are \"line|content\" → strip the \"line|\" prefix\n return rr.lines.map(l => {\n const idx = l.indexOf('|');\n return idx >= 0 ? l.slice(idx + 1) : l;\n });\n } catch (err) {\n // File doesn't exist or can't be read - log error but don't throw\n // This handles cases where the agent hallucinated a path or the file was deleted\n const errorMsg = err instanceof Error ? err.message : String(err);\n fileReadErrors.push({ path: p, error: errorMsg });\n console.error(`[warp_grep] Failed to read file: ${p} - ${errorMsg}`);\n return [`[couldn't find: ${p}]`];\n }\n }\n );\n\n timings.finish_resolution_ms = Date.now() - finishResolutionStart;\n\n // Add file read errors to the result so MCP can report them\n if (fileReadErrors.length > 0) {\n errors.push(...fileReadErrors.map(e => ({ message: `File read error: ${e.path} - ${e.error}` })));\n }\n\n timings.total_ms = Date.now() - totalStart;\n return {\n terminationReason: 'completed',\n messages,\n finish: { payload, metadata: finishMeta, resolved },\n timings: timings as WarpGrepExecutionMetrics,\n };\n}\n"],"mappings":"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","names":[]}
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  executeToolCall,
7
7
  formatResult
8
- } from "./chunk-4VMIPD4G.js";
8
+ } from "./chunk-HRK53IKL.js";
9
9
  import {
10
10
  getSystemPrompt
11
11
  } from "./chunk-FMLHRJDF.js";
@@ -50,4 +50,4 @@ export {
50
50
  execute,
51
51
  createWarpGrepTool
52
52
  };
53
- //# sourceMappingURL=chunk-Z2HDXUH7.js.map
53
+ //# sourceMappingURL=chunk-RL4JBZ3T.js.map
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-KW7OEGZK.js";
4
4
  import {
5
5
  executeToolCall
6
- } from "./chunk-4VMIPD4G.js";
6
+ } from "./chunk-HRK53IKL.js";
7
7
 
8
8
  // tools/warp_grep/vercel.ts
9
9
  import { tool } from "ai";
@@ -38,4 +38,4 @@ export {
38
38
  createWarpGrepTool,
39
39
  vercel_default
40
40
  };
41
- //# sourceMappingURL=chunk-OFMDENAQ.js.map
41
+ //# sourceMappingURL=chunk-S27A4NQM.js.map
@@ -7,7 +7,7 @@ import { MorphGit } from './git/client.js';
7
7
  import { OpenAIRouter, AnthropicRouter, GeminiRouter, RawRouter } from './modelrouter/core.js';
8
8
  import { EditFileConfig, EditFileInput, EditFileResult, EditChanges } from './tools/fastapply/types.js';
9
9
  import { CodebaseSearchConfig, CodebaseSearchInput, CodebaseSearchResult } from './tools/codebase_search/types.js';
10
- import { d as WarpGrepToolConfig, b as WarpGrepResult, c as WarpGrepContext } from './types-CnvVDM63.js';
10
+ import { d as WarpGrepToolConfig, b as WarpGrepResult, c as WarpGrepContext } from './types-Cv4LpqVl.js';
11
11
  import * as openai_resources_index_mjs from 'openai/resources/index.mjs';
12
12
  import * as _anthropic_ai_sdk_resources_messages_mjs from '@anthropic-ai/sdk/resources/messages.mjs';
13
13
  import * as ai from 'ai';
package/dist/client.cjs CHANGED
@@ -987,9 +987,15 @@ async function checkHealth(config = {}) {
987
987
  }
988
988
 
989
989
  // tools/warp_grep/agent/config.ts
990
+ var parseEnvTimeout = (envValue, defaultMs) => {
991
+ if (!envValue) return defaultMs;
992
+ const parsed = parseInt(envValue, 10);
993
+ return isNaN(parsed) || parsed <= 0 ? defaultMs : parsed;
994
+ };
990
995
  var AGENT_CONFIG = {
991
996
  MAX_TURNS: 4,
992
- TIMEOUT_MS: 3e4,
997
+ /** Default timeout for model calls. Can be overridden via MORPH_WARP_GREP_TIMEOUT env var (in ms) */
998
+ TIMEOUT_MS: parseEnvTimeout(process.env.MORPH_WARP_GREP_TIMEOUT, 3e4),
993
999
  MAX_CONTEXT_CHARS: 54e4,
994
1000
  MAX_OUTPUT_LINES: 200,
995
1001
  MAX_READ_LINES: 800,
@@ -1857,7 +1863,8 @@ async function callModel(messages, model, options = {}) {
1857
1863
  },
1858
1864
  options.retryConfig
1859
1865
  );
1860
- const resp = await withTimeout(fetchPromise, AGENT_CONFIG.TIMEOUT_MS, "morph-warp-grep request timed out");
1866
+ const timeoutMs = options.timeout ?? AGENT_CONFIG.TIMEOUT_MS;
1867
+ const resp = await withTimeout(fetchPromise, timeoutMs, "morph-warp-grep request timed out");
1861
1868
  if (!resp.ok) {
1862
1869
  if (resp.status === 404) {
1863
1870
  throw new Error(
@@ -1875,10 +1882,15 @@ async function callModel(messages, model, options = {}) {
1875
1882
  return content;
1876
1883
  }
1877
1884
  async function runWarpGrep(config) {
1885
+ const totalStart = Date.now();
1886
+ const timeoutMs = config.timeout ?? AGENT_CONFIG.TIMEOUT_MS;
1887
+ const timings = { turns: [], timeout_ms: timeoutMs };
1878
1888
  const repoRoot = import_path3.default.resolve(config.repoRoot || process.cwd());
1879
1889
  const messages = [];
1880
1890
  messages.push({ role: "system", content: getSystemPrompt() });
1891
+ const initialStateStart = Date.now();
1881
1892
  const initialState = await buildInitialState(repoRoot, config.query, config.provider);
1893
+ timings.initial_state_ms = Date.now() - initialStateStart;
1882
1894
  messages.push({ role: "user", content: initialState });
1883
1895
  const maxTurns = AGENT_CONFIG.MAX_TURNS;
1884
1896
  const model = config.model || DEFAULT_MODEL;
@@ -1887,21 +1899,29 @@ async function runWarpGrep(config) {
1887
1899
  let finishMeta;
1888
1900
  let terminationReason = "terminated";
1889
1901
  for (let turn = 1; turn <= maxTurns; turn += 1) {
1902
+ const turnMetrics = { turn, morph_api_ms: 0, local_tools_ms: 0 };
1890
1903
  enforceContextLimit(messages);
1904
+ const modelCallStart = Date.now();
1891
1905
  const assistantContent = await callModel(messages, model, {
1892
1906
  morphApiKey: config.morphApiKey,
1893
1907
  morphApiUrl: config.morphApiUrl,
1894
- retryConfig: config.retryConfig
1908
+ retryConfig: config.retryConfig,
1909
+ timeout: timeoutMs
1895
1910
  }).catch((e) => {
1896
1911
  errors.push({ message: e instanceof Error ? e.message : String(e) });
1897
1912
  return "";
1898
1913
  });
1899
- if (!assistantContent) break;
1914
+ turnMetrics.morph_api_ms = Date.now() - modelCallStart;
1915
+ if (!assistantContent) {
1916
+ timings.turns.push(turnMetrics);
1917
+ break;
1918
+ }
1900
1919
  messages.push({ role: "assistant", content: assistantContent });
1901
1920
  const toolCalls = parser.parse(assistantContent);
1902
1921
  if (toolCalls.length === 0) {
1903
1922
  errors.push({ message: "No tool calls produced by the model. Your MCP is likely out of date! Update it by running: rm -rf ~/.npm/_npx && npm cache clean --force && npx -y @morphllm/morphmcp@latest" });
1904
1923
  terminationReason = "terminated";
1924
+ timings.turns.push(turnMetrics);
1905
1925
  break;
1906
1926
  }
1907
1927
  const finishCalls = toolCalls.filter((c) => c.name === "finish");
@@ -1942,7 +1962,9 @@ async function runWarpGrep(config) {
1942
1962
  )
1943
1963
  );
1944
1964
  }
1965
+ const toolExecStart = Date.now();
1945
1966
  const allResults = await Promise.all(allPromises);
1967
+ turnMetrics.local_tools_ms = Date.now() - toolExecStart;
1946
1968
  for (const result of allResults) {
1947
1969
  formatted.push(result);
1948
1970
  }
@@ -1951,6 +1973,7 @@ async function runWarpGrep(config) {
1951
1973
  const contextBudget = calculateContextBudget(messages);
1952
1974
  messages.push({ role: "user", content: formatted.join("\n") + turnMessage + "\n" + contextBudget });
1953
1975
  }
1976
+ timings.turns.push(turnMetrics);
1954
1977
  if (finishCalls.length) {
1955
1978
  const fc = finishCalls[0];
1956
1979
  const files = fc.arguments?.files ?? [];
@@ -1960,7 +1983,8 @@ async function runWarpGrep(config) {
1960
1983
  }
1961
1984
  }
1962
1985
  if (terminationReason !== "completed" || !finishMeta) {
1963
- return { terminationReason, messages, errors };
1986
+ timings.total_ms = Date.now() - totalStart;
1987
+ return { terminationReason, messages, errors, timings };
1964
1988
  }
1965
1989
  const parts = ["Relevant context found:"];
1966
1990
  for (const f of finishMeta.files) {
@@ -1968,6 +1992,7 @@ async function runWarpGrep(config) {
1968
1992
  parts.push(`- ${f.path}: ${ranges}`);
1969
1993
  }
1970
1994
  const payload = parts.join("\n");
1995
+ const finishResolutionStart = Date.now();
1971
1996
  const fileReadErrors = [];
1972
1997
  const resolved = await readFinishFiles(
1973
1998
  repoRoot,
@@ -1987,13 +2012,16 @@ async function runWarpGrep(config) {
1987
2012
  }
1988
2013
  }
1989
2014
  );
2015
+ timings.finish_resolution_ms = Date.now() - finishResolutionStart;
1990
2016
  if (fileReadErrors.length > 0) {
1991
2017
  errors.push(...fileReadErrors.map((e) => ({ message: `File read error: ${e.path} - ${e.error}` })));
1992
2018
  }
2019
+ timings.total_ms = Date.now() - totalStart;
1993
2020
  return {
1994
2021
  terminationReason: "completed",
1995
2022
  messages,
1996
- finish: { payload, metadata: finishMeta, resolved }
2023
+ finish: { payload, metadata: finishMeta, resolved },
2024
+ timings
1997
2025
  };
1998
2026
  }
1999
2027
 
@@ -2622,7 +2650,8 @@ var WarpGrepClient = class {
2622
2650
  debug: input.debug ?? this.config.debug,
2623
2651
  morphApiKey: this.config.morphApiKey,
2624
2652
  morphApiUrl: this.config.morphApiUrl,
2625
- retryConfig: this.config.retryConfig
2653
+ retryConfig: this.config.retryConfig,
2654
+ timeout: this.config.timeout
2626
2655
  }
2627
2656
  );
2628
2657
  }
@@ -2639,7 +2668,8 @@ async function executeToolCall(input, config) {
2639
2668
  debug: config.debug ?? false,
2640
2669
  morphApiKey: config.morphApiKey,
2641
2670
  morphApiUrl: config.morphApiUrl,
2642
- retryConfig: config.retryConfig
2671
+ retryConfig: config.retryConfig,
2672
+ timeout: config.timeout
2643
2673
  });
2644
2674
  const finish = result.finish;
2645
2675
  if (result.terminationReason !== "completed" || !finish?.metadata) {