@minpeter/pss-runtime 0.1.0-next.0 → 0.1.0-next.1

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 (96) hide show
  1. package/README.md +85 -194
  2. package/dist/agent-loop.js +8 -14
  3. package/dist/agent-loop.js.map +1 -1
  4. package/dist/agent-namespace.js +17 -0
  5. package/dist/agent-namespace.js.map +1 -0
  6. package/dist/agent-validation.js +35 -0
  7. package/dist/agent-validation.js.map +1 -0
  8. package/dist/agent.d.ts +21 -10
  9. package/dist/agent.js +81 -37
  10. package/dist/agent.js.map +1 -1
  11. package/dist/child-session-cleanups.js +61 -0
  12. package/dist/child-session-cleanups.js.map +1 -0
  13. package/dist/hooks.d.ts +32 -0
  14. package/dist/index.d.ts +4 -8
  15. package/dist/index.js +1 -6
  16. package/dist/llm.js +1 -7
  17. package/dist/llm.js.map +1 -1
  18. package/dist/session/events.d.ts +23 -20
  19. package/dist/session/input-normalization.js +66 -0
  20. package/dist/session/input-normalization.js.map +1 -0
  21. package/dist/session/input.d.ts +0 -4
  22. package/dist/session/mapping.js +1 -2
  23. package/dist/session/mapping.js.map +1 -1
  24. package/dist/session/run.js +1 -0
  25. package/dist/session/run.js.map +1 -1
  26. package/dist/session/runtime-input.js +38 -58
  27. package/dist/session/runtime-input.js.map +1 -1
  28. package/dist/session/session-errors.js +23 -0
  29. package/dist/session/session-errors.js.map +1 -0
  30. package/dist/session/session-kill.js +23 -0
  31. package/dist/session/session-kill.js.map +1 -0
  32. package/dist/session/session-runtime-drain.js +22 -0
  33. package/dist/session/session-runtime-drain.js.map +1 -0
  34. package/dist/session/session-state.js +102 -0
  35. package/dist/session/session-state.js.map +1 -0
  36. package/dist/session/session-turn-error.js +35 -0
  37. package/dist/session/session-turn-error.js.map +1 -0
  38. package/dist/session/session.js +103 -285
  39. package/dist/session/session.js.map +1 -1
  40. package/dist/session/snapshot.js +5 -31
  41. package/dist/session/snapshot.js.map +1 -1
  42. package/dist/session/store/file.d.ts +1 -0
  43. package/dist/session/store/file.js +14 -0
  44. package/dist/session/store/file.js.map +1 -1
  45. package/dist/session/store/memory.d.ts +1 -0
  46. package/dist/session/store/memory.js +5 -0
  47. package/dist/session/store/memory.js.map +1 -1
  48. package/dist/session/store/types.d.ts +1 -0
  49. package/dist/subagent-job-cancel.js +28 -0
  50. package/dist/subagent-job-cancel.js.map +1 -0
  51. package/dist/subagent-job-output.js +63 -0
  52. package/dist/subagent-job-output.js.map +1 -0
  53. package/dist/subagent-jobs.js +151 -0
  54. package/dist/subagent-jobs.js.map +1 -0
  55. package/dist/subagent-prompt-schema.js +114 -0
  56. package/dist/subagent-prompt-schema.js.map +1 -0
  57. package/dist/subagent-run.js +111 -0
  58. package/dist/subagent-run.js.map +1 -0
  59. package/dist/subagents.js +92 -0
  60. package/dist/subagents.js.map +1 -0
  61. package/package.json +1 -6
  62. package/dist/plugins/compaction.d.ts +0 -15
  63. package/dist/plugins/compaction.js +0 -98
  64. package/dist/plugins/compaction.js.map +0 -1
  65. package/dist/plugins/index.d.ts +0 -5
  66. package/dist/plugins/index.js +0 -5
  67. package/dist/plugins/memory.d.ts +0 -11
  68. package/dist/plugins/memory.js +0 -146
  69. package/dist/plugins/memory.js.map +0 -1
  70. package/dist/plugins/runner.d.ts +0 -1
  71. package/dist/plugins/runner.js +0 -83
  72. package/dist/plugins/runner.js.map +0 -1
  73. package/dist/plugins/scope.js +0 -13
  74. package/dist/plugins/scope.js.map +0 -1
  75. package/dist/plugins/sessions.d.ts +0 -12
  76. package/dist/plugins/sessions.js +0 -34
  77. package/dist/plugins/sessions.js.map +0 -1
  78. package/dist/plugins/tool-hook-handlers.js +0 -77
  79. package/dist/plugins/tool-hook-handlers.js.map +0 -1
  80. package/dist/plugins/tool-hook-results.js +0 -64
  81. package/dist/plugins/tool-hook-results.js.map +0 -1
  82. package/dist/plugins/tool-hooks.js +0 -111
  83. package/dist/plugins/tool-hooks.js.map +0 -1
  84. package/dist/plugins/types.d.ts +0 -105
  85. package/dist/plugins/types.js +0 -20
  86. package/dist/plugins/types.js.map +0 -1
  87. package/dist/session/lifecycle.d.ts +0 -12
  88. package/dist/session/lifecycle.js +0 -126
  89. package/dist/session/lifecycle.js.map +0 -1
  90. package/dist/session/overlay-anchor.js +0 -151
  91. package/dist/session/overlay-anchor.js.map +0 -1
  92. package/dist/session/overlay.js +0 -141
  93. package/dist/session/overlay.js.map +0 -1
  94. package/dist/session/snapshot.d.ts +0 -1
  95. /package/dist/{agent-loop.d.ts → session/history.d.ts} +0 -0
  96. /package/dist/{plugins/scope.d.ts → session/session-state.d.ts} +0 -0
package/dist/agent.js CHANGED
@@ -1,77 +1,121 @@
1
+ import { agentNamespace, parentSessionNamespace, randomAgentNamespace } from "./agent-namespace.js";
2
+ import { assertSubagents } from "./agent-validation.js";
3
+ import { ChildSessionCleanups } from "./child-session-cleanups.js";
1
4
  import { createLlm } from "./llm.js";
2
- import { resolveAgentPlugins } from "./plugins/runner.js";
3
5
  import { AgentSession } from "./session/session.js";
4
6
  import { MemorySessionStore } from "./session/store/memory.js";
7
+ import { createSubagentTools } from "./subagents.js";
5
8
  //#region src/agent.ts
6
9
  var Agent = class Agent {
7
- #internalLlm;
10
+ #baseTools;
11
+ #hooks;
8
12
  #llm;
9
- #onPluginError;
10
- #plugins;
13
+ #modelOptions;
14
+ #childSessionCleanups = new ChildSessionCleanups();
15
+ #sessionGenerations = /* @__PURE__ */ new Map();
11
16
  #sessions = /* @__PURE__ */ new Map();
17
+ #sessionNamespace;
12
18
  #store;
13
- constructor(options, resolvedPlugins) {
19
+ #subagents;
20
+ description;
21
+ name;
22
+ constructor(options) {
14
23
  assertAgentOptions(options);
15
- this.#plugins = resolvedPlugins;
16
- this.#onPluginError = options.onPluginError;
17
- this.#store = resolvedPlugins.sessionStore?.store ?? new MemorySessionStore();
18
- if (hasCustomLlm(options)) {
19
- this.#internalLlm = options.llm;
20
- this.#llm = options.llm;
21
- } else {
22
- this.#internalLlm = createLlm({
23
- instructions: options.instructions,
24
- model: options.model
25
- });
26
- this.#llm = createLlm({
24
+ this.description = options.description;
25
+ this.name = options.name;
26
+ this.#sessionNamespace = stableAgentNamespace(options);
27
+ this.#store = options.sessions?.store ?? new MemorySessionStore();
28
+ this.#hooks = options.hooks;
29
+ assertSubagents(options, Agent, hasCustomLlm(options));
30
+ this.#subagents = hasCustomLlm(options) ? [] : options.subagents ?? [];
31
+ if (hasCustomLlm(options)) this.#llm = options.llm;
32
+ else {
33
+ this.#baseTools = options.tools;
34
+ this.#modelOptions = {
27
35
  instructions: options.instructions,
28
36
  model: options.model,
29
- toolChoice: options.toolChoice,
30
- tools: resolvedPlugins.tools
31
- });
37
+ toolChoice: options.toolChoice
38
+ };
32
39
  }
33
40
  }
34
- static async create(options) {
35
- assertAgentOptions(options);
36
- return new Agent(options, await resolveAgentPlugins({
37
- callerTools: hasCustomLlm(options) ? void 0 : options.tools,
38
- plugins: options.plugins
39
- }));
40
- }
41
41
  send(input) {
42
42
  return this.session("default").send(input);
43
43
  }
44
44
  session(key) {
45
45
  const existing = this.#sessions.get(key);
46
46
  if (existing) return existing;
47
- const session = new AgentSession(this.#llm, {
47
+ let session;
48
+ const getSession = () => {
49
+ if (!session) throw new Error("Agent session is not initialized.");
50
+ return session;
51
+ };
52
+ const parentAgentNamespace = parentSessionNamespace({
53
+ generation: this.#sessionGenerations.get(key) ?? 0,
54
+ sessionKey: key,
55
+ sessionNamespace: this.#sessionNamespace
56
+ });
57
+ session = new AgentSession(this.#llm ?? createLlm(this.#createLlmOptionsForSession(key, parentAgentNamespace, (input, placement) => getSession().enqueueRuntimeInput(input, placement), (event) => getSession().emitObserverEvent(event))), {
48
58
  key,
49
59
  store: this.#store
50
- }, this.#plugins, this.#internalLlm, this.#onPluginError);
60
+ }, this.#hooks);
51
61
  const handle = {
62
+ delete: async () => {
63
+ await session.delete();
64
+ this.#sessions.delete(key);
65
+ this.#sessionGenerations.set(key, (this.#sessionGenerations.get(key) ?? 0) + 1);
66
+ await this.#deleteChildSessions(key);
67
+ },
52
68
  interrupt: () => session.interrupt(),
53
69
  kill: () => {
54
70
  session.kill();
71
+ this.#sessionGenerations.set(key, (this.#sessionGenerations.get(key) ?? 0) + 1);
72
+ this.#deleteChildSessions(key).catch(() => void 0);
55
73
  this.#sessions.delete(key);
56
74
  },
57
- overlay: (input) => session.overlay(input),
58
75
  send: (input) => session.send(input),
59
76
  steer: (input) => session.steer(input)
60
77
  };
61
78
  this.#sessions.set(key, handle);
62
79
  return handle;
63
80
  }
81
+ #createLlmOptionsForSession(key, parentAgentNamespace, enqueueRuntimeInput, emitObserverEvent) {
82
+ const modelOptions = this.#modelOptions;
83
+ if (!modelOptions) throw new Error("Agent: missing model options.");
84
+ const tools = this.#subagents.length === 0 ? this.#baseTools : {
85
+ ...this.#baseTools,
86
+ ...createSubagentTools({
87
+ parentAgentNamespace,
88
+ parentSession: {
89
+ emitObserverEvent,
90
+ enqueueRuntimeInput
91
+ },
92
+ parentSessionKey: key,
93
+ registerChildSession: (sessionKey, cleanup) => this.#childSessionCleanups.register(sessionKey, cleanup),
94
+ subagents: this.#subagents
95
+ })
96
+ };
97
+ return {
98
+ instructions: modelOptions.instructions,
99
+ model: modelOptions.model,
100
+ toolChoice: modelOptions.toolChoice,
101
+ tools
102
+ };
103
+ }
104
+ async #deleteChildSessions(parentSessionKey) {
105
+ await this.#childSessionCleanups.delete(parentSessionKey);
106
+ }
64
107
  };
108
+ function stableAgentNamespace(options) {
109
+ const namespace = options.sessions?.namespace ?? options.name;
110
+ return namespace ? agentNamespace(namespace) : randomAgentNamespace();
111
+ }
65
112
  function assertAgentOptions(options) {
66
113
  if (options === null || typeof options !== "object") throw new TypeError("Agent options are required. Provide either { model } or { llm }.");
67
- if ("sessions" in options) throw new TypeError("Agent.create: options.sessions was removed. Use plugins: [sessions.custom(store)].");
68
- if ("hooks" in options) throw new TypeError("Agent.create: options.hooks was removed. Use run.events() with session.steer() for app control or plugin lifecycle handlers for middleware.");
69
114
  const hasLlm = hasCustomLlm(options);
70
- const hasModel = "model" in options && options.model !== void 0 && options.model !== null;
71
- if (hasLlm && hasModel) throw new TypeError("Agent.create: provide either options.llm or options.model, not both.");
72
- if ("llm" in options && options.llm !== void 0 && !hasLlm) throw new TypeError("Agent.create: invalid options.llm.");
73
- if ("onPluginError" in options && options.onPluginError !== void 0 && typeof options.onPluginError !== "function") throw new TypeError("Agent.create: invalid options.onPluginError.");
74
- if (!(hasLlm || hasModel)) throw new TypeError("Agent.create: missing options.model.");
115
+ const hasModel = "model" in options && options.model != null;
116
+ if (hasLlm && hasModel) throw new TypeError("Agent: provide either options.llm or options.model.");
117
+ if ("llm" in options && options.llm !== void 0 && !hasLlm) throw new TypeError("Agent: invalid options.llm.");
118
+ if (!(hasLlm || hasModel)) throw new TypeError("Agent: missing options.model.");
75
119
  }
76
120
  function hasCustomLlm(options) {
77
121
  return "llm" in options && typeof options.llm === "function";
package/dist/agent.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"agent.js","names":["#internalLlm","#llm","#onPluginError","#plugins","#sessions","#store"],"sources":["../src/agent.ts"],"sourcesContent":["import type { LanguageModel, ToolSet } from \"ai\";\nimport { type AgentToolChoice, createLlm, type Llm } from \"./llm\";\nimport type { AgentPlugin } from \"./plugins\";\nimport {\n type ResolvedAgentPlugins,\n resolveAgentPlugins,\n} from \"./plugins/runner\";\nimport type { AgentPluginErrorHandler } from \"./session/lifecycle\";\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 AgentLanguageModelOptions {\n instructions?: string;\n llm?: never;\n model: LanguageModel;\n onPluginError?: AgentPluginErrorHandler;\n plugins?: readonly AgentPlugin[];\n toolChoice?: AgentToolChoice;\n tools?: ToolSet;\n}\n\ninterface AgentLlmOptions {\n instructions?: never;\n llm: Llm;\n model?: never;\n onPluginError?: AgentPluginErrorHandler;\n plugins?: readonly AgentPlugin[];\n toolChoice?: never;\n tools?: never;\n}\n\nexport interface SessionHandle {\n interrupt(): void;\n kill(): void;\n overlay(input: AgentInput): Promise<AgentRun>;\n send(input: AgentInput): Promise<AgentRun>;\n steer(input: AgentInput): Promise<AgentRun>;\n}\n\nexport type AgentOptions = AgentLanguageModelOptions | AgentLlmOptions;\n\nexport class Agent {\n readonly #internalLlm: Llm;\n readonly #llm: Llm;\n readonly #onPluginError?: AgentPluginErrorHandler;\n readonly #plugins: ResolvedAgentPlugins;\n readonly #sessions = new Map<string, SessionHandle>();\n readonly #store: SessionStore;\n\n private constructor(\n options: AgentOptions,\n resolvedPlugins: ResolvedAgentPlugins\n ) {\n assertAgentOptions(options);\n\n this.#plugins = resolvedPlugins;\n this.#onPluginError = options.onPluginError;\n this.#store =\n resolvedPlugins.sessionStore?.store ?? new MemorySessionStore();\n if (hasCustomLlm(options)) {\n this.#internalLlm = options.llm;\n this.#llm = options.llm;\n } else {\n this.#internalLlm = createLlm({\n instructions: options.instructions,\n model: options.model,\n });\n this.#llm = createLlm({\n instructions: options.instructions,\n model: options.model,\n toolChoice: options.toolChoice,\n tools: resolvedPlugins.tools,\n });\n }\n }\n\n static async create(options: AgentOptions): Promise<Agent> {\n assertAgentOptions(options);\n const resolvedPlugins = await resolveAgentPlugins({\n callerTools: hasCustomLlm(options) ? undefined : options.tools,\n plugins: options.plugins,\n });\n return new Agent(options, resolvedPlugins);\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.#plugins,\n this.#internalLlm,\n this.#onPluginError\n );\n const handle: SessionHandle = {\n interrupt: () => session.interrupt(),\n kill: () => {\n session.kill();\n this.#sessions.delete(key);\n },\n overlay: (input) => session.overlay(input),\n send: (input) => session.send(input),\n steer: (input) => session.steer(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 if (\"sessions\" in options) {\n throw new TypeError(\n \"Agent.create: options.sessions was removed. Use plugins: [sessions.custom(store)].\"\n );\n }\n\n if (\"hooks\" in options) {\n throw new TypeError(\n \"Agent.create: options.hooks was removed. Use run.events() with session.steer() for app control or plugin lifecycle handlers for middleware.\"\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 (\n \"onPluginError\" in options &&\n options.onPluginError !== undefined &&\n typeof options.onPluginError !== \"function\"\n ) {\n throw new TypeError(\"Agent.create: invalid options.onPluginError.\");\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":";;;;;AA2CA,IAAa,QAAb,MAAa,MAAM;CACjB;CACA;CACA;CACA;CACA,4BAAqB,IAAI,IAA2B;CACpD;CAEA,YACE,SACA,iBACA;EACA,mBAAmB,OAAO;EAE1B,KAAKG,WAAW;EAChB,KAAKD,iBAAiB,QAAQ;EAC9B,KAAKG,SACH,gBAAgB,cAAc,SAAS,IAAI,mBAAmB;EAChE,IAAI,aAAa,OAAO,GAAG;GACzB,KAAKL,eAAe,QAAQ;GAC5B,KAAKC,OAAO,QAAQ;EACtB,OAAO;GACL,KAAKD,eAAe,UAAU;IAC5B,cAAc,QAAQ;IACtB,OAAO,QAAQ;GACjB,CAAC;GACD,KAAKC,OAAO,UAAU;IACpB,cAAc,QAAQ;IACtB,OAAO,QAAQ;IACf,YAAY,QAAQ;IACpB,OAAO,gBAAgB;GACzB,CAAC;EACH;CACF;CAEA,aAAa,OAAO,SAAuC;EACzD,mBAAmB,OAAO;EAK1B,OAAO,IAAI,MAAM,SAAS,MAJI,oBAAoB;GAChD,aAAa,aAAa,OAAO,IAAI,KAAA,IAAY,QAAQ;GACzD,SAAS,QAAQ;EACnB,CAAC,CACwC;CAC3C;CAEA,KAAK,OAAsC;EACzC,OAAO,KAAK,QAAQ,SAAS,EAAE,KAAK,KAAK;CAC3C;CAEA,QAAQ,KAA4B;EAClC,MAAM,WAAW,KAAKG,UAAU,IAAI,GAAG;EACvC,IAAI,UACF,OAAO;EAGT,MAAM,UAAU,IAAI,aAClB,KAAKH,MACL;GAAE;GAAK,OAAO,KAAKI;EAAO,GAC1B,KAAKF,UACL,KAAKH,cACL,KAAKE,cACP;EACA,MAAM,SAAwB;GAC5B,iBAAiB,QAAQ,UAAU;GACnC,YAAY;IACV,QAAQ,KAAK;IACb,KAAKE,UAAU,OAAO,GAAG;GAC3B;GACA,UAAU,UAAU,QAAQ,QAAQ,KAAK;GACzC,OAAO,UAAU,QAAQ,KAAK,KAAK;GACnC,QAAQ,UAAU,QAAQ,MAAM,KAAK;EACvC;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,IAAI,cAAc,SAChB,MAAM,IAAI,UACR,oFACF;CAGF,IAAI,WAAW,SACb,MAAM,IAAI,UACR,6IACF;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,IACE,mBAAmB,WACnB,QAAQ,kBAAkB,KAAA,KAC1B,OAAO,QAAQ,kBAAkB,YAEjC,MAAM,IAAI,UAAU,8CAA8C;CAGpE,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":["#baseTools","#hooks","#llm","#modelOptions","#childSessionCleanups","#sessionGenerations","#sessions","#sessionNamespace","#store","#subagents","#createLlmOptionsForSession","#deleteChildSessions"],"sources":["../src/agent.ts"],"sourcesContent":["import type { LanguageModel, ToolSet } from \"ai\";\nimport {\n agentNamespace,\n parentSessionNamespace,\n randomAgentNamespace,\n} from \"./agent-namespace\";\nimport { assertSubagents } from \"./agent-validation\";\nimport { ChildSessionCleanups } from \"./child-session-cleanups\";\nimport type { AgentHooks } from \"./hooks\";\nimport { type AgentToolChoice, createLlm, type Llm } from \"./llm\";\nimport type { UserInput } from \"./session/events\";\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\";\nimport { createSubagentTools } from \"./subagents\";\n\ninterface AgentLanguageModelOptions {\n description?: string;\n hooks?: AgentHooks;\n instructions?: string;\n llm?: never;\n model: LanguageModel;\n name?: string;\n sessions?: AgentSessionOptions;\n subagents?: readonly Agent[];\n toolChoice?: AgentToolChoice;\n tools?: ToolSet;\n}\n\ninterface AgentLlmOptions {\n description?: string;\n hooks?: AgentHooks;\n instructions?: never;\n llm: Llm;\n model?: never;\n name?: string;\n sessions?: AgentSessionOptions;\n subagents?: never;\n toolChoice?: never;\n tools?: never;\n}\n\nexport interface AgentSessionOptions {\n namespace?: string;\n store?: SessionStore;\n}\n\nexport interface SessionHandle {\n delete(): Promise<void>;\n interrupt(): void;\n kill(): void;\n send(input: AgentInput): Promise<AgentRun>;\n steer(input: AgentInput): Promise<AgentRun>;\n}\n\nexport type AgentOptions = AgentLanguageModelOptions | AgentLlmOptions;\ntype AgentModelOptions = Pick<\n AgentLanguageModelOptions,\n \"instructions\" | \"model\" | \"toolChoice\"\n>;\n\nexport class Agent {\n readonly #baseTools?: ToolSet;\n readonly #hooks?: AgentHooks;\n readonly #llm?: Llm;\n readonly #modelOptions?: AgentModelOptions;\n readonly #childSessionCleanups = new ChildSessionCleanups();\n readonly #sessionGenerations = new Map<string, number>();\n readonly #sessions = new Map<string, SessionHandle>();\n readonly #sessionNamespace: string;\n readonly #store: SessionStore;\n readonly #subagents: readonly Agent[];\n readonly description?: string;\n readonly name?: string;\n\n constructor(options: AgentOptions) {\n assertAgentOptions(options);\n\n this.description = options.description;\n this.name = options.name;\n this.#sessionNamespace = stableAgentNamespace(options);\n this.#store = options.sessions?.store ?? new MemorySessionStore();\n this.#hooks = options.hooks;\n assertSubagents(options, Agent, hasCustomLlm(options));\n this.#subagents = hasCustomLlm(options) ? [] : (options.subagents ?? []);\n if (hasCustomLlm(options)) {\n this.#llm = options.llm;\n } else {\n this.#baseTools = options.tools;\n this.#modelOptions = {\n instructions: options.instructions,\n model: options.model,\n toolChoice: options.toolChoice,\n };\n }\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 let session: AgentSession | undefined;\n const getSession = () => {\n if (!session) {\n throw new Error(\"Agent session is not initialized.\");\n }\n return session;\n };\n const parentAgentNamespace = parentSessionNamespace({\n generation: this.#sessionGenerations.get(key) ?? 0,\n sessionKey: key,\n sessionNamespace: this.#sessionNamespace,\n });\n const llm =\n this.#llm ??\n createLlm(\n this.#createLlmOptionsForSession(\n key,\n parentAgentNamespace,\n (input: UserInput, placement?: \"turn-start\") =>\n getSession().enqueueRuntimeInput(input, placement),\n (event) => getSession().emitObserverEvent(event)\n )\n );\n session = new AgentSession(llm, { key, store: this.#store }, this.#hooks);\n const handle: SessionHandle = {\n delete: async () => {\n await session.delete();\n this.#sessions.delete(key);\n this.#sessionGenerations.set(\n key,\n (this.#sessionGenerations.get(key) ?? 0) + 1\n );\n await this.#deleteChildSessions(key);\n },\n interrupt: () => session.interrupt(),\n kill: () => {\n session.kill();\n this.#sessionGenerations.set(\n key,\n (this.#sessionGenerations.get(key) ?? 0) + 1\n );\n this.#deleteChildSessions(key).catch(() => undefined);\n this.#sessions.delete(key);\n },\n send: (input) => session.send(input),\n steer: (input) => session.steer(input),\n };\n this.#sessions.set(key, handle);\n return handle;\n }\n\n #createLlmOptionsForSession(\n key: string,\n parentAgentNamespace: string,\n enqueueRuntimeInput: AgentSession[\"enqueueRuntimeInput\"],\n emitObserverEvent: AgentSession[\"emitObserverEvent\"]\n ): Parameters<typeof createLlm>[0] {\n const modelOptions = this.#modelOptions;\n if (!modelOptions) {\n throw new Error(\"Agent: missing model options.\");\n }\n const tools =\n this.#subagents.length === 0\n ? this.#baseTools\n : {\n ...this.#baseTools,\n ...createSubagentTools({\n parentAgentNamespace,\n parentSession: { emitObserverEvent, enqueueRuntimeInput },\n parentSessionKey: key,\n registerChildSession: (sessionKey, cleanup) =>\n this.#childSessionCleanups.register(sessionKey, cleanup),\n subagents: this.#subagents,\n }),\n };\n\n return {\n instructions: modelOptions.instructions,\n model: modelOptions.model,\n toolChoice: modelOptions.toolChoice,\n tools,\n };\n }\n\n async #deleteChildSessions(parentSessionKey: string): Promise<void> {\n await this.#childSessionCleanups.delete(parentSessionKey);\n }\n}\n\nfunction stableAgentNamespace(options: AgentOptions): string {\n const namespace = options.sessions?.namespace ?? options.name;\n return namespace ? agentNamespace(namespace) : randomAgentNamespace();\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 = \"model\" in options && options.model != null;\n\n if (hasLlm && hasModel) {\n throw new TypeError(\"Agent: provide either options.llm or options.model.\");\n }\n\n if (\"llm\" in options && options.llm !== undefined && !hasLlm) {\n throw new TypeError(\"Agent: invalid options.llm.\");\n }\n\n if (!(hasLlm || hasModel)) {\n throw new TypeError(\"Agent: 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":";;;;;;;;AA8DA,IAAa,QAAb,MAAa,MAAM;CACjB;CACA;CACA;CACA;CACA,wBAAiC,IAAI,qBAAqB;CAC1D,sCAA+B,IAAI,IAAoB;CACvD,4BAAqB,IAAI,IAA2B;CACpD;CACA;CACA;CACA;CACA;CAEA,YAAY,SAAuB;EACjC,mBAAmB,OAAO;EAE1B,KAAK,cAAc,QAAQ;EAC3B,KAAK,OAAO,QAAQ;EACpB,KAAKO,oBAAoB,qBAAqB,OAAO;EACrD,KAAKC,SAAS,QAAQ,UAAU,SAAS,IAAI,mBAAmB;EAChE,KAAKP,SAAS,QAAQ;EACtB,gBAAgB,SAAS,OAAO,aAAa,OAAO,CAAC;EACrD,KAAKQ,aAAa,aAAa,OAAO,IAAI,CAAC,IAAK,QAAQ,aAAa,CAAC;EACtE,IAAI,aAAa,OAAO,GACtB,KAAKP,OAAO,QAAQ;OACf;GACL,KAAKF,aAAa,QAAQ;GAC1B,KAAKG,gBAAgB;IACnB,cAAc,QAAQ;IACtB,OAAO,QAAQ;IACf,YAAY,QAAQ;GACtB;EACF;CACF;CAEA,KAAK,OAAsC;EACzC,OAAO,KAAK,QAAQ,SAAS,EAAE,KAAK,KAAK;CAC3C;CAEA,QAAQ,KAA4B;EAClC,MAAM,WAAW,KAAKG,UAAU,IAAI,GAAG;EACvC,IAAI,UACF,OAAO;EAGT,IAAI;EACJ,MAAM,mBAAmB;GACvB,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,mCAAmC;GAErD,OAAO;EACT;EACA,MAAM,uBAAuB,uBAAuB;GAClD,YAAY,KAAKD,oBAAoB,IAAI,GAAG,KAAK;GACjD,YAAY;GACZ,kBAAkB,KAAKE;EACzB,CAAC;EAYD,UAAU,IAAI,aAVZ,KAAKL,QACL,UACE,KAAKQ,4BACH,KACA,uBACC,OAAkB,cACjB,WAAW,EAAE,oBAAoB,OAAO,SAAS,IAClD,UAAU,WAAW,EAAE,kBAAkB,KAAK,CACjD,CACF,GAC8B;GAAE;GAAK,OAAO,KAAKF;EAAO,GAAG,KAAKP,MAAM;EACxE,MAAM,SAAwB;GAC5B,QAAQ,YAAY;IAClB,MAAM,QAAQ,OAAO;IACrB,KAAKK,UAAU,OAAO,GAAG;IACzB,KAAKD,oBAAoB,IACvB,MACC,KAAKA,oBAAoB,IAAI,GAAG,KAAK,KAAK,CAC7C;IACA,MAAM,KAAKM,qBAAqB,GAAG;GACrC;GACA,iBAAiB,QAAQ,UAAU;GACnC,YAAY;IACV,QAAQ,KAAK;IACb,KAAKN,oBAAoB,IACvB,MACC,KAAKA,oBAAoB,IAAI,GAAG,KAAK,KAAK,CAC7C;IACA,KAAKM,qBAAqB,GAAG,EAAE,YAAY,KAAA,CAAS;IACpD,KAAKL,UAAU,OAAO,GAAG;GAC3B;GACA,OAAO,UAAU,QAAQ,KAAK,KAAK;GACnC,QAAQ,UAAU,QAAQ,MAAM,KAAK;EACvC;EACA,KAAKA,UAAU,IAAI,KAAK,MAAM;EAC9B,OAAO;CACT;CAEA,4BACE,KACA,sBACA,qBACA,mBACiC;EACjC,MAAM,eAAe,KAAKH;EAC1B,IAAI,CAAC,cACH,MAAM,IAAI,MAAM,+BAA+B;EAEjD,MAAM,QACJ,KAAKM,WAAW,WAAW,IACvB,KAAKT,aACL;GACE,GAAG,KAAKA;GACR,GAAG,oBAAoB;IACrB;IACA,eAAe;KAAE;KAAmB;IAAoB;IACxD,kBAAkB;IAClB,uBAAuB,YAAY,YACjC,KAAKI,sBAAsB,SAAS,YAAY,OAAO;IACzD,WAAW,KAAKK;GAClB,CAAC;EACH;EAEN,OAAO;GACL,cAAc,aAAa;GAC3B,OAAO,aAAa;GACpB,YAAY,aAAa;GACzB;EACF;CACF;CAEA,MAAME,qBAAqB,kBAAyC;EAClE,MAAM,KAAKP,sBAAsB,OAAO,gBAAgB;CAC1D;AACF;AAEA,SAAS,qBAAqB,SAA+B;CAC3D,MAAM,YAAY,QAAQ,UAAU,aAAa,QAAQ;CACzD,OAAO,YAAY,eAAe,SAAS,IAAI,qBAAqB;AACtE;AAEA,SAAS,mBAAmB,SAAmD;CAC7E,IAAI,YAAY,QAAQ,OAAO,YAAY,UACzC,MAAM,IAAI,UACR,kEACF;CAGF,MAAM,SAAS,aAAa,OAAO;CACnC,MAAM,WAAW,WAAW,WAAW,QAAQ,SAAS;CAExD,IAAI,UAAU,UACZ,MAAM,IAAI,UAAU,qDAAqD;CAG3E,IAAI,SAAS,WAAW,QAAQ,QAAQ,KAAA,KAAa,CAAC,QACpD,MAAM,IAAI,UAAU,6BAA6B;CAGnD,IAAI,EAAE,UAAU,WACd,MAAM,IAAI,UAAU,+BAA+B;AAEvD;AAEA,SAAS,aAAa,SAA6C;CACjE,OAAO,SAAS,WAAW,OAAO,QAAQ,QAAQ;AACpD"}
@@ -0,0 +1,61 @@
1
+ //#region src/child-session-cleanups.ts
2
+ var ChildSessionCleanups = class {
3
+ #byParentSession = /* @__PURE__ */ new Map();
4
+ async delete(parentSessionKey) {
5
+ const cleanups = this.#byParentSession.get(parentSessionKey);
6
+ if (!cleanups) return;
7
+ this.#byParentSession.delete(parentSessionKey);
8
+ const results = await Promise.all([...cleanups].map(runCleanup));
9
+ const failedCleanups = [];
10
+ let firstError;
11
+ for (const result of results) {
12
+ if (result.ok) continue;
13
+ firstError ??= result.error;
14
+ failedCleanups.push(result.cleanup);
15
+ }
16
+ if (failedCleanups.length === 0) return;
17
+ this.#restore(parentSessionKey, failedCleanups);
18
+ throw firstError instanceof Error ? firstError : new Error(String(firstError));
19
+ }
20
+ register(parentSessionKey, cleanup) {
21
+ const existing = this.#byParentSession.get(parentSessionKey);
22
+ if (existing) {
23
+ existing.add(cleanup);
24
+ return () => this.#unregister(parentSessionKey, existing, cleanup);
25
+ }
26
+ const cleanups = new Set([cleanup]);
27
+ this.#byParentSession.set(parentSessionKey, cleanups);
28
+ return () => this.#unregister(parentSessionKey, cleanups, cleanup);
29
+ }
30
+ #unregister(parentSessionKey, cleanups, cleanup) {
31
+ cleanups.delete(cleanup);
32
+ if (cleanups.size === 0 && this.#byParentSession.get(parentSessionKey) === cleanups) this.#byParentSession.delete(parentSessionKey);
33
+ }
34
+ #restore(parentSessionKey, failedCleanups) {
35
+ const current = this.#byParentSession.get(parentSessionKey);
36
+ if (current) {
37
+ for (const cleanup of failedCleanups) current.add(cleanup);
38
+ return;
39
+ }
40
+ this.#byParentSession.set(parentSessionKey, new Set(failedCleanups));
41
+ }
42
+ };
43
+ async function runCleanup(cleanup) {
44
+ try {
45
+ await cleanup();
46
+ return {
47
+ cleanup,
48
+ ok: true
49
+ };
50
+ } catch (error) {
51
+ return {
52
+ cleanup,
53
+ error,
54
+ ok: false
55
+ };
56
+ }
57
+ }
58
+ //#endregion
59
+ export { ChildSessionCleanups };
60
+
61
+ //# sourceMappingURL=child-session-cleanups.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"child-session-cleanups.js","names":["#byParentSession","#restore","#unregister"],"sources":["../src/child-session-cleanups.ts"],"sourcesContent":["type ChildSessionCleanup = () => Promise<void>;\n\ntype CleanupResult =\n | { readonly cleanup: ChildSessionCleanup; readonly ok: true }\n | {\n readonly cleanup: ChildSessionCleanup;\n readonly error: unknown;\n readonly ok: false;\n };\n\nexport class ChildSessionCleanups {\n readonly #byParentSession = new Map<string, Set<ChildSessionCleanup>>();\n\n async delete(parentSessionKey: string): Promise<void> {\n const cleanups = this.#byParentSession.get(parentSessionKey);\n if (!cleanups) {\n return;\n }\n\n this.#byParentSession.delete(parentSessionKey);\n const results = await Promise.all([...cleanups].map(runCleanup));\n const failedCleanups: ChildSessionCleanup[] = [];\n let firstError: unknown;\n for (const result of results) {\n if (result.ok) {\n continue;\n }\n\n firstError ??= result.error;\n failedCleanups.push(result.cleanup);\n }\n\n if (failedCleanups.length === 0) {\n return;\n }\n\n this.#restore(parentSessionKey, failedCleanups);\n throw firstError instanceof Error\n ? firstError\n : new Error(String(firstError));\n }\n\n register(parentSessionKey: string, cleanup: ChildSessionCleanup): () => void {\n const existing = this.#byParentSession.get(parentSessionKey);\n if (existing) {\n existing.add(cleanup);\n return () => this.#unregister(parentSessionKey, existing, cleanup);\n }\n\n const cleanups = new Set([cleanup]);\n this.#byParentSession.set(parentSessionKey, cleanups);\n return () => this.#unregister(parentSessionKey, cleanups, cleanup);\n }\n\n #unregister(\n parentSessionKey: string,\n cleanups: Set<ChildSessionCleanup>,\n cleanup: ChildSessionCleanup\n ): void {\n cleanups.delete(cleanup);\n if (\n cleanups.size === 0 &&\n this.#byParentSession.get(parentSessionKey) === cleanups\n ) {\n this.#byParentSession.delete(parentSessionKey);\n }\n }\n\n #restore(\n parentSessionKey: string,\n failedCleanups: readonly ChildSessionCleanup[]\n ): void {\n const current = this.#byParentSession.get(parentSessionKey);\n if (current) {\n for (const cleanup of failedCleanups) {\n current.add(cleanup);\n }\n return;\n }\n\n this.#byParentSession.set(parentSessionKey, new Set(failedCleanups));\n }\n}\n\nasync function runCleanup(\n cleanup: ChildSessionCleanup\n): Promise<CleanupResult> {\n try {\n await cleanup();\n return { cleanup, ok: true };\n } catch (error) {\n return { cleanup, error, ok: false };\n }\n}\n"],"mappings":";AAUA,IAAa,uBAAb,MAAkC;CAChC,mCAA4B,IAAI,IAAsC;CAEtE,MAAM,OAAO,kBAAyC;EACpD,MAAM,WAAW,KAAKA,iBAAiB,IAAI,gBAAgB;EAC3D,IAAI,CAAC,UACH;EAGF,KAAKA,iBAAiB,OAAO,gBAAgB;EAC7C,MAAM,UAAU,MAAM,QAAQ,IAAI,CAAC,GAAG,QAAQ,EAAE,IAAI,UAAU,CAAC;EAC/D,MAAM,iBAAwC,CAAC;EAC/C,IAAI;EACJ,KAAK,MAAM,UAAU,SAAS;GAC5B,IAAI,OAAO,IACT;GAGF,eAAe,OAAO;GACtB,eAAe,KAAK,OAAO,OAAO;EACpC;EAEA,IAAI,eAAe,WAAW,GAC5B;EAGF,KAAKC,SAAS,kBAAkB,cAAc;EAC9C,MAAM,sBAAsB,QACxB,aACA,IAAI,MAAM,OAAO,UAAU,CAAC;CAClC;CAEA,SAAS,kBAA0B,SAA0C;EAC3E,MAAM,WAAW,KAAKD,iBAAiB,IAAI,gBAAgB;EAC3D,IAAI,UAAU;GACZ,SAAS,IAAI,OAAO;GACpB,aAAa,KAAKE,YAAY,kBAAkB,UAAU,OAAO;EACnE;EAEA,MAAM,WAAW,IAAI,IAAI,CAAC,OAAO,CAAC;EAClC,KAAKF,iBAAiB,IAAI,kBAAkB,QAAQ;EACpD,aAAa,KAAKE,YAAY,kBAAkB,UAAU,OAAO;CACnE;CAEA,YACE,kBACA,UACA,SACM;EACN,SAAS,OAAO,OAAO;EACvB,IACE,SAAS,SAAS,KAClB,KAAKF,iBAAiB,IAAI,gBAAgB,MAAM,UAEhD,KAAKA,iBAAiB,OAAO,gBAAgB;CAEjD;CAEA,SACE,kBACA,gBACM;EACN,MAAM,UAAU,KAAKA,iBAAiB,IAAI,gBAAgB;EAC1D,IAAI,SAAS;GACX,KAAK,MAAM,WAAW,gBACpB,QAAQ,IAAI,OAAO;GAErB;EACF;EAEA,KAAKA,iBAAiB,IAAI,kBAAkB,IAAI,IAAI,cAAc,CAAC;CACrE;AACF;AAEA,eAAe,WACb,SACwB;CACxB,IAAI;EACF,MAAM,QAAQ;EACd,OAAO;GAAE;GAAS,IAAI;EAAK;CAC7B,SAAS,OAAO;EACd,OAAO;GAAE;GAAS;GAAO,IAAI;EAAM;CACrC;AACF"}
@@ -0,0 +1,32 @@
1
+ import { RuntimeLlmContext } from "./llm.js";
2
+ import { UserInput } from "./session/input.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,12 +1,8 @@
1
1
  import { AgentToolChoice, AgentToolExecute, AgentToolExecutionOptions, LlmOutputPart, RuntimeCreateLlmOptions, RuntimeLlm, RuntimeLlmContext, RuntimeLlmOutput, createLlm } from "./llm.js";
2
2
  import { AgentInput, SessionInput, UserInput, UserMessage, UserMessageContent, UserMessageContentPart, UserMessageFileData, UserMessageFilePart, UserMessageImagePart, UserMessageTextPart, UserText, UserTextContent } from "./session/input.js";
3
- import { AgentEvent, AgentEventListener, AssistantReasoning, AssistantText, OverlayAccepted, OverlayExpired, OverlayInputSummary, OverlayPlacement, RuntimeInput, ToolCall, ToolResult } from "./session/events.js";
3
+ import { AgentAfterStepContext, AgentAfterTurnContext, AgentBeforeStepContext, AgentBeforeTurnContext, AgentHooks, AgentStepResult, AgentTurnResult } from "./hooks.js";
4
+ import { AgentEvent, AgentEventListener, AssistantReasoning, AssistantText, RuntimeInput, ToolCall, ToolResult } from "./session/events.js";
4
5
  import { AgentRun } from "./session/run.js";
5
6
  import { CommitResult, ExpectedSessionVersion, SessionStore, SessionStoreCommit, StoredSession } from "./session/store/types.js";
6
- import { AgentContextTransform, AgentPlugin, AgentPluginEvent, AgentPluginEventFor, AgentPluginEventName, AgentPluginHandler, AgentPluginHandlerResult, AgentPluginHandlerReturn, AgentPluginHost, AgentPluginMaybePromise, AgentPluginStepAfterEvent, AgentPluginStepBeforeEvent, AgentPluginStepResult, AgentPluginToolCallEvent, AgentPluginToolCallResult, AgentPluginToolResultEvent, AgentPluginToolResultResult, AgentPluginToolResultStatus, AgentPluginToolSyntheticResult, AgentPluginTurnAfterEvent, AgentPluginTurnBeforeEvent, AgentPluginTurnResult, definePlugin } from "./plugins/types.js";
7
- import { CompactionOptions, compaction } from "./plugins/compaction.js";
8
- import { memory } from "./plugins/memory.js";
9
- import { sessions } from "./plugins/sessions.js";
10
- import { AgentPluginErrorHandler, AgentPluginHandlerError } from "./session/lifecycle.js";
11
- import { Agent, AgentOptions, SessionHandle } from "./agent.js";
12
- export { Agent, type AgentContextTransform, type AgentEvent, type AgentEventListener, type AgentInput, type AgentOptions, type AgentPlugin, type AgentPluginErrorHandler, type AgentPluginEvent, type AgentPluginEventFor, type AgentPluginEventName, type AgentPluginHandler, type AgentPluginHandlerError, type AgentPluginHandlerResult, type AgentPluginHandlerReturn, type AgentPluginHost, type AgentPluginMaybePromise, type AgentPluginStepAfterEvent, type AgentPluginStepBeforeEvent, type AgentPluginStepResult, type AgentPluginToolCallEvent, type AgentPluginToolCallResult, type AgentPluginToolResultEvent, type AgentPluginToolResultResult, type AgentPluginToolResultStatus, type AgentPluginToolSyntheticResult, type AgentPluginTurnAfterEvent, type AgentPluginTurnBeforeEvent, type AgentPluginTurnResult, type AgentRun, type AgentToolChoice, type AgentToolExecute, type AgentToolExecutionOptions, type AssistantReasoning, type AssistantText, type CommitResult, type CompactionOptions, type ExpectedSessionVersion, type LlmOutputPart, type OverlayAccepted, type OverlayExpired, type OverlayInputSummary, type OverlayPlacement, type RuntimeCreateLlmOptions, type RuntimeInput, type RuntimeLlm, type RuntimeLlmContext, type RuntimeLlmOutput, type SessionHandle, type SessionInput, type SessionStore, type SessionStoreCommit, 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, compaction, createLlm, definePlugin, memory, sessions };
7
+ import { Agent, AgentOptions, AgentSessionOptions, SessionHandle } from "./agent.js";
8
+ export { Agent, type AgentAfterStepContext, type AgentAfterTurnContext, type AgentBeforeStepContext, type AgentBeforeTurnContext, type AgentEvent, type AgentEventListener, type AgentHooks, type AgentInput, type AgentOptions, type AgentRun, type AgentSessionOptions, type AgentStepResult, type AgentToolChoice, type AgentToolExecute, type AgentToolExecutionOptions, type AgentTurnResult, type AssistantReasoning, type AssistantText, type CommitResult, type ExpectedSessionVersion, type LlmOutputPart, type RuntimeCreateLlmOptions, type RuntimeInput, type RuntimeLlm, type RuntimeLlmContext, type RuntimeLlmOutput, type SessionHandle, type SessionInput, type SessionStore, type SessionStoreCommit, 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 };
package/dist/index.js CHANGED
@@ -1,8 +1,3 @@
1
1
  import { createLlm } from "./llm.js";
2
- import { definePlugin } from "./plugins/types.js";
3
2
  import { Agent } from "./agent.js";
4
- import { compaction } from "./plugins/compaction.js";
5
- import { memory } from "./plugins/memory.js";
6
- import { sessions } from "./plugins/sessions.js";
7
- import "./plugins/index.js";
8
- export { Agent, compaction, createLlm, definePlugin, memory, sessions };
3
+ export { Agent, createLlm };
package/dist/llm.js CHANGED
@@ -1,20 +1,14 @@
1
- import { wrapToolsWithPluginHooks } from "./plugins/tool-hooks.js";
2
1
  import { generateText } from "ai";
3
2
  //#region src/llm.ts
4
3
  function createLlm({ model, instructions, toolChoice, tools }) {
5
4
  return async ({ history, signal }) => {
6
- const scopedTools = wrapToolsWithPluginHooks({
7
- history,
8
- signal,
9
- tools
10
- });
11
5
  const { responseMessages } = await generateText({
12
6
  abortSignal: signal,
13
7
  instructions,
14
8
  messages: [...history],
15
9
  model,
16
10
  toolChoice,
17
- tools: scopedTools
11
+ tools
18
12
  });
19
13
  return responseMessages;
20
14
  };
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\";\nimport { wrapToolsWithPluginHooks } from \"./plugins/tool-hooks\";\n\nexport type AgentToolExecutionOptions = ToolExecutionOptions<unknown>;\nexport type AgentToolExecute = NonNullable<Tool[\"execute\"]>;\nexport type AgentToolChoice = \"auto\" | \"required\";\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?: ToolSet;\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 scopedTools = wrapToolsWithPluginHooks({\n history,\n signal,\n tools,\n });\n const { responseMessages } = await generateText({\n abortSignal: signal,\n instructions,\n messages: [...history],\n model,\n toolChoice,\n tools: scopedTools,\n });\n\n return responseMessages;\n };\n}\n"],"mappings":";;;AAqCA,SAAgB,UAAU,EACxB,OACA,cACA,YACA,SACwB;CACxB,OAAO,OAAO,EAAE,SAAS,aAAa;EACpC,MAAM,cAAc,yBAAyB;GAC3C;GACA;GACA;EACF,CAAC;EACD,MAAM,EAAE,qBAAqB,MAAM,aAAa;GAC9C,aAAa;GACb;GACA,UAAU,CAAC,GAAG,OAAO;GACrB;GACA;GACA,OAAO;EACT,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 AgentToolChoice = \"auto\" | \"required\";\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?: ToolSet;\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":";;AAoCA,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"}
@@ -10,23 +10,6 @@ interface RuntimeInput {
10
10
  placement: "turn-start" | "step-start" | "step-end";
11
11
  type: "runtime-input";
12
12
  }
13
- type OverlayPlacement = "idle" | "step-end" | "step-start" | "turn-start";
14
- interface OverlayInputSummary {
15
- partCount?: number;
16
- preview: string;
17
- textLength?: number;
18
- type: UserInput["type"];
19
- }
20
- interface OverlayAccepted {
21
- input: OverlayInputSummary;
22
- placement: OverlayPlacement;
23
- type: "overlay-accepted";
24
- }
25
- interface OverlayExpired {
26
- count: number;
27
- reason: "kill" | "turn-abort" | "turn-end" | "turn-error";
28
- type: "overlay-expired";
29
- }
30
13
  interface AssistantText {
31
14
  text: string;
32
15
  type: "assistant-text";
@@ -47,7 +30,8 @@ interface ToolResult {
47
30
  toolName: string;
48
31
  type: "tool-result";
49
32
  }
50
- type AgentEvent = /** User input was accepted into the session queue. */UserText /** User multipart input was accepted into the session queue. */ | UserMessage /** Runtime/API-originated input inserted into the current turn, not human input. */ | RuntimeInput | OverlayAccepted | OverlayExpired /** A queued user input started running as a turn. */ | {
33
+ type SubagentJobStatus = "aborted" | "cancelled" | "completed" | "error" | "pending" | "running";
34
+ type AgentEvent = /** User input was accepted into the session queue. */UserText /** User multipart input was accepted into the session queue. */ | UserMessage /** Runtime/API-originated input inserted into the current turn, not human input. */ | RuntimeInput /** A queued user input started running as a turn. */ | {
51
35
  type: "turn-start";
52
36
  } /** The active turn was interrupted before normal completion. */ | {
53
37
  type: "turn-abort";
@@ -58,10 +42,29 @@ type AgentEvent = /** User input was accepted into the session queue. */UserText
58
42
  type: "turn-end";
59
43
  } /** One model/tool-loop iteration started within the active turn. */ | {
60
44
  type: "step-start";
61
- } /** The model produced reasoning content. */ | AssistantReasoning /** The model produced visible assistant text. */ | AssistantText /** The model requested a tool call. */ | ToolCall /** A tool call returned a result. */ | ToolResult /** One model/tool-loop iteration finished within the active turn. */ | {
45
+ } /** The model produced reasoning content. */ | AssistantReasoning /** The model produced visible assistant text. */ | AssistantText /** The model requested a tool call. */ | ToolCall /** A tool call returned a result. */ | ToolResult | {
46
+ description?: string;
47
+ run_in_background: boolean;
48
+ subagent: string;
49
+ task_id?: string;
50
+ type: "subagent-job-start";
51
+ } | {
52
+ eventType?: AgentEvent["type"];
53
+ status: SubagentJobStatus;
54
+ subagent: string;
55
+ task_id: string;
56
+ type: "subagent-job-update";
57
+ } | {
58
+ error?: string;
59
+ eventCount: number;
60
+ status: Exclude<SubagentJobStatus, "pending" | "running">;
61
+ subagent: string;
62
+ task_id?: string;
63
+ type: "subagent-job-end";
64
+ } /** One model/tool-loop iteration finished within the active turn. */ | {
62
65
  type: "step-end";
63
66
  };
64
67
  type AgentEventListener = (event: AgentEvent) => void;
65
68
  //#endregion
66
- export { AgentEvent, AgentEventListener, AssistantReasoning, AssistantText, OverlayAccepted, OverlayExpired, OverlayInputSummary, OverlayPlacement, RuntimeInput, ToolCall, ToolResult };
69
+ export { AgentEvent, AgentEventListener, AssistantReasoning, AssistantText, RuntimeInput, ToolCall, ToolResult };
67
70
  //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1,66 @@
1
+ //#region src/session/input-normalization.ts
2
+ function normalizeAgentInput(input) {
3
+ if (typeof input === "string") return {
4
+ type: "user-text",
5
+ text: input
6
+ };
7
+ if (isStringArrayInput(input)) return {
8
+ type: "user-text",
9
+ text: structuredClone(input)
10
+ };
11
+ if (isArrayInput(input)) {
12
+ assertUserMessageContent(input);
13
+ return {
14
+ type: "user-message",
15
+ content: structuredClone(input)
16
+ };
17
+ }
18
+ if (isUserMessage(input)) {
19
+ assertUserMessageContent(input.content);
20
+ return structuredClone(input);
21
+ }
22
+ if (isUserText(input)) return structuredClone(input);
23
+ throw new TypeError("Agent input must be text, text parts, content parts, user-text, or user-message.");
24
+ }
25
+ function isStringArrayInput(input) {
26
+ return Array.isArray(input) && hasDenseItems(input, isString);
27
+ }
28
+ function isArrayInput(input) {
29
+ return Array.isArray(input);
30
+ }
31
+ function isUserMessage(input) {
32
+ return input !== null && typeof input === "object" && !isArrayInput(input) && input.type === "user-message" && "content" in input && Array.isArray(input.content);
33
+ }
34
+ function isUserText(input) {
35
+ return input !== null && typeof input === "object" && !isArrayInput(input) && input.type === "user-text" && (typeof input.text === "string" || isStringArrayInput(input.text));
36
+ }
37
+ function assertUserMessageContent(input) {
38
+ for (const part of input) if (!isUserMessageContentPart(part)) throw new TypeError("Agent input content parts must be { type: \"text\", text }, { type: \"image\", image }, or { type: \"file\", data, mediaType }.");
39
+ }
40
+ function isUserMessageContentPart(part) {
41
+ if (part === null || typeof part !== "object" || !("type" in part)) return false;
42
+ if (part.type === "text") return "text" in part && typeof part.text === "string";
43
+ if (part.type === "image") return "image" in part && typeof part.image === "string" && (!("mediaType" in part) || typeof part.mediaType === "string");
44
+ if (part.type === "file") return "data" in part && isUserMessageFileData(part.data) && "mediaType" in part && typeof part.mediaType === "string" && (!("filename" in part) || typeof part.filename === "string");
45
+ return false;
46
+ }
47
+ function isUserMessageFileData(data) {
48
+ if (typeof data === "string") return true;
49
+ if (data === null || typeof data !== "object" || !("type" in data)) return false;
50
+ if (data.type === "data") return "data" in data && typeof data.data === "string";
51
+ if (data.type === "reference") return "reference" in data && data.reference !== null && typeof data.reference === "object" && Object.values(data.reference).every((value) => typeof value === "string");
52
+ if (data.type === "text") return "text" in data && typeof data.text === "string";
53
+ if (data.type === "url") return "url" in data && typeof data.url === "string";
54
+ return false;
55
+ }
56
+ function hasDenseItems(input, predicate) {
57
+ for (let index = 0; index < input.length; index += 1) if (!(index in input && predicate(input[index]))) return false;
58
+ return true;
59
+ }
60
+ function isString(value) {
61
+ return typeof value === "string";
62
+ }
63
+ //#endregion
64
+ export { normalizeAgentInput };
65
+
66
+ //# sourceMappingURL=input-normalization.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-normalization.js","names":[],"sources":["../../src/session/input-normalization.ts"],"sourcesContent":["import type {\n AgentInput,\n UserInput,\n UserMessage,\n UserMessageContentPart,\n UserText,\n} from \"./input\";\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),\n };\n }\n\n if (isArrayInput(input)) {\n assertUserMessageContent(input);\n return {\n type: \"user-message\",\n content: structuredClone(input),\n };\n }\n\n if (isUserMessage(input)) {\n assertUserMessageContent(input.content);\n return structuredClone(input);\n }\n\n if (isUserText(input)) {\n return structuredClone(input);\n }\n\n throw new TypeError(\n \"Agent input must be text, text parts, content parts, user-text, or user-message.\"\n );\n}\n\nfunction isStringArrayInput(input: unknown): input is readonly string[] {\n return Array.isArray(input) && hasDenseItems(input, isString);\n}\n\nfunction isArrayInput(\n input: AgentInput\n): input is readonly string[] | readonly UserMessageContentPart[] {\n return Array.isArray(input);\n}\n\nfunction isUserMessage(input: AgentInput): input is UserMessage {\n return (\n input !== null &&\n typeof input === \"object\" &&\n !isArrayInput(input) &&\n input.type === \"user-message\" &&\n \"content\" in input &&\n Array.isArray(input.content)\n );\n}\n\nfunction isUserText(input: AgentInput): input is UserText {\n return (\n input !== null &&\n typeof input === \"object\" &&\n !isArrayInput(input) &&\n input.type === \"user-text\" &&\n (typeof input.text === \"string\" || isStringArrayInput(input.text))\n );\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 hasDenseItems<T>(\n input: readonly unknown[],\n predicate: (value: unknown) => value is T\n): input is readonly T[] {\n for (let index = 0; index < input.length; index += 1) {\n if (!(index in input && predicate(input[index]))) {\n return false;\n }\n }\n\n return true;\n}\n\nfunction isString(value: unknown): value is string {\n return typeof value === \"string\";\n}\n"],"mappings":";AAQA,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,GAAG;EACxB,yBAAyB,MAAM,OAAO;EACtC,OAAO,gBAAgB,KAAK;CAC9B;CAEA,IAAI,WAAW,KAAK,GAClB,OAAO,gBAAgB,KAAK;CAG9B,MAAM,IAAI,UACR,kFACF;AACF;AAEA,SAAS,mBAAmB,OAA4C;CACtE,OAAO,MAAM,QAAQ,KAAK,KAAK,cAAc,OAAO,QAAQ;AAC9D;AAEA,SAAS,aACP,OACgE;CAChE,OAAO,MAAM,QAAQ,KAAK;AAC5B;AAEA,SAAS,cAAc,OAAyC;CAC9D,OACE,UAAU,QACV,OAAO,UAAU,YACjB,CAAC,aAAa,KAAK,KACnB,MAAM,SAAS,kBACf,aAAa,SACb,MAAM,QAAQ,MAAM,OAAO;AAE/B;AAEA,SAAS,WAAW,OAAsC;CACxD,OACE,UAAU,QACV,OAAO,UAAU,YACjB,CAAC,aAAa,KAAK,KACnB,MAAM,SAAS,gBACd,OAAO,MAAM,SAAS,YAAY,mBAAmB,MAAM,IAAI;AAEpE;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,cACP,OACA,WACuB;CACvB,KAAK,IAAI,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GACjD,IAAI,EAAE,SAAS,SAAS,UAAU,MAAM,MAAM,IAC5C,OAAO;CAIX,OAAO;AACT;AAEA,SAAS,SAAS,OAAiC;CACjD,OAAO,OAAO,UAAU;AAC1B"}
@@ -1,5 +1,3 @@
1
- import { UserModelMessage } from "ai";
2
-
3
1
  //#region src/session/input.d.ts
4
2
  type UserTextContent = string | readonly string[];
5
3
  interface UserText {
@@ -36,10 +34,8 @@ interface UserMessageFilePart {
36
34
  }
37
35
  type UserMessageContentPart = UserMessageFilePart | UserMessageImagePart | UserMessageTextPart;
38
36
  type UserMessageContent = readonly UserMessageContentPart[];
39
- type UserMessageMetadata = UserModelMessage["providerOptions"];
40
37
  interface UserMessage {
41
38
  content: UserMessageContent;
42
- metadata?: UserMessageMetadata;
43
39
  type: "user-message";
44
40
  }
45
41
  type UserInput = UserMessage | UserText;
@@ -19,8 +19,7 @@ function userTextContentToUserContent(text) {
19
19
  function userMessageToModelMessage(input) {
20
20
  return {
21
21
  role: "user",
22
- content: userMessageContentToUserContent(input.content),
23
- ...input.metadata === void 0 ? {} : { providerOptions: structuredClone(input.metadata) }
22
+ content: userMessageContentToUserContent(input.content)
24
23
  };
25
24
  }
26
25
  function userMessageContentToUserContent(content) {
@@ -1 +1 @@
1
- {"version":3,"file":"mapping.js","names":[],"sources":["../../src/session/mapping.ts"],"sourcesContent":["import type {\n AssistantContent,\n AssistantModelMessage,\n ModelMessage,\n ToolModelMessage,\n UserModelMessage,\n} from \"ai\";\nimport type {\n AssistantReasoning,\n AssistantText,\n ToolCall,\n ToolResult,\n UserMessage,\n UserMessageContent,\n UserMessageContentPart,\n UserMessageFileData,\n UserText,\n UserTextContent,\n} from \"./events\";\nimport type { UserInput } from \"./input\";\n\ntype AssistantContentPart = Exclude<AssistantContent, string>[number];\ntype ToolContentPart = ToolModelMessage[\"content\"][number];\ntype ModelEvent = AssistantReasoning | AssistantText | ToolCall | ToolResult;\n\n// UserInput -> AI SDK UserModelMessage\nexport function userInputToModelMessage(input: UserInput): UserModelMessage {\n if (input.type === \"user-message\") {\n return userMessageToModelMessage(input);\n }\n\n return userTextToModelMessage(input);\n}\n\nexport function userTextToModelMessage(input: UserText): UserModelMessage {\n return { role: \"user\", content: userTextContentToUserContent(input.text) };\n}\n\nfunction userTextContentToUserContent(\n text: UserTextContent\n): UserModelMessage[\"content\"] {\n if (typeof text === \"string\") {\n return text;\n }\n\n return text.map((part) => ({ type: \"text\", text: part }));\n}\n\nexport function userMessageToModelMessage(\n input: UserMessage\n): UserModelMessage {\n return {\n role: \"user\",\n content: userMessageContentToUserContent(input.content),\n ...(input.metadata === undefined\n ? {}\n : { providerOptions: structuredClone(input.metadata) }),\n };\n}\n\nfunction userMessageContentToUserContent(\n content: UserMessageContent\n): Exclude<UserModelMessage[\"content\"], string> {\n return content.map(userMessageContentPartToUserContentPart);\n}\n\nfunction userMessageContentPartToUserContentPart(\n part: UserMessageContentPart\n): Exclude<UserModelMessage[\"content\"], string>[number] {\n if (part.type === \"text\") {\n return { type: \"text\", text: part.text };\n }\n\n if (part.type === \"image\") {\n return {\n type: \"file\",\n data: part.image,\n mediaType: part.mediaType ?? \"image\",\n };\n }\n\n return {\n type: \"file\",\n data: userMessageFileDataToFileData(part.data),\n mediaType: part.mediaType,\n ...(part.filename === undefined ? {} : { filename: part.filename }),\n };\n}\n\nfunction userMessageFileDataToFileData(\n data: UserMessageFileData\n): Extract<\n Exclude<UserModelMessage[\"content\"], string>[number],\n { type: \"file\" }\n>[\"data\"] {\n if (typeof data === \"string\") {\n return data;\n }\n\n if (data.type === \"url\") {\n return data.url;\n }\n\n if (data.type === \"data\") {\n return { type: \"data\", data: data.data };\n }\n\n if (data.type === \"reference\") {\n return { type: \"reference\", reference: { ...data.reference } };\n }\n\n return { type: \"text\", text: data.text };\n}\n\n// AI SDK ModelMessage -> public agent events\nexport function modelMessageToAgentEvents(message: ModelMessage): ModelEvent[] {\n if (message.role === \"assistant\") {\n return assistantReasoningFirstParts(assistantContentParts(message)).flatMap(\n assistantContentPartToEvents\n );\n }\n\n if (message.role === \"tool\") {\n return message.content.flatMap(toolContentPartToEvents);\n }\n\n return [];\n}\n\nfunction assistantContentParts(\n message: AssistantModelMessage\n): AssistantContentPart[] {\n return typeof message.content === \"string\"\n ? [{ type: \"text\", text: message.content }]\n : message.content;\n}\n\nfunction assistantReasoningFirstParts(\n parts: AssistantContentPart[]\n): AssistantContentPart[] {\n return [\n ...parts.filter((part) => part.type === \"reasoning\"),\n ...parts.filter((part) => part.type !== \"reasoning\"),\n ];\n}\n\nfunction assistantContentPartToEvents(\n part: AssistantContentPart\n): ModelEvent[] {\n if (part.type === \"text\") {\n return part.text ? [{ type: \"assistant-text\", text: part.text }] : [];\n }\n\n if (part.type === \"reasoning\") {\n return part.text ? [{ type: \"assistant-reasoning\", text: part.text }] : [];\n }\n\n if (part.type === \"tool-call\") {\n return [\n {\n type: \"tool-call\",\n input: part.input,\n toolCallId: part.toolCallId,\n toolName: part.toolName,\n },\n ];\n }\n\n return [];\n}\n\nfunction toolContentPartToEvents(part: ToolContentPart): ModelEvent[] {\n if (part.type === \"tool-result\") {\n return toolResultPartToEvents(part);\n }\n\n return [];\n}\n\nfunction toolResultPartToEvents(part: {\n output: unknown;\n toolCallId: string;\n toolName: string;\n type: \"tool-result\";\n}): ModelEvent[] {\n return [\n {\n type: \"tool-result\",\n output: part.output,\n toolCallId: part.toolCallId,\n toolName: part.toolName,\n },\n ];\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"mapping.js","names":[],"sources":["../../src/session/mapping.ts"],"sourcesContent":["import type {\n AssistantContent,\n AssistantModelMessage,\n ModelMessage,\n ToolModelMessage,\n UserModelMessage,\n} from \"ai\";\nimport type {\n AssistantReasoning,\n AssistantText,\n ToolCall,\n ToolResult,\n UserMessage,\n UserMessageContent,\n UserMessageContentPart,\n UserMessageFileData,\n UserText,\n UserTextContent,\n} from \"./events\";\nimport type { UserInput } from \"./input\";\n\ntype AssistantContentPart = Exclude<AssistantContent, string>[number];\ntype ToolContentPart = ToolModelMessage[\"content\"][number];\ntype ModelEvent = AssistantReasoning | AssistantText | ToolCall | ToolResult;\n\n// UserInput -> AI SDK UserModelMessage\nexport function userInputToModelMessage(input: UserInput): UserModelMessage {\n if (input.type === \"user-message\") {\n return userMessageToModelMessage(input);\n }\n\n return userTextToModelMessage(input);\n}\n\nexport function userTextToModelMessage(input: UserText): UserModelMessage {\n return { role: \"user\", content: userTextContentToUserContent(input.text) };\n}\n\nfunction userTextContentToUserContent(\n text: UserTextContent\n): UserModelMessage[\"content\"] {\n if (typeof text === \"string\") {\n return text;\n }\n\n return text.map((part) => ({ type: \"text\", text: part }));\n}\n\nexport function userMessageToModelMessage(\n input: UserMessage\n): UserModelMessage {\n return {\n role: \"user\",\n content: userMessageContentToUserContent(input.content),\n };\n}\n\nfunction userMessageContentToUserContent(\n content: UserMessageContent\n): Exclude<UserModelMessage[\"content\"], string> {\n return content.map(userMessageContentPartToUserContentPart);\n}\n\nfunction userMessageContentPartToUserContentPart(\n part: UserMessageContentPart\n): Exclude<UserModelMessage[\"content\"], string>[number] {\n if (part.type === \"text\") {\n return { type: \"text\", text: part.text };\n }\n\n if (part.type === \"image\") {\n return {\n type: \"file\",\n data: part.image,\n mediaType: part.mediaType ?? \"image\",\n };\n }\n\n return {\n type: \"file\",\n data: userMessageFileDataToFileData(part.data),\n mediaType: part.mediaType,\n ...(part.filename === undefined ? {} : { filename: part.filename }),\n };\n}\n\nfunction userMessageFileDataToFileData(\n data: UserMessageFileData\n): Extract<\n Exclude<UserModelMessage[\"content\"], string>[number],\n { type: \"file\" }\n>[\"data\"] {\n if (typeof data === \"string\") {\n return data;\n }\n\n if (data.type === \"url\") {\n return data.url;\n }\n\n if (data.type === \"data\") {\n return { type: \"data\", data: data.data };\n }\n\n if (data.type === \"reference\") {\n return { type: \"reference\", reference: { ...data.reference } };\n }\n\n return { type: \"text\", text: data.text };\n}\n\n// AI SDK ModelMessage -> public agent events\nexport function modelMessageToAgentEvents(message: ModelMessage): ModelEvent[] {\n if (message.role === \"assistant\") {\n return assistantReasoningFirstParts(assistantContentParts(message)).flatMap(\n assistantContentPartToEvents\n );\n }\n\n if (message.role === \"tool\") {\n return message.content.flatMap(toolContentPartToEvents);\n }\n\n return [];\n}\n\nfunction assistantContentParts(\n message: AssistantModelMessage\n): AssistantContentPart[] {\n return typeof message.content === \"string\"\n ? [{ type: \"text\", text: message.content }]\n : message.content;\n}\n\nfunction assistantReasoningFirstParts(\n parts: AssistantContentPart[]\n): AssistantContentPart[] {\n return [\n ...parts.filter((part) => part.type === \"reasoning\"),\n ...parts.filter((part) => part.type !== \"reasoning\"),\n ];\n}\n\nfunction assistantContentPartToEvents(\n part: AssistantContentPart\n): ModelEvent[] {\n if (part.type === \"text\") {\n return part.text ? [{ type: \"assistant-text\", text: part.text }] : [];\n }\n\n if (part.type === \"reasoning\") {\n return part.text ? [{ type: \"assistant-reasoning\", text: part.text }] : [];\n }\n\n if (part.type === \"tool-call\") {\n return [\n {\n type: \"tool-call\",\n input: part.input,\n toolCallId: part.toolCallId,\n toolName: part.toolName,\n },\n ];\n }\n\n return [];\n}\n\nfunction toolContentPartToEvents(part: ToolContentPart): ModelEvent[] {\n if (part.type === \"tool-result\") {\n return toolResultPartToEvents(part);\n }\n\n return [];\n}\n\nfunction toolResultPartToEvents(part: {\n output: unknown;\n toolCallId: string;\n toolName: string;\n type: \"tool-result\";\n}): ModelEvent[] {\n return [\n {\n type: \"tool-result\",\n output: part.output,\n toolCallId: part.toolCallId,\n toolName: part.toolName,\n },\n ];\n}\n"],"mappings":";AA0BA,SAAgB,wBAAwB,OAAoC;CAC1E,IAAI,MAAM,SAAS,gBACjB,OAAO,0BAA0B,KAAK;CAGxC,OAAO,uBAAuB,KAAK;AACrC;AAEA,SAAgB,uBAAuB,OAAmC;CACxE,OAAO;EAAE,MAAM;EAAQ,SAAS,6BAA6B,MAAM,IAAI;CAAE;AAC3E;AAEA,SAAS,6BACP,MAC6B;CAC7B,IAAI,OAAO,SAAS,UAClB,OAAO;CAGT,OAAO,KAAK,KAAK,UAAU;EAAE,MAAM;EAAQ,MAAM;CAAK,EAAE;AAC1D;AAEA,SAAgB,0BACd,OACkB;CAClB,OAAO;EACL,MAAM;EACN,SAAS,gCAAgC,MAAM,OAAO;CACxD;AACF;AAEA,SAAS,gCACP,SAC8C;CAC9C,OAAO,QAAQ,IAAI,uCAAuC;AAC5D;AAEA,SAAS,wCACP,MACsD;CACtD,IAAI,KAAK,SAAS,QAChB,OAAO;EAAE,MAAM;EAAQ,MAAM,KAAK;CAAK;CAGzC,IAAI,KAAK,SAAS,SAChB,OAAO;EACL,MAAM;EACN,MAAM,KAAK;EACX,WAAW,KAAK,aAAa;CAC/B;CAGF,OAAO;EACL,MAAM;EACN,MAAM,8BAA8B,KAAK,IAAI;EAC7C,WAAW,KAAK;EAChB,GAAI,KAAK,aAAa,KAAA,IAAY,CAAC,IAAI,EAAE,UAAU,KAAK,SAAS;CACnE;AACF;AAEA,SAAS,8BACP,MAIQ;CACR,IAAI,OAAO,SAAS,UAClB,OAAO;CAGT,IAAI,KAAK,SAAS,OAChB,OAAO,KAAK;CAGd,IAAI,KAAK,SAAS,QAChB,OAAO;EAAE,MAAM;EAAQ,MAAM,KAAK;CAAK;CAGzC,IAAI,KAAK,SAAS,aAChB,OAAO;EAAE,MAAM;EAAa,WAAW,EAAE,GAAG,KAAK,UAAU;CAAE;CAG/D,OAAO;EAAE,MAAM;EAAQ,MAAM,KAAK;CAAK;AACzC;AAGA,SAAgB,0BAA0B,SAAqC;CAC7E,IAAI,QAAQ,SAAS,aACnB,OAAO,6BAA6B,sBAAsB,OAAO,CAAC,EAAE,QAClE,4BACF;CAGF,IAAI,QAAQ,SAAS,QACnB,OAAO,QAAQ,QAAQ,QAAQ,uBAAuB;CAGxD,OAAO,CAAC;AACV;AAEA,SAAS,sBACP,SACwB;CACxB,OAAO,OAAO,QAAQ,YAAY,WAC9B,CAAC;EAAE,MAAM;EAAQ,MAAM,QAAQ;CAAQ,CAAC,IACxC,QAAQ;AACd;AAEA,SAAS,6BACP,OACwB;CACxB,OAAO,CACL,GAAG,MAAM,QAAQ,SAAS,KAAK,SAAS,WAAW,GACnD,GAAG,MAAM,QAAQ,SAAS,KAAK,SAAS,WAAW,CACrD;AACF;AAEA,SAAS,6BACP,MACc;CACd,IAAI,KAAK,SAAS,QAChB,OAAO,KAAK,OAAO,CAAC;EAAE,MAAM;EAAkB,MAAM,KAAK;CAAK,CAAC,IAAI,CAAC;CAGtE,IAAI,KAAK,SAAS,aAChB,OAAO,KAAK,OAAO,CAAC;EAAE,MAAM;EAAuB,MAAM,KAAK;CAAK,CAAC,IAAI,CAAC;CAG3E,IAAI,KAAK,SAAS,aAChB,OAAO,CACL;EACE,MAAM;EACN,OAAO,KAAK;EACZ,YAAY,KAAK;EACjB,UAAU,KAAK;CACjB,CACF;CAGF,OAAO,CAAC;AACV;AAEA,SAAS,wBAAwB,MAAqC;CACpE,IAAI,KAAK,SAAS,eAChB,OAAO,uBAAuB,IAAI;CAGpC,OAAO,CAAC;AACV;AAEA,SAAS,uBAAuB,MAKf;CACf,OAAO,CACL;EACE,MAAM;EACN,QAAQ,KAAK;EACb,YAAY,KAAK;EACjB,UAAU,KAAK;CACjB,CACF;AACF"}
@@ -25,6 +25,7 @@ var BufferedAgentRun = class {
25
25
  this.#closed = true;
26
26
  this.#error = error;
27
27
  this.#settlePendingAck();
28
+ this.#settleQueuedAcks();
28
29
  if (!this.#waiter) return;
29
30
  const waiter = this.#waiter;
30
31
  this.#waiter = void 0;