Files
wehub-resource-sync d25d482dc2
Publish CLI Package / publish-npm (push) Waiting to run
Publish Python SDK / publish-pypi (push) Waiting to run
Publish TypeScript SDK / publish-npm (push) Waiting to run
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
chore: import upstream snapshot with attribution
2026-07-13 13:20:55 +08:00

108 lines
3.7 KiB
TypeScript

/**
* Adapts user-selected Sim tools into backend-neutral {@link PiToolSpec}s that
* Pi can call in local mode. Each spec carries the tool's JSON-schema parameters
* and an `execute` that runs the real Sim tool through `executeTool`, so the
* agent's calls go through the same credential-access checks as any block.
*
* MCP and custom tools are skipped in v1; block/integration tools are supported.
*/
import { createLogger } from '@sim/logger'
import { getErrorMessage } from '@sim/utils/errors'
import { getAllBlocks } from '@/blocks/registry'
import type { ToolInput } from '@/executor/handlers/agent/types'
import type { PiToolResult, PiToolSpec } from '@/executor/handlers/pi/backend'
import type { ExecutionContext } from '@/executor/types'
import { transformBlockTool } from '@/providers/utils'
import { executeTool } from '@/tools'
import type { ToolResponse } from '@/tools/types'
import { getTool } from '@/tools/utils'
import { getToolAsync } from '@/tools/utils.server'
const logger = createLogger('PiSimTools')
function toToolResult(result: ToolResponse): PiToolResult {
if (result.success) {
const text =
typeof result.output === 'string' ? result.output : JSON.stringify(result.output ?? {})
return { text, isError: false }
}
return { text: result.error || 'Tool execution failed', isError: true }
}
/**
* Builds the Sim tool specs exposed to Pi for a local run. Only tools the user
* added to the block are included, and `usageControl: 'none'` tools are dropped.
*/
export async function buildSimToolSpecs(
ctx: ExecutionContext,
inputTools: unknown
): Promise<PiToolSpec[]> {
if (!Array.isArray(inputTools)) return []
const specs: PiToolSpec[] = []
for (const tool of inputTools as ToolInput[]) {
if ((tool.usageControl || 'auto') === 'none') continue
if (!tool.type || tool.type === 'mcp' || tool.type === 'custom-tool') continue
try {
const provider = await transformBlockTool(tool, {
selectedOperation: tool.operation,
getAllBlocks,
getTool,
getToolAsync,
})
if (!provider?.id) continue
const toolId = provider.id
const preseededParams = provider.params || {}
specs.push({
name: toolId,
description: provider.description || '',
parameters: (provider.parameters as Record<string, unknown>) || {
type: 'object',
properties: {},
},
execute: async (args) => {
try {
const result = await executeTool(
toolId,
{
...preseededParams,
...args,
// Trusted execution context, spread last so an LLM-supplied
// `_context` arg can't override it. executeTool reads this directly
// for OAuth-credential resolution and internal-route identity, the
// same way the Agent block's tool calls do.
_context: {
workflowId: ctx.workflowId,
workspaceId: ctx.workspaceId,
executionId: ctx.executionId,
userId: ctx.userId,
isDeployedContext: ctx.isDeployedContext,
enforceCredentialAccess: ctx.enforceCredentialAccess,
callChain: ctx.callChain,
},
},
{ executionContext: ctx }
)
return toToolResult(result)
} catch (error) {
return { text: getErrorMessage(error, 'Tool execution failed'), isError: true }
}
},
})
} catch (error) {
logger.warn('Failed to adapt Sim tool for Pi', {
type: tool.type,
error: getErrorMessage(error),
})
}
}
return specs
}