@oracle-agent/oracle 0.32.0 → 0.34.0
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/graphics/oracle_card.py +36 -6
- package/dist/assets/skills/oracle-chain-graphs-telegram-cards/SKILL.md +6 -0
- package/dist/assets/skills/oracle-desk-product/SKILL.md +1 -1
- package/dist/bin/oracle-gateway.mjs +38 -37
- package/dist/bin/oracle-telegram-mcp.mjs +23 -0
- package/dist/bin/oracle.mjs +2 -1
- package/dist/cli/commands/auth.mjs +8 -8
- package/dist/cli/commands/chat.mjs +192 -180
- package/dist/cli/commands/doctor.mjs +1 -1
- package/dist/cli/commands/eval.mjs +84 -81
- package/dist/cli/commands/harness.mjs +1 -1
- package/dist/cli/commands/model.mjs +196 -184
- package/dist/cli/commands/setup.mjs +49 -47
- package/dist/cli/commands/telegram.mjs +20 -0
- package/dist/cli/commands/venues.mjs +1 -1
- package/package.json +6 -5
|
@@ -34,8 +34,27 @@ ORACLE = {
|
|
|
34
34
|
"chip_ink": "#061018",
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
# Assets ship with the package, next to this
|
|
38
|
-
|
|
37
|
+
# Assets ship with the package. Search env, next to this file, then the
|
|
38
|
+
# published npm graphics tree so a copied renderer still finds lockups.
|
|
39
|
+
def _resolve_assets() -> Path:
|
|
40
|
+
env = os.environ.get("ORACLE_CARD_ASSETS")
|
|
41
|
+
if env:
|
|
42
|
+
p = Path(env)
|
|
43
|
+
if p.is_dir():
|
|
44
|
+
return p
|
|
45
|
+
here = Path(__file__).resolve().parent
|
|
46
|
+
candidates = [
|
|
47
|
+
here / "assets",
|
|
48
|
+
here.parent / "assets" / "graphics" / "assets",
|
|
49
|
+
here.parent / "graphics" / "assets",
|
|
50
|
+
]
|
|
51
|
+
for cand in candidates:
|
|
52
|
+
if (cand / "robinhood-lockup.png").is_file() or (cand / "oracle-globe.png").is_file():
|
|
53
|
+
return cand
|
|
54
|
+
return here / "assets"
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
_ASSETS = _resolve_assets()
|
|
39
58
|
_WM = _ASSETS
|
|
40
59
|
ORACLE_MARK = _ASSETS / "oracle-globe.png"
|
|
41
60
|
CHAINS = {
|
|
@@ -224,6 +243,16 @@ def chain_meta(venue: str) -> dict:
|
|
|
224
243
|
return CHAINS.get(key, {"label": key.upper() or "UNKNOWN", "accent": ORACLE["blue"], "logo": None, "kind": "ohlc"})
|
|
225
244
|
|
|
226
245
|
|
|
246
|
+
def _logo_wh(lockup):
|
|
247
|
+
size = getattr(lockup, "size", None)
|
|
248
|
+
if isinstance(size, (tuple, list)) and len(size) >= 2:
|
|
249
|
+
return int(size[0] or 0), int(size[1] or 0)
|
|
250
|
+
shape = getattr(lockup, "shape", None)
|
|
251
|
+
if isinstance(shape, tuple) and len(shape) >= 2:
|
|
252
|
+
return int(shape[1] or 0), int(shape[0] or 0)
|
|
253
|
+
return 180, 28
|
|
254
|
+
|
|
255
|
+
|
|
227
256
|
def _load_logo(path: Path | None):
|
|
228
257
|
if not path or not Path(path).exists():
|
|
229
258
|
return None
|
|
@@ -275,11 +304,12 @@ def _chrome(fig, *, venue: str, eyebrow: str, hero: str, hero_color: str, chip:
|
|
|
275
304
|
drew_lockup = False
|
|
276
305
|
if lockup is not None:
|
|
277
306
|
try:
|
|
278
|
-
w, h =
|
|
307
|
+
w, h = _logo_wh(lockup)
|
|
279
308
|
aspect = (w / max(h, 1)) if w and h else 6.0
|
|
280
|
-
lh = 0.
|
|
281
|
-
lw = min(lh * aspect * (6.3 / 11.2), 0.
|
|
282
|
-
lax = fig.add_axes([tag_x + 0.
|
|
309
|
+
lh = 0.062
|
|
310
|
+
lw = min(lh * aspect * (6.3 / 11.2), 0.30)
|
|
311
|
+
lax = fig.add_axes([tag_x + 0.052, 0.922 - lh / 2, lw, lh], zorder=8)
|
|
312
|
+
lax.set_facecolor("none")
|
|
283
313
|
lax.imshow(lockup)
|
|
284
314
|
lax.axis("off")
|
|
285
315
|
drew_lockup = True
|
|
@@ -43,6 +43,12 @@ cards.
|
|
|
43
43
|
prepares an unsigned artifact for the local signer / owner wallet.
|
|
44
44
|
- Approve cards (Photon-style Allow/Deny) are Telegram-first. They appear when
|
|
45
45
|
the local signer is running and a pending artifact exists.
|
|
46
|
+
- Interactive artifact cards (TrueNorth-style) are a separate layer:
|
|
47
|
+
`src/telegram/interactive-cards.mjs`. Desktop issues
|
|
48
|
+
`https://t.me/<bot>?start=<32-hex>` via `issueTelegramLink`. `/start <token>`
|
|
49
|
+
redeems once, owner-bound, expiring. The card itself has Deepen / Refresh /
|
|
50
|
+
optional unsigned Prepare. Follow-up text in the same DM continues that
|
|
51
|
+
artifact thread. Execute/broadcast stay on Allow/Deny only. No Mini App.
|
|
46
52
|
- `/approve` / `/deny` are owner-only fallbacks for WhatsApp, Discord, Signal,
|
|
47
53
|
and any chat that cannot render inline buttons. Do not prefer them on Telegram
|
|
48
54
|
when the card is available.
|
|
@@ -97,7 +97,7 @@ does not prove npm users receive it. A locally hosted model/data/policy loop doe
|
|
|
97
97
|
a bundled signer. A merged feature is not public until the npm artifact containing it is
|
|
98
98
|
published and inspected.
|
|
99
99
|
|
|
100
|
-
**Candidate release in this source tree:** public package `@oracle-agent/oracle@0.
|
|
100
|
+
**Candidate release in this source tree:** public package `@oracle-agent/oracle@0.34.0`
|
|
101
101
|
ships the encrypted local vault + short-lived loopback signer. Hosted/keyless
|
|
102
102
|
Oracle cannot hold keys or move funds. Self-host after `oracle sign init|import` is **auto-armed**
|
|
103
103
|
for user-initiated actions. Public still charges the disclosed fee card; Administrator
|
|
@@ -1,50 +1,51 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var
|
|
3
|
-
`,{mode:384}),
|
|
4
|
-
`)}function
|
|
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
|
|
2
|
+
var Sr=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 M=(t,e)=>{for(var r in e)Sr(t,r,{get:e[r],enumerable:!0})};var qe={};M(qe,{A2ABus:()=>me,normalizeName:()=>X});function X(t){return String(t||"").trim().toLowerCase().replace(/^@/,"")}var me,We=w(()=>{me=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=X(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(X(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=X(e),l=X(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 br from"node:os";import F from"node:path";import{fileURLToPath as xr}from"node:url";function he(){return process.env.ORACLE_FAKE_HOME||br.homedir()}function Ar(){return process.env.ORACLE_PUBLIC_DESKTOP==="1"}function C(){return Ar()?process.env.ORACLE_CONFIG_DIR||F.join(he(),".config","oracle"):F.join(he(),".config","oracle")}function $r(){return F.join(C(),"desk.json")}function Cr(){return F.join(C(),"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=Cr();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=$r();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 vr,Uo,ie=w(()=>{vr=F.dirname(xr(import.meta.url)),Uo=F.resolve(vr,"../..");try{B()}catch{}});function se(t){return String(t||"").trim()||void 0}function Er(t,{required:e=!1}={}){let r=se(t)?.toLowerCase();if(!r){if(e)throw new Error("model provider is required");return}if(!_r.has(r))throw new Error(`unsupported provider: ${r}`);return r}function Or(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 Rr(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 ze({provider:t,model:e,baseUrl:r}={},{requireModel:n=!1}={}){let o=Er(t),a=Or(e,{required:n});if(o==="custom")return{provider:o,...a?{model:a}:{},baseUrl:Rr(r)};if(se(r))throw new Error("baseUrl is only supported for the custom provider");return{...o?{provider:o}:{},...a?{model:a}:{}}}var _r,Ve=w(()=>{_r=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 Ke(){return ge.join(C(),"model.json")}function H(t){return String(t||"").trim()||void 0}function Ye(t={}){let e=H(t.backend)?.toLowerCase()||"auto",r=ze({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(!Ir.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=Ke();if(!G.existsSync(t))return null;try{return Ye(JSON.parse(G.readFileSync(t,"utf8")))}catch{return null}}function ye(t){let e=Ye(t),r=Ke();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 Ir,Je=w(()=>{ie();Ve();Ir=new Set(["auto","standalone","hermes","remote","arch"])});import{existsSync as Lr,readFileSync as Nr}from"node:fs";import{request as Tr}from"node:http";import Pr from"node:path";function jr(t=process.env){let e=String(t.ORACLE_SIGNER_URL||Dr).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 Ur(t=process.env){if(t.ORACLE_SIGNER_TOKEN)return String(t.ORACLE_SIGNER_TOKEN);let e=Pr.join(C(),"signer","signer-token");return Lr(e)?Nr(e,"utf8").trim():null}function T(t,{method:e="GET",body:r=null,env:n=process.env,timeoutMs:o=4e3}={}){let a=jr(n),i=Ur(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=Tr({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 f=[];p.on("data",h=>f.push(h)),p.on("end",()=>{let h=Buffer.concat(f).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 Dr,ce=w(()=>{ie();Dr="http://127.0.0.1:9462"});function Qe(t){return Br.get(Number(t))||null}var Mr,Br,Xe=w(()=>{Mr={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}},Br=new Map(Object.values(Mr).map(t=>[t.chainId,t]))});function u(t){return S(t)?String(t).replace(Fr,e=>`\\${e}`):m}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 m;let e=String(t).replace(/`/g,"");return e===""?m:`\`${e}\``}function P(t,{decimals:e=2}={}){if(!S(t))return m;let r=Number(t);return Number.isFinite(r)?r.toLocaleString("en-US",{minimumFractionDigits:0,maximumFractionDigits:e}):m}function b(t,{decimals:e=2}={}){let r=P(t,{decimals:e});return r===m?m:`${r} USD`}function we(t,{decimals:e=2}={}){let r=P(t,{decimals:e});return r===m?m:`${r}%`}function le(t){let e=P(t,{decimals:0});return e===m?m:`${e} bps`}function D(t,e){if(!S(t))return m;let r=Number(e);if(!Number.isInteger(r)||r<0||r>77)return m;let n;try{n=BigInt(typeof t=="string"?t.trim():t)}catch{return m}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 ke(t){if(typeof t=="number"&&Number.isFinite(t))return t<0||t>1?m: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 m}function R(t={}){let e=t.chainId;if(!S(e)||!Number.isFinite(Number(e)))return S(t.chain)?u(t.chain):m;let n=Qe(e)?.name||(S(t.chain)?String(t.chain):m);return`${u(n)} (chainId ${Number(e)})`}function Ze(t={}){return u(t.venue??t.dex??t.pool?.venue)}function Hr(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 j(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 Gr(t){let e=j(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,a]of e)n.push(`${o}: ${a==null||a===""?m:a}`);return n.push(`Chart: ${Hr(r.chart)}`),n.push(`Actions: ${Gr(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){return["Confidence",ke(t.confidence)]}function qr(t){let e=t.quote;if(!e||typeof e!="object")return[];let r=S(e.decimals)?D(e.amountOutRaw??e.out??e.raw,e.decimals):m;return[["Quote out (raw)",A(e.amountOutRaw??e.out??e.raw)],["Quote out",r===m?m:`${u(r)} ${u(e.symbol??"")}`.trim()]]}function et(t){let e=t.autoSlippage;if(!e||typeof e!="object")return["Auto-slippage",m];let r=le(e.selectedBps),n=le(e.capBps);return["Auto-slippage",r===m&&n===m?m:`${r} selected, cap ${n}`]}function Wr(t={}){let e=t||{};return _(`ORACLE TOKEN \u2014 ${u(e.symbol??e.token??e.name)}`,[["Chain",R(e)],["Venue",Ze(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",we(e.priceChange24h)],["Fee tier",S(e.feeTier)?`${le(Number(e.feeTier)/100)} (${P(e.feeTier,{decimals:0})})`:m],["Age",u(e.age)],...qr(e),et(e),E(e)],e)}function zr(t={}){let e=t||{};return _(`ORACLE LAUNCH \u2014 ${u(e.symbol??e.token??e.name)}`,[["Chain",R(e)],["Venue",Ze(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)],et(e),E(e)],e)}function Vr(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",we(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 Kr(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",we(e.edge)],["Position",u(e.position)],E(e)],e)}function Yr(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 Jr(t={}){let e=t||{},r=S(e.completedSplits)&&S(e.totalSplits)?`${P(e.completedSplits,{decimals:0})} / ${P(e.totalSplits,{decimals:0})}`:m;return _(`ORACLE TWAP \u2014 ${u(e.pair??e.symbol??e.name)}`,[["Chain",R(e)],["Side",u(e.side??e.direction)],["Amount",`${u(D(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 Qr(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(D(e.amount,e.fromDecimals??18))} ${u(e.fromSymbol??"")}`.trim()],["Best route",u(e.bestRoute??e.winner)],["Est. received",`${u(D(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 Xr(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("; "):m}function Zr(t){let e=t.rankedOn??t.swap?.rankedOn??t.best?.rankedOn;return S(e)?u(e):m}function en(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(D(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(D(o.netOut??o.amountOut??r.amountOut,e.decimalsOut??18))} ${u(e.tokenOutSymbol??"")}`.trim()],["Ranked on",Zr(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`:m],["Runners-up",Xr(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(D(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 Se(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):m],["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 be({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
|
+
`),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 m,Zo,Fr,ea,xe=w(()=>{Xe();m="UNKNOWN",Zo=Object.freeze(["token","launch","hip3","hip4","polymarket","twap","bridge","swap","approve"]),Fr=/[_*[\]`]/g;ea=Object.freeze({token:Wr,launch:zr,hip3:Vr,hip4:Kr,polymarket:Yr,twap:Jr,bridge:Qr,swap:en,approve:Se})});function ve(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 Ae(t,{platform:e,grant:r,armed:n}){if(!t.length)return{text:"No pending local-signer artifacts.",buttons:be({platform:e,hasGrant:!1})};let o=t[0];return{text:t.map(i=>Se({...i,armed:n,grant:r,confidence:n?"high":"medium"})).join(`
|
|
6
6
|
|
|
7
|
-
`),buttons:
|
|
8
|
-
`),buttons:null}}let
|
|
9
|
-
Tx: \`${s}\``,buttons:null,executed:!0,hash:s}:{text:`Local signer executed ${d}. Check the signer receipt if no hash was returned.`,buttons:null,executed:!0,result:
|
|
10
|
-
`)}catch{}}async function
|
|
11
|
-
Update it the same way you installed it \u2014 git pull, or npm install -g @oracle-agent/oracle@latest.`};let o=`${
|
|
7
|
+
`),buttons:be({platform:e,id:o.id,digest:o.digest,hasGrant:j({grant:r}).allowed})}}async function $e({platform:t,text:e,grant:r={local:!0},env:n=process.env,ownerProof:o}={}){let a=ve(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 f=Array.isArray(p.items)?p.items:[],h=Ae(f,{platform:t,grant:r,armed:p.armed===!0});if(i)return h;if(!f.length)return{text:"No pending local-signer artifacts. /approve is only needed when cards are unavailable.",buttons:null};let g=f.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(`
|
|
8
|
+
`),buttons:null}}let l=a.verb==="approve"?"/ack":"/deny";if(!a.id)return{text:"Usage: /approve <id> (only when approve cards are not available)",buttons:null};let c=await T(l,{method:"POST",body:{id:a.id,...o?{ownerProof:o}:{}},env:n});if(c.httpStatus===404||c.error==="no pending artifact")return{text:"Nothing pending with that id. It may have expired or already been decided.",buttons:null};if(c.ok===!1||c.httpStatus&&c.httpStatus>=400)return{text:`Local signer refused: ${c.error||"not running"}`,buttons:null};if(a.verb==="deny")return{text:`Denied ${c.id||a.id}. Artifact dropped. Nothing signed.`,buttons:null};let s=c.result?.hash||c.result?.txHash||c.result?.transactionHash||c.hash,d=c.id||a.id;return s?{text:`Bought. Local signer executed ${d}.
|
|
9
|
+
Tx: \`${s}\``,buttons:null,executed:!0,hash:s}:{text:`Local signer executed ${d}. Check the signer receipt if no hash was returned.`,buttons:null,executed:!0,result:c.result||null}}async function tt({platform:t,data:e,senderId:r,chatId:n,ownerProofAuthority:o,grant:a={local:!0},env:i=process.env}={}){let c=String(e||"").match(/^oracle:(approve|deny):([0-9a-fA-F]{4,64})$/i);if(!c)return null;let s=c[1].toLowerCase()==="approve"?"approve":"deny",d;if(s==="approve"&&o){let f=(await T("/pending",{env:i})).items?.find(h=>h.id===c[2].toLowerCase()||h.digest===c[2].toLowerCase());if(!f)return{text:"Nothing pending with that id. It may have expired or already been decided.",buttons:null};d=o.mint({digest:f.digest,senderId:r,chatId:n,platform:t})}return $e({platform:t,text:`/${s} ${c[2]}`,grant:a,env:i,ownerProof:d})}var Ce=w(()=>{ce();xe();ce()});import{execFile as tn}from"node:child_process";import{existsSync as rn,mkdirSync as nn,readFileSync as rt,realpathSync as on,writeFileSync as an}from"node:fs";import I from"node:path";import{promisify as sn}from"node:util";import{fileURLToPath as nt}from"node:url";function dn(t=import.meta.url){try{let e=on(nt(t)),r=`${I.sep}node_modules${I.sep}`,n=e.lastIndexOf(r);if(n>0)return{root:e.slice(0,n),managed:!0}}catch{}return{root:null,managed:!1}}function Ee(t=import.meta.url){try{let e=I.dirname(nt(t));for(let r=0;r<8;r+=1){let n=I.join(e,"package.json");if(rn(n)){let a=JSON.parse(rt(n,"utf8"));if(a?.name===_e&&a.version)return a.version}let o=I.dirname(e);if(o===e)break;e=o}}catch{return null}return null}function pn(t,e){let r=a=>String(a).replace(/^v/,"").split("-")[0].split(".").map(i=>Number.parseInt(i,10)||0),n=r(t),o=r(e);for(let a=0;a<Math.max(n.length,o.length);a+=1){let i=n[a]??0,l=o[a]??0;if(i>l)return 1;if(i<l)return-1}return 0}function ot(t){let e=t?.stateDir||I.join(process.env.HOME||".",".oracle");return I.join(e,"update-check.json")}function fn(t){try{return JSON.parse(rt(ot(t),"utf8"))}catch{return null}}function mn(t,e){try{let r=ot(t);nn(I.dirname(r),{recursive:!0}),an(r,`${JSON.stringify(e,null,2)}
|
|
10
|
+
`)}catch{}}async function hn({timeoutMs:t=4e3}={}){try{let e=new AbortController,r=setTimeout(()=>e.abort(),t),n=await fetch(`${ln}/${encodeURIComponent(_e)}/latest`,{signal:e.signal});return clearTimeout(r),n.ok&&(await n.json())?.version||null}catch{return null}}async function at({paths:t,force:e=!1,timeoutMs:r=4e3}={}){let n=Ee(),o=e?null:fn(t),i=o&&Date.now()-(o.checkedAt||0)<un?o.latest:null;return i||(i=await hn({timeoutMs:r}),i&&mn(t,{latest:i,checkedAt:Date.now()})),!n||!i?{current:n,latest:i,updateAvailable:!1,checked:!!i}:{current:n,latest:i,updateAvailable:pn(i,n)>0,checked:!0}}async function it({version:t="latest",dryRun:e=!1}={}){let{root:r,managed:n}=dn();if(!n||!r)return{ok:!1,reason:"unmanaged",message:`oracle is not running from a resolvable node_modules tree (source checkout or linked dev install).
|
|
11
|
+
Update it the same way you installed it \u2014 git pull, or npm install -g @oracle-agent/oracle@latest.`};let o=`${_e}@${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 cn("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 cn,_e,ln,un,st=w(()=>{cn=sn(tn),_e="@oracle-agent/oracle",ln="https://registry.npmjs.org",un=1440*60*1e3});import gn from"node:fs";import yn from"node:os";import ct from"node:path";function W(t){return String(t||"").trim().toLowerCase().replace(/^\/+/,"").replace(/\s+/g,"-")}function wn(){let t=process.env.ORACLE_CONFIG_DIR||ct.join(yn.homedir(),".config","oracle");return ct.join(t,"chains.json")}function kn(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(!ut.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"&&ut.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 Sn(t=gn.readFileSync){try{let e=JSON.parse(t(wn(),"utf8")),r=Array.isArray(e?.chains)?e.chains:[],n=[],o=new Set;for(let a of r){let i=kn(a);!i||o.has(i.key)||(o.add(i.key),n.push(i))}return n}catch{return[]}}function dt(){let t=Sn();if(t.length===0)return lt;let e=new Map(lt.map(r=>[r.key,r]));for(let r of t)e.set(r.key,r);return[...e.values()]}function bn({buildOnly:t=!1}={}){return dt().filter(e=>t?e.build:!0)}function ee(t){let e=W(t);if(!e)return null;for(let r of dt())if(r.key===e||String(r.chainId).toLowerCase()===e||(r.aliases||[]).map(W).includes(e)||W(r.name)===e)return r;return null}function pt({selectedKey:t=null,buildOnly:e=!1}={}){let r=bn({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
|
-
`}var
|
|
14
|
-
`,{mode:384}),r}var
|
|
15
|
-
`)}
|
|
16
|
-
Oracle
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
`}var lt,ut,Oe=w(()=>{lt=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}]);ut=/^[a-z0-9][a-z0-9-]*$/});import Re from"node:fs";import xn from"node:path";function ft(){return xn.join(C(),"active-chain.json")}function Ie(){let t=ft();if(!Re.existsSync(t))return null;try{let e=JSON.parse(Re.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 mt(t){let e=ee(t);if(!e){let n=new Error(`unknown chain '${t}'`);throw n.code="UNKNOWN_CHAIN",n}ae(C());let r={key:e.key,chainId:e.chainId,name:e.name,agent:e.agent,selectedAt:new Date().toISOString()};return Re.writeFileSync(ft(),JSON.stringify(r,null,2)+`
|
|
14
|
+
`,{mode:384}),r}var ht=w(()=>{Oe();ie()});import{createHash as vn,randomBytes as Aa}from"node:crypto";import{mkdirSync as An,readFileSync as $n,writeFileSync as Cn}from"node:fs";import{homedir as _n}from"node:os";import{dirname as En,join as gt}from"node:path";function re(t=process.env){return gt(t.ORACLE_CONFIG_DIR||gt(_n(),".config","oracle"),"telegram-cards.json")}function ne(){return{links:{},artifacts:{},threads:{}}}function ue(){return te}function yt(t,{readFile:e=$n}={}){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=Cn,mkdir:n=An}={}){n(En(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 Nn(t){return vn("sha256").update(String(t)).digest("hex")}function Le(t){if(Array.isArray(t))return t.map(Le);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]=Le(n));return e}function Tn(t){let r=String(t||"").trim().match(/^oracle:card:(deepen|refresh|prepare):([a-z0-9-]{4,40})$/i);return r?{action:r[1].toLowerCase(),artifactId:r[2].toLowerCase()}:null}function wt({platform:t="telegram",artifactId:e,openUrl:r,hasGrant:n=!1}={}){let o=String(e||"").trim().toLowerCase();if(!Ne.test(o))return{kind:"text_menu",text:"no artifact to continue",cancelHint:""};let a=[];L(r)&&a.push({text:"Open",url:String(r)});let i=[{text:"Deepen",callback_data:`oracle:card:deepen:${o}`},{text:"Refresh",callback_data:`oracle:card:refresh:${o}`}];if(n&&i.push({text:"Prepare",callback_data:`oracle:card:prepare:${o}`}),String(t)==="telegram")return{kind:"inline_keyboard",replyMarkup:{inline_keyboard:[a,i].filter(s=>s.length>0)},cancelHint:n?"Prepare queues an unsigned artifact. Allow/Deny still required to sign.":"prepare-only \u2014 Deepen and Refresh stay read-only."};let l=[],c=0;for(let s of[...a,...i])c+=1,l.push(s.url?`${c}. ${s.text}: ${s.url}`:`${c}. ${s.text} (reply ${c})`);return{kind:"text_menu",text:l.join(`
|
|
15
|
+
`),cancelHint:""}}function kt(t={}){let r=[`*${L(t.title)?u(t.title):"Oracle artifact"}*`,`Kind: ${L(t.kind)?u(t.kind):m}`,`Id: ${L(t.id)?`\`${String(t.id).replace(/`/g,"")}\``:m}`,`Summary: ${L(t.summary)?u(t.summary):m}`,`Confidence: ${ke(t.confidence)}`];(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(o=>u(o)).join("; ")}`);let n=j(t);return r.push(n.allowed?"Actions: Deepen / Refresh / Prepare (unsigned)":`Actions: Deepen / Refresh \u2014 ${u(n.reason)}`),r.join(`
|
|
16
|
+
`)}function Pn(t,e={},{now:r=Date.now()}={}){let n=t||ne(),o=String(e.id||"").trim().toLowerCase();if(!Ne.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:Le(e.payload||{}),createdAt:new Date(r).toISOString()};return n.artifacts[o]=a,a}function Te(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(!Ne.test(i))throw new TypeError("artifact id required");return o.threads[a]={artifactId:i,updatedAt:n},o.threads[a]}function St(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 bt(t,{token:e,telegramUserId:r,now:n=Date.now()}={}){let o=t||ne(),a=String(e||"").trim(),i=String(r||"").trim();if(!In.test(a))return{ok:!1,error:"invalid start token"};if(!Ln.test(i))return{ok:!1,error:"invalid telegram user"};let l=Nn(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 xt(t,{data:e,chatId:r,grant:n=null,now:o=Date.now()}={}){let a=Tn(e);if(!a)return null;if(!Rn.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&&Te(t,{chatId:r,artifactId:i.id,now:o});let l=j({grant:n},{now:o}),c=wt({artifactId:i.id,openUrl:i.openUrl,hasGrant:l.allowed});return a.action==="refresh"?{text:kt(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.`}: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 vt(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=Pn(o,{...t,id:a},{now:r}),l=j({grant:e},{now:r});return{text:kt({...i,grant:e}),replyMarkup:wt({artifactId:i.id,openUrl:i.openUrl,hasGrant:l.allowed}).replyMarkup,artifact:i,state:o}}var On,Rn,Ne,In,Ln,te,Pe=w(()=>{xe();On=Object.freeze(["deepen","refresh","prepare"]),Rn=new Set(On),Ne=/^[a-z0-9-]{4,40}$/i,In=/^[0-9a-f]{32}$/,Ln=/^\d+$/;te=ne()});var zt={};M(zt,{NON_OWNER_REPLY:()=>V,buildPersona:()=>K,handleSelfUpdate:()=>Rt,isForwarded:()=>It,isOwnerSender:()=>z,ownerIdsFor:()=>Et,parseGatewayChainCommand:()=>Bt,parseGatewayCompactCommand:()=>Mt,parseGatewayEffortCommand:()=>Pt,parseGatewayGoalCommand:()=>Ut,parseGatewayHelpCommand:()=>Dt,parseGatewayModelCommand:()=>Tt,parseGatewaySetupModelCommand:()=>Vn,parseGatewayStatusCommand:()=>jt,parsePeerAsk:()=>Ht,parseSelfUpdate:()=>Ot,resolveBackendArgv:()=>Gt,resolveGatewayModel:()=>Lt,resolveOracleBin:()=>_t,routePeerConsult:()=>oe,routeToAgent:()=>O});import{spawn as Ct}from"node:child_process";import{dirname as Dn,join as je}from"node:path";import{homedir as jn}from"node:os";import{mkdirSync as Un,readFileSync as Mn,writeFileSync as Bn,unlinkSync as Fn}from"node:fs";import{fileURLToPath as Hn}from"node:url";function _t({env:t=process.env,moduleUrl:e=import.meta.url}={}){return t.ORACLE_CLI_ENTRY||je(Dn(Hn(e)),"oracle.mjs")}function Et(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?Et(t,n).has(o)?!0:Array.isArray(r)?r.map(a=>String(a).trim()).filter(Boolean).includes(o):!1:!1}function Ot(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 Rt(t,{check:e=at,update:r=it,versionOf:n=Ee}={}){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(`
|
|
17
|
+
`)}function It(t={}){return!!(t.forwarded||t.forward_from||t.forward_from_chat||t.forward_origin||t.forward_sender_name||t.forward_date)}function Lt({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 Tt(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=Nt[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 Pt(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"}:qn.includes(n)?{action:"set",reasoningEffort:n}:{action:"usage"}}function Wn({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}
|
|
18
|
+
Oracle persona unchanged. Native harness only \u2014 Hermes Telegram uses its own /model.`}function zn(t){let e=q();if(!e)throw new Error("no model configured \u2014 run /model first");return`effort ${ye({...e,reasoningEffort:t}).reasoningEffort||t}
|
|
19
|
+
Native harness only.`}function At(){let t=q(),e=["Oracle native models (tap /model <id> to switch):"];for(let[r,n]of Object.entries(Nt)){let o=t?.provider===n.provider&&t?.model===n.model?" \u2190 current":"";e.push(`/model ${r} ${n.provider} / ${n.model}${o}`)}return e.push(""),e.push("Add another provider: /setup model"),e.push("Or set exact id: /model <provider> <model-id>"),e.push("/effort low|medium|high"),t?.provider&&(e.push(""),e.push(`current ${t.provider} / ${t.model||"unset"} \xB7 effort ${t.reasoningEffort||"default"}`)),e.join(`
|
|
20
|
+
`)}function De(){let t=q();return t?[`backend ${t.backend||"auto"}`,`provider ${t.provider||"unset"}`,`model ${t.model||"unset"}`,`effort ${t.reasoningEffort||"default"}`,"Aliases: claude, codex, grok, openrouter, nous, qwen, glm, deepseek, gemini, kimi, mistral, local, ollama","/effort low|medium|high"].join(`
|
|
19
21
|
`):["No standalone model configured.","Use /model openrouter","or /model qwen","or /model glm","or /model nous","or /model <provider> <model-id>"].join(`
|
|
20
|
-
`)}function
|
|
21
|
-
`,{mode:384}),e}function
|
|
22
|
-
`)}function
|
|
23
|
-
`)}function
|
|
24
|
-
`);return
|
|
25
|
-
`),
|
|
26
|
-
`),null;let h=
|
|
27
|
-
${
|
|
28
|
-
`)}`:"No peer agents registered."}}let
|
|
29
|
-
${t}`:t;return
|
|
30
|
-
|
|
31
|
-
`),await
|
|
32
|
-
`)}}),await n.login(t.token),{platform:"discord",name:o,client:n}}var Ft=w(()=>{q()});var Gt={};T(Gt,{whatsapp:()=>Pn});import{join as Ht}from"node:path";import{homedir as Nn}from"node:os";async function Pn(t){let[{Client:e,LocalAuth:r},{generate:n}]=await Promise.all([import("whatsapp-web.js"),import("qrcode-terminal")]),o=new e({authStrategy:new r({dataPath:Ht(In,".wwebjs_auth")}),puppeteer:{headless:!0,args:["--no-sandbox"]}});return o.on("qr",a=>{process.stderr.write(`
|
|
22
|
+
`)}function Vn(t){let r=String(t||"").trim().match(/^\/setup(?:\s+model(?:\s+(.+))?)?$/i);if(!r)return null;let n=String(r[1]||"").trim();return n?{action:"hint",provider:n.split(/\s+/)[0]}:{action:"menu"}}function Dt(t){let e=String(t||"").trim();return/^\/(?:help|commands|\?)$/i.test(e)?{action:"help"}:null}function jt(t){let e=String(t||"").trim();return/^\/(?:status|usage)$/i.test(e)?{action:"status"}:null}function Ut(t){let r=String(t||"").trim().match(/^\/goal(?:\s+(.+))?$/i);if(!r)return null;let n=String(r[1]||"").trim();return!n||n.toLowerCase()==="show"?{action:"show"}:/^(clear|done|complete)$/i.test(n)?{action:"clear"}:{action:"set",goal:n}}function Mt(t){let r=String(t||"").trim().match(/^\/(?:compact|compress)(?:\s+(.+))?$/i);return r?{action:"compact",focus:String(r[1]||"").trim()}:null}function Bt(t){let r=String(t||"").trim().match(/^\/chain(?:\s+(.+))?$/i);if(!r)return null;let n=String(r[1]||"").trim();return!n||n.toLowerCase()==="list"?{action:"list"}:{action:"set",chain:n}}function Me(){return je(Ue,"gateway-goal.json")}function Ft(){try{let t=JSON.parse(Mn(Me(),"utf8"));return t&&typeof t.goal=="string"?t:null}catch{return null}}function Kn(t){Un(Ue,{recursive:!0,mode:448});let e={schemaVersion:1,goal:String(t),updatedAt:new Date().toISOString()};return Bn(Me(),`${JSON.stringify(e,null,2)}
|
|
23
|
+
`,{mode:384}),e}function Yn(){try{Fn(Me())}catch{}}function Jn(){return["Oracle native Telegram \u2014 owner commands","","Start here","/help this list","/commands same as /help","/status model, effort, chain, goal","","Models (like TUI /model)","/model list models you can use now","/model <id> switch: openrouter, nous, qwen, glm, claude, codex, grok, deepseek, gemini, kimi, mistral","/model <provider> <id> set an exact model id","/setup model how to add OpenRouter, Nous Portal, Qwen, GLM, ...","/setup model <id> TTY command to add that provider (never paste keys here)","/effort show current reasoning effort","/effort low|medium|high set effort like Hermes","","Session (like TUI / Hermes)","/goal show pinned objective","/goal <text> pin the session objective","/goal clear clear the objective","/compact [focus] compact context","/compress [focus] alias for /compact","/chain list working chains","/chain <name> switch chain","","Trading / signer","/update install latest Oracle","/approve Allow pending local-signer action","/deny Deny pending local-signer action","","Do not paste API keys into Telegram. Hermes Telegram keeps its own /model."].join(`
|
|
24
|
+
`)}function Qn(){let t=De(),e=Ie(),r=Ft();return[t,`chain ${e?.key||e?.name||"default"}`,`goal ${r?.goal||"unset"}`].join(`
|
|
25
|
+
`)}function Ht(t){let e=String(t||"").trim();if(!e)return null;let r=e.match(/^\/ask(?:@[\w_]+)?\s+([\w-]+)\s+([\s\S]+)$/i);return r||(r=e.match(/^@([\w-]+)\s+([\s\S]+)$/)),r?{peer:r[1].toLowerCase(),text:r[2].trim()}:null}function K(t={}){let e=[];return t.role&&e.push(String(t.role)),Array.isArray(t.chains)&&t.chains.length&&e.push(`chains: ${t.chains.join(", ")}`),t.persona&&e.push(String(t.persona)),e.join(" \xB7 ")}function Gt(t,e,{profile:r}={}){let n=String(t||"oracle").toLowerCase(),o=String(e||"");if(n==="oracle")return{ok:!0,bin:null,args:["chat","-q",o]};if(n==="grok")return{ok:!0,bin:"grok",args:["-p",o]};if(n==="hermes"){let a=[];return r&&a.push("-p",String(r)),a.push("-z",o),{ok:!0,bin:"hermes",args:a}}return n==="claude"?{ok:!0,bin:"claude",args:["-p",o]}:{ok:!1,error:`unknown backend '${t}' (allowed: oracle, grok, hermes, claude)`}}async function oe({from:t,text:e,persona:r="",backend:n,profile:o}={}){let a=[`[a2a consult from agent '${t}' \u2014 answer with information only; do not prepare, arm, or execute anything]`,r?`[your role: ${r}]`:"",String(e||"").trim()].filter(Boolean).join(`
|
|
26
|
+
`);return Wt({text:a,backend:n,profile:o,unconfiguredPrefix:"unconfigured: "})}async function O({platform:t,chatId:e,senderId:r,text:n,userName:o,meta:a={},updater:i,extraOwners:l,bus:c,agentName:s,persona:d,backend:p,profile:f}={}){if(!z({platform:t,senderId:r,extraOwners:l}))return process.stderr.write(`gateway: denied non-owner sender ${t}:${String(r||"unknown")}
|
|
27
|
+
`),V;if(It(a))return process.stderr.write(`gateway: dropped forwarded message on ${t}
|
|
28
|
+
`),null;let h=Ot(n);if(h)return Rt(h,i);let g=Tt(n);if(g)try{return g.action==="list"?At():g.action==="show"?De():g.action==="usage"?At():Wn(g)}catch(y){return`model not saved: ${y.message}`}let k=Pt(n);if(k)try{return k.action==="show"?De():k.action==="usage"?"usage: /effort low|medium|high":zn(k.reasoningEffort)}catch(y){return`effort not saved: ${y.message}`}if(Dt(n))return Jn();if(jt(n))return Qn();let v=Ut(n);if(v){if(v.action==="show"){let y=Ft();return y?.goal?`goal ${y.goal}`:"goal unset \u2014 /goal <objective>"}return v.action==="clear"?(Yn(),"goal cleared"):(Kn(v.goal),`goal pinned: ${v.goal}`)}let x=Mt(n);if(x){let y=x.focus?` Focus: ${x.focus}.`:"";return $t({platform:t,chatId:e,senderId:r,text:`Compact this session context now.${y} Summarize older turns, keep the current goal, model, chain, and any pending unsigned prepare artifacts. Do not sign or broadcast.`,userName:o,persona:d,backend:p,profile:f})}let $=Bt(n);if($){if($.action==="list")return pt({selectedKey:Ie()?.key||null});let y=ee($.chain);return y?(mt(y.key),`chain ${y.key}`):`unknown chain '${$.chain}' \u2014 /chain list`}if(ve(n)){let y=await $e({platform:t,text:n,grant:{local:!0}});return y?y.buttons?.kind==="inline_keyboard"?{text:y.text,replyMarkup:y.buttons.replyMarkup}:y.text:null}if(c){let y=Ht(n);if(y){let N=await c.send({from:s||"oracle",to:y.peer,text:y.text,kind:"consult"});return N.ok?N.reply?`[${y.peer}] ${N.reply}`:`[${y.peer}] (no reply)`:N.error}if(/^\/(agents|roster)\b/i.test(String(n||"").trim())){let N=c.roster().map(Q=>`\u2022 ${Q.name}${Q.role?` \u2014 ${Q.role}`:""}${Q.chains.length?` (${Q.chains.join(", ")})`:""}`);return N.length?`Agents on the bus:
|
|
29
|
+
${N.join(`
|
|
30
|
+
`)}`:"No peer agents registered."}}let kr=n.toLowerCase().trim();return/\b(buy|sell|swap|bridge|send|transfer|balance|portfolio|watch|quote|price)\b/.test(kr)?Zn({platform:t,chatId:e,senderId:r,text:n,userName:o}):$t({platform:t,chatId:e,senderId:r,text:n,userName:o,persona:d,backend:p,profile:f})}function qt(t,{timeout:e=12e4}={}){return new Promise(r=>{let n=Ct(process.execPath,[Gn,...t],{stdio:["ignore","pipe","pipe"],timeout:e,env:{...process.env,ORACLE_CONFIG_DIR:Ue}}),o="",a="";n.stdout.on("data",i=>o+=i.toString()),n.stderr.on("data",i=>a+=i.toString()),n.on("close",i=>r({code:i,out:o.trim(),err:a.trim()}))})}function Xn(t,e,{timeout:r=18e4}={}){return new Promise(n=>{let o=Ct(t,e,{stdio:["ignore","pipe","pipe"],timeout:r,env:{...process.env}}),a="",i="";o.on("error",l=>n({code:127,out:"",err:String(l.message)})),o.stdout.on("data",l=>a+=l.toString()),o.stderr.on("data",l=>i+=l.toString()),o.on("close",l=>n({code:l,out:a.trim(),err:i.trim()}))})}async function Zn({text:t,chatId:e}){let r=await qt(["route","swap","--text",t],{timeout:3e4});if(r.code===0&&r.out)try{return eo(JSON.parse(r.out),{chatId:e})}catch{return r.out}return`Trade routing failed. Try: \`${t}\` again.`}async function $t({text:t,persona:e,backend:r,profile:n}){let o=e?`[your role: ${e}]
|
|
31
|
+
${t}`:t;return Wt({text:o,backend:r,profile:n,unconfiguredPrefix:"Oracle is not configured yet: "})}async function Wt({text:t,backend:e,profile:r,unconfiguredPrefix:n}){let o=Gt(e,t,{profile:r});if(!o.ok)return`${n}${o.error}`;if(!o.bin){let i=Lt();if(!i.ok)return`${n}${i.error}`;let l=await qt(o.args);return l.code===0&&l.out?l.out:l.err||"Oracle could not answer that. Try again."}let a=await Xn(o.bin,o.args);return a.code===0&&a.out?a.out:/ENOENT/.test(a.err)?`${n}backend '${o.bin}' is not installed on this machine`:a.err||`${o.bin} could not answer that. Try again.`}function eo(t,{chatId:e}={}){if(t.error)return`\u274C ${t.error}`;let r=t.quote||t.portfolio||(t.tx?"Unsigned trade prepared. Sign from your own wallet.":"");if(!r&&!t.tx)return JSON.stringify(t,null,2);let n=vt({id:String(t.artifactId||`trade-${Date.now().toString(36)}`).toLowerCase().slice(0,40),kind:t.tx?"prepared_action":t.quote?"strategy":"thesis",title:t.tx?"Prepared trade":t.quote?"Quote":"Desk update",summary:r,payload:t},{grant:{local:!0}});return e&&Te(n.state,{chatId:e,artifactId:n.artifact.id}),de(re(),n.state),{text:n.text,replyMarkup:n.replyMarkup}}var Ue,Gn,V,Nt,qn,Y=w(()=>{Je();Ce();st();Oe();ht();Pe();Ue=process.env.ORACLE_CONFIG_DIR||je(jn(),".config","oracle");Gn=_t();V="Oracle is self-hostable. Install your own instance: npm install -g @oracle-agent/oracle";Nt=Object.freeze({claude:{provider:"anthropic-oauth",model:"claude-sonnet-4-20250514"},anthropic:{provider:"anthropic",model:"claude-sonnet-4-6"},codex:{provider:"openai-codex",model:"gpt-5.4"},openai:{provider:"openai",model:"gpt-4.1-mini"},grok:{provider:"xai-oauth",model:"grok-4.6"},xai:{provider:"xai",model:"grok-4.6"},openrouter:{provider:"openrouter",model:"openrouter/auto"},nous:{provider:"nous",model:"moonshotai/kimi-k3"},deepseek:{provider:"deepseek",model:"deepseek-chat"},gemini:{provider:"gemini",model:"gemini-2.5-flash"},kimi:{provider:"kimi",model:"kimi-k3"},mistral:{provider:"mistral",model:"mistral-large-latest"},qwen:{provider:"qwen",model:"qwen-plus"},glm:{provider:"glm",model:"glm-4.5"},local:{provider:"local",model:"Qwen3-8B-Q4_K_M"},llama:{provider:"local",model:"Qwen3-8B-Q4_K_M"},ollama:{provider:"ollama",model:"llama3.2"}}),qn=Object.freeze(["low","medium","high"])});function ro(t,e){let r=new Set,n=[];for(let o of Array.isArray(t)?t:[]){let a=typeof o?.digest=="string"?o.digest:null;a&&(r.add(a),e.has(a)||n.push(o))}e.clear();for(let o of r)e.add(o);return n}function Vt({onNew:t,intervalMs:e=to,env:r=process.env,signerCall:n=T,setIntervalFn:o=setInterval,clearIntervalFn:a=clearInterval}={}){if(typeof t!="function")throw new Error("pending-watch: onNew callback required");let i=new Set,l=!1,c=!1;async function s(){if(!c){c=!0;try{let p=await n("/pending",{env:r});if(!p||p.ok===!1||p.error||!Array.isArray(p.items))return;let f=ro(p.items,i);if(!l){l=!0;return}if(f.length===0)return;try{await t(f,{armed:p.armed===!0})}catch{}}catch{}finally{c=!1}}}let d=o(s,e);return typeof d?.unref=="function"&&d.unref(),{stop(){a(d)},tick:s}}var to,Kt=w(()=>{ce();to=4e3});import U from"node:fs";function no(t){if(!t.isFile())throw new Error("local-vault: secret source must be a regular file");if(t.uid!==process.getuid?.())throw new Error("local-vault: secret source must be owned by this user");if(t.nlink!==1)throw new Error("local-vault: refusing hard-linked secret source");if((t.mode&63)!==0)throw new Error("local-vault: secret source must be owner-only (0600)")}function Yt(t){let e;try{e=U.openSync(t,U.constants.O_RDONLY|U.constants.O_NOFOLLOW)}catch(r){throw r.code==="ELOOP"?new Error("local-vault: refusing symlink"):r}try{let r=U.fstatSync(e);if(no(r),r.size>1024*1024)throw new Error("local-vault: secret source changed or is too large");let n=U.lstatSync(t);if(n.isSymbolicLink()||n.dev!==r.dev||n.ino!==r.ino)throw new Error("local-vault: secret source changed or is too large");return U.readFileSync(e,"utf8").replace(/[\r\n]+$/,"")}finally{U.closeSync(e)}}var Wa,za,Va,Jt=w(()=>{Wa=Object.freeze({N:1<<17,r:8,p:1}),za=256*1024*1024,Va=16*1024});import{createHash as oo,createHmac as Qt,randomBytes as ao,timingSafeEqual as io}from"node:crypto";function er({keyFile:t,approvedTelegramOwners:e,nowMs:r=Date.now}={}){if(!t)throw new Error("cex owner proof: signer policy key required");let n=new Set((e||[]).map(J).filter(Boolean));if(!n.size)throw new Error("cex owner proof: approved owner context required");let o=new Set,a=l=>{let c=Buffer.from(Yt(t));try{return l(c)}finally{c.fill(0)}},i=a(l=>oo("sha256").update("cex-owner-instance\0").update(l).digest("hex"));return Object.freeze({mint({digest:l,senderId:c,chatId:s,platform:d,ttlMs:p=15e3}={}){let f=J(c),h=J(s),g=r();if(d!=="telegram"||!f||h!==f||!n.has(f))throw new Error("cex owner proof: exact Telegram owner DM required");if(!/^[0-9a-f]{64}$/.test(String(l||""))||!Number.isSafeInteger(p)||p<1||p>3e4)throw new Error("cex owner proof: binding refused");let k={version:1,decision:"Allow",digest:l,ownerSenderId:f,telegramChatId:h,audience:Xt,instance:i,nonce:ao(16).toString("hex"),issuedAtMs:g,expiresAtMs:g+p},v=a(x=>Qt("sha256",x).update(Zt(k)).digest("hex"));return{claims:k,mac:v}},verify(l,{digest:c}={}){let s=l?.claims,d=r();if(!s||s.version!==1||s.decision!=="Allow"||s.digest!==c||s.audience!==Xt||s.instance!==i||!/^[0-9a-f]{32}$/.test(s.nonce||"")||J(s.ownerSenderId)!==J(s.telegramChatId)||!n.has(J(s.ownerSenderId))||!Number.isSafeInteger(s.issuedAtMs)||!Number.isSafeInteger(s.expiresAtMs)||s.expiresAtMs<=d||s.issuedAtMs>d||s.expiresAtMs-s.issuedAtMs>3e4||o.has(s.nonce))return!1;let p=a(f=>Qt("sha256",f).update(Zt(s)).digest("hex"));return so(l.mac,p)?(o.add(s.nonce),!0):!1}})}var Xt,J,Zt,so,tr=w(()=>{Jt();Xt="oracle-local-signer-cex-owner-allow-v1",J=t=>/^(?:0|[1-9]\d{0,19})$/.test(String(t||""))?String(t):null,Zt=t=>JSON.stringify(t),so=(t,e)=>{let r=Buffer.from(String(t)),n=Buffer.from(String(e));return r.length===n.length&&io(r,n)}});var ar={};M(ar,{buildPersona:()=>K,telegram:()=>lo,telegramPendingRecipients:()=>or});import{join as rr}from"node:path";import{homedir as co}from"node:os";function pe(t=process.env){return yt(re(t)),ue()}function nr(t=process.env){de(re(t),ue())}function or({extraOwners:t,env:e=process.env}={}){let r=String(e.ORACLE_OWNER_TELEGRAM||"").split(",").map(o=>o.trim()).filter(Boolean),n=Array.isArray(t)?t.map(o=>String(o).trim()):[];return[...new Set([...r,...n])].filter(o=>/^\d+$/.test(o))}function Be(t,e){if(!e)return;if(typeof e=="string")return t.reply(e,{parse_mode:"Markdown"});let r=e.replyMarkup?{reply_markup:e.replyMarkup}:{};return t.reply(e.text,{parse_mode:"Markdown",...r})}async function lo(t){let{Bot:e}=await import("grammy");pe();let r=new e(t.token),n=String(t.name||"oracle").toLowerCase(),o=K(t),a=Array.isArray(t.owners)?t.owners:void 0,i=t.bus;i&&i.register(n,{role:t.role||"",chains:t.chains||[],handler:s=>oe({from:s.from,text:s.text,persona:o,backend:t.backend,profile:t.hermesProfile})}),r.command("start",s=>{let d=String(s.from?.id||s.chat.id);if(!z({platform:"telegram",senderId:d,extraOwners:a}))return s.reply(V);let p=String(s.match||"").trim();if(p){let f=pe(),h=bt(f,{token:p,telegramUserId:d});return nr(),h.ok?s.reply("Telegram linked to Oracle. Agent artifacts will land as interactive cards. Deepen stays in this thread."):s.reply(`Link failed: ${h.error}`)}return s.reply(`${n} ready. /help lists every native command. /model lists models. /setup model adds OpenRouter, Nous Portal, Qwen, GLM. /effort sets reasoning. /update installs latest.${i?" /agents lists peers.":""}`)}),r.command("update",async s=>{let d=String(s.from?.id||s.chat.id),p=String(s.chat.id);if(!z({platform:"telegram",senderId:d,extraOwners:a}))return s.reply(V);if(s.message.forward_origin||s.message.forward_from||s.message.forward_date)return;s.replyWithChatAction("typing").catch(()=>{});let f=await O({platform:"telegram",chatId:p,senderId:d,text:s.match?`update ${s.match}`.trim():"update",userName:s.from?.username||s.from?.first_name||"user"});if(f)return Be(s,f)}),r.on("message:text",async s=>{let d=String(s.chat.id),p=String(s.from?.id||d),f=s.message.text;try{s.replyWithChatAction("typing").catch(()=>{});let h=pe(),g=St(h,{chatId:d,text:f}),k=await O({platform:"telegram",chatId:d,senderId:p,text:g||f,userName:s.from?.username||s.from?.first_name||"user",extraOwners:a,bus:i,agentName:n,persona:o,backend:t.backend,profile:t.hermesProfile,meta:{forward_origin:s.message.forward_origin,forward_from:s.message.forward_from,forward_from_chat:s.message.forward_from_chat,forward_sender_name:s.message.forward_sender_name,forward_date:s.message.forward_date}});k&&await Be(s,k)}catch(h){process.stderr.write(`telegram-gateway[${n}]: ${h.message}
|
|
32
|
+
`),await s.reply("Something went wrong. Try again.").catch(()=>{})}}),r.on("callback_query:data",async s=>{let d=String(s.from?.id||"");if(!z({platform:"telegram",senderId:d,extraOwners:a})){await s.answerCallbackQuery({text:V.slice(0,180),show_alert:!0}).catch(()=>{});return}let p=String(s.callbackQuery?.data||""),f=String(process.env.ORACLE_OWNER_TELEGRAM||"").split(",").map(v=>v.trim()).filter(Boolean),h=process.env.ORACLE_CONFIG_DIR||rr(co(),".config","oracle"),g;try{g=er({keyFile:rr(h,"signer","policy-integrity-key"),approvedTelegramOwners:f})}catch{}let k=await tt({platform:"telegram",data:p,senderId:d,chatId:String(s.chat?.id||""),ownerProofAuthority:g,grant:{local:!0}});if(!k){let v=pe(),x=xt(v,{data:p,chatId:String(s.chat?.id||""),grant:{local:!0}});if(nr(),!x){await s.answerCallbackQuery().catch(()=>{});return}if(await s.answerCallbackQuery({text:"ok"}).catch(()=>{}),x.prompt){let $=await O({platform:"telegram",chatId:String(s.chat?.id||""),senderId:d,text:x.prompt,extraOwners:a,bus:i,agentName:n,persona:o,backend:t.backend,profile:t.hermesProfile});$&&await Be(s,$);return}if(x.text){let $=x.buttons?.replyMarkup?{reply_markup:x.buttons.replyMarkup}:{};await s.reply(x.text,{parse_mode:"Markdown",...$}).catch(()=>{})}return}await s.answerCallbackQuery({text:"ok"}).catch(()=>{}),k.text&&await s.reply(k.text,{parse_mode:"Markdown"}).catch(()=>{})}),r.start();let l=or({extraOwners:a}),c=null;return l.length>0&&t.pendingWatch!==!1&&(c=Vt({intervalMs:t.pendingWatchIntervalMs,onNew:async(s,{armed:d})=>{let p=Ae(s,{platform:"telegram",grant:{local:!0},armed:d}),f=p.buttons?.replyMarkup?{reply_markup:p.buttons.replyMarkup}:{};for(let h of l)await r.api.sendMessage(h,p.text,{parse_mode:"Markdown",...f}).catch(()=>{})}})),{platform:"telegram",name:n,bot:r,stopPendingWatch:()=>c?.stop()}}var ir=w(()=>{Y();Ce();Kt();tr();Pe()});var sr={};M(sr,{discord:()=>uo});async function uo(t){let{Client:e,GatewayIntentBits:r}=await import("discord.js"),n=new e({intents:[r.Guilds,r.GuildMessages,r.MessageContent,r.DirectMessages]}),o=String(t.name||"oracle").toLowerCase(),a=K(t),i=Array.isArray(t.owners)?t.owners:void 0,l=t.bus;return l&&l.register(o,{role:t.role||"",chains:t.chains||[],handler:c=>oe({from:c.from,text:c.text,persona:a,backend:t.backend,profile:t.hermesProfile})}),n.on("messageCreate",async c=>{if(c.author.bot)return;let s=c.channel.id,d=c.author.id,p=c.content;try{let f=!c.guild,h=c.mentions.has(n.user.id);if(!f&&!h)return;c.channel.sendTyping().catch(()=>{});let g=await O({platform:"discord",chatId:s,senderId:d,text:p.replace(`<@${n.user.id}>`,"").trim(),userName:c.author.username,extraOwners:i,bus:l,agentName:o,persona:a,backend:t.backend,profile:t.hermesProfile,meta:{forwarded:c.reference?.type===1||Array.isArray(c.messageSnapshots)&&c.messageSnapshots.length>0}});g&&await c.reply(typeof g=="string"?g:g.text).catch(()=>{})}catch(f){process.stderr.write(`discord-gateway[${o}]: ${f.message}
|
|
33
|
+
`)}}),await n.login(t.token),{platform:"discord",name:o,client:n}}var cr=w(()=>{Y()});var ur={};M(ur,{whatsapp:()=>mo});import{join as lr}from"node:path";import{homedir as po}from"node:os";async function mo(t){let[{Client:e,LocalAuth:r},{generate:n}]=await Promise.all([import("whatsapp-web.js"),import("qrcode-terminal")]),o=new e({authStrategy:new r({dataPath:lr(fo,".wwebjs_auth")}),puppeteer:{headless:!0,args:["--no-sandbox"]}});return o.on("qr",a=>{process.stderr.write(`
|
|
33
34
|
WhatsApp: scan this QR code in WhatsApp \u2192 Linked Devices:
|
|
34
35
|
|
|
35
36
|
`),n(a,{small:!0}),process.stderr.write(`
|
|
36
37
|
`)}),o.on("ready",()=>{process.stderr.write(`whatsapp-gateway: connected
|
|
37
|
-
`)}),o.on("message",async a=>{if(a.fromMe)return;let i=a.from,
|
|
38
|
-
`)}}),await o.initialize(),{platform:"whatsapp",client:o}}var
|
|
38
|
+
`)}),o.on("message",async a=>{if(a.fromMe)return;let i=a.from,l=a.author||a.from,c=a.body;try{let s=await O({platform:"whatsapp",chatId:i,senderId:l,text:c,userName:a._data?.notifyName||"user",meta:{forwarded:a.isForwarded||a._data?.isForwarded,forward_date:a._data?.forwardingScore?!0:void 0}});if(s){let p=(typeof s=="string"?s:s.text).replace(/\*\*/g,"*").replace(/```[\s\S]*?```/g,"[code]").replace(/`/g,"");await a.reply(p)}}catch(s){process.stderr.write(`whatsapp-gateway: ${s.message}
|
|
39
|
+
`)}}),await o.initialize(),{platform:"whatsapp",client:o}}var fo,dr=w(()=>{Y();fo=process.env.ORACLE_CONFIG_DIR||lr(po(),".config","oracle")});var pr={};M(pr,{signal_:()=>ho});async function ho(t){return process.stderr.write(`signal-gateway: requires signal-cli binary
|
|
39
40
|
`),process.stderr.write(`signal-gateway: not built yet \u2014 use Telegram or Discord for now
|
|
40
|
-
`),{platform:"signal",status:"stub"}}var
|
|
41
|
+
`),{platform:"signal",status:"stub"}}var fr=w(()=>{Y()});import{createServer as go}from"node:http";import{env as gr}from"node:process";import{join as Ge}from"node:path";import{homedir as yo}from"node:os";import{readFileSync as yr,existsSync as wo,mkdirSync as ko,writeFileSync as So}from"node:fs";import{randomBytes as bo}from"node:crypto";var wr=gr.ORACLE_CONFIG_DIR||Ge(yo(),".config","oracle"),mr=Ge(wr,"gateway.json");function xo(){return wo(mr)?JSON.parse(yr(mr,"utf8")):{platforms:{}}}function Fe(t){return t?Array.isArray(t)?t.filter(Boolean):[t]:[]}var vo=Object.freeze({telegram:"grammy",discord:"discord.js",whatsapp:"whatsapp-web.js"});async function fe(t,e,r,n){try{n.push(await e(r))}catch(o){let a=vo[t];if(a&&/Cannot find (module|package)|ERR_MODULE_NOT_FOUND/.test(String(o.message))){process.stderr.write(`oracle-gateway: ${t} needs an optional dependency. Install it first:
|
|
41
42
|
npm install -g ${a}
|
|
42
43
|
`);return}process.stderr.write(`oracle-gateway: ${t} failed to start: ${o.message}
|
|
43
|
-
`)}}async function
|
|
44
|
+
`)}}async function Ao(){let t=xo(),e=[],r=Fe(t.platforms?.telegram),n=Fe(t.platforms?.discord),o=Fe(t.agents),i=r.length+n.length+o.length>1?new(await Promise.resolve().then(()=>(We(),qe))).A2ABus:null;if(i&&o.length){let{routePeerConsult:c,buildPersona:s}=await Promise.resolve().then(()=>(Y(),zt));for(let d of o)try{let p=s(d);i.register(d.name,{role:d.role||"",chains:d.chains||[],handler:f=>c({from:f.from,text:f.text,persona:p,backend:d.backend,profile:d.hermesProfile})}),process.stderr.write(`oracle-gateway: headless agent '${d.name}' on bus (backend: ${d.backend||"oracle"})
|
|
44
45
|
`)}catch(p){process.stderr.write(`oracle-gateway: headless agent '${d.name||"?"}' skipped: ${p.message}
|
|
45
|
-
`)}}for(let
|
|
46
|
+
`)}}for(let c of r)await fe("telegram",async()=>(await Promise.resolve().then(()=>(ir(),ar))).telegram({...c,bus:i}),t,e);for(let c of n)await fe("discord",async()=>(await Promise.resolve().then(()=>(cr(),sr))).discord({...c,bus:i}),t,e);t.platforms?.whatsapp&&await fe("whatsapp",async c=>(await Promise.resolve().then(()=>(dr(),ur))).whatsapp(c.platforms.whatsapp),t,e),t.platforms?.signal&&await fe("signal",async c=>(await Promise.resolve().then(()=>(fr(),pr))).signal_(c.platforms.signal),t,e),e.length===0&&process.stderr.write(`oracle-gateway: no platforms configured. Run 'oracle setup telegram' first.
|
|
46
47
|
`),process.stderr.write(`oracle-gateway: ${e.length} platform(s) connected
|
|
47
|
-
`);let
|
|
48
|
-
`)}var
|
|
49
|
-
`,{mode:384}),r}var{pathToFileURL:
|
|
50
|
-
`),process.exit(1)});export{
|
|
48
|
+
`);let l=i?Eo():null;go((c,s)=>Co(c,s,{config:t,bus:i,a2aToken:l})).listen(gr.ORACLE_GATEWAY_PORT||9270,"127.0.0.1"),i&&process.stderr.write(`oracle-gateway: a2a loopback contract at GET /a2a (token: a2a-token in config dir)
|
|
49
|
+
`)}var $o=16384;async function Co(t,e,{config:r,bus:n,a2aToken:o}){let a=new URL(t.url||"/","http://127.0.0.1"),i=(c,s)=>{e.writeHead(c,{"Content-Type":"application/json"}),e.end(JSON.stringify(s))};if(t.method==="GET"&&(a.pathname==="/"||a.pathname==="/health"))return i(200,{status:"ok",platforms:Object.keys(r.platforms||{}),a2a:!!n});if(!a.pathname.startsWith("/a2a"))return i(404,{error:"not found"});if(!n)return i(404,{error:"a2a bus not running (fewer than 2 agents configured)"});if(t.method==="GET"&&a.pathname==="/a2a")return i(200,{contract:"oracle-a2a/1",auth:"Authorization: Bearer <contents of a2a-token in the oracle config dir>",endpoints:["GET /a2a","GET /a2a/agents","POST /a2a/ask {to,text,from?}"],note:"consult-only; loopback-only; peers answer with information, never actions"});let l=String(t.headers.authorization||"");if(!o||l!==`Bearer ${o}`)return i(401,{error:"bad or missing bearer token (read a2a-token in the oracle config dir)"});if(t.method==="GET"&&a.pathname==="/a2a/agents")return i(200,{agents:n.roster()});if(t.method==="POST"&&a.pathname==="/a2a/ask"){let c="";t.on("data",s=>{c+=s,c.length>$o&&t.destroy()}),t.on("end",async()=>{try{let s=JSON.parse(c||"{}"),d=_o(s.from);n.agents.has(d)||n.register(d,{role:"loopback client",handler:async()=>null});let p=await n.send({from:d,to:s.to,text:s.text,kind:"consult"});return i(p.ok?200:400,p)}catch(s){return i(400,{ok:!1,error:`bad request: ${s.message}`})}});return}return i(404,{error:"not found"})}function _o(t){return String(t||"local").trim().toLowerCase().replace(/[^a-z0-9_-]/g,"").slice(0,32)||"local"}function Eo(t=wr){let e=Ge(t,"a2a-token");try{let n=yr(e,"utf8").trim();if(n)return n}catch{}let r=bo(24).toString("hex");return ko(t,{recursive:!0}),So(e,`${r}
|
|
50
|
+
`,{mode:384}),r}var{pathToFileURL:Oo}=await import("node:url"),{realpathSync:Ro}=await import("node:fs"),hr=process.argv[1],He=!1;if(hr)try{He=import.meta.url===Oo(Ro(hr)).href}catch{He=!1}He&&Ao().catch(t=>{process.stderr.write(`oracle-gateway: ${t.message}
|
|
51
|
+
`),process.exit(1)});export{Eo as ensureA2AToken,Co as serveHttp,Fe as toEntries};
|