#!/usr/bin/env bare /** * Smoke-test agent-web-fetch under the Bare runtime (loads lib via bare-fs, evaluates helpers). * * From repo root (after coreutils build): * bare scripts/smoke-agent-web-fetch-bare.mjs * * Requires: npm install (bare-fetch, bare-fs, bare-abort-controller, b4a). */ import 'bare-abort-controller/global' import fetch from 'bare-fetch' import { readFile } from 'bare-fs/promises' import b4a from 'b4a' const agentWebFetchUrl = new URL( '../packages/bare-os-coreutils/lib/agent-web-fetch.js', import.meta.url ) /** Minimal TextDecoder for bareWebDecodeBytes (Bare has no global TextDecoder). */ class TextDecoderPolyfill { /** * @param {string} [_label] * @param {unknown} [_opts] */ constructor(_label, _opts) {} /** * @param {Uint8Array} bytes */ decode(bytes) { return b4a.toString(bytes) } } async function main() { let buf = await readFile(agentWebFetchUrl) let code = typeof buf === 'string' ? buf : b4a.toString(buf) /** @type {typeof bareEditSgr | undefined} */ function bareEditSgr(cls, on) { if (!on) return '' switch (cls) { case 'keyword': return '\x1b[36m' case 'string': return '\x1b[32m' case 'comment': return '\x1b[90m' case 'number': return '\x1b[33m' case 'dim': return '\x1b[2m' default: return '' } } const EDIT_ANSI_RESET = '\x1b[0m' const sandbox = { URL, TextDecoder: typeof globalThis.TextDecoder !== 'undefined' ? globalThis.TextDecoder : TextDecoderPolyfill, TextEncoder: typeof globalThis.TextEncoder !== 'undefined' ? globalThis.TextEncoder : /** @type {unknown} */ (undefined), Uint8Array, AbortController: globalThis.AbortController, AbortSignal: globalThis.AbortSignal, ReadableStream: typeof globalThis.ReadableStream !== 'undefined' ? globalThis.ReadableStream : /** @type {unknown} */ (undefined), Response: typeof globalThis.Response !== 'undefined' ? globalThis.Response : /** @type {unknown} */ (undefined), Request: typeof globalThis.Request !== 'undefined' ? globalThis.Request : /** @type {unknown} */ (undefined), console, bareEditSgr, EDIT_ANSI_RESET, fetch, globalThis } const fn = new Function( ...Object.keys(sandbox), code + '\n;return { bareWebFmtErr, bareWebRunTool };' ) const out = fn(...Object.values(sandbox)) const bareWebFmtErrFn = out.bareWebFmtErr const bareWebRunToolFn = out.bareWebRunTool if (typeof bareWebFmtErrFn !== 'function') throw new Error('bareWebFmtErr not defined after eval') console.log('[smoke-bare-web-fetch] bareWebFmtErr(null)=', bareWebFmtErrFn(null)) console.log( '[smoke-bare-web-fetch] bareWebFmtErr(undefined)=', bareWebFmtErrFn(undefined) ) if (typeof bareWebRunToolFn !== 'function') { console.log('[smoke-bare-web-fetch] skip bareWebRunTool') return } /** Same contract as bare-fetch: reject with `signal.reason` when aborted. */ async function hangUntilAbort(_url, init) { const sig = init && init.signal if (!sig) return new Promise(() => {}) return new Promise((_res, rej) => { if (sig.aborted) rej(sig.reason) else sig.addEventListener('abort', () => rej(sig.reason), { once: true }) }) } const timeoutProbe = await bareWebRunToolFn({ ctx: { httpFetch: hangUntilAbort }, url: 'https://hang.test/', format: 'meta', timeout_ms: 50 }) if (timeoutProbe.ok) throw new Error('[smoke-bare-web-fetch] timeout probe expected ok=false') const te = String(timeoutProbe.error || '') if (te.includes('promise_rejected_with_undefined')) throw new Error( '[smoke-bare-web-fetch] abort must carry a reason for bare-fetch: ' + te ) if (!/timeout|TimeoutError|exceeded/i.test(te)) throw new Error('[smoke-bare-web-fetch] expected timeout message: ' + te) console.log('[smoke-bare-web-fetch] timeout-abort contract ok') const result = await bareWebRunToolFn({ ctx: { httpFetch: fetch }, url: 'https://example.com/', format: 'meta', timeout_ms: 15000, max_response_bytes: 65536 }) console.log('[smoke-bare-web-fetch] https://example.com ok=', result.ok) if (!result.ok) console.log('[smoke-bare-web-fetch] error=', result.error) else { console.log('[smoke-bare-web-fetch] status=', result.status) console.log('[smoke-bare-web-fetch] extract.title=', result.extract?.title) } } main().catch((e) => { console.error('[smoke-bare-web-fetch] fatal', e) if (typeof globalThis.process !== 'undefined') /** @type {{ exitCode?: number }} */ (globalThis.process).exitCode = 1 })