@minpeter/pss-runtime 0.0.6 → 0.0.7

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.
@@ -1,5 +1,6 @@
1
1
  import { Llm } from "./llm.js";
2
2
  import { AgentEventListener } from "./session/events.js";
3
+ import { AgentHooks } from "./hooks.js";
3
4
  import { ModelMessage } from "ai";
4
5
 
5
6
  //#region src/agent-loop.d.ts
@@ -10,6 +11,7 @@ interface ModelHistory {
10
11
  interface RunAgentLoopOptions {
11
12
  emit: AgentEventListener;
12
13
  history: ModelHistory;
14
+ hooks?: AgentHooks;
13
15
  llm: Llm;
14
16
  signal?: AbortSignal;
15
17
  }
@@ -17,6 +19,7 @@ type AgentLoopResult = "completed" | "aborted";
17
19
  declare function runAgentLoop({
18
20
  emit,
19
21
  history,
22
+ hooks,
20
23
  llm,
21
24
  signal
22
25
  }: RunAgentLoopOptions): Promise<AgentLoopResult>;
@@ -1,7 +1,14 @@
1
1
  import { modelMessageToAgentEvents } from "./session/mapping.js";
2
2
  //#region src/agent-loop.ts
3
- async function runAgentLoop({ emit, history, llm, signal = new AbortController().signal }) {
3
+ async function runAgentLoop({ emit, history, hooks, llm, signal = new AbortController().signal }) {
4
+ let stepIndex = 0;
4
5
  while (true) {
6
+ if (signal.aborted) return "aborted";
7
+ await hooks?.beforeStep?.({
8
+ history: history.modelSnapshot(),
9
+ signal,
10
+ stepIndex
11
+ });
5
12
  if (signal.aborted) return "aborted";
6
13
  emit({ type: "step-start" });
7
14
  const output = await readLlmOutput({
@@ -17,10 +24,22 @@ async function runAgentLoop({ emit, history, llm, signal = new AbortController()
17
24
  signal
18
25
  });
19
26
  if (result === "aborted") return "aborted";
27
+ await runAfterStepHook(hooks, {
28
+ history: history.modelSnapshot(),
29
+ result,
30
+ signal,
31
+ stepIndex
32
+ });
20
33
  emit({ type: "step-end" });
21
34
  if (result === "completed") return "completed";
35
+ stepIndex += 1;
22
36
  }
23
37
  }
38
+ async function runAfterStepHook(hooks, context) {
39
+ const hook = hooks?.afterStep;
40
+ if (!hook) return;
41
+ await Promise.allSettled([Promise.resolve().then(() => hook(context))]);
42
+ }
24
43
  async function readLlmOutput({ history, llm, signal }) {
25
44
  try {
26
45
  return await llm({
@@ -1 +1 @@
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"}
1
+ {"version":3,"file":"agent-loop.js","names":[],"sources":["../src/agent-loop.ts"],"sourcesContent":["import type { ModelMessage } from \"ai\";\nimport type { AgentHooks, AgentStepResult } from \"./hooks\";\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 hooks?: AgentHooks;\n llm: Llm;\n signal?: AbortSignal;\n}\n\nexport type AgentLoopResult = \"completed\" | \"aborted\";\ntype StepOutputResult = AgentStepResult | \"aborted\";\n\nexport async function runAgentLoop({\n emit,\n history,\n hooks,\n llm,\n signal = new AbortController().signal,\n}: RunAgentLoopOptions): Promise<AgentLoopResult> {\n let stepIndex = 0;\n\n while (true) {\n if (signal.aborted) {\n return \"aborted\";\n }\n\n await hooks?.beforeStep?.({\n history: history.modelSnapshot(),\n signal,\n stepIndex,\n });\n\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 await runAfterStepHook(hooks, {\n history: history.modelSnapshot(),\n result,\n signal,\n stepIndex,\n });\n emit({ type: \"step-end\" });\n\n if (result === \"completed\") {\n return \"completed\";\n }\n\n stepIndex += 1;\n }\n}\n\nasync function runAfterStepHook(\n hooks: AgentHooks | undefined,\n context: Parameters<NonNullable<AgentHooks[\"afterStep\"]>>[0]\n): Promise<void> {\n const hook = hooks?.afterStep;\n if (!hook) {\n return;\n }\n\n await Promise.allSettled([Promise.resolve().then(() => hook(context))]);\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":";;AAsBA,eAAsB,aAAa,EACjC,MACA,SACA,OACA,KACA,SAAS,IAAI,gBAAgB,EAAE,UACiB;CAChD,IAAI,YAAY;CAEhB,OAAO,MAAM;EACX,IAAI,OAAO,SACT,OAAO;EAGT,MAAM,OAAO,aAAa;GACxB,SAAS,QAAQ,cAAc;GAC/B;GACA;EACF,CAAC;EAED,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,MAAM,iBAAiB,OAAO;GAC5B,SAAS,QAAQ,cAAc;GAC/B;GACA;GACA;EACF,CAAC;EACD,KAAK,EAAE,MAAM,WAAW,CAAC;EAEzB,IAAI,WAAW,aACb,OAAO;EAGT,aAAa;CACf;AACF;AAEA,eAAe,iBACb,OACA,SACe;CACf,MAAM,OAAO,OAAO;CACpB,IAAI,CAAC,MACH;CAGF,MAAM,QAAQ,WAAW,CAAC,QAAQ,QAAQ,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC;AACxE;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,22 +1,27 @@
1
- import { AgentTools, Llm } from "./llm.js";
1
+ import { AgentToolChoice, AgentTools, Llm } from "./llm.js";
2
2
  import { AgentRun } from "./session/run.js";
3
3
  import { SessionStore } from "./session/store/types.js";
4
4
  import { AgentInput } from "./session/session.js";
5
+ import { AgentHooks } from "./hooks.js";
5
6
  import { LanguageModel } from "ai";
6
7
 
7
8
  //#region src/agent.d.ts
8
9
  interface AgentModelOptions {
10
+ hooks?: AgentHooks;
9
11
  instructions?: string;
10
12
  llm?: never;
11
13
  model: LanguageModel;
12
14
  sessions?: AgentSessionOptions;
15
+ toolChoice?: AgentToolChoice;
13
16
  tools?: AgentTools;
14
17
  }
15
18
  interface AgentLlmOptions {
19
+ hooks?: AgentHooks;
16
20
  instructions?: never;
17
21
  llm: Llm;
18
22
  model?: never;
19
23
  sessions?: AgentSessionOptions;
24
+ toolChoice?: never;
20
25
  tools?: never;
21
26
  }
22
27
  interface AgentSessionOptions {
package/dist/agent.js CHANGED
@@ -3,15 +3,18 @@ import { AgentSession } from "./session/session.js";
3
3
  import { MemorySessionStore } from "./session/store/memory.js";
4
4
  //#region src/agent.ts
5
5
  var Agent = class Agent {
6
+ #hooks;
6
7
  #llm;
7
8
  #sessions = /* @__PURE__ */ new Map();
8
9
  #store;
9
10
  constructor(options) {
10
11
  assertAgentOptions(options);
11
12
  this.#store = options.sessions?.store ?? new MemorySessionStore();
13
+ this.#hooks = options.hooks;
12
14
  this.#llm = hasCustomLlm(options) ? options.llm : createLlm({
13
15
  instructions: options.instructions,
14
16
  model: options.model,
17
+ toolChoice: options.toolChoice,
15
18
  tools: options.tools
16
19
  });
17
20
  }
@@ -27,7 +30,7 @@ var Agent = class Agent {
27
30
  const session = new AgentSession(this.#llm, {
28
31
  key,
29
32
  store: this.#store
30
- });
33
+ }, this.#hooks);
31
34
  const handle = {
32
35
  interrupt: () => session.interrupt(),
33
36
  kill: () => {
package/dist/agent.js.map CHANGED
@@ -1 +1 @@
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"}
1
+ {"version":3,"file":"agent.js","names":["#hooks","#llm","#sessions","#store"],"sources":["../src/agent.ts"],"sourcesContent":["import type { LanguageModel } from \"ai\";\nimport type { AgentHooks } from \"./hooks\";\nimport {\n type AgentToolChoice,\n type AgentTools,\n createLlm,\n type Llm,\n} 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 hooks?: AgentHooks;\n instructions?: string;\n llm?: never;\n model: LanguageModel;\n sessions?: AgentSessionOptions;\n toolChoice?: AgentToolChoice;\n tools?: AgentTools;\n}\n\ninterface AgentLlmOptions {\n hooks?: AgentHooks;\n instructions?: never;\n llm: Llm;\n model?: never;\n sessions?: AgentSessionOptions;\n toolChoice?: never;\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 #hooks?: AgentHooks;\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.#hooks = options.hooks;\n this.#llm = hasCustomLlm(options)\n ? options.llm\n : createLlm({\n instructions: options.instructions,\n model: options.model,\n toolChoice: options.toolChoice,\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(\n this.#llm,\n { key, store: this.#store },\n this.#hooks\n );\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":";;;;AA6CA,IAAa,QAAb,MAAa,MAAM;CACjB;CACA;CACA,4BAAqB,IAAI,IAA2B;CACpD;CAEA,YAAoB,SAAuB;EACzC,mBAAmB,OAAO;EAE1B,KAAKG,SAAS,QAAQ,UAAU,SAAS,IAAI,mBAAmB;EAChE,KAAKH,SAAS,QAAQ;EACtB,KAAKC,OAAO,aAAa,OAAO,IAC5B,QAAQ,MACR,UAAU;GACR,cAAc,QAAQ;GACtB,OAAO,QAAQ;GACf,YAAY,QAAQ;GACpB,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,aAClB,KAAKD,MACL;GAAE;GAAK,OAAO,KAAKE;EAAO,GAC1B,KAAKH,MACP;EACA,MAAM,SAAwB;GAC5B,iBAAiB,QAAQ,UAAU;GACnC,YAAY;IACV,QAAQ,KAAK;IACb,KAAKE,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"}
@@ -0,0 +1,32 @@
1
+ import { RuntimeLlmContext } from "./llm.js";
2
+ import { UserInput } from "./session/session.js";
3
+
4
+ //#region src/hooks.d.ts
5
+ type AgentTurnResult = "aborted" | "completed";
6
+ type AgentStepResult = "completed" | "continue";
7
+ type MaybePromise<T> = PromiseLike<T> | T;
8
+ interface AgentBeforeTurnContext {
9
+ readonly history: RuntimeLlmContext["history"];
10
+ readonly input: UserInput;
11
+ readonly signal: AbortSignal;
12
+ }
13
+ interface AgentAfterTurnContext extends AgentBeforeTurnContext {
14
+ readonly result: AgentTurnResult;
15
+ }
16
+ interface AgentBeforeStepContext {
17
+ readonly history: RuntimeLlmContext["history"];
18
+ readonly signal: AbortSignal;
19
+ readonly stepIndex: number;
20
+ }
21
+ interface AgentAfterStepContext extends AgentBeforeStepContext {
22
+ readonly result: AgentStepResult;
23
+ }
24
+ interface AgentHooks {
25
+ afterStep?(context: AgentAfterStepContext): MaybePromise<void>;
26
+ afterTurn?(context: AgentAfterTurnContext): MaybePromise<void>;
27
+ beforeStep?(context: AgentBeforeStepContext): MaybePromise<void>;
28
+ beforeTurn?(context: AgentBeforeTurnContext): MaybePromise<void>;
29
+ }
30
+ //#endregion
31
+ export { AgentAfterStepContext, AgentAfterTurnContext, AgentBeforeStepContext, AgentBeforeTurnContext, AgentHooks, AgentStepResult, AgentTurnResult };
32
+ //# sourceMappingURL=hooks.d.ts.map
package/dist/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
- import { AgentModel, AgentTool, AgentToolExecute, AgentToolExecutionOptions, AgentTools, LlmOutputPart, RuntimeCreateLlmOptions, RuntimeLlm, RuntimeLlmContext, RuntimeLlmOutput, createLlm } from "./llm.js";
1
+ import { AgentModel, AgentTool, AgentToolChoice, AgentToolExecute, AgentToolExecutionOptions, AgentTools, LlmOutputPart, RuntimeCreateLlmOptions, RuntimeLlm, RuntimeLlmContext, RuntimeLlmOutput, createLlm } from "./llm.js";
2
2
  import { AgentEvent, AgentEventListener, AssistantReasoning, AssistantText, ToolCall, ToolResult, UserMessage, UserMessageContent, UserMessageContentPart, UserMessageFileData, UserMessageFilePart, UserMessageImagePart, UserMessageTextPart, UserText, UserTextContent } from "./session/events.js";
3
3
  import { AgentRun } from "./session/run.js";
4
4
  import { CommitResult, ExpectedSessionVersion, SessionStore, StoredSession } from "./session/store/types.js";
5
5
  import { AgentInput, SessionInput, UserInput } from "./session/session.js";
6
+ import { AgentAfterStepContext, AgentAfterTurnContext, AgentBeforeStepContext, AgentBeforeTurnContext, AgentHooks, AgentStepResult, AgentTurnResult } from "./hooks.js";
6
7
  import { Agent, AgentOptions, AgentSessionOptions, SessionHandle } from "./agent.js";
7
8
  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 };
9
+ export { Agent, type AgentAfterStepContext, type AgentAfterTurnContext, type AgentBeforeStepContext, type AgentBeforeTurnContext, type AgentEvent, type AgentEventListener, type AgentHooks, type AgentInput, type AgentLoopResult, type AgentModel, type AgentOptions, type AgentRun, type AgentSessionOptions, type AgentStepResult, type AgentTool, type AgentToolChoice, type AgentToolExecute, type AgentToolExecutionOptions, type AgentTools, type AgentTurnResult, 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/llm.d.ts CHANGED
@@ -5,6 +5,7 @@ type AgentToolExecutionOptions = ToolExecutionOptions<unknown>;
5
5
  type AgentToolExecute = NonNullable<Tool["execute"]>;
6
6
  type AgentTool = Tool;
7
7
  type AgentTools = ToolSet;
8
+ type AgentToolChoice = "auto" | "required";
8
9
  type AgentModel = LanguageModel;
9
10
  type LlmOutput = Awaited<ReturnType<typeof generateText>>["responseMessages"];
10
11
  type LlmOutputPart = LlmOutput[number];
@@ -16,6 +17,7 @@ type Llm = (context: LlmContext) => Promise<LlmOutput>;
16
17
  interface CreateLlmOptions {
17
18
  instructions?: string;
18
19
  model: LanguageModel;
20
+ toolChoice?: AgentToolChoice;
19
21
  tools?: AgentTools;
20
22
  }
21
23
  type RuntimeCreateLlmOptions = CreateLlmOptions;
@@ -25,8 +27,9 @@ type RuntimeLlmOutput = LlmOutput;
25
27
  declare function createLlm({
26
28
  model,
27
29
  instructions,
30
+ toolChoice,
28
31
  tools
29
32
  }: CreateLlmOptions): Llm;
30
33
  //#endregion
31
- export { AgentModel, AgentTool, AgentToolExecute, AgentToolExecutionOptions, AgentTools, Llm, LlmOutputPart, RuntimeCreateLlmOptions, RuntimeLlm, RuntimeLlmContext, RuntimeLlmOutput, createLlm };
34
+ export { AgentModel, AgentTool, AgentToolChoice, AgentToolExecute, AgentToolExecutionOptions, AgentTools, Llm, LlmOutputPart, RuntimeCreateLlmOptions, RuntimeLlm, RuntimeLlmContext, RuntimeLlmOutput, createLlm };
32
35
  //# sourceMappingURL=llm.d.ts.map
package/dist/llm.js CHANGED
@@ -1,12 +1,13 @@
1
1
  import { generateText } from "ai";
2
2
  //#region src/llm.ts
3
- function createLlm({ model, instructions, tools }) {
3
+ function createLlm({ model, instructions, toolChoice, tools }) {
4
4
  return async ({ history, signal }) => {
5
5
  const { responseMessages } = await generateText({
6
6
  abortSignal: signal,
7
7
  instructions,
8
8
  messages: [...history],
9
9
  model,
10
+ toolChoice,
10
11
  tools
11
12
  });
12
13
  return responseMessages;
package/dist/llm.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"llm.js","names":[],"sources":["../src/llm.ts"],"sourcesContent":["import type {\n LanguageModel,\n ModelMessage,\n Tool,\n ToolExecutionOptions,\n ToolSet,\n} from \"ai\";\nimport { generateText } from \"ai\";\n\nexport type AgentToolExecutionOptions = ToolExecutionOptions<unknown>;\nexport type AgentToolExecute = NonNullable<Tool[\"execute\"]>;\nexport type AgentTool = Tool;\nexport type AgentTools = ToolSet;\nexport type AgentModel = LanguageModel;\nexport type AgentMessage = ModelMessage;\nexport type LlmOutput = Awaited<\n ReturnType<typeof generateText>\n>[\"responseMessages\"];\nexport type LlmOutputPart = LlmOutput[number];\n\nexport interface LlmContext {\n history: readonly ModelMessage[];\n signal: AbortSignal;\n}\n\nexport type Llm = (context: LlmContext) => Promise<LlmOutput>;\n\nexport interface CreateLlmOptions {\n instructions?: string;\n model: LanguageModel;\n tools?: AgentTools;\n}\n\nexport type RuntimeCreateLlmOptions = CreateLlmOptions;\nexport type RuntimeLlm = Llm;\nexport type RuntimeLlmContext = LlmContext;\nexport type RuntimeLlmOutput = LlmOutput;\n\nexport function createLlm({\n model,\n instructions,\n tools,\n}: CreateLlmOptions): Llm {\n return async ({ history, signal }) => {\n const { responseMessages } = await generateText({\n abortSignal: signal,\n instructions,\n messages: [...history],\n model,\n tools,\n });\n\n return responseMessages;\n };\n}\n"],"mappings":";;AAsCA,SAAgB,UAAU,EACxB,OACA,cACA,SACwB;CACxB,OAAO,OAAO,EAAE,SAAS,aAAa;EACpC,MAAM,EAAE,qBAAqB,MAAM,aAAa;GAC9C,aAAa;GACb;GACA,UAAU,CAAC,GAAG,OAAO;GACrB;GACA;EACF,CAAC;EAED,OAAO;CACT;AACF"}
1
+ {"version":3,"file":"llm.js","names":[],"sources":["../src/llm.ts"],"sourcesContent":["import type {\n LanguageModel,\n ModelMessage,\n Tool,\n ToolExecutionOptions,\n ToolSet,\n} from \"ai\";\nimport { generateText } from \"ai\";\n\nexport type AgentToolExecutionOptions = ToolExecutionOptions<unknown>;\nexport type AgentToolExecute = NonNullable<Tool[\"execute\"]>;\nexport type AgentTool = Tool;\nexport type AgentTools = ToolSet;\nexport type AgentToolChoice = \"auto\" | \"required\";\nexport type AgentModel = LanguageModel;\nexport type AgentMessage = ModelMessage;\nexport type LlmOutput = Awaited<\n ReturnType<typeof generateText>\n>[\"responseMessages\"];\nexport type LlmOutputPart = LlmOutput[number];\n\nexport interface LlmContext {\n history: readonly ModelMessage[];\n signal: AbortSignal;\n}\n\nexport type Llm = (context: LlmContext) => Promise<LlmOutput>;\n\nexport interface CreateLlmOptions {\n instructions?: string;\n model: LanguageModel;\n toolChoice?: AgentToolChoice;\n tools?: AgentTools;\n}\n\nexport type RuntimeCreateLlmOptions = CreateLlmOptions;\nexport type RuntimeLlm = Llm;\nexport type RuntimeLlmContext = LlmContext;\nexport type RuntimeLlmOutput = LlmOutput;\n\nexport function createLlm({\n model,\n instructions,\n toolChoice,\n tools,\n}: CreateLlmOptions): Llm {\n return async ({ history, signal }) => {\n const { responseMessages } = await generateText({\n abortSignal: signal,\n instructions,\n messages: [...history],\n model,\n toolChoice,\n tools,\n });\n\n return responseMessages;\n };\n}\n"],"mappings":";;AAwCA,SAAgB,UAAU,EACxB,OACA,cACA,YACA,SACwB;CACxB,OAAO,OAAO,EAAE,SAAS,aAAa;EACpC,MAAM,EAAE,qBAAqB,MAAM,aAAa;GAC9C,aAAa;GACb;GACA,UAAU,CAAC,GAAG,OAAO;GACrB;GACA;GACA;EACF,CAAC;EAED,OAAO;CACT;AACF"}
@@ -1,6 +1,5 @@
1
1
  import { UserMessage, UserMessageContentPart, UserText } from "./events.js";
2
2
  import { AgentRun } from "./run.js";
3
-
4
3
  //#region src/session/session.d.ts
5
4
  type UserInput = UserMessage | UserText;
6
5
  type AgentInput = readonly string[] | readonly UserMessageContentPart[] | string | UserInput;
@@ -4,6 +4,7 @@ import { BufferedAgentRun } from "./run.js";
4
4
  import { decodeStoredSessionSnapshot, encodeSessionSnapshot } from "./snapshot.js";
5
5
  //#region src/session/session.ts
6
6
  var AgentSession = class {
7
+ #hooks;
7
8
  #inputQueue = [];
8
9
  #llm;
9
10
  #persistence;
@@ -14,7 +15,8 @@ var AgentSession = class {
14
15
  #loaded = false;
15
16
  #running = false;
16
17
  #storeVersion;
17
- constructor(llm, persistence) {
18
+ constructor(llm, persistence, hooks) {
19
+ this.#hooks = hooks;
18
20
  this.#llm = llm;
19
21
  this.#persistence = persistence;
20
22
  }
@@ -90,16 +92,28 @@ var AgentSession = class {
90
92
  this.#activeAbort = new AbortController();
91
93
  const historySnapshot = this.#history.modelSnapshot();
92
94
  try {
95
+ await this.#hooks?.beforeTurn?.({
96
+ history: this.#history.modelSnapshot(),
97
+ input,
98
+ signal: this.#activeAbort.signal
99
+ });
93
100
  run.emit({ type: "turn-start" });
94
101
  this.#history.appendUserInput(input);
95
102
  await this.#commitHistory();
96
103
  const result = await runAgentLoop({
97
104
  emit: (event) => run.emit(event),
98
105
  history: this.#history,
106
+ hooks: this.#hooks,
99
107
  llm: this.#llm,
100
108
  signal: this.#activeAbort.signal
101
109
  });
102
110
  await this.#commitHistory();
111
+ await runAfterTurnHook(this.#hooks, {
112
+ history: this.#history.modelSnapshot(),
113
+ input,
114
+ result,
115
+ signal: this.#activeAbort.signal
116
+ });
103
117
  run.emit({ type: result === "aborted" ? "turn-abort" : "turn-end" });
104
118
  } catch (error) {
105
119
  if (error instanceof SessionCommitConflictError) {
@@ -140,6 +154,11 @@ var AgentSession = class {
140
154
  this.#storeVersion = result.version;
141
155
  }
142
156
  };
157
+ async function runAfterTurnHook(hooks, context) {
158
+ const hook = hooks?.afterTurn;
159
+ if (!hook) return;
160
+ await Promise.allSettled([Promise.resolve().then(() => hook(context))]);
161
+ }
143
162
  function normalizeAgentInput(input) {
144
163
  if (typeof input === "string") return {
145
164
  type: "user-text",
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","names":["#inputQueue","#llm","#persistence","#killed","#ensureLoaded","#drainInputQueue","#activeAbort","#loaded","#loadPromise","#loadSessionState","#replaceWithStoredSession","#storeVersion","#history","#running","#processQueuedInput","#commitHistory"],"sources":["../../src/session/session.ts"],"sourcesContent":["import { runAgentLoop } from \"../agent-loop\";\nimport type { Llm } from \"../llm\";\nimport type { UserMessage, UserMessageContentPart, UserText } from \"./events\";\nimport { AgentModelHistory } from \"./history\";\nimport type { AgentRun } from \"./run\";\nimport { BufferedAgentRun } from \"./run\";\nimport { decodeStoredSessionSnapshot, encodeSessionSnapshot } from \"./snapshot\";\nimport type { SessionStore } from \"./store/types\";\n\nexport type UserInput = UserMessage | UserText;\nexport type AgentInput =\n | readonly string[]\n | readonly UserMessageContentPart[]\n | string\n | UserInput;\nexport type SessionInput = AgentInput;\nexport type { AgentRun } from \"./run\";\n\ninterface SessionPersistenceOptions {\n readonly key: string;\n readonly store: SessionStore;\n}\n\ninterface QueuedInput {\n readonly input: UserInput;\n readonly run: BufferedAgentRun;\n}\n\nexport class AgentSession {\n readonly #inputQueue: QueuedInput[] = [];\n readonly #llm: Llm;\n readonly #persistence: SessionPersistenceOptions;\n #activeAbort?: AbortController;\n #history = new AgentModelHistory();\n #killed = false;\n #loadPromise?: Promise<void>;\n #loaded = false;\n #running = false;\n #storeVersion: string | undefined;\n\n constructor(llm: Llm, persistence: SessionPersistenceOptions) {\n this.#llm = llm;\n this.#persistence = persistence;\n }\n\n async send(input: AgentInput): Promise<AgentRun> {\n if (this.#killed) {\n throw sessionKilledError();\n }\n\n await this.#ensureLoaded();\n\n if (this.#killed) {\n throw sessionKilledError();\n }\n\n const acceptedInput = normalizeAgentInput(input);\n const run = new BufferedAgentRun();\n run.emit(acceptedInput);\n this.#inputQueue.push({ input: structuredClone(acceptedInput), run });\n this.#drainInputQueue().catch((error: unknown) => {\n run.emit({ type: \"turn-error\", message: errorMessage(error) });\n run.close();\n });\n return run;\n }\n\n interrupt(): void {\n this.#activeAbort?.abort();\n }\n\n kill(): void {\n if (this.#killed) {\n return;\n }\n\n this.#killed = true;\n this.#activeAbort?.abort();\n\n while (this.#inputQueue.length > 0) {\n const item = this.#inputQueue.shift();\n item?.run.emit({\n type: \"turn-error\",\n message: sessionKilledError().message,\n });\n item?.run.close();\n }\n }\n\n async #ensureLoaded(): Promise<void> {\n if (this.#loaded) {\n return;\n }\n\n this.#loadPromise ??= this.#loadSessionState();\n try {\n await this.#loadPromise;\n } catch (error) {\n this.#loadPromise = undefined;\n throw error;\n }\n }\n\n async #loadSessionState(): Promise<void> {\n if (this.#loaded) {\n return;\n }\n\n await this.#replaceWithStoredSession();\n this.#loaded = true;\n }\n\n async #replaceWithStoredSession(): Promise<void> {\n const stored = await this.#persistence.store.load(this.#persistence.key);\n this.#storeVersion = stored?.version;\n this.#history = new AgentModelHistory(decodeStoredSessionSnapshot(stored));\n }\n\n async #drainInputQueue(): Promise<void> {\n if (this.#running) {\n return;\n }\n\n this.#running = true;\n try {\n while (!this.#killed && this.#inputQueue.length > 0) {\n const item = this.#inputQueue.shift();\n if (item) {\n await this.#processQueuedInput(item);\n }\n }\n } finally {\n this.#running = false;\n }\n }\n\n async #processQueuedInput({ input, run }: QueuedInput): Promise<void> {\n this.#activeAbort = new AbortController();\n const historySnapshot = this.#history.modelSnapshot();\n\n try {\n run.emit({ type: \"turn-start\" });\n this.#history.appendUserInput(input);\n await this.#commitHistory();\n\n const result = await runAgentLoop({\n emit: (event) => run.emit(event),\n history: this.#history,\n llm: this.#llm,\n signal: this.#activeAbort.signal,\n });\n\n await this.#commitHistory();\n run.emit({ type: result === \"aborted\" ? \"turn-abort\" : \"turn-end\" });\n } catch (error) {\n if (error instanceof SessionCommitConflictError) {\n run.emit({ type: \"turn-error\", message: error.message });\n return;\n }\n\n this.#history.rollback(historySnapshot);\n try {\n await this.#commitHistory();\n } catch (rollbackError) {\n run.emit({\n type: \"turn-error\",\n message: `${errorMessage(error)}; history rollback persistence failed: ${errorMessage(\n rollbackError\n )}`,\n });\n return;\n }\n run.emit({ type: \"turn-error\", message: errorMessage(error) });\n } finally {\n run.close();\n this.#activeAbort = undefined;\n }\n }\n\n async #commitHistory(): Promise<void> {\n const result = await this.#persistence.store.commit(\n this.#persistence.key,\n {\n state: encodeSessionSnapshot(this.#history.modelSnapshot()),\n version: this.#storeVersion,\n },\n { expectedVersion: this.#storeVersion ?? null }\n );\n\n if (!result.ok) {\n await this.#replaceWithStoredSession();\n throw new SessionCommitConflictError(this.#persistence.key);\n }\n\n this.#storeVersion = result.version;\n }\n}\n\nexport function normalizeAgentInput(input: AgentInput): UserInput {\n if (typeof input === \"string\") {\n return {\n type: \"user-text\",\n text: input,\n };\n }\n\n if (isStringArrayInput(input)) {\n return {\n type: \"user-text\",\n text: structuredClone(input) as readonly string[],\n };\n }\n\n if (isArrayInput(input)) {\n assertUserMessageContent(input);\n return {\n type: \"user-message\",\n content: structuredClone(input) as readonly UserMessageContentPart[],\n };\n }\n\n if (isUserMessage(input)) {\n assertUserMessageContent(input.content);\n }\n\n return structuredClone(input);\n}\n\nfunction isStringArrayInput(input: AgentInput): input is readonly string[] {\n return isArrayInput(input) && input.every((part) => typeof part === \"string\");\n}\n\nfunction isArrayInput(\n input: AgentInput\n): input is readonly string[] | readonly UserMessageContentPart[] {\n return Array.isArray(input);\n}\n\nfunction isUserMessage(input: UserInput): input is UserMessage {\n return input.type === \"user-message\";\n}\n\nfunction assertUserMessageContent(\n input: readonly unknown[]\n): asserts input is readonly UserMessageContentPart[] {\n for (const part of input) {\n if (!isUserMessageContentPart(part)) {\n throw new TypeError(\n 'Agent input content parts must be { type: \"text\", text }, { type: \"image\", image }, or { type: \"file\", data, mediaType }.'\n );\n }\n }\n}\n\nfunction isUserMessageContentPart(\n part: unknown\n): part is UserMessageContentPart {\n if (part === null || typeof part !== \"object\" || !(\"type\" in part)) {\n return false;\n }\n\n if (part.type === \"text\") {\n return \"text\" in part && typeof part.text === \"string\";\n }\n\n if (part.type === \"image\") {\n return (\n \"image\" in part &&\n typeof part.image === \"string\" &&\n (!(\"mediaType\" in part) || typeof part.mediaType === \"string\")\n );\n }\n\n if (part.type === \"file\") {\n return (\n \"data\" in part &&\n isUserMessageFileData(part.data) &&\n \"mediaType\" in part &&\n typeof part.mediaType === \"string\" &&\n (!(\"filename\" in part) || typeof part.filename === \"string\")\n );\n }\n\n return false;\n}\n\nfunction isUserMessageFileData(data: unknown): boolean {\n if (typeof data === \"string\") {\n return true;\n }\n\n if (data === null || typeof data !== \"object\" || !(\"type\" in data)) {\n return false;\n }\n\n if (data.type === \"data\") {\n return \"data\" in data && typeof data.data === \"string\";\n }\n\n if (data.type === \"reference\") {\n return (\n \"reference\" in data &&\n data.reference !== null &&\n typeof data.reference === \"object\" &&\n Object.values(data.reference).every((value) => typeof value === \"string\")\n );\n }\n\n if (data.type === \"text\") {\n return \"text\" in data && typeof data.text === \"string\";\n }\n\n if (data.type === \"url\") {\n return \"url\" in data && typeof data.url === \"string\";\n }\n\n return false;\n}\n\nfunction errorMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n\n return String(error);\n}\n\nfunction sessionKilledError(): Error {\n return new Error(\"Session killed\");\n}\n\nclass SessionCommitConflictError extends Error {\n constructor(key: string) {\n super(`Session ${JSON.stringify(key)} commit conflict`);\n }\n}\n"],"mappings":";;;;;AA4BA,IAAa,eAAb,MAA0B;CACxB,cAAsC,CAAC;CACvC;CACA;CACA;CACA,WAAW,IAAI,kBAAkB;CACjC,UAAU;CACV;CACA,UAAU;CACV,WAAW;CACX;CAEA,YAAY,KAAU,aAAwC;EAC5D,KAAKC,OAAO;EACZ,KAAKC,eAAe;CACtB;CAEA,MAAM,KAAK,OAAsC;EAC/C,IAAI,KAAKC,SACP,MAAM,mBAAmB;EAG3B,MAAM,KAAKC,cAAc;EAEzB,IAAI,KAAKD,SACP,MAAM,mBAAmB;EAG3B,MAAM,gBAAgB,oBAAoB,KAAK;EAC/C,MAAM,MAAM,IAAI,iBAAiB;EACjC,IAAI,KAAK,aAAa;EACtB,KAAKH,YAAY,KAAK;GAAE,OAAO,gBAAgB,aAAa;GAAG;EAAI,CAAC;EACpE,KAAKK,iBAAiB,EAAE,OAAO,UAAmB;GAChD,IAAI,KAAK;IAAE,MAAM;IAAc,SAAS,aAAa,KAAK;GAAE,CAAC;GAC7D,IAAI,MAAM;EACZ,CAAC;EACD,OAAO;CACT;CAEA,YAAkB;EAChB,KAAKC,cAAc,MAAM;CAC3B;CAEA,OAAa;EACX,IAAI,KAAKH,SACP;EAGF,KAAKA,UAAU;EACf,KAAKG,cAAc,MAAM;EAEzB,OAAO,KAAKN,YAAY,SAAS,GAAG;GAClC,MAAM,OAAO,KAAKA,YAAY,MAAM;GACpC,MAAM,IAAI,KAAK;IACb,MAAM;IACN,SAAS,mBAAmB,EAAE;GAChC,CAAC;GACD,MAAM,IAAI,MAAM;EAClB;CACF;CAEA,MAAMI,gBAA+B;EACnC,IAAI,KAAKG,SACP;EAGF,KAAKC,iBAAiB,KAAKC,kBAAkB;EAC7C,IAAI;GACF,MAAM,KAAKD;EACb,SAAS,OAAO;GACd,KAAKA,eAAe,KAAA;GACpB,MAAM;EACR;CACF;CAEA,MAAMC,oBAAmC;EACvC,IAAI,KAAKF,SACP;EAGF,MAAM,KAAKG,0BAA0B;EACrC,KAAKH,UAAU;CACjB;CAEA,MAAMG,4BAA2C;EAC/C,MAAM,SAAS,MAAM,KAAKR,aAAa,MAAM,KAAK,KAAKA,aAAa,GAAG;EACvE,KAAKS,gBAAgB,QAAQ;EAC7B,KAAKC,WAAW,IAAI,kBAAkB,4BAA4B,MAAM,CAAC;CAC3E;CAEA,MAAMP,mBAAkC;EACtC,IAAI,KAAKQ,UACP;EAGF,KAAKA,WAAW;EAChB,IAAI;GACF,OAAO,CAAC,KAAKV,WAAW,KAAKH,YAAY,SAAS,GAAG;IACnD,MAAM,OAAO,KAAKA,YAAY,MAAM;IACpC,IAAI,MACF,MAAM,KAAKc,oBAAoB,IAAI;GAEvC;EACF,UAAU;GACR,KAAKD,WAAW;EAClB;CACF;CAEA,MAAMC,oBAAoB,EAAE,OAAO,OAAmC;EACpE,KAAKR,eAAe,IAAI,gBAAgB;EACxC,MAAM,kBAAkB,KAAKM,SAAS,cAAc;EAEpD,IAAI;GACF,IAAI,KAAK,EAAE,MAAM,aAAa,CAAC;GAC/B,KAAKA,SAAS,gBAAgB,KAAK;GACnC,MAAM,KAAKG,eAAe;GAE1B,MAAM,SAAS,MAAM,aAAa;IAChC,OAAO,UAAU,IAAI,KAAK,KAAK;IAC/B,SAAS,KAAKH;IACd,KAAK,KAAKX;IACV,QAAQ,KAAKK,aAAa;GAC5B,CAAC;GAED,MAAM,KAAKS,eAAe;GAC1B,IAAI,KAAK,EAAE,MAAM,WAAW,YAAY,eAAe,WAAW,CAAC;EACrE,SAAS,OAAO;GACd,IAAI,iBAAiB,4BAA4B;IAC/C,IAAI,KAAK;KAAE,MAAM;KAAc,SAAS,MAAM;IAAQ,CAAC;IACvD;GACF;GAEA,KAAKH,SAAS,SAAS,eAAe;GACtC,IAAI;IACF,MAAM,KAAKG,eAAe;GAC5B,SAAS,eAAe;IACtB,IAAI,KAAK;KACP,MAAM;KACN,SAAS,GAAG,aAAa,KAAK,EAAE,yCAAyC,aACvE,aACF;IACF,CAAC;IACD;GACF;GACA,IAAI,KAAK;IAAE,MAAM;IAAc,SAAS,aAAa,KAAK;GAAE,CAAC;EAC/D,UAAU;GACR,IAAI,MAAM;GACV,KAAKT,eAAe,KAAA;EACtB;CACF;CAEA,MAAMS,iBAAgC;EACpC,MAAM,SAAS,MAAM,KAAKb,aAAa,MAAM,OAC3C,KAAKA,aAAa,KAClB;GACE,OAAO,sBAAsB,KAAKU,SAAS,cAAc,CAAC;GAC1D,SAAS,KAAKD;EAChB,GACA,EAAE,iBAAiB,KAAKA,iBAAiB,KAAK,CAChD;EAEA,IAAI,CAAC,OAAO,IAAI;GACd,MAAM,KAAKD,0BAA0B;GACrC,MAAM,IAAI,2BAA2B,KAAKR,aAAa,GAAG;EAC5D;EAEA,KAAKS,gBAAgB,OAAO;CAC9B;AACF;AAEA,SAAgB,oBAAoB,OAA8B;CAChE,IAAI,OAAO,UAAU,UACnB,OAAO;EACL,MAAM;EACN,MAAM;CACR;CAGF,IAAI,mBAAmB,KAAK,GAC1B,OAAO;EACL,MAAM;EACN,MAAM,gBAAgB,KAAK;CAC7B;CAGF,IAAI,aAAa,KAAK,GAAG;EACvB,yBAAyB,KAAK;EAC9B,OAAO;GACL,MAAM;GACN,SAAS,gBAAgB,KAAK;EAChC;CACF;CAEA,IAAI,cAAc,KAAK,GACrB,yBAAyB,MAAM,OAAO;CAGxC,OAAO,gBAAgB,KAAK;AAC9B;AAEA,SAAS,mBAAmB,OAA+C;CACzE,OAAO,aAAa,KAAK,KAAK,MAAM,OAAO,SAAS,OAAO,SAAS,QAAQ;AAC9E;AAEA,SAAS,aACP,OACgE;CAChE,OAAO,MAAM,QAAQ,KAAK;AAC5B;AAEA,SAAS,cAAc,OAAwC;CAC7D,OAAO,MAAM,SAAS;AACxB;AAEA,SAAS,yBACP,OACoD;CACpD,KAAK,MAAM,QAAQ,OACjB,IAAI,CAAC,yBAAyB,IAAI,GAChC,MAAM,IAAI,UACR,iIACF;AAGN;AAEA,SAAS,yBACP,MACgC;CAChC,IAAI,SAAS,QAAQ,OAAO,SAAS,YAAY,EAAE,UAAU,OAC3D,OAAO;CAGT,IAAI,KAAK,SAAS,QAChB,OAAO,UAAU,QAAQ,OAAO,KAAK,SAAS;CAGhD,IAAI,KAAK,SAAS,SAChB,OACE,WAAW,QACX,OAAO,KAAK,UAAU,aACrB,EAAE,eAAe,SAAS,OAAO,KAAK,cAAc;CAIzD,IAAI,KAAK,SAAS,QAChB,OACE,UAAU,QACV,sBAAsB,KAAK,IAAI,KAC/B,eAAe,QACf,OAAO,KAAK,cAAc,aACzB,EAAE,cAAc,SAAS,OAAO,KAAK,aAAa;CAIvD,OAAO;AACT;AAEA,SAAS,sBAAsB,MAAwB;CACrD,IAAI,OAAO,SAAS,UAClB,OAAO;CAGT,IAAI,SAAS,QAAQ,OAAO,SAAS,YAAY,EAAE,UAAU,OAC3D,OAAO;CAGT,IAAI,KAAK,SAAS,QAChB,OAAO,UAAU,QAAQ,OAAO,KAAK,SAAS;CAGhD,IAAI,KAAK,SAAS,aAChB,OACE,eAAe,QACf,KAAK,cAAc,QACnB,OAAO,KAAK,cAAc,YAC1B,OAAO,OAAO,KAAK,SAAS,EAAE,OAAO,UAAU,OAAO,UAAU,QAAQ;CAI5E,IAAI,KAAK,SAAS,QAChB,OAAO,UAAU,QAAQ,OAAO,KAAK,SAAS;CAGhD,IAAI,KAAK,SAAS,OAChB,OAAO,SAAS,QAAQ,OAAO,KAAK,QAAQ;CAG9C,OAAO;AACT;AAEA,SAAS,aAAa,OAAwB;CAC5C,IAAI,iBAAiB,OACnB,OAAO,MAAM;CAGf,OAAO,OAAO,KAAK;AACrB;AAEA,SAAS,qBAA4B;CACnC,uBAAO,IAAI,MAAM,gBAAgB;AACnC;AAEA,IAAM,6BAAN,cAAyC,MAAM;CAC7C,YAAY,KAAa;EACvB,MAAM,WAAW,KAAK,UAAU,GAAG,EAAE,iBAAiB;CACxD;AACF"}
1
+ {"version":3,"file":"session.js","names":["#hooks","#inputQueue","#llm","#persistence","#killed","#ensureLoaded","#drainInputQueue","#activeAbort","#loaded","#loadPromise","#loadSessionState","#replaceWithStoredSession","#storeVersion","#history","#running","#processQueuedInput","#commitHistory"],"sources":["../../src/session/session.ts"],"sourcesContent":["import { runAgentLoop } from \"../agent-loop\";\nimport type { AgentHooks } from \"../hooks\";\nimport type { Llm } from \"../llm\";\nimport type { UserMessage, UserMessageContentPart, UserText } from \"./events\";\nimport { AgentModelHistory } from \"./history\";\nimport type { AgentRun } from \"./run\";\nimport { BufferedAgentRun } from \"./run\";\nimport { decodeStoredSessionSnapshot, encodeSessionSnapshot } from \"./snapshot\";\nimport type { SessionStore } from \"./store/types\";\n\nexport type UserInput = UserMessage | UserText;\nexport type AgentInput =\n | readonly string[]\n | readonly UserMessageContentPart[]\n | string\n | UserInput;\nexport type SessionInput = AgentInput;\nexport type { AgentRun } from \"./run\";\n\ninterface SessionPersistenceOptions {\n readonly key: string;\n readonly store: SessionStore;\n}\n\ninterface QueuedInput {\n readonly input: UserInput;\n readonly run: BufferedAgentRun;\n}\n\nexport class AgentSession {\n readonly #hooks?: AgentHooks;\n readonly #inputQueue: QueuedInput[] = [];\n readonly #llm: Llm;\n readonly #persistence: SessionPersistenceOptions;\n #activeAbort?: AbortController;\n #history = new AgentModelHistory();\n #killed = false;\n #loadPromise?: Promise<void>;\n #loaded = false;\n #running = false;\n #storeVersion: string | undefined;\n\n constructor(\n llm: Llm,\n persistence: SessionPersistenceOptions,\n hooks?: AgentHooks\n ) {\n this.#hooks = hooks;\n this.#llm = llm;\n this.#persistence = persistence;\n }\n\n async send(input: AgentInput): Promise<AgentRun> {\n if (this.#killed) {\n throw sessionKilledError();\n }\n\n await this.#ensureLoaded();\n\n if (this.#killed) {\n throw sessionKilledError();\n }\n\n const acceptedInput = normalizeAgentInput(input);\n const run = new BufferedAgentRun();\n run.emit(acceptedInput);\n this.#inputQueue.push({ input: structuredClone(acceptedInput), run });\n this.#drainInputQueue().catch((error: unknown) => {\n run.emit({ type: \"turn-error\", message: errorMessage(error) });\n run.close();\n });\n return run;\n }\n\n interrupt(): void {\n this.#activeAbort?.abort();\n }\n\n kill(): void {\n if (this.#killed) {\n return;\n }\n\n this.#killed = true;\n this.#activeAbort?.abort();\n\n while (this.#inputQueue.length > 0) {\n const item = this.#inputQueue.shift();\n item?.run.emit({\n type: \"turn-error\",\n message: sessionKilledError().message,\n });\n item?.run.close();\n }\n }\n\n async #ensureLoaded(): Promise<void> {\n if (this.#loaded) {\n return;\n }\n\n this.#loadPromise ??= this.#loadSessionState();\n try {\n await this.#loadPromise;\n } catch (error) {\n this.#loadPromise = undefined;\n throw error;\n }\n }\n\n async #loadSessionState(): Promise<void> {\n if (this.#loaded) {\n return;\n }\n\n await this.#replaceWithStoredSession();\n this.#loaded = true;\n }\n\n async #replaceWithStoredSession(): Promise<void> {\n const stored = await this.#persistence.store.load(this.#persistence.key);\n this.#storeVersion = stored?.version;\n this.#history = new AgentModelHistory(decodeStoredSessionSnapshot(stored));\n }\n\n async #drainInputQueue(): Promise<void> {\n if (this.#running) {\n return;\n }\n\n this.#running = true;\n try {\n while (!this.#killed && this.#inputQueue.length > 0) {\n const item = this.#inputQueue.shift();\n if (item) {\n await this.#processQueuedInput(item);\n }\n }\n } finally {\n this.#running = false;\n }\n }\n\n async #processQueuedInput({ input, run }: QueuedInput): Promise<void> {\n this.#activeAbort = new AbortController();\n const historySnapshot = this.#history.modelSnapshot();\n\n try {\n await this.#hooks?.beforeTurn?.({\n history: this.#history.modelSnapshot(),\n input,\n signal: this.#activeAbort.signal,\n });\n run.emit({ type: \"turn-start\" });\n this.#history.appendUserInput(input);\n await this.#commitHistory();\n\n const result = await runAgentLoop({\n emit: (event) => run.emit(event),\n history: this.#history,\n hooks: this.#hooks,\n llm: this.#llm,\n signal: this.#activeAbort.signal,\n });\n\n await this.#commitHistory();\n await runAfterTurnHook(this.#hooks, {\n history: this.#history.modelSnapshot(),\n input,\n result,\n signal: this.#activeAbort.signal,\n });\n run.emit({ type: result === \"aborted\" ? \"turn-abort\" : \"turn-end\" });\n } catch (error) {\n if (error instanceof SessionCommitConflictError) {\n run.emit({ type: \"turn-error\", message: error.message });\n return;\n }\n\n this.#history.rollback(historySnapshot);\n try {\n await this.#commitHistory();\n } catch (rollbackError) {\n run.emit({\n type: \"turn-error\",\n message: `${errorMessage(error)}; history rollback persistence failed: ${errorMessage(\n rollbackError\n )}`,\n });\n return;\n }\n run.emit({ type: \"turn-error\", message: errorMessage(error) });\n } finally {\n run.close();\n this.#activeAbort = undefined;\n }\n }\n\n async #commitHistory(): Promise<void> {\n const result = await this.#persistence.store.commit(\n this.#persistence.key,\n {\n state: encodeSessionSnapshot(this.#history.modelSnapshot()),\n version: this.#storeVersion,\n },\n { expectedVersion: this.#storeVersion ?? null }\n );\n\n if (!result.ok) {\n await this.#replaceWithStoredSession();\n throw new SessionCommitConflictError(this.#persistence.key);\n }\n\n this.#storeVersion = result.version;\n }\n}\n\nasync function runAfterTurnHook(\n hooks: AgentHooks | undefined,\n context: Parameters<NonNullable<AgentHooks[\"afterTurn\"]>>[0]\n): Promise<void> {\n const hook = hooks?.afterTurn;\n if (!hook) {\n return;\n }\n\n await Promise.allSettled([Promise.resolve().then(() => hook(context))]);\n}\n\nexport function normalizeAgentInput(input: AgentInput): UserInput {\n if (typeof input === \"string\") {\n return {\n type: \"user-text\",\n text: input,\n };\n }\n\n if (isStringArrayInput(input)) {\n return {\n type: \"user-text\",\n text: structuredClone(input) as readonly string[],\n };\n }\n\n if (isArrayInput(input)) {\n assertUserMessageContent(input);\n return {\n type: \"user-message\",\n content: structuredClone(input) as readonly UserMessageContentPart[],\n };\n }\n\n if (isUserMessage(input)) {\n assertUserMessageContent(input.content);\n }\n\n return structuredClone(input);\n}\n\nfunction isStringArrayInput(input: AgentInput): input is readonly string[] {\n return isArrayInput(input) && input.every((part) => typeof part === \"string\");\n}\n\nfunction isArrayInput(\n input: AgentInput\n): input is readonly string[] | readonly UserMessageContentPart[] {\n return Array.isArray(input);\n}\n\nfunction isUserMessage(input: UserInput): input is UserMessage {\n return input.type === \"user-message\";\n}\n\nfunction assertUserMessageContent(\n input: readonly unknown[]\n): asserts input is readonly UserMessageContentPart[] {\n for (const part of input) {\n if (!isUserMessageContentPart(part)) {\n throw new TypeError(\n 'Agent input content parts must be { type: \"text\", text }, { type: \"image\", image }, or { type: \"file\", data, mediaType }.'\n );\n }\n }\n}\n\nfunction isUserMessageContentPart(\n part: unknown\n): part is UserMessageContentPart {\n if (part === null || typeof part !== \"object\" || !(\"type\" in part)) {\n return false;\n }\n\n if (part.type === \"text\") {\n return \"text\" in part && typeof part.text === \"string\";\n }\n\n if (part.type === \"image\") {\n return (\n \"image\" in part &&\n typeof part.image === \"string\" &&\n (!(\"mediaType\" in part) || typeof part.mediaType === \"string\")\n );\n }\n\n if (part.type === \"file\") {\n return (\n \"data\" in part &&\n isUserMessageFileData(part.data) &&\n \"mediaType\" in part &&\n typeof part.mediaType === \"string\" &&\n (!(\"filename\" in part) || typeof part.filename === \"string\")\n );\n }\n\n return false;\n}\n\nfunction isUserMessageFileData(data: unknown): boolean {\n if (typeof data === \"string\") {\n return true;\n }\n\n if (data === null || typeof data !== \"object\" || !(\"type\" in data)) {\n return false;\n }\n\n if (data.type === \"data\") {\n return \"data\" in data && typeof data.data === \"string\";\n }\n\n if (data.type === \"reference\") {\n return (\n \"reference\" in data &&\n data.reference !== null &&\n typeof data.reference === \"object\" &&\n Object.values(data.reference).every((value) => typeof value === \"string\")\n );\n }\n\n if (data.type === \"text\") {\n return \"text\" in data && typeof data.text === \"string\";\n }\n\n if (data.type === \"url\") {\n return \"url\" in data && typeof data.url === \"string\";\n }\n\n return false;\n}\n\nfunction errorMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n\n return String(error);\n}\n\nfunction sessionKilledError(): Error {\n return new Error(\"Session killed\");\n}\n\nclass SessionCommitConflictError extends Error {\n constructor(key: string) {\n super(`Session ${JSON.stringify(key)} commit conflict`);\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@minpeter/pss-runtime",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "description": "Generic agent runtime for sessions, model loops, and event streams.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",