@godspeedai/cognate-runtime-bun 0.1.1 → 0.1.2
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 +158 -38
- package/package.json +12 -12
package/README.md
CHANGED
|
@@ -1,40 +1,160 @@
|
|
|
1
1
|
# @godspeedai/cognate-runtime-bun
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
run
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
3
|
+
The Cognate reference runtime for Bun: durable agent runs, human-in-the-loop continuations,
|
|
4
|
+
artifacts, projections, and optional cognition, composed in-process behind a single
|
|
5
|
+
`RuntimeService`. Point it at a SQLite file and your application's history survives restarts.
|
|
6
|
+
|
|
7
|
+
**When to use this package:** to run agents for real — in a server, a worker, or a script. Pair it
|
|
8
|
+
with [`@godspeedai/cognate-client`](https://www.npmjs.com/package/@godspeedai/cognate-client) to
|
|
9
|
+
consume it from the same process, or with a transport adapter to serve it over the network.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
bun add @godspeedai/cognate-runtime-bun
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Requires [Bun](https://bun.sh) >= 1.4.0 (the default store uses Bun's built-in `bun:sqlite`).
|
|
18
|
+
|
|
19
|
+
## Quick start
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import { createRuntime } from "@godspeedai/cognate-runtime-bun";
|
|
23
|
+
import type { AgentDefinition } from "@godspeedai/cognate-runtime-api";
|
|
24
|
+
|
|
25
|
+
const agent: AgentDefinition = {
|
|
26
|
+
id: "agent.order",
|
|
27
|
+
version: "1.0.0",
|
|
28
|
+
async run(_input, ctx) {
|
|
29
|
+
// Shared state: a snapshot, then JSON Patch deltas — clients derive the same state.
|
|
30
|
+
await ctx.emit("state.changed", { snapshot: { order: { id: "o-1", status: "open", total: 0 } } });
|
|
31
|
+
await ctx.emit("state.changed", { patch: [{ op: "replace", path: "/order/status", value: "paid" }] });
|
|
32
|
+
await ctx.emit("state.changed", { patch: [{ op: "replace", path: "/order/total", value: 42 }] });
|
|
33
|
+
return { done: true };
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const caller = { actor: { id: "alice", kind: "user" }, tenant: "tenant-a" } as const;
|
|
38
|
+
|
|
39
|
+
const runtime = await createRuntime({
|
|
40
|
+
store: "./app.sqlite", // a durable file; use ":memory:" for an ephemeral runtime
|
|
41
|
+
// policy authorizes capability invocations; actions authorizes run/continuation actions.
|
|
42
|
+
policy: { authorize: () => ({ allow: true, policyId: "p", reason: "allowed" }) },
|
|
43
|
+
actions: { authorize: () => ({ allow: true, reason: "allowed" }) },
|
|
44
|
+
agents: [agent],
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const started = await runtime.service.startRun(caller, {
|
|
48
|
+
agent: "agent.order",
|
|
49
|
+
input: {},
|
|
50
|
+
idempotencyKey: "order-1", // repeating the key returns the same run, never a duplicate
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
await runtime.idle(); // background work queued so far has been processed
|
|
54
|
+
|
|
55
|
+
const run = await runtime.service.getRun(caller, { runId: started.runId });
|
|
56
|
+
console.log(run.status, run.output); // completed { done: true }
|
|
57
|
+
|
|
58
|
+
await runtime.close();
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Suspending on a durable continuation
|
|
62
|
+
|
|
63
|
+
`ctx.waitFor` suspends the run until someone resolves the continuation it opens. The run's progress
|
|
64
|
+
is durable: it can sit waiting through restarts.
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
const refundAgent: AgentDefinition = {
|
|
68
|
+
id: "agent.refund",
|
|
69
|
+
version: "1.0.0",
|
|
70
|
+
async run(input, ctx) {
|
|
71
|
+
const { amount } = input as { amount: number };
|
|
72
|
+
const decision = (await ctx.waitFor("approve", {
|
|
73
|
+
type: "refund-approval",
|
|
74
|
+
condition: { kind: "human_approval" },
|
|
75
|
+
payload: { amount },
|
|
76
|
+
})) as { approved: boolean };
|
|
77
|
+
return { amount, approved: decision.approved };
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const waiting = await runtime.service.startRun(caller, {
|
|
82
|
+
agent: "agent.refund",
|
|
83
|
+
input: { amount: 75 },
|
|
84
|
+
idempotencyKey: "refund-1",
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Meanwhile — from a webhook, an admin UI, a shell — list and resolve open continuations.
|
|
88
|
+
const [continuation] = await runtime.service.listContinuations(caller, {
|
|
89
|
+
runId: waiting.runId,
|
|
90
|
+
status: "OPEN",
|
|
91
|
+
});
|
|
92
|
+
await runtime.service.resolveContinuation(caller, {
|
|
93
|
+
continuationId: continuation!.id,
|
|
94
|
+
action: "resume",
|
|
95
|
+
input: { approved: true },
|
|
96
|
+
idempotencyKey: "approve-1",
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The run re-enters the agent from the top, receives the recorded decision, and completes. Replays
|
|
101
|
+
never repeat recorded work: every `ctx.step`, `emit`, `invoke`, `artifact`, and `waitFor` result is
|
|
102
|
+
an event on the run's stream, and re-entry returns those results instead of re-executing.
|
|
103
|
+
|
|
104
|
+
## What you get from `createRuntime`
|
|
105
|
+
|
|
106
|
+
The returned `Runtime` exposes:
|
|
107
|
+
|
|
108
|
+
- `service` — the full `RuntimeService`: start/get/cancel/list runs, a reconnectable event stream
|
|
109
|
+
(`service.events(caller, { follow: true })`), continuations, direct capability `invoke`,
|
|
110
|
+
`getArtifact`, public projection reads, and shared run/thread state reads and updates.
|
|
111
|
+
- `store` — the underlying `DurableStore`, if you need direct access to the event log.
|
|
112
|
+
- `kernel` — the embedded capability kernel.
|
|
113
|
+
- `inspect(correlationId)` — the causal chain for a correlation id: runs, events, invocations,
|
|
114
|
+
artifacts, observations.
|
|
115
|
+
- `erase(eventId, reason, actor)` — erase an event's payload; derived views and the cognitive index
|
|
116
|
+
drop it too.
|
|
117
|
+
- `rebuildCognition()`, `pollApprovals()`, `idle(timeoutMs?)`, and `close()`.
|
|
118
|
+
|
|
119
|
+
Notable options beyond the quick start: `components` (capability-providing kernel components your
|
|
120
|
+
agents can `ctx.invoke`), `projections` ([`@godspeedai/cognate-projections`](https://www.npmjs.com/package/@godspeedai/cognate-projections)
|
|
121
|
+
kept current automatically), `cognition` (index completed runs and recall them via `ctx.recall`),
|
|
122
|
+
`outboxFor` (extra outbox intents committed atomically with each run event), `governance`, and
|
|
123
|
+
`tickMs` (background loop interval, default 10 ms).
|
|
124
|
+
|
|
125
|
+
## Limitations
|
|
126
|
+
|
|
127
|
+
- **One process, one writer.** All runs live in the process that opened the store; executions
|
|
128
|
+
within a tick run sequentially, so a slow agent delays others. To scale out, split runtimes per
|
|
129
|
+
store file.
|
|
130
|
+
- **Steps are at-least-once.** A step that was in flight during a crash re-executes after restart.
|
|
131
|
+
Keep steps idempotent, and put irreversible external calls behind a `ctx.waitFor` continuation so
|
|
132
|
+
they happen once, resolved deliberately.
|
|
133
|
+
- **Polling, not pushing, inside the process.** Background work (run execution, resume delivery,
|
|
134
|
+
continuation expiry) runs on a loop every `tickMs`.
|
|
135
|
+
- **Erasure has copies.** `runtime.erase` removes an event's payload from the log, derived views,
|
|
136
|
+
and the cognitive index — but content copied into continuation payloads, idempotency snapshots,
|
|
137
|
+
or recall results stays.
|
|
138
|
+
- **Public projections are tenant-partitioned.** Register projections that key their state
|
|
139
|
+
`<tenant>/<key>`; `service.readProjection` returns only the caller's tenant partition.
|
|
140
|
+
- **Denied means invisible.** Reading an artifact you are not allowed to see returns the same
|
|
141
|
+
"not found" as a missing one.
|
|
142
|
+
- **Recall degrades gracefully.** Without a `cognition` configuration, `ctx.recall` returns
|
|
143
|
+
`{ status: "degraded" }` instead of failing the run.
|
|
144
|
+
|
|
145
|
+
## Related packages
|
|
146
|
+
|
|
147
|
+
- [`@godspeedai/cognate-client`](https://www.npmjs.com/package/@godspeedai/cognate-client) — the
|
|
148
|
+
headless client for consuming this runtime; derives live run state for you.
|
|
149
|
+
- [`@godspeedai/cognate-runtime-api`](https://www.npmjs.com/package/@godspeedai/cognate-runtime-api) —
|
|
150
|
+
the service and agent-authoring contract this package implements.
|
|
151
|
+
- [`@godspeedai/cognate-store-sqlite`](https://www.npmjs.com/package/@godspeedai/cognate-store-sqlite) —
|
|
152
|
+
the durable store behind `store: "<path>"`.
|
|
153
|
+
- [`@godspeedai/cognate-store-memory`](https://www.npmjs.com/package/@godspeedai/cognate-store-memory) —
|
|
154
|
+
bring your own ephemeral store via `store: { store }`.
|
|
155
|
+
- [`@godspeedai/cognate`](https://www.npmjs.com/package/@godspeedai/cognate) — the SDK umbrella;
|
|
156
|
+
one install for the runtime and the client together.
|
|
157
|
+
|
|
158
|
+
## License
|
|
159
|
+
|
|
160
|
+
Apache-2.0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@godspeedai/cognate-runtime-bun",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Bun reference runtime: composes kernel, durable store, runs, continuations, commitments, artifacts, and cognition behind RuntimeService.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -22,17 +22,17 @@
|
|
|
22
22
|
".": "./src/index.ts"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@godspeedai/cognate-artifacts": "^0.1.
|
|
26
|
-
"@godspeedai/cognate-capabilities": "^0.1.
|
|
27
|
-
"@godspeedai/cognate-cognitive-api": "^0.1.
|
|
28
|
-
"@godspeedai/cognate-continuations": "^0.1.
|
|
29
|
-
"@godspeedai/cognate-events": "^0.1.
|
|
30
|
-
"@godspeedai/cognate-kernel-api": "^0.1.
|
|
31
|
-
"@godspeedai/cognate-kernel-cordis": "^0.1.
|
|
32
|
-
"@godspeedai/cognate-projections": "^0.1.
|
|
33
|
-
"@godspeedai/cognate-runtime-api": "^0.1.
|
|
34
|
-
"@godspeedai/cognate-store-memory": "^0.1.
|
|
35
|
-
"@godspeedai/cognate-store-sqlite": "^0.1.
|
|
25
|
+
"@godspeedai/cognate-artifacts": "^0.1.2",
|
|
26
|
+
"@godspeedai/cognate-capabilities": "^0.1.2",
|
|
27
|
+
"@godspeedai/cognate-cognitive-api": "^0.1.2",
|
|
28
|
+
"@godspeedai/cognate-continuations": "^0.1.2",
|
|
29
|
+
"@godspeedai/cognate-events": "^0.1.2",
|
|
30
|
+
"@godspeedai/cognate-kernel-api": "^0.1.2",
|
|
31
|
+
"@godspeedai/cognate-kernel-cordis": "^0.1.2",
|
|
32
|
+
"@godspeedai/cognate-projections": "^0.1.2",
|
|
33
|
+
"@godspeedai/cognate-runtime-api": "^0.1.2",
|
|
34
|
+
"@godspeedai/cognate-store-memory": "^0.1.2",
|
|
35
|
+
"@godspeedai/cognate-store-sqlite": "^0.1.2"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@godspeedai/cognate-cognitive-memory": "workspace:*"
|