Merge branch 'main' into docs/pinokio-browser-performance

This commit is contained in:
Sameh Khamis committed 2026-10-14 12:33:46 -07:00
commit ffbd91c209
6 files changed
+81 -7

No files matched your search

+1 -1
View File
@@ -150,7 +150,7 @@ jobs:
run: npm run check:boundaries
- name: Run focused onboarding tests
run: node --test src/setupDoctor.test.mjs src/pinokioEnvironment.test.mjs src/pinokioPreflight.test.mjs src/pinokioLauncherContract.test.mjs src/keySetupHardening.test.mjs src/mapStartup.test.mjs src/hudSummaryResponse.test.mjs
run: node --test src/setupDoctor.test.mjs src/pinokioEnvironment.test.mjs src/pinokioPreflight.test.mjs src/pinokioLauncherContract.test.mjs src/keySetupHardening.test.mjs src/mapStartup.test.mjs src/hudSummaryResponse.test.mjs src/codexOauthRealtime.test.mjs
- name: Build production bundle
run: npm run build
+1 -1
View File
@@ -158,7 +158,7 @@ routing and regional caches. Request parameters cannot override these endpoints.
Voice controls accept an action runner and a controller factory through
`createVoiceCommands` (`./voice/commands`). The default Realtime controller owns
microphone tracks, playback, push-to-talk, tool cancellation and radio handoff.
Its backend supplies `requestToken({ tier, signal })` and
Its backend supplies `requestToken({ tier, authMode, signal })` and
`negotiate({ offerSdp, credential, signal })`. The Realtime-compatible adapter
(`./voice/realtime-backend`) accepts separate token and connection transports
and endpoints. Only the short-lived client secret reaches the SDP endpoint.
+10
View File
@@ -8,6 +8,7 @@ The session adapter, action runner and backend interfaces remain unchanged.
| Owner | State and responsibility |
| --- | --- |
| `realtimeConnection.js` | Start generation, request cancellation, peer/data channel, acquired microphone stream and playback element |
| `realtimeBackend.js` | Token and SDP requests, their separate transports, the abort/timeout scope around both, and client-secret expiry |
| `realtimeTurns.js` | Active and superseded responses, pending confirmations, deduplicated calls and action cancellation |
| `realtimeRadio.js` | Speaker ducking, prepared playback, stronger-action reservations and playback observers |
| `realtimeInput.js` | Physical Space gesture, microphone mute, input/output meters and their frame/listener lifetime |
@@ -21,6 +22,15 @@ The session adapter, action runner and backend interfaces remain unchanged.
| `resultDisplay.js` | What the voice card shows for a result and which items it numbers (read by the card and `referents.js`) |
| `gevActions.js` runner | Analyst follow-up memory (session: `resetConversation()` on stop, `dispose()` on removal) |
The backend is replaceable per deployment: `realtimeController.js` accepts it as a
`backend` option and falls back to `createRealtimeBackend()`. Its two method
signatures live with [application construction](APPLICATION.md); what belongs here
is the ownership. The connection is the backend's only consumer in the application.
The connection reads credential metadata for diagnostics and cost accounting,
then passes the complete credential unchanged to `negotiate`. Client-secret expiry is refused inside the backend, not by the connection.
`realtimeOwners.test.mjs` drives whole sessions through a substitute that
implements only those two methods.
Pure input policy, preferences and protocol-response policy have separate modules.
Owners receive named readers, operations or focused collaborators. Cross-owner
cancellation uses operations; response handling does not own Radio's reservations
+13 -2
View File
@@ -21,9 +21,20 @@ export function assertNode24AllocationRuntime(version = process.versions.node) {
return version;
}
/**
* Directories this runner searches for `*.test.mjs`, in stable order.
*
* `server/` belongs here because provider modules own tests of their own: a
* suite placed beside the module it covers must run, and CI's unit-test job runs
* `npm test`, so a directory missing from this list is a suite that never runs
* there. `unitTestRunner.test.mjs` asserts the list covers every `*.test.mjs`
* outside dependencies, build output and dot-directories, so adding a tree
* without adding it here fails.
*/
export const UNIT_TEST_ROOTS = Object.freeze(['src', 'server']);
/** Discover repository unit tests in stable path order. */
export function discoverUnitTestFiles(root = process.cwd()) {
const sourceRoot = path.join(root, 'src');
const files = [];
const visit = (directory) => {
for (const entry of readdirSync(directory, { withFileTypes: true })) {
@@ -34,7 +45,7 @@ export function discoverUnitTestFiles(root = process.cwd()) {
}
}
};
visit(sourceRoot);
for (const testRoot of UNIT_TEST_ROOTS) visit(path.join(root, testRoot));
return files.sort();
}
+5 -2
View File
@@ -145,17 +145,20 @@ test('Codex OAuth reader enforces expiry margin and bounds tokens without exp by
test('Codex login resolves an installed executable before PATH and starts browser auth detached', async () => {
const checked = [];
// Built with path.join so the stub matches the resolver on Windows too,
// where the separators are backslashes.
const installed = path.join('/home/fixture', '.local', 'bin', 'codex');
assert.equal(
resolveCodexExecutable({
environment: {},
home: '/home/fixture',
access(candidate) {
checked.push(candidate);
if (candidate.endsWith('/.local/bin/codex')) return;
if (candidate === installed) return;
throw new Error('missing');
},
}),
path.join('/home/fixture', '.local', 'bin', 'codex'),
installed,
);
assert.equal(checked.length, 1);
+51 -1
View File
@@ -1,14 +1,40 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import { readFileSync, readdirSync } from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import {
ALLOCATION_TEST_FILES,
UNIT_TEST_ROOTS,
allocationTestArgs,
assertNode24AllocationRuntime,
buildUnitTestPlan,
discoverUnitTestFiles,
isCalibratedAllocationRuntime,
} from '../scripts/run-unit-tests.mjs';
const repositoryRoot = fileURLToPath(new URL('..', import.meta.url));
/** Every `*.test.mjs` a contributor could add, found without consulting the runner. */
function testFilesOnDisk(root) {
// Build outputs and dependencies are not places a contributor writes a test,
// and walking them would be slow enough to matter. Everything else counts.
const skip = new Set(['node_modules', 'dist', 'build', 'public']);
const found = [];
const visit = (directory) => {
for (const entry of readdirSync(directory, { withFileTypes: true })) {
if (entry.name.startsWith('.') || skip.has(entry.name)) continue;
const absolute = path.join(directory, entry.name);
if (entry.isDirectory()) visit(absolute);
else if (entry.isFile() && entry.name.endsWith('.test.mjs')) {
found.push(path.relative(root, absolute).split(path.sep).join('/'));
}
}
};
visit(root);
return found.sort();
}
test('unit runner serializes only GC-bracketed allocation microbenchmarks', () => {
const ordinary = [
'src/data/manager.test.mjs',
@@ -37,6 +63,30 @@ test('unit runner serializes only GC-bracketed allocation microbenchmarks', () =
);
});
test('the runner discovers every test file in the repository', () => {
// CI's unit-test job runs `npm test`, which runs exactly what this function
// returns. A `*.test.mjs` outside the searched roots therefore never runs
// there, while still reading — in review and to its author — like covered
// code. Compare the two sets rather than their sizes, so the failure names the
// files instead of only disagreeing about a count. The final equality also
// catches the reverse: files the runner finds that this walk skips.
const discovered = discoverUnitTestFiles(repositoryRoot);
const onDisk = testFilesOnDisk(repositoryRoot);
const undiscovered = onDisk.filter((file) => !discovered.includes(file));
assert.deepEqual(
undiscovered,
[],
`test files the runner never executes: ${undiscovered.join(', ')}`,
);
assert.deepEqual(discovered, onDisk);
for (const file of discovered) {
assert.ok(
UNIT_TEST_ROOTS.some((root) => file.startsWith(`${root}/`)),
`${file} should sit under one of ${UNIT_TEST_ROOTS.join(', ')}`,
);
}
});
test('allocation runtime calibration is explicit and pinned to Node 24', () => {
assert.equal(assertNode24AllocationRuntime('24.19.0'), '24.19.0');
assert.throws(