@minpeter/pss-runtime 0.1.0-next.1 → 0.1.0-next.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 +169 -28
- package/dist/agent-child-runs.js +16 -0
- package/dist/agent-child-runs.js.map +1 -0
- package/dist/agent-host-capabilities.js +9 -0
- package/dist/agent-host-capabilities.js.map +1 -0
- package/dist/agent-host-session-store.js +12 -0
- package/dist/agent-host-session-store.js.map +1 -0
- package/dist/agent-loop.js +58 -28
- package/dist/agent-loop.js.map +1 -1
- package/dist/agent-namespace.js +8 -1
- package/dist/agent-namespace.js.map +1 -1
- package/dist/agent-options.d.ts +35 -0
- package/dist/agent-options.js +16 -0
- package/dist/agent-options.js.map +1 -0
- package/dist/agent-resume.js +143 -0
- package/dist/agent-resume.js.map +1 -0
- package/dist/agent-session-entry.d.ts +13 -0
- package/dist/agent-validation.js +2 -2
- package/dist/agent-validation.js.map +1 -1
- package/dist/agent.d.ts +5 -41
- package/dist/agent.js +81 -49
- package/dist/agent.js.map +1 -1
- package/dist/execution/host.js +14 -0
- package/dist/execution/host.js.map +1 -0
- package/dist/execution/index.d.ts +4 -0
- package/dist/execution/index.js +3 -0
- package/dist/execution/memory-notifications.js +54 -0
- package/dist/execution/memory-notifications.js.map +1 -0
- package/dist/execution/memory-state.js +34 -0
- package/dist/execution/memory-state.js.map +1 -0
- package/dist/execution/memory-store.js +203 -0
- package/dist/execution/memory-store.js.map +1 -0
- package/dist/execution/memory.d.ts +7 -0
- package/dist/execution/memory.js +28 -0
- package/dist/execution/memory.js.map +1 -0
- package/dist/execution/run.js +55 -0
- package/dist/execution/run.js.map +1 -0
- package/dist/execution/types.d.ts +155 -0
- package/dist/index.d.ts +8 -5
- package/dist/llm-tool-execution.d.ts +35 -0
- package/dist/llm-tool-execution.js +126 -0
- package/dist/llm-tool-execution.js.map +1 -0
- package/dist/llm.d.ts +11 -15
- package/dist/llm.js +5 -3
- package/dist/llm.js.map +1 -1
- package/dist/plugins.d.ts +20 -0
- package/dist/plugins.js +14 -0
- package/dist/plugins.js.map +1 -0
- package/dist/session/events.d.ts +3 -0
- package/dist/session/runtime-input.js +5 -23
- package/dist/session/runtime-input.js.map +1 -1
- package/dist/session/session-errors.js +1 -6
- package/dist/session/session-errors.js.map +1 -1
- package/dist/session/session-events.js +59 -0
- package/dist/session/session-events.js.map +1 -0
- package/dist/session/session-execution.js +88 -0
- package/dist/session/session-execution.js.map +1 -0
- package/dist/session/session-notification.js +58 -0
- package/dist/session/session-notification.js.map +1 -0
- package/dist/session/session-runtime-drain.js +2 -2
- package/dist/session/session-runtime-drain.js.map +1 -1
- package/dist/session/session-turn-processor.js +135 -0
- package/dist/session/session-turn-processor.js.map +1 -0
- package/dist/session/session.js +73 -101
- package/dist/session/session.js.map +1 -1
- package/dist/session/snapshot.js.map +1 -1
- package/dist/subagent-background-child-run-state.js +51 -0
- package/dist/subagent-background-child-run-state.js.map +1 -0
- package/dist/subagent-background-child-run.js +103 -0
- package/dist/subagent-background-child-run.js.map +1 -0
- package/dist/subagent-background-in-process.js +98 -0
- package/dist/subagent-background-in-process.js.map +1 -0
- package/dist/subagent-background-notification-inbox.js +106 -0
- package/dist/subagent-background-notification-inbox.js.map +1 -0
- package/dist/subagent-background-notify.js +136 -0
- package/dist/subagent-background-notify.js.map +1 -0
- package/dist/subagent-background-resume-group.js +99 -0
- package/dist/subagent-background-resume-group.js.map +1 -0
- package/dist/subagent-background-runner.js +115 -0
- package/dist/subagent-background-runner.js.map +1 -0
- package/dist/subagent-background-schedule.js +43 -0
- package/dist/subagent-background-schedule.js.map +1 -0
- package/dist/subagent-child-run.js +68 -0
- package/dist/subagent-child-run.js.map +1 -0
- package/dist/subagent-job-cancel.js +60 -4
- package/dist/subagent-job-cancel.js.map +1 -1
- package/dist/subagent-job-observer.js +19 -0
- package/dist/subagent-job-observer.js.map +1 -0
- package/dist/subagent-job-output.js +28 -4
- package/dist/subagent-job-output.js.map +1 -1
- package/dist/subagent-job-state.js +66 -0
- package/dist/subagent-job-state.js.map +1 -0
- package/dist/subagent-jobs.js +78 -133
- package/dist/subagent-jobs.js.map +1 -1
- package/dist/subagent-run.js +4 -4
- package/dist/subagent-run.js.map +1 -1
- package/dist/subagents.js +68 -35
- package/dist/subagents.js.map +1 -1
- package/package.json +11 -1
- package/dist/hooks.d.ts +0 -32
- /package/dist/session/{runtime-input.d.ts → session-execution.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -10,12 +10,31 @@ Minimal, platform-agnostic agent runtime with keyed sessions, synchronized
|
|
|
10
10
|
## Core DX
|
|
11
11
|
|
|
12
12
|
```ts
|
|
13
|
+
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
|
|
13
14
|
import { Agent } from "@minpeter/pss-runtime";
|
|
14
|
-
import {
|
|
15
|
+
import { createEnv } from "@t3-oss/env-core";
|
|
16
|
+
import { config as loadEnv } from "dotenv";
|
|
17
|
+
import { z } from "zod";
|
|
18
|
+
|
|
19
|
+
loadEnv({ path: ".env", quiet: true, override: true });
|
|
20
|
+
const env = createEnv({
|
|
21
|
+
runtimeEnv: process.env,
|
|
22
|
+
server: {
|
|
23
|
+
AI_API_KEY: z.string().trim().min(1),
|
|
24
|
+
AI_BASE_URL: z.url().trim().default("https://apis.opengateway.ai/v1"),
|
|
25
|
+
AI_MODEL: z.string().trim().min(1).default("minimax/MiniMax-M2.7"),
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const provider = createOpenAICompatible({
|
|
30
|
+
name: "custom",
|
|
31
|
+
apiKey: env.AI_API_KEY,
|
|
32
|
+
baseURL: env.AI_BASE_URL,
|
|
33
|
+
});
|
|
15
34
|
|
|
16
35
|
const agent = new Agent({
|
|
17
36
|
instructions: "Answer briefly.",
|
|
18
|
-
model:
|
|
37
|
+
model: provider(env.AI_MODEL),
|
|
19
38
|
});
|
|
20
39
|
|
|
21
40
|
const run = await agent.send("Hello");
|
|
@@ -30,6 +49,23 @@ consume the events for the run to progress. This is what lets code react to
|
|
|
30
49
|
`turn-start`, `step-start`, and `step-end` before the next model snapshot is
|
|
31
50
|
created.
|
|
32
51
|
|
|
52
|
+
`model` is the single public constructor key for model execution. Pass an AI SDK
|
|
53
|
+
`LanguageModel` for the managed runtime path with `instructions`, `tools`, and
|
|
54
|
+
`subagents`, or pass a custom `RuntimeLlm` function when you want to own the model
|
|
55
|
+
adapter yourself:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import { Agent, type RuntimeLlm } from "@minpeter/pss-runtime";
|
|
59
|
+
|
|
60
|
+
const runtimeModel: RuntimeLlm = async ({ history }) => [
|
|
61
|
+
{ role: "assistant", content: `Seen ${history.length} messages.` },
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
const agent = new Agent({
|
|
65
|
+
model: runtimeModel,
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
|
|
33
69
|
Per-key conversations use `session(key)`:
|
|
34
70
|
|
|
35
71
|
```ts
|
|
@@ -117,9 +153,11 @@ delegate_to_researcher({
|
|
|
117
153
|
```
|
|
118
154
|
|
|
119
155
|
When the model sets `run_in_background: true`, the parent run can finish while
|
|
120
|
-
the child keeps working. The launch result includes a `bg_...` `task_id
|
|
121
|
-
|
|
122
|
-
|
|
156
|
+
the child keeps working. The launch result includes a `bg_...` `task_id` and
|
|
157
|
+
tells the model to wait for a `<system-reminder>` before retrieving output.
|
|
158
|
+
When background work finishes, the session is notified with compact runtime
|
|
159
|
+
input. Hosts that support durable background work should resume the parent session
|
|
160
|
+
through the notification inbox and drain the returned `AgentRun`.
|
|
123
161
|
|
|
124
162
|
```ts
|
|
125
163
|
delegate_to_researcher({
|
|
@@ -127,6 +165,7 @@ delegate_to_researcher({
|
|
|
127
165
|
run_in_background: true,
|
|
128
166
|
});
|
|
129
167
|
|
|
168
|
+
// After the completion reminder arrives:
|
|
130
169
|
background_output({ task_id: "bg_...", block: true });
|
|
131
170
|
background_cancel({ task_id: "bg_..." });
|
|
132
171
|
```
|
|
@@ -134,20 +173,38 @@ background_cancel({ task_id: "bg_..." });
|
|
|
134
173
|
The parent model context stays compact by default: completion reminders include
|
|
135
174
|
the task id, subagent name, description, and retrieval instruction. Full child
|
|
136
175
|
traces are not injected into the parent transcript by default. Background jobs
|
|
137
|
-
run in task-scoped child sessions
|
|
138
|
-
|
|
176
|
+
run in task-scoped child sessions. In-memory job handles are cleaned up after
|
|
177
|
+
completed output retrieval, while durable hosts keep compact completed output
|
|
178
|
+
available through the execution store for reconstructed agents. Background jobs
|
|
179
|
+
launched during the same parent turn share an internal completion barrier:
|
|
180
|
+
successful jobs notify once when the group settles, while failed jobs notify
|
|
181
|
+
immediately.
|
|
139
182
|
|
|
140
|
-
## Send and Steer
|
|
183
|
+
## Send, Host Resume, and Steer
|
|
141
184
|
|
|
142
185
|
Use `session.send(input)` for a new user turn. If a run is already active, the
|
|
143
|
-
turn is queued until the active run finishes. Use `session.steer(input)` when
|
|
144
|
-
input should steer the active run; if no run is active, it starts a normal
|
|
186
|
+
turn is queued until the active run finishes. Use `session.steer(input)` when
|
|
187
|
+
the input should steer the active run; if no run is active, it starts a normal
|
|
188
|
+
run.
|
|
189
|
+
|
|
190
|
+
Durable hosts resume completed background work by writing a notification record
|
|
191
|
+
and calling `agent.resume(notificationRunId)`. The resume call claims the
|
|
192
|
+
notification idempotently through its durable run id and returns one `AgentRun`,
|
|
193
|
+
or `null` when a duplicate queue/alarm delivery already claimed it.
|
|
194
|
+
|
|
195
|
+
Runtime-originated input is delivered through the host notification inbox and
|
|
196
|
+
internal plugin paths. App code should use `session.send()`, `session.steer()`,
|
|
197
|
+
or `agent.resume(runId)` for host-scheduled durable work.
|
|
145
198
|
|
|
146
|
-
|
|
199
|
+
Each accepted call returns one `AgentRun`. Drain that run's `events()` stream to
|
|
200
|
+
observe the turn; each `AgentRun.events()` stream is single-consumer.
|
|
201
|
+
|
|
202
|
+
Input APIs accept the same input shapes: strings, arrays of strings,
|
|
147
203
|
`{ type: "user-text", text }`, and multipart `{ type: "user-message", content }`
|
|
148
|
-
values. Active steering
|
|
149
|
-
runtime/API-originated input mapped internally to the model's
|
|
150
|
-
distinct from human-origin `user-text` and `user-message`
|
|
204
|
+
values. Active steering and host resume input emit `runtime-input` events. A
|
|
205
|
+
`runtime-input` is runtime/API-originated input mapped internally to the model's
|
|
206
|
+
user role. It is distinct from human-origin `user-text` and `user-message`
|
|
207
|
+
events.
|
|
151
208
|
|
|
152
209
|
Runtime input windows are tied to synchronized events:
|
|
153
210
|
|
|
@@ -188,6 +245,10 @@ Stored session state is an opaque, versioned runtime snapshot for continuation.
|
|
|
188
245
|
Do not inspect it as a replay log; exact replay should be modeled separately as
|
|
189
246
|
an `AgentEvent` log if that capability is added later.
|
|
190
247
|
|
|
248
|
+
`SessionStore` is snapshot-only. It does not own background task ids, run
|
|
249
|
+
leases, checkpoints, notification inbox state, or scheduling. Those live on the
|
|
250
|
+
optional `host` execution contract.
|
|
251
|
+
|
|
191
252
|
Custom stores own version generation. `load(key)` returns the opaque `state` with
|
|
192
253
|
the store-minted `version`; `commit(key, { state }, { expectedVersion })` receives
|
|
193
254
|
state only and should reject stale versions by returning `{ ok: false, reason:
|
|
@@ -196,15 +257,14 @@ new version to the runtime. `delete(key)` removes the persisted session for that
|
|
|
196
257
|
key.
|
|
197
258
|
|
|
198
259
|
```ts
|
|
199
|
-
import type { SessionStore } from "@minpeter/pss-runtime";
|
|
200
260
|
import { MemorySessionStore } from "@minpeter/pss-runtime/session-store/memory";
|
|
201
261
|
|
|
202
262
|
const agent = new Agent({
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
namespace: "support-agent",
|
|
206
|
-
store: new MemorySessionStore(), // default when omitted
|
|
263
|
+
host: {
|
|
264
|
+
sessionStore: new MemorySessionStore(), // default when omitted
|
|
207
265
|
},
|
|
266
|
+
model,
|
|
267
|
+
namespace: "support-agent",
|
|
208
268
|
});
|
|
209
269
|
```
|
|
210
270
|
|
|
@@ -216,17 +276,65 @@ session and child `sessionKey` suffixes back to the same child transcripts:
|
|
|
216
276
|
import { FileSessionStore } from "@minpeter/pss-runtime/session-store/file";
|
|
217
277
|
|
|
218
278
|
const agent = new Agent({
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
namespace: "support-agent",
|
|
222
|
-
store: new FileSessionStore(".pss/sessions"),
|
|
279
|
+
host: {
|
|
280
|
+
sessionStore: new FileSessionStore(".pss/sessions"),
|
|
223
281
|
},
|
|
282
|
+
model,
|
|
283
|
+
namespace: "support-agent",
|
|
224
284
|
});
|
|
225
285
|
```
|
|
226
286
|
|
|
227
|
-
|
|
287
|
+
Hosts that need durable runs pass `host:` into `Agent`. A durable host owns
|
|
288
|
+
execution state, scheduling, and its session snapshot store through
|
|
289
|
+
`store.sessions`; `ExecutionHost` does not accept a separate `sessionStore`
|
|
290
|
+
override.
|
|
291
|
+
|
|
292
|
+
```ts
|
|
293
|
+
import { Agent } from "@minpeter/pss-runtime";
|
|
294
|
+
import {
|
|
295
|
+
createInMemoryExecutionHost,
|
|
296
|
+
type ExecutionHost,
|
|
297
|
+
} from "@minpeter/pss-runtime/execution";
|
|
298
|
+
|
|
299
|
+
const host = createInMemoryExecutionHost();
|
|
300
|
+
|
|
301
|
+
const agent = new Agent({
|
|
302
|
+
host,
|
|
303
|
+
model,
|
|
304
|
+
namespace: "support-agent",
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
const durableHost: ExecutionHost = {
|
|
308
|
+
capabilities: { backgroundSubagents: "durable" },
|
|
309
|
+
scheduler,
|
|
310
|
+
store,
|
|
311
|
+
};
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
## Supported Deployment Shapes
|
|
315
|
+
|
|
316
|
+
The runtime supports both long-running Node.js processes and edge hosts that
|
|
317
|
+
reconstruct runtime objects between turns. The same public DX stays centered on
|
|
318
|
+
`new Agent({ subagents: [...] })`; host-specific durability and scheduling live
|
|
319
|
+
behind the `host` boundary.
|
|
320
|
+
|
|
321
|
+
Long-running Node.js can keep an `Agent` and `SessionHandle` alive across turns.
|
|
322
|
+
The default in-memory host advertises in-process background subagent capability,
|
|
323
|
+
so `run_in_background`, `background_output`, and `background_cancel` remain
|
|
324
|
+
available while that process owns the work. `FileSessionStore` persists session
|
|
325
|
+
snapshots only; it does not make background work durable by itself.
|
|
326
|
+
|
|
327
|
+
Cloudflare Durable Objects and similar edge hosts should reconstruct `Agent`
|
|
328
|
+
objects per turn and persist opaque session state through `store.sessions`.
|
|
329
|
+
When a host does not advertise background subagent capability, the runtime hides
|
|
330
|
+
background tools from the parent model and exposes blocking delegation only.
|
|
331
|
+
This avoids pretending that in-memory background work survived a hibernation,
|
|
332
|
+
isolate restart, or request deadline.
|
|
333
|
+
|
|
334
|
+
See `examples/cloudflare-edge-subagent` for an edge-hosted turn loop with a
|
|
335
|
+
Worker/Durable Object-shaped host, and `examples/subagent` for a long-running
|
|
336
|
+
local background subagent flow.
|
|
228
337
|
|
|
229
|
-
Cloudflare Durable Objects are a future adapter target, not a runtime dependency.
|
|
230
338
|
The same core API supports room/user/session routing through stable session keys.
|
|
231
339
|
|
|
232
340
|
Recommended key patterns:
|
|
@@ -235,6 +343,39 @@ Recommended key patterns:
|
|
|
235
343
|
- Per-user memory inside room: `room:<roomId>:user:<userId>`
|
|
236
344
|
- Ticketed workspace flows: `tenant:<tenantId>:ticket:<ticketId>`
|
|
237
345
|
|
|
238
|
-
In a Durable Object, map the
|
|
239
|
-
durable across hibernation/restores, while in-memory state remains
|
|
240
|
-
Do not store canonical agent session state in memory
|
|
346
|
+
In a Durable Object, map the execution store contract to `ctx.storage` so DO
|
|
347
|
+
storage is durable across hibernation/restores, while in-memory state remains
|
|
348
|
+
request-local. Do not store canonical agent session or run state in memory
|
|
349
|
+
attachments.
|
|
350
|
+
|
|
351
|
+
Durable background subagents require a host capability that owns task ids,
|
|
352
|
+
attempts, leases, checkpoints, cancellation, scheduling, and completion
|
|
353
|
+
notifications. The Cloudflare edge example includes a Worker/Durable
|
|
354
|
+
Object-shaped host that persists scheduled runs and session prompts, sets alarms, and
|
|
355
|
+
resumes work through `Agent.resume(...)`.
|
|
356
|
+
|
|
357
|
+
## Checkpoints and Cancellation
|
|
358
|
+
|
|
359
|
+
Resume is safe only at committed boundaries. Durable hosts can checkpoint before
|
|
360
|
+
and after model steps, around notifications, before child run creation, when a
|
|
361
|
+
child link is committed, and when a run suspends. If a process is killed inside a
|
|
362
|
+
provider call or unsafe tool execution, resume rolls back to the last committed
|
|
363
|
+
checkpoint and may re-enter the operation.
|
|
364
|
+
|
|
365
|
+
When `Agent` receives an `ExecutionHost`, high-level model turns create a
|
|
366
|
+
`user-turn` run record and thread tool execution context into managed model
|
|
367
|
+
calls. Tools are checkpointed before and after execution and receive stable
|
|
368
|
+
`attempt`, `idempotencyKey`, `retryPolicy`, `signal`, and public `toolCallId`
|
|
369
|
+
values. The `@minpeter/pss-runtime/execution` entrypoint also exposes the same
|
|
370
|
+
low-level tool execution checkpoint types for custom resume runners built
|
|
371
|
+
directly on `createLlm`.
|
|
372
|
+
|
|
373
|
+
These checkpoints are rollback boundaries, not a complete host adapter by
|
|
374
|
+
themselves. Edge hosts still need durable scheduling, leases, resume workers,
|
|
375
|
+
and notification resume handling; externally visible side-effect tools still need
|
|
376
|
+
idempotent execution or a manual recovery flow.
|
|
377
|
+
|
|
378
|
+
Cancellation is persisted before aborting active work. Parent `delete()` and
|
|
379
|
+
`kill()` mark linked child runs as `cancelled` through the execution store before
|
|
380
|
+
falling back to process-local cleanup, so stale child completions cannot enqueue
|
|
381
|
+
new parent notifications.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { executionHost } from "./execution/host.js";
|
|
2
|
+
import { cancelBackgroundChildRun } from "./subagent-background-child-run.js";
|
|
3
|
+
//#region src/agent-child-runs.ts
|
|
4
|
+
async function cancelDurableChildRuns(host, parentRunId) {
|
|
5
|
+
const durableHost = executionHost(host);
|
|
6
|
+
if (!durableHost) return;
|
|
7
|
+
const childRuns = await durableHost.store.runs.listByParentRunId(parentRunId);
|
|
8
|
+
await Promise.all(childRuns.map((run) => cancelBackgroundChildRun({
|
|
9
|
+
executionHost: durableHost,
|
|
10
|
+
runId: run.runId
|
|
11
|
+
})));
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { cancelDurableChildRuns };
|
|
15
|
+
|
|
16
|
+
//# sourceMappingURL=agent-child-runs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-child-runs.js","names":[],"sources":["../src/agent-child-runs.ts"],"sourcesContent":["import { executionHost } from \"./execution/host\";\nimport type { AgentHost } from \"./execution/types\";\nimport { cancelBackgroundChildRun } from \"./subagent-background-child-run\";\n\nexport async function cancelDurableChildRuns(\n host: AgentHost,\n parentRunId: string\n): Promise<void> {\n const durableHost = executionHost(host);\n if (!durableHost) {\n return;\n }\n\n const childRuns = await durableHost.store.runs.listByParentRunId(parentRunId);\n await Promise.all(\n childRuns.map((run) =>\n cancelBackgroundChildRun({\n executionHost: durableHost,\n runId: run.runId,\n })\n )\n );\n}\n"],"mappings":";;;AAIA,eAAsB,uBACpB,MACA,aACe;CACf,MAAM,cAAc,cAAc,IAAI;CACtC,IAAI,CAAC,aACH;CAGF,MAAM,YAAY,MAAM,YAAY,MAAM,KAAK,kBAAkB,WAAW;CAC5E,MAAM,QAAQ,IACZ,UAAU,KAAK,QACb,yBAAyB;EACvB,eAAe;EACf,OAAO,IAAI;CACb,CAAC,CACH,CACF;AACF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region src/agent-host-capabilities.ts
|
|
2
|
+
function supportsBackgroundSubagents(host, executionHost) {
|
|
3
|
+
const capability = host.capabilities?.backgroundSubagents;
|
|
4
|
+
return capability === "in-process" || capability === "durable" && executionHost !== void 0;
|
|
5
|
+
}
|
|
6
|
+
//#endregion
|
|
7
|
+
export { supportsBackgroundSubagents };
|
|
8
|
+
|
|
9
|
+
//# sourceMappingURL=agent-host-capabilities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-host-capabilities.js","names":[],"sources":["../src/agent-host-capabilities.ts"],"sourcesContent":["import type { AgentHost, ExecutionHost } from \"./execution/types\";\n\nexport function supportsBackgroundSubagents(\n host: AgentHost,\n executionHost: ExecutionHost | undefined\n): boolean {\n const capability = host.capabilities?.backgroundSubagents;\n return (\n capability === \"in-process\" ||\n (capability === \"durable\" && executionHost !== undefined)\n );\n}\n"],"mappings":";AAEA,SAAgB,4BACd,MACA,eACS;CACT,MAAM,aAAa,KAAK,cAAc;CACtC,OACE,eAAe,gBACd,eAAe,aAAa,kBAAkB,KAAA;AAEnD"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { executionHost } from "./execution/host.js";
|
|
2
|
+
import { MemorySessionStore } from "./session/store/memory.js";
|
|
3
|
+
//#region src/agent-host-session-store.ts
|
|
4
|
+
function sessionStoreForHost(host) {
|
|
5
|
+
if ("sessionStore" in host && host.sessionStore) return host.sessionStore;
|
|
6
|
+
const hostExecution = executionHost(host);
|
|
7
|
+
return hostExecution ? hostExecution.store.sessions : new MemorySessionStore();
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
10
|
+
export { sessionStoreForHost };
|
|
11
|
+
|
|
12
|
+
//# sourceMappingURL=agent-host-session-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-host-session-store.js","names":[],"sources":["../src/agent-host-session-store.ts"],"sourcesContent":["import { executionHost } from \"./execution/host\";\nimport type { AgentHost } from \"./execution/types\";\nimport { MemorySessionStore } from \"./session/store/memory\";\nimport type { SessionStore } from \"./session/store/types\";\n\nexport function sessionStoreForHost(host: AgentHost): SessionStore {\n if (\"sessionStore\" in host && host.sessionStore) {\n return host.sessionStore;\n }\n\n const hostExecution = executionHost(host);\n return hostExecution\n ? hostExecution.store.sessions\n : new MemorySessionStore();\n}\n"],"mappings":";;;AAKA,SAAgB,oBAAoB,MAA+B;CACjE,IAAI,kBAAkB,QAAQ,KAAK,cACjC,OAAO,KAAK;CAGd,MAAM,gBAAgB,cAAc,IAAI;CACxC,OAAO,gBACH,cAAc,MAAM,WACpB,IAAI,mBAAmB;AAC7B"}
|
package/dist/agent-loop.js
CHANGED
|
@@ -1,39 +1,29 @@
|
|
|
1
1
|
import { modelMessageToAgentEvents } from "./session/mapping.js";
|
|
2
2
|
//#region src/agent-loop.ts
|
|
3
|
-
async function runAgentLoop({ emit, history,
|
|
4
|
-
let stepIndex = 0;
|
|
3
|
+
async function runAgentLoop({ captureObserverEvents = captureNoObserverEvents, emit, history, llm, signal = new AbortController().signal, toolExecution }) {
|
|
5
4
|
while (true) {
|
|
6
|
-
if (signal.aborted) return "aborted";
|
|
7
|
-
await hooks?.beforeStep?.({
|
|
8
|
-
history: history.modelSnapshot(),
|
|
9
|
-
signal,
|
|
10
|
-
stepIndex
|
|
11
|
-
});
|
|
12
5
|
if (signal.aborted) return "aborted";
|
|
13
6
|
if (await emitBoundary({
|
|
14
7
|
emit,
|
|
15
8
|
event: { type: "step-start" },
|
|
16
9
|
signal
|
|
17
10
|
}) === "aborted") return "aborted";
|
|
18
|
-
const
|
|
11
|
+
const capturedOutput = await captureObserverEvents(() => readLlmOutput({
|
|
19
12
|
history,
|
|
20
13
|
llm,
|
|
21
|
-
signal
|
|
22
|
-
|
|
14
|
+
signal,
|
|
15
|
+
toolExecution
|
|
16
|
+
}));
|
|
17
|
+
const output = capturedOutput.value;
|
|
23
18
|
if (output === "aborted") return "aborted";
|
|
24
|
-
const result =
|
|
19
|
+
const result = await appendCapturedStepOutput({
|
|
20
|
+
capturedOutput,
|
|
25
21
|
emit,
|
|
26
22
|
history,
|
|
27
23
|
output,
|
|
28
24
|
signal
|
|
29
25
|
});
|
|
30
26
|
if (result === "aborted") return "aborted";
|
|
31
|
-
await runAfterStepHook(hooks, {
|
|
32
|
-
history: history.modelSnapshot(),
|
|
33
|
-
result,
|
|
34
|
-
signal,
|
|
35
|
-
stepIndex
|
|
36
|
-
});
|
|
37
27
|
const stepEndDecision = await emitBoundary({
|
|
38
28
|
emit,
|
|
39
29
|
event: { type: "step-end" },
|
|
@@ -41,7 +31,6 @@ async function runAgentLoop({ emit, history, hooks, llm, signal = new AbortContr
|
|
|
41
31
|
});
|
|
42
32
|
if (stepEndDecision === "aborted") return "aborted";
|
|
43
33
|
if (result === "completed" && !stepEndDecision?.runtimeInputAdded) return "completed";
|
|
44
|
-
stepIndex += 1;
|
|
45
34
|
}
|
|
46
35
|
}
|
|
47
36
|
async function emitBoundary({ emit, event, signal }) {
|
|
@@ -68,34 +57,75 @@ function createAbortBoundary(signal) {
|
|
|
68
57
|
promise
|
|
69
58
|
};
|
|
70
59
|
}
|
|
71
|
-
async function
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
60
|
+
async function captureNoObserverEvents(callback) {
|
|
61
|
+
return {
|
|
62
|
+
events: [],
|
|
63
|
+
release: releaseNoObserverEvents,
|
|
64
|
+
value: await callback()
|
|
65
|
+
};
|
|
75
66
|
}
|
|
76
|
-
|
|
67
|
+
function releaseNoObserverEvents() {}
|
|
68
|
+
async function readLlmOutput({ history, llm, signal, toolExecution }) {
|
|
77
69
|
try {
|
|
78
70
|
return await llm({
|
|
79
71
|
history: history.modelSnapshot(),
|
|
80
|
-
signal
|
|
72
|
+
signal,
|
|
73
|
+
toolExecution
|
|
81
74
|
});
|
|
82
75
|
} catch (error) {
|
|
83
76
|
if (signal.aborted) return "aborted";
|
|
84
77
|
throw error;
|
|
85
78
|
}
|
|
86
79
|
}
|
|
87
|
-
function
|
|
80
|
+
async function appendCapturedStepOutput({ capturedOutput, emit, history, output, signal }) {
|
|
81
|
+
try {
|
|
82
|
+
return await appendStepOutput({
|
|
83
|
+
emit,
|
|
84
|
+
history,
|
|
85
|
+
observerEvents: capturedOutput.events,
|
|
86
|
+
output,
|
|
87
|
+
signal
|
|
88
|
+
});
|
|
89
|
+
} finally {
|
|
90
|
+
capturedOutput.release();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async function appendStepOutput({ emit, history, observerEvents, output, signal }) {
|
|
88
94
|
if (signal.aborted) return "aborted";
|
|
89
95
|
let shouldContinue = false;
|
|
96
|
+
const pendingObserverEvents = observerEvents;
|
|
97
|
+
const flushObserverEvents = async (shouldFlush = () => true) => {
|
|
98
|
+
for (let index = 0; index < pendingObserverEvents.length;) {
|
|
99
|
+
const event = pendingObserverEvents[index];
|
|
100
|
+
if (!(event && shouldFlush(event))) {
|
|
101
|
+
index += 1;
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
pendingObserverEvents.splice(index, 1);
|
|
105
|
+
await emit(event);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
90
108
|
for (const message of output) {
|
|
91
109
|
if (signal.aborted) return "aborted";
|
|
92
110
|
history.appendModelMessage(message);
|
|
93
111
|
const events = modelMessageToAgentEvents(message);
|
|
94
|
-
|
|
95
|
-
|
|
112
|
+
const hasToolResult = events.some((event) => event.type === "tool-result");
|
|
113
|
+
for (const event of events) {
|
|
114
|
+
await emit(event);
|
|
115
|
+
if (event.type === "tool-call") {
|
|
116
|
+
shouldContinue = true;
|
|
117
|
+
await flushObserverEvents(isLaunchOrBlockingObserverEvent);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (hasToolResult) await flushObserverEvents();
|
|
96
121
|
}
|
|
122
|
+
await flushObserverEvents();
|
|
97
123
|
return shouldContinue ? "continue" : "completed";
|
|
98
124
|
}
|
|
125
|
+
function isLaunchOrBlockingObserverEvent(event) {
|
|
126
|
+
if (event.type === "subagent-job-update") return false;
|
|
127
|
+
return !(event.type === "subagent-job-end" && event.task_id);
|
|
128
|
+
}
|
|
99
129
|
//#endregion
|
|
100
130
|
export { runAgentLoop };
|
|
101
131
|
|
package/dist/agent-loop.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-loop.js","names":[],"sources":["../src/agent-loop.ts"],"sourcesContent":["import type { ModelMessage } from \"ai\";\nimport type {
|
|
1
|
+
{"version":3,"file":"agent-loop.js","names":[],"sources":["../src/agent-loop.ts"],"sourcesContent":["import type { ModelMessage } from \"ai\";\nimport type { RuntimeLlm, RuntimeLlmOutput } from \"./llm\";\nimport type { RuntimeToolExecutionContext } from \"./llm-tool-execution\";\nimport type { AgentEvent } from \"./session/events\";\nimport { modelMessageToAgentEvents } from \"./session/mapping\";\n\ninterface ModelHistory {\n appendModelMessage(message: ModelMessage): void;\n modelSnapshot(): ModelMessage[];\n}\n\ninterface RunAgentLoopOptions {\n captureObserverEvents?: ObserverEventCapture;\n emit: AgentLoopEventListener;\n history: ModelHistory;\n llm: RuntimeLlm;\n signal?: AbortSignal;\n toolExecution?: RuntimeToolExecutionContext;\n}\n\ntype AgentLoopResult = \"completed\" | \"aborted\";\ntype AgentLoopBoundaryEvent = Extract<\n AgentEvent,\n { type: \"step-end\" } | { type: \"step-start\" }\n>;\ninterface AgentLoopBoundaryDecision {\n readonly runtimeInputAdded?: boolean;\n}\ntype AgentLoopEventListener = (\n event: AgentEvent\n) =>\n | AgentLoopBoundaryDecision\n | Promise<AgentLoopBoundaryDecision | undefined>\n | undefined;\ntype StepOutputResult = \"aborted\" | \"completed\" | \"continue\";\ninterface ObserverEventCaptureResult<T> {\n readonly events: AgentEvent[];\n readonly release: () => void;\n readonly value: T;\n}\ntype ObserverEventCapture = <T>(\n callback: () => Promise<T>\n) => Promise<ObserverEventCaptureResult<T>>;\n\nexport async function runAgentLoop({\n captureObserverEvents = captureNoObserverEvents,\n emit,\n history,\n llm,\n signal = new AbortController().signal,\n toolExecution,\n}: RunAgentLoopOptions): Promise<AgentLoopResult> {\n while (true) {\n if (signal.aborted) {\n return \"aborted\";\n }\n\n const stepStartDecision = await emitBoundary({\n emit,\n event: { type: \"step-start\" },\n signal,\n });\n\n if (stepStartDecision === \"aborted\") {\n return \"aborted\";\n }\n\n const capturedOutput = await captureObserverEvents(() =>\n readLlmOutput({ history, llm, signal, toolExecution })\n );\n const output = capturedOutput.value;\n\n if (output === \"aborted\") {\n return \"aborted\";\n }\n\n const result = await appendCapturedStepOutput({\n capturedOutput,\n emit,\n history,\n output,\n signal,\n });\n\n if (result === \"aborted\") {\n return \"aborted\";\n }\n\n const stepEndDecision = await emitBoundary({\n emit,\n event: { type: \"step-end\" },\n signal,\n });\n\n if (stepEndDecision === \"aborted\") {\n return \"aborted\";\n }\n\n // Runtime input after step-end intentionally forces another inference step,\n // even after final-looking assistant text. Unconditional insertion on every\n // step-end can create an unbounded loop.\n if (result === \"completed\" && !stepEndDecision?.runtimeInputAdded) {\n return \"completed\";\n }\n }\n}\n\nasync function emitBoundary({\n emit,\n event,\n signal,\n}: Pick<RunAgentLoopOptions, \"emit\"> & {\n event: AgentLoopBoundaryEvent;\n signal: AbortSignal;\n}): Promise<AgentLoopBoundaryDecision | \"aborted\" | undefined> {\n if (signal.aborted) {\n return \"aborted\";\n }\n\n const abort = createAbortBoundary(signal);\n try {\n return await Promise.race([Promise.resolve(emit(event)), abort.promise]);\n } catch (error) {\n if (signal.aborted) {\n return \"aborted\";\n }\n\n throw error;\n } finally {\n abort.dispose();\n }\n}\n\nfunction createAbortBoundary(signal: AbortSignal): {\n dispose: () => void;\n promise: Promise<\"aborted\">;\n} {\n let dispose: () => void = () => undefined;\n\n const promise = new Promise<\"aborted\">((resolve) => {\n const onAbort = () => resolve(\"aborted\");\n dispose = () => signal.removeEventListener(\"abort\", onAbort);\n signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n\n return { dispose, promise };\n}\n\nasync function captureNoObserverEvents<T>(callback: () => Promise<T>): Promise<{\n readonly events: AgentEvent[];\n readonly release: () => void;\n readonly value: T;\n}> {\n return {\n events: [],\n release: releaseNoObserverEvents,\n value: await callback(),\n };\n}\n\nfunction releaseNoObserverEvents(): void {\n return;\n}\n\nasync function readLlmOutput({\n history,\n llm,\n signal,\n toolExecution,\n}: Pick<RunAgentLoopOptions, \"history\" | \"llm\"> & {\n signal: AbortSignal;\n toolExecution?: RuntimeToolExecutionContext;\n}): Promise<RuntimeLlmOutput | \"aborted\"> {\n try {\n return await llm({\n history: history.modelSnapshot(),\n signal,\n toolExecution,\n });\n } catch (error) {\n if (signal.aborted) {\n return \"aborted\";\n }\n\n throw error;\n }\n}\n\nasync function appendCapturedStepOutput({\n capturedOutput,\n emit,\n history,\n output,\n signal,\n}: Pick<RunAgentLoopOptions, \"emit\"> & { history: ModelHistory } & {\n capturedOutput: ObserverEventCaptureResult<RuntimeLlmOutput | \"aborted\">;\n output: RuntimeLlmOutput;\n signal: AbortSignal;\n}): Promise<StepOutputResult> {\n try {\n return await appendStepOutput({\n emit,\n history,\n observerEvents: capturedOutput.events,\n output,\n signal,\n });\n } finally {\n capturedOutput.release();\n }\n}\n\nasync function appendStepOutput({\n emit,\n history,\n observerEvents,\n output,\n signal,\n}: Pick<RunAgentLoopOptions, \"emit\"> & { history: ModelHistory } & {\n observerEvents: AgentEvent[];\n output: RuntimeLlmOutput;\n signal: AbortSignal;\n}): Promise<StepOutputResult> {\n if (signal.aborted) {\n return \"aborted\";\n }\n\n let shouldContinue = false;\n const pendingObserverEvents = observerEvents;\n const flushObserverEvents = async (\n shouldFlush: (event: AgentEvent) => boolean = () => true\n ) => {\n for (let index = 0; index < pendingObserverEvents.length; ) {\n const event = pendingObserverEvents[index];\n if (!(event && shouldFlush(event))) {\n index += 1;\n continue;\n }\n pendingObserverEvents.splice(index, 1);\n await emit(event);\n }\n };\n\n for (const message of output) {\n if (signal.aborted) {\n return \"aborted\";\n }\n\n history.appendModelMessage(message);\n const events = modelMessageToAgentEvents(message);\n const hasToolResult = events.some((event) => event.type === \"tool-result\");\n\n for (const event of events) {\n await emit(event);\n if (event.type === \"tool-call\") {\n shouldContinue = true;\n await flushObserverEvents(isLaunchOrBlockingObserverEvent);\n }\n }\n\n if (hasToolResult) {\n await flushObserverEvents();\n }\n }\n\n await flushObserverEvents();\n\n return shouldContinue ? \"continue\" : \"completed\";\n}\n\nfunction isLaunchOrBlockingObserverEvent(event: AgentEvent): boolean {\n if (event.type === \"subagent-job-update\") {\n return false;\n }\n\n return !(event.type === \"subagent-job-end\" && event.task_id);\n}\n"],"mappings":"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"}
|
package/dist/agent-namespace.js
CHANGED
|
@@ -11,7 +11,14 @@ function namespacePart(value) {
|
|
|
11
11
|
function parentSessionNamespace({ generation, sessionKey, sessionNamespace }) {
|
|
12
12
|
return `${sessionNamespace}:session:${namespacePart(sessionKey)}:generation:${generation}`;
|
|
13
13
|
}
|
|
14
|
+
function ownsAgentNamespace(ownerNamespace, sessionNamespace) {
|
|
15
|
+
return ownerNamespace === sessionNamespace || ownerNamespace?.startsWith(`${sessionNamespace}:session:`) === true;
|
|
16
|
+
}
|
|
17
|
+
function stableAgentNamespace({ name, namespace }) {
|
|
18
|
+
const stableNamespace = namespace ?? name;
|
|
19
|
+
return stableNamespace ? agentNamespace(stableNamespace) : randomAgentNamespace();
|
|
20
|
+
}
|
|
14
21
|
//#endregion
|
|
15
|
-
export {
|
|
22
|
+
export { ownsAgentNamespace, parentSessionNamespace, stableAgentNamespace };
|
|
16
23
|
|
|
17
24
|
//# sourceMappingURL=agent-namespace.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-namespace.js","names":[],"sources":["../src/agent-namespace.ts"],"sourcesContent":["export function randomAgentNamespace(): string {\n return agentNamespace(crypto.randomUUID());\n}\n\nexport function agentNamespace(namespace: string): string {\n return `agent:${namespacePart(namespace)}`;\n}\n\nexport function namespacePart(value: string): string {\n return encodeURIComponent(value);\n}\n\nexport function parentSessionNamespace({\n generation,\n sessionKey,\n sessionNamespace,\n}: {\n readonly generation: number;\n readonly sessionKey: string;\n readonly sessionNamespace: string;\n}): string {\n return `${sessionNamespace}:session:${namespacePart(\n sessionKey\n )}:generation:${generation}`;\n}\n"],"mappings":";AAAA,SAAgB,uBAA+B;CAC7C,OAAO,eAAe,OAAO,WAAW,CAAC;AAC3C;AAEA,SAAgB,eAAe,WAA2B;CACxD,OAAO,SAAS,cAAc,SAAS;AACzC;AAEA,SAAgB,cAAc,OAAuB;CACnD,OAAO,mBAAmB,KAAK;AACjC;AAEA,SAAgB,uBAAuB,EACrC,YACA,YACA,oBAKS;CACT,OAAO,GAAG,iBAAiB,WAAW,cACpC,UACF,EAAE,cAAc;AAClB"}
|
|
1
|
+
{"version":3,"file":"agent-namespace.js","names":[],"sources":["../src/agent-namespace.ts"],"sourcesContent":["export function randomAgentNamespace(): string {\n return agentNamespace(crypto.randomUUID());\n}\n\nexport function agentNamespace(namespace: string): string {\n return `agent:${namespacePart(namespace)}`;\n}\n\nexport function namespacePart(value: string): string {\n return encodeURIComponent(value);\n}\n\nexport function parentSessionNamespace({\n generation,\n sessionKey,\n sessionNamespace,\n}: {\n readonly generation: number;\n readonly sessionKey: string;\n readonly sessionNamespace: string;\n}): string {\n return `${sessionNamespace}:session:${namespacePart(\n sessionKey\n )}:generation:${generation}`;\n}\n\nexport function ownsAgentNamespace(\n ownerNamespace: string | undefined,\n sessionNamespace: string\n): boolean {\n return (\n ownerNamespace === sessionNamespace ||\n ownerNamespace?.startsWith(`${sessionNamespace}:session:`) === true\n );\n}\n\nexport function stableAgentNamespace({\n name,\n namespace,\n}: {\n readonly name?: string;\n readonly namespace?: string;\n}): string {\n const stableNamespace = namespace ?? name;\n return stableNamespace\n ? agentNamespace(stableNamespace)\n : randomAgentNamespace();\n}\n"],"mappings":";AAAA,SAAgB,uBAA+B;CAC7C,OAAO,eAAe,OAAO,WAAW,CAAC;AAC3C;AAEA,SAAgB,eAAe,WAA2B;CACxD,OAAO,SAAS,cAAc,SAAS;AACzC;AAEA,SAAgB,cAAc,OAAuB;CACnD,OAAO,mBAAmB,KAAK;AACjC;AAEA,SAAgB,uBAAuB,EACrC,YACA,YACA,oBAKS;CACT,OAAO,GAAG,iBAAiB,WAAW,cACpC,UACF,EAAE,cAAc;AAClB;AAEA,SAAgB,mBACd,gBACA,kBACS;CACT,OACE,mBAAmB,oBACnB,gBAAgB,WAAW,GAAG,iBAAiB,UAAU,MAAM;AAEnE;AAEA,SAAgB,qBAAqB,EACnC,MACA,aAIS;CACT,MAAM,kBAAkB,aAAa;CACrC,OAAO,kBACH,eAAe,eAAe,IAC9B,qBAAqB;AAC3B"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { AgentToolChoice, RuntimeLlm } from "./llm.js";
|
|
2
|
+
import { AgentHost } from "./execution/types.js";
|
|
3
|
+
import { AgentPlugin } from "./plugins.js";
|
|
4
|
+
import { Agent } from "./agent.js";
|
|
5
|
+
import { LanguageModel, ToolSet } from "ai";
|
|
6
|
+
|
|
7
|
+
//#region src/agent-options.d.ts
|
|
8
|
+
interface AgentLanguageModelOptions {
|
|
9
|
+
readonly description?: string;
|
|
10
|
+
readonly host?: AgentHost;
|
|
11
|
+
readonly instructions?: string;
|
|
12
|
+
readonly model: LanguageModel;
|
|
13
|
+
readonly name?: string;
|
|
14
|
+
readonly namespace?: string;
|
|
15
|
+
readonly plugins?: readonly AgentPlugin[];
|
|
16
|
+
readonly subagents?: readonly Agent[];
|
|
17
|
+
readonly toolChoice?: AgentToolChoice;
|
|
18
|
+
readonly tools?: ToolSet;
|
|
19
|
+
}
|
|
20
|
+
interface AgentRuntimeModelOptions {
|
|
21
|
+
readonly description?: string;
|
|
22
|
+
readonly host?: AgentHost;
|
|
23
|
+
readonly instructions?: never;
|
|
24
|
+
readonly model: RuntimeLlm;
|
|
25
|
+
readonly name?: string;
|
|
26
|
+
readonly namespace?: string;
|
|
27
|
+
readonly plugins?: readonly AgentPlugin[];
|
|
28
|
+
readonly subagents?: never;
|
|
29
|
+
readonly toolChoice?: never;
|
|
30
|
+
readonly tools?: never;
|
|
31
|
+
}
|
|
32
|
+
type AgentOptions = AgentLanguageModelOptions | AgentRuntimeModelOptions;
|
|
33
|
+
//#endregion
|
|
34
|
+
export { AgentOptions };
|
|
35
|
+
//# sourceMappingURL=agent-options.d.ts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region src/agent-options.ts
|
|
2
|
+
function assertAgentOptions(options) {
|
|
3
|
+
if (options === null || typeof options !== "object") throw new TypeError("Agent options are required. Provide { model }.");
|
|
4
|
+
if ("sessions" in options) throw new TypeError("Agent: unsupported options.sessions. Use host: { sessionStore } and namespace instead.");
|
|
5
|
+
if ("runtime" in options) throw new TypeError("Agent: unsupported options.runtime. Use host.");
|
|
6
|
+
if ("llm" in options) throw new TypeError("Agent: unsupported options.llm. Use model for both AI SDK models and custom RuntimeLlm functions.");
|
|
7
|
+
if (!("model" in options && options.model != null)) throw new TypeError("Agent: missing options.model.");
|
|
8
|
+
if (typeof options.model !== "function" && (typeof options.model !== "object" || options.model === null)) throw new TypeError("Agent: invalid options.model.");
|
|
9
|
+
}
|
|
10
|
+
function hasRuntimeModel(options) {
|
|
11
|
+
return typeof options.model === "function";
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { assertAgentOptions, hasRuntimeModel };
|
|
15
|
+
|
|
16
|
+
//# sourceMappingURL=agent-options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-options.js","names":[],"sources":["../src/agent-options.ts"],"sourcesContent":["import type { LanguageModel, ToolSet } from \"ai\";\nimport type { Agent } from \"./agent\";\nimport type { AgentHost } from \"./execution/types\";\nimport type { AgentToolChoice, RuntimeLlm } from \"./llm\";\nimport type { AgentPlugin } from \"./plugins\";\n\ninterface AgentLanguageModelOptions {\n readonly description?: string;\n readonly host?: AgentHost;\n readonly instructions?: string;\n readonly model: LanguageModel;\n readonly name?: string;\n readonly namespace?: string;\n readonly plugins?: readonly AgentPlugin[];\n readonly subagents?: readonly Agent[];\n readonly toolChoice?: AgentToolChoice;\n readonly tools?: ToolSet;\n}\n\ninterface AgentRuntimeModelOptions {\n readonly description?: string;\n readonly host?: AgentHost;\n readonly instructions?: never;\n readonly model: RuntimeLlm;\n readonly name?: string;\n readonly namespace?: string;\n readonly plugins?: readonly AgentPlugin[];\n readonly subagents?: never;\n readonly toolChoice?: never;\n readonly tools?: never;\n}\n\nexport type AgentModelOptions = Pick<\n AgentLanguageModelOptions,\n \"instructions\" | \"model\" | \"toolChoice\"\n>;\nexport type AgentOptions = AgentLanguageModelOptions | AgentRuntimeModelOptions;\n\nexport function assertAgentOptions(\n options: unknown\n): asserts options is AgentOptions {\n if (options === null || typeof options !== \"object\") {\n throw new TypeError(\"Agent options are required. Provide { model }.\");\n }\n\n if (\"sessions\" in options) {\n throw new TypeError(\n \"Agent: unsupported options.sessions. Use host: { sessionStore } and namespace instead.\"\n );\n }\n\n if (\"runtime\" in options) {\n throw new TypeError(\"Agent: unsupported options.runtime. Use host.\");\n }\n\n if (\"llm\" in options) {\n throw new TypeError(\n \"Agent: unsupported options.llm. Use model for both AI SDK models and custom RuntimeLlm functions.\"\n );\n }\n\n const hasModel = \"model\" in options && options.model != null;\n\n if (!hasModel) {\n throw new TypeError(\"Agent: missing options.model.\");\n }\n\n if (\n typeof options.model !== \"function\" &&\n (typeof options.model !== \"object\" || options.model === null)\n ) {\n throw new TypeError(\"Agent: invalid options.model.\");\n }\n}\n\nexport function hasRuntimeModel(\n options: AgentOptions\n): options is AgentRuntimeModelOptions {\n return typeof options.model === \"function\";\n}\n"],"mappings":";AAsCA,SAAgB,mBACd,SACiC;CACjC,IAAI,YAAY,QAAQ,OAAO,YAAY,UACzC,MAAM,IAAI,UAAU,gDAAgD;CAGtE,IAAI,cAAc,SAChB,MAAM,IAAI,UACR,wFACF;CAGF,IAAI,aAAa,SACf,MAAM,IAAI,UAAU,+CAA+C;CAGrE,IAAI,SAAS,SACX,MAAM,IAAI,UACR,mGACF;CAKF,IAAI,EAFa,WAAW,WAAW,QAAQ,SAAS,OAGtD,MAAM,IAAI,UAAU,+BAA+B;CAGrD,IACE,OAAO,QAAQ,UAAU,eACxB,OAAO,QAAQ,UAAU,YAAY,QAAQ,UAAU,OAExD,MAAM,IAAI,UAAU,+BAA+B;AAEvD;AAEA,SAAgB,gBACd,SACqC;CACrC,OAAO,OAAO,QAAQ,UAAU;AAClC"}
|