Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,25 @@ import {transformedPromptsAtomFamily} from "@/oss/state/newPlayground/core/promp

import {CommitVariantChangesModalContentProps} from "../types"

// ===== Diff helpers (field-level diff) =====
type DiffInput = Record<string, unknown>

function buildPromptDiffInput(params?: Record<string, any>): DiffInput {
if (!params) return {}
return {
prompt: params.prompt,
Copy link
Member

Choose a reason for hiding this comment

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

This assumes there is a property called prompt in params. That is not always the case (for instance with custom workflows)

Copy link
Author

Choose a reason for hiding this comment

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

Good point — agreed.

The current version assumes a top-level prompt field, which won’t hold for custom workflows or alternative config shapes.

I’ll update the diff input builder to iterate over the config entries and extract nested prompt fields only when present, so the diff remains field-level without making assumptions about the schema.

}
}
Comment on lines +23 to +28
Copy link
Contributor

Choose a reason for hiding this comment

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

🟡 buildPromptDiffInput extracts non-existent prompt property, resulting in empty diff

The buildPromptDiffInput function extracts params.prompt assuming there's a top-level prompt property, but the actual data structure has prompt names as keys with prompt as a nested property inside each.

Click to expand

Data Structure Mismatch

The params variable (line 94) is either:

  • derivedAgConfig from transformedPromptsAtomFamily(variantId)?.ag_config - which has structure like { "promptName": { prompt: [...], llm_config: {...} } }
  • jsonOverride - a parameters override object
  • variant.parameters - which has structure like { ag_config: { promptName: { ... } } }

The buildPromptDiffInput function at lines 23-28:

function buildPromptDiffInput(params?: Record<string, any>): DiffInput {
    if (!params) return {}
    return {
        prompt: params.prompt,  // This will be undefined!
    }
}

Since params.prompt is undefined (the actual prompt arrays are nested under prompt name keys), the function returns { prompt: undefined }. When JSON.stringify is called on this, the undefined value is omitted, resulting in "{}".

Impact

The diff preview in the commit modal will always show an empty or near-empty comparison (e.g., {} vs {}), making it useless for reviewing actual prompt changes before committing.

Recommendation: The function should iterate over the prompt keys in the config object and extract the nested prompt arrays. For example:

function buildPromptDiffInput(params?: Record<string, any>): DiffInput {
    if (!params) return {}
    const result: DiffInput = {}
    for (const [key, value] of Object.entries(params)) {
        if (value && typeof value === 'object' && 'prompt' in value) {
            result[key] = { prompt: value.prompt }
        }
    }
    return result
}
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.


function stringifyForDiff(input: DiffInput): string {
try {
return JSON.stringify(input, null, 2)
} catch {
return ""
}
}


const {Text} = Typography

const CommitVariantChangesModalContent = ({
Expand Down Expand Up @@ -80,10 +99,14 @@ const CommitVariantChangesModalContent = ({
// Compute snapshot lazily on first render after mount
if (variant && initialOriginalRef.current === null && initialModifiedRef.current === null) {
try {
initialOriginalRef.current = JSON.stringify(sanitizedOldParams)
initialOriginalRef.current = stringifyForDiff(
buildPromptDiffInput(sanitizedOldParams),
)
// Use the same transformed local prompts ag_config that drives dirty-state
if (params !== undefined) {
initialModifiedRef.current = JSON.stringify(sanitizedParams)
initialModifiedRef.current = stringifyForDiff(
buildPromptDiffInput(sanitizedParams),
)
}
} catch {
// Keep refs null; we will fall back to live values below
Expand All @@ -98,9 +121,13 @@ const CommitVariantChangesModalContent = ({
}))

// Ensure DiffView gets strings even when params are undefined
const originalForDiff = initialOriginalRef.current ?? JSON.stringify(sanitizedOldParams ?? {})
const originalForDiff =
initialOriginalRef.current ??
stringifyForDiff(buildPromptDiffInput(sanitizedOldParams))

const modifiedForDiff =
initialModifiedRef.current ?? JSON.stringify(sanitizedParams ?? sanitizedOldParams ?? {})
initialModifiedRef.current ??
stringifyForDiff(buildPromptDiffInput(sanitizedParams ?? sanitizedOldParams))

return (
<div className="flex h-full min-h-0 flex-col gap-6 md:flex-row">
Expand Down