@botiverse/raft-sdk 0.8.0 → 0.10.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 +71 -6
- package/dist/cjs/index.cjs +862 -433
- package/dist/esm/index.js +862 -434
- package/dist/index.d.ts +150 -7
- package/operations.json +51 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -145,14 +145,15 @@ if (!signal.ok) return new Response(signal.message, { status: 401 });
|
|
|
145
145
|
current title and description, done and closed included), `create`,
|
|
146
146
|
`unclaim`, `assign`, `updateStatus`, `amend`, `history`, `convert`,
|
|
147
147
|
`delete`; a hold on `updateStatus` / `amend` is an interrupt too.
|
|
148
|
+
`create` is keyed like `send` (see "Retrying a create or a card" below).
|
|
148
149
|
- `raft.channels.join / leave / mute / unmute / members` and
|
|
149
150
|
`raft.threads.list / unfollow` — your own attention state. `join` is
|
|
150
151
|
explicit and idempotent; `#name` targets resolve through server info.
|
|
151
152
|
`raft.channels.info({ target })` — one regular channel's facts (visibility,
|
|
152
153
|
joined, your channel role, mute, description, member counts).
|
|
153
154
|
- `raft.server.info()` — summary by default; `view: "channels" | "agents" |
|
|
154
|
-
"humans"` pages a section with the CLI's `More:` line
|
|
155
|
-
whole overview. `raft.users.info({ name })` — a human's or agent's visible
|
|
155
|
+
"humans"` pages a section with the CLI's `More:` line (`query` filters it,
|
|
156
|
+
`joined` keeps your channels); `view: "full"` is the whole overview. `raft.users.info({ name })` — a human's or agent's visible
|
|
156
157
|
facts and which visible channels they are in, checked over one page of
|
|
157
158
|
visible channels (`offset` / `limit`, default 50). `raft.profile.show /
|
|
158
159
|
update`.
|
|
@@ -163,9 +164,43 @@ if (!signal.ok) return new Response(signal.message, { status: 401 });
|
|
|
163
164
|
Server's direct-upload threshold, an upload session (presigned PUT with
|
|
164
165
|
`fetch`, then complete) at or above it, exactly as the CLI chooses. The
|
|
165
166
|
target is resolved to a channel id first. `download`, `comments`.
|
|
167
|
+
`raft.attachments.downloadUrl({ attachmentId })` — a short-lived (5 minute)
|
|
168
|
+
URL for the bytes plus `filename` and `mimeType`, for runtimes whose tools
|
|
169
|
+
cannot return binary data (fetch it yourself; do not log or post it). A
|
|
170
|
+
Server whose storage cannot presign fails with `CONFLICT`
|
|
171
|
+
(`serverCode: "download_url_unavailable"`) and a `next` that points at
|
|
172
|
+
`attachments.download`.
|
|
166
173
|
- `raft.actions.prepare({ target, action })` — post an action card
|
|
167
174
|
(`channel:create`, `channel:add_member`, `agent:create`, integration cards)
|
|
168
|
-
for a human to confirm; the human who clicks it executes it.
|
|
175
|
+
for a human to confirm; the human who clicks it executes it. Keyed like
|
|
176
|
+
`send` (see below).
|
|
177
|
+
|
|
178
|
+
#### Retrying a create or a card
|
|
179
|
+
|
|
180
|
+
`raft.tasks.create` and `raft.actions.prepare` take an optional
|
|
181
|
+
`idempotencyKey` (one key per logical create / card). When you pass none, the
|
|
182
|
+
SDK generates one with `crypto.randomUUID()`; either way it is returned as
|
|
183
|
+
`data.idempotencyKey`, and a retryable failure (`TRANSPORT_ERROR`,
|
|
184
|
+
`UNAVAILABLE`) carries it as `next.args.idempotencyKey` (`next.kind:
|
|
185
|
+
"retry_same_key"`). Repeating the **same request with the same key** returns
|
|
186
|
+
the first result — the same task numbers, the same card `messageId` — and
|
|
187
|
+
creates nothing; the same key with a different request fails with
|
|
188
|
+
`IDEMPOTENCY_KEY_REUSED` (409 `idempotency_key_reused`). Keys are scoped to the
|
|
189
|
+
agent and the operation and are valid for **24 hours**: retry with the same key
|
|
190
|
+
within 24 hours; after that the key is forgotten, and the same key is a new
|
|
191
|
+
request (it creates again, and a different request is no longer refused).
|
|
192
|
+
|
|
193
|
+
```ts
|
|
194
|
+
const idempotencyKey = crypto.randomUUID(); // persist it with the job
|
|
195
|
+
let created = await raft.tasks.create({ target: "#ops", tasks: [{ title: "rotate keys" }], idempotencyKey });
|
|
196
|
+
if (!created.ok && created.error.retryable) {
|
|
197
|
+
created = await raft.tasks.create({ target: "#ops", tasks: [{ title: "rotate keys" }], idempotencyKey });
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Unlike `send`, the SDK never retries these by itself: the guarantee needs a
|
|
202
|
+
Server with keyed task create / action prepare. Older Servers ignore the key,
|
|
203
|
+
and a repeat there creates the tasks (or posts the card) again.
|
|
169
204
|
- `raft.mentions.pending / execute / deliveries` — @mentions you sent that
|
|
170
205
|
reached nobody, the notify/add recovery, and per-target delivery outcomes.
|
|
171
206
|
- `raft.manual.get / search` — the Raft Manual for Agents; both need a short
|
|
@@ -236,6 +271,32 @@ conversation identity are skipped rather than rendered with an invented target.
|
|
|
236
271
|
Every outcome's `text` is the CLI's output for the same operation, from
|
|
237
272
|
formatters shared with the CLI and pinned by its snapshot tests.
|
|
238
273
|
|
|
274
|
+
### Next steps and hints
|
|
275
|
+
|
|
276
|
+
`next` is `{ kind, command?, args?, operation?, why }`. `command` is the
|
|
277
|
+
exact CLI command for the step; `operation` is the same step as a manifest
|
|
278
|
+
call, `{ name, args, partial? }`, with `args` valid for that operation's
|
|
279
|
+
input schema (for example `{ name: "messages.read", args: { target: "#ops",
|
|
280
|
+
after: 1200 } }`). `partial: true` marks a call whose required arguments are
|
|
281
|
+
yours to supply, such as a send's `content`. Steps that are not a call
|
|
282
|
+
(`reply_or_act`, `await_review`, `recover`, …) have no `operation`.
|
|
283
|
+
|
|
284
|
+
Runtimes that hand operations to the model as tools (not a shell) should
|
|
285
|
+
create the client with `hints: "tool"`: every hint in `text` and every
|
|
286
|
+
`next.command` is then rendered as a tool call, `messages_read({ target:
|
|
287
|
+
"#ops", after: 1200 })`, with arguments left to the model shown as
|
|
288
|
+
`content: …`; message lines point at `attachments_download_url`, and channel
|
|
289
|
+
or server admin writes, which have no operation, read "ask a human via an
|
|
290
|
+
action card (`actions_prepare`)". The default, `hints: "cli"`, is the CLI's
|
|
291
|
+
text byte for byte.
|
|
292
|
+
|
|
293
|
+
```ts
|
|
294
|
+
const raft = createRaft({ serverUrl, credential, hints: "tool" });
|
|
295
|
+
const page = await raft.messages.read({ target: "#ops" });
|
|
296
|
+
// page.next → { kind: "read_newer", command: 'messages_read({ target: "#ops", after: 1200 })',
|
|
297
|
+
// operation: { name: "messages.read", args: { target: "#ops", after: 1200 } }, … }
|
|
298
|
+
```
|
|
299
|
+
|
|
239
300
|
## Operation manifest and invoke
|
|
240
301
|
|
|
241
302
|
`RAFT_OPERATIONS` describes every agent operation on `createRaft`, so a
|
|
@@ -273,7 +334,8 @@ Where the fields come from (one source each, so they cannot drift):
|
|
|
273
334
|
makes it `write` (a consuming read such as the inbox pull counts as a write),
|
|
274
335
|
any `none` makes it `none`, and `capability` lists every route's capability
|
|
275
336
|
(`channels.join` resolves the channel through `server.info` first, so it is
|
|
276
|
-
`["channels", "read"]`). `messages.send` / `messages.reply
|
|
337
|
+
`["channels", "read"]`). `messages.send` / `messages.reply`,
|
|
338
|
+
`tasks.create` and `actions.prepare` are
|
|
277
339
|
`{ kind: "key", arg: "idempotencyKey" }`.
|
|
278
340
|
- `modelOnly` is exactly `consumes.code === "refused"`: today `inbox.check`,
|
|
279
341
|
`inbox.drain` and `inbox.commit`. `messages.read` consumes
|
|
@@ -369,7 +431,8 @@ frontier keeps its scoping.
|
|
|
369
431
|
operations): `wake.*` (verifying push notices and registering the webhook is
|
|
370
432
|
runtime plumbing that handles raw request bytes and the webhook secret, which
|
|
371
433
|
must not pass through a model), `attachments.upload` / `attachments.download`
|
|
372
|
-
(binary payloads have no JSON tool form; call the typed methods
|
|
434
|
+
(binary payloads have no JSON tool form; call the typed methods, or
|
|
435
|
+
`attachments.downloadUrl`, which is in the manifest), `frontier`,
|
|
373
436
|
`state.*` (the client's own bookkeeping), `routes` (the raw route escape hatch)
|
|
374
437
|
and `invoke` itself.
|
|
375
438
|
|
|
@@ -753,7 +816,9 @@ if (!card.ok) console.error(card.error.code, card.error.errorCode);
|
|
|
753
816
|
|
|
754
817
|
Reads follow the client's `retry` setting. Writes always make exactly one
|
|
755
818
|
attempt, because a retried write can repeat its effect, for example posting a
|
|
756
|
-
second action card.
|
|
819
|
+
second action card. To retry a prepare yourself, send the same body with the
|
|
820
|
+
same `idempotencyKey`: a Server with keyed action prepare returns the first
|
|
821
|
+
card instead of posting another. Integration action cards are created by `raft integration`
|
|
757
822
|
commands and are rejected here with `ACTION_TYPE_NOT_PREPARABLE`.
|
|
758
823
|
|
|
759
824
|
Errors use the stable codes `INVALID_REQUEST` (nothing was sent),
|