Skip to content

ruvbot 0.3.6: fix ESM import; web UI sends the API key - #1356

Merged
ruvnet merged 2 commits into
mainfrom
fix/ruvbot-esm-ui-auth
Nov 5, 2026
Merged

ruvnet merged 2 commits into
mainfrom
fix/ruvbot-esm-ui-auth

Conversation

@ruvnet

@ruvnet ruvnet commented Nov 5, 2026

Copy link
Copy Markdown
Owner

Summary

  • ESM import fixed. import('ruvbot') threw in 0.3.4/0.3.5 (require worked). Two causes: dist/esm had no package.json with {"type":"module"} (the package root is CommonJS), and src/core/index.ts / src/integration/index.ts re-exported directories ('./agent', './slack', …). tsc's bundler resolution allows that, but Node ESM rejects it ("Directory import … is not supported"). The re-exports now point at /index.js. A new post-build step, scripts/fix-esm.js, writes dist/esm/package.json and fails the build if any relative ESM specifier doesn't resolve to a file.
  • Web UI works with RUVBOT_API_KEY. Since 0.3.4, /api/* requires Authorization: Bearer <key> when the key is set, and the bundled chat UI never sent it. Its /api calls now go through a small client. On a 401 it asks for the key once, keeps it in sessionStorage and sends it as a Bearer header. The key never goes in a URL, and there is no EventSource. With no key set on the server, the UI works as before.
  • Version bumped to 0.3.6.

Tests

  • tests/integration/package/pack-exports.test.ts builds the package, runs npm pack, installs the tarball into a scratch project, and loads ruvbot, ruvbot/core, ruvbot/learning, ruvbot/integrations/slack and ruvbot/integrations/webhooks through both require() and import(). It also checks that the ESM and CJS roots export the same runtime keys. It fails on the 0.3.5 build and passes with this change.
  • tests/unit/api/ui-api-client.test.ts (9 tests) pulls the client out of the shipped index.html and runs it against a fake server. It covers the header being attached, prompting once then reusing the key, the key never appearing in a URL, a single shared prompt for concurrent 401s, cancelling, re-prompting after a rejected key, no-op behaviour with no key, and that no bare fetch('/api…') calls remain.
  • Full vitest run: 11 failures. The same 11 fail on unmodified main (byzantine-consensus, bm25, hybrid-search, plugin-manager IPFS, wasm bindings); none are related to this change. tsc --noEmit passes.

Tarball

Compared with ruvbot@0.3.5, the only added files are dist/esm/package.json and scripts/fix-esm.js. Nothing was removed.

🤖 Generated with claude-flow

ESM: `import('ruvbot')` failed in 0.3.4/0.3.5 for two reasons. dist/esm had
no package.json with {"type":"module"} (the package root is CommonJS), and
src/core/index.ts and src/integration/index.ts used directory re-exports
('./agent', './slack', ...) that tsc's "bundler" resolution accepts but Node
ESM rejects ("Directory import ... is not supported"). The re-exports now
name '/index.js', and scripts/fix-esm.js runs after build:esm: it writes
dist/esm/package.json and fails the build if any relative ESM specifier does
not resolve to a file.

UI: when RUVBOT_API_KEY is set, /api/* needs "Authorization: Bearer <key>",
which the bundled chat UI never sent. Its /api calls now go through a small
client that, on a 401, asks for the key once, keeps it in sessionStorage and
sends it as a Bearer header (never in a URL). With no key set server-side
the UI behaves as before.

Tests: tests/integration/package/pack-exports.test.ts packs the tarball,
installs it in a scratch project and loads ruvbot, ./core, ./learning,
./integrations/slack and ./integrations/webhooks through require() and
import(). tests/unit/api/ui-api-client.test.ts runs the UI client from the
shipped index.html against a fake server.

Co-Authored-By: claude-flow <ruv@ruv.net>
build:esm now runs scripts/fix-esm.js, so the builder stage copies it.
npm ci needs --legacy-peer-deps (vitest 4 vs @vitest/coverage-v8 3 peer
range), and a .dockerignore keeps node_modules/dist out of the context.

Co-Authored-By: claude-flow <ruv@ruv.net>
@ruvnet
ruvnet merged commit dae9658 into main Nov 5, 2026
50 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant