@oracle-agent/oracle 0.22.2 → 0.22.4

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.
Files changed (35) hide show
  1. package/README.md +4 -4
  2. package/artifacts/specialist-packs/oracle-full-crypto.json +1 -1
  3. package/dist/assets/profiles/oracle/SOUL.md +18 -21
  4. package/dist/assets/skills/multichain-prepare-desk.md +29 -0
  5. package/dist/assets/skills/oracle-chat/SKILL.md +9 -13
  6. package/dist/assets/skills/oracle-desk.md +1 -1
  7. package/dist/assets/skills/oracle-prime-research/SKILL.md +40 -0
  8. package/dist/bin/desk-server.mjs +11 -11
  9. package/dist/bin/oracle-data-mcp.mjs +5 -5
  10. package/dist/bin/oracle-gateway.mjs +16 -16
  11. package/dist/bin/oracle-route.mjs +12 -12
  12. package/dist/bin/oracle-upgrade.mjs +7 -15
  13. package/dist/bin/oracle.mjs +16 -33
  14. package/dist/cli/commands/doctor.mjs +4 -5
  15. package/dist/cli/commands/eval.mjs +100 -16
  16. package/dist/cli/commands/init.mjs +3 -3
  17. package/dist/cli/commands/mcp.mjs +36 -45
  18. package/dist/cli/commands/prime.mjs +26 -0
  19. package/dist/cli/commands/swap.mjs +4 -4
  20. package/dist/cli/commands/version.mjs +2 -2
  21. package/dist/data/desk-data.mjs +5 -5
  22. package/dist/index.mjs +16 -16
  23. package/dist/router/index.mjs +1 -1
  24. package/dist/router/prepare-bridge.mjs +1 -1
  25. package/package.json +12 -5
  26. package/public/oracle-console/app.js +1 -1
  27. package/public/oracle-console/bitcoin-wallets.js +48 -111
  28. package/public/oracle-console/index.html +1 -1
  29. package/dist/assets/skills/multichain-exec-desk.md +0 -33
  30. package/dist/cli/commands/credential.mjs +0 -1
  31. package/dist/cli/commands/runner.mjs +0 -1
  32. package/dist/cli/commands/sign.mjs +0 -5
  33. package/dist/cli/commands/signer.mjs +0 -1
  34. package/dist/cli/commands/vault.mjs +0 -1
  35. package/dist/gateway/telegram-exact-action-callbacks.mjs +0 -1
@@ -1,7 +1,6 @@
1
- // Multi-wallet Bitcoin connector for Oracle Console.
2
- // Injected providers only - no npm wallet SDK required in the static console.
3
- // Supported: Xverse, UniSat, Leather, OKX, Phantom, Magic Eden, generic.
4
- // Signing: PSBT stays in the wallet. Oracle never sees private keys.
1
+ // Multi-wallet Bitcoin address connector for Oracle Console.
2
+ // Injected providers only, no npm wallet SDK required in the static console.
3
+ // Supported: Xverse, UniSat, Leather, OKX, Phantom, Magic Eden.
5
4
 
6
5
  (function (root) {
7
6
  "use strict";
@@ -16,14 +15,7 @@
16
15
  const address = accounts && accounts[0];
17
16
  if (!address) throw new Error("UniSat returned no address");
18
17
  const network = (await provider.getNetwork?.()) || "livenet";
19
- return { address, network, provider };
20
- },
21
- async signPsbt(provider, psbtHex, options = {}) {
22
- return provider.signPsbt(psbtHex, options);
23
- },
24
- async pushPsbt(provider, psbtHex) {
25
- if (typeof provider.pushPsbt === "function") return provider.pushPsbt(psbtHex);
26
- throw new Error("UniSat pushPsbt unavailable - use Oracle broadcast with raw hex");
18
+ return { address, network };
27
19
  },
28
20
  },
29
21
  {
@@ -32,16 +24,10 @@
32
24
  detect: () => window.okxwallet && window.okxwallet.bitcoin,
33
25
  async connect(provider) {
34
26
  const result = await provider.connect();
35
- const address = result?.address || result?.addresses?.[0] || (Array.isArray(result) && result[0]);
27
+ const address =
28
+ result?.address || result?.addresses?.[0] || (Array.isArray(result) && result[0]);
36
29
  if (!address) throw new Error("OKX returned no address");
37
- return { address, network: result?.network || "livenet", provider };
38
- },
39
- async signPsbt(provider, psbtHex, options = {}) {
40
- return provider.signPsbt(psbtHex, options);
41
- },
42
- async pushPsbt(provider, psbtHex) {
43
- if (typeof provider.pushPsbt === "function") return provider.pushPsbt(psbtHex);
44
- throw new Error("OKX pushPsbt unavailable - use Oracle broadcast with raw hex");
30
+ return { address, network: result?.network || "livenet" };
45
31
  },
46
32
  },
47
33
  {
@@ -52,43 +38,27 @@
52
38
  window.BitcoinProvider ||
53
39
  (window.xverse && window.xverse.bitcoin),
54
40
  async connect(provider) {
55
- // Sats Connect request shape when provider.request exists
56
41
  if (typeof provider.request === "function") {
57
- const res = await provider.request("getAccounts", {
42
+ const result = await provider.request("getAccounts", {
58
43
  purposes: ["payment", "ordinals"],
59
44
  message: "Connect to Oracle",
60
45
  });
61
- const arr = res?.result || res;
62
- const payment = Array.isArray(arr) ? arr.find((a) => a.purpose === "payment") || arr[0] : null;
46
+ const accounts = result?.result || result;
47
+ const payment = Array.isArray(accounts)
48
+ ? accounts.find((account) => account.purpose === "payment") || accounts[0]
49
+ : null;
63
50
  const address = payment?.address || payment;
64
51
  if (!address) throw new Error("Xverse returned no address");
65
- return { address, network: payment?.network || "Mainnet", provider };
52
+ return { address, network: payment?.network || "Mainnet" };
66
53
  }
67
54
  if (typeof provider.connect === "function") {
68
- const res = await provider.connect("Oracle");
69
- const address = res?.addresses?.payment?.address || res?.paymentAddress || res?.address;
55
+ const result = await provider.connect("Oracle");
56
+ const address =
57
+ result?.addresses?.payment?.address || result?.paymentAddress || result?.address;
70
58
  if (!address) throw new Error("Xverse returned no address");
71
- return { address, network: res?.network || "Mainnet", provider };
72
- }
73
- throw new Error("Xverse provider has no connect/request method");
74
- },
75
- async signPsbt(provider, psbtBase64, options = {}) {
76
- if (typeof provider.request === "function") {
77
- const res = await provider.request("signPsbt", {
78
- psbt: psbtBase64,
79
- allowedSignHash: options.allowedSignHash,
80
- signInputs: options.signInputs,
81
- broadcast: false,
82
- });
83
- return res?.result?.psbt || res?.psbt || res;
59
+ return { address, network: result?.network || "Mainnet" };
84
60
  }
85
- if (typeof provider.signPsbt === "function") {
86
- return provider.signPsbt(psbtBase64, options);
87
- }
88
- throw new Error("Xverse signPsbt unavailable");
89
- },
90
- async pushPsbt() {
91
- throw new Error("Xverse: finalize in wallet or broadcast raw hex via Oracle");
61
+ throw new Error("Xverse provider has no connect or request method");
92
62
  },
93
63
  },
94
64
  {
@@ -96,27 +66,17 @@
96
66
  label: "Leather",
97
67
  detect: () => window.LeatherProvider || window.HiroWalletProvider || window.btc,
98
68
  async connect(provider) {
99
- if (typeof provider.request === "function") {
100
- const res = await provider.request("getAddresses");
101
- const addrs = res?.result?.addresses || res?.addresses || [];
102
- const payment = addrs.find((a) => a.type === "p2wpkh" || a.symbol === "BTC") || addrs[0];
103
- const address = payment?.address;
104
- if (!address) throw new Error("Leather returned no address");
105
- return { address, network: payment?.network || "mainnet", provider };
69
+ if (typeof provider.request !== "function") {
70
+ throw new Error("Leather provider has no request method");
106
71
  }
107
- throw new Error("Leather provider has no request method");
108
- },
109
- async signPsbt(provider, psbtBase64, options = {}) {
110
- const res = await provider.request("signPsbt", {
111
- hex: options.hex || undefined,
112
- base64: psbtBase64,
113
- broadcast: false,
114
- ...options,
115
- });
116
- return res?.result?.hex || res?.result?.base64 || res?.hex || res;
117
- },
118
- async pushPsbt() {
119
- throw new Error("Leather: broadcast raw hex via Oracle");
72
+ const result = await provider.request("getAddresses");
73
+ const addresses = result?.result?.addresses || result?.addresses || [];
74
+ const payment =
75
+ addresses.find((account) => account.type === "p2wpkh" || account.symbol === "BTC") ||
76
+ addresses[0];
77
+ const address = payment?.address;
78
+ if (!address) throw new Error("Leather returned no address");
79
+ return { address, network: payment?.network || "mainnet" };
120
80
  },
121
81
  },
122
82
  {
@@ -124,17 +84,10 @@
124
84
  label: "Phantom",
125
85
  detect: () => window.phantom && window.phantom.bitcoin,
126
86
  async connect(provider) {
127
- const res = await provider.requestAccounts();
128
- const address = res?.[0]?.address || res?.[0];
87
+ const accounts = await provider.requestAccounts();
88
+ const address = accounts?.[0]?.address || accounts?.[0];
129
89
  if (!address) throw new Error("Phantom returned no BTC address");
130
- return { address, network: "mainnet", provider };
131
- },
132
- async signPsbt(provider, psbtHex, options = {}) {
133
- const res = await provider.signPSBT(Buffer.from(psbtHex, "hex"), options);
134
- return res;
135
- },
136
- async pushPsbt() {
137
- throw new Error("Phantom: broadcast raw hex via Oracle");
90
+ return { address, network: "mainnet" };
138
91
  },
139
92
  },
140
93
  {
@@ -142,65 +95,49 @@
142
95
  label: "Magic Eden",
143
96
  detect: () => window.magicEden && window.magicEden.bitcoin,
144
97
  async connect(provider) {
145
- const res = await provider.connect();
146
- const address = res?.address || res?.ordinals?.address || res?.payment?.address;
98
+ const result = await provider.connect();
99
+ const address = result?.address || result?.ordinals?.address || result?.payment?.address;
147
100
  if (!address) throw new Error("Magic Eden returned no address");
148
- return { address, network: "mainnet", provider };
149
- },
150
- async signPsbt(provider, psbt, options = {}) {
151
- return provider.signPsbt(psbt, options);
152
- },
153
- async pushPsbt() {
154
- throw new Error("Magic Eden: broadcast raw hex via Oracle");
101
+ return { address, network: "mainnet" };
155
102
  },
156
103
  },
157
104
  ];
158
105
 
159
- function listDetected() {
160
- return WALLETS.filter((w) => {
106
+ function detectedWallets() {
107
+ return WALLETS.filter((wallet) => {
161
108
  try {
162
- return !!w.detect();
109
+ return Boolean(wallet.detect());
163
110
  } catch {
164
111
  return false;
165
112
  }
166
- }).map((w) => ({ id: w.id, label: w.label }));
113
+ });
114
+ }
115
+
116
+ function listDetected() {
117
+ return detectedWallets().map((wallet) => ({ id: wallet.id, label: wallet.label }));
167
118
  }
168
119
 
169
120
  async function connect(preferredId) {
170
- const detected = WALLETS.filter((w) => {
171
- try {
172
- return !!w.detect();
173
- } catch {
174
- return false;
175
- }
176
- });
121
+ const detected = detectedWallets();
177
122
  if (!detected.length) {
178
123
  throw new Error(
179
- "No Bitcoin wallet detected. Install Xverse, UniSat, Leather, OKX, Phantom, or Magic Eden."
124
+ "No Bitcoin wallet detected. Install Xverse, UniSat, Leather, OKX, Phantom, or Magic Eden.",
180
125
  );
181
126
  }
182
- const wallet = (preferredId && detected.find((w) => w.id === preferredId)) || detected[0];
183
- const provider = wallet.detect();
184
- const session = await wallet.connect(provider);
127
+ const wallet =
128
+ (preferredId && detected.find((candidate) => candidate.id === preferredId)) || detected[0];
129
+ const session = await wallet.connect(wallet.detect());
185
130
  return {
186
131
  walletId: wallet.id,
187
132
  walletLabel: wallet.label,
188
133
  address: session.address,
189
134
  network: session.network,
190
- provider: session.provider,
191
- wallet,
192
135
  };
193
136
  }
194
137
 
195
- async function signPsbt(session, psbt, options = {}) {
196
- if (!session?.wallet || !session?.provider) throw new Error("Bitcoin wallet not connected");
197
- return session.wallet.signPsbt(session.provider, psbt, options);
198
- }
199
-
200
138
  root.OracleBitcoinWallets = {
201
139
  listDetected,
202
140
  connect,
203
- signPsbt,
204
- supported: WALLETS.map((w) => ({ id: w.id, label: w.label })),
141
+ supported: WALLETS.map((wallet) => ({ id: wallet.id, label: wallet.label })),
205
142
  };
206
143
  })(typeof window !== "undefined" ? window : globalThis);
@@ -29,7 +29,7 @@
29
29
 
30
30
  <section id="btc-panel" class="permission-panel btc-panel" hidden>
31
31
  <h2 class="panel-title">Bitcoin lane</h2>
32
- <p class="panel-note">Actual BTC L1 + ordinals/runes via Satflow. Sign in wallet (Xverse / UniSat / Leather / OKX / Phantom). Magic Eden BTC marketplace is dead. Oracle never holds keys.</p>
32
+ <p class="panel-note">Actual BTC L1 + ordinals/runes via Satflow. Connect an address-only wallet (Xverse / UniSat / Leather / OKX / Phantom). Magic Eden BTC marketplace is dead. Oracle never holds keys.</p>
33
33
  <dl class="panel-grid">
34
34
  <dt>Wallet</dt>
35
35
  <dd id="btc-wallet-label">.</dd>
@@ -1,33 +0,0 @@
1
- ---
2
- name: multichain-exec-desk
3
- description: Use for cross-chain or multi-chain execution tasks.
4
- ---
5
-
6
- # Multichain execution desk
7
-
8
- ## Chain routing
9
- - RH 4663 → oracle owns it (rhbot executor)
10
- - Hyperliquid → hl-info / hl-ws (read-only, keyless)
11
- - EVM chains → mad_exec evm_* tools
12
- - Solana → Jupiter tools
13
- - Bitcoin → btc_* tools
14
-
15
- ## Execution flow
16
- 1. `data evm_chains` — list supported chains
17
- 2. `data dex_search` — resolve token
18
- 3. `exec evm_quote` — quote swap
19
- 4. `data best_swap_route` — compare aggregators
20
- 5. `exec evm_prepare` — build unsigned tx
21
- 6. `exec evm_simulate` — simulate (optional but recommended)
22
- 7. `exec evm_sign` — sign (gated)
23
- 8. `exec evm_send` — broadcast (gated)
24
-
25
- ## Cross-chain
26
- - `data best_bridge_route` — compare bridge providers
27
- - `data prepare_best_bridge_route` — build signable bridge tx
28
- - `data rfq_quote` — RFQ/intent routing for large sizes
29
-
30
- ## Safety
31
- - Verify destination chainId matches intent
32
- - Check bridge provider is live (data health first)
33
- - Never route through unverified contracts
@@ -1 +0,0 @@
1
- var r={name:"credential",summary:"OS credential store glue",group:"sign",usage:"oracle credential <get|set|delete> ...",async run(e){return e.dispatchOperator("oracle-credential",e.argv,{appendHintOnError:!0})}};export{r as default};
@@ -1 +0,0 @@
1
- var n={name:"runner",summary:"action runner daemon",group:"sign",usage:"oracle runner [--interval-ms N ...]",async run(r){return r.dispatchOperator("oracle-runner",r.argv,{appendHintOnError:!0})}};export{n as default};
@@ -1,5 +0,0 @@
1
- var i={name:"sign",summary:"check signer status (key handling requires the operator package)",group:"sign",usage:"oracle sign <init|doctor|import> ...",async run(r){let e=r.argv[0];return e==="init"?r.dispatchOperator("oracle-agentic-init",r.argv.slice(1),{appendHintOnError:!0}):e==="doctor"?r.dispatchOperator("oracle-agentic-doctor",r.argv.slice(1),{appendHintOnError:!0}):e==="import"?r.dispatchOperator("oracle-agentic-init",[],{appendHintOnError:!0}):(process.stderr.write(`usage: oracle sign <init|doctor|import> ...
2
- oracle sign init provision keys + policy (interactive)
3
- oracle sign import import an existing EVM private key
4
- oracle sign doctor check local signer readiness
5
- `),1)}};export{i as default};
@@ -1 +0,0 @@
1
- var e={name:"signer",summary:"loopback signer daemon",group:"sign",usage:"oracle signer [--port N ...]",async run(r){return r.dispatchOperator("oracle-signer",r.argv,{appendHintOnError:!0})}};export{e as default};
@@ -1 +0,0 @@
1
- var e={name:"vault",summary:"encrypt local key files at rest",group:"sign",usage:"oracle vault <encrypt|rekey|inspect|decrypt> ...",async run(r){return r.dispatchOperator("oracle-vault",r.argv,{appendHintOnError:!0})}};export{e as default};
@@ -1 +0,0 @@
1
- import{createHash as $,randomBytes as C}from"node:crypto";import{chmodSync as h,mkdirSync as R,readFileSync as x,renameSync as H,rmSync as k,writeFileSync as L}from"node:fs";import{homedir as D}from"node:os";import{join as O}from"node:path";var m="oa1",j=12,F=1440*60*1e3,T=new Set(["evm-swap","sol","btc"]);function c(e){throw new Error(`oracle-telegram-callback: ${e}`)}function p(e,a){return(!e||typeof e!="object"||Array.isArray(e)||Object.getPrototypeOf(e)!==Object.prototype)&&c(`${a} must be an object`),e}function v(e,a){try{return JSON.parse(JSON.stringify(e))}catch{c(`${a} must be JSON-serializable`)}}function B(e,a){let i=`${m}:${e}:${a}`;return Buffer.byteLength(i,"utf8")>=64&&c("callback ID exceeds Telegram's 64-byte limit"),i}function P(e){if(e.ownerId)return String(e.ownerId);let a=e.ownerConfig?.owner;if(typeof a=="string"&&a.startsWith("telegram:"))return a.slice(9);if(a?.platform==="telegram"&&a.userId)return String(a.userId);let i=String(e.env?.ORACLE_OWNER_TELEGRAM??process.env.ORACLE_OWNER_TELEGRAM??"").trim();if(i)return i;c("an exact Telegram owner identity is required")}function z(e={}){let a=e.control,i=a?.oracle_control_arm?t=>a.oracle_control_arm(t):a?.call?t=>a.call("oracle_control_arm",t):null,g=a?.oracle_control_confirm?t=>a.oracle_control_confirm(t):a?.call?t=>a.call("oracle_control_confirm",t):null;(!i||!g)&&c("bounded arm/confirm control is required");let b=P(e),E=e.now??Date.now,y=e.randomBytes??C,u=e.callbackDir??O(D(),".config","oracle","telegram-callbacks");R(u,{recursive:!0,mode:448}),h(u,448);function d(t){return O(u,`${$("sha256").update(t).digest("hex")}.json`)}function N(t){try{return x(d(t)),!0}catch(o){if(o?.code==="ENOENT")return!1;throw o}}function S(t,o){let r=d(t),n=`${r}.${process.pid}.${y(6).toString("hex")}.tmp`;L(n,JSON.stringify(o),{mode:384,flag:"wx"}),h(n,384),H(n,r),h(r,384)}function M(t){try{return JSON.parse(x(d(t),"utf8"))}catch(o){if(o?.code==="ENOENT")return null;c("callback state is unreadable")}}function _(t,o,r){let n=M(t);return(!n||n.kind!==o)&&c("unknown or consumed callback"),String(r??"")!==n.chatId&&c("chat mismatch"),E()>=n.expiresAtMs&&(k(d(t),{force:!0}),c("callback expired")),k(d(t),{force:!0}),n}function I(t){for(let o=0;o<8;o++){let r=B(t,y(j).toString("base64url"));if(!N(r))return r}c("could not allocate a unique callback ID")}return Object.freeze({issue(t,o={}){let r=v(p(t,"action"),"action"),n=p(r.intent,"action.intent"),s=String(n.surface??"");T.has(s)||c(`unsupported surface ${s||"missing"}`),(s==="sol"||s==="btc")&&!r.prepared&&c(`${s} action requires a prepared envelope`);let l=o.ttlMs??12e4;(!Number.isSafeInteger(l)||l<1||l>F)&&c("ttlMs is outside the bounded range");let f=E()+l,A=String(o.chatId??b);A||c("an exact Telegram chat identity is required");let w=I("a");return S(w,{kind:"arm",expiresAtMs:f,chatId:A,action:{...r,expiresAt:new Date(f).toISOString(),maxExecutions:1}}),w},async handle(t){p(t,"callback request"),(t.platform!=="telegram"||String(t.senderId??"")!==b)&&c("owner mismatch");let o=String(t.callbackData??"");if(o.startsWith(`${m}:a:`)){let r=_(o,"arm",t.chatId),n=await i(r.action);(n?.state??n?.status)!=="pending_confirmation"&&c("arm did not create a pending action"),n?.maxExecutions!=null&&n.maxExecutions!==1&&c("arm did not create a one-shot action"),(!n?.id||!/^[a-f0-9]{64}$/i.test(String(n.intentHash??"")))&&c("arm did not return an exact intent hash");let l=I("c"),f=Date.parse(n.expiresAt??"");return S(l,{kind:"confirm",expiresAtMs:Number.isFinite(f)?Math.min(r.expiresAtMs,f):r.expiresAtMs,chatId:r.chatId,actionId:n.id,intentHash:n.intentHash}),{phase:"pending_confirmation",callbackData:l,actionId:n.id,intentHash:n.intentHash}}if(o.startsWith(`${m}:c:`)){let r=_(o,"confirm",t.chatId),n=await g({id:r.actionId,intentHash:r.intentHash}),s=n?.state??n?.status;return(n?.id!==r.actionId||n?.intentHash!==r.intentHash||s!=="active")&&c("control confirmed a different action"),{phase:"active",actionId:n.id,intentHash:n.intentHash}}c("unknown or consumed callback")}})}var K=m,U=Object.freeze([...T]);export{K as TELEGRAM_EXACT_ACTION_CALLBACK_PREFIX,U as TELEGRAM_EXACT_ACTION_SURFACES,z as createTelegramExactActionCallbacks};