Files
ruvnet__ruflo/v3/@claude-flow/cli/vitest.config.ts
rUv 07f1cf3a3f fix(agentbbs-tools): detect the real CLI-only agentbbs package instead of a nonexistent JS import (#3250)
* fix(agentbbs-tools): detect the real CLI-only agentbbs package instead of a nonexistent JS import

The published `agentbbs` package (0.2.1) is a CLI-only launcher — a `bin`
script with no importable JS entry point — that downloads/builds a Rust
binary and shells out to it. loadAgentbbs()'s `await import('agentbbs')`
could therefore never resolve, even with the CLI correctly installed and
on PATH, so all 4 federation_bbs_* tools reported degraded:true
unconditionally regardless of install state.

Replace the dynamic import with a subprocess presence probe
(agentbbsCliAvailable(), `agentbbs --version`), matching how the rest of
the codebase treats optional CLI tools. shell:true is required for the
probe to find npm's Windows .cmd shim (child_process does not consult
PATHEXT otherwise).

Making the probe actually succeed surfaced two further pre-existing bugs
in code that was previously always skipped:
- vitest.config.ts externalized @noble/ed25519 alongside genuinely-optional
  deps (agentic-flow, agentdb, ...), but it is an always-installed hard
  dependency; externalizing it broke dynamic-import resolution under Vite's
  SSR transform.
- federation_bbs_human_join dynamically imported @noble/ed25519 a second
  time (getSigningKey() already does), which is now deduplicated behind one
  memoized loadEd25519() loader.

All 12 tests in agentbbs-tools.test.ts now pass, including the 4
happy-path tests that were previously always skipped.

* fix(agentbbs-tools): gate the probe shell to win32 instead of always on

`shell: true` was unconditional, and the probed binary comes from
`process.env.AGENTBBS_BIN`. Under a shell that argument is command-interpreted,
so `AGENTBBS_BIN='agentbbs --version; touch /tmp/PWNED'` executes the trailing
command. Verified locally: the file is created with `shell: true` and the spawn
fails with ENOENT once the shell is gated off.

This is the case browser-tools.ts already warns about in the comment beside the
same pattern -- "if user-controlled args are ever added, escape them before
spawn" -- and `shell: process.platform === 'win32'` is the convention already
used at browser-tools.ts:49, commands/init.ts:856 and :1194, and
init/helpers-generator.ts:1459. Unconditional `shell: true` appeared nowhere
else in the package.

The Windows behaviour the original was reaching for is unchanged: cmd.exe still
resolves the `agentbbs.cmd` shim via PATHEXT. POSIX simply stops interpreting
the override. Added windowsHide to match the sibling call sites.

Verified the fix still does what it set out to do: with the CLI resolvable the
suite is 12/12 and the four previously-always-skipped happy-path tests execute,
with the shell disabled on POSIX.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_013u4pmL9ZUAXb6usVQgNo67
2026-09-09 20:14:19 +00:00

44 lines
1.7 KiB
TypeScript

import { defineConfig } from 'vitest/config';
import { fileURLToPath } from 'node:url';
export default defineConfig({
resolve: {
conditions: ['node'],
// Exercise the workspace security source rather than a stale installed
// package during cross-package policy integration tests (ADR-324).
alias: {
'@claude-flow/security': fileURLToPath(new URL('../security/src/index.ts', import.meta.url)),
},
},
plugins: [
{
name: 'externalize-optional-deps',
enforce: 'pre',
resolveId(source) {
// Don't let Vite resolve optional deps that may have missing subpath
// exports. These are imported via try/catch dynamic import in src/
// (sona-optimizer falls back to no-SONA when the package isn't
// installed). External-marking them keeps vitest from failing
// module resolution at transform time.
if (source.startsWith('agentic-flow')) return { id: source, external: true };
if (source.startsWith('agentdb')) return { id: source, external: true };
// memory-bridge dynamic-imports this inside try/catch and degrades to
// the sql.js path; its dist is absent unless the workspace was built.
if (source === '@claude-flow/memory') return { id: source, external: true };
if (source.startsWith('@ruvector/')) return { id: source, external: true };
if (source.startsWith('@huggingface/transformers')) return { id: source, external: true };
if (source.startsWith('@xenova/transformers')) return { id: source, external: true };
return null;
},
},
],
test: {
environment: 'node',
include: ['__tests__/**/*.test.ts'],
globals: true,
coverage: {
enabled: false,
},
},
});