@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.
Files changed (44) hide show
  1. package/README.md +53 -107
  2. package/dist/agent-loop.d.ts +20 -12
  3. package/dist/agent-loop.js +45 -48
  4. package/dist/agent-loop.js.map +1 -1
  5. package/dist/agent.d.ts +34 -17
  6. package/dist/agent.js +50 -31
  7. package/dist/agent.js.map +1 -1
  8. package/dist/index.d.ts +8 -7
  9. package/dist/index.js +4 -5
  10. package/dist/llm.d.ts +30 -23
  11. package/dist/llm.js +15 -11
  12. package/dist/llm.js.map +1 -1
  13. package/dist/session/events.d.ts +42 -61
  14. package/dist/session/history.js +31 -29
  15. package/dist/session/history.js.map +1 -1
  16. package/dist/session/mapping.js +47 -53
  17. package/dist/session/mapping.js.map +1 -1
  18. package/dist/session/run.d.ts +9 -0
  19. package/dist/session/run.js +78 -0
  20. package/dist/session/run.js.map +1 -0
  21. package/dist/session/session.d.ts +7 -16
  22. package/dist/session/session.js +172 -321
  23. package/dist/session/session.js.map +1 -1
  24. package/dist/session/store/file.d.ts +14 -0
  25. package/dist/session/store/file.js +106 -0
  26. package/dist/session/store/file.js.map +1 -0
  27. package/dist/session/store/memory.d.ts +13 -0
  28. package/dist/session/store/memory.js +31 -0
  29. package/dist/session/store/memory.js.map +1 -0
  30. package/dist/session/store/types.d.ts +22 -0
  31. package/package.json +16 -2
  32. package/dist/agent-loop.d.ts.map +0 -1
  33. package/dist/agent.d.ts.map +0 -1
  34. package/dist/index.d.ts.map +0 -1
  35. package/dist/index.js.map +0 -1
  36. package/dist/llm.d.ts.map +0 -1
  37. package/dist/session/events.d.ts.map +0 -1
  38. package/dist/session/events.js +0 -2
  39. package/dist/session/events.js.map +0 -1
  40. package/dist/session/history.d.ts +0 -11
  41. package/dist/session/history.d.ts.map +0 -1
  42. package/dist/session/mapping.d.ts +0 -7
  43. package/dist/session/mapping.d.ts.map +0 -1
  44. 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
- Reusable pss-next agent runtime for sessions, model loops, and event streams.
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, type AgentModel } from "@minpeter/pss-runtime";
9
+ import { Agent } from "@minpeter/pss-runtime";
10
+ import { createYourLanguageModel } from "...";
7
11
 
8
- const model: AgentModel = createYourLanguageModel();
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
- ## Session history
22
-
23
- Use `history` when the caller already owns the stored model-message history and
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.
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
- `getHistory()` returns a cloned snapshot, so callers can persist or inspect it
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
- 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
- }
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
- ### Safe event subscriptions
33
+ `agent.send(...)` is shorthand for `agent.session("default").send(...)`.
34
+
35
+ ## Session storage and portability
92
36
 
93
- When subscribing to session events, unsubscribe in a `finally` block to prevent
94
- listener leaks in persistent environments or multi-turn execution loops.
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
- const session = agent.createSession();
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
- try {
112
- await session.submit({ type: "user-text", text: "What's the weather today?" });
113
- } finally {
114
- // Always clean up to prevent memory/listener leaks!
115
- unsubscribe();
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
- `submit()` also accepts `text` as an array of strings. The runtime keeps those
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
- await session.submit({
126
- type: "user-text",
127
- text: [
128
- "Context: user timezone is Asia/Seoul.",
129
- "Please remind me tomorrow morning.",
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.
@@ -1,17 +1,25 @@
1
- import type { ModelMessage } from "ai";
2
- import type { Llm } from "./llm";
3
- import type { AgentEventListener } from "./session/events";
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
- appendModelMessage(message: ModelMessage): void;
6
- modelSnapshot(): ModelMessage[];
7
+ appendModelMessage(message: ModelMessage): void;
8
+ modelSnapshot(): ModelMessage[];
7
9
  }
8
10
  interface RunAgentLoopOptions {
9
- emit: AgentEventListener;
10
- history: ModelHistory;
11
- llm: Llm;
12
- signal?: AbortSignal;
11
+ emit: AgentEventListener;
12
+ history: ModelHistory;
13
+ llm: Llm;
14
+ signal?: AbortSignal;
13
15
  }
14
- export type AgentLoopResult = "completed" | "aborted";
15
- export declare function runAgentLoop({ emit, history, llm, signal, }: RunAgentLoopOptions): Promise<AgentLoopResult>;
16
- export {};
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
@@ -1,53 +1,50 @@
1
1
  import { modelMessageToAgentEvents } from "./session/mapping.js";
2
- export async function runAgentLoop({ emit, history, llm, signal = new AbortController().signal, }) {
3
- while (true) {
4
- if (signal.aborted) {
5
- return "aborted";
6
- }
7
- emit({ type: "step-start" });
8
- const output = await readLlmOutput({ history, llm, signal });
9
- if (output === "aborted") {
10
- return "aborted";
11
- }
12
- const result = appendStepOutput({ emit, history, output, signal });
13
- if (result === "aborted") {
14
- return "aborted";
15
- }
16
- emit({ type: "step-end" });
17
- if (result === "completed") {
18
- return "completed";
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
- try {
24
- return await llm({ history: history.modelSnapshot(), signal });
25
- }
26
- catch (error) {
27
- if (signal.aborted) {
28
- return "aborted";
29
- }
30
- throw error;
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
- if (signal.aborted) {
35
- return "aborted";
36
- }
37
- let shouldContinue = false;
38
- for (const message of output) {
39
- if (signal.aborted) {
40
- return "aborted";
41
- }
42
- history.appendModelMessage(message);
43
- const events = modelMessageToAgentEvents(message);
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
@@ -1 +1 @@
1
- {"version":3,"file":"agent-loop.js","sourceRoot":"","sources":["../src/agent-loop.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAiB9D,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,EACjC,IAAI,EACJ,OAAO,EACP,GAAG,EACH,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC,MAAM,GACjB;IACpB,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,IAAI,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;QAC7B,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;QAE7D,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,MAAM,GAAG,gBAAgB,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QAEnE,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;QAE3B,IAAI,MAAM,KAAK,WAAW,EAAE,CAAC;YAC3B,OAAO,WAAW,CAAC;QACrB,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,EAC3B,OAAO,EACP,GAAG,EACH,MAAM,GAGP;IACC,IAAI,CAAC;QACH,OAAO,MAAM,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IACjE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,EACxB,IAAI,EACJ,OAAO,EACP,MAAM,EACN,MAAM,GAIP;IACC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,cAAc,GAAG,KAAK,CAAC;IAE3B,KAAK,MAAM,OAAO,IAAI,MAAM,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,OAAO,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,yBAAyB,CAAC,OAAO,CAAC,CAAC;QAElD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,CAAC,KAAK,CAAC,CAAC;QACd,CAAC;QAED,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC,EAAE,CAAC;YACvD,cAAc,GAAG,IAAI,CAAC;QACxB,CAAC;IACH,CAAC;IAED,OAAO,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC;AACnD,CAAC"}
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 type { LanguageModel } from "ai";
2
- import { type AgentTools, type Llm } from "./llm";
3
- import { AgentSession, type SessionOptions } from "./session/session";
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
- instructions?: string;
6
- llm?: never;
7
- model: LanguageModel;
8
- tools?: AgentTools;
9
+ instructions?: string;
10
+ llm?: never;
11
+ model: LanguageModel;
12
+ sessions?: AgentSessionOptions;
13
+ tools?: AgentTools;
9
14
  }
10
15
  interface AgentLlmOptions {
11
- instructions?: never;
12
- llm: Llm;
13
- model?: never;
14
- tools?: never;
16
+ instructions?: never;
17
+ llm: Llm;
18
+ model?: never;
19
+ sessions?: AgentSessionOptions;
20
+ tools?: never;
15
21
  }
16
- export type AgentOptions = AgentModelOptions | AgentLlmOptions;
17
- export declare class Agent {
18
- #private;
19
- constructor(options: AgentOptions);
20
- createSession(options?: SessionOptions): AgentSession;
22
+ interface AgentSessionOptions {
23
+ store?: SessionStore;
21
24
  }
22
- export {};
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
- export class Agent {
4
- #llm;
5
- constructor(options) {
6
- assertAgentOptions(options);
7
- this.#llm = hasCustomLlm(options)
8
- ? options.llm
9
- : createLlm({
10
- instructions: options.instructions,
11
- model: options.model,
12
- tools: options.tools,
13
- });
14
- }
15
- createSession(options) {
16
- return new AgentSession(this.#llm, options);
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
- if (options === null || typeof options !== "object") {
21
- throw new TypeError("Agent options are required. Provide either { model } or { llm }.");
22
- }
23
- const hasLlm = hasCustomLlm(options);
24
- const hasModel = "model" in options && options.model !== undefined && options.model !== null;
25
- if (hasLlm && hasModel) {
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
- return "llm" in options && typeof options.llm === "function";
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","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AACA,OAAO,EAAmB,SAAS,EAAY,MAAM,OAAO,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAuB,MAAM,mBAAmB,CAAC;AAkBtE,MAAM,OAAO,KAAK;IACP,IAAI,CAAM;IAEnB,YAAY,OAAqB;QAC/B,kBAAkB,CAAC,OAAO,CAAC,CAAC;QAE5B,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC;YAC/B,CAAC,CAAC,OAAO,CAAC,GAAG;YACb,CAAC,CAAC,SAAS,CAAC;gBACR,YAAY,EAAE,OAAO,CAAC,YAAY;gBAClC,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,KAAK,EAAE,OAAO,CAAC,KAAK;aACrB,CAAC,CAAC;IACT,CAAC;IAED,aAAa,CAAC,OAAwB;QACpC,OAAO,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;CACF;AAED,SAAS,kBAAkB,CAAC,OAAgB;IAC1C,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QACpD,MAAM,IAAI,SAAS,CACjB,kEAAkE,CACnE,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACrC,MAAM,QAAQ,GACZ,OAAO,IAAI,OAAO,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC,KAAK,KAAK,IAAI,CAAC;IAE9E,IAAI,MAAM,IAAI,QAAQ,EAAE,CAAC;QACvB,MAAM,IAAI,SAAS,CACjB,2EAA2E,CAC5E,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,IAAI,OAAO,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,IAAI,CAAC,MAAM,EAAE,CAAC;QAC7D,MAAM,IAAI,SAAS,CAAC,yCAAyC,CAAC,CAAC;IACjE,CAAC;IAED,IAAI,CAAC,CAAC,MAAM,IAAI,QAAQ,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,SAAS,CAAC,2CAA2C,CAAC,CAAC;IACnE,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,OAAe;IACnC,OAAO,KAAK,IAAI,OAAO,IAAI,OAAO,OAAO,CAAC,GAAG,KAAK,UAAU,CAAC;AAC/D,CAAC"}
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
- export { Agent, type AgentOptions } from "./agent";
2
- export { type AgentLoopResult, runAgentLoop } from "./agent-loop";
3
- export type { AgentMessage, AgentModel, AgentTool, AgentToolExecute, AgentToolExecutionOptions, AgentTools, LlmOutputPart, RuntimeCreateLlmOptions, RuntimeLlm, RuntimeLlmContext, RuntimeLlmOutput, } from "./llm";
4
- export { createLlm } from "./llm";
5
- export type { AgentEvent, AgentEventListener, AssistantReasoning, AssistantText, ToolCall, ToolResult, UserText, UserTextContent, } from "./session/events";
6
- export { AgentSession, type SessionInput, type SessionOptions, } from "./session/session";
7
- //# sourceMappingURL=index.d.ts.map
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
- export { Agent } from "./agent.js";
2
- export { runAgentLoop } from "./agent-loop.js";
3
- export { createLlm } from "./llm.js";
4
- export { AgentSession, } from "./session/session.js";
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 type { LanguageModel, ModelMessage, Tool, ToolExecutionOptions, ToolSet } from "ai";
2
- import { generateText } from "ai";
3
- export type AgentToolExecutionOptions = ToolExecutionOptions<unknown>;
4
- export type AgentToolExecute = NonNullable<Tool["execute"]>;
5
- export type AgentTool = Tool;
6
- export type AgentTools = ToolSet;
7
- export type AgentModel = LanguageModel;
8
- export type AgentMessage = ModelMessage;
9
- export type LlmOutput = Awaited<ReturnType<typeof generateText>>["responseMessages"];
10
- export type LlmOutputPart = LlmOutput[number];
11
- export interface LlmContext {
12
- history: readonly ModelMessage[];
13
- signal: AbortSignal;
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
- export type Llm = (context: LlmContext) => Promise<LlmOutput>;
16
- export interface CreateLlmOptions {
17
- instructions?: string;
18
- model: LanguageModel;
19
- tools?: AgentTools;
16
+ type Llm = (context: LlmContext) => Promise<LlmOutput>;
17
+ interface CreateLlmOptions {
18
+ instructions?: string;
19
+ model: LanguageModel;
20
+ tools?: AgentTools;
20
21
  }
21
- export type RuntimeCreateLlmOptions = CreateLlmOptions;
22
- export type RuntimeLlm = Llm;
23
- export type RuntimeLlmContext = LlmContext;
24
- export type RuntimeLlmOutput = LlmOutput;
25
- export declare function createLlm({ model, instructions, tools, }: CreateLlmOptions): Llm;
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
- export function createLlm({ model, instructions, tools, }) {
3
- return async ({ history, signal }) => {
4
- const { responseMessages } = await generateText({
5
- abortSignal: signal,
6
- instructions,
7
- messages: [...history],
8
- model,
9
- tools,
10
- });
11
- return responseMessages;
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