@morphllm/morphsdk 0.2.109 → 0.2.111

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 (64) hide show
  1. package/dist/{chunk-UILVPDO3.js → chunk-23R562QJ.js} +23 -19
  2. package/dist/chunk-23R562QJ.js.map +1 -0
  3. package/dist/{chunk-KRDIR7GG.js → chunk-3MLWXJTJ.js} +8 -2
  4. package/dist/chunk-3MLWXJTJ.js.map +1 -0
  5. package/dist/{chunk-3L6QGAMK.js → chunk-ALTKGCG5.js} +2 -2
  6. package/dist/{chunk-QE53XISP.js → chunk-FL4ZBHK2.js} +2 -2
  7. package/dist/{chunk-EREXPWY4.js → chunk-HI35Y6EZ.js} +2 -2
  8. package/dist/{chunk-PRKYN7WR.js → chunk-JYKYQ5DN.js} +115 -22
  9. package/dist/chunk-JYKYQ5DN.js.map +1 -0
  10. package/dist/{chunk-4KMBU6T3.js → chunk-YJZP5ZL5.js} +4 -4
  11. package/dist/{chunk-ZROQPUCQ.js → chunk-YY7NZLAI.js} +2 -2
  12. package/dist/{client-DYnecl6H.d.ts → client-DksVOIsG.d.ts} +200 -6
  13. package/dist/client.cjs +136 -33
  14. package/dist/client.cjs.map +1 -1
  15. package/dist/client.d.ts +2 -2
  16. package/dist/client.js +7 -7
  17. package/dist/index.cjs +136 -33
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.ts +2 -2
  20. package/dist/index.js +9 -9
  21. package/dist/tools/warp_grep/agent/runner.cjs +7 -1
  22. package/dist/tools/warp_grep/agent/runner.cjs.map +1 -1
  23. package/dist/tools/warp_grep/agent/runner.js +2 -2
  24. package/dist/tools/warp_grep/agent/types.cjs.map +1 -1
  25. package/dist/tools/warp_grep/agent/types.d.ts +1 -1
  26. package/dist/tools/warp_grep/anthropic.cjs +23 -14
  27. package/dist/tools/warp_grep/anthropic.cjs.map +1 -1
  28. package/dist/tools/warp_grep/anthropic.d.ts +1 -1
  29. package/dist/tools/warp_grep/anthropic.js +4 -4
  30. package/dist/tools/warp_grep/client.cjs +26 -16
  31. package/dist/tools/warp_grep/client.cjs.map +1 -1
  32. package/dist/tools/warp_grep/client.d.ts +1 -1
  33. package/dist/tools/warp_grep/client.js +3 -3
  34. package/dist/tools/warp_grep/gemini.cjs +23 -14
  35. package/dist/tools/warp_grep/gemini.cjs.map +1 -1
  36. package/dist/tools/warp_grep/gemini.d.ts +1 -1
  37. package/dist/tools/warp_grep/gemini.js +3 -3
  38. package/dist/tools/warp_grep/harness.cjs +7 -1
  39. package/dist/tools/warp_grep/harness.cjs.map +1 -1
  40. package/dist/tools/warp_grep/harness.js +3 -3
  41. package/dist/tools/warp_grep/index.cjs +26 -16
  42. package/dist/tools/warp_grep/index.cjs.map +1 -1
  43. package/dist/tools/warp_grep/index.d.ts +1 -1
  44. package/dist/tools/warp_grep/index.js +8 -8
  45. package/dist/tools/warp_grep/openai.cjs +23 -14
  46. package/dist/tools/warp_grep/openai.cjs.map +1 -1
  47. package/dist/tools/warp_grep/openai.d.ts +1 -1
  48. package/dist/tools/warp_grep/openai.js +4 -4
  49. package/dist/tools/warp_grep/providers/local.js +2 -2
  50. package/dist/tools/warp_grep/providers/remote.d.ts +1 -1
  51. package/dist/tools/warp_grep/vercel.cjs +23 -14
  52. package/dist/tools/warp_grep/vercel.cjs.map +1 -1
  53. package/dist/tools/warp_grep/vercel.d.ts +1 -1
  54. package/dist/tools/warp_grep/vercel.js +4 -4
  55. package/dist/{types-BMowL9iZ.d.ts → types-D5p8QErL.d.ts} +2 -0
  56. package/package.json +1 -1
  57. package/dist/chunk-KRDIR7GG.js.map +0 -1
  58. package/dist/chunk-PRKYN7WR.js.map +0 -1
  59. package/dist/chunk-UILVPDO3.js.map +0 -1
  60. /package/dist/{chunk-3L6QGAMK.js.map → chunk-ALTKGCG5.js.map} +0 -0
  61. /package/dist/{chunk-QE53XISP.js.map → chunk-FL4ZBHK2.js.map} +0 -0
  62. /package/dist/{chunk-EREXPWY4.js.map → chunk-HI35Y6EZ.js.map} +0 -0
  63. /package/dist/{chunk-4KMBU6T3.js.map → chunk-YJZP5ZL5.js.map} +0 -0
  64. /package/dist/{chunk-ZROQPUCQ.js.map → chunk-YY7NZLAI.js.map} +0 -0
@@ -1,10 +1,10 @@
1
- import {
2
- RemoteCommandsProvider
3
- } from "./chunk-PUGSTXLO.js";
4
1
  import {
5
2
  runWarpGrep,
6
3
  runWarpGrepStreaming
7
- } from "./chunk-ZROQPUCQ.js";
4
+ } from "./chunk-YY7NZLAI.js";
5
+ import {
6
+ RemoteCommandsProvider
7
+ } from "./chunk-PUGSTXLO.js";
8
8
 
9
9
  // tools/warp_grep/client.ts
10
10
  async function getLocalProvider(repoRoot, excludes) {
@@ -69,7 +69,8 @@ async function executeToolCall(input, config) {
69
69
  }
70
70
  const contexts = (finish.resolved ?? []).map((r) => ({
71
71
  file: r.path,
72
- content: r.content
72
+ content: r.content,
73
+ lines: r.ranges
73
74
  }));
74
75
  return { success: true, contexts, summary: finish.payload };
75
76
  }
@@ -80,7 +81,8 @@ function processAgentResult(result) {
80
81
  }
81
82
  const contexts = (finish.resolved ?? []).map((r) => ({
82
83
  file: r.path,
83
- content: r.content
84
+ content: r.content,
85
+ lines: r.ranges
84
86
  }));
85
87
  return { success: true, contexts, summary: finish.payload };
86
88
  }
@@ -117,20 +119,22 @@ function formatResult(result) {
117
119
  if (!result.contexts || result.contexts.length === 0) {
118
120
  return "No relevant code found. Try rephrasing your query.";
119
121
  }
120
- const lines = [];
121
- lines.push(`Found ${result.contexts.length} relevant code sections:
122
+ const parts = [];
123
+ parts.push(`Morph Fast Context subagent performed search on repository:
122
124
  `);
123
- result.contexts.forEach((ctx, i) => {
124
- lines.push(`${i + 1}. ${ctx.file}`);
125
- lines.push("```");
126
- lines.push(ctx.content);
127
- lines.push("```");
128
- lines.push("");
129
- });
130
- if (result.summary) {
131
- lines.push(`Summary: ${result.summary}`);
125
+ parts.push("Relevant context found:");
126
+ for (const ctx of result.contexts) {
127
+ const rangeStr = !ctx.lines || ctx.lines === "*" ? "*" : ctx.lines.map(([s, e]) => `${s}-${e}`).join(",");
128
+ parts.push(`- ${ctx.file}:${rangeStr}`);
129
+ }
130
+ parts.push("\nHere is the content of files:\n");
131
+ for (const ctx of result.contexts) {
132
+ const rangeStr = !ctx.lines || ctx.lines === "*" ? "" : ` lines="${ctx.lines.map(([s, e]) => `${s}-${e}`).join(",")}"`;
133
+ parts.push(`<file path="${ctx.file}"${rangeStr}>`);
134
+ parts.push(ctx.content);
135
+ parts.push("</file>\n");
132
136
  }
133
- return lines.join("\n");
137
+ return parts.join("\n");
134
138
  }
135
139
 
136
140
  export {
@@ -139,4 +143,4 @@ export {
139
143
  executeToolCall,
140
144
  formatResult
141
145
  };
142
- //# sourceMappingURL=chunk-UILVPDO3.js.map
146
+ //# sourceMappingURL=chunk-23R562QJ.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, runWarpGrepStreaming } from './agent/runner.js';\nimport { RemoteCommandsProvider } from './providers/remote.js';\nimport type { WarpGrepProvider } from './providers/types.js';\nimport type { AgentRunResult, WarpGrepStep } from './agent/types.js';\nimport type {\n WarpGrepClientConfig,\n WarpGrepInput,\n WarpGrepResult,\n WarpGrepContext,\n WarpGrepToolConfig,\n} from './types.js';\n\n/**\n * Lazy-load LocalRipgrepProvider to avoid importing Node.js-specific\n * modules (child_process, fs) in edge environments like Cloudflare Workers.\n * Only loads when actually needed (i.e., when no remoteCommands or provider is specified).\n */\nasync function getLocalProvider(repoRoot: string, excludes?: string[]): Promise<WarpGrepProvider> {\n const { LocalRipgrepProvider } = await import('./providers/local.js');\n return new LocalRipgrepProvider(repoRoot, excludes);\n}\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, or an AsyncGenerator if streamSteps is true\n *\n * @example\n * ```typescript\n * // Standard execution\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 * // Streaming execution\n * const stream = client.execute({\n * query: 'Find auth middleware',\n * repoRoot: '.',\n * streamSteps: true\n * });\n *\n * for await (const step of stream) {\n * console.log(`Turn ${step.turn}:`, step.toolCalls);\n * }\n * ```\n */\n execute(input: WarpGrepInput & { streamSteps: true }): AsyncGenerator<WarpGrepStep, WarpGrepResult, undefined>;\n execute(input: WarpGrepInput & { streamSteps?: false | undefined }): Promise<WarpGrepResult>;\n execute(input: WarpGrepInput): Promise<WarpGrepResult> | AsyncGenerator<WarpGrepStep, WarpGrepResult, undefined> {\n const toolConfig: WarpGrepToolConfig = {\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 if (input.streamSteps) {\n return executeToolCallStreaming({ query: input.query }, toolConfig);\n }\n return executeToolCall({ query: input.query }, toolConfig);\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, or an AsyncGenerator if streamSteps is true\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 * // Streaming\n * const stream = executeWarpGrep({\n * query: 'Find auth',\n * repoRoot: '.',\n * streamSteps: true\n * });\n * for await (const step of stream) {\n * console.log(step.turn, step.toolCalls);\n * }\n * ```\n */\nexport function executeWarpGrep(\n input: WarpGrepInput & { streamSteps: true },\n config?: WarpGrepClientConfig\n): AsyncGenerator<WarpGrepStep, WarpGrepResult, undefined>;\nexport function executeWarpGrep(\n input: WarpGrepInput & { streamSteps?: false | undefined },\n config?: WarpGrepClientConfig\n): Promise<WarpGrepResult>;\nexport function executeWarpGrep(\n input: WarpGrepInput,\n config?: WarpGrepClientConfig\n): Promise<WarpGrepResult> | AsyncGenerator<WarpGrepStep, WarpGrepResult, undefined> {\n const client = new WarpGrepClient(config);\n if (input.streamSteps) {\n return client.execute({ ...input, streamSteps: true });\n }\n return client.execute({ ...input, streamSteps: false });\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 (lazy-loaded for edge compatibility)\n const provider = config.remoteCommands\n ? new RemoteCommandsProvider(config.repoRoot, config.remoteCommands)\n : config.provider ?? await getLocalProvider(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 lines: r.ranges,\n }));\n\n return { success: true, contexts, summary: finish.payload };\n}\n\n/**\n * Helper to process AgentRunResult into WarpGrepResult\n */\nfunction processAgentResult(result: AgentRunResult): WarpGrepResult {\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 lines: r.ranges,\n }));\n\n return { success: true, contexts, summary: finish.payload };\n}\n\n/**\n * Streaming version of executeToolCall that yields WarpGrepStep for each turn.\n */\nasync function* executeToolCallStreaming(\n input: { query: string } | string,\n config: WarpGrepToolConfig\n): AsyncGenerator<WarpGrepStep, WarpGrepResult, undefined> {\n const parsed = typeof input === 'string' ? JSON.parse(input) : input;\n\n // Priority: remoteCommands > provider > LocalRipgrepProvider (lazy-loaded for edge compatibility)\n const provider = config.remoteCommands\n ? new RemoteCommandsProvider(config.repoRoot, config.remoteCommands)\n : config.provider ?? await getLocalProvider(config.repoRoot, config.excludes);\n\n const generator = runWarpGrepStreaming({\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 // Forward all yielded steps\n let agentResult: AgentRunResult;\n for (;;) {\n const { value, done } = await generator.next();\n if (done) {\n agentResult = value;\n break;\n }\n yield value;\n }\n\n return processAgentResult(agentResult);\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 parts: string[] = [];\n parts.push(`Morph Fast Context subagent performed search on repository:\\n`);\n parts.push('Relevant context found:');\n\n for (const ctx of result.contexts) {\n const rangeStr = !ctx.lines || ctx.lines === '*'\n ? '*'\n : ctx.lines.map(([s, e]) => `${s}-${e}`).join(',');\n parts.push(`- ${ctx.file}:${rangeStr}`);\n }\n\n parts.push('\\nHere is the content of files:\\n');\n\n for (const ctx of result.contexts) {\n const rangeStr = !ctx.lines || ctx.lines === '*'\n ? ''\n : ` lines=\"${ctx.lines.map(([s, e]) => `${s}-${e}`).join(',')}\"`;\n parts.push(`<file path=\"${ctx.file}\"${rangeStr}>`);\n parts.push(ctx.content);\n parts.push('</file>\\n');\n }\n\n return parts.join('\\n');\n}\n\n"],"mappings":"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","names":[]}
@@ -109,7 +109,13 @@ async function readFinishFiles(repoRoot, files, reader) {
109
109
  } else {
110
110
  const ranges = mergeRanges(validRanges);
111
111
  const chunks = [];
112
- for (const [s, e] of ranges) {
112
+ for (let i = 0; i < ranges.length; i++) {
113
+ const [s, e] = ranges[i];
114
+ if (i === 0 && s > 1) {
115
+ chunks.push(`// ... existing code, block starting at line ${s} ...`);
116
+ } else if (i > 0) {
117
+ chunks.push(`// ... existing code, block starting at line ${s} ...`);
118
+ }
113
119
  const lines = await reader(f.path, s, e);
114
120
  chunks.push(lines.join("\n"));
115
121
  }
@@ -237,4 +243,4 @@ export {
237
243
  formatListDirectoryTree,
238
244
  enforceContextLimit
239
245
  };
240
- //# sourceMappingURL=chunk-KRDIR7GG.js.map
246
+ //# sourceMappingURL=chunk-3MLWXJTJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../tools/warp_grep/agent/tools/grep.ts","../tools/warp_grep/agent/tools/read.ts","../tools/warp_grep/agent/tools/list_directory.ts","../tools/warp_grep/agent/tools/finish.ts","../tools/warp_grep/agent/helpers.ts"],"sourcesContent":["import type { WarpGrepProvider } from '../../providers/types.js';\n\nexport async function toolGrep(\n provider: WarpGrepProvider,\n args: { pattern: string; path: string; glob?: string }\n): Promise<{ output: string }> {\n const res = await provider.grep(args);\n \n // Return errors as output - let the model see and handle them\n if (res.error) {\n return { output: res.error };\n }\n \n if (!res.lines.length) {\n return { output: 'no matches' };\n }\n \n return { output: res.lines.join('\\n') };\n}\n\n","import type { WarpGrepProvider } from '../../providers/types.js';\n\nfunction isValidRange(start: unknown, end: unknown): boolean {\n return (\n typeof start === 'number' &&\n typeof end === 'number' &&\n Number.isFinite(start) &&\n Number.isFinite(end) &&\n start > 0 &&\n end >= start\n );\n}\n\nexport async function toolRead(\n provider: WarpGrepProvider,\n args: { path: string; start?: number; end?: number; lines?: Array<[number, number]> }\n): Promise<string> {\n if (args.lines && Array.isArray(args.lines) && args.lines.length > 0) {\n const validRanges: Array<[number, number]> = [];\n for (const range of args.lines) {\n if (Array.isArray(range) && range.length >= 2 && isValidRange(range[0], range[1])) {\n validRanges.push([range[0], range[1]]);\n }\n }\n \n if (validRanges.length === 0) {\n const res = await provider.read({ path: args.path });\n if (res.error) return res.error;\n if (!res.lines.length) return '(empty file)';\n return res.lines.join('\\n');\n }\n \n const chunks: string[] = [];\n for (const [start, end] of validRanges) {\n const res = await provider.read({ path: args.path, start, end });\n if (res.error) return res.error;\n chunks.push(res.lines.join('\\n'));\n }\n if (chunks.every(c => c === '')) return '(empty file)';\n return chunks.join('\\n...\\n');\n }\n\n const res = await provider.read({ path: args.path, start: args.start, end: args.end });\n if (res.error) {\n return res.error;\n }\n if (!res.lines.length) return '(empty file)';\n return res.lines.join('\\n');\n}\n\n","import type { WarpGrepProvider } from '../../providers/types.js';\nimport { AGENT_CONFIG } from '../config.js';\n\nexport async function toolListDirectory(\n provider: WarpGrepProvider,\n args: { path: string; pattern?: string | null; maxResults?: number; maxDepth?: number }\n): Promise<string> {\n\n const maxResults = args.maxResults ?? AGENT_CONFIG.MAX_OUTPUT_LINES;\n const initialDepth = args.maxDepth ?? AGENT_CONFIG.MAX_LIST_DEPTH;\n\n type DirectoryEntries = Awaited<ReturnType<typeof provider.listDirectory>>;\n async function getListRecursive(currentDepth: number): Promise<{ entries: DirectoryEntries; }> {\n const entries = await provider.listDirectory({\n path: args.path,\n pattern: args.pattern ?? null,\n maxResults,\n maxDepth: currentDepth,\n });\n\n if (entries.length >= maxResults && currentDepth > 0) {\n return getListRecursive(currentDepth - 1);\n }\n\n return { entries };\n }\n const { entries: list } = await getListRecursive(initialDepth);\n\n if (!list.length) return 'empty';\n if (list.length >= maxResults) {\n return 'query not specific enough, tool called tried to return too much context and failed';\n }\n return list\n .map((e) => {\n const indent = ' '.repeat(e.depth);\n const name = e.type === 'dir' ? `${e.name}/` : e.name;\n return `${indent}${name}`;\n })\n .join('\\n');\n}","import type { FinishFileSpec } from '../types.js';\n\nfunction isValidRange(range: unknown): range is [number, number] {\n return (\n Array.isArray(range) &&\n range.length >= 2 &&\n typeof range[0] === 'number' &&\n typeof range[1] === 'number' &&\n Number.isFinite(range[0]) &&\n Number.isFinite(range[1]) &&\n range[0] > 0 &&\n range[1] >= range[0]\n );\n}\n\nfunction extractValidRanges(lines: unknown): Array<[number, number]> | null {\n if (!Array.isArray(lines)) return null;\n const valid: Array<[number, number]> = [];\n for (const range of lines) {\n if (isValidRange(range)) {\n valid.push([range[0], range[1]]);\n }\n }\n return valid.length > 0 ? valid : null;\n}\n\nexport function normalizeFinishFiles(files: FinishFileSpec[]): FinishFileSpec[] {\n return files.map((f) => {\n if (f.lines === '*') return { path: f.path, lines: '*' };\n const validRanges = extractValidRanges(f.lines);\n if (!validRanges) return { path: f.path, lines: '*' };\n return { path: f.path, lines: mergeRanges(validRanges) };\n });\n}\n\nexport async function readFinishFiles(\n repoRoot: string,\n files: FinishFileSpec[],\n reader: (path: string, start?: number, end?: number) => Promise<string[]>\n): Promise<{ path: string; ranges: '*' | Array<[number, number]>; content: string }[]> {\n const out: { path: string; ranges: '*' | Array<[number, number]>; content: string }[] = [];\n for (const f of files) {\n const validRanges = f.lines === '*' ? null : extractValidRanges(f.lines);\n if (f.lines === '*' || !validRanges) {\n const lines = await reader(f.path);\n out.push({ path: f.path, ranges: '*', content: lines.join('\\n') });\n } else {\n const ranges = mergeRanges(validRanges);\n const chunks: string[] = [];\n for (let i = 0; i < ranges.length; i++) {\n const [s, e] = ranges[i];\n if (i === 0 && s > 1) {\n chunks.push(`// ... existing code, block starting at line ${s} ...`);\n } else if (i > 0) {\n chunks.push(`// ... existing code, block starting at line ${s} ...`);\n }\n const lines = await reader(f.path, s, e);\n chunks.push(lines.join('\\n'));\n }\n out.push({ path: f.path, ranges, content: chunks.join('\\n') });\n }\n }\n return out;\n}\n\nfunction mergeRanges(ranges: Array<[number, number]>): Array<[number, number]> {\n if (!ranges.length) return [];\n const sorted = [...ranges].sort((a, b) => a[0] - b[0]);\n const merged: Array<[number, number]> = [];\n let [cs, ce] = sorted[0];\n for (let i = 1; i < sorted.length; i++) {\n const [s, e] = sorted[i];\n if (s <= ce + 1) {\n ce = Math.max(ce, e);\n } else {\n merged.push([cs, ce]);\n cs = s;\n ce = e;\n }\n }\n merged.push([cs, ce]);\n return merged;\n}\n\n","/**\n * Shared helper functions for warp-grep agent loop.\n * Used by both the internal runner and exported for harness users.\n */\n\nimport path from 'path';\nimport { AGENT_CONFIG } from './config.js';\nimport type { ChatMessage } from './types.js';\nimport type { WarpGrepProvider, ListDirectoryEntry } from '../providers/types.js';\n\nconst TRUNCATED_MARKER = '[truncated for context limit]';\n\n/**\n * Format the turn counter message shown to the model.\n */\nexport function formatTurnMessage(turnsUsed: number, maxTurns: number): string {\n const turnsRemaining = maxTurns - turnsUsed;\n if (turnsRemaining === 1) {\n return `\\nYou have used ${turnsUsed} turns, you only have 1 turn remaining. You have run out of turns to explore the code base and MUST call the finish tool now`;\n }\n return `\\nYou have used ${turnsUsed} turn${turnsUsed === 1 ? '' : 's'} and have ${turnsRemaining} remaining`;\n}\n\n/**\n * Calculate and format the context budget indicator.\n */\nexport function calculateContextBudget(messages: ChatMessage[]): string {\n const totalChars = messages.reduce((sum, m) => sum + m.content.length, 0);\n const maxChars = AGENT_CONFIG.MAX_CONTEXT_CHARS;\n const percent = Math.round((totalChars / maxChars) * 100);\n const usedK = Math.round(totalChars / 1000);\n const maxK = Math.round(maxChars / 1000);\n return `<context_budget>${percent}% (${usedK}K/${maxK}K chars)</context_budget>`;\n}\n\n/**\n * Build the initial state message containing repo structure and query.\n */\nexport async function buildInitialState(\n repoRoot: string,\n query: string,\n provider: WarpGrepProvider\n): Promise<string> {\n try {\n const entries = await provider.listDirectory({\n path: '.',\n maxResults: AGENT_CONFIG.MAX_OUTPUT_LINES,\n maxDepth: 2,\n });\n const treeLines = entries.map((e) => {\n const indent = ' '.repeat(e.depth);\n const name = e.type === 'dir' ? `${e.name}/` : e.name;\n return `${indent}${name}`;\n });\n\n const repoName = path.basename(repoRoot);\n const treeOutput =\n treeLines.length > 0 ? `${repoName}/\\n${treeLines.join('\\n')}` : `${repoName}/`;\n\n return `<repo_structure>\\n${treeOutput}\\n</repo_structure>\\n\\n<search_string>\\n${query}\\n</search_string>`;\n } catch {\n const repoName = path.basename(repoRoot);\n return `<repo_structure>\\n${repoName}/\\n</repo_structure>\\n\\n<search_string>\\n${query}\\n</search_string>`;\n }\n}\n\n/**\n * Format directory entries as an indented tree string.\n */\nexport function formatListDirectoryTree(entries: ListDirectoryEntry[]): string {\n if (!entries.length) return 'empty';\n return entries\n .map((e) => {\n const indent = ' '.repeat(e.depth);\n const name = e.type === 'dir' ? `${e.name}/` : e.name;\n return `${indent}${name}`;\n })\n .join('\\n');\n}\n\n/**\n * Enforce hard context limit by truncating user messages.\n * Preserves system prompt, first user message (initial query), and all assistant messages.\n * Removes tool result user messages from oldest to newest until under the threshold.\n * \n * @param messages - The conversation messages array (mutated in place)\n * @param maxChars - Maximum total character count (defaults to AGENT_CONFIG.MAX_CONTEXT_CHARS)\n * @returns The same messages array, truncated if necessary\n */\nexport function enforceContextLimit(\n messages: ChatMessage[],\n maxChars: number = AGENT_CONFIG.MAX_CONTEXT_CHARS\n): ChatMessage[] {\n const getTotalChars = () => messages.reduce((sum, m) => sum + m.content.length, 0);\n \n if (getTotalChars() <= maxChars) {\n return messages;\n }\n\n // Find indices of user messages, skipping the first one (initial query with repo structure)\n // We truncate tool result messages from oldest to newest\n const userIndices: number[] = [];\n let firstUserSkipped = false;\n for (let i = 0; i < messages.length; i++) {\n if (messages[i].role === 'user') {\n if (!firstUserSkipped) {\n firstUserSkipped = true;\n continue; // Skip first user message (contains the search query)\n }\n userIndices.push(i);\n }\n }\n\n // Truncate user messages from oldest to newest until under limit\n for (const idx of userIndices) {\n if (getTotalChars() <= maxChars) {\n break;\n }\n // Only truncate if not already truncated\n if (messages[idx].content !== TRUNCATED_MARKER) {\n messages[idx] = { role: 'user', content: TRUNCATED_MARKER };\n }\n }\n\n return messages;\n}\n\n"],"mappings":"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","names":["res","isValidRange"]}
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  executeToolCall,
7
7
  formatResult
8
- } from "./chunk-UILVPDO3.js";
8
+ } from "./chunk-23R562QJ.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-3L6QGAMK.js.map
53
+ //# sourceMappingURL=chunk-ALTKGCG5.js.map
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  executeToolCall,
7
7
  formatResult
8
- } from "./chunk-UILVPDO3.js";
8
+ } from "./chunk-23R562QJ.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-QE53XISP.js.map
61
+ //# sourceMappingURL=chunk-FL4ZBHK2.js.map
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-KW7OEGZK.js";
4
4
  import {
5
5
  executeToolCall
6
- } from "./chunk-UILVPDO3.js";
6
+ } from "./chunk-23R562QJ.js";
7
7
 
8
8
  // tools/warp_grep/vercel.ts
9
9
  import { tool } from "ai";
@@ -50,4 +50,4 @@ export {
50
50
  createWarpGrepTool,
51
51
  vercel_default
52
52
  };
53
- //# sourceMappingURL=chunk-EREXPWY4.js.map
53
+ //# sourceMappingURL=chunk-HI35Y6EZ.js.map
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  createWarpGrepTool
3
- } from "./chunk-QE53XISP.js";
3
+ } from "./chunk-FL4ZBHK2.js";
4
4
  import {
5
5
  createWarpGrepTool as createWarpGrepTool3
6
- } from "./chunk-EREXPWY4.js";
6
+ } from "./chunk-HI35Y6EZ.js";
7
7
  import {
8
8
  createWarpGrepTool as createWarpGrepTool2
9
- } from "./chunk-3L6QGAMK.js";
9
+ } from "./chunk-ALTKGCG5.js";
10
10
  import {
11
11
  WarpGrepClient
12
- } from "./chunk-UILVPDO3.js";
12
+ } from "./chunk-23R562QJ.js";
13
13
  import {
14
14
  createCodebaseSearchTool as createCodebaseSearchTool3
15
15
  } from "./chunk-O5DA5V5S.js";
@@ -77,11 +77,13 @@ var PermissionError = class extends GitHubError {
77
77
  };
78
78
 
79
79
  // tools/github/core.ts
80
- var DEFAULT_BASE_URL = "https://api.morphllm.com";
80
+ var LANDING_BASE_URL = "https://api.morphllm.com";
81
+ var BACKEND_BASE_URL = "https://browser.morphllm.com";
81
82
  var DEFAULT_TIMEOUT = 3e4;
82
83
  var GitHubClient = class {
83
84
  apiKey;
84
- baseUrl;
85
+ landingUrl;
86
+ backendUrl;
85
87
  timeout;
86
88
  debug;
87
89
  defaultInstallationId;
@@ -89,6 +91,8 @@ var GitHubClient = class {
89
91
  installations;
90
92
  /** Repository operations */
91
93
  repos;
94
+ /** Project operations (monorepo sub-projects) */
95
+ projects;
92
96
  /** Pull request operations */
93
97
  pullRequests;
94
98
  /** Deployment operations */
@@ -97,9 +101,17 @@ var GitHubClient = class {
97
101
  comments;
98
102
  /** Check run operations */
99
103
  checkRuns;
104
+ /**
105
+ * Get the GitHub App installation URL.
106
+ * Users visit this URL once to install the Morph GitHub App on their account/org.
107
+ */
108
+ getInstallUrl() {
109
+ return "https://github.com/apps/morph-subagents/installations/new";
110
+ }
100
111
  constructor(config = {}) {
101
112
  this.apiKey = config.apiKey || process.env.MORPH_API_KEY || "";
102
- this.baseUrl = config.baseUrl || DEFAULT_BASE_URL;
113
+ this.landingUrl = config.baseUrl || LANDING_BASE_URL;
114
+ this.backendUrl = config.backendUrl || BACKEND_BASE_URL;
103
115
  this.timeout = config.timeout || DEFAULT_TIMEOUT;
104
116
  this.debug = config.debug || false;
105
117
  this.defaultInstallationId = config.installationId;
@@ -108,10 +120,22 @@ var GitHubClient = class {
108
120
  }
109
121
  this.installations = {
110
122
  list: this.listInstallations.bind(this),
111
- get: this.getInstallation.bind(this)
123
+ get: this.getInstallation.bind(this),
124
+ update: this.updateInstallation.bind(this),
125
+ disconnect: this.disconnectInstallation.bind(this)
112
126
  };
113
127
  this.repos = {
114
- list: this.listRepos.bind(this)
128
+ list: this.listRepos.bind(this),
129
+ get: this.getRepo.bind(this),
130
+ update: this.updateRepo.bind(this),
131
+ remove: this.removeRepo.bind(this),
132
+ sync: this.syncRepos.bind(this)
133
+ };
134
+ this.projects = {
135
+ list: this.listProjects.bind(this),
136
+ create: this.createProject.bind(this),
137
+ update: this.updateProject.bind(this),
138
+ delete: this.deleteProject.bind(this)
115
139
  };
116
140
  this.pullRequests = {
117
141
  list: this.listPullRequests.bind(this),
@@ -132,10 +156,24 @@ var GitHubClient = class {
132
156
  };
133
157
  }
134
158
  /**
135
- * Make an API request to the Morph GitHub proxy
159
+ * Make an API request to the browser backend (CRUD endpoints)
136
160
  */
137
161
  async request(method, path, body) {
138
- const url = `${this.baseUrl}${path}`;
162
+ return this._fetch(this.backendUrl, method, path, body);
163
+ }
164
+ // TODO: These endpoints use Octokit and currently live in landing.
165
+ // Move them to the backend so all GitHub SDK traffic goes through a single URL.
166
+ /**
167
+ * Make an API request to the landing app (Octokit-based endpoints)
168
+ */
169
+ async landingRequest(method, path, body) {
170
+ return this._fetch(this.landingUrl, method, path, body);
171
+ }
172
+ /**
173
+ * Shared fetch logic for both backend and landing requests
174
+ */
175
+ async _fetch(baseUrl, method, path, body) {
176
+ const url = `${baseUrl}${path}`;
139
177
  if (this.debug) {
140
178
  console.log(`[GitHub SDK] ${method} ${path}`, body || "");
141
179
  }
@@ -154,7 +192,7 @@ var GitHubClient = class {
154
192
  clearTimeout(timeoutId);
155
193
  if (!response.ok) {
156
194
  const errorData = await response.json().catch(() => ({}));
157
- const message = errorData.error || errorData.message || response.statusText;
195
+ const message = errorData.error || errorData.detail || errorData.message || response.statusText;
158
196
  if (this.debug) {
159
197
  console.error(`[GitHub SDK] Error ${response.status}:`, message);
160
198
  }
@@ -204,6 +242,15 @@ var GitHubClient = class {
204
242
  async getInstallation(installationId) {
205
243
  return this.request("GET", `/api/v1/github/installations/${installationId}`);
206
244
  }
245
+ async updateInstallation(input) {
246
+ if (this.debug) console.log("[GitHub SDK] updateInstallation", input.installationId);
247
+ const { installationId, ...body } = input;
248
+ return this.request("PATCH", `/api/v1/github/installations/${installationId}`, body);
249
+ }
250
+ async disconnectInstallation(installationId) {
251
+ if (this.debug) console.log("[GitHub SDK] disconnectInstallation", installationId);
252
+ return this.request("DELETE", `/api/v1/github/installations/${installationId}`);
253
+ }
207
254
  // ==========================================================================
208
255
  // Repositories
209
256
  // ==========================================================================
@@ -214,8 +261,51 @@ var GitHubClient = class {
214
261
  }
215
262
  return this.request("GET", `/api/v1/github/installations/${installationId}/repos`);
216
263
  }
264
+ async getRepo(repoId) {
265
+ if (this.debug) console.log("[GitHub SDK] getRepo", repoId);
266
+ return this.request("GET", `/api/v1/github/repos/${repoId}`);
267
+ }
268
+ async updateRepo(input) {
269
+ if (this.debug) console.log("[GitHub SDK] updateRepo", input.repoId);
270
+ const { repoId, ...body } = input;
271
+ return this.request("PATCH", `/api/v1/github/repos/${repoId}`, body);
272
+ }
273
+ async removeRepo(repoId) {
274
+ if (this.debug) console.log("[GitHub SDK] removeRepo", repoId);
275
+ return this.request("DELETE", `/api/v1/github/repos/${repoId}`);
276
+ }
277
+ async syncRepos(input) {
278
+ const installationId = input.installationId || this.defaultInstallationId;
279
+ if (!installationId) {
280
+ throw new NoInstallationError("installationId required. Call installations.list() first.");
281
+ }
282
+ if (this.debug) console.log("[GitHub SDK] syncRepos", installationId);
283
+ return this.request("POST", `/api/v1/github/installations/${installationId}/repos/sync`);
284
+ }
285
+ // ==========================================================================
286
+ // Projects (monorepo sub-projects)
287
+ // ==========================================================================
288
+ async listProjects(input) {
289
+ if (this.debug) console.log("[GitHub SDK] listProjects", input.repoId);
290
+ return this.request("GET", `/api/v1/github/repos/${input.repoId}/projects`);
291
+ }
292
+ async createProject(input) {
293
+ if (this.debug) console.log("[GitHub SDK] createProject", input.repoId, input.name);
294
+ const { repoId, ...body } = input;
295
+ return this.request("POST", `/api/v1/github/repos/${repoId}/projects`, body);
296
+ }
297
+ async updateProject(input) {
298
+ if (this.debug) console.log("[GitHub SDK] updateProject", input.projectId);
299
+ const { projectId, ...body } = input;
300
+ return this.request("PATCH", `/api/v1/github/projects/${projectId}`, body);
301
+ }
302
+ async deleteProject(projectId) {
303
+ if (this.debug) console.log("[GitHub SDK] deleteProject", projectId);
304
+ return this.request("DELETE", `/api/v1/github/projects/${projectId}`);
305
+ }
217
306
  // ==========================================================================
218
307
  // Pull Requests
308
+ // TODO: Move to backend — currently uses Octokit in landing
219
309
  // ==========================================================================
220
310
  async listPullRequests(input) {
221
311
  const installationId = this.getInstallationId(input);
@@ -225,7 +315,7 @@ var GitHubClient = class {
225
315
  ...input.state && { state: input.state },
226
316
  ...installationId && { installationId }
227
317
  });
228
- return this.request("GET", `/api/v1/github/pulls?${params}`);
318
+ return this.landingRequest("GET", `/api/v1/github/pulls?${params}`);
229
319
  }
230
320
  async getPullRequest(input) {
231
321
  const installationId = this.getInstallationId(input);
@@ -234,13 +324,14 @@ var GitHubClient = class {
234
324
  repo: input.repo,
235
325
  ...installationId && { installationId }
236
326
  });
237
- return this.request(
327
+ return this.landingRequest(
238
328
  "GET",
239
329
  `/api/v1/github/pulls/${input.number}?${params}`
240
330
  );
241
331
  }
242
332
  // ==========================================================================
243
333
  // Deployments
334
+ // TODO: Move to backend — currently uses Octokit in landing
244
335
  // ==========================================================================
245
336
  async listDeployments(input) {
246
337
  const installationId = this.getInstallationId(input);
@@ -251,10 +342,11 @@ var GitHubClient = class {
251
342
  ...input.environment && { environment: input.environment },
252
343
  ...installationId && { installationId }
253
344
  });
254
- return this.request("GET", `/api/v1/github/deployments?${params}`);
345
+ return this.landingRequest("GET", `/api/v1/github/deployments?${params}`);
255
346
  }
256
347
  // ==========================================================================
257
348
  // Comments
349
+ // TODO: Move to backend — currently uses Octokit in landing
258
350
  // ==========================================================================
259
351
  async listComments(input) {
260
352
  const installationId = this.getInstallationId(input);
@@ -264,11 +356,11 @@ var GitHubClient = class {
264
356
  pr: String(input.pr),
265
357
  ...installationId && { installationId }
266
358
  });
267
- return this.request("GET", `/api/v1/github/comments?${params}`);
359
+ return this.landingRequest("GET", `/api/v1/github/comments?${params}`);
268
360
  }
269
361
  async createComment(input) {
270
362
  const installationId = this.getInstallationId(input);
271
- return this.request("POST", "/api/v1/github/comments", {
363
+ return this.landingRequest("POST", "/api/v1/github/comments", {
272
364
  owner: input.owner,
273
365
  repo: input.repo,
274
366
  pr: input.pr,
@@ -278,7 +370,7 @@ var GitHubClient = class {
278
370
  }
279
371
  async updateComment(input) {
280
372
  const installationId = this.getInstallationId(input);
281
- return this.request("PATCH", `/api/v1/github/comments/${input.commentId}`, {
373
+ return this.landingRequest("PATCH", `/api/v1/github/comments/${input.commentId}`, {
282
374
  owner: input.owner,
283
375
  repo: input.repo,
284
376
  body: input.body,
@@ -292,14 +384,15 @@ var GitHubClient = class {
292
384
  repo: input.repo,
293
385
  ...installationId && { installationId }
294
386
  });
295
- await this.request("DELETE", `/api/v1/github/comments/${input.commentId}?${params}`);
387
+ await this.landingRequest("DELETE", `/api/v1/github/comments/${input.commentId}?${params}`);
296
388
  }
297
389
  // ==========================================================================
298
390
  // Check Runs
391
+ // TODO: Move to backend — currently uses Octokit in landing
299
392
  // ==========================================================================
300
393
  async createCheckRun(input) {
301
394
  const installationId = this.getInstallationId(input);
302
- return this.request("POST", "/api/v1/github/check-runs", {
395
+ return this.landingRequest("POST", "/api/v1/github/check-runs", {
303
396
  owner: input.owner,
304
397
  repo: input.repo,
305
398
  sha: input.sha,
@@ -312,7 +405,7 @@ var GitHubClient = class {
312
405
  }
313
406
  async updateCheckRun(input) {
314
407
  const installationId = this.getInstallationId(input);
315
- return this.request("PATCH", `/api/v1/github/check-runs/${input.checkRunId}`, {
408
+ return this.landingRequest("PATCH", `/api/v1/github/check-runs/${input.checkRunId}`, {
316
409
  owner: input.owner,
317
410
  repo: input.repo,
318
411
  ...input.status && { status: input.status },
@@ -571,4 +664,4 @@ export {
571
664
  VercelToolFactory,
572
665
  MorphClient
573
666
  };
574
- //# sourceMappingURL=chunk-PRKYN7WR.js.map
667
+ //# sourceMappingURL=chunk-JYKYQ5DN.js.map