@oneie/sdk 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 (71) hide show
  1. package/README.md +333 -190
  2. package/dist/auth.d.ts +102 -0
  3. package/dist/auth.d.ts.map +1 -0
  4. package/dist/auth.js +154 -0
  5. package/dist/auth.js.map +1 -0
  6. package/dist/client.d.ts +221 -24
  7. package/dist/client.d.ts.map +1 -1
  8. package/dist/client.js +331 -154
  9. package/dist/client.js.map +1 -1
  10. package/dist/compile.d.ts +123 -0
  11. package/dist/compile.d.ts.map +1 -0
  12. package/dist/compile.js +652 -0
  13. package/dist/compile.js.map +1 -0
  14. package/dist/fetch.d.ts +40 -0
  15. package/dist/fetch.d.ts.map +1 -0
  16. package/dist/fetch.js +158 -0
  17. package/dist/fetch.js.map +1 -0
  18. package/dist/generated/types.d.ts +104 -0
  19. package/dist/generated/types.d.ts.map +1 -0
  20. package/dist/generated/types.js +5 -0
  21. package/dist/generated/types.js.map +1 -0
  22. package/dist/index.d.ts +8 -1
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +6 -1
  25. package/dist/index.js.map +1 -1
  26. package/dist/pay.d.ts +2 -2
  27. package/dist/pay.d.ts.map +1 -1
  28. package/dist/pay.js +5 -5
  29. package/dist/pay.js.map +1 -1
  30. package/dist/schemas.d.ts +39 -0
  31. package/dist/schemas.d.ts.map +1 -1
  32. package/dist/schemas.js +26 -0
  33. package/dist/schemas.js.map +1 -1
  34. package/dist/skills.d.ts +40 -0
  35. package/dist/skills.d.ts.map +1 -0
  36. package/dist/skills.js +16 -0
  37. package/dist/skills.js.map +1 -0
  38. package/dist/storage.d.ts +7 -8
  39. package/dist/storage.d.ts.map +1 -1
  40. package/dist/storage.js +61 -33
  41. package/dist/storage.js.map +1 -1
  42. package/dist/telemetry.d.ts +9 -0
  43. package/dist/telemetry.d.ts.map +1 -1
  44. package/dist/telemetry.js +11 -0
  45. package/dist/telemetry.js.map +1 -1
  46. package/dist/testing/index.d.ts.map +1 -1
  47. package/dist/testing/index.js +4 -3
  48. package/dist/testing/index.js.map +1 -1
  49. package/dist/types.d.ts +148 -20
  50. package/dist/types.d.ts.map +1 -1
  51. package/package.json +26 -17
  52. package/dist/react/context.d.ts +0 -11
  53. package/dist/react/context.d.ts.map +0 -1
  54. package/dist/react/context.js +0 -13
  55. package/dist/react/context.js.map +0 -1
  56. package/dist/react/hooks.d.ts +0 -104
  57. package/dist/react/hooks.d.ts.map +0 -1
  58. package/dist/react/hooks.js +0 -247
  59. package/dist/react/hooks.js.map +0 -1
  60. package/dist/react/index.d.ts +0 -6
  61. package/dist/react/index.d.ts.map +0 -1
  62. package/dist/react/index.js +0 -5
  63. package/dist/react/index.js.map +0 -1
  64. package/dist/react/optimistic.d.ts +0 -45
  65. package/dist/react/optimistic.d.ts.map +0 -1
  66. package/dist/react/optimistic.js +0 -52
  67. package/dist/react/optimistic.js.map +0 -1
  68. package/dist/react/stream.d.ts +0 -18
  69. package/dist/react/stream.d.ts.map +0 -1
  70. package/dist/react/stream.js +0 -60
  71. package/dist/react/stream.js.map +0 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @oneie/sdk
2
2
 
3
- Client SDK for the ONE substrate — signals, units, persist, launch handoff.
3
+ TypeScript SDK for the ONE substrate — signal routing, agent registration, skill discovery, pheromone paths, and agent-to-agent payments.
4
4
 
5
5
  ```bash
6
6
  npm install @oneie/sdk
@@ -9,91 +9,140 @@ npm install @oneie/sdk
9
9
  ## Quick Start
10
10
 
11
11
  ```typescript
12
- import { getApiUrl, resolveApiKey } from "@oneie/sdk/urls";
13
- import * as storage from "@oneie/sdk/storage";
12
+ import { SubstrateClient } from "@oneie/sdk";
14
13
 
15
- // Resolve base URL (env: ONEIE_API_URL, default: https://api.one.ie)
16
- const url = getApiUrl();
14
+ const client = SubstrateClient.fromApiKey(process.env.ONEIE_API_KEY);
17
15
 
18
- // Storage CRUD
19
- await storage.put("my-key", { hello: "world" }, { apiKey: resolveApiKey() });
20
- const value = await storage.get("my-key");
21
- await storage.del("my-key");
16
+ // Send a signal and wait for response
17
+ const outcome = await client.ask("tutor:explain", { topic: "TypeScript" });
18
+ if (outcome.kind === "result") {
19
+ console.log("Got:", outcome.result);
20
+ } else if (outcome.kind === "timeout") {
21
+ console.log("Timed out");
22
+ }
23
+
24
+ // Mark a successful path to strengthen routing
25
+ await client.mark("tutor→learner", { fit: 1, form: 1, truth: 1, taste: 1 });
26
+
27
+ // View the highest-strength paths (highways)
28
+ const { highways } = await client.highways(10);
29
+ highways.forEach(h => console.log(`${h.path}: ${h.net}`));
22
30
  ```
23
31
 
24
32
  ## Modules
25
33
 
26
34
  | Import | What |
27
35
  |--------|------|
28
- | `@oneie/sdk` | Types + all re-exports |
36
+ | `@oneie/sdk` | Main client + types + all re-exports |
29
37
  | `@oneie/sdk/urls` | `getApiUrl()`, `resolveApiKey()`, `resolveBaseUrl()` |
30
38
  | `@oneie/sdk/storage` | `get()`, `put()`, `del()`, `list()` — `/api/storage/*` |
31
- | `@oneie/sdk/launch` | `launchToken()` — generate agent launch tokens |
39
+ | `@oneie/sdk/launch` | `launchToken()` — generate agent launch tokens on Sui/EVM |
32
40
  | `@oneie/sdk/handoff` | Token handoff helpers |
41
+ | `@oneie/sdk/compile` | `compileAgent()`, `parse()` — agent markdown → Python / MCP / SKILL.md |
42
+ | `@oneie/sdk/react` | `useAgent()`, `useDiscover()`, `useHighways()`, `streamChat()` — React hooks |
43
+ | `@oneie/sdk/testing` | `createMockSubstrate()` — mock client for tests |
44
+ | `@oneie/sdk/errors` | Error types: `AuthError`, `RateLimitError`, `ValidationError`, etc. |
45
+ | `@oneie/sdk/schemas` | Zod schemas for response validation |
33
46
 
34
- ## Types
47
+ ## Core Client
48
+
49
+ ### Initialize
35
50
 
36
51
  ```typescript
37
- import type { SdkConfig, OneSdkError, Outcome } from "@oneie/sdk";
52
+ import { SubstrateClient } from "@oneie/sdk";
53
+
54
+ // From env: ONEIE_API_KEY (required), ONEIE_API_URL (optional, default https://api.one.ie)
55
+ const client = SubstrateClient.fromApiKey(process.env.ONEIE_API_KEY);
38
56
 
39
- // Outcome the 4-result type from the substrate
40
- type Outcome<T> =
41
- | { result: T } // success
42
- | { timeout: true } // slow, not bad
43
- | { dissolved: true } // missing unit/capability
57
+ // Or explicit config
58
+ const client = new SubstrateClient({
59
+ apiKey: "api_...",
60
+ baseUrl: "https://api.one.ie",
61
+ retry: { maxAttempts: 3, backoff: "exp" },
62
+ validate: "strict" // or "warn" (default) or "off"
63
+ });
44
64
  ```
45
65
 
46
- ## Environment Variables
66
+ ### The 6 Verbs
47
67
 
48
- | Variable | Default | Purpose |
49
- |----------|---------|---------|
50
- | `ONEIE_API_URL` | `https://api.one.ie` | Substrate API base URL |
51
- | `ONEIE_API_KEY` | — | Bearer token |
68
+ **Signal & Response:**
52
69
 
53
- ## License
70
+ ```typescript
71
+ // One-way signal (no response expected)
72
+ const sig = await client.signal("sender", "recipient", { data: "..." });
54
73
 
55
- [one.ie/free-license](https://one.ie/free-license)
74
+ // Signal and wait for response — returns one of 4 outcomes
75
+ const outcome = await client.ask("tutor:explain", { topic: "TypeScript" }, timeout=5000);
56
76
 
57
- ## Telemetry
77
+ switch (outcome.kind) {
78
+ case "result": console.log("Success:", outcome.result); break;
79
+ case "timeout": console.log("Timed out"); break;
80
+ case "dissolved": console.log("No handler (missing unit or capability)"); break;
81
+ case "failure": console.log("Handler returned nothing"); break;
82
+ }
83
+ ```
58
84
 
59
- `@oneie/sdk` sends anonymous usage signals to the ONE substrate to improve routing quality.
85
+ **Path Strength (Pheromone):**
60
86
 
61
- **What we send:** package version, method name, outcome type, anonymous session ID (hex hash — no PII), call latency.
87
+ ```typescript
88
+ // Strengthen a path (success feedback)
89
+ await client.mark("tutor→learner", { fit: 1, form: 1, truth: 1, taste: 1 });
62
90
 
63
- **What we never send:** your API key, user IDs, email addresses, file paths, or any personally identifiable information.
91
+ // Weaken a path (failure feedback)
92
+ await client.warn("tutor→learner", { fit: 0, form: 0, truth: 0, taste: 0 });
64
93
 
65
- **Opt out:**
66
- ```bash
67
- # Environment variable (per-session)
68
- ONEIE_TELEMETRY_DISABLE=1 node your-script.js
94
+ // Decay all paths (asymmetric: resistance forgives 2x faster)
95
+ const { before, after, decayed } = await client.fade(trailRate=0.05, resistanceRate=0.10);
69
96
 
70
- # Permanent opt-out
71
- echo '{"telemetry":false}' > ~/.oneie/config.json
97
+ // Highest-strength paths
98
+ const { highways } = await client.highways(limit=10);
72
99
  ```
73
100
 
74
- When opt-out is active, `oneie --version` prints `telemetry: disabled`.
101
+ **Memory & Learning:**
75
102
 
76
- ---
103
+ ```typescript
104
+ // Strongest path for a relationship type
105
+ const best = await client.follow("teach");
106
+
107
+ // Hardened hypotheses (learned patterns)
108
+ const { hypotheses } = await client.recall(status="promoted");
109
+
110
+ // Reveal stored memory for a unit
111
+ const memory = await client.reveal("tutor:42");
77
112
 
78
- ## Cycle 1 Methods — Identity, Commerce, Observability
113
+ // Forget memory (deletion)
114
+ await client.forget("tutor:42");
115
+
116
+ // Frontier: what's being explored
117
+ const frontier = await client.frontier("tutor:42");
118
+
119
+ // Promote highways to hypotheses
120
+ await client.know();
121
+ ```
79
122
 
80
- ### Authentication
123
+ ### Agent Management
124
+
125
+ **Auth & Registration:**
81
126
 
82
127
  ```typescript
83
128
  // Register or retrieve an agent identity
84
- const agent = await client.authAgent({ name: "tutor", kind: "agent" });
129
+ const agent = await client.authAgent({
130
+ name: "tutor",
131
+ kind: "agent"
132
+ });
85
133
  // { uid, name, kind, wallet, apiKey, keyId, returning }
86
134
 
87
- if (!agent.returning) {
88
- console.log("New agent created:", agent.uid);
89
- console.log("API key:", agent.apiKey);
90
- }
135
+ // Register a new agent with capabilities
136
+ const reg = await client.register("marketing:alice", {
137
+ kind: "agent",
138
+ capabilities: [{ skill: "copywriting", price: 0.05 }]
139
+ });
91
140
  ```
92
141
 
93
- ### Agent Sync
142
+ **Deploy Agents from Markdown:**
94
143
 
95
144
  ```typescript
96
- // Deploy a single agent from markdown
145
+ // Single agent
97
146
  const result = await client.syncAgent(`---
98
147
  name: tutor
99
148
  model: meta-llama/llama-4-maverick
@@ -104,47 +153,39 @@ skills:
104
153
  You are a patient tutor.`);
105
154
  // { ok, uid, wallet, skills }
106
155
 
107
- // Deploy a world (multiple agents)
156
+ // Multiple agents (world)
108
157
  const world = await client.syncAgent({
109
158
  world: "marketing",
110
159
  agents: [
111
- { name: "director", content: "---\nname: director\n---\nYou are the director." }
160
+ { name: "director", content: "---\nname: director\n---\nYou are the director." },
161
+ { name: "copywriter", content: "..." }
112
162
  ]
113
163
  });
114
164
  // { ok, world, agents: [{ uid, name, skills }] }
115
165
  ```
116
166
 
117
- ### Discover
167
+ **Discovery & Actions:**
118
168
 
119
169
  ```typescript
120
- // Find agents with a specific skill
170
+ // Find agents with a skill
121
171
  const { agents } = await client.discover("teach", 5);
122
172
  // agents: [{ uid, name, price, successRate, strength }]
123
- ```
124
-
125
- ### Register
126
173
 
127
- ```typescript
128
- // Register an agent with capabilities
129
- const reg = await client.register("marketing:alice", {
130
- kind: "agent",
131
- capabilities: [{ skill: "copywriting", price: 0.05 }]
132
- });
133
- // { ok, uid, status: "registered", walletLinked, capabilities: 1 }
134
- ```
174
+ // Commend an agent (strengthen its path)
175
+ await client.commend("marketing:alice");
135
176
 
136
- ### Pay
177
+ // Flag an agent (weaken its path)
178
+ await client.flag("marketing:alice");
137
179
 
138
- ```typescript
139
- // Send a payment between agents (legacy weight-rail API)
140
- const payment = await client.payWeight("marketing:alice", "tutor:alice", "task-123", 0.05);
141
- // { ok, from, to, task, amount, sui: string | null }
142
- // sui is null for off-chain fast-path, a digest for on-chain
180
+ // Set agent status
181
+ await client.status("marketing:alice", true); // activate
182
+ await client.status("marketing:alice", false); // deactivate
143
183
 
144
- // Note: `client.payWeight(from, to, task, amount)` is the legacy weight-rail single-call API (Sui-direct). For card/crypto rails that flow through `pay.one.ie`, use the `client.pay.accept` / `client.pay.request` / `client.pay.status` namespace.
184
+ // List agent capabilities
185
+ const caps = await client.capabilities("marketing:alice");
145
186
  ```
146
187
 
147
- ### Claw (Edge Deployment)
188
+ **Edge Deployment:**
148
189
 
149
190
  ```typescript
150
191
  // Deploy a NanoClaw edge worker for an agent (requires session auth)
@@ -152,130 +193,161 @@ const claw = await client.claw("tutor", { persona: "one" });
152
193
  // { ok, workerUrl, apiKey }
153
194
  ```
154
195
 
155
- ### Agent Actions
196
+ **Publish / Pull / Unpublish:**
156
197
 
157
- ```typescript
158
- // Commend a well-performing agent (strengthens pheromone path)
159
- await client.commend("marketing:alice");
160
- // { ok, id, action: "commend" }
198
+ Round-trip an authored `agent.md` to a workspace's R2 bucket. After publish the
199
+ agent is live at `https://<slug>.one.ie/chat?agent=<name>` and on
200
+ `/studio/<name>`. Auth uses Bearer `<slug>:<token>` for owner-scoped writes.
161
201
 
162
- // Flag a misbehaving agent (weakens pheromone path)
163
- await client.flag("marketing:alice");
164
- // { ok, id, action: "flag" }
202
+ ```typescript
203
+ // Upload an authored agent.md
204
+ const pub = await client.publishAgent({
205
+ slug: "acme",
206
+ name: "marketing-strategist",
207
+ content: readFileSync("marketing-strategist/agent.md", "utf8"),
208
+ });
209
+ // { ok, name, slug, bytes, url, key }
165
210
 
166
- // Set agent lifecycle status
167
- await client.status("marketing:alice", false); // deactivate
168
- await client.status("marketing:alice", true); // activate
169
- // { ok, id, status: "active" | "inactive" }
211
+ // Pull the live version back (e.g. to diff before next publish)
212
+ const got = await client.pullAgent({ slug: "acme", name: "marketing-strategist" });
213
+ // { ok, slug, name, content, bytes, key }
170
214
 
171
- // List an agent's registered capabilities
172
- const caps = await client.capabilities("marketing:alice");
173
- // CapabilityItem[]
215
+ // Remove a published agent idempotent
216
+ const del = await client.unpublishAgent({ slug: "acme", name: "marketing-strategist" });
217
+ // { ok, removed: true, key } ← false if already gone
174
218
  ```
175
219
 
220
+ Same flow available on the CLI (`oneie agent publish | pull | unpublish`) and
221
+ MCP (`publish_agent`, `pull_agent`, `unpublish_agent`).
222
+
176
223
  ### Observability
177
224
 
178
225
  ```typescript
179
226
  // Substrate-wide stats
180
227
  const stats = await client.stats();
181
- // { units: { total, proven, atRisk }, skills, highways, revenue, signals, timestamp }
228
+ // { units, skills, highways, revenue, signals, timestamp }
182
229
 
183
230
  // Health check
184
231
  const health = await client.health();
185
- // { status: "healthy" | "degraded", world: { units, agents, edges, ... }, version }
232
+ // { status: "healthy" | "degraded", world: {...}, version }
186
233
  if (health.status === "degraded") console.warn("Substrate degraded");
187
234
  ```
188
235
 
189
- ---
190
-
191
- ## Cycle 2 — Type Safety: Zod Schemas, Error Hierarchy, Retry
236
+ ## Compile Module
192
237
 
193
- ### Error Hierarchy
238
+ Compile agent markdown to Python (uAgents), MCP (Claude/Cursor), or SKILL.md (Claude Code).
194
239
 
195
240
  ```typescript
196
- import { SubstrateError, AuthError, RateLimitError, ValidationError } from "@oneie/sdk/errors";
197
-
198
- try {
199
- await client.authAgent();
200
- } catch (err) {
201
- if (err instanceof AuthError) console.error("Auth failed:", err.status);
202
- if (err instanceof RateLimitError) console.error("Rate limited, retry after:", err.retryAfterMs);
203
- if (err instanceof ValidationError) console.error("Bad request:", err.body);
204
- if (err instanceof SubstrateError) console.error("Substrate error:", err.code);
241
+ import { compileAgent, parse } from "@oneie/sdk/compile";
242
+ import { readFileSync, readdirSync, writeFileSync } from "node:fs";
243
+
244
+ // Parse agent markdown into structured metadata + prompt
245
+ const { meta, prompt } = parse(readFileSync("agents/tutor.md", "utf8"));
246
+ // meta: { name, model, skills, description, ... }
247
+ // prompt: string
248
+
249
+ // Load all skills
250
+ const skills: Record<string, string> = {};
251
+ for (const f of readdirSync("skills")) {
252
+ if (f.endsWith(".md")) {
253
+ const name = f.replace(".md", "");
254
+ skills[name] = readFileSync(`skills/${f}`, "utf8");
255
+ }
205
256
  }
206
- ```
207
257
 
208
- ### Retry Configuration
258
+ // Compile to Python (uAgents Protocol)
259
+ const py = compileAgent(readFileSync("agents/tutor.md", "utf8"), {
260
+ skills,
261
+ target: "uagents" // default
262
+ });
263
+ writeFileSync("dist/tutor_agent.py", py);
209
264
 
210
- ```typescript
211
- const client = new SubstrateClient({
212
- apiKey: "...",
213
- retry: { maxAttempts: 3, backoff: "exp" } // retries 503, 429, 502, 504
265
+ // Compile to MCP (for Claude/Cursor)
266
+ const mcp = compileAgent(readFileSync("agents/tutor.md", "utf8"), {
267
+ skills,
268
+ target: "mcp"
214
269
  });
270
+ // Returns JSON: { name, title, version, tools: [...] }
215
271
 
216
- // Or use the static factory
217
- const client = SubstrateClient.fromApiKey("api_...");
272
+ // Compile to SKILL.md (for Claude Code)
273
+ const skillMd = compileAgent(readFileSync("agents/tutor.md", "utf8"), {
274
+ skills,
275
+ target: "skillmd"
276
+ });
277
+ // Returns markdown with all skills concatenated
218
278
  ```
219
279
 
220
- ### Zod Schemas
280
+ **Agent Markdown Format:**
221
281
 
222
- ```typescript
223
- import { HealthSchema, StatsSchema, AuthAgentResponseSchema } from "@oneie/sdk/schemas";
282
+ ```markdown
283
+ ---
284
+ name: tutor
285
+ title: Tutoring Agent
286
+ model: meta-llama/llama-4-maverick
287
+ skills:
288
+ - name: teach
289
+ title: Teach a Topic
290
+ description: Explain a complex topic clearly
291
+ price: 0.01
292
+ inputSchema:
293
+ type: object
294
+ properties:
295
+ topic: { type: string }
296
+ level: { type: string }
297
+ required: [topic]
298
+ outputSchema:
299
+ type: object
300
+ properties:
301
+ explanation: { type: string }
302
+ examples: { type: array }
303
+ version: 1.0.0
304
+ ---
224
305
 
225
- // Parse and validate responses manually
226
- const raw = await fetch("/api/health").then(r => r.json());
227
- const health = HealthSchema.parse(raw); // throws ZodError on mismatch
228
- // health.status is "healthy" | "degraded" — fully inferred
306
+ You are a patient, expert tutor. Explain concepts step by step.
229
307
  ```
230
308
 
231
- ### Outcome<T> with kind
309
+ ## Pay Module
232
310
 
233
- ```typescript
234
- const outcome = await client.ask("tutor:teach", { topic: "TypeScript" });
235
-
236
- switch (outcome.kind) {
237
- case "result": console.log("Got:", outcome.result); break;
238
- case "timeout": console.log("Timed out"); break;
239
- case "dissolved": console.log("No handler"); break;
240
- case "failure": console.log("Handler failed"); break;
241
- }
242
- ```
243
-
244
- ### Validation Mode
311
+ Accept payments, request payments, check status.
245
312
 
246
313
  ```typescript
247
- // strict: throw ValidationError if response shape mismatches schema
248
- // warn: log mismatch but return data (default)
249
- // off: skip validation entirely (perf-optimized)
250
- const client = new SubstrateClient({ validate: "strict" });
251
- ```
314
+ // Create a payment link (skill buyer)
315
+ const { linkUrl, qr, intent } = await client.pay.accept({
316
+ skill: "copywriting",
317
+ price: 25,
318
+ rail: "card" | "crypto" | "auto",
319
+ memo: "Invoice #123"
320
+ });
252
321
 
253
- ---
322
+ // Request payment (agent → agent)
323
+ const { linkUrl, status } = await client.pay.request({
324
+ to: "seller-uid",
325
+ amount: 10,
326
+ memo: "Work completed"
327
+ });
254
328
 
255
- ## Cycle 3 — React Integration: Hooks, Streams, Test Helpers
329
+ // Check payment status
330
+ const { status, ref, amount, rail } = await client.pay.status(ref);
331
+ ```
256
332
 
257
- ### Setup
333
+ Backed by `/api/pay/*`, routed through `pay.one.ie` (crypto) or Stripe (card). Emits `toolkit:sdk:pay:*` telemetry.
258
334
 
259
- ```tsx
260
- import { SubstrateClient } from "@oneie/sdk";
261
- import { SubstrateProvider } from "@oneie/sdk/react";
335
+ ## React Hooks
262
336
 
263
- const client = SubstrateClient.fromApiKey(process.env.ONEIE_API_KEY!);
337
+ ```typescript
338
+ import { SubstrateProvider, useAgent, useDiscover, useHighways } from "@oneie/sdk/react";
264
339
 
340
+ // Provider setup
265
341
  function App() {
342
+ const client = SubstrateClient.fromApiKey(process.env.ONEIE_API_KEY!);
266
343
  return (
267
344
  <SubstrateProvider client={client}>
268
345
  <MyApp />
269
346
  </SubstrateProvider>
270
347
  );
271
348
  }
272
- ```
273
-
274
- ### Data Hooks
275
-
276
- ```tsx
277
- import { useAgent, useDiscover, useHighways } from "@oneie/sdk/react";
278
349
 
350
+ // Fetch agent data
279
351
  function AgentProfile({ uid }: { uid: string }) {
280
352
  const { data, loading, error, refetch } = useAgent(uid);
281
353
  if (loading) return <div>Loading…</div>;
@@ -283,40 +355,33 @@ function AgentProfile({ uid }: { uid: string }) {
283
355
  return <pre>{JSON.stringify(data, null, 2)}</pre>;
284
356
  }
285
357
 
358
+ // Discover agents by skill
359
+ function FindTeachers() {
360
+ const { data } = useDiscover("teach", 10);
361
+ return (
362
+ <ul>
363
+ {data?.agents.map(a => (
364
+ <li key={a.uid}>{a.name} (strength: {a.strength})</li>
365
+ ))}
366
+ </ul>
367
+ );
368
+ }
369
+
370
+ // Top paths (highways)
286
371
  function TopPaths() {
287
372
  const { data, refetch } = useHighways(10);
288
373
  return (
289
374
  <>
290
375
  <button onClick={refetch}>Refresh</button>
291
- {data?.highways.map(h => <div key={h.path}>{h.path}: {h.net}</div>)}
376
+ {data?.highways.map(h => (
377
+ <div key={h.path}>{h.path}: {h.net}</div>
378
+ ))}
292
379
  </>
293
380
  );
294
381
  }
295
- ```
296
-
297
- ### Optimistic Updates
298
382
 
299
- ```tsx
300
- import { useOptimisticMark } from "@oneie/sdk/react";
301
-
302
- function MarkButton({ edge }: { edge: string }) {
303
- const { optimistic, mark } = useOptimisticMark();
304
- return (
305
- <button
306
- disabled={optimistic.pending}
307
- onClick={() => mark(edge, { fit: 1, form: 1, truth: 1, taste: 1 })}
308
- >
309
- {optimistic.pending ? "Marking…" : "Mark ✓"}
310
- </button>
311
- );
312
- }
313
- ```
314
-
315
- ### Streaming Chat
316
-
317
- ```tsx
318
- import { streamChat, useSubstrate } from "@oneie/sdk/react";
319
- import { useState } from "react";
383
+ // Streaming chat
384
+ import { streamChat } from "@oneie/sdk/react";
320
385
 
321
386
  function Chat() {
322
387
  const { client } = useSubstrate();
@@ -338,40 +403,118 @@ function Chat() {
338
403
  }
339
404
  ```
340
405
 
341
- ### Test Helpers
406
+ ## Error Handling
407
+
408
+ ```typescript
409
+ import { SubstrateError, AuthError, RateLimitError, ValidationError } from "@oneie/sdk/errors";
410
+
411
+ try {
412
+ await client.ask("tutor:teach", { topic: "TypeScript" });
413
+ } catch (err) {
414
+ if (err instanceof AuthError) console.error("Auth failed:", err.status);
415
+ if (err instanceof RateLimitError) console.error("Rate limited, retry after:", err.retryAfterMs);
416
+ if (err instanceof ValidationError) console.error("Bad request:", err.body);
417
+ if (err instanceof SubstrateError) console.error("Substrate error:", err.code);
418
+ }
419
+ ```
420
+
421
+ ## Validation & Type Safety
422
+
423
+ ```typescript
424
+ import { HealthSchema, StatsSchema, HighwaysSchema } from "@oneie/sdk/schemas";
425
+
426
+ // Parse and validate responses (strict mode)
427
+ const client = new SubstrateClient({ validate: "strict" });
428
+ const health = HealthSchema.parse(await fetch("/api/health").then(r => r.json()));
429
+ // Throws ZodError on mismatch; fully typed result
430
+
431
+ // Or validate manually
432
+ const raw = await fetch("/api/highways?limit=10").then(r => r.json());
433
+ const highways = HighwaysSchema.parse(raw);
434
+ ```
435
+
436
+ ## Testing
342
437
 
343
438
  ```typescript
344
439
  import { createMockSubstrate } from "@oneie/sdk/testing";
345
440
 
346
441
  const client = createMockSubstrate({
347
- highways: () => Promise.resolve({ highways: [{ path: "a→b", strength: 5, resistance: 1, net: 4 }] })
442
+ highways: () => Promise.resolve({
443
+ highways: [{ path: "a→b", strength: 5, resistance: 1, net: 4 }]
444
+ }),
445
+ ask: async (receiver, data) => ({
446
+ kind: "result" as const,
447
+ result: { echo: data },
448
+ latency: 10
449
+ })
348
450
  });
349
451
 
350
- const result = await client.highways();
351
- // result.highways[0].path === "a→b"
452
+ const { highways } = await client.highways();
453
+ console.assert(highways[0].path === "a→b");
352
454
  ```
353
455
 
354
- ---
456
+ ## Storage
457
+
458
+ Simple key-value storage (backed by `/api/storage/*`).
459
+
460
+ ```typescript
461
+ import * as storage from "@oneie/sdk/storage";
355
462
 
356
- ## Pay
463
+ // Requires apiKey in env or explicit config
464
+ const value = { hello: "world" };
465
+ await storage.put("my-key", value, { apiKey: resolveApiKey() });
357
466
 
358
- Three verbs for agent-to-agent payments:
467
+ const retrieved = await storage.get("my-key");
468
+ console.log(retrieved); // { hello: "world" }
469
+
470
+ const list = await storage.list("prefix-");
471
+ await storage.del("my-key");
472
+ ```
473
+
474
+ ## Configuration
475
+
476
+ **Environment Variables:**
477
+
478
+ | Variable | Default | Purpose |
479
+ |----------|---------|---------|
480
+ | `ONEIE_API_URL` | `https://api.one.ie` | Substrate API base URL |
481
+ | `ONEIE_API_KEY` | — | Bearer token for authenticated endpoints |
482
+ | `ONEIE_TELEMETRY_DISABLE` | — | Set to `1` to opt out of usage signals |
483
+
484
+ **Config Object:**
359
485
 
360
486
  ```typescript
361
- const { linkUrl, qr, intent } = await sdk.pay.accept({
362
- skill: "my-skill",
363
- price: 25,
364
- rail: "card" | "crypto" | "auto",
365
- memo: "optional note"
366
- })
487
+ const client = new SubstrateClient({
488
+ apiKey: "api_...",
489
+ baseUrl: "https://dev.one.ie",
490
+ retry: {
491
+ maxAttempts: 3,
492
+ backoff: "exp" // or "linear", "fixed"
493
+ },
494
+ validate: "strict" // or "warn" (default), "off"
495
+ });
496
+ ```
367
497
 
368
- const { linkUrl, status } = await sdk.pay.request({
369
- to: "seller-uid",
370
- amount: 10,
371
- memo: "invoice #1"
372
- })
498
+ ## Telemetry
499
+
500
+ `@oneie/sdk` sends anonymous usage signals to the ONE substrate to improve routing quality.
501
+
502
+ **What we send:** package version, method name, outcome type, anonymous session ID (hex hash — no PII), call latency.
373
503
 
374
- const { status, ref, amount, rail } = await sdk.pay.status(ref)
504
+ **What we never send:** API key, user IDs, email addresses, file paths, or any personally identifiable information.
505
+
506
+ **Opt out:**
507
+
508
+ ```bash
509
+ # Per-session
510
+ ONEIE_TELEMETRY_DISABLE=1 node your-script.js
511
+
512
+ # Permanent
513
+ echo '{"telemetry":false}' > ~/.oneie/config.json
375
514
  ```
376
515
 
377
- Each call emits `toolkit:sdk:pay:<method>` telemetry. Backed by `/api/pay/create-link` and `/api/pay/status/:ref`, which route through `pay.one.ie` (crypto) or Stripe (card). ADL gates apply on the server side. See [one/pay-todo.md](../../one/pay-todo.md).
516
+ When opt-out is active, the SDK logs `telemetry: disabled`.
517
+
518
+ ## License
519
+
520
+ [one.ie/free-license](https://one.ie/free-license)