Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
25 changes: 25 additions & 0 deletions apps/docs/openapi-v2-workflows.json
Original file line number Diff line number Diff line change
Expand Up @@ -7995,6 +7995,11 @@
"enum": ["auto", "force", "none"],
"description": "When the Agent may call the tool: `auto` lets the model decide, `force` requires a call, and `none` disables it. Omitted means `auto`."
},
"usageControlExpression": {
"type": "string",
"maxLength": 2048,
"description": "Variable-capable tool mode value used when the matching canonical mode is `advanced`. It must resolve to `auto`, `force`, or `none` at execution time."
},
"params": {
"type": "object",
"propertyNames": {
Expand Down Expand Up @@ -8041,6 +8046,11 @@
"type": "string",
"enum": ["auto", "force", "none"],
"description": "When the Agent may call the tool: `auto` lets the model decide, `force` requires a call, and `none` disables it. Omitted means `auto`."
},
"usageControlExpression": {
"type": "string",
"maxLength": 2048,
"description": "Variable-capable tool mode value used when the matching canonical mode is `advanced`. It must resolve to `auto`, `force`, or `none` at execution time."
}
},
"required": ["type", "customToolId"],
Expand Down Expand Up @@ -8109,6 +8119,11 @@
"type": "string",
"enum": ["auto", "force", "none"],
"description": "When the Agent may call the tool: `auto` lets the model decide, `force` requires a call, and `none` disables it. Omitted means `auto`."
},
"usageControlExpression": {
"type": "string",
"maxLength": 2048,
"description": "Variable-capable tool mode value used when the matching canonical mode is `advanced`. It must resolve to `auto`, `force`, or `none` at execution time."
}
},
"required": ["type", "schema", "code"],
Expand Down Expand Up @@ -8174,6 +8189,11 @@
"type": "string",
"enum": ["auto", "force", "none"],
"description": "When the Agent may call the tool: `auto` lets the model decide, `force` requires a call, and `none` disables it. Omitted means `auto`."
},
"usageControlExpression": {
"type": "string",
"maxLength": 2048,
"description": "Variable-capable tool mode value used when the matching canonical mode is `advanced`. It must resolve to `auto`, `force`, or `none` at execution time."
}
},
"required": ["type", "params"],
Expand Down Expand Up @@ -8282,6 +8302,11 @@
"type": "string",
"enum": ["auto", "force", "none"],
"description": "When the Agent may call the tool: `auto` lets the model decide, `force` requires a call, and `none` disables it. Omitted means `auto`."
},
"usageControlExpression": {
"type": "string",
"maxLength": 2048,
"description": "Variable-capable tool mode value used when the matching canonical mode is `advanced`. It must resolve to `auto`, `force`, or `none` at execution time."
}
},
"required": ["type", "params"],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { Button, ChipCombobox, cn, Label, Tooltip } from '@sim/emcn'
import { ArrowLeftRight } from '@sim/emcn/icons'
import type { CanonicalMode } from '@/lib/workflows/subblocks/visibility'
import type { StoredTool } from '@/lib/workflows/tool-input/types'
import { ShortInput } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/short-input'

interface ToolUsageControlProps {
blockId: string
aggregateSubBlockId: string
toolIndex: number
tool: StoredTool
mode: CanonicalMode
supportsForce: boolean
disabled: boolean
onFixedChange: (value: NonNullable<StoredTool['usageControl']>) => void
onExpressionChange: (value: string) => void
onModeToggle: () => void
}

const MODE_OPTIONS = [
{
value: 'auto',
label: 'Auto',
suffixElement: <span className='text-[var(--text-tertiary)]'>(model decides)</span>,
},
{
value: 'force',
label: 'Force',
suffixElement: <span className='text-[var(--text-tertiary)]'>(always use)</span>,
},
{
value: 'none',
label: 'None',
suffixElement: <span className='text-[var(--text-tertiary)]'>(disable tool)</span>,
},
] as const
Comment thread
j15z marked this conversation as resolved.

export function ToolUsageControl({
blockId,
aggregateSubBlockId,
toolIndex,
tool,
mode,
supportsForce,
disabled,
onFixedChange,
onExpressionChange,
onModeToggle,
}: ToolUsageControlProps) {
const toggleLabel = mode === 'advanced' ? 'Switch to selector' : 'Switch to variable'

return (
<div className='subblock-content flex w-full min-w-0 flex-col gap-2.5'>
<div className='flex items-center justify-between gap-1.5 pl-0.5'>
<Label>Permission Mode</Label>
<Tooltip.Root>
<Tooltip.Trigger asChild>
<Button
type='button'
variant='ghost'
size='icon'
className='shrink-0'
onClick={onModeToggle}
disabled={disabled}
aria-label={toggleLabel}
>
<ArrowLeftRight
className={cn(
'size-[12px]!',
mode === 'advanced'
? 'text-[var(--text-primary)]'
: 'text-[var(--text-secondary)]'
)}
Comment thread
j15z marked this conversation as resolved.
/>
</Button>
</Tooltip.Trigger>
<Tooltip.Content side='top'>{toggleLabel}</Tooltip.Content>
</Tooltip.Root>
</div>
{mode === 'advanced' ? (
<ShortInput
blockId={blockId}
subBlockId={aggregateSubBlockId}
config={{
id: 'usageControlExpression',
title: 'Permission Mode',
type: 'short-input',
}}
value={tool.usageControlExpression ?? ''}
onChange={onExpressionChange}
placeholder='"auto", "force", or "none"'
disabled={disabled}
workflowSearchValuePath={[toolIndex, 'usageControlExpression']}
/>
) : (
<ChipCombobox
options={MODE_OPTIONS.map((option) => ({
...option,
disabled: option.value === 'force' && !supportsForce,
suffixElement:
option.value === 'force' && !supportsForce ? (
<span className='text-[var(--text-tertiary)]'>(not supported by model)</span>
) : (
option.suffixElement
),
onSelect: () => onFixedChange(option.value),
}))}
value={tool.usageControl ?? 'auto'}
disabled={disabled}
aria-label='Permission Mode'
/>
)}
</div>
)
}
Loading