🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@mochi.js/core

Package Overview
Dependencies
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@mochi.js/core - npm Package Compare versions

Comparing version
0.8.0
to
0.8.1
+5
-4
package.json
{
"name": "@mochi.js/core",
"version": "0.8.0",
"version": "0.8.1",
"description": "The library for faithful browser automation. Bun-native; relational fingerprint matrix, biomechanical input, stock Chromium-for-Testing.",

@@ -52,6 +52,7 @@ "license": "MIT",

"dependencies": {
"@mochi.js/behavioral": "^0.1.4",
"@mochi.js/behavioral": "^0.1.5",
"@mochi.js/challenges": "^0.2.1",
"@mochi.js/consistency": "^0.1.3",
"@mochi.js/inject": "^0.3.0"
"@mochi.js/consistency": "^0.1.4",
"@mochi.js/inject": "^0.3.1",
"@mochi.js/profiles": "^0.2.0"
},

@@ -58,0 +59,0 @@ "publishConfig": {

@@ -14,2 +14,3 @@ /**

import { deriveMatrix, type ProfileV1 } from "@mochi.js/consistency";
import { getProfile, ProfileBaselineMissingError, UnknownProfileIdError } from "@mochi.js/profiles";
import { resolveBinary } from "./binary";

@@ -266,5 +267,7 @@ import { defaultProfileForHost, unsupportedHostMessage } from "./default-profile";

// Inline `ProfileV1` objects flow straight through; string profile ids
// are resolved against a placeholder profile until `@mochi.js/profiles`
// ships its first capture (phase 0.4). The matrix is bit-stable per
// `(profile, seed)` excluding the `derivedAt` timestamp.
// resolve to the captured `data/<id>/profile.json` baseline shipped by
// `@mochi.js/profiles`. When the catalog declares an id but no captured
// baseline ships yet (e.g. `mac-m2-chrome-stable`), we fall back to a
// synthesized placeholder so the launch still succeeds. The matrix is
// bit-stable per `(profile, seed)` excluding the `derivedAt` timestamp.
//

@@ -275,3 +278,3 @@ // Task 0272 — when `profile` is omitted, auto-pick the host-OS-matching

// musl). Explicit `profile:` always wins; the auto-pick never overrides.
const profileSource = resolveProfileSource(opts.profile);
const profileSource = await resolveProfileSource(opts.profile);
const matrix = deriveMatrix(profileSource.profile, opts.seed);

@@ -515,17 +518,23 @@ if (profileSource.autoPicked) {

* false; `id` taken from the inline object.
* 2. Explicit `ProfileId` string — same placeholder synthesis as before.
* `autoPicked` false.
* 2. Explicit `ProfileId` string — load the captured baseline from
* `@mochi.js/profiles`. If the id is known to the catalog but no
* captured baseline ships, fall back to a placeholder synthesis so
* the launch still succeeds (and the consistency engine still locks
* a relationally-consistent Matrix from the skeleton). Unknown ids
* propagate as a hard error. `autoPicked` false.
* 3. `undefined` — task 0272: call `defaultProfileForHost()`. Throw with
* the unsupported-host diagnostic when the resolver returns `null`.
* `autoPicked` true.
* `autoPicked` true; same captured-vs-placeholder fallback as branch
* 2.
*
* Pure function — does not log. The launcher emits the INFO line itself
* after observing `autoPicked === true` so test fixtures can assert the
* resolution without intercepting `console`.
* Async because `getProfile` reads `data/<id>/profile.json` from disk via
* `Bun.file().json()`. The launcher does not log here — the INFO line for
* `autoPicked === true` is emitted at the call-site so test fixtures can
* assert the resolution without intercepting `console`.
*/
function resolveProfileSource(profile: ProfileId | ProfileV1 | undefined): {
async function resolveProfileSource(profile: ProfileId | ProfileV1 | undefined): Promise<{
profile: ProfileV1;
id: ProfileId;
autoPicked: boolean;
} {
}> {
if (typeof profile === "object") {

@@ -536,3 +545,3 @@ return { profile, id: profile.id, autoPicked: false };

return {
profile: synthesizePlaceholderProfile(profile),
profile: await loadProfileWithFallback(profile),
id: profile,

@@ -548,3 +557,3 @@ autoPicked: false,

return {
profile: synthesizePlaceholderProfile(picked),
profile: await loadProfileWithFallback(picked),
id: picked,

@@ -556,7 +565,58 @@ autoPicked: true,

/**
* Synthesize a generic placeholder `ProfileV1` from a profile id. Until
* `@mochi.js/profiles.getProfile` lands (phase 0.4), the consistency engine
* still produces a real, relationally-locked Matrix from this skeleton —
* the id is what flows into `sha256(profile.id + seed)`.
* Load a `ProfileV1` for `id` from `@mochi.js/profiles` if a captured
* baseline ships, otherwise synthesize a placeholder. Unknown ids also fall
* back to the placeholder (with a console.warn) — preserving the
* pre-getProfile() contract that any string id produces a working session.
* E2E test fixtures rely on synthetic ids like "test-humanize".
*
* Critical correctness path: the captured baselines pin tip-of-stable Chrome
* majors (147+ as of 2026-05). The pre-fix code path called
* `synthesizePlaceholderProfile` for every string id, which hardcoded
* Chrome 131 and produced a UA mismatch with the actual Chromium-for-Testing
* binary.
*/
async function loadProfileWithFallback(id: ProfileId): Promise<ProfileV1> {
try {
// `ProfileId` here is the loose `string` alias the launcher accepts
// (see comment near the type definition). `getProfile` narrows it
// back to the catalog union at runtime and throws
// `UnknownProfileIdError` for ids outside the catalog.
return await getProfile(id as Parameters<typeof getProfile>[0]);
} catch (err) {
if (err instanceof ProfileBaselineMissingError) {
// Known catalog entry, no baseline shipped yet — fall back to the
// synthesized placeholder so the launch still succeeds.
return synthesizePlaceholderProfile(id);
}
if (err instanceof UnknownProfileIdError) {
// Caller passed an id that isn't in `KNOWN_PROFILE_IDS`. Surface a
// warning so typos are visible, but fall back to the placeholder so
// synthetic test-fixture ids (e.g. "test-humanize") keep working.
// biome-ignore lint/suspicious/noConsole: dev-facing diagnostic
console.warn(
`[mochi] profile id "${id}" is not in @mochi.js/profiles.KNOWN_PROFILE_IDS; ` +
"falling back to a synthesized placeholder. Pass a ProfileV1 object directly " +
"or use one of the catalog ids to silence this warning.",
);
return synthesizePlaceholderProfile(id);
}
throw err;
}
}
/**
* Synthesize a generic placeholder `ProfileV1` from a profile id, used as
* a fallback when the catalog declares an id but no captured baseline
* ships in `@mochi.js/profiles` yet. The consistency engine still produces
* a real, relationally-locked Matrix from this skeleton — the id is what
* flows into `sha256(profile.id + seed)`.
*
* The major version pinned here MUST track the live Chromium-for-Testing
* pin (`packages/cli/src/browsers/manifest.ts:PINNED_FALLBACK_VERSION`)
* and the tip entry in
* `packages/consistency/src/rules/lookups/browser.ts:BROWSER_TIP_FULL_VERSION`.
* A drift between these surfaces ships a UA whose major doesn't match the
* installed binary — the canonical fingerprint-mismatch bug R-004 was
* meant to prevent. Bump all three together.
*/
function synthesizePlaceholderProfile(profile: ProfileId): ProfileV1 {

@@ -567,3 +627,3 @@ return {

engine: "chromium",
browser: { name: "chrome", channel: "stable", minVersion: "131", maxVersion: "133" },
browser: { name: "chrome", channel: "stable", minVersion: "148", maxVersion: "148" },
os: { name: "linux", version: "22", arch: "x64" },

@@ -593,7 +653,9 @@ device: {

behavior: { hand: "right", tremor: 0.18, wpm: 60, scrollStyle: "smooth" },
// Deprecated — kept for one release for migration; runtime no longer
// reads the field. Drops in 0.8.
// `wreqPreset` is required by the ProfileV1 schema for one release of
// back-compat (see `schemas/profile.schema.json`). The runtime no
// longer reads it — `Session.fetch` rides Chromium's network stack via
// CDP, so JA4 is real Chrome by definition. Drops in 0.8.
wreqPreset: "chrome_148_linux",
userAgent:
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36",
uaCh: {},

@@ -600,0 +662,0 @@ entropyBudget: { fixed: [], perSeed: [] },