(
ctx: ExecutionContext,
block: SerializedBlock,
inputs: Record<string, any>
)
| 55 | } |
| 56 | |
| 57 | async execute( |
| 58 | ctx: ExecutionContext, |
| 59 | block: SerializedBlock, |
| 60 | inputs: Record<string, any> |
| 61 | ): Promise<BlockOutput | StreamingExecution> { |
| 62 | const task = asOptString(inputs.task) |
| 63 | if (!task) throw new Error('Task is required') |
| 64 | const model = asOptString(inputs.model) ?? DEFAULT_MODEL |
| 65 | |
| 66 | // Validate the mode up front so an invalid value reports a mode error rather |
| 67 | // than a misattributed credential error from key resolution below. |
| 68 | if (inputs.mode !== 'cloud' && inputs.mode !== 'local') { |
| 69 | throw new Error(`Invalid Pi mode: ${String(inputs.mode)}`) |
| 70 | } |
| 71 | const mode: 'cloud' | 'local' = inputs.mode |
| 72 | |
| 73 | const { providerId, apiKey, isBYOK } = await resolvePiModelKey({ |
| 74 | model, |
| 75 | mode, |
| 76 | workspaceId: ctx.workspaceId, |
| 77 | userId: ctx.userId, |
| 78 | apiKey: asRawString(inputs.apiKey), |
| 79 | vertexCredential: asOptString(inputs.vertexCredential), |
| 80 | }) |
| 81 | |
| 82 | const skills = await resolvePiSkills(inputs.skills, ctx.workspaceId) |
| 83 | const memoryConfig: PiMemoryConfig = { |
| 84 | memoryType: asOptString(inputs.memoryType) as PiMemoryConfig['memoryType'], |
| 85 | conversationId: asOptString(inputs.conversationId), |
| 86 | slidingWindowSize: asOptString(inputs.slidingWindowSize), |
| 87 | slidingWindowTokens: asOptString(inputs.slidingWindowTokens), |
| 88 | model, |
| 89 | } |
| 90 | const initialMessages = await loadPiMemory(ctx, memoryConfig) |
| 91 | |
| 92 | const base = { |
| 93 | model, |
| 94 | providerId, |
| 95 | apiKey, |
| 96 | isBYOK, |
| 97 | task, |
| 98 | thinkingLevel: asOptString(inputs.thinkingLevel), |
| 99 | skills, |
| 100 | initialMessages, |
| 101 | } |
| 102 | |
| 103 | if (mode === 'local') { |
| 104 | const host = asOptString(inputs.host) |
| 105 | const username = asOptString(inputs.username) |
| 106 | const repoPath = asOptString(inputs.repoPath) |
| 107 | if (!host || !username || !repoPath) { |
| 108 | throw new Error('Local mode requires host, username, and repository path') |
| 109 | } |
| 110 | const usePrivateKey = inputs.authMethod === 'privateKey' |
| 111 | const port = parseOptionalNumberInput(inputs.port, 'port', { integer: true, min: 1 }) ?? 22 |
| 112 | const tools = await buildSimToolSpecs(ctx, inputs.tools) |
| 113 | const params: PiLocalRunParams = { |
| 114 | ...base, |
nothing calls this directly
no test coverage detected