diff --git a/apps/sim/blocks/blocks/pi.test.ts b/apps/sim/blocks/blocks/pi.test.ts index 55724836117..70371fdaaba 100644 --- a/apps/sim/blocks/blocks/pi.test.ts +++ b/apps/sim/blocks/blocks/pi.test.ts @@ -18,7 +18,7 @@ vi.mock('@/lib/core/config/env', async (importOriginal) => { import { evaluateSubBlockCondition } from '@/lib/workflows/subblocks/visibility' import { PiBlock } from '@/blocks/blocks/pi' -import { PI_SEARCH_PROVIDERS } from '@/executor/handlers/pi/keys' +import { PI_SEARCH_PROVIDERS } from '@/executor/handlers/pi/core/keys' const searchProviderField = PiBlock.subBlocks.find((subBlock) => subBlock.id === 'searchProvider') const searchApiKeyField = PiBlock.subBlocks.find((subBlock) => subBlock.id === 'searchApiKey') diff --git a/apps/sim/executor/handlers/pi/cloud-backend.test.ts b/apps/sim/executor/handlers/pi/cloud/authoring/backend.test.ts similarity index 99% rename from apps/sim/executor/handlers/pi/cloud-backend.test.ts rename to apps/sim/executor/handlers/pi/cloud/authoring/backend.test.ts index 20d485e0f5f..20bfe39ad98 100644 --- a/apps/sim/executor/handlers/pi/cloud-backend.test.ts +++ b/apps/sim/executor/handlers/pi/cloud/authoring/backend.test.ts @@ -30,19 +30,19 @@ vi.mock('@/lib/execution/remote-sandbox/pi-lifetime', () => ({ // lifetime is the ceiling because there is nothing shorter to narrow to. resolvePiRunLifetimeMs: () => 40 * 60 * 1000, })) -vi.mock('@/executor/handlers/pi/babysit-backend', () => ({ +vi.mock('@/executor/handlers/pi/cloud/babysit/backend', () => ({ runBabysitPi: mockRunBabysit, })) vi.mock('@/tools', () => ({ executeTool: mockExecuteTool })) -vi.mock('@/executor/handlers/pi/keys', () => ({ +vi.mock('@/executor/handlers/pi/core/keys', () => ({ providerApiKeyEnvVar: mockProviderEnvVar, mapThinkingLevel: () => 'medium', })) -vi.mock('@/executor/handlers/pi/context', () => ({ buildPiPrompt: () => 'PROMPT' })) +vi.mock('@/executor/handlers/pi/core/context', () => ({ buildPiPrompt: () => 'PROMPT' })) import { createTimeoutAbortController } from '@/lib/core/execution-limits' -import type { PiCloudBranchRunParams, PiCloudRunParams } from '@/executor/handlers/pi/backend' -import { runCloudBranchPi, runCloudPi } from '@/executor/handlers/pi/cloud-backend' +import { runCloudBranchPi, runCloudPi } from '@/executor/handlers/pi/cloud/authoring/backend' +import type { PiCloudBranchRunParams, PiCloudRunParams } from '@/executor/handlers/pi/core/backend' function baseParams(overrides: Partial = {}): PiCloudRunParams { return { diff --git a/apps/sim/executor/handlers/pi/cloud-backend.ts b/apps/sim/executor/handlers/pi/cloud/authoring/backend.ts similarity index 98% rename from apps/sim/executor/handlers/pi/cloud-backend.ts rename to apps/sim/executor/handlers/pi/cloud/authoring/backend.ts index f6faee07d04..6b6934a29a9 100644 --- a/apps/sim/executor/handlers/pi/cloud-backend.ts +++ b/apps/sim/executor/handlers/pi/cloud/authoring/backend.ts @@ -28,14 +28,13 @@ import { resolvePiRunLifetimeMs, resolvePiSandboxLifetimeMs, } from '@/lib/execution/remote-sandbox/pi-lifetime' -import { runBabysitPi } from '@/executor/handlers/pi/babysit-backend' -import type { - PiBackendRun, - PiCloudBranchRunParams, - PiCloudRunParams, - PiRunContext, - PiRunResult, -} from '@/executor/handlers/pi/backend' +import { runBabysitPi } from '@/executor/handlers/pi/cloud/babysit/backend' +import { + type BranchPullRequest, + fetchOpenPrForBranch, + findOpenPrForBranch, + setPullRequestDraftState, +} from '@/executor/handlers/pi/cloud/github-pr' import { buildPiScript, CLONE_TIMEOUT_MS, @@ -54,26 +53,27 @@ import { raceAbort, resolvePiTimeoutMs, scrubGitSecrets, -} from '@/executor/handlers/pi/cloud-shared' -import { buildPiPrompt } from '@/executor/handlers/pi/context' +} from '@/executor/handlers/pi/cloud/shared' +import type { + PiBackendRun, + PiCloudBranchRunParams, + PiCloudRunParams, + PiRunContext, + PiRunResult, +} from '@/executor/handlers/pi/core/backend' +import { buildPiPrompt } from '@/executor/handlers/pi/core/context' import { applyPiEvent, createPiTotals, type PiRunTotals, parseJsonLine, -} from '@/executor/handlers/pi/events' -import { - type BranchPullRequest, - fetchOpenPrForBranch, - findOpenPrForBranch, - setPullRequestDraftState, -} from '@/executor/handlers/pi/github-pr' -import { mapThinkingLevel, providerApiKeyEnvVar } from '@/executor/handlers/pi/keys' +} from '@/executor/handlers/pi/core/events' +import { mapThinkingLevel, providerApiKeyEnvVar } from '@/executor/handlers/pi/core/keys' import { createScrubbedPiError, scrubPiEvent, scrubPiSecrets, -} from '@/executor/handlers/pi/redaction' +} from '@/executor/handlers/pi/core/redaction' import { PI_SEARCH_API_KEY_ENV_VAR, PI_SEARCH_EXTENSION_PATH, diff --git a/apps/sim/executor/handlers/pi/babysit-backend.test.ts b/apps/sim/executor/handlers/pi/cloud/babysit/backend.test.ts similarity index 98% rename from apps/sim/executor/handlers/pi/babysit-backend.test.ts rename to apps/sim/executor/handlers/pi/cloud/babysit/backend.test.ts index e80812d7edd..179f808ee48 100644 --- a/apps/sim/executor/handlers/pi/babysit-backend.test.ts +++ b/apps/sim/executor/handlers/pi/cloud/babysit/backend.test.ts @@ -46,8 +46,9 @@ vi.mock('@/lib/execution/remote-sandbox/pi-lifetime', async (importOriginal) => resolvePiSandboxLifetimeMs: mockResolvePiSandboxLifetime, } }) -vi.mock('@/executor/handlers/pi/babysit-github', async (importOriginal) => { - const original = await importOriginal() +vi.mock('@/executor/handlers/pi/cloud/babysit/github', async (importOriginal) => { + const original = + await importOriginal() return { ...original, fetchBabysitSnapshot: mockFetchSnapshot, @@ -64,10 +65,10 @@ import { createTimeoutAbortController, getMaxExecutionTimeout } from '@/lib/core import { resolveBabysitExecutionBudgetMs, runBabysitPiWithOptions, -} from '@/executor/handlers/pi/babysit-backend' -import { BABYSIT_ROUND_PATH } from '@/executor/handlers/pi/babysit-round' -import type { PiBabysitContinuationParams } from '@/executor/handlers/pi/backend' -import { DIFF_PATH } from '@/executor/handlers/pi/cloud-shared' +} from '@/executor/handlers/pi/cloud/babysit/backend' +import { BABYSIT_ROUND_PATH } from '@/executor/handlers/pi/cloud/babysit/round' +import { DIFF_PATH } from '@/executor/handlers/pi/cloud/shared' +import type { PiBabysitContinuationParams } from '@/executor/handlers/pi/core/backend' afterAll(resetEnvMock) diff --git a/apps/sim/executor/handlers/pi/babysit-backend.ts b/apps/sim/executor/handlers/pi/cloud/babysit/backend.ts similarity index 99% rename from apps/sim/executor/handlers/pi/babysit-backend.ts rename to apps/sim/executor/handlers/pi/cloud/babysit/backend.ts index 6fa3f1c94fa..12975c1b810 100644 --- a/apps/sim/executor/handlers/pi/babysit-backend.ts +++ b/apps/sim/executor/handlers/pi/cloud/babysit/backend.ts @@ -29,18 +29,13 @@ import { fetchBabysitThreads, replyAndResolveBabysitThreads, requestBabysitReview, -} from '@/executor/handlers/pi/babysit-github' +} from '@/executor/handlers/pi/cloud/babysit/github' import { BABYSIT_ROUND_PATH, MAX_ROUND_FILE_BYTES, MAX_THREADS_PER_ROUND, parseBabysitRound, -} from '@/executor/handlers/pi/babysit-round' -import type { - PiBabysitContinuationParams, - PiRunContext, - PiRunResult, -} from '@/executor/handlers/pi/backend' +} from '@/executor/handlers/pi/cloud/babysit/round' import { buildPiScript, CLONE_TIMEOUT_MS, @@ -58,20 +53,25 @@ import { raceAbort, resolvePiTimeoutMs, scrubGitSecrets, -} from '@/executor/handlers/pi/cloud-shared' -import { buildPiPrompt } from '@/executor/handlers/pi/context' +} from '@/executor/handlers/pi/cloud/shared' +import type { + PiBabysitContinuationParams, + PiRunContext, + PiRunResult, +} from '@/executor/handlers/pi/core/backend' +import { buildPiPrompt } from '@/executor/handlers/pi/core/context' import { applyPiEvent, createPiTotals, type PiRunTotals, parseJsonLine, -} from '@/executor/handlers/pi/events' -import { mapThinkingLevel, providerApiKeyEnvVar } from '@/executor/handlers/pi/keys' +} from '@/executor/handlers/pi/core/events' +import { mapThinkingLevel, providerApiKeyEnvVar } from '@/executor/handlers/pi/core/keys' import { createScrubbedPiError, scrubPiEvent, scrubPiSecrets, -} from '@/executor/handlers/pi/redaction' +} from '@/executor/handlers/pi/core/redaction' import { PI_SEARCH_API_KEY_ENV_VAR, PI_SEARCH_EXTENSION_PATH, diff --git a/apps/sim/executor/handlers/pi/babysit-github.test.ts b/apps/sim/executor/handlers/pi/cloud/babysit/github.test.ts similarity index 99% rename from apps/sim/executor/handlers/pi/babysit-github.test.ts rename to apps/sim/executor/handlers/pi/cloud/babysit/github.test.ts index a0c1eb443b0..804b4d75bb5 100644 --- a/apps/sim/executor/handlers/pi/babysit-github.test.ts +++ b/apps/sim/executor/handlers/pi/cloud/babysit/github.test.ts @@ -12,7 +12,7 @@ import { fetchBabysitSnapshot, fetchBabysitThreads, replyAndResolveBabysitThreads, -} from '@/executor/handlers/pi/babysit-github' +} from '@/executor/handlers/pi/cloud/babysit/github' const HEAD_SHA = 'a'.repeat(40) const BASE_SHA = 'b'.repeat(40) diff --git a/apps/sim/executor/handlers/pi/babysit-github.ts b/apps/sim/executor/handlers/pi/cloud/babysit/github.ts similarity index 99% rename from apps/sim/executor/handlers/pi/babysit-github.ts rename to apps/sim/executor/handlers/pi/cloud/babysit/github.ts index 8d08169996b..870e37d6ca2 100644 --- a/apps/sim/executor/handlers/pi/babysit-github.ts +++ b/apps/sim/executor/handlers/pi/cloud/babysit/github.ts @@ -1,13 +1,13 @@ import { getErrorMessage } from '@sim/utils/errors' import { truncate } from '@sim/utils/string' -import type { BabysitRoundDecision } from '@/executor/handlers/pi/babysit-round' +import type { BabysitRoundDecision } from '@/executor/handlers/pi/cloud/babysit/round' import { fetchPrSnapshot, type PullRequestCoordinates, type PullRequestSnapshot, validateRepositoryCoordinates, -} from '@/executor/handlers/pi/github-pr' -import { scrubPiSecrets } from '@/executor/handlers/pi/redaction' +} from '@/executor/handlers/pi/cloud/github-pr' +import { scrubPiSecrets } from '@/executor/handlers/pi/core/redaction' import { executeTool } from '@/tools' import { isRecord, diff --git a/apps/sim/executor/handlers/pi/babysit-round.test.ts b/apps/sim/executor/handlers/pi/cloud/babysit/round.test.ts similarity index 98% rename from apps/sim/executor/handlers/pi/babysit-round.test.ts rename to apps/sim/executor/handlers/pi/cloud/babysit/round.test.ts index 501898c8fc5..007bd01fb9a 100644 --- a/apps/sim/executor/handlers/pi/babysit-round.test.ts +++ b/apps/sim/executor/handlers/pi/cloud/babysit/round.test.ts @@ -7,7 +7,7 @@ import { MAX_ROUND_REPLY_LENGTH, MAX_THREADS_PER_ROUND, parseBabysitRound, -} from '@/executor/handlers/pi/babysit-round' +} from '@/executor/handlers/pi/cloud/babysit/round' const allowed = new Set(['thread-1', 'thread-2']) diff --git a/apps/sim/executor/handlers/pi/babysit-round.ts b/apps/sim/executor/handlers/pi/cloud/babysit/round.ts similarity index 98% rename from apps/sim/executor/handlers/pi/babysit-round.ts rename to apps/sim/executor/handlers/pi/cloud/babysit/round.ts index 920db25aa3e..030f7f81dc1 100644 --- a/apps/sim/executor/handlers/pi/babysit-round.ts +++ b/apps/sim/executor/handlers/pi/cloud/babysit/round.ts @@ -1,6 +1,6 @@ import { type Static, type TSchema, Type } from 'typebox' import { Check, Errors } from 'typebox/schema' -import { scrubPiSecrets } from '@/executor/handlers/pi/redaction' +import { scrubPiSecrets } from '@/executor/handlers/pi/core/redaction' /** Sandbox path used for the single-use, agent-authored round decision file. */ export const BABYSIT_ROUND_PATH = '/workspace/sim-babysit-round.json' diff --git a/apps/sim/executor/handlers/pi/github-pr.test.ts b/apps/sim/executor/handlers/pi/cloud/github-pr.test.ts similarity index 99% rename from apps/sim/executor/handlers/pi/github-pr.test.ts rename to apps/sim/executor/handlers/pi/cloud/github-pr.test.ts index bd533374099..ce5627c8c19 100644 --- a/apps/sim/executor/handlers/pi/github-pr.test.ts +++ b/apps/sim/executor/handlers/pi/cloud/github-pr.test.ts @@ -13,7 +13,7 @@ import { findOpenPrForBranch, setPullRequestDraftState, validateRepositoryCoordinates, -} from '@/executor/handlers/pi/github-pr' +} from '@/executor/handlers/pi/cloud/github-pr' const HEAD_SHA = 'a'.repeat(40) const BASE_SHA = 'b'.repeat(40) diff --git a/apps/sim/executor/handlers/pi/github-pr.ts b/apps/sim/executor/handlers/pi/cloud/github-pr.ts similarity index 100% rename from apps/sim/executor/handlers/pi/github-pr.ts rename to apps/sim/executor/handlers/pi/cloud/github-pr.ts diff --git a/apps/sim/executor/handlers/pi/cloud-review-backend.test.ts b/apps/sim/executor/handlers/pi/cloud/review/backend.test.ts similarity index 98% rename from apps/sim/executor/handlers/pi/cloud-review-backend.test.ts rename to apps/sim/executor/handlers/pi/cloud/review/backend.test.ts index 2aa7b116602..b10b8365a9f 100644 --- a/apps/sim/executor/handlers/pi/cloud-review-backend.test.ts +++ b/apps/sim/executor/handlers/pi/cloud/review/backend.test.ts @@ -64,11 +64,11 @@ vi.mock('@/lib/execution/remote-sandbox', () => ({ fn({ run: mockRun, writeFile: mockWriteFile }), })) vi.mock('@/tools', () => ({ executeTool: mockExecuteTool })) -vi.mock('@/executor/handlers/pi/keys', () => ({ mapThinkingLevel: () => 'medium' })) -vi.mock('@/executor/handlers/pi/context', () => ({ +vi.mock('@/executor/handlers/pi/core/keys', () => ({ mapThinkingLevel: () => 'medium' })) +vi.mock('@/executor/handlers/pi/core/context', () => ({ buildPiPrompt: ({ task, guidance }: { task: string; guidance: string }) => `${guidance}\n${task}`, })) -vi.mock('@/executor/handlers/pi/cloud-review-tools', () => ({ +vi.mock('@/executor/handlers/pi/cloud/review/tools', () => ({ CLOUD_REVIEW_TOOL_NAMES: [ 'read_repo_file', 'search_repo', @@ -83,16 +83,16 @@ vi.mock('@/executor/handlers/pi/cloud-review-tools', () => ({ createCloudReviewTools: mockCreateTools, })) // `toPiTool` stays real so the search tool's scrubbing boundary is the one shipped, not a stub. -vi.mock('@/executor/handlers/pi/pi-sdk', async (importOriginal) => ({ - ...(await importOriginal()), +vi.mock('@/executor/handlers/pi/core/pi-sdk', async (importOriginal) => ({ + ...(await importOriginal()), loadPiSdk: () => Promise.resolve(mockSdk), createPiModelRuntime: mockCreatePiModelRuntime, resolvePiSdkModel: () => ({ id: 'claude', provider: 'anthropic' }), createSealedPiResourceLoader: mockCreateSealedResourceLoader, })) -import type { PiCloudReviewRunParams } from '@/executor/handlers/pi/backend' -import { runCloudReviewPi } from '@/executor/handlers/pi/cloud-review-backend' +import { runCloudReviewPi } from '@/executor/handlers/pi/cloud/review/backend' +import type { PiCloudReviewRunParams } from '@/executor/handlers/pi/core/backend' /** * The mock logger instance the global `@sim/logger` mock handed to the module diff --git a/apps/sim/executor/handlers/pi/cloud-review-backend.ts b/apps/sim/executor/handlers/pi/cloud/review/backend.ts similarity index 97% rename from apps/sim/executor/handlers/pi/cloud-review-backend.ts rename to apps/sim/executor/handlers/pi/cloud/review/backend.ts index e82a648554e..c402f2cf9bb 100644 --- a/apps/sim/executor/handlers/pi/cloud-review-backend.ts +++ b/apps/sim/executor/handlers/pi/cloud/review/backend.ts @@ -12,42 +12,42 @@ import { createLogger } from '@sim/logger' import { truncate } from '@sim/utils/string' import { withPiSandbox } from '@/lib/execution/remote-sandbox' import { resolvePiRunLifetimeMs } from '@/lib/execution/remote-sandbox/pi-lifetime' -import type { PiBackendRun, PiCloudReviewRunParams } from '@/executor/handlers/pi/backend' +import { + fetchOpenPrSnapshot, + MAX_REVIEW_BODY_LENGTH, + type PullRequestSnapshot, + validateRepositoryCoordinates, +} from '@/executor/handlers/pi/cloud/github-pr' import { CLOUD_REVIEW_TOOL_NAMES, createCloudReviewTools, installCloudReviewTools, preflightCloudReviewCheckout, -} from '@/executor/handlers/pi/cloud-review-tools' +} from '@/executor/handlers/pi/cloud/review/tools' import { CLONE_TIMEOUT_MS, extractMarkerValues, REPO_DIR, raceAbort, scrubGitSecrets, -} from '@/executor/handlers/pi/cloud-shared' -import { buildPiPrompt } from '@/executor/handlers/pi/context' -import { applyPiEvent, createPiTotals, normalizePiEvent } from '@/executor/handlers/pi/events' -import { - fetchOpenPrSnapshot, - MAX_REVIEW_BODY_LENGTH, - type PullRequestSnapshot, - validateRepositoryCoordinates, -} from '@/executor/handlers/pi/github-pr' -import { mapThinkingLevel } from '@/executor/handlers/pi/keys' +} from '@/executor/handlers/pi/cloud/shared' +import type { PiBackendRun, PiCloudReviewRunParams } from '@/executor/handlers/pi/core/backend' +import { buildPiPrompt } from '@/executor/handlers/pi/core/context' +import { applyPiEvent, createPiTotals, normalizePiEvent } from '@/executor/handlers/pi/core/events' +import { mapThinkingLevel } from '@/executor/handlers/pi/core/keys' import { createPiModelRuntime, createSealedPiResourceLoader, loadPiSdk, resolvePiSdkModel, toPiTool, -} from '@/executor/handlers/pi/pi-sdk' +} from '@/executor/handlers/pi/core/pi-sdk' import { createScrubbedPiError, getScrubbedPiErrorMessage, scrubPiEvent, scrubPiSecrets, -} from '@/executor/handlers/pi/redaction' +} from '@/executor/handlers/pi/core/redaction' import { PI_SEARCH_TOOL_NAME, PI_SEARCH_UNTRUSTED_SENTENCE, diff --git a/apps/sim/executor/handlers/pi/cloud-review-tools-script.ts b/apps/sim/executor/handlers/pi/cloud/review/tools-script.ts similarity index 100% rename from apps/sim/executor/handlers/pi/cloud-review-tools-script.ts rename to apps/sim/executor/handlers/pi/cloud/review/tools-script.ts diff --git a/apps/sim/executor/handlers/pi/cloud-review-tools.test.ts b/apps/sim/executor/handlers/pi/cloud/review/tools.test.ts similarity index 99% rename from apps/sim/executor/handlers/pi/cloud-review-tools.test.ts rename to apps/sim/executor/handlers/pi/cloud/review/tools.test.ts index 357a4dfcd77..d43d1f1c4ae 100644 --- a/apps/sim/executor/handlers/pi/cloud-review-tools.test.ts +++ b/apps/sim/executor/handlers/pi/cloud/review/tools.test.ts @@ -19,7 +19,7 @@ import { CLOUD_REVIEW_TOOL_NAMES, createCloudReviewTools, installCloudReviewTools, -} from '@/executor/handlers/pi/cloud-review-tools' +} from '@/executor/handlers/pi/cloud/review/tools' const BASE_SHA = 'b'.repeat(40) const HEAD_SHA = 'a'.repeat(40) diff --git a/apps/sim/executor/handlers/pi/cloud-review-tools.ts b/apps/sim/executor/handlers/pi/cloud/review/tools.ts similarity index 97% rename from apps/sim/executor/handlers/pi/cloud-review-tools.ts rename to apps/sim/executor/handlers/pi/cloud/review/tools.ts index 7c5c329c36e..aaea6e735bb 100644 --- a/apps/sim/executor/handlers/pi/cloud-review-tools.ts +++ b/apps/sim/executor/handlers/pi/cloud/review/tools.ts @@ -1,10 +1,10 @@ import type { ToolDefinition } from '@earendil-works/pi-coding-agent' import { Type } from 'typebox' import type { PiSandboxRunner } from '@/lib/execution/remote-sandbox' -import { REVIEW_TOOLS_SCRIPT } from '@/executor/handlers/pi/cloud-review-tools-script' -import { raceAbort } from '@/executor/handlers/pi/cloud-shared' -import type { PiSdk } from '@/executor/handlers/pi/pi-sdk' -import { scrubPiSecrets } from '@/executor/handlers/pi/redaction' +import { REVIEW_TOOLS_SCRIPT } from '@/executor/handlers/pi/cloud/review/tools-script' +import { raceAbort } from '@/executor/handlers/pi/cloud/shared' +import type { PiSdk } from '@/executor/handlers/pi/core/pi-sdk' +import { scrubPiSecrets } from '@/executor/handlers/pi/core/redaction' import { parseReviewFindings, type ReviewFindings, diff --git a/apps/sim/executor/handlers/pi/cloud-shared.test.ts b/apps/sim/executor/handlers/pi/cloud/shared.test.ts similarity index 98% rename from apps/sim/executor/handlers/pi/cloud-shared.test.ts rename to apps/sim/executor/handlers/pi/cloud/shared.test.ts index 2b7f547f955..f58c020064d 100644 --- a/apps/sim/executor/handlers/pi/cloud-shared.test.ts +++ b/apps/sim/executor/handlers/pi/cloud/shared.test.ts @@ -12,7 +12,7 @@ import { FINALIZE_TIMEOUT_MS, MIN_PI_TIMEOUT_MS, resolvePiTimeoutMs, -} from '@/executor/handlers/pi/cloud-shared' +} from '@/executor/handlers/pi/cloud/shared' describe('resolvePiTimeoutMs', () => { it('reserves every command budget that brackets the agent turn', () => { diff --git a/apps/sim/executor/handlers/pi/cloud-shared.ts b/apps/sim/executor/handlers/pi/cloud/shared.ts similarity index 99% rename from apps/sim/executor/handlers/pi/cloud-shared.ts rename to apps/sim/executor/handlers/pi/cloud/shared.ts index f1b46e25b75..f83ba0e5a0f 100644 --- a/apps/sim/executor/handlers/pi/cloud-shared.ts +++ b/apps/sim/executor/handlers/pi/cloud/shared.ts @@ -7,7 +7,7 @@ import { getMaxExecutionTimeout } from '@/lib/core/execution-limits' import { resolvePiSandboxLifetimeMs } from '@/lib/execution/remote-sandbox/pi-lifetime' -import { scrubPiSecrets } from '@/executor/handlers/pi/redaction' +import { scrubPiSecrets } from '@/executor/handlers/pi/core/redaction' export const REPO_DIR = '/workspace/repo' export const PROMPT_PATH = '/workspace/pi-prompt.txt' diff --git a/apps/sim/executor/handlers/pi/backend.ts b/apps/sim/executor/handlers/pi/core/backend.ts similarity index 98% rename from apps/sim/executor/handlers/pi/backend.ts rename to apps/sim/executor/handlers/pi/core/backend.ts index dbca3e2779b..cf4fcd3b63b 100644 --- a/apps/sim/executor/handlers/pi/backend.ts +++ b/apps/sim/executor/handlers/pi/core/backend.ts @@ -11,8 +11,8 @@ import type { TSchema } from 'typebox' import type { SSHConnectionConfig } from '@/app/api/tools/ssh/utils' import type { Message } from '@/executor/handlers/agent/types' -import type { PiEvent, PiRunTotals } from '@/executor/handlers/pi/events' -import type { PiSearchProvider } from '@/executor/handlers/pi/keys' +import type { PiEvent, PiRunTotals } from '@/executor/handlers/pi/core/events' +import type { PiSearchProvider } from '@/executor/handlers/pi/core/keys' import type { PiSupportedProvider } from '@/providers/pi-provider-configs' /** A conversation message seeded into the Pi run (subset of the Agent block's message). */ diff --git a/apps/sim/executor/handlers/pi/context.ts b/apps/sim/executor/handlers/pi/core/context.ts similarity index 99% rename from apps/sim/executor/handlers/pi/context.ts rename to apps/sim/executor/handlers/pi/core/context.ts index b6e41e74e50..e5b2a899aa2 100644 --- a/apps/sim/executor/handlers/pi/context.ts +++ b/apps/sim/executor/handlers/pi/core/context.ts @@ -11,7 +11,7 @@ import { getErrorMessage } from '@sim/utils/errors' import { memoryService } from '@/executor/handlers/agent/memory' import { resolveSkillContentById } from '@/executor/handlers/agent/skills-resolver' import type { AgentInputs, Message, SkillInput } from '@/executor/handlers/agent/types' -import type { PiMessage, PiSkill } from '@/executor/handlers/pi/backend' +import type { PiMessage, PiSkill } from '@/executor/handlers/pi/core/backend' import type { ExecutionContext } from '@/executor/types' const logger = createLogger('PiContext') diff --git a/apps/sim/executor/handlers/pi/events.test.ts b/apps/sim/executor/handlers/pi/core/events.test.ts similarity index 99% rename from apps/sim/executor/handlers/pi/events.test.ts rename to apps/sim/executor/handlers/pi/core/events.test.ts index 1df73a40035..7f342bc603d 100644 --- a/apps/sim/executor/handlers/pi/events.test.ts +++ b/apps/sim/executor/handlers/pi/core/events.test.ts @@ -8,7 +8,7 @@ import { normalizePiEvent, parseJsonLine, streamTextForEvent, -} from '@/executor/handlers/pi/events' +} from '@/executor/handlers/pi/core/events' describe('normalizePiEvent', () => { it('maps a text_delta message_update to a text event', () => { diff --git a/apps/sim/executor/handlers/pi/events.ts b/apps/sim/executor/handlers/pi/core/events.ts similarity index 100% rename from apps/sim/executor/handlers/pi/events.ts rename to apps/sim/executor/handlers/pi/core/events.ts diff --git a/apps/sim/executor/handlers/pi/keys.test.ts b/apps/sim/executor/handlers/pi/core/keys.test.ts similarity index 99% rename from apps/sim/executor/handlers/pi/keys.test.ts rename to apps/sim/executor/handlers/pi/core/keys.test.ts index 5c0181d85b4..67553ee0a26 100644 --- a/apps/sim/executor/handlers/pi/keys.test.ts +++ b/apps/sim/executor/handlers/pi/core/keys.test.ts @@ -33,7 +33,7 @@ import { providerApiKeyEnvVar, resolvePiModelKey, resolvePiSearchKey, -} from '@/executor/handlers/pi/keys' +} from '@/executor/handlers/pi/core/keys' beforeAll(() => { envFlagsMockFns.getCostMultiplier.mockReturnValue(2) diff --git a/apps/sim/executor/handlers/pi/keys.ts b/apps/sim/executor/handlers/pi/core/keys.ts similarity index 100% rename from apps/sim/executor/handlers/pi/keys.ts rename to apps/sim/executor/handlers/pi/core/keys.ts diff --git a/apps/sim/executor/handlers/pi/pi-sdk.ts b/apps/sim/executor/handlers/pi/core/pi-sdk.ts similarity index 97% rename from apps/sim/executor/handlers/pi/pi-sdk.ts rename to apps/sim/executor/handlers/pi/core/pi-sdk.ts index 4599285e69e..3477839c2a6 100644 --- a/apps/sim/executor/handlers/pi/pi-sdk.ts +++ b/apps/sim/executor/handlers/pi/core/pi-sdk.ts @@ -1,7 +1,7 @@ import { InMemoryCredentialStore } from '@earendil-works/pi-ai' import type { ModelRuntime, ResourceLoader, ToolDefinition } from '@earendil-works/pi-coding-agent' -import type { PiToolSpec } from '@/executor/handlers/pi/backend' -import { createScrubbedPiError, scrubPiSecrets } from '@/executor/handlers/pi/redaction' +import type { PiToolSpec } from '@/executor/handlers/pi/core/backend' +import { createScrubbedPiError, scrubPiSecrets } from '@/executor/handlers/pi/core/redaction' /** The Pi SDK module, loaded dynamically so it stays externalized from the bundle. */ export type PiSdk = typeof import('@earendil-works/pi-coding-agent') diff --git a/apps/sim/executor/handlers/pi/redaction.test.ts b/apps/sim/executor/handlers/pi/core/redaction.test.ts similarity index 97% rename from apps/sim/executor/handlers/pi/redaction.test.ts rename to apps/sim/executor/handlers/pi/core/redaction.test.ts index 529deaf9b2e..e9835769b9e 100644 --- a/apps/sim/executor/handlers/pi/redaction.test.ts +++ b/apps/sim/executor/handlers/pi/core/redaction.test.ts @@ -7,7 +7,7 @@ import { getScrubbedPiErrorMessage, scrubPiEvent, scrubPiSecrets, -} from '@/executor/handlers/pi/redaction' +} from '@/executor/handlers/pi/core/redaction' describe('Pi secret redaction', () => { it('redacts literal and URL-encoded secret representations', () => { diff --git a/apps/sim/executor/handlers/pi/redaction.ts b/apps/sim/executor/handlers/pi/core/redaction.ts similarity index 96% rename from apps/sim/executor/handlers/pi/redaction.ts rename to apps/sim/executor/handlers/pi/core/redaction.ts index 904d9ae9f8d..faa5f27aabd 100644 --- a/apps/sim/executor/handlers/pi/redaction.ts +++ b/apps/sim/executor/handlers/pi/core/redaction.ts @@ -1,5 +1,5 @@ import { getErrorMessage } from '@sim/utils/errors' -import type { PiEvent } from '@/executor/handlers/pi/events' +import type { PiEvent } from '@/executor/handlers/pi/core/events' /** Redacts exact secret values and their URL-encoded forms from surfaced text. */ export function scrubPiSecrets(text: string, secrets: readonly string[]): string { diff --git a/apps/sim/executor/handlers/pi/local-backend.test.ts b/apps/sim/executor/handlers/pi/local/backend.test.ts similarity index 94% rename from apps/sim/executor/handlers/pi/local-backend.test.ts rename to apps/sim/executor/handlers/pi/local/backend.test.ts index 97c9da9e563..ec27dde622a 100644 --- a/apps/sim/executor/handlers/pi/local-backend.test.ts +++ b/apps/sim/executor/handlers/pi/local/backend.test.ts @@ -50,26 +50,26 @@ const mockModelRuntime = { removeRuntimeApiKey: mockRemoveRuntimeApiKey, } -vi.mock('@/executor/handlers/pi/context', () => ({ +vi.mock('@/executor/handlers/pi/core/context', () => ({ buildPiPrompt: ({ task }: { task: string }) => task, })) -vi.mock('@/executor/handlers/pi/keys', () => ({ mapThinkingLevel: () => 'medium' })) +vi.mock('@/executor/handlers/pi/core/keys', () => ({ mapThinkingLevel: () => 'medium' })) // `toPiTool` stays real: the scrubbing boundary it applies to tool results is what these tests // assert, and a stub would make them pass while the boundary was gone. -vi.mock('@/executor/handlers/pi/pi-sdk', async (importOriginal) => ({ - ...(await importOriginal()), +vi.mock('@/executor/handlers/pi/core/pi-sdk', async (importOriginal) => ({ + ...(await importOriginal()), loadPiSdk: () => Promise.resolve(mockSdk), createPiModelRuntime: mockCreatePiModelRuntime, resolvePiSdkModel: () => ({ id: 'claude', provider: 'anthropic' }), })) -vi.mock('@/executor/handlers/pi/ssh-tools', () => ({ +vi.mock('@/executor/handlers/pi/local/ssh-tools', () => ({ openSshSession: mockOpenSshSession, buildSshToolSpecs: mockBuildSshToolSpecs, captureRepoChanges: mockCaptureRepoChanges, })) -import type { PiLocalRunParams } from '@/executor/handlers/pi/backend' -import { runLocalPi } from '@/executor/handlers/pi/local-backend' +import type { PiLocalRunParams } from '@/executor/handlers/pi/core/backend' +import { runLocalPi } from '@/executor/handlers/pi/local/backend' function baseParams(): PiLocalRunParams { return { diff --git a/apps/sim/executor/handlers/pi/local-backend.ts b/apps/sim/executor/handlers/pi/local/backend.ts similarity index 94% rename from apps/sim/executor/handlers/pi/local-backend.ts rename to apps/sim/executor/handlers/pi/local/backend.ts index 63f6ad87b87..1f9371a3c24 100644 --- a/apps/sim/executor/handlers/pi/local-backend.ts +++ b/apps/sim/executor/handlers/pi/local/backend.ts @@ -18,29 +18,29 @@ import type { PiLocalRunParams, PiRunContext, PiRunResult, -} from '@/executor/handlers/pi/backend' -import { buildPiPrompt } from '@/executor/handlers/pi/context' -import { applyPiEvent, createPiTotals, normalizePiEvent } from '@/executor/handlers/pi/events' -import { mapThinkingLevel } from '@/executor/handlers/pi/keys' +} from '@/executor/handlers/pi/core/backend' +import { buildPiPrompt } from '@/executor/handlers/pi/core/context' +import { applyPiEvent, createPiTotals, normalizePiEvent } from '@/executor/handlers/pi/core/events' +import { mapThinkingLevel } from '@/executor/handlers/pi/core/keys' import { createPiModelRuntime, loadPiSdk, type PiSdk, resolvePiSdkModel, toPiTool, -} from '@/executor/handlers/pi/pi-sdk' +} from '@/executor/handlers/pi/core/pi-sdk' import { createScrubbedPiError, getScrubbedPiErrorMessage, scrubPiEvent, scrubPiSecrets, -} from '@/executor/handlers/pi/redaction' +} from '@/executor/handlers/pi/core/redaction' import { buildSshToolSpecs, captureRepoChanges, openSshSession, type PiSshSession, -} from '@/executor/handlers/pi/ssh-tools' +} from '@/executor/handlers/pi/local/ssh-tools' import { getPiProviderId } from '@/providers/pi-providers' const logger = createLogger('PiLocalBackend') diff --git a/apps/sim/executor/handlers/pi/sim-tools.test.ts b/apps/sim/executor/handlers/pi/local/sim-tools.test.ts similarity index 99% rename from apps/sim/executor/handlers/pi/sim-tools.test.ts rename to apps/sim/executor/handlers/pi/local/sim-tools.test.ts index 2e1760cfbcc..c2f7945a631 100644 --- a/apps/sim/executor/handlers/pi/sim-tools.test.ts +++ b/apps/sim/executor/handlers/pi/local/sim-tools.test.ts @@ -13,7 +13,7 @@ vi.mock('@/tools', () => ({ executeTool: mockExecuteTool })) vi.mock('@/tools/utils', () => ({ getTool: vi.fn() })) vi.mock('@/tools/utils.server', () => ({ getToolAsync: vi.fn() })) -import { buildSimToolSpecs } from '@/executor/handlers/pi/sim-tools' +import { buildSimToolSpecs } from '@/executor/handlers/pi/local/sim-tools' import type { ExecutionContext } from '@/executor/types' import { ResolvedSecretTraceRegistry } from '@/executor/utils/resolved-secret-trace-registry' import { ToolSchemaEnrichmentError } from '@/tools/params' diff --git a/apps/sim/executor/handlers/pi/sim-tools.ts b/apps/sim/executor/handlers/pi/local/sim-tools.ts similarity index 99% rename from apps/sim/executor/handlers/pi/sim-tools.ts rename to apps/sim/executor/handlers/pi/local/sim-tools.ts index f49c511ce48..785d1477c6a 100644 --- a/apps/sim/executor/handlers/pi/sim-tools.ts +++ b/apps/sim/executor/handlers/pi/local/sim-tools.ts @@ -12,7 +12,7 @@ import { getErrorMessage } from '@sim/utils/errors' import { resolveCustomBlockToolBinding } from '@/lib/workflows/custom-blocks/operations' import { getAllBlocks } from '@/blocks/registry' import type { ToolInput } from '@/executor/handlers/agent/types' -import type { PiToolResult, PiToolSpec } from '@/executor/handlers/pi/backend' +import type { PiToolResult, PiToolSpec } from '@/executor/handlers/pi/core/backend' import type { ExecutionContext } from '@/executor/types' import { projectResolvedSecretModelContent, diff --git a/apps/sim/executor/handlers/pi/ssh-tools.test.ts b/apps/sim/executor/handlers/pi/local/ssh-tools.test.ts similarity index 96% rename from apps/sim/executor/handlers/pi/ssh-tools.test.ts rename to apps/sim/executor/handlers/pi/local/ssh-tools.test.ts index ff70cdb2669..05a4b21e9be 100644 --- a/apps/sim/executor/handlers/pi/ssh-tools.test.ts +++ b/apps/sim/executor/handlers/pi/local/ssh-tools.test.ts @@ -20,8 +20,7 @@ vi.mock('@/app/api/tools/ssh/utils', () => ({ }, })) -import type { PiSshSession } from '@/executor/handlers/pi/ssh-tools' -import { buildSshToolSpecs } from '@/executor/handlers/pi/ssh-tools' +import { buildSshToolSpecs, type PiSshSession } from '@/executor/handlers/pi/local/ssh-tools' function createSession(files: Record): PiSshSession { const sftp = { diff --git a/apps/sim/executor/handlers/pi/ssh-tools.ts b/apps/sim/executor/handlers/pi/local/ssh-tools.ts similarity index 99% rename from apps/sim/executor/handlers/pi/ssh-tools.ts rename to apps/sim/executor/handlers/pi/local/ssh-tools.ts index 0fa471e2190..182d8caf6fb 100644 --- a/apps/sim/executor/handlers/pi/ssh-tools.ts +++ b/apps/sim/executor/handlers/pi/local/ssh-tools.ts @@ -15,7 +15,7 @@ import { sanitizeCommand, sanitizePath, } from '@/app/api/tools/ssh/utils' -import type { PiSshConnection, PiToolResult, PiToolSpec } from '@/executor/handlers/pi/backend' +import type { PiSshConnection, PiToolResult, PiToolSpec } from '@/executor/handlers/pi/core/backend' const logger = createLogger('PiSshTools') diff --git a/apps/sim/executor/handlers/pi/pi-handler.test.ts b/apps/sim/executor/handlers/pi/pi-handler.test.ts index a236123c412..784f4f9e325 100644 --- a/apps/sim/executor/handlers/pi/pi-handler.test.ts +++ b/apps/sim/executor/handlers/pi/pi-handler.test.ts @@ -39,7 +39,7 @@ const { MockToolNotAllowedError: class ToolNotAllowedError extends Error {}, })) -vi.mock('@/executor/handlers/pi/keys', () => ({ +vi.mock('@/executor/handlers/pi/core/keys', () => ({ resolvePiModelKey: mockResolveKey, computePiCost: () => ({ input: 0, output: 0, total: 0 }), parsePiSearchProvider: mockParseSearchProvider, @@ -56,20 +56,20 @@ vi.mock('@/ee/access-control/utils/permission-check', () => ({ assertPermissionsAllowed: mockAssertPermissionsAllowed, ToolNotAllowedError: MockToolNotAllowedError, })) -vi.mock('@/executor/handlers/pi/context', () => ({ +vi.mock('@/executor/handlers/pi/core/context', () => ({ resolvePiSkills: mockResolveSkills, loadPiMemory: mockLoadMemory, appendPiMemory: mockAppendMemory, })) -vi.mock('@/executor/handlers/pi/sim-tools', () => ({ +vi.mock('@/executor/handlers/pi/local/sim-tools', () => ({ buildSimToolSpecs: vi.fn().mockResolvedValue([]), })) -vi.mock('@/executor/handlers/pi/local-backend', () => ({ runLocalPi: mockRunLocal })) -vi.mock('@/executor/handlers/pi/cloud-backend', () => ({ +vi.mock('@/executor/handlers/pi/local/backend', () => ({ runLocalPi: mockRunLocal })) +vi.mock('@/executor/handlers/pi/cloud/authoring/backend', () => ({ runCloudPi: mockRunCloud, runCloudBranchPi: mockRunCloudBranch, })) -vi.mock('@/executor/handlers/pi/cloud-review-backend', () => ({ +vi.mock('@/executor/handlers/pi/cloud/review/backend', () => ({ runCloudReviewPi: mockRunCloudReview, })) vi.mock('@/providers/pi-providers', () => ({ diff --git a/apps/sim/executor/handlers/pi/pi-handler.ts b/apps/sim/executor/handlers/pi/pi-handler.ts index 7a847270ee9..130f152f25a 100644 --- a/apps/sim/executor/handlers/pi/pi-handler.ts +++ b/apps/sim/executor/handlers/pi/pi-handler.ts @@ -14,6 +14,8 @@ import { ToolNotAllowedError, } from '@/ee/access-control/utils/permission-check' import { BlockType } from '@/executor/constants' +import { runCloudBranchPi, runCloudPi } from '@/executor/handlers/pi/cloud/authoring/backend' +import { runCloudReviewPi } from '@/executor/handlers/pi/cloud/review/backend' import type { PiBackendRun, PiCloudBranchRunParams, @@ -24,26 +26,24 @@ import type { PiRunParams, PiRunResult, PiSearchConfig, -} from '@/executor/handlers/pi/backend' -import { runCloudBranchPi, runCloudPi } from '@/executor/handlers/pi/cloud-backend' -import { runCloudReviewPi } from '@/executor/handlers/pi/cloud-review-backend' +} from '@/executor/handlers/pi/core/backend' import { appendPiMemory, loadPiMemory, type PiMemoryConfig, resolvePiSkills, -} from '@/executor/handlers/pi/context' -import { streamTextForEvent } from '@/executor/handlers/pi/events' +} from '@/executor/handlers/pi/core/context' +import { streamTextForEvent } from '@/executor/handlers/pi/core/events' import { computePiCost, PI_SEARCH_PROVIDERS, parsePiSearchProvider, resolvePiModelKey, resolvePiSearchKey, -} from '@/executor/handlers/pi/keys' -import { runLocalPi } from '@/executor/handlers/pi/local-backend' +} from '@/executor/handlers/pi/core/keys' +import { runLocalPi } from '@/executor/handlers/pi/local/backend' +import { buildSimToolSpecs } from '@/executor/handlers/pi/local/sim-tools' import { buildPiSearchToolSpec } from '@/executor/handlers/pi/search/tool' -import { buildSimToolSpecs } from '@/executor/handlers/pi/sim-tools' import type { BlockHandler, ExecutionContext, diff --git a/apps/sim/executor/handlers/pi/search/extension-source.test.ts b/apps/sim/executor/handlers/pi/search/extension-source.test.ts index 0926057faab..e04fb7bb085 100644 --- a/apps/sim/executor/handlers/pi/search/extension-source.test.ts +++ b/apps/sim/executor/handlers/pi/search/extension-source.test.ts @@ -11,7 +11,7 @@ import { tmpdir } from 'node:os' import { join } from 'node:path' import { pathToFileURL } from 'node:url' import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest' -import { PI_SEARCH_PROVIDERS, type PiSearchProvider } from '@/executor/handlers/pi/keys' +import { PI_SEARCH_PROVIDERS, type PiSearchProvider } from '@/executor/handlers/pi/core/keys' import { PI_SEARCH_API_KEY_ENV_VAR, PI_SEARCH_EXTENSION_PATH, diff --git a/apps/sim/executor/handlers/pi/search/normalize.ts b/apps/sim/executor/handlers/pi/search/normalize.ts index 39fc79d844d..9bc556d331f 100644 --- a/apps/sim/executor/handlers/pi/search/normalize.ts +++ b/apps/sim/executor/handlers/pi/search/normalize.ts @@ -9,7 +9,7 @@ * holds the two request paths together. */ -import type { PiSearchProvider } from '@/executor/handlers/pi/keys' +import type { PiSearchProvider } from '@/executor/handlers/pi/core/keys' /** The tool name Pi sees, in every mode. */ export const PI_SEARCH_TOOL_NAME = 'web_search' diff --git a/apps/sim/executor/handlers/pi/search/parity.test.ts b/apps/sim/executor/handlers/pi/search/parity.test.ts index 6c894042f59..d3ce8752aae 100644 --- a/apps/sim/executor/handlers/pi/search/parity.test.ts +++ b/apps/sim/executor/handlers/pi/search/parity.test.ts @@ -15,7 +15,7 @@ import { tmpdir } from 'node:os' import { join } from 'node:path' import { pathToFileURL } from 'node:url' import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest' -import { PI_SEARCH_PROVIDERS, type PiSearchProvider } from '@/executor/handlers/pi/keys' +import { PI_SEARCH_PROVIDERS, type PiSearchProvider } from '@/executor/handlers/pi/core/keys' import { PI_SEARCH_API_KEY_ENV_VAR, PI_SEARCH_EXTENSION_SOURCE, diff --git a/apps/sim/executor/handlers/pi/search/tool.ts b/apps/sim/executor/handlers/pi/search/tool.ts index d86ff6d546d..13e9d034bdc 100644 --- a/apps/sim/executor/handlers/pi/search/tool.ts +++ b/apps/sim/executor/handlers/pi/search/tool.ts @@ -8,8 +8,8 @@ */ import { createLogger } from '@sim/logger' -import type { PiSearchConfig, PiToolSpec } from '@/executor/handlers/pi/backend' -import { PI_SEARCH_PROVIDERS } from '@/executor/handlers/pi/keys' +import type { PiSearchConfig, PiToolSpec } from '@/executor/handlers/pi/core/backend' +import { PI_SEARCH_PROVIDERS } from '@/executor/handlers/pi/core/keys' import { buildPiSearchProviderArgs, extractPiSearchRecords,