chore: import upstream snapshot with attribution
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:20:55 +08:00
commit d25d482dc2
13754 changed files with 4996608 additions and 0 deletions
@@ -0,0 +1,285 @@
import { createLogger } from '@sim/logger'
import { truncate } from '@sim/utils/string'
import { buildSelectorContextFromBlock } from '@/lib/workflows/subblocks/context'
import { getBlock } from '@/blocks/registry'
import { SELECTOR_TYPES_HYDRATION_REQUIRED, type SubBlockConfig } from '@/blocks/types'
import { isUuid } from '@/executor/constants'
import { fetchOAuthCredentialDetail } from '@/hooks/queries/oauth/oauth-credentials'
import { getSelectorDefinition, loadAllSelectorOptions } from '@/hooks/selectors/registry'
import { resolveSelectorForSubBlock } from '@/hooks/selectors/resolution'
import type { SelectorContext, SelectorKey } from '@/hooks/selectors/types'
import type { WorkflowState } from '@/stores/workflows/workflow/types'
import { formatParameterLabel } from '@/tools/params'
const logger = createLogger('ResolveValues')
/**
* Result of resolving a value for display
*/
interface ResolvedValue {
/** The original value before resolution */
original: unknown
/** Human-readable label for display */
displayLabel: string
/** Whether the value was successfully resolved to a name */
resolved: boolean
}
/**
* Context needed to resolve values for display
*/
interface ResolutionContext {
/** The block type (e.g., 'slack', 'gmail') */
blockType: string
/** The subBlock field ID (e.g., 'channel', 'credential') */
subBlockId: string
/** The workflow ID for API calls */
workflowId: string
/** The workspace scope for selector-based lookups */
workspaceId?: string
/** The current workflow state for extracting additional context */
currentState: WorkflowState
/** The block ID being resolved */
blockId?: string
}
function getSemanticFallback(subBlockConfig: SubBlockConfig): string {
return (subBlockConfig.title ?? subBlockConfig.id).toLowerCase()
}
async function resolveCredential(credentialId: string, workflowId: string): Promise<string | null> {
try {
const credentials = await fetchOAuthCredentialDetail(credentialId, workflowId)
if (credentials.length > 0) {
return credentials[0].name ?? null
}
return null
} catch (error) {
logger.warn('Failed to resolve credential', { credentialId, error })
return null
}
}
async function resolveWorkflow(workflowId: string, workspaceId?: string): Promise<string | null> {
if (!workspaceId) return null
try {
const definition = getSelectorDefinition('sim.workflows')
if (definition.fetchById) {
const result = await definition.fetchById({
key: 'sim.workflows',
context: { workspaceId },
detailId: workflowId,
})
return result?.label ?? null
}
return null
} catch (error) {
logger.warn('Failed to resolve workflow', { workflowId, error })
return null
}
}
async function resolveSelectorValue(
value: string,
selectorKey: SelectorKey,
selectorContext: SelectorContext
): Promise<string | null> {
try {
const definition = getSelectorDefinition(selectorKey)
if (definition.fetchById) {
const result = await definition.fetchById({
key: selectorKey,
context: selectorContext,
detailId: value,
})
if (result?.label) {
return result.label
}
}
const options = await loadAllSelectorOptions(definition, {
key: selectorKey,
context: selectorContext,
})
const match = options.find((opt) => opt.id === value)
return match?.label ?? null
} catch (error) {
logger.warn('Failed to resolve selector value', { value, selectorKey, error })
return null
}
}
function extractMcpToolName(toolId: string): string {
const withoutPrefix = toolId.startsWith('mcp-') ? toolId.slice(4) : toolId
const parts = withoutPrefix.split('_')
if (parts.length >= 2) {
return parts[parts.length - 1]
}
return withoutPrefix
}
/**
* Resolves a subBlock field ID to its human-readable title.
* Falls back to the raw ID if the block or subBlock is not found.
*/
export function resolveFieldLabel(blockType: string, subBlockId: string): string {
if (subBlockId.startsWith('data.')) {
return formatParameterLabel(subBlockId.slice(5))
}
const blockConfig = getBlock(blockType)
if (!blockConfig) return subBlockId
const subBlockConfig = blockConfig.subBlocks.find((sb) => sb.id === subBlockId)
return subBlockConfig?.title ?? subBlockId
}
/**
* Resolves a dropdown option ID to its human-readable label.
* Returns null if the subBlock is not a dropdown or the value is not found.
*/
function resolveDropdownLabel(subBlockConfig: SubBlockConfig, value: string): string | null {
if (subBlockConfig.type !== 'dropdown') return null
if (!subBlockConfig.options) return null
const options =
typeof subBlockConfig.options === 'function' ? subBlockConfig.options() : subBlockConfig.options
const match = options.find((opt) => opt.id === value)
return match?.label ?? null
}
/**
* Formats a value for display in diff descriptions.
*/
export function formatValueForDisplay(value: unknown): string {
if (value === null || value === undefined) return '(none)'
if (typeof value === 'string') {
if (value.length > 50) return truncate(value, 50)
return value || '(empty)'
}
if (typeof value === 'boolean') return value ? 'enabled' : 'disabled'
if (typeof value === 'number') return String(value)
if (Array.isArray(value)) return `[${value.length} items]`
if (typeof value === 'object') {
const json = JSON.stringify(value)
return truncate(json, 50)
}
return String(value)
}
function extractSelectorContext(
blockId: string,
currentState: WorkflowState,
workflowId: string,
workspaceId?: string
): SelectorContext {
const block = currentState.blocks?.[blockId]
if (!block?.subBlocks) return { workflowId, workspaceId }
return buildSelectorContextFromBlock(block.type, block.subBlocks, {
workflowId,
workspaceId,
canonicalModes: block.data?.canonicalModes,
})
}
/**
* Resolves a value to a human-readable display label.
* Uses the selector registry infrastructure to resolve IDs to names.
*
* @param value - The value to resolve (credential ID, channel ID, UUID, etc.)
* @param context - Context needed for resolution (block type, subBlock ID, workflow state)
* @returns ResolvedValue with the display label and resolution status
*/
export async function resolveValueForDisplay(
value: unknown,
context: ResolutionContext
): Promise<ResolvedValue> {
if (typeof value !== 'string' || !value) {
return {
original: value,
displayLabel: formatValueForDisplay(value),
resolved: false,
}
}
const blockConfig = getBlock(context.blockType)
const subBlockConfig = blockConfig?.subBlocks.find((sb) => sb.id === context.subBlockId)
if (!subBlockConfig) {
return { original: value, displayLabel: formatValueForDisplay(value), resolved: false }
}
const semanticFallback = getSemanticFallback(subBlockConfig)
const selectorCtx = context.blockId
? extractSelectorContext(
context.blockId,
context.currentState,
context.workflowId,
context.workspaceId
)
: { workflowId: context.workflowId, workspaceId: context.workspaceId }
const isCredentialField =
subBlockConfig.type === 'oauth-input' || context.subBlockId === 'credential'
if (isCredentialField && isUuid(value)) {
const label = await resolveCredential(value, context.workflowId)
if (label) {
return { original: value, displayLabel: label, resolved: true }
}
return { original: value, displayLabel: semanticFallback, resolved: true }
}
if (subBlockConfig.type === 'workflow-selector' && isUuid(value)) {
const label = await resolveWorkflow(value, selectorCtx.workspaceId)
if (label) {
return { original: value, displayLabel: label, resolved: true }
}
return { original: value, displayLabel: semanticFallback, resolved: true }
}
if (subBlockConfig.type === 'mcp-tool-selector') {
const toolName = extractMcpToolName(value)
return { original: value, displayLabel: toolName, resolved: true }
}
if (subBlockConfig.type === 'dropdown') {
try {
const label = resolveDropdownLabel(subBlockConfig, value)
if (label) {
return { original: value, displayLabel: label, resolved: true }
}
} catch (error) {
logger.warn('Failed to resolve dropdown label', {
value,
subBlockId: context.subBlockId,
error,
})
}
}
if (SELECTOR_TYPES_HYDRATION_REQUIRED.includes(subBlockConfig.type)) {
const resolution = resolveSelectorForSubBlock(subBlockConfig, selectorCtx)
if (resolution?.key) {
const label = await resolveSelectorValue(value, resolution.key, selectorCtx)
if (label) {
return { original: value, displayLabel: label, resolved: true }
}
}
return { original: value, displayLabel: semanticFallback, resolved: true }
}
if (isUuid(value)) {
return { original: value, displayLabel: semanticFallback, resolved: true }
}
if (/^C[A-Z0-9]{8,}$/.test(value) || /^[UW][A-Z0-9]{8,}$/.test(value)) {
return { original: value, displayLabel: semanticFallback, resolved: true }
}
return {
original: value,
displayLabel: formatValueForDisplay(value),
resolved: false,
}
}