Align runtime naming with the current architecture by replacing PM-prefixed runtime services/env wiring with runtime-host terminology while keeping legacy PM env vars as fallbacks for compatibility.
Unified · Split
| @@ -104,7 +104,7 @@ Important boundary: · 103 unmodified lines | ||
| 104 | 104 | |
| 105 | 105 | ### Modes |
| 106 | 106 | |
| 107 | −- local-lite: PM daemon + in-memory hot state + file durability | |
| 107 | +- local-lite: Runtime Host daemon + in-memory hot state + file durability | |
| 108 | 108 | - remote: SQL-backed target (Postgres remote, SQLite local) |
| 109 | 109 | |
| 110 | 110 | ### Runtime targets |
| @@ -265,7 +265,7 @@ Secrets/credentials: · 154 unmodified lines | ||
| 265 | 265 | --- |
| 266 | 266 | |
| 267 | 267 | ## 12) Security posture |
| 268 | −- PM binds to loopback by default. | |
| 268 | +- Runtime Host binds to loopback by default. | |
| 269 | 269 | - Runtime callbacks require internal token validation. |
| 270 | 270 | - Secrets do not pass through model args/transcripts. |
| 271 | 271 | - Credential refs in state; secret values in secure stores. |
| @@ -279,7 +279,7 @@ Secrets/credentials: · 7 unmodified lines | ||
| 279 | 279 | v2/ |
| 280 | 280 | apps/ |
| 281 | 281 | cli/ |
| 282 | − pm/ | |
| 282 | + runtime-host/ | |
| 283 | 283 | web/ |
| 284 | 284 | packages/ |
| 285 | 285 | schema/ |
| @@ -340,7 +340,7 @@ Rules: · 54 unmodified lines | ||
| 340 | 340 | |
| 341 | 341 | ### Phase 1: local-lite execute vertical slice |
| 342 | 342 | |
| 343 | −- PM execute path with persisted run lifecycle | |
| 343 | +- Runtime Host execute path with persisted run lifecycle | |
| 344 | 344 | - runtime callback path wired through shared invocation service |
| 345 | 345 | - openapi + in_memory providers |
| 346 | 346 | |
| @@ -403,7 +403,7 @@ Implemented in `v2` so far: · 56 unmodified lines | ||
| 403 | 403 | - local in-process JS runner with `tools.*` proxy |
| 404 | 404 | - Deno subprocess runtime path with IPC tool-call proxying and tests |
| 405 | 405 | - runtime adapter contract + registry scaffold |
| 406 | −- PM execute lifecycle scaffold via MCP execute path | |
| 406 | +- Runtime Host execute lifecycle scaffold via MCP execute path | |
| 407 | 407 | |
| 408 | 408 | Still missing: |
| 409 | 409 | |
| @@ -417,7 +417,7 @@ Still missing: · 7 unmodified lines | ||
| 417 | 417 | |
| 418 | 418 | ## 19) Immediate next steps |
| 419 | 419 | |
| 420 | −1. Land shared `ToolInvocationService` contract in v2 and wire PM execute callback path through it. | |
| 420 | +1. Land shared `ToolInvocationService` contract in v2 and wire Runtime Host execute callback path through it. | |
| 421 | 421 | 2. Add `CredentialResolver` interfaces and local/remote implementations; integrate at invocation-time only. |
| 422 | 422 | 3. Implement control handlers for sources (`add/list/remove`) and route both host API and `tools.executor.*` through same code path. |
| 423 | 423 | 4. Implement cloudflare-worker-loader runtime dispatch adapter in v2 and wire callback endpoints. |
| @@ -26,13 +26,19 @@ Supported commands: · 25 unmodified lines | ||
| 26 | 26 | - `executor workspace use <workspace-id>` |
| 27 | 27 | - `executor run execute --code ...` |
| 28 | 28 | - `executor run execute --file ...` |
| 29 | −- `executor run bootstrap openapi --spec-url ... --source-base-url ...` | |
| 30 | −- `executor run bootstrap github` | |
| 29 | + | |
| 30 | +Control-plane management from CLI should happen through `run execute` and discovered | |
| 31 | +source tool paths (for example, add Executor's own OpenAPI source, then call its | |
| 32 | +tool paths to manage other sources). | |
| 31 | 33 | |
| 32 | 34 | Run locally: |
| 33 | 35 | |
| 34 | 36 | - `bun run --cwd apps/cli start -- target show` |
| 35 | 37 | - `bun run --cwd apps/cli start -- run execute --target local --code "return 1"` |
| 36 | −- `bun run --cwd apps/cli start -- run bootstrap github --target local` | |
| 37 | 38 | - `bun run --cwd apps/cli start -- --help` |
| 38 | 39 | - `bun run --cwd apps/cli start -- server start --port 8788` |
| 40 | + | |
| 41 | +Seed Executor's own OpenAPI source (example): | |
| 42 | + | |
| 43 | +- `bun run --cwd apps/cli start -- run execute --target local --workspace ws_local --code "const workspaceId='ws_local'; const res=await fetch('http://127.0.0.1:8788/v1/workspaces/'+workspaceId+'/sources',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({id:'src_executor_openapi',name:'executor:openapi',kind:'openapi',endpoint:'http://127.0.0.1:8788/v1/openapi.json',enabled:true,configJson:JSON.stringify({baseUrl:'http://127.0.0.1:8788'})})}); return await res.json();"` | |
| 44 | +- Then use `tools.discover(...)` in `run execute` to locate and call source tool paths. | |
| @@ -36,20 +36,6 @@ type WorkspaceRecord = { · 35 unmodified lines | ||
| 36 | 36 | id: string; |
| 37 | 37 | }; |
| 38 | 38 | |
| 39 | −type SourceRecord = { | |
| 40 | − id: string; | |
| 41 | − name: string; | |
| 42 | − endpoint: string; | |
| 43 | − configJson: string; | |
| 44 | −}; | |
| 45 | − | |
| 46 | −type SourceToolSummaryRecord = { | |
| 47 | − toolId: string; | |
| 48 | − method: string; | |
| 49 | − path: string; | |
| 50 | − name: string; | |
| 51 | −}; | |
| 52 | − | |
| 53 | 39 | type DeviceAuthorizationResponse = { |
| 54 | 40 | device_code: string; |
| 55 | 41 | user_code: string; |
| @@ -78,10 +64,6 @@ type CommonTargetOptions = { · 22 unmodified lines | ||
| 78 | 64 | |
| 79 | 65 | const DEFAULT_LOCAL_BASE_URL = "http://127.0.0.1:8788"; |
| 80 | 66 | const DEFAULT_WORKOS_AUTH_BASE_URL = "https://api.workos.com"; |
| 81 | −const DEFAULT_GITHUB_OPENAPI_SPEC_URL = | |
| 82 | − "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.json"; | |
| 83 | −const DEFAULT_GITHUB_API_BASE_URL = "https://api.github.com"; | |
| 84 | −const DEFAULT_GITHUB_OPENAPI_SOURCE_ID = "src_github_openapi"; | |
| 85 | 67 | const CONFIG_PATH = join(homedir(), ".config", "executor", "cli.json"); |
| 86 | 68 | |
| 87 | 69 | const toErrorMessage = (cause: unknown): string => |
| @@ -518,6 +500,8 @@ class ExecutorServerClient { · 430 unmodified lines | ||
| 518 | 500 | const childEnv = { |
| 519 | 501 | ...cleanEnv(), |
| 520 | 502 | PORT: localPort, |
| 503 | + EXECUTOR_RUNTIME_KIND: | |
| 504 | + process.env.EXECUTOR_LOCAL_RUNTIME_KIND?.trim() || "local-inproc", | |
| 521 | 505 | PM_RUNTIME_KIND: |
| 522 | 506 | process.env.EXECUTOR_LOCAL_RUNTIME_KIND?.trim() || "local-inproc", |
| 523 | 507 | }; |
| @@ -597,87 +581,6 @@ const ensureWorkspaceId = async ( · 73 unmodified lines | ||
| 597 | 581 | return workspaceId; |
| 598 | 582 | }; |
| 599 | 583 | |
| 600 | −const deriveSourceName = (kind: string, endpoint: string): string => { | |
| 601 | − try { | |
| 602 | − const url = new URL(endpoint); | |
| 603 | − const host = url.hostname.replace(/^api\./, ""); | |
| 604 | − return `${kind}:${host}`; | |
| 605 | − } catch { | |
| 606 | − return `${kind}:source`; | |
| 607 | − } | |
| 608 | −}; | |
| 609 | − | |
| 610 | −const bootstrapOpenApiSource = async (input: { | |
| 611 | − client: ExecutorServerClient; | |
| 612 | − config: ExecutorCliConfig; | |
| 613 | − workspaceOverride?: string; | |
| 614 | − specUrl: string; | |
| 615 | − baseUrl: string; | |
| 616 | − name?: string; | |
| 617 | − sourceId?: string; | |
| 618 | −}): Promise<{ | |
| 619 | − workspaceId: string; | |
| 620 | − source: SourceRecord; | |
| 621 | − tools: Array<SourceToolSummaryRecord>; | |
| 622 | − sampleToolPath: string | null; | |
| 623 | −}> => { | |
| 624 | − const workspaceId = await ensureWorkspaceId( | |
| 625 | − input.client, | |
| 626 | − input.config, | |
| 627 | − input.workspaceOverride, | |
| 628 | − ); | |
| 629 | − const normalizedSpecUrl = input.specUrl.trim(); | |
| 630 | − const normalizedBaseUrl = input.baseUrl.trim(); | |
| 631 | − | |
| 632 | − if (normalizedSpecUrl.length === 0) { | |
| 633 | − throw new Error("OpenAPI bootstrap requires --spec-url."); | |
| 634 | − } | |
| 635 | − | |
| 636 | − if (normalizedBaseUrl.length === 0) { | |
| 637 | − throw new Error("OpenAPI bootstrap requires --source-base-url."); | |
| 638 | − } | |
| 639 | − | |
| 640 | − const source = await input.client.runControlPlane((api) => | |
| 641 | − api.sources.upsert({ | |
| 642 | − path: { workspaceId }, | |
| 643 | − payload: { | |
| 644 | − ...(input.sourceId && input.sourceId.trim().length > 0 | |
| 645 | − ? { id: input.sourceId.trim() } | |
| 646 | − : {}), | |
| 647 | − name: | |
| 648 | − input.name && input.name.trim().length > 0 | |
| 649 | − ? input.name.trim() | |
| 650 | − : deriveSourceName("openapi", normalizedBaseUrl), | |
| 651 | − kind: "openapi", | |
| 652 | − endpoint: normalizedSpecUrl, | |
| 653 | − status: "connected", | |
| 654 | − enabled: true, | |
| 655 | − configJson: JSON.stringify({ baseUrl: normalizedBaseUrl }), | |
| 656 | − }, | |
| 657 | − }), | |
| 658 | − ) as SourceRecord; | |
| 659 | − | |
| 660 | − const tools = await input.client.runControlPlane((api) => | |
| 661 | − api.tools.listSourceTools({ | |
| 662 | − path: { | |
| 663 | − workspaceId, | |
| 664 | − sourceId: source.id, | |
| 665 | − }, | |
| 666 | − }), | |
| 667 | − ) as Array<SourceToolSummaryRecord>; | |
| 668 | − | |
| 669 | − const sampleToolPath = tools[0]?.toolId | |
| 670 | − ? `source.${source.id}.${tools[0].toolId}` | |
| 671 | − : null; | |
| 672 | − | |
| 673 | − return { | |
| 674 | − workspaceId, | |
| 675 | − source, | |
| 676 | − tools, | |
| 677 | − sampleToolPath, | |
| 678 | − }; | |
| 679 | −}; | |
| 680 | − | |
| 681 | 584 | const postForm = async ( |
| 682 | 585 | url: string, |
| 683 | 586 | params: Record<string, string>, |
| @@ -859,8 +762,9 @@ const commonTargetOptions = () => ({ · 175 unmodified lines | ||
| 859 | 762 | }); |
| 860 | 763 | |
| 861 | 764 | const startEmbeddedLocalServer = async (port: number): Promise<void> => { |
| 862 | − process.env.PM_RUNTIME_KIND = | |
| 765 | + process.env.EXECUTOR_RUNTIME_KIND = | |
| 863 | 766 | process.env.EXECUTOR_LOCAL_RUNTIME_KIND?.trim() || "local-inproc"; |
| 767 | + process.env.PM_RUNTIME_KIND = process.env.EXECUTOR_RUNTIME_KIND; | |
| 864 | 768 | |
| 865 | 769 | const { |
| 866 | 770 | createLocalPrincipal, |
| @@ -1254,134 +1158,8 @@ const runExecuteCommand = Command.make( · 387 unmodified lines | ||
| 1254 | 1158 | Command.withDescription("Execute TypeScript code through Executor runtime"), |
| 1255 | 1159 | ); |
| 1256 | 1160 | |
| 1257 | −const runBootstrapOpenApiCommand = Command.make( | |
| 1258 | − "openapi", | |
| 1259 | − { | |
| 1260 | − ...commonTargetOptions(), | |
| 1261 | − specUrl: Options.text("spec-url"), | |
| 1262 | − sourceBaseUrl: Options.text("source-base-url"), | |
| 1263 | − name: Options.text("name").pipe(Options.optional), | |
| 1264 | − sourceId: Options.text("source-id").pipe(Options.optional), | |
| 1265 | − }, | |
| 1266 | − (input) => | |
| 1267 | − Effect.tryPromise({ | |
| 1268 | − try: async () => { | |
| 1269 | − const common: CommonTargetOptions = { | |
| 1270 | − target: input.target, | |
| 1271 | − workspace: input.workspace, | |
| 1272 | − baseUrl: input.baseUrl, | |
| 1273 | − json: input.json, | |
| 1274 | − }; | |
| 1275 | − | |
| 1276 | − await withClient(common, async ({ client, config, workspaceOverride, asJson }) => { | |
| 1277 | − const setup = await bootstrapOpenApiSource({ | |
| 1278 | − client, | |
| 1279 | − config, | |
| 1280 | − workspaceOverride, | |
| 1281 | − specUrl: input.specUrl, | |
| 1282 | − baseUrl: input.sourceBaseUrl, | |
| 1283 | − name: optionToUndefined(input.name), | |
| 1284 | − sourceId: optionToUndefined(input.sourceId), | |
| 1285 | − }); | |
| 1286 | − | |
| 1287 | − printOutput( | |
| 1288 | − { | |
| 1289 | − ok: true, | |
| 1290 | − workspaceId: setup.workspaceId, | |
| 1291 | − source: { | |
| 1292 | − id: setup.source.id, | |
| 1293 | − name: setup.source.name, | |
| 1294 | − endpoint: setup.source.endpoint, | |
| 1295 | − configJson: setup.source.configJson, | |
| 1296 | − }, | |
| 1297 | − toolCount: setup.tools.length, | |
| 1298 | − sampleToolPath: setup.sampleToolPath, | |
| 1299 | − }, | |
| 1300 | − asJson, | |
| 1301 | − ); | |
| 1302 | − }); | |
| 1303 | − }, | |
| 1304 | − catch: toErrorMessage, | |
| 1305 | − }), | |
| 1306 | −).pipe( | |
| 1307 | − Command.withDescription("Bootstrap an OpenAPI source with runtime base URL"), | |
| 1308 | −); | |
| 1309 | − | |
| 1310 | −const runBootstrapGithubCommand = Command.make( | |
| 1311 | − "github", | |
| 1312 | − { | |
| 1313 | − ...commonTargetOptions(), | |
| 1314 | − name: Options.text("name").pipe(Options.optional), | |
| 1315 | − sourceId: Options.text("source-id").pipe(Options.optional), | |
| 1316 | − specUrl: Options.text("spec-url").pipe(Options.withDefault(DEFAULT_GITHUB_OPENAPI_SPEC_URL)), | |
| 1317 | − sourceBaseUrl: Options.text("source-base-url").pipe(Options.withDefault(DEFAULT_GITHUB_API_BASE_URL)), | |
| 1318 | − }, | |
| 1319 | − (input) => | |
| 1320 | − Effect.tryPromise({ | |
| 1321 | − try: async () => { | |
| 1322 | − const common: CommonTargetOptions = { | |
| 1323 | − target: input.target, | |
| 1324 | − workspace: input.workspace, | |
| 1325 | − baseUrl: input.baseUrl, | |
| 1326 | − json: input.json, | |
| 1327 | − }; | |
| 1328 | − | |
| 1329 | − await withClient(common, async ({ client, config, workspaceOverride, asJson }) => { | |
| 1330 | − const setup = await bootstrapOpenApiSource({ | |
| 1331 | − client, | |
| 1332 | − config, | |
| 1333 | − workspaceOverride, | |
| 1334 | − specUrl: input.specUrl, | |
| 1335 | − baseUrl: input.sourceBaseUrl, | |
| 1336 | − name: optionToUndefined(input.name) ?? "github:openapi", | |
| 1337 | − sourceId: optionToUndefined(input.sourceId) ?? DEFAULT_GITHUB_OPENAPI_SOURCE_ID, | |
| 1338 | − }); | |
| 1339 | − | |
| 1340 | − const suggestedTool = | |
| 1341 | − setup.tools.find((tool) => | |
| 1342 | − tool.toolId.includes("issues-and-pull-requests"), | |
| 1343 | − ) | |
| 1344 | − ?? setup.tools[0] | |
| 1345 | − ?? null; | |
| 1346 | − | |
| 1347 | − printOutput( | |
| 1348 | − { | |
| 1349 | − ok: true, | |
| 1350 | − workspaceId: setup.workspaceId, | |
| 1351 | − source: { | |
| 1352 | − id: setup.source.id, | |
| 1353 | − name: setup.source.name, | |
| 1354 | − endpoint: setup.source.endpoint, | |
| 1355 | − configJson: setup.source.configJson, | |
| 1356 | − }, | |
| 1357 | − toolCount: setup.tools.length, | |
| 1358 | − suggestedToolPath: suggestedTool | |
| 1359 | − ? `source.${setup.source.id}.${suggestedTool.toolId}` | |
| 1360 | − : null, | |
| 1361 | − executeHint: suggestedTool | |
| 1362 | − ? `executor run execute --code \"return await tools['source.${setup.source.id}.${suggestedTool.toolId}']({ q: 'repo:owner/repo is:issue state:open', per_page: 5 });\"` | |
| 1363 | − : null, | |
| 1364 | − }, | |
| 1365 | − asJson, | |
| 1366 | − ); | |
| 1367 | − }); | |
| 1368 | − }, | |
| 1369 | − catch: toErrorMessage, | |
| 1370 | − }), | |
| 1371 | −).pipe( | |
| 1372 | − Command.withDescription("Bootstrap GitHub OpenAPI source for public issue queries"), | |
| 1373 | −); | |
| 1374 | − | |
| 1375 | −const runBootstrapCommand = Command.make("bootstrap").pipe( | |
| 1376 | − Command.withSubcommands([ | |
| 1377 | − runBootstrapOpenApiCommand, | |
| 1378 | − runBootstrapGithubCommand, | |
| 1379 | − ] as any), | |
| 1380 | − Command.withDescription("Bootstrap source setup shortcuts for execution workflows"), | |
| 1381 | −); | |
| 1382 | − | |
| 1383 | 1161 | const runCommand = Command.make("run").pipe( |
| 1384 | − Command.withSubcommands([runExecuteCommand, runBootstrapCommand] as any), | |
| 1162 | + Command.withSubcommands([runExecuteCommand] as any), | |
| 1385 | 1163 | Command.withDescription("Code execution commands"), |
| 1386 | 1164 | ); |
| 1387 | 1165 | |
| @@ -30,19 +30,19 @@ import { · 29 unmodified lines | ||
| 30 | 30 | type ToolRegistryDiscoverOutput, |
| 31 | 31 | } from "@executor-v2/engine"; |
| 32 | 32 | import { |
| 33 | − PmActorLive, | |
| 33 | + RuntimeHostActorLive, | |
| 34 | 34 | createKeychainSecretMaterialStore, |
| 35 | − createPmApprovalsService, | |
| 36 | − createPmCredentialsService, | |
| 37 | − createPmExecuteRuntimeRun, | |
| 38 | − createPmMcpHandler, | |
| 39 | − createPmOrganizationsService, | |
| 40 | − createPmPersistentToolApprovalPolicy, | |
| 41 | − createPmPoliciesService, | |
| 42 | − createPmResolveToolCredentials, | |
| 43 | − createPmStorageService, | |
| 44 | − createPmToolsService, | |
| 45 | − createPmWorkspacesService, | |
| 35 | + createRuntimeHostApprovalsService, | |
| 36 | + createRuntimeHostCredentialsService, | |
| 37 | + createRuntimeHostExecuteRuntimeRun, | |
| 38 | + createRuntimeHostMcpHandler, | |
| 39 | + createRuntimeHostOrganizationsService, | |
| 40 | + createRuntimeHostPersistentToolApprovalPolicy, | |
| 41 | + createRuntimeHostPoliciesService, | |
| 42 | + createRuntimeHostResolveToolCredentials, | |
| 43 | + createRuntimeHostStorageService, | |
| 44 | + createRuntimeHostToolsService, | |
| 45 | + createRuntimeHostWorkspacesService, | |
| 46 | 46 | createSqlSecretMaterialStore, |
| 47 | 47 | parseSecretMaterialBackendKind, |
| 48 | 48 | } from "@executor-v2/control-plane-runtime"; |
| @@ -585,25 +585,25 @@ const createControlPlaneRuntime = async (): Promise<ControlPlaneRuntime> => { · 536 unmodified lines | ||
| 585 | 585 | ]; |
| 586 | 586 | const runtimeAdapters = makeRuntimeAdapterRegistry(runtimeAdapterList); |
| 587 | 587 | const defaultRuntimeKind = |
| 588 | − webServerEnvironment.pmRuntimeKind | |
| 588 | + webServerEnvironment.executorRuntimeKind | |
| 589 | 589 | ?? runtimeAdapterList[0]?.kind |
| 590 | 590 | ?? "local-inproc"; |
| 591 | − const requireToolApprovals = webServerEnvironment.pmRequireToolApprovals; | |
| 591 | + const requireToolApprovals = webServerEnvironment.executorRuntimeRequireToolApprovals; | |
| 592 | 592 | const defaultToolExposureMode = |
| 593 | − parseExecuteToolExposureMode(webServerEnvironment.pmToolExposureMode) | |
| 593 | + parseExecuteToolExposureMode(webServerEnvironment.executorRuntimeToolExposureMode) | |
| 594 | 594 | ?? defaultExecuteToolExposureMode; |
| 595 | 595 | const toolProviderRegistry = makeToolProviderRegistry([ |
| 596 | 596 | makeOpenApiToolProvider(), |
| 597 | 597 | makeMcpToolProvider(), |
| 598 | 598 | makeGraphqlToolProvider(), |
| 599 | 599 | ]); |
| 600 | − const persistentApprovalPolicy = createPmPersistentToolApprovalPolicy( | |
| 600 | + const persistentApprovalPolicy = createRuntimeHostPersistentToolApprovalPolicy( | |
| 601 | 601 | persistence.rows, |
| 602 | 602 | { |
| 603 | 603 | requireApprovals: requireToolApprovals, |
| 604 | 604 | }, |
| 605 | 605 | ); |
| 606 | − const resolveCredentials = createPmResolveToolCredentials( | |
| 606 | + const resolveCredentials = createRuntimeHostResolveToolCredentials( | |
| 607 | 607 | persistence.rows, |
| 608 | 608 | secretMaterialStore, |
| 609 | 609 | ); |
| @@ -722,20 +722,20 @@ const createControlPlaneRuntime = async (): Promise<ControlPlaneRuntime> => { · 112 unmodified lines | ||
| 722 | 722 | |
| 723 | 723 | const controlPlaneService = makeControlPlaneService({ |
| 724 | 724 | sources: sourcesService, |
| 725 | − credentials: createPmCredentialsService(persistence.rows, secretMaterialStore), | |
| 726 | − policies: createPmPoliciesService(persistence.rows), | |
| 727 | − organizations: createPmOrganizationsService(persistence.rows), | |
| 728 | − workspaces: createPmWorkspacesService(persistence.rows), | |
| 729 | − tools: createPmToolsService(sourceStore, toolArtifactStore), | |
| 730 | − storage: createPmStorageService(persistence.rows, { | |
| 725 | + credentials: createRuntimeHostCredentialsService(persistence.rows, secretMaterialStore), | |
| 726 | + policies: createRuntimeHostPoliciesService(persistence.rows), | |
| 727 | + organizations: createRuntimeHostOrganizationsService(persistence.rows), | |
| 728 | + workspaces: createRuntimeHostWorkspacesService(persistence.rows), | |
| 729 | + tools: createRuntimeHostToolsService(sourceStore, toolArtifactStore), | |
| 730 | + storage: createRuntimeHostStorageService(persistence.rows, { | |
| 731 | 731 | stateRootDir, |
| 732 | 732 | }), |
| 733 | − approvals: createPmApprovalsService(persistence.rows), | |
| 733 | + approvals: createRuntimeHostApprovalsService(persistence.rows), | |
| 734 | 734 | }); |
| 735 | 735 | |
| 736 | 736 | const controlPlaneWebHandler = makeControlPlaneWebHandler( |
| 737 | 737 | Layer.succeed(ControlPlaneService, controlPlaneService), |
| 738 | − PmActorLive(persistence.rows), | |
| 738 | + RuntimeHostActorLive(persistence.rows), | |
| 739 | 739 | ); |
| 740 | 740 | |
| 741 | 741 | const rememberRunWorkspace = (runId: string, workspaceId: string): void => { |
| @@ -772,7 +772,7 @@ const createControlPlaneRuntime = async (): Promise<ControlPlaneRuntime> => { · 30 unmodified lines | ||
| 772 | 772 | toolProviderRegistry, |
| 773 | 773 | approvalPolicy: persistentApprovalPolicy, |
| 774 | 774 | }); |
| 775 | − const executeRuntimeRun = createPmExecuteRuntimeRun({ | |
| 775 | + const executeRuntimeRun = createRuntimeHostExecuteRuntimeRun({ | |
| 776 | 776 | defaultRuntimeKind, |
| 777 | 777 | runtimeAdapters, |
| 778 | 778 | toolRegistry, |
| @@ -784,7 +784,7 @@ const createControlPlaneRuntime = async (): Promise<ControlPlaneRuntime> => { · 5 unmodified lines | ||
| 784 | 784 | return runId; |
| 785 | 785 | }, |
| 786 | 786 | }); |
| 787 | − const next = createPmMcpHandler(runExecutor.executeRun, { | |
| 787 | + const next = createRuntimeHostMcpHandler(runExecutor.executeRun, { | |
| 788 | 788 | toolRegistry, |
| 789 | 789 | defaultToolExposureMode, |
| 790 | 790 | }); |
| @@ -8,9 +8,18 @@ const webServerEnvConfig = configSchema("WebServerEnvironment", { · 7 unmodified lines | ||
| 8 | 8 | env: "CONTROL_PLANE_POSTGRES_CONNECTION_TARGET", |
| 9 | 9 | optional: true, |
| 10 | 10 | }), |
| 11 | − pmRuntimeKind: server({ env: "PM_RUNTIME_KIND", optional: true }), | |
| 12 | − pmRequireToolApprovals: server({ env: "PM_REQUIRE_TOOL_APPROVALS", optional: true }), | |
| 13 | − pmToolExposureMode: server({ env: "PM_TOOL_EXPOSURE_MODE", optional: true }), | |
| 11 | + executorRuntimeKind: server({ env: "EXECUTOR_RUNTIME_KIND", optional: true }), | |
| 12 | + legacyPmRuntimeKind: server({ env: "PM_RUNTIME_KIND", optional: true }), | |
| 13 | + executorRuntimeRequireToolApprovals: server({ | |
| 14 | + env: "EXECUTOR_RUNTIME_REQUIRE_TOOL_APPROVALS", | |
| 15 | + optional: true, | |
| 16 | + }), | |
| 17 | + legacyPmRequireToolApprovals: server({ env: "PM_REQUIRE_TOOL_APPROVALS", optional: true }), | |
| 18 | + executorRuntimeToolExposureMode: server({ | |
| 19 | + env: "EXECUTOR_RUNTIME_TOOL_EXPOSURE_MODE", | |
| 20 | + optional: true, | |
| 21 | + }), | |
| 22 | + legacyPmToolExposureMode: server({ env: "PM_TOOL_EXPOSURE_MODE", optional: true }), | |
| 14 | 23 | cloudflareSandboxCallbackSecret: server({ |
| 15 | 24 | env: "CLOUDFLARE_SANDBOX_CALLBACK_SECRET", |
| 16 | 25 | optional: true, |
| @@ -36,14 +45,18 @@ const webServerEnvConfig = configSchema("WebServerEnvironment", { · 19 unmodified lines | ||
| 36 | 45 | }); |
| 37 | 46 | |
| 38 | 47 | const env = webServerEnvConfig.server; |
| 48 | +const executorRuntimeRequireToolApprovalsRaw = | |
| 49 | + trim(env.executorRuntimeRequireToolApprovals) | |
| 50 | + ?? trim(env.legacyPmRequireToolApprovals); | |
| 39 | 51 | |
| 40 | 52 | export const webServerEnvironment = { |
| 41 | 53 | nodeEnv: trim(env.nodeEnv) ?? "development", |
| 42 | 54 | databaseUrl: trim(env.databaseUrl), |
| 43 | 55 | controlPlanePostgresConnectionTarget: trim(env.controlPlanePostgresConnectionTarget)?.toLowerCase(), |
| 44 | − pmRuntimeKind: trim(env.pmRuntimeKind), | |
| 45 | − pmRequireToolApprovals: isTruthy(env.pmRequireToolApprovals), | |
| 46 | − pmToolExposureMode: trim(env.pmToolExposureMode), | |
| 56 | + executorRuntimeKind: trim(env.executorRuntimeKind) ?? trim(env.legacyPmRuntimeKind), | |
| 57 | + executorRuntimeRequireToolApprovals: isTruthy(executorRuntimeRequireToolApprovalsRaw), | |
| 58 | + executorRuntimeToolExposureMode: | |
| 59 | + trim(env.executorRuntimeToolExposureMode) ?? trim(env.legacyPmToolExposureMode), | |
| 47 | 60 | cloudflareSandboxCallbackSecret: trim(env.cloudflareSandboxCallbackSecret), |
| 48 | 61 | executorPublicOrigin: trim(env.executorPublicOrigin), |
| 49 | 62 | vercelProjectProductionUrl: trim(env.vercelProjectProductionUrl), |
| @@ -84,14 +84,17 @@ const resolveActorFromSnapshot = ( · 83 unmodified lines | ||
| 84 | 84 | }); |
| 85 | 85 | }); |
| 86 | 86 | |
| 87 | −export const PmActorLive = (rows: ActorRows) => | |
| 87 | +export const RuntimeHostActorLive = (rows: ActorRows) => | |
| 88 | 88 | { |
| 89 | + const localAdminFallbackValue = | |
| 90 | + process.env.EXECUTOR_RUNTIME_ALLOW_LOCAL_ADMIN?.trim().toLowerCase() | |
| 91 | + ?? process.env.PM_ALLOW_LOCAL_ADMIN?.trim().toLowerCase() | |
| 92 | + ?? ""; | |
| 93 | + | |
| 89 | 94 | const localAdminFallbackEnabled = |
| 90 | − (process.env.PM_ALLOW_LOCAL_ADMIN?.trim().toLowerCase() ?? "") === "" | |
| 95 | + localAdminFallbackValue === "" | |
| 91 | 96 | ? process.env.NODE_ENV !== "production" |
| 92 | − : ["1", "true", "yes"].includes( | |
| 93 | − process.env.PM_ALLOW_LOCAL_ADMIN?.trim().toLowerCase() ?? "", | |
| 94 | − ); | |
| 97 | + : ["1", "true", "yes"].includes(localAdminFallbackValue); | |
| 95 | 98 | |
| 96 | 99 | return ControlPlaneActorResolverLive({ |
| 97 | 100 | resolveActor: (input) => resolveActorFromSnapshot(rows, input.headers, localAdminFallbackEnabled), |
| @@ -47,14 +47,14 @@ const toPersistentApprovalRecord = (approval: Approval): PersistentToolApprovalR · 46 unmodified lines | ||
| 47 | 47 | reason: approval.reason, |
| 48 | 48 | }); |
| 49 | 49 | |
| 50 | −export type PmPersistentToolApprovalPolicyOptions = { | |
| 50 | +export type RuntimeHostPersistentToolApprovalPolicyOptions = { | |
| 51 | 51 | requireApprovals?: boolean; |
| 52 | 52 | retryAfterMs?: number; |
| 53 | 53 | }; |
| 54 | 54 | |
| 55 | −export const createPmPersistentToolApprovalPolicy = ( | |
| 55 | +export const createRuntimeHostPersistentToolApprovalPolicy = ( | |
| 56 | 56 | rows: ApprovalRows, |
| 57 | − options: PmPersistentToolApprovalPolicyOptions = {}, | |
| 57 | + options: RuntimeHostPersistentToolApprovalPolicyOptions = {}, | |
| 58 | 58 | ): ToolApprovalPolicy => { |
| 59 | 59 | const store: PersistentToolApprovalStore = { |
| 60 | 60 | findByRunAndCall: (input) => |
| @@ -106,7 +106,7 @@ export const createPmPersistentToolApprovalPolicy = ( · 45 unmodified lines | ||
| 106 | 106 | }); |
| 107 | 107 | }; |
| 108 | 108 | |
| 109 | −export const createPmApprovalsService = ( | |
| 109 | +export const createRuntimeHostApprovalsService = ( | |
| 110 | 110 | rows: ApprovalRows, |
| 111 | 111 | ): ControlPlaneApprovalsServiceShape => |
| 112 | 112 | makeControlPlaneApprovalsService({ |
| @@ -163,7 +163,7 @@ const buildSecretHeaders = ( · 162 unmodified lines | ||
| 163 | 163 | return {}; |
| 164 | 164 | }; |
| 165 | 165 | |
| 166 | −export const createPmResolveToolCredentials = ( | |
| 166 | +export const createRuntimeHostResolveToolCredentials = ( | |
| 167 | 167 | rows: CredentialResolverRows, |
| 168 | 168 | secretMaterialStore: SecretMaterialStore, |
| 169 | 169 | ): ResolveToolCredentials => |
| @@ -73,7 +73,7 @@ const uniqueHandles = (handles: ReadonlyArray<string | null | undefined>): Array · 72 unmodified lines | ||
| 73 | 73 | return next; |
| 74 | 74 | }; |
| 75 | 75 | |
| 76 | −export const createPmCredentialsService = ( | |
| 76 | +export const createRuntimeHostCredentialsService = ( | |
| 77 | 77 | rows: CredentialRows, |
| 78 | 78 | secretMaterialStore: SecretMaterialStore, |
| 79 | 79 | ): ControlPlaneCredentialsServiceShape => |
| @@ -1,14 +1,14 @@ | ||
| 1 | −export { PmActorLive } from "./actor"; | |
| 1 | +export { RuntimeHostActorLive } from "./actor"; | |
| 2 | 2 | export { |
| 3 | − createPmApprovalsService, | |
| 4 | − createPmPersistentToolApprovalPolicy, | |
| 3 | + createRuntimeHostApprovalsService, | |
| 4 | + createRuntimeHostPersistentToolApprovalPolicy, | |
| 5 | 5 | } from "./approvals-service"; |
| 6 | −export { createPmResolveToolCredentials } from "./credential-resolver"; | |
| 7 | −export { createPmCredentialsService } from "./credentials-service"; | |
| 8 | −export { createPmMcpHandler } from "./mcp-handler"; | |
| 9 | −export { createPmOrganizationsService } from "./organizations-service"; | |
| 10 | −export { createPmPoliciesService } from "./policies-service"; | |
| 11 | −export { createPmExecuteRuntimeRun } from "./runtime-execution-port"; | |
| 6 | +export { createRuntimeHostResolveToolCredentials } from "./credential-resolver"; | |
| 7 | +export { createRuntimeHostCredentialsService } from "./credentials-service"; | |
| 8 | +export { createRuntimeHostMcpHandler } from "./mcp-handler"; | |
| 9 | +export { createRuntimeHostOrganizationsService } from "./organizations-service"; | |
| 10 | +export { createRuntimeHostPoliciesService } from "./policies-service"; | |
| 11 | +export { createRuntimeHostExecuteRuntimeRun } from "./runtime-execution-port"; | |
| 12 | 12 | export { |
| 13 | 13 | createKeychainSecretMaterialStore, |
| 14 | 14 | createSqlSecretMaterialStore, |
| @@ -19,6 +19,6 @@ export { · 4 unmodified lines | ||
| 19 | 19 | type SecretMaterialScope, |
| 20 | 20 | type SecretMaterialStore, |
| 21 | 21 | } from "./secret-material-store"; |
| 22 | −export { createPmStorageService } from "./storage-service"; | |
| 23 | −export { createPmToolsService } from "./tools-service"; | |
| 24 | −export { createPmWorkspacesService } from "./workspaces-service"; | |
| 22 | +export { createRuntimeHostStorageService } from "./storage-service"; | |
| 23 | +export { createRuntimeHostToolsService } from "./tools-service"; | |
| 24 | +export { createRuntimeHostWorkspacesService } from "./workspaces-service"; | |
| @@ -14,7 +14,7 @@ import { · 13 unmodified lines | ||
| 14 | 14 | import { handleMcpHttpRequest } from "@executor-v2/mcp-gateway"; |
| 15 | 15 | import * as Effect from "effect/Effect"; |
| 16 | 16 | |
| 17 | −export type PmMcpHandlerOptions = { | |
| 17 | +export type RuntimeHostMcpHandlerOptions = { | |
| 18 | 18 | toolRegistry: ToolRegistry; |
| 19 | 19 | defaultToolExposureMode?: ExecuteToolExposureMode; |
| 20 | 20 | }; |
| @@ -48,9 +48,9 @@ const resolveExecuteToolDescription = async ( · 27 unmodified lines | ||
| 48 | 48 | } |
| 49 | 49 | }; |
| 50 | 50 | |
| 51 | −export const createPmMcpHandler = ( | |
| 51 | +export const createRuntimeHostMcpHandler = ( | |
| 52 | 52 | executeRun: (input: ExecuteRunInput) => Effect.Effect<ExecuteRunResult>, |
| 53 | − options: PmMcpHandlerOptions, | |
| 53 | + options: RuntimeHostMcpHandlerOptions, | |
| 54 | 54 | ): ((request: Request) => Promise<Response>) => { |
| 55 | 55 | const runClient = createExecutorRunClient((input) => |
| 56 | 56 | Effect.runPromise(executeRun(input)), |
| @@ -67,7 +67,7 @@ export const createPmMcpHandler = ( · 10 unmodified lines | ||
| 67 | 67 | ); |
| 68 | 68 | |
| 69 | 69 | return handleMcpHttpRequest(request, { |
| 70 | − serverName: "executor-v2-pm", | |
| 70 | + serverName: "executor-v2-runtime-host", | |
| 71 | 71 | serverVersion: "0.0.0", |
| 72 | 72 | runClient, |
| 73 | 73 | executeToolDescription, |
| @@ -33,7 +33,7 @@ const sortOrganizations = ( · 32 unmodified lines | ||
| 33 | 33 | return leftName.localeCompare(rightName); |
| 34 | 34 | }); |
| 35 | 35 | |
| 36 | −export const createPmOrganizationsService = ( | |
| 36 | +export const createRuntimeHostOrganizationsService = ( | |
| 37 | 37 | rows: OrganizationRows, |
| 38 | 38 | ): ControlPlaneOrganizationsServiceShape => |
| 39 | 39 | makeControlPlaneOrganizationsService({ |
| @@ -24,7 +24,7 @@ const sortPolicies = (policies: ReadonlyArray<Policy>): Array<Policy> => · 23 unmodified lines | ||
| 24 | 24 | return leftPattern.localeCompare(rightPattern); |
| 25 | 25 | }); |
| 26 | 26 | |
| 27 | −export const createPmPoliciesService = ( | |
| 27 | +export const createRuntimeHostPoliciesService = ( | |
| 28 | 28 | rows: PolicyRows, |
| 29 | 29 | ): ControlPlanePoliciesServiceShape => |
| 30 | 30 | makeControlPlanePoliciesService({ |
| @@ -9,14 +9,14 @@ import { · 8 unmodified lines | ||
| 9 | 9 | } from "@executor-v2/engine"; |
| 10 | 10 | import * as Effect from "effect/Effect"; |
| 11 | 11 | |
| 12 | −export type PmRuntimeExecutionPortOptions = { | |
| 12 | +export type RuntimeHostExecutionPortOptions = { | |
| 13 | 13 | defaultRuntimeKind: string; |
| 14 | 14 | runtimeAdapters: RuntimeAdapterRegistry; |
| 15 | 15 | toolRegistry: ToolRegistry; |
| 16 | 16 | }; |
| 17 | 17 | |
| 18 | −export const createPmExecuteRuntimeRun = ( | |
| 19 | − options: PmRuntimeExecutionPortOptions, | |
| 18 | +export const createRuntimeHostExecuteRuntimeRun = ( | |
| 19 | + options: RuntimeHostExecutionPortOptions, | |
| 20 | 20 | ): ExecuteRuntimeRun => { |
| 21 | 21 | const runtimeToolCallService = createRuntimeToolCallService(options.toolRegistry); |
| 22 | 22 | |
| @@ -35,14 +35,14 @@ export const createPmExecuteRuntimeRun = ( · 12 unmodified lines | ||
| 35 | 35 | ), |
| 36 | 36 | ); |
| 37 | 37 | |
| 38 | − const isAvailable = yield* runtimeAdapter.isAvailable(); | |
| 39 | − if (!isAvailable) { | |
| 40 | − return yield* new RuntimeExecutionPortError({ | |
| 41 | − operation: "runtime_available", | |
| 42 | − message: `Runtime '${options.defaultRuntimeKind}' is not available in this pm process.`, | |
| 43 | − details: null, | |
| 44 | − }); | |
| 45 | − } | |
| 38 | + const isAvailable = yield* runtimeAdapter.isAvailable(); | |
| 39 | + if (!isAvailable) { | |
| 40 | + return yield* new RuntimeExecutionPortError({ | |
| 41 | + operation: "runtime_available", | |
| 42 | + message: `Runtime '${options.defaultRuntimeKind}' is not available in this runtime host process.`, | |
| 43 | + details: null, | |
| 44 | + }); | |
| 45 | + } | |
| 46 | 46 | |
| 47 | 47 | return yield* runtimeAdapter |
| 48 | 48 | .execute({ |
| @@ -136,7 +136,7 @@ const loadStorageScope = ( · 135 unmodified lines | ||
| 136 | 136 | }), |
| 137 | 137 | ); |
| 138 | 138 | |
| 139 | −export const createPmStorageService = ( | |
| 139 | +export const createRuntimeHostStorageService = ( | |
| 140 | 140 | rows: StorageRows, |
| 141 | 141 | options: { |
| 142 | 142 | stateRootDir: string; |
| @@ -141,7 +141,7 @@ const listSourceTools = ( · 140 unmodified lines | ||
| 141 | 141 | return yield* parseArtifactManifest(source, artifact); |
| 142 | 142 | }); |
| 143 | 143 | |
| 144 | −export const createPmToolsService = ( | |
| 144 | +export const createRuntimeHostToolsService = ( | |
| 145 | 145 | sourceStore: SourceStore, |
| 146 | 146 | toolArtifactStore: ToolArtifactStore, |
| 147 | 147 | ): ControlPlaneToolsServiceShape => |
| @@ -25,7 +25,7 @@ const sortWorkspaces = (workspaces: ReadonlyArray<Workspace>): Array<Workspace> · 24 unmodified lines | ||
| 25 | 25 | return leftName.localeCompare(rightName); |
| 26 | 26 | }); |
| 27 | 27 | |
| 28 | −export const createPmWorkspacesService = ( | |
| 28 | +export const createRuntimeHostWorkspacesService = ( | |
| 29 | 29 | rows: WorkspaceRows, |
| 30 | 30 | ): ControlPlaneWorkspacesServiceShape => |
| 31 | 31 | makeControlPlaneWorkspacesService({ |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | "CONTROL_PLANE_POSTGRES_MAX_CONNECTIONS", |
| 20 | 20 | "DATABASE_URL", |
| 21 | 21 | "MCP_AUTHORIZATION_SERVER", |
| 22 | + "EXECUTOR_RUNTIME_KIND", | |
| 22 | 23 | "PM_RUNTIME_KIND", |
| 23 | 24 | "VITE_CONVEX_URL", |
| 24 | 25 | "WORKOS_API_KEY", |