@oracle-agent/oracle 0.7.0 → 0.9.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.
Files changed (36) hide show
  1. package/README.md +6 -4
  2. package/SETUP.md +1 -0
  3. package/bin/desk-server.mjs +2 -2
  4. package/docs/cli.md +2 -2
  5. package/package.json +1 -1
  6. package/profiles/oracle/SOUL.md +2 -2
  7. package/protocols/templates/safe-erc20/README.md +9 -0
  8. package/public/oracle-splash/assets/llms/codex-icon.svg +1 -0
  9. package/public/oracle-splash/assets/llms/gemini-icon.svg +1 -0
  10. package/public/oracle-splash/assets/wordmarks/across-icon.webp +0 -0
  11. package/public/oracle-splash/assets/wordmarks/hop-icon.webp +0 -0
  12. package/public/oracle-splash/assets/wordmarks/markets.svg +1 -0
  13. package/public/oracle-splash/assets/wordmarks/oneinch-icon.webp +0 -0
  14. package/public/oracle-splash/assets/wordmarks/opensea-icon.svg +17 -0
  15. package/public/oracle-splash/assets/wordmarks/satflow-icon.png +0 -0
  16. package/public/oracle-splash/assets/wordmarks/stargate-icon.webp +0 -0
  17. package/public/oracle-splash/assets/wordmarks/zerox-icon.webp +0 -0
  18. package/public/oracle-splash/favicon.ico +0 -0
  19. package/public/oracle-splash/favicon.svg +6 -0
  20. package/public/oracle-splash/index.html +153 -96
  21. package/scripts/check-doc-drift.mjs +1 -0
  22. package/skills/oracle-chat/setup.SKILL.md +2 -2
  23. package/skins/oracle.yaml +45 -41
  24. package/src/cli/commands/bootstrap.mjs +87 -0
  25. package/src/cli/commands/chat.mjs +140 -25
  26. package/src/cli/commands/doctor.mjs +5 -10
  27. package/src/cli/commands/model.mjs +19 -13
  28. package/src/cli/commands/setup.mjs +11 -19
  29. package/src/cli/first-run.mjs +2 -2
  30. package/src/cli/kernel.mjs +5 -4
  31. package/src/cli/messaging-platforms.mjs +1 -1
  32. package/src/cli/oracle-harness.py +226 -70
  33. package/src/cli/runtime.mjs +351 -0
  34. package/src/data/catalog.mjs +17 -2
  35. package/src/public-api/http.mjs +16 -1
  36. package/src/public-control/runtime-config.mjs +11 -1
@@ -3,19 +3,26 @@
3
3
  /** @typedef {{ id: string, venue: string, chainIds: number[], auth: 'none'|'apiKey'|'agentKey', ops: string[], baseEnv?: string[], description?: string }} ProviderMeta */
4
4
 
5
5
  const REGISTRY = new Map();
6
+ const BUILTIN_PROVIDER_IDS = new Set();
7
+ let BUILTINS_LOCKED = false;
6
8
 
7
9
  export function registerProvider(meta) {
8
10
  if (!meta?.id) throw new Error("registerProvider requires id");
9
11
  if (!meta.venue) throw new Error("registerProvider requires venue");
10
12
  if (!Array.isArray(meta.ops)) throw new Error("registerProvider requires ops[]");
11
- REGISTRY.set(meta.id, {
13
+ const id = String(meta.id);
14
+ if (BUILTINS_LOCKED && BUILTIN_PROVIDER_IDS.has(id)) {
15
+ throw new Error(`registerProvider refuses to overwrite built-in provider: ${id}`);
16
+ }
17
+ REGISTRY.set(id, {
12
18
  chainIds: meta.chainIds || [],
13
19
  auth: meta.auth || "none",
14
20
  description: meta.description || "",
15
21
  baseEnv: meta.baseEnv || [],
16
22
  ...meta,
23
+ id,
17
24
  });
18
- return REGISTRY.get(meta.id);
25
+ return REGISTRY.get(id);
19
26
  }
20
27
 
21
28
  export function getProvider(id) {
@@ -33,6 +40,12 @@ export function clearProvidersForTest() {
33
40
  REGISTRY.clear();
34
41
  }
35
42
 
43
+ function lockBuiltinProviders() {
44
+ BUILTIN_PROVIDER_IDS.clear();
45
+ for (const id of REGISTRY.keys()) BUILTIN_PROVIDER_IDS.add(id);
46
+ BUILTINS_LOCKED = true;
47
+ }
48
+
36
49
  // ── Built-in providers ──────────────────────────────────────────────────────
37
50
 
38
51
  registerProvider({
@@ -537,3 +550,5 @@ registerProvider({
537
550
  baseEnv: ["ZEROX_API_KEY", "ONEINCH_API_KEY"],
538
551
  description: "Cross-chain RFQ intent normalizer and firm-quote fanout over reviewed venues. Prepares artifacts only, never signs or broadcasts.",
539
552
  });
553
+
554
+ lockBuiltinProviders();
@@ -41,6 +41,8 @@ export const DEFAULT_HOST = "127.0.0.1";
41
41
  export const DEFAULT_PORT = 8799;
42
42
  export const VERSION = pkg.version;
43
43
 
44
+ const LOOPBACK_HOSTS = new Set(["127.0.0.1", "localhost", "::1"]);
45
+
44
46
  const ROOT_DIR = join(dirname(fileURLToPath(import.meta.url)), "../..");
45
47
  const CONSOLE_DIR = join(ROOT_DIR, "public", "oracle-console");
46
48
 
@@ -136,6 +138,18 @@ function asPlainObject(v, code) {
136
138
  return v;
137
139
  }
138
140
 
141
+ function normalizeHost(host) {
142
+ return String(host || "").trim().toLowerCase().replace(/^\[|\]$/g, "");
143
+ }
144
+
145
+ function assertLoopbackBindHost(host) {
146
+ const normalized = normalizeHost(host);
147
+ if (!LOOPBACK_HOSTS.has(normalized)) {
148
+ throw new TypeError(`oracle-public only binds loopback hosts; got ${String(host)}`);
149
+ }
150
+ return normalized === "::1" ? "::1" : String(host).trim();
151
+ }
152
+
139
153
  // ---------------------------------------------------------------------------
140
154
  // Route handlers — each returns { status, body }; errors are thrown.
141
155
  // ---------------------------------------------------------------------------
@@ -354,9 +368,10 @@ export function createPublicServer() {
354
368
  /**
355
369
  * Resolve host/port: explicit args > ORACLE_PUBLIC_HOST/PORT env (via
356
370
  * oracle-env's env() helper) > loopback 127.0.0.1:8799 default.
371
+ * Non-loopback binds fail closed; this plane has no remote peer/origin guard.
357
372
  */
358
373
  export function resolvePublicBind({ host, port } = {}) {
359
- const h = host ?? env("ORACLE_PUBLIC_HOST", "MAD_PUBLIC_HOST", DEFAULT_HOST);
374
+ const h = assertLoopbackBindHost(host ?? env("ORACLE_PUBLIC_HOST", "MAD_PUBLIC_HOST", DEFAULT_HOST));
360
375
  const rawPort = port ?? env("ORACLE_PUBLIC_PORT", "MAD_PUBLIC_PORT", String(DEFAULT_PORT));
361
376
  const p = Number(rawPort);
362
377
  if (!Number.isInteger(p) || p < 0 || p > 65535) {
@@ -107,6 +107,7 @@ const CHAIN_SEEDS = Object.freeze([
107
107
  export const DEFAULT_CHAIN_ID = 8453;
108
108
  export const DEFAULT_PUBLIC_HOST = "127.0.0.1";
109
109
  export const DEFAULT_PUBLIC_PORT = 8799;
110
+ const LOOPBACK_HOSTS = new Set(["127.0.0.1", "localhost", "::1"]);
110
111
 
111
112
  function buildChainEntry(seed, env) {
112
113
  const entry = {
@@ -143,6 +144,15 @@ function parsePort(raw, label) {
143
144
  return n;
144
145
  }
145
146
 
147
+ function parsePublicHost(raw, label) {
148
+ const host = String(raw).trim();
149
+ const normalized = host.toLowerCase().replace(/^\[|\]$/g, "");
150
+ if (!LOOPBACK_HOSTS.has(normalized)) {
151
+ fail(`${label} must be a loopback host, got ${JSON.stringify(raw)}`);
152
+ }
153
+ return normalized === "::1" ? "::1" : host;
154
+ }
155
+
146
156
  /**
147
157
  * Parse the public runtime config (chain/bundler/paymaster registry + public
148
158
  * HTTP bind) from an env-like object. Pure function, no I/O, no network.
@@ -182,7 +192,7 @@ export function loadPublicConfig(env = process.env) {
182
192
 
183
193
  const publicHost = (() => {
184
194
  const v = env.ORACLE_PUBLIC_HOST ?? env.MAD_PUBLIC_HOST;
185
- return v != null && String(v).trim() !== "" ? String(v) : DEFAULT_PUBLIC_HOST;
195
+ return v != null && String(v).trim() !== "" ? parsePublicHost(v, "ORACLE_PUBLIC_HOST") : DEFAULT_PUBLIC_HOST;
186
196
  })();
187
197
 
188
198
  const publicPort = (() => {