@oracle-agent/oracle 0.4.2 → 0.6.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/README.md +76 -18
- package/SETUP.md +13 -0
- package/bin/oracle-data-mcp.mjs +1 -1
- package/bin/oracle.mjs +33 -0
- package/docs/cli.md +47 -0
- package/docs/connectors.md +13 -0
- package/package.json +6 -2
- package/profiles/oracle/SOUL.md +10 -4
- package/profiles/robinhood-agent/SOUL.md +5 -3
- package/protocols/templates/safe-erc20/README.md +9 -0
- package/public/agent-connect/app.js +16 -13
- package/public/oracle-splash/assets/hero/orb.avif +0 -0
- package/public/oracle-splash/assets/hero/orb.webm +0 -0
- package/public/oracle-splash/assets/llms/claude.svg +1 -0
- package/public/oracle-splash/assets/llms/codex.svg +1 -0
- package/public/oracle-splash/assets/llms/cursor.svg +17 -0
- package/public/oracle-splash/assets/llms/deepseek.svg +1 -0
- package/public/oracle-splash/assets/llms/gemini.svg +1 -0
- package/public/oracle-splash/assets/llms/grok.svg +8 -0
- package/public/oracle-splash/assets/llms/hermes.png +0 -0
- package/public/oracle-splash/assets/llms/kimi.svg +1 -0
- package/public/oracle-splash/assets/llms/manus.svg +18 -0
- package/public/oracle-splash/assets/llms/openclaw.svg +22 -0
- package/public/oracle-splash/assets/llms/perplexity.svg +1 -0
- package/public/oracle-splash/assets/llms/qwen.svg +1 -0
- package/public/oracle-splash/assets/llms/windsurf.svg +1 -0
- package/public/oracle-splash/assets/protocols/abcdex.png +0 -0
- package/public/oracle-splash/assets/protocols/across.png +0 -0
- package/public/oracle-splash/assets/protocols/aerodrome.png +0 -0
- package/public/oracle-splash/assets/protocols/balancer.png +0 -0
- package/public/oracle-splash/assets/protocols/cowswap.png +0 -0
- package/public/oracle-splash/assets/protocols/curve.png +0 -0
- package/public/oracle-splash/assets/protocols/dreamcash.png +0 -0
- package/public/oracle-splash/assets/protocols/felix.png +0 -0
- package/public/oracle-splash/assets/protocols/gmx.png +0 -0
- package/public/oracle-splash/assets/protocols/hyena.png +0 -0
- package/public/oracle-splash/assets/protocols/hyperbeat.png +0 -0
- package/public/oracle-splash/assets/protocols/hyperliquid.png +0 -0
- package/public/oracle-splash/assets/protocols/hyperswap.png +0 -0
- package/public/oracle-splash/assets/protocols/jupiter.png +0 -0
- package/public/oracle-splash/assets/protocols/kinetiq.png +0 -0
- package/public/oracle-splash/assets/protocols/lfj.png +0 -0
- package/public/oracle-splash/assets/protocols/lifi.png +0 -0
- package/public/oracle-splash/assets/protocols/magic-eden.png +0 -0
- package/public/oracle-splash/assets/protocols/morpho.png +0 -0
- package/public/oracle-splash/assets/protocols/odos.png +0 -0
- package/public/oracle-splash/assets/protocols/oneinch.png +0 -0
- package/public/oracle-splash/assets/protocols/opensea.png +0 -0
- package/public/oracle-splash/assets/protocols/pancakeswap.png +0 -0
- package/public/oracle-splash/assets/protocols/paragon.png +0 -0
- package/public/oracle-splash/assets/protocols/paraswap.png +0 -0
- package/public/oracle-splash/assets/protocols/pendle.png +0 -0
- package/public/oracle-splash/assets/protocols/polymarket.png +0 -0
- package/public/oracle-splash/assets/protocols/quickswap.png +0 -0
- package/public/oracle-splash/assets/protocols/relay.png +0 -0
- package/public/oracle-splash/assets/protocols/stargate.png +0 -0
- package/public/oracle-splash/assets/protocols/tradexyz.png +0 -0
- package/public/oracle-splash/assets/protocols/uniswap.png +0 -0
- package/public/oracle-splash/assets/protocols/velodrome.png +0 -0
- package/public/oracle-splash/assets/protocols/ventuals.png +0 -0
- package/public/oracle-splash/assets/wordmarks/across.svg +4 -0
- package/public/oracle-splash/assets/wordmarks/aerodrome.svg +23 -0
- package/public/oracle-splash/assets/wordmarks/balancer.svg +3 -0
- package/public/oracle-splash/assets/wordmarks/cowswap.svg +1 -0
- package/public/oracle-splash/assets/wordmarks/gmx.svg +13 -0
- package/public/oracle-splash/assets/wordmarks/hyena.svg +7 -0
- package/public/oracle-splash/assets/wordmarks/hyperliquid.svg +21 -0
- package/public/oracle-splash/assets/wordmarks/hyperswap.svg +13 -0
- package/public/oracle-splash/assets/wordmarks/jupiter.svg +35 -0
- package/public/oracle-splash/assets/wordmarks/lifi.png +0 -0
- package/public/oracle-splash/assets/wordmarks/magic-eden.svg +1 -0
- package/public/oracle-splash/assets/wordmarks/morpho.svg +1 -0
- package/public/oracle-splash/assets/wordmarks/odos.svg +3 -0
- package/public/oracle-splash/assets/wordmarks/oneinch.svg +6 -0
- package/public/oracle-splash/assets/wordmarks/opensea.svg +1 -0
- package/public/oracle-splash/assets/wordmarks/outcome.svg +16 -0
- package/public/oracle-splash/assets/wordmarks/pancakeswap.svg +18 -0
- package/public/oracle-splash/assets/wordmarks/paraswap.svg +16 -0
- package/public/oracle-splash/assets/wordmarks/pendle.png +0 -0
- package/public/oracle-splash/assets/wordmarks/polymarket.png +0 -0
- package/public/oracle-splash/assets/wordmarks/quickswap.png +0 -0
- package/public/oracle-splash/assets/wordmarks/relay.svg +8 -0
- package/public/oracle-splash/assets/wordmarks/stargate.svg +15 -0
- package/public/oracle-splash/assets/wordmarks/uniswap.svg +18 -0
- package/public/oracle-splash/assets/wordmarks/velodrome.svg +84 -0
- package/public/oracle-splash/assets/wordmarks/xyz.svg +12 -0
- package/public/oracle-splash/index.html +784 -498
- package/scripts/check-doc-drift.mjs +111 -0
- package/skills/oracle-chat/SKILL.md +61 -0
- package/skills/oracle-chat/chain.SKILL.md +31 -0
- package/skills/oracle-chat/setup.SKILL.md +37 -0
- package/skins/oracle.yaml +52 -0
- package/src/cli/chain-catalog.mjs +215 -0
- package/src/cli/chain-state.mjs +74 -0
- package/src/cli/commands/chain.mjs +143 -0
- package/src/cli/commands/chat.mjs +268 -0
- package/src/cli/commands/credential.mjs +9 -0
- package/src/cli/commands/data-mcp.mjs +18 -0
- package/src/cli/commands/data.mjs +73 -0
- package/src/cli/commands/doctor.mjs +131 -0
- package/src/cli/commands/help.mjs +7 -0
- package/src/cli/commands/init.mjs +27 -0
- package/src/cli/commands/mcp.mjs +142 -0
- package/src/cli/commands/model.mjs +37 -0
- package/src/cli/commands/prepare.mjs +12 -0
- package/src/cli/commands/public.mjs +20 -0
- package/src/cli/commands/route.mjs +12 -0
- package/src/cli/commands/runner.mjs +9 -0
- package/src/cli/commands/scan.mjs +12 -0
- package/src/cli/commands/setup.mjs +283 -0
- package/src/cli/commands/sign.mjs +21 -0
- package/src/cli/commands/signer.mjs +9 -0
- package/src/cli/commands/upgrade.mjs +12 -0
- package/src/cli/commands/vault.mjs +9 -0
- package/src/cli/commands/version.mjs +22 -0
- package/src/cli/first-run.mjs +23 -0
- package/src/cli/kernel.mjs +237 -0
- package/src/cli/mcp-targets/chatgpt.mjs +51 -0
- package/src/cli/mcp-targets/claude-code.mjs +39 -0
- package/src/cli/mcp-targets/claude-desktop.mjs +24 -0
- package/src/cli/mcp-targets/codex.mjs +41 -0
- package/src/cli/mcp-targets/shared.mjs +61 -0
- package/src/cli/messaging-platforms.mjs +209 -0
- package/src/cli/operator-dispatch.mjs +258 -0
- package/src/cli/oracle-harness.py +148 -0
- package/src/cli/paths.mjs +83 -0
- package/src/cli/setup-state.mjs +168 -0
- package/src/cli/spawn-child.mjs +43 -0
- package/src/public-api/connect-agent.mjs +29 -10
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Release gate: shipped prose must not contradict shipped behavior.
|
|
3
|
+
//
|
|
4
|
+
// Why this exists. The 2026-08-01 four-model audit found the same stale claim
|
|
5
|
+
// in 20 places across both packages: docs said the unattended signer was
|
|
6
|
+
// limited to `hl` and `poly` long after six bounded surfaces had shipped. The
|
|
7
|
+
// worst instances were not READMEs — they were `profiles/oracle/SOUL.md` and
|
|
8
|
+
// `skills/oracle-action-semantics/SKILL.md`, which are read by the MODEL. An
|
|
9
|
+
// agent told that EVM daemon execution is impossible reasons incorrectly about
|
|
10
|
+
// its own authority, and no test suite can see a false sentence.
|
|
11
|
+
//
|
|
12
|
+
// This scans every doc surface that ships in the tarball, including model-facing
|
|
13
|
+
// SOUL and skill text, which is exactly where drift hides longest.
|
|
14
|
+
|
|
15
|
+
import { readFileSync, existsSync, readdirSync, statSync } from "node:fs";
|
|
16
|
+
import { fileURLToPath } from "node:url";
|
|
17
|
+
import path from "node:path";
|
|
18
|
+
|
|
19
|
+
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
20
|
+
const pkg = JSON.parse(readFileSync(path.join(root, "package.json"), "utf8"));
|
|
21
|
+
const failures = [];
|
|
22
|
+
|
|
23
|
+
// Claims that shipped in a real release and are now false.
|
|
24
|
+
const STALE_CLAIMS = [
|
|
25
|
+
{ re: /limited\s+to\s+`?hl`?\s+and\s+`?poly`?/i, why: "says the unattended signer is limited to hl+poly" },
|
|
26
|
+
{ re: /only\s+`?hl`?\s+and\s+`?poly`?\s+are\s+enabled/i, why: "says only hl+poly are daemon-enabled" },
|
|
27
|
+
{ re: /daemon\s+surfaces\s+remain\s+`?hl`?\s+and\s+`?poly`?/i, why: "freezes the surface list at hl+poly" },
|
|
28
|
+
{ re: /policy-bounded\s+`?hl`?\s+and\s+`?poly`?\s+only/i, why: "restricts the daemon to hl+poly" },
|
|
29
|
+
{ re: /agent-facing\s+daemon\s+supports\s+only\s+policy-bounded\s+Hyperliquid\s+and\s+Polymarket\s+execution/i, why: "says the agent-facing daemon supports only Hyperliquid+Polymarket" },
|
|
30
|
+
{ re: /`?evm`?,?\s+`?btc`?,?\s+and\s+`?sol`?\s+fail\s+closed\s+at\s+the\s+daemon/i, why: "claims evm/btc/sol are refused at the daemon" },
|
|
31
|
+
{ re: /EVM,\s*BTC,?\s*and\s+Solana\s+are\s+not\s+daemon\s+surfaces/i, why: "denies evm/btc/sol are daemon surfaces" },
|
|
32
|
+
{ re: /companion\s+daemon\s+is\s+`?hl`?\s*\/\s*`?poly`?[- ]only/i, why: "describes the companion daemon as hl/poly-only" },
|
|
33
|
+
{ re: /daemon\s+supports\s+only\s+policy-bounded\s+Hyperliquid\s+and\s+Polymarket/i, why: "describes the daemon as Hyperliquid/Polymarket-only" },
|
|
34
|
+
{ re: /unattended\s+signer\s+remains\s+`?hl`?\s*\/\s*`?poly`?/i, why: "freezes the generic signer at hl/poly" },
|
|
35
|
+
{ re: /supports\s+autonomous\s+Hyperliquid\s+and\s+Polymarket\s+execution/i, why: "describes the daemon as Hyperliquid/Polymarket-only" },
|
|
36
|
+
{ re: /\(HL\s*\+\s*Poly,\s*capped\)/i, why: "documents autosign as hl/poly-only" },
|
|
37
|
+
{ re: /policy-bounded\s+HL\s*\/\s*Polymarket\s+exec/i, why: "documents the signer daemon as hl/poly-only" },
|
|
38
|
+
{ re: /policy-bounded\s+daemon\s+surfaces:\s*hl\s*\|\s*poly\s*$/i, why: "documents only two of six daemon surfaces" },
|
|
39
|
+
{ re: /ORACLE_SIGNER_SURFACES=hl,poly\s*$/i, why: "quickstart freezes ORACLE_SIGNER_SURFACES at hl,poly" },
|
|
40
|
+
{ re: /ORACLE_AUTONOMOUS_TRADING=1.*(?:or\s+run\s+the\s+signer\s+daemon|same(?:-tier)?).*oracle-signer/i, why: "frames direct exec and oracle-signer as equivalent agent paths" },
|
|
41
|
+
{ re: /(?:or\s+run\s+the\s+signer\s+daemon|same(?:-tier)?).*oracle-signer.*ORACLE_AUTONOMOUS_TRADING=1/i, why: "frames direct exec and oracle-signer as equivalent agent paths" },
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
// Version pins that go stale the moment a release ships. The audit found the
|
|
45
|
+
// quickstart advertising 0.3.6/0.6.1 inside a 0.4.0 tarball, so a copy-paste
|
|
46
|
+
// install handed users an older wall set.
|
|
47
|
+
function checkVersionPins(rel, text) {
|
|
48
|
+
const lines = text.split("\n");
|
|
49
|
+
lines.forEach((line, i) => {
|
|
50
|
+
const pin = line.match(/@oracle-agent\/oracle@(\d+\.\d+\.\d+)/);
|
|
51
|
+
if (pin && pin[1] !== pkg.version) {
|
|
52
|
+
failures.push(
|
|
53
|
+
`${rel}:${i + 1} pins @oracle-agent/oracle@${pin[1]} but this package is ${pkg.version}\n ${line.trim().slice(0, 120)}`,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
const latest = line.match(/Latest:.*oracle\s+`(\d+\.\d+\.\d+)`/i);
|
|
57
|
+
if (latest && latest[1] !== pkg.version) {
|
|
58
|
+
failures.push(
|
|
59
|
+
`${rel}:${i + 1} advertises oracle ${latest[1]} as latest but this package is ${pkg.version}\n ${line.trim().slice(0, 120)}`,
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Every markdown surface that ships to a user or a model.
|
|
66
|
+
function docFiles() {
|
|
67
|
+
const out = [];
|
|
68
|
+
for (const rel of ["README.md", "SETUP.md", "SECURITY.md"]) {
|
|
69
|
+
if (existsSync(path.join(root, rel))) out.push(rel);
|
|
70
|
+
}
|
|
71
|
+
for (const dir of ["docs", "profiles", "skills"]) {
|
|
72
|
+
const abs = path.join(root, dir);
|
|
73
|
+
if (!existsSync(abs)) continue;
|
|
74
|
+
const walk = (d) => {
|
|
75
|
+
for (const entry of readdirSync(d)) {
|
|
76
|
+
const full = path.join(d, entry);
|
|
77
|
+
if (statSync(full).isDirectory()) walk(full);
|
|
78
|
+
else if (entry.endsWith(".md")) out.push(path.relative(root, full));
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
walk(abs);
|
|
82
|
+
}
|
|
83
|
+
return out;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const files = docFiles();
|
|
87
|
+
for (const rel of files) {
|
|
88
|
+
const text = readFileSync(path.join(root, rel), "utf8");
|
|
89
|
+
text.split("\n").forEach((line, i) => {
|
|
90
|
+
for (const claim of STALE_CLAIMS) {
|
|
91
|
+
if (claim.re.test(line)) {
|
|
92
|
+
failures.push(`${rel}:${i + 1} ${claim.why}\n ${line.trim().slice(0, 140)}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
checkVersionPins(rel, text);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
console.log(`package version: ${pkg.version}`);
|
|
100
|
+
console.log(`doc surfaces scanned: ${files.length} (README/SETUP/SECURITY + docs/ + profiles/ + skills/)`);
|
|
101
|
+
console.log("");
|
|
102
|
+
|
|
103
|
+
if (failures.length) {
|
|
104
|
+
console.error(`FAIL — ${failures.length} doc/code drift finding(s):\n`);
|
|
105
|
+
for (const f of failures) console.error(` ${f}\n`);
|
|
106
|
+
console.error("Shipped prose contradicts shipped behavior. Model-facing SOUL/skill text counts:");
|
|
107
|
+
console.error("an agent that reads a false capability claim reasons wrongly about its own authority.");
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
console.log("PASS — no stale capability claims or version pins in shipped docs");
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oracle-chat
|
|
3
|
+
description: "Use when opening the one oracle chat surface, selecting chains with /chain, or configuring messaging with /setup."
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# oracle chat surface
|
|
8
|
+
|
|
9
|
+
You are **oracle** — one lowercase persona. Models can change underneath via `/model`. Branding stays oracle.
|
|
10
|
+
|
|
11
|
+
## commands the user may type
|
|
12
|
+
- `/chain` or `oracle chain` — list working chains
|
|
13
|
+
- `/chain hyperliquid` — pin build/trade context to hyperliquid / hyperevm 999
|
|
14
|
+
- `/chain show` — show active chain
|
|
15
|
+
- `/chain clear` — unset
|
|
16
|
+
- `/setup` — messaging platform menu (telegram, discord, slack, whatsapp, signal, matrix, ...)
|
|
17
|
+
- `/setup telegram` — configure telegram bot token into this hermes profile
|
|
18
|
+
- `/setup discord` — configure discord bot token
|
|
19
|
+
- `/setup messaging` — open full hermes gateway setup wizard
|
|
20
|
+
- `/model` — switch model for this session; persona stays oracle
|
|
21
|
+
|
|
22
|
+
## behavior
|
|
23
|
+
1. When the user asks to build on a chain, prefer the active chain from env:
|
|
24
|
+
- `ORACLE_ACTIVE_CHAIN`
|
|
25
|
+
- `ORACLE_ACTIVE_CHAIN_ID`
|
|
26
|
+
- `ORACLE_ACTIVE_AGENT`
|
|
27
|
+
2. If they name a chain ("build on hyperliquid"), run or instruct:
|
|
28
|
+
`oracle chain use hyperliquid`
|
|
29
|
+
3. Never claim signing/broadcast happened without a real local operator receipt.
|
|
30
|
+
4. Hosted remote models remain read/prepare-only unless a local operator path is explicit.
|
|
31
|
+
5. Keep replies lowercase-friendly and terse. No glaze.
|
|
32
|
+
|
|
33
|
+
## terminal and telegram are the same oracle
|
|
34
|
+
|
|
35
|
+
`oracle` in a TTY launches Hermes with `-p oracle`. Telegram is wired to that
|
|
36
|
+
same profile. The interface changes; the profile, tools, memory, model routing,
|
|
37
|
+
wallet/data MCPs, and custody policy do not.
|
|
38
|
+
|
|
39
|
+
- Do not downgrade a local terminal owner to read-only merely because the turn
|
|
40
|
+
arrived through the CLI.
|
|
41
|
+
- For an explicit owner trade instruction this turn, follow the profile's
|
|
42
|
+
venue-specific executor route when one exists. Otherwise prepare, simulate,
|
|
43
|
+
enforce the active-chain/operator policy, then invoke the configured local
|
|
44
|
+
execution MCP. The signer/operator remains authoritative.
|
|
45
|
+
- If confirmation is not explicit, show the exact action and wait for it.
|
|
46
|
+
- `arm` is a chat action for one exact intent and TTL. Never tell the owner to
|
|
47
|
+
flip an execution environment variable.
|
|
48
|
+
- A tool refusal is a real policy wall. Report the exact refusal instead of
|
|
49
|
+
bypassing it.
|
|
50
|
+
- Never claim a trade executed without a real tx hash, order id, or signed
|
|
51
|
+
operator receipt.
|
|
52
|
+
|
|
53
|
+
## shell helpers
|
|
54
|
+
```bash
|
|
55
|
+
oracle chain list
|
|
56
|
+
oracle chain use hyperliquid
|
|
57
|
+
oracle setup status
|
|
58
|
+
oracle setup telegram --token <BOT_TOKEN>
|
|
59
|
+
oracle setup gateway restart
|
|
60
|
+
oracle chat
|
|
61
|
+
```
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: chain
|
|
3
|
+
description: "Use when the user types /chain or wants to list/select oracle working chains (hyperliquid, base, solana, bitcoin, ...)."
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
disable-model-invocation: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# /chain
|
|
9
|
+
|
|
10
|
+
Run the local oracle chain selector. Do not invent chains.
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
# list
|
|
14
|
+
oracle chain list
|
|
15
|
+
|
|
16
|
+
# select build surface
|
|
17
|
+
oracle chain use {{arg1}}
|
|
18
|
+
|
|
19
|
+
# show / clear
|
|
20
|
+
oracle chain show
|
|
21
|
+
oracle chain clear
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
If `{{arg1}}` is empty, run `oracle chain list`.
|
|
25
|
+
If `{{arg1}}` is `show`, `status`, `clear`, `list`, or a chain key, pass it through:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
oracle chain {{arg1}} {{arg2}}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
After selection, confirm active chain key + id + agent in lowercase.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: setup
|
|
3
|
+
description: "Use when the user types /setup or wants to connect telegram, discord, slack, or other hermes messaging platforms to oracle."
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
disable-model-invocation: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# /setup
|
|
9
|
+
|
|
10
|
+
Configure hermes messaging for the oracle profile. Secrets stay local.
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
# menu + status (never prints tokens)
|
|
14
|
+
oracle setup status
|
|
15
|
+
|
|
16
|
+
# open full hermes wizard
|
|
17
|
+
oracle setup messaging
|
|
18
|
+
|
|
19
|
+
# platform shortcuts
|
|
20
|
+
oracle setup telegram
|
|
21
|
+
oracle setup discord
|
|
22
|
+
oracle setup slack
|
|
23
|
+
oracle setup whatsapp
|
|
24
|
+
|
|
25
|
+
# gateway control
|
|
26
|
+
oracle setup gateway status
|
|
27
|
+
oracle setup gateway restart
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
If the user passed args after `/setup`, forward them:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
oracle setup {{arg1}} {{arg2}} {{arg3}}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
If no args, show `oracle setup status`.
|
|
37
|
+
Never echo bot tokens, app tokens, or passwords back into chat.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
name: oracle
|
|
2
|
+
description: plain lowercase ascii oracle
|
|
3
|
+
colors:
|
|
4
|
+
banner_border: "#30363d"
|
|
5
|
+
banner_title: "#e6edf3"
|
|
6
|
+
banner_accent: "#e6edf3"
|
|
7
|
+
banner_dim: "#7d8590"
|
|
8
|
+
banner_text: "#b1bac4"
|
|
9
|
+
ui_accent: "#e6edf3"
|
|
10
|
+
ui_label: "#b1bac4"
|
|
11
|
+
ui_ok: "#7ee787"
|
|
12
|
+
ui_error: "#ff7b72"
|
|
13
|
+
ui_warn: "#d29922"
|
|
14
|
+
prompt: "#e6edf3"
|
|
15
|
+
input_rule: "#30363d"
|
|
16
|
+
response_border: "#30363d"
|
|
17
|
+
status_bar_bg: "#0d1117"
|
|
18
|
+
status_bar_text: "#b1bac4"
|
|
19
|
+
status_bar_strong: "#e6edf3"
|
|
20
|
+
status_bar_dim: "#7d8590"
|
|
21
|
+
status_bar_good: "#7ee787"
|
|
22
|
+
status_bar_warn: "#d29922"
|
|
23
|
+
status_bar_bad: "#ff7b72"
|
|
24
|
+
status_bar_critical: "#ff7b72"
|
|
25
|
+
session_label: "#b1bac4"
|
|
26
|
+
session_border: "#30363d"
|
|
27
|
+
voice_status_bg: "#0d1117"
|
|
28
|
+
selection_bg: "#21262d"
|
|
29
|
+
completion_menu_bg: "#0d1117"
|
|
30
|
+
completion_menu_current_bg: "#21262d"
|
|
31
|
+
completion_menu_meta_bg: "#0d1117"
|
|
32
|
+
completion_menu_meta_current_bg: "#21262d"
|
|
33
|
+
spinner:
|
|
34
|
+
waiting_faces: [".", "..", "..."]
|
|
35
|
+
thinking_faces: [".", "..", "..."]
|
|
36
|
+
thinking_verbs: ["working", "reading", "checking", "routing"]
|
|
37
|
+
wings: [["", ""]]
|
|
38
|
+
branding:
|
|
39
|
+
agent_name: "oracle"
|
|
40
|
+
welcome: ""
|
|
41
|
+
goodbye: "exit"
|
|
42
|
+
response_label: "oracle"
|
|
43
|
+
prompt_symbol: ">"
|
|
44
|
+
help_header: "oracle"
|
|
45
|
+
tool_prefix: ">"
|
|
46
|
+
banner_logo: |
|
|
47
|
+
[#e6edf3] _[/]
|
|
48
|
+
[#e6edf3] ___ _ _ __ _ __| |___[/]
|
|
49
|
+
[#e6edf3]/ _ \ '_/ _` / _| / -_)[/]
|
|
50
|
+
[#e6edf3]\___/_| \__,_\__|_\___|[/]
|
|
51
|
+
banner_hero: |
|
|
52
|
+
[#e6edf3]oracle[/]
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
// Working chain surface for the oracle chat/CLI selector.
|
|
2
|
+
// Keys stay lowercase. Hyperliquid is the product name; HyperEVM is chain 999.
|
|
3
|
+
|
|
4
|
+
export const WORKING_CHAINS = Object.freeze([
|
|
5
|
+
{
|
|
6
|
+
key: "hyperliquid",
|
|
7
|
+
aliases: ["hl", "hyperevm", "hype", "999"],
|
|
8
|
+
chainId: 999,
|
|
9
|
+
name: "hyperliquid",
|
|
10
|
+
kind: "evm",
|
|
11
|
+
family: "hyperliquid",
|
|
12
|
+
agent: "hyperliquid-agent",
|
|
13
|
+
note: "perps · hip-3/4 · hyperevm 999",
|
|
14
|
+
build: true,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
key: "ethereum",
|
|
18
|
+
aliases: ["eth", "mainnet", "1"],
|
|
19
|
+
chainId: 1,
|
|
20
|
+
name: "ethereum",
|
|
21
|
+
kind: "evm",
|
|
22
|
+
family: "evm",
|
|
23
|
+
agent: "oracle",
|
|
24
|
+
note: "l1 · bridge hub",
|
|
25
|
+
build: true,
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
key: "base",
|
|
29
|
+
aliases: ["8453"],
|
|
30
|
+
chainId: 8453,
|
|
31
|
+
name: "base",
|
|
32
|
+
kind: "evm",
|
|
33
|
+
family: "evm",
|
|
34
|
+
agent: "oracle",
|
|
35
|
+
note: "evm l2",
|
|
36
|
+
build: true,
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
key: "arbitrum",
|
|
40
|
+
aliases: ["arb", "42161"],
|
|
41
|
+
chainId: 42161,
|
|
42
|
+
name: "arbitrum",
|
|
43
|
+
kind: "evm",
|
|
44
|
+
family: "evm",
|
|
45
|
+
agent: "oracle",
|
|
46
|
+
note: "evm l2",
|
|
47
|
+
build: true,
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
key: "optimism",
|
|
51
|
+
aliases: ["op", "10"],
|
|
52
|
+
chainId: 10,
|
|
53
|
+
name: "optimism",
|
|
54
|
+
kind: "evm",
|
|
55
|
+
family: "evm",
|
|
56
|
+
agent: "oracle",
|
|
57
|
+
note: "op mainnet",
|
|
58
|
+
build: true,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
key: "polygon",
|
|
62
|
+
aliases: ["matic", "137"],
|
|
63
|
+
chainId: 137,
|
|
64
|
+
name: "polygon",
|
|
65
|
+
kind: "evm",
|
|
66
|
+
family: "evm",
|
|
67
|
+
agent: "oracle",
|
|
68
|
+
note: "evm l2",
|
|
69
|
+
build: true,
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
key: "bsc",
|
|
73
|
+
aliases: ["bnb", "56"],
|
|
74
|
+
chainId: 56,
|
|
75
|
+
name: "bnb chain",
|
|
76
|
+
kind: "evm",
|
|
77
|
+
family: "evm",
|
|
78
|
+
agent: "oracle",
|
|
79
|
+
note: "bsc",
|
|
80
|
+
build: true,
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
key: "avalanche",
|
|
84
|
+
aliases: ["avax", "43114"],
|
|
85
|
+
chainId: 43114,
|
|
86
|
+
name: "avalanche",
|
|
87
|
+
kind: "evm",
|
|
88
|
+
family: "evm",
|
|
89
|
+
agent: "oracle",
|
|
90
|
+
note: "c-chain",
|
|
91
|
+
build: true,
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
key: "abstract",
|
|
95
|
+
aliases: ["abs", "2741"],
|
|
96
|
+
chainId: 2741,
|
|
97
|
+
name: "abstract",
|
|
98
|
+
kind: "evm",
|
|
99
|
+
family: "evm",
|
|
100
|
+
agent: "oracle",
|
|
101
|
+
note: "open / add agent",
|
|
102
|
+
build: true,
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
key: "stable",
|
|
106
|
+
aliases: ["988"],
|
|
107
|
+
chainId: 988,
|
|
108
|
+
name: "stable",
|
|
109
|
+
kind: "evm",
|
|
110
|
+
family: "stable",
|
|
111
|
+
agent: "stable-agent",
|
|
112
|
+
note: "usdt0 gas · stable agent",
|
|
113
|
+
build: true,
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
key: "robinhood",
|
|
117
|
+
aliases: ["rh", "4663"],
|
|
118
|
+
chainId: 4663,
|
|
119
|
+
name: "robinhood",
|
|
120
|
+
kind: "evm",
|
|
121
|
+
family: "robinhood",
|
|
122
|
+
agent: "robinhood-agent",
|
|
123
|
+
note: "rh chain 4663",
|
|
124
|
+
build: true,
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
key: "solana",
|
|
128
|
+
aliases: ["sol"],
|
|
129
|
+
chainId: "SOL",
|
|
130
|
+
name: "solana",
|
|
131
|
+
kind: "svm",
|
|
132
|
+
family: "solana",
|
|
133
|
+
agent: "solana-agent",
|
|
134
|
+
note: "jup · nfts · dexs",
|
|
135
|
+
build: true,
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
key: "bitcoin",
|
|
139
|
+
aliases: ["btc"],
|
|
140
|
+
chainId: "BTC",
|
|
141
|
+
name: "bitcoin",
|
|
142
|
+
kind: "utxo",
|
|
143
|
+
family: "bitcoin",
|
|
144
|
+
agent: "bitcoin-agent",
|
|
145
|
+
note: "ord · runes · l1",
|
|
146
|
+
build: true,
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
key: "polymarket",
|
|
150
|
+
aliases: ["poly", "polygon-poly"],
|
|
151
|
+
chainId: 137,
|
|
152
|
+
name: "polymarket",
|
|
153
|
+
kind: "venue",
|
|
154
|
+
family: "polymarket",
|
|
155
|
+
agent: "polymarket-agent",
|
|
156
|
+
note: "prediction markets (polygon venue)",
|
|
157
|
+
build: false,
|
|
158
|
+
},
|
|
159
|
+
]);
|
|
160
|
+
|
|
161
|
+
function normalize(raw) {
|
|
162
|
+
return String(raw || "")
|
|
163
|
+
.trim()
|
|
164
|
+
.toLowerCase()
|
|
165
|
+
.replace(/^\/+/, "")
|
|
166
|
+
.replace(/\s+/g, "-");
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export function listWorkingChains({ buildOnly = false } = {}) {
|
|
170
|
+
return WORKING_CHAINS.filter((c) => (buildOnly ? c.build : true));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function findWorkingChain(query) {
|
|
174
|
+
const q = normalize(query);
|
|
175
|
+
if (!q) return null;
|
|
176
|
+
for (const chain of WORKING_CHAINS) {
|
|
177
|
+
if (chain.key === q) return chain;
|
|
178
|
+
if (String(chain.chainId).toLowerCase() === q) return chain;
|
|
179
|
+
if ((chain.aliases || []).map(normalize).includes(q)) return chain;
|
|
180
|
+
if (normalize(chain.name) === q) return chain;
|
|
181
|
+
}
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export function renderChainList({ selectedKey = null, buildOnly = false } = {}) {
|
|
186
|
+
const rows = listWorkingChains({ buildOnly });
|
|
187
|
+
const lines = [
|
|
188
|
+
"oracle chains",
|
|
189
|
+
"",
|
|
190
|
+
"pick a build/trade surface:",
|
|
191
|
+
"",
|
|
192
|
+
];
|
|
193
|
+
for (const c of rows) {
|
|
194
|
+
const mark = selectedKey && selectedKey === c.key ? "*" : " ";
|
|
195
|
+
const id = String(c.chainId).padEnd(6);
|
|
196
|
+
const key = c.key.padEnd(12);
|
|
197
|
+
lines.push(`${mark} ${key} ${id} ${c.note}`);
|
|
198
|
+
}
|
|
199
|
+
lines.push("");
|
|
200
|
+
lines.push("usage:");
|
|
201
|
+
lines.push(" /chain list");
|
|
202
|
+
lines.push(" /chain hyperliquid select");
|
|
203
|
+
lines.push(" /chain show current");
|
|
204
|
+
lines.push(" /chain clear unset");
|
|
205
|
+
lines.push(" oracle chain use base same from shell");
|
|
206
|
+
if (selectedKey) lines.push("", `active: ${selectedKey}`);
|
|
207
|
+
return lines.join("\n") + "\n";
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export default {
|
|
211
|
+
WORKING_CHAINS,
|
|
212
|
+
listWorkingChains,
|
|
213
|
+
findWorkingChain,
|
|
214
|
+
renderChainList,
|
|
215
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { findWorkingChain } from "./chain-catalog.mjs";
|
|
4
|
+
import { homeDir, ensureDir, oracleConfigDir } from "./paths.mjs";
|
|
5
|
+
|
|
6
|
+
export function activeChainPath() {
|
|
7
|
+
return path.join(oracleConfigDir(), "active-chain.json");
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function readActiveChain() {
|
|
11
|
+
const p = activeChainPath();
|
|
12
|
+
if (!fs.existsSync(p)) return null;
|
|
13
|
+
try {
|
|
14
|
+
const raw = JSON.parse(fs.readFileSync(p, "utf8"));
|
|
15
|
+
if (!raw || typeof raw !== "object" || !raw.key) return null;
|
|
16
|
+
const chain = findWorkingChain(raw.key);
|
|
17
|
+
if (!chain) return null;
|
|
18
|
+
return {
|
|
19
|
+
key: chain.key,
|
|
20
|
+
chainId: chain.chainId,
|
|
21
|
+
name: chain.name,
|
|
22
|
+
agent: chain.agent,
|
|
23
|
+
selectedAt: raw.selectedAt || null,
|
|
24
|
+
};
|
|
25
|
+
} catch {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function writeActiveChain(query) {
|
|
31
|
+
const chain = findWorkingChain(query);
|
|
32
|
+
if (!chain) {
|
|
33
|
+
const err = new Error(`unknown chain '${query}'`);
|
|
34
|
+
err.code = "UNKNOWN_CHAIN";
|
|
35
|
+
throw err;
|
|
36
|
+
}
|
|
37
|
+
ensureDir(oracleConfigDir());
|
|
38
|
+
const payload = {
|
|
39
|
+
key: chain.key,
|
|
40
|
+
chainId: chain.chainId,
|
|
41
|
+
name: chain.name,
|
|
42
|
+
agent: chain.agent,
|
|
43
|
+
selectedAt: new Date().toISOString(),
|
|
44
|
+
};
|
|
45
|
+
fs.writeFileSync(activeChainPath(), JSON.stringify(payload, null, 2) + "\n", {
|
|
46
|
+
mode: 0o600,
|
|
47
|
+
});
|
|
48
|
+
return payload;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function clearActiveChain() {
|
|
52
|
+
const p = activeChainPath();
|
|
53
|
+
if (fs.existsSync(p)) fs.unlinkSync(p);
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function activeChainEnv(extra = {}) {
|
|
58
|
+
const active = readActiveChain();
|
|
59
|
+
const env = { ...process.env, ...extra };
|
|
60
|
+
if (!active) return env;
|
|
61
|
+
env.ORACLE_ACTIVE_CHAIN = active.key;
|
|
62
|
+
env.ORACLE_ACTIVE_CHAIN_ID = String(active.chainId);
|
|
63
|
+
env.ORACLE_ACTIVE_AGENT = active.agent || "oracle";
|
|
64
|
+
return env;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export default {
|
|
68
|
+
activeChainPath,
|
|
69
|
+
readActiveChain,
|
|
70
|
+
writeActiveChain,
|
|
71
|
+
clearActiveChain,
|
|
72
|
+
activeChainEnv,
|
|
73
|
+
homeDir,
|
|
74
|
+
};
|