@executor-js/sdk 1.5.11 → 1.5.12

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 (41) hide show
  1. package/dist/{chunk-UKOTOKXM.js → chunk-6EED5LAL.js} +33 -1
  2. package/dist/{chunk-UKOTOKXM.js.map → chunk-6EED5LAL.js.map} +1 -1
  3. package/dist/{chunk-YPVKRUZV.js → chunk-WKKKHDH2.js} +554 -378
  4. package/dist/chunk-WKKKHDH2.js.map +1 -0
  5. package/dist/client.d.ts +23 -1
  6. package/dist/client.d.ts.map +1 -1
  7. package/dist/client.js.map +1 -1
  8. package/dist/connection.d.ts +13 -0
  9. package/dist/connection.d.ts.map +1 -1
  10. package/dist/core-schema.d.ts +10 -2
  11. package/dist/core-schema.d.ts.map +1 -1
  12. package/dist/core-tools.d.ts.map +1 -1
  13. package/dist/core.js +10 -38
  14. package/dist/core.js.map +1 -1
  15. package/dist/elicitation.d.ts +1 -0
  16. package/dist/elicitation.d.ts.map +1 -1
  17. package/dist/errors.d.ts +9 -0
  18. package/dist/errors.d.ts.map +1 -1
  19. package/dist/executor.d.ts +5 -1
  20. package/dist/executor.d.ts.map +1 -1
  21. package/dist/index.d.ts +2 -2
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +2 -2
  24. package/dist/integration.d.ts +8 -0
  25. package/dist/integration.d.ts.map +1 -1
  26. package/dist/plugin.d.ts +4 -1
  27. package/dist/plugin.d.ts.map +1 -1
  28. package/dist/promise.d.ts +1 -1
  29. package/dist/promise.d.ts.map +1 -1
  30. package/dist/public-origin.d.ts +35 -0
  31. package/dist/public-origin.d.ts.map +1 -0
  32. package/dist/public-origin.test.d.ts +2 -0
  33. package/dist/public-origin.test.d.ts.map +1 -0
  34. package/dist/shared.d.ts +1 -1
  35. package/dist/shared.d.ts.map +1 -1
  36. package/dist/shared.js +1 -1
  37. package/dist/testing.js +2 -2
  38. package/dist/tool-result.d.ts +18 -1
  39. package/dist/tool-result.d.ts.map +1 -1
  40. package/package.json +7 -1
  41. package/dist/chunk-YPVKRUZV.js.map +0 -1
package/dist/client.d.ts CHANGED
@@ -59,6 +59,19 @@ export interface IntegrationAccountHandoff {
59
59
  /** Non-secret connection label to prefill. */
60
60
  readonly label?: string;
61
61
  }
62
+ /** Outcome of applying an edit-sheet section's staged change. `summary` is
63
+ * toasted on success; `ok: false` keeps the sheet open (the section renders
64
+ * its own error inline). */
65
+ export type EditSheetApplyResult = {
66
+ readonly ok: true;
67
+ readonly summary: string | null;
68
+ } | {
69
+ readonly ok: false;
70
+ };
71
+ export interface EditSheetSectionProps {
72
+ readonly sourceId: string;
73
+ readonly onPendingChange?: (apply: (() => Promise<EditSheetApplyResult>) | null) => void;
74
+ }
62
75
  export interface IntegrationPlugin {
63
76
  /** Unique key matching the SDK plugin id (e.g. "openapi"). */
64
77
  readonly key: string;
@@ -74,10 +87,19 @@ export interface IntegrationPlugin {
74
87
  readonly initialPreset?: string;
75
88
  readonly initialNamespace?: string;
76
89
  }>;
77
- readonly edit: ComponentType<{
90
+ /** Legacy full-page edit surface. No host renders this anymore — plugin
91
+ * configuration lives in the integration Edit sheet via `editSheet`. */
92
+ readonly edit?: ComponentType<{
78
93
  readonly sourceId: string;
79
94
  readonly onSave: () => void;
80
95
  }>;
96
+ /** Plugin-owned configuration rendered inside the integration's Edit sheet,
97
+ * below the shared metadata fields (e.g. the OpenAPI spec-update controls).
98
+ * The sheet has ONE Save: the section stages its pending change locally and
99
+ * reports it through `onPendingChange` — a thunk that applies the staged
100
+ * change. Save runs the metadata update, then the staged apply; a failed
101
+ * apply keeps the sheet open with the section showing its own error. */
102
+ readonly editSheet?: ComponentType<EditSheetSectionProps>;
81
103
  readonly summary?: ComponentType<{
82
104
  readonly sourceId: string;
83
105
  readonly variant?: "badge" | "panel";
@@ -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":"AAWA,OAAO,EAEL,aAAa,EAIb,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC7E,OAAO,EAA+B,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACtF,OAAO,KAAK,WAAW,MAAM,wCAAwC,CAAC;AAOtE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEjF,OAAO,KAAK,WAAW,MAAM,wCAAwC,CAAC;AACtE,OAAO,KAAK,IAAI,MAAM,iCAAiC,CAAC;AACxD,OAAO,KAAK,WAAW,MAAM,wCAAwC,CAAC;AAEtE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAW5F,MAAM,WAAW,QAAQ;IACvB,wEAAwE;IACxE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC;sEACkE;IAClE,QAAQ,CAAC,GAAG,CAAC,EAAE;QACb,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;KAC3B,CAAC;CACH;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;IAC/C,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACjC;AAED;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAcnE,MAAM,WAAW,iBAAiB;IAChC,mDAAmD;IACnD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;oDACgD;IAChD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB;4CACwC;IACxC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,yCAAyC;IACzC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,yBAAyB;IACxC,8EAA8E;IAC9E,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IAChC,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,8CAA8C;IAC9C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;6BAE6B;AAC7B,MAAM,MAAM,oBAAoB,GAC5B;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GACtD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAA;CAAE,CAAC;AAE3B,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,MAAM,OAAO,CAAC,oBAAoB,CAAC,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC;CAC1F;AAED,MAAM,WAAW,iBAAiB;IAChC,8DAA8D;IAC9D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,aAAa,CAAC;QAC1B;;;sEAG8D;QAC9D,QAAQ,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;QAC7C,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC;QAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAC7B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;QAChC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;KACpC,CAAC,CAAC;IACH;6EACyE;IACzE,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC;QAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC;KAC7B,CAAC,CAAC;IACH;;;;;6EAKyE;IACzE,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC,qBAAqB,CAAC,CAAC;IAC1D,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;QAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;QACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;KAChC,CAAC,CAAC;IACH;;4EAEwE;IACxE,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC;QAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;QACjC,QAAQ,CAAC,cAAc,CAAC,EAAE,yBAAyB,GAAG,IAAI,CAAC;KAC5D,CAAC,CAAC;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAChD;;wDAEoD;IACpD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CAC/B;AAQD,MAAM,WAAW,oBAAoB;IACnC,kEAAkE;IAClE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;CACzD;AAED,MAAM,WAAW,gBAAgB,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM;IAC3D,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC;IACjB,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAC;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IACzC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC/C;;;4EAGwE;IACxE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IAC/C;;yEAEqE;IACrE,QAAQ,CAAC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;CACtD;AAED;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAAI,KAAK,CAAC,GAAG,SAAS,MAAM,EACzD,MAAM,gBAAgB,CAAC,GAAG,CAAC,KAC1B,gBAAgB,CAAC,GAAG,CAAS,CAAC;AAkBjC,MAAM,WAAW,6BAA6B;IAC5C;;oCAEgC;IAChC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,CAAC;IAC3C;oEACgE;IAChE,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC;CACtE;AAED,MAAM,WAAW,uCAAuC;IACtD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,MAAM,CAAC;IAChC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC;CACtE;AAED,gBAAgB;AAChB,eAAO,MAAM,qCAAqC,GAChD,SAAS,iBAAiB,CAAC,iBAAiB,EAC5C,SAAS,uCAAuC,KAC/C,iBAAiB,CAAC,iBAUpB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,GACjC,CAAC,SAAS,YAAY,CAAC,YAAY,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,EAAE,OAAO,CAAC,EAEzE,OAAO,CAAC,EACR,UAAS,6BAAkC,kGA8B5C,CAAC;AA0BF,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,OAAO,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC9C,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;CAC9B;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,4BAA4B,GAClC,UAAU,CAAC,OAAO,aAAa,CAAC,CAoBlC;AAWD,qDAAqD;AACrD,eAAO,MAAM,gBAAgB,QAAO,SAAS,gBAAgB,EAClB,CAAC;AAE5C,8EAA8E;AAC9E,eAAO,MAAM,qBAAqB,QAAO,SAAS,iBAAiB,EACR,CAAC;AAE5D,qFAAqF;AACrF,eAAO,MAAM,wBAAwB,QAAO,SAAS,oBAAoB,EACR,CAAC"}
@@ -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, 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// IntegrationPlugin / IntegrationPreset — UI contract for plugins that expose\n// \"integrations\" (OpenAPI specs, MCP servers, GraphQL endpoints, etc.). The\n// host owns the integration 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 `integrationPlugin`\n// alongside `pages`/`widgets`, and the host derives the union list\n// from `virtual:executor/plugins-client`.\n// ---------------------------------------------------------------------------\n\nexport interface IntegrationPreset {\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 /** Endpoint passed to agent-facing probe/add tools when their schema\n * uses `endpoint` instead of `url`. */\n readonly endpoint?: string;\n /** Optional icon URL (favicon, logo). */\n readonly icon?: string;\n /** Shown in the top-level grid on the integrations page when true. */\n readonly featured?: boolean;\n}\n\nexport interface IntegrationAccountHandoff {\n /** Changes on each handoff URL, so the accounts UI can open once per link. */\n readonly key: string;\n readonly owner?: \"org\" | \"user\";\n /** Auth template/method to preselect when present. */\n readonly template?: string;\n /** Non-secret connection label to prefill. */\n readonly label?: string;\n}\n\nexport interface IntegrationPlugin {\n /** Unique key matching the SDK plugin id (e.g. \"openapi\"). */\n readonly key: string;\n readonly label: string;\n readonly add: ComponentType<{\n /** Called when the integration has been registered. Receives the slug of\n * the just-registered integration, so the host can route to its detail\n * hub (`/integrations/<slug>`). Optional so existing no-arg calls still\n * typecheck while plugins are threading the slug through. */\n readonly onComplete: (slug?: string) => 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 /** Renders the integration's Accounts hub (auth methods + connections) inside\n * the detail page's Accounts tab. Plugins that declare auth methods implement\n * this; the page falls back to a generic accounts list when absent. */\n readonly accounts?: ComponentType<{\n readonly sourceId: string;\n readonly integrationName: string;\n readonly accountHandoff?: IntegrationAccountHandoff | null;\n }>;\n readonly presets?: readonly IntegrationPreset[];\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 /** Integration plugin contribution — populated by plugins that expose\n * `kind` rows in the core `source` table (openapi, mcp, graphql).\n * The host's integrations page derives its provider\n * list from the union of every loaded plugin's `integrationPlugin`. */\n readonly integrationPlugin?: IntegrationPlugin;\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 /** Optional dynamic Authorization header for hosts whose active\n * Executor Server Connection requires Basic or Bearer auth. */\n readonly authorizationHeader?: string | null | (() => string | null);\n}\n\nexport interface PluginAtomClientRequestTransformOptions {\n readonly baseUrl?: () => string;\n readonly authorizationHeader?: string | null | (() => string | null);\n}\n\n/** @internal */\nexport const applyPluginAtomClientRequestTransform = (\n request: HttpClientRequest.HttpClientRequest,\n options: PluginAtomClientRequestTransformOptions,\n): HttpClientRequest.HttpClientRequest => {\n let next = options.baseUrl ? HttpClientRequest.prependUrl(request, options.baseUrl()) : request;\n const authorization =\n typeof options.authorizationHeader === \"function\"\n ? options.authorizationHeader()\n : options.authorizationHeader;\n if (authorization) {\n next = HttpClientRequest.setHeader(next, \"authorization\", authorization);\n }\n return next;\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\", authorizationHeader } = options;\n const pluginId = group.identifier;\n const bundle = HttpApi.make(`plugin-${pluginId}`).add(group);\n const getBaseUrl = typeof baseUrl === \"function\" ? baseUrl : null;\n const staticBaseUrl = typeof baseUrl === \"function\" ? undefined : baseUrl;\n const getAuthorizationHeader =\n typeof authorizationHeader === \"function\" ? authorizationHeader : null;\n const hasAuthorization = authorizationHeader !== undefined && authorizationHeader !== null;\n const transformClient =\n getBaseUrl || hasAuthorization\n ? HttpClient.mapRequest((request) =>\n applyPluginAtomClientRequestTransform(request, {\n ...(getBaseUrl ? { baseUrl: getBaseUrl } : {}),\n ...(getAuthorizationHeader\n ? { authorizationHeader: getAuthorizationHeader }\n : authorizationHeader !== undefined\n ? { authorizationHeader }\n : {}),\n }),\n )\n : undefined;\n\n return AtomHttpApi.Service<`Plugin_${G[\"identifier\"]}Client`>()(`Plugin_${pluginId}Client`, {\n api: bundle,\n httpClient: FetchHttpClient.layer,\n ...(staticBaseUrl !== undefined ? { baseUrl: staticBaseUrl } : {}),\n ...(transformClient ? { transformClient } : {}),\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 (`useIntegrationPlugins` 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 integrationPlugins: readonly IntegrationPlugin[];\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 integrationPlugins: plugins.flatMap((p) =>\n p.integrationPlugin ? [p.integrationPlugin] : [],\n ),\n secretProviderPlugins: plugins.flatMap((p) =>\n p.secretProviderPlugin ? [p.secretProviderPlugin] : [],\n ),\n }),\n [plugins],\n );\n // Kick off lazy chunk downloads for every integration plugin once the host\n // mounts, so navigating into an add/edit page doesn't suspend.\n useEffect(() => {\n for (const ip of value.integrationPlugins) ip.preload?.();\n }, [value.integrationPlugins]);\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/** Integration plugins extracted from `clientPlugins[].integrationPlugin`. */\nexport const useIntegrationPlugins = (): readonly IntegrationPlugin[] =>\n usePluginsCtx(\"useIntegrationPlugins\").integrationPlugins;\n\n/** Secret-provider plugins extracted from `clientPlugins[].secretProviderPlugin`. */\nexport const useSecretProviderPlugins = (): readonly SecretProviderPlugin[] =>\n usePluginsCtx(\"useSecretProviderPlugins\").secretProviderPlugins;\n"],"mappings":"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","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// IntegrationPlugin / IntegrationPreset — UI contract for plugins that expose\n// \"integrations\" (OpenAPI specs, MCP servers, GraphQL endpoints, etc.). The\n// host owns the integration 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 `integrationPlugin`\n// alongside `pages`/`widgets`, and the host derives the union list\n// from `virtual:executor/plugins-client`.\n// ---------------------------------------------------------------------------\n\nexport interface IntegrationPreset {\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 /** Endpoint passed to agent-facing probe/add tools when their schema\n * uses `endpoint` instead of `url`. */\n readonly endpoint?: string;\n /** Optional icon URL (favicon, logo). */\n readonly icon?: string;\n /** Shown in the top-level grid on the integrations page when true. */\n readonly featured?: boolean;\n}\n\nexport interface IntegrationAccountHandoff {\n /** Changes on each handoff URL, so the accounts UI can open once per link. */\n readonly key: string;\n readonly owner?: \"org\" | \"user\";\n /** Auth template/method to preselect when present. */\n readonly template?: string;\n /** Non-secret connection label to prefill. */\n readonly label?: string;\n}\n\n/** Outcome of applying an edit-sheet section's staged change. `summary` is\n * toasted on success; `ok: false` keeps the sheet open (the section renders\n * its own error inline). */\nexport type EditSheetApplyResult =\n | { readonly ok: true; readonly summary: string | null }\n | { readonly ok: false };\n\nexport interface EditSheetSectionProps {\n readonly sourceId: string;\n readonly onPendingChange?: (apply: (() => Promise<EditSheetApplyResult>) | null) => void;\n}\n\nexport interface IntegrationPlugin {\n /** Unique key matching the SDK plugin id (e.g. \"openapi\"). */\n readonly key: string;\n readonly label: string;\n readonly add: ComponentType<{\n /** Called when the integration has been registered. Receives the slug of\n * the just-registered integration, so the host can route to its detail\n * hub (`/integrations/<slug>`). Optional so existing no-arg calls still\n * typecheck while plugins are threading the slug through. */\n readonly onComplete: (slug?: string) => void;\n readonly onCancel: () => void;\n readonly initialUrl?: string;\n readonly initialPreset?: string;\n readonly initialNamespace?: string;\n }>;\n /** Legacy full-page edit surface. No host renders this anymore — plugin\n * configuration lives in the integration Edit sheet via `editSheet`. */\n readonly edit?: ComponentType<{\n readonly sourceId: string;\n readonly onSave: () => void;\n }>;\n /** Plugin-owned configuration rendered inside the integration's Edit sheet,\n * below the shared metadata fields (e.g. the OpenAPI spec-update controls).\n * The sheet has ONE Save: the section stages its pending change locally and\n * reports it through `onPendingChange` — a thunk that applies the staged\n * change. Save runs the metadata update, then the staged apply; a failed\n * apply keeps the sheet open with the section showing its own error. */\n readonly editSheet?: ComponentType<EditSheetSectionProps>;\n readonly summary?: ComponentType<{\n readonly sourceId: string;\n readonly variant?: \"badge\" | \"panel\";\n readonly onAction?: () => void;\n }>;\n /** Renders the integration's Accounts hub (auth methods + connections) inside\n * the detail page's Accounts tab. Plugins that declare auth methods implement\n * this; the page falls back to a generic accounts list when absent. */\n readonly accounts?: ComponentType<{\n readonly sourceId: string;\n readonly integrationName: string;\n readonly accountHandoff?: IntegrationAccountHandoff | null;\n }>;\n readonly presets?: readonly IntegrationPreset[];\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 /** Integration plugin contribution — populated by plugins that expose\n * `kind` rows in the core `source` table (openapi, mcp, graphql).\n * The host's integrations page derives its provider\n * list from the union of every loaded plugin's `integrationPlugin`. */\n readonly integrationPlugin?: IntegrationPlugin;\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 /** Optional dynamic Authorization header for hosts whose active\n * Executor Server Connection requires Basic or Bearer auth. */\n readonly authorizationHeader?: string | null | (() => string | null);\n}\n\nexport interface PluginAtomClientRequestTransformOptions {\n readonly baseUrl?: () => string;\n readonly authorizationHeader?: string | null | (() => string | null);\n}\n\n/** @internal */\nexport const applyPluginAtomClientRequestTransform = (\n request: HttpClientRequest.HttpClientRequest,\n options: PluginAtomClientRequestTransformOptions,\n): HttpClientRequest.HttpClientRequest => {\n let next = options.baseUrl ? HttpClientRequest.prependUrl(request, options.baseUrl()) : request;\n const authorization =\n typeof options.authorizationHeader === \"function\"\n ? options.authorizationHeader()\n : options.authorizationHeader;\n if (authorization) {\n next = HttpClientRequest.setHeader(next, \"authorization\", authorization);\n }\n return next;\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\", authorizationHeader } = options;\n const pluginId = group.identifier;\n const bundle = HttpApi.make(`plugin-${pluginId}`).add(group);\n const getBaseUrl = typeof baseUrl === \"function\" ? baseUrl : null;\n const staticBaseUrl = typeof baseUrl === \"function\" ? undefined : baseUrl;\n const getAuthorizationHeader =\n typeof authorizationHeader === \"function\" ? authorizationHeader : null;\n const hasAuthorization = authorizationHeader !== undefined && authorizationHeader !== null;\n const transformClient =\n getBaseUrl || hasAuthorization\n ? HttpClient.mapRequest((request) =>\n applyPluginAtomClientRequestTransform(request, {\n ...(getBaseUrl ? { baseUrl: getBaseUrl } : {}),\n ...(getAuthorizationHeader\n ? { authorizationHeader: getAuthorizationHeader }\n : authorizationHeader !== undefined\n ? { authorizationHeader }\n : {}),\n }),\n )\n : undefined;\n\n return AtomHttpApi.Service<`Plugin_${G[\"identifier\"]}Client`>()(`Plugin_${pluginId}Client`, {\n api: bundle,\n httpClient: FetchHttpClient.layer,\n ...(staticBaseUrl !== undefined ? { baseUrl: staticBaseUrl } : {}),\n ...(transformClient ? { transformClient } : {}),\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 (`useIntegrationPlugins` 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 integrationPlugins: readonly IntegrationPlugin[];\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 integrationPlugins: plugins.flatMap((p) =>\n p.integrationPlugin ? [p.integrationPlugin] : [],\n ),\n secretProviderPlugins: plugins.flatMap((p) =>\n p.secretProviderPlugin ? [p.secretProviderPlugin] : [],\n ),\n }),\n [plugins],\n );\n // Kick off lazy chunk downloads for every integration plugin once the host\n // mounts, so navigating into an add/edit page doesn't suspend.\n useEffect(() => {\n for (const ip of value.integrationPlugins) ip.preload?.();\n }, [value.integrationPlugins]);\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/** Integration plugins extracted from `clientPlugins[].integrationPlugin`. */\nexport const useIntegrationPlugins = (): readonly IntegrationPlugin[] =>\n usePluginsCtx(\"useIntegrationPlugins\").integrationPlugins;\n\n/** Secret-provider plugins extracted from `clientPlugins[].secretProviderPlugin`. */\nexport const useSecretProviderPlugins = (): readonly SecretProviderPlugin[] =>\n usePluginsCtx(\"useSecretProviderPlugins\").secretProviderPlugins;\n"],"mappings":"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","names":["HttpApi","AtomHttpApi"]}
@@ -14,6 +14,11 @@ export interface Connection {
14
14
  readonly address: ConnectionAddress;
15
15
  /** Optional human label (which account). Not load-bearing. */
16
16
  readonly identityLabel?: string | null;
17
+ /** User-curated description of what this connection is for. Agent-visible:
18
+ * surfaces next to the connection's prefix in the execute-tool inventory
19
+ * and in `connections.list`, so it is the place to give agents context a
20
+ * spec can't (e.g. "the staging CRM — reads only"). */
21
+ readonly description?: string | null;
17
22
  /** Epoch ms when an OAuth access token expires; null/absent for static creds. */
18
23
  readonly expiresAt?: number | null;
19
24
  /** The OAuth app (`oauth_client` slug) that minted this connection, when it
@@ -77,5 +82,13 @@ export type CreateConnectionInput = {
77
82
  readonly integration: IntegrationSlug;
78
83
  readonly template: AuthTemplateSlug;
79
84
  readonly identityLabel?: string | null;
85
+ readonly description?: string | null;
80
86
  } & ConnectionValueInput;
87
+ /** Edit a connection's user-curated metadata. Only the provided fields change;
88
+ * credentials and OAuth lifecycle are untouchable here (recreate or refresh
89
+ * instead). */
90
+ export interface UpdateConnectionInput {
91
+ readonly description?: string | null;
92
+ readonly identityLabel?: string | null;
93
+ }
81
94
  //# sourceMappingURL=connection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,eAAe,EACf,KAAK,EACL,cAAc,EACd,WAAW,EACZ,MAAM,OAAO,CAAC;AAUf,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,kDAAkD;IAClD,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAC;IACtC,kFAAkF;IAClF,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC;kCAC8B;IAC9B,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B;qCACiC;IACjC,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;IACpC,8DAA8D;IAC9D,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,iFAAiF;IACjF,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC;;iFAE6E;IAC7E,QAAQ,CAAC,WAAW,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9C;;;mFAG+E;IAC/E,QAAQ,CAAC,gBAAgB,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;IACzC;;;oFAGgF;IAChF,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED,sEAAsE;AACtE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAC;CACvC;AAED;;;;kBAIkB;AAClB,MAAM,MAAM,qBAAqB,GAC7B;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC1B;IAAE,QAAQ,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;QAAC,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAA;KAAE,CAAA;CAAE,CAAC;AAEvF;;;;;2EAK2E;AAC3E,MAAM,MAAM,oBAAoB,GAC5B;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC1B;IAAE,QAAQ,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;QAAC,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAA;KAAE,CAAA;CAAE,GAClF;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAC3C;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAA;CAAE,CAAC;AAE/D;;6BAE6B;AAC7B,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAC;IACtC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxC,GAAG,oBAAoB,CAAC"}
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,eAAe,EACf,KAAK,EACL,cAAc,EACd,WAAW,EACZ,MAAM,OAAO,CAAC;AAUf,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,kDAAkD;IAClD,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAC;IACtC,kFAAkF;IAClF,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC;kCAC8B;IAC9B,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B;qCACiC;IACjC,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;IACpC,8DAA8D;IAC9D,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC;;;4DAGwD;IACxD,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,iFAAiF;IACjF,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC;;iFAE6E;IAC7E,QAAQ,CAAC,WAAW,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9C;;;mFAG+E;IAC/E,QAAQ,CAAC,gBAAgB,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;IACzC;;;oFAGgF;IAChF,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED,sEAAsE;AACtE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAC;CACvC;AAED;;;;kBAIkB;AAClB,MAAM,MAAM,qBAAqB,GAC7B;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC1B;IAAE,QAAQ,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;QAAC,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAA;KAAE,CAAA;CAAE,CAAC;AAEvF;;;;;2EAK2E;AAC3E,MAAM,MAAM,oBAAoB,GAC5B;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC1B;IAAE,QAAQ,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;QAAC,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAA;KAAE,CAAA;CAAE,GAClF;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAC3C;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAA;CAAE,CAAC;AAE/D;;6BAE6B;AAC7B,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAC;IACtC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC,GAAG,oBAAoB,CAAC;AAEzB;;gBAEgB;AAChB,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxC"}
@@ -13,8 +13,10 @@ export declare const coreTables: {
13
13
  readonly integration: import("@executor-js/fumadb/schema").Table<{
14
14
  readonly slug: import("@executor-js/fumadb/schema").Column<"varchar(255)", string, string>;
15
15
  readonly plugin_id: import("@executor-js/fumadb/schema").Column<"string", string, string>;
16
- readonly description: import("@executor-js/fumadb/schema").Column<"string", string, string>;
16
+ readonly name: import("@executor-js/fumadb/schema").Column<"string", string | null, string | null>;
17
+ readonly description: import("@executor-js/fumadb/schema").Column<"string", string | null, string | null>;
17
18
  readonly config: import("@executor-js/fumadb/schema").Column<"json", unknown, unknown>;
19
+ readonly config_revised_at: import("@executor-js/fumadb/schema").Column<"bigint", bigint | null, bigint | null>;
18
20
  readonly can_remove: import("@executor-js/fumadb/schema").Column<"bool", boolean | null, boolean>;
19
21
  readonly can_refresh: import("@executor-js/fumadb/schema").Column<"bool", boolean | null, boolean>;
20
22
  readonly created_at: import("@executor-js/fumadb/schema").Column<"timestamp", Date, Date>;
@@ -30,6 +32,8 @@ export declare const coreTables: {
30
32
  readonly provider: import("@executor-js/fumadb/schema").Column<"string", string, string>;
31
33
  readonly item_ids: import("@executor-js/fumadb/schema").Column<"json", unknown, unknown>;
32
34
  readonly identity_label: import("@executor-js/fumadb/schema").Column<"string", string | null, string | null>;
35
+ readonly description: import("@executor-js/fumadb/schema").Column<"string", string | null, string | null>;
36
+ readonly tools_synced_at: import("@executor-js/fumadb/schema").Column<"bigint", bigint | null, bigint | null>;
33
37
  readonly oauth_client: import("@executor-js/fumadb/schema").Column<"string", string | null, string | null>;
34
38
  readonly oauth_client_owner: import("@executor-js/fumadb/schema").Column<"string", string | null, string | null>;
35
39
  readonly refresh_item_id: import("@executor-js/fumadb/schema").Column<"string", string | null, string | null>;
@@ -148,8 +152,10 @@ export declare const coreSchema: {
148
152
  readonly integration: import("@executor-js/fumadb/schema").Table<{
149
153
  readonly slug: import("@executor-js/fumadb/schema").Column<"varchar(255)", string, string>;
150
154
  readonly plugin_id: import("@executor-js/fumadb/schema").Column<"string", string, string>;
151
- readonly description: import("@executor-js/fumadb/schema").Column<"string", string, string>;
155
+ readonly name: import("@executor-js/fumadb/schema").Column<"string", string | null, string | null>;
156
+ readonly description: import("@executor-js/fumadb/schema").Column<"string", string | null, string | null>;
152
157
  readonly config: import("@executor-js/fumadb/schema").Column<"json", unknown, unknown>;
158
+ readonly config_revised_at: import("@executor-js/fumadb/schema").Column<"bigint", bigint | null, bigint | null>;
153
159
  readonly can_remove: import("@executor-js/fumadb/schema").Column<"bool", boolean | null, boolean>;
154
160
  readonly can_refresh: import("@executor-js/fumadb/schema").Column<"bool", boolean | null, boolean>;
155
161
  readonly created_at: import("@executor-js/fumadb/schema").Column<"timestamp", Date, Date>;
@@ -165,6 +171,8 @@ export declare const coreSchema: {
165
171
  readonly provider: import("@executor-js/fumadb/schema").Column<"string", string, string>;
166
172
  readonly item_ids: import("@executor-js/fumadb/schema").Column<"json", unknown, unknown>;
167
173
  readonly identity_label: import("@executor-js/fumadb/schema").Column<"string", string | null, string | null>;
174
+ readonly description: import("@executor-js/fumadb/schema").Column<"string", string | null, string | null>;
175
+ readonly tools_synced_at: import("@executor-js/fumadb/schema").Column<"bigint", bigint | null, bigint | null>;
168
176
  readonly oauth_client: import("@executor-js/fumadb/schema").Column<"string", string | null, string | null>;
169
177
  readonly oauth_client_owner: import("@executor-js/fumadb/schema").Column<"string", string | null, string | null>;
170
178
  readonly refresh_item_id: import("@executor-js/fumadb/schema").Column<"string", string | null, string | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"core-schema.d.ts","sourceRoot":"","sources":["../src/core-schema.ts"],"names":[],"mappings":"AAGA,OAAO,EAAgB,KAAK,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAiB5D,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,0EAA2B,CAAC;AACnE,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,wFAAsC,CAAC;AACtF,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,gFAAiC,CAAC;AACxE,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,8FAA4C,CAAC;AAC3F,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,EAAE,cAAc,OAAO,iFAChB,CAAC;AAC/C,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,0EAA2B,CAAC;AACrE,eAAO,MAAM,oBAAoB,GAAI,MAAM,MAAM,wFAAsC,CAAC;AACxF,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,0EAAyB,CAAC;AACjE,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,0EAAoC,CAAC;AACpF,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,yEAA8B,CAAC;AAmFtE,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuKrB,CAAC;AAEH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAa,CAAC;AACrC,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC;AAE3C,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC;AAChE,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC;AAC9D,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC;AACjE,MAAM,MAAM,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC;AACnE,MAAM,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;AAClD;;;4EAG4E;AAC5E,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,eAAe,CAAC,CAAC;AAChF,+EAA+E;AAC/E,eAAO,MAAM,uBAAuB,qJAYW,CAAC;AAChD,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC;AAC9D,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC;AAC/D,MAAM,MAAM,gBAAgB,GAAG,OAAO,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC,CAAC;AACrE,MAAM,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;AAElD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,kBAAkB,GAAG,OAAO,CAAC;AAExE,eAAO,MAAM,mBAAmB,mDAIgB,CAAC;AAEjD,eAAO,MAAM,kBAAkB,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,gBAC4B,CAAC"}
1
+ {"version":3,"file":"core-schema.d.ts","sourceRoot":"","sources":["../src/core-schema.ts"],"names":[],"mappings":"AAGA,OAAO,EAAgB,KAAK,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAiB5D,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,0EAA2B,CAAC;AACnE,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,wFAAsC,CAAC;AACtF,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,gFAAiC,CAAC;AACxE,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,8FAA4C,CAAC;AAC3F,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,EAAE,cAAc,OAAO,iFAChB,CAAC;AAC/C,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,0EAA2B,CAAC;AACrE,eAAO,MAAM,oBAAoB,GAAI,MAAM,MAAM,wFAAsC,CAAC;AACxF,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,0EAAyB,CAAC;AACjE,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,0EAAoC,CAAC;AACpF,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,yEAA8B,CAAC;AAmFtE,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4LrB,CAAC;AAEH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAa,CAAC;AACrC,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC;AAE3C,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC;AAChE,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC;AAC9D,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC;AACjE,MAAM,MAAM,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC;AACnE,MAAM,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;AAClD;;;4EAG4E;AAC5E,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,eAAe,CAAC,CAAC;AAChF,+EAA+E;AAC/E,eAAO,MAAM,uBAAuB,qJAYW,CAAC;AAChD,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC;AAC9D,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC;AAC/D,MAAM,MAAM,gBAAgB,GAAG,OAAO,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC,CAAC;AACrE,MAAM,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;AAElD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,kBAAkB,GAAG,OAAO,CAAC;AAExE,eAAO,MAAM,mBAAmB,mDAIgB,CAAC;AAEjD,eAAO,MAAM,kBAAkB,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,gBAC4B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"core-tools.d.ts","sourceRoot":"","sources":["../src/core-tools.ts"],"names":[],"mappings":"AA4XA,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED,eAAO,MAAM,eAAe,uMAgWzB,CAAC"}
1
+ {"version":3,"file":"core-tools.d.ts","sourceRoot":"","sources":["../src/core-tools.ts"],"names":[],"mappings":"AA8XA,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED,eAAO,MAAM,eAAe,uMAgWzB,CAAC"}
package/dist/core.js CHANGED
@@ -19,7 +19,9 @@ import {
19
19
  ORG_SUBJECT,
20
20
  StorageError,
21
21
  TOOL_POLICY_ACTIONS,
22
+ ToolResult,
22
23
  UniqueViolationError,
24
+ annotateToolResultOutcome,
23
25
  bigintColumn,
24
26
  boolColumn,
25
27
  buildToolTypeScriptPreview,
@@ -35,6 +37,7 @@ import {
35
37
  executorUnscopedPolicyName,
36
38
  isStorageFailure,
37
39
  isToolPolicyAction,
40
+ isToolResult,
38
41
  jsonColumn,
39
42
  keyColumn,
40
43
  makeFumaBlobStore,
@@ -50,7 +53,7 @@ import {
50
53
  textColumn,
51
54
  tool,
52
55
  toolAddress
53
- } from "./chunk-YPVKRUZV.js";
56
+ } from "./chunk-WKKKHDH2.js";
54
57
  import {
55
58
  ConnectionNotFoundError,
56
59
  CredentialProviderNotRegisteredError,
@@ -79,7 +82,7 @@ import {
79
82
  effectivePolicyFromSorted,
80
83
  isValidPattern,
81
84
  matchPattern
82
- } from "./chunk-UKOTOKXM.js";
85
+ } from "./chunk-6EED5LAL.js";
83
86
  import "./chunk-EIHWBY6T.js";
84
87
  import {
85
88
  AuthTemplateSlug,
@@ -103,7 +106,7 @@ import {
103
106
  import "./chunk-7D4SUZUM.js";
104
107
 
105
108
  // src/index.ts
106
- import { Context, Effect as Effect3, Layer, Schema as Schema3, Data as Data2, Option as Option2 } from "effect";
109
+ import { Context, Effect as Effect3, Layer, Schema as Schema2, Data as Data2, Option as Option2 } from "effect";
107
110
  import {
108
111
  HttpApi,
109
112
  HttpApiBuilder,
@@ -141,38 +144,6 @@ var mergeAuthTemplates = (existing, incoming) => {
141
144
  return result;
142
145
  };
143
146
 
144
- // src/tool-result.ts
145
- import { Schema } from "effect";
146
- var ToolErrorSchema = Schema.Struct({
147
- code: Schema.String,
148
- message: Schema.String,
149
- status: Schema.optional(Schema.Number),
150
- details: Schema.optional(Schema.Unknown),
151
- retryable: Schema.optional(Schema.Boolean)
152
- });
153
- var ToolHttpMetaSchema = Schema.Struct({
154
- status: Schema.Number,
155
- headers: Schema.Record(Schema.String, Schema.String)
156
- });
157
- var ToolResult = {
158
- ok: (data, meta) => ({
159
- ok: true,
160
- data,
161
- ...meta?.http ? { http: meta.http } : {}
162
- }),
163
- fail: (error) => ({ ok: false, error })
164
- };
165
- var ToolResultSchema = Schema.Union([
166
- Schema.Struct({
167
- ok: Schema.Literal(true),
168
- data: Schema.Unknown,
169
- http: Schema.optional(ToolHttpMetaSchema)
170
- }),
171
- Schema.Struct({ ok: Schema.Literal(false), error: ToolErrorSchema })
172
- ]);
173
- var isUnknownToolResult = Schema.is(ToolResultSchema);
174
- var isToolResult = (value) => isUnknownToolResult(value);
175
-
176
147
  // src/sqlite-data-migrations.ts
177
148
  import { Data, Effect } from "effect";
178
149
  var DataMigrationError = class extends Data.TaggedError("DataMigrationError") {
@@ -226,8 +197,8 @@ var runSqliteDataMigrations = (client, migrations) => Effect.gen(function* () {
226
197
  });
227
198
 
228
199
  // src/sqlite-config-blob-migration.ts
229
- import { Effect as Effect2, Option, Schema as Schema2 } from "effect";
230
- var decodeJsonOption = Schema2.decodeUnknownOption(Schema2.UnknownFromJsonString);
200
+ import { Effect as Effect2, Option, Schema } from "effect";
201
+ var decodeJsonOption = Schema.decodeUnknownOption(Schema.UnknownFromJsonString);
231
202
  var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
232
203
  var runSqliteConfigBlobMigration = (client, options) => Effect2.gen(function* () {
233
204
  const execute2 = (stmt) => Effect2.tryPromise({
@@ -369,7 +340,7 @@ export {
369
340
  PolicyId,
370
341
  ProviderItemId,
371
342
  ProviderKey,
372
- Schema3 as Schema,
343
+ Schema2 as Schema,
373
344
  StorageError,
374
345
  Subject,
375
346
  TOOL_POLICY_ACTIONS,
@@ -384,6 +355,7 @@ export {
384
355
  ToolSchemaView,
385
356
  UniqueViolationError,
386
357
  UrlElicitation,
358
+ annotateToolResultOutcome,
387
359
  apiBaseUrlForServerOrigin,
388
360
  authToolFailure,
389
361
  bigintColumn,
package/dist/core.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/integration.ts","../src/tool-result.ts","../src/sqlite-data-migrations.ts","../src/sqlite-config-blob-migration.ts","../src/auth-tool-failure.ts"],"sourcesContent":["// ---------------------------------------------------------------------------\n// @executor-js/sdk — public surface (v2)\n// ---------------------------------------------------------------------------\n\n// Re-export the Effect/Schema/HttpApi primitives plugin authors need so a\n// plugin can be written importing only from `@executor-js/sdk`.\nexport { Context, Effect, Layer, Schema, Data, Option } from \"effect\";\nexport {\n HttpApi,\n HttpApiBuilder,\n HttpApiClient,\n HttpApiEndpoint,\n HttpApiGroup,\n HttpApiMiddleware,\n HttpApiSchema,\n} from \"effect/unstable/httpapi\";\n\n// FumaDB integration.\nexport { fumadb } from \"@executor-js/fumadb\";\nexport type { FumaDB } from \"@executor-js/fumadb\";\nexport type { AbstractQuery, Condition, ConditionBuilder } from \"@executor-js/fumadb/query\";\nexport { column, idColumn, schema as fumaSchema, table } from \"@executor-js/fumadb/schema\";\nexport type {\n AnyColumn,\n AnySchema,\n AnyTable,\n Column,\n Schema as FumaSchema,\n} from \"@executor-js/fumadb/schema\";\n\nexport type {\n FumaDb,\n FumaQuery,\n FumaRow,\n FumaTables,\n IFumaClient,\n StorageFailure,\n} from \"./fuma-runtime\";\nexport { StorageError, UniqueViolationError, isStorageFailure } from \"./fuma-runtime\";\n\n// IDs (branded) — the v2 set.\nexport {\n IntegrationSlug,\n AuthTemplateSlug,\n ConnectionName,\n OAuthClientSlug,\n OAuthState,\n ProviderKey,\n ProviderItemId,\n ConnectionAddress,\n ToolAddress,\n ToolName,\n ElicitationId,\n PolicyId,\n Tenant,\n Subject,\n Owner,\n} from \"./ids\";\nexport { connectionIdentifier, isConnectionIdentifier } from \"./connection-name-identifier\";\n\n// Errors (tagged) — the ExecuteError set + integration lifecycle.\nexport {\n ToolNotFoundError,\n ToolInvocationError,\n ToolBlockedError,\n NoHandlerError,\n PluginNotLoadedError,\n IntegrationNotFoundError,\n IntegrationAlreadyExistsError,\n IntegrationRemovalNotAllowedError,\n ConnectionNotFoundError,\n CredentialProviderNotRegisteredError,\n CredentialResolutionError,\n type ExecuteError,\n type ExecutorError,\n} from \"./errors\";\n\n// Integration / connection / tool domain contracts.\nexport type {\n AuthMethodDescriptor,\n AuthMethodOAuthDescriptor,\n AuthPlacementDescriptor,\n Integration,\n IntegrationConfig,\n IntegrationDisplayDescriptor,\n RegisterIntegrationInput,\n} from \"./integration\";\nexport { freshCustomAuthSlug, mergeAuthTemplates } from \"./integration\";\nexport type {\n Connection,\n ConnectionRef,\n ConnectionValueInput,\n CreateConnectionInput,\n} from \"./connection\";\nexport type { Tool, ToolDef, ToolListFilter, ToolAnnotations } from \"./tool\";\n\n// Credential providers.\nexport type { CredentialProvider, ProviderEntry } from \"./provider\";\n\n// Public projections / detection.\nexport { ToolSchemaView, IntegrationDetectionResult } from \"./types\";\n\n// Core schema.\nexport {\n bigintColumn,\n boolColumn,\n coreSchema,\n coreTables,\n dateColumn,\n isToolPolicyAction,\n jsonColumn,\n keyColumn,\n nullableBigintColumn,\n nullableJsonColumn,\n nullableKeyColumn,\n nullableTextColumn,\n textColumn,\n TOOL_POLICY_ACTIONS,\n type CoreSchema,\n type IntegrationRow,\n type ConnectionRow,\n type OAuthClientRow,\n type OAuthSessionRow,\n type ToolRow,\n type ToolInvocationRow,\n type DefinitionRow,\n type ToolPolicyRow,\n type PluginStorageRow,\n type BlobRow,\n type ToolPolicyAction,\n} from \"./core-schema\";\n\n// Owner policy.\nexport {\n ORG_SUBJECT,\n executorOwnerPolicyName,\n executorUnscopedPolicyName,\n type ExecutorOwnerPolicyContext,\n} from \"./owner-policy\";\n\n// Tool policies.\nexport {\n matchPattern,\n isValidPattern,\n effectivePolicyFromSorted,\n ToolPolicyActionSchema,\n type ToolPolicy,\n type CreateToolPolicyInput,\n type UpdateToolPolicyInput,\n type RemoveToolPolicyInput,\n type PolicyMatch,\n type EffectivePolicy,\n type PolicySource,\n} from \"./policies\";\n\n// Elicitation.\nexport {\n FormElicitation,\n UrlElicitation,\n ElicitationAction,\n ElicitationResponse,\n ElicitationDeclinedError,\n type ElicitationRequest,\n type ElicitationHandler,\n type ElicitationContext,\n type OnElicitation,\n type InvokeOptions,\n} from \"./elicitation\";\n\n// Blob store — the plugin-facing contract (`BlobStore`/`PluginBlobStore`)\n// plus the platform-neutral backends (`makeFumaBlobStore` default,\n// `makeInMemoryBlobStore` for tests). Platform-specific backends live with\n// their host (R2: `@executor-js/cloudflare/blob-store`).\nexport {\n pluginBlobStore,\n makeInMemoryBlobStore,\n makeFumaBlobStore,\n sha256Hex,\n type BlobStore,\n type PluginBlobStore,\n type OwnerPartitions,\n} from \"./blob\";\n\n// Plugin storage.\nexport {\n definePluginStorageCollection,\n pluginStorageId,\n type PluginStorageCollectionDefinition,\n type PluginStorageCollectionFacade,\n type PluginStorageCollectionIndexedField,\n type PluginStorageCollectionKeyInput,\n type PluginStorageCollectionListInput,\n type PluginStorageCollectionOrderBy,\n type PluginStorageCollectionPutInput,\n type PluginStorageCollectionQueryInput,\n type PluginStorageCollectionScopedKeyInput,\n type PluginStorageCollectionWhere,\n type PluginStorageConfig,\n type PluginStorageEntry,\n type PluginStorageFacade,\n type PluginStorageIndexField,\n type PluginStorageIndexSpec,\n type PluginStorageKeyInput,\n type PluginStorageListInput,\n type PluginStoragePutInput,\n type PluginStorageRuntimeCollectionDefinition,\n type PluginStorageRuntimeIndexSpec,\n type PluginStorageSchema,\n type PluginStorageSchemaType,\n type PluginStorageScopedKeyInput,\n type PluginStorageWhereFilter,\n type PluginStorageWhereValue,\n} from \"./plugin-storage\";\n\n// OAuth (v2 contracts).\nexport { OAUTH2_PROVIDER_KEY, OAUTH2_SESSION_TTL_MS } from \"./oauth\";\nexport {\n OAuthStartError,\n OAuthCompleteError,\n OAuthProbeError,\n OAuthRegisterDynamicError,\n OAuthSessionNotFoundError,\n type OAuthGrant,\n type OAuthAuthentication,\n type OAuthClient,\n type OAuthClientSummary,\n type CreateOAuthClientInput,\n type RegisterDynamicClientInput,\n type ConnectResult,\n type OAuthStartInput,\n type OAuthCompleteInput,\n type OAuthProbeInput,\n type OAuthProbeResult,\n type OAuthService,\n} from \"./oauth-client\";\n\n// NOTE: the OAuth 2.1 implementation helpers (`./oauth-helpers`,\n// `makeOAuthService` in `./oauth-service`, discovery in `./oauth-discovery`)\n// are SDK-internal — consumed only by `createExecutor`. The hosted HTTP client\n// builder is host-internal and reachable via `@executor-js/sdk/host-internal`.\n\nexport {\n DEFAULT_EXECUTOR_SERVER_ORIGIN,\n DEFAULT_EXECUTOR_SERVER_USERNAME,\n apiBaseUrlForServerOrigin,\n getExecutorServerAuthorizationHeader,\n normalizeExecutorServerConnection,\n normalizeExecutorServerOrigin,\n originFromApiBaseUrl,\n type ExecutorServerAuth,\n type ExecutorServerConnection,\n type ExecutorServerConnectionInput,\n type ExecutorServerConnectionKind,\n} from \"./server-connection\";\n\nexport {\n OAUTH_POPUP_MESSAGE_TYPE,\n type OAuthPopupResult,\n isOAuthPopupResult,\n} from \"./oauth-popup-types\";\n\n// Plugin definition.\nexport {\n type Plugin,\n type PluginSpec,\n type PluginCtx,\n type PluginExtensions,\n type ConfiguredPlugin,\n type AnyPlugin,\n type StorageDeps,\n type OwnerBinding,\n type IntegrationRecord,\n type StaticSourceDecl,\n type StaticToolDecl,\n type StaticToolSchema,\n type StaticToolExecuteContext,\n type StaticToolHandlerInput,\n type StaticToolInput,\n type ConfigureIntegrationHandlerInput,\n type InvokeToolInput,\n type ConnectionLifecycleInput,\n type IntegrationConfigureDecl,\n type IntegrationConfigureSchema,\n type IntegrationPreset,\n type IntegrationPresetCatalogEntry,\n type ResolveToolsInput,\n type ResolveToolsResult,\n type ToolInvocationCredential,\n type Elicit,\n definePlugin,\n tool,\n} from \"./plugin\";\n\n// Executor.\n//\n// `collectTables` is host/tooling-only (cli schema cmd, kernel worker,\n// local/cloud DB bring-up). Its definition stays here because `createExecutor`\n// uses it; the host surface (`@executor-js/api/server`) re-exports it.\nexport {\n type Executor,\n type ExecutorConfig,\n type ExecutorDb,\n type ExecutorDbFactory,\n type ExecutorDbInput,\n type ParsedToolAddress,\n createExecutor,\n collectTables,\n parseToolAddress,\n connectionAddress,\n toolAddress,\n} from \"./executor\";\n\n// CLI / runtime config.\nexport {\n defineExecutorConfig,\n type ExecutorCliConfig,\n type ExecutorPluginsFactory,\n} from \"./config\";\n\n// The one TS-preview generator plugins assert against.\nexport { buildToolTypeScriptPreview } from \"./schema-types\";\n\n// Wire-level HTTP error schemas usable by plugin HttpApiGroup definitions.\nexport { InternalError } from \"./api-errors\";\n\n// ToolResult — typed value-based discriminated union for tool outcomes.\nexport { ToolResult, isToolResult, type ToolError, type ToolHttpMeta } from \"./tool-result\";\n\n// Stamped boot-time data-migration ledger for the libSQL-backed apps.\nexport {\n DataMigrationError,\n DuplicateDataMigrationError,\n runSqliteDataMigrations,\n sqliteDataMigration,\n type SqliteDataMigration,\n type SqliteDataMigrationClient,\n} from \"./sqlite-data-migrations\";\n// Shared inline-config-field → blob-table migration body; the protocol\n// plugins bind their field names and export the ledger entries.\nexport {\n runSqliteConfigBlobMigration,\n type SqliteConfigBlobMigrationOptions,\n} from \"./sqlite-config-blob-migration\";\nexport {\n authToolFailure,\n type AuthToolFailureCode,\n type AuthToolFailureInput,\n} from \"./auth-tool-failure\";\n","import type { IntegrationSlug } from \"./ids\";\n\n/* Core knows only an integration's catalog identity — slug + description + which\n * plugin (`kind`) owns it. The type-specific shape (openapi auth templates + spec,\n * an mcp url, …) lives in the plugin and is stored as an opaque `config` blob core\n * never parses. An integration is one API surface; multi-API providers (Google)\n * are bundled into a single integration by their plugin, so one credential covers\n * the whole provider. */\n\n// ---------------------------------------------------------------------------\n// Declared auth methods — a plugin-agnostic projection of an integration's\n// stored `config` into the catalog response. Each plugin derives these from its\n// own opaque config (`describeAuthMethods`); core never parses config itself.\n// The client renders these as the integration's selectable auth methods, so the\n// catalog is authoritative even when the integration has zero connections.\n//\n// This is a DERIVED projection — there is no DB column. A plugin that declares\n// no projector contributes `[]`, and the client falls through to its existing\n// connection-inference behavior (no regression).\n// ---------------------------------------------------------------------------\n\nexport interface IntegrationDisplayDescriptor {\n /** Non-secret URL suitable for display metadata such as favicons. */\n readonly url?: string;\n}\n\n/** Where a credential value is carried on the outbound request. Mirrors the\n * client's `Placement`. */\nexport interface AuthPlacementDescriptor {\n readonly carrier: \"header\" | \"query\";\n readonly name: string;\n /** Literal prepended to the value (e.g. `\"Bearer \"`). Empty when bare. */\n readonly prefix: string;\n /** The input variable this placement renders from. `token` for single-input\n * methods; a distinct name per input for multi-input ones (e.g. Datadog).\n * Absent → treated as `token`. */\n readonly variable?: string;\n /** Set when the placement renders this exact value instead of a credential\n * (a static header/param the method carries). Such placements reference no\n * input variable. */\n readonly literal?: string;\n}\n\n/** OAuth specifics for an `oauth` auth method. For probe-at-connect providers\n * (MCP) only `discoveryUrl` + `supportsDynamicRegistration` are known up front;\n * the authorize/token endpoints are discovered live at connect time. For\n * providers that store endpoints (OpenAPI) the resolved URLs are carried. */\nexport interface AuthMethodOAuthDescriptor {\n /** For probe-at-connect providers (MCP): the endpoint to discover metadata\n * from (RFC 9728 PRM → RFC 8414 AS metadata). */\n readonly discoveryUrl?: string;\n readonly authorizationUrl?: string;\n readonly tokenUrl?: string;\n readonly scopes?: readonly string[];\n readonly registrationEndpoint?: string;\n /** True when the integration is known to support RFC 7591 dynamic client\n * registration (drives the transparent auto-register connect flow). */\n readonly supportsDynamicRegistration?: boolean;\n}\n\n/** A single declared auth method on an integration's catalog response. */\nexport interface AuthMethodDescriptor {\n /** Stable id within the integration (e.g. the auth template slug). */\n readonly id: string;\n readonly label: string;\n readonly kind: \"oauth\" | \"apikey\" | \"header\" | \"none\";\n /** The auth-template slug a connection binds against. */\n readonly template: string;\n readonly placements?: readonly AuthPlacementDescriptor[];\n readonly oauth?: AuthMethodOAuthDescriptor;\n}\n\n/** Public projection of an integration — what `integrations.list/get` return.\n * Carries no credentials and no plugin-internal config. */\nexport interface Integration {\n readonly slug: IntegrationSlug;\n readonly description: string;\n /** The plugin that owns this integration kind (e.g. \"openapi\", \"mcp\"). */\n readonly kind: string;\n /** Whether the user can remove this integration from the catalog. `false`\n * for static / built-in integrations declared by a plugin at startup. */\n readonly canRemove: boolean;\n /** Whether the owning plugin supports re-resolving a connection's tools\n * (`connections.refresh`). */\n readonly canRefresh: boolean;\n /** Declared auth methods derived from the owning plugin's stored config (a\n * derived projection, not a DB column). Always present, possibly empty. */\n readonly authMethods: readonly AuthMethodDescriptor[];\n /** Non-secret display URL derived by the owning plugin from opaque config.\n * Used for catalog favicons; never includes credentials or plugin config. */\n readonly displayUrl?: string;\n}\n\n/** Plugin-owned, opaque-to-core configuration stored on the integration row. The\n * owning plugin writes it at register time and reads it back at execute time to\n * render auth / produce tools. Core treats it as an opaque JSON blob. */\nexport type IntegrationConfig = unknown;\n\n// ---------------------------------------------------------------------------\n// Auth-template merge — shared by every plugin whose config carries a slugged\n// `authenticationTemplate` array (openapi, graphql, mcp). The custom-method\n// flow merge-appends: an incoming entry with a matching slug replaces the\n// existing entry in place; entries lacking a slug (or colliding with another\n// entry added in the same call) get a fresh `custom_<id>` slug.\n// ---------------------------------------------------------------------------\n\nconst shortId = (): string => Math.random().toString(36).slice(2, 8);\n\nexport const freshCustomAuthSlug = (taken: ReadonlySet<string>): string => {\n let candidate = `custom_${shortId()}`;\n while (taken.has(candidate)) candidate = `custom_${shortId()}`;\n return candidate;\n};\n\nexport const mergeAuthTemplates = <T extends { readonly slug: string }>(\n existing: readonly T[],\n incoming: readonly T[],\n): readonly T[] => {\n const result: T[] = existing.map((entry: T) => entry);\n const taken = new Set<string>(result.map((entry: T) => String(entry.slug)));\n for (const entry of incoming) {\n // `slug` may be branded-required in the plugin's schema, but JSON callers\n // can submit it empty/blank — read defensively and backfill so every\n // stored template has a stable slug.\n const rawSlug = (entry as { readonly slug?: unknown }).slug;\n const requested = typeof rawSlug === \"string\" ? rawSlug.trim() : \"\";\n const existingIndex = result.findIndex((current: T) => String(current.slug) === requested);\n if (requested.length > 0 && existingIndex >= 0) {\n result[existingIndex] = entry;\n continue;\n }\n const slug =\n requested.length > 0 && !taken.has(requested) ? requested : freshCustomAuthSlug(taken);\n taken.add(slug);\n result.push({ ...entry, slug } as T);\n }\n return result;\n};\n\n/** What a plugin's extension method passes to `ctx.core.integrations.register`.\n * The v2 analog of v1's `SourceInput`, minus the per-source tool list (tools are\n * produced per-connection now). */\nexport interface RegisterIntegrationInput {\n readonly slug: IntegrationSlug;\n readonly description: string;\n /** Opaque plugin config (auth templates, spec ref, mcp url, …). */\n readonly config: IntegrationConfig;\n readonly canRemove?: boolean;\n readonly canRefresh?: boolean;\n}\n","// ---------------------------------------------------------------------------\n// ToolResult — typed value-based discriminated union returned by tool\n// handlers and `invokeTool`. Domain success and expected failure both\n// resolve through Effect's success channel; only true infra defects use\n// the Effect failure channel.\n// ---------------------------------------------------------------------------\n\nimport { Schema } from \"effect\";\n\nexport const ToolErrorSchema = Schema.Struct({\n code: Schema.String,\n message: Schema.String,\n status: Schema.optional(Schema.Number),\n details: Schema.optional(Schema.Unknown),\n retryable: Schema.optional(Schema.Boolean),\n});\n\nexport type ToolError = typeof ToolErrorSchema.Type;\n\nexport const ToolHttpMetaSchema = Schema.Struct({\n status: Schema.Number,\n headers: Schema.Record(Schema.String, Schema.String),\n});\n\n/**\n * Transport metadata for HTTP-backed tools (OpenAPI). Kept beside `data`\n * rather than wrapped around it: `data` stays the upstream payload, while\n * cross-cutting transport facts (pagination Link headers, rate-limit\n * headers) remain reachable for callers that need them.\n */\nexport type ToolHttpMeta = typeof ToolHttpMetaSchema.Type;\n\nexport type ToolResult<T> =\n | { readonly ok: true; readonly data: T; readonly http?: ToolHttpMeta }\n | { readonly ok: false; readonly error: ToolError };\n\nexport const ToolResult = {\n ok: <T>(data: T, meta?: { readonly http?: ToolHttpMeta }): ToolResult<T> => ({\n ok: true,\n data,\n ...(meta?.http ? { http: meta.http } : {}),\n }),\n fail: <T = never>(error: ToolError): ToolResult<T> => ({ ok: false, error }),\n} as const;\n\nconst ToolResultSchema = Schema.Union([\n Schema.Struct({\n ok: Schema.Literal(true),\n data: Schema.Unknown,\n http: Schema.optional(ToolHttpMetaSchema),\n }),\n Schema.Struct({ ok: Schema.Literal(false), error: ToolErrorSchema }),\n]);\n\nconst isUnknownToolResult = Schema.is(ToolResultSchema);\n\nexport const isToolResult = (value: unknown): value is ToolResult<unknown> =>\n isUnknownToolResult(value);\n","// ---------------------------------------------------------------------------\n// Stamped data-migration ledger for the libSQL-backed apps (local boot,\n// selfhost boot). Cloud runs schema + data migrations through its drizzle\n// chain out-of-band; the local apps have no operator, so their migrations\n// run at boot — and before this ledger existed, each one re-scanned its\n// tables on every startup to decide \"did I already run?\" by data shape.\n// That accumulates (N migrations = N full-table scans per boot, forever)\n// and makes idempotence a per-migration proof obligation.\n//\n// This is the rail instead: a `data_migration` table (name → completion\n// time), an ordered registry the app composes, and a runner that executes\n// each pending migration once and stamps it. Stamped names are skipped\n// without touching the data.\n//\n// Write migrations idempotently anyway (defense in depth — the support\n// remedy for a half-applied state is deleting the stamp row and\n// rebooting). One deliberate semantics change from the scan-every-boot\n// era: after a migration is stamped, rows written later by an OLDER binary\n// (downgrade, then re-upgrade) are NOT re-healed. That matches the cloud\n// chain's semantics; the stamp row, not the data shape, is the source of\n// truth.\n// ---------------------------------------------------------------------------\n\nimport { Data, Effect } from \"effect\";\n\n/** Structural client interface so this module stays dependency-free;\n * `@libsql/client` satisfies it. */\nexport interface SqliteDataMigrationClient {\n execute(\n stmt: string | { readonly sql: string; readonly args: readonly unknown[] },\n ): Promise<{ readonly rows: readonly Record<string, unknown>[] }>;\n}\n\nexport class DataMigrationError extends Data.TaggedError(\"DataMigrationError\")<{\n /** The migration that failed, or null when the ledger itself did. */\n readonly migration: string | null;\n readonly cause: unknown;\n}> {}\n\nexport class DuplicateDataMigrationError extends Data.TaggedError(\"DuplicateDataMigrationError\")<{\n readonly name: string;\n}> {}\n\nexport interface SqliteDataMigration {\n /** Stable unique id, date-prefixed so the registry reads in order\n * (e.g. \"2026-06-05-auth-config-placements\"). Renaming an applied\n * migration re-runs it — never rename. */\n readonly name: string;\n readonly run: (client: SqliteDataMigrationClient) => Effect.Effect<void, DataMigrationError>;\n}\n\nconst LEDGER_TABLE = \"data_migration\";\n\nconst execute = (\n client: SqliteDataMigrationClient,\n stmt: string | { readonly sql: string; readonly args: readonly unknown[] },\n migration: string | null,\n) =>\n Effect.tryPromise({\n try: () => client.execute(stmt),\n catch: (cause) => new DataMigrationError({ migration, cause }),\n });\n\n/** Wrap a promise-shaped migration body as a registry entry. */\nexport const sqliteDataMigration = (\n name: string,\n run: (client: SqliteDataMigrationClient) => Promise<unknown>,\n): SqliteDataMigration => ({\n name,\n run: (client) =>\n Effect.tryPromise({\n try: () => run(client),\n catch: (cause) => new DataMigrationError({ migration: name, cause }),\n }).pipe(Effect.asVoid),\n});\n\n/**\n * Run every registry entry whose name has no stamp row, in registry order,\n * stamping each on success. Returns the applied names.\n *\n * Atomicity is the migration's own job (the existing migrations run their\n * rewrites inside BEGIN…COMMIT), so the runner does not wrap them — SQLite\n * has no nested transactions. The stamp is written after the migration\n * succeeds; a crash between the two re-runs the (idempotent) migration on\n * the next boot, which is a no-op. A failed migration leaves no stamp and\n * fails the boot.\n */\nexport const runSqliteDataMigrations = (\n client: SqliteDataMigrationClient,\n migrations: readonly SqliteDataMigration[],\n): Effect.Effect<readonly string[], DataMigrationError | DuplicateDataMigrationError> =>\n Effect.gen(function* () {\n const names = new Set<string>();\n for (const migration of migrations) {\n if (names.has(migration.name)) {\n return yield* new DuplicateDataMigrationError({ name: migration.name });\n }\n names.add(migration.name);\n }\n\n yield* execute(\n client,\n `CREATE TABLE IF NOT EXISTS ${LEDGER_TABLE} (name TEXT PRIMARY KEY, time_completed INTEGER NOT NULL)`,\n null,\n );\n const stamped = yield* execute(client, `SELECT name FROM ${LEDGER_TABLE}`, null);\n const completed = new Set(\n stamped.rows.map((row) => row.name).filter((name) => typeof name === \"string\"),\n );\n\n const applied: string[] = [];\n for (const migration of migrations) {\n if (completed.has(migration.name)) continue;\n yield* migration.run(client);\n yield* execute(\n client,\n {\n sql: `INSERT INTO ${LEDGER_TABLE} (name, time_completed) VALUES (?, ?)`,\n args: [migration.name, Date.now()],\n },\n migration.name,\n );\n applied.push(migration.name);\n }\n return applied;\n });\n","// ---------------------------------------------------------------------------\n// Data migration: move an oversized inline `integration.config` field into\n// the blob table. The shape both protocol plugins need is identical — only\n// the field names differ — so the body lives here and each plugin exports a\n// ledger entry that binds its constants (openapi: spec → specHash under\n// `spec/<hash>`; graphql: introspectionJson → introspectionHash under\n// `introspection/<hash>`).\n//\n// Blob rows are written with the EXACT naming `makeFumaBlobStore` +\n// `pluginBlobStore` read back at runtime: namespace `o:<tenant>/<pluginId>`\n// (the org partition — integration configs are catalog-level), key\n// `<prefix>/<sha256>`, id `JSON.stringify([namespace, key])`. That makes it\n// correct ONLY for hosts whose runtime blob backend is the FumaDB store\n// (local, selfhost) — a host that reads blobs elsewhere (the D1 host reads\n// R2) must not register it, or the rewritten pointers would dangle.\n//\n// Idempotent: pointer-shaped configs (no inline field) plan zero updates,\n// and blob writes are content-addressed upserts.\n// ---------------------------------------------------------------------------\n\nimport { Effect, Option, Schema } from \"effect\";\n\nimport { sha256Hex } from \"./blob\";\nimport { DataMigrationError, type SqliteDataMigrationClient } from \"./sqlite-data-migrations\";\n\nexport interface SqliteConfigBlobMigrationOptions {\n /** The ledger entry name, for error attribution. */\n readonly migrationName: string;\n /** Rows whose `plugin_id` equals this are candidates. */\n readonly pluginId: string;\n /** The config field holding the inline text to move (e.g. `spec`). */\n readonly inlineField: string;\n /** The config field that will carry the content hash (e.g. `specHash`). */\n readonly hashField: string;\n /** Blob key prefix; the key is `<prefix>/<sha256>` (e.g. `spec`). */\n readonly blobKeyPrefix: string;\n}\n\nconst decodeJsonOption = Schema.decodeUnknownOption(Schema.UnknownFromJsonString);\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n/**\n * Move every inline `options.inlineField` in this plugin's integration\n * configs into the blob table and rewrite the config to carry\n * `options.hashField`. Returns the number of rows rewritten. The\n * `integration` table may not exist yet on a fresh database — that counts\n * as nothing to migrate.\n */\nexport const runSqliteConfigBlobMigration = (\n client: SqliteDataMigrationClient,\n options: SqliteConfigBlobMigrationOptions,\n): Effect.Effect<number, DataMigrationError> =>\n Effect.gen(function* () {\n const execute = (stmt: string | { readonly sql: string; readonly args: readonly unknown[] }) =>\n Effect.tryPromise({\n try: () => client.execute(stmt),\n catch: (cause) => new DataMigrationError({ migration: options.migrationName, cause }),\n });\n\n const exists = yield* execute(\n \"SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'integration'\",\n );\n if (exists.rows.length === 0) return 0;\n\n const result = yield* execute({\n sql: \"SELECT row_id, tenant, config FROM integration WHERE plugin_id = ? AND config IS NOT NULL\",\n args: [options.pluginId],\n });\n\n interface PlannedMove {\n readonly rowId: string;\n readonly namespace: string;\n readonly key: string;\n readonly blobId: string;\n readonly inlineText: string;\n readonly nextConfig: string;\n }\n const moves: PlannedMove[] = [];\n for (const row of result.rows) {\n if (typeof row.row_id !== \"string\" || typeof row.tenant !== \"string\") continue;\n if (typeof row.config !== \"string\") continue;\n const decoded = decodeJsonOption(row.config);\n if (Option.isNone(decoded) || !isRecord(decoded.value)) continue;\n const inline = decoded.value[options.inlineField];\n if (typeof inline !== \"string\") continue;\n\n const hash = yield* sha256Hex(inline);\n const namespace = `o:${row.tenant}/${options.pluginId}`;\n const key = `${options.blobKeyPrefix}/${hash}`;\n const { [options.inlineField]: _removed, ...rest } = decoded.value;\n moves.push({\n rowId: row.row_id,\n namespace,\n key,\n blobId: JSON.stringify([namespace, key]),\n inlineText: inline,\n nextConfig: JSON.stringify({ ...rest, [options.hashField]: hash }),\n });\n }\n if (moves.length === 0) return 0;\n\n const applyAll = Effect.gen(function* () {\n for (const move of moves) {\n const existing = yield* execute({\n sql: \"SELECT row_id FROM blob WHERE id = ?\",\n args: [move.blobId],\n });\n if (existing.rows.length === 0) {\n yield* execute({\n sql: \"INSERT INTO blob (namespace, key, value, row_id, id) VALUES (?, ?, ?, ?, ?)\",\n args: [move.namespace, move.key, move.inlineText, crypto.randomUUID(), move.blobId],\n });\n } else {\n yield* execute({\n sql: \"UPDATE blob SET value = ? WHERE id = ?\",\n args: [move.inlineText, move.blobId],\n });\n }\n yield* execute({\n sql: \"UPDATE integration SET config = ? WHERE row_id = ?\",\n args: [move.nextConfig, move.rowId],\n });\n }\n yield* execute(\"COMMIT\");\n });\n\n yield* execute(\"BEGIN\");\n yield* applyAll.pipe(Effect.tapError(() => execute(\"ROLLBACK\").pipe(Effect.ignore)));\n return moves.length;\n });\n","import { ToolResult, type ToolError } from \"./tool-result\";\n\nexport type AuthToolFailureCode =\n | \"connection_value_missing\"\n | \"connection_rejected\"\n | \"oauth_connection_missing\"\n | \"oauth_refresh_failed\"\n | \"oauth_reauth_required\";\n\nexport type AuthToolFailureInput = {\n readonly code: AuthToolFailureCode;\n readonly message: string;\n readonly source?: {\n readonly id: string;\n readonly scope?: string;\n };\n readonly credential?: {\n readonly kind: \"secret\" | \"oauth\" | \"upstream\";\n readonly label?: string;\n readonly slotKey?: string;\n readonly secretId?: string;\n readonly connectionId?: string;\n };\n readonly status?: number;\n readonly upstream?: {\n readonly status?: number;\n readonly details?: unknown;\n };\n readonly recovery?: {\n readonly configureSourceTool?: string;\n };\n};\n\n// In v1.5 a connection IS the credential: there is no standalone secret to\n// \"bind\" to a source afterward. Manually-entered credentials are created via\n// the connection handoff (the user enters the value in the web UI, which\n// creates the bound connection in one step); OAuth credentials are minted by\n// the OAuth start flow. These strings are read by the agent resolving the\n// failure, so they must name tools that actually exist on the executor.\nconst authRecovery = (input?: AuthToolFailureInput[\"recovery\"]) => ({\n createConnectionTool: \"executor.coreTools.connections.createHandoff\",\n startOAuthTool: \"executor.coreTools.oauth.start\",\n listConnectionsTool: \"executor.coreTools.connections.list\",\n ...(input?.configureSourceTool ? { configureSourceTool: input.configureSourceTool } : {}),\n connectionInstructions:\n \"For API keys and tokens, call createConnectionTool for the integration to get a browser URL; the user enters the credential there, which creates the bound connection. Do not ask the user to paste secrets into chat. Then call listConnectionsTool to confirm the connection exists before retrying this tool.\",\n oauthInstructions:\n \"For OAuth credentials, call startOAuthTool and give the returned authorizationUrl to the user. The completed connection binds automatically, then retry the tool.\",\n});\n\nexport const authToolFailure = <T = never>(input: AuthToolFailureInput): ToolResult<T> => {\n const error: ToolError = {\n code: input.code,\n message: input.message,\n retryable: false,\n ...(input.status !== undefined ? { status: input.status } : {}),\n details: {\n category: \"authentication\",\n ...(input.source ? { source: input.source } : {}),\n ...(input.credential ? { credential: input.credential } : {}),\n ...(input.upstream ? { upstream: input.upstream } : {}),\n recovery: authRecovery(input.recovery),\n },\n };\n return ToolResult.fail(error);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAMA,SAAS,SAAS,UAAAA,SAAQ,OAAO,UAAAC,SAAQ,QAAAC,OAAM,UAAAC,eAAc;AAC7D;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP,SAAS,cAAc;AAGvB,SAAS,QAAQ,UAAoB,QAAY,aAAa;;;ACqF9D,IAAM,UAAU,MAAc,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC;AAE5D,IAAM,sBAAsB,CAAC,UAAuC;AACzE,MAAI,YAAY,UAAU,QAAQ,CAAC;AACnC,SAAO,MAAM,IAAI,SAAS,EAAG,aAAY,UAAU,QAAQ,CAAC;AAC5D,SAAO;AACT;AAEO,IAAM,qBAAqB,CAChC,UACA,aACiB;AACjB,QAAM,SAAc,SAAS,IAAI,CAAC,UAAa,KAAK;AACpD,QAAM,QAAQ,IAAI,IAAY,OAAO,IAAI,CAAC,UAAa,OAAO,MAAM,IAAI,CAAC,CAAC;AAC1E,aAAW,SAAS,UAAU;AAI5B,UAAM,UAAW,MAAsC;AACvD,UAAM,YAAY,OAAO,YAAY,WAAW,QAAQ,KAAK,IAAI;AACjE,UAAM,gBAAgB,OAAO,UAAU,CAAC,YAAe,OAAO,QAAQ,IAAI,MAAM,SAAS;AACzF,QAAI,UAAU,SAAS,KAAK,iBAAiB,GAAG;AAC9C,aAAO,aAAa,IAAI;AACxB;AAAA,IACF;AACA,UAAM,OACJ,UAAU,SAAS,KAAK,CAAC,MAAM,IAAI,SAAS,IAAI,YAAY,oBAAoB,KAAK;AACvF,UAAM,IAAI,IAAI;AACd,WAAO,KAAK,EAAE,GAAG,OAAO,KAAK,CAAM;AAAA,EACrC;AACA,SAAO;AACT;;;AClIA,SAAS,cAAc;AAEhB,IAAM,kBAAkB,OAAO,OAAO;AAAA,EAC3C,MAAM,OAAO;AAAA,EACb,SAAS,OAAO;AAAA,EAChB,QAAQ,OAAO,SAAS,OAAO,MAAM;AAAA,EACrC,SAAS,OAAO,SAAS,OAAO,OAAO;AAAA,EACvC,WAAW,OAAO,SAAS,OAAO,OAAO;AAC3C,CAAC;AAIM,IAAM,qBAAqB,OAAO,OAAO;AAAA,EAC9C,QAAQ,OAAO;AAAA,EACf,SAAS,OAAO,OAAO,OAAO,QAAQ,OAAO,MAAM;AACrD,CAAC;AAcM,IAAM,aAAa;AAAA,EACxB,IAAI,CAAI,MAAS,UAA4D;AAAA,IAC3E,IAAI;AAAA,IACJ;AAAA,IACA,GAAI,MAAM,OAAO,EAAE,MAAM,KAAK,KAAK,IAAI,CAAC;AAAA,EAC1C;AAAA,EACA,MAAM,CAAY,WAAqC,EAAE,IAAI,OAAO,MAAM;AAC5E;AAEA,IAAM,mBAAmB,OAAO,MAAM;AAAA,EACpC,OAAO,OAAO;AAAA,IACZ,IAAI,OAAO,QAAQ,IAAI;AAAA,IACvB,MAAM,OAAO;AAAA,IACb,MAAM,OAAO,SAAS,kBAAkB;AAAA,EAC1C,CAAC;AAAA,EACD,OAAO,OAAO,EAAE,IAAI,OAAO,QAAQ,KAAK,GAAG,OAAO,gBAAgB,CAAC;AACrE,CAAC;AAED,IAAM,sBAAsB,OAAO,GAAG,gBAAgB;AAE/C,IAAM,eAAe,CAAC,UAC3B,oBAAoB,KAAK;;;AClC3B,SAAS,MAAM,cAAc;AAUtB,IAAM,qBAAN,cAAiC,KAAK,YAAY,oBAAoB,EAI1E;AAAC;AAEG,IAAM,8BAAN,cAA0C,KAAK,YAAY,6BAA6B,EAE5F;AAAC;AAUJ,IAAM,eAAe;AAErB,IAAM,UAAU,CACd,QACA,MACA,cAEA,OAAO,WAAW;AAAA,EAChB,KAAK,MAAM,OAAO,QAAQ,IAAI;AAAA,EAC9B,OAAO,CAAC,UAAU,IAAI,mBAAmB,EAAE,WAAW,MAAM,CAAC;AAC/D,CAAC;AAGI,IAAM,sBAAsB,CACjC,MACA,SACyB;AAAA,EACzB;AAAA,EACA,KAAK,CAAC,WACJ,OAAO,WAAW;AAAA,IAChB,KAAK,MAAM,IAAI,MAAM;AAAA,IACrB,OAAO,CAAC,UAAU,IAAI,mBAAmB,EAAE,WAAW,MAAM,MAAM,CAAC;AAAA,EACrE,CAAC,EAAE,KAAK,OAAO,MAAM;AACzB;AAaO,IAAM,0BAA0B,CACrC,QACA,eAEA,OAAO,IAAI,aAAa;AACtB,QAAM,QAAQ,oBAAI,IAAY;AAC9B,aAAW,aAAa,YAAY;AAClC,QAAI,MAAM,IAAI,UAAU,IAAI,GAAG;AAC7B,aAAO,OAAO,IAAI,4BAA4B,EAAE,MAAM,UAAU,KAAK,CAAC;AAAA,IACxE;AACA,UAAM,IAAI,UAAU,IAAI;AAAA,EAC1B;AAEA,SAAO;AAAA,IACL;AAAA,IACA,8BAA8B,YAAY;AAAA,IAC1C;AAAA,EACF;AACA,QAAM,UAAU,OAAO,QAAQ,QAAQ,oBAAoB,YAAY,IAAI,IAAI;AAC/E,QAAM,YAAY,IAAI;AAAA,IACpB,QAAQ,KAAK,IAAI,CAAC,QAAQ,IAAI,IAAI,EAAE,OAAO,CAAC,SAAS,OAAO,SAAS,QAAQ;AAAA,EAC/E;AAEA,QAAM,UAAoB,CAAC;AAC3B,aAAW,aAAa,YAAY;AAClC,QAAI,UAAU,IAAI,UAAU,IAAI,EAAG;AACnC,WAAO,UAAU,IAAI,MAAM;AAC3B,WAAO;AAAA,MACL;AAAA,MACA;AAAA,QACE,KAAK,eAAe,YAAY;AAAA,QAChC,MAAM,CAAC,UAAU,MAAM,KAAK,IAAI,CAAC;AAAA,MACnC;AAAA,MACA,UAAU;AAAA,IACZ;AACA,YAAQ,KAAK,UAAU,IAAI;AAAA,EAC7B;AACA,SAAO;AACT,CAAC;;;ACzGH,SAAS,UAAAC,SAAQ,QAAQ,UAAAC,eAAc;AAkBvC,IAAM,mBAAmBC,QAAO,oBAAoBA,QAAO,qBAAqB;AAEhF,IAAM,WAAW,CAAC,UAChB,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAS9D,IAAM,+BAA+B,CAC1C,QACA,YAEAC,QAAO,IAAI,aAAa;AACtB,QAAMC,WAAU,CAAC,SACfD,QAAO,WAAW;AAAA,IAChB,KAAK,MAAM,OAAO,QAAQ,IAAI;AAAA,IAC9B,OAAO,CAAC,UAAU,IAAI,mBAAmB,EAAE,WAAW,QAAQ,eAAe,MAAM,CAAC;AAAA,EACtF,CAAC;AAEH,QAAM,SAAS,OAAOC;AAAA,IACpB;AAAA,EACF;AACA,MAAI,OAAO,KAAK,WAAW,EAAG,QAAO;AAErC,QAAM,SAAS,OAAOA,SAAQ;AAAA,IAC5B,KAAK;AAAA,IACL,MAAM,CAAC,QAAQ,QAAQ;AAAA,EACzB,CAAC;AAUD,QAAM,QAAuB,CAAC;AAC9B,aAAW,OAAO,OAAO,MAAM;AAC7B,QAAI,OAAO,IAAI,WAAW,YAAY,OAAO,IAAI,WAAW,SAAU;AACtE,QAAI,OAAO,IAAI,WAAW,SAAU;AACpC,UAAM,UAAU,iBAAiB,IAAI,MAAM;AAC3C,QAAI,OAAO,OAAO,OAAO,KAAK,CAAC,SAAS,QAAQ,KAAK,EAAG;AACxD,UAAM,SAAS,QAAQ,MAAM,QAAQ,WAAW;AAChD,QAAI,OAAO,WAAW,SAAU;AAEhC,UAAM,OAAO,OAAO,UAAU,MAAM;AACpC,UAAM,YAAY,KAAK,IAAI,MAAM,IAAI,QAAQ,QAAQ;AACrD,UAAM,MAAM,GAAG,QAAQ,aAAa,IAAI,IAAI;AAC5C,UAAM,EAAE,CAAC,QAAQ,WAAW,GAAG,UAAU,GAAG,KAAK,IAAI,QAAQ;AAC7D,UAAM,KAAK;AAAA,MACT,OAAO,IAAI;AAAA,MACX;AAAA,MACA;AAAA,MACA,QAAQ,KAAK,UAAU,CAAC,WAAW,GAAG,CAAC;AAAA,MACvC,YAAY;AAAA,MACZ,YAAY,KAAK,UAAU,EAAE,GAAG,MAAM,CAAC,QAAQ,SAAS,GAAG,KAAK,CAAC;AAAA,IACnE,CAAC;AAAA,EACH;AACA,MAAI,MAAM,WAAW,EAAG,QAAO;AAE/B,QAAM,WAAWD,QAAO,IAAI,aAAa;AACvC,eAAW,QAAQ,OAAO;AACxB,YAAM,WAAW,OAAOC,SAAQ;AAAA,QAC9B,KAAK;AAAA,QACL,MAAM,CAAC,KAAK,MAAM;AAAA,MACpB,CAAC;AACD,UAAI,SAAS,KAAK,WAAW,GAAG;AAC9B,eAAOA,SAAQ;AAAA,UACb,KAAK;AAAA,UACL,MAAM,CAAC,KAAK,WAAW,KAAK,KAAK,KAAK,YAAY,OAAO,WAAW,GAAG,KAAK,MAAM;AAAA,QACpF,CAAC;AAAA,MACH,OAAO;AACL,eAAOA,SAAQ;AAAA,UACb,KAAK;AAAA,UACL,MAAM,CAAC,KAAK,YAAY,KAAK,MAAM;AAAA,QACrC,CAAC;AAAA,MACH;AACA,aAAOA,SAAQ;AAAA,QACb,KAAK;AAAA,QACL,MAAM,CAAC,KAAK,YAAY,KAAK,KAAK;AAAA,MACpC,CAAC;AAAA,IACH;AACA,WAAOA,SAAQ,QAAQ;AAAA,EACzB,CAAC;AAED,SAAOA,SAAQ,OAAO;AACtB,SAAO,SAAS,KAAKD,QAAO,SAAS,MAAMC,SAAQ,UAAU,EAAE,KAAKD,QAAO,MAAM,CAAC,CAAC;AACnF,SAAO,MAAM;AACf,CAAC;;;AC5FH,IAAM,eAAe,CAAC,WAA8C;AAAA,EAClE,sBAAsB;AAAA,EACtB,gBAAgB;AAAA,EAChB,qBAAqB;AAAA,EACrB,GAAI,OAAO,sBAAsB,EAAE,qBAAqB,MAAM,oBAAoB,IAAI,CAAC;AAAA,EACvF,wBACE;AAAA,EACF,mBACE;AACJ;AAEO,IAAM,kBAAkB,CAAY,UAA+C;AACxF,QAAM,QAAmB;AAAA,IACvB,MAAM,MAAM;AAAA,IACZ,SAAS,MAAM;AAAA,IACf,WAAW;AAAA,IACX,GAAI,MAAM,WAAW,SAAY,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,IAC7D,SAAS;AAAA,MACP,UAAU;AAAA,MACV,GAAI,MAAM,SAAS,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,MAC/C,GAAI,MAAM,aAAa,EAAE,YAAY,MAAM,WAAW,IAAI,CAAC;AAAA,MAC3D,GAAI,MAAM,WAAW,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;AAAA,MACrD,UAAU,aAAa,MAAM,QAAQ;AAAA,IACvC;AAAA,EACF;AACA,SAAO,WAAW,KAAK,KAAK;AAC9B;","names":["Effect","Schema","Data","Option","Effect","Schema","Schema","Effect","execute"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/integration.ts","../src/sqlite-data-migrations.ts","../src/sqlite-config-blob-migration.ts","../src/auth-tool-failure.ts"],"sourcesContent":["// ---------------------------------------------------------------------------\n// @executor-js/sdk — public surface (v2)\n// ---------------------------------------------------------------------------\n\n// Re-export the Effect/Schema/HttpApi primitives plugin authors need so a\n// plugin can be written importing only from `@executor-js/sdk`.\nexport { Context, Effect, Layer, Schema, Data, Option } from \"effect\";\nexport {\n HttpApi,\n HttpApiBuilder,\n HttpApiClient,\n HttpApiEndpoint,\n HttpApiGroup,\n HttpApiMiddleware,\n HttpApiSchema,\n} from \"effect/unstable/httpapi\";\n\n// FumaDB integration.\nexport { fumadb } from \"@executor-js/fumadb\";\nexport type { FumaDB } from \"@executor-js/fumadb\";\nexport type { AbstractQuery, Condition, ConditionBuilder } from \"@executor-js/fumadb/query\";\nexport { column, idColumn, schema as fumaSchema, table } from \"@executor-js/fumadb/schema\";\nexport type {\n AnyColumn,\n AnySchema,\n AnyTable,\n Column,\n Schema as FumaSchema,\n} from \"@executor-js/fumadb/schema\";\n\nexport type {\n FumaDb,\n FumaQuery,\n FumaRow,\n FumaTables,\n IFumaClient,\n StorageFailure,\n} from \"./fuma-runtime\";\nexport { StorageError, UniqueViolationError, isStorageFailure } from \"./fuma-runtime\";\n\n// IDs (branded) — the v2 set.\nexport {\n IntegrationSlug,\n AuthTemplateSlug,\n ConnectionName,\n OAuthClientSlug,\n OAuthState,\n ProviderKey,\n ProviderItemId,\n ConnectionAddress,\n ToolAddress,\n ToolName,\n ElicitationId,\n PolicyId,\n Tenant,\n Subject,\n Owner,\n} from \"./ids\";\nexport { connectionIdentifier, isConnectionIdentifier } from \"./connection-name-identifier\";\n\n// Errors (tagged) — the ExecuteError set + integration lifecycle.\nexport {\n ToolNotFoundError,\n ToolInvocationError,\n ToolBlockedError,\n NoHandlerError,\n PluginNotLoadedError,\n IntegrationNotFoundError,\n IntegrationAlreadyExistsError,\n IntegrationRemovalNotAllowedError,\n ConnectionNotFoundError,\n CredentialProviderNotRegisteredError,\n CredentialResolutionError,\n type ExecuteError,\n type ExecutorError,\n} from \"./errors\";\n\n// Integration / connection / tool domain contracts.\nexport type {\n AuthMethodDescriptor,\n AuthMethodOAuthDescriptor,\n AuthPlacementDescriptor,\n Integration,\n IntegrationConfig,\n IntegrationDisplayDescriptor,\n RegisterIntegrationInput,\n} from \"./integration\";\nexport { freshCustomAuthSlug, mergeAuthTemplates } from \"./integration\";\nexport type {\n Connection,\n ConnectionRef,\n ConnectionValueInput,\n CreateConnectionInput,\n UpdateConnectionInput,\n} from \"./connection\";\nexport type { Tool, ToolDef, ToolListFilter, ToolAnnotations } from \"./tool\";\n\n// Credential providers.\nexport type { CredentialProvider, ProviderEntry } from \"./provider\";\n\n// Public projections / detection.\nexport { ToolSchemaView, IntegrationDetectionResult } from \"./types\";\n\n// Core schema.\nexport {\n bigintColumn,\n boolColumn,\n coreSchema,\n coreTables,\n dateColumn,\n isToolPolicyAction,\n jsonColumn,\n keyColumn,\n nullableBigintColumn,\n nullableJsonColumn,\n nullableKeyColumn,\n nullableTextColumn,\n textColumn,\n TOOL_POLICY_ACTIONS,\n type CoreSchema,\n type IntegrationRow,\n type ConnectionRow,\n type OAuthClientRow,\n type OAuthSessionRow,\n type ToolRow,\n type ToolInvocationRow,\n type DefinitionRow,\n type ToolPolicyRow,\n type PluginStorageRow,\n type BlobRow,\n type ToolPolicyAction,\n} from \"./core-schema\";\n\n// Owner policy.\nexport {\n ORG_SUBJECT,\n executorOwnerPolicyName,\n executorUnscopedPolicyName,\n type ExecutorOwnerPolicyContext,\n} from \"./owner-policy\";\n\n// Tool policies.\nexport {\n matchPattern,\n isValidPattern,\n effectivePolicyFromSorted,\n ToolPolicyActionSchema,\n type ToolPolicy,\n type CreateToolPolicyInput,\n type UpdateToolPolicyInput,\n type RemoveToolPolicyInput,\n type PolicyMatch,\n type EffectivePolicy,\n type PolicySource,\n} from \"./policies\";\n\n// Elicitation.\nexport {\n FormElicitation,\n UrlElicitation,\n ElicitationAction,\n ElicitationResponse,\n ElicitationDeclinedError,\n type ElicitationRequest,\n type ElicitationHandler,\n type ElicitationContext,\n type OnElicitation,\n type InvokeOptions,\n} from \"./elicitation\";\n\n// Blob store — the plugin-facing contract (`BlobStore`/`PluginBlobStore`)\n// plus the platform-neutral backends (`makeFumaBlobStore` default,\n// `makeInMemoryBlobStore` for tests). Platform-specific backends live with\n// their host (R2: `@executor-js/cloudflare/blob-store`).\nexport {\n pluginBlobStore,\n makeInMemoryBlobStore,\n makeFumaBlobStore,\n sha256Hex,\n type BlobStore,\n type PluginBlobStore,\n type OwnerPartitions,\n} from \"./blob\";\n\n// Plugin storage.\nexport {\n definePluginStorageCollection,\n pluginStorageId,\n type PluginStorageCollectionDefinition,\n type PluginStorageCollectionFacade,\n type PluginStorageCollectionIndexedField,\n type PluginStorageCollectionKeyInput,\n type PluginStorageCollectionListInput,\n type PluginStorageCollectionOrderBy,\n type PluginStorageCollectionPutInput,\n type PluginStorageCollectionQueryInput,\n type PluginStorageCollectionScopedKeyInput,\n type PluginStorageCollectionWhere,\n type PluginStorageConfig,\n type PluginStorageEntry,\n type PluginStorageFacade,\n type PluginStorageIndexField,\n type PluginStorageIndexSpec,\n type PluginStorageKeyInput,\n type PluginStorageListInput,\n type PluginStoragePutInput,\n type PluginStorageRuntimeCollectionDefinition,\n type PluginStorageRuntimeIndexSpec,\n type PluginStorageSchema,\n type PluginStorageSchemaType,\n type PluginStorageScopedKeyInput,\n type PluginStorageWhereFilter,\n type PluginStorageWhereValue,\n} from \"./plugin-storage\";\n\n// OAuth (v2 contracts).\nexport { OAUTH2_PROVIDER_KEY, OAUTH2_SESSION_TTL_MS } from \"./oauth\";\nexport {\n OAuthStartError,\n OAuthCompleteError,\n OAuthProbeError,\n OAuthRegisterDynamicError,\n OAuthSessionNotFoundError,\n type OAuthGrant,\n type OAuthAuthentication,\n type OAuthClient,\n type OAuthClientSummary,\n type CreateOAuthClientInput,\n type RegisterDynamicClientInput,\n type ConnectResult,\n type OAuthStartInput,\n type OAuthCompleteInput,\n type OAuthProbeInput,\n type OAuthProbeResult,\n type OAuthService,\n} from \"./oauth-client\";\n\n// NOTE: the OAuth 2.1 implementation helpers (`./oauth-helpers`,\n// `makeOAuthService` in `./oauth-service`, discovery in `./oauth-discovery`)\n// are SDK-internal — consumed only by `createExecutor`. The hosted HTTP client\n// builder is host-internal and reachable via `@executor-js/sdk/host-internal`.\n\nexport {\n DEFAULT_EXECUTOR_SERVER_ORIGIN,\n DEFAULT_EXECUTOR_SERVER_USERNAME,\n apiBaseUrlForServerOrigin,\n getExecutorServerAuthorizationHeader,\n normalizeExecutorServerConnection,\n normalizeExecutorServerOrigin,\n originFromApiBaseUrl,\n type ExecutorServerAuth,\n type ExecutorServerConnection,\n type ExecutorServerConnectionInput,\n type ExecutorServerConnectionKind,\n} from \"./server-connection\";\n\nexport {\n OAUTH_POPUP_MESSAGE_TYPE,\n type OAuthPopupResult,\n isOAuthPopupResult,\n} from \"./oauth-popup-types\";\n\n// Plugin definition.\nexport {\n type Plugin,\n type PluginSpec,\n type PluginCtx,\n type PluginExtensions,\n type ConfiguredPlugin,\n type AnyPlugin,\n type StorageDeps,\n type OwnerBinding,\n type IntegrationRecord,\n type StaticSourceDecl,\n type StaticToolDecl,\n type StaticToolSchema,\n type StaticToolExecuteContext,\n type StaticToolHandlerInput,\n type StaticToolInput,\n type ConfigureIntegrationHandlerInput,\n type InvokeToolInput,\n type ConnectionLifecycleInput,\n type IntegrationConfigureDecl,\n type IntegrationConfigureSchema,\n type IntegrationPreset,\n type IntegrationPresetCatalogEntry,\n type ResolveToolsInput,\n type ResolveToolsResult,\n type ToolInvocationCredential,\n type Elicit,\n definePlugin,\n tool,\n} from \"./plugin\";\n\n// Executor.\n//\n// `collectTables` is host/tooling-only (cli schema cmd, kernel worker,\n// local/cloud DB bring-up). Its definition stays here because `createExecutor`\n// uses it; the host surface (`@executor-js/api/server`) re-exports it.\nexport {\n type Executor,\n type ExecutorConfig,\n type ExecutorDb,\n type ExecutorDbFactory,\n type ExecutorDbInput,\n type ParsedToolAddress,\n createExecutor,\n collectTables,\n parseToolAddress,\n connectionAddress,\n toolAddress,\n} from \"./executor\";\n\n// CLI / runtime config.\nexport {\n defineExecutorConfig,\n type ExecutorCliConfig,\n type ExecutorPluginsFactory,\n} from \"./config\";\n\n// The one TS-preview generator plugins assert against.\nexport { buildToolTypeScriptPreview } from \"./schema-types\";\n\n// Wire-level HTTP error schemas usable by plugin HttpApiGroup definitions.\nexport { InternalError } from \"./api-errors\";\n\n// ToolResult — typed value-based discriminated union for tool outcomes.\nexport {\n ToolResult,\n annotateToolResultOutcome,\n isToolResult,\n type ToolError,\n type ToolHttpMeta,\n} from \"./tool-result\";\n\n// Stamped boot-time data-migration ledger for the libSQL-backed apps.\nexport {\n DataMigrationError,\n DuplicateDataMigrationError,\n runSqliteDataMigrations,\n sqliteDataMigration,\n type SqliteDataMigration,\n type SqliteDataMigrationClient,\n} from \"./sqlite-data-migrations\";\n// Shared inline-config-field → blob-table migration body; the protocol\n// plugins bind their field names and export the ledger entries.\nexport {\n runSqliteConfigBlobMigration,\n type SqliteConfigBlobMigrationOptions,\n} from \"./sqlite-config-blob-migration\";\nexport {\n authToolFailure,\n type AuthToolFailureCode,\n type AuthToolFailureInput,\n} from \"./auth-tool-failure\";\n","import type { IntegrationSlug } from \"./ids\";\n\n/* Core knows only an integration's catalog identity — slug + description + which\n * plugin (`kind`) owns it. The type-specific shape (openapi auth templates + spec,\n * an mcp url, …) lives in the plugin and is stored as an opaque `config` blob core\n * never parses. An integration is one API surface; multi-API providers (Google)\n * are bundled into a single integration by their plugin, so one credential covers\n * the whole provider. */\n\n// ---------------------------------------------------------------------------\n// Declared auth methods — a plugin-agnostic projection of an integration's\n// stored `config` into the catalog response. Each plugin derives these from its\n// own opaque config (`describeAuthMethods`); core never parses config itself.\n// The client renders these as the integration's selectable auth methods, so the\n// catalog is authoritative even when the integration has zero connections.\n//\n// This is a DERIVED projection — there is no DB column. A plugin that declares\n// no projector contributes `[]`, and the client falls through to its existing\n// connection-inference behavior (no regression).\n// ---------------------------------------------------------------------------\n\nexport interface IntegrationDisplayDescriptor {\n /** Non-secret URL suitable for display metadata such as favicons. */\n readonly url?: string;\n}\n\n/** Where a credential value is carried on the outbound request. Mirrors the\n * client's `Placement`. */\nexport interface AuthPlacementDescriptor {\n readonly carrier: \"header\" | \"query\";\n readonly name: string;\n /** Literal prepended to the value (e.g. `\"Bearer \"`). Empty when bare. */\n readonly prefix: string;\n /** The input variable this placement renders from. `token` for single-input\n * methods; a distinct name per input for multi-input ones (e.g. Datadog).\n * Absent → treated as `token`. */\n readonly variable?: string;\n /** Set when the placement renders this exact value instead of a credential\n * (a static header/param the method carries). Such placements reference no\n * input variable. */\n readonly literal?: string;\n}\n\n/** OAuth specifics for an `oauth` auth method. For probe-at-connect providers\n * (MCP) only `discoveryUrl` + `supportsDynamicRegistration` are known up front;\n * the authorize/token endpoints are discovered live at connect time. For\n * providers that store endpoints (OpenAPI) the resolved URLs are carried. */\nexport interface AuthMethodOAuthDescriptor {\n /** For probe-at-connect providers (MCP): the endpoint to discover metadata\n * from (RFC 9728 PRM → RFC 8414 AS metadata). */\n readonly discoveryUrl?: string;\n readonly authorizationUrl?: string;\n readonly tokenUrl?: string;\n readonly scopes?: readonly string[];\n readonly registrationEndpoint?: string;\n /** True when the integration is known to support RFC 7591 dynamic client\n * registration (drives the transparent auto-register connect flow). */\n readonly supportsDynamicRegistration?: boolean;\n}\n\n/** A single declared auth method on an integration's catalog response. */\nexport interface AuthMethodDescriptor {\n /** Stable id within the integration (e.g. the auth template slug). */\n readonly id: string;\n readonly label: string;\n readonly kind: \"oauth\" | \"apikey\" | \"header\" | \"none\";\n /** The auth-template slug a connection binds against. */\n readonly template: string;\n readonly placements?: readonly AuthPlacementDescriptor[];\n readonly oauth?: AuthMethodOAuthDescriptor;\n}\n\n/** Public projection of an integration — what `integrations.list/get` return.\n * Carries no credentials and no plugin-internal config. */\nexport interface Integration {\n readonly slug: IntegrationSlug;\n /** Display name. Pre-split rows stored the name in `description`; readers\n * fall back, so this is always populated. */\n readonly name: string;\n /** Agent-visible context (\"what this API is and when to reach for it\").\n * Distinct from the display name; may equal it on legacy rows. */\n readonly description: string;\n /** The plugin that owns this integration kind (e.g. \"openapi\", \"mcp\"). */\n readonly kind: string;\n /** Whether the user can remove this integration from the catalog. `false`\n * for static / built-in integrations declared by a plugin at startup. */\n readonly canRemove: boolean;\n /** Whether the owning plugin supports re-resolving a connection's tools\n * (`connections.refresh`). */\n readonly canRefresh: boolean;\n /** Declared auth methods derived from the owning plugin's stored config (a\n * derived projection, not a DB column). Always present, possibly empty. */\n readonly authMethods: readonly AuthMethodDescriptor[];\n /** Non-secret display URL derived by the owning plugin from opaque config.\n * Used for catalog favicons; never includes credentials or plugin config. */\n readonly displayUrl?: string;\n}\n\n/** Plugin-owned, opaque-to-core configuration stored on the integration row. The\n * owning plugin writes it at register time and reads it back at execute time to\n * render auth / produce tools. Core treats it as an opaque JSON blob. */\nexport type IntegrationConfig = unknown;\n\n// ---------------------------------------------------------------------------\n// Auth-template merge — shared by every plugin whose config carries a slugged\n// `authenticationTemplate` array (openapi, graphql, mcp). The custom-method\n// flow merge-appends: an incoming entry with a matching slug replaces the\n// existing entry in place; entries lacking a slug (or colliding with another\n// entry added in the same call) get a fresh `custom_<id>` slug.\n// ---------------------------------------------------------------------------\n\nconst shortId = (): string => Math.random().toString(36).slice(2, 8);\n\nexport const freshCustomAuthSlug = (taken: ReadonlySet<string>): string => {\n let candidate = `custom_${shortId()}`;\n while (taken.has(candidate)) candidate = `custom_${shortId()}`;\n return candidate;\n};\n\nexport const mergeAuthTemplates = <T extends { readonly slug: string }>(\n existing: readonly T[],\n incoming: readonly T[],\n): readonly T[] => {\n const result: T[] = existing.map((entry: T) => entry);\n const taken = new Set<string>(result.map((entry: T) => String(entry.slug)));\n for (const entry of incoming) {\n // `slug` may be branded-required in the plugin's schema, but JSON callers\n // can submit it empty/blank — read defensively and backfill so every\n // stored template has a stable slug.\n const rawSlug = (entry as { readonly slug?: unknown }).slug;\n const requested = typeof rawSlug === \"string\" ? rawSlug.trim() : \"\";\n const existingIndex = result.findIndex((current: T) => String(current.slug) === requested);\n if (requested.length > 0 && existingIndex >= 0) {\n result[existingIndex] = entry;\n continue;\n }\n const slug =\n requested.length > 0 && !taken.has(requested) ? requested : freshCustomAuthSlug(taken);\n taken.add(slug);\n result.push({ ...entry, slug } as T);\n }\n return result;\n};\n\n/** What a plugin's extension method passes to `ctx.core.integrations.register`.\n * The v2 analog of v1's `SourceInput`, minus the per-source tool list (tools are\n * produced per-connection now). */\nexport interface RegisterIntegrationInput {\n readonly slug: IntegrationSlug;\n /** Display name. Falls back to `description` then the slug when omitted\n * (legacy callers registered with description-as-name). */\n readonly name?: string;\n readonly description: string;\n /** Opaque plugin config (auth templates, spec ref, mcp url, …). */\n readonly config: IntegrationConfig;\n readonly canRemove?: boolean;\n readonly canRefresh?: boolean;\n}\n","// ---------------------------------------------------------------------------\n// Stamped data-migration ledger for the libSQL-backed apps (local boot,\n// selfhost boot). Cloud runs schema + data migrations through its drizzle\n// chain out-of-band; the local apps have no operator, so their migrations\n// run at boot — and before this ledger existed, each one re-scanned its\n// tables on every startup to decide \"did I already run?\" by data shape.\n// That accumulates (N migrations = N full-table scans per boot, forever)\n// and makes idempotence a per-migration proof obligation.\n//\n// This is the rail instead: a `data_migration` table (name → completion\n// time), an ordered registry the app composes, and a runner that executes\n// each pending migration once and stamps it. Stamped names are skipped\n// without touching the data.\n//\n// Write migrations idempotently anyway (defense in depth — the support\n// remedy for a half-applied state is deleting the stamp row and\n// rebooting). One deliberate semantics change from the scan-every-boot\n// era: after a migration is stamped, rows written later by an OLDER binary\n// (downgrade, then re-upgrade) are NOT re-healed. That matches the cloud\n// chain's semantics; the stamp row, not the data shape, is the source of\n// truth.\n// ---------------------------------------------------------------------------\n\nimport { Data, Effect } from \"effect\";\n\n/** Structural client interface so this module stays dependency-free;\n * `@libsql/client` satisfies it. */\nexport interface SqliteDataMigrationClient {\n execute(\n stmt: string | { readonly sql: string; readonly args: readonly unknown[] },\n ): Promise<{ readonly rows: readonly Record<string, unknown>[] }>;\n}\n\nexport class DataMigrationError extends Data.TaggedError(\"DataMigrationError\")<{\n /** The migration that failed, or null when the ledger itself did. */\n readonly migration: string | null;\n readonly cause: unknown;\n}> {}\n\nexport class DuplicateDataMigrationError extends Data.TaggedError(\"DuplicateDataMigrationError\")<{\n readonly name: string;\n}> {}\n\nexport interface SqliteDataMigration {\n /** Stable unique id, date-prefixed so the registry reads in order\n * (e.g. \"2026-06-05-auth-config-placements\"). Renaming an applied\n * migration re-runs it — never rename. */\n readonly name: string;\n readonly run: (client: SqliteDataMigrationClient) => Effect.Effect<void, DataMigrationError>;\n}\n\nconst LEDGER_TABLE = \"data_migration\";\n\nconst execute = (\n client: SqliteDataMigrationClient,\n stmt: string | { readonly sql: string; readonly args: readonly unknown[] },\n migration: string | null,\n) =>\n Effect.tryPromise({\n try: () => client.execute(stmt),\n catch: (cause) => new DataMigrationError({ migration, cause }),\n });\n\n/** Wrap a promise-shaped migration body as a registry entry. */\nexport const sqliteDataMigration = (\n name: string,\n run: (client: SqliteDataMigrationClient) => Promise<unknown>,\n): SqliteDataMigration => ({\n name,\n run: (client) =>\n Effect.tryPromise({\n try: () => run(client),\n catch: (cause) => new DataMigrationError({ migration: name, cause }),\n }).pipe(Effect.asVoid),\n});\n\n/**\n * Run every registry entry whose name has no stamp row, in registry order,\n * stamping each on success. Returns the applied names.\n *\n * Atomicity is the migration's own job (the existing migrations run their\n * rewrites inside BEGIN…COMMIT), so the runner does not wrap them — SQLite\n * has no nested transactions. The stamp is written after the migration\n * succeeds; a crash between the two re-runs the (idempotent) migration on\n * the next boot, which is a no-op. A failed migration leaves no stamp and\n * fails the boot.\n */\nexport const runSqliteDataMigrations = (\n client: SqliteDataMigrationClient,\n migrations: readonly SqliteDataMigration[],\n): Effect.Effect<readonly string[], DataMigrationError | DuplicateDataMigrationError> =>\n Effect.gen(function* () {\n const names = new Set<string>();\n for (const migration of migrations) {\n if (names.has(migration.name)) {\n return yield* new DuplicateDataMigrationError({ name: migration.name });\n }\n names.add(migration.name);\n }\n\n yield* execute(\n client,\n `CREATE TABLE IF NOT EXISTS ${LEDGER_TABLE} (name TEXT PRIMARY KEY, time_completed INTEGER NOT NULL)`,\n null,\n );\n const stamped = yield* execute(client, `SELECT name FROM ${LEDGER_TABLE}`, null);\n const completed = new Set(\n stamped.rows.map((row) => row.name).filter((name) => typeof name === \"string\"),\n );\n\n const applied: string[] = [];\n for (const migration of migrations) {\n if (completed.has(migration.name)) continue;\n yield* migration.run(client);\n yield* execute(\n client,\n {\n sql: `INSERT INTO ${LEDGER_TABLE} (name, time_completed) VALUES (?, ?)`,\n args: [migration.name, Date.now()],\n },\n migration.name,\n );\n applied.push(migration.name);\n }\n return applied;\n });\n","// ---------------------------------------------------------------------------\n// Data migration: move an oversized inline `integration.config` field into\n// the blob table. The shape both protocol plugins need is identical — only\n// the field names differ — so the body lives here and each plugin exports a\n// ledger entry that binds its constants (openapi: spec → specHash under\n// `spec/<hash>`; graphql: introspectionJson → introspectionHash under\n// `introspection/<hash>`).\n//\n// Blob rows are written with the EXACT naming `makeFumaBlobStore` +\n// `pluginBlobStore` read back at runtime: namespace `o:<tenant>/<pluginId>`\n// (the org partition — integration configs are catalog-level), key\n// `<prefix>/<sha256>`, id `JSON.stringify([namespace, key])`. That makes it\n// correct ONLY for hosts whose runtime blob backend is the FumaDB store\n// (local, selfhost) — a host that reads blobs elsewhere (the D1 host reads\n// R2) must not register it, or the rewritten pointers would dangle.\n//\n// Idempotent: pointer-shaped configs (no inline field) plan zero updates,\n// and blob writes are content-addressed upserts.\n// ---------------------------------------------------------------------------\n\nimport { Effect, Option, Schema } from \"effect\";\n\nimport { sha256Hex } from \"./blob\";\nimport { DataMigrationError, type SqliteDataMigrationClient } from \"./sqlite-data-migrations\";\n\nexport interface SqliteConfigBlobMigrationOptions {\n /** The ledger entry name, for error attribution. */\n readonly migrationName: string;\n /** Rows whose `plugin_id` equals this are candidates. */\n readonly pluginId: string;\n /** The config field holding the inline text to move (e.g. `spec`). */\n readonly inlineField: string;\n /** The config field that will carry the content hash (e.g. `specHash`). */\n readonly hashField: string;\n /** Blob key prefix; the key is `<prefix>/<sha256>` (e.g. `spec`). */\n readonly blobKeyPrefix: string;\n}\n\nconst decodeJsonOption = Schema.decodeUnknownOption(Schema.UnknownFromJsonString);\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n/**\n * Move every inline `options.inlineField` in this plugin's integration\n * configs into the blob table and rewrite the config to carry\n * `options.hashField`. Returns the number of rows rewritten. The\n * `integration` table may not exist yet on a fresh database — that counts\n * as nothing to migrate.\n */\nexport const runSqliteConfigBlobMigration = (\n client: SqliteDataMigrationClient,\n options: SqliteConfigBlobMigrationOptions,\n): Effect.Effect<number, DataMigrationError> =>\n Effect.gen(function* () {\n const execute = (stmt: string | { readonly sql: string; readonly args: readonly unknown[] }) =>\n Effect.tryPromise({\n try: () => client.execute(stmt),\n catch: (cause) => new DataMigrationError({ migration: options.migrationName, cause }),\n });\n\n const exists = yield* execute(\n \"SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'integration'\",\n );\n if (exists.rows.length === 0) return 0;\n\n const result = yield* execute({\n sql: \"SELECT row_id, tenant, config FROM integration WHERE plugin_id = ? AND config IS NOT NULL\",\n args: [options.pluginId],\n });\n\n interface PlannedMove {\n readonly rowId: string;\n readonly namespace: string;\n readonly key: string;\n readonly blobId: string;\n readonly inlineText: string;\n readonly nextConfig: string;\n }\n const moves: PlannedMove[] = [];\n for (const row of result.rows) {\n if (typeof row.row_id !== \"string\" || typeof row.tenant !== \"string\") continue;\n if (typeof row.config !== \"string\") continue;\n const decoded = decodeJsonOption(row.config);\n if (Option.isNone(decoded) || !isRecord(decoded.value)) continue;\n const inline = decoded.value[options.inlineField];\n if (typeof inline !== \"string\") continue;\n\n const hash = yield* sha256Hex(inline);\n const namespace = `o:${row.tenant}/${options.pluginId}`;\n const key = `${options.blobKeyPrefix}/${hash}`;\n const { [options.inlineField]: _removed, ...rest } = decoded.value;\n moves.push({\n rowId: row.row_id,\n namespace,\n key,\n blobId: JSON.stringify([namespace, key]),\n inlineText: inline,\n nextConfig: JSON.stringify({ ...rest, [options.hashField]: hash }),\n });\n }\n if (moves.length === 0) return 0;\n\n const applyAll = Effect.gen(function* () {\n for (const move of moves) {\n const existing = yield* execute({\n sql: \"SELECT row_id FROM blob WHERE id = ?\",\n args: [move.blobId],\n });\n if (existing.rows.length === 0) {\n yield* execute({\n sql: \"INSERT INTO blob (namespace, key, value, row_id, id) VALUES (?, ?, ?, ?, ?)\",\n args: [move.namespace, move.key, move.inlineText, crypto.randomUUID(), move.blobId],\n });\n } else {\n yield* execute({\n sql: \"UPDATE blob SET value = ? WHERE id = ?\",\n args: [move.inlineText, move.blobId],\n });\n }\n yield* execute({\n sql: \"UPDATE integration SET config = ? WHERE row_id = ?\",\n args: [move.nextConfig, move.rowId],\n });\n }\n yield* execute(\"COMMIT\");\n });\n\n yield* execute(\"BEGIN\");\n yield* applyAll.pipe(Effect.tapError(() => execute(\"ROLLBACK\").pipe(Effect.ignore)));\n return moves.length;\n });\n","import { ToolResult, type ToolError } from \"./tool-result\";\n\nexport type AuthToolFailureCode =\n | \"connection_value_missing\"\n | \"connection_rejected\"\n | \"oauth_connection_missing\"\n | \"oauth_refresh_failed\"\n | \"oauth_reauth_required\";\n\nexport type AuthToolFailureInput = {\n readonly code: AuthToolFailureCode;\n readonly message: string;\n readonly source?: {\n readonly id: string;\n readonly scope?: string;\n };\n readonly credential?: {\n readonly kind: \"secret\" | \"oauth\" | \"upstream\";\n readonly label?: string;\n readonly slotKey?: string;\n readonly secretId?: string;\n readonly connectionId?: string;\n };\n readonly status?: number;\n readonly upstream?: {\n readonly status?: number;\n readonly details?: unknown;\n };\n readonly recovery?: {\n readonly configureSourceTool?: string;\n };\n};\n\n// In v1.5 a connection IS the credential: there is no standalone secret to\n// \"bind\" to a source afterward. Manually-entered credentials are created via\n// the connection handoff (the user enters the value in the web UI, which\n// creates the bound connection in one step); OAuth credentials are minted by\n// the OAuth start flow. These strings are read by the agent resolving the\n// failure, so they must name tools that actually exist on the executor.\nconst authRecovery = (input?: AuthToolFailureInput[\"recovery\"]) => ({\n createConnectionTool: \"executor.coreTools.connections.createHandoff\",\n startOAuthTool: \"executor.coreTools.oauth.start\",\n listConnectionsTool: \"executor.coreTools.connections.list\",\n ...(input?.configureSourceTool ? { configureSourceTool: input.configureSourceTool } : {}),\n connectionInstructions:\n \"For API keys and tokens, call createConnectionTool for the integration to get a browser URL; the user enters the credential there, which creates the bound connection. Do not ask the user to paste secrets into chat. Then call listConnectionsTool to confirm the connection exists before retrying this tool.\",\n oauthInstructions:\n \"For OAuth credentials, call startOAuthTool and give the returned authorizationUrl to the user. The completed connection binds automatically, then retry the tool.\",\n});\n\nexport const authToolFailure = <T = never>(input: AuthToolFailureInput): ToolResult<T> => {\n const error: ToolError = {\n code: input.code,\n message: input.message,\n retryable: false,\n ...(input.status !== undefined ? { status: input.status } : {}),\n details: {\n category: \"authentication\",\n ...(input.source ? { source: input.source } : {}),\n ...(input.credential ? { credential: input.credential } : {}),\n ...(input.upstream ? { upstream: input.upstream } : {}),\n recovery: authRecovery(input.recovery),\n },\n };\n return ToolResult.fail(error);\n};\n"],"mappings":"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","names":["Effect","Schema","Data","Option","Effect","Effect","execute"]}
@@ -46,6 +46,7 @@ declare const ElicitationDeclinedError_base: Schema.Class<ElicitationDeclinedErr
46
46
  }>, import("effect/Cause").YieldableError>;
47
47
  /** A tool was declined or cancelled during elicitation. */
48
48
  export declare class ElicitationDeclinedError extends ElicitationDeclinedError_base {
49
+ get message(): string;
49
50
  }
50
51
  export {};
51
52
  //# sourceMappingURL=elicitation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"elicitation.d.ts","sourceRoot":"","sources":["../src/elicitation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAExC,OAAO,EAAiB,WAAW,EAAE,MAAM,OAAO,CAAC;AAMnD,iEAAiE;AACjE,eAAO,MAAM,eAAe;;IAE1B,oDAAoD;;EAEpD,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,eAAe,CAAC,IAAI,CAAC;AAE1D,uEAAuE;AACvE,eAAO,MAAM,cAAc;;;IAGzB,wDAAwD;;EAExD,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,cAAc,CAAC,IAAI,CAAC;AAExD,MAAM,MAAM,kBAAkB,GAAG,eAAe,GAAG,cAAc,CAAC;AAElE,eAAO,MAAM,iBAAiB,2DAAmD,CAAC;AAClF,MAAM,MAAM,iBAAiB,GAAG,OAAO,iBAAiB,CAAC,IAAI,CAAC;AAE9D,eAAO,MAAM,mBAAmB;;IAE9B,sEAAsE;;EAEtE,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,OAAO,mBAAmB,CAAC,IAAI,CAAC;AAElE,iFAAiF;AACjF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;CACtC;AAED,0EAA0E;AAC1E,MAAM,MAAM,kBAAkB,GAAG,CAAC,GAAG,EAAE,kBAAkB,KAAK,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;AAEjG;iEACiE;AACjE,MAAM,MAAM,aAAa,GAAG,kBAAkB,GAAG,YAAY,CAAC;AAE9D,sCAAsC;AACtC,MAAM,WAAW,aAAa;IAC5B,gEAAgE;IAChE,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;CACxC;;;;;AAED,2DAA2D;AAC3D,qBAAa,wBAAyB,SAAQ,6BAM7C;CAAG"}
1
+ {"version":3,"file":"elicitation.d.ts","sourceRoot":"","sources":["../src/elicitation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAExC,OAAO,EAAiB,WAAW,EAAE,MAAM,OAAO,CAAC;AAMnD,iEAAiE;AACjE,eAAO,MAAM,eAAe;;IAE1B,oDAAoD;;EAEpD,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,eAAe,CAAC,IAAI,CAAC;AAE1D,uEAAuE;AACvE,eAAO,MAAM,cAAc;;;IAGzB,wDAAwD;;EAExD,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,cAAc,CAAC,IAAI,CAAC;AAExD,MAAM,MAAM,kBAAkB,GAAG,eAAe,GAAG,cAAc,CAAC;AAElE,eAAO,MAAM,iBAAiB,2DAAmD,CAAC;AAClF,MAAM,MAAM,iBAAiB,GAAG,OAAO,iBAAiB,CAAC,IAAI,CAAC;AAE9D,eAAO,MAAM,mBAAmB;;IAE9B,sEAAsE;;EAEtE,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,OAAO,mBAAmB,CAAC,IAAI,CAAC;AAElE,iFAAiF;AACjF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;CACtC;AAED,0EAA0E;AAC1E,MAAM,MAAM,kBAAkB,GAAG,CAAC,GAAG,EAAE,kBAAkB,KAAK,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;AAEjG;iEACiE;AACjE,MAAM,MAAM,aAAa,GAAG,kBAAkB,GAAG,YAAY,CAAC;AAE9D,sCAAsC;AACtC,MAAM,WAAW,aAAa;IAC5B,gEAAgE;IAChE,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;CACxC;;;;;AAED,2DAA2D;AAC3D,qBAAa,wBAAyB,SAAQ,6BAM7C;IAGC,IAAa,OAAO,IAAI,MAAM,CAE7B;CACF"}