Skip to content

feat(canvas): Phase 3 — Tool, Condition, HumanInput nodes + settings page#13

Open
prosdev wants to merge 13 commits intomainfrom
plan/canvas-phase-3
Open

feat(canvas): Phase 3 — Tool, Condition, HumanInput nodes + settings page#13
prosdev wants to merge 13 commits intomainfrom
plan/canvas-phase-3

Conversation

@prosdev
Copy link
Contributor

@prosdev prosdev commented Mar 17, 2026

Summary

  • 3.1 Register Tool, Condition, and HumanInput node types — toolbar items, placeholder node components, CSS accent classes, nodeTypes registry
  • 3.2 ToolNode config panel — tool select dropdown (from /v1/settings/tools), input mapping editor with free-text + datalist autocomplete, output key field; settingsSlice with fetch-once pattern; GET /v1/settings/tools endpoint
  • 3.3 ConditionNode config + edge wiring — all 6 condition types (field_equals, field_contains, field_exists, llm_router, tool_error, iteration_limit), inline branch rename editor, config.branches derived from edges at save time, GWEdgeData type for lossless edge round-trips, onConnect/onReconnect branch auto-assignment
  • 3.4 HumanInputNode config — prompt textarea, input_key, timeout_ms with NaN guard
  • 3.5 Validation rules 6–12 — tool_name, output_key, condition_branch on edges, default_branch for non-exhaustive types, HumanInput prompt and input_key
  • 3.6 Settings page — provider status cards (configured/not-configured with env key hint) + tool list; /settings route; gear icon on HomeView
  • Fixes/v1/ prefix for settings endpoints (Vite proxy mismatch), output_key auto-registration in saveGraph, CanvasRoute test fix (RunPanel mock + graphSlice nodes/edges)

Input mapping expressions

The "From state" field accepts any simpleeval expression evaluated against graph state:

Expression Passes
messages[0].content Text of the latest user message (LangChain HumanMessage)
tool_result.result Result value from a previous tool node
"literal" A hardcoded string value
messages[-1].content Last message in the list

Validated manually against all 6 built-in tools:

Tool Param Expression Result
calculator expression messages[0].content {"success":true,"result":"4"} with input 2+2
datetime action "now" current ISO timestamp
web_search query messages[0].content Tavily results
wikipedia query messages[0].content article summary
url_fetch url messages[0].content page content
weather location messages[0].content temperature, humidity, wind

Code review findings addressed

Pre-merge review found 5 warnings, 2 addressed before merge:

  • W1 fixed — aligned condition node defaults (branch: "yes", no else_branch) with CONDITION_CONFIG_DEFAULTS
  • S1 fixedToolNodeConfig now resets rows state when node.id changes, preventing stale mapping display when switching between tool nodes
  • W3, W5, S3 — tracked as follow-up (race condition in settings fetch, updateEdge type breadth, test coverage for new config panels)

Test plan

  • Drag each node type (Tool, Condition, HumanInput) from toolbar onto canvas
  • Configure and run a Tool node for each of the 6 built-in tools using the expressions above
  • Add a Condition node, connect outgoing edges, rename branches in the config panel
  • Verify branch labels appear on canvas edges after save
  • Add a HumanInput node, configure prompt and input_key, run and resume
  • Check Settings page shows provider status and tool list
  • Validate graph rejects missing tool_name, condition_branch, and HumanInput prompt

🤖 Generated with Claude Code

prosdev and others added 13 commits March 17, 2026 00:24
6-part plan for Tool, Condition, HumanInput nodes and settings page.
Three review passes: general, React Flow interactions, schema/execution
alignment. Key design: condition config values drive edge branch names,
lossless condition_branch round-trip through mappers, branch sync at
save time.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix edge ID collisions: crypto.randomUUID() for all edge creation
- Add complete onConnect/onReconnect replacement snippets
- Add spliceEdge condition_branch propagation snippet
- Fix validation rule 10: split into 10a (non-exhaustive) / 10b (exhaustive)
- Add settingsSlice error fields (toolsError, providersError)
- Add 4 regression test specs across plan files
- Reviewed and approved after 3 fix-review cycles

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add NODE_DEFAULTS, toolbar items, CSS accent borders, placeholder node
components, and nodeTypes registration for the three new node types.
ToolNode shows tool_name badge; ConditionNode shows condition type badge;
HumanInputNode shows truncated prompt preview.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add GET /settings/tools endpoint returning tool registry names and
descriptions. Create settings.ts API client and settingsSlice with
fetch-once pattern and error surfaces. ToolNodeConfig has tool select,
input_map key-value editor, and output_key. Wire into NodeConfigPanel.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- mappers.ts: GWEdgeData type, condition_branch preserved in toRFEdge/toEdgeSchema
- graphSlice: updateEdge action; saveGraph derives config.branches from edges
- GraphCanvas: onConnect auto-assigns branch_N for condition edges (UUID IDs);
  onReconnect preserves condition_branch; isValidConnection exempts condition nodes
  from duplicate-edge check
- useNodePlacement: spliceEdge preserves condition_branch on first segment (UUID IDs)
- ConditionBranchEditor: inline branch rename with duplicate detection
- ConditionNodeConfig: all 6 condition types, default_branch dropdown, branch editor
- ConditionNode: shows condition type badge + branch count

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add HumanInputNodeConfig with prompt (Textarea), input_key, and timeout_ms
fields. Timeout sanitizes NaN/empty to 300000. Wire into NodeConfigPanel.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add rules 6-12:
- Tool: tool_name and output_key must not be empty
- Condition: must have outgoing branch edges, all edges need condition_branch,
  non-exhaustive types require non-empty default_branch pointing to a valid branch;
  exhaustive types (tool_error, iteration_limit) skip default_branch validation
- HumanInput: prompt and input_key must not be empty

9 new test cases; all pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add /settings route with LLM provider status cards and tool list. Shows
configured/not-configured status per provider and full tool registry.
Settings gear icon added to HomeView header.

Fix CanvasRoute.test.tsx: mock RunPanel and add nodes/edges to graphSlice
mock to prevent "nodes is not iterable" crash. All 208 tests pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Vite proxy rewrites /api/* → /v1/* so settings/tools and
settings/providers must be at /v1/settings/* to be reachable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tool and LLM nodes write their output to output_key, but the builder
validates that this key exists in the graph's state fields. Without this
fix users get a 422 "output_key not found in state fields" on every run.

saveGraph now auto-adds any output_key from llm/tool nodes that isn't
already in state (type: object, reducer: replace).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace free-text state_key input with a Select populated from the
graph's actual state fields. Adds "Map tool parameters to state fields"
description and renames columns to "Tool param" / "From state".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace state-field-only Select with a free-text Input backed by a
datalist for autocomplete suggestions. This lets users type either a
state field name or any simpleeval expression (e.g. messages[0].content
for the latest message, or "literal" for a fixed string).

Add inline hint text documenting the two most common patterns:
- messages[0].content — text from the latest user message
- "literal" — a hardcoded string value

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Align condition node default (branch: "yes", no else_branch) with
  CONDITION_CONFIG_DEFAULTS to prevent stale properties in serialized JSON
- Sync ToolNodeConfig rows state when node.id changes to prevent stale
  input mapping display when switching between tool nodes

Co-Authored-By: Claude Sonnet 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.

1 participant