@oracle-agent/oracle 0.35.18 → 0.35.20
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.
- package/dist/assets/skills/oracle-desk-product/SKILL.md +1 -1
- package/dist/bin/oracle-data-mcp.mjs +12 -11
- package/dist/bin/oracle-gateway.mjs +3 -3
- package/dist/bin/oracle-telegram-mcp.mjs +5 -5
- package/dist/cli/commands/chat.mjs +177 -177
- package/dist/cli/commands/doctor.mjs +7 -7
- package/dist/cli/commands/eval.mjs +110 -110
- package/dist/cli/commands/model.mjs +183 -183
- package/dist/cli/commands/quickstart.mjs +6 -6
- package/dist/cli/commands/sign.mjs +12 -12
- package/dist/cli/commands/signer.mjs +23 -17
- package/dist/cli/commands/swap.mjs +10 -10
- package/dist/cli/commands/telegram.mjs +6 -6
- package/dist/cli/commands/venues.mjs +2 -2
- package/dist/local-signer/anvil-attestation-worker.mjs +1 -1
- package/dist/local-signer/index.mjs +3 -3
- package/dist/local-signer/runtime.mjs +20 -14
- package/package.json +1 -1
- package/public/eval-report.json +23 -9
- package/public/oracle-splash/index.html +43 -22
- package/server.json +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
var vr=Object.defineProperty;var w=(t,e,r)=>()=>{if(r)throw r[0];try{return t&&(e=t(t=0)),e}catch(n){throw r=[n],n}};var j=(t,e)=>{for(var r in e)vr(t,r,{get:e[r],enumerable:!0})};var We={};j(We,{A2ABus:()=>fe,normalizeName:()=>Q});function Q(t){return String(t||"").trim().toLowerCase().replace(/^@/,"")}var fe,ze=w(()=>{fe=class{constructor({maxHops:e=4,historyCap:r=200}={}){this.maxHops=e,this.historyCap=r,this.agents=new Map,this.history=[],this.seq=0}register(e,{role:r="",chains:n=[],handler:o}={}){let a=Q(e);if(!a)throw new Error("a2a: agent name required");if(this.agents.has(a))throw new Error(`a2a: agent '${a}' already registered`);if(typeof o!="function")throw new Error(`a2a: agent '${a}' needs a handler`);return this.agents.set(a,{name:a,role:String(r),chains:n.map(String),handler:o}),this.agents.get(a)}unregister(e){this.agents.delete(Q(e))}roster(){return[...this.agents.values()].map(({name:e,role:r,chains:n})=>({name:e,role:r,chains:n}))}async send({from:e,to:r,text:n,kind:o="consult",hops:a=0}={}){let i=Q(e),l=Q(r);if(!i||!this.agents.has(i))return{ok:!1,error:`a2a: unknown sender '${e}'`};if(!l||!this.agents.has(l))return{ok:!1,error:`a2a: unknown recipient '${r}' (roster: ${[...this.agents.keys()].join(", ")||"empty"})`};if(l===i)return{ok:!1,error:"a2a: self-send refused"};let c=String(n||"").trim().slice(0,8e3);if(!c)return{ok:!1,error:"a2a: empty message"};let s=Number(a)+1;if(s>this.maxHops)return this.record({from:i,to:l,kind:o,dropped:"hop-limit"}),{ok:!1,error:`a2a: hop limit ${this.maxHops} reached \u2014 dropped`};let d={id:`a2a-${Date.now()}-${++this.seq}`,from:i,to:l,kind:String(o),text:c,hops:s,ts:new Date().toISOString()};this.record(d);try{let p=await this.agents.get(l).handler(d);return p&&this.record({id:`${d.id}-reply`,from:l,to:i,kind:"reply",text:String(p).slice(0,8e3),hops:s,ts:new Date().toISOString()}),{ok:!0,reply:p||null,id:d.id}}catch(p){return{ok:!1,error:`a2a: '${l}' handler failed: ${p.message}`}}}record(e){this.history.push(e),this.history.length>this.historyCap&&this.history.splice(0,this.history.length-this.historyCap)}recent(e=20){return this.history.slice(-e)}}});import Z from"node:fs";import Ar from"node:os";import F from"node:path";import{fileURLToPath as Cr}from"node:url";function he(){return process.env.ORACLE_FAKE_HOME||Ar.homedir()}function _r(){return process.env.ORACLE_PUBLIC_DESKTOP==="1"}function $(){return _r()?process.env.ORACLE_CONFIG_DIR||F.join(he(),".config","oracle"):F.join(he(),".config","oracle")}function Er(){return F.join($(),"desk.json")}function Or(){return F.join($(),"env")}function B({force:t=!1}={}){if(B._done&&!t)return B._result||null;B._done=!0;let e={},r=(o,a)=>{if(a==null)return;let i=String(a).trim();i&&(process.env[o]!=null&&String(process.env[o]).trim()!==""||(process.env[o]=i,e[o]=i))};try{let o=Or();if(Z.existsSync(o))for(let a of Z.readFileSync(o,"utf8").split(/\r?\n/)){let i=a.match(/^\s*([A-Z0-9_]+)\s*=\s*(.*?)\s*$/);if(!i||i[2].startsWith("#"))continue;let l=i[2];(l.startsWith('"')&&l.endsWith('"')||l.startsWith("'")&&l.endsWith("'"))&&(l=l.slice(1,-1)),r(i[1],l)}}catch{}try{let o=Er();if(Z.existsSync(o)){let a=JSON.parse(Z.readFileSync(o,"utf8"));a&&typeof a=="object"&&(r("ORACLE_DESK_URL",a.deskUrl||a.dataUrl||a.url),r("ORACLE_DATA_URL",a.dataUrl||a.deskUrl||a.url),r("ORACLE_API_URL",a.apiUrl||a.dataUrl||a.deskUrl),r("ORACLE_PUBLIC_URL",a.publicUrl||a.deskUrl||a.dataUrl),r("ORACLE_EXEC_URL",a.execUrl),r("MAD_DESK_URL",a.deskUrl||a.dataUrl))}}catch{}let n=process.env.ORACLE_DESK_URL||process.env.ORACLE_DATA_URL||"";return n&&(r("ORACLE_DESK_URL",n),r("ORACLE_DATA_URL",n),r("ORACLE_API_URL",n),r("ORACLE_PUBLIC_URL",n),r("MAD_DESK_URL",n)),B._result=Object.keys(e).length?e:null,B._result}function ae(t){return Z.mkdirSync(t,{recursive:!0}),t}var $r,Go,ie=w(()=>{$r=F.dirname(Cr(import.meta.url)),Go=F.resolve($r,"../..");try{B()}catch{}});function se(t){return String(t||"").trim()||void 0}function Nr(t,{required:e=!1}={}){let r=se(t)?.toLowerCase();if(!r){if(e)throw new Error("model provider is required");return}if(!Rr.has(r))throw new Error(`unsupported provider: ${r}`);return r}function Lr(t,{required:e=!1}={}){let r=se(t);if(!r){if(e)throw new Error("model is required");return}if(r.includes("..")||r.startsWith("/")||!/^[a-zA-Z0-9._:/-]{1,200}$/.test(r))throw new Error("invalid model id");return r}function Ir(t){let e=se(t);if(!e||e.length>2048)throw new Error("invalid custom base URL");let r;try{r=new URL(e)}catch{throw new Error("invalid custom base URL")}let n=r.hostname.toLowerCase().replace(/^\[|\]$/g,""),o=n==="localhost"||n==="127.0.0.1"||n==="::1";if(r.protocol!=="https:"&&!(r.protocol==="http:"&&o)||r.username||r.password||r.search||r.hash)throw new Error("custom base URL must use HTTPS or loopback HTTP without credentials, query, or fragment");return r.toString().replace(/\/+$/,"")}function Ve({provider:t,model:e,baseUrl:r}={},{requireModel:n=!1}={}){let o=Nr(t),a=Lr(e,{required:n});if(o==="custom")return{provider:o,...a?{model:a}:{},baseUrl:Ir(r)};if(se(r))throw new Error("baseUrl is only supported for the custom provider");return{...o?{provider:o}:{},...a?{model:a}:{}}}var Rr,Ke=w(()=>{Rr=new Set(["openrouter","openai","anthropic","xai","deepseek","gemini","kimi","mistral","nous","qwen","glm","local","ollama","custom","anthropic-oauth","openai-codex","xai-oauth"])});import G from"node:fs";import ge from"node:path";function Ye(){return ge.join($(),"model.json")}function H(t){return String(t||"").trim()||void 0}function Je(t={}){let e=H(t.backend)?.toLowerCase()||"auto",r=Ve({provider:t.provider,model:t.model,baseUrl:t.baseUrl},{requireModel:e==="standalone"}),n=H(t.apiKeyEnv),o=Number.parseInt(String(t.contextLength||""),10),a=H(t.reasoningEffort),i=H(t.computeHost||t.remoteHost),l=H(t.computeUser||t.remoteUser),c=H(t.computePath||t.remotePath);if(!Tr.has(e))throw new Error(`unsupported backend: ${e}`);if(process.env.ORACLE_PUBLIC_DESKTOP==="1"&&["remote","arch"].includes(e))throw new Error("remote compute backends are disabled in the public desktop");if(n&&!/^[A-Z][A-Z0-9_]*$/.test(n))throw new Error("api key env must be an uppercase environment variable name");if(e==="remote"&&!i)throw new Error("remote backend requires computeHost");return{backend:e,...r,...n?{apiKeyEnv:n}:{},...Number.isFinite(o)&&o>0?{contextLength:o}:{},...a?{reasoningEffort:a}:{},...i?{computeHost:i}:{},...l?{computeUser:l}:{},...c?{computePath:c}:{}}}function q(){let t=Ye();if(!G.existsSync(t))return null;try{return Je(JSON.parse(G.readFileSync(t,"utf8")))}catch{return null}}function ye(t){let e=Je(t),r=Ye();ae(ge.dirname(r)),process.platform!=="win32"&&G.chmodSync(ge.dirname(r),448);let n=`${r}.${process.pid}.tmp`;return G.writeFileSync(n,`${JSON.stringify(e,null,2)}
|
|
3
|
-
`,{mode:384}),G.renameSync(n,r),process.platform!=="win32"&&G.chmodSync(r,384),e}var Tr,Xe=w(()=>{ie();Ke();Tr=new Set(["auto","standalone","hermes","remote","arch"])});import{existsSync as Pr,readFileSync as Mr}from"node:fs";import{request as Ur}from"node:http";import Dr from"node:path";function Br(t=process.env){let e=String(t.ORACLE_SIGNER_URL||jr).replace(/\/$/,""),r;try{r=new URL(e)}catch{return null}return r.hostname!=="127.0.0.1"&&r.hostname!=="localhost"&&r.hostname!=="::1"?null:r.origin}function Fr(t=process.env){if(t.ORACLE_SIGNER_TOKEN)return String(t.ORACLE_SIGNER_TOKEN);let e=Dr.join($(),"signer","signer-token");return Pr(e)?Mr(e,"utf8").trim():null}function T(t,{method:e="GET",body:r=null,env:n=process.env,timeoutMs:o=4e3}={}){let a=Br(n),i=Fr(n);return!a||!i?Promise.resolve({ok:!1,error:"local signer is not running"}):new Promise(l=>{let c=new URL(t,a),s=r?Buffer.from(JSON.stringify(r)):null,d=Ur({hostname:c.hostname,port:c.port||80,path:c.pathname,method:e,timeout:o,headers:{authorization:`Bearer ${i}`,origin:a,...s?{"content-type":"application/json","content-length":s.length}:{}}},p=>{let m=[];p.on("data",h=>m.push(h)),p.on("end",()=>{let h=Buffer.concat(m).toString("utf8"),g={};try{g=h?JSON.parse(h):{}}catch{g={error:"signer refused"}}l({httpStatus:p.statusCode,...g})})});d.on("timeout",()=>{d.destroy(),l({ok:!1,error:"local signer timed out"})}),d.on("error",()=>l({ok:!1,error:"local signer is not running"})),s&&d.write(s),d.end()})}var jr,ce=w(()=>{ie();jr="http://127.0.0.1:9462"});function Qe(t){return Gr.get(Number(t))||null}var Hr,Gr,Ze=w(()=>{Hr={robinhood:{chainId:4663,name:"Robinhood Chain",rpcEnv:["RH_CHAIN_RPC"],evm:!0},ethereum:{chainId:1,name:"Ethereum",rpcEnv:["ETH_RPC_URL","ETHEREUM_RPC_URL","MAINNET_RPC_URL"],evm:!0},polygon:{chainId:137,name:"Polygon",rpcEnv:["POLYGON_RPC_URL","POLYGON_RPC"],evm:!0},arbitrum:{chainId:42161,name:"Arbitrum One",rpcEnv:["ARBITRUM_RPC_URL","ARB_RPC_URL"],evm:!0},base:{chainId:8453,name:"Base",rpcEnv:["BASE_RPC_URL"],evm:!0},hyperevm:{chainId:999,name:"HyperEVM",rpcEnv:["HYPEREVM_RPC_URL","HYPER_EVM_RPC"],evm:!0},bsc:{chainId:56,name:"BNB Smart Chain",rpcEnv:["BSC_RPC_URL","BNB_RPC_URL"],evm:!0},avalanche:{chainId:43114,name:"Avalanche C-Chain",rpcEnv:["AVALANCHE_RPC_URL","AVAX_RPC_URL"],evm:!0},optimism:{chainId:10,name:"OP Mainnet",rpcEnv:["OPTIMISM_RPC_URL","OP_RPC_URL"],evm:!0},abstract:{chainId:2741,name:"Abstract",rpcEnv:["ABSTRACT_RPC_URL","ABS_RPC_URL"],evm:!0},stable:{chainId:988,name:"Stable Mainnet",rpcEnv:["STABLE_RPC_URL","STABLE_RPC"],evm:!0}},Gr=new Map(Object.values(Hr).map(t=>[t.chainId,t]))});function Wr(t){let e=String(t||"").trim();if(!e||e.includes("ts.net")||!/^https:\/\//i.test(e))return null;try{return new URL(e)}catch{return null}}function et(t,{coin:e,side:r,sizeUsd:n,leverage:o,venue:a,confirm:i,user:l}={}){let c=Wr(t);if(!c)return null;if(e&&qr.test(String(e).toUpperCase())&&c.searchParams.set("coin",String(e).toUpperCase()),(r==="long"||r==="short")&&c.searchParams.set("side",r),Number.isFinite(Number(n))&&Number(n)>=1&&c.searchParams.set("size",String(Math.min(1e5,Math.round(Number(n))))),Number.isInteger(Number(o))&&Number(o)>=1&&c.searchParams.set("lev",String(Math.min(50,Number(o)))),a){let s=String(a).toLowerCase()==="hl"?"hyperliquid":String(a).toLowerCase();c.searchParams.set("venue",s)}else c.searchParams.get("venue")||c.searchParams.set("venue","hyperliquid");return c.searchParams.set("view","perps"),c.searchParams.set("build","1"),i&&/^[0-9a-f]{32}$/i.test(String(i))&&c.searchParams.set("confirm",String(i).toLowerCase()),l&&/^0x[0-9a-fA-F]{40}$/.test(String(l))&&c.searchParams.set("user",String(l).toLowerCase()),c.toString()}var qr,we=w(()=>{qr=/^[A-Z0-9][A-Z0-9._-]{0,11}$/});var ia,sa,tt=w(()=>{we();ia=Object.freeze([100,50,25]),sa=Object.freeze([100,50,25,10])});function u(t){return S(t)?String(t).replace(zr,e=>`\\${e}`):f}function S(t){return t==null?!1:typeof t=="number"?Number.isFinite(t):typeof t=="string"?t.trim()!=="":!0}function A(t){if(!S(t))return f;let e=String(t).replace(/`/g,"");return e===""?f:`\`${e}\``}function P(t,{decimals:e=2}={}){if(!S(t))return f;let r=Number(t);return Number.isFinite(r)?r.toLocaleString("en-US",{minimumFractionDigits:0,maximumFractionDigits:e}):f}function b(t,{decimals:e=2}={}){let r=P(t,{decimals:e});return r===f?f:`${r} USD`}function ke(t,{decimals:e=2}={}){let r=P(t,{decimals:e});return r===f?f:`${r}%`}function le(t){let e=P(t,{decimals:0});return e===f?f:`${e} bps`}function M(t,e){if(!S(t))return f;let r=Number(e);if(!Number.isInteger(r)||r<0||r>77)return f;let n;try{n=BigInt(typeof t=="string"?t.trim():t)}catch{return f}let o=n<0n,a=o?-n:n,i=10n**BigInt(r),l=(a/i).toString(),c=(a%i).toString().padStart(r,"0").replace(/0+$/,"");return`${o?"-":""}${l}${c?`.${c}`:""}`}function Se(t){if(typeof t=="number"&&Number.isFinite(t))return t<0||t>1?f:t>=.75?"HIGH":t>=.4?"MEDIUM":"LOW";if(typeof t=="string"){let e=t.trim().toUpperCase();if(e==="HIGH"||e==="MEDIUM"||e==="LOW")return e}return f}function R(t={}){let e=t.chainId;if(!S(e)||!Number.isFinite(Number(e)))return S(t.chain)?u(t.chain):f;let n=Qe(e)?.name||(S(t.chain)?String(t.chain):f);return`${u(n)} (chainId ${Number(e)})`}function rt(t={}){return u(t.venue??t.dex??t.pool?.venue)}function Vr(t){return t==null?"NONE (text card only)":typeof t=="string"?t.trim()?A(t):"NONE (text card only)":t.error||t.ok===!1||t.available===!1?`UNAVAILABLE${S(t.error)?` \u2014 ${u(t.error)}`:""} (text card stands)`:S(t.url)?A(t.url):"NONE (text card only)"}function U(t={},{now:e=Date.now()}={}){let r=t.grant??t.session??null;if(!r||typeof r!="object")return{allowed:!1,reason:"no local grant/session",actions:[]};if(r.local===!1)return{allowed:!1,reason:"grant is not local",actions:[]};if(r.revoked===!0)return{allowed:!1,reason:"grant revoked",actions:[]};let n=r.expiresAt??r.expiry;if(S(n)){let a=typeof n=="number"?n:Date.parse(n);if(!Number.isFinite(a))return{allowed:!1,reason:"grant expiry unreadable",actions:[]};if(a<=e)return{allowed:!1,reason:"grant expired",actions:[]}}return{allowed:!0,reason:"valid local grant",actions:Array.isArray(r.actions)&&r.actions.length?r.actions.slice():["BUY","SELL"]}}function Kr(t){let e=U(t);return e.allowed?`${e.actions.map(r=>u(r)).join(" / ")} (${u(e.reason)})`:`prepare-only \u2014 ${u(e.reason)}`}function _(t,e,r={}){let n=[`*${t}*`];for(let
|
|
4
|
-
`)}function E(t){return["Confidence",
|
|
3
|
+
`,{mode:384}),G.renameSync(n,r),process.platform!=="win32"&&G.chmodSync(r,384),e}var Tr,Xe=w(()=>{ie();Ke();Tr=new Set(["auto","standalone","hermes","remote","arch"])});import{existsSync as Pr,readFileSync as Mr}from"node:fs";import{request as Ur}from"node:http";import Dr from"node:path";function Br(t=process.env){let e=String(t.ORACLE_SIGNER_URL||jr).replace(/\/$/,""),r;try{r=new URL(e)}catch{return null}return r.hostname!=="127.0.0.1"&&r.hostname!=="localhost"&&r.hostname!=="::1"?null:r.origin}function Fr(t=process.env){if(t.ORACLE_SIGNER_TOKEN)return String(t.ORACLE_SIGNER_TOKEN);let e=Dr.join($(),"signer","signer-token");return Pr(e)?Mr(e,"utf8").trim():null}function T(t,{method:e="GET",body:r=null,env:n=process.env,timeoutMs:o=4e3}={}){let a=Br(n),i=Fr(n);return!a||!i?Promise.resolve({ok:!1,error:"local signer is not running"}):new Promise(l=>{let c=new URL(t,a),s=r?Buffer.from(JSON.stringify(r)):null,d=Ur({hostname:c.hostname,port:c.port||80,path:c.pathname,method:e,timeout:o,headers:{authorization:`Bearer ${i}`,origin:a,...s?{"content-type":"application/json","content-length":s.length}:{}}},p=>{let m=[];p.on("data",h=>m.push(h)),p.on("end",()=>{let h=Buffer.concat(m).toString("utf8"),g={};try{g=h?JSON.parse(h):{}}catch{g={error:"signer refused"}}l({httpStatus:p.statusCode,...g})})});d.on("timeout",()=>{d.destroy(),l({ok:!1,error:"local signer timed out"})}),d.on("error",()=>l({ok:!1,error:"local signer is not running"})),s&&d.write(s),d.end()})}var jr,ce=w(()=>{ie();jr="http://127.0.0.1:9462"});function Qe(t){return Gr.get(Number(t))||null}var Hr,Gr,Ze=w(()=>{Hr={robinhood:{chainId:4663,name:"Robinhood Chain",rpcEnv:["RH_CHAIN_RPC"],evm:!0},ethereum:{chainId:1,name:"Ethereum",rpcEnv:["ETH_RPC_URL","ETHEREUM_RPC_URL","MAINNET_RPC_URL"],evm:!0},polygon:{chainId:137,name:"Polygon",rpcEnv:["POLYGON_RPC_URL","POLYGON_RPC"],evm:!0},arbitrum:{chainId:42161,name:"Arbitrum One",rpcEnv:["ARBITRUM_RPC_URL","ARB_RPC_URL"],evm:!0},base:{chainId:8453,name:"Base",rpcEnv:["BASE_RPC_URL"],evm:!0},hyperevm:{chainId:999,name:"HyperEVM",rpcEnv:["HYPEREVM_RPC_URL","HYPER_EVM_RPC"],evm:!0},bsc:{chainId:56,name:"BNB Smart Chain",rpcEnv:["BSC_RPC_URL","BNB_RPC_URL"],evm:!0},avalanche:{chainId:43114,name:"Avalanche C-Chain",rpcEnv:["AVALANCHE_RPC_URL","AVAX_RPC_URL"],evm:!0},optimism:{chainId:10,name:"OP Mainnet",rpcEnv:["OPTIMISM_RPC_URL","OP_RPC_URL"],evm:!0},abstract:{chainId:2741,name:"Abstract",rpcEnv:["ABSTRACT_RPC_URL","ABS_RPC_URL"],evm:!0},stable:{chainId:988,name:"Stable Mainnet",rpcEnv:["STABLE_RPC_URL","STABLE_RPC"],evm:!0}},Gr=new Map(Object.values(Hr).map(t=>[t.chainId,t]))});function Wr(t){let e=String(t||"").trim();if(!e||e.includes("ts.net")||!/^https:\/\//i.test(e))return null;try{return new URL(e)}catch{return null}}function et(t,{coin:e,side:r,sizeUsd:n,leverage:o,venue:a,confirm:i,user:l}={}){let c=Wr(t);if(!c)return null;if(e&&qr.test(String(e).toUpperCase())&&c.searchParams.set("coin",String(e).toUpperCase()),(r==="long"||r==="short")&&c.searchParams.set("side",r),Number.isFinite(Number(n))&&Number(n)>=1&&c.searchParams.set("size",String(Math.min(1e5,Math.round(Number(n))))),Number.isInteger(Number(o))&&Number(o)>=1&&c.searchParams.set("lev",String(Math.min(50,Number(o)))),a){let s=String(a).toLowerCase()==="hl"?"hyperliquid":String(a).toLowerCase();c.searchParams.set("venue",s)}else c.searchParams.get("venue")||c.searchParams.set("venue","hyperliquid");return c.searchParams.set("view","perps"),c.searchParams.set("build","1"),i&&/^[0-9a-f]{32}$/i.test(String(i))&&c.searchParams.set("confirm",String(i).toLowerCase()),l&&/^0x[0-9a-fA-F]{40}$/.test(String(l))&&c.searchParams.set("user",String(l).toLowerCase()),c.toString()}var qr,we=w(()=>{qr=/^[A-Z0-9][A-Z0-9._-]{0,11}$/});var ia,sa,tt=w(()=>{we();ia=Object.freeze([100,50,25]),sa=Object.freeze([100,50,25,10])});function u(t){return S(t)?String(t).replace(zr,e=>`\\${e}`):f}function S(t){return t==null?!1:typeof t=="number"?Number.isFinite(t):typeof t=="string"?t.trim()!=="":!0}function A(t){if(!S(t))return f;let e=String(t).replace(/`/g,"");return e===""?f:`\`${e}\``}function P(t,{decimals:e=2}={}){if(!S(t))return f;let r=Number(t);return Number.isFinite(r)?r.toLocaleString("en-US",{minimumFractionDigits:0,maximumFractionDigits:e}):f}function b(t,{decimals:e=2}={}){let r=P(t,{decimals:e});return r===f?f:`${r} USD`}function ke(t,{decimals:e=2}={}){let r=P(t,{decimals:e});return r===f?f:`${r}%`}function le(t){let e=P(t,{decimals:0});return e===f?f:`${e} bps`}function M(t,e){if(!S(t))return f;let r=Number(e);if(!Number.isInteger(r)||r<0||r>77)return f;let n;try{n=BigInt(typeof t=="string"?t.trim():t)}catch{return f}let o=n<0n,a=o?-n:n,i=10n**BigInt(r),l=(a/i).toString(),c=(a%i).toString().padStart(r,"0").replace(/0+$/,"");return`${o?"-":""}${l}${c?`.${c}`:""}`}function Se(t){if(typeof t=="number"&&Number.isFinite(t))return t<0||t>1?f:t>=.75?"HIGH":t>=.4?"MEDIUM":"LOW";if(typeof t=="string"){let e=t.trim().toUpperCase();if(e==="HIGH"||e==="MEDIUM"||e==="LOW")return e}return f}function R(t={}){let e=t.chainId;if(!S(e)||!Number.isFinite(Number(e)))return S(t.chain)?u(t.chain):f;let n=Qe(e)?.name||(S(t.chain)?String(t.chain):f);return`${u(n)} (chainId ${Number(e)})`}function rt(t={}){return u(t.venue??t.dex??t.pool?.venue)}function Vr(t){return t==null?"NONE (text card only)":typeof t=="string"?t.trim()?A(t):"NONE (text card only)":t.error||t.ok===!1||t.available===!1?`UNAVAILABLE${S(t.error)?` \u2014 ${u(t.error)}`:""} (text card stands)`:S(t.url)?A(t.url):"NONE (text card only)"}function U(t={},{now:e=Date.now()}={}){let r=t.grant??t.session??null;if(!r||typeof r!="object")return{allowed:!1,reason:"no local grant/session",actions:[]};if(r.local===!1)return{allowed:!1,reason:"grant is not local",actions:[]};if(r.revoked===!0)return{allowed:!1,reason:"grant revoked",actions:[]};let n=r.expiresAt??r.expiry;if(S(n)){let a=typeof n=="number"?n:Date.parse(n);if(!Number.isFinite(a))return{allowed:!1,reason:"grant expiry unreadable",actions:[]};if(a<=e)return{allowed:!1,reason:"grant expired",actions:[]}}return{allowed:!0,reason:"valid local grant",actions:Array.isArray(r.actions)&&r.actions.length?r.actions.slice():["BUY","SELL"]}}function Kr(t){let e=U(t);return e.allowed?`${e.actions.map(r=>u(r)).join(" / ")} (${u(e.reason)})`:`prepare-only \u2014 ${u(e.reason)}`}function _(t,e,r={}){let n=[`*${t}*`];for(let o of e){if(!o)continue;let[a,i]=o;n.push(`${a}: ${i==null||i===""?f:i}`)}return n.push(`Chart: ${Vr(r.chart)}`),n.push(`Actions: ${Kr(r)}`),Array.isArray(r.warnings)&&r.warnings.length&&n.push(`Warnings: ${r.warnings.map(o=>u(o)).join("; ")}`),(S(r.source)||S(r.fetchedAt))&&n.push(`Source: ${u(r.source)} at ${u(r.fetchedAt)}`),n.join(`
|
|
4
|
+
`)}function E(t){let e=Se(t.confidence);return e===f?null:["Confidence",e]}function Yr(t){let e=t.quote;if(!e||typeof e!="object")return[];let r=S(e.decimals)?M(e.amountOutRaw??e.out??e.raw,e.decimals):f;return[["Quote out (raw)",A(e.amountOutRaw??e.out??e.raw)],["Quote out",r===f?f:`${u(r)} ${u(e.symbol??"")}`.trim()]]}function nt(t){let e=t.autoSlippage;if(!e||typeof e!="object")return["Auto-slippage",f];let r=le(e.selectedBps),n=le(e.capBps);return["Auto-slippage",r===f&&n===f?f:`${r} selected, cap ${n}`]}function Jr(t={}){let e=t||{};return _(`ORACLE TOKEN \u2014 ${u(e.symbol??e.token??e.name)}`,[["Chain",R(e)],["Venue",rt(e)],["Name",u(e.name)],["Address",A(e.address??e.mint??e.contract)],["Price",b(e.priceUsd,{decimals:8})],["Market cap",b(e.marketCapUsd)],["Liquidity",b(e.liquidityUsd)],["Volume 24h",b(e.volume24hUsd)],["Change 24h",ke(e.priceChange24h)],["Fee tier",S(e.feeTier)?`${le(Number(e.feeTier)/100)} (${P(e.feeTier,{decimals:0})})`:f],["Age",u(e.age)],...Yr(e),nt(e),E(e)],e)}function Xr(t={}){let e=t||{};return _(`ORACLE LAUNCH \u2014 ${u(e.symbol??e.token??e.name)}`,[["Chain",R(e)],["Venue",rt(e)],["Address",A(e.address??e.mint??e.contract)],["Pool",A(e.pool?.address??e.poolAddress??e.pool)],["Liquidity",b(e.liquidityUsd)],["Route ready",u(e.routeReady)],["Sellable",u(e.sellable)],["Sell sim",u(e.sellSimulation??e.sellSim)],["Smart wallets",u(e.smartWalletOverlap)],["Risk",u(e.risk??e.riskStatus)],["Prepared ticket",u(e.preparedTicket??e.ticketStatus)],nt(e),E(e)],e)}function Qr(t={}){let e=t||{};return _(`ORACLE HIP-3 \u2014 ${u(e.market??e.coin??e.name)}`,[["Venue",`Hyperliquid builder-dex ${u(e.dex)}`],["Market",u(e.market??e.coin)],["Mark",b(e.markPx,{decimals:6})],["Oracle",b(e.oraclePx,{decimals:6})],["Funding",ke(e.funding,{decimals:6})],["Open interest",b(e.openInterestUsd)],["Depth",u(e.depth)],["Liquidation notes",u(e.liquidationNotes??e.riskNotes)],["Account context",u(e.accountContext)],E(e)],e)}function Zr(t={}){let e=t||{};return _(`ORACLE HIP-4 \u2014 ${u(e.event??e.market??e.name)}`,[["Venue",`Hyperliquid HIP-4 ${u(e.dex??"outcome")}`],["Event",u(e.event)],["Outcome",u(e.outcome)],["Market id",A(e.marketId??e.market)],["Bid",b(e.bid,{decimals:6})],["Ask",b(e.ask,{decimals:6})],["Depth",u(e.depth)],["Edge",ke(e.edge)],["Position",u(e.position)],E(e)],e)}function en(t={}){let e=t||{};return _(`ORACLE POLYMARKET \u2014 ${u(e.event??e.market??e.name)}`,[["Venue","Polymarket CLOB"],["Event",u(e.event)],["Market",u(e.market)],["Market id",A(e.marketId??e.conditionId??e.tokenId)],["Yes",b(e.yesPrice,{decimals:4})],["No",b(e.noPrice,{decimals:4})],["Best bid / ask",`${b(e.bestBid,{decimals:4})} / ${b(e.bestAsk,{decimals:4})}`],["Volume",b(e.volumeUsd)],["Resolution risk",u(e.resolutionRisk)],["Order intent",u(e.orderIntent)],E(e)],e)}function tn(t={}){let e=t||{},r=S(e.completedSplits)&&S(e.totalSplits)?`${P(e.completedSplits,{decimals:0})} / ${P(e.totalSplits,{decimals:0})}`:f;return _(`ORACLE TWAP \u2014 ${u(e.pair??e.symbol??e.name)}`,[["Chain",R(e)],["Side",u(e.side??e.direction)],["Amount",`${u(M(e.amountTotal??e.amount,e.decimals??18))} ${u(e.symbol??"")}`.trim()],["Splits",`${P(e.totalSplits,{decimals:0})} over ${u(e.window)}`],["Progress",r],["Avg price",b(e.averagePrice,{decimals:6})],["Next split",u(e.nextSplitAt)],["Slippage cap",le(e.slippageBps)],["Status",u(e.status)],E(e)],e)}function rn(t={}){let e=t||{},r=e.approval??e.revokeCheck??{},n=r.needsRevoke&&r.spender?`revoke.cash \u2014 ${u(r.spender)}`:r.needsRevoke===!1?"revoke.cash \u2014 clean":"revoke.cash \u2014 unchecked";return _(`ORACLE BRIDGE \u2014 ${u(e.pair??e.fromSymbol)} \u2192 ${u(e.toSymbol??"")}`.replace(/→ $/,""),[["Bridging","deBridge \xB7 LI.FI \u2014 best route wins"],["From chain",R({chainId:e.fromChainId,chain:e.fromChain})],["To chain",R({chainId:e.toChainId,chain:e.toChain})],["Amount",`${u(M(e.amount,e.fromDecimals??18))} ${u(e.fromSymbol??"")}`.trim()],["Best route",u(e.bestRoute??e.winner)],["Est. received",`${u(M(e.amountOut,e.toDecimals??18))} ${u(e.toSymbol??"")}`.trim()],["Fee",b(e.feeUsd)],["Est. time",u(e.estimatedTime)],["Revoke check",n],["All providers",u(e.providers?.join(", "))],["Preparable",u(e.preparable)],E(e)],e)}function nn(t){let r=(Array.isArray(t)?t:[]).slice(1,4).map(n=>{let o=u(n.source??n.venue??n.name),a=n.improvementBps==null&&n.deltaBps==null?null:Number(n.improvementBps??n.deltaBps),i=Number.isFinite(a)?`${Math.abs(a).toFixed(0)} bps behind`:"spread UNKNOWN";return`${o} (${i})`});return r.length?r.join("; "):f}function on(t){let e=t.rankedOn??t.swap?.rankedOn??t.best?.rankedOn;return S(e)?u(e):f}function an(t={}){let e=t||{},r=e.swap&&typeof e.swap=="object"?e.swap:e,n=e.bridge&&typeof e.bridge=="object"?e.bridge:null,o=r.best??r.winner??{},a=`${u(e.tokenInSymbol??e.fromSymbol??"IN")} \u2192 ${u(e.tokenOutSymbol??e.toSymbol??"OUT")}`,i=[["Intent",u(e.intent??"swap")],["Chain",R({chainId:e.chainId??r.chainId,chain:e.chain??r.chain})],["Pair",a],["Amount in",`${u(M(e.amountIn??r.amountIn,e.decimalsIn??18))} ${u(e.tokenInSymbol??"")}`.trim()],["Best swap",u(o.source??o.venue??r.bestRoute??e.bestRoute)],["Net out",`${u(M(o.netOut??o.amountOut??r.amountOut,e.decimalsOut??18))} ${u(e.tokenOutSymbol??"")}`.trim()],["Ranked on",on(r)],["Gas accounted",u(o.costAccounted===!0?"yes":o.costAccounted===!1?"no \u2014 gross ranking may flatter this route":null)],["Spread vs next",S(r.improvementBps)?`${u(r.improvementBps)} bps`:f],["Runners-up",nn(r.routes??e.routes)]];if(n){let l=n.best??n.winner??{};i.push(["Best bridge",u(l.source??n.bestRoute??e.bestBridge)],["Bridge out",`${u(M(l.netOut??l.amountOut??n.amountOut,e.bridgeDecimalsOut??e.decimalsOut??18))} ${u(e.bridgeOutSymbol??e.tokenOutSymbol??"")}`.trim()],["Bridge to",R({chainId:n.toChainId??e.toChainId,chain:n.toChain??e.toChain})],["Est. time",u(n.estimatedTime??l.meta?.durationSeconds)])}else i.push(["Best bridge","same-chain \u2014 use Best swap"]);return i.push(["Preparable",u(e.preparable??o.executionReady)],E(e)),_(`ORACLE SWAP \u2014 ${a}`,i,e)}function be(t={}){let e=t||{};return _("ORACLE APPROVE \u2014 local signer",[["Pending id",A(e.id??(typeof e.digest=="string"?e.digest.slice(0,8):null))],["Surface",u(e.surface)],["Action",u(e.action)],["Chain",R({chainId:e.chain??e.chainId,chain:e.chainName})],["To",A(e.to??e.destination)],["Value",S(e.value)?u(e.value):f],["Signer",u(e.armed===!0?"running + armed":e.armed===!1?"running, disarmed":"not running")],E({confidence:e.confidence??(e.armed===!0?"high":"low")})],e)}function xe({platform:t="telegram",id:e,digest:r,hasGrant:n=!1}={}){let o=String(e||(typeof r=="string"?r.slice(0,8):"")||"").trim();return n?o?String(t)==="telegram"?{kind:"inline_keyboard",replyMarkup:{inline_keyboard:[[{text:"Allow",callback_data:`oracle:approve:${o}`},{text:"Deny",callback_data:`oracle:deny:${o}`}]]},cancelHint:"Allow signs with the local signer. Deny drops the pending artifact."}:{kind:"text_menu",text:["1. Allow \u2014 reply /approve "+o,"2. Deny \u2014 reply /deny "+o].join(`
|
|
5
5
|
`),cancelHint:"Cards are not available on this chat. Use /approve or /deny."}:{kind:"text_menu",text:"nothing to approve",cancelHint:""}:String(t)==="telegram"?{kind:"inline_keyboard",replyMarkup:{inline_keyboard:[]},cancelHint:"prepare-only \u2014 no local grant/session"}:{kind:"text_menu",text:"prepare-only \u2014 no local grant/session",cancelHint:""}}var f,pa,zr,ma,ve=w(()=>{Ze();tt();f="UNKNOWN",pa=Object.freeze(["token","launch","hip3","hip4","polymarket","twap","bridge","swap","approve"]),zr=/[_*[\]`]/g;ma=Object.freeze({token:Jr,launch:Xr,hip3:Qr,hip4:Zr,polymarket:en,twap:tn,bridge:rn,swap:an,approve:be})});function Ae(t){let r=String(t||"").trim().match(/^\/(approve|deny|pending)(?:@[\w_]+)?(?:\s+([0-9a-fA-F]{4,64}))?\s*$/i);return r?{verb:r[1].toLowerCase(),id:r[2]?r[2].toLowerCase():null}:null}function Ce(t,{platform:e,grant:r,armed:n}){if(!t.length)return{text:"No pending local-signer artifacts.",buttons:xe({platform:e,hasGrant:!1})};let o=t[0];return{text:t.map(i=>be({...i,armed:n,grant:r,confidence:n?"high":"medium"})).join(`
|
|
6
6
|
|
|
7
7
|
`),buttons:xe({platform:e,id:o.id,digest:o.digest,hasGrant:U({grant:r}).allowed})}}async function $e({platform:t,text:e,grant:r={local:!0},env:n=process.env,ownerProof:o}={}){let a=Ae(e);if(!a)return null;let i=String(t)==="telegram";if(i&&a.verb!=="pending"&&!a.id)return{text:"On Telegram, tap Allow or Deny on the approve card. /approve is only for chats without cards.",buttons:null};if(a.verb==="pending"){let p=await T("/pending",{env:n});if(p.ok===!1||p.error)return{text:`Local signer: ${p.error||"not running"}. Start \`oracle signer\` on this machine first.`,buttons:null};let m=Array.isArray(p.items)?p.items:[],h=Ce(m,{platform:t,grant:r,armed:p.armed===!0});if(i)return h;if(!m.length)return{text:"No pending local-signer artifacts. /approve is only needed when cards are unavailable.",buttons:null};let g=m.map(k=>`\u2022 ${k.id} ${k.surface}/${k.action} to ${k.to||"n/a"}`);return g.push("Cards are not available here. Reply /approve <id> or /deny <id>."),{text:g.join(`
|
|
@@ -11,7 +11,7 @@ Tx: \`${s}\``,buttons:null,executed:!0,hash:s}:{text:`Local signer executed ${d}
|
|
|
11
11
|
Update it the same way you installed it \u2014 git pull, or npm install -g @oracle-agent/oracle@latest.`};let o=`${Ee}@${t}`,a=["install","--prefix",r,"--no-audit","--no-fund",o];if(e)return{ok:!0,dryRun:!0,root:r,command:`npm ${a.join(" ")}`};try{let{stdout:i,stderr:l}=await mn("npm",a,{timeout:3e5,maxBuffer:16777216});return{ok:!0,root:r,stdout:i,stderr:l}}catch(i){return{ok:!1,reason:"npm-failed",root:r,message:i?.stderr||i?.message||"npm install failed"}}}var mn,Ee,fn,hn,ut=w(()=>{mn=pn(sn),Ee="@oracle-agent/oracle",fn="https://registry.npmjs.org",hn=1440*60*1e3});import bn from"node:fs";import xn from"node:os";import dt from"node:path";function W(t){return String(t||"").trim().toLowerCase().replace(/^\/+/,"").replace(/\s+/g,"-")}function vn(){let t=process.env.ORACLE_CONFIG_DIR||dt.join(xn.homedir(),".config","oracle");return dt.join(t,"chains.json")}function An(t){if(!t||typeof t!="object")return null;let e=String(t.key??"").trim();if(!e||/[/\\.]/.test(e))return null;let r=W(e);if(!mt.test(r))return null;let n=typeof t.chainId=="string"?t.chainId.trim():Number(t.chainId);if(n===""||n===null||n===void 0||typeof n=="number"&&!Number.isFinite(n))return null;let o=typeof t.agent=="string"&&mt.test(t.agent.trim())?t.agent.trim():"oracle";return{key:r,aliases:Array.isArray(t.aliases)?t.aliases.map(W).filter(Boolean).slice(0,8):[],chainId:n,name:String(t.name||r).slice(0,60),kind:["evm","svm","utxo","venue"].includes(t.kind)?t.kind:"evm",family:W(t.family)||r,agent:o,note:String(t.note||"user-defined").slice(0,80),build:t.build!==!1,source:"user"}}function Cn(t=bn.readFileSync){try{let e=JSON.parse(t(vn(),"utf8")),r=Array.isArray(e?.chains)?e.chains:[],n=[],o=new Set;for(let a of r){let i=An(a);!i||o.has(i.key)||(o.add(i.key),n.push(i))}return n}catch{return[]}}function ft(){let t=Cn();if(t.length===0)return pt;let e=new Map(pt.map(r=>[r.key,r]));for(let r of t)e.set(r.key,r);return[...e.values()]}function $n({buildOnly:t=!1}={}){return ft().filter(e=>t?e.build:!0)}function ee(t){let e=W(t);if(!e)return null;for(let r of ft())if(r.key===e||String(r.chainId).toLowerCase()===e||(r.aliases||[]).map(W).includes(e)||W(r.name)===e)return r;return null}function ht({selectedKey:t=null,buildOnly:e=!1}={}){let r=$n({buildOnly:e}),n=["oracle chains","","pick a build/trade surface:",""];for(let o of r){let a=t&&t===o.key?"*":" ",i=String(o.chainId).padEnd(6),l=o.key.padEnd(12);n.push(`${a} ${l} ${i} ${o.note}`)}return n.push(""),n.push("usage:"),n.push(" /chain list"),n.push(" /chain hyperliquid select"),n.push(" /chain show current"),n.push(" /chain clear unset"),n.push(" oracle chain use base same from shell"),t&&n.push("",`active: ${t}`),n.join(`
|
|
12
12
|
`)+`
|
|
13
13
|
`}var pt,mt,Re=w(()=>{pt=Object.freeze([{key:"hyperliquid",aliases:["hl","hyperevm","hype","999"],chainId:999,name:"hyperliquid",kind:"evm",family:"hyperliquid",agent:"hyperliquid-agent",note:"perps \xB7 hip-3/4 \xB7 hyperevm 999",build:!0},{key:"ethereum",aliases:["eth","mainnet","1"],chainId:1,name:"ethereum",kind:"evm",family:"evm",agent:"oracle",note:"l1 \xB7 bridge hub",build:!0},{key:"base",aliases:["8453"],chainId:8453,name:"base",kind:"evm",family:"evm",agent:"oracle",note:"evm l2",build:!0},{key:"arbitrum",aliases:["arb","42161"],chainId:42161,name:"arbitrum",kind:"evm",family:"evm",agent:"oracle",note:"evm l2",build:!0},{key:"optimism",aliases:["op","10"],chainId:10,name:"optimism",kind:"evm",family:"evm",agent:"oracle",note:"op mainnet",build:!0},{key:"polygon",aliases:["matic","137"],chainId:137,name:"polygon",kind:"evm",family:"evm",agent:"oracle",note:"evm l2",build:!0},{key:"bsc",aliases:["bnb","56"],chainId:56,name:"bnb chain",kind:"evm",family:"evm",agent:"oracle",note:"bsc",build:!0},{key:"avalanche",aliases:["avax","43114"],chainId:43114,name:"avalanche",kind:"evm",family:"evm",agent:"oracle",note:"c-chain",build:!0},{key:"abstract",aliases:["abs","2741"],chainId:2741,name:"abstract",kind:"evm",family:"evm",agent:"oracle",note:"open / add agent",build:!0},{key:"stable",aliases:["988"],chainId:988,name:"stable",kind:"evm",family:"stable",agent:"stable-agent",note:"usdt0 gas \xB7 stable agent",build:!0},{key:"robinhood",aliases:["rh","4663"],chainId:4663,name:"robinhood",kind:"evm",family:"robinhood",agent:"robinhood-agent",note:"rh chain 4663",build:!0},{key:"solana",aliases:["sol"],chainId:"SOL",name:"solana",kind:"svm",family:"solana",agent:"solana-agent",note:"jup \xB7 nfts \xB7 dexs",build:!0},{key:"bitcoin",aliases:["btc"],chainId:"BTC",name:"bitcoin",kind:"utxo",family:"bitcoin",agent:"bitcoin-agent",note:"ord \xB7 runes \xB7 l1",build:!0},{key:"polymarket",aliases:["poly","polygon-poly"],chainId:137,name:"polymarket",kind:"venue",family:"polymarket",agent:"polymarket-agent",note:"prediction markets (polygon venue)",build:!1}]);mt=/^[a-z0-9][a-z0-9-]*$/});import Ne from"node:fs";import _n from"node:path";function gt(){return _n.join($(),"active-chain.json")}function Le(){let t=gt();if(!Ne.existsSync(t))return null;try{let e=JSON.parse(Ne.readFileSync(t,"utf8"));if(!e||typeof e!="object"||!e.key)return null;let r=ee(e.key);return r?{key:r.key,chainId:r.chainId,name:r.name,agent:r.agent,selectedAt:e.selectedAt||null}:null}catch{return null}}function yt(t){let e=ee(t);if(!e){let n=new Error(`unknown chain '${t}'`);throw n.code="UNKNOWN_CHAIN",n}ae($());let r={key:e.key,chainId:e.chainId,name:e.name,agent:e.agent,selectedAt:new Date().toISOString()};return Ne.writeFileSync(gt(),JSON.stringify(r,null,2)+`
|
|
14
|
-
`,{mode:384}),r}var wt=w(()=>{Re();ie()});import{createHash as En,randomBytes as Ua}from"node:crypto";import{mkdirSync as On,readFileSync as Rn,writeFileSync as Nn}from"node:fs";import{homedir as Ln}from"node:os";import{dirname as In,join as kt}from"node:path";function re(t=process.env){return kt(t.ORACLE_CONFIG_DIR||kt(Ln(),".config","oracle"),"telegram-cards.json")}function ne(){return{links:{},artifacts:{},threads:{}}}function ue(){return te}function St(t,{readFile:e=Rn}={}){try{let r=JSON.parse(String(e(t)));te={links:r.links&&typeof r.links=="object"?r.links:{},artifacts:r.artifacts&&typeof r.artifacts=="object"?r.artifacts:{},threads:r.threads&&typeof r.threads=="object"?r.threads:{}}}catch{te=ne()}return te}function de(t,e=te,{writeFile:r=Nn,mkdir:n=On}={}){n(In(t),{recursive:!0,mode:448}),r(t,JSON.stringify(e),{mode:384})}function L(t){return t==null?!1:typeof t=="string"?t.trim()!=="":!0}function Dn(t){return En("sha256").update(String(t)).digest("hex")}function Ie(t){if(Array.isArray(t))return t.map(Ie);if(!t||typeof t!="object")return t;let e={};for(let[r,n]of Object.entries(t))/(secret|token|key|seed|private|password|mnemonic|auth)/i.test(r)||(e[r]=Ie(n));return e}function jn(t){let r=String(t||"").trim().match(/^oracle:card:(deepen|refresh|prepare|ta|fa|long|short|allow|deny):([a-z0-9-]{4,40})$/i);return r?{action:r[1].toLowerCase(),artifactId:r[2].toLowerCase()}:null}function bt({platform:t="telegram",artifactId:e,openUrl:r,hasGrant:n=!1}={}){let o=String(e||"").trim().toLowerCase();if(!Te.test(o))return{kind:"text_menu",text:"no artifact to continue",cancelHint:""};let a=[],i=[{text:"TA",callback_data:`oracle:card:ta:${o}`},{text:"FA",callback_data:`oracle:card:fa:${o}`}],l=p=>et(r,{side:p}),c=l("long"),s=l("short"),d=c&&s?[{text:"LONG",url:c},{text:"SHORT",url:s}]:[{text:"LONG",callback_data:`oracle:card:long:${o}`},{text:"SHORT",callback_data:`oracle:card:short:${o}`}];return L(r)?(a.push([{text:"Open",url:String(r)},i[0]]),a.push(d),a.push(n?[i[1],{text:"Prep",callback_data:`oracle:card:prepare:${o}`}]:[i[1]])):(a.push(i),a.push(d),n&&a.push([{text:"Prep",callback_data:`oracle:card:prepare:${o}`}])),String(t)==="telegram"?{kind:"inline_keyboard",replyMarkup:{inline_keyboard:a.filter(p=>p.length>0)},cancelHint:"LONG/SHORT open the graph. CONFIRM there. Telegram never sends."}:{kind:"text_menu",text:"TA / FA / LONG / SHORT",cancelHint:""}}function xt(t={}){let r=[`*${L(t.title)?u(t.title):"Oracle artifact"}*`,`Kind: ${L(t.kind)?u(t.kind):f}`,`Id: ${L(t.id)?`\`${String(t.id).replace(/`/g,"")}\``:f}`,`Summary: ${L(t.summary)?u(t.summary):f}
|
|
14
|
+
`,{mode:384}),r}var wt=w(()=>{Re();ie()});import{createHash as En,randomBytes as Ua}from"node:crypto";import{mkdirSync as On,readFileSync as Rn,writeFileSync as Nn}from"node:fs";import{homedir as Ln}from"node:os";import{dirname as In,join as kt}from"node:path";function re(t=process.env){return kt(t.ORACLE_CONFIG_DIR||kt(Ln(),".config","oracle"),"telegram-cards.json")}function ne(){return{links:{},artifacts:{},threads:{}}}function ue(){return te}function St(t,{readFile:e=Rn}={}){try{let r=JSON.parse(String(e(t)));te={links:r.links&&typeof r.links=="object"?r.links:{},artifacts:r.artifacts&&typeof r.artifacts=="object"?r.artifacts:{},threads:r.threads&&typeof r.threads=="object"?r.threads:{}}}catch{te=ne()}return te}function de(t,e=te,{writeFile:r=Nn,mkdir:n=On}={}){n(In(t),{recursive:!0,mode:448}),r(t,JSON.stringify(e),{mode:384})}function L(t){return t==null?!1:typeof t=="string"?t.trim()!=="":!0}function Dn(t){return En("sha256").update(String(t)).digest("hex")}function Ie(t){if(Array.isArray(t))return t.map(Ie);if(!t||typeof t!="object")return t;let e={};for(let[r,n]of Object.entries(t))/(secret|token|key|seed|private|password|mnemonic|auth)/i.test(r)||(e[r]=Ie(n));return e}function jn(t){let r=String(t||"").trim().match(/^oracle:card:(deepen|refresh|prepare|ta|fa|long|short|allow|deny):([a-z0-9-]{4,40})$/i);return r?{action:r[1].toLowerCase(),artifactId:r[2].toLowerCase()}:null}function bt({platform:t="telegram",artifactId:e,openUrl:r,hasGrant:n=!1}={}){let o=String(e||"").trim().toLowerCase();if(!Te.test(o))return{kind:"text_menu",text:"no artifact to continue",cancelHint:""};let a=[],i=[{text:"TA",callback_data:`oracle:card:ta:${o}`},{text:"FA",callback_data:`oracle:card:fa:${o}`}],l=p=>et(r,{side:p}),c=l("long"),s=l("short"),d=c&&s?[{text:"LONG",url:c},{text:"SHORT",url:s}]:[{text:"LONG",callback_data:`oracle:card:long:${o}`},{text:"SHORT",callback_data:`oracle:card:short:${o}`}];return L(r)?(a.push([{text:"Open",url:String(r)},i[0]]),a.push(d),a.push(n?[i[1],{text:"Prep",callback_data:`oracle:card:prepare:${o}`}]:[i[1]])):(a.push(i),a.push(d),n&&a.push([{text:"Prep",callback_data:`oracle:card:prepare:${o}`}])),String(t)==="telegram"?{kind:"inline_keyboard",replyMarkup:{inline_keyboard:a.filter(p=>p.length>0)},cancelHint:"LONG/SHORT open the graph. CONFIRM there. Telegram never sends."}:{kind:"text_menu",text:"TA / FA / LONG / SHORT",cancelHint:""}}function xt(t={}){let r=[`*${L(t.title)?u(t.title):"Oracle artifact"}*`,`Kind: ${L(t.kind)?u(t.kind):f}`,`Id: ${L(t.id)?`\`${String(t.id).replace(/`/g,"")}\``:f}`,`Summary: ${L(t.summary)?u(t.summary):f}`],n=Se(t.confidence);n!==f&&r.push(`Confidence: ${n}`),(L(t.source)||L(t.fetchedAt))&&r.push(`Source: ${u(t.source)} at ${u(t.fetchedAt)}`),Array.isArray(t.warnings)&&t.warnings.length&&r.push(`Warnings: ${t.warnings.map(a=>u(a)).join("; ")}`);let o=U(t);return r.push(o.allowed?"Actions: TA / FA / LONG / SHORT open the graph. Execute on CONFIRM there.":`Actions: TA / FA / LONG / SHORT \u2014 ${u(o.reason)}`),r.join(`
|
|
15
15
|
`)}function Bn(t,e={},{now:r=Date.now()}={}){let n=t||ne(),o=String(e.id||"").trim().toLowerCase();if(!Te.test(o))throw new TypeError("artifact id required");let a={id:o,kind:String(e.kind||"thesis"),title:String(e.title||"Oracle artifact"),summary:String(e.summary||""),openUrl:L(e.openUrl)?String(e.openUrl):null,confidence:e.confidence,source:e.source||"oracle",fetchedAt:e.fetchedAt||new Date(r).toISOString(),warnings:Array.isArray(e.warnings)?e.warnings.map(String):[],payload:Ie(e.payload||{}),createdAt:new Date(r).toISOString()};return n.artifacts[o]=a,a}function Pe(t,{chatId:e,artifactId:r,now:n=Date.now()}={}){let o=t||ne(),a=String(e||"").trim(),i=String(r||"").trim().toLowerCase();if(!a)throw new TypeError("chat id required");if(!Te.test(i))throw new TypeError("artifact id required");return o.threads[a]={artifactId:i,updatedAt:n},o.threads[a]}function vt(t,{chatId:e,text:r}={}){let n=String(e||"").trim(),o=String(r||"").trim();if(!n||!o||/^\//.test(o))return null;let a=t?.threads?.[n];if(!a?.artifactId)return null;let i=t.artifacts?.[a.artifactId];return i?`Continue artifact ${i.id} (${i.kind}). Prior: ${i.summary||i.title}. User: ${o}`:null}function At(t,{token:e,telegramUserId:r,now:n=Date.now()}={}){let o=t||ne(),a=String(e||"").trim(),i=String(r||"").trim();if(!Mn.test(a))return{ok:!1,error:"invalid start token"};if(!Un.test(i))return{ok:!1,error:"invalid telegram user"};let l=Dn(a),c=o.links[l];return c?(delete o.links[l],Number(c.expiresAt)<=n?{ok:!1,error:"start token expired"}:String(c.ownerId)!==i?{ok:!1,error:"start token is bound to a different owner"}:{ok:!0,ownerId:i}):{ok:!1,error:"unknown or already used start token"}}function Ct(t,{data:e,chatId:r,grant:n=null,now:o=Date.now()}={}){let a=jn(e);if(!a)return null;if(!Pn.has(a.action))return{text:"That card action is not available.",buttons:null};let i=t?.artifacts?.[a.artifactId];if(!i)return{text:"That artifact is gone. Ask again and I will issue a new card.",buttons:null};r&&Pe(t,{chatId:r,artifactId:i.id,now:o});let l=U({grant:n},{now:o}),c=bt({artifactId:i.id,openUrl:i.openUrl,hasGrant:l.allowed});return a.action==="refresh"?{text:xt(i),buttons:c,prompt:null}:a.action==="deepen"?{text:null,buttons:null,prompt:`Deepen artifact ${i.id} (${i.kind}). Prior: ${i.summary||i.title}. Be terse. Do not sign or broadcast.`}:a.action==="ta"?{text:null,buttons:null,prompt:`TA artifact ${i.id}. Prior: ${i.summary||i.title}. Run deterministic TA on the coin/venue in the artifact (RSI divergence, S/R, candle patterns). Reply in this Telegram chat with the verdict rows and say what was drawn. Do not sign or broadcast.`}:a.action==="fa"?{text:null,buttons:null,prompt:`FA artifact ${i.id}. Prior: ${i.summary||i.title}. Run per-coin FA (funding, OI, book, premium) plus the separate MACRO thesis (M1/M2/Fed BS/net liquidity) if relevant. Cite receipts. Stay in this Telegram chat. Do not sign or broadcast.`}:a.action==="allow"?{text:"Allow is the graph. Open the ticket there and CONFIRM. Telegram did not send.",buttons:null,prompt:null}:a.action==="deny"?{text:`Denied ${i.id}. Ticket cancelled. Nothing signed.`,buttons:null,prompt:null}:a.action==="long"||a.action==="short"?{text:null,buttons:null,prompt:`Open the live graph ticket for a ${a.action} on artifact ${i.id}. Prior: ${i.summary||i.title}. Size from the connected HL account. Execute only on CONFIRM on the graph. Never sign from Telegram.`}:l.allowed?{text:`Queued unsigned prepare for ${i.id}. Nothing signed. Allow/Deny still required.`,buttons:c,prompt:null,prepare:{artifactId:i.id,unsigned:!0,broadcast:!1}}:{text:`Prepare blocked \u2014 ${l.reason}. Deepen and Refresh still work.`,buttons:c,prompt:null}}function $t(t={},{grant:e=null,now:r=Date.now(),state:n}={}){let o=n||ue(),a=String(t.id||`art-${Math.abs(Number(r)).toString(36)}`).toLowerCase().slice(0,40),i=Bn(o,{...t,id:a},{now:r}),l=U({grant:e},{now:r});return{text:xt({...i,grant:e}),replyMarkup:bt({artifactId:i.id,openUrl:i.openUrl,hasGrant:l.allowed}).replyMarkup,artifact:i,state:o}}var Tn,Pn,Te,Mn,Un,te,Me=w(()=>{we();ve();Tn=Object.freeze(["deepen","refresh","prepare","ta","fa","long","short","allow","deny"]),Pn=new Set(Tn),Te=/^[a-z0-9-]{4,40}$/i,Mn=/^[0-9a-f]{32}$/,Un=/^\d+$/;te=ne()});var Yt={};j(Yt,{NON_OWNER_REPLY:()=>V,buildPersona:()=>K,handleSelfUpdate:()=>It,isForwarded:()=>Tt,isOwnerSender:()=>z,ownerIdsFor:()=>Nt,parseGatewayChainCommand:()=>Gt,parseGatewayCompactCommand:()=>Ht,parseGatewayEffortCommand:()=>Dt,parseGatewayGoalCommand:()=>Ft,parseGatewayHelpCommand:()=>jt,parseGatewayModelCommand:()=>Ut,parseGatewaySetupModelCommand:()=>Qn,parseGatewayStatusCommand:()=>Bt,parsePeerAsk:()=>Wt,parseSelfUpdate:()=>Lt,resolveBackendArgv:()=>zt,resolveGatewayModel:()=>Pt,resolveOracleBin:()=>Rt,routePeerConsult:()=>oe,routeToAgent:()=>O});import{spawn as Ot}from"node:child_process";import{dirname as Fn,join as De}from"node:path";import{homedir as Hn}from"node:os";import{mkdirSync as Gn,readFileSync as qn,writeFileSync as Wn,unlinkSync as zn}from"node:fs";import{fileURLToPath as Vn}from"node:url";function Rt({env:t=process.env,moduleUrl:e=import.meta.url}={}){return t.ORACLE_CLI_ENTRY||De(Fn(Vn(e)),"oracle.mjs")}function Nt(t,e=process.env){let r=String(e[`ORACLE_OWNER_${String(t).toUpperCase()}`]||""),n=String(e.ORACLE_OWNER_IDS||"");return new Set(`${r},${n}`.split(",").map(o=>o.trim()).filter(Boolean))}function z({platform:t,senderId:e,extraOwners:r},n=process.env){let o=String(e||"").trim();return o?Nt(t,n).has(o)?!0:Array.isArray(r)?r.map(a=>String(a).trim()).filter(Boolean).includes(o):!1:!1}function Lt(t){let e=String(t||"").trim();if(!e)return null;let r=e.replace(/^\/update(?:@[\w_]+)?\b/i,"update");return/^(?:oracle\s+)?update\s+--check\s*$/i.test(r)?{checkOnly:!0}:/^(?:oracle\s+)?update\s*$/i.test(r)?{checkOnly:!1}:null}async function It(t,{check:e=ct,update:r=lt,versionOf:n=Oe}={}){let o=await e({force:!0});if(t.checkOnly)return o.checked?o.updateAvailable?`oracle ${o.current} \u2192 ${o.latest} available. Send /update to install.`:`oracle ${o.current} is up to date`:`oracle ${o.current||"?"} \u2014 could not reach npm`;if(o.checked&&!o.updateAvailable)return`oracle ${o.current} is already up to date`;let a=o.latest||"latest",i=await r({version:a==="latest"?"latest":a});if(!i.ok)return`oracle update failed: ${i.message}`;let l=n();return[`oracle ${o.current||"?"} \u2192 ${l||a}`,"Restart the gateway to load it: oracle gateway"].join(`
|
|
16
16
|
`)}function Tt(t={}){return!!(t.forwarded||t.forward_from||t.forward_from_chat||t.forward_origin||t.forward_sender_name||t.forward_date)}function Pt({readConfig:t=q}={}){let e=t();return e?e.backend==="hermes"?{ok:!1,error:"model config delegates to hermes; the gateway runs Oracle's native loop. Set a standalone backend: oracle model --backend standalone"}:e.model?{ok:!0,provider:e.provider,model:e.model,reasoningEffort:e.reasoningEffort||null}:{ok:!1,error:"model config has no model \u2014 run: oracle model --backend standalone --provider <p> --model <m>"}:{ok:!1,error:"gateway has no model configured \u2014 run: oracle model --backend standalone --provider <p> --model <m>"}}function Ut(t){let r=String(t||"").trim().match(/^\/model(?:\s+(.+))?$/i);if(!r)return null;let n=String(r[1]||"").trim();if(!n)return{action:"list"};if(n.toLowerCase()==="show"||n==="?")return{action:"show"};if(n.toLowerCase()==="list")return{action:"list"};let o=n.split(/\s+/),a=Mt[o[0].toLowerCase()];if(a&&o.length===1)return{action:"set",provider:a.provider,model:a.model};if(a&&o.length>=2)return{action:"set",provider:a.provider,model:o.slice(1).join(" ")};if(o.length>=2)return{action:"set",provider:o[0],model:o.slice(1).join(" ")};if(o[0]?.includes(":")){let[i,l]=o[0].split(":");if(i&&l)return{action:"set",provider:i,model:l}}return{action:"usage"}}function Dt(t){let r=String(t||"").trim().match(/^\/(?:effort|reasoning)(?:\s+(.+))?$/i);if(!r)return null;let n=String(r[1]||"").trim().toLowerCase();return!n||n==="show"||n==="?"?{action:"show"}:Yn.includes(n)?{action:"set",reasoningEffort:n}:{action:"usage"}}function Jn({provider:t,model:e}){let r=q()||{},n=ye({...r,backend:r.backend&&r.backend!=="auto"?r.backend:"standalone",provider:t,model:e});return`model ${n.provider} / ${n.model}
|
|
17
17
|
Oracle persona unchanged. Native harness only \u2014 Hermes Telegram uses its own /model.`}function Xn(t){let e=q();if(!e)throw new Error("no model configured \u2014 run /model first");return`effort ${ye({...e,reasoningEffort:t}).reasoningEffort||t}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{createInterface as Ce}from"node:readline";var S=Object.freeze({maxRequestBytes:256*1024,maxResponseBytes:2*1024*1024,maxTools:256,maxToolNameLength:64,maxArgumentBytes:128*1024,defaultCallTimeoutMs:3e4,maxCallTimeoutMs:6e4,maxConcurrentCalls:32}),Ae=/^[A-Za-z0-9_-]{1,64}$/;function q(t,e){return{jsonrpc:"2.0",id:t??null,result:e}}function g(t,e,r){return{jsonrpc:"2.0",id:t??null,error:{code:e,message:r}}}function Re(t){return!!(t&&typeof t=="object"&&!Array.isArray(t)&&t.jsonrpc==="2.0"&&typeof t.method=="string"&&t.method.length>0)}function _e(t){if(!Array.isArray(t))return[];let e=[],r=new Set;for(let n of t){if(e.length>=S.maxTools)break;if(!n||typeof n!="object"||Array.isArray(n))continue;let o=typeof n.name=="string"?n.name.trim():"";if(!Ae.test(o)||r.has(o))continue;r.add(o);let a=n.inputSchema&&typeof n.inputSchema=="object"&&!Array.isArray(n.inputSchema)?{...n.inputSchema}:{type:"object",properties:{},additionalProperties:!1};a.type==="object"&&a.additionalProperties===void 0&&(a.additionalProperties=!1),e.push({...n,name:o,inputSchema:a})}return e}function Ne(t){let e=Number(t)||S.defaultCallTimeoutMs;return Math.min(Math.max(e,1),S.maxCallTimeoutMs)}async function Oe(t,e,r){let n;try{return await Promise.race([t,new Promise((o,a)=>{n=setTimeout(()=>{let i=new Error("tool call timed out");i.code="ORACLE_MCP_TIMEOUT",a(i);try{r?.()}catch{}},e)})])}finally{clearTimeout(n)}}function Ee(t){return t===null?"null":Array.isArray(t)?"array":Number.isInteger(t)?"integer":typeof t}function j(t,e,r="arguments",n=0){if(!e||typeof e!="object"||Array.isArray(e))return null;if(n>12)return`${r} exceeded the nesting limit`;if(Array.isArray(e.oneOf)&&e.oneOf.length&&!e.oneOf.some(a=>j(t,a,r,n+1)===null))return`${r} did not match an allowed shape`;if(Array.isArray(e.anyOf)&&e.anyOf.length&&!e.anyOf.some(a=>j(t,a,r,n+1)===null))return`${r} did not match a required alternative`;if(Array.isArray(e.enum)&&!e.enum.some(o=>Object.is(o,t)))return`${r} must be one of the allowed values`;if(Object.hasOwn(e,"const")&&!Object.is(e.const,t))return`${r} must equal the required constant`;if(e.type){let o=Ee(t);if(!(e.type==="number"?typeof t=="number"&&Number.isFinite(t):e.type==="integer"?Number.isSafeInteger(t):o===e.type))return`${r} must be ${e.type}`}if(typeof t=="string"){let o=Math.min(Number.isSafeInteger(e.maxLength)?e.maxLength:16384,16384);if(t.length>o)return`${r} exceeded the string limit`;if(Number.isSafeInteger(e.minLength)&&t.length<e.minLength)return`${r} is too short`}if(Array.isArray(t)){let o=Math.min(Number.isSafeInteger(e.maxItems)?e.maxItems:1e3,1e3);if(t.length>o)return`${r} exceeded the array limit`;if(Number.isSafeInteger(e.minItems)&&t.length<e.minItems)return`${r} has too few items`;if(e.items)for(let a=0;a<t.length;a+=1){let i=j(t[a],e.items,`${r}[${a}]`,n+1);if(i)return i}}if(t&&typeof t=="object"&&!Array.isArray(t)){let o=Object.keys(t);if(o.length>256)return`${r} exceeded the property limit`;let a=e.properties&&typeof e.properties=="object"?e.properties:{};for(let i of Array.isArray(e.required)?e.required:[])if(!Object.hasOwn(t,i))return`${r}.${i} is required`;if(e.additionalProperties===!1){let i=o.find(
|
|
2
|
+
import{createInterface as Ce}from"node:readline";var S=Object.freeze({maxRequestBytes:256*1024,maxResponseBytes:2*1024*1024,maxTools:256,maxToolNameLength:64,maxArgumentBytes:128*1024,defaultCallTimeoutMs:3e4,maxCallTimeoutMs:6e4,maxConcurrentCalls:32}),Ae=/^[A-Za-z0-9_-]{1,64}$/;function q(t,e){return{jsonrpc:"2.0",id:t??null,result:e}}function g(t,e,r){return{jsonrpc:"2.0",id:t??null,error:{code:e,message:r}}}function Re(t){return!!(t&&typeof t=="object"&&!Array.isArray(t)&&t.jsonrpc==="2.0"&&typeof t.method=="string"&&t.method.length>0)}function _e(t){if(!Array.isArray(t))return[];let e=[],r=new Set;for(let n of t){if(e.length>=S.maxTools)break;if(!n||typeof n!="object"||Array.isArray(n))continue;let o=typeof n.name=="string"?n.name.trim():"";if(!Ae.test(o)||r.has(o))continue;r.add(o);let a=n.inputSchema&&typeof n.inputSchema=="object"&&!Array.isArray(n.inputSchema)?{...n.inputSchema}:{type:"object",properties:{},additionalProperties:!1};a.type==="object"&&a.additionalProperties===void 0&&(a.additionalProperties=!1),e.push({...n,name:o,inputSchema:a})}return e}function Ne(t){let e=Number(t)||S.defaultCallTimeoutMs;return Math.min(Math.max(e,1),S.maxCallTimeoutMs)}async function Oe(t,e,r){let n;try{return await Promise.race([t,new Promise((o,a)=>{n=setTimeout(()=>{let i=new Error("tool call timed out");i.code="ORACLE_MCP_TIMEOUT",a(i);try{r?.()}catch{}},e)})])}finally{clearTimeout(n)}}function Ee(t){return t===null?"null":Array.isArray(t)?"array":Number.isInteger(t)?"integer":typeof t}function j(t,e,r="arguments",n=0){if(!e||typeof e!="object"||Array.isArray(e))return null;if(n>12)return`${r} exceeded the nesting limit`;if(Array.isArray(e.oneOf)&&e.oneOf.length&&!e.oneOf.some(a=>j(t,a,r,n+1)===null))return`${r} did not match an allowed shape`;if(Array.isArray(e.anyOf)&&e.anyOf.length&&!e.anyOf.some(a=>j(t,a,r,n+1)===null))return`${r} did not match a required alternative`;if(Array.isArray(e.enum)&&!e.enum.some(o=>Object.is(o,t)))return`${r} must be one of the allowed values`;if(Object.hasOwn(e,"const")&&!Object.is(e.const,t))return`${r} must equal the required constant`;if(e.type){let o=Ee(t);if(!(e.type==="number"?typeof t=="number"&&Number.isFinite(t):e.type==="integer"?Number.isSafeInteger(t):o===e.type))return`${r} must be ${e.type}`}if(typeof t=="string"){let o=Math.min(Number.isSafeInteger(e.maxLength)?e.maxLength:16384,16384);if(t.length>o)return`${r} exceeded the string limit`;if(Number.isSafeInteger(e.minLength)&&t.length<e.minLength)return`${r} is too short`}if(Array.isArray(t)){let o=Math.min(Number.isSafeInteger(e.maxItems)?e.maxItems:1e3,1e3);if(t.length>o)return`${r} exceeded the array limit`;if(Number.isSafeInteger(e.minItems)&&t.length<e.minItems)return`${r} has too few items`;if(e.items)for(let a=0;a<t.length;a+=1){let i=j(t[a],e.items,`${r}[${a}]`,n+1);if(i)return i}}if(t&&typeof t=="object"&&!Array.isArray(t)){let o=Object.keys(t);if(o.length>256)return`${r} exceeded the property limit`;let a=e.properties&&typeof e.properties=="object"?e.properties:{};for(let i of Array.isArray(e.required)?e.required:[])if(!Object.hasOwn(t,i))return`${r}.${i} is required`;if(e.additionalProperties===!1){let i=o.find(l=>!Object.hasOwn(a,l));if(i)return`${r}.${i} is not allowed`}for(let i of o){if(!Object.hasOwn(a,i))continue;let l=j(t[i],a[i],`${r}.${i}`,n+1);if(l)return l}}return null}function Ie(t,e={}){let r=_e(t?.tools),n=new Set(r.map(d=>d.name)),o=new Map(r.map(d=>[d.name,d])),a=typeof t?.name=="string"&&t.name?t.name.slice(0,80):"oracle-mcp",i=typeof t?.version=="string"&&t.version?t.version.slice(0,40):"1",l=Ne(e.callTimeoutMs),u=!1;return async function(f){let p=f?.id??null;if(!Re(f))return g(p,-32600,"invalid request");if(f.method==="initialize")return u=!0,q(p,{protocolVersion:f.params?.protocolVersion??"2025-03-26",capabilities:{tools:{}},serverInfo:{name:a,version:i}});if(f.method==="notifications/initialized")return null;if(f.method==="ping")return q(p,{});if(!u)return g(p,-32002,"server not initialized");if(f.method==="tools/list")return q(p,{tools:r});if(f.method==="tools/call"){let $=f.params?.name,w=f.params?.arguments??{};if(typeof $!="string"||!n.has($))return g(p,-32602,"unknown tool");if(!w||typeof w!="object"||Array.isArray(w))return g(p,-32602,"tool arguments must be an object");let N;try{N=JSON.stringify(w)}catch{return g(p,-32602,"tool arguments are not serializable")}if(Buffer.byteLength(N)>S.maxArgumentBytes)return g(p,-32602,"tool arguments exceeded the size limit");let P=j(w,o.get($)?.inputSchema);if(P)return g(p,-32602,P);try{let x=new AbortController,O=await Oe(Promise.resolve(t.call($,w,{signal:x.signal})),l,()=>x.abort(new Error("tool call timed out")));return q(p,O)}catch(x){if(x?.code==="ORACLE_MCP_TIMEOUT")return g(p,-32001,"tool call timed out");let O=typeof x?.message=="string"?x.message.replace(/\s+/g," ").trim():"",B=/\b(requires?|must be|missing|unknown|invalid|expected|unsupported|out of range|too (?:large|small|long|many)|not a|cannot convert)\b/i.test(O),F=/https?:\/\/|[/~][\w.-]+\/|0x[0-9a-fA-F]{8,}|[A-Za-z0-9+/_-]{24,}={0,2}|\b(?:secret|apikey|api[-_ ]key|private[-_ ]?key|token|password|credential|seed|mnemonic)s?\b/i.test(O.replace(/\btoken(?:In|Out|s\b)/g,"asset"));return B&&!F&&O.length<=200?g(p,-32e3,`tool call failed: ${O}`):g(p,-32e3,"tool call failed")}}return g(p,-32601,"method not found")}}function te(t,e={}){let r=e.input||process.stdin,n=e.output||process.stdout,o=Math.min(Math.max(Number(e.maxRequestBytes)||S.maxRequestBytes,64),S.maxRequestBytes),a=Math.min(Math.max(Number(e.maxResponseBytes)||S.maxResponseBytes,256),S.maxResponseBytes),i=Math.min(Math.max(Number(e.maxConcurrentCalls)||S.maxConcurrentCalls,1),S.maxConcurrentCalls),l=i*8,u=Ie(t,e),d={closed:!1,inflight:0},f=Ce({input:r,terminal:!1,crlfDelay:1/0}),p=0,$=[],w=!1,N=!1;function P(){if(d.closed||d.readerClosed)return;let y=d.inflight>=i||$.length>0||N;y&&!w?(w=!0,f.pause(),typeof r.pause=="function"&&r.pause()):!y&&w&&(w=!1,typeof r.resume=="function"&&r.resume(),f.resume())}function x(y){if(!y||d.closed)return;let k=JSON.stringify(y);Buffer.byteLength(k)>a&&(k=JSON.stringify(g(y.id,-32003,"response exceeded the size limit"))),n.write(`${k}
|
|
3
3
|
`)===!1&&!N&&(N=!0,P(),n.once("drain",()=>{N=!1,B()}))}function O(y){d.inflight+=1,P(),Promise.resolve(u(y)).then(x).catch(()=>x(g(y?.id,-32603,"internal error"))).finally(()=>{d.inflight-=1,B()})}function B(){for(;!d.closed&&!N&&d.inflight<i&&$.length>0;)O($.shift());P()}function F(){d.closed||(x(g(null,-32700,"request exceeded the size limit")),d.closed=!0,f.close(),typeof r.destroy=="function"&&r.destroy())}return r.on("data",y=>{if(d.closed)return;let k=String(y).split(`
|
|
4
|
-
`);for(let U=0;U<k.length;U+=1){if(p+=Buffer.byteLength(k[U]),p>o){F();return}U<k.length-1&&(p=0)}}),f.on("line",y=>{if(d.closed)return;if(Buffer.byteLength(y)>o){F();return}let k;try{k=JSON.parse(y)}catch{x(g(null,-32700,"parse error"));return}if($.length>=
|
|
5
|
-
`)}function R(t){return["Confidence",
|
|
6
|
-
`)}function st(t,e={},{now:r=Date.now()}={}){let n=t||M(),o=String(e.id||"").trim().toLowerCase();if(!Y.test(o))throw new TypeError("artifact id required");let a={id:o,kind:String(e.kind||"thesis"),title:String(e.title||"Oracle artifact"),summary:String(e.summary||""),openUrl:I(e.openUrl)?String(e.openUrl):null,confidence:e.confidence,source:e.source||"oracle",fetchedAt:e.fetchedAt||new Date(r).toISOString(),warnings:Array.isArray(e.warnings)?e.warnings.map(String):[],payload:J(e.payload||{}),createdAt:new Date(r).toISOString()};return n.artifacts[o]=a,a}function Z(t,{chatId:e,artifactId:r,now:n=Date.now()}={}){let o=t||M(),a=String(e||"").trim(),i=String(r||"").trim().toLowerCase();if(!a)throw new TypeError("chat id required");if(!Y.test(i))throw new TypeError("artifact id required");return o.threads[a]={artifactId:i,updatedAt:n},o.threads[a]}function me(t,{chatId:e,text:r}={}){let n=String(e||"").trim(),o=String(r||"").trim();if(!n||!o||/^\//.test(o))return null;let a=t?.threads?.[n];if(!a?.artifactId)return null;let i=t.artifacts?.[a.artifactId];return i?`Continue artifact ${i.id} (${i.kind}). Prior: ${i.summary||i.title}. User: ${o}`:null}function he(t,{ownerId:e,botUsername:r,now:n=Date.now(),ttlMs:o=600*1e3,token:a,randomBytes:i=Ze}={}){let
|
|
4
|
+
`);for(let U=0;U<k.length;U+=1){if(p+=Buffer.byteLength(k[U]),p>o){F();return}U<k.length-1&&(p=0)}}),f.on("line",y=>{if(d.closed)return;if(Buffer.byteLength(y)>o){F();return}let k;try{k=JSON.parse(y)}catch{x(g(null,-32700,"parse error"));return}if($.length>=l){x(g(k?.id,-32e3,"server busy"));return}$.push(k),B()}),f.on("close",()=>{d.readerClosed=!0,e.exitOnClose!==!1&&(process.exitCode=0)}),d}import{createHash as Xe,randomBytes as Ze}from"node:crypto";import{mkdirSync as Qe,readFileSync as et,writeFileSync as tt}from"node:fs";import{homedir as rt}from"node:os";import{dirname as nt,join as ae}from"node:path";var Le=/^[A-Z0-9][A-Z0-9._-]{0,11}$/;function Te(t){let e=String(t||"").trim();if(!e||e.includes("ts.net")||!/^https:\/\//i.test(e))return null;try{return new URL(e)}catch{return null}}function re(t,{coin:e,side:r,sizeUsd:n,leverage:o,venue:a,confirm:i,user:l}={}){let u=Te(t);if(!u)return null;if(e&&Le.test(String(e).toUpperCase())&&u.searchParams.set("coin",String(e).toUpperCase()),(r==="long"||r==="short")&&u.searchParams.set("side",r),Number.isFinite(Number(n))&&Number(n)>=1&&u.searchParams.set("size",String(Math.min(1e5,Math.round(Number(n))))),Number.isInteger(Number(o))&&Number(o)>=1&&u.searchParams.set("lev",String(Math.min(50,Number(o)))),a){let d=String(a).toLowerCase()==="hl"?"hyperliquid":String(a).toLowerCase();u.searchParams.set("venue",d)}else u.searchParams.get("venue")||u.searchParams.set("venue","hyperliquid");return u.searchParams.set("view","perps"),u.searchParams.set("build","1"),i&&/^[0-9a-f]{32}$/i.test(String(i))&&u.searchParams.set("confirm",String(i).toLowerCase()),l&&/^0x[0-9a-fA-F]{40}$/.test(String(l))&&u.searchParams.set("user",String(l).toLowerCase()),u.toString()}var Pe={robinhood:{chainId:4663,name:"Robinhood Chain",rpcEnv:["RH_CHAIN_RPC"],evm:!0},ethereum:{chainId:1,name:"Ethereum",rpcEnv:["ETH_RPC_URL","ETHEREUM_RPC_URL","MAINNET_RPC_URL"],evm:!0},polygon:{chainId:137,name:"Polygon",rpcEnv:["POLYGON_RPC_URL","POLYGON_RPC"],evm:!0},arbitrum:{chainId:42161,name:"Arbitrum One",rpcEnv:["ARBITRUM_RPC_URL","ARB_RPC_URL"],evm:!0},base:{chainId:8453,name:"Base",rpcEnv:["BASE_RPC_URL"],evm:!0},hyperevm:{chainId:999,name:"HyperEVM",rpcEnv:["HYPEREVM_RPC_URL","HYPER_EVM_RPC"],evm:!0},bsc:{chainId:56,name:"BNB Smart Chain",rpcEnv:["BSC_RPC_URL","BNB_RPC_URL"],evm:!0},avalanche:{chainId:43114,name:"Avalanche C-Chain",rpcEnv:["AVALANCHE_RPC_URL","AVAX_RPC_URL"],evm:!0},optimism:{chainId:10,name:"OP Mainnet",rpcEnv:["OPTIMISM_RPC_URL","OP_RPC_URL"],evm:!0},abstract:{chainId:2741,name:"Abstract",rpcEnv:["ABSTRACT_RPC_URL","ABS_RPC_URL"],evm:!0},stable:{chainId:988,name:"Stable Mainnet",rpcEnv:["STABLE_RPC_URL","STABLE_RPC"],evm:!0}},Me=new Map(Object.values(Pe).map(t=>[t.chainId,t]));function ne(t){return Me.get(Number(t))||null}var At=Object.freeze([100,50,25]),Rt=Object.freeze([100,50,25,10]);var c="UNKNOWN",It=Object.freeze(["token","launch","hip3","hip4","polymarket","twap","bridge","swap","approve"]),ve=/[_*[\]`]/g;function s(t){return m(t)?String(t).replace(ve,e=>`\\${e}`):c}function m(t){return t==null?!1:typeof t=="number"?Number.isFinite(t):typeof t=="string"?t.trim()!=="":!0}function C(t){if(!m(t))return c;let e=String(t).replace(/`/g,"");return e===""?c:`\`${e}\``}function L(t,{decimals:e=2}={}){if(!m(t))return c;let r=Number(t);return Number.isFinite(r)?r.toLocaleString("en-US",{minimumFractionDigits:0,maximumFractionDigits:e}):c}function h(t,{decimals:e=2}={}){let r=L(t,{decimals:e});return r===c?c:`${r} USD`}function W(t,{decimals:e=2}={}){let r=L(t,{decimals:e});return r===c?c:`${r}%`}function z(t){let e=L(t,{decimals:0});return e===c?c:`${e} bps`}function T(t,e){if(!m(t))return c;let r=Number(e);if(!Number.isInteger(r)||r<0||r>77)return c;let n;try{n=BigInt(typeof t=="string"?t.trim():t)}catch{return c}let o=n<0n,a=o?-n:n,i=10n**BigInt(r),l=(a/i).toString(),u=(a%i).toString().padStart(r,"0").replace(/0+$/,"");return`${o?"-":""}${l}${u?`.${u}`:""}`}function K(t){if(typeof t=="number"&&Number.isFinite(t))return t<0||t>1?c:t>=.75?"HIGH":t>=.4?"MEDIUM":"LOW";if(typeof t=="string"){let e=t.trim().toUpperCase();if(e==="HIGH"||e==="MEDIUM"||e==="LOW")return e}return c}function E(t={}){let e=t.chainId;if(!m(e)||!Number.isFinite(Number(e)))return m(t.chain)?s(t.chain):c;let n=ne(e)?.name||(m(t.chain)?String(t.chain):c);return`${s(n)} (chainId ${Number(e)})`}function ie(t={}){return s(t.venue??t.dex??t.pool?.venue)}function Be(t){return t==null?"NONE (text card only)":typeof t=="string"?t.trim()?C(t):"NONE (text card only)":t.error||t.ok===!1||t.available===!1?`UNAVAILABLE${m(t.error)?` \u2014 ${s(t.error)}`:""} (text card stands)`:m(t.url)?C(t.url):"NONE (text card only)"}function H(t={},{now:e=Date.now()}={}){let r=t.grant??t.session??null;if(!r||typeof r!="object")return{allowed:!1,reason:"no local grant/session",actions:[]};if(r.local===!1)return{allowed:!1,reason:"grant is not local",actions:[]};if(r.revoked===!0)return{allowed:!1,reason:"grant revoked",actions:[]};let n=r.expiresAt??r.expiry;if(m(n)){let a=typeof n=="number"?n:Date.parse(n);if(!Number.isFinite(a))return{allowed:!1,reason:"grant expiry unreadable",actions:[]};if(a<=e)return{allowed:!1,reason:"grant expired",actions:[]}}return{allowed:!0,reason:"valid local grant",actions:Array.isArray(r.actions)&&r.actions.length?r.actions.slice():["BUY","SELL"]}}function Ue(t){let e=H(t);return e.allowed?`${e.actions.map(r=>s(r)).join(" / ")} (${s(e.reason)})`:`prepare-only \u2014 ${s(e.reason)}`}function A(t,e,r={}){let n=[`*${t}*`];for(let o of e){if(!o)continue;let[a,i]=o;n.push(`${a}: ${i==null||i===""?c:i}`)}return n.push(`Chart: ${Be(r.chart)}`),n.push(`Actions: ${Ue(r)}`),Array.isArray(r.warnings)&&r.warnings.length&&n.push(`Warnings: ${r.warnings.map(o=>s(o)).join("; ")}`),(m(r.source)||m(r.fetchedAt))&&n.push(`Source: ${s(r.source)} at ${s(r.fetchedAt)}`),n.join(`
|
|
5
|
+
`)}function R(t){let e=K(t.confidence);return e===c?null:["Confidence",e]}function je(t){let e=t.quote;if(!e||typeof e!="object")return[];let r=m(e.decimals)?T(e.amountOutRaw??e.out??e.raw,e.decimals):c;return[["Quote out (raw)",C(e.amountOutRaw??e.out??e.raw)],["Quote out",r===c?c:`${s(r)} ${s(e.symbol??"")}`.trim()]]}function oe(t){let e=t.autoSlippage;if(!e||typeof e!="object")return["Auto-slippage",c];let r=z(e.selectedBps),n=z(e.capBps);return["Auto-slippage",r===c&&n===c?c:`${r} selected, cap ${n}`]}function He(t={}){let e=t||{};return A(`ORACLE TOKEN \u2014 ${s(e.symbol??e.token??e.name)}`,[["Chain",E(e)],["Venue",ie(e)],["Name",s(e.name)],["Address",C(e.address??e.mint??e.contract)],["Price",h(e.priceUsd,{decimals:8})],["Market cap",h(e.marketCapUsd)],["Liquidity",h(e.liquidityUsd)],["Volume 24h",h(e.volume24hUsd)],["Change 24h",W(e.priceChange24h)],["Fee tier",m(e.feeTier)?`${z(Number(e.feeTier)/100)} (${L(e.feeTier,{decimals:0})})`:c],["Age",s(e.age)],...je(e),oe(e),R(e)],e)}function De(t={}){let e=t||{};return A(`ORACLE LAUNCH \u2014 ${s(e.symbol??e.token??e.name)}`,[["Chain",E(e)],["Venue",ie(e)],["Address",C(e.address??e.mint??e.contract)],["Pool",C(e.pool?.address??e.poolAddress??e.pool)],["Liquidity",h(e.liquidityUsd)],["Route ready",s(e.routeReady)],["Sellable",s(e.sellable)],["Sell sim",s(e.sellSimulation??e.sellSim)],["Smart wallets",s(e.smartWalletOverlap)],["Risk",s(e.risk??e.riskStatus)],["Prepared ticket",s(e.preparedTicket??e.ticketStatus)],oe(e),R(e)],e)}function Fe(t={}){let e=t||{};return A(`ORACLE HIP-3 \u2014 ${s(e.market??e.coin??e.name)}`,[["Venue",`Hyperliquid builder-dex ${s(e.dex)}`],["Market",s(e.market??e.coin)],["Mark",h(e.markPx,{decimals:6})],["Oracle",h(e.oraclePx,{decimals:6})],["Funding",W(e.funding,{decimals:6})],["Open interest",h(e.openInterestUsd)],["Depth",s(e.depth)],["Liquidation notes",s(e.liquidationNotes??e.riskNotes)],["Account context",s(e.accountContext)],R(e)],e)}function qe(t={}){let e=t||{};return A(`ORACLE HIP-4 \u2014 ${s(e.event??e.market??e.name)}`,[["Venue",`Hyperliquid HIP-4 ${s(e.dex??"outcome")}`],["Event",s(e.event)],["Outcome",s(e.outcome)],["Market id",C(e.marketId??e.market)],["Bid",h(e.bid,{decimals:6})],["Ask",h(e.ask,{decimals:6})],["Depth",s(e.depth)],["Edge",W(e.edge)],["Position",s(e.position)],R(e)],e)}function ze(t={}){let e=t||{};return A(`ORACLE POLYMARKET \u2014 ${s(e.event??e.market??e.name)}`,[["Venue","Polymarket CLOB"],["Event",s(e.event)],["Market",s(e.market)],["Market id",C(e.marketId??e.conditionId??e.tokenId)],["Yes",h(e.yesPrice,{decimals:4})],["No",h(e.noPrice,{decimals:4})],["Best bid / ask",`${h(e.bestBid,{decimals:4})} / ${h(e.bestAsk,{decimals:4})}`],["Volume",h(e.volumeUsd)],["Resolution risk",s(e.resolutionRisk)],["Order intent",s(e.orderIntent)],R(e)],e)}function Ve(t={}){let e=t||{},r=m(e.completedSplits)&&m(e.totalSplits)?`${L(e.completedSplits,{decimals:0})} / ${L(e.totalSplits,{decimals:0})}`:c;return A(`ORACLE TWAP \u2014 ${s(e.pair??e.symbol??e.name)}`,[["Chain",E(e)],["Side",s(e.side??e.direction)],["Amount",`${s(T(e.amountTotal??e.amount,e.decimals??18))} ${s(e.symbol??"")}`.trim()],["Splits",`${L(e.totalSplits,{decimals:0})} over ${s(e.window)}`],["Progress",r],["Avg price",h(e.averagePrice,{decimals:6})],["Next split",s(e.nextSplitAt)],["Slippage cap",z(e.slippageBps)],["Status",s(e.status)],R(e)],e)}function We(t={}){let e=t||{},r=e.approval??e.revokeCheck??{},n=r.needsRevoke&&r.spender?`revoke.cash \u2014 ${s(r.spender)}`:r.needsRevoke===!1?"revoke.cash \u2014 clean":"revoke.cash \u2014 unchecked";return A(`ORACLE BRIDGE \u2014 ${s(e.pair??e.fromSymbol)} \u2192 ${s(e.toSymbol??"")}`.replace(/→ $/,""),[["Bridging","deBridge \xB7 LI.FI \u2014 best route wins"],["From chain",E({chainId:e.fromChainId,chain:e.fromChain})],["To chain",E({chainId:e.toChainId,chain:e.toChain})],["Amount",`${s(T(e.amount,e.fromDecimals??18))} ${s(e.fromSymbol??"")}`.trim()],["Best route",s(e.bestRoute??e.winner)],["Est. received",`${s(T(e.amountOut,e.toDecimals??18))} ${s(e.toSymbol??"")}`.trim()],["Fee",h(e.feeUsd)],["Est. time",s(e.estimatedTime)],["Revoke check",n],["All providers",s(e.providers?.join(", "))],["Preparable",s(e.preparable)],R(e)],e)}function Ke(t){let r=(Array.isArray(t)?t:[]).slice(1,4).map(n=>{let o=s(n.source??n.venue??n.name),a=n.improvementBps==null&&n.deltaBps==null?null:Number(n.improvementBps??n.deltaBps),i=Number.isFinite(a)?`${Math.abs(a).toFixed(0)} bps behind`:"spread UNKNOWN";return`${o} (${i})`});return r.length?r.join("; "):c}function Je(t){let e=t.rankedOn??t.swap?.rankedOn??t.best?.rankedOn;return m(e)?s(e):c}function Ye(t={}){let e=t||{},r=e.swap&&typeof e.swap=="object"?e.swap:e,n=e.bridge&&typeof e.bridge=="object"?e.bridge:null,o=r.best??r.winner??{},a=`${s(e.tokenInSymbol??e.fromSymbol??"IN")} \u2192 ${s(e.tokenOutSymbol??e.toSymbol??"OUT")}`,i=[["Intent",s(e.intent??"swap")],["Chain",E({chainId:e.chainId??r.chainId,chain:e.chain??r.chain})],["Pair",a],["Amount in",`${s(T(e.amountIn??r.amountIn,e.decimalsIn??18))} ${s(e.tokenInSymbol??"")}`.trim()],["Best swap",s(o.source??o.venue??r.bestRoute??e.bestRoute)],["Net out",`${s(T(o.netOut??o.amountOut??r.amountOut,e.decimalsOut??18))} ${s(e.tokenOutSymbol??"")}`.trim()],["Ranked on",Je(r)],["Gas accounted",s(o.costAccounted===!0?"yes":o.costAccounted===!1?"no \u2014 gross ranking may flatter this route":null)],["Spread vs next",m(r.improvementBps)?`${s(r.improvementBps)} bps`:c],["Runners-up",Ke(r.routes??e.routes)]];if(n){let l=n.best??n.winner??{};i.push(["Best bridge",s(l.source??n.bestRoute??e.bestBridge)],["Bridge out",`${s(T(l.netOut??l.amountOut??n.amountOut,e.bridgeDecimalsOut??e.decimalsOut??18))} ${s(e.bridgeOutSymbol??e.tokenOutSymbol??"")}`.trim()],["Bridge to",E({chainId:n.toChainId??e.toChainId,chain:n.toChain??e.toChain})],["Est. time",s(n.estimatedTime??l.meta?.durationSeconds)])}else i.push(["Best bridge","same-chain \u2014 use Best swap"]);return i.push(["Preparable",s(e.preparable??o.executionReady)],R(e)),A(`ORACLE SWAP \u2014 ${a}`,i,e)}function Ge(t={}){let e=t||{};return A("ORACLE APPROVE \u2014 local signer",[["Pending id",C(e.id??(typeof e.digest=="string"?e.digest.slice(0,8):null))],["Surface",s(e.surface)],["Action",s(e.action)],["Chain",E({chainId:e.chain??e.chainId,chain:e.chainName})],["To",C(e.to??e.destination)],["Value",m(e.value)?s(e.value):c],["Signer",s(e.armed===!0?"running + armed":e.armed===!1?"running, disarmed":"not running")],R({confidence:e.confidence??(e.armed===!0?"high":"low")})],e)}var Lt=Object.freeze({token:He,launch:De,hip3:Fe,hip4:qe,polymarket:ze,twap:Ve,bridge:We,swap:Ye,approve:Ge});var it=Object.freeze(["deepen","refresh","prepare","ta","fa","long","short","allow","deny"]),ot=new Set(it),Y=/^[a-z0-9-]{4,40}$/i,se=/^[0-9a-f]{32}$/,ce=/^\d+$/;function G(t=process.env){return ae(t.ORACLE_CONFIG_DIR||ae(rt(),".config","oracle"),"telegram-cards.json")}function M(){return{links:{},artifacts:{},threads:{}}}var D=M();function X(){return D}function le(t,{readFile:e=et}={}){try{let r=JSON.parse(String(e(t)));D={links:r.links&&typeof r.links=="object"?r.links:{},artifacts:r.artifacts&&typeof r.artifacts=="object"?r.artifacts:{},threads:r.threads&&typeof r.threads=="object"?r.threads:{}}}catch{D=M()}return D}function ue(t,e=D,{writeFile:r=tt,mkdir:n=Qe}={}){n(nt(t),{recursive:!0,mode:448}),r(t,JSON.stringify(e),{mode:384})}function I(t){return t==null?!1:typeof t=="string"?t.trim()!=="":!0}function de(t){return Xe("sha256").update(String(t)).digest("hex")}function J(t){if(Array.isArray(t))return t.map(J);if(!t||typeof t!="object")return t;let e={};for(let[r,n]of Object.entries(t))/(secret|token|key|seed|private|password|mnemonic|auth)/i.test(r)||(e[r]=J(n));return e}function at(t){let r=String(t||"").trim().match(/^oracle:card:(deepen|refresh|prepare|ta|fa|long|short|allow|deny):([a-z0-9-]{4,40})$/i);return r?{action:r[1].toLowerCase(),artifactId:r[2].toLowerCase()}:null}function fe({platform:t="telegram",artifactId:e,openUrl:r,hasGrant:n=!1}={}){let o=String(e||"").trim().toLowerCase();if(!Y.test(o))return{kind:"text_menu",text:"no artifact to continue",cancelHint:""};let a=[],i=[{text:"TA",callback_data:`oracle:card:ta:${o}`},{text:"FA",callback_data:`oracle:card:fa:${o}`}],l=p=>re(r,{side:p}),u=l("long"),d=l("short"),f=u&&d?[{text:"LONG",url:u},{text:"SHORT",url:d}]:[{text:"LONG",callback_data:`oracle:card:long:${o}`},{text:"SHORT",callback_data:`oracle:card:short:${o}`}];return I(r)?(a.push([{text:"Open",url:String(r)},i[0]]),a.push(f),a.push(n?[i[1],{text:"Prep",callback_data:`oracle:card:prepare:${o}`}]:[i[1]])):(a.push(i),a.push(f),n&&a.push([{text:"Prep",callback_data:`oracle:card:prepare:${o}`}])),String(t)==="telegram"?{kind:"inline_keyboard",replyMarkup:{inline_keyboard:a.filter(p=>p.length>0)},cancelHint:"LONG/SHORT open the graph. CONFIRM there. Telegram never sends."}:{kind:"text_menu",text:"TA / FA / LONG / SHORT",cancelHint:""}}function pe(t={}){let r=[`*${I(t.title)?s(t.title):"Oracle artifact"}*`,`Kind: ${I(t.kind)?s(t.kind):c}`,`Id: ${I(t.id)?`\`${String(t.id).replace(/`/g,"")}\``:c}`,`Summary: ${I(t.summary)?s(t.summary):c}`],n=K(t.confidence);n!==c&&r.push(`Confidence: ${n}`),(I(t.source)||I(t.fetchedAt))&&r.push(`Source: ${s(t.source)} at ${s(t.fetchedAt)}`),Array.isArray(t.warnings)&&t.warnings.length&&r.push(`Warnings: ${t.warnings.map(a=>s(a)).join("; ")}`);let o=H(t);return r.push(o.allowed?"Actions: TA / FA / LONG / SHORT open the graph. Execute on CONFIRM there.":`Actions: TA / FA / LONG / SHORT \u2014 ${s(o.reason)}`),r.join(`
|
|
6
|
+
`)}function st(t,e={},{now:r=Date.now()}={}){let n=t||M(),o=String(e.id||"").trim().toLowerCase();if(!Y.test(o))throw new TypeError("artifact id required");let a={id:o,kind:String(e.kind||"thesis"),title:String(e.title||"Oracle artifact"),summary:String(e.summary||""),openUrl:I(e.openUrl)?String(e.openUrl):null,confidence:e.confidence,source:e.source||"oracle",fetchedAt:e.fetchedAt||new Date(r).toISOString(),warnings:Array.isArray(e.warnings)?e.warnings.map(String):[],payload:J(e.payload||{}),createdAt:new Date(r).toISOString()};return n.artifacts[o]=a,a}function Z(t,{chatId:e,artifactId:r,now:n=Date.now()}={}){let o=t||M(),a=String(e||"").trim(),i=String(r||"").trim().toLowerCase();if(!a)throw new TypeError("chat id required");if(!Y.test(i))throw new TypeError("artifact id required");return o.threads[a]={artifactId:i,updatedAt:n},o.threads[a]}function me(t,{chatId:e,text:r}={}){let n=String(e||"").trim(),o=String(r||"").trim();if(!n||!o||/^\//.test(o))return null;let a=t?.threads?.[n];if(!a?.artifactId)return null;let i=t.artifacts?.[a.artifactId];return i?`Continue artifact ${i.id} (${i.kind}). Prior: ${i.summary||i.title}. User: ${o}`:null}function he(t,{ownerId:e,botUsername:r,now:n=Date.now(),ttlMs:o=600*1e3,token:a,randomBytes:i=Ze}={}){let l=t||M(),u=String(e||"").trim(),d=String(r||"").replace(/^@/,"").trim();if(!ce.test(u))throw new TypeError("owner Telegram id required");if(!/^[A-Za-z0-9_]{5,32}$/.test(d))throw new TypeError("bot username required");let f=a||i(16).toString("hex");if(!se.test(f))throw new TypeError("link token must be 32 hex chars");return l.links[de(f)]={ownerId:u,expiresAt:n+Number(o)},{token:f,url:`https://t.me/${d}?start=${f}`,expiresAt:n+Number(o)}}function ge(t,{token:e,telegramUserId:r,now:n=Date.now()}={}){let o=t||M(),a=String(e||"").trim(),i=String(r||"").trim();if(!se.test(a))return{ok:!1,error:"invalid start token"};if(!ce.test(i))return{ok:!1,error:"invalid telegram user"};let l=de(a),u=o.links[l];return u?(delete o.links[l],Number(u.expiresAt)<=n?{ok:!1,error:"start token expired"}:String(u.ownerId)!==i?{ok:!1,error:"start token is bound to a different owner"}:{ok:!0,ownerId:i}):{ok:!1,error:"unknown or already used start token"}}function ye(t,{data:e,chatId:r,grant:n=null,now:o=Date.now()}={}){let a=at(e);if(!a)return null;if(!ot.has(a.action))return{text:"That card action is not available.",buttons:null};let i=t?.artifacts?.[a.artifactId];if(!i)return{text:"That artifact is gone. Ask again and I will issue a new card.",buttons:null};r&&Z(t,{chatId:r,artifactId:i.id,now:o});let l=H({grant:n},{now:o}),u=fe({artifactId:i.id,openUrl:i.openUrl,hasGrant:l.allowed});return a.action==="refresh"?{text:pe(i),buttons:u,prompt:null}:a.action==="deepen"?{text:null,buttons:null,prompt:`Deepen artifact ${i.id} (${i.kind}). Prior: ${i.summary||i.title}. Be terse. Do not sign or broadcast.`}:a.action==="ta"?{text:null,buttons:null,prompt:`TA artifact ${i.id}. Prior: ${i.summary||i.title}. Run deterministic TA on the coin/venue in the artifact (RSI divergence, S/R, candle patterns). Reply in this Telegram chat with the verdict rows and say what was drawn. Do not sign or broadcast.`}:a.action==="fa"?{text:null,buttons:null,prompt:`FA artifact ${i.id}. Prior: ${i.summary||i.title}. Run per-coin FA (funding, OI, book, premium) plus the separate MACRO thesis (M1/M2/Fed BS/net liquidity) if relevant. Cite receipts. Stay in this Telegram chat. Do not sign or broadcast.`}:a.action==="allow"?{text:"Allow is the graph. Open the ticket there and CONFIRM. Telegram did not send.",buttons:null,prompt:null}:a.action==="deny"?{text:`Denied ${i.id}. Ticket cancelled. Nothing signed.`,buttons:null,prompt:null}:a.action==="long"||a.action==="short"?{text:null,buttons:null,prompt:`Open the live graph ticket for a ${a.action} on artifact ${i.id}. Prior: ${i.summary||i.title}. Size from the connected HL account. Execute only on CONFIRM on the graph. Never sign from Telegram.`}:l.allowed?{text:`Queued unsigned prepare for ${i.id}. Nothing signed. Allow/Deny still required.`,buttons:u,prompt:null,prepare:{artifactId:i.id,unsigned:!0,broadcast:!1}}:{text:`Prepare blocked \u2014 ${l.reason}. Deepen and Refresh still work.`,buttons:u,prompt:null}}function be(t={},{grant:e=null,now:r=Date.now(),state:n}={}){let o=n||X(),a=String(t.id||`art-${Math.abs(Number(r)).toString(36)}`).toLowerCase().slice(0,40),i=st(o,{...t,id:a},{now:r}),l=H({grant:e},{now:r});return{text:pe({...i,grant:e}),replyMarkup:fe({artifactId:i.id,openUrl:i.openUrl,hasGrant:l.allowed}).replyMarkup,artifact:i,state:o}}var xe=`oracle telegram \u2014 TrueNorth-style interactive cards (native, no Hermes)
|
|
7
7
|
|
|
8
8
|
oracle telegram link --owner <tg-id> --bot <username>
|
|
9
9
|
oracle telegram redeem --token <32hex> --user <tg-id>
|
|
@@ -16,7 +16,7 @@ must call this CLI instead of owning card state. Prepare is unsigned. Execute
|
|
|
16
16
|
stays on Allow/Deny.`;function b(t,e){let r=t.indexOf(e);return r<0||r+1>=t.length?null:t[r+1]}function we(t,e){return t.includes(e)}function ct(){return le(G()),X()}function V(t){ue(G(),t)}function v(t,e){t.write(JSON.stringify(e)+`
|
|
17
17
|
`)}async function ke(t=[],e={}){let r=e.out??process.stdout,n=e.err??process.stderr,o=t[0];if(!o||o==="--help"||o==="-h"||o==="help")return r.write(xe+`
|
|
18
18
|
`),0;let a=ct();if(o==="link")try{let i=he(a,{ownerId:b(t,"--owner"),botUsername:b(t,"--bot")});return V(a),v(r,{ok:!0,...i}),0}catch(i){return n.write(String(i.message||i)+`
|
|
19
|
-
`),1}if(o==="redeem"){let i=ge(a,{token:b(t,"--token"),telegramUserId:b(t,"--user")});return V(a),v(r,i),i.ok?0:1}if(o==="wrap")try{let i=be({id:b(t,"--id"),kind:b(t,"--kind")||"thesis",title:b(t,"--title")||"Oracle artifact",summary:b(t,"--summary")||"",openUrl:b(t,"--url"),source:"oracle-telegram"},{grant:we(t,"--grant")?{local:!0}:null,state:a}),
|
|
19
|
+
`),1}if(o==="redeem"){let i=ge(a,{token:b(t,"--token"),telegramUserId:b(t,"--user")});return V(a),v(r,i),i.ok?0:1}if(o==="wrap")try{let i=be({id:b(t,"--id"),kind:b(t,"--kind")||"thesis",title:b(t,"--title")||"Oracle artifact",summary:b(t,"--summary")||"",openUrl:b(t,"--url"),source:"oracle-telegram"},{grant:we(t,"--grant")?{local:!0}:null,state:a}),l=b(t,"--chat");return l&&Z(a,{chatId:l,artifactId:i.artifact.id}),V(a),v(r,{ok:!0,text:i.text,replyMarkup:i.replyMarkup||null,artifactId:i.artifact.id,fallback:`Reply: deepen ${i.artifact.id} | refresh ${i.artifact.id}`}),0}catch(i){return n.write(String(i.message||i)+`
|
|
20
20
|
`),1}if(o==="callback"){let i=ye(a,{data:b(t,"--data"),chatId:b(t,"--chat"),grant:we(t,"--grant")?{local:!0}:null});return V(a),i?(v(r,{ok:!0,...i}),0):(v(r,{ok:!1,error:"not an interactive card callback"}),1)}if(o==="continue"){let i=me(a,{chatId:b(t,"--chat"),text:b(t,"--text")});return v(r,{ok:!0,prompt:i}),0}return n.write(`unknown telegram verb '${o}'
|
|
21
21
|
${xe}
|
|
22
22
|
`),1}var lt=40,ut=200,dt=4e3,ft=4e3,pt=128,$e=/^[a-z0-9][a-z0-9-]{3,39}$/i,Q=/^\d{1,20}$/,mt=/^oracle:card:(deepen|refresh|prepare|ta|fa|long|short|allow|deny):[a-z0-9][a-z0-9-]{3,39}$/i;function ht(t=process.env){return t.ORACLE_TELEGRAM_CARD_GRANT==="1"?{local:!0}:null}function _(t,{field:e,max:r,pattern:n}){if(typeof t!="string")throw new Error(`${e} must be a string`);let o=t.trim();if(!o)throw new Error(`${e} is required`);if(o.length>r)throw new Error(`${e} exceeds ${r} chars`);if(n&&!n.test(o))throw new Error(`${e} is malformed`);return o}function gt(){let t="",e="";return{io:{out:{write(r){return t+=String(r),!0}},err:{write(r){return e+=String(r),!0}}},stdout(){return t},stderr(){return e}}}async function ee(t){let e=gt(),r=await ke(t,e.io),n;try{n=JSON.parse(e.stdout()||"{}")}catch{n={text:e.stdout()}}return r!==0&&!n.error&&(n.error=e.stderr()||"telegram command failed"),{content:[{type:"text",text:JSON.stringify({code:r,...n})}]}}function Se(t){return{isError:!0,content:[{type:"text",text:JSON.stringify({error:t})}]}}var yt=[{name:"telegram_wrap",description:"Wrap a scan/quote/thesis as a TrueNorth-style Oracle artifact card. Prepare stays unsigned. No Execute button.",inputSchema:{type:"object",required:["id","title","summary"],properties:{id:{type:"string",description:"artifact id, [a-z0-9-]{4,40}"},title:{type:"string"},summary:{type:"string"},kind:{type:"string"},chat:{type:"string",description:"Telegram chat id, digits only"}}}},{name:"telegram_callback",description:"Handle deepen/refresh/prepare on an Oracle artifact card. Prepare is unsigned. Execute stays on Allow/Deny.",inputSchema:{type:"object",required:["data","chat"],properties:{data:{type:"string",description:"oracle:card:<action>:<id>"},chat:{type:"string"}}}},{name:"telegram_continue",description:"Continue the last artifact thread for this Telegram chat.",inputSchema:{type:"object",required:["chat","text"],properties:{chat:{type:"string"},text:{type:"string"}}}}],bt={name:"oracle-telegram",version:"2",tools:yt,async call(t,e={},{env:r=process.env}={}){let n=ht(r);try{if(t==="telegram_wrap"){let o=["wrap","--id",_(e.id,{field:"id",max:lt,pattern:$e}),"--title",_(e.title,{field:"title",max:ut}),"--summary",_(e.summary,{field:"summary",max:dt})];return e.kind!==void 0&&o.push("--kind",_(e.kind,{field:"kind",max:40,pattern:$e})),e.chat!==void 0&&o.push("--chat",_(e.chat,{field:"chat",max:20,pattern:Q})),n&&o.push("--grant"),await ee(o)}if(t==="telegram_callback"){let o=["callback","--data",_(e.data,{field:"data",max:pt,pattern:mt}),"--chat",_(e.chat,{field:"chat",max:20,pattern:Q})];return n&&o.push("--grant"),await ee(o)}if(t==="telegram_continue")return await ee(["continue","--chat",_(e.chat,{field:"chat",max:20,pattern:Q}),"--text",_(e.text,{field:"text",max:ft})])}catch(o){return Se(o.message)}return Se("unknown tool")}};process.argv[1]&&process.argv[1].endsWith("oracle-telegram-mcp.mjs")&&te(bt);export{ht as grantFromEnv,bt as server};
|