Skip to content

feat: add DAG definition improvement flow from the spec editor#1980

Merged
yohamta0 merged 3 commits into
mainfrom
feat/dag-definition-improvement-agent-flow
Apr 9, 2026
Merged

feat: add DAG definition improvement flow from the spec editor#1980
yohamta0 merged 3 commits into
mainfrom
feat/dag-definition-improvement-agent-flow

Conversation

@yohamta0

@yohamta0 yohamta0 commented Apr 9, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • add an Improve action to the DAG spec editor that opens a focused modal for describing what part of the definition should be improved
  • start a fresh agent session from that modal with the DAG reference, the latest DAG run details, and the user prompt so the agent can update the definition with that context
  • add prompt-building helpers and tests for the improvement-session bootstrap, and keep the UI typecheck green with the missing components import in the queues page

Test plan

  • pnpm typecheck
  • pnpm test -- improveDagDefinitionPrompt

Summary by CodeRabbit

  • New Features
    • Added "Improve" button to DAG editor interface, enabling users to request AI-powered suggestions for enhancing DAG definitions.
    • New improvement dialog collects user instructions and displays latest DAG run context (including status and error details) to provide relevant improvement recommendations.
    • Improvement requests are blocked while unsaved edits exist, ensuring data integrity before submission.

@coderabbitai

coderabbitai Bot commented Apr 9, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 056b137a-cb55-45ff-9b7e-c7da10f5bfc3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

These changes extend the DAG details components to pass latest run information through the hierarchy and introduce an "Improve DAG Definition" feature that integrates with AI agent chat orchestration. New prompt-building utilities construct contextual improvement requests from DAG file content, run metadata, and identified failure points.

Changes

Cohort / File(s) Summary
Data Threading
ui/src/features/dags/components/dag-details/DAGDetailsContent.tsx, ui/src/features/dags/components/dag-details/DAGDetailsPanel.tsx, ui/src/pages/dags/dag/index.tsx
Added optional latestDAGRun prop to component signature and destructuring; threaded through component hierarchy from page to details panel to content component.
Improve Modal Component
ui/src/features/dags/components/dag-editor/ImproveDAGDefinitionModal.tsx
New dialog component that collects user improvement prompts, displays DAG metadata and run status badges, validates submission, and manages loading state during async operations.
Improve Prompt Utilities
ui/src/features/dags/components/dag-editor/improveDagDefinitionPrompt.ts
New module exporting buildImproveDAGDefinitionPrompt() and formatLatestDAGRunDetail() functions; constructs contextual improvement prompts with DAG file, run metadata, and problematic step summaries from failed nodes.
DAG Editor Integration
ui/src/features/dags/components/dag-editor/DAGSpec.tsx
Added latestDAGRun prop, integrated useAgentChatContext() hook, implemented handleImproveSubmit() callback for agent session creation via POST to /agent/sessions, added modal rendering and "Improve" button in header with sparkles icon.
Prompt Test Suite
ui/src/features/dags/components/dag-editor/__tests__/improveDagDefinitionPrompt.test.ts
New Vitest suite testing prompt construction with realistic failed DAG run context, including problematic node detection and fallback message handling.
Minor Type Update
ui/src/pages/queues/index.tsx
Added import of components schema and applied type cast to error object as components['schemas']['Error'].

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Modal as ImproveDAG<br/>Modal
    participant DAGSpec as DAGSpec<br/>Component
    participant API as Agent<br/>API
    participant Chat as Agent Chat<br/>Context

    User->>Modal: Opens improve dialog
    User->>Modal: Enters improvement prompt
    User->>Modal: Clicks "Start Improvement"
    
    Modal->>Modal: Validates prompt (non-empty)
    Modal->>DAGSpec: onSubmit(userPrompt)
    
    DAGSpec->>DAGSpec: Check for unsaved edits
    alt Has unsaved edits
        DAGSpec->>Modal: Show error
    else Ready to improve
        DAGSpec->>DAGSpec: buildImproveDAGDefinitionPrompt()<br/>(dagFile, dagName,<br/>latestDAGRun, userPrompt)
        DAGSpec->>API: POST /agent/sessions<br/>(with contextual prompt)
        API-->>DAGSpec: Return session ID
        DAGSpec->>Chat: Initialize agent session<br/>setAgentSession()
        DAGSpec->>Chat: Set pending message<br/>setUserPendingMessage()
        DAGSpec->>Modal: Close modal
        DAGSpec->>Chat: Open chat panel
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and specifically describes the main feature addition: an improvement flow for DAG definitions accessible from the spec editor.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/dag-definition-improvement-agent-flow

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (1)
ui/src/features/dags/components/dag-editor/ImproveDAGDefinitionModal.tsx (1)

89-103: Tighten modal density to match the compact UI standard.

This modal currently uses roomier spacing/background choices than the repository’s compact modal/input/metadata conventions. Consider reducing header/content padding and aligning metadata/input styling with the prescribed compact classes.

As per coding guidelines, ui/**/*.{ts,tsx}: Keep modal headers small and information-dense with minimal padding (p-2 or p-3 instead of p-4 or p-6); ensure all form inputs use compact padding (py-0.5 or py-1) and consistent background colors; use consistent metadata styling with bg-slate-200 dark:bg-slate-700.

Also applies to: 122-145

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/src/features/dags/components/dag-editor/ImproveDAGDefinitionModal.tsx`
around lines 89 - 103, The modal in ImproveDAGDefinitionModal (components
DialogContent, DialogHeader, DialogTitle, DialogDescription and the inner
container divs) uses too-large spacing and non-compact backgrounds; update the
classNames to the repository’s compact conventions: reduce header/content
padding to p-2 or p-3 on DialogHeader/DialogContent, change inner container
padding from p-4 to p-2/p-3, switch form/input padding to py-0.5 or py-1, and
normalize metadata/background colors to bg-slate-200 dark:bg-slate-700 (and
remove muted/40 where present) so the modal matches the compact UI standards.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@ui/src/features/dags/components/dag-editor/__tests__/improveDagDefinitionPrompt.test.ts`:
- Line 1: This new test file improveDagDefinitionPrompt.test.ts is missing the
project's GPL v3 license header; add the standard GPL v3 license header block at
the very top of the file (matching other .ts/.tsx files in the repo) and then
run the repository tool to apply/verify headers (e.g., run make addlicense) so
the file conforms to the project's license header policy.

In `@ui/src/features/dags/components/dag-editor/ImproveDAGDefinitionModal.tsx`:
- Line 1: This new TypeScript React file is missing the GPLv3 license header;
add the standard GPL v3 header comment at the very top of
ImproveDAGDefinitionModal.tsx (above the existing import lines, e.g., above
"import { components, StatusLabel } from '@/api/v1/schema';"), then run the
repository license/header step (e.g., make addlicense or the project's
license-header task) to ensure formatting and consistency with the project's
GPLv3 headers.

In `@ui/src/features/dags/components/dag-editor/improveDagDefinitionPrompt.ts`:
- Line 1: This file is missing the required GPL v3 license header; add the
standard GPL v3 header block at the very top of the file (before the existing
import line "import { components, NodeStatus } from '@/api/v1/schema';") so the
file complies with the repository rule for .ts/.tsx files; you can either run
the repo's automated tool (make addlicense) or manually insert the canonical GPL
v3 header comment block above the import to satisfy the guideline.
- Around line 81-83: latestDAGRun.params is being embedded into the agent prompt
verbatim (via formatParams), which risks leaking secrets; update the code to
sanitize/redact sensitive values before formatting and embedding. Implement or
call a helper (e.g., sanitizeParams or maskSensitiveValues) that walks
latestDAGRun.params and replaces values for keys like "token", "secret",
"password", "api_key", "access_token" (and other common secret patterns) with a
masked placeholder (e.g., "<REDACTED>") or truncates long opaque values, then
pass the sanitized output into formatParams; apply the same change wherever
latestDAGRun.params is used for prompts (including the other usage around lines
122-128) so all prompt embeddings use the sanitized params.

---

Nitpick comments:
In `@ui/src/features/dags/components/dag-editor/ImproveDAGDefinitionModal.tsx`:
- Around line 89-103: The modal in ImproveDAGDefinitionModal (components
DialogContent, DialogHeader, DialogTitle, DialogDescription and the inner
container divs) uses too-large spacing and non-compact backgrounds; update the
classNames to the repository’s compact conventions: reduce header/content
padding to p-2 or p-3 on DialogHeader/DialogContent, change inner container
padding from p-4 to p-2/p-3, switch form/input padding to py-0.5 or py-1, and
normalize metadata/background colors to bg-slate-200 dark:bg-slate-700 (and
remove muted/40 where present) so the modal matches the compact UI standards.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: af3999d6-532e-4185-a7ec-512f122ca2bc

📥 Commits

Reviewing files that changed from the base of the PR and between 9d80ee8 and 710f70f.

📒 Files selected for processing (8)
  • ui/src/features/dags/components/dag-details/DAGDetailsContent.tsx
  • ui/src/features/dags/components/dag-details/DAGDetailsPanel.tsx
  • ui/src/features/dags/components/dag-editor/DAGSpec.tsx
  • ui/src/features/dags/components/dag-editor/ImproveDAGDefinitionModal.tsx
  • ui/src/features/dags/components/dag-editor/__tests__/improveDagDefinitionPrompt.test.ts
  • ui/src/features/dags/components/dag-editor/improveDagDefinitionPrompt.ts
  • ui/src/pages/dags/dag/index.tsx
  • ui/src/pages/queues/index.tsx

@@ -0,0 +1,79 @@
import {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add the GPL v3 license header to this new source file.

This file is newly introduced and should include the project’s required license header.

As per coding guidelines, **/*.{go,ts,tsx,js}: Apply GPL v3 license headers on source files, managed via make addlicense.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@ui/src/features/dags/components/dag-editor/__tests__/improveDagDefinitionPrompt.test.ts`
at line 1, This new test file improveDagDefinitionPrompt.test.ts is missing the
project's GPL v3 license header; add the standard GPL v3 license header block at
the very top of the file (matching other .ts/.tsx files in the repo) and then
run the repository tool to apply/verify headers (e.g., run make addlicense) so
the file conforms to the project's license header policy.

Comment on lines +290 to +359
const handleImproveSubmit = React.useCallback(
async (userPrompt: string) => {
if (localHasUnsavedChanges) {
showError(
'Save or discard local edits first',
'The agent can only improve the saved DAG definition that exists on disk.'
);
return;
}

setIsLaunchingImproveSession(true);
clearAgentSession();
setPendingUserMessage(userPrompt);

const { data: sessionData, error } = await client.POST('/agent/sessions', {
params: {
query: { remoteNode },
},
body: {
message: buildImproveDAGDefinitionPrompt({
dagFile: fileName,
dagName: data?.dag?.name || fileName,
latestDAGRun,
userPrompt,
}),
dagContexts: [
{
dagFile: fileName,
dagRunId: latestDAGRun?.dagRunId,
},
],
safeMode: preferences.safeMode,
},
});

if (error || !sessionData) {
setPendingUserMessage(null);
setIsLaunchingImproveSession(false);
showError(
error?.message || 'Failed to start improvement session',
'Please try again after the agent service is available.'
);
return;
}

setSessionId(sessionData.sessionId);
setSessionState({
session_id: sessionData.sessionId,
working: true,
});
setIsImproveModalOpen(false);
setIsLaunchingImproveSession(false);
openChat();
},
[
localHasUnsavedChanges,
clearAgentSession,
setPendingUserMessage,
client,
remoteNode,
fileName,
data?.dag?.name,
latestDAGRun,
preferences.safeMode,
setSessionId,
setSessionState,
openChat,
showError,
]
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Harden improvement-session launch against duplicate submits and thrown errors.

/agent/sessions creation is non-idempotent, but this handler has no in-flight guard and no try/catch/finally. A fast double submit can start multiple sessions, and a thrown error can leave isLaunchingImproveSession stuck true.

💡 Proposed fix
   const handleImproveSubmit = React.useCallback(
     async (userPrompt: string) => {
+      if (isLaunchingImproveSession) {
+        return;
+      }
       if (localHasUnsavedChanges) {
         showError(
           'Save or discard local edits first',
           'The agent can only improve the saved DAG definition that exists on disk.'
         );
         return;
       }

       setIsLaunchingImproveSession(true);
       clearAgentSession();
       setPendingUserMessage(userPrompt);

-      const { data: sessionData, error } = await client.POST('/agent/sessions', {
-        params: {
-          query: { remoteNode },
-        },
-        body: {
-          message: buildImproveDAGDefinitionPrompt({
-            dagFile: fileName,
-            dagName: data?.dag?.name || fileName,
-            latestDAGRun,
-            userPrompt,
-          }),
-          dagContexts: [
-            {
-              dagFile: fileName,
-              dagRunId: latestDAGRun?.dagRunId,
-            },
-          ],
-          safeMode: preferences.safeMode,
-        },
-      });
-
-      if (error || !sessionData) {
-        setPendingUserMessage(null);
-        setIsLaunchingImproveSession(false);
-        showError(
-          error?.message || 'Failed to start improvement session',
-          'Please try again after the agent service is available.'
-        );
-        return;
-      }
-
-      setSessionId(sessionData.sessionId);
-      setSessionState({
-        session_id: sessionData.sessionId,
-        working: true,
-      });
-      setIsImproveModalOpen(false);
-      setIsLaunchingImproveSession(false);
-      openChat();
+      try {
+        const { data: sessionData, error } = await client.POST('/agent/sessions', {
+          params: {
+            query: { remoteNode },
+          },
+          body: {
+            message: buildImproveDAGDefinitionPrompt({
+              dagFile: fileName,
+              dagName: data?.dag?.name || fileName,
+              latestDAGRun,
+              userPrompt,
+            }),
+            dagContexts: [
+              {
+                dagFile: fileName,
+                dagRunId: latestDAGRun?.dagRunId,
+              },
+            ],
+            safeMode: preferences.safeMode,
+          },
+        });
+
+        if (error || !sessionData) {
+          setPendingUserMessage(null);
+          showError(
+            error?.message || 'Failed to start improvement session',
+            'Please try again after the agent service is available.'
+          );
+          return;
+        }
+
+        setSessionId(sessionData.sessionId);
+        setSessionState({
+          session_id: sessionData.sessionId,
+          working: true,
+        });
+        setIsImproveModalOpen(false);
+        openChat();
+      } catch {
+        setPendingUserMessage(null);
+        showError(
+          'Failed to start improvement session',
+          'Please try again after the agent service is available.'
+        );
+      } finally {
+        setIsLaunchingImproveSession(false);
+      }
     },
     [
+      isLaunchingImproveSession,
       localHasUnsavedChanges,
       clearAgentSession,
       setPendingUserMessage,
       client,

@@ -0,0 +1,176 @@
import { components, StatusLabel } from '@/api/v1/schema';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add the GPL v3 license header to this new source file.

Please run the repository license-header step for this file before merge.

As per coding guidelines, **/*.{go,ts,tsx,js}: Apply GPL v3 license headers on source files, managed via make addlicense.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/src/features/dags/components/dag-editor/ImproveDAGDefinitionModal.tsx` at
line 1, This new TypeScript React file is missing the GPLv3 license header; add
the standard GPL v3 header comment at the very top of
ImproveDAGDefinitionModal.tsx (above the existing import lines, e.g., above
"import { components, StatusLabel } from '@/api/v1/schema';"), then run the
repository license/header step (e.g., make addlicense or the project's
license-header task) to ensure formatting and consistency with the project's
GPLv3 headers.

@@ -0,0 +1,139 @@
import { components, NodeStatus } from '@/api/v1/schema';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add the GPL v3 license header to this new source file.

This new TypeScript source file should include the required GPL header before merge.

As per coding guidelines, **/*.{go,ts,tsx,js}: Apply GPL v3 license headers on source files, managed via make addlicense.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/src/features/dags/components/dag-editor/improveDagDefinitionPrompt.ts` at
line 1, This file is missing the required GPL v3 license header; add the
standard GPL v3 header block at the very top of the file (before the existing
import line "import { components, NodeStatus } from '@/api/v1/schema';") so the
file complies with the repository rule for .ts/.tsx files; you can either run
the repo's automated tool (make addlicense) or manually insert the canonical GPL
v3 header comment block above the import to satisfy the guideline.

Comment on lines +81 to +83
if (latestDAGRun.params) {
lines.push(`- Params: ${formatParams(latestDAGRun.params)}`);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Redact sensitive run params before embedding them in the agent prompt.

latestDAGRun.params is forwarded into the prompt almost verbatim. If params contain secrets/tokens, this leaks sensitive data into agent session content.

🔐 Proposed fix
 const MAX_PROBLEM_STEPS = 5;
 const MAX_VALUE_LENGTH = 240;
+const SENSITIVE_KEY_PATTERN =
+  /(pass(word)?|secret|token|api[-_]?key|authorization|credential|private[-_]?key)/i;

@@
 function formatParams(params: string): string {
   try {
-    return truncate(JSON.stringify(JSON.parse(params)));
+    return truncate(JSON.stringify(redactSensitive(JSON.parse(params))));
   } catch {
-    return truncate(cleanInline(params));
+    return truncate(maskInlineSecrets(cleanInline(params)));
   }
 }
+
+function redactSensitive(value: unknown): unknown {
+  if (Array.isArray(value)) {
+    return value.map(redactSensitive);
+  }
+  if (value && typeof value === 'object') {
+    return Object.fromEntries(
+      Object.entries(value as Record<string, unknown>).map(([key, val]) => [
+        key,
+        SENSITIVE_KEY_PATTERN.test(key) ? '[REDACTED]' : redactSensitive(val),
+      ])
+    );
+  }
+  return value;
+}
+
+function maskInlineSecrets(value: string): string {
+  return value.replace(
+    /\b(password|pass|secret|token|api[_-]?key|authorization|credential)\s*[:=]\s*([^\s,;]+)/gi,
+    '$1=[REDACTED]'
+  );
+}

Also applies to: 122-128

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/src/features/dags/components/dag-editor/improveDagDefinitionPrompt.ts`
around lines 81 - 83, latestDAGRun.params is being embedded into the agent
prompt verbatim (via formatParams), which risks leaking secrets; update the code
to sanitize/redact sensitive values before formatting and embedding. Implement
or call a helper (e.g., sanitizeParams or maskSensitiveValues) that walks
latestDAGRun.params and replaces values for keys like "token", "secret",
"password", "api_key", "access_token" (and other common secret patterns) with a
masked placeholder (e.g., "<REDACTED>") or truncates long opaque values, then
pass the sanitized output into formatParams; apply the same change wherever
latestDAGRun.params is used for prompts (including the other usage around lines
122-128) so all prompt embeddings use the sanitized params.

@yohamta0 yohamta0 merged commit e20db22 into main Apr 9, 2026
2 checks passed
@yohamta0 yohamta0 deleted the feat/dag-definition-improvement-agent-flow branch April 9, 2026 15:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant