feat: add DAG definition improvement flow from the spec editor#1980
Conversation
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughThese 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
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
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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 withbg-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
📒 Files selected for processing (8)
ui/src/features/dags/components/dag-details/DAGDetailsContent.tsxui/src/features/dags/components/dag-details/DAGDetailsPanel.tsxui/src/features/dags/components/dag-editor/DAGSpec.tsxui/src/features/dags/components/dag-editor/ImproveDAGDefinitionModal.tsxui/src/features/dags/components/dag-editor/__tests__/improveDagDefinitionPrompt.test.tsui/src/features/dags/components/dag-editor/improveDagDefinitionPrompt.tsui/src/pages/dags/dag/index.tsxui/src/pages/queues/index.tsx
| @@ -0,0 +1,79 @@ | |||
| import { | |||
There was a problem hiding this comment.
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.
| 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, | ||
| ] | ||
| ); |
There was a problem hiding this comment.
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'; | |||
There was a problem hiding this comment.
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'; | |||
There was a problem hiding this comment.
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.
| if (latestDAGRun.params) { | ||
| lines.push(`- Params: ${formatParams(latestDAGRun.params)}`); | ||
| } |
There was a problem hiding this comment.
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.
Summary
Improveaction to the DAG spec editor that opens a focused modal for describing what part of the definition should be improvedcomponentsimport in the queues pageTest plan
pnpm typecheckpnpm test -- improveDagDefinitionPromptSummary by CodeRabbit