@puku-ai/sdk 4.0.5 → 4.0.6
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 +151 -19
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -77,7 +77,6 @@ returns a model-not-found error.
|
|
|
77
77
|
|---------------|----------|-------|
|
|
78
78
|
| `puku-ai-2.7` | Puku AI | Cheaper, lower-latency. |
|
|
79
79
|
| `puku-ai-2.8` | Puku AI | Default for most workloads. |
|
|
80
|
-
| `opus-4.8` | Opus | Strongest reasoning; pick this for fallbacks (`fallbacks: [{ model: "opus-4.8" }]`). |
|
|
81
80
|
|
|
82
81
|
|
|
83
82
|
## Usage
|
|
@@ -168,25 +167,155 @@ Every feature below was exercised against the live Puku gateway at
|
|
|
168
167
|
| `stream.finalMessage()` | ✅ works | `MessageStream` |
|
|
169
168
|
| `stream.on("text", cb)` listener | ✅ works | `MessageStream` |
|
|
170
169
|
| `client.beta.messages.toolRunner(...).runUntilDone()` | ✅ works | `client.beta.messages` |
|
|
170
|
+
| `client.messages.countTokens` | ✅ works | `count-tokens.ts` |
|
|
171
|
+
| `client.messages.batches.create / retrieve / results` | ✅ works | `batch-results.ts` (D1-backed storage) |
|
|
172
|
+
| Server-side `web_search` (both streaming + non-streaming variants) | ✅ works | `web-search.ts`, `web-search-stream.ts` (gateway forwards `tool_use` to puku-research-gateway and maps back to `web_search_tool_result`) |
|
|
173
|
+
| Structured outputs (`output_config.format`) — zod / json-schema / raw / standard-schema | ✅ works (non-streaming; raw occasionally flaky) | `structured-outputs-*.ts` |
|
|
171
174
|
| `ToolError` class (exceptions from the runner) | ✅ works | `helpers/beta` |
|
|
172
175
|
| MCP helpers (`mcpTool`, `mcpTools`, `mcpMessage`, `mcpMessages`, `mcpResourceToContent`, `mcpResourceToFile`) | ✅ exported | `helpers/beta/mcp` |
|
|
173
176
|
| Agent toolset (`betaAgentToolset20260401`, `betaBashTool`, `betaReadTool`, `betaWriteTool`, `betaEditTool`, `betaGlobTool`, `betaGrepTool`) | ✅ exported | `tools/agent-toolset` |
|
|
174
177
|
| Full error hierarchy (`APIError`, `RateLimitError`, `AuthenticationError`, …) | ✅ works | static on `PukuAI` |
|
|
175
178
|
|
|
176
|
-
### Known gateway gaps
|
|
179
|
+
### Known gateway gaps
|
|
177
180
|
|
|
178
181
|
| Feature | Status | Note |
|
|
179
182
|
|--------------------------------------|--------|------|
|
|
180
|
-
| `
|
|
181
|
-
| `
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
183
|
+
| Structured-outputs JSON parser (`output_config.format`) — streaming variant | ⚠ flaky | Passes most runs but `puku-ai-2.8` / `puku-ai-2.7` occasionally emit a duplicate JSON key in the payload which the SDK's Zod parser rejects. Re-running usually passes — not a regression, just model-output variance. |
|
|
184
|
+
| Structured-outputs JSON parser (`output_config.format`) — `raw` variant | ⚠ flaky | Same root cause: `puku-ai-2.8` occasionally emits non-JSON prose (e.g. `I computed …`) or a malformed JSON payload (e.g. an unterminated string) inside the synthetic tool call, which the SDK's `JSON.parse` rejects. Re-running usually passes — not a regression, just model-output variance. |
|
|
185
|
+
|
|
186
|
+
### Beta managed-agents surface (preview)
|
|
187
|
+
|
|
188
|
+
The Puku gateway serves Anthropic-shaped responses for the beta managed-agents
|
|
189
|
+
namespace so SDK code that calls them does not 404. These exist so SDK
|
|
190
|
+
examples round-trip against the live gateway while the full managed-agents
|
|
191
|
+
runtime track is reopened — they are **not a production control plane**.
|
|
192
|
+
|
|
193
|
+
| Surface | Status | What you can do with it |
|
|
194
|
+
|--------------------------------------|--------|-------------------------|
|
|
195
|
+
| `client.beta.sessions.*` | ✅ works | Run a managed-agent loop — create session, post `events.send`, stream `events.stream`. The gateway drives the LLM turn and emits the same Anthropic-shaped SSE events the SDK's `SessionToolRunner` consumes. |
|
|
196
|
+
| `client.beta.agents.*` | ⚠ limited | CRUD round-trip. `agents.create` returns a populated `BetaAgent` shape but no remote agent execution. |
|
|
197
|
+
| `client.beta.environments.*` | ⚠ limited | `POST /environments` returns `{id, status:'ready'}` synchronously — no `creating → ready` polling. |
|
|
198
|
+
| `client.beta.environments.*.work.{poll,ack,heartbeat,stop,retrieve,update}` | ⚠ limited | The work queue round-trips so `WorkPoller`/`EnvironmentWorker` terminate. One synthetic work item per session. |
|
|
199
|
+
| `client.beta.vaults.*` | ⚠ limited | CRUD + `credentials.create`. Secret tokens are dropped — `vault_ids` passed to `sessions.create` are ignored (sessions don't need credentials in puku). |
|
|
200
|
+
| `client.beta.skills.{create,list,retrieve,delete}` | ⚠ limited | Multipart upload + metadata only. Accepts `files` and `files[]` field names. |
|
|
201
|
+
| `client.beta.skills.versions.{create,list,retrieve,delete}` | ⚠ limited | Multipart upload + metadata only. Idempotent on `(skill_id, version)` — 409 on duplicate. |
|
|
202
|
+
| `client.beta.skills.versions.download` | ⚠ limited | Returns a 22-byte empty-zip body so `response.blob()` decodes a real `Blob`. Real archive bytes are not stored. |
|
|
203
|
+
| `client.files.{upload,list,retrieve,download,delete}` (non-beta `/v1/files`) | ⚠ limited | Bytes held in-memory only — not persisted anywhere durable. |
|
|
204
|
+
|
|
205
|
+
#### Working example: managed-agent session with `toolRunner`
|
|
206
|
+
|
|
207
|
+
This is the loop `client.beta.sessions.*` actually drives for you. You create
|
|
208
|
+
a session, post a user message, open the event stream, and the SDK's
|
|
209
|
+
`toolRunner` dispatches any `agent.tool_use` events back through
|
|
210
|
+
`events.send` automatically.
|
|
211
|
+
|
|
212
|
+
```ts
|
|
213
|
+
import PukuAI from "@puku-ai/sdk";
|
|
214
|
+
|
|
215
|
+
const client = new PukuAI();
|
|
216
|
+
|
|
217
|
+
// 1. Create an environment + an agent + a session.
|
|
218
|
+
const env = await client.beta.environments.create({ name: "demo" });
|
|
219
|
+
const agent = await client.beta.agents.create({
|
|
220
|
+
name: "weather-bot",
|
|
221
|
+
model: "puku-ai-2.8",
|
|
222
|
+
environment: { type: "cloud", id: env.id },
|
|
223
|
+
tools: [
|
|
224
|
+
// Tools the gateway's tool registry will resolve at agent-turn time.
|
|
225
|
+
{ type: "agent_toolset_20260401" },
|
|
226
|
+
],
|
|
227
|
+
});
|
|
228
|
+
const session = await client.beta.sessions.create({
|
|
229
|
+
agent_id: agent.id,
|
|
230
|
+
environment_id: env.id,
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
// 2. Define a runnable tool the gateway will round-trip.
|
|
234
|
+
const getWeather = {
|
|
235
|
+
name: "get_weather",
|
|
236
|
+
description: "Return the current temperature for a city.",
|
|
237
|
+
input_schema: {
|
|
238
|
+
type: "object",
|
|
239
|
+
properties: { city: { type: "string" } },
|
|
240
|
+
required: ["city"],
|
|
241
|
+
},
|
|
242
|
+
run: async (input: { city: string }) =>
|
|
243
|
+
JSON.stringify({ temp_c: 22.4, city: input.city }),
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
// 3. Post a user message and stream the agent turn.
|
|
247
|
+
await client.beta.sessions.events.send(session.id, {
|
|
248
|
+
type: "user.message",
|
|
249
|
+
content: [{ type: "text", text: "What's the weather in Tokyo?" }],
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
for await (const event of client.beta.sessions.events.stream(session.id)) {
|
|
253
|
+
// `agent.message` is the final assistant turn; everything before it
|
|
254
|
+
// is either tool_use / tool_result round-trips or status transitions.
|
|
255
|
+
if (event.type === "agent.message") {
|
|
256
|
+
console.log("agent:", event.content);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// 4. Clean up.
|
|
261
|
+
await client.beta.sessions.delete(session.id);
|
|
262
|
+
await client.beta.agents.delete(agent.id);
|
|
263
|
+
await client.beta.environments.delete(env.id);
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
#### Working example: skill upload + version
|
|
267
|
+
|
|
268
|
+
The skills router accepts multipart upload and round-trips a single version
|
|
269
|
+
per skill. Real archive bytes are not stored — `versions.download` returns a
|
|
270
|
+
22-byte empty zip so `response.blob()` succeeds.
|
|
271
|
+
|
|
272
|
+
```ts
|
|
273
|
+
import PukuAI from "@puku-ai/sdk";
|
|
274
|
+
|
|
275
|
+
const client = new PukuAI();
|
|
276
|
+
|
|
277
|
+
// Upload a skill.
|
|
278
|
+
const skill = await client.skills.create({
|
|
279
|
+
display_name: "my-skill",
|
|
280
|
+
files: [new File(["# SKILL"], "SKILL.md", { type: "text/markdown" })],
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
// Add a version (auto-generated timestamp, or pass one explicitly).
|
|
284
|
+
const v1 = await client.beta.skills.versions.create(skill.id, {
|
|
285
|
+
files: [new File(["# v1"], "SKILL.md", { type: "text/markdown" })],
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
// List versions, retrieve one, download (returns an empty zip blob).
|
|
289
|
+
const page = await client.beta.skills.versions.list(skill.id);
|
|
290
|
+
const fetched = await client.beta.skills.versions.retrieve(skill.id, v1.version);
|
|
291
|
+
const blob = await client.beta.skills.versions.download(skill.id, v1.version);
|
|
292
|
+
console.log(page.data.length, fetched.version, blob.size); // 1, "20260101T000000Z", 22
|
|
293
|
+
|
|
294
|
+
// Cleanup — delete cascades to all versions.
|
|
295
|
+
await client.beta.skills.delete(skill.id);
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
#### Working example: file upload + download (non-beta `/v1/files`)
|
|
299
|
+
|
|
300
|
+
`client.files.*` is the non-beta Anthropic Files API stub. Bytes are held in
|
|
301
|
+
memory and not persisted anywhere durable.
|
|
302
|
+
|
|
303
|
+
```ts
|
|
304
|
+
import PukuAI from "@puku-ai/sdk";
|
|
305
|
+
|
|
306
|
+
const client = new PukuAI();
|
|
307
|
+
|
|
308
|
+
const file = await client.files.upload({
|
|
309
|
+
file: new File(["hello"], "hello.txt", { type: "text/plain" }),
|
|
310
|
+
});
|
|
311
|
+
console.log(file.id, file.filename, file.size_bytes); // file_xxx, "hello.txt", 5
|
|
312
|
+
|
|
313
|
+
const list = await client.files.list();
|
|
314
|
+
const blob = await client.files.download(file.id);
|
|
315
|
+
console.log(await blob.text()); // "hello"
|
|
316
|
+
|
|
317
|
+
await client.files.delete(file.id);
|
|
318
|
+
```
|
|
190
319
|
|
|
191
320
|
|
|
192
321
|
|
|
@@ -263,7 +392,7 @@ import PukuAI, { mcpTools, mcpMessage, mcpMessages, mcpResourceToFile } from "@p
|
|
|
263
392
|
const client = new PukuAI();
|
|
264
393
|
|
|
265
394
|
// `mcpTools` converts an MCP client from @modelcontextprotocol/sdk into
|
|
266
|
-
|
|
395
|
+
|
|
267
396
|
|
|
268
397
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
269
398
|
import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
|
|
@@ -318,12 +447,15 @@ import { betaReadTool, betaBashTool } from "@puku-ai/sdk";
|
|
|
318
447
|
const tools = [betaReadTool({ workdir: "/tmp/sandbox" })];
|
|
319
448
|
```
|
|
320
449
|
|
|
321
|
-
> `setupSkills`, `resolveSkillVersion`, and `extractSkillArchive`
|
|
322
|
-
> `/v1/skills/{id}/versions/{version}`
|
|
323
|
-
>
|
|
324
|
-
>
|
|
325
|
-
>
|
|
326
|
-
>
|
|
450
|
+
> `setupSkills`, `resolveSkillVersion`, and `extractSkillArchive` round-trip
|
|
451
|
+
> against `/v1/skills/{id}/versions/{version}` + `/v1/sessions/{id}`. The
|
|
452
|
+
> gateway now serves those endpoints (multipart upload + metadata in-memory,
|
|
453
|
+
> download returns a 22-byte empty zip), so the helpers no longer 404 —
|
|
454
|
+
> but `extractSkillArchive` will receive an empty zip body and cannot
|
|
455
|
+
> extract real archive contents. The pure archive-validation helpers
|
|
456
|
+
> (`assertSafeMemberNames`, `assertNoSpecialMembers`, `runArchiveTool`,
|
|
457
|
+
> `archiveTopDir`, `readHead`) stay available — they don't touch the
|
|
458
|
+
> gateway.
|
|
327
459
|
|
|
328
460
|
## Namespace
|
|
329
461
|
|