web_fetch fix
This commit is contained in:
+43
-3
@@ -1670,20 +1670,37 @@ async function bareAgentCompleteOnce(opts) {
|
||||
* @returns {string}
|
||||
*/
|
||||
function bareWebFmtErr(e) {
|
||||
if (e == null) return '(null)'
|
||||
if (e === undefined)
|
||||
return 'promise_rejected_with_undefined (no rejection reason)'
|
||||
if (e === null) return 'promise_rejected_with_null'
|
||||
if (typeof e === 'string') return e
|
||||
if (typeof e !== 'object') return String(e)
|
||||
const o = /** @type {Record<string, unknown>} */ (e)
|
||||
const msg = o.message
|
||||
if (typeof msg === 'string' && msg.trim()) return msg
|
||||
if (typeof msg === 'number' || typeof msg === 'boolean') return String(msg)
|
||||
if (typeof msg === 'string' && msg.trim()) return bareWebFmtErrAugment(o, msg.trim())
|
||||
if (typeof msg === 'number' || typeof msg === 'boolean')
|
||||
return bareWebFmtErrAugment(o, String(msg))
|
||||
const nm = o.name
|
||||
const code = o.code
|
||||
const errno = o.errno
|
||||
/** @type {string[]} */
|
||||
const bits = []
|
||||
if (typeof nm === 'string' && nm.trim()) bits.push(nm)
|
||||
if (code !== undefined && code !== null && String(code) !== '')
|
||||
bits.push('code=' + String(code))
|
||||
if (errno !== undefined && errno !== null && String(errno) !== '')
|
||||
bits.push('errno=' + String(errno))
|
||||
const cause = o.cause
|
||||
if (cause !== undefined && cause !== null && cause !== e) {
|
||||
const cs = bareWebFmtErr(cause)
|
||||
if (cs && cs !== 'unknown_error') bits.push('cause=(' + cs.slice(0, 280) + ')')
|
||||
}
|
||||
const errs = o.errors
|
||||
if (Array.isArray(errs) && errs.length) {
|
||||
errs.slice(0, 5).forEach((sub, i) => {
|
||||
bits.push('agg' + i + '=' + bareWebFmtErr(sub).slice(0, 120))
|
||||
})
|
||||
}
|
||||
if (bits.length) return bits.join(' ')
|
||||
try {
|
||||
const j = JSON.stringify(o)
|
||||
@@ -1702,6 +1719,29 @@ function bareWebFmtErr(e) {
|
||||
return 'unknown_error'
|
||||
}
|
||||
|
||||
/**
|
||||
* Append errno/syscall from Node-ish errors when message alone is vague.
|
||||
* @param {Record<string, unknown>} o
|
||||
* @param {string} base
|
||||
*/
|
||||
function bareWebFmtErrAugment(o, base) {
|
||||
const syscall = o.syscall
|
||||
const code = o.code
|
||||
const errno = o.errno
|
||||
/** @type {string[]} */
|
||||
const tail = []
|
||||
if (typeof syscall === 'string' && syscall.trim()) tail.push('syscall=' + syscall)
|
||||
if (code !== undefined && code !== null && String(code) !== '') tail.push(String(code))
|
||||
if (errno !== undefined && errno !== null && String(errno) !== '')
|
||||
tail.push('errno=' + String(errno))
|
||||
const cause = o.cause
|
||||
if (cause !== undefined && cause !== null) {
|
||||
const cs = bareWebFmtErr(cause)
|
||||
if (cs && cs !== 'unknown_error') tail.push('cause=(' + cs.slice(0, 240) + ')')
|
||||
}
|
||||
return tail.length ? base + ' [' + tail.join(', ') + ']' : base
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Record<string, unknown>} ctx
|
||||
* @returns {typeof fetch | null}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"schema": 2,
|
||||
"profileId": "bare-os-posix-like",
|
||||
"generatedAt": "2026-04-22T05:30:18.374Z",
|
||||
"generatedAt": "2026-04-22T05:38:34.635Z",
|
||||
"note": "Sparse POSIX Issue 7 coverage hints for /bin utilities. Omitted command names are not yet profiled here.",
|
||||
"commandIndex": [
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"atMs": 1776835818373,
|
||||
"atMs": 1776836314634,
|
||||
"commands": [
|
||||
"agent",
|
||||
"arch",
|
||||
|
||||
File diff suppressed because one or more lines are too long
+2
-1
@@ -32,7 +32,8 @@
|
||||
"lint": "prettier --check .",
|
||||
"os:seeder": "npm run build -w bare-os-coreutils && npm run build -w bare-os-openssh && npm run build -w bare-os-bare-libs && node scripts/ensure-pear-node-modules.mjs packages/bare-os-seeder && cd packages/bare-os-seeder && pear run --dev .",
|
||||
"os:booter": "node scripts/ensure-pear-node-modules.mjs packages/bare-os-booter && cd packages/bare-os-booter && pear run --dev .",
|
||||
"vendor:bare-node-shims": "node scripts/vendor-bare-node-shims.mjs"
|
||||
"vendor:bare-node-shims": "node scripts/vendor-bare-node-shims.mjs",
|
||||
"smoke:agent-web-fetch:bare": "bare scripts/smoke-agent-web-fetch-bare.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
|
||||
@@ -5,20 +5,37 @@
|
||||
* @returns {string}
|
||||
*/
|
||||
function bareWebFmtErr(e) {
|
||||
if (e == null) return '(null)'
|
||||
if (e === undefined)
|
||||
return 'promise_rejected_with_undefined (no rejection reason)'
|
||||
if (e === null) return 'promise_rejected_with_null'
|
||||
if (typeof e === 'string') return e
|
||||
if (typeof e !== 'object') return String(e)
|
||||
const o = /** @type {Record<string, unknown>} */ (e)
|
||||
const msg = o.message
|
||||
if (typeof msg === 'string' && msg.trim()) return msg
|
||||
if (typeof msg === 'number' || typeof msg === 'boolean') return String(msg)
|
||||
if (typeof msg === 'string' && msg.trim()) return bareWebFmtErrAugment(o, msg.trim())
|
||||
if (typeof msg === 'number' || typeof msg === 'boolean')
|
||||
return bareWebFmtErrAugment(o, String(msg))
|
||||
const nm = o.name
|
||||
const code = o.code
|
||||
const errno = o.errno
|
||||
/** @type {string[]} */
|
||||
const bits = []
|
||||
if (typeof nm === 'string' && nm.trim()) bits.push(nm)
|
||||
if (code !== undefined && code !== null && String(code) !== '')
|
||||
bits.push('code=' + String(code))
|
||||
if (errno !== undefined && errno !== null && String(errno) !== '')
|
||||
bits.push('errno=' + String(errno))
|
||||
const cause = o.cause
|
||||
if (cause !== undefined && cause !== null && cause !== e) {
|
||||
const cs = bareWebFmtErr(cause)
|
||||
if (cs && cs !== 'unknown_error') bits.push('cause=(' + cs.slice(0, 280) + ')')
|
||||
}
|
||||
const errs = o.errors
|
||||
if (Array.isArray(errs) && errs.length) {
|
||||
errs.slice(0, 5).forEach((sub, i) => {
|
||||
bits.push('agg' + i + '=' + bareWebFmtErr(sub).slice(0, 120))
|
||||
})
|
||||
}
|
||||
if (bits.length) return bits.join(' ')
|
||||
try {
|
||||
const j = JSON.stringify(o)
|
||||
@@ -37,6 +54,29 @@ function bareWebFmtErr(e) {
|
||||
return 'unknown_error'
|
||||
}
|
||||
|
||||
/**
|
||||
* Append errno/syscall from Node-ish errors when message alone is vague.
|
||||
* @param {Record<string, unknown>} o
|
||||
* @param {string} base
|
||||
*/
|
||||
function bareWebFmtErrAugment(o, base) {
|
||||
const syscall = o.syscall
|
||||
const code = o.code
|
||||
const errno = o.errno
|
||||
/** @type {string[]} */
|
||||
const tail = []
|
||||
if (typeof syscall === 'string' && syscall.trim()) tail.push('syscall=' + syscall)
|
||||
if (code !== undefined && code !== null && String(code) !== '') tail.push(String(code))
|
||||
if (errno !== undefined && errno !== null && String(errno) !== '')
|
||||
tail.push('errno=' + String(errno))
|
||||
const cause = o.cause
|
||||
if (cause !== undefined && cause !== null) {
|
||||
const cs = bareWebFmtErr(cause)
|
||||
if (cs && cs !== 'unknown_error') tail.push('cause=(' + cs.slice(0, 240) + ')')
|
||||
}
|
||||
return tail.length ? base + ' [' + tail.join(', ') + ']' : base
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Record<string, unknown>} ctx
|
||||
* @returns {typeof fetch | null}
|
||||
|
||||
@@ -145,9 +145,14 @@ test('bareWebRunTool truncates large body stream', async (t) => {
|
||||
t.ok(out.truncated)
|
||||
})
|
||||
|
||||
test('bareWebFmtErr never stringifies undefined as text', async (t) => {
|
||||
test('bareWebFmtErr null/undefined and node-like errors', async (t) => {
|
||||
const s = loadSandbox()
|
||||
const fmt = /** @type {(e: unknown) => string} */ (s.bareWebFmtErr)
|
||||
t.ok(fmt(null).includes('rejected_with_null'))
|
||||
t.ok(fmt(undefined).includes('rejected_with_undefined'))
|
||||
t.absent(fmt({ message: undefined }) === 'undefined')
|
||||
t.ok(fmt({ name: 'TypeError', code: 'ETIMEDOUT' }).includes('ETIMEDOUT'))
|
||||
const withCause = new Error('outer')
|
||||
withCause.cause = new Error('inner')
|
||||
t.ok(fmt(withCause).includes('inner'))
|
||||
})
|
||||
|
||||
@@ -1670,20 +1670,37 @@ async function bareAgentCompleteOnce(opts) {
|
||||
* @returns {string}
|
||||
*/
|
||||
function bareWebFmtErr(e) {
|
||||
if (e == null) return '(null)'
|
||||
if (e === undefined)
|
||||
return 'promise_rejected_with_undefined (no rejection reason)'
|
||||
if (e === null) return 'promise_rejected_with_null'
|
||||
if (typeof e === 'string') return e
|
||||
if (typeof e !== 'object') return String(e)
|
||||
const o = /** @type {Record<string, unknown>} */ (e)
|
||||
const msg = o.message
|
||||
if (typeof msg === 'string' && msg.trim()) return msg
|
||||
if (typeof msg === 'number' || typeof msg === 'boolean') return String(msg)
|
||||
if (typeof msg === 'string' && msg.trim()) return bareWebFmtErrAugment(o, msg.trim())
|
||||
if (typeof msg === 'number' || typeof msg === 'boolean')
|
||||
return bareWebFmtErrAugment(o, String(msg))
|
||||
const nm = o.name
|
||||
const code = o.code
|
||||
const errno = o.errno
|
||||
/** @type {string[]} */
|
||||
const bits = []
|
||||
if (typeof nm === 'string' && nm.trim()) bits.push(nm)
|
||||
if (code !== undefined && code !== null && String(code) !== '')
|
||||
bits.push('code=' + String(code))
|
||||
if (errno !== undefined && errno !== null && String(errno) !== '')
|
||||
bits.push('errno=' + String(errno))
|
||||
const cause = o.cause
|
||||
if (cause !== undefined && cause !== null && cause !== e) {
|
||||
const cs = bareWebFmtErr(cause)
|
||||
if (cs && cs !== 'unknown_error') bits.push('cause=(' + cs.slice(0, 280) + ')')
|
||||
}
|
||||
const errs = o.errors
|
||||
if (Array.isArray(errs) && errs.length) {
|
||||
errs.slice(0, 5).forEach((sub, i) => {
|
||||
bits.push('agg' + i + '=' + bareWebFmtErr(sub).slice(0, 120))
|
||||
})
|
||||
}
|
||||
if (bits.length) return bits.join(' ')
|
||||
try {
|
||||
const j = JSON.stringify(o)
|
||||
@@ -1702,6 +1719,29 @@ function bareWebFmtErr(e) {
|
||||
return 'unknown_error'
|
||||
}
|
||||
|
||||
/**
|
||||
* Append errno/syscall from Node-ish errors when message alone is vague.
|
||||
* @param {Record<string, unknown>} o
|
||||
* @param {string} base
|
||||
*/
|
||||
function bareWebFmtErrAugment(o, base) {
|
||||
const syscall = o.syscall
|
||||
const code = o.code
|
||||
const errno = o.errno
|
||||
/** @type {string[]} */
|
||||
const tail = []
|
||||
if (typeof syscall === 'string' && syscall.trim()) tail.push('syscall=' + syscall)
|
||||
if (code !== undefined && code !== null && String(code) !== '') tail.push(String(code))
|
||||
if (errno !== undefined && errno !== null && String(errno) !== '')
|
||||
tail.push('errno=' + String(errno))
|
||||
const cause = o.cause
|
||||
if (cause !== undefined && cause !== null) {
|
||||
const cs = bareWebFmtErr(cause)
|
||||
if (cs && cs !== 'unknown_error') tail.push('cause=(' + cs.slice(0, 240) + ')')
|
||||
}
|
||||
return tail.length ? base + ' [' + tail.join(', ') + ']' : base
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Record<string, unknown>} ctx
|
||||
* @returns {typeof fetch | null}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"schema": 2,
|
||||
"profileId": "bare-os-posix-like",
|
||||
"generatedAt": "2026-04-22T05:30:18.374Z",
|
||||
"generatedAt": "2026-04-22T05:38:34.635Z",
|
||||
"note": "Sparse POSIX Issue 7 coverage hints for /bin utilities. Omitted command names are not yet profiled here.",
|
||||
"commandIndex": [
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"atMs": 1776835818373,
|
||||
"atMs": 1776836314634,
|
||||
"commands": [
|
||||
"agent",
|
||||
"arch",
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,134 @@
|
||||
#!/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
|
||||
}
|
||||
|
||||
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
|
||||
})
|
||||
Reference in New Issue
Block a user