@tangle-network/agent-runtime 0.15.1 → 0.16.1

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
@@ -2,10 +2,11 @@
2
2
 
3
3
  Production runtime substrate for domain agents. Owns the task lifecycle
4
4
  (knowledge readiness, control loop, session resume, sanitized telemetry,
5
- durable runs across worker / DO crashes, canonical `RuntimeRunRow`
6
- persistence + cost ledger), the chat-model catalog + admission, and the
7
- declarative `defineAgent` manifest — so domain repos stop inventing their
8
- own.
5
+ canonical `RuntimeRunRow` persistence + cost ledger), the chat-turn
6
+ engine (NDJSON envelope + product hooks), the chat-model catalog +
7
+ admission, and the declarative `defineAgent` manifest — so domain
8
+ repos stop inventing their own. Long-running execution durability
9
+ (reconnect, replay, dedup) lives in `@tangle-network/sandbox`.
9
10
 
10
11
  ```bash
11
12
  pnpm add @tangle-network/agent-runtime @tangle-network/agent-eval
@@ -17,12 +18,9 @@ pnpm add @tangle-network/agent-runtime @tangle-network/agent-eval
17
18
  |---|---|
18
19
  | `runAgentTask` | Single-shot adapter-driven task with eval/verification |
19
20
  | `runAgentTaskStream` | Streaming product loop with session resume + backends |
20
- | `runDurableTurn` | Checkpoint+replay chat turn survives a worker crash *after* completion |
21
- | `runSupervisedTurn` | Always-attached durable turn re-attaches an in-flight sandbox run *during* a crash |
22
- | `SessionSupervisorDO` | Cloudflare Durable Object host for `runSupervisedTurn` (with alarm-driven orphan re-attach) |
23
- | `DurableChatTurnEngine` | Framework-neutral chat-turn orchestrator (durable turn + NDJSON + session lifecycle + product hooks) |
21
+ | `handleChatTurn` | Framework-neutral chat-turn orchestrator (NDJSON + `session.run.*` envelope + product hooks) |
22
+ | `deriveExecutionId` | Stable substrate executionId for `X-Execution-ID` cross-process reconnect |
24
23
  | `startRuntimeRun` | Canonical production-run row + cost ledger |
25
- | `runDurable` + `*DurableRunStore` | General durable-step substrate (in-memory / file-system / D1) |
26
24
  | `defineAgent` | Declarative per-vertical agent manifest — surfaces, knowledge, rubric, run fn |
27
25
  | `resolveChatModel` / `validateChatModelId` / `getModels` | Router catalog fetch + fail-closed admission + precedence resolver |
28
26
  | `createTraceBridge` | Map `RuntimeStreamEvent` → `agent-eval` `TraceEvent` |
@@ -53,65 +51,54 @@ const result = await runAgentTask({
53
51
  console.log(result.status, result.runRecords)
54
52
  ```
55
53
 
56
- ## Durable chat turns
54
+ ## Chat turns
57
55
 
58
- A 15-minute agentic turn must survive a Cloudflare worker isolate dying.
59
- `runDurableTurn` replays a *completed* turn from cache (worker died after
60
- the turn finished). `runSupervisedTurn` closes the harder gap a turn
61
- interrupted *mid-stream* by relocating the durability boundary off the
62
- ephemeral worker:
63
-
64
- - The supervisor drains every event into the substrate's own ordered log
65
- (`appendStreamEvent`, idempotent on `eventId`).
66
- - It persists the substrate `RunHandle` the instant the sandbox yields it.
67
- - A fresh supervisor reads the log for its cursor and resumes via
68
- `adapter.attach(handle, cursor)` — no event lost, none delivered twice.
69
-
70
- The reconnect glue is one typed contract — `SandboxReconnectAdapter` —
71
- implemented once per substrate, not per product.
56
+ `handleChatTurn` wraps a product `produce()` hook with the `session.run.*`
57
+ lifecycle envelope, drains the producer stream through the NDJSON line
58
+ protocol, and calls the persist / post-process hooks after drain.
59
+ Framework-neutral: takes already-resolved values, never a `Request` or
60
+ `Context`.
72
61
 
73
62
  ```ts
74
- import { runSupervisedTurn, InMemoryDurableRunStore } from '@tangle-network/agent-runtime'
75
-
76
- const store = new InMemoryDurableRunStore()
77
- const supervised = runSupervisedTurn({
78
- store, runId: `chat:${threadId}:${turnIndex}`, manifest, workerId,
79
- adapter: mySandboxAdapter,
63
+ import { handleChatTurn } from '@tangle-network/agent-runtime'
64
+
65
+ const result = handleChatTurn({
66
+ identity: { tenantId: workspaceId, sessionId: threadId, userId, turnIndex },
67
+ hooks: {
68
+ produce: () => ({
69
+ stream: box.streamPrompt(prompt, sandboxOptions),
70
+ finalText: () => assembled,
71
+ }),
72
+ persistAssistantMessage: async ({ identity, finalText }) => db.insert(messages).values(...),
73
+ onTurnComplete: async ({ identity, finalText }) => extractProposals(finalText),
74
+ traceFlush: () => traceSink.flush(),
75
+ },
76
+ waitUntil: ctx.waitUntil,
80
77
  })
81
- for await (const event of supervised.stream) sendToClient(event)
82
- // supervised.mode() === 'fresh' | 'resumed' | 'replayed'
78
+ return new Response(result.body, { headers: { 'content-type': result.contentType } })
83
79
  ```
84
80
 
85
- Full runnable: [`examples/durable-supervisor/`](./examples/durable-supervisor/).
81
+ ## Execution continuity
86
82
 
87
- ### Cloudflare Durable Object host
83
+ Long-running execution durability reconnect, replay, dedup — lives in
84
+ the substrate. `@tangle-network/sandbox`'s `box.streamPrompt`
85
+ auto-reconnects in-call (extracts `executionId` from the response and
86
+ replays via the runtime endpoint on drop). Cross-process reconnect —
87
+ worker dies, a fresh worker resumes the same execution — requires
88
+ either bypassing the SDK and POSTing directly with `X-Execution-ID`
89
+ (see `tax-agent/sessions.ts`) or a future SDK release that surfaces the
90
+ field on `PromptOptions`.
88
91
 
89
- `SessionSupervisorDO` hosts the supervisor on a real DO `fetch` streams the
90
- turn, `alarm()` re-attaches a run a dropped response stream abandoned.
92
+ `deriveExecutionId` is the convention helper for the stable id the
93
+ product persists alongside its session row:
91
94
 
92
95
  ```ts
93
- import { createSessionSupervisorDO } from '@tangle-network/agent-runtime'
96
+ import { deriveExecutionId } from '@tangle-network/agent-runtime'
94
97
 
95
- export const SessionSupervisor = createSessionSupervisorDO({
96
- resolveRun(request, env, state) { /* return RunSupervisorOptions */ },
97
- resolveOrphan(runId, env, state) { /* same, for the alarm path */ },
98
- encodeEvent(event) { return `data: ${JSON.stringify(event)}\n\n` },
99
- })
100
- ```
101
-
102
- ```toml
103
- # wrangler.toml
104
- [[durable_objects.bindings]]
105
- name = "SESSION_SUPERVISOR"
106
- class_name = "SessionSupervisor"
107
- [[migrations]]
108
- tag = "v1"
109
- new_classes = ["SessionSupervisor"]
98
+ const executionId = deriveExecutionId({ projectId, sessionId, turnIndex })
99
+ // pass as `X-Execution-ID` header when calling the orchestrator directly
110
100
  ```
111
101
 
112
- CF types are structural (`DurableObjectStateLike`) — no
113
- `@cloudflare/workers-types` runtime dep.
114
-
115
102
  ## Chat-model resolution
116
103
 
117
104
  One primitive every chat handler needs and was hand-rolling per repo:
@@ -157,7 +144,7 @@ export const myAgent = defineAgent({
157
144
  knowledge: { /* requirements + provider */ },
158
145
  rubric: { /* dimensions + weights */ },
159
146
  run: async (ctx) => {
160
- /* product-specific run — typically wraps runSupervisedTurn or runAgentTaskStream */
147
+ /* product-specific run — typically wraps handleChatTurn or runAgentTaskStream */
161
148
  },
162
149
  })
163
150
  ```
@@ -213,9 +200,6 @@ for await (const event of runAgentTaskStream({ task, backend, input })) {
213
200
  | `BackendTransportError` | Backend HTTP / IPC call returned non-success |
214
201
  | `SessionMismatchError` | Resume requested against a different backend |
215
202
  | `RuntimeRunStateError` | `RuntimeRunHandle` lifecycle methods called out of order |
216
- | `DurableRunLeaseHeldError` | Another worker holds a live lease on the run |
217
- | `DurableRunInputMismatchError` | A `runId` exists with a different manifest hash |
218
- | `DurableRunDivergenceError` | A step's intent changed across replays |
219
203
 
220
204
  All extend `AgentEvalError` (re-exported from `@tangle-network/agent-eval`)
221
205
  and carry a stable `code` so cross-package handlers pattern-match
@@ -240,7 +224,7 @@ console.log(telemetry.events, telemetry.summary())
240
224
 
241
225
  | Package | Owns |
242
226
  |---|---|
243
- | `agent-runtime` | Lifecycle, adapters, backends, durable substrate, supervisor + DO, model resolution, trace bridge, `defineAgent` |
227
+ | `agent-runtime` | Task lifecycle, adapters, backends, chat-turn engine, execution-handle contract, model resolution, trace bridge, `defineAgent`. **Does not** own long-running execution state — that lives in `@tangle-network/sandbox` + orchestrator. |
244
228
  | `agent-runtime/platform` | Cross-site SSO (`PlatformAuthClient`) + integrations hub (`PlatformHubClient`) |
245
229
  | `agent-runtime/agent` | `defineAgent` + surfaces / outcome adapters |
246
230
  | `agent-runtime/analyst-loop` | `runAnalystLoop` — analyst registry driver |
@@ -263,16 +247,14 @@ Runnable in [`examples/`](./examples/). Every example imports from
263
247
  - [`openai-stream-backend/`](./examples/openai-stream-backend/) — `createOpenAICompatibleBackend`
264
248
  - [`runtime-run/`](./examples/runtime-run/) — production-run row + cost ledger
265
249
  - [`model-resolution/`](./examples/model-resolution/) — router catalog + fail-closed admission
266
- - [`durable-supervisor/`](./examples/durable-supervisor/) — cross-worker resume keystone
267
250
  - [`agent-into-reviewer/`](./examples/agent-into-reviewer/) — pipe one runtime's stream into a reviewer agent
268
- - [`chat-handler/`](./examples/chat-handler/) — `DurableChatTurnEngine.runTurn` (the centerpiece production pattern)
251
+ - [`chat-handler/`](./examples/chat-handler/) — `handleChatTurn` (the centerpiece production pattern)
269
252
  - [`production-trace-sink/`](./examples/production-trace-sink/) — `createProductionTraceSink` data capture
270
253
 
271
254
  ## Tests
272
255
 
273
256
  ```bash
274
- pnpm test # full Node suite (251 tests)
275
- pnpm test:workers # real workerd DO integration test
257
+ pnpm test
276
258
  pnpm typecheck
277
259
  pnpm lint
278
260
  pnpm build
package/dist/agent.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as _tangle_network_agent_eval from '@tangle-network/agent-eval';
2
2
  import { FindingSubject, TraceAnalystKindSpec, AnalystFinding, TraceStore, RunCompleteHook, FeedbackLabel, FeedbackTrajectoryStore } from '@tangle-network/agent-eval';
3
- import { R as RuntimeStreamEvent } from './types-CYxfw14J.js';
3
+ import { R as RuntimeStreamEvent } from './types-DmhXdAhu.js';
4
4
  import { I as ImprovementAdapter, K as KnowledgeAdapter, a as RunAnalystLoopResult } from './types-D_MXrmJP.js';
5
5
 
6
6
  /**