@1kbirds/chidori 3.5.1 → 3.7.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/README.md CHANGED
@@ -36,14 +36,42 @@ npm run build
36
36
  ### Authoring agents and tools
37
37
 
38
38
  Agent and tool files run *inside* the Chidori runtime, not as a normal Node
39
- program. They get their authoring typesand the `chidori`/`run` globals from
40
- the **virtual** module `chidori:agent`:
39
+ program. They import their authoring surface — the `chidori` host object, the
40
+ `run` definer, and every authoring type — from the **virtual** module
41
+ `chidori:agent`:
41
42
 
42
43
  ```ts
43
44
  /// <reference types="@1kbirds/chidori/agent-env" />
44
- import type { Chidori, ToolDefinition } from "chidori:agent";
45
+ import { chidori, run } from "chidori:agent";
46
+
47
+ run(async (input: { document: string }) => {
48
+ const summary = await chidori.prompt("Summarize:\n" + input.document);
49
+ return { summary };
50
+ });
45
51
  ```
46
52
 
53
+ (Tool files import `type { ToolDefinition }` from the same module. The legacy
54
+ agent form — `export async function agent(input, chidori)` — is still accepted.)
55
+
56
+ > **Typing the input: use a `type` alias, not an `interface`.** The handler's
57
+ > input parameter is constrained to `AgentJson` (JSON-compatible data), and a
58
+ > TypeScript `interface` has no implicit index signature, so
59
+ > `run(async (input: MyInterface) => …)` fails the constraint with a
60
+ > confusing `Type 'AgentJson' is not assignable` error. A structurally
61
+ > identical `type MyInput = { … }` (or an inline object type, as above)
62
+ > satisfies it.
63
+ >
64
+ > **Version note:** install the SDK version matching your `chidori` binary —
65
+ > the published types must agree with the runtime (e.g. `LlmResponseJson`
66
+ > uses `toolCalls`, camelCase, since 3.6.x runtimes).
67
+
68
+ So there are exactly **two** specifiers, with different jobs:
69
+
70
+ | Specifier | What it is | Where it's used |
71
+ |---|---|---|
72
+ | `chidori:agent` | Virtual module the runtime injects | Inside agent/tool files |
73
+ | `@1kbirds/chidori` | This npm package (HTTP client + the ambient types for `chidori:agent`) | In your Node/browser app |
74
+
47
75
  There is no installable package behind `chidori:agent`; it is a URL-style scheme
48
76
  (like `node:fs`) that the runtime strips and injects at execution time, so the
49
77
  unrelated `chidori` npm package can never be pulled in by mistake. The
@@ -58,6 +86,11 @@ import { AgentClient, Checkpoint, isSignalQueued } from "@1kbirds/chidori";
58
86
 
59
87
  const client = new AgentClient("http://localhost:8080");
60
88
 
89
+ // Against a production server (CHIDORI_API_KEY set — see docs/deployment.md),
90
+ // pass the bearer token; it is sent on every request, including stream():
91
+ // new AgentClient("https://agents.example.com", { apiKey: process.env.CHIDORI_API_KEY });
92
+ // `headers: {...}` merges extra headers for proxies / custom auth schemes.
93
+
61
94
  // Run an agent
62
95
  const session = await client.run({ document: "Rust is a systems language." });
63
96
  console.log(session.output);
@@ -109,6 +142,48 @@ if (isSignalQueued(result)) {
109
142
 
110
143
  See the top-level `sdk/python/chidori` for the Python equivalent.
111
144
 
145
+ ## Timeouts, retries, and errors
146
+
147
+ `apiKey` sends `Authorization: Bearer <apiKey>` on every request — required
148
+ against a server started with `CHIDORI_API_KEY` (any non-loopback bind). An
149
+ explicit `headers.Authorization` entry overrides it.
150
+
151
+ Every request is bounded by `timeoutMs` (default 300 000 — generous because
152
+ `run()` executes the whole agent before responding; pass `0` to disable).
153
+ Idempotent GETs are retried `retries` times (default 2, exponential backoff
154
+ from `retryDelayMs`) on connection errors, timeouts, and 429/502/503/504
155
+ responses. POSTs are **never** retried — `run`/`resume`/`signal` are not
156
+ idempotent. For `stream()` the timeout covers connection establishment only,
157
+ never the open event stream.
158
+
159
+ ```ts
160
+ const client = new AgentClient("http://localhost:8080", { timeoutMs: 60_000, retries: 3 });
161
+ ```
162
+
163
+ Failures throw typed errors, all extending `AgentClientError`:
164
+
165
+ ```ts
166
+ import { AgentClientError, ConnectionError, HttpError, TimeoutError } from "@1kbirds/chidori";
167
+
168
+ try {
169
+ await client.signal(sessionId, { name: "review", payload: { decision: "approve" } });
170
+ } catch (err) {
171
+ if (err instanceof HttpError) {
172
+ // err.status distinguishes the documented semantics:
173
+ // 400 empty name, 404 unknown session, 409 terminal run
174
+ if (err.status === 409) console.log("run already finished:", err.detail);
175
+ } else if (err instanceof TimeoutError) {
176
+ // server hung past timeoutMs
177
+ } else if (err instanceof ConnectionError) {
178
+ // nothing listening / connection refused
179
+ }
180
+ }
181
+ ```
182
+
183
+ `HttpError` carries `.status`, the raw `.body`, and `.detail` (the server's
184
+ `error` field when the body was JSON), so status handling never string-matches
185
+ messages.
186
+
112
187
  ## Snapshot-aware checkpoints
113
188
 
114
189
  `Checkpoint` contains the replay call log plus optional `snapshotManifest`
@@ -120,9 +195,9 @@ the raw `runtime.snapshot` VM bytes.
120
195
  `client.replay(checkpoint)` uses the call log for deterministic replay. Durable
121
196
  resume is exposed through `client.resume(sessionId, response)` for paused
122
197
  sessions, recovering through persisted host-promise metadata and the replay
123
- journal. Replay **is** the resume mechanism by design — the QuickJS live-VM
124
- snapshot path was removed in #39, not merely deferred, so the manifest carries
125
- journal/scaffold metadata rather than serialized VM bytes.
198
+ journal. Replay **is** the resume mechanism by design — there is no live-VM
199
+ image to restore; the manifest carries journal/scaffold metadata rather than
200
+ serialized VM bytes.
126
201
 
127
202
  Use `client.getSnapshotManifest(sessionId)` when a UI needs only snapshot
128
203
  metadata. The endpoint never returns the binary VM snapshot.