@executor-js/sdk 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/README.md +21 -29
  2. package/dist/api-errors.d.ts +10 -0
  3. package/dist/api-errors.d.ts.map +1 -0
  4. package/dist/blob.d.ts.map +1 -1
  5. package/dist/chunk-6SQWMOM4.js +51 -0
  6. package/dist/chunk-6SQWMOM4.js.map +1 -0
  7. package/dist/chunk-NPWV4R3N.js +5563 -0
  8. package/dist/chunk-NPWV4R3N.js.map +1 -0
  9. package/dist/chunk-QQK7X3DM.js +103 -0
  10. package/dist/chunk-QQK7X3DM.js.map +1 -0
  11. package/dist/client.d.ts +2 -5
  12. package/dist/client.d.ts.map +1 -1
  13. package/dist/client.js +12 -18
  14. package/dist/client.js.map +1 -1
  15. package/dist/connections.d.ts +7 -0
  16. package/dist/connections.d.ts.map +1 -1
  17. package/dist/core-schema.d.ts +83 -3
  18. package/dist/core-schema.d.ts.map +1 -1
  19. package/dist/core.js +94 -52
  20. package/dist/core.js.map +1 -1
  21. package/dist/credential-bindings.d.ts +173 -0
  22. package/dist/credential-bindings.d.ts.map +1 -0
  23. package/dist/credential-bindings.test.d.ts +2 -0
  24. package/dist/credential-bindings.test.d.ts.map +1 -0
  25. package/dist/errors.d.ts +27 -5
  26. package/dist/errors.d.ts.map +1 -1
  27. package/dist/executor.d.ts +47 -13
  28. package/dist/executor.d.ts.map +1 -1
  29. package/dist/hosted-http-client.d.ts +17 -0
  30. package/dist/hosted-http-client.d.ts.map +1 -0
  31. package/dist/hosted-http-client.test.d.ts +2 -0
  32. package/dist/hosted-http-client.test.d.ts.map +1 -0
  33. package/dist/ids.d.ts +2 -0
  34. package/dist/ids.d.ts.map +1 -1
  35. package/dist/index.d.ts +15 -10
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +16 -18
  38. package/dist/index.js.map +1 -1
  39. package/dist/oauth-discovery.d.ts +19 -4
  40. package/dist/oauth-discovery.d.ts.map +1 -1
  41. package/dist/oauth-helpers.d.ts +21 -0
  42. package/dist/oauth-helpers.d.ts.map +1 -1
  43. package/dist/oauth-popup-types.d.ts.map +1 -1
  44. package/dist/oauth-service.d.ts +16 -5
  45. package/dist/oauth-service.d.ts.map +1 -1
  46. package/dist/oauth.d.ts +19 -16
  47. package/dist/oauth.d.ts.map +1 -1
  48. package/dist/oxlint-plugin-executor.test.d.ts +2 -0
  49. package/dist/oxlint-plugin-executor.test.d.ts.map +1 -0
  50. package/dist/plugin.d.ts +84 -19
  51. package/dist/plugin.d.ts.map +1 -1
  52. package/dist/policies.d.ts +10 -15
  53. package/dist/policies.d.ts.map +1 -1
  54. package/dist/promise-executor.d.ts.map +1 -1
  55. package/dist/promise.d.ts +5 -3
  56. package/dist/promise.d.ts.map +1 -1
  57. package/dist/schema-types.d.ts.map +1 -1
  58. package/dist/scoped-adapter.d.ts +17 -2
  59. package/dist/scoped-adapter.d.ts.map +1 -1
  60. package/dist/secrets.d.ts +12 -0
  61. package/dist/secrets.d.ts.map +1 -1
  62. package/dist/test-config.d.ts +10 -0
  63. package/dist/test-config.d.ts.map +1 -0
  64. package/dist/testing.d.ts +30 -8
  65. package/dist/testing.d.ts.map +1 -1
  66. package/dist/testing.js +56 -0
  67. package/dist/testing.js.map +1 -0
  68. package/dist/types.d.ts +11 -3
  69. package/dist/types.d.ts.map +1 -1
  70. package/dist/usage-visibility.test.d.ts +2 -0
  71. package/dist/usage-visibility.test.d.ts.map +1 -0
  72. package/dist/usages.d.ts +20 -0
  73. package/dist/usages.d.ts.map +1 -0
  74. package/package.json +26 -14
  75. package/dist/chunk-2WV7VSNL.js +0 -4440
  76. package/dist/chunk-2WV7VSNL.js.map +0 -1
@@ -0,0 +1,103 @@
1
+ import {
2
+ Scope,
3
+ ScopeId,
4
+ collectSchemas,
5
+ makeInMemoryBlobStore
6
+ } from "./chunk-NPWV4R3N.js";
7
+
8
+ // src/plugin.ts
9
+ import { Effect } from "effect";
10
+ var defineSchema = (schema) => schema;
11
+ var decodeStaticToolArgs = (schema, args) => {
12
+ if (schema == null) return Effect.succeed(args);
13
+ return Effect.promise(() => Promise.resolve(schema["~standard"].validate(args))).pipe(
14
+ Effect.flatMap(
15
+ (result) => "value" in result ? Effect.succeed(result.value) : Effect.fail(result)
16
+ )
17
+ );
18
+ };
19
+ var tool = (input) => ({
20
+ name: input.name,
21
+ description: input.description,
22
+ inputSchema: input.inputSchema,
23
+ outputSchema: input.outputSchema,
24
+ annotations: input.annotations,
25
+ handler: ({ args, ctx, elicit }) => decodeStaticToolArgs(input.inputSchema, args).pipe(
26
+ Effect.flatMap(
27
+ (decoded) => input.execute(
28
+ decoded,
29
+ { ctx, elicit }
30
+ )
31
+ )
32
+ )
33
+ });
34
+ function definePlugin(authorFactory) {
35
+ return (options) => {
36
+ const {
37
+ storage: storageOverride,
38
+ ...rest
39
+ } = options ?? {};
40
+ const hasAuthorOptions = Object.keys(rest).length > 0;
41
+ const spec = authorFactory(hasAuthorOptions ? rest : void 0);
42
+ return {
43
+ ...spec,
44
+ storage: storageOverride ?? spec.storage
45
+ };
46
+ };
47
+ }
48
+
49
+ // src/test-config.ts
50
+ import { makeMemoryAdapter } from "@executor-js/storage-core/testing/memory";
51
+ import { Effect as Effect2 } from "effect";
52
+ var makeTestConfig = (options) => {
53
+ const scopes = options?.scopes ?? [
54
+ new Scope({
55
+ id: ScopeId.make("test-scope"),
56
+ name: options?.scopeName ?? "test",
57
+ createdAt: /* @__PURE__ */ new Date()
58
+ })
59
+ ];
60
+ const schema = collectSchemas(options?.plugins ?? []);
61
+ return {
62
+ scopes,
63
+ adapter: makeMemoryAdapter({ schema }),
64
+ blobs: makeInMemoryBlobStore(),
65
+ plugins: options?.plugins,
66
+ // Tests default to auto-accepting elicitation prompts. Override via
67
+ // a wrapping spread if a test exercises a real handler:
68
+ // { ...makeTestConfig(...), onElicitation: customHandler }
69
+ onElicitation: "accept-all"
70
+ };
71
+ };
72
+ var memorySecretsPlugin = definePlugin(() => {
73
+ const store = /* @__PURE__ */ new Map();
74
+ const provider = {
75
+ key: "memory",
76
+ writable: true,
77
+ get: (id, scope) => Effect2.sync(() => store.get(`${scope}\0${id}`) ?? null),
78
+ set: (id, value, scope) => Effect2.sync(() => {
79
+ store.set(`${scope}\0${id}`, value);
80
+ }),
81
+ delete: (id, scope) => Effect2.sync(() => store.delete(`${scope}\0${id}`)),
82
+ list: () => Effect2.sync(
83
+ () => Array.from(store.keys()).map((key) => {
84
+ const name = key.split("\0", 2)[1] ?? key;
85
+ return { id: name, name };
86
+ })
87
+ )
88
+ };
89
+ return {
90
+ id: "memory-secrets",
91
+ storage: () => ({}),
92
+ secretProviders: [provider]
93
+ };
94
+ });
95
+
96
+ export {
97
+ defineSchema,
98
+ tool,
99
+ definePlugin,
100
+ makeTestConfig,
101
+ memorySecretsPlugin
102
+ };
103
+ //# sourceMappingURL=chunk-QQK7X3DM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/plugin.ts","../src/test-config.ts"],"sourcesContent":["import { Effect } from \"effect\";\nimport type { Context, Layer } from \"effect\";\nimport type { HttpClient } from \"effect/unstable/http\";\nimport type { HttpApiGroup } from \"effect/unstable/httpapi\";\nimport type { StandardJSONSchemaV1, StandardSchemaV1 } from \"@standard-schema/spec\";\nimport type { DBSchema, StorageFailure } from \"@executor-js/storage-core\";\n\nimport type { PluginBlobStore } from \"./blob\";\nimport type {\n ConnectionProvider,\n ConnectionRef,\n ConnectionRefreshError,\n CreateConnectionInput,\n RemoveConnectionInput,\n UpdateConnectionTokensInput,\n} from \"./connections\";\nimport type { CredentialBindingsFacade } from \"./credential-bindings\";\nimport type { DefinitionsInput, SourceInput, ToolAnnotations, ToolRow } from \"./core-schema\";\nimport type { RemoveSourceInput, SourceDetectionResult } from \"./types\";\nimport type {\n ElicitationDeclinedError,\n ElicitationHandler,\n ElicitationRequest,\n ElicitationResponse,\n} from \"./elicitation\";\nimport type {\n ConnectionInUseError,\n ConnectionNotFoundError,\n ConnectionProviderNotRegisteredError,\n ConnectionReauthRequiredError,\n ConnectionRefreshNotSupportedError,\n SecretInUseError,\n SecretOwnedByConnectionError,\n} from \"./errors\";\nimport type { OAuthService } from \"./oauth\";\nimport type { Scope } from \"./scope\";\nimport type { ScopedDBAdapter, ScopedTypedAdapter } from \"./scoped-adapter\";\nimport type { RemoveSecretInput, SecretProvider, SecretRef, SetSecretInput } from \"./secrets\";\nimport type { Usage, UsagesForConnectionInput, UsagesForSecretInput } from \"./usages\";\n\n// ---------------------------------------------------------------------------\n// StorageDeps — backing passed to a plugin's `storage` factory. The only\n// place a plugin ever sees storage; `PluginCtx` does not carry it. The\n// `adapter` field is a `TypedAdapter<TSchema>` view narrowed by the\n// plugin's own declared `schema` — plugins never import or construct\n// a typed adapter themselves, the executor infers TSchema from the\n// `schema` field on their spec and hands back a typed view.\n//\n// Plugins with no schema (secret-provider-only plugins, etc.) get a\n// bare `DBAdapter` they can ignore.\n// ---------------------------------------------------------------------------\n\nexport interface StorageDeps<TSchema extends DBSchema | undefined = undefined> {\n /**\n * Precedence-ordered scope stack visible to this executor. Innermost\n * first. Reads on scoped tables walk every scope; writes require the\n * plugin to name a target scope explicitly (via `scope_id` on the\n * adapter payload, via `options.scope` on the blob store).\n */\n readonly scopes: readonly Scope[];\n /**\n * Plugin-facing typed adapter. Failures surface as raw `StorageFailure`\n * (`StorageError` | `UniqueViolationError`). Plugins can\n * `catchTag(\"UniqueViolationError\", …)` to translate to their own\n * user-facing errors. `StorageError` bubbles up; the HTTP edge (see\n * `@executor-js/api` `withCapture`) is the one place that\n * translates it to the opaque `InternalError({ traceId })`.\n */\n readonly adapter: TSchema extends DBSchema ? ScopedTypedAdapter<TSchema> : ScopedDBAdapter;\n readonly blobs: PluginBlobStore;\n}\n\n// ---------------------------------------------------------------------------\n// defineSchema — sugar around `as const satisfies DBSchema`. Preserves\n// literal types via the `const` type parameter modifier so plugins can\n// just write `const mySchema = defineSchema({ ... })` without annotation\n// ceremony.\n// ---------------------------------------------------------------------------\n\nexport const defineSchema = <const S extends DBSchema>(schema: S): S => schema;\n\n// ---------------------------------------------------------------------------\n// Elicit — suspends the fiber, calls the invoke-time elicitation\n// handler, resumes with the user's response. Available on both static\n// tool handlers and dynamic `invokeTool` handlers. Threaded through\n// the executor from `createExecutor({ onElicitation })`.\n// ---------------------------------------------------------------------------\n\nexport type Elicit = (\n request: ElicitationRequest,\n) => Effect.Effect<ElicitationResponse, ElicitationDeclinedError>;\n\n// ---------------------------------------------------------------------------\n// PluginCtx — threaded into every extension method, static tool handler,\n// and dynamic tool handler. No raw adapter, no raw blobs. Core writes\n// go through `core.sources.register` / `core.definitions.register`.\n// ---------------------------------------------------------------------------\n\nexport interface PluginCtx<TStore = unknown> {\n /**\n * Precedence-ordered scope stack visible to this executor. Innermost\n * first. Plugins that write scoped rows must pick an element of\n * `scopes` as the `scope`/`scope_id` they stamp; reads through the\n * adapter or `ctx.secrets` automatically fall through the stack.\n */\n readonly scopes: readonly Scope[];\n readonly storage: TStore;\n readonly httpClientLayer: Layer.Layer<HttpClient.HttpClient>;\n\n readonly core: {\n readonly sources: {\n readonly register: (input: SourceInput) => Effect.Effect<void, StorageFailure>;\n readonly unregister: (input: RemoveSourceInput) => Effect.Effect<void, StorageFailure>;\n readonly update: (input: {\n readonly id: string;\n readonly scope: string;\n readonly name?: string;\n readonly url?: string | null;\n }) => Effect.Effect<void, StorageFailure>;\n };\n /** Register shared JSON-schema `$defs` for a source. Tool\n * input/output schemas registered via `sources.register` can carry\n * `$ref: \"#/$defs/X\"` pointers; `executor.tools.schema(toolId)`\n * attaches matching defs to the returned schema. Call inside the\n * same `ctx.transaction` as `sources.register` for atomicity.\n * Replaces any existing defs for the given sourceId. */\n readonly definitions: {\n readonly register: (input: DefinitionsInput) => Effect.Effect<void, StorageFailure>;\n };\n };\n\n readonly secrets: {\n readonly get: (\n id: string,\n ) => Effect.Effect<string | null, SecretOwnedByConnectionError | StorageFailure>;\n readonly getAtScope: (\n id: string,\n scope: string,\n ) => Effect.Effect<string | null, SecretOwnedByConnectionError | StorageFailure>;\n /** List user-visible secrets. Connection-owned secrets (rows with\n * `owned_by_connection_id` set) are filtered out so they don't\n * clutter the UI — users see the Connection instead. */\n readonly list: () => Effect.Effect<\n readonly { readonly id: string; readonly name: string; readonly provider: string }[],\n StorageFailure\n >;\n /** Write a secret value through a provider. Used by plugins that\n * mint secrets on behalf of the user (OAuth2 token storage,\n * interactive onboarding flows). Normally writes go through\n * `executor.secrets.set` on the host surface, but OAuth2 refresh\n * and one-shot token capture from plugin-owned flows need it here\n * too. Same routing rules as the host-level setter. */\n readonly set: (input: SetSecretInput) => Effect.Effect<SecretRef, StorageFailure>;\n /** Delete a secret from its pinned provider and the core table.\n * Rejects with `SecretOwnedByConnectionError` if the row is owned\n * by a connection — callers must go through `connections.remove`\n * to drop the whole sign-in. Rejects with `SecretInUseError` if\n * any plugin reports the secret as in use; the caller should ask\n * the user to detach the listed sources first. */\n readonly remove: (\n input: RemoveSecretInput,\n ) => Effect.Effect<void, SecretOwnedByConnectionError | SecretInUseError | StorageFailure>;\n };\n\n /** Connections — product-level sign-in state. Owns backing secret\n * rows via `secret.owned_by_connection_id`. Plugins call\n * `connections.accessToken(id)` at invoke time to get a guaranteed-\n * fresh token (the SDK handles refresh via the registered provider\n * keyed by `connection.provider`). */\n readonly connections: {\n readonly get: (id: string) => Effect.Effect<ConnectionRef | null, StorageFailure>;\n readonly getAtScope: (\n id: string,\n scope: string,\n ) => Effect.Effect<ConnectionRef | null, StorageFailure>;\n readonly list: () => Effect.Effect<readonly ConnectionRef[], StorageFailure>;\n readonly create: (\n input: CreateConnectionInput,\n ) => Effect.Effect<ConnectionRef, ConnectionProviderNotRegisteredError | StorageFailure>;\n readonly updateTokens: (\n input: UpdateConnectionTokensInput,\n ) => Effect.Effect<ConnectionRef, ConnectionNotFoundError | StorageFailure>;\n readonly setIdentityLabel: (\n id: string,\n label: string | null,\n ) => Effect.Effect<void, ConnectionNotFoundError | StorageFailure>;\n /** Get a guaranteed-fresh access token. Calls the provider's\n * `refresh` handler if `expires_at` is in the past / within the\n * refresh skew window. */\n readonly accessToken: (\n id: string,\n ) => Effect.Effect<\n string,\n | ConnectionNotFoundError\n | ConnectionProviderNotRegisteredError\n | ConnectionRefreshNotSupportedError\n | ConnectionReauthRequiredError\n | ConnectionRefreshError\n | StorageFailure\n >;\n readonly accessTokenAtScope: (\n id: string,\n scope: string,\n ) => Effect.Effect<\n string,\n | ConnectionNotFoundError\n | ConnectionProviderNotRegisteredError\n | ConnectionRefreshNotSupportedError\n | ConnectionReauthRequiredError\n | ConnectionRefreshError\n | StorageFailure\n >;\n /** Refuses with `ConnectionInUseError` if any plugin reports the\n * connection as in use. Caller surfaces the `usages` list to the\n * user. */\n readonly remove: (\n input: RemoveConnectionInput,\n ) => Effect.Effect<void, ConnectionInUseError | StorageFailure>;\n };\n\n readonly credentialBindings: CredentialBindingsFacade;\n\n /** Shared OAuth service. Plugins use this to probe/start/complete OAuth\n * flows; invocation should still resolve tokens via `connections.accessToken`. */\n readonly oauth: OAuthService;\n\n /** Run `effect` inside a database transaction. Wraps the underlying\n * adapter's transaction method. Use this in extension methods that\n * need atomicity across plugin storage writes AND core source/tool\n * registration. */\n readonly transaction: <A, E>(effect: Effect.Effect<A, E>) => Effect.Effect<A, E | StorageFailure>;\n}\n\n// ---------------------------------------------------------------------------\n// Static tool / source declarations. Pure data + handlers declared at\n// plugin-definition time.\n//\n// Importantly, `StaticToolDecl.handler` does NOT reference TExtension.\n// If it did, the nested generic would break inference for the whole\n// PluginSpec (TS would fall back to the `object` constraint on TExtension).\n// `self: NoInfer<TExtension>` lives on `staticSources` one level up\n// instead, and plugin authors close over it via the arrow-function\n// closure when they write their handler.\n// ---------------------------------------------------------------------------\n\nexport interface StaticToolHandlerInput<TStore = unknown> {\n readonly ctx: PluginCtx<TStore>;\n readonly args: unknown;\n /** Suspend the fiber to request user input. The handler passed to\n * `createExecutor({ onElicitation })` is called. */\n readonly elicit: Elicit;\n}\n\nexport interface StaticToolExecuteContext<TStore = unknown> {\n readonly ctx: PluginCtx<TStore>;\n /** Suspend the fiber to request user input. The handler passed to\n * `createExecutor({ onElicitation })` is called. */\n readonly elicit: Elicit;\n}\n\nexport type StaticToolSchema<Input = unknown, Output = Input> = StandardSchemaV1<Input, Output> &\n StandardJSONSchemaV1<Input, Output>;\n\nexport interface StaticToolDecl<TStore = unknown> {\n readonly name: string;\n readonly description: string;\n readonly inputSchema?: StaticToolSchema;\n readonly outputSchema?: StaticToolSchema;\n /** Default-policy annotations — `requiresApproval`, `approvalDescription`,\n * `mayElicit`. Enforced by the executor before the handler runs.\n * Inline because static tools have no plugin storage to resolve from;\n * the plugin author literally writes this at definition time. */\n readonly annotations?: ToolAnnotations;\n readonly handler: (input: StaticToolHandlerInput<TStore>) => Effect.Effect<unknown, unknown>;\n}\n\nconst decodeStaticToolArgs = (\n schema: StaticToolSchema | undefined,\n args: unknown,\n): Effect.Effect<unknown, unknown> => {\n if (schema == null) return Effect.succeed(args);\n return Effect.promise(() => Promise.resolve(schema[\"~standard\"].validate(args))).pipe(\n Effect.flatMap((result) =>\n \"value\" in result ? Effect.succeed(result.value) : Effect.fail(result),\n ),\n );\n};\n\nexport interface StaticToolInput<\n TStore = unknown,\n TInputSchema extends StaticToolSchema | undefined = StaticToolSchema | undefined,\n> {\n readonly name: string;\n readonly description: string;\n readonly inputSchema?: TInputSchema;\n readonly outputSchema?: StaticToolSchema;\n /** Default-policy annotations — `requiresApproval`, `approvalDescription`,\n * `mayElicit`. Enforced by the executor before the handler runs. */\n readonly annotations?: ToolAnnotations;\n readonly execute: (\n args: TInputSchema extends StaticToolSchema\n ? StandardSchemaV1.InferOutput<TInputSchema>\n : unknown,\n context: StaticToolExecuteContext<TStore>,\n ) => Effect.Effect<unknown, unknown>;\n}\n\nexport const tool = <\n TStore = unknown,\n TInputSchema extends StaticToolSchema | undefined = StaticToolSchema | undefined,\n>(\n input: StaticToolInput<TStore, TInputSchema>,\n): StaticToolDecl<TStore> => ({\n name: input.name,\n description: input.description,\n inputSchema: input.inputSchema,\n outputSchema: input.outputSchema,\n annotations: input.annotations,\n handler: ({ args, ctx, elicit }) =>\n decodeStaticToolArgs(input.inputSchema, args).pipe(\n Effect.flatMap((decoded) =>\n input.execute(\n decoded as TInputSchema extends StaticToolSchema\n ? StandardSchemaV1.InferOutput<TInputSchema>\n : unknown,\n { ctx, elicit },\n ),\n ),\n ),\n});\n\nexport interface StaticSourceDecl<TStore = unknown> {\n readonly id: string;\n readonly kind: string;\n readonly name: string;\n readonly url?: string;\n /** Static sources default to `canRemove: false` because they are\n * plugin-provided surfaces and shouldn't usually be user-removable.\n * Override only if you really want that. */\n readonly canRemove?: boolean;\n readonly canRefresh?: boolean;\n readonly canEdit?: boolean;\n readonly tools: readonly StaticToolDecl<TStore>[];\n}\n\n// ---------------------------------------------------------------------------\n// Dynamic invoke / source lifecycle inputs.\n// ---------------------------------------------------------------------------\n\nexport interface InvokeToolInput<TStore = unknown> {\n readonly ctx: PluginCtx<TStore>;\n /** Already-loaded tool row. Plugin doesn't need to re-fetch or parse\n * the tool id. Carries source_id, name, input/output schemas,\n * annotations. */\n readonly toolRow: ToolRow;\n readonly args: unknown;\n /** Elicitation handle for plugins that need mid-invocation user input\n * (onepassword auth prompt, interactive MCP tools, etc.). */\n readonly elicit: Elicit;\n}\n\nexport interface SourceLifecycleInput<TStore = unknown> {\n readonly ctx: PluginCtx<TStore>;\n readonly sourceId: string;\n /**\n * Scope of the source row being removed/refreshed — resolved by the\n * SDK's `sources.remove` / `sources.refresh` via innermost-wins lookup\n * across the executor's scope stack. Plugins that own a side table\n * keyed by (id, scope_id) must pin their own cleanup to this scope;\n * relying on the scoped adapter's `scope_id IN (stack)` fall-through\n * would widen the mutation across the whole stack and wipe a\n * shadowed outer-scope row.\n */\n readonly scope: string;\n}\n\n// ---------------------------------------------------------------------------\n// PluginSpec — what a `definePlugin(factory)` call returns.\n// ---------------------------------------------------------------------------\n\n// Defaults are `any` for slots that surface in contravariant positions\n// (storage/extension callbacks consume `TStore`/`TSchema`; `staticSources`\n// closes over `TExtension` via `NoInfer`). `any` is bivariant, so\n// `Plugin<string>` is a structural supertype of every concrete plugin\n// — `AnyPlugin = Plugin<string>` keeps the generic explosion contained\n// to this single declaration. Concrete specs ignore the defaults; TS\n// infers each slot from the literal returned by the author factory.\n//\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface PluginSpec<\n TId extends string = string,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n TExtension extends object = any,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n TStore = any,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n TSchema extends DBSchema | undefined = any,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n TExtensionService extends Context.Service<any, any> | undefined = any,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n THandlersLayer extends Layer.Layer<any, any, any> = any,\n TGroup extends HttpApiGroup.Any = HttpApiGroup.Any,\n> {\n readonly id: TId;\n /** npm package name. The Vite plugin uses this to derive the\n * `./client` import path for the frontend bundle (so the same\n * `executor.config.ts` drives both server and client) — `${packageName}/client`\n * is what gets bundled. The author writes the same string they\n * publish to npm; no transforms, no scope conventions. Required for\n * plugins that ship a `./client` entry; can be omitted for SDK-only\n * plugins (no client bundle = nothing to resolve). */\n readonly packageName?: string;\n /** Plugin-declared schema. Merged with coreSchema and other plugins'\n * schemas at executor startup via `collectSchemas`. The type flows\n * into the `storage` factory's `deps.adapter` as a `TypedAdapter<TSchema>`\n * so plugins get narrowed model names + typed rows for free. */\n readonly schema?: TSchema;\n /** Build the plugin's typed store from backing. `deps.adapter` is\n * already narrowed to this plugin's schema; `deps.blobs` is already\n * scoped to the plugin id so key collisions across plugins are\n * structurally impossible. */\n readonly storage: (deps: StorageDeps<TSchema>) => TStore;\n\n /** JSON-serializable config the plugin wants its `./client` bundle to\n * see. The Vite plugin reads this off each `executor.config.ts` spec\n * at build time and bakes it into the virtual `plugins-client`\n * module by calling the plugin's default `./client` export as a\n * factory: `__p(<JSON.stringify(clientConfig)>)`. Plugins that don't\n * set this stay as bare-value default exports — no churn.\n *\n * Use this when a server-side option (e.g. `dangerouslyAllowStdioMCP`)\n * needs to drive client UI behaviour: declaring it once in\n * `executor.config.ts` flows through to the bundle automatically,\n * with no runtime fetch and no parallel client-side flag to keep in\n * sync. */\n readonly clientConfig?: unknown;\n\n /** Build the plugin's extension API. The returned object becomes\n * `executor[plugin.id]` and is also the `self` passed to\n * `staticSources`. Field order matters: `extension` MUST appear\n * before `staticSources` so TS infers TExtension from this\n * factory's return BEFORE type-checking `self: NoInfer<TExtension>`. */\n readonly extension?: (ctx: PluginCtx<TStore>) => TExtension;\n\n /** Static sources contributed by this plugin with inline tool\n * handlers. Lives entirely in memory — no DB writes at startup.\n * Handlers close over `self` via the closure, so a control tool\n * that delegates to the plugin's real API is a one-liner:\n * `({ args }) => self.addSpec(args)`. */\n readonly staticSources?: (self: NoInfer<TExtension>) => readonly StaticSourceDecl<TStore>[];\n\n /** HttpApiGroup contributed by this plugin. Composed into the host's\n * `HttpApi` via the `addGroup` helper at runtime. The host mounts\n * the group at `/_executor/plugins/{id}/...` (or wherever the\n * plugin declares its base path) with the host's auth + scope\n * middleware applied. Endpoints automatically appear in the\n * executor OpenAPI doc and the typed reactive client.\n *\n * TGroup is inferred from the plugin's own group declaration so the\n * precise group identity flows through `composePluginApi(plugins)` —\n * the host's typed `HttpApi<\"executor\", CoreGroups | PluginGroups>`\n * is derived from the plugin tuple alone, with no per-plugin Group\n * imports at the host. Per-endpoint typing already lives inside the\n * plugin — its `handlers` Layer is built against its own bundled\n * `HttpApi.make(\"foo\").add(FooApi)` for full `.handle(\"name\", ...)`\n * inference, and its client imports the same group directly. */\n readonly routes?: () => TGroup;\n\n /** Handlers Layer for this plugin's group. Built by the plugin against\n * its own bundled API for full type safety on `.handle(\"name\", ...)`,\n * composes into the host's runtime `FullApi` because\n * `HttpApiBuilder.group` keys the layer by group identity, not by the\n * surrounding API.\n *\n * Late-binding: the layer leaves the plugin's extension as a Service\n * Tag requirement (see `extensionService` below). The host satisfies\n * it however its runtime wants:\n * - local: at boot via `Layer.succeed(extensionService)(executor[id])`\n * (see `composePluginHandlers`)\n * - cloud: per-request via `Effect.provideService(extensionService,\n * requestExecutor[id])` in the auth middleware\n *\n * The Layer's channels are typed `any` because `Layer<RIn, E, ROut>`'s\n * `ROut` is contravariant — the host accepts any layer here and merges\n * them; per-plugin requirements flow through the merge. */\n readonly handlers?: () => THandlersLayer;\n\n /** Service tag the plugin's `handlers` layer requires. Set by plugins\n * whose handlers consume their extension via a `Context.Service` tag\n * (the established pattern: `*Handlers` reads `*ExtensionService`).\n * The host binds the tag to the live extension — at boot for local,\n * per request for cloud. Pairs with `handlers`; either both fields\n * are set or neither.\n *\n * Inferred via the `TExtensionService` generic so the per-plugin\n * Service class identity propagates through `composePluginHandlers`,\n * `composePluginHandlerLayer`, and `providePluginExtensions` —\n * cloud's per-request middleware needs the precise tag for layer\n * satisfaction. */\n readonly extensionService?: TExtensionService;\n\n /** Invoke a dynamic tool. Called when the executor's static-handler\n * map doesn't have the toolId. The plugin reads its own enrichment\n * via `ctx.storage` and returns the result. Optional — plugins with\n * only static tools can omit it. */\n readonly invokeTool?: (input: InvokeToolInput<TStore>) => Effect.Effect<unknown, unknown>;\n\n /** Bulk resolve annotations (requiresApproval, approvalDescription,\n * mayElicit) for a set of tool rows under a single source. Called\n * by the executor:\n * - at invoke time with a single-element `toolRows` array, to\n * enforce approval on the about-to-run tool\n * - at list time with every dynamic tool row under each source,\n * grouped by source_id, to populate `Tool.annotations` for UI\n *\n * The expected implementation for most plugins is: read plugin\n * storage once for the given source/rows, derive annotations from\n * the same data that was used to build the tool (HTTP method +\n * path for openapi, introspection kind for graphql, etc.), return\n * a map keyed by tool id.\n *\n * Omit if the plugin has no annotations to contribute — executor\n * treats tools from that plugin as auto-approved with no\n * elicitation. */\n readonly resolveAnnotations?: (input: {\n readonly ctx: PluginCtx<TStore>;\n readonly sourceId: string;\n readonly toolRows: readonly ToolRow[];\n }) => Effect.Effect<Record<string, ToolAnnotations>, unknown>;\n\n /** Find every place a secret id is referenced by this plugin's stored\n * rows. Implementations query their normalized columns (e.g.\n * `WHERE secret_id = $1`) and return one `Usage` per hit, with\n * `ownerKind` / `slot` tagging the location. The executor fans out\n * across all plugins and the result powers the Secrets-tab \"Used\n * by\" list and the deletion-blocking check in `secrets.remove`.\n *\n * Plugins that never store secret refs (secret-provider-only\n * plugins like keychain / file-secrets / 1password) omit this. */\n readonly usagesForSecret?: (input: {\n readonly ctx: PluginCtx<TStore>;\n readonly args: UsagesForSecretInput;\n }) => Effect.Effect<readonly Usage[], unknown>;\n\n /** Same shape as `usagesForSecret`, but for connection refs. */\n readonly usagesForConnection?: (input: {\n readonly ctx: PluginCtx<TStore>;\n readonly args: UsagesForConnectionInput;\n }) => Effect.Effect<readonly Usage[], unknown>;\n\n /** Called when `executor.sources.remove({ id, targetScope })` targets\n * a source owned by this plugin. Plugin-side cleanup only; the\n * executor deletes the core source/tool rows after this callback\n * returns, inside the same transaction. */\n readonly removeSource?: (input: SourceLifecycleInput<TStore>) => Effect.Effect<void, unknown>;\n\n readonly refreshSource?: (input: SourceLifecycleInput<TStore>) => Effect.Effect<void, unknown>;\n\n /** URL autodetection hook. When the user pastes a URL in the\n * onboarding UI, `executor.sources.detect(url)` fans out to every\n * plugin's `detect`. Return a `SourceDetectionResult` if you\n * recognize the URL, `null` otherwise. Implementations should be\n * defensive — swallow fetch errors and return null rather than\n * throwing. First high-confidence match wins. */\n readonly detect?: (input: {\n readonly ctx: PluginCtx<TStore>;\n readonly url: string;\n }) => Effect.Effect<SourceDetectionResult | null, unknown>;\n\n /** Secret providers contributed by this plugin. Either a static\n * array, a function of ctx (for providers that need per-instance\n * state like the keychain's scope-derived service name), or a\n * function returning an Effect so plugins can probe for backend\n * availability at startup and register conditionally. Called once\n * at executor startup after `storage` and `extension` have been\n * built. */\n readonly secretProviders?:\n | readonly SecretProvider[]\n | ((ctx: PluginCtx<TStore>) => readonly SecretProvider[])\n | ((ctx: PluginCtx<TStore>) => Effect.Effect<readonly SecretProvider[]>);\n\n /** Connection providers contributed by this plugin. Same registration\n * shape as `secretProviders`. Each provider's `key` is what\n * `connection.provider` references in the core table; the `refresh`\n * handler is the SDK's single entry point for token lifecycle —\n * plugins don't run their own refresh loops anymore. */\n readonly connectionProviders?:\n | readonly ConnectionProvider[]\n | ((ctx: PluginCtx<TStore>) => readonly ConnectionProvider[])\n | ((ctx: PluginCtx<TStore>) => Effect.Effect<readonly ConnectionProvider[]>);\n\n readonly close?: () => Effect.Effect<void, unknown>;\n}\n\nexport interface Plugin<\n TId extends string = string,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n TExtension extends object = any,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n TStore = any,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n TSchema extends DBSchema | undefined = any,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n TExtensionService extends Context.Service<any, any> | undefined = any,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n THandlersLayer extends Layer.Layer<any, any, any> = any,\n TGroup extends HttpApiGroup.Any = HttpApiGroup.Any,\n> extends PluginSpec<TId, TExtension, TStore, TSchema, TExtensionService, THandlersLayer, TGroup> {}\n\n// ---------------------------------------------------------------------------\n// definePlugin — factory-returning-spec. Options from the author factory\n// are merged with a storage override so consumers can swap the default\n// store implementation without touching plugin internals.\n// ---------------------------------------------------------------------------\n\nexport type ConfiguredPlugin<\n TId extends string,\n TExtension extends object,\n TStore,\n TOptions extends object,\n TSchema extends DBSchema | undefined,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n TExtensionService extends Context.Service<any, any> | undefined = undefined,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n THandlersLayer extends Layer.Layer<any, any, any> = Layer.Layer<unknown, never, never>,\n TGroup extends HttpApiGroup.Any = HttpApiGroup.Any,\n> = (\n options?: TOptions & {\n readonly storage?: (deps: StorageDeps<TSchema>) => TStore;\n },\n) => Plugin<TId, TExtension, TStore, TSchema, TExtensionService, THandlersLayer, TGroup>;\n\n// eslint-disable-next-line @typescript-eslint/ban-types\nexport function definePlugin<\n TId extends string,\n TExtension extends object,\n TStore,\n TSchema extends DBSchema | undefined = undefined,\n TOptions extends object = {},\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n TExtensionService extends Context.Service<any, any> | undefined = undefined,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n THandlersLayer extends Layer.Layer<any, any, any> = Layer.Layer<unknown, never, never>,\n TGroup extends HttpApiGroup.Any = HttpApiGroup.Any,\n>(\n authorFactory: (\n options?: TOptions,\n ) => PluginSpec<TId, TExtension, TStore, TSchema, TExtensionService, THandlersLayer, TGroup>,\n): ConfiguredPlugin<\n TId,\n TExtension,\n TStore,\n TOptions,\n TSchema,\n TExtensionService,\n THandlersLayer,\n TGroup\n> {\n return (options) => {\n const {\n storage: storageOverride,\n ...rest\n }: {\n storage?: (deps: StorageDeps<TSchema>) => TStore;\n [key: string]: unknown;\n } = options ?? {};\n\n const hasAuthorOptions = Object.keys(rest).length > 0;\n const spec = authorFactory(hasAuthorOptions ? (rest as TOptions) : undefined);\n\n return {\n ...spec,\n storage: storageOverride ?? spec.storage,\n };\n };\n}\n\n// ---------------------------------------------------------------------------\n// AnyPlugin / PluginExtensions — type-level glue for the Executor surface.\n// ---------------------------------------------------------------------------\n\n// `Plugin<string>` (with all subsequent slots taking their wide defaults)\n// is structurally any concrete plugin — the `any` cascade stays inside\n// the spec's defaults instead of leaking into every consumer.\nexport type AnyPlugin = Plugin<string>;\n\nexport type PluginExtensions<TPlugins extends readonly AnyPlugin[]> = {\n readonly [P in TPlugins[number] as P[\"id\"]]: P extends Plugin<string, infer TExt> ? TExt : never;\n};\n\n/** Lightweight projection of a secret entry as returned by `ctx.secrets.list`. */\nexport interface SecretListEntry {\n readonly id: string;\n readonly name: string;\n readonly provider: string;\n}\n\n// Re-exported for consumers that check the elicitation handler type.\nexport type { ElicitationHandler };\n","import { makeMemoryAdapter } from \"@executor-js/storage-core/testing/memory\";\n\nimport { Effect } from \"effect\";\n\nimport { makeInMemoryBlobStore } from \"./blob\";\nimport type { ExecutorConfig } from \"./executor\";\nimport { collectSchemas } from \"./executor\";\nimport { ScopeId } from \"./ids\";\nimport { definePlugin, type AnyPlugin } from \"./plugin\";\nimport { Scope } from \"./scope\";\nimport type { SecretProvider } from \"./secrets\";\n\n// ---------------------------------------------------------------------------\n// makeTestConfig — build an ExecutorConfig backed by in-memory adapter +\n// blob store. For unit tests, plugin authors validating their plugin,\n// REPL experimentation. No persistence.\n//\n// Defaults to a single-element scope stack (\"test-scope\") — tests that\n// need multi-scope behavior can pass `scopes` explicitly.\n// ---------------------------------------------------------------------------\n\nexport const makeTestConfig = <const TPlugins extends readonly AnyPlugin[] = []>(options?: {\n readonly scopeName?: string;\n readonly scopes?: readonly Scope[];\n readonly plugins?: TPlugins;\n}): ExecutorConfig<TPlugins> => {\n const scopes = options?.scopes ?? [\n new Scope({\n id: ScopeId.make(\"test-scope\"),\n name: options?.scopeName ?? \"test\",\n createdAt: new Date(),\n }),\n ];\n\n const schema = collectSchemas(options?.plugins ?? []);\n\n return {\n scopes,\n adapter: makeMemoryAdapter({ schema }),\n blobs: makeInMemoryBlobStore(),\n plugins: options?.plugins,\n // Tests default to auto-accepting elicitation prompts. Override via\n // a wrapping spread if a test exercises a real handler:\n // { ...makeTestConfig(...), onElicitation: customHandler }\n onElicitation: \"accept-all\",\n };\n};\n\nexport const memorySecretsPlugin = definePlugin(() => {\n const store = new Map<string, string>();\n\n const provider: SecretProvider = {\n key: \"memory\",\n writable: true,\n get: (id, scope) => Effect.sync(() => store.get(`${scope}\\u0000${id}`) ?? null),\n set: (id, value, scope) =>\n Effect.sync(() => {\n store.set(`${scope}\\u0000${id}`, value);\n }),\n delete: (id, scope) => Effect.sync(() => store.delete(`${scope}\\u0000${id}`)),\n list: () =>\n Effect.sync(() =>\n Array.from(store.keys()).map((key) => {\n const name = key.split(\"\\u0000\", 2)[1] ?? key;\n return { id: name, name };\n }),\n ),\n };\n\n return {\n id: \"memory-secrets\" as const,\n storage: () => ({}),\n secretProviders: [provider],\n };\n});\n"],"mappings":"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","names":["Effect","Effect"]}
package/dist/client.d.ts CHANGED
@@ -6,7 +6,7 @@ export { HttpApi, HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi"
6
6
  export * as AsyncResult from "effect/unstable/reactivity/AsyncResult";
7
7
  export * as Atom from "effect/unstable/reactivity/Atom";
8
8
  export * as AtomHttpApi from "effect/unstable/reactivity/AtomHttpApi";
9
- export { useAtomValue, useAtomSet, useAtomMount, useAtomRefresh, } from "@effect/atom-react";
9
+ export { useAtomValue, useAtomSet, useAtomMount, useAtomRefresh } from "@effect/atom-react";
10
10
  export interface PageDecl {
11
11
  /** Path relative to the plugin's mount point, e.g. `/`, `/edit/$id`. */
12
12
  readonly path: string;
@@ -66,9 +66,6 @@ export interface SourcePlugin {
66
66
  readonly variant?: "badge" | "panel";
67
67
  readonly onAction?: () => void;
68
68
  }>;
69
- readonly signIn?: ComponentType<{
70
- readonly sourceId: string;
71
- }>;
72
69
  readonly presets?: readonly SourcePreset[];
73
70
  /** Trigger early download of the plugin's lazy component chunks (add/edit/etc.).
74
71
  * Call from the host on intent (hover/focus) so the chunks land before the
@@ -107,7 +104,7 @@ export interface CreatePluginAtomClientOptions {
107
104
  /** Override the base URL. Defaults to `/api` (host strips this prefix
108
105
  * when forwarding to the Effect handler) — same convention as the
109
106
  * core `ExecutorApiClient`. */
110
- readonly baseUrl?: string;
107
+ readonly baseUrl?: string | (() => string);
111
108
  }
112
109
  /**
113
110
  * Build a typed reactive client for a plugin's HttpApiGroup.
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/client.js CHANGED
@@ -7,32 +7,28 @@ import {
7
7
  useMemo
8
8
  } from "react";
9
9
  import { HttpApi } from "effect/unstable/httpapi";
10
- import { FetchHttpClient } from "effect/unstable/http";
10
+ import { FetchHttpClient, HttpClient, HttpClientRequest } from "effect/unstable/http";
11
11
  import * as AtomHttpApi from "effect/unstable/reactivity/AtomHttpApi";
12
12
  import { Schema } from "effect";
13
13
  import { HttpApi as HttpApi2, HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi";
14
14
  import * as AsyncResult from "effect/unstable/reactivity/AsyncResult";
15
15
  import * as Atom from "effect/unstable/reactivity/Atom";
16
16
  import * as AtomHttpApi2 from "effect/unstable/reactivity/AtomHttpApi";
17
- import {
18
- useAtomValue,
19
- useAtomSet,
20
- useAtomMount,
21
- useAtomRefresh
22
- } from "@effect/atom-react";
17
+ import { useAtomValue, useAtomSet, useAtomMount, useAtomRefresh } from "@effect/atom-react";
23
18
  var defineClientPlugin = (spec) => spec;
24
19
  var createPluginAtomClient = (group, options = {}) => {
25
20
  const { baseUrl = "/api" } = options;
26
21
  const pluginId = group.identifier;
27
22
  const bundle = HttpApi.make(`plugin-${pluginId}`).add(group);
28
- return AtomHttpApi.Service()(
29
- `Plugin_${pluginId}Client`,
30
- {
31
- api: bundle,
32
- httpClient: FetchHttpClient.layer,
33
- baseUrl
34
- }
35
- );
23
+ return AtomHttpApi.Service()(`Plugin_${pluginId}Client`, {
24
+ api: bundle,
25
+ httpClient: FetchHttpClient.layer,
26
+ ...typeof baseUrl === "function" ? {
27
+ transformClient: HttpClient.mapRequest(
28
+ (request) => HttpClientRequest.prependUrl(request, baseUrl())
29
+ )
30
+ } : { baseUrl }
31
+ });
36
32
  };
37
33
  var ExecutorPluginsContext = createContext(null);
38
34
  ExecutorPluginsContext.displayName = "ExecutorPluginsContext";
@@ -56,9 +52,7 @@ function ExecutorPluginsProvider(props) {
56
52
  var usePluginsCtx = (hookName) => {
57
53
  const ctx = useContext(ExecutorPluginsContext);
58
54
  if (!ctx) {
59
- throw new Error(
60
- `${hookName} must be called inside an <ExecutorPluginsProvider>.`
61
- );
55
+ throw new Error(`${hookName} must be called inside an <ExecutorPluginsProvider>.`);
62
56
  }
63
57
  return ctx;
64
58
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client.ts"],"sourcesContent":["// ---------------------------------------------------------------------------\n// @executor-js/sdk/client — frontend half of the plugin SDK.\n//\n// Plugins import from this entry to register pages/widgets and consume\n// their own typed reactive client. Server bundles must NOT import this\n// module — it pulls in React + @effect/atom-react. Plugin packages should\n// keep React/atom imports inside `./client.tsx` and Effect/Node imports\n// inside `./server.ts`; shared schema definitions go in `./shared.ts` and\n// can be imported from both halves.\n// ---------------------------------------------------------------------------\n\nimport {\n createContext,\n createElement,\n useContext,\n useEffect,\n useMemo,\n type ComponentType,\n type ReactNode,\n} from \"react\";\nimport { HttpApi } from \"effect/unstable/httpapi\";\nimport type { HttpApiEndpoint, HttpApiGroup } from \"effect/unstable/httpapi\";\nimport { FetchHttpClient } from \"effect/unstable/http\";\nimport * as AtomHttpApi from \"effect/unstable/reactivity/AtomHttpApi\";\n\n// ---------------------------------------------------------------------------\n// Re-exports — the curated set of primitives a plugin author needs to\n// build a typed reactive UI without reaching into `effect/*` directly.\n// ---------------------------------------------------------------------------\n\nexport { Schema } from \"effect\";\nexport { HttpApi, HttpApiEndpoint, HttpApiGroup } from \"effect/unstable/httpapi\";\n\nexport * as AsyncResult from \"effect/unstable/reactivity/AsyncResult\";\nexport * as Atom from \"effect/unstable/reactivity/Atom\";\nexport * as AtomHttpApi from \"effect/unstable/reactivity/AtomHttpApi\";\n\nexport {\n useAtomValue,\n useAtomSet,\n useAtomMount,\n useAtomRefresh,\n} from \"@effect/atom-react\";\n\n// ---------------------------------------------------------------------------\n// defineClientPlugin — declarative spec for the frontend half of a plugin.\n//\n// Mirror of `definePlugin` on the server, but everything here is React /\n// browser-only. The host treats the value as data: collects routes,\n// widgets, and slot components from every loaded plugin and mounts them\n// alongside the host's own UI.\n// ---------------------------------------------------------------------------\n\nexport interface PageDecl {\n /** Path relative to the plugin's mount point, e.g. `/`, `/edit/$id`. */\n readonly path: string;\n readonly component: ComponentType;\n /** Optional sidebar nav metadata — the host renders these alongside its\n * own nav links. Omit to register a page without a nav entry. */\n readonly nav?: {\n readonly label: string;\n readonly section?: string;\n };\n}\n\nexport interface WidgetProps {\n readonly scopeId?: string;\n}\n\nexport interface WidgetDecl {\n readonly id: string;\n readonly component: ComponentType<WidgetProps>;\n readonly size?: \"half\" | \"full\";\n}\n\n/**\n * Open record of host-defined slot components a plugin can fill. Slot\n * names are part of the host UI contract — plugins opt in by registering\n * a component for the slot they care about. Adding a slot is a host-side\n * change; plugin authors don't define new slots.\n */\nexport type SlotComponent = ComponentType<Record<string, unknown>>;\n\n// ---------------------------------------------------------------------------\n// SourcePlugin / SourcePreset — UI contract for plugins that expose\n// \"sources\" (OpenAPI specs, MCP servers, GraphQL endpoints, etc.). The\n// host owns the source list / detail chrome; the plugin owns the\n// add-flow, edit form, and (optional) summary + sign-in buttons.\n//\n// Lives here, not in `@executor-js/react`, so it's part of the plugin\n// contract: a plugin's `./client` entry assembles its `sourcePlugin`\n// alongside `pages`/`widgets`, and the host derives the union list\n// from `virtual:executor/plugins-client`.\n// ---------------------------------------------------------------------------\n\nexport interface SourcePreset {\n /** Unique id (e.g. \"stripe\", \"github-graphql\"). */\n readonly id: string;\n readonly name: string;\n readonly summary: string;\n /** URL passed as `initialUrl` to the add form. Omit for presets that\n * don't use a URL (e.g. stdio MCP presets). */\n readonly url?: string;\n /** Optional icon URL (favicon, logo). */\n readonly icon?: string;\n /** Shown in the top-level grid on the sources page when true. */\n readonly featured?: boolean;\n}\n\nexport interface SourcePlugin {\n /** Unique key matching the SDK plugin id (e.g. \"openapi\"). */\n readonly key: string;\n readonly label: string;\n readonly add: ComponentType<{\n readonly onComplete: () => void;\n readonly onCancel: () => void;\n readonly initialUrl?: string;\n readonly initialPreset?: string;\n readonly initialNamespace?: string;\n }>;\n readonly edit: ComponentType<{\n readonly sourceId: string;\n readonly onSave: () => void;\n }>;\n readonly summary?: ComponentType<{\n readonly sourceId: string;\n readonly variant?: \"badge\" | \"panel\";\n readonly onAction?: () => void;\n }>;\n readonly signIn?: ComponentType<{\n readonly sourceId: string;\n }>;\n readonly presets?: readonly SourcePreset[];\n /** Trigger early download of the plugin's lazy component chunks (add/edit/etc.).\n * Call from the host on intent (hover/focus) so the chunks land before the\n * user navigates into the add page. Idempotent. */\n readonly preload?: () => void;\n}\n\n// ---------------------------------------------------------------------------\n// SecretProviderPlugin — UI contract for plugins that contribute secret\n// providers (1Password, WorkOS Vault, etc.). The host owns the secrets\n// page chrome; the plugin owns the settings card rendered inside.\n// ---------------------------------------------------------------------------\n\nexport interface SecretProviderPlugin {\n /** Unique key matching the SDK plugin id (e.g. \"onepassword\"). */\n readonly key: string;\n readonly label: string;\n readonly settings: ComponentType<Record<string, never>>;\n}\n\nexport interface ClientPluginSpec<TId extends string = string> {\n readonly id: TId;\n readonly pages?: readonly PageDecl[];\n readonly widgets?: readonly WidgetDecl[];\n readonly slots?: Record<string, SlotComponent>;\n /** Source plugin contribution — populated by plugins that expose\n * `kind` rows in the core `source` table (openapi, mcp, graphql,\n * google-discovery). The host's sources page derives its provider\n * list from the union of every loaded plugin's `sourcePlugin`. */\n readonly sourcePlugin?: SourcePlugin;\n /** Secret provider plugin contribution — populated by plugins that\n * also ship a `secretProviders` (or related) server-side capability\n * AND want to expose a settings card on the host's secrets page. */\n readonly secretProviderPlugin?: SecretProviderPlugin;\n}\n\n/**\n * Identity factory — returns the spec unchanged but pins the inferred\n * literal type of `id` so the host can index plugin records by id with\n * full autocomplete. Plugins export this as their package's default\n * (or named) export from `./client`.\n */\nexport const defineClientPlugin = <const TId extends string>(\n spec: ClientPluginSpec<TId>,\n): ClientPluginSpec<TId> => spec;\n\n// ---------------------------------------------------------------------------\n// createPluginAtomClient — typed reactive HTTP client for one plugin.\n//\n// Wraps the plugin's `HttpApiGroup` in a per-plugin `HttpApi`, then\n// hands back an `AtomHttpApi.Service` keyed to that bundle. The\n// resulting service exposes `.query(\"group\", \"endpoint\", opts)` and\n// `.mutation(\"group\", \"endpoint\")` factories — same shape as the host's\n// existing `ExecutorApiClient` (see packages/react/src/api/client.tsx).\n// Per-endpoint payload/response/error types flow through from the\n// imported group, so plugin client code typechecks without codegen.\n//\n// The plugin id (used for the Service Tag and the synthetic API id) is\n// read from `group.identifier` — the same string the plugin passed to\n// `HttpApiGroup.make(\"foo\")`. No second-source duplication.\n// ---------------------------------------------------------------------------\n\nexport interface CreatePluginAtomClientOptions {\n /** Override the base URL. Defaults to `/api` (host strips this prefix\n * when forwarding to the Effect handler) — same convention as the\n * core `ExecutorApiClient`. */\n readonly baseUrl?: string;\n}\n\n/**\n * Build a typed reactive client for a plugin's HttpApiGroup.\n *\n * const FooClient = createPluginAtomClient(FooApi)\n * export const fooThings = FooClient.query(\"foo\", \"listThings\", { ... })\n * export const fooSync = FooClient.mutation(\"foo\", \"syncThing\")\n *\n * Each plugin gets a private service Tag (`Plugin_<id>Client`) keyed by\n * the group's `identifier`, so multiple plugins coexist in the same\n * React tree without colliding.\n */\nexport const createPluginAtomClient = <\n G extends HttpApiGroup.HttpApiGroup<string, HttpApiEndpoint.Any, boolean>,\n>(\n group: G,\n options: CreatePluginAtomClientOptions = {},\n) => {\n const { baseUrl = \"/api\" } = options;\n const pluginId = group.identifier;\n const bundle = HttpApi.make(`plugin-${pluginId}`).add(group);\n return AtomHttpApi.Service<`Plugin_${G[\"identifier\"]}Client`>()(\n `Plugin_${pluginId}Client`,\n {\n api: bundle,\n httpClient: FetchHttpClient.layer,\n baseUrl,\n },\n );\n};\n\n// ---------------------------------------------------------------------------\n// ExecutorPluginsProvider + hooks — host-level distribution of the loaded\n// `ClientPluginSpec[]` via React context.\n//\n// The host wraps once at the root of its tree (typically reading from\n// `virtual:executor/plugins-client`); pages and shared components consume\n// via the focused hooks (`useSourcePlugins` etc.) so they don't import\n// from any host-app aggregator file. Pages stay portable across hosts —\n// the same component renders against whatever plugin set the surrounding\n// `<ExecutorPluginsProvider>` provides.\n//\n// Hooks throw if no provider is in scope so missing setup fails loudly;\n// matches the pattern of `useScope` / `useAuth` already in the codebase.\n// ---------------------------------------------------------------------------\n\ninterface ExecutorPluginsContextValue {\n readonly plugins: readonly ClientPluginSpec[];\n readonly sourcePlugins: readonly SourcePlugin[];\n readonly secretProviderPlugins: readonly SecretProviderPlugin[];\n}\n\nconst ExecutorPluginsContext = createContext<\n ExecutorPluginsContextValue | null\n>(null);\nExecutorPluginsContext.displayName = \"ExecutorPluginsContext\";\n\nexport interface ExecutorPluginsProviderProps {\n readonly plugins: readonly ClientPluginSpec[];\n readonly children: ReactNode;\n}\n\nexport function ExecutorPluginsProvider(\n props: ExecutorPluginsProviderProps,\n): ReturnType<typeof createElement> {\n const { plugins, children } = props;\n const value = useMemo<ExecutorPluginsContextValue>(\n () => ({\n plugins,\n sourcePlugins: plugins.flatMap((p) => (p.sourcePlugin ? [p.sourcePlugin] : [])),\n secretProviderPlugins: plugins.flatMap((p) =>\n p.secretProviderPlugin ? [p.secretProviderPlugin] : [],\n ),\n }),\n [plugins],\n );\n // Kick off lazy chunk downloads for every source plugin once the host\n // mounts, so navigating into an add/edit page doesn't suspend.\n useEffect(() => {\n for (const sp of value.sourcePlugins) sp.preload?.();\n }, [value.sourcePlugins]);\n return createElement(ExecutorPluginsContext.Provider, { value }, children);\n}\n\nconst usePluginsCtx = (hookName: string): ExecutorPluginsContextValue => {\n const ctx = useContext(ExecutorPluginsContext);\n if (!ctx) {\n throw new Error(\n `${hookName} must be called inside an <ExecutorPluginsProvider>.`,\n );\n }\n return ctx;\n};\n\n/** Full list of loaded `ClientPluginSpec` values. */\nexport const useClientPlugins = (): readonly ClientPluginSpec[] =>\n usePluginsCtx(\"useClientPlugins\").plugins;\n\n/** Source plugins extracted from `clientPlugins[].sourcePlugin`. */\nexport const useSourcePlugins = (): readonly SourcePlugin[] =>\n usePluginsCtx(\"useSourcePlugins\").sourcePlugins;\n\n/** Secret-provider plugins extracted from `clientPlugins[].secretProviderPlugin`. */\nexport const useSecretProviderPlugins = (): readonly SecretProviderPlugin[] =>\n usePluginsCtx(\"useSecretProviderPlugins\").secretProviderPlugins;\n"],"mappings":";AAWA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AACP,SAAS,eAAe;AAExB,SAAS,uBAAuB;AAChC,YAAY,iBAAiB;AAO7B,SAAS,cAAc;AACvB,SAAS,WAAAA,UAAS,iBAAiB,oBAAoB;AAEvD,YAAY,iBAAiB;AAC7B,YAAY,UAAU;AACtB,YAAYC,kBAAiB;AAE7B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAoIA,IAAM,qBAAqB,CAChC,SAC0B;AAoCrB,IAAM,yBAAyB,CAGpC,OACA,UAAyC,CAAC,MACvC;AACH,QAAM,EAAE,UAAU,OAAO,IAAI;AAC7B,QAAM,WAAW,MAAM;AACvB,QAAM,SAAS,QAAQ,KAAK,UAAU,QAAQ,EAAE,EAAE,IAAI,KAAK;AAC3D,SAAmB,oBAA2C;AAAA,IAC5D,UAAU,QAAQ;AAAA,IAClB;AAAA,MACE,KAAK;AAAA,MACL,YAAY,gBAAgB;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AACF;AAuBA,IAAM,yBAAyB,cAE7B,IAAI;AACN,uBAAuB,cAAc;AAO9B,SAAS,wBACd,OACkC;AAClC,QAAM,EAAE,SAAS,SAAS,IAAI;AAC9B,QAAM,QAAQ;AAAA,IACZ,OAAO;AAAA,MACL;AAAA,MACA,eAAe,QAAQ,QAAQ,CAAC,MAAO,EAAE,eAAe,CAAC,EAAE,YAAY,IAAI,CAAC,CAAE;AAAA,MAC9E,uBAAuB,QAAQ;AAAA,QAAQ,CAAC,MACtC,EAAE,uBAAuB,CAAC,EAAE,oBAAoB,IAAI,CAAC;AAAA,MACvD;AAAA,IACF;AAAA,IACA,CAAC,OAAO;AAAA,EACV;AAGA,YAAU,MAAM;AACd,eAAW,MAAM,MAAM,cAAe,IAAG,UAAU;AAAA,EACrD,GAAG,CAAC,MAAM,aAAa,CAAC;AACxB,SAAO,cAAc,uBAAuB,UAAU,EAAE,MAAM,GAAG,QAAQ;AAC3E;AAEA,IAAM,gBAAgB,CAAC,aAAkD;AACvE,QAAM,MAAM,WAAW,sBAAsB;AAC7C,MAAI,CAAC,KAAK;AACR,UAAM,IAAI;AAAA,MACR,GAAG,QAAQ;AAAA,IACb;AAAA,EACF;AACA,SAAO;AACT;AAGO,IAAM,mBAAmB,MAC9B,cAAc,kBAAkB,EAAE;AAG7B,IAAM,mBAAmB,MAC9B,cAAc,kBAAkB,EAAE;AAG7B,IAAM,2BAA2B,MACtC,cAAc,0BAA0B,EAAE;","names":["HttpApi","AtomHttpApi"]}
1
+ {"version":3,"sources":["../src/client.ts"],"sourcesContent":["// ---------------------------------------------------------------------------\n// @executor-js/sdk/client — frontend half of the plugin SDK.\n//\n// Plugins import from this entry to register pages/widgets and consume\n// their own typed reactive client. Server bundles must NOT import this\n// module — it pulls in React + @effect/atom-react. Plugin packages should\n// keep React/atom imports inside `./client.tsx` and Effect/Node imports\n// inside `./server.ts`; shared schema definitions go in `./shared.ts` and\n// can be imported from both halves.\n// ---------------------------------------------------------------------------\n\nimport {\n createContext,\n createElement,\n useContext,\n useEffect,\n useMemo,\n type ComponentType,\n type ReactNode,\n} from \"react\";\nimport { HttpApi } from \"effect/unstable/httpapi\";\nimport type { HttpApiEndpoint, HttpApiGroup } from \"effect/unstable/httpapi\";\nimport { FetchHttpClient, HttpClient, HttpClientRequest } from \"effect/unstable/http\";\nimport * as AtomHttpApi from \"effect/unstable/reactivity/AtomHttpApi\";\n\n// ---------------------------------------------------------------------------\n// Re-exports — the curated set of primitives a plugin author needs to\n// build a typed reactive UI without reaching into `effect/*` directly.\n// ---------------------------------------------------------------------------\n\nexport { Schema } from \"effect\";\nexport { HttpApi, HttpApiEndpoint, HttpApiGroup } from \"effect/unstable/httpapi\";\n\nexport * as AsyncResult from \"effect/unstable/reactivity/AsyncResult\";\nexport * as Atom from \"effect/unstable/reactivity/Atom\";\nexport * as AtomHttpApi from \"effect/unstable/reactivity/AtomHttpApi\";\n\nexport { useAtomValue, useAtomSet, useAtomMount, useAtomRefresh } from \"@effect/atom-react\";\n\n// ---------------------------------------------------------------------------\n// defineClientPlugin — declarative spec for the frontend half of a plugin.\n//\n// Mirror of `definePlugin` on the server, but everything here is React /\n// browser-only. The host treats the value as data: collects routes,\n// widgets, and slot components from every loaded plugin and mounts them\n// alongside the host's own UI.\n// ---------------------------------------------------------------------------\n\nexport interface PageDecl {\n /** Path relative to the plugin's mount point, e.g. `/`, `/edit/$id`. */\n readonly path: string;\n readonly component: ComponentType;\n /** Optional sidebar nav metadata — the host renders these alongside its\n * own nav links. Omit to register a page without a nav entry. */\n readonly nav?: {\n readonly label: string;\n readonly section?: string;\n };\n}\n\nexport interface WidgetProps {\n readonly scopeId?: string;\n}\n\nexport interface WidgetDecl {\n readonly id: string;\n readonly component: ComponentType<WidgetProps>;\n readonly size?: \"half\" | \"full\";\n}\n\n/**\n * Open record of host-defined slot components a plugin can fill. Slot\n * names are part of the host UI contract — plugins opt in by registering\n * a component for the slot they care about. Adding a slot is a host-side\n * change; plugin authors don't define new slots.\n */\nexport type SlotComponent = ComponentType<Record<string, unknown>>;\n\n// ---------------------------------------------------------------------------\n// SourcePlugin / SourcePreset — UI contract for plugins that expose\n// \"sources\" (OpenAPI specs, MCP servers, GraphQL endpoints, etc.). The\n// host owns the source list / detail chrome; the plugin owns the\n// add-flow, edit form, and (optional) summary + sign-in buttons.\n//\n// Lives here, not in `@executor-js/react`, so it's part of the plugin\n// contract: a plugin's `./client` entry assembles its `sourcePlugin`\n// alongside `pages`/`widgets`, and the host derives the union list\n// from `virtual:executor/plugins-client`.\n// ---------------------------------------------------------------------------\n\nexport interface SourcePreset {\n /** Unique id (e.g. \"stripe\", \"github-graphql\"). */\n readonly id: string;\n readonly name: string;\n readonly summary: string;\n /** URL passed as `initialUrl` to the add form. Omit for presets that\n * don't use a URL (e.g. stdio MCP presets). */\n readonly url?: string;\n /** Optional icon URL (favicon, logo). */\n readonly icon?: string;\n /** Shown in the top-level grid on the sources page when true. */\n readonly featured?: boolean;\n}\n\nexport interface SourcePlugin {\n /** Unique key matching the SDK plugin id (e.g. \"openapi\"). */\n readonly key: string;\n readonly label: string;\n readonly add: ComponentType<{\n readonly onComplete: () => void;\n readonly onCancel: () => void;\n readonly initialUrl?: string;\n readonly initialPreset?: string;\n readonly initialNamespace?: string;\n }>;\n readonly edit: ComponentType<{\n readonly sourceId: string;\n readonly onSave: () => void;\n }>;\n readonly summary?: ComponentType<{\n readonly sourceId: string;\n readonly variant?: \"badge\" | \"panel\";\n readonly onAction?: () => void;\n }>;\n readonly presets?: readonly SourcePreset[];\n /** Trigger early download of the plugin's lazy component chunks (add/edit/etc.).\n * Call from the host on intent (hover/focus) so the chunks land before the\n * user navigates into the add page. Idempotent. */\n readonly preload?: () => void;\n}\n\n// ---------------------------------------------------------------------------\n// SecretProviderPlugin — UI contract for plugins that contribute secret\n// providers (1Password, WorkOS Vault, etc.). The host owns the secrets\n// page chrome; the plugin owns the settings card rendered inside.\n// ---------------------------------------------------------------------------\n\nexport interface SecretProviderPlugin {\n /** Unique key matching the SDK plugin id (e.g. \"onepassword\"). */\n readonly key: string;\n readonly label: string;\n readonly settings: ComponentType<Record<string, never>>;\n}\n\nexport interface ClientPluginSpec<TId extends string = string> {\n readonly id: TId;\n readonly pages?: readonly PageDecl[];\n readonly widgets?: readonly WidgetDecl[];\n readonly slots?: Record<string, SlotComponent>;\n /** Source plugin contribution — populated by plugins that expose\n * `kind` rows in the core `source` table (openapi, mcp, graphql,\n * google-discovery). The host's sources page derives its provider\n * list from the union of every loaded plugin's `sourcePlugin`. */\n readonly sourcePlugin?: SourcePlugin;\n /** Secret provider plugin contribution — populated by plugins that\n * also ship a `secretProviders` (or related) server-side capability\n * AND want to expose a settings card on the host's secrets page. */\n readonly secretProviderPlugin?: SecretProviderPlugin;\n}\n\n/**\n * Identity factory — returns the spec unchanged but pins the inferred\n * literal type of `id` so the host can index plugin records by id with\n * full autocomplete. Plugins export this as their package's default\n * (or named) export from `./client`.\n */\nexport const defineClientPlugin = <const TId extends string>(\n spec: ClientPluginSpec<TId>,\n): ClientPluginSpec<TId> => spec;\n\n// ---------------------------------------------------------------------------\n// createPluginAtomClient — typed reactive HTTP client for one plugin.\n//\n// Wraps the plugin's `HttpApiGroup` in a per-plugin `HttpApi`, then\n// hands back an `AtomHttpApi.Service` keyed to that bundle. The\n// resulting service exposes `.query(\"group\", \"endpoint\", opts)` and\n// `.mutation(\"group\", \"endpoint\")` factories — same shape as the host's\n// existing `ExecutorApiClient` (see packages/react/src/api/client.tsx).\n// Per-endpoint payload/response/error types flow through from the\n// imported group, so plugin client code typechecks without codegen.\n//\n// The plugin id (used for the Service Tag and the synthetic API id) is\n// read from `group.identifier` — the same string the plugin passed to\n// `HttpApiGroup.make(\"foo\")`. No second-source duplication.\n// ---------------------------------------------------------------------------\n\nexport interface CreatePluginAtomClientOptions {\n /** Override the base URL. Defaults to `/api` (host strips this prefix\n * when forwarding to the Effect handler) — same convention as the\n * core `ExecutorApiClient`. */\n readonly baseUrl?: string | (() => string);\n}\n\n/**\n * Build a typed reactive client for a plugin's HttpApiGroup.\n *\n * const FooClient = createPluginAtomClient(FooApi)\n * export const fooThings = FooClient.query(\"foo\", \"listThings\", { ... })\n * export const fooSync = FooClient.mutation(\"foo\", \"syncThing\")\n *\n * Each plugin gets a private service Tag (`Plugin_<id>Client`) keyed by\n * the group's `identifier`, so multiple plugins coexist in the same\n * React tree without colliding.\n */\nexport const createPluginAtomClient = <\n G extends HttpApiGroup.HttpApiGroup<string, HttpApiEndpoint.Any, boolean>,\n>(\n group: G,\n options: CreatePluginAtomClientOptions = {},\n) => {\n const { baseUrl = \"/api\" } = options;\n const pluginId = group.identifier;\n const bundle = HttpApi.make(`plugin-${pluginId}`).add(group);\n return AtomHttpApi.Service<`Plugin_${G[\"identifier\"]}Client`>()(`Plugin_${pluginId}Client`, {\n api: bundle,\n httpClient: FetchHttpClient.layer,\n ...(typeof baseUrl === \"function\"\n ? {\n transformClient: HttpClient.mapRequest((request) =>\n HttpClientRequest.prependUrl(request, baseUrl()),\n ),\n }\n : { baseUrl }),\n });\n};\n\n// ---------------------------------------------------------------------------\n// ExecutorPluginsProvider + hooks — host-level distribution of the loaded\n// `ClientPluginSpec[]` via React context.\n//\n// The host wraps once at the root of its tree (typically reading from\n// `virtual:executor/plugins-client`); pages and shared components consume\n// via the focused hooks (`useSourcePlugins` etc.) so they don't import\n// from any host-app aggregator file. Pages stay portable across hosts —\n// the same component renders against whatever plugin set the surrounding\n// `<ExecutorPluginsProvider>` provides.\n//\n// Hooks throw if no provider is in scope so missing setup fails loudly;\n// matches the pattern of `useScope` / `useAuth` already in the codebase.\n// ---------------------------------------------------------------------------\n\ninterface ExecutorPluginsContextValue {\n readonly plugins: readonly ClientPluginSpec[];\n readonly sourcePlugins: readonly SourcePlugin[];\n readonly secretProviderPlugins: readonly SecretProviderPlugin[];\n}\n\nconst ExecutorPluginsContext = createContext<ExecutorPluginsContextValue | null>(null);\nExecutorPluginsContext.displayName = \"ExecutorPluginsContext\";\n\nexport interface ExecutorPluginsProviderProps {\n readonly plugins: readonly ClientPluginSpec[];\n readonly children: ReactNode;\n}\n\nexport function ExecutorPluginsProvider(\n props: ExecutorPluginsProviderProps,\n): ReturnType<typeof createElement> {\n const { plugins, children } = props;\n const value = useMemo<ExecutorPluginsContextValue>(\n () => ({\n plugins,\n sourcePlugins: plugins.flatMap((p) => (p.sourcePlugin ? [p.sourcePlugin] : [])),\n secretProviderPlugins: plugins.flatMap((p) =>\n p.secretProviderPlugin ? [p.secretProviderPlugin] : [],\n ),\n }),\n [plugins],\n );\n // Kick off lazy chunk downloads for every source plugin once the host\n // mounts, so navigating into an add/edit page doesn't suspend.\n useEffect(() => {\n for (const sp of value.sourcePlugins) sp.preload?.();\n }, [value.sourcePlugins]);\n return createElement(ExecutorPluginsContext.Provider, { value }, children);\n}\n\nconst usePluginsCtx = (hookName: string): ExecutorPluginsContextValue => {\n const ctx = useContext(ExecutorPluginsContext);\n if (!ctx) {\n // oxlint-disable-next-line executor/no-try-catch-or-throw, executor/no-error-constructor -- boundary: React hook invariant\n throw new Error(`${hookName} must be called inside an <ExecutorPluginsProvider>.`);\n }\n return ctx;\n};\n\n/** Full list of loaded `ClientPluginSpec` values. */\nexport const useClientPlugins = (): readonly ClientPluginSpec[] =>\n usePluginsCtx(\"useClientPlugins\").plugins;\n\n/** Source plugins extracted from `clientPlugins[].sourcePlugin`. */\nexport const useSourcePlugins = (): readonly SourcePlugin[] =>\n usePluginsCtx(\"useSourcePlugins\").sourcePlugins;\n\n/** Secret-provider plugins extracted from `clientPlugins[].secretProviderPlugin`. */\nexport const useSecretProviderPlugins = (): readonly SecretProviderPlugin[] =>\n usePluginsCtx(\"useSecretProviderPlugins\").secretProviderPlugins;\n"],"mappings":";AAWA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AACP,SAAS,eAAe;AAExB,SAAS,iBAAiB,YAAY,yBAAyB;AAC/D,YAAY,iBAAiB;AAO7B,SAAS,cAAc;AACvB,SAAS,WAAAA,UAAS,iBAAiB,oBAAoB;AAEvD,YAAY,iBAAiB;AAC7B,YAAY,UAAU;AACtB,YAAYC,kBAAiB;AAE7B,SAAS,cAAc,YAAY,cAAc,sBAAsB;AAiIhE,IAAM,qBAAqB,CAChC,SAC0B;AAoCrB,IAAM,yBAAyB,CAGpC,OACA,UAAyC,CAAC,MACvC;AACH,QAAM,EAAE,UAAU,OAAO,IAAI;AAC7B,QAAM,WAAW,MAAM;AACvB,QAAM,SAAS,QAAQ,KAAK,UAAU,QAAQ,EAAE,EAAE,IAAI,KAAK;AAC3D,SAAmB,oBAA2C,EAAE,UAAU,QAAQ,UAAU;AAAA,IAC1F,KAAK;AAAA,IACL,YAAY,gBAAgB;AAAA,IAC5B,GAAI,OAAO,YAAY,aACnB;AAAA,MACE,iBAAiB,WAAW;AAAA,QAAW,CAAC,YACtC,kBAAkB,WAAW,SAAS,QAAQ,CAAC;AAAA,MACjD;AAAA,IACF,IACA,EAAE,QAAQ;AAAA,EAChB,CAAC;AACH;AAuBA,IAAM,yBAAyB,cAAkD,IAAI;AACrF,uBAAuB,cAAc;AAO9B,SAAS,wBACd,OACkC;AAClC,QAAM,EAAE,SAAS,SAAS,IAAI;AAC9B,QAAM,QAAQ;AAAA,IACZ,OAAO;AAAA,MACL;AAAA,MACA,eAAe,QAAQ,QAAQ,CAAC,MAAO,EAAE,eAAe,CAAC,EAAE,YAAY,IAAI,CAAC,CAAE;AAAA,MAC9E,uBAAuB,QAAQ;AAAA,QAAQ,CAAC,MACtC,EAAE,uBAAuB,CAAC,EAAE,oBAAoB,IAAI,CAAC;AAAA,MACvD;AAAA,IACF;AAAA,IACA,CAAC,OAAO;AAAA,EACV;AAGA,YAAU,MAAM;AACd,eAAW,MAAM,MAAM,cAAe,IAAG,UAAU;AAAA,EACrD,GAAG,CAAC,MAAM,aAAa,CAAC;AACxB,SAAO,cAAc,uBAAuB,UAAU,EAAE,MAAM,GAAG,QAAQ;AAC3E;AAEA,IAAM,gBAAgB,CAAC,aAAkD;AACvE,QAAM,MAAM,WAAW,sBAAsB;AAC7C,MAAI,CAAC,KAAK;AAER,UAAM,IAAI,MAAM,GAAG,QAAQ,sDAAsD;AAAA,EACnF;AACA,SAAO;AACT;AAGO,IAAM,mBAAmB,MAC9B,cAAc,kBAAkB,EAAE;AAG7B,IAAM,mBAAmB,MAC9B,cAAc,kBAAkB,EAAE;AAG7B,IAAM,2BAA2B,MACtC,cAAc,0BAA0B,EAAE;","names":["HttpApi","AtomHttpApi"]}
@@ -103,5 +103,12 @@ declare const UpdateConnectionTokensInput_base: Schema.Class<UpdateConnectionTok
103
103
  }>, {}>;
104
104
  export declare class UpdateConnectionTokensInput extends UpdateConnectionTokensInput_base {
105
105
  }
106
+ declare const RemoveConnectionInput_base: Schema.Class<RemoveConnectionInput, Schema.Struct<{
107
+ readonly id: Schema.brand<Schema.String, "ConnectionId">;
108
+ /** Scope id whose connection row and owned token secrets should be removed. */
109
+ readonly targetScope: Schema.brand<Schema.String, "ScopeId">;
110
+ }>, {}>;
111
+ export declare class RemoveConnectionInput extends RemoveConnectionInput_base {
112
+ }
106
113
  export {};
107
114
  //# sourceMappingURL=connections.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"connections.d.ts","sourceRoot":"","sources":["../src/connections.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,OAAO,EAAY,MAAM,OAAO,CAAC;AAWxD;;;WAGW;AACX,eAAO,MAAM,uBAAuB,+CAA+C,CAAC;AACpF,MAAM,MAAM,uBAAuB,GAAG,OAAO,uBAAuB,CAAC,IAAI,CAAC;;;;;;;;IAexE,oEAAoE;;IAEpE;sEACkE;;;;;;AAVpE,qBAAa,aAAc,SAAQ,kBAejC;CAAG;;IAeH;+DAC2D;;IAE3D;yDACqD;;;;AALvD,qBAAa,aAAc,SAAQ,kBAQjC;CAAG;;;IAMH;;6DAEyD;;;;;;;IAOzD,wEAAwE;;;;AAb1E,qBAAa,qBAAsB,SAAQ,0BAgBzC;CAAG;;;;AAQL,qBAAa,sBAAuB,SAAQ,4BAE1C;IACA,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;;;;;OAOG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;CAAG;AASL,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,wEAAwE;IACxE,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,gEAAgE;IAChE,QAAQ,CAAC,aAAa,EAAE,uBAAuB,GAAG,IAAI,CAAC;IACvD,uDAAuD;IACvD,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAaD,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,aAAa,CAAC,EAAE,uBAAuB,GAAG,IAAI,CAAC;CACzD;AAcD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,CAAC,EAAE,CACjB,KAAK,EAAE,sBAAsB,KAC1B,MAAM,CAAC,MAAM,CAAC,uBAAuB,EAAE,sBAAsB,CAAC,CAAC;CACrE;;;;;;;;;;AASD,qBAAa,2BAA4B,SAAQ,gCAU/C;CAAG"}
1
+ {"version":3,"file":"connections.d.ts","sourceRoot":"","sources":["../src/connections.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,OAAO,EAAY,MAAM,OAAO,CAAC;AAWxD;;;WAGW;AACX,eAAO,MAAM,uBAAuB,+CAA+C,CAAC;AACpF,MAAM,MAAM,uBAAuB,GAAG,OAAO,uBAAuB,CAAC,IAAI,CAAC;;;;;;;;IAexE,oEAAoE;;IAEpE;sEACkE;;;;;;AAVpE,qBAAa,aAAc,SAAQ,kBAejC;CAAG;;IAeH;+DAC2D;;IAE3D;yDACqD;;;;AALvD,qBAAa,aAAc,SAAQ,kBAQjC;CAAG;;;IAMH;;6DAEyD;;;;;;;IAOzD,wEAAwE;;;;AAb1E,qBAAa,qBAAsB,SAAQ,0BAgBzC;CAAG;;;;AAQL,qBAAa,sBAAuB,SAAQ,4BAA2C;IACrF,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;;;;;OAOG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;CAAG;AASL,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,wEAAwE;IACxE,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,gEAAgE;IAChE,QAAQ,CAAC,aAAa,EAAE,uBAAuB,GAAG,IAAI,CAAC;IACvD,uDAAuD;IACvD,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAaD,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,aAAa,CAAC,EAAE,uBAAuB,GAAG,IAAI,CAAC;CACzD;AAcD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,CAAC,EAAE,CACjB,KAAK,EAAE,sBAAsB,KAC1B,MAAM,CAAC,MAAM,CAAC,uBAAuB,EAAE,sBAAsB,CAAC,CAAC;CACrE;;;;;;;;;;AASD,qBAAa,2BAA4B,SAAQ,gCAU/C;CAAG;;;IAMH,+EAA+E;;;AAJjF,qBAAa,qBAAsB,SAAQ,0BAMzC;CAAG"}
@@ -1,4 +1,5 @@
1
1
  import type { InferDBFieldsOutput } from "@executor-js/storage-core";
2
+ export declare const credentialBindingKinds: ["text", "secret", "connection"];
2
3
  export declare const coreSchema: {
3
4
  readonly source: {
4
5
  readonly fields: {
@@ -177,9 +178,8 @@ export declare const coreSchema: {
177
178
  readonly required: true;
178
179
  readonly index: true;
179
180
  };
180
- /** Routing key into `plugin.connectionProviders`. Typical shape
181
- * is `${pluginId}:${kind}` (e.g. `openapi:oauth2`, `mcp:oauth2`,
182
- * `google-discovery:google`). Mirrors `secret.provider`. */
181
+ /** Routing key into `plugin.connectionProviders`. OAuth2 connections
182
+ * use the shared `oauth2` provider. Mirrors `secret.provider`. */
183
183
  readonly provider: {
184
184
  readonly type: "string";
185
185
  readonly required: true;
@@ -279,6 +279,72 @@ export declare const coreSchema: {
279
279
  };
280
280
  };
281
281
  };
282
+ readonly credential_binding: {
283
+ readonly fields: {
284
+ readonly id: {
285
+ readonly type: "string";
286
+ readonly required: true;
287
+ };
288
+ readonly scope_id: {
289
+ readonly type: "string";
290
+ readonly required: true;
291
+ readonly index: true;
292
+ };
293
+ readonly plugin_id: {
294
+ readonly type: "string";
295
+ readonly required: true;
296
+ readonly index: true;
297
+ };
298
+ readonly source_id: {
299
+ readonly type: "string";
300
+ readonly required: true;
301
+ readonly index: true;
302
+ };
303
+ readonly source_scope_id: {
304
+ readonly type: "string";
305
+ readonly required: true;
306
+ readonly index: true;
307
+ };
308
+ readonly slot_key: {
309
+ readonly type: "string";
310
+ readonly required: true;
311
+ readonly index: true;
312
+ };
313
+ /** "text" | "secret" | "connection". */
314
+ readonly kind: {
315
+ readonly type: ["text", "secret", "connection"];
316
+ readonly required: true;
317
+ readonly index: true;
318
+ };
319
+ readonly text_value: {
320
+ readonly type: "string";
321
+ readonly required: false;
322
+ };
323
+ readonly secret_id: {
324
+ readonly type: "string";
325
+ readonly required: false;
326
+ readonly index: true;
327
+ };
328
+ readonly secret_scope_id: {
329
+ readonly type: "string";
330
+ readonly required: false;
331
+ readonly index: true;
332
+ };
333
+ readonly connection_id: {
334
+ readonly type: "string";
335
+ readonly required: false;
336
+ readonly index: true;
337
+ };
338
+ readonly created_at: {
339
+ readonly type: "date";
340
+ readonly required: true;
341
+ };
342
+ readonly updated_at: {
343
+ readonly type: "date";
344
+ readonly required: true;
345
+ };
346
+ };
347
+ };
282
348
  readonly tool_policy: {
283
349
  readonly fields: {
284
350
  readonly id: {
@@ -327,6 +393,19 @@ export type ToolRow = InferDBFieldsOutput<CoreSchema["tool"]["fields"]> & Record
327
393
  export type DefinitionRow = InferDBFieldsOutput<CoreSchema["definition"]["fields"]> & Record<string, unknown>;
328
394
  export type SecretRow = InferDBFieldsOutput<CoreSchema["secret"]["fields"]> & Record<string, unknown>;
329
395
  export type ConnectionRow = InferDBFieldsOutput<CoreSchema["connection"]["fields"]> & Record<string, unknown>;
396
+ type CredentialBindingRowFields = InferDBFieldsOutput<CoreSchema["credential_binding"]["fields"]>;
397
+ type CredentialBindingRowBase = Omit<CredentialBindingRowFields, "kind" | "text_value" | "secret_id" | "secret_scope_id" | "connection_id">;
398
+ export type CredentialBindingRow = CredentialBindingRowBase & ({
399
+ kind: "text";
400
+ text_value: string;
401
+ } | {
402
+ kind: "secret";
403
+ secret_id: string;
404
+ secret_scope_id?: string;
405
+ } | {
406
+ kind: "connection";
407
+ connection_id: string;
408
+ }) & Record<string, unknown>;
330
409
  export type ToolPolicyRow = InferDBFieldsOutput<CoreSchema["tool_policy"]["fields"]> & Record<string, unknown>;
331
410
  export type ToolPolicyAction = "approve" | "require_approval" | "block";
332
411
  export declare const TOOL_POLICY_ACTIONS: readonly ["approve", "require_approval", "block"];
@@ -369,4 +448,5 @@ export interface DefinitionsInput {
369
448
  readonly scope: string;
370
449
  readonly definitions: Record<string, unknown>;
371
450
  }
451
+ export {};
372
452
  //# sourceMappingURL=core-schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"core-schema.d.ts","sourceRoot":"","sources":["../src/core-schema.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"core-schema.d.ts","sourceRoot":"","sources":["../src/core-schema.ts"],"names":[],"mappings":"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"}