openzoo 0.51.29 → 0.51.31

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 CHANGED
@@ -191,10 +191,12 @@ Manage it:
191
191
 
192
192
  ```bash
193
193
  npx openzoo contexts # list bound corpora (hash, context id, age, api base)
194
- npx openzoo contexts --forget 60464d # drop one by hash prefix
195
- npx openzoo contexts --forget all # drop everything
194
+ npx openzoo contexts --forget 60464d # erase one by hash prefix (on the zoo AND locally)
195
+ npx openzoo contexts --forget all # erase everything you have bound
196
196
  ```
197
197
 
198
+ **Retention.** A bound corpus is a cache of your own prompt, not a record. The zoo keeps it for **24 hours after its last use** (every recall refreshes the clock) and then deletes it — `state`, text blobs and delta chunks — from disk. `--forget` sends a wallet-signed `DELETE /v1/contexts/:id` for each matching context and only then drops it from the local manifest, so you can erase earlier than the TTL and only the wallet that bound a context can erase it. Stored text is compressed, not encrypted; see the security note below.
199
+
198
200
  Opt out with `OPENZOO_NO_CONTEXT_CACHE=1` (always ship the full body); tune the threshold with `OPENZOO_CONTEXT_MIN_CHARS` (default 16384 chars).
199
201
 
200
202
  ## Using openzoo from a cloud IDE (Cursor, Windsurf, hosted agents)
@@ -283,7 +285,7 @@ The rail is chosen from the 402's `accepts[]` itself (Solana first). **Steer it
283
285
  | `OPENZOO_RPC` | mainnet-beta public RPC | Solana RPC |
284
286
  | `OPENZOO_TOKEN` | (internal) | preferred 402 rail — leave unset |
285
287
  | `OPENZOO_RAIL` | (unset) | force a rail: `solana` \| `base` \| `robinhood`. Errors if the live 402 doesn't offer it |
286
- | `OPENZOO_BASE_RPC` | `https://mainnet.base.org` | Base RPC (balances / preflight) |
288
+ | `OPENZOO_BASE_RPC` | `https://base-rpc.publicnode.com` | Base RPC (balances / preflight) |
287
289
  | `OPENZOO_RH_RPC` | `https://rpc.mainnet.chain.robinhood.com` | Robinhood Chain RPC (balances / preflight) |
288
290
  | `OPENZOO_WALLET` | `~/.openzoo/wallet.json` | wallet path |
289
291
  | `OPENZOO_MAX_USD_PER_CALL` | `0.5` | refuse quotes above this |
package/bin/openzoo.js CHANGED
@@ -295,12 +295,17 @@ async function main() {
295
295
  await (await import('../lib/demo.js')).runDemo();
296
296
  break;
297
297
  case 'contexts': {
298
- const { listContexts, forgetContexts } = await import('../lib/contexts.js');
298
+ const { listContexts, forgetContextsRemote } = await import('../lib/contexts.js');
299
299
  const fi = process.argv.indexOf('--forget');
300
300
  if (fi !== -1) {
301
301
  const sel = process.argv[fi + 1];
302
302
  if (!sel) throw new Error('usage: openzoo contexts --forget <hash-prefix|all>');
303
- console.log(`forgot ${forgetContexts(sel)} context(s)`);
303
+ const r = await forgetContextsRemote(sel);
304
+ console.log(`forgot ${r.removed} context(s): ${r.deleted} erased on the zoo`);
305
+ for (const f of r.failed) {
306
+ console.error(` ! ${f.context_id} @ ${f.apiBase}: HTTP ${f.status} ${f.body}`.trimEnd());
307
+ }
308
+ if (r.failed.length) process.exitCode = 1;
304
309
  break;
305
310
  }
306
311
  const all = listContexts();
package/lib/config.js CHANGED
@@ -20,7 +20,7 @@ export const config = {
20
20
  // pickAccept errors clearly when the live 402 does not offer the forced rail.
21
21
  rail: (process.env.OPENZOO_RAIL || '').toLowerCase() || null,
22
22
  // EVM RPCs for balance reads / preflight checks on the Base and RH rails.
23
- baseRpcUrl: process.env.OPENZOO_BASE_RPC || 'https://mainnet.base.org',
23
+ baseRpcUrl: process.env.OPENZOO_BASE_RPC || 'https://base-rpc.publicnode.com',
24
24
  rhRpcUrl: process.env.OPENZOO_RH_RPC || 'https://rpc.mainnet.chain.robinhood.com',
25
25
  walletPath: process.env.OPENZOO_WALLET || path.join(os.homedir(), '.openzoo', 'wallet.json'),
26
26
  // Refuse to auto-pay any single 402 quote above this many USD (extra.billedUsd).
package/lib/contexts.js CHANGED
@@ -100,3 +100,41 @@ export function forgetContexts(selector) {
100
100
  if (removed) save(map);
101
101
  return removed;
102
102
  }
103
+
104
+ /**
105
+ * Forget for real: tell each gateway to delete the bound context, THEN drop
106
+ * it from the local manifest. Returns { removed, deleted, failed }.
107
+ *
108
+ * `--forget` used to edit only ~/.openzoo/contexts.json, which made the next
109
+ * ask re-upload while the corpus sat on the zoo's sidecar untouched. That is
110
+ * not forgetting. DELETE /v1/contexts/:id is free and wallet-signed with the
111
+ * same namespace proof that bound the context, so only the owner can erase.
112
+ * The local entry is dropped even when the gateway call fails — the caller
113
+ * asked us to stop reusing it — and the failure is reported, not hidden.
114
+ */
115
+ export async function forgetContextsRemote(selector, { fetchImpl = globalThis.fetch } = {}) {
116
+ const { withNamespace } = await import('./namespace.js');
117
+ const map = load();
118
+ const targets = [];
119
+ for (const [apiBase, entries] of Object.entries(map)) {
120
+ for (const [hash, e] of Object.entries(entries)) {
121
+ if (selector === 'all' || hash.startsWith(selector)) targets.push({ apiBase, hash, context_id: e.context_id });
122
+ }
123
+ }
124
+ let deleted = 0;
125
+ const failed = [];
126
+ for (const t of targets) {
127
+ try {
128
+ const r = await fetchImpl(`${t.apiBase}/v1/contexts/${encodeURIComponent(t.context_id)}`, {
129
+ method: 'DELETE',
130
+ headers: withNamespace(),
131
+ });
132
+ if (r.status === 200) deleted += 1;
133
+ else failed.push({ ...t, status: r.status, body: (await r.text().catch(() => '')).slice(0, 200) });
134
+ } catch (err) {
135
+ failed.push({ ...t, status: 0, body: String(err?.message || err) });
136
+ }
137
+ }
138
+ const removed = forgetContexts(selector);
139
+ return { removed, deleted, failed };
140
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openzoo",
3
- "version": "0.51.29",
3
+ "version": "0.51.31",
4
4
  "description": "Local x402-paying proxy + MCP server for openzoo.fun — point any OpenAI-compatible harness (Cursor, Claude Code, aider, SDKs) at localhost and it pays per call from a local burner wallet. Solana and Base rails live; Robinhood experimental.",
5
5
  "license": "MIT",
6
6
  "type": "module",