feat(morph): add Morph Fast Apply settings and strategy selection

This commit is contained in:
Roo Code 2025-09-09 20:34:32 +00:00
parent bbd3d9883b
commit cc6a3b89e9
5 changed files with 44 additions and 7 deletions

View file

@ -205,6 +205,7 @@ export const SECRET_STATE_KEYS = [
"fireworksApiKey",
"featherlessApiKey",
"ioIntelligenceApiKey",
"morphApiKey",
"vercelAiGatewayApiKey",
] as const

View file

@ -101,6 +101,10 @@ const baseProviderSettingsSchema = z.object({
diffEnabled: z.boolean().optional(),
todoListEnabled: z.boolean().optional(),
fuzzyMatchThreshold: z.number().optional(),
// Morph Fast Apply - optional provider-scoped controls
morphFastApplyEnabled: z.boolean().optional(),
morphApiKey: z.string().optional(),
modelTemperature: z.number().nullish(),
rateLimitSeconds: z.number().optional(),
consecutiveMistakeLimit: z.number().min(0).optional(),

View file

@ -394,17 +394,18 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
// Only set up diff strategy if diff is enabled.
if (this.diffEnabled) {
// Default to old strategy, will be updated if experiment is enabled.
// Default to legacy single-file strategy
this.diffStrategy = new MultiSearchReplaceDiffStrategy(this.fuzzyMatchThreshold)
// Check experiment asynchronously and update strategy if needed.
// Prefer MultiFile when Morph Fast Apply is enabled, otherwise respect experiment flag.
provider.getState().then((state) => {
const isMultiFileApplyDiffEnabled = experiments.isEnabled(
state.experiments ?? {},
EXPERIMENT_IDS.MULTI_FILE_APPLY_DIFF,
)
const isMorphFastApplyEnabled = state.apiConfiguration?.morphFastApplyEnabled === true
if (isMultiFileApplyDiffEnabled) {
if (isMorphFastApplyEnabled || isMultiFileApplyDiffEnabled) {
this.diffStrategy = new MultiFileSearchReplaceDiffStrategy(this.fuzzyMatchThreshold)
}
})

View file

@ -27,15 +27,20 @@ export const generateSystemPrompt = async (provider: ClineProvider, message: Web
maxConcurrentFileReads,
} = await provider.getState()
// Check experiment to determine which diff strategy to use
// Determine which diff strategy to use:
// - If Morph Fast Apply is enabled, force MultiFile strategy for best tolerance and batching
// - Otherwise, fall back to experiment flag to choose between MultiFile and single-file strategies
const isMultiFileApplyDiffEnabled = experimentsModule.isEnabled(
experiments ?? {},
EXPERIMENT_IDS.MULTI_FILE_APPLY_DIFF,
)
const isMorphFastApplyEnabled = apiConfiguration?.morphFastApplyEnabled === true
const diffStrategy = isMultiFileApplyDiffEnabled
const diffStrategy = isMorphFastApplyEnabled
? new MultiFileSearchReplaceDiffStrategy(fuzzyMatchThreshold)
: new MultiSearchReplaceDiffStrategy(fuzzyMatchThreshold)
: isMultiFileApplyDiffEnabled
? new MultiFileSearchReplaceDiffStrategy(fuzzyMatchThreshold)
: new MultiSearchReplaceDiffStrategy(fuzzyMatchThreshold)
const cwd = provider.cwd

View file

@ -1,7 +1,7 @@
import React, { memo, useCallback, useEffect, useMemo, useState } from "react"
import { convertHeadersToObject } from "./utils/headers"
import { useDebounce } from "react-use"
import { VSCodeLink, VSCodeButton } from "@vscode/webview-ui-toolkit/react"
import { VSCodeLink, VSCodeButton, VSCodeCheckbox, VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
import { ExternalLinkIcon } from "@radix-ui/react-icons"
import {
@ -765,6 +765,32 @@ const ApiOptions = ({
fuzzyMatchThreshold={apiConfiguration.fuzzyMatchThreshold}
onChange={(field, value) => setApiConfigurationField(field, value)}
/>
{/* Morph Fast Apply - provider-scoped controls */}
<div className="pl-3 border-l-2 border-vscode-button-background space-y-2">
<label className="block font-medium">Morph Fast Apply</label>
<div className="flex flex-col gap-1">
<VSCodeCheckbox
checked={Boolean(apiConfiguration.morphFastApplyEnabled)}
onChange={(e: any) =>
setApiConfigurationField("morphFastApplyEnabled", e.target.checked)
}>
Enable Morph Fast Apply (fuzzy multi-file)
</VSCodeCheckbox>
<VSCodeTextField
value={apiConfiguration?.morphApiKey || ""}
type="password"
onInput={(e: any) => setApiConfigurationField("morphApiKey", e.target.value)}
placeholder="Optional API key">
Morph API key (optional)
</VSCodeTextField>
<div className="text-sm text-vscode-descriptionForeground">
When enabled, apply_diff uses faster tolerant matching across multiple files. An API
key is only required if using a hosted Morph service.
</div>
</div>
</div>
{selectedModelInfo?.supportsTemperature !== false && (
<TemperatureControl
value={apiConfiguration.modelTemperature}