experimental-agent 0.2.3 → 0.4.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 +103 -241
- package/dist/adapter-zgOel4wW.d.mts +256 -0
- package/dist/adapter-zgOel4wW.d.ts +256 -0
- package/dist/chunk-BFFNCESS.mjs +302 -0
- package/dist/chunk-C4VSUEY2.mjs +72 -0
- package/dist/chunk-GKASMIBR.mjs +50 -0
- package/dist/chunk-IV75IMEW.mjs +328 -0
- package/dist/chunk-JO3JDCH5.mjs +107 -0
- package/dist/chunk-MSTM6W3Y.mjs +99 -0
- package/dist/chunk-MSWINCCM.mjs +128 -0
- package/dist/chunk-RT72C52I.mjs +324 -0
- package/dist/chunk-ZUFJJYC4.mjs +150 -0
- package/dist/{handler-FRUPZ4LX.mjs → docker-QPCLWLYR.mjs} +3 -4
- package/dist/entry-6HYg5qqg.d.mts +36 -0
- package/dist/entry-BrWOmEK2.d.ts +36 -0
- package/dist/index.d.mts +401 -18
- package/dist/index.d.ts +401 -18
- package/dist/index.js +3396 -5500
- package/dist/index.mjs +3511 -1166
- package/dist/lifecycle-workflow-steps.d.mts +5 -0
- package/dist/lifecycle-workflow-steps.d.ts +5 -0
- package/dist/lifecycle-workflow-steps.js +263 -0
- package/dist/lifecycle-workflow-steps.mjs +9 -0
- package/dist/lifecycle-workflow.d.mts +6 -6
- package/dist/lifecycle-workflow.d.ts +6 -6
- package/dist/lifecycle-workflow.js +192 -905
- package/dist/lifecycle-workflow.mjs +3 -1
- package/dist/local-KJ3BSIFJ.mjs +8 -0
- package/dist/next/loader.js +31 -7
- package/dist/next/loader.mjs +1 -1
- package/dist/next.js +35 -8
- package/dist/next.mjs +6 -3
- package/dist/{process-manager-JDUJDYGU.mjs → process-manager-WQHAIVRB.mjs} +1 -1
- package/dist/sandbox.d.mts +6 -0
- package/dist/sandbox.d.ts +6 -0
- package/dist/sandbox.js +1070 -0
- package/dist/sandbox.mjs +19 -0
- package/dist/steps-BIsP57pm.d.mts +173 -0
- package/dist/steps-DShnXBLf.d.ts +173 -0
- package/dist/storage.d.mts +17 -0
- package/dist/storage.d.ts +17 -0
- package/dist/storage.js +368 -0
- package/dist/storage.mjs +16 -0
- package/dist/vercel-QZ6INPMV.mjs +11 -0
- package/package.json +29 -5
- package/dist/agent-workflow.d.mts +0 -30
- package/dist/agent-workflow.d.ts +0 -30
- package/dist/agent-workflow.js +0 -5433
- package/dist/agent-workflow.mjs +0 -14
- package/dist/chunk-7M6UPURS.mjs +0 -75
- package/dist/chunk-AML2VCQS.mjs +0 -1287
- package/dist/chunk-FQ67QZOI.mjs +0 -75
- package/dist/chunk-NO7RHGTH.mjs +0 -2367
- package/dist/chunk-NXDVNJRS.mjs +0 -106
- package/dist/chunk-OZZVS6L5.mjs +0 -139
- package/dist/chunk-SJVFFE5D.mjs +0 -402
- package/dist/chunk-TAXLUVIC.mjs +0 -1
- package/dist/chunk-TGNVXSMX.mjs +0 -399
- package/dist/chunk-YRYXN7W4.mjs +0 -48
- package/dist/chunk-ZIAHPXOJ.mjs +0 -595
- package/dist/client-BKA7XBGW.mjs +0 -15
- package/dist/client-CEeSFGva.d.mts +0 -2376
- package/dist/client-CEeSFGva.d.ts +0 -2376
- package/dist/docker-FB2MJTHJ.mjs +0 -12
- package/dist/local-fs-handlers-SYOCKTPN.mjs +0 -447
- package/dist/sandbox-UENKQV3T.mjs +0 -21
- package/dist/storage-LSDMRW73.mjs +0 -20
- package/dist/vercel-SD3JTECG.mjs +0 -20
- package/dist/vercel-sdk-I6A4MVAN.mjs +0 -8
package/README.md
CHANGED
|
@@ -9,10 +9,10 @@ pnpm i experimental-agent
|
|
|
9
9
|
## Why
|
|
10
10
|
|
|
11
11
|
- **AI SDK compatible** — Built on `ai`. Uses `UIMessage`, `GatewayModelId`, streams the same way. If you know AI SDK, you know this.
|
|
12
|
-
- **
|
|
12
|
+
- **Opt-in durability** — Works in-process by default. Add a `"use workflow"` wrapper for full durability that survives crashes, timeouts, and deploys.
|
|
13
|
+
- **Bring your own storage** — Implement a flat handler map backed by any database. Built-in `localStorage()` for dev.
|
|
13
14
|
- **Managed sandbox** — Auto-starts on first use, auto-snapshots when idle, auto-resumes. You don't manage the VM.
|
|
14
|
-
- **Built-in
|
|
15
|
-
- **Built-in tools** — Read, Grep, List, Bash. No setup.
|
|
15
|
+
- **Built-in tools** — Read, Grep, List, Bash, Write, Edit, Skill, JavaScript. No setup.
|
|
16
16
|
|
|
17
17
|
## Quick Start
|
|
18
18
|
|
|
@@ -20,9 +20,25 @@ pnpm i experimental-agent
|
|
|
20
20
|
// lib/agent.ts
|
|
21
21
|
import { agent } from "experimental-agent";
|
|
22
22
|
|
|
23
|
-
export const myAgent = agent({
|
|
24
|
-
model: "anthropic/claude-opus-4.
|
|
23
|
+
export const myAgent = agent("my-agent", {
|
|
24
|
+
model: "anthropic/claude-opus-4.6",
|
|
25
25
|
system: "You are a helpful coding assistant.",
|
|
26
|
+
skills: [
|
|
27
|
+
{ type: "sandbox", path: ".agent/skills/project" },
|
|
28
|
+
{ type: "host", path: "./skills/company" },
|
|
29
|
+
{
|
|
30
|
+
type: "git",
|
|
31
|
+
repo: "https://github.com/acme/agent-skills.git",
|
|
32
|
+
ref: "v1.2.0",
|
|
33
|
+
path: "skills",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
type: "inline",
|
|
37
|
+
name: "incident-triage",
|
|
38
|
+
description: "Triage incidents safely",
|
|
39
|
+
instructions: "1. Gather context\n2. Confirm blast radius\n3. Propose mitigations",
|
|
40
|
+
},
|
|
41
|
+
],
|
|
26
42
|
});
|
|
27
43
|
```
|
|
28
44
|
|
|
@@ -33,10 +49,10 @@ import { createUIMessageStreamResponse } from "ai";
|
|
|
33
49
|
|
|
34
50
|
export async function POST(req: Request, { params }: { params: { chatId: string } }) {
|
|
35
51
|
const { chatId } = await params;
|
|
36
|
-
const { message } = await req.json();
|
|
52
|
+
const { message } = await req.json();
|
|
37
53
|
|
|
38
|
-
const session =
|
|
39
|
-
await session.send(
|
|
54
|
+
const session = myAgent.session(chatId);
|
|
55
|
+
await session.send(message);
|
|
40
56
|
const stream = await session.stream();
|
|
41
57
|
|
|
42
58
|
return createUIMessageStreamResponse({ stream });
|
|
@@ -44,275 +60,120 @@ export async function POST(req: Request, { params }: { params: { chatId: string
|
|
|
44
60
|
|
|
45
61
|
export async function GET(req: Request, { params }: { params: { chatId: string } }) {
|
|
46
62
|
const { chatId } = await params;
|
|
47
|
-
const session =
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
return new Response("Internal server error", { status: 500 });
|
|
63
|
+
const session = myAgent.session(chatId);
|
|
64
|
+
try {
|
|
65
|
+
const stream = await session.stream();
|
|
66
|
+
return createUIMessageStreamResponse({ stream });
|
|
67
|
+
} catch {
|
|
68
|
+
return Response.json(await session.history());
|
|
55
69
|
}
|
|
56
|
-
|
|
57
|
-
return createUIMessageStreamResponse({ stream });
|
|
58
70
|
}
|
|
59
71
|
```
|
|
60
72
|
|
|
73
|
+
## Adding Workflow
|
|
61
74
|
|
|
75
|
+
Everything works without workflow. To add durability:
|
|
62
76
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
`session.ui()` returns `UIMessage[]` — the same format `useChat` uses.
|
|
66
|
-
|
|
67
|
-
### RSC Pattern
|
|
68
|
-
|
|
69
|
-
Server component fetches initial state, client component handles streaming:
|
|
70
|
-
|
|
71
|
-
```tsx
|
|
72
|
-
// app/chat/[chatId]/page.tsx (server component)
|
|
77
|
+
```ts
|
|
78
|
+
// workflow.ts
|
|
73
79
|
import { myAgent } from "@/lib/agent";
|
|
74
|
-
import {
|
|
75
|
-
|
|
76
|
-
export
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
throw new Error("Failed to get messages");
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return (
|
|
86
|
-
<>
|
|
87
|
-
{ui.messages.map((m) => (
|
|
88
|
-
<MessageView key={m.id} message={m} />
|
|
89
|
-
))}
|
|
90
|
-
<Chat chatId={chatId} streamingMessageId={ui.streamingMessageId} />
|
|
91
|
-
</>
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
```tsx
|
|
97
|
-
// chat-client.tsx
|
|
98
|
-
"use client";
|
|
99
|
-
|
|
100
|
-
import { useEffect } from "react";
|
|
101
|
-
import { useChat, DefaultChatTransport } from "@ai-sdk/react";
|
|
102
|
-
|
|
103
|
-
export function Chat({ chatId, streamingMessageId }) {
|
|
104
|
-
const { messages, resumeStream, sendMessage, status } = useChat({
|
|
105
|
-
id: chatId,
|
|
106
|
-
transport: new DefaultChatTransport({
|
|
107
|
-
api: `/api/chat/${chatId}`,
|
|
108
|
-
prepareSendMessagesRequest: ({ messages }) => ({
|
|
109
|
-
body: { message: messages.at(-1) },
|
|
110
|
-
}),
|
|
111
|
-
prepareReconnectToStreamRequest: (request) => ({
|
|
112
|
-
...request,
|
|
113
|
-
api: `/api/chat/${chatId}`,
|
|
114
|
-
}),
|
|
115
|
-
}),
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
useEffect(() => {
|
|
119
|
-
if (streamingMessageId) {
|
|
120
|
-
resumeStream();
|
|
121
|
-
}
|
|
122
|
-
}, [streamingMessageId, resumeStream]);
|
|
123
|
-
|
|
124
|
-
return (
|
|
125
|
-
<>
|
|
126
|
-
{messages.map((m) => (
|
|
127
|
-
<MessageView key={m.id} message={m} />
|
|
128
|
-
))}
|
|
129
|
-
<form
|
|
130
|
-
onSubmit={async (e) => {
|
|
131
|
-
e.preventDefault();
|
|
132
|
-
const form = e.currentTarget;
|
|
133
|
-
const textarea = form.elements.namedItem("composer") as HTMLTextAreaElement | null;
|
|
134
|
-
const text = textarea ? textarea.value : "";
|
|
135
|
-
if (text.trim()) {
|
|
136
|
-
await sendMessage({ parts: [{ type: "text", text }] });
|
|
137
|
-
textarea.value = "";
|
|
138
|
-
}
|
|
139
|
-
}}
|
|
140
|
-
>
|
|
141
|
-
<textarea name="composer" />
|
|
142
|
-
<button type="submit" disabled={status !== "ready"}>
|
|
143
|
-
Send
|
|
144
|
-
</button>
|
|
145
|
-
</form>
|
|
146
|
-
</>
|
|
147
|
-
);
|
|
80
|
+
import type { SessionSendArgs } from "experimental-agent";
|
|
81
|
+
|
|
82
|
+
export async function agentWorkflow(
|
|
83
|
+
sessionId: string,
|
|
84
|
+
...args: SessionSendArgs<typeof myAgent>
|
|
85
|
+
) {
|
|
86
|
+
"use workflow";
|
|
87
|
+
return await myAgent.session(sessionId).send(...args);
|
|
148
88
|
}
|
|
149
89
|
```
|
|
150
90
|
|
|
151
|
-
|
|
152
|
-
## Tools
|
|
153
|
-
|
|
154
|
-
| Tool | Description |
|
|
155
|
-
|------|-------------|
|
|
156
|
-
| **Read** | Read files. Large files (>200 lines) paginate automatically. |
|
|
157
|
-
| **Grep** | ripgrep-powered search. Regex, file types, context lines. |
|
|
158
|
-
| **List** | Directory listing with depth control and glob filtering. |
|
|
159
|
-
| **Bash** | Shell commands. Background processes via `waitUntil: 0`. Persistent CWD. |
|
|
160
|
-
|
|
161
|
-
## Configuration
|
|
162
|
-
|
|
163
|
-
```ts
|
|
164
|
-
const myAgent = agent({
|
|
165
|
-
model: "anthropic/claude-haiku-4.5", // Required
|
|
166
|
-
system: "...", // System prompt
|
|
167
|
-
sandbox: { type: "vercel" }, // or "local"
|
|
168
|
-
storage: { type: "vercel" }, // or "local" or "custom"
|
|
169
|
-
skillsDir: ".agent/skills", // Skills location
|
|
170
|
-
mcp: { ... }, // Custom tools
|
|
171
|
-
})
|
|
172
|
-
|
|
173
|
-
// overrides per session
|
|
174
|
-
myAgent.session("<session-id>", {
|
|
175
|
-
model: "anthropic/claude-opus-4.5"
|
|
176
|
-
})
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
## Sessions
|
|
180
|
-
|
|
181
91
|
```ts
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
await session.send({ input: "Hello" });
|
|
186
|
-
await session.send({ input: { role: "user", parts: [{ type: "text", text: "Hello" }] } });
|
|
92
|
+
// route.ts
|
|
93
|
+
import { start } from "workflow/api";
|
|
94
|
+
import { agentWorkflow } from "./workflow";
|
|
187
95
|
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
await session.tag.set("category", "support");
|
|
96
|
+
const result = await start(agentWorkflow, [chatId, message, opts]);
|
|
97
|
+
const stream = await session.stream(result);
|
|
98
|
+
return createUIMessageStreamResponse({ stream });
|
|
192
99
|
```
|
|
193
100
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
- `myAgent.session(id)` and `myAgent.sandbox(id)` return orchestration handles.
|
|
197
|
-
- Handles are use-case APIs (send, stream, run tools, resume sandbox lifecycle).
|
|
198
|
-
- `myAgent.storage.*` is the raw record API (`Session`, `SandboxRecord`, `Message`, `Part`, `Command`, `SetupSnapshot`).
|
|
199
|
-
- Use `storage` for record lookups and filters (for example existence checks and list queries).
|
|
200
|
-
|
|
201
|
-
### Durable UI
|
|
202
|
-
|
|
203
|
-
Unlike `useChat` alone, messages survive refresh. They're persisted to storage.
|
|
204
|
-
|
|
205
|
-
- Close laptop, open tomorrow — conversation is there
|
|
206
|
-
- Browser crashes mid-stream — reload, partial response preserved
|
|
207
|
-
- Share a session URL — another user sees the same conversation
|
|
208
|
-
|
|
209
|
-
The server component renders completed messages from `session.ui()`. The client component handles new input and streaming. State lives in storage, not browser memory.
|
|
210
|
-
|
|
211
|
-
## Sandbox
|
|
101
|
+
## Storage
|
|
212
102
|
|
|
213
103
|
```ts
|
|
214
|
-
//
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
104
|
+
// Dev — built-in filesystem storage
|
|
105
|
+
import { localStorage } from "experimental-agent/storage";
|
|
106
|
+
agent("my-agent", { storage: localStorage() })
|
|
107
|
+
|
|
108
|
+
// Prod — your own database
|
|
109
|
+
agent("my-agent", {
|
|
110
|
+
async storage(store) {
|
|
111
|
+
return await store.on({
|
|
112
|
+
"session.get": async ({ id }) => await db.sessions.findById(id),
|
|
113
|
+
"session.set": async ({ id, value }) => await db.sessions.upsert(id, value),
|
|
114
|
+
// ... all handlers
|
|
115
|
+
});
|
|
116
|
+
},
|
|
117
|
+
})
|
|
221
118
|
|
|
222
|
-
//
|
|
223
|
-
|
|
119
|
+
// To add workflow durability, just add "use step" at the top:
|
|
120
|
+
agent("my-agent", {
|
|
121
|
+
async storage(store) {
|
|
122
|
+
"use step";
|
|
123
|
+
return await store.on({ /* same handlers */ });
|
|
124
|
+
},
|
|
125
|
+
})
|
|
224
126
|
```
|
|
225
127
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
```ts
|
|
229
|
-
const sharedBox = await myAgent.sandbox("some-sandbox")
|
|
230
|
-
|
|
231
|
-
await myAgent.session("s1", { sandbox: sharedBox.id });
|
|
232
|
-
await myAgent.session("s2", { sandbox: sharedBox.id });
|
|
233
|
-
```
|
|
128
|
+
The SDK stores `Session`, `Message`, `Part`, `Sandbox`. Everything else — users, titles, access control — belongs in your database. Session ID is your join key.
|
|
234
129
|
|
|
235
130
|
## Skills
|
|
236
131
|
|
|
237
|
-
|
|
132
|
+
`skills` is the canonical skills API for both `agent(...)` defaults and `session.update(...)` overrides.
|
|
238
133
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
---
|
|
244
|
-
|
|
245
|
-
Run `vercel deploy` in the project root.
|
|
246
|
-
```
|
|
134
|
+
- `{ type: "sandbox", path: "..." }` reads skills already present in sandbox
|
|
135
|
+
- `{ type: "host", path: "..." }` copies skills from host filesystem into sandbox materialized dirs
|
|
136
|
+
- `{ type: "git", ... }` clones a git repo into sandbox materialized dirs (optionally with `ref`, `path`, `name`)
|
|
137
|
+
- `{ type: "inline", ... }` writes an inline `SKILL.md` into sandbox materialized dirs
|
|
247
138
|
|
|
248
139
|
```ts
|
|
249
|
-
|
|
140
|
+
const session = myAgent.session("chat-123");
|
|
141
|
+
|
|
142
|
+
await session.update({
|
|
143
|
+
skills: [
|
|
144
|
+
{
|
|
145
|
+
type: "git",
|
|
146
|
+
repo: "https://github.com/acme/agent-skills.git",
|
|
147
|
+
ref: "main",
|
|
148
|
+
path: "skills",
|
|
149
|
+
name: "release-playbook",
|
|
150
|
+
},
|
|
151
|
+
],
|
|
152
|
+
});
|
|
250
153
|
```
|
|
251
154
|
|
|
252
|
-
|
|
155
|
+
### Migration
|
|
253
156
|
|
|
254
|
-
|
|
157
|
+
Legacy `skillsDir` configuration is deprecated. Migrate to `skills`:
|
|
255
158
|
|
|
256
159
|
```ts
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
const myAgent = agent({
|
|
261
|
-
mcp: {
|
|
262
|
-
vercel: mcp({
|
|
263
|
-
url: "/api/mcp",
|
|
264
|
-
headersSchema: z.object({ authorization: z.string() }),
|
|
265
|
-
tools: {
|
|
266
|
-
listProjects: {
|
|
267
|
-
description: "List Vercel projects",
|
|
268
|
-
inputSchema: z.object({ teamId: z.string().optional() }),
|
|
269
|
-
},
|
|
270
|
-
},
|
|
271
|
-
}),
|
|
272
|
-
},
|
|
160
|
+
// before
|
|
161
|
+
agent("my-agent", {
|
|
162
|
+
skillsDir: [".agent/skills", ".agent/skills/shared"],
|
|
273
163
|
});
|
|
274
164
|
|
|
275
|
-
//
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
165
|
+
// after
|
|
166
|
+
agent("my-agent", {
|
|
167
|
+
skills: [
|
|
168
|
+
{ type: "sandbox", path: ".agent/skills" },
|
|
169
|
+
{ type: "sandbox", path: ".agent/skills/shared" },
|
|
170
|
+
],
|
|
279
171
|
});
|
|
280
|
-
|
|
281
|
-
// Handle in your API
|
|
282
|
-
await myAgent.handleMcpToolCall(body, {
|
|
283
|
-
"vercel/listProjects": async ({ input, headers }) => {
|
|
284
|
-
return fetchProjects(input.teamId, headers.authorization);
|
|
285
|
-
},
|
|
286
|
-
});
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
## Storage
|
|
290
|
-
|
|
291
|
-
HTTP-based (workflow inputs must be serializable).
|
|
292
|
-
|
|
293
|
-
```ts
|
|
294
|
-
agent({ storage: { type: "vercel" } }) // default — hosted service
|
|
295
|
-
agent({ storage: { type: "local" } }) // dev — filesystem
|
|
296
|
-
agent({ storage: { type: "custom", url: "https://...", headers: {} } })
|
|
297
172
|
```
|
|
298
173
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
Everything else—users, titles, access control—belongs in your database. Session ID is your join key.
|
|
302
|
-
|
|
303
|
-
For session queries scoped to a sandbox, use `storage.session.listBySandbox({ sandboxId, ... })`.
|
|
304
|
-
|
|
305
|
-
### Vercel Agent Storage
|
|
174
|
+
## Documentation
|
|
306
175
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
- **Zero config** — authenticates via Vercel OIDC, no API keys needed
|
|
310
|
-
- **Multi-tenant** — data isolated by owner, project, and environment
|
|
311
|
-
- **Postgres-backed** — reliable, queryable, scales with you
|
|
312
|
-
|
|
313
|
-
Just deploy to Vercel and it works. No database setup, no connection strings.
|
|
314
|
-
|
|
315
|
-
For self-hosting or custom backends, see [apps/storage](../../apps/storage/) for a reference implementation using `handleStorageRpc`.
|
|
176
|
+
Full docs at [packages/agent/docs](./docs/).
|
|
316
177
|
|
|
317
178
|
## Development
|
|
318
179
|
|
|
@@ -324,3 +185,4 @@ pnpm test # vitest run
|
|
|
324
185
|
pnpm test:watch # vitest watch
|
|
325
186
|
pnpm typecheck # tsc --noEmit
|
|
326
187
|
```
|
|
188
|
+
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { WORKFLOW_SERIALIZE, WORKFLOW_DESERIALIZE } from '@workflow/serde';
|
|
2
|
+
import { NetworkPolicy } from '@vercel/sandbox';
|
|
3
|
+
import { UIMessage } from 'ai';
|
|
4
|
+
|
|
5
|
+
type SkillSourceType = "sandbox" | "host" | "git" | "inline";
|
|
6
|
+
type SandboxSkillInput = {
|
|
7
|
+
type: "sandbox";
|
|
8
|
+
path: string;
|
|
9
|
+
};
|
|
10
|
+
type HostSkillInput = {
|
|
11
|
+
type: "host";
|
|
12
|
+
path: string;
|
|
13
|
+
};
|
|
14
|
+
type GitSkillInput = {
|
|
15
|
+
type: "git";
|
|
16
|
+
repo: string;
|
|
17
|
+
ref?: string;
|
|
18
|
+
path?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Skill directory name under `path`.
|
|
21
|
+
*/
|
|
22
|
+
name?: string;
|
|
23
|
+
};
|
|
24
|
+
type InlineSkillInput = {
|
|
25
|
+
type: "inline";
|
|
26
|
+
name: string;
|
|
27
|
+
description: string;
|
|
28
|
+
instructions: string;
|
|
29
|
+
};
|
|
30
|
+
type SkillInput = SandboxSkillInput | HostSkillInput | GitSkillInput | InlineSkillInput;
|
|
31
|
+
type SandboxSkillEntry = {
|
|
32
|
+
type: "sandbox";
|
|
33
|
+
path: string;
|
|
34
|
+
};
|
|
35
|
+
type HostSkillEntry = {
|
|
36
|
+
type: "host";
|
|
37
|
+
path: string;
|
|
38
|
+
};
|
|
39
|
+
type GitSkillEntry = {
|
|
40
|
+
type: "git";
|
|
41
|
+
repo: string;
|
|
42
|
+
ref?: string;
|
|
43
|
+
path?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Skill directory name under `path`.
|
|
46
|
+
*/
|
|
47
|
+
name?: string;
|
|
48
|
+
};
|
|
49
|
+
type InlineSkillEntry = {
|
|
50
|
+
type: "inline";
|
|
51
|
+
name: string;
|
|
52
|
+
description: string;
|
|
53
|
+
instructions: string;
|
|
54
|
+
};
|
|
55
|
+
type SkillEntry = SandboxSkillEntry | HostSkillEntry | GitSkillEntry | InlineSkillEntry;
|
|
56
|
+
|
|
57
|
+
type GenerationOptions = {
|
|
58
|
+
maxSteps?: number;
|
|
59
|
+
temperature?: number;
|
|
60
|
+
topK?: number;
|
|
61
|
+
topP?: number;
|
|
62
|
+
frequencyPenalty?: number;
|
|
63
|
+
presencePenalty?: number;
|
|
64
|
+
maxOutputTokens?: number;
|
|
65
|
+
headers?: Record<string, string>;
|
|
66
|
+
};
|
|
67
|
+
type Session = {
|
|
68
|
+
id: string;
|
|
69
|
+
createdAt: number;
|
|
70
|
+
updatedAt: number;
|
|
71
|
+
model: string | null;
|
|
72
|
+
system: string | null;
|
|
73
|
+
sandboxId: string | null;
|
|
74
|
+
lastMessageId: string | null;
|
|
75
|
+
activeTools: string[] | null;
|
|
76
|
+
skills: SkillInput[] | null;
|
|
77
|
+
generation: GenerationOptions | null;
|
|
78
|
+
};
|
|
79
|
+
type MessageUsage = {
|
|
80
|
+
steps: {
|
|
81
|
+
stepIndex: number;
|
|
82
|
+
model: string;
|
|
83
|
+
inputTokens: number;
|
|
84
|
+
outputTokens: number;
|
|
85
|
+
totalTokens: number;
|
|
86
|
+
cacheReadTokens: number;
|
|
87
|
+
cacheWriteTokens: number;
|
|
88
|
+
reasoningTokens: number;
|
|
89
|
+
}[];
|
|
90
|
+
summary: {
|
|
91
|
+
model: string;
|
|
92
|
+
inputTokens: number;
|
|
93
|
+
outputTokens: number;
|
|
94
|
+
totalTokens: number;
|
|
95
|
+
cacheReadTokens: number;
|
|
96
|
+
cacheWriteTokens: number;
|
|
97
|
+
reasoningTokens: number;
|
|
98
|
+
stepCount: number;
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
type Message = {
|
|
102
|
+
id: string;
|
|
103
|
+
sessionId: string;
|
|
104
|
+
role: "user" | "assistant" | "system";
|
|
105
|
+
createdAt: number;
|
|
106
|
+
startedAt: number | null;
|
|
107
|
+
completedAt: number | null;
|
|
108
|
+
interruptedAt: number | null;
|
|
109
|
+
interruptedLastPart: {
|
|
110
|
+
index: number;
|
|
111
|
+
part: unknown;
|
|
112
|
+
} | null;
|
|
113
|
+
usage: MessageUsage | null;
|
|
114
|
+
workflowRunId?: string | null;
|
|
115
|
+
metadata?: Record<string, unknown> | null;
|
|
116
|
+
};
|
|
117
|
+
type Part = {
|
|
118
|
+
id: string;
|
|
119
|
+
messageId: string;
|
|
120
|
+
sessionId: string;
|
|
121
|
+
index: number;
|
|
122
|
+
part: UIMessage["parts"][number];
|
|
123
|
+
};
|
|
124
|
+
type Sandbox = {
|
|
125
|
+
id: string;
|
|
126
|
+
setup: {
|
|
127
|
+
binding: string;
|
|
128
|
+
version: string | null;
|
|
129
|
+
completedAt: number | null;
|
|
130
|
+
metadata: Record<string, unknown> | null;
|
|
131
|
+
networkPolicy: NetworkPolicy | null;
|
|
132
|
+
};
|
|
133
|
+
createdAt: number | null;
|
|
134
|
+
lastActiveAt: number | null;
|
|
135
|
+
};
|
|
136
|
+
type Setup = {
|
|
137
|
+
version: string;
|
|
138
|
+
snapshotId: string | null;
|
|
139
|
+
createdAt: number;
|
|
140
|
+
lastUsedAt: number | null;
|
|
141
|
+
};
|
|
142
|
+
type SetupSnapshot = Setup;
|
|
143
|
+
|
|
144
|
+
type StorageHandlers = {
|
|
145
|
+
"session.get"(p: {
|
|
146
|
+
id: string;
|
|
147
|
+
}): Promise<Session | null>;
|
|
148
|
+
"session.set"(p: {
|
|
149
|
+
id: string;
|
|
150
|
+
value: Session;
|
|
151
|
+
}): Promise<void>;
|
|
152
|
+
"session.update"(p: {
|
|
153
|
+
id: string;
|
|
154
|
+
updates: Partial<Session>;
|
|
155
|
+
}): Promise<Session>;
|
|
156
|
+
"message.get"(p: {
|
|
157
|
+
id: string;
|
|
158
|
+
}): Promise<Message | null>;
|
|
159
|
+
"message.set"(p: {
|
|
160
|
+
id: string;
|
|
161
|
+
value: Message;
|
|
162
|
+
}): Promise<void>;
|
|
163
|
+
"message.update"(p: {
|
|
164
|
+
id: string;
|
|
165
|
+
updates: Partial<Message>;
|
|
166
|
+
}): Promise<Message>;
|
|
167
|
+
"message.listBySession"(p: {
|
|
168
|
+
sessionId: string;
|
|
169
|
+
}): Promise<Message[]>;
|
|
170
|
+
"part.get"(p: {
|
|
171
|
+
id: string;
|
|
172
|
+
}): Promise<Part | null>;
|
|
173
|
+
"part.set"(p: {
|
|
174
|
+
id: string;
|
|
175
|
+
value: Part;
|
|
176
|
+
}): Promise<void>;
|
|
177
|
+
"part.listBySession"(p: {
|
|
178
|
+
sessionId: string;
|
|
179
|
+
}): Promise<Part[]>;
|
|
180
|
+
"sandbox.get"(p: {
|
|
181
|
+
id: string;
|
|
182
|
+
}): Promise<Sandbox | null>;
|
|
183
|
+
"sandbox.set"(p: {
|
|
184
|
+
id: string;
|
|
185
|
+
value: Sandbox;
|
|
186
|
+
}): Promise<void>;
|
|
187
|
+
"sandbox.update"(p: {
|
|
188
|
+
id: string;
|
|
189
|
+
updates: Partial<Sandbox>;
|
|
190
|
+
}): Promise<Sandbox>;
|
|
191
|
+
"setup.get"(p: {
|
|
192
|
+
id: string;
|
|
193
|
+
}): Promise<Setup | null>;
|
|
194
|
+
"setup.set"(p: {
|
|
195
|
+
id: string;
|
|
196
|
+
value: Setup;
|
|
197
|
+
}): Promise<void>;
|
|
198
|
+
};
|
|
199
|
+
type StorageCall = {
|
|
200
|
+
[K in keyof StorageHandlers]: {
|
|
201
|
+
method: K;
|
|
202
|
+
} & Parameters<StorageHandlers[K]>[0];
|
|
203
|
+
}[keyof StorageHandlers];
|
|
204
|
+
declare class StorageStep {
|
|
205
|
+
event: StorageCall;
|
|
206
|
+
constructor(event: StorageCall);
|
|
207
|
+
static [WORKFLOW_SERIALIZE](instance: StorageStep): {
|
|
208
|
+
event: StorageCall;
|
|
209
|
+
};
|
|
210
|
+
static [WORKFLOW_DESERIALIZE](data: {
|
|
211
|
+
event: StorageCall;
|
|
212
|
+
}): StorageStep;
|
|
213
|
+
on(handlers: StorageHandlers): Promise<any>;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* A single function that handles all storage operations. Intended to be
|
|
217
|
+
* marked with `"use step"` so that its body (and Node.js-dependent
|
|
218
|
+
* imports like database clients) is extracted by the workflow bundler
|
|
219
|
+
* and runs server-side.
|
|
220
|
+
*
|
|
221
|
+
* The step receives a `StorageStep` instance (serializable via
|
|
222
|
+
* `@workflow/serde`) and should call `step.handle({ ... })` with a
|
|
223
|
+
* `StorageHandlers` map.
|
|
224
|
+
*/
|
|
225
|
+
type StorageStepFunction = (store: StorageStep) => Promise<any>;
|
|
226
|
+
interface Storage {
|
|
227
|
+
session: {
|
|
228
|
+
get(key: string): Promise<Session | null>;
|
|
229
|
+
set(key: string, value: Session): Promise<void>;
|
|
230
|
+
update(key: string, updates: Partial<Session>): Promise<Session>;
|
|
231
|
+
};
|
|
232
|
+
message: {
|
|
233
|
+
get(key: string): Promise<Message | null>;
|
|
234
|
+
set(key: string, value: Message): Promise<void>;
|
|
235
|
+
update(key: string, updates: Partial<Message>): Promise<Message>;
|
|
236
|
+
listBySession(sessionId: string): Promise<Message[]>;
|
|
237
|
+
};
|
|
238
|
+
part: {
|
|
239
|
+
get(key: string): Promise<Part | null>;
|
|
240
|
+
set(key: string, value: Part): Promise<void>;
|
|
241
|
+
listBySession(sessionId: string): Promise<Part[]>;
|
|
242
|
+
};
|
|
243
|
+
sandbox: {
|
|
244
|
+
get(key: string): Promise<Sandbox | null>;
|
|
245
|
+
set(key: string, value: Sandbox): Promise<void>;
|
|
246
|
+
update(key: string, updates: Partial<Sandbox>): Promise<Sandbox>;
|
|
247
|
+
};
|
|
248
|
+
setup: {
|
|
249
|
+
get(key: string): Promise<Setup | null>;
|
|
250
|
+
set(key: string, value: Setup): Promise<void>;
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
type StorageInput = StorageHandlers | StorageStepFunction;
|
|
254
|
+
declare function toStorage(h: StorageInput): Storage;
|
|
255
|
+
|
|
256
|
+
export { type GenerationOptions as G, type HostSkillEntry as H, type InlineSkillEntry as I, type Message as M, type Part as P, type StorageHandlers as S, type MessageUsage as a, type Sandbox as b, type Session as c, type Setup as d, type SetupSnapshot as e, type Storage as f, type StorageCall as g, StorageStep as h, type StorageStepFunction as i, type SkillInput as j, type StorageInput as k, type GitSkillEntry as l, type GitSkillInput as m, type HostSkillInput as n, type InlineSkillInput as o, type SandboxSkillEntry as p, type SandboxSkillInput as q, type SkillEntry as r, type SkillSourceType as s, toStorage as t };
|