@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.
Files changed (46) hide show
  1. package/README.md +89 -101
  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 +29 -23
  11. package/dist/llm.js +15 -11
  12. package/dist/llm.js.map +1 -1
  13. package/dist/session/events.d.ts +76 -61
  14. package/dist/session/history.js +32 -30
  15. package/dist/session/history.js.map +1 -1
  16. package/dist/session/mapping.js +92 -52
  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 +9 -16
  22. package/dist/session/session.js +193 -320
  23. package/dist/session/session.js.map +1 -1
  24. package/dist/session/snapshot.js +20 -0
  25. package/dist/session/snapshot.js.map +1 -0
  26. package/dist/session/store/file.d.ts +14 -0
  27. package/dist/session/store/file.js +106 -0
  28. package/dist/session/store/file.js.map +1 -0
  29. package/dist/session/store/memory.d.ts +13 -0
  30. package/dist/session/store/memory.js +31 -0
  31. package/dist/session/store/memory.js.map +1 -0
  32. package/dist/session/store/types.d.ts +22 -0
  33. package/package.json +16 -2
  34. package/dist/agent-loop.d.ts.map +0 -1
  35. package/dist/agent.d.ts.map +0 -1
  36. package/dist/index.d.ts.map +0 -1
  37. package/dist/index.js.map +0 -1
  38. package/dist/llm.d.ts.map +0 -1
  39. package/dist/session/events.d.ts.map +0 -1
  40. package/dist/session/events.js +0 -2
  41. package/dist/session/events.js.map +0 -1
  42. package/dist/session/history.d.ts +0 -11
  43. package/dist/session/history.d.ts.map +0 -1
  44. package/dist/session/mapping.d.ts +0 -7
  45. package/dist/session/mapping.d.ts.map +0 -1
  46. 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
- 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
17
+ const run = await agent.send("Hello");
18
+ for await (const event of run.stream()) {
19
+ console.log(event);
20
+ }
21
+ ```
22
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.
23
+ Per-key conversations use `session(key)`:
27
24
 
28
25
  ```ts
29
- import { type AgentMessage } from "@minpeter/pss-runtime";
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
- const history: AgentMessage[] = [
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
- const session = agent.createSession({ history });
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
- const currentHistory: AgentMessage[] = session.getHistory();
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
- `getHistory()` returns a cloned snapshot, so callers can persist or inspect it
42
- without mutating the session.
50
+ File parts use the same JSON-serializable shape when the selected model supports
51
+ file input:
43
52
 
44
- ### Reactive storage synchronization
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
- 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`.
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
- 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.
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
- ```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
- }
88
- }
89
- ```
73
+ ## Session storage and portability
90
74
 
91
- ### Safe event subscriptions
75
+ The runtime owns full session state encoding and history compaction semantics.
76
+ Adapters own persistence only through `SessionStore`:
92
77
 
93
- When subscribing to session events, unsubscribe in a `finally` block to prevent
94
- listener leaks in persistent environments or multi-turn execution loops.
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
- 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
- });
83
+ import type { SessionStore } from "@minpeter/pss-runtime";
84
+ import { MemorySessionStore } from "@minpeter/pss-runtime/session-store/memory";
110
85
 
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
- }
86
+ const agent = await Agent.create({
87
+ model,
88
+ sessions: {
89
+ store: new MemorySessionStore(), // default when omitted
90
+ },
91
+ });
117
92
  ```
118
93
 
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.
94
+ For durable sessions, use the exported file POC:
123
95
 
124
96
  ```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
- ],
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.
@@ -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 { 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
- 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,32 @@
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 LlmOutput = Awaited<ReturnType<typeof generateText>>["responseMessages"];
10
+ type LlmOutputPart = LlmOutput[number];
11
+ interface LlmContext {
12
+ history: readonly ModelMessage[];
13
+ signal: AbortSignal;
14
14
  }
15
- export type Llm = (context: LlmContext) => Promise<LlmOutput>;
16
- export interface CreateLlmOptions {
17
- instructions?: string;
18
- model: LanguageModel;
19
- tools?: AgentTools;
15
+ type Llm = (context: LlmContext) => Promise<LlmOutput>;
16
+ interface CreateLlmOptions {
17
+ instructions?: string;
18
+ model: LanguageModel;
19
+ tools?: AgentTools;
20
20
  }
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;
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