mirror of
https://github.com/simstudioai/sim.git
synced 2026-02-14 08:25:03 -05:00
Compare commits
2 Commits
feat/mult-
...
fix/cancel
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c51d4437a | ||
|
|
529ff71b90 |
@@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
|
|||||||
|
|
||||||
<BlockInfoCard
|
<BlockInfoCard
|
||||||
type="google_books"
|
type="google_books"
|
||||||
color="#FFFFFF"
|
color="#E0E0E0"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
## Usage Instructions
|
## Usage Instructions
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ Retrieve an object from an AWS S3 bucket
|
|||||||
| --------- | ---- | -------- | ----------- |
|
| --------- | ---- | -------- | ----------- |
|
||||||
| `accessKeyId` | string | Yes | Your AWS Access Key ID |
|
| `accessKeyId` | string | Yes | Your AWS Access Key ID |
|
||||||
| `secretAccessKey` | string | Yes | Your AWS Secret Access Key |
|
| `secretAccessKey` | string | Yes | Your AWS Secret Access Key |
|
||||||
|
| `region` | string | No | Optional region override when URL does not include region \(e.g., us-east-1, eu-west-1\) |
|
||||||
| `s3Uri` | string | Yes | S3 Object URL \(e.g., https://bucket.s3.region.amazonaws.com/path/to/file\) |
|
| `s3Uri` | string | Yes | S3 Object URL \(e.g., https://bucket.s3.region.amazonaws.com/path/to/file\) |
|
||||||
|
|
||||||
#### Output
|
#### Output
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ Send messages to Slack channels or direct messages. Supports Slack mrkdwn format
|
|||||||
| `channel` | string | No | Slack channel ID \(e.g., C1234567890\) |
|
| `channel` | string | No | Slack channel ID \(e.g., C1234567890\) |
|
||||||
| `dmUserId` | string | No | Slack user ID for direct messages \(e.g., U1234567890\) |
|
| `dmUserId` | string | No | Slack user ID for direct messages \(e.g., U1234567890\) |
|
||||||
| `text` | string | Yes | Message text to send \(supports Slack mrkdwn formatting\) |
|
| `text` | string | Yes | Message text to send \(supports Slack mrkdwn formatting\) |
|
||||||
| `thread_ts` | string | No | Thread timestamp to reply to \(creates thread reply\) |
|
| `threadTs` | string | No | Thread timestamp to reply to \(creates thread reply\) |
|
||||||
| `files` | file[] | No | Files to attach to the message |
|
| `files` | file[] | No | Files to attach to the message |
|
||||||
|
|
||||||
#### Output
|
#### Output
|
||||||
|
|||||||
@@ -238,6 +238,11 @@ Use this context to calculate relative dates like "yesterday", "last week", "beg
|
|||||||
finalSystemPrompt += currentTimeContext
|
finalSystemPrompt += currentTimeContext
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (generationType === 'cron-expression') {
|
||||||
|
finalSystemPrompt +=
|
||||||
|
'\n\nIMPORTANT: Return ONLY the raw cron expression (e.g., "0 9 * * 1-5"). Do NOT wrap it in markdown code blocks, backticks, or quotes. Do NOT include any explanation or text before or after the expression.'
|
||||||
|
}
|
||||||
|
|
||||||
if (generationType === 'json-object') {
|
if (generationType === 'json-object') {
|
||||||
finalSystemPrompt +=
|
finalSystemPrompt +=
|
||||||
'\n\nIMPORTANT: Return ONLY the raw JSON object. Do NOT wrap it in markdown code blocks (no ```json or ```). Do NOT include any explanation or text before or after the JSON. The response must start with { and end with }.'
|
'\n\nIMPORTANT: Return ONLY the raw JSON object. Do NOT wrap it in markdown code blocks (no ```json or ```). Do NOT include any explanation or text before or after the JSON. The response must start with { and end with }.'
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useEffect, useRef } from 'react'
|
import { useEffect, useRef } from 'react'
|
||||||
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
|
|
||||||
import { SubBlock } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/sub-block'
|
import { SubBlock } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/sub-block'
|
||||||
import type { SubBlockConfig as BlockSubBlockConfig } from '@/blocks/types'
|
import type { SubBlockConfig as BlockSubBlockConfig } from '@/blocks/types'
|
||||||
|
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
|
||||||
|
import { useSubBlockStore } from '@/stores/workflows/subblock/store'
|
||||||
|
|
||||||
interface ToolSubBlockRendererProps {
|
interface ToolSubBlockRendererProps {
|
||||||
blockId: string
|
blockId: string
|
||||||
@@ -44,53 +45,43 @@ export function ToolSubBlockRenderer({
|
|||||||
canonicalToggle,
|
canonicalToggle,
|
||||||
}: ToolSubBlockRendererProps) {
|
}: ToolSubBlockRendererProps) {
|
||||||
const syntheticId = `${subBlockId}-tool-${toolIndex}-${effectiveParamId}`
|
const syntheticId = `${subBlockId}-tool-${toolIndex}-${effectiveParamId}`
|
||||||
const [storeValue, setStoreValue] = useSubBlockValue(blockId, syntheticId)
|
|
||||||
|
|
||||||
const toolParamValue = toolParams?.[effectiveParamId] ?? ''
|
const toolParamValue = toolParams?.[effectiveParamId] ?? ''
|
||||||
const isObjectType = OBJECT_SUBBLOCK_TYPES.has(subBlock.type)
|
const isObjectType = OBJECT_SUBBLOCK_TYPES.has(subBlock.type)
|
||||||
|
|
||||||
const lastPushedToStoreRef = useRef<string | null>(null)
|
const syncedRef = useRef<string | null>(null)
|
||||||
const lastPushedToParamsRef = useRef<string | null>(null)
|
const onParamChangeRef = useRef(onParamChange)
|
||||||
|
onParamChangeRef.current = onParamChange
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!toolParamValue && lastPushedToStoreRef.current === null) {
|
const unsub = useSubBlockStore.subscribe((state, prevState) => {
|
||||||
lastPushedToStoreRef.current = toolParamValue
|
const wfId = useWorkflowRegistry.getState().activeWorkflowId
|
||||||
lastPushedToParamsRef.current = toolParamValue
|
if (!wfId) return
|
||||||
return
|
const newVal = state.workflowValues[wfId]?.[blockId]?.[syntheticId]
|
||||||
}
|
const oldVal = prevState.workflowValues[wfId]?.[blockId]?.[syntheticId]
|
||||||
if (toolParamValue !== lastPushedToStoreRef.current) {
|
if (newVal === oldVal) return
|
||||||
lastPushedToStoreRef.current = toolParamValue
|
const stringified =
|
||||||
lastPushedToParamsRef.current = toolParamValue
|
newVal == null ? '' : typeof newVal === 'string' ? newVal : JSON.stringify(newVal)
|
||||||
|
if (stringified === syncedRef.current) return
|
||||||
|
syncedRef.current = stringified
|
||||||
|
onParamChangeRef.current(toolIndex, effectiveParamId, stringified)
|
||||||
|
})
|
||||||
|
return unsub
|
||||||
|
}, [blockId, syntheticId, toolIndex, effectiveParamId])
|
||||||
|
|
||||||
if (isObjectType && typeof toolParamValue === 'string' && toolParamValue) {
|
useEffect(() => {
|
||||||
try {
|
if (toolParamValue === syncedRef.current) return
|
||||||
const parsed = JSON.parse(toolParamValue)
|
syncedRef.current = toolParamValue
|
||||||
if (typeof parsed === 'object' && parsed !== null) {
|
if (isObjectType && toolParamValue) {
|
||||||
setStoreValue(parsed)
|
try {
|
||||||
return
|
const parsed = JSON.parse(toolParamValue)
|
||||||
}
|
if (typeof parsed === 'object' && parsed !== null) {
|
||||||
} catch {
|
useSubBlockStore.getState().setValue(blockId, syntheticId, parsed)
|
||||||
// Not valid JSON — fall through to set as string
|
return
|
||||||
}
|
}
|
||||||
}
|
} catch {}
|
||||||
setStoreValue(toolParamValue)
|
|
||||||
}
|
}
|
||||||
}, [toolParamValue, setStoreValue, isObjectType])
|
useSubBlockStore.getState().setValue(blockId, syntheticId, toolParamValue)
|
||||||
|
}, [toolParamValue, blockId, syntheticId, isObjectType])
|
||||||
useEffect(() => {
|
|
||||||
if (storeValue == null && lastPushedToParamsRef.current === null) return
|
|
||||||
const stringValue =
|
|
||||||
storeValue == null
|
|
||||||
? ''
|
|
||||||
: typeof storeValue === 'string'
|
|
||||||
? storeValue
|
|
||||||
: JSON.stringify(storeValue)
|
|
||||||
if (stringValue !== lastPushedToParamsRef.current) {
|
|
||||||
lastPushedToParamsRef.current = stringValue
|
|
||||||
lastPushedToStoreRef.current = stringValue
|
|
||||||
onParamChange(toolIndex, effectiveParamId, stringValue)
|
|
||||||
}
|
|
||||||
}, [storeValue, toolIndex, effectiveParamId, onParamChange])
|
|
||||||
|
|
||||||
const visibility = subBlock.paramVisibility ?? 'user-or-llm'
|
const visibility = subBlock.paramVisibility ?? 'user-or-llm'
|
||||||
const isOptionalForUser = visibility !== 'user-only'
|
const isOptionalForUser = visibility !== 'user-only'
|
||||||
|
|||||||
@@ -1741,36 +1741,97 @@ export const ToolInput = memo(function ToolInput({
|
|||||||
) : null
|
) : null
|
||||||
})()}
|
})()}
|
||||||
|
|
||||||
{requiresOAuth && oauthConfig && (
|
|
||||||
<div className='relative min-w-0 space-y-[6px]'>
|
|
||||||
<div className='font-medium text-[13px] text-[var(--text-primary)]'>
|
|
||||||
Account <span className='ml-0.5'>*</span>
|
|
||||||
</div>
|
|
||||||
<div className='w-full min-w-0'>
|
|
||||||
<ToolCredentialSelector
|
|
||||||
value={tool.params?.credential || ''}
|
|
||||||
onChange={(value: string) =>
|
|
||||||
handleParamChange(toolIndex, 'credential', value)
|
|
||||||
}
|
|
||||||
provider={oauthConfig.provider as OAuthProvider}
|
|
||||||
requiredScopes={
|
|
||||||
toolBlock?.subBlocks?.find((sb) => sb.id === 'credential')
|
|
||||||
?.requiredScopes ||
|
|
||||||
getCanonicalScopesForProvider(oauthConfig.provider)
|
|
||||||
}
|
|
||||||
serviceId={oauthConfig.provider}
|
|
||||||
disabled={disabled}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{(() => {
|
{(() => {
|
||||||
const renderedElements: React.ReactNode[] = []
|
const renderedElements: React.ReactNode[] = []
|
||||||
|
|
||||||
|
const showOAuth =
|
||||||
|
requiresOAuth && oauthConfig && tool.params?.authMethod !== 'bot_token'
|
||||||
|
|
||||||
|
const renderOAuthAccount = (): React.ReactNode => {
|
||||||
|
if (!showOAuth || !oauthConfig) return null
|
||||||
|
const credentialSubBlock = toolBlock?.subBlocks?.find(
|
||||||
|
(s) => s.type === 'oauth-input'
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
<div key='oauth-account' className='relative min-w-0 space-y-[6px]'>
|
||||||
|
<div className='font-medium text-[13px] text-[var(--text-primary)]'>
|
||||||
|
{credentialSubBlock?.title || 'Account'}{' '}
|
||||||
|
<span className='ml-0.5'>*</span>
|
||||||
|
</div>
|
||||||
|
<div className='w-full min-w-0'>
|
||||||
|
<ToolCredentialSelector
|
||||||
|
value={tool.params?.credential || ''}
|
||||||
|
onChange={(value: string) =>
|
||||||
|
handleParamChange(toolIndex, 'credential', value)
|
||||||
|
}
|
||||||
|
provider={oauthConfig.provider as OAuthProvider}
|
||||||
|
requiredScopes={
|
||||||
|
credentialSubBlock?.requiredScopes ||
|
||||||
|
getCanonicalScopesForProvider(oauthConfig.provider)
|
||||||
|
}
|
||||||
|
serviceId={oauthConfig.provider}
|
||||||
|
disabled={disabled}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const renderSubBlock = (sb: BlockSubBlockConfig): React.ReactNode => {
|
||||||
|
const effectiveParamId = sb.id
|
||||||
|
const canonicalId = toolCanonicalIndex?.canonicalIdBySubBlockId[sb.id]
|
||||||
|
const canonicalGroup = canonicalId
|
||||||
|
? toolCanonicalIndex?.groupsById[canonicalId]
|
||||||
|
: undefined
|
||||||
|
const hasCanonicalPair = isCanonicalPair(canonicalGroup)
|
||||||
|
const canonicalMode =
|
||||||
|
canonicalGroup && hasCanonicalPair
|
||||||
|
? resolveCanonicalMode(
|
||||||
|
canonicalGroup,
|
||||||
|
{ operation: tool.operation, ...tool.params },
|
||||||
|
toolScopedOverrides
|
||||||
|
)
|
||||||
|
: undefined
|
||||||
|
|
||||||
|
const canonicalToggleProp =
|
||||||
|
hasCanonicalPair && canonicalMode && canonicalId
|
||||||
|
? {
|
||||||
|
mode: canonicalMode,
|
||||||
|
onToggle: () => {
|
||||||
|
const nextMode = canonicalMode === 'advanced' ? 'basic' : 'advanced'
|
||||||
|
collaborativeSetBlockCanonicalMode(
|
||||||
|
blockId,
|
||||||
|
`${tool.type}:${canonicalId}`,
|
||||||
|
nextMode
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
|
||||||
|
const sbWithTitle = sb.title
|
||||||
|
? sb
|
||||||
|
: { ...sb, title: formatParameterLabel(effectiveParamId) }
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ToolSubBlockRenderer
|
||||||
|
key={sb.id}
|
||||||
|
blockId={blockId}
|
||||||
|
subBlockId={subBlockId}
|
||||||
|
toolIndex={toolIndex}
|
||||||
|
subBlock={sbWithTitle}
|
||||||
|
effectiveParamId={effectiveParamId}
|
||||||
|
toolParams={tool.params}
|
||||||
|
onParamChange={handleParamChange}
|
||||||
|
disabled={disabled}
|
||||||
|
canonicalToggle={canonicalToggleProp}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (useSubBlocks && displaySubBlocks.length > 0) {
|
if (useSubBlocks && displaySubBlocks.length > 0) {
|
||||||
|
const allBlockSubBlocks = toolBlock?.subBlocks || []
|
||||||
const coveredParamIds = new Set(
|
const coveredParamIds = new Set(
|
||||||
displaySubBlocks.flatMap((sb) => {
|
allBlockSubBlocks.flatMap((sb) => {
|
||||||
const ids = [sb.id]
|
const ids = [sb.id]
|
||||||
if (sb.canonicalParamId) ids.push(sb.canonicalParamId)
|
if (sb.canonicalParamId) ids.push(sb.canonicalParamId)
|
||||||
const cId = toolCanonicalIndex?.canonicalIdBySubBlockId[sb.id]
|
const cId = toolCanonicalIndex?.canonicalIdBySubBlockId[sb.id]
|
||||||
@@ -1785,57 +1846,45 @@ export const ToolInput = memo(function ToolInput({
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
displaySubBlocks.forEach((sb) => {
|
type RenderItem =
|
||||||
const effectiveParamId = sb.id
|
| { kind: 'subblock'; sb: BlockSubBlockConfig }
|
||||||
const canonicalId = toolCanonicalIndex?.canonicalIdBySubBlockId[sb.id]
|
| { kind: 'oauth' }
|
||||||
const canonicalGroup = canonicalId
|
|
||||||
? toolCanonicalIndex?.groupsById[canonicalId]
|
|
||||||
: undefined
|
|
||||||
const hasCanonicalPair = isCanonicalPair(canonicalGroup)
|
|
||||||
const canonicalMode =
|
|
||||||
canonicalGroup && hasCanonicalPair
|
|
||||||
? resolveCanonicalMode(
|
|
||||||
canonicalGroup,
|
|
||||||
{ operation: tool.operation, ...tool.params },
|
|
||||||
toolScopedOverrides
|
|
||||||
)
|
|
||||||
: undefined
|
|
||||||
|
|
||||||
const canonicalToggleProp =
|
const renderOrder: RenderItem[] = displaySubBlocks.map((sb) => ({
|
||||||
hasCanonicalPair && canonicalMode && canonicalId
|
kind: 'subblock' as const,
|
||||||
? {
|
sb,
|
||||||
mode: canonicalMode,
|
}))
|
||||||
onToggle: () => {
|
|
||||||
const nextMode =
|
|
||||||
canonicalMode === 'advanced' ? 'basic' : 'advanced'
|
|
||||||
collaborativeSetBlockCanonicalMode(
|
|
||||||
blockId,
|
|
||||||
`${tool.type}:${canonicalId}`,
|
|
||||||
nextMode
|
|
||||||
)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
: undefined
|
|
||||||
|
|
||||||
const sbWithTitle = sb.title
|
if (showOAuth) {
|
||||||
? sb
|
const credentialIdx = allBlockSubBlocks.findIndex(
|
||||||
: { ...sb, title: formatParameterLabel(effectiveParamId) }
|
(sb) => sb.type === 'oauth-input'
|
||||||
|
|
||||||
renderedElements.push(
|
|
||||||
<ToolSubBlockRenderer
|
|
||||||
key={sb.id}
|
|
||||||
blockId={blockId}
|
|
||||||
subBlockId={subBlockId}
|
|
||||||
toolIndex={toolIndex}
|
|
||||||
subBlock={sbWithTitle}
|
|
||||||
effectiveParamId={effectiveParamId}
|
|
||||||
toolParams={tool.params}
|
|
||||||
onParamChange={handleParamChange}
|
|
||||||
disabled={disabled}
|
|
||||||
canonicalToggle={canonicalToggleProp}
|
|
||||||
/>
|
|
||||||
)
|
)
|
||||||
})
|
if (credentialIdx >= 0) {
|
||||||
|
const sbPositions = new Map(allBlockSubBlocks.map((sb, i) => [sb.id, i]))
|
||||||
|
const insertAt = renderOrder.findIndex(
|
||||||
|
(item) =>
|
||||||
|
item.kind === 'subblock' &&
|
||||||
|
(sbPositions.get(item.sb.id) ?? Number.POSITIVE_INFINITY) >
|
||||||
|
credentialIdx
|
||||||
|
)
|
||||||
|
if (insertAt === -1) {
|
||||||
|
renderOrder.push({ kind: 'oauth' })
|
||||||
|
} else {
|
||||||
|
renderOrder.splice(insertAt, 0, { kind: 'oauth' })
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
renderOrder.unshift({ kind: 'oauth' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const item of renderOrder) {
|
||||||
|
if (item.kind === 'oauth') {
|
||||||
|
const el = renderOAuthAccount()
|
||||||
|
if (el) renderedElements.push(el)
|
||||||
|
} else {
|
||||||
|
renderedElements.push(renderSubBlock(item.sb))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const uncoveredParams = displayParams.filter(
|
const uncoveredParams = displayParams.filter(
|
||||||
(param) =>
|
(param) =>
|
||||||
@@ -1873,6 +1922,11 @@ export const ToolInput = memo(function ToolInput({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const el = renderOAuthAccount()
|
||||||
|
if (el) renderedElements.push(el)
|
||||||
|
}
|
||||||
|
|
||||||
const filteredParams = displayParams.filter((param) =>
|
const filteredParams = displayParams.filter((param) =>
|
||||||
evaluateParameterCondition(param, tool)
|
evaluateParameterCondition(param, tool)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -122,6 +122,25 @@ export const ScheduleBlock: BlockConfig = {
|
|||||||
required: true,
|
required: true,
|
||||||
mode: 'trigger',
|
mode: 'trigger',
|
||||||
condition: { field: 'scheduleType', value: 'custom' },
|
condition: { field: 'scheduleType', value: 'custom' },
|
||||||
|
wandConfig: {
|
||||||
|
enabled: true,
|
||||||
|
prompt: `You are an expert at writing cron expressions. Generate a valid cron expression based on the user's description.
|
||||||
|
|
||||||
|
Cron format: minute hour day-of-month month day-of-week
|
||||||
|
- minute: 0-59
|
||||||
|
- hour: 0-23
|
||||||
|
- day-of-month: 1-31
|
||||||
|
- month: 1-12
|
||||||
|
- day-of-week: 0-7 (0 and 7 are Sunday)
|
||||||
|
|
||||||
|
Special characters: * (any), , (list), - (range), / (step)
|
||||||
|
|
||||||
|
{context}
|
||||||
|
|
||||||
|
Return ONLY the cron expression, nothing else. No explanation, no backticks, no quotes.`,
|
||||||
|
placeholder: 'Describe your schedule (e.g., "every weekday at 9am")',
|
||||||
|
generationType: 'cron-expression',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ export type GenerationType =
|
|||||||
| 'neo4j-parameters'
|
| 'neo4j-parameters'
|
||||||
| 'timestamp'
|
| 'timestamp'
|
||||||
| 'timezone'
|
| 'timezone'
|
||||||
|
| 'cron-expression'
|
||||||
|
|
||||||
export type SubBlockType =
|
export type SubBlockType =
|
||||||
| 'short-input' // Single line input
|
| 'short-input' // Single line input
|
||||||
|
|||||||
@@ -827,11 +827,10 @@ export function formatParameterLabel(paramId: string): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SubBlock IDs that are "structural" — they control tool routing or auth,
|
* SubBlock IDs that control tool routing, not user-facing parameters.
|
||||||
* not user-facing parameters. These are excluded from tool-input rendering
|
* Excluded from tool-input rendering unless they have an explicit paramVisibility set.
|
||||||
* unless they have an explicit paramVisibility set.
|
|
||||||
*/
|
*/
|
||||||
const STRUCTURAL_SUBBLOCK_IDS = new Set(['operation', 'authMethod', 'destinationType'])
|
const STRUCTURAL_SUBBLOCK_IDS = new Set(['operation'])
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SubBlock types that represent auth/credential inputs handled separately
|
* SubBlock types that represent auth/credential inputs handled separately
|
||||||
@@ -955,12 +954,8 @@ export function getSubBlocksForToolInput(
|
|||||||
} else if (sb.id in toolParamVisibility) {
|
} else if (sb.id in toolParamVisibility) {
|
||||||
visibility = toolParamVisibility[sb.id]
|
visibility = toolParamVisibility[sb.id]
|
||||||
} else if (sb.canonicalParamId) {
|
} else if (sb.canonicalParamId) {
|
||||||
// SubBlock has a canonicalParamId that doesn't directly match a tool param.
|
|
||||||
// This means the block's params() function transforms it before sending to the tool
|
|
||||||
// (e.g. listFolderId → folderId). These are user-facing inputs, default to user-or-llm.
|
|
||||||
visibility = 'user-or-llm'
|
visibility = 'user-or-llm'
|
||||||
} else {
|
} else {
|
||||||
// SubBlock has no corresponding tool param — skip it
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ export const slackMessageTool: ToolConfig<SlackMessageParams, SlackMessageRespon
|
|||||||
visibility: 'user-or-llm',
|
visibility: 'user-or-llm',
|
||||||
description: 'Message text to send (supports Slack mrkdwn formatting)',
|
description: 'Message text to send (supports Slack mrkdwn formatting)',
|
||||||
},
|
},
|
||||||
thread_ts: {
|
threadTs: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
required: false,
|
required: false,
|
||||||
visibility: 'user-or-llm',
|
visibility: 'user-or-llm',
|
||||||
@@ -84,7 +84,7 @@ export const slackMessageTool: ToolConfig<SlackMessageParams, SlackMessageRespon
|
|||||||
channel: isDM ? undefined : params.channel,
|
channel: isDM ? undefined : params.channel,
|
||||||
userId: isDM ? params.dmUserId : params.userId,
|
userId: isDM ? params.dmUserId : params.userId,
|
||||||
text: params.text,
|
text: params.text,
|
||||||
thread_ts: params.thread_ts || undefined,
|
thread_ts: params.threadTs || undefined,
|
||||||
files: params.files || null,
|
files: params.files || null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -516,7 +516,7 @@ export interface SlackMessageParams extends SlackBaseParams {
|
|||||||
dmUserId?: string
|
dmUserId?: string
|
||||||
userId?: string
|
userId?: string
|
||||||
text: string
|
text: string
|
||||||
thread_ts?: string
|
threadTs?: string
|
||||||
files?: UserFile[]
|
files?: UserFile[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user