Skip to content

plugin-file-secrets and plugin-keychain import StorageError from the sdk root, which does not export it (unusable under npm) #1833

Description

@TheGreatestGgoat

Both local credential-store plugins fail to import when installed from npm. The integration plugins are fine, so the impact is narrow but load-bearing: connections.create needs a registered writable provider, and these are the two file/OS-backed options.

Repro

mkdir r && cd r && npm init -y
npm i @executor-js/sdk@1.6.3 @executor-js/plugin-file-secrets@1.6.3
node --input-type=module -e "import('@executor-js/plugin-file-secrets')"
file:///.../node_modules/@executor-js/plugin-file-secrets/dist/chunk-4DRGSORC.js:10
  StorageError
  ^^^^^^^^^^^^
SyntaxError: The requested module '@executor-js/sdk' does not provide an export named 'StorageError'

Cause

The symbol is exported from the ./core entry, not the root:

node -e "import('@executor-js/sdk/core').then(c=>console.log('core:', 'StorageError' in c))"  # true
node -e "import('@executor-js/sdk').then(r=>console.log('root:', 'StorageError' in r))"       # false

The root entry maps to dist/index.js (the promise surface); StorageError lives in dist/core.js. So the plugin's import { StorageError } from "@executor-js/sdk" should be from "@executor-js/sdk/core". Presumably resolves inside the monorepo (workspace/bundle) and only breaks against the published package.

Affected, measured on 1.6.3

package import
plugin-file-secrets BROKEN
plugin-keychain BROKEN (same symbol)
plugin-openapi OK
plugin-mcp OK
plugin-graphql OK
plugin-onepassword OK

Workaround

Hand-roll the provider — the interface is five Effect methods, so this is a small unblock rather than a fork:

const mem = new Map();
const provider = {
  key: "default", writable: true,
  get: (id) => Effect.succeed(mem.get(id) ?? null),
  has: (id) => Effect.succeed(mem.has(id)),
  set: (id, v) => Effect.sync(() => { mem.set(id, v); }),
  delete: (id) => Effect.sync(() => { mem.delete(id); }),
  list: () => Effect.succeed([]),
};
await createExecutor({ plugins: [openApiPlugin()], providers: [provider] });

Context: evaluating Executor as the integration layer for a multi-agent platform, embedding the SDK so the host owns the approval loop via onElicitation. That part works nicely — InvokeOptions being per-call is what lets a host attribute a tool call to the specific agent that made it.

Two much smaller things noticed while getting there, mentioning rather than filing separately:

  • The README's integration example uses executor call executor openapi addIntegration; the actual tool is executor.openapi.addSpec (addIntegration returns tool_not_found).
  • Tools materialise per connection, not per integration — addSpec alone leaves tools.list empty and tools integrations showing toolCount: 0, which reads as a failed add until you create a connection. Possibly worth a line in the concepts docs.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions