@oracle-agent/oracle 0.35.4 → 0.35.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,19 @@
1
+ import V from"node:fs";import Z from"node:os";import Q from"node:path";import w from"node:fs";import j from"node:os";import S from"node:path";import{createHash as D,randomUUID as P}from"node:crypto";var E=1,x=Object.freeze([300*1e3,3600*1e3,14400*1e3,1440*60*1e3]),R=new Set(["prepare","no_trade"]),T=new Set(["buy","sell","long","short","hold","none"]),I=Object.freeze(["privatekey","secretkey","seed","mnemonic","passphrase","password","keystore","keymaterial","apikey","authtoken","accesstoken","refreshtoken","credential","bearer","signature","authorization","xprv","xpriv","wif"]);function h(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function f(e){return e==null?e:JSON.parse(JSON.stringify(e))}function b(e){return Array.isArray(e)?e.map(b):h(e)?Object.fromEntries(Object.keys(e).sort().map(r=>[r,b(e[r])])):e}function v(e){return JSON.stringify(b(e))}function $(e){return D("sha256").update(v(e),"utf8").digest("hex")}function H(e){return String(e).toLowerCase().replace(/[^a-z0-9]/g,"")}function g(e,r="$"){if(Array.isArray(e)){e.forEach((o,t)=>g(o,`${r}[${t}]`));return}if(h(e))for(let[o,t]of Object.entries(e)){let i=H(o);if(I.some(n=>i.includes(n)))throw new Error(`prepare-shadow-ledger: forbidden secret-like field at ${r}.${o}`);g(t,`${r}.${o}`)}}function p(e,r){if(e==null||e==="")return null;let o=Number(e);if(!Number.isFinite(o))throw new TypeError(`${r} must be finite`);return o}function l(e,r=256){return e==null||e===""?null:String(e).trim().slice(0,r)||null}function O(e,r,o=1){let t=Number(e);if(!Number.isInteger(t)||t<o)throw new TypeError(`${r} must be an integer >= ${o}`);return t}function J(e){let r=Array.isArray(e)&&e.length?e:x,o=[...new Set(r.map(t=>O(t,"horizonMs")))].sort((t,i)=>t-i);if(o.length>12)throw new TypeError("prepare-shadow-ledger: at most 12 horizons are allowed");return o}function F(e){return e==="buy"||e==="long"?1:e==="sell"||e==="short"?-1:0}function B(){return S.join(j.homedir(),".oracle","prepare-shadow-ledger.json")}function L(e){if(typeof e!="string"||!e||!S.isAbsolute(e))throw new Error("prepare-shadow-ledger: path must be absolute")}function k(e){let r;try{r=w.lstatSync(e)}catch(o){if(o?.code==="ENOENT")return;throw o}if(r.isSymbolicLink())throw new Error("prepare-shadow-ledger: store path must not be a symlink");if(!r.isFile())throw new Error("prepare-shadow-ledger: store path must be a regular file");if((r.mode&18)!==0)throw new Error("prepare-shadow-ledger: store file must not be group or world writable")}function q(){return{version:E,decisions:[],outcomes:[]}}function z(e,r){let o;try{o=JSON.parse(e)}catch{throw new Error("prepare-shadow-ledger: malformed JSON")}if(!h(o))throw new Error("prepare-shadow-ledger: malformed JSON root");if(o.version!==E)throw new Error(`prepare-shadow-ledger: unsupported version ${o.version}`);if(!Array.isArray(o.decisions))throw new Error("prepare-shadow-ledger: decisions must be an array");if(!Array.isArray(o.outcomes))throw new Error("prepare-shadow-ledger: outcomes must be an array");return g(o,S.basename(r)),{version:E,decisions:o.decisions.map(t=>f(t)),outcomes:o.outcomes.map(t=>f(t))}}function N(e,r){g(r,"store");let o=S.dirname(e);w.mkdirSync(o,{recursive:!0,mode:448});let t=S.join(o,`.prepare-shadow-ledger.${process.pid}.${Date.now()}.${P()}.tmp`);try{w.writeFileSync(t,`${JSON.stringify(r)}
2
+ `,{mode:384,flag:"wx"}),w.renameSync(t,e);try{w.chmodSync(e,384)}catch{}}catch(i){try{w.unlinkSync(t)}catch{}throw i}}function G(e={},r={}){if(!h(e))throw new TypeError("prepare-shadow-ledger: decision must be a plain object");g(e,"decision");let o=O(r.nowMs??e.createdAt??Date.now(),"createdAt",0),t=String(e.kind||"prepare").trim();if(!R.has(t))throw new TypeError("prepare-shadow-ledger: kind must be prepare or no_trade");let i=l(e.source,96)||"oracle",n=String(e.side||(t==="no_trade"?"none":"hold")).trim().toLowerCase();if(!T.has(n))throw new TypeError("prepare-shadow-ledger: side is invalid");let d={version:1,kind:t,source:i,createdAt:o,chain:l(e.chain,96),venue:l(e.venue,128),instrument:l(e.instrument??e.asset??e.market,160),side:n,intendedNotionalUsd:p(e.intendedNotionalUsd??e.notionalUsd,"intendedNotionalUsd"),decisionPriceUsd:p(e.decisionPriceUsd??e.priceUsd??e.midPriceUsd,"decisionPriceUsd"),score:p(e.score,"score"),confidence:p(e.confidence,"confidence"),signalId:l(e.signalId,128),prepareHash:l(e.prepareHash,128),routeId:l(e.routeId,128),simulation:h(e.simulation)?b(e.simulation):null,features:h(e.features)?b(e.features):null,note:l(e.note,512),horizonsMs:J(e.horizonsMs),executionAllowed:!1,custody:"none"};return d.id=l(e.id,128)||$({...d,id:void 0}),Object.freeze(d)}function K(e,r){let o=p(e?.decisionPriceUsd,"decisionPriceUsd"),t=p(r?.observedPriceUsd,"observedPriceUsd"),i=F(e?.side);return!(o>0)||!(t>0)||i===0?null:(t-o)/o*1e4*i}function W(e,r={},o={}){if(!h(e))throw new TypeError("prepare-shadow-ledger: decision required");if(!h(r))throw new TypeError("prepare-shadow-ledger: outcome must be a plain object");g(r,"outcome");let t=O(r.horizonMs,"horizonMs");if(!Array.isArray(e.horizonsMs)||!e.horizonsMs.includes(t))throw new Error("prepare-shadow-ledger: outcome horizon was not declared on the decision");let i=O(r.observedAt??o.nowMs??Date.now(),"observedAt",0);if(i<e.createdAt)throw new Error("prepare-shadow-ledger: observedAt cannot precede decision time");let n=p(r.quotedOut,"quotedOut"),d=p(r.actualOut,"actualOut"),s=p(r.observedPriceUsd??r.priceUsd,"observedPriceUsd"),a=p(r.gasUsd,"gasUsd"),c=K(e,{observedPriceUsd:s}),u=n>0&&d!=null?(d-n)/n*1e4:null,m=e.kind==="no_trade"?c==null?null:c<=0:c==null?null:c>0,U={id:l(r.id,128)||$({decisionId:e.id,horizonMs:t,observedAt:i,observedPriceUsd:s,quotedOut:n,actualOut:d,gasUsd:a}),decisionId:e.id,horizonMs:t,observedAt:i,observedPriceUsd:s,quotedOut:n,actualOut:d,outputDeltaBps:u,gasUsd:a,forwardReturnBps:c,good:m,txHash:l(r.txHash??r.transactionHash,128),source:l(r.source,96)||"mark",note:l(r.note,512)};return Object.freeze(U)}var A=new Map;function C(e={}){let r=e.path||B();if(L(r),k(r),w.existsSync(r)?z(w.readFileSync(r,"utf8"),r):N(r,q()),A.has(r))return A.get(r);function o(){return k(r),z(w.readFileSync(r,"utf8"),r)}function t(n){N(r,n)}let i=Object.freeze({path:r,record(n,d={}){let s=G(n,d),a=o();if(a.decisions.some(c=>c.id===s.id))throw new Error(`prepare-shadow-ledger: decision id already exists: ${s.id}`);return a.decisions.push(f(s)),t(a),f(s)},mark(n,d,s={}){let a=o(),c=a.decisions.find(m=>m.id===n);if(!c)throw new Error(`prepare-shadow-ledger: decision not found: ${n}`);let u=W(c,d,s);if(a.outcomes.some(m=>m.decisionId===u.decisionId&&m.horizonMs===u.horizonMs))throw new Error("prepare-shadow-ledger: outcome already exists for decision horizon");return a.outcomes.push(f(u)),t(a),f(u)},list({kind:n}={}){return o().decisions.filter(s=>!n||s.kind===n).map(s=>f(s))},get(n){let d=o(),s=d.decisions.find(c=>c.id===n);if(!s)return null;let a=d.outcomes.filter(c=>c.decisionId===n);return{decision:f(s),outcomes:a.map(c=>f(c))}},outcomes(n=null){return o().outcomes.filter(s=>!n||s.decisionId===n).map(s=>f(s))},summary(){let n=o();return Y(n)}});return A.set(r,i),i}function Y(e={}){let r=Array.isArray(e.decisions)?e.decisions:[],o=Array.isArray(e.outcomes)?e.outcomes:[],t={prepare:0,no_trade:0};for(let s of r)s.kind in t&&(t[s.kind]+=1);let i=new Map,n=new Map(r.map(s=>[s.id,s]));for(let s of o){let a=n.get(s.decisionId),c=String(s.horizonMs);i.has(c)||i.set(c,{horizonMs:s.horizonMs,count:0,prepareCount:0,noTradeCount:0,goodCount:0,knownGoodCount:0,avgForwardReturnBps:null,avgOutputDeltaBps:null});let u=i.get(c);u.count+=1,a?.kind==="prepare"&&(u.prepareCount+=1),a?.kind==="no_trade"&&(u.noTradeCount+=1),typeof s.good=="boolean"&&(u.knownGoodCount+=1,s.good&&(u.goodCount+=1)),Number.isFinite(s.forwardReturnBps)&&(u._forwardSum=(u._forwardSum||0)+s.forwardReturnBps,u._forwardCount=(u._forwardCount||0)+1),Number.isFinite(s.outputDeltaBps)&&(u._outputSum=(u._outputSum||0)+s.outputDeltaBps,u._outputCount=(u._outputCount||0)+1)}let d=[...i.values()].sort((s,a)=>s.horizonMs-a.horizonMs).map(s=>{let a={...s};return s._forwardCount&&(a.avgForwardReturnBps=s._forwardSum/s._forwardCount),s._outputCount&&(a.avgOutputDeltaBps=s._outputSum/s._outputCount),a.goodRate=s.knownGoodCount?s.goodCount/s.knownGoodCount:null,delete a._forwardSum,delete a._forwardCount,delete a._outputSum,delete a._outputCount,a});return{version:E,totalDecisions:r.length,totalOutcomes:o.length,byKind:t,horizons:d,verdict:r.length===0?"empty: no prepare or NO_TRADE decisions recorded yet":"shadow ledger active: prepares and NO_TRADE calls can be graded before arming"}}var _=`oracle shadow <record|mark|list|get|outcomes|summary> [args]
3
+
4
+ oracle shadow record --json '{"kind":"prepare","source":"signal_score","instrument":"HYPE","side":"buy","decisionPriceUsd":44}'
5
+ oracle shadow mark <decision-id> --json '{"horizonMs":300000,"observedPriceUsd":45}'
6
+ oracle shadow list --json
7
+ oracle shadow get <decision-id>
8
+ oracle shadow outcomes <decision-id>
9
+ oracle shadow summary --json
10
+
11
+ Records prepare and NO_TRADE decisions only. No signing, no broadcast, no keys.
12
+ `;function X(e=[]){let r={},o=[];for(let t=0;t<e.length;t++){let i=e[t];if(!i.startsWith("--")){o.push(i);continue}let n=i.slice(2),d=e[t+1];d!=null&&!d.startsWith("--")?(r[n]=d,t+=1):r[n]=!0}return{flags:r,positional:o}}function ee(){return Q.join(Z.homedir(),".oracle","prepare-shadow-ledger.json")}function M(e,r){let o=e.json??e.file;if(!o)throw new Error(`shadow ${r}: --json or --file required`);let t=e.file?V.readFileSync(String(e.file),"utf8"):String(o);try{return JSON.parse(t)}catch{throw new Error(`shadow ${r}: input must be valid JSON`)}}function y(e){process.stdout.write(`${JSON.stringify(e,null,2)}
13
+ `)}function re(e){if(!e.length){process.stdout.write(`no shadow decisions
14
+ `);return}for(let r of e)process.stdout.write(`${r.id} ${r.kind} ${r.source} ${r.chain||"?"}/${r.instrument||"?"} ${r.side}
15
+ `)}function oe(e,r=process.env){if(e.store&&r.ORACLE_CHAT_TOOL==="1")throw new Error("shadow --store is unavailable from oracle_cli; use the default ledger store");return e.store||ee()}var fe={name:"shadow",summary:"prepare and NO_TRADE shadow ledger with outcome grading",group:"read",usage:_,async run(e){let{flags:r,positional:o}=X(e.argv||[]),t=o[0];if(!t||r.help)return process.stdout.write(_),0;let i=C({path:oe(r)});if(t==="record"){let n=i.record(M(r,"record"));return y({ok:!0,decision:n}),0}if(t==="mark"){let n=o[1];if(!n)throw new Error("shadow mark: decision id required");let d=i.mark(n,M(r,"mark"));return y({ok:!0,outcome:d}),0}if(t==="list"){let n=i.list({kind:r.kind});return r.json?y({decisions:n}):re(n),0}if(t==="get"){let n=o[1];if(!n)throw new Error("shadow get: decision id required");let d=i.get(n);return d?(y(d),0):(process.stderr.write(`shadow decision not found
16
+ `),1)}if(t==="outcomes")return y({outcomes:i.outcomes(o[1]||null)}),0;if(t==="summary"){let n=i.summary();if(r.json)y(n);else{process.stdout.write(`${n.verdict}
17
+ `),process.stdout.write(`decisions ${n.totalDecisions} outcomes ${n.totalOutcomes}
18
+ `);for(let d of n.horizons)process.stdout.write(`horizon ${d.horizonMs}ms count ${d.count} goodRate ${d.goodRate??"unknown"}
19
+ `)}return 0}return process.stderr.write(_),1}};export{fe as default};