@minpeter/pss-runtime 0.0.4 → 0.0.6
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 +89 -101
- 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 +29 -23
- package/dist/llm.js +15 -11
- package/dist/llm.js.map +1 -1
- package/dist/session/events.d.ts +76 -61
- package/dist/session/history.js +32 -30
- package/dist/session/history.js.map +1 -1
- package/dist/session/mapping.js +92 -52
- 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 +9 -16
- package/dist/session/session.js +193 -320
- package/dist/session/session.js.map +1 -1
- package/dist/session/snapshot.js +20 -0
- package/dist/session/snapshot.js.map +1 -0
- 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,120 @@
|
|
|
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
|
-
|
|
17
|
+
const run = await agent.send("Hello");
|
|
18
|
+
for await (const event of run.stream()) {
|
|
19
|
+
console.log(event);
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
needs a new `AgentSession` to continue from that state. This is the best fit for
|
|
25
|
-
stateless request handlers, background jobs, and tests that persist history
|
|
26
|
-
outside the runtime.
|
|
23
|
+
Per-key conversations use `session(key)`:
|
|
27
24
|
|
|
28
25
|
```ts
|
|
29
|
-
|
|
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
|
|
30
|
+
}
|
|
31
|
+
```
|
|
30
32
|
|
|
31
|
-
|
|
32
|
-
{ role: "user", content: "Hello!" },
|
|
33
|
-
{ role: "assistant", content: "Hi! How can I help you today?" },
|
|
34
|
-
];
|
|
33
|
+
`agent.send(...)` is shorthand for `agent.session("default").send(...)`.
|
|
35
34
|
|
|
36
|
-
|
|
35
|
+
For model providers that support multimodal input, send JSON-serializable content
|
|
36
|
+
parts through the same API. String input and `readonly string[]` remain supported
|
|
37
|
+
shortcuts for text-only turns.
|
|
37
38
|
|
|
38
|
-
|
|
39
|
+
```ts
|
|
40
|
+
const run = await agent.send([
|
|
41
|
+
{ type: "text", text: "Describe this UI screenshot." },
|
|
42
|
+
{
|
|
43
|
+
type: "image",
|
|
44
|
+
image: "data:image/png;base64,iVBORw0KGgo...",
|
|
45
|
+
mediaType: "image/png",
|
|
46
|
+
},
|
|
47
|
+
]);
|
|
39
48
|
```
|
|
40
49
|
|
|
41
|
-
|
|
42
|
-
|
|
50
|
+
File parts use the same JSON-serializable shape when the selected model supports
|
|
51
|
+
file input:
|
|
43
52
|
|
|
44
|
-
|
|
53
|
+
```ts
|
|
54
|
+
await agent.send([
|
|
55
|
+
{ type: "text", text: "Summarize the attached report." },
|
|
56
|
+
{
|
|
57
|
+
type: "file",
|
|
58
|
+
data: "data:application/pdf;base64,JVBERi0x...",
|
|
59
|
+
filename: "report.pdf",
|
|
60
|
+
mediaType: "application/pdf",
|
|
61
|
+
},
|
|
62
|
+
]);
|
|
63
|
+
```
|
|
45
64
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
turn. If persistence fails, the turn rolls back in-memory history and surfaces a
|
|
50
|
-
`turn-error`.
|
|
65
|
+
The runtime normalizes and persists these content parts as session continuation
|
|
66
|
+
state; it does not fetch remote media, decode files, or guarantee provider support
|
|
67
|
+
for every media type.
|
|
51
68
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
69
|
+
The public transcript protocol is `AgentEvent`: live runs emit runtime-defined
|
|
70
|
+
events through `run.stream()`. Provider/model message history is internal
|
|
71
|
+
continuation state, not a public history API.
|
|
55
72
|
|
|
56
|
-
|
|
57
|
-
import { Agent, type AgentMessage, type AgentSession } from "@minpeter/pss-runtime";
|
|
58
|
-
|
|
59
|
-
export class AgentDurableObject {
|
|
60
|
-
private agent: Agent;
|
|
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
|
-
}
|
|
88
|
-
}
|
|
89
|
-
```
|
|
73
|
+
## Session storage and portability
|
|
90
74
|
|
|
91
|
-
|
|
75
|
+
The runtime owns full session state encoding and history compaction semantics.
|
|
76
|
+
Adapters own persistence only through `SessionStore`:
|
|
92
77
|
|
|
93
|
-
|
|
94
|
-
|
|
78
|
+
Stored session state is an opaque, versioned runtime snapshot for continuation.
|
|
79
|
+
Do not inspect it as a replay log; exact replay should be modeled separately as
|
|
80
|
+
an `AgentEvent` log if that capability is added later.
|
|
95
81
|
|
|
96
82
|
```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
|
-
});
|
|
83
|
+
import type { SessionStore } from "@minpeter/pss-runtime";
|
|
84
|
+
import { MemorySessionStore } from "@minpeter/pss-runtime/session-store/memory";
|
|
110
85
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
86
|
+
const agent = await Agent.create({
|
|
87
|
+
model,
|
|
88
|
+
sessions: {
|
|
89
|
+
store: new MemorySessionStore(), // default when omitted
|
|
90
|
+
},
|
|
91
|
+
});
|
|
117
92
|
```
|
|
118
93
|
|
|
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.
|
|
94
|
+
For durable sessions, use the exported file POC:
|
|
123
95
|
|
|
124
96
|
```ts
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
97
|
+
import { FileSessionStore } from "@minpeter/pss-runtime/session-store/file";
|
|
98
|
+
|
|
99
|
+
const agent = await Agent.create({
|
|
100
|
+
model,
|
|
101
|
+
sessions: {
|
|
102
|
+
store: new FileSessionStore(".pss/sessions"),
|
|
103
|
+
},
|
|
131
104
|
});
|
|
132
105
|
```
|
|
106
|
+
|
|
107
|
+
## Future adapter boundary: Cloudflare multi-user DX
|
|
108
|
+
|
|
109
|
+
Cloudflare Durable Objects are a future adapter target, not a runtime dependency.
|
|
110
|
+
The same core API supports room/user/session routing through stable session keys.
|
|
111
|
+
|
|
112
|
+
Recommended key patterns:
|
|
113
|
+
|
|
114
|
+
- Shared room conversation: `room:<roomId>`
|
|
115
|
+
- Per-user memory inside room: `room:<roomId>:user:<userId>`
|
|
116
|
+
- Ticketed workspace flows: `tenant:<tenantId>:ticket:<ticketId>`
|
|
117
|
+
|
|
118
|
+
In a Durable Object, map the `SessionStore` contract to `ctx.storage` so DO storage is
|
|
119
|
+
durable across hibernation/restores, while in-memory state remains request-local.
|
|
120
|
+
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 { AgentModel, AgentTool, AgentToolExecute, AgentToolExecutionOptions, AgentTools, LlmOutputPart, RuntimeCreateLlmOptions, RuntimeLlm, RuntimeLlmContext, RuntimeLlmOutput, createLlm } from "./llm.js";
|
|
2
|
+
import { AgentEvent, AgentEventListener, AssistantReasoning, AssistantText, ToolCall, ToolResult, UserMessage, UserMessageContent, UserMessageContentPart, UserMessageFileData, UserMessageFilePart, UserMessageImagePart, UserMessageTextPart, 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, SessionInput, UserInput } 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 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 SessionInput, type SessionStore, type StoredSession, type ToolCall, type ToolResult, type UserInput, type UserMessage, type UserMessageContent, type UserMessageContentPart, type UserMessageFileData, type UserMessageFilePart, type UserMessageImagePart, type UserMessageTextPart, 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,32 @@
|
|
|
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 LlmOutput = Awaited<ReturnType<typeof generateText>>["responseMessages"];
|
|
10
|
+
type LlmOutputPart = LlmOutput[number];
|
|
11
|
+
interface LlmContext {
|
|
12
|
+
history: readonly ModelMessage[];
|
|
13
|
+
signal: AbortSignal;
|
|
14
14
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
type Llm = (context: LlmContext) => Promise<LlmOutput>;
|
|
16
|
+
interface CreateLlmOptions {
|
|
17
|
+
instructions?: string;
|
|
18
|
+
model: LanguageModel;
|
|
19
|
+
tools?: AgentTools;
|
|
20
20
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
type RuntimeCreateLlmOptions = CreateLlmOptions;
|
|
22
|
+
type RuntimeLlm = Llm;
|
|
23
|
+
type RuntimeLlmContext = LlmContext;
|
|
24
|
+
type RuntimeLlmOutput = LlmOutput;
|
|
25
|
+
declare function createLlm({
|
|
26
|
+
model,
|
|
27
|
+
instructions,
|
|
28
|
+
tools
|
|
29
|
+
}: CreateLlmOptions): Llm;
|
|
30
|
+
//#endregion
|
|
31
|
+
export { AgentModel, AgentTool, AgentToolExecute, AgentToolExecutionOptions, AgentTools, Llm, LlmOutputPart, RuntimeCreateLlmOptions, RuntimeLlm, RuntimeLlmContext, RuntimeLlmOutput, createLlm };
|
|
26
32
|
//# sourceMappingURL=llm.d.ts.map
|