Skip to content

feat: workflow builder with visual DAG editor#39

Open
JayantDevkar wants to merge 26 commits intomainfrom
feat/workflow-builder
Open

feat: workflow builder with visual DAG editor#39
JayantDevkar wants to merge 26 commits intomainfrom
feat/workflow-builder

Conversation

@JayantDevkar
Copy link
Owner

Summary

  • Visual DAG workflow editor using Svelte Flow for building multi-step Claude Code pipelines
  • Each step configurable with model (haiku/sonnet/opus), prompt template with {{ }} variables, tool selection, and max turns
  • Workflow execution engine with topological sort, edge conditions, and template resolution
  • Live execution view with 3s polling, step-level status tracking, and Claude session linking
  • Normalized workflow.db with proper relational tables (steps, edges, inputs as rows)
  • Security: project path validation, no Bash by default, prompt injection sanitization, cycle detection, resource limits

UX Improvements (latest commits)

  • Step naming: editable labels on workflow steps
  • Richer nodes: tool icons, prompt preview, model badges
  • Input management: full CRUD panel for workflow input parameters
  • Edge conditions: click edges to set conditional execution expressions
  • Run input form: modal with typed inputs when workflow has parameters
  • Workflow deletion: confirmation modal with cascade warning
  • Toast notifications: replaced all alert() with non-blocking toasts
  • Back navigation: breadcrumbs in editor toolbar
  • Hide Run on new: Run button only shows for saved workflows

Test plan

  • API tests pass: cd api && pytest tests/test_workflow_schema.py tests/test_workflow_engine.py tests/api/test_workflow_endpoints.py -v
  • Frontend type check: cd frontend && npm run check
  • Create workflow at /workflows/new — verify breadcrumbs, no Run button
  • Add steps, name them, connect with edges, set edge conditions
  • Add inputs via Inputs panel
  • Save → verify toast notification (not alert)
  • Run → verify input form modal appears
  • View execution at /workflows/{id}/runs/{run_id} with live polling
  • Delete workflow → verify confirmation modal → redirects to list

🤖 Generated with Claude Code

@gabiudrescu
Copy link

it would be great if you could share a screenshot of this feature, sounds very promising :D

JayantDevkar and others added 20 commits March 4, 2026 13:25
Add workflows, workflow_runs, and workflow_run_steps tables with
incremental migration from v8.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Security fixes:
- Validate project_path (block sensitive dirs, require home dir)
- Remove Bash from default tools (opt-in only)
- Sanitize step outputs to prevent prompt injection
- Add cycle detection in topological sort
- Add resource limits (prompt length, max_turns, step count, concurrent runs)
- Restrict template variable access to allowed prefixes

Backend quality:
- Store asyncio task references with error callbacks
- Eliminate N+1 query in list_runs via batch fetch
- Deduplicate _get_write_conn to shared db/connection.py
- Fix Optional type annotation on trigger_run
- Return created_at in update_workflow response
- Return real step UUIDs in trigger_run response
- Use COALESCE to prevent started_at overwrite
- Sanitize error messages (no internal details leaked)

Frontend:
- Add try/catch + resp.ok checks on save/run handlers
- Make step ID read-only (prevent orphan state)
- Fix polling cleanup with single $effect
- Extract shared statusColors to constants.ts
- Remove proOptions attribution hide (license issue)
- Add aria-label and aria-pressed for accessibility

Tests:
- Add execute_workflow success + failure tests
- Add run_claude_step test with mocked subprocess
- Add trigger_run endpoint test
- Add cycle detection, evaluate_condition edge case tests
- Add missing 404 endpoint tests
- Deduplicate fixtures to shared conftest.py

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move workflow tables from metadata.db JSON blobs into a dedicated
workflow.db with proper normalized tables (steps, edges, inputs as
rows). Conditions moved from steps to edges for correct DAG semantics.
Adds cycle detection at save time (422 on cycles), single write
connection per engine run, and auto-migration from metadata.db.

- Add workflow_db_path to config, create workflow_schema.py + workflow_db.py
- Normalize schema: workflows, workflow_steps, workflow_edges, workflow_inputs
- v10 migration drops old workflow tables from metadata.db (with safety check)
- Rewrite router CRUD to use normalized tables
- Engine uses edge conditions instead of step conditions
- Remove get_write_conn() dead code from connection.py
- Update frontend types and remove condition from step config panel
- All 1293 tests passing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add optional label column to workflow_steps table with incremental
migration from v1. Update CRUD router and response schemas to
read/write step labels.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace all alert() calls with non-blocking toasts. Svelte 5
rune-based store with success/error/info variants, auto-dismiss
after 4s, mounted globally in root layout.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Step naming: editable label field in config panel, shown on nodes
- Richer nodes: tool icon, prompt preview, label display
- Input management: InputsPanel with CRUD for workflow inputs
- Edge conditions: EdgeConfigPanel for editing edge conditions
- Back navigation: breadcrumbs in editor toolbar
- Hide Run on new: Run button only shows for saved workflows
- Delete button: trash icon in toolbar for saved workflows

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Run modal: shows input form when workflow has inputs, runs directly
  when none defined
- Delete workflow: confirmation modal with cascade warning
- Replace all alert() calls with addToast() in workflow pages

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rectness

Critical fixes:
- Add asyncio.Lock to serialize concurrent SQLite writes in workflow engine
- Validate project_path is absolute and exists before subprocess execution
- Make concurrent run limit check atomic with INSERT (TOCTOU fix)

Important fixes:
- Wrap workflow create/update in transactions to prevent partial writes
- Init stepCounter from max existing ID suffix to avoid collisions
- Isolate migration errors so they don't block app startup
- Add validation for prompt_template length, max_turns bounds, model/tools allowlists
- Fix EdgeConfigPanel placeholder to show supported operators (== and !=)
- Add $effect to re-sync condition state on edge prop change
- Guard against None dereference in create/update response path
- Use stable key (inp.name) instead of index for inputs {#each}

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@JayantDevkar JayantDevkar force-pushed the feat/workflow-builder branch from 692fb52 to 77cc2da Compare March 4, 2026 21:36
JayantDevkar and others added 4 commits March 4, 2026 14:06
The toast store used Svelte 5's $state rune in a plain .ts file, which
caused "rune_outside_svelte" SSR errors in Vite 7. Converted to Svelte's
writable() store API which works in regular .ts files without requiring
.svelte.ts extension and its associated module resolution issues.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
#47)

* feat: Replace timeline event keyboard navigation with Cmd+K search focus and add direct links for skill and subagent events.

* feat: Implement timeline event popup navigation with keyboard support, display a new UI for thinking events without stored content.
@the-non-expert
Copy link
Collaborator

Rebased from main after the merge.

JayantDevkar and others added 2 commits March 7, 2026 16:16
The session reconciler was designed to detect Desktop "session handoffs"
where a parent session gets replaced without firing SessionEnd. It checks
for newer JSONL files in the same project directory as evidence of
replacement.

However, STOPPED sessions (agent finished, session still open) were
incorrectly targeted. When a user opens a new independent session in the
same project, the reconciler would see the newer JSONL and mark the
STOPPED session as ENDED with reason "session_handoff" — even though it
wasn't replaced.

Remove STOPPED from reconciler targets. STOPPED sessions naturally
resolve via SessionEnd hook when the user closes the terminal, and have
other cleanup paths (stale display after 60s, auto-cleanup of ENDED
files after 10 min).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.

3 participants