@minpeter/pss-runtime 0.0.4 → 0.0.5
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 +53 -107
- package/dist/agent-loop.d.ts +20 -12
- package/dist/agent-loop.js +45 -48
- package/dist/agent-loop.js.map +1 -1
- package/dist/agent.d.ts +34 -17
- package/dist/agent.js +50 -31
- package/dist/agent.js.map +1 -1
- package/dist/index.d.ts +8 -7
- package/dist/index.js +4 -5
- package/dist/llm.d.ts +30 -23
- package/dist/llm.js +15 -11
- package/dist/llm.js.map +1 -1
- package/dist/session/events.d.ts +42 -61
- package/dist/session/history.js +31 -29
- package/dist/session/history.js.map +1 -1
- package/dist/session/mapping.js +47 -53
- package/dist/session/mapping.js.map +1 -1
- package/dist/session/run.d.ts +9 -0
- package/dist/session/run.js +78 -0
- package/dist/session/run.js.map +1 -0
- package/dist/session/session.d.ts +7 -16
- package/dist/session/session.js +172 -321
- package/dist/session/session.js.map +1 -1
- package/dist/session/store/file.d.ts +14 -0
- package/dist/session/store/file.js +106 -0
- package/dist/session/store/file.js.map +1 -0
- package/dist/session/store/memory.d.ts +13 -0
- package/dist/session/store/memory.js +31 -0
- package/dist/session/store/memory.js.map +1 -0
- package/dist/session/store/types.d.ts +22 -0
- package/package.json +16 -2
- package/dist/agent-loop.d.ts.map +0 -1
- package/dist/agent.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/llm.d.ts.map +0 -1
- package/dist/session/events.d.ts.map +0 -1
- package/dist/session/events.js +0 -2
- package/dist/session/events.js.map +0 -1
- package/dist/session/history.d.ts +0 -11
- package/dist/session/history.d.ts.map +0 -1
- package/dist/session/mapping.d.ts +0 -7
- package/dist/session/mapping.d.ts.map +0 -1
- package/dist/session/session.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -1,132 +1,78 @@
|
|
|
1
1
|
# @minpeter/pss-runtime
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Minimal, platform-agnostic agent runtime with sessions keyed through `run.stream()` and
|
|
4
|
+
opaque persistence contracts.
|
|
5
|
+
|
|
6
|
+
## Core DX
|
|
4
7
|
|
|
5
8
|
```ts
|
|
6
|
-
import { Agent
|
|
9
|
+
import { Agent } from "@minpeter/pss-runtime";
|
|
10
|
+
import { createYourLanguageModel } from "...";
|
|
7
11
|
|
|
8
|
-
const
|
|
9
|
-
const agent = new Agent({
|
|
12
|
+
const agent = await Agent.create({
|
|
10
13
|
instructions: "Answer briefly.",
|
|
11
|
-
model,
|
|
14
|
+
model: createYourLanguageModel(),
|
|
12
15
|
});
|
|
13
|
-
const session = agent.createSession();
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
The runtime does not read environment variables or create a default provider.
|
|
17
|
-
Pass a caller-owned `LanguageModel` through `model`, or pass a custom `llm`.
|
|
18
|
-
Product tools are intentionally not included; pass tools from a separate package
|
|
19
|
-
when constructing an `Agent`.
|
|
20
16
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
stateless request handlers, background jobs, and tests that persist history
|
|
26
|
-
outside the runtime.
|
|
27
|
-
|
|
28
|
-
```ts
|
|
29
|
-
import { type AgentMessage } from "@minpeter/pss-runtime";
|
|
30
|
-
|
|
31
|
-
const history: AgentMessage[] = [
|
|
32
|
-
{ role: "user", content: "Hello!" },
|
|
33
|
-
{ role: "assistant", content: "Hi! How can I help you today?" },
|
|
34
|
-
];
|
|
35
|
-
|
|
36
|
-
const session = agent.createSession({ history });
|
|
37
|
-
|
|
38
|
-
const currentHistory: AgentMessage[] = session.getHistory();
|
|
17
|
+
const run = await agent.send("Hello");
|
|
18
|
+
for await (const event of run.stream()) {
|
|
19
|
+
console.log(event);
|
|
20
|
+
}
|
|
39
21
|
```
|
|
40
22
|
|
|
41
|
-
`
|
|
42
|
-
without mutating the session.
|
|
43
|
-
|
|
44
|
-
### Reactive storage synchronization
|
|
45
|
-
|
|
46
|
-
Use `onHistoryChange` when the host should persist every history mutation as the
|
|
47
|
-
turn runs. Calls are serialized, receive the mutation-time snapshot, and are
|
|
48
|
-
awaited before `submit()` resolves, rejects, or advances to the next queued
|
|
49
|
-
turn. If persistence fails, the turn rolls back in-memory history and surfaces a
|
|
50
|
-
`turn-error`.
|
|
51
|
-
|
|
52
|
-
This is the best fit for stateful serverless hosts such as Cloudflare Durable
|
|
53
|
-
Objects, where a long-lived session mirrors history into Durable Object Storage,
|
|
54
|
-
SQLite, or another caller-owned store.
|
|
23
|
+
Per-key conversations use `session(key)`:
|
|
55
24
|
|
|
56
25
|
```ts
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
private session: AgentSession | null = null;
|
|
62
|
-
private storage: DurableObjectStorage;
|
|
63
|
-
|
|
64
|
-
constructor(state: DurableObjectState) {
|
|
65
|
-
this.storage = state.storage;
|
|
66
|
-
this.agent = new Agent({
|
|
67
|
-
instructions: "You are a helpful assistant.",
|
|
68
|
-
model: yourLanguageModel,
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
async fetch(request: Request) {
|
|
73
|
-
if (!this.session) {
|
|
74
|
-
const history =
|
|
75
|
-
(await this.storage.get<AgentMessage[]>("history")) ?? [];
|
|
76
|
-
|
|
77
|
-
this.session = this.agent.createSession({
|
|
78
|
-
history,
|
|
79
|
-
onHistoryChange: async (nextHistory) => {
|
|
80
|
-
await this.storage.put("history", nextHistory);
|
|
81
|
-
},
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Process the incoming request (e.g. submit user text and stream back events).
|
|
86
|
-
// ...
|
|
87
|
-
}
|
|
26
|
+
const roomSession = agent.session("room:123:user:456");
|
|
27
|
+
const run = await roomSession.send(["Context: user prefers short answers", "Hi"]);
|
|
28
|
+
for await (const event of run.stream()) {
|
|
29
|
+
// stream events for this single turn
|
|
88
30
|
}
|
|
89
31
|
```
|
|
90
32
|
|
|
91
|
-
|
|
33
|
+
`agent.send(...)` is shorthand for `agent.session("default").send(...)`.
|
|
34
|
+
|
|
35
|
+
## Session storage and portability
|
|
92
36
|
|
|
93
|
-
|
|
94
|
-
|
|
37
|
+
The runtime owns full session state encoding and history compaction semantics.
|
|
38
|
+
Adapters own persistence only through `SessionStore`:
|
|
95
39
|
|
|
96
40
|
```ts
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
// Subscribe to events and get the unsubscribe function
|
|
100
|
-
const unsubscribe = session.subscribe((event) => {
|
|
101
|
-
switch (event.type) {
|
|
102
|
-
case "assistant-text":
|
|
103
|
-
process.stdout.write(event.text);
|
|
104
|
-
break;
|
|
105
|
-
case "tool-call":
|
|
106
|
-
console.log(`\nCalling tool: ${event.name}`);
|
|
107
|
-
break;
|
|
108
|
-
}
|
|
109
|
-
});
|
|
41
|
+
import type { SessionStore } from "@minpeter/pss-runtime";
|
|
42
|
+
import { MemorySessionStore } from "@minpeter/pss-runtime/session-store/memory";
|
|
110
43
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
44
|
+
const agent = await Agent.create({
|
|
45
|
+
model,
|
|
46
|
+
sessions: {
|
|
47
|
+
store: new MemorySessionStore(), // default when omitted
|
|
48
|
+
},
|
|
49
|
+
});
|
|
117
50
|
```
|
|
118
51
|
|
|
119
|
-
|
|
120
|
-
strings together as one user turn and forwards them to the model as AI SDK text
|
|
121
|
-
content parts, which is useful when the host needs to prepend per-turn context
|
|
122
|
-
without flattening it into the user's visible message.
|
|
52
|
+
For durable sessions, use the exported file POC:
|
|
123
53
|
|
|
124
54
|
```ts
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
55
|
+
import { FileSessionStore } from "@minpeter/pss-runtime/session-store/file";
|
|
56
|
+
|
|
57
|
+
const agent = await Agent.create({
|
|
58
|
+
model,
|
|
59
|
+
sessions: {
|
|
60
|
+
store: new FileSessionStore(".pss/sessions"),
|
|
61
|
+
},
|
|
131
62
|
});
|
|
132
63
|
```
|
|
64
|
+
|
|
65
|
+
## Future adapter boundary: Cloudflare multi-user DX
|
|
66
|
+
|
|
67
|
+
Cloudflare Durable Objects are a future adapter target, not a runtime dependency.
|
|
68
|
+
The same core API supports room/user/session routing through stable session keys.
|
|
69
|
+
|
|
70
|
+
Recommended key patterns:
|
|
71
|
+
|
|
72
|
+
- Shared room conversation: `room:<roomId>`
|
|
73
|
+
- Per-user memory inside room: `room:<roomId>:user:<userId>`
|
|
74
|
+
- Ticketed workspace flows: `tenant:<tenantId>:ticket:<ticketId>`
|
|
75
|
+
|
|
76
|
+
In a Durable Object, map the `SessionStore` contract to `ctx.storage` so DO storage is
|
|
77
|
+
durable across hibernation/restores, while in-memory state remains request-local.
|
|
78
|
+
Do not store canonical agent session state in memory attachments.
|
package/dist/agent-loop.d.ts
CHANGED
|
@@ -1,17 +1,25 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import { Llm } from "./llm.js";
|
|
2
|
+
import { AgentEventListener } from "./session/events.js";
|
|
3
|
+
import { ModelMessage } from "ai";
|
|
4
|
+
|
|
5
|
+
//#region src/agent-loop.d.ts
|
|
4
6
|
interface ModelHistory {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
appendModelMessage(message: ModelMessage): void;
|
|
8
|
+
modelSnapshot(): ModelMessage[];
|
|
7
9
|
}
|
|
8
10
|
interface RunAgentLoopOptions {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
emit: AgentEventListener;
|
|
12
|
+
history: ModelHistory;
|
|
13
|
+
llm: Llm;
|
|
14
|
+
signal?: AbortSignal;
|
|
13
15
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
type AgentLoopResult = "completed" | "aborted";
|
|
17
|
+
declare function runAgentLoop({
|
|
18
|
+
emit,
|
|
19
|
+
history,
|
|
20
|
+
llm,
|
|
21
|
+
signal
|
|
22
|
+
}: RunAgentLoopOptions): Promise<AgentLoopResult>;
|
|
23
|
+
//#endregion
|
|
24
|
+
export { AgentLoopResult, runAgentLoop };
|
|
17
25
|
//# sourceMappingURL=agent-loop.d.ts.map
|
package/dist/agent-loop.js
CHANGED
|
@@ -1,53 +1,50 @@
|
|
|
1
1
|
import { modelMessageToAgentEvents } from "./session/mapping.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
2
|
+
//#region src/agent-loop.ts
|
|
3
|
+
async function runAgentLoop({ emit, history, llm, signal = new AbortController().signal }) {
|
|
4
|
+
while (true) {
|
|
5
|
+
if (signal.aborted) return "aborted";
|
|
6
|
+
emit({ type: "step-start" });
|
|
7
|
+
const output = await readLlmOutput({
|
|
8
|
+
history,
|
|
9
|
+
llm,
|
|
10
|
+
signal
|
|
11
|
+
});
|
|
12
|
+
if (output === "aborted") return "aborted";
|
|
13
|
+
const result = appendStepOutput({
|
|
14
|
+
emit,
|
|
15
|
+
history,
|
|
16
|
+
output,
|
|
17
|
+
signal
|
|
18
|
+
});
|
|
19
|
+
if (result === "aborted") return "aborted";
|
|
20
|
+
emit({ type: "step-end" });
|
|
21
|
+
if (result === "completed") return "completed";
|
|
22
|
+
}
|
|
21
23
|
}
|
|
22
|
-
async function readLlmOutput({ history, llm, signal
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
async function readLlmOutput({ history, llm, signal }) {
|
|
25
|
+
try {
|
|
26
|
+
return await llm({
|
|
27
|
+
history: history.modelSnapshot(),
|
|
28
|
+
signal
|
|
29
|
+
});
|
|
30
|
+
} catch (error) {
|
|
31
|
+
if (signal.aborted) return "aborted";
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
32
34
|
}
|
|
33
|
-
function appendStepOutput({ emit, history, output, signal
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
for (const event of events) {
|
|
45
|
-
emit(event);
|
|
46
|
-
}
|
|
47
|
-
if (events.some((event) => event.type === "tool-call")) {
|
|
48
|
-
shouldContinue = true;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
return shouldContinue ? "continue" : "completed";
|
|
35
|
+
function appendStepOutput({ emit, history, output, signal }) {
|
|
36
|
+
if (signal.aborted) return "aborted";
|
|
37
|
+
let shouldContinue = false;
|
|
38
|
+
for (const message of output) {
|
|
39
|
+
if (signal.aborted) return "aborted";
|
|
40
|
+
history.appendModelMessage(message);
|
|
41
|
+
const events = modelMessageToAgentEvents(message);
|
|
42
|
+
for (const event of events) emit(event);
|
|
43
|
+
if (events.some((event) => event.type === "tool-call")) shouldContinue = true;
|
|
44
|
+
}
|
|
45
|
+
return shouldContinue ? "continue" : "completed";
|
|
52
46
|
}
|
|
47
|
+
//#endregion
|
|
48
|
+
export { runAgentLoop };
|
|
49
|
+
|
|
53
50
|
//# sourceMappingURL=agent-loop.js.map
|
package/dist/agent-loop.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-loop.js","
|
|
1
|
+
{"version":3,"file":"agent-loop.js","names":[],"sources":["../src/agent-loop.ts"],"sourcesContent":["import type { ModelMessage } from \"ai\";\nimport type { Llm, LlmOutput } from \"./llm\";\nimport type { AgentEventListener } from \"./session/events\";\nimport { modelMessageToAgentEvents } from \"./session/mapping\";\n\ninterface ModelHistory {\n appendModelMessage(message: ModelMessage): void;\n modelSnapshot(): ModelMessage[];\n}\n\ninterface RunAgentLoopOptions {\n emit: AgentEventListener;\n history: ModelHistory;\n llm: Llm;\n signal?: AbortSignal;\n}\n\nexport type AgentLoopResult = \"completed\" | \"aborted\";\ntype StepOutputResult = \"continue\" | \"completed\" | \"aborted\";\n\nexport async function runAgentLoop({\n emit,\n history,\n llm,\n signal = new AbortController().signal,\n}: RunAgentLoopOptions): Promise<AgentLoopResult> {\n while (true) {\n if (signal.aborted) {\n return \"aborted\";\n }\n\n emit({ type: \"step-start\" });\n const output = await readLlmOutput({ history, llm, signal });\n\n if (output === \"aborted\") {\n return \"aborted\";\n }\n\n const result = appendStepOutput({ emit, history, output, signal });\n\n if (result === \"aborted\") {\n return \"aborted\";\n }\n\n emit({ type: \"step-end\" });\n\n if (result === \"completed\") {\n return \"completed\";\n }\n }\n}\n\nasync function readLlmOutput({\n history,\n llm,\n signal,\n}: Pick<RunAgentLoopOptions, \"history\" | \"llm\"> & {\n signal: AbortSignal;\n}): Promise<LlmOutput | \"aborted\"> {\n try {\n return await llm({ history: history.modelSnapshot(), signal });\n } catch (error) {\n if (signal.aborted) {\n return \"aborted\";\n }\n\n throw error;\n }\n}\n\nfunction appendStepOutput({\n emit,\n history,\n output,\n signal,\n}: Pick<RunAgentLoopOptions, \"emit\" | \"history\"> & {\n output: LlmOutput;\n signal: AbortSignal;\n}): StepOutputResult {\n if (signal.aborted) {\n return \"aborted\";\n }\n\n let shouldContinue = false;\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\n for (const event of events) {\n emit(event);\n }\n\n if (events.some((event) => event.type === \"tool-call\")) {\n shouldContinue = true;\n }\n }\n\n return shouldContinue ? \"continue\" : \"completed\";\n}\n"],"mappings":";;AAoBA,eAAsB,aAAa,EACjC,MACA,SACA,KACA,SAAS,IAAI,gBAAgB,EAAE,UACiB;CAChD,OAAO,MAAM;EACX,IAAI,OAAO,SACT,OAAO;EAGT,KAAK,EAAE,MAAM,aAAa,CAAC;EAC3B,MAAM,SAAS,MAAM,cAAc;GAAE;GAAS;GAAK;EAAO,CAAC;EAE3D,IAAI,WAAW,WACb,OAAO;EAGT,MAAM,SAAS,iBAAiB;GAAE;GAAM;GAAS;GAAQ;EAAO,CAAC;EAEjE,IAAI,WAAW,WACb,OAAO;EAGT,KAAK,EAAE,MAAM,WAAW,CAAC;EAEzB,IAAI,WAAW,aACb,OAAO;CAEX;AACF;AAEA,eAAe,cAAc,EAC3B,SACA,KACA,UAGiC;CACjC,IAAI;EACF,OAAO,MAAM,IAAI;GAAE,SAAS,QAAQ,cAAc;GAAG;EAAO,CAAC;CAC/D,SAAS,OAAO;EACd,IAAI,OAAO,SACT,OAAO;EAGT,MAAM;CACR;AACF;AAEA,SAAS,iBAAiB,EACxB,MACA,SACA,QACA,UAImB;CACnB,IAAI,OAAO,SACT,OAAO;CAGT,IAAI,iBAAiB;CAErB,KAAK,MAAM,WAAW,QAAQ;EAC5B,IAAI,OAAO,SACT,OAAO;EAGT,QAAQ,mBAAmB,OAAO;EAClC,MAAM,SAAS,0BAA0B,OAAO;EAEhD,KAAK,MAAM,SAAS,QAClB,KAAK,KAAK;EAGZ,IAAI,OAAO,MAAM,UAAU,MAAM,SAAS,WAAW,GACnD,iBAAiB;CAErB;CAEA,OAAO,iBAAiB,aAAa;AACvC"}
|
package/dist/agent.d.ts
CHANGED
|
@@ -1,23 +1,40 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { AgentTools, Llm } from "./llm.js";
|
|
2
|
+
import { AgentRun } from "./session/run.js";
|
|
3
|
+
import { SessionStore } from "./session/store/types.js";
|
|
4
|
+
import { AgentInput } from "./session/session.js";
|
|
5
|
+
import { LanguageModel } from "ai";
|
|
6
|
+
|
|
7
|
+
//#region src/agent.d.ts
|
|
4
8
|
interface AgentModelOptions {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
instructions?: string;
|
|
10
|
+
llm?: never;
|
|
11
|
+
model: LanguageModel;
|
|
12
|
+
sessions?: AgentSessionOptions;
|
|
13
|
+
tools?: AgentTools;
|
|
9
14
|
}
|
|
10
15
|
interface AgentLlmOptions {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
16
|
+
instructions?: never;
|
|
17
|
+
llm: Llm;
|
|
18
|
+
model?: never;
|
|
19
|
+
sessions?: AgentSessionOptions;
|
|
20
|
+
tools?: never;
|
|
15
21
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
#private;
|
|
19
|
-
constructor(options: AgentOptions);
|
|
20
|
-
createSession(options?: SessionOptions): AgentSession;
|
|
22
|
+
interface AgentSessionOptions {
|
|
23
|
+
store?: SessionStore;
|
|
21
24
|
}
|
|
22
|
-
|
|
25
|
+
interface SessionHandle {
|
|
26
|
+
interrupt(): void;
|
|
27
|
+
kill(): void;
|
|
28
|
+
send(input: AgentInput): Promise<AgentRun>;
|
|
29
|
+
}
|
|
30
|
+
type AgentOptions = AgentModelOptions | AgentLlmOptions;
|
|
31
|
+
declare class Agent {
|
|
32
|
+
#private;
|
|
33
|
+
private constructor();
|
|
34
|
+
static create(options: AgentOptions): Promise<Agent>;
|
|
35
|
+
send(input: AgentInput): Promise<AgentRun>;
|
|
36
|
+
session(key: string): SessionHandle;
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
export { Agent, AgentOptions, AgentSessionOptions, SessionHandle };
|
|
23
40
|
//# sourceMappingURL=agent.d.ts.map
|
package/dist/agent.js
CHANGED
|
@@ -1,38 +1,57 @@
|
|
|
1
1
|
import { createLlm } from "./llm.js";
|
|
2
2
|
import { AgentSession } from "./session/session.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
3
|
+
import { MemorySessionStore } from "./session/store/memory.js";
|
|
4
|
+
//#region src/agent.ts
|
|
5
|
+
var Agent = class Agent {
|
|
6
|
+
#llm;
|
|
7
|
+
#sessions = /* @__PURE__ */ new Map();
|
|
8
|
+
#store;
|
|
9
|
+
constructor(options) {
|
|
10
|
+
assertAgentOptions(options);
|
|
11
|
+
this.#store = options.sessions?.store ?? new MemorySessionStore();
|
|
12
|
+
this.#llm = hasCustomLlm(options) ? options.llm : createLlm({
|
|
13
|
+
instructions: options.instructions,
|
|
14
|
+
model: options.model,
|
|
15
|
+
tools: options.tools
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
static create(options) {
|
|
19
|
+
return Promise.resolve().then(() => new Agent(options));
|
|
20
|
+
}
|
|
21
|
+
send(input) {
|
|
22
|
+
return this.session("default").send(input);
|
|
23
|
+
}
|
|
24
|
+
session(key) {
|
|
25
|
+
const existing = this.#sessions.get(key);
|
|
26
|
+
if (existing) return existing;
|
|
27
|
+
const session = new AgentSession(this.#llm, {
|
|
28
|
+
key,
|
|
29
|
+
store: this.#store
|
|
30
|
+
});
|
|
31
|
+
const handle = {
|
|
32
|
+
interrupt: () => session.interrupt(),
|
|
33
|
+
kill: () => {
|
|
34
|
+
session.kill();
|
|
35
|
+
this.#sessions.delete(key);
|
|
36
|
+
},
|
|
37
|
+
send: (input) => session.send(input)
|
|
38
|
+
};
|
|
39
|
+
this.#sessions.set(key, handle);
|
|
40
|
+
return handle;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
19
43
|
function assertAgentOptions(options) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
throw new TypeError("Agent constructor: provide either options.llm or options.model, not both.");
|
|
27
|
-
}
|
|
28
|
-
if ("llm" in options && options.llm !== undefined && !hasLlm) {
|
|
29
|
-
throw new TypeError("Agent constructor: invalid options.llm.");
|
|
30
|
-
}
|
|
31
|
-
if (!(hasLlm || hasModel)) {
|
|
32
|
-
throw new TypeError("Agent constructor: missing options.model.");
|
|
33
|
-
}
|
|
44
|
+
if (options === null || typeof options !== "object") throw new TypeError("Agent options are required. Provide either { model } or { llm }.");
|
|
45
|
+
const hasLlm = hasCustomLlm(options);
|
|
46
|
+
const hasModel = "model" in options && options.model !== void 0 && options.model !== null;
|
|
47
|
+
if (hasLlm && hasModel) throw new TypeError("Agent.create: provide either options.llm or options.model, not both.");
|
|
48
|
+
if ("llm" in options && options.llm !== void 0 && !hasLlm) throw new TypeError("Agent.create: invalid options.llm.");
|
|
49
|
+
if (!(hasLlm || hasModel)) throw new TypeError("Agent.create: missing options.model.");
|
|
34
50
|
}
|
|
35
51
|
function hasCustomLlm(options) {
|
|
36
|
-
|
|
52
|
+
return "llm" in options && typeof options.llm === "function";
|
|
37
53
|
}
|
|
54
|
+
//#endregion
|
|
55
|
+
export { Agent };
|
|
56
|
+
|
|
38
57
|
//# sourceMappingURL=agent.js.map
|
package/dist/agent.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.js","
|
|
1
|
+
{"version":3,"file":"agent.js","names":["#llm","#sessions","#store"],"sources":["../src/agent.ts"],"sourcesContent":["import type { LanguageModel } from \"ai\";\nimport { type AgentTools, createLlm, type Llm } from \"./llm\";\nimport type { AgentRun } from \"./session/run\";\nimport { type AgentInput, AgentSession } from \"./session/session\";\nimport { MemorySessionStore } from \"./session/store/memory\";\nimport type { SessionStore } from \"./session/store/types\";\n\ninterface AgentModelOptions {\n instructions?: string;\n llm?: never;\n model: LanguageModel;\n sessions?: AgentSessionOptions;\n tools?: AgentTools;\n}\n\ninterface AgentLlmOptions {\n instructions?: never;\n llm: Llm;\n model?: never;\n sessions?: AgentSessionOptions;\n tools?: never;\n}\n\nexport interface AgentSessionOptions {\n store?: SessionStore;\n}\n\nexport interface SessionHandle {\n interrupt(): void;\n kill(): void;\n send(input: AgentInput): Promise<AgentRun>;\n}\n\nexport type AgentOptions = AgentModelOptions | AgentLlmOptions;\n\nexport class Agent {\n readonly #llm: Llm;\n readonly #sessions = new Map<string, SessionHandle>();\n readonly #store: SessionStore;\n\n private constructor(options: AgentOptions) {\n assertAgentOptions(options);\n\n this.#store = options.sessions?.store ?? new MemorySessionStore();\n this.#llm = hasCustomLlm(options)\n ? options.llm\n : createLlm({\n instructions: options.instructions,\n model: options.model,\n tools: options.tools,\n });\n }\n\n static create(options: AgentOptions): Promise<Agent> {\n return Promise.resolve().then(() => new Agent(options));\n }\n\n send(input: AgentInput): Promise<AgentRun> {\n return this.session(\"default\").send(input);\n }\n\n session(key: string): SessionHandle {\n const existing = this.#sessions.get(key);\n if (existing) {\n return existing;\n }\n\n const session = new AgentSession(this.#llm, { key, store: this.#store });\n const handle: SessionHandle = {\n interrupt: () => session.interrupt(),\n kill: () => {\n session.kill();\n this.#sessions.delete(key);\n },\n send: (input) => session.send(input),\n };\n this.#sessions.set(key, handle);\n return handle;\n }\n}\n\nfunction assertAgentOptions(options: unknown): asserts options is AgentOptions {\n if (options === null || typeof options !== \"object\") {\n throw new TypeError(\n \"Agent options are required. Provide either { model } or { llm }.\"\n );\n }\n\n const hasLlm = hasCustomLlm(options);\n const hasModel =\n \"model\" in options && options.model !== undefined && options.model !== null;\n\n if (hasLlm && hasModel) {\n throw new TypeError(\n \"Agent.create: provide either options.llm or options.model, not both.\"\n );\n }\n\n if (\"llm\" in options && options.llm !== undefined && !hasLlm) {\n throw new TypeError(\"Agent.create: invalid options.llm.\");\n }\n\n if (!(hasLlm || hasModel)) {\n throw new TypeError(\"Agent.create: missing options.model.\");\n }\n}\n\nfunction hasCustomLlm(options: object): options is AgentLlmOptions {\n return \"llm\" in options && typeof options.llm === \"function\";\n}\n"],"mappings":";;;;AAmCA,IAAa,QAAb,MAAa,MAAM;CACjB;CACA,4BAAqB,IAAI,IAA2B;CACpD;CAEA,YAAoB,SAAuB;EACzC,mBAAmB,OAAO;EAE1B,KAAKE,SAAS,QAAQ,UAAU,SAAS,IAAI,mBAAmB;EAChE,KAAKF,OAAO,aAAa,OAAO,IAC5B,QAAQ,MACR,UAAU;GACR,cAAc,QAAQ;GACtB,OAAO,QAAQ;GACf,OAAO,QAAQ;EACjB,CAAC;CACP;CAEA,OAAO,OAAO,SAAuC;EACnD,OAAO,QAAQ,QAAQ,EAAE,WAAW,IAAI,MAAM,OAAO,CAAC;CACxD;CAEA,KAAK,OAAsC;EACzC,OAAO,KAAK,QAAQ,SAAS,EAAE,KAAK,KAAK;CAC3C;CAEA,QAAQ,KAA4B;EAClC,MAAM,WAAW,KAAKC,UAAU,IAAI,GAAG;EACvC,IAAI,UACF,OAAO;EAGT,MAAM,UAAU,IAAI,aAAa,KAAKD,MAAM;GAAE;GAAK,OAAO,KAAKE;EAAO,CAAC;EACvE,MAAM,SAAwB;GAC5B,iBAAiB,QAAQ,UAAU;GACnC,YAAY;IACV,QAAQ,KAAK;IACb,KAAKD,UAAU,OAAO,GAAG;GAC3B;GACA,OAAO,UAAU,QAAQ,KAAK,KAAK;EACrC;EACA,KAAKA,UAAU,IAAI,KAAK,MAAM;EAC9B,OAAO;CACT;AACF;AAEA,SAAS,mBAAmB,SAAmD;CAC7E,IAAI,YAAY,QAAQ,OAAO,YAAY,UACzC,MAAM,IAAI,UACR,kEACF;CAGF,MAAM,SAAS,aAAa,OAAO;CACnC,MAAM,WACJ,WAAW,WAAW,QAAQ,UAAU,KAAA,KAAa,QAAQ,UAAU;CAEzE,IAAI,UAAU,UACZ,MAAM,IAAI,UACR,sEACF;CAGF,IAAI,SAAS,WAAW,QAAQ,QAAQ,KAAA,KAAa,CAAC,QACpD,MAAM,IAAI,UAAU,oCAAoC;CAG1D,IAAI,EAAE,UAAU,WACd,MAAM,IAAI,UAAU,sCAAsC;AAE9D;AAEA,SAAS,aAAa,SAA6C;CACjE,OAAO,SAAS,WAAW,OAAO,QAAQ,QAAQ;AACpD"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import { AgentMessage, AgentModel, AgentTool, AgentToolExecute, AgentToolExecutionOptions, AgentTools, LlmOutputPart, RuntimeCreateLlmOptions, RuntimeLlm, RuntimeLlmContext, RuntimeLlmOutput, createLlm } from "./llm.js";
|
|
2
|
+
import { AgentEvent, AgentEventListener, AssistantReasoning, AssistantText, ToolCall, ToolResult, UserText, UserTextContent } from "./session/events.js";
|
|
3
|
+
import { AgentRun } from "./session/run.js";
|
|
4
|
+
import { CommitResult, ExpectedSessionVersion, SessionStore, StoredSession } from "./session/store/types.js";
|
|
5
|
+
import { AgentInput } from "./session/session.js";
|
|
6
|
+
import { Agent, AgentOptions, AgentSessionOptions, SessionHandle } from "./agent.js";
|
|
7
|
+
import { AgentLoopResult, runAgentLoop } from "./agent-loop.js";
|
|
8
|
+
export { Agent, type AgentEvent, type AgentEventListener, type AgentInput, type AgentLoopResult, type AgentMessage, type AgentModel, type AgentOptions, type AgentRun, type AgentSessionOptions, type AgentTool, type AgentToolExecute, type AgentToolExecutionOptions, type AgentTools, type AssistantReasoning, type AssistantText, type CommitResult, type ExpectedSessionVersion, type LlmOutputPart, type RuntimeCreateLlmOptions, type RuntimeLlm, type RuntimeLlmContext, type RuntimeLlmOutput, type SessionHandle, type SessionStore, type StoredSession, type ToolCall, type ToolResult, type UserText, type UserTextContent, createLlm, runAgentLoop };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export {
|
|
5
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
import { createLlm } from "./llm.js";
|
|
2
|
+
import { runAgentLoop } from "./agent-loop.js";
|
|
3
|
+
import { Agent } from "./agent.js";
|
|
4
|
+
export { Agent, createLlm, runAgentLoop };
|
package/dist/llm.d.ts
CHANGED
|
@@ -1,26 +1,33 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
import { LanguageModel, ModelMessage, Tool, ToolExecutionOptions, ToolSet, generateText } from "ai";
|
|
2
|
+
|
|
3
|
+
//#region src/llm.d.ts
|
|
4
|
+
type AgentToolExecutionOptions = ToolExecutionOptions<unknown>;
|
|
5
|
+
type AgentToolExecute = NonNullable<Tool["execute"]>;
|
|
6
|
+
type AgentTool = Tool;
|
|
7
|
+
type AgentTools = ToolSet;
|
|
8
|
+
type AgentModel = LanguageModel;
|
|
9
|
+
type AgentMessage = ModelMessage;
|
|
10
|
+
type LlmOutput = Awaited<ReturnType<typeof generateText>>["responseMessages"];
|
|
11
|
+
type LlmOutputPart = LlmOutput[number];
|
|
12
|
+
interface LlmContext {
|
|
13
|
+
history: readonly ModelMessage[];
|
|
14
|
+
signal: AbortSignal;
|
|
14
15
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
type Llm = (context: LlmContext) => Promise<LlmOutput>;
|
|
17
|
+
interface CreateLlmOptions {
|
|
18
|
+
instructions?: string;
|
|
19
|
+
model: LanguageModel;
|
|
20
|
+
tools?: AgentTools;
|
|
20
21
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
type RuntimeCreateLlmOptions = CreateLlmOptions;
|
|
23
|
+
type RuntimeLlm = Llm;
|
|
24
|
+
type RuntimeLlmContext = LlmContext;
|
|
25
|
+
type RuntimeLlmOutput = LlmOutput;
|
|
26
|
+
declare function createLlm({
|
|
27
|
+
model,
|
|
28
|
+
instructions,
|
|
29
|
+
tools
|
|
30
|
+
}: CreateLlmOptions): Llm;
|
|
31
|
+
//#endregion
|
|
32
|
+
export { AgentMessage, AgentModel, AgentTool, AgentToolExecute, AgentToolExecutionOptions, AgentTools, Llm, LlmOutputPart, RuntimeCreateLlmOptions, RuntimeLlm, RuntimeLlmContext, RuntimeLlmOutput, createLlm };
|
|
26
33
|
//# sourceMappingURL=llm.d.ts.map
|
package/dist/llm.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import { generateText } from "ai";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
2
|
+
//#region src/llm.ts
|
|
3
|
+
function createLlm({ model, instructions, tools }) {
|
|
4
|
+
return async ({ history, signal }) => {
|
|
5
|
+
const { responseMessages } = await generateText({
|
|
6
|
+
abortSignal: signal,
|
|
7
|
+
instructions,
|
|
8
|
+
messages: [...history],
|
|
9
|
+
model,
|
|
10
|
+
tools
|
|
11
|
+
});
|
|
12
|
+
return responseMessages;
|
|
13
|
+
};
|
|
13
14
|
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { createLlm };
|
|
17
|
+
|
|
14
18
|
//# sourceMappingURL=llm.js.map
|