feat(canvas): Phase 4 — state panel, input maps, model fetching, Radix Select#14
Merged
feat(canvas): Phase 4 — state panel, input maps, model fetching, Radix Select#14
Conversation
Mark Phase 3 complete. Document 10 features pulled forward from Phase 4 (run dialog, graph traversal, auto-map, reducer-aware classification, etc). Update canvas README with revised Phase 4 scope. Add risk mitigation pass to plan-reviewer agent. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CanvasHeader now checks consumedFields — if no user input is needed, starts the run immediately without opening the dialog. RunInputDialog switched from classifyFields to getConsumedInputFields so only fields actually read by nodes appear. Execution layer state_utils now calls model_dump() on Pydantic objects (e.g. LangChain messages) so expressions like messages[-1].content resolve correctly. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
LLM nodes now write to a dedicated llm_response field (replace reducer) instead of directly to messages. The execution layer dual-writes an AIMessage to messages for conversation history. Add llm_response to DEFAULT_STATE with type "string". Fix saveGraph auto-registration to use type "string" for LLM output_keys. Add readonly guard to removeStateFields. Clean up classifyFields comments — reducer check is intentional, not a workaround. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the placeholder text with a full two-tier input mapping editor. Users can add/remove mapping rows, select source fields from context-aware dropdowns, and configure the output_key. Model Settings section is collapsible to reduce scrolling. Contextual labels: "This node reads from", "Result saved to". Terminal LLM nodes hide the output_key field. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update GET /settings/providers to query each configured provider for available models. OpenAI uses AsyncOpenAI.models.list() with exclude-list filter (keeps o1/o3/chatgpt models). Gemini uses asyncio.to_thread for sync list_models(). Anthropic uses curated list. LLMNodeConfig now reads from settingsSlice with hardcoded fallback. Provider change picks from fetched models when available. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Toggleable left-side Sheet showing all graph state fields with type and reducer. Add/remove field capabilities with safety warnings when removing fields referenced by nodes. Undo toast for field deletion. Clickable node names in usage display. Human-friendly "When updated" labels in AddFieldForm. Toggle button in FloatingToolbar with Database icon. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix stale closure in StatePanel undo timer by using useRef instead of useState (W3). Hoist buildPresetsForParam outside map loop in LLMNodeConfig expanded view (S1). Improve _with_timeout type annotation and add broad exception catch for defense-in-depth. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Empty strings in input_map represent unmapped optional params (e.g. DateTime tool's 'date' when action is 'now'). Previously simpleeval would crash on empty string evaluation. Now skipped. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Every graph that takes user input needs this field. Adding it to defaults alongside messages and llm_response means auto-map can wire tools to user_input out of the box, and the run dialog prompts for it without manual state panel setup. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
State panel toggle now lives alongside Pointer and Nodes in the collapsed toolbar — always visible without expanding. Add cursor-pointer to all clickable toolbar buttons for clear affordance. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rewrite Select.tsx as a Radix-based compound component (Select, SelectTrigger, SelectValue, SelectContent, SelectItem) matching the existing Popover dark-theme pattern. Migrate all 9 usages across AddFieldForm, LLMNodeConfig, ToolNodeConfig, and ConditionNodeConfig. Update handler signatures from ChangeEvent to direct string values. Fix LLMNodeConfig tests for Radix compatibility and add pointer capture stubs to test setup. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add StatePanel.test.tsx with 12 tests covering render, delete/undo flow, confirm-delete for in-use fields, add field, node navigation - Add removeStateFields readonly guard and addStateFields dedup tests - Guard against NaN in LLMNodeConfig temperature/max_tokens handlers - Clear undo timer on StatePanel unmount - Remove api_key local var from models.py, use logger.error over logger.exception to avoid leaking keys in stack frames Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Short reducer labels, smart type→reducer defaults, upward dropdowns, info tooltip with Radix portal positioning, secondary button variant, and autocomplete off. Refactor StateFieldRow to group usage with arrows and disambiguate duplicate node labels. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tool output fields (registered as type "object") were excluded from suggestion chips because buildPresetsForParam only passed through string-typed fields for paramType "string". Add object-type pass-through so tool outputs appear as clickable chips. Also adds chip variant to Button component and updates test mocks to match real store behavior. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Run panel was leaking state across graphs because resetRun() was never called on navigation. Adds a useEffect that watches the route id and clears run state only on id changes (not on initial mount). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds deduplicateOutputKey and isAutoOutputKey helpers. Tool nodes now
auto-rename output_key to {tool_name}_result when selecting a tool,
and placement deduplicates colliding keys (tool_result → tool_result_2).
Manual renames are preserved — only auto-generated names get overwritten.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Chips, dropdowns, and collapsed summaries now display the originating node label next to output keys (e.g. "web_search_result (Search)"). When two nodes share an output_key, both labels appear comma-separated. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Source node names are now rendered as a subtle "from X" line below the key in chips, dropdowns, and collapsed summaries. The label stays the raw state key — no length issue regardless of node names. SelectItem gains a description prop that renders outside ItemText so the trigger stays clean. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a tool/LLM node's output_key changes (auto-rename on tool switch or manual edit), downstream nodes referencing the old key in input_map or condition.field are now automatically updated. Adds rewriteStateExpression utility, renameOutputKey store action, and blur-based cascade for manual edits. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When multiple tools would both auto-map a param to user_input, the second
tool now gets a unique field name ({param_name}_input) instead of silently
sharing the same runtime input. Adds getClaimedInputKeys helper and extends
autoMapParams with optional claimedInputKeys parameter.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
prosdev
added a commit
that referenced
this pull request
Mar 20, 2026
- Add StatePanel.test.tsx with 12 tests covering render, delete/undo flow, confirm-delete for in-use fields, add field, node navigation - Add removeStateFields readonly guard and addStateFields dedup tests - Guard against NaN in LLMNodeConfig temperature/max_tokens handlers - Clear undo timer on StatePanel unmount - Remove api_key local var from models.py, use logger.error over logger.exception to avoid leaking keys in stack frames Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
<select>dropdowns with Radix-based compound component matching the existing dark themeresolve_input_map, Pydantic model support for run inputs, zero-input graph auto-startTest plan
pnpm --filter @graphweave/canvas exec tsc --noEmitpassespnpm --filter @graphweave/canvas test— all 380 tests pass🤖 Generated with Claude Code