Prd 5298 2#2817
Conversation
🦋 Changeset detectedLatest commit: 8efffd5 The changes in this PR will be included in the next version bump. This PR includes changesets to release 10 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…ive form state, subAgents and defaultSubAgentId are actually keyed by node key, not persisted subagent ID; then submit-time transforms convert some of that back to persisted IDs. That translation is spread across the resolver, hydrateNodesWithFormData, and serializeAgentData, so form.reset changes semantics mid-session. See validation.ts (line 160), validation.ts (line 240), serialize.ts (line 87), serialize.ts (line 150), sub-agent-selector.tsx (line 32).
…ive form state, subAgents and defaultSubAgentId are actually keyed by node key, not persisted subagent ID; then submit-time transforms convert some of that back to persisted IDs. That translation is spread across the resolver, hydrateNodesWithFormData, and serializeAgentData, so form.reset changes semantics mid-session. See validation.ts (line 160), validation.ts (line 240), serialize.ts (line 87), serialize.ts (line 150), sub-agent-selector.tsx (line 32).
…ive form state, subAgents and defaultSubAgentId are actually keyed by node key, not persisted subagent ID; then submit-time transforms convert some of that back to persisted IDs. That translation is spread across the resolver, hydrateNodesWithFormData, and serializeAgentData, so form.reset changes semantics mid-session. See validation.ts (line 160), validation.ts (line 240), serialize.ts (line 87), serialize.ts (line 150), sub-agent-selector.tsx (line 32).
…ive form state, subAgents and defaultSubAgentId are actually keyed by node key, not persisted subagent ID; then submit-time transforms convert some of that back to persisted IDs. That translation is spread across the resolver, hydrateNodesWithFormData, and serializeAgentData, so form.reset changes semantics mid-session. See validation.ts (line 160), validation.ts (line 240), serialize.ts (line 87), serialize.ts (line 150), sub-agent-selector.tsx (line 32).
…ive form state, subAgents and defaultSubAgentId are actually keyed by node key, not persisted subagent ID; then submit-time transforms convert some of that back to persisted IDs. That translation is spread across the resolver, hydrateNodesWithFormData, and serializeAgentData, so form.reset changes semantics mid-session. See validation.ts (line 160), validation.ts (line 240), serialize.ts (line 87), serialize.ts (line 150), sub-agent-selector.tsx (line 32).
…ive form state, subAgents and defaultSubAgentId are actually keyed by node key, not persisted subagent ID; then submit-time transforms convert some of that back to persisted IDs. That translation is spread across the resolver, hydrateNodesWithFormData, and serializeAgentData, so form.reset changes semantics mid-session. See validation.ts (line 160), validation.ts (line 240), serialize.ts (line 87), serialize.ts (line 150), sub-agent-selector.tsx (line 32).
…ive form state, subAgents and defaultSubAgentId are actually keyed by node key, not persisted subagent ID; then submit-time transforms convert some of that back to persisted IDs. That translation is spread across the resolver, hydrateNodesWithFormData, and serializeAgentData, so form.reset changes semantics mid-session. See validation.ts (line 160), validation.ts (line 240), serialize.ts (line 87), serialize.ts (line 150), sub-agent-selector.tsx (line 32).
…ive form state, subAgents and defaultSubAgentId are actually keyed by node key, not persisted subagent ID; then submit-time transforms convert some of that back to persisted IDs. That translation is spread across the resolver, hydrateNodesWithFormData, and serializeAgentData, so form.reset changes semantics mid-session. See validation.ts (line 160), validation.ts (line 240), serialize.ts (line 87), serialize.ts (line 150), sub-agent-selector.tsx (line 32).
…ive form state, subAgents and defaultSubAgentId are actually keyed by node key, not persisted subagent ID; then submit-time transforms convert some of that back to persisted IDs. That translation is spread across the resolver, hydrateNodesWithFormData, and serializeAgentData, so form.reset changes semantics mid-session. See validation.ts (line 160), validation.ts (line 240), serialize.ts (line 87), serialize.ts (line 150), sub-agent-selector.tsx (line 32).
…ive form state, subAgents and defaultSubAgentId are actually keyed by node key, not persisted subagent ID; then submit-time transforms convert some of that back to persisted IDs. That translation is spread across the resolver, hydrateNodesWithFormData, and serializeAgentData, so form.reset changes semantics mid-session. See validation.ts (line 160), validation.ts (line 240), serialize.ts (line 87), serialize.ts (line 150), sub-agent-selector.tsx (line 32).
…already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63).
…already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63).
…already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63).
…already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63).
…already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63).
…already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63).
…already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63).
…already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63).
…already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63).
…already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63).
…already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63).
…already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63).
…already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63).
There was a problem hiding this comment.
PR Review Summary
(1) Total Issues | Risk: Low
Delta Review — This review covers only the 4 commits since the last automated review (
2410bdf3e9ed→c003f67e9).
✅ What Was Fixed
The delta commits address sarah-inkeep's bug report about the "requires approval" flag not persisting:
-
✅ Function tool approval policies fix (
validation.ts:259-303,363-371)- New
sharedFunctionToolPoliciesmap properly hydratestempToolPoliciesfrom API duringapiToFormValues() - Merges policies across multiple subAgents with OR logic for
needsApproval - This fixes the bug where "requires approval" was not persisting after save/reload
- New
-
✅ Model inheritance display fixed (
sub-agent-node.tsx:102-107)- Added
getModelInheritanceStatus()call to properly determine if model is inherited (inherited)text now displays correctly based on inheritance hierarchy
- Added
-
✅ Edge removal cleanup (
page.client.tsx:378-396,832-857)- Removed
requestAnimationFramedeferral for form cleanup - Switched from
setValue(..., undefined)toform.unregister()for cleaner form state management - This is a more correct approach for removing form fields
- Removed
-
✅ Test coverage added (
deserialize.test.ts)- New test "hydrates function tool approval policies back into form state" verifies the roundtrip
🟠⚠️ Major (1) 🟠⚠️
Inline Comments:
- 🟠 Major:
function-tool-node-editor.tsx:52Barereturnproduces invalid React output (same pattern that was just fixed in MCP editor)
💭 Consider (1) 💭
Inline Comments:
- 💭 Consider:
sub-agent-node.tsx:81Removed optional chaining onsubAgent.models— verify this can't be nullish
🕐 Pending from Prior Reviews
These items from earlier reviews remain valid considerations for follow-up:
- 🟠
serialize.ts:166— Type assertionas stringbypasses null safety forsubAgentId - 🟠
graph-keys.ts+sub-agent-identity.ts— Missing dedicated unit tests for critical identity modules - 🟡
serialize.ts:130-136—requireFormValueerrors crash submission without user feedback
📋 sarah-inkeep's Feedback Status
| Issue | Status |
|---|---|
| "requires approval" flag not persisting | ✅ Fixed in this delta |
| Missing "(inherited)" text on model nodes | ✅ Fixed in this delta |
| Error removing MCP tool: "toolId: Invalid input" |
💡 APPROVE WITH SUGGESTIONS
Summary: This delta successfully addresses the critical bug report from sarah-inkeep about the "requires approval" flag not persisting. The fix is well-implemented with proper test coverage. The only new issue is a minor pattern inconsistency (bare return instead of return null) in the function tool editor, which is a quick fix. The model inheritance display is also now correctly implemented.
The MCP tool removal error ("toolId: Invalid input: expected string, received undefined") mentioned by sarah-inkeep is not addressed in this delta and may need separate investigation.
Reviewers (1)
| Reviewer | Returned | Main Findings | Consider | While You're Here | Inline Comments | Pending Recs | Discarded |
|---|---|---|---|---|---|---|---|
orchestrator |
2 | 1 | 1 | 0 | 2 | 3 | 0 |
| Total | 2 | 1 | 1 | 0 | 2 | 3 | 0 |
Note: Delta review — 6 files changed since last review; 2 findings are from this delta.
| const [writeWithAIInstructions, setWriteWithAIInstructions] = useState(''); | ||
| // if we remove function tool, functionId can be undefined | ||
| if (!functionId) { | ||
| return; |
There was a problem hiding this comment.
🟠 MAJOR: Bare return produces invalid React output
Issue: Line 52's bare return; returns undefined, which is not valid JSX for a React component body. This is the same pattern that was just fixed in mcp-node-editor.tsx.
Why: React components must return valid JSX, null, or a React fragment. Returning undefined causes a runtime warning and can lead to unexpected rendering behavior. This could affect users navigating to a function tool node after it's been deleted or during transient form state.
Fix: Return null or proper fallback UI:
| return; | |
| // if we remove function tool, functionId can be undefined | |
| if (!functionId) { | |
| return null; | |
| } |
Or with a user-friendly message:
if (!functionId) {
return (
<div className="flex items-center justify-center p-4">
<div className="text-sm text-muted-foreground">Loading function tool...</div>
</div>
);
}Refs:
| const projectModel = project?.models; | ||
| const modelName = | ||
| subAgent.models?.base.model ?? agentModel.base.model ?? (projectModel?.base.model as string); | ||
| subAgent.models.base.model ?? agentModel.base.model ?? projectModel?.base.model ?? ''; |
There was a problem hiding this comment.
💭 Consider: Potential runtime error if subAgent.models is nullish
Issue: Line 81 accesses subAgent.models.base.model directly. The previous code used optional chaining (subAgent.models?.base.model). If subAgent.models or subAgent.models.base is undefined/null, this will throw a TypeError.
Why: While the form schema likely guarantees models exists, this is a defensive programming concern. The change from models?. to models. removes a safety net that previously existed.
Context: Looking at the test data in the PR, subAgent form data includes models with defaults, so this may be safe in practice. However, during deserialization edge cases or form reset, models could be transiently undefined.
Refs:
|
|
||
| const sharedExternalAgentHeaders = new Map<string, string>(); | ||
| const sharedTeamAgentHeaders = new Map<string, string>(); | ||
| const sharedFunctionToolPolicies = new Map<string, Record<string, { needsApproval?: boolean }>>(); |
There was a problem hiding this comment.
✅ Good fix: This addresses sarah-inkeep's bug report
The new sharedFunctionToolPolicies map and the loop at lines 279-303 properly hydrate function tool approval policies (needsApproval) from the API response back into form state as tempToolPolicies. This fixes the bug where the "requires approval" flag was not persisting after save/reload.
How it works:
- Iterates through all subAgents'
canUserelations - Extracts
toolPoliciesfrom each relation - Merges policies across multiple subAgents (uses OR logic: if any relation has
needsApproval: true, the final value istrue) - Stores in
sharedFunctionToolPoliciesmap keyed by toolId - Applies to
functionToolsoutput at lines 363-371
The test at deserialize.test.ts confirms the roundtrip works correctly.
There was a problem hiding this comment.
PR Review Summary
(1) Total Issues | Risk: Low
Delta Review — This review covers only the 1 commit since the last automated review (
c003f67e9→dba1bef57).
🟠⚠️ Major (1) 🟠⚠️
Inline Comments:
- 🟠 Major:
mcp-node-editor.tsx:93Barereturnproduces invalid React output (returnsundefined)
✅ What's Good in This Delta
-
Race condition fix (
mcp-node-editor.tsx:91-94)- Added guard for when
mcpRelationis removed but component is still mounted - Correctly identifies the timing issue with
headersbeing set to empty string - The fix intent is correct, but the implementation returns
undefinedinstead of valid JSX
- Added guard for when
-
Simplified edge removal cleanup (
page.client.tsx:381-388)- Changed from unregistering both
relationshipIdandheadersto onlyrelationshipId - This is a sensible cleanup since headers don't need separate cleanup on edge removal
- Changed from unregistering both
🕐 Pending from Prior Reviews
These items from earlier reviews remain valid considerations for follow-up:
- 🟠
serialize.ts:166— Type assertionas stringbypasses null safety forsubAgentId - 🟠
graph-keys.ts+sub-agent-identity.ts— Missing dedicated unit tests for critical identity modules - 🟡
serialize.ts:130-136—requireFormValueerrors crash submission without user feedback
📋 sarah-inkeep's Feedback Status
| Issue | Status |
|---|---|
| "requires approval" flag not persisting | ✅ Fixed in prior delta |
| Missing "(inherited)" text on model nodes | ✅ Fixed in prior delta |
| Error removing MCP tool: "toolId: Invalid input" |
💡 APPROVE WITH SUGGESTIONS
Summary: This delta correctly identifies and attempts to fix a race condition when MCP relations are removed. However, the fix introduces a bare return; statement that returns undefined — the same pattern that was previously fixed elsewhere in this file. The fix is one character: change return; to return null;. The overall PR architecture is solid and this is a minor issue that doesn't block the refactor.
Discarded (0)
| Location | Issue | Reason Discarded |
|---|---|---|
| — | — | No findings discarded in this delta review |
Reviewers (1)
| Reviewer | Returned | Main Findings | Consider | While You're Here | Inline Comments | Pending Recs | Discarded |
|---|---|---|---|---|---|---|---|
orchestrator |
1 | 0 | 0 | 0 | 1 | 3 | 0 |
| Total | 1 | 0 | 0 | 0 | 1 | 3 | 0 |
Note: Delta review — only 2 files changed since last review; 1 finding is from this delta.
| }, [liveToolData, orphanedTools, nodeId]); | ||
| // MCP was removed, fix race condition when mcpRelation.headers will be set as '' | ||
| if (!mcpRelation) { | ||
| return; |
There was a problem hiding this comment.
🟠 MAJOR: Bare return produces invalid React output
Issue: Line 93's bare return; returns undefined, which is not valid JSX for a React component body. This is the same pattern that was just fixed at lines 96-101 (where it now properly returns JSX).
Why: React components must return valid JSX, null, or a React fragment. Returning undefined causes a runtime warning and potentially unexpected rendering behavior. This can occur when the MCP relation is removed but the component is still mounted.
Fix:
| return; | |
| // MCP was removed, fix race condition when mcpRelation.headers will be set as '' | |
| if (!mcpRelation) { | |
| return null; | |
| } |
Or combine with the subsequent guard for a cleaner single check:
if (!mcpRelation || !toolData || !tool) {
return (
<div className="flex items-center justify-center p-4">
<div className="text-sm text-muted-foreground">
{!mcpRelation ? 'Loading...' : `Tool data not found for ${toolId}.`}
</div>
</div>
);
}Refs:
|
@claude write a detailed changeset based on changes in this PR |
|
Claude finished @dimaMachina's task in 1m 48s —— View job Changeset Created
Added
Commit: |
There was a problem hiding this comment.
PR Review Summary
(1) Total Issues | Risk: Low
Delta Review — This review covers only the 1 commit since the last automated review (
dba1bef57→428de52dd).
✅ What Was Fixed in This Delta
- Model inheritance display (
sub-agent-node.tsx:91-111)- Refactored model name resolution to use a
ModelNameobject with proper optional chaining - Changed from
subAgent.models.base.modeltosubAgent.models?.base.model - Destructured
{ inheritedFrom }fromgetModelInheritanceStatus()for cleaner usage - This addresses the prior review concern about potential nullish property access
- Refactored model name resolution to use a
🟠⚠️ Major (1) 🟠⚠️
Inline Comments:
- 🟠 Major:
mcp-node-editor.tsx:90-91Barereturn;produces invalid React output (returnsundefined)
This issue was flagged in the previous review but remains unresolved. The fix is a one-character change: return; → return null;
🕐 Pending from Prior Reviews
These items from earlier reviews remain valid considerations for follow-up:
- 🟠
serialize.ts:166— Type assertionas stringbypasses null safety forsubAgentId - 🟠
graph-keys.ts+sub-agent-identity.ts— Missing dedicated unit tests for critical identity modules - 🟡
serialize.ts:130-136—requireFormValueerrors crash submission without user feedback - 🟠
function-tool-node-editor.tsx:52— Barereturnin function tool editor (same pattern)
💡 APPROVE WITH SUGGESTIONS
Summary: The delta commit successfully addresses the model inheritance display issue with proper optional chaining. However, the bare return; statement in mcp-node-editor.tsx (flagged in the previous review) remains unresolved. This is a quick one-character fix (return; → return null;). The overall PR architecture is solid and ready to ship once this minor issue is addressed.
The thin-node / RHF-as-single-source-of-truth refactor is a meaningful improvement. Great work on this significant architectural cleanup! 🎉
Discarded (0)
| Location | Issue | Reason Discarded |
|---|---|---|
| — | — | No findings discarded in this delta review |
Reviewers (1)
| Reviewer | Returned | Main Findings | Consider | While You're Here | Inline Comments | Pending Recs | Discarded |
|---|---|---|---|---|---|---|---|
orchestrator |
1 | 0 | 0 | 0 | 1 | 4 | 0 |
| Total | 1 | 0 | 0 | 0 | 1 | 4 | 0 |
Note: Delta review — 2 files changed since last review; 1 finding persists from prior review.
| // MCP was removed, fix race condition when mcpRelation.headers will be set as '' | ||
| if (!mcpRelation) { | ||
| return; | ||
| } |
There was a problem hiding this comment.
🟠 MAJOR: Bare return produces invalid React output
Issue: Line 90's bare return; returns undefined, which is not valid JSX for a React component body. This was flagged in the previous review at dba1bef57 and remains unresolved.
Why: React components must return valid JSX, null, or a React fragment. Returning undefined causes a runtime warning and potentially unexpected rendering behavior. This can occur when the MCP relation is removed but the component is still mounted.
Fix:
| } | |
| // MCP was removed, fix race condition when mcpRelation.headers will be set as '' | |
| if (!mcpRelation) { | |
| return null; | |
| } |
Refs:
Co-authored-by: Dimitri POSTOLOV <[email protected]> Co-Authored-By: Claude Opus 4.6 <[email protected]>
Ito Test Report ❌15 test cases ran. 1 failed, 14 passed. The unified run executed 15 test cases with 14 passing and 1 failing, showing strong overall stability across routing, graph editing integrity, validation navigation, unsaved-change guardrails, mobile usability, and security/resilience checks (including encoded query tampering and JSON/header injection payloads) with no crashes or script execution. The key issue is a confirmed medium-severity regression in browser Back/Forward behavior where sidepane selection and URL query state can desynchronize (including lost edge selection), likely because selection-sync paths use history replacement instead of preserving navigable selection history, and the failure is tied to code modified in this PR. ❌ Failed (1)
🟠 Back/forward navigation desynchronizes graph selection and URL query state
Relevant code:
const onSelectionChange: OnSelectionChangeFunc = ({ nodes, edges }) => {
const node = nodes.length === 1 ? nodes[0] : null;
const edge =
edges.length === 1 &&
(edges[0]?.type === EdgeType.A2A || edges[0]?.type === EdgeType.SelfLoop)
? edges[0]
: null;
const defaultPane = isOpen ? 'agent' : null;
setQueryState(
{
pane: node ? 'node' : edge ? 'edge' : defaultPane,
nodeId: node ? getNodeGraphKey(node) : null,
edgeId: edge ? getEdgeGraphKey(edge, nodes) : null,
},
{ history: 'replace' }
);
};
if (singleSelectedNode) {
const nextNodeId = getNodeGraphKey(singleSelectedNode);
if (nextNodeId && nextNodeId !== nodeId) {
setQueryState(
{
pane: 'node',
nodeId: nextNodeId,
edgeId: null,
},
{ history: 'replace' }
);
}
return;
}
if (
singleSelectedEdge &&
(singleSelectedEdge.type === EdgeType.A2A || singleSelectedEdge.type === EdgeType.SelfLoop)
) {
const nextEdgeId = getEdgeGraphKey(singleSelectedEdge, nodes);
if (nextEdgeId && nextEdgeId !== edgeId) {
setQueryState(
{
pane: 'edge',
nodeId: null,
edgeId: nextEdgeId,
},
{ history: 'replace' }
);
}
}✅ Passed (14)Commit: Tell us how we did: Give Ito Feedback |
… schemas from `agents-core` (#1799) * upd * schemas changes * upd * move to serializeJson * upd * upd * all type errors are gone * fix knip * less diff * less diff * tweaks, fix tests * tweaks, fix tests * tweaks, fix tests * tweaks, fix tests * add changeset * add changeset * update openapi * rollback nullable update for some fields * fix some missing shouldDirty * fix typecheck * add `GenericJsonEditor`/`GenericPromptEditor` * move * move * move * move * move * upd * upd * add lintignore * format * Add changeset for GenericJsonEditor and GenericPromptEditor Co-authored-by: dimaMachina <[email protected]> * polish * polish * polishing * polishing * upd * upd * add tests * upd * format * use GenericJsonSchemaEditor * upd * fix agent prompt tests * polish tests * remove unneeded JSON suffix * increase timeout * add more tests * upd * fixes * upd * fix typecheck * fix tests * fix * fix missing cypress tests * try change in core to see docs deployment * update snapshot * format * feat(dashboard): refactor agent pages `subAgent`, `mcp-tool`, `function-tool`, `teamAgent`, `externalAgent` forms to use zod schemas from `agents-core` (#2400) * dependencies * add generic code editor * execute code * migrate tempToolPolicies * migrate external agent node editor * migrate external agent editor * base url * better monaco loading for action buttons * description and baseUrl * format * headers * team agent name and id * description and headers in team agent * knip * knip InputField * mcp tool id name and headers * polish * update zod type * reuse validation * migrate config.mcp.server.url * remove use callback * update subagent node * destructure is default too * mark name and id as required for subagent * fix subagent flow errors * add useProcessedErrors * polish external agent * upd * upd * upd * functional tools * fix saving * remove use memo * remove error Helpers * format * upd use agent errors * upd use agent errors * rm useAgentErrors * update agent error summary * fix agent error summary * remove toast error which duplicate agent summary * rm old states * make tools field as record * rm * rm * upd * more * polish * show badge in agent settings * format * upd * rm PartialFullAgentDefinition * rm PartialFullAgentDefinition * upd * upd * cleanup * fix type errors * improve types * fix type errors * more fix type errors * fix deserializeAgentData, pick only used types * more typecheck fixes * fix typecheck * 2 type errors left * fix type errors * lint is good now * rm unused types * format * polish * remove unneeded arguments * polish * add go to for agent settings * upd * polish * polish * polish * polish agent error summary * upd * upd * upd * upd * upd * upd * upd * upd * upd * add ToolPoliciesSchema * upd mcp * upd mcp * upd mcp * upd mcp * rm tempHeaders * rm tempHeaders * rm tempHeaders * rm tempHeaders * rm tempHeaders * upd * upd * upd * upd * upd * upd * upd * cleanup * cleanup * fix * fix * fix * fix * fix sidepane * imrpove AgentErrorSummary, show popup only on blur * rm agent-error-parser.ts * show server errors in agent error summary * add useGroupedAgentErrors * remove isDefault * upd * upd * use animate graph * upd * upd * move deleteSelected * use useDefaultSubAgentIdRef * upd * upd * cleanup * format * upd * splits functions tools to functions and function tools * fix agent summary, upd function and function tools * update snapshot * update snapshot * upd * upd * update external agents * update team agents * upd * upd * upd * upd flatNestedFieldMessage * upd flatNestedFieldMessage * upd validation * upd isRequired in function-tool-node-editor.tsx * rm * update useAgentShortcuts * cleanup serialize * upd * upd name and description * trigger dirty state * add super refine * upd * update onDrop * upd * upd * upd * upd * upd * upd * upd mcp * upd mcp * upd mcp moreeeeeee * upd * upd validation * sub agent editor * external agent selector * update team agent * upd * toolid * handle tool null * upd team agent and external agent * upd errors styles * upd errors styles * upd errors styles * upd errors styles * upd errors styles * upd errors styles * upd button * upd agent error summary * updd * updd * upd typecheck * upd typecheck * upd skills type * rm * rm * rm * rm * upd * flowButton * flowButton * TeamRelation * fix * fix serialize * deserialize * upd * upd * fix form.unregister * fix type * upd serialize * rm functionToolId * knip * openapi * fix dirty state * fix core tests * fix tests * fix cypress * fix cypress * fix lint * fix some tests * fix some tests * fix rest of tests * fix api tests * fix cypress validation tests * fix more tests * fix edit with ai * fix tests * add more tests * lint * remove @ts-expect-error * fix typecheck * polish * fix typecheck * fix(dashboard): address review feedback for agent form refactor * format * apply merge fixes * undo making inputSchema required * chore: update OpenAPI snapshot * fixes * review * show errors for skills * refactor data components and artifacts * refactor data components and artifacts * upd * upd models * upd model section * fix skills * rm * fixes * fixes * fixes * fix typecheck * Update agents-manage-ui/src/components/agent/sidepane/nodes/model-section.tsx Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> * one last fix * fix test * style: auto-format with biome --------- Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> * fix `inkeep pull` tests * upd * duplicate sub agent id validation * set subAgent only for right type * fallbacks * sync saved agent graph wip * subagents, ext agents and team agents can be optional * move error to zod superRefine * more fallbacks * fix defaultSubAgentId * Prd 5298 2 (#2817) * fix typecheck * fix modelName * fix * [P1] The current model hides two different identities behind id. In live form state, subAgents and defaultSubAgentId are actually keyed by node key, not persisted subagent ID; then submit-time transforms convert some of that back to persisted IDs. That translation is spread across the resolver, hydrateNodesWithFormData, and serializeAgentData, so form.reset changes semantics mid-session. See validation.ts (line 160), validation.ts (line 240), serialize.ts (line 87), serialize.ts (line 150), sub-agent-selector.tsx (line 32). * [P1] The current model hides two different identities behind id. In live form state, subAgents and defaultSubAgentId are actually keyed by node key, not persisted subagent ID; then submit-time transforms convert some of that back to persisted IDs. That translation is spread across the resolver, hydrateNodesWithFormData, and serializeAgentData, so form.reset changes semantics mid-session. See validation.ts (line 160), validation.ts (line 240), serialize.ts (line 87), serialize.ts (line 150), sub-agent-selector.tsx (line 32). * [P1] The current model hides two different identities behind id. In live form state, subAgents and defaultSubAgentId are actually keyed by node key, not persisted subagent ID; then submit-time transforms convert some of that back to persisted IDs. That translation is spread across the resolver, hydrateNodesWithFormData, and serializeAgentData, so form.reset changes semantics mid-session. See validation.ts (line 160), validation.ts (line 240), serialize.ts (line 87), serialize.ts (line 150), sub-agent-selector.tsx (line 32). * [P1] The current model hides two different identities behind id. In live form state, subAgents and defaultSubAgentId are actually keyed by node key, not persisted subagent ID; then submit-time transforms convert some of that back to persisted IDs. That translation is spread across the resolver, hydrateNodesWithFormData, and serializeAgentData, so form.reset changes semantics mid-session. See validation.ts (line 160), validation.ts (line 240), serialize.ts (line 87), serialize.ts (line 150), sub-agent-selector.tsx (line 32). * [P1] The current model hides two different identities behind id. In live form state, subAgents and defaultSubAgentId are actually keyed by node key, not persisted subagent ID; then submit-time transforms convert some of that back to persisted IDs. That translation is spread across the resolver, hydrateNodesWithFormData, and serializeAgentData, so form.reset changes semantics mid-session. See validation.ts (line 160), validation.ts (line 240), serialize.ts (line 87), serialize.ts (line 150), sub-agent-selector.tsx (line 32). * [P1] The current model hides two different identities behind id. In live form state, subAgents and defaultSubAgentId are actually keyed by node key, not persisted subagent ID; then submit-time transforms convert some of that back to persisted IDs. That translation is spread across the resolver, hydrateNodesWithFormData, and serializeAgentData, so form.reset changes semantics mid-session. See validation.ts (line 160), validation.ts (line 240), serialize.ts (line 87), serialize.ts (line 150), sub-agent-selector.tsx (line 32). * [P1] The current model hides two different identities behind id. In live form state, subAgents and defaultSubAgentId are actually keyed by node key, not persisted subagent ID; then submit-time transforms convert some of that back to persisted IDs. That translation is spread across the resolver, hydrateNodesWithFormData, and serializeAgentData, so form.reset changes semantics mid-session. See validation.ts (line 160), validation.ts (line 240), serialize.ts (line 87), serialize.ts (line 150), sub-agent-selector.tsx (line 32). * [P1] The current model hides two different identities behind id. In live form state, subAgents and defaultSubAgentId are actually keyed by node key, not persisted subagent ID; then submit-time transforms convert some of that back to persisted IDs. That translation is spread across the resolver, hydrateNodesWithFormData, and serializeAgentData, so form.reset changes semantics mid-session. See validation.ts (line 160), validation.ts (line 240), serialize.ts (line 87), serialize.ts (line 150), sub-agent-selector.tsx (line 32). * [P1] The current model hides two different identities behind id. In live form state, subAgents and defaultSubAgentId are actually keyed by node key, not persisted subagent ID; then submit-time transforms convert some of that back to persisted IDs. That translation is spread across the resolver, hydrateNodesWithFormData, and serializeAgentData, so form.reset changes semantics mid-session. See validation.ts (line 160), validation.ts (line 240), serialize.ts (line 87), serialize.ts (line 150), sub-agent-selector.tsx (line 32). * [P1] The current model hides two different identities behind id. In live form state, subAgents and defaultSubAgentId are actually keyed by node key, not persisted subagent ID; then submit-time transforms convert some of that back to persisted IDs. That translation is spread across the resolver, hydrateNodesWithFormData, and serializeAgentData, so form.reset changes semantics mid-session. See validation.ts (line 160), validation.ts (line 240), serialize.ts (line 87), serialize.ts (line 150), sub-agent-selector.tsx (line 32). * [P2] Business data is duplicated in RHF and node.data, but renderers already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63). * [P2] Business data is duplicated in RHF and node.data, but renderers already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63). * [P2] Business data is duplicated in RHF and node.data, but renderers already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63). * [P2] Business data is duplicated in RHF and node.data, but renderers already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63). * [P2] Business data is duplicated in RHF and node.data, but renderers already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63). * [P2] Business data is duplicated in RHF and node.data, but renderers already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63). * [P2] Business data is duplicated in RHF and node.data, but renderers already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63). * [P2] Business data is duplicated in RHF and node.data, but renderers already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63). * [P2] Business data is duplicated in RHF and node.data, but renderers already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63). * [P2] Business data is duplicated in RHF and node.data, but renderers already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63). * [P2] Business data is duplicated in RHF and node.data, but renderers already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63). * [P2] Business data is duplicated in RHF and node.data, but renderers already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63). * [P2] Business data is duplicated in RHF and node.data, but renderers already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63). * [P2] Business data is duplicated in RHF and node.data, but renderers already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63). * [P2] Business data is duplicated in RHF and node.data, but renderers already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63). * [P2] Business data is duplicated in RHF and node.data, but renderers already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63). * [P2] Business data is duplicated in RHF and node.data, but renderers already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63). * [P2] Business data is duplicated in RHF and node.data, but renderers already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63). * [P2] Business data is duplicated in RHF and node.data, but renderers already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63). * [P2] Business data is duplicated in RHF and node.data, but renderers already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63). * [P2] Business data is duplicated in RHF and node.data, but renderers already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63). * [P2] Business data is duplicated in RHF and node.data, but renderers already trust RHF. hydrateNodesWithFormData() exists only because serializeAgentData() reads node payload fields from node.data; the UI mostly ignores those same fields and watches RHF instead. That duplication is the main drift source. See serialize.ts (line 87), deserialize.ts (line 123), sub-agent-node.tsx (line 50), function-tool-node.tsx (line 17), mcp-node.tsx (line 63). * Group 1: Stabilize graph identity * Group 2: Finish RHF as the business source of truth * Group 2: Finish RHF as the business source of truth * Group 2: Finish RHF as the business source of truth * Group 3: Remove layout dependence on node business payload * upd * upd * upd * upd * upd * upd * upd * upd * upd * upd * upd * upd * upd * upd * upd * upd * upd * upd * renames * Group 1: Fix remaining schema mismatches * Group 1: Fix remaining schema mismatches * Group 1: Fix remaining schema mismatches * Group 1: Fix remaining schema mismatches * upd * upd * upd * Group 3: Collapse connection state into one relation model * Group 3: Collapse connection state into one relation model * Group 3: Collapse connection state into one relation model * Group 3: Collapse connection state into one relation model * Group 3: Collapse connection state into one relation model * Group 3: Collapse connection state into one relation model * Group 3: Collapse connection state into one relation model * Group 3: Collapse connection state into one relation model * Group 3: Collapse connection state into one relation model * Group 3: Collapse connection state into one relation model * Group 3: Collapse connection state into one relation model * Group 3: Collapse connection state into one relation model * Group 3: Collapse connection state into one relation model * Group 3: Collapse connection state into one relation model * Group 3: Collapse connection state into one relation model * Group 3: Collapse connection state into one relation model * Group 3: Collapse connection state into one relation model * more * more * rm * rm * Group 3: Finish explicit graph identity * comment * upd * upd * upd * upd * upd * upd * simplify * lint * update snapshot * fix zod omit issue * fix cypress * style: auto-format with biome * fix review * Update mcp-node-editor.tsx * apply more review * fix: differentiate loading vs missing state in MCP node editor null guard * Update mcp-node-editor.tsx * fix inheritance in subagent node * fix needs approval * polish * fix issue * fix race condition * fix error * Add detailed changeset for graph identity refactor Co-authored-by: Dimitri POSTOLOV <[email protected]> Co-Authored-By: Claude Opus 4.6 <[email protected]> --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com> Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Dimitri POSTOLOV <[email protected]> Co-authored-by: Claude Opus 4.6 <[email protected]> * format * fix typecheck * fix conflicts * lintfix --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: dimaMachina <[email protected]> Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> Co-authored-by: Dimitri POSTOLOV <[email protected]> Co-authored-by: Claude Opus 4.6 <[email protected]>
No description provided.