@oracle-agent/oracle 0.35.0 → 0.35.2
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/README.md +1 -1
- package/dist/assets/skills/oracle-desk-product/SKILL.md +1 -1
- package/dist/bin/desk-server.mjs +23 -23
- package/dist/bin/oracle-data-mcp.mjs +11 -11
- package/dist/bin/oracle-gateway.mjs +36 -37
- package/dist/bin/oracle-telegram-mcp.mjs +12 -13
- package/dist/cli/commands/chat.mjs +200 -189
- package/dist/cli/commands/doctor.mjs +3 -3
- package/dist/cli/commands/eval.mjs +68 -67
- package/dist/cli/commands/farm.mjs +15 -15
- package/dist/cli/commands/model.mjs +204 -193
- package/dist/cli/commands/setup.mjs +35 -35
- package/dist/cli/commands/telegram.mjs +10 -11
- package/dist/data/desk-data.mjs +21 -21
- package/dist/index.mjs +35 -35
- package/package.json +1 -1
- package/public/install.ps1 +3 -3
- package/public/oracle-splash/assets/oracle-cli-v035-poster.jpg +0 -0
- package/public/oracle-splash/assets/oracle-cli-v035.gif +0 -0
- package/public/oracle-splash/downloads/index.html +2 -16
- package/public/oracle-splash/index.html +202 -138
- package/public/oracle-splash/install.ps1 +3 -3
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{createInterface as Ae}from"node:readline";var
|
|
3
|
-
`)===!1&&!O&&(O=!0,
|
|
4
|
-
`);for(let
|
|
5
|
-
`)}function R(t){return["Confidence",K(t.confidence)]}function
|
|
6
|
-
`)
|
|
7
|
-
`)}function it(t,e={},{now:r=Date.now()}={}){let n=t||P(),i=String(e.id||"").trim().toLowerCase();if(!Y.test(i))throw new TypeError("artifact id required");let s={id:i,kind:String(e.kind||"thesis"),title:String(e.title||"Oracle artifact"),summary:String(e.summary||""),openUrl:N(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[i]=s,s}function Q(t,{chatId:e,artifactId:r,now:n=Date.now()}={}){let i=t||P(),s=String(e||"").trim(),o=String(r||"").trim().toLowerCase();if(!s)throw new TypeError("chat id required");if(!Y.test(o))throw new TypeError("artifact id required");return i.threads[s]={artifactId:o,updatedAt:n},i.threads[s]}function pe(t,{chatId:e,text:r}={}){let n=String(e||"").trim(),i=String(r||"").trim();if(!n||!i||/^\//.test(i))return null;let s=t?.threads?.[n];if(!s?.artifactId)return null;let o=t.artifacts?.[s.artifactId];return o?`Continue artifact ${o.id} (${o.kind}). Prior: ${o.summary||o.title}. User: ${i}`:null}function me(t,{ownerId:e,botUsername:r,now:n=Date.now(),ttlMs:i=600*1e3,token:s,randomBytes:o=Ye}={}){let l=t||P(),d=String(e||"").trim(),u=String(r||"").replace(/^@/,"").trim();if(!se.test(d))throw new TypeError("owner Telegram id required");if(!/^[A-Za-z0-9_]{5,32}$/.test(u))throw new TypeError("bot username required");let f=s||o(16).toString("hex");if(!ae.test(f))throw new TypeError("link token must be 32 hex chars");return l.links[ue(f)]={ownerId:d,expiresAt:n+Number(i)},{token:f,url:`https://t.me/${u}?start=${f}`,expiresAt:n+Number(i)}}function he(t,{token:e,telegramUserId:r,now:n=Date.now()}={}){let i=t||P(),s=String(e||"").trim(),o=String(r||"").trim();if(!ae.test(s))return{ok:!1,error:"invalid start token"};if(!se.test(o))return{ok:!1,error:"invalid telegram user"};let l=ue(s),d=i.links[l];return d?(delete i.links[l],Number(d.expiresAt)<=n?{ok:!1,error:"start token expired"}:String(d.ownerId)!==o?{ok:!1,error:"start token is bound to a different owner"}:{ok:!0,ownerId:o}):{ok:!1,error:"unknown or already used start token"}}function ge(t,{data:e,chatId:r,grant:n=null,now:i=Date.now()}={}){let s=nt(e);if(!s)return null;if(!rt.has(s.action))return{text:"That card action is not available.",buttons:null};let o=t?.artifacts?.[s.artifactId];if(!o)return{text:"That artifact is gone. Ask again and I will issue a new card.",buttons:null};r&&Q(t,{chatId:r,artifactId:o.id,now:i});let l=D({grant:n},{now:i}),d=de({artifactId:o.id,openUrl:o.openUrl,hasGrant:l.allowed});return s.action==="refresh"?{text:fe(o),buttons:d,prompt:null}:s.action==="deepen"?{text:null,buttons:null,prompt:`Deepen artifact ${o.id} (${o.kind}). Prior: ${o.summary||o.title}. Be terse. Do not sign or broadcast.`}:l.allowed?{text:`Queued unsigned prepare for ${o.id}. Nothing signed. Allow/Deny still required.`,buttons:d,prompt:null,prepare:{artifactId:o.id,unsigned:!0,broadcast:!1}}:{text:`Prepare blocked \u2014 ${l.reason}. Deepen and Refresh still work.`,buttons:d,prompt:null}}function ye(t={},{grant:e=null,now:r=Date.now(),state:n}={}){let i=n||G(),s=String(t.id||`art-${Math.abs(Number(r)).toString(36)}`).toLowerCase().slice(0,40),o=it(i,{...t,id:s},{now:r}),l=D({grant:e},{now:r});return{text:fe({...o,grant:e}),replyMarkup:de({artifactId:o.id,openUrl:o.openUrl,hasGrant:l.allowed}).replyMarkup,artifact:o,state:i}}var be=`oracle telegram \u2014 TrueNorth-style interactive cards (native, no Hermes)
|
|
2
|
+
import{createInterface as Ae}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}),Ce=/^[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(!Ce.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 Oe(t){let e=Number(t)||S.defaultCallTimeoutMs;return Math.min(Math.max(e,1),S.maxCallTimeoutMs)}async function Ne(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(c=>c.name)),o=new Map(r.map(c=>[c.name,c])),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=Oe(e.callTimeoutMs),d=!1;return async function(f){let p=f?.id??null;if(!Re(f))return g(p,-32600,"invalid request");if(f.method==="initialize")return d=!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(!d)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 O;try{O=JSON.stringify(w)}catch{return g(p,-32602,"tool arguments are not serializable")}if(Buffer.byteLength(O)>S.maxArgumentBytes)return g(p,-32602,"tool arguments exceeded the size limit");let v=j(w,o.get($)?.inputSchema);if(v)return g(p,-32602,v);try{let x=new AbortController,N=await Ne(Promise.resolve(t.call($,w,{signal:x.signal})),l,()=>x.abort(new Error("tool call timed out")));return q(p,N)}catch(x){if(x?.code==="ORACLE_MCP_TIMEOUT")return g(p,-32001,"tool call timed out");let N=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(N),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(N.replace(/\btoken(?:In|Out|s\b)/g,"asset"));return B&&!F&&N.length<=200?g(p,-32e3,`tool call failed: ${N}`):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,d=Ie(t,e),c={closed:!1,inflight:0},f=Ae({input:r,terminal:!1,crlfDelay:1/0}),p=0,$=[],w=!1,O=!1;function v(){if(c.closed||c.readerClosed)return;let y=c.inflight>=i||$.length>0||O;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||c.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
|
+
`)===!1&&!O&&(O=!0,v(),n.once("drain",()=>{O=!1,B()}))}function N(y){c.inflight+=1,v(),Promise.resolve(d(y)).then(x).catch(()=>x(g(y?.id,-32603,"internal error"))).finally(()=>{c.inflight-=1,B()})}function B(){for(;!c.closed&&!O&&c.inflight<i&&$.length>0;)N($.shift());v()}function F(){c.closed||(x(g(null,-32700,"request exceeded the size limit")),c.closed=!0,f.close(),typeof r.destroy=="function"&&r.destroy())}return r.on("data",y=>{if(c.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(c.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",()=>{c.readerClosed=!0,e.exitOnClose!==!1&&(process.exitCode=0)}),c}import{createHash as Ye,randomBytes as Xe}from"node:crypto";import{mkdirSync as Ze,readFileSync as Qe,writeFileSync as et}from"node:fs";import{homedir as tt}from"node:os";import{dirname as rt,join as ae}from"node:path";var Le=/^[A-Z0-9][A-Z0-9._-]{0,11}$/;function re(t,{coin:e,side:r,sizeUsd:n,leverage:o,venue:a,confirm:i,user:l}={}){let d=String(t||"").trim();if(!d||d.includes("ts.net")||!/^https:\/\//i.test(d))return null;let c=new URL(d);if(e&&Le.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 f=String(a).toLowerCase()==="hl"?"hyperliquid":String(a).toLowerCase();c.searchParams.set("venue",f)}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 Te={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}},ve=new Map(Object.values(Te).map(t=>[t.chainId,t]));function ne(t){return ve.get(Number(t))||null}var u="UNKNOWN",St=Object.freeze(["token","launch","hip3","hip4","polymarket","twap","bridge","swap","approve"]),Pe=/[_*[\]`]/g;function s(t){return m(t)?String(t).replace(Pe,e=>`\\${e}`):u}function m(t){return t==null?!1:typeof t=="number"?Number.isFinite(t):typeof t=="string"?t.trim()!=="":!0}function A(t){if(!m(t))return u;let e=String(t).replace(/`/g,"");return e===""?u:`\`${e}\``}function L(t,{decimals:e=2}={}){if(!m(t))return u;let r=Number(t);return Number.isFinite(r)?r.toLocaleString("en-US",{minimumFractionDigits:0,maximumFractionDigits:e}):u}function h(t,{decimals:e=2}={}){let r=L(t,{decimals:e});return r===u?u:`${r} USD`}function W(t,{decimals:e=2}={}){let r=L(t,{decimals:e});return r===u?u:`${r}%`}function z(t){let e=L(t,{decimals:0});return e===u?u:`${e} bps`}function T(t,e){if(!m(t))return u;let r=Number(e);if(!Number.isInteger(r)||r<0||r>77)return u;let n;try{n=BigInt(typeof t=="string"?t.trim():t)}catch{return u}let o=n<0n,a=o?-n:n,i=10n**BigInt(r),l=(a/i).toString(),d=(a%i).toString().padStart(r,"0").replace(/0+$/,"");return`${o?"-":""}${l}${d?`.${d}`:""}`}function K(t){if(typeof t=="number"&&Number.isFinite(t))return t<0||t>1?u: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 u}function E(t={}){let e=t.chainId;if(!m(e)||!Number.isFinite(Number(e)))return m(t.chain)?s(t.chain):u;let n=ne(e)?.name||(m(t.chain)?String(t.chain):u);return`${s(n)} (chainId ${Number(e)})`}function ie(t={}){return s(t.venue??t.dex??t.pool?.venue)}function Me(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${m(t.error)?` \u2014 ${s(t.error)}`:""} (text card stands)`:m(t.url)?A(t.url):"NONE (text card only)"}function D(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 Be(t){let e=D(t);return e.allowed?`${e.actions.map(r=>s(r)).join(" / ")} (${s(e.reason)})`:`prepare-only \u2014 ${s(e.reason)}`}function C(t,e,r={}){let n=[`*${t}*`];for(let[o,a]of e)n.push(`${o}: ${a==null||a===""?u:a}`);return n.push(`Chart: ${Me(r.chart)}`),n.push(`Actions: ${Be(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){return["Confidence",K(t.confidence)]}function Ue(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):u;return[["Quote out (raw)",A(e.amountOutRaw??e.out??e.raw)],["Quote out",r===u?u:`${s(r)} ${s(e.symbol??"")}`.trim()]]}function oe(t){let e=t.autoSlippage;if(!e||typeof e!="object")return["Auto-slippage",u];let r=z(e.selectedBps),n=z(e.capBps);return["Auto-slippage",r===u&&n===u?u:`${r} selected, cap ${n}`]}function je(t={}){let e=t||{};return C(`ORACLE TOKEN \u2014 ${s(e.symbol??e.token??e.name)}`,[["Chain",E(e)],["Venue",ie(e)],["Name",s(e.name)],["Address",A(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})})`:u],["Age",s(e.age)],...Ue(e),oe(e),R(e)],e)}function De(t={}){let e=t||{};return C(`ORACLE LAUNCH \u2014 ${s(e.symbol??e.token??e.name)}`,[["Chain",E(e)],["Venue",ie(e)],["Address",A(e.address??e.mint??e.contract)],["Pool",A(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 He(t={}){let e=t||{};return C(`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 Fe(t={}){let e=t||{};return C(`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",A(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 qe(t={}){let e=t||{};return C(`ORACLE POLYMARKET \u2014 ${s(e.event??e.market??e.name)}`,[["Venue","Polymarket CLOB"],["Event",s(e.event)],["Market",s(e.market)],["Market id",A(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 ze(t={}){let e=t||{},r=m(e.completedSplits)&&m(e.totalSplits)?`${L(e.completedSplits,{decimals:0})} / ${L(e.totalSplits,{decimals:0})}`:u;return C(`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 Ve(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 C(`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 We(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("; "):u}function Ke(t){let e=t.rankedOn??t.swap?.rankedOn??t.best?.rankedOn;return m(e)?s(e):u}function Je(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",Ke(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`:u],["Runners-up",We(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)),C(`ORACLE SWAP \u2014 ${a}`,i,e)}function Ge(t={}){let e=t||{};return C("ORACLE APPROVE \u2014 local signer",[["Pending id",A(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",A(e.to??e.destination)],["Value",m(e.value)?s(e.value):u],["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 At=Object.freeze({token:je,launch:De,hip3:He,hip4:Fe,polymarket:qe,twap:ze,bridge:Ve,swap:Je,approve:Ge});var nt=Object.freeze(["deepen","refresh","prepare","ta","fa","long","short","allow","deny"]),it=new Set(nt),G=/^[a-z0-9-]{4,40}$/i,se=/^[0-9a-f]{32}$/,ce=/^\d+$/;function Y(t=process.env){return ae(t.ORACLE_CONFIG_DIR||ae(tt(),".config","oracle"),"telegram-cards.json")}function P(){return{links:{},artifacts:{},threads:{}}}var H=P();function X(){return H}function le(t,{readFile:e=Qe}={}){try{let r=JSON.parse(String(e(t)));H={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{H=P()}return H}function ue(t,e=H,{writeFile:r=et,mkdir:n=Ze}={}){n(rt(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 Ye("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 ot(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(!G.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}),d=l("long"),c=l("short"),f=d&&c?[{text:"LONG",url:d},{text:"SHORT",url:c}]:[{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):u}`,`Id: ${I(t.id)?`\`${String(t.id).replace(/`/g,"")}\``:u}`,`Summary: ${I(t.summary)?s(t.summary):u}`,`Confidence: ${K(t.confidence)}`];(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(o=>s(o)).join("; ")}`);let n=D(t);return r.push(n.allowed?"Actions: TA / FA / LONG / SHORT open the graph. Execute on CONFIRM there.":`Actions: TA / FA / LONG / SHORT \u2014 ${s(n.reason)}`),r.join(`
|
|
6
|
+
`)}function at(t,e={},{now:r=Date.now()}={}){let n=t||P(),o=String(e.id||"").trim().toLowerCase();if(!G.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||P(),a=String(e||"").trim(),i=String(r||"").trim().toLowerCase();if(!a)throw new TypeError("chat id required");if(!G.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=Xe}={}){let l=t||P(),d=String(e||"").trim(),c=String(r||"").replace(/^@/,"").trim();if(!ce.test(d))throw new TypeError("owner Telegram id required");if(!/^[A-Za-z0-9_]{5,32}$/.test(c))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:d,expiresAt:n+Number(o)},{token:f,url:`https://t.me/${c}?start=${f}`,expiresAt:n+Number(o)}}function ge(t,{token:e,telegramUserId:r,now:n=Date.now()}={}){let o=t||P(),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),d=o.links[l];return d?(delete o.links[l],Number(d.expiresAt)<=n?{ok:!1,error:"start token expired"}:String(d.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=ot(e);if(!a)return null;if(!it.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=D({grant:n},{now:o}),d=fe({artifactId:i.id,openUrl:i.openUrl,hasGrant:l.allowed});return a.action==="refresh"?{text:pe(i),buttons:d,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:d,prompt:null,prepare:{artifactId:i.id,unsigned:!0,broadcast:!1}}:{text:`Prepare blocked \u2014 ${l.reason}. Deepen and Refresh still work.`,buttons:d,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=at(o,{...t,id:a},{now:r}),l=D({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)
|
|
8
7
|
|
|
9
8
|
oracle telegram link --owner <tg-id> --bot <username>
|
|
10
9
|
oracle telegram redeem --token <32hex> --user <tg-id>
|
|
@@ -14,10 +13,10 @@ import{createInterface as Ae}from"node:readline";var A=Object.freeze({maxRequest
|
|
|
14
13
|
|
|
15
14
|
Native oracle-gateway uses the same module. Hermes is an optional adapter that
|
|
16
15
|
must call this CLI instead of owning card state. Prepare is unsigned. Execute
|
|
17
|
-
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
|
|
18
|
-
`)}async function ke(t=[],e={}){let r=e.out??process.stdout,n=e.err??process.stderr,
|
|
19
|
-
`),0;let
|
|
20
|
-
`),1}if(
|
|
21
|
-
`),1}if(
|
|
22
|
-
${
|
|
23
|
-
`),1}var
|
|
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 st(){return le(Y()),X()}function V(t){ue(Y(),t)}function M(t,e){t.write(JSON.stringify(e)+`
|
|
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
|
+
`),0;let a=st();if(o==="link")try{let i=he(a,{ownerId:b(t,"--owner"),botUsername:b(t,"--bot")});return V(a),M(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),M(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),M(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
|
+
`),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?(M(r,{ok:!0,...i}),0):(M(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 M(r,{ok:!0,prompt:i}),0}return n.write(`unknown telegram verb '${o}'
|
|
21
|
+
${xe}
|
|
22
|
+
`),1}var ct=40,lt=200,ut=4e3,dt=4e3,ft=128,$e=/^[a-z0-9][a-z0-9-]{3,39}$/i,Q=/^\d{1,20}$/,pt=/^oracle:card:(deepen|refresh|prepare|ta|fa|long|short|allow|deny):[a-z0-9][a-z0-9-]{3,39}$/i;function mt(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 ht(){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=ht(),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 gt=[{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"}}}}],yt={name:"oracle-telegram",version:"2",tools:gt,async call(t,e={},{env:r=process.env}={}){let n=mt(r);try{if(t==="telegram_wrap"){let o=["wrap","--id",_(e.id,{field:"id",max:ct,pattern:$e}),"--title",_(e.title,{field:"title",max:lt}),"--summary",_(e.summary,{field:"summary",max:ut})];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:ft,pattern:pt}),"--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:dt})])}catch(o){return Se(o.message)}return Se("unknown tool")}};process.argv[1]&&process.argv[1].endsWith("oracle-telegram-mcp.mjs")&&te(yt);export{mt as grantFromEnv,yt as server};
|