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 +5 -3
- package/bin/openzoo.js +7 -2
- package/lib/config.js +1 -1
- package/lib/contexts.js +38 -0
- package/package.json +1 -1
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 #
|
|
195
|
-
npx openzoo contexts --forget all #
|
|
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://
|
|
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,
|
|
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
|
-
|
|
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://
|
|
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.
|
|
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",
|