export class HunchError extends Error {
constructor(message, { status, report } = {}) { super(message); this.name = 'HunchError'; this.status = status; this.report = report; }
}
export class HunchClient {
constructor({ baseUrl = 'https://hunchagents.xyz', profile = 'conservative', timeoutMs = 22000 } = {}) {
const url = new URL(baseUrl);
if (url.protocol !== 'https:' && !(url.protocol === 'http:' && ['localhost','127.0.0.1'].includes(url.hostname))) throw new Error('Use HTTPS or a loopback development server.');
if (!['conservative','standard'].includes(profile)) throw new Error('Unknown Hunch policy profile.');
this.baseUrl = url; this.profile = profile; this.timeoutMs = timeoutMs;
}
async request(path, body) {
let response;
try { response = await fetch(new URL(path,this.baseUrl), { method:'POST', redirect:'error', headers:{'content-type':'application/json'}, body:JSON.stringify(body), signal:AbortSignal.timeout(this.timeoutMs) }); }
catch { throw new HunchError('Hunch is unavailable. Stop and request review.'); }
let result;
try { result = await response.json(); } catch { throw new HunchError('Hunch returned an unreadable result. Stop and request review.', {status:response.status}); }
if (!response.ok) throw new HunchError(result.error || 'Hunch could not complete the check.', {status:response.status});
return result;
}
inspectToken(address) { return this.request('/api/rh/intelligence',{address}); }
getDecisionContext({address, tokens = '1', counterAsset, transaction}) { return this.request('/api/rh/context',{address,tokens,...(counterAsset===undefined?{}:{counterAsset}),...(transaction===undefined?{}:{transaction})}); }
inspectInstrument(address, tokens = '1') { return this.request('/api/rh/instrument',{address,tokens}); }
inspectText(text) { return this.request('/api/text',{text}); }
assessAction({ address, amountUsd, slippageBps, text }) { return this.request('/api/rh/assess',{address,amountUsd,slippageBps,...(text !== undefined ? {text}:{}),profile:this.profile}); }
simulateTransaction(transaction) { return this.request('/api/rh/simulate',{transaction}); }
async requireWithinProfile(action) {
const report = await this.assessAction(action);
if (report.decision !== 'within_profile') throw new HunchError(`Action requires ${report.decision || 'review'}.`, {report});
return report;
}
}