diff --git a/v3/@claude-flow/watermark/README.md b/v3/@claude-flow/watermark/README.md index be4f993bea..b816640873 100644 --- a/v3/@claude-flow/watermark/README.md +++ b/v3/@claude-flow/watermark/README.md @@ -63,11 +63,35 @@ console.log(r.zScore, r.log10P, r.isWatermarked(1e-6)); // strong, true key sees nothing. Confidence grows with the number of low-stakes token choices, so short or low-entropy (factual/code) text carries little to no mark. +## Browser / Deno / bundler + +The `@claude-flow/watermark/web` entry is an ESM build. Instantiate the WASM once +with `await init()`, then use the same API. In a browser, `init()` with no +argument fetches the sibling `.wasm`; pass a `URL` / `Response` / bytes to +override. + +```js +import { init, Watermarker, detect } from '@claude-flow/watermark/web'; + +await init(); // browser: auto-fetches the wasm + +const wm = new Watermarker({ key: '8F3A91C7', scheme: 'gumbel' }); +const tokens = Uint32Array.from({ length: 128 }, (_, i) => i); +const probs = new Float32Array(128).fill(1 / 128); +const out = new Uint32Array(600); +for (let i = 0; i < out.length; i++) out[i] = tokens[wm.step(tokens, probs)]; +wm.free(); + +console.log(detect(out, { key: '8F3A91C7', scheme: 'gumbel' }).isWatermarked(1e-6)); +``` + +The `.` entry is the Node (CommonJS) build shown earlier; the `/web` entry is for +browser / Deno / bundlers. + ## Scope -This build targets Node (CommonJS). The bindings are generated from the Rust -crate with `npm run build:wasm` (`wasm-pack --target nodejs`); browser/bundler -targets can be produced the same way (`--target web`/`bundler`). The crate -exposes more than this WASM surface — the Bayesian/Higher-Criticism detectors, -the robustness-evaluation harness, the Darwin/flywheel detector tuner, and the -authorized un-marked-generation governance path are Rust-only for now. +Bindings are generated from the Rust crate with `npm run build:wasm` +(`wasm-pack`, both `nodejs` and `web` targets). The crate exposes more than this +WASM surface — the Bayesian/Higher-Criticism detectors, the robustness-evaluation +harness, the Darwin/flywheel detector tuner, and the authorized un-marked- +generation governance path are Rust-only for now. diff --git a/v3/@claude-flow/watermark/package.json b/v3/@claude-flow/watermark/package.json index 4d45f0bca3..759bfa462e 100644 --- a/v3/@claude-flow/watermark/package.json +++ b/v3/@claude-flow/watermark/package.json @@ -1,7 +1,7 @@ { "name": "@claude-flow/watermark", - "version": "0.1.0", - "description": "SynthID-Text-style LLM text watermarking (generation + detection) as a WASM module — Tournament / non-distortionary / distortion-free schemes, indel-robust and short-text detectors. No watermark-removal tooling.", + "version": "0.2.0", + "description": "SynthID-Text-style LLM text watermarking (generation + detection) as a WASM module — Tournament / non-distortionary / distortion-free schemes, indel-robust and short-text detectors. Node + browser. No watermark-removal tooling.", "license": "MIT", "author": "rUv ", "homepage": "https://github.com/ruvnet/ruflo/tree/main/v3/crates/ruflo-watermark", @@ -24,6 +24,18 @@ "type": "commonjs", "main": "index.js", "types": "index.d.ts", + "exports": { + ".": { + "types": "./index.d.ts", + "require": "./index.js", + "import": "./index.js" + }, + "./web": { + "types": "./web/index.d.ts", + "import": "./web/index.mjs" + }, + "./package.json": "./package.json" + }, "files": [ "index.js", "index.d.ts", @@ -31,6 +43,13 @@ "wasm/ruflo_watermark_bg.wasm", "wasm/ruflo_watermark.d.ts", "wasm/ruflo_watermark_bg.wasm.d.ts", + "web/package.json", + "web/index.mjs", + "web/index.d.ts", + "web/ruflo_watermark.js", + "web/ruflo_watermark_bg.wasm", + "web/ruflo_watermark.d.ts", + "web/ruflo_watermark_bg.wasm.d.ts", "README.md" ], "engines": { @@ -41,6 +60,8 @@ }, "scripts": { "build:wasm": "bash scripts/build-wasm.sh", - "test": "node test/smoke.cjs" + "test": "node test/smoke.cjs && node test/smoke-web.mjs", + "test:node": "node test/smoke.cjs", + "test:web": "node test/smoke-web.mjs" } } diff --git a/v3/@claude-flow/watermark/scripts/build-wasm.sh b/v3/@claude-flow/watermark/scripts/build-wasm.sh index dce87cb8a9..3772be9402 100755 --- a/v3/@claude-flow/watermark/scripts/build-wasm.sh +++ b/v3/@claude-flow/watermark/scripts/build-wasm.sh @@ -1,5 +1,6 @@ #!/usr/bin/env bash -# Regenerate the WASM bindings in ./wasm from the ruflo-watermark Rust crate. +# Regenerate the WASM bindings from the ruflo-watermark Rust crate: the Node +# (CommonJS) build in ./wasm and the browser/Deno (ESM) build in ./web. # # Requires: rustup + wasm32-unknown-unknown target + wasm-pack. # rustup target add wasm32-unknown-unknown @@ -12,15 +13,19 @@ set -euo pipefail here="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" crate="$here/../../crates/ruflo-watermark" -CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUSTFLAGS="" RUSTFLAGS="" \ - wasm-pack build --release --target nodejs \ - --out-dir "$crate/pkg-nodejs" --out-name ruflo_watermark \ - "$crate" -- --features wasm +build() { # + CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUSTFLAGS="" RUSTFLAGS="" \ + wasm-pack build --release --target "$1" \ + --out-dir "$crate/$2" --out-name ruflo_watermark \ + "$crate" -- --features wasm +} -cp "$crate/pkg-nodejs/ruflo_watermark.js" \ - "$crate/pkg-nodejs/ruflo_watermark_bg.wasm" \ - "$crate/pkg-nodejs/ruflo_watermark.d.ts" \ - "$crate/pkg-nodejs/ruflo_watermark_bg.wasm.d.ts" \ - "$here/wasm/" +files=(ruflo_watermark.js ruflo_watermark_bg.wasm ruflo_watermark.d.ts ruflo_watermark_bg.wasm.d.ts) -echo "Rebuilt wasm/ from $crate" +build nodejs pkg-nodejs +for f in "${files[@]}"; do cp "$crate/pkg-nodejs/$f" "$here/wasm/"; done + +build web pkg-web +for f in "${files[@]}"; do cp "$crate/pkg-web/$f" "$here/web/"; done + +echo "Rebuilt wasm/ (nodejs) and web/ (browser) from $crate" diff --git a/v3/@claude-flow/watermark/test/smoke-web.mjs b/v3/@claude-flow/watermark/test/smoke-web.mjs new file mode 100644 index 0000000000..5dadb217b1 --- /dev/null +++ b/v3/@claude-flow/watermark/test/smoke-web.mjs @@ -0,0 +1,54 @@ +// Web-entry smoke test, run under Node ESM: init the WASM from bytes, then +// generate + detect through the browser-facing API. Mirrors what a browser does +// after `await init()` (in a browser, init() auto-fetches the .wasm). +import { readFileSync } from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { dirname, join } from 'node:path'; +import { init, isReady, Watermarker, detect, detectSelfSync, detectExact } from '../web/index.mjs'; + +const here = dirname(fileURLToPath(import.meta.url)); +const wasmBytes = readFileSync(join(here, '..', 'web', 'ruflo_watermark_bg.wasm')); + +let ok = true; +const check = (name, cond, detail) => { + console.log(` ${cond ? 'ok: ' : 'FAIL:'} ${name} — ${detail}`); + if (!cond) ok = false; +}; + +// Guard before init. +let threw = false; +try { + detect(Uint32Array.from([1, 2, 3]), { key: 'k' }); +} catch { + threw = true; +} +check('throws before init()', threw, `isReady=${isReady()}`); + +await init(wasmBytes); +check('isReady() after init', isReady(), 'true'); + +const KEY = '8F3A91C7'; +const VOCAB = 128; +const tokens = Uint32Array.from({ length: VOCAB }, (_, i) => i); +const probs = new Float32Array(VOCAB).fill(1 / VOCAB); + +for (const scheme of ['tournament', 'tournament_nd', 'gumbel']) { + const wm = new Watermarker({ key: KEY, scheme, layers: 6 }); + const out = new Uint32Array(600); + for (let i = 0; i < 600; i++) out[i] = tokens[wm.step(tokens, probs)]; + wm.free(); + const hit = detect(out, { key: KEY, scheme, layers: 6 }); + const wrong = detect(out, { key: 'WRONG', scheme, layers: 6 }); + check(`${scheme}: detects own output`, hit.isWatermarked(1e-6), `z=${hit.zScore.toFixed(1)}`); + check(`${scheme}: wrong key rejected`, !wrong.isWatermarked(1e-6), `z=${wrong.zScore.toFixed(2)}`); +} + +const g = new Watermarker({ key: KEY, scheme: 'gumbel' }); +const gs = new Uint32Array(600); +for (let i = 0; i < 600; i++) gs[i] = tokens[g.step(tokens, probs)]; +g.free(); +check('self-sync detector fires', detectSelfSync(gs, { key: KEY }).zScore > 8, 'z>8'); +check('exact short-text detector fires', detectExact(gs.slice(0, 120), { key: KEY }).log10P < -3, 'log10p<-3'); + +console.log(ok ? '\nWEB SMOKE OK' : '\nWEB SMOKE FAILED'); +process.exit(ok ? 0 : 1); diff --git a/v3/@claude-flow/watermark/web/index.d.ts b/v3/@claude-flow/watermark/web/index.d.ts new file mode 100644 index 0000000000..ee530bdfa2 --- /dev/null +++ b/v3/@claude-flow/watermark/web/index.d.ts @@ -0,0 +1,25 @@ +// Types for @claude-flow/watermark/web (browser / Deno / bundler entry). +import type { Detection, Scheme, WatermarkerOptions, SelfSyncOptions } from '../index.d.ts'; + +export type { Detection, Scheme, WatermarkerOptions, SelfSyncOptions }; + +/** WASM init input: fetched URL/Response, raw bytes, or a compiled module. */ +export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; + +/** Instantiate the WASM module. Await once before any other call. */ +export function init(input?: InitInput | Promise): Promise; + +/** True once `init()` has completed. */ +export function isReady(): boolean; + +export class Watermarker { + constructor(opts: WatermarkerOptions); + step(tokens: Uint32Array | number[], probs: Float32Array | number[]): number; + free(): void; +} + +export function detect(tokens: Uint32Array | number[], opts: WatermarkerOptions): Detection; +export function detectSelfSync(tokens: Uint32Array | number[], opts: SelfSyncOptions): Detection; +export function detectExact(tokens: Uint32Array | number[], opts: SelfSyncOptions): Detection; + +export const SCHEMES: ReadonlySet; diff --git a/v3/@claude-flow/watermark/web/index.mjs b/v3/@claude-flow/watermark/web/index.mjs new file mode 100644 index 0000000000..21aabb1d2b --- /dev/null +++ b/v3/@claude-flow/watermark/web/index.mjs @@ -0,0 +1,89 @@ +// @claude-flow/watermark/web — browser / Deno / bundler ESM entry. +// +// The WASM must be instantiated before use: `await init()` once, then use the +// same ergonomic API as the Node build. In a browser, `init()` with no argument +// fetches the sibling `ruflo_watermark_bg.wasm`; pass a URL / Response / +// BufferSource / WebAssembly.Module to override (e.g. in Node tests). +// +// Generation + detection only — no watermark-removal surface. + +import initWasm, { + WasmWatermarker, + detect as _detect, + detect_selfsync as _detectSelfSync, + detect_exact as _detectExact, +} from './ruflo_watermark.js'; + +let _ready = false; + +/** Instantiate the WASM module. Await once before any other call. */ +export async function init(input) { + if (_ready) return; + // Non-deprecated wasm-bindgen call shape; no arg => browser auto-fetch. + await initWasm(input === undefined ? undefined : { module_or_path: input }); + _ready = true; +} + +/** True once `init()` has completed. */ +export function isReady() { + return _ready; +} + +function assertReady() { + if (!_ready) throw new Error('@claude-flow/watermark/web: call `await init()` before use'); +} + +const SCHEMES = new Set(['tournament', 'tournament_nd', 'gumbel']); +const enc = new TextEncoder(); +const toKeyBytes = (k) => (typeof k === 'string' ? enc.encode(k) : k); +const toU32 = (a) => (a instanceof Uint32Array ? a : Uint32Array.from(a)); +const toF32 = (a) => (a instanceof Float32Array ? a : Float32Array.from(a)); +function normScheme(s) { + const v = s || 'gumbel'; + if (!SCHEMES.has(v)) throw new RangeError(`unknown scheme "${v}" (tournament | tournament_nd | gumbel)`); + return v; +} +function shape(r) { + const out = { + zScore: r.z_score, + pValue: r.p_value, + log10P: r.log10_p, + scoredPositions: r.scored_positions, + isWatermarked(alpha = 1e-6) { + return out.log10P <= Math.log10(alpha); + }, + }; + r.free(); + return out; +} + +/** Streaming watermarked sampler (call `await init()` first). */ +export class Watermarker { + constructor({ key, scheme = 'gumbel', contextWidth = 4, layers = 6 } = {}) { + assertReady(); + this._inner = new WasmWatermarker(toKeyBytes(key), contextWidth, layers, normScheme(scheme)); + } + step(tokens, probs) { + return this._inner.step(toU32(tokens), toF32(probs)); + } + free() { + this._inner.free(); + } +} + +export function detect(tokens, { key, scheme = 'gumbel', contextWidth = 4, layers = 6 } = {}) { + assertReady(); + return shape(_detect(toU32(tokens), toKeyBytes(key), contextWidth, layers, normScheme(scheme))); +} + +export function detectSelfSync(tokens, { key, contextWidth = 4 } = {}) { + assertReady(); + return shape(_detectSelfSync(toU32(tokens), toKeyBytes(key), contextWidth)); +} + +export function detectExact(tokens, { key, contextWidth = 4 } = {}) { + assertReady(); + return shape(_detectExact(toU32(tokens), toKeyBytes(key), contextWidth)); +} + +export { SCHEMES }; diff --git a/v3/@claude-flow/watermark/web/package.json b/v3/@claude-flow/watermark/web/package.json new file mode 100644 index 0000000000..5ffd9800b9 --- /dev/null +++ b/v3/@claude-flow/watermark/web/package.json @@ -0,0 +1 @@ +{ "type": "module" } diff --git a/v3/@claude-flow/watermark/web/ruflo_watermark.d.ts b/v3/@claude-flow/watermark/web/ruflo_watermark.d.ts new file mode 100644 index 0000000000..77d6534c54 --- /dev/null +++ b/v3/@claude-flow/watermark/web/ruflo_watermark.d.ts @@ -0,0 +1,93 @@ +/* tslint:disable */ +/* eslint-disable */ + +/** + * Detection result, JS-facing (fields via getters). + */ +export class WasmDetection { + private constructor(); + free(): void; + [Symbol.dispose](): void; + readonly log10_p: number; + readonly p_value: number; + readonly scored_positions: number; + readonly z_score: number; +} + +/** + * Streaming watermarked sampler, JS-facing. + */ +export class WasmWatermarker { + free(): void; + [Symbol.dispose](): void; + /** + * `key_material`: arbitrary secret bytes (e.g. a hex string's bytes). + * `scheme`: `"tournament"` | `"tournament_nd"` | `"gumbel"` (default gumbel). + */ + constructor(key_material: Uint8Array, context_width: number, layers: number, scheme: string); + /** + * Emit one token: returns the index into `tokens`/`probs` of the chosen + * candidate. Advances the rolling context. + */ + step(tokens: Uint32Array, probs: Float32Array): number; +} + +/** + * Detect a watermark over an emitted token id sequence, using the named scheme. + */ +export function detect(tokens: Uint32Array, key_material: Uint8Array, context_width: number, layers: number, scheme: string): WasmDetection; + +/** + * Exact-null short-text detection (Gumbel, exact Gamma tail): correct p-values + * at small token counts where the normal approximation misleads. See `bayes.rs`. + */ +export function detect_exact(tokens: Uint32Array, key_material: Uint8Array, context_width: number): WasmDetection; + +/** + * Indel-robust detection (Gumbel self-sync): far stronger than the standard + * detector on edited / repetitive text. See `align.rs`. + */ +export function detect_selfsync(tokens: Uint32Array, key_material: Uint8Array, context_width: number): WasmDetection; + +export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; + +export interface InitOutput { + readonly memory: WebAssembly.Memory; + readonly __wbg_wasmdetection_free: (a: number, b: number) => void; + readonly __wbg_wasmwatermarker_free: (a: number, b: number) => void; + readonly detect: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => number; + readonly detect_exact: (a: number, b: number, c: number, d: number, e: number) => number; + readonly detect_selfsync: (a: number, b: number, c: number, d: number, e: number) => number; + readonly wasmdetection_log10_p: (a: number) => number; + readonly wasmdetection_p_value: (a: number) => number; + readonly wasmdetection_scored_positions: (a: number) => number; + readonly wasmdetection_z_score: (a: number) => number; + readonly wasmwatermarker_new: (a: number, b: number, c: number, d: number, e: number, f: number) => number; + readonly wasmwatermarker_step: (a: number, b: number, c: number, d: number, e: number) => number; + readonly __wbindgen_externrefs: WebAssembly.Table; + readonly __wbindgen_malloc: (a: number, b: number) => number; + readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; + readonly __wbindgen_start: () => void; +} + +export type SyncInitInput = BufferSource | WebAssembly.Module; + +/** + * Instantiates the given `module`, which can either be bytes or + * a precompiled `WebAssembly.Module`. + * + * @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated. + * + * @returns {InitOutput} + */ +export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput; + +/** + * If `module_or_path` is {RequestInfo} or {URL}, makes a request and + * for everything else, calls `WebAssembly.instantiate` directly. + * + * @param {{ module_or_path: InitInput | Promise }} module_or_path - Passing `InitInput` directly is deprecated. + * + * @returns {Promise} + */ +export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise } | InitInput | Promise): Promise; diff --git a/v3/@claude-flow/watermark/web/ruflo_watermark.js b/v3/@claude-flow/watermark/web/ruflo_watermark.js new file mode 100644 index 0000000000..57a7064ca7 --- /dev/null +++ b/v3/@claude-flow/watermark/web/ruflo_watermark.js @@ -0,0 +1,398 @@ +/* @ts-self-types="./ruflo_watermark.d.ts" */ + +/** + * Detection result, JS-facing (fields via getters). + */ +export class WasmDetection { + static __wrap(ptr) { + const obj = Object.create(WasmDetection.prototype); + obj.__wbg_ptr = ptr; + WasmDetectionFinalization.register(obj, obj.__wbg_ptr, obj); + return obj; + } + __destroy_into_raw() { + const ptr = this.__wbg_ptr; + this.__wbg_ptr = 0; + WasmDetectionFinalization.unregister(this); + return ptr; + } + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_wasmdetection_free(ptr, 0); + } + /** + * @returns {number} + */ + get log10_p() { + const ret = wasm.wasmdetection_log10_p(this.__wbg_ptr); + return ret; + } + /** + * @returns {number} + */ + get p_value() { + const ret = wasm.wasmdetection_p_value(this.__wbg_ptr); + return ret; + } + /** + * @returns {number} + */ + get scored_positions() { + const ret = wasm.wasmdetection_scored_positions(this.__wbg_ptr); + return ret >>> 0; + } + /** + * @returns {number} + */ + get z_score() { + const ret = wasm.wasmdetection_z_score(this.__wbg_ptr); + return ret; + } +} +if (Symbol.dispose) WasmDetection.prototype[Symbol.dispose] = WasmDetection.prototype.free; + +/** + * Streaming watermarked sampler, JS-facing. + */ +export class WasmWatermarker { + __destroy_into_raw() { + const ptr = this.__wbg_ptr; + this.__wbg_ptr = 0; + WasmWatermarkerFinalization.unregister(this); + return ptr; + } + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_wasmwatermarker_free(ptr, 0); + } + /** + * `key_material`: arbitrary secret bytes (e.g. a hex string's bytes). + * `scheme`: `"tournament"` | `"tournament_nd"` | `"gumbel"` (default gumbel). + * @param {Uint8Array} key_material + * @param {number} context_width + * @param {number} layers + * @param {string} scheme + */ + constructor(key_material, context_width, layers, scheme) { + const ptr0 = passArray8ToWasm0(key_material, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(scheme, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ret = wasm.wasmwatermarker_new(ptr0, len0, context_width, layers, ptr1, len1); + this.__wbg_ptr = ret; + WasmWatermarkerFinalization.register(this, this.__wbg_ptr, this); + return this; + } + /** + * Emit one token: returns the index into `tokens`/`probs` of the chosen + * candidate. Advances the rolling context. + * @param {Uint32Array} tokens + * @param {Float32Array} probs + * @returns {number} + */ + step(tokens, probs) { + const ptr0 = passArray32ToWasm0(tokens, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passArrayF32ToWasm0(probs, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + const ret = wasm.wasmwatermarker_step(this.__wbg_ptr, ptr0, len0, ptr1, len1); + return ret >>> 0; + } +} +if (Symbol.dispose) WasmWatermarker.prototype[Symbol.dispose] = WasmWatermarker.prototype.free; + +/** + * Detect a watermark over an emitted token id sequence, using the named scheme. + * @param {Uint32Array} tokens + * @param {Uint8Array} key_material + * @param {number} context_width + * @param {number} layers + * @param {string} scheme + * @returns {WasmDetection} + */ +export function detect(tokens, key_material, context_width, layers, scheme) { + const ptr0 = passArray32ToWasm0(tokens, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passArray8ToWasm0(key_material, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passStringToWasm0(scheme, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len2 = WASM_VECTOR_LEN; + const ret = wasm.detect(ptr0, len0, ptr1, len1, context_width, layers, ptr2, len2); + return WasmDetection.__wrap(ret); +} + +/** + * Exact-null short-text detection (Gumbel, exact Gamma tail): correct p-values + * at small token counts where the normal approximation misleads. See `bayes.rs`. + * @param {Uint32Array} tokens + * @param {Uint8Array} key_material + * @param {number} context_width + * @returns {WasmDetection} + */ +export function detect_exact(tokens, key_material, context_width) { + const ptr0 = passArray32ToWasm0(tokens, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passArray8ToWasm0(key_material, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + const ret = wasm.detect_exact(ptr0, len0, ptr1, len1, context_width); + return WasmDetection.__wrap(ret); +} + +/** + * Indel-robust detection (Gumbel self-sync): far stronger than the standard + * detector on edited / repetitive text. See `align.rs`. + * @param {Uint32Array} tokens + * @param {Uint8Array} key_material + * @param {number} context_width + * @returns {WasmDetection} + */ +export function detect_selfsync(tokens, key_material, context_width) { + const ptr0 = passArray32ToWasm0(tokens, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passArray8ToWasm0(key_material, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + const ret = wasm.detect_selfsync(ptr0, len0, ptr1, len1, context_width); + return WasmDetection.__wrap(ret); +} +function __wbg_get_imports() { + const import0 = { + __proto__: null, + __wbg___wbindgen_throw_bb96b2010945f0bc: function(arg0, arg1) { + throw new Error(getStringFromWasm0(arg0, arg1)); + }, + __wbindgen_init_externref_table: function() { + const table = wasm.__wbindgen_externrefs; + const offset = table.grow(4); + table.set(0, undefined); + table.set(offset + 0, undefined); + table.set(offset + 1, null); + table.set(offset + 2, true); + table.set(offset + 3, false); + }, + }; + return { + __proto__: null, + "./ruflo_watermark_bg.js": import0, + }; +} + +const WasmDetectionFinalization = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(ptr => wasm.__wbg_wasmdetection_free(ptr, 1)); +const WasmWatermarkerFinalization = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(ptr => wasm.__wbg_wasmwatermarker_free(ptr, 1)); + +let cachedFloat32ArrayMemory0 = null; +function getFloat32ArrayMemory0() { + if (cachedFloat32ArrayMemory0 === null || cachedFloat32ArrayMemory0.byteLength === 0) { + cachedFloat32ArrayMemory0 = new Float32Array(wasm.memory.buffer); + } + return cachedFloat32ArrayMemory0; +} + +function getStringFromWasm0(ptr, len) { + return decodeText(ptr >>> 0, len); +} + +let cachedUint32ArrayMemory0 = null; +function getUint32ArrayMemory0() { + if (cachedUint32ArrayMemory0 === null || cachedUint32ArrayMemory0.byteLength === 0) { + cachedUint32ArrayMemory0 = new Uint32Array(wasm.memory.buffer); + } + return cachedUint32ArrayMemory0; +} + +let cachedUint8ArrayMemory0 = null; +function getUint8ArrayMemory0() { + if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) { + cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer); + } + return cachedUint8ArrayMemory0; +} + +function passArray32ToWasm0(arg, malloc) { + const ptr = malloc(arg.length * 4, 4) >>> 0; + getUint32ArrayMemory0().set(arg, ptr / 4); + WASM_VECTOR_LEN = arg.length; + return ptr; +} + +function passArray8ToWasm0(arg, malloc) { + const ptr = malloc(arg.length * 1, 1) >>> 0; + getUint8ArrayMemory0().set(arg, ptr / 1); + WASM_VECTOR_LEN = arg.length; + return ptr; +} + +function passArrayF32ToWasm0(arg, malloc) { + const ptr = malloc(arg.length * 4, 4) >>> 0; + getFloat32ArrayMemory0().set(arg, ptr / 4); + WASM_VECTOR_LEN = arg.length; + return ptr; +} + +function passStringToWasm0(arg, malloc, realloc) { + if (realloc === undefined) { + const buf = cachedTextEncoder.encode(arg); + const ptr = malloc(buf.length, 1) >>> 0; + getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf); + WASM_VECTOR_LEN = buf.length; + return ptr; + } + + let len = arg.length; + let ptr = malloc(len, 1) >>> 0; + + const mem = getUint8ArrayMemory0(); + + let offset = 0; + + for (; offset < len; offset++) { + const code = arg.charCodeAt(offset); + if (code > 0x7F) break; + mem[ptr + offset] = code; + } + if (offset !== len) { + if (offset !== 0) { + arg = arg.slice(offset); + } + ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0; + const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len); + const ret = cachedTextEncoder.encodeInto(arg, view); + + offset += ret.written; + ptr = realloc(ptr, len, offset, 1) >>> 0; + } + + WASM_VECTOR_LEN = offset; + return ptr; +} + +let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }); +cachedTextDecoder.decode(); +const MAX_SAFARI_DECODE_BYTES = 2146435072; +let numBytesDecoded = 0; +function decodeText(ptr, len) { + numBytesDecoded += len; + if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) { + cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }); + cachedTextDecoder.decode(); + numBytesDecoded = len; + } + return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len)); +} + +const cachedTextEncoder = new TextEncoder(); + +if (!('encodeInto' in cachedTextEncoder)) { + cachedTextEncoder.encodeInto = function (arg, view) { + const buf = cachedTextEncoder.encode(arg); + view.set(buf); + return { + read: arg.length, + written: buf.length + }; + }; +} + +let WASM_VECTOR_LEN = 0; + +let wasmModule, wasmInstance, wasm; +function __wbg_finalize_init(instance, module) { + wasmInstance = instance; + wasm = instance.exports; + wasmModule = module; + cachedFloat32ArrayMemory0 = null; + cachedUint32ArrayMemory0 = null; + cachedUint8ArrayMemory0 = null; + wasm.__wbindgen_start(); + return wasm; +} + +async function __wbg_load(module, imports) { + if (typeof Response === 'function' && module instanceof Response) { + if (!module.ok) { + throw new Error(`failed to fetch Wasm: ${module.status} ${module.statusText} fetching '${module.url}'`); + } + + if (typeof WebAssembly.instantiateStreaming === 'function') { + try { + return await WebAssembly.instantiateStreaming(module, imports); + } catch (e) { + const validResponse = expectedResponseType(module.type); + + if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') { + console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e); + + } else { throw e; } + } + } + + const bytes = await module.arrayBuffer(); + return await WebAssembly.instantiate(bytes, imports); + } else { + const instance = await WebAssembly.instantiate(module, imports); + + if (instance instanceof WebAssembly.Instance) { + return { instance, module }; + } else { + return instance; + } + } + + function expectedResponseType(type) { + switch (type) { + case 'basic': case 'cors': case 'default': return true; + } + return false; + } +} + +function initSync(module) { + if (wasm !== undefined) return wasm; + + + if (module !== undefined) { + if (Object.getPrototypeOf(module) === Object.prototype) { + ({module} = module) + } else { + console.warn('using deprecated parameters for `initSync()`; pass a single object instead') + } + } + + const imports = __wbg_get_imports(); + if (!(module instanceof WebAssembly.Module)) { + module = new WebAssembly.Module(module); + } + const instance = new WebAssembly.Instance(module, imports); + return __wbg_finalize_init(instance, module); +} + +async function __wbg_init(module_or_path) { + if (wasm !== undefined) return wasm; + + + if (module_or_path !== undefined) { + if (Object.getPrototypeOf(module_or_path) === Object.prototype) { + ({module_or_path} = module_or_path) + } else { + console.warn('using deprecated parameters for the initialization function; pass a single object instead') + } + } + + if (module_or_path === undefined) { + module_or_path = new URL('ruflo_watermark_bg.wasm', import.meta.url); + } + const imports = __wbg_get_imports(); + + if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) { + module_or_path = fetch(module_or_path); + } + + const { instance, module } = await __wbg_load(await module_or_path, imports); + + return __wbg_finalize_init(instance, module); +} + +export { initSync, __wbg_init as default }; diff --git a/v3/@claude-flow/watermark/web/ruflo_watermark_bg.wasm b/v3/@claude-flow/watermark/web/ruflo_watermark_bg.wasm new file mode 100644 index 0000000000..14e572235d Binary files /dev/null and b/v3/@claude-flow/watermark/web/ruflo_watermark_bg.wasm differ diff --git a/v3/@claude-flow/watermark/web/ruflo_watermark_bg.wasm.d.ts b/v3/@claude-flow/watermark/web/ruflo_watermark_bg.wasm.d.ts new file mode 100644 index 0000000000..ef4372a905 --- /dev/null +++ b/v3/@claude-flow/watermark/web/ruflo_watermark_bg.wasm.d.ts @@ -0,0 +1,18 @@ +/* tslint:disable */ +/* eslint-disable */ +export const memory: WebAssembly.Memory; +export const __wbg_wasmdetection_free: (a: number, b: number) => void; +export const __wbg_wasmwatermarker_free: (a: number, b: number) => void; +export const detect: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => number; +export const detect_exact: (a: number, b: number, c: number, d: number, e: number) => number; +export const detect_selfsync: (a: number, b: number, c: number, d: number, e: number) => number; +export const wasmdetection_log10_p: (a: number) => number; +export const wasmdetection_p_value: (a: number) => number; +export const wasmdetection_scored_positions: (a: number) => number; +export const wasmdetection_z_score: (a: number) => number; +export const wasmwatermarker_new: (a: number, b: number, c: number, d: number, e: number, f: number) => number; +export const wasmwatermarker_step: (a: number, b: number, c: number, d: number, e: number) => number; +export const __wbindgen_externrefs: WebAssembly.Table; +export const __wbindgen_malloc: (a: number, b: number) => number; +export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; +export const __wbindgen_start: () => void; diff --git a/v3/crates/ruflo-watermark/.gitignore b/v3/crates/ruflo-watermark/.gitignore index a104ff3806..a32297e4b8 100644 --- a/v3/crates/ruflo-watermark/.gitignore +++ b/v3/crates/ruflo-watermark/.gitignore @@ -12,3 +12,4 @@ .ruvector/ /pkg /pkg-nodejs +/pkg-web