@jettson/sdk 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jettson
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,249 @@
1
+ # Jettson SDK for Node.js
2
+
3
+ Build AI agents in 3 lines of code.
4
+
5
+ ```bash
6
+ npm install @jettson/sdk
7
+ ```
8
+
9
+ ```ts
10
+ import { Jettson } from "@jettson/sdk";
11
+
12
+ const jettson = new Jettson({ apiKey: process.env.JETTSON_API_KEY! });
13
+
14
+ const agent = await jettson.agents.spawn({
15
+ task: "Research linear.app and tell me what they do.",
16
+ });
17
+ const result = await jettson.agents.wait(agent.agent_id);
18
+
19
+ console.log(result.final_result);
20
+ ```
21
+
22
+ That's it. No vector database, no container orchestration, no agent loop you have to maintain.
23
+
24
+ ---
25
+
26
+ ## Installation
27
+
28
+ Requires Node.js 18 or newer.
29
+
30
+ ```bash
31
+ npm install @jettson/sdk
32
+ # or
33
+ pnpm add @jettson/sdk
34
+ # or
35
+ yarn add @jettson/sdk
36
+ ```
37
+
38
+ The SDK has zero runtime dependencies — it uses native `fetch`.
39
+
40
+ ## Quickstart
41
+
42
+ Get an API key at [jettson.dev/console/api-keys](https://jettson.dev/console/api-keys), then:
43
+
44
+ ```ts
45
+ import { Jettson } from "@jettson/sdk";
46
+
47
+ const jettson = new Jettson({ apiKey: process.env.JETTSON_API_KEY! });
48
+
49
+ const agent = await jettson.agents.spawn({
50
+ task: "Browse https://news.ycombinator.com and return the top story title.",
51
+ });
52
+
53
+ // `wait` polls until completion with gentle exponential backoff.
54
+ const result = await jettson.agents.wait(agent.agent_id);
55
+
56
+ console.log(result.status); // "completed"
57
+ console.log(result.final_result); // The agent's answer
58
+ ```
59
+
60
+ ## Authentication
61
+
62
+ ```ts
63
+ new Jettson({
64
+ apiKey: "jett_sk_live_…",
65
+ baseUrl: "https://jettson.dev/api/v1", // optional — this is the default
66
+ maxRetries: 3, // optional — retries on 429/5xx
67
+ });
68
+ ```
69
+
70
+ The API key is bearer-auth'd on every request. Store it in `process.env.JETTSON_API_KEY` (or your platform's secret store), never commit it.
71
+
72
+ ## Examples
73
+
74
+ ### Spawn → wait → use the result
75
+
76
+ ```ts
77
+ const agent = await jettson.agents.spawn({
78
+ task: "Summarize the latest version of the OpenTelemetry spec in 3 bullets.",
79
+ });
80
+ const final = await jettson.agents.wait(agent.agent_id, {
81
+ timeoutMs: 5 * 60 * 1000, // 5 minutes
82
+ pollIntervalMs: 1000, // initial 1s, backs off to 5s
83
+ });
84
+ console.log(final.final_result);
85
+ ```
86
+
87
+ ### Spawn in a specific region
88
+
89
+ Multi-region warm pool is live in `iad` (US East), `lhr` (Europe), and `syd` (Asia Pacific):
90
+
91
+ ```ts
92
+ const agent = await jettson.agents.spawn({
93
+ task: "…",
94
+ region: "lhr", // or pass `metadata: { region: "lhr" }`
95
+ });
96
+ ```
97
+
98
+ If you don't specify a region the server picks `iad`. The pool's hit rate per region is on the [Console overview](https://jettson.dev/console).
99
+
100
+ ### Cancel a running agent
101
+
102
+ ```ts
103
+ await jettson.agents.cancel(agent.agent_id);
104
+ ```
105
+
106
+ Idempotent — already-terminal agents return 200 unchanged.
107
+
108
+ ### Memory: write, search, recall
109
+
110
+ Memory is user-scoped — every agent you spawn under the same account shares the same pool.
111
+
112
+ ```ts
113
+ await jettson.memory.put({
114
+ key: "brand_color",
115
+ value: "Brand primary color is #FF5733",
116
+ namespace: "user_profile",
117
+ importance: 8,
118
+ tags: ["brand"],
119
+ });
120
+
121
+ const results = await jettson.memory.search({
122
+ query: "what color is the brand?",
123
+ namespace: "user_profile",
124
+ mode: "hybrid", // 'hybrid' | 'semantic' | 'keyword'
125
+ });
126
+
127
+ for (const r of results) {
128
+ console.log(`${r.key}: ${r.value} (score=${r.score.toFixed(2)})`);
129
+ }
130
+ ```
131
+
132
+ ### Idempotent spawn (defensive retries)
133
+
134
+ If your code might retry a spawn because of a network blip on the way to Jettson, pass an idempotency key. The same key inside a short window returns the same agent instead of creating a duplicate.
135
+
136
+ ```ts
137
+ const requestId = `spawn:${userId}:${Date.now()}`;
138
+ await jettson.agents.spawn({
139
+ task: "…",
140
+ idempotencyKey: requestId,
141
+ });
142
+ ```
143
+
144
+ ### List + paginate
145
+
146
+ ```ts
147
+ let cursor: string | undefined;
148
+ do {
149
+ const page = await jettson.agents.list({ limit: 50, cursor });
150
+ for (const a of page.data) {
151
+ console.log(a.agent_id, a.status);
152
+ }
153
+ cursor = page.next_cursor ?? undefined;
154
+ } while (cursor);
155
+ ```
156
+
157
+ ## API Reference
158
+
159
+ ### `new Jettson(options)`
160
+
161
+ | Field | Type | Description |
162
+ | --- | --- | --- |
163
+ | `apiKey` **(required)** | `string` | Your Jettson API key. |
164
+ | `baseUrl` | `string` | Defaults to `https://jettson.dev/api/v1`. |
165
+ | `maxRetries` | `number` | Retries on 429 / 5xx (default 3). |
166
+
167
+ ### `jettson.agents`
168
+
169
+ | Method | Description |
170
+ | --- | --- |
171
+ | `spawn(input)` | POST `/agents`. Returns immediately with `status: "spawning"`. |
172
+ | `get(agentId)` | GET `/agents/{id}`. |
173
+ | `list(options?)` | Paginated `{ data, next_cursor }`. |
174
+ | `cancel(agentId)` | DELETE `/agents/{id}`. Idempotent. |
175
+ | `wait(agentId, options?)` | Poll until `completed` / `error` / `stopped`. Throws `AgentTimeoutError` on timeout. |
176
+
177
+ ### `jettson.memory`
178
+
179
+ | Method | Description |
180
+ | --- | --- |
181
+ | `put(input)` | Create or version-update a memory. |
182
+ | `get(key, options?)` | Returns the memory or `null` if not found. |
183
+ | `delete(key, options?)` | Soft delete (pass `hardDelete: true` for permanent). |
184
+ | `search(input)` | Hybrid semantic + keyword search. |
185
+ | `list(options?)` | Newest-first, no ranking. |
186
+ | `dedupe(options?)` | Soft-delete near-duplicates. |
187
+ | `consolidate(options?)` | Cluster + summarize related memories. |
188
+ | `namespaces()` | Per-namespace live-counts. |
189
+ | `export()` | Dump every live memory. |
190
+ | `import(memories)` | Bulk insert (round-trips with `export()`). |
191
+
192
+ ## Error handling
193
+
194
+ Every HTTP failure surfaces as a typed error. All extend `JettsonError`.
195
+
196
+ ```ts
197
+ import {
198
+ JettsonAuthError,
199
+ JettsonRateLimitError,
200
+ JettsonQuotaExceededError,
201
+ JettsonValidationError,
202
+ JettsonNotFoundError,
203
+ JettsonServerError,
204
+ JettsonNetworkError,
205
+ AgentTimeoutError,
206
+ } from "@jettson/sdk";
207
+
208
+ try {
209
+ await jettson.agents.spawn({ task: "…" });
210
+ } catch (err) {
211
+ if (err instanceof JettsonRateLimitError) {
212
+ console.log(`Backing off ${err.retryAfterSeconds}s`);
213
+ } else if (err instanceof JettsonQuotaExceededError) {
214
+ console.log(`Hit quota: ${err.used}/${err.limit} on plan ${err.plan}`);
215
+ } else if (err instanceof JettsonAuthError) {
216
+ console.log("Bad API key.");
217
+ } else {
218
+ throw err;
219
+ }
220
+ }
221
+ ```
222
+
223
+ `memory.get()` is the one exception: instead of throwing on 404, it returns `null` (so the "lookup or fallback" pattern stays clean).
224
+
225
+ ## Retries and rate limits
226
+
227
+ The HTTP client retries automatically:
228
+
229
+ - **429** — waits the duration in `Retry-After`, then retries (up to `maxRetries`, default 3)
230
+ - **5xx** — exponential backoff (1s → 2s → 4s), up to `maxRetries`
231
+ - **Network failure** — one retry after the initial backoff window
232
+
233
+ Disable retries with `new Jettson({ apiKey, maxRetries: 0 })` if you need first-failure semantics.
234
+
235
+ ## Development
236
+
237
+ ```bash
238
+ git clone https://github.com/jettsondev/jettson-sdk-node
239
+ cd jettson-sdk-node
240
+ npm install
241
+ npm run build
242
+ npm test
243
+ ```
244
+
245
+ The SDK is intentionally small (~1k LOC + tests). Read the source.
246
+
247
+ ## License
248
+
249
+ MIT — see [LICENSE](./LICENSE).