161 lines
4.7 KiB
JavaScript
161 lines
4.7 KiB
JavaScript
#!/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
|
|
})
|