Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,28 @@ BargeKit is a small ESM package. The public surface is split by runtime so apps
import { createBargeKit, BargeKitEngine, MODES, STATES, EVENTS } from '@bargekit/core';
```

Use `createBargeKit(config)` for the deterministic turn-taking state machine. Feed it level frames with `engine.ingestLevel({ timestamp, level })`; subscribe with `engine.on(EVENTS.userSpeechStarted, handler)`.
Use `createBargeKit(config)` for the deterministic turn-taking state machine. Feed it level frames with `engine.ingestLevel({ timestamp, level })`; subscribe with the literal event names listed in `EVENTS`:

```js
const engine = createBargeKit({ mode: 'vad' });
const unsubscribe = engine.on('bargekit.user_speech.started', handler);
engine.ingestLevel({ timestamp: Date.now(), level: 0.7 });
unsubscribe();
```

Key behaviours:

- `vad` mode opens from level threshold and debounce timing.
- `push_to_talk` ignores hot levels until `setPushToTalk(true)`.
- `wake_hook` requires `triggerWake()` before speech can open the gate.
- `push_to_talk` ignores hot levels until `press()` and stops accepting them after `release()`.
- `wake_hook` requires `detectWake()` before speech can open the gate.
- `half_duplex` holds input while agent output is active.
- mute always wins over speech detection.

## Fixtures

```js
import { SYNTHETIC_FIXTURES, runFixture, loadFixtureFile } from '@bargekit/core/fixtures';
import { saveFixtureFile, createFixtureFromLevels } from '@bargekit/core/fixture-io';
import { SYNTHETIC_FIXTURES, runFixture } from '@bargekit/core/fixtures';
import { loadFixtureFile, saveFixtureFile, createFixtureFromLevels } from '@bargekit/core/fixture-io';
```

Built-in fixtures are synthetic level traces, not recordings. Checked-in JSON fixtures live in `tests/fixtures/` for test and CLI compatibility.
Expand Down
33 changes: 29 additions & 4 deletions scripts/verify-documented-imports.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ const documentedImports = [
.map((match) => match[1])
)
];
const staleCoreExamples = ['EVENTS.userSpeechStarted', 'setPushToTalk(', 'triggerWake('];

for (const example of staleCoreExamples) {
if (apiDocs.includes(example)) {
throw new Error(`docs/API.md references unsupported core API: ${example}`);
}
}

if (documentedImports.length === 0) {
throw new Error('docs/API.md does not contain any @bargekit/core imports');
Expand Down Expand Up @@ -51,10 +58,28 @@ try {
['install', '--ignore-scripts', '--no-audit', '--no-fund', tarballPath],
{ cwd: consumerDir, stdio: 'inherit' }
);
writeFileSync(
join(consumerDir, 'verify.mjs'),
`await Promise.all(${JSON.stringify(documentedImports)}.map((specifier) => import(specifier)));\n`
);
const documentedNames = new Map();
for (const match of apiDocs.matchAll(/import\s*{([^}]+)}\s*from\s*['"](@bargekit\/core(?:\/[^'"]+)?)['"]/g)) {
const names = match[1].split(',').map((name) => name.trim()).filter(Boolean);
documentedNames.set(match[2], [...(documentedNames.get(match[2]) ?? []), ...names]);
}
writeFileSync(join(consumerDir, 'verify.mjs'), `
const documentedNames = new Map(${JSON.stringify([...documentedNames])});
for (const [specifier, names] of documentedNames) {
const module = await import(specifier);
for (const name of names) {
if (!(name in module)) throw new Error(\`\${specifier} does not export \${name}\`);
}
}
const { createBargeKit } = await import('@bargekit/core');
const engine = createBargeKit({ mode: 'vad' });
for (const method of ['on', 'ingestLevel', 'press', 'release', 'detectWake']) {
if (typeof engine[method] !== 'function') throw new Error(\`BargeKitEngine does not provide \${method}()\`);
}
const unsubscribe = engine.on('bargekit.user_speech.started', () => {});
if (typeof unsubscribe !== 'function') throw new Error('BargeKitEngine.on() must return an unsubscribe function');
unsubscribe();
`);
execFileSync('node', ['verify.mjs'], { cwd: consumerDir, stdio: 'inherit' });

console.log(`verified documented imports from packed tarball: ${documentedImports.join(', ')}`);
Expand Down
Loading