feat: add client-scoped filtering to node input params#6107
feat: add client-scoped filtering to node input params#6107
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces client-based filtering for node parameters and options across the agentflow, server, and UI packages. It defines a ClientType and adds a client property to node configurations, allowing specific inputs or options to be restricted to certain clients such as agentflowv2 or agentflowsdk. The server-side logic now includes a filterNodeByClient utility to prune these restricted fields before returning node data to the requester. Feedback suggests that the filtering logic should be updated to handle nested parameters within tabs or array properties and the credential field to ensure comprehensive restriction enforcement.
| export const filterNodeByClient = (node: INode, client?: ClientType): INode => { | ||
| if (!client || !node.inputs) return node | ||
|
|
||
| node.inputs = (node.inputs as INodeParams[]) | ||
| .filter((param) => !param.client || param.client.includes(client)) | ||
| .map((param) => { | ||
| if (!param.options) return param | ||
| return { | ||
| ...param, | ||
| options: param.options.filter((opt: INodeOptionsValue) => !opt.client || opt.client.includes(client)) | ||
| } | ||
| }) | ||
|
|
||
| return node | ||
| } |
There was a problem hiding this comment.
The current implementation of filterNodeByClient only filters top-level inputs and their options. However, INodeParams can contain nested parameters within tabs or array properties. These nested parameters should also be filtered recursively to ensure that client-scoped restrictions are applied throughout the entire node configuration. Additionally, the credential field of INode should also be checked for client restrictions.
export const filterNodeByClient = (node: INode, client?: ClientType): INode => {
if (!client) return node
const filterParam = (param: INodeParams): INodeParams | null => {
if (param.client && !param.client.includes(client)) {
return null
}
const p = { ...param }
if (p.options) {
p.options = p.options.filter((opt) => !opt.client || opt.client.includes(client))
}
if (p.tabs) {
p.tabs = p.tabs.map(filterParam).filter((t): t is INodeParams => !!t)
}
if (p.array) {
p.array = p.array.map(filterParam).filter((a): a is INodeParams => !!a)
}
return p
}
if (node.inputs) {
node.inputs = node.inputs.map(filterParam).filter((p): p is INodeParams => !!p)
}
if (node.credential) {
const filteredCredential = filterParam(node.credential)
node.credential = filteredCredential || undefined
}
return node
}There was a problem hiding this comment.
allows recursive calls for tabs and arrays, implemented.
Skipped node.credential though, it's just metadata that says which credential type the node needs, not a real input
Adds a `client` field to `INodeParams` and `INodeOptionsValue` so node authors can restrict params or dropdown options to specific clients (agentflowv2 canvas or agentflowsdk). The server filters params before responding based on a `?client=` query param passed by each client. - Add `ClientType = 'agentflowv2' | 'agentflowsdk'` to Interface.ts - Add `client?: Array<ClientType>` to INodeParams and INodeOptionsValue - Server nodes service: add filterNodeByClient() applied to all node fetch paths - Server nodes controller: read and forward ?client= query param - packages/agentflow API: pass ?client=agentflowsdk on all node fetches - packages/ui API: pass ?client=agentflowv2 on all node fetches - Add tests for filterNodeByClient and update agentflow node API tests Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Made-with: Cursor
3df5c7f to
eb380fa
Compare
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| [key: string]: unknown | ||
| } | ||
|
|
||
| export type ClientType = 'agentflowv2' | 'agentflowsdk' |
There was a problem hiding this comment.
Duplicate ClientType definition (Low - Maintenance)
ClientType is defined identically in both packages/components/src/Interface.ts and here. If a third client value is added later, both must be updated in sync.
Suggestion — have this package import from flowise-components (or extract to a shared constants package) to maintain a single source of truth.
There was a problem hiding this comment.
Hey @jocelynlin-wd , I can make it reference from packages/components/src/Interface.ts,
but seems like the convention for packages/agentflow has never reference anything from packages/components and vice versa. If we deprecate the canvas eventually, adding that reference might also be a bad idea. The closest precedent is server importing from ui/components.
So I think keeping two ClientType definitions in sync is the safer? any thoughts?
There was a problem hiding this comment.
I don't have strong opinion either way. But to be clear, we are not deprecating packages/components as we still share the node definitions there and many other stuff. The part that will be replaced by sdk is packages/ui/src/views/agentflowsv2 (so it's the ui package not components)
(this comment is not PR blocker)
- Validate ?client= query param against allowlist before casting to ClientType - Extract VALID_CLIENT_TYPES const to flowise-components Interface.ts as single source of truth - Make filterNodeByClient pure by returning a new object instead of mutating node.inputs - Add immutability test to nodes.test.ts Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1b92f1f to
cc9f2ed
Compare
jocelynlin-wd
left a comment
There was a problem hiding this comment.
thanks for adding tests
Goal: To allow the ability to hide or show an input node in
agentflowsdkoragentflowv2so we can hide UI inputs that are not synced and ready to be shown or used inagentflowsdk(package/agentflow)Specific Changes
Adds a
clientfield toINodeParamsandINodeOptionsValueso node authors can restrict params or dropdown options to specific clients (agentflowv2 canvas or agentflowsdk). The server filters params before responding based on a?client=query param passed by each client.ClientType = 'agentflowv2' | 'agentflowsdk'to Interface.tsclient?: Array<ClientType>to INodeParams and INodeOptionsValueDemo
If `client` is omitted, should appear in both agentflowsdk and agentflowv2
FormInput-All-Appear.mp4
Hide Form Input Type in Canvas (agentflowv2)
Canvas-Hide-FormInput-Types.mp4
Hide Form Input Type in package/agentflow (agentflowsdk)
Agentflow-Hide-FormInput-Types.mp4
Hide Form Input Type's Type selection in package/agentflow (agentflowsdk)
Agentflow-Hide-FormInput-Type-TypeInArray.mp4
Hide Form Input Type String Option in package/agentflow (agentflowsdk)
Agentflow-Hide-FormInput-String-Option.mp4