Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/types/src/global-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ export const SECRET_STATE_KEYS = [
"fireworksApiKey",
"featherlessApiKey",
"ioIntelligenceApiKey",
"morphApiKey",
"vercelAiGatewayApiKey",
] as const

Expand Down
4 changes: 4 additions & 0 deletions packages/types/src/provider-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment formatting here doesn't match the established pattern in this file. Other optional sections use a format like:

But this uses:

Minor inconsistency, but worth keeping the style uniform.

morphFastApplyEnabled: z.boolean().optional(),
morphApiKey: z.string().optional(),

modelTemperature: z.number().nullish(),
rateLimitSeconds: z.number().optional(),
consecutiveMistakeLimit: z.number().min(0).optional(),
Expand Down
7 changes: 4 additions & 3 deletions src/core/task/Task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic here gives Morph Fast Apply precedence over the experiment flag, but this priority isn't documented. Could we add a comment explaining why morphFastApplyEnabled takes priority? Something like:

this.diffStrategy = new MultiFileSearchReplaceDiffStrategy(this.fuzzyMatchThreshold)
}
})
Expand Down
11 changes: 8 additions & 3 deletions src/core/webview/generateSystemPrompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the same strategy selection logic as in Task.ts. Consider extracting this to a shared utility function to avoid duplication and ensure consistency. Something like:

? new MultiFileSearchReplaceDiffStrategy(fuzzyMatchThreshold)
: new MultiSearchReplaceDiffStrategy(fuzzyMatchThreshold)
: isMultiFileApplyDiffEnabled
? new MultiFileSearchReplaceDiffStrategy(fuzzyMatchThreshold)
: new MultiSearchReplaceDiffStrategy(fuzzyMatchThreshold)

const cwd = provider.cwd

Expand Down
28 changes: 27 additions & 1 deletion webview-ui/src/components/settings/ApiOptions.tsx
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -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>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing i18n for these UI strings. The rest of the application uses translation keys from the i18n system, but these new controls have hardcoded English text:

  • "Morph Fast Apply"
  • "Enable Morph Fast Apply (fuzzy multi-file)"
  • "Morph API key (optional)"
  • "When enabled, apply_diff uses faster tolerant matching..."

Consider adding these to the translation files for consistency.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider replacing the hardcoded label text 'Morph Fast Apply' with a translatable string (e.g. using t('settings:providers.morphFastApply.title')) to support internationalization.

Suggested change
<label className="block font-medium">Morph Fast Apply</label>
<label className="block font-medium">{t('settings:providers.morphFastApply.title')}</label>

This comment was generated because it violated a code review rule: irule_C0ez7Rji6ANcGkkX.

<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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace the checkbox text 'Enable Morph Fast Apply (fuzzy multi-file)' with a translatable string to ensure consistency with the app’s localization strategy.

Suggested change
Enable Morph Fast Apply (fuzzy multi-file)
{t('settings:advancedSettings.enableMorphFastApply')}

This comment was generated because it violated a code review rule: irule_C0ez7Rji6ANcGkkX.

</VSCodeCheckbox>

<VSCodeTextField
value={apiConfiguration?.morphApiKey || ""}
type="password"
onInput={(e: any) => setApiConfigurationField("morphApiKey", e.target.value)}
placeholder="Optional API key">
Morph API key (optional)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace the inner text 'Morph API key (optional)' in the VSCodeTextField with a call to the translation function (e.g. t('settings:providers.morphApiKey.label')) to support i18n.

Suggested change
Morph API key (optional)
{t('settings:providers.morphApiKey.label')}

This comment was generated because it violated a code review rule: irule_C0ez7Rji6ANcGkkX.

</VSCodeTextField>
<div className="text-sm text-vscode-descriptionForeground">
When enabled, apply_diff uses faster tolerant matching across multiple files. An API
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace the hardcoded description text with a translatable string so that this user-facing message can be localized.

This comment was generated because it violated a code review rule: irule_C0ez7Rji6ANcGkkX.

key is only required if using a hosted Morph service.
</div>
</div>
</div>
{selectedModelInfo?.supportsTemperature !== false && (
<TemperatureControl
value={apiConfiguration.modelTemperature}
Expand Down
Loading