Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
c3ad232
feat(ambient-agents): Add webhook trigger UI on start node (#6068)
jchui-wd Apr 2, 2026
17bd94d
merged with main and resolved conflicts
jchui-wd Apr 8, 2026
bd1e913
feat/365-366-Webhooks-Server-Route-And-Execution (#6164)
jchui-wd Apr 14, 2026
22472f5
merged with main and resolved conflicts
jchui-wd Apr 15, 2026
bbb7161
feat/389-Webhooks-Headers-Query-params-Methods-validation (#6217)
jchui-wd Apr 17, 2026
883e258
Merge remote-tracking branch 'origin' into feat/344-ambient-agents-we…
jchui-wd Apr 17, 2026
f8cf2ee
feat:533 webhook secrets (#6227)
jchui-wd Apr 24, 2026
bf2e368
feat:367 | Webhooks - Human Input + Callback Support (#6263)
jchui-wd Apr 24, 2026
0a50bf9
feat: add object/array body param types and per-option show/hide on d…
jchui-wd Apr 24, 2026
42bf191
resolved conflicts and merged with main
jchui-wd Apr 24, 2026
b6d11d7
fix: prevent SSRF in webhook callback URL
jchui-wd Apr 24, 2026
1f29935
Merge branch 'main' into feat/344-ambient-agents-webhooks
HenryHengZJ Apr 27, 2026
1d3f843
fix: exclude HTTP method from webhook URL copy
jchui-wd Apr 28, 2026
ea83891
Merge branch 'feat/344-ambient-agents-webhooks' of https://github.com…
HenryHengZJ May 1, 2026
11f40ec
Merge branch 'main' into feat/344-ambient-agents-webhooks
HenryHengZJ May 1, 2026
7d61862
feat: enhance webhook functionality in Start node
HenryHengZJ May 2, 2026
68a64b3
adds a generic SSE observer primitive and a webhook listener registry…
HenryHengZJ May 4, 2026
c1eb19e
fix webhook tests by mocking webhook listener registry and updating e…
HenryHengZJ May 4, 2026
2360a4e
fix: harden webhook trigger surface against SSRF, secret leakage, and…
HenryHengZJ May 4, 2026
12b2396
fix: improve webhook listener reliability with initial heartbeat and …
HenryHengZJ May 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion packages/agentflow/src/core/types/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,17 @@ export interface InputParam {
type: string
default?: unknown
optional?: boolean
options?: Array<{ label: string; name: string; description?: string; client?: Array<ClientType> } | string>
options?: Array<
| {
label: string
name: string
description?: string
client?: Array<ClientType>
show?: Record<string, unknown>
hide?: Record<string, unknown>
}
| string
>
placeholder?: string
rows?: number
description?: string
Expand Down
98 changes: 98 additions & 0 deletions packages/agentflow/src/core/utils/fieldVisibility.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,104 @@
expect(params[0].display).toBeUndefined()
expect(params[1].display).toBeUndefined()
})

describe('option-level show/hide filtering', () => {
it('removes options whose hide condition matches', () => {
const param = makeParam({
type: 'options',
options: [
{ label: 'String', name: 'string' },
{ label: 'Object', name: 'object', hide: { contentType: 'application/x-www-form-urlencoded' } }
] as any

Check warning on line 205 in packages/agentflow/src/core/utils/fieldVisibility.test.ts

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 20.20.2)

Unexpected any. Specify a different type
})

const result = evaluateFieldVisibility([param], { contentType: 'application/x-www-form-urlencoded' })
expect(result[0].options).toHaveLength(1)
expect(result[0].options![0]).toMatchObject({ name: 'string' })
})

it('keeps options whose hide condition does not match', () => {
const param = makeParam({
type: 'options',
options: [
{ label: 'String', name: 'string' },
{ label: 'Object', name: 'object', hide: { contentType: 'application/x-www-form-urlencoded' } }
] as any

Check warning on line 219 in packages/agentflow/src/core/utils/fieldVisibility.test.ts

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 20.20.2)

Unexpected any. Specify a different type
})

const result = evaluateFieldVisibility([param], { contentType: 'application/json' })
expect(result[0].options).toHaveLength(2)
})

it('removes options whose show condition does not match', () => {
const param = makeParam({
type: 'options',
options: [
{ label: 'Basic', name: 'basic' },
{ label: 'Advanced', name: 'advanced', show: { mode: 'expert' } }
] as any

Check warning on line 232 in packages/agentflow/src/core/utils/fieldVisibility.test.ts

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 20.20.2)

Unexpected any. Specify a different type
})

const result = evaluateFieldVisibility([param], { mode: 'beginner' })
expect(result[0].options).toHaveLength(1)
expect(result[0].options![0]).toMatchObject({ name: 'basic' })
})

it('keeps options whose show condition matches', () => {
const param = makeParam({
type: 'options',
options: [
{ label: 'Basic', name: 'basic' },
{ label: 'Advanced', name: 'advanced', show: { mode: 'expert' } }
] as any

Check warning on line 246 in packages/agentflow/src/core/utils/fieldVisibility.test.ts

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 20.20.2)

Unexpected any. Specify a different type
})

const result = evaluateFieldVisibility([param], { mode: 'expert' })
expect(result[0].options).toHaveLength(2)
})

it('passes through string options unchanged', () => {
const param = makeParam({
type: 'options',
options: ['one', 'two', 'three'] as any

Check warning on line 256 in packages/agentflow/src/core/utils/fieldVisibility.test.ts

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 20.20.2)

Unexpected any. Specify a different type
})

const result = evaluateFieldVisibility([param], {})
expect(result[0].options).toHaveLength(3)
})

it('passes through options with no show/hide unchanged', () => {
const param = makeParam({
type: 'options',
options: [
{ label: 'A', name: 'a' },
{ label: 'B', name: 'b' }
] as any

Check warning on line 269 in packages/agentflow/src/core/utils/fieldVisibility.test.ts

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 20.20.2)

Unexpected any. Specify a different type
})

const result = evaluateFieldVisibility([param], {})
expect(result[0].options).toHaveLength(2)
})

it('does not mutate the original options array', () => {
const options = [
{ label: 'String', name: 'string' },
{ label: 'Object', name: 'object', hide: { contentType: 'application/x-www-form-urlencoded' } }
] as any

Check warning on line 280 in packages/agentflow/src/core/utils/fieldVisibility.test.ts

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 20.20.2)

Unexpected any. Specify a different type
const param = makeParam({ type: 'options', options })

evaluateFieldVisibility([param], { contentType: 'application/x-www-form-urlencoded' })

// Original options array is untouched
expect(options).toHaveLength(2)
})

it('does not affect non-options params', () => {
const param = makeParam({ type: 'string' })
const result = evaluateFieldVisibility([param], {})
expect(result[0].options).toBeUndefined()
})
})
})

describe('evaluateFieldVisibility – nested array $index pattern (Start node formInputTypes)', () => {
Expand Down
22 changes: 18 additions & 4 deletions packages/agentflow/src/core/utils/fieldVisibility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,27 @@ export function evaluateParamVisibility(param: InputParam, inputValues: Record<s

/**
* Evaluate visibility for all params, returning new param objects with computed `display`.
* Also filters individual options within `type: 'options'` params based on their own show/hide conditions.
* Does not mutate the originals.
*/
export function evaluateFieldVisibility(params: InputParam[], inputValues: Record<string, unknown>, arrayIndex?: number): InputParam[] {
return params.map((param) => ({
...param,
display: evaluateParamVisibility(param, inputValues, arrayIndex)
}))
return params.map((param) => {
const withDisplay = { ...param, display: evaluateParamVisibility(param, inputValues, arrayIndex) }

if (withDisplay.type === 'options' && withDisplay.options) {
const filteredOptions = withDisplay.options.filter((opt) => {
if (typeof opt === 'string' || (!opt.show && !opt.hide)) return true
return evaluateParamVisibility(
{ id: '', name: '', label: '', type: '', show: opt.show, hide: opt.hide },
inputValues,
arrayIndex
)
})
return filteredOptions.length === withDisplay.options.length ? withDisplay : { ...withDisplay, options: filteredOptions }
}

return withDisplay
})
}

/**
Expand Down
Loading
Loading