kernl 0.2.0 → 0.6.0

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 (267) hide show
  1. package/.turbo/turbo-build.log +4 -5
  2. package/.turbo/turbo-check-types.log +4 -0
  3. package/CHANGELOG.md +147 -0
  4. package/LICENSE +1 -1
  5. package/dist/agent/__tests__/concurrency.test.d.ts +2 -0
  6. package/dist/agent/__tests__/concurrency.test.d.ts.map +1 -0
  7. package/dist/agent/__tests__/concurrency.test.js +152 -0
  8. package/dist/agent/__tests__/run.test.d.ts +2 -0
  9. package/dist/agent/__tests__/run.test.d.ts.map +1 -0
  10. package/dist/agent/__tests__/run.test.js +357 -0
  11. package/dist/agent/index.d.ts +1 -0
  12. package/dist/agent/index.d.ts.map +1 -0
  13. package/dist/agent.d.ts +32 -9
  14. package/dist/agent.d.ts.map +1 -1
  15. package/dist/agent.js +102 -14
  16. package/dist/api/__tests__/cursor-page.test.d.ts +2 -0
  17. package/dist/api/__tests__/cursor-page.test.d.ts.map +1 -0
  18. package/dist/api/__tests__/cursor-page.test.js +414 -0
  19. package/dist/api/__tests__/offset-page.test.d.ts +2 -0
  20. package/dist/api/__tests__/offset-page.test.d.ts.map +1 -0
  21. package/dist/api/__tests__/offset-page.test.js +510 -0
  22. package/dist/api/__tests__/threads.test.d.ts +2 -0
  23. package/dist/api/__tests__/threads.test.d.ts.map +1 -0
  24. package/dist/api/__tests__/threads.test.js +338 -0
  25. package/dist/api/models/index.d.ts +2 -0
  26. package/dist/api/models/index.d.ts.map +1 -0
  27. package/dist/api/models/thread.d.ts +120 -0
  28. package/dist/api/models/thread.d.ts.map +1 -0
  29. package/dist/api/pagination/base.d.ts +48 -0
  30. package/dist/api/pagination/base.d.ts.map +1 -0
  31. package/dist/api/pagination/base.js +45 -0
  32. package/dist/api/pagination/cursor.d.ts +44 -0
  33. package/dist/api/pagination/cursor.d.ts.map +1 -0
  34. package/dist/api/pagination/cursor.js +52 -0
  35. package/dist/api/pagination/offset.d.ts +42 -0
  36. package/dist/api/pagination/offset.d.ts.map +1 -0
  37. package/dist/api/pagination/offset.js +55 -0
  38. package/dist/api/resources/threads/events.d.ts +21 -0
  39. package/dist/api/resources/threads/events.d.ts.map +1 -0
  40. package/dist/api/resources/threads/events.js +24 -0
  41. package/dist/api/resources/threads/index.d.ts +4 -0
  42. package/dist/api/resources/threads/index.d.ts.map +1 -0
  43. package/dist/api/resources/threads/index.js +2 -0
  44. package/dist/api/resources/threads/threads.d.ts +57 -0
  45. package/dist/api/resources/threads/threads.d.ts.map +1 -0
  46. package/dist/api/resources/threads/threads.js +199 -0
  47. package/dist/api/resources/threads/types.d.ts +123 -0
  48. package/dist/api/resources/threads/types.d.ts.map +1 -0
  49. package/dist/api/resources/threads/utils.d.ts +18 -0
  50. package/dist/api/resources/threads/utils.d.ts.map +1 -0
  51. package/dist/api/resources/threads/utils.js +78 -0
  52. package/dist/context.d.ts +5 -1
  53. package/dist/context.d.ts.map +1 -1
  54. package/dist/context.js +6 -1
  55. package/dist/index.d.ts +9 -1
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +7 -0
  58. package/dist/internal.d.ts +4 -0
  59. package/dist/internal.d.ts.map +1 -0
  60. package/dist/internal.js +2 -0
  61. package/dist/kernl/index.d.ts +3 -0
  62. package/dist/kernl/index.d.ts.map +1 -0
  63. package/dist/kernl/index.js +2 -0
  64. package/dist/kernl/kernl.d.ts +64 -0
  65. package/dist/kernl/kernl.d.ts.map +1 -0
  66. package/dist/kernl/kernl.js +116 -0
  67. package/dist/kernl/threads.d.ts +110 -0
  68. package/dist/kernl/threads.d.ts.map +1 -0
  69. package/dist/kernl/threads.js +126 -0
  70. package/dist/kernl.d.ts +22 -6
  71. package/dist/kernl.d.ts.map +1 -1
  72. package/dist/kernl.js +73 -10
  73. package/dist/lib/env.d.ts +3 -3
  74. package/dist/lib/env.js +1 -1
  75. package/dist/mcp/__tests__/integration.test.js +8 -8
  76. package/dist/mcp/__tests__/utils.test.js +6 -6
  77. package/dist/mcp/http.d.ts +1 -1
  78. package/dist/mcp/http.d.ts.map +1 -1
  79. package/dist/mcp/http.js +9 -9
  80. package/dist/mcp/sse.d.ts +1 -1
  81. package/dist/mcp/sse.d.ts.map +1 -1
  82. package/dist/mcp/sse.js +7 -7
  83. package/dist/mcp/utils.d.ts +1 -1
  84. package/dist/mcp/utils.d.ts.map +1 -1
  85. package/dist/mcp/utils.js +4 -5
  86. package/dist/storage/__tests__/in-memory.test.d.ts +2 -0
  87. package/dist/storage/__tests__/in-memory.test.d.ts.map +1 -0
  88. package/dist/storage/__tests__/in-memory.test.js +455 -0
  89. package/dist/storage/base.d.ts +64 -0
  90. package/dist/storage/base.d.ts.map +1 -0
  91. package/dist/storage/base.js +4 -0
  92. package/dist/storage/in-memory.d.ts +62 -0
  93. package/dist/storage/in-memory.d.ts.map +1 -0
  94. package/dist/storage/in-memory.js +283 -0
  95. package/dist/storage/index.d.ts +10 -0
  96. package/dist/storage/index.d.ts.map +1 -0
  97. package/dist/storage/index.js +7 -0
  98. package/dist/storage/thread.d.ts +123 -0
  99. package/dist/storage/thread.d.ts.map +1 -0
  100. package/dist/storage/thread.js +4 -0
  101. package/dist/task.d.ts +5 -3
  102. package/dist/task.d.ts.map +1 -1
  103. package/dist/task.js +10 -8
  104. package/dist/thread/__tests__/fixtures/mock-model.d.ts +1 -2
  105. package/dist/thread/__tests__/fixtures/mock-model.d.ts.map +1 -1
  106. package/dist/thread/__tests__/integration.test.js +73 -5
  107. package/dist/thread/__tests__/namespace.test.d.ts +2 -0
  108. package/dist/thread/__tests__/namespace.test.d.ts.map +1 -0
  109. package/dist/thread/__tests__/namespace.test.js +131 -0
  110. package/dist/thread/__tests__/thread-persistence.test.d.ts +2 -0
  111. package/dist/thread/__tests__/thread-persistence.test.d.ts.map +1 -0
  112. package/dist/thread/__tests__/thread-persistence.test.js +351 -0
  113. package/dist/thread/__tests__/thread.test.js +49 -51
  114. package/dist/thread/thread.d.ts +70 -18
  115. package/dist/thread/thread.d.ts.map +1 -1
  116. package/dist/thread/thread.js +211 -73
  117. package/dist/thread/utils.d.ts +36 -8
  118. package/dist/thread/utils.d.ts.map +1 -1
  119. package/dist/thread/utils.js +52 -8
  120. package/dist/tool/__tests__/fixtures.js +1 -1
  121. package/dist/tool/__tests__/toolkit.test.js +15 -12
  122. package/dist/tool/tool.js +3 -3
  123. package/dist/types/kernl.d.ts +42 -0
  124. package/dist/types/kernl.d.ts.map +1 -0
  125. package/dist/types/thread.d.ts +108 -22
  126. package/dist/types/thread.d.ts.map +1 -1
  127. package/dist/types/thread.js +12 -0
  128. package/package.json +11 -7
  129. package/src/agent/__tests__/concurrency.test.ts +194 -0
  130. package/src/agent/__tests__/run.test.ts +441 -0
  131. package/src/agent/index.ts +0 -0
  132. package/src/agent.ts +141 -24
  133. package/src/api/__tests__/cursor-page.test.ts +512 -0
  134. package/src/api/__tests__/offset-page.test.ts +624 -0
  135. package/src/api/__tests__/threads.test.ts +415 -0
  136. package/src/api/models/index.ts +6 -0
  137. package/src/api/models/thread.ts +138 -0
  138. package/src/api/pagination/base.ts +79 -0
  139. package/src/api/pagination/cursor.ts +86 -0
  140. package/src/api/pagination/offset.ts +89 -0
  141. package/src/api/resources/threads/events.ts +26 -0
  142. package/src/api/resources/threads/index.ts +9 -0
  143. package/src/api/resources/threads/threads.ts +256 -0
  144. package/src/api/resources/threads/types.ts +143 -0
  145. package/src/api/resources/threads/utils.ts +104 -0
  146. package/src/context.ts +10 -1
  147. package/src/index.ts +49 -1
  148. package/src/internal.ts +15 -0
  149. package/src/kernl.ts +86 -17
  150. package/src/mcp/__tests__/integration.test.ts +8 -9
  151. package/src/mcp/__tests__/utils.test.ts +6 -6
  152. package/src/mcp/http.ts +9 -9
  153. package/src/mcp/sse.ts +7 -7
  154. package/src/mcp/utils.ts +6 -5
  155. package/src/storage/__tests__/in-memory.test.ts +534 -0
  156. package/src/storage/base.ts +77 -0
  157. package/src/storage/in-memory.ts +372 -0
  158. package/src/storage/index.ts +21 -0
  159. package/src/storage/thread.ts +141 -0
  160. package/src/task.ts +12 -10
  161. package/src/thread/__tests__/fixtures/mock-model.ts +2 -4
  162. package/src/thread/__tests__/integration.test.ts +111 -10
  163. package/src/thread/__tests__/namespace.test.ts +158 -0
  164. package/src/thread/__tests__/thread-persistence.test.ts +367 -0
  165. package/src/thread/__tests__/thread.test.ts +52 -54
  166. package/src/thread/thread.ts +247 -96
  167. package/src/thread/utils.ts +76 -13
  168. package/src/tool/__tests__/fixtures.ts +1 -1
  169. package/src/tool/__tests__/toolkit.test.ts +15 -12
  170. package/src/tool/tool.ts +3 -3
  171. package/src/types/kernl.ts +51 -0
  172. package/src/types/thread.ts +139 -25
  173. package/vitest.config.ts +1 -0
  174. package/dist/env.d.ts +0 -45
  175. package/dist/env.d.ts.map +0 -1
  176. package/dist/env.js +0 -31
  177. package/dist/error.d.ts +0 -1
  178. package/dist/error.d.ts.map +0 -1
  179. package/dist/kernel.d.ts +0 -7
  180. package/dist/kernel.d.ts.map +0 -1
  181. package/dist/kernel.js +0 -7
  182. package/dist/lib/serde/__tests__/codec.test.d.ts +0 -2
  183. package/dist/lib/serde/__tests__/codec.test.d.ts.map +0 -1
  184. package/dist/lib/serde/__tests__/codec.test.js +0 -75
  185. package/dist/lib/serde/codec.d.ts +0 -12
  186. package/dist/lib/serde/codec.d.ts.map +0 -1
  187. package/dist/lib/serde/codec.js +0 -54
  188. package/dist/lib/serde/thread.d.ts +0 -1
  189. package/dist/lib/serde/thread.d.ts.map +0 -1
  190. package/dist/lib/serde/thread.js +0 -172
  191. package/dist/lib/serde/tool.d.ts +0 -36
  192. package/dist/lib/serde/tool.d.ts.map +0 -1
  193. package/dist/lib/utils.d.ts +0 -19
  194. package/dist/lib/utils.d.ts.map +0 -1
  195. package/dist/lib/utils.js +0 -41
  196. package/dist/logger.d.ts +0 -36
  197. package/dist/logger.d.ts.map +0 -1
  198. package/dist/logger.js +0 -43
  199. package/dist/mcp/__tests__/fixtures/echo-server.d.ts +0 -3
  200. package/dist/mcp/__tests__/fixtures/echo-server.d.ts.map +0 -1
  201. package/dist/mcp/__tests__/fixtures/echo-server.js +0 -92
  202. package/dist/mcp/__tests__/fixtures/math-server.d.ts +0 -3
  203. package/dist/mcp/__tests__/fixtures/math-server.d.ts.map +0 -1
  204. package/dist/mcp/__tests__/fixtures/math-server.js +0 -98
  205. package/dist/mcp/__tests__/fixtures/test-server.d.ts +0 -3
  206. package/dist/mcp/__tests__/fixtures/test-server.d.ts.map +0 -1
  207. package/dist/mcp/__tests__/fixtures/test-server.js +0 -163
  208. package/dist/mcp/__tests__/test-utils.d.ts +0 -17
  209. package/dist/mcp/__tests__/test-utils.d.ts.map +0 -1
  210. package/dist/mcp/__tests__/test-utils.js +0 -42
  211. package/dist/mcp/node.d.ts +0 -60
  212. package/dist/mcp/node.d.ts.map +0 -1
  213. package/dist/mcp/node.js +0 -297
  214. package/dist/model.d.ts +0 -175
  215. package/dist/model.d.ts.map +0 -1
  216. package/dist/providers/ai.d.ts +0 -1
  217. package/dist/providers/ai.d.ts.map +0 -1
  218. package/dist/providers/ai.js +0 -1
  219. package/dist/providers/default.d.ts +0 -16
  220. package/dist/providers/default.d.ts.map +0 -1
  221. package/dist/providers/default.js +0 -17
  222. package/dist/providers/registry.d.ts +0 -1
  223. package/dist/providers/registry.d.ts.map +0 -1
  224. package/dist/providers/registry.js +0 -1
  225. package/dist/sched/scheduler.d.ts +0 -20
  226. package/dist/sched/scheduler.d.ts.map +0 -1
  227. package/dist/sched/task.d.ts +0 -92
  228. package/dist/sched/task.d.ts.map +0 -1
  229. package/dist/sched/task.js +0 -102
  230. package/dist/serde/__tests__/codec.test.d.ts +0 -2
  231. package/dist/serde/__tests__/codec.test.d.ts.map +0 -1
  232. package/dist/serde/__tests__/codec.test.js +0 -75
  233. package/dist/serde/codec.d.ts +0 -12
  234. package/dist/serde/codec.d.ts.map +0 -1
  235. package/dist/serde/codec.js +0 -54
  236. package/dist/serde/json.d.ts +0 -8
  237. package/dist/serde/json.d.ts.map +0 -1
  238. package/dist/serde/json.js +0 -13
  239. package/dist/serde/thread.d.ts +0 -687
  240. package/dist/serde/thread.d.ts.map +0 -1
  241. package/dist/serde/thread.js +0 -158
  242. package/dist/serde/tool.d.ts +0 -36
  243. package/dist/serde/tool.d.ts.map +0 -1
  244. package/dist/session.d.ts +0 -1
  245. package/dist/session.d.ts.map +0 -1
  246. package/dist/session.js +0 -1
  247. package/dist/thread/__tests__/stream.test.d.ts +0 -2
  248. package/dist/thread/__tests__/stream.test.d.ts.map +0 -1
  249. package/dist/thread/__tests__/stream.test.js +0 -244
  250. package/dist/tool/mcp.d.ts +0 -75
  251. package/dist/tool/mcp.d.ts.map +0 -1
  252. package/dist/tool/mcp.js +0 -111
  253. package/dist/tools.d.ts +0 -362
  254. package/dist/tools.d.ts.map +0 -1
  255. package/dist/tools.js +0 -220
  256. package/dist/types/proto.d.ts +0 -1551
  257. package/dist/types/proto.d.ts.map +0 -1
  258. package/dist/types/proto.js +0 -531
  259. package/dist/usage.d.ts +0 -43
  260. package/dist/usage.d.ts.map +0 -1
  261. package/dist/usage.js +0 -61
  262. package/src/lib/serde/thread.ts +0 -188
  263. /package/dist/{error.js → agent/index.js} +0 -0
  264. /package/dist/{lib/serde/tool.js → api/models/index.js} +0 -0
  265. /package/dist/{model.js → api/models/thread.js} +0 -0
  266. /package/dist/{sched/scheduler.js → api/resources/threads/types.js} +0 -0
  267. /package/dist/{serde/tool.js → types/kernl.js} +0 -0
package/src/context.ts CHANGED
@@ -8,6 +8,11 @@ export type ApprovalStatus = "approved" | "rejected" | "pending";
8
8
  * execution units.
9
9
  */
10
10
  export class Context<TContext = UnknownContext> {
11
+ /**
12
+ * The namespace that this context belongs to.
13
+ */
14
+ namespace: string;
15
+
11
16
  /**
12
17
  * The inner context object.
13
18
  */
@@ -59,7 +64,11 @@ export class Context<TContext = UnknownContext> {
59
64
  // */
60
65
  // #approvals: Map<string, ApprovalRecord>;
61
66
 
62
- constructor(context: TContext = {} as TContext) {
67
+ constructor(
68
+ namespace: string = "kernl",
69
+ context: TContext = {} as TContext,
70
+ ) {
71
+ this.namespace = namespace;
63
72
  this.context = context;
64
73
  this.approvals = new Map();
65
74
  // this.format = format; // (TODO): configure()
package/src/index.ts CHANGED
@@ -1,4 +1,52 @@
1
1
  export { Kernl } from "./kernl";
2
+ export type {
3
+ KernlOptions,
4
+ StorageOptions,
5
+ AgentRegistry,
6
+ ModelRegistry,
7
+ } from "./types/kernl";
2
8
  export { Agent } from "./agent";
3
- export type { Context } from "./context";
9
+ export { Context } from "./context";
10
+
11
+ // --- tools --
4
12
  export { tool, Toolkit, FunctionToolkit, MCPToolkit } from "./tool";
13
+ export { MCPServerSSE } from "./mcp/sse";
14
+ export { MCPServerStdio } from "./mcp/stdio";
15
+ export { MCPServerStreamableHttp } from "./mcp/http";
16
+
17
+ // --- thread models ---
18
+ export type {
19
+ MThread as Thread,
20
+ MThreadEvent as ThreadEvent,
21
+ MThreadEventBase as ThreadEventBase,
22
+ } from "./api/models";
23
+
24
+ // --- thread resource types ---
25
+ export type {
26
+ RThreadsListParams as ThreadsListParams,
27
+ RThreadGetOptions as ThreadGetOptions,
28
+ RThreadHistoryParams as ThreadHistoryParams,
29
+ RThreadCreateParams as ThreadCreateParams,
30
+ RThreadUpdateParams as ThreadUpdateParams,
31
+ } from "./api/resources/threads";
32
+
33
+ // --- thread state enums ---
34
+ export {
35
+ THREAD_STATES,
36
+ type ThreadState,
37
+ type PublicThreadEvent,
38
+ } from "./types/thread";
39
+
40
+ // --- storage types ---
41
+ export type {
42
+ ThreadStore,
43
+ NewThread,
44
+ ThreadUpdate,
45
+ ThreadFilter,
46
+ ThreadHistoryOptions,
47
+ ThreadInclude,
48
+ ThreadListOptions,
49
+ SortOrder,
50
+ KernlStorage,
51
+ Transaction,
52
+ } from "./storage";
@@ -0,0 +1,15 @@
1
+ export { Thread } from "./thread/thread";
2
+
3
+ export type {
4
+ IThread,
5
+ ThreadEvent,
6
+ ThreadEventBase,
7
+ ThreadEventInner,
8
+ ThreadSystemEvent,
9
+ ThreadState,
10
+ PublicThreadEvent,
11
+ } from "./types/thread";
12
+
13
+ export { THREAD_STATES } from "./types/thread";
14
+
15
+
package/src/kernl.ts CHANGED
@@ -1,21 +1,41 @@
1
- import { Agent } from "./agent";
2
- import { UnknownContext } from "./context";
3
- import { KernlHooks } from "./lifecycle";
4
- import type { Thread } from "./thread";
1
+ import type { LanguageModel } from "@kernl-sdk/protocol";
5
2
 
6
- import type { AgentResponseType } from "./types/agent";
7
- import type { ThreadExecuteResult, ThreadStreamEvent } from "./types/thread";
8
- import type { ResolvedAgentResponse } from "./guardrail";
3
+ import { Agent } from "@/agent";
4
+ import { UnknownContext } from "@/context";
5
+ import { KernlHooks } from "@/lifecycle";
6
+ import type { Thread } from "@/thread";
7
+ import type { ResolvedAgentResponse } from "@/guardrail";
8
+ import { InMemoryStorage, type KernlStorage } from "@/storage";
9
+ import { RThreads } from "@/api/resources/threads";
10
+
11
+ import type { KernlOptions } from "@/types/kernl";
12
+ import type { ThreadExecuteResult, ThreadStreamEvent } from "@/types/thread";
13
+ import type { AgentResponseType } from "@/types/agent";
9
14
 
10
15
  /**
11
- * The kernl - manages agent processes, scheduling, and task lifecycle
16
+ * The kernl - manages agent processes, scheduling, and task lifecycle.
12
17
  *
13
18
  * Orchestrates agent execution, including guardrails, tool calls, session persistence, and
14
19
  * tracing.
15
20
  */
16
21
  export class Kernl extends KernlHooks<UnknownContext, AgentResponseType> {
17
22
  private agents: Map<string, Agent> = new Map();
18
- threads: Map<string, Thread<any, any>> = new Map();
23
+ private models: Map<string, LanguageModel> = new Map();
24
+
25
+ readonly storage: KernlStorage;
26
+ athreads: Map<string, Thread<any, any>> = new Map(); /* active threads */
27
+
28
+ private initPromise: Promise<void> | null = null;
29
+
30
+ // --- public API ---
31
+ readonly threads: RThreads; /* Threads resource */
32
+
33
+ constructor(options: KernlOptions = {}) {
34
+ super();
35
+ this.storage = options.storage?.db ?? new InMemoryStorage();
36
+ this.storage.bind({ agents: this.agents, models: this.models });
37
+ this.threads = new RThreads(this.storage.threads);
38
+ }
19
39
 
20
40
  /**
21
41
  * Registers a new agent with the kernl instance.
@@ -23,6 +43,14 @@ export class Kernl extends KernlHooks<UnknownContext, AgentResponseType> {
23
43
  register(agent: Agent): void {
24
44
  this.agents.set(agent.id, agent);
25
45
  agent.bind(this);
46
+
47
+ // (TODO): implement exhaustive model registry in protocol/ package
48
+ //
49
+ // auto-populate model registry for storage hydration
50
+ const key = `${agent.model.provider}/${agent.model.modelId}`;
51
+ if (!this.models.has(key)) {
52
+ this.models.set(key, agent.model);
53
+ }
26
54
  }
27
55
 
28
56
  /**
@@ -31,8 +59,13 @@ export class Kernl extends KernlHooks<UnknownContext, AgentResponseType> {
31
59
  async spawn<TContext, TResponse extends AgentResponseType>(
32
60
  thread: Thread<TContext, TResponse>,
33
61
  ): Promise<ThreadExecuteResult<ResolvedAgentResponse<TResponse>>> {
34
- this.threads.set(thread.id, thread);
35
- return await thread.execute();
62
+ await this.ensureInitialized();
63
+ this.athreads.set(thread.tid, thread);
64
+ try {
65
+ return await thread.execute();
66
+ } finally {
67
+ this.athreads.delete(thread.tid);
68
+ }
36
69
  }
37
70
 
38
71
  /**
@@ -43,29 +76,65 @@ export class Kernl extends KernlHooks<UnknownContext, AgentResponseType> {
43
76
  async schedule<TContext, TResponse extends AgentResponseType>(
44
77
  thread: Thread<TContext, TResponse>,
45
78
  ): Promise<ThreadExecuteResult<ResolvedAgentResponse<TResponse>>> {
46
- return await thread.execute();
79
+ await this.ensureInitialized();
80
+ this.athreads.set(thread.tid, thread);
81
+ try {
82
+ return await thread.execute();
83
+ } finally {
84
+ this.athreads.delete(thread.tid);
85
+ }
47
86
  }
48
87
 
49
88
  /**
50
- * (TMP) - probably won't make sense with assync scheduling contexts
89
+ * (TMP) - won't make sense in async scheduling contexts
51
90
  *
52
91
  * Spawn a new thread - streaming execution
53
92
  */
54
93
  async *spawnStream<TContext, TResponse extends AgentResponseType>(
55
94
  thread: Thread<TContext, TResponse>,
56
95
  ): AsyncIterable<ThreadStreamEvent> {
57
- this.threads.set(thread.id, thread);
58
- yield* thread.stream();
96
+ await this.ensureInitialized();
97
+ this.athreads.set(thread.tid, thread);
98
+ try {
99
+ yield* thread.stream();
100
+ } finally {
101
+ this.athreads.delete(thread.tid);
102
+ }
59
103
  }
60
104
 
61
105
  /**
62
- * (TMP) - probably won't make sense with assync scheduling contexts
106
+ * (TMP) - won't make sense with async scheduling contexts
63
107
  *
64
108
  * Schedule an existing thread - streaming execution
65
109
  */
66
110
  async *scheduleStream<TContext, TResponse extends AgentResponseType>(
67
111
  thread: Thread<TContext, TResponse>,
68
112
  ): AsyncIterable<ThreadStreamEvent> {
69
- yield* thread.stream();
113
+ await this.ensureInitialized();
114
+ this.athreads.set(thread.tid, thread);
115
+ try {
116
+ yield* thread.stream();
117
+ } finally {
118
+ this.athreads.delete(thread.tid);
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Ensure the underlying storage backend has been initialized.
124
+ *
125
+ * This is called lazily on first use so that callers do not need to worry
126
+ * about calling storage.init() themselves. Safe and idempotent to call
127
+ * multiple times; concurrent calls share the same initialization promise.
128
+ */
129
+ private async ensureInitialized(): Promise<void> {
130
+ if (!this.initPromise) {
131
+ this.initPromise = this.storage.init().catch((error) => {
132
+ // allow a retry if initialization fails.
133
+ this.initPromise = null;
134
+ throw error;
135
+ });
136
+ }
137
+
138
+ await this.initPromise;
70
139
  }
71
140
  }
@@ -7,7 +7,6 @@ import { Agent } from "@/agent";
7
7
  import { Context } from "@/context";
8
8
  import { tool } from "@/tool";
9
9
  import { z } from "zod";
10
- import { Thread } from "@/thread";
11
10
  import { createMCPToolStaticFilter } from "../utils";
12
11
  import { createMockModel } from "@/thread/__tests__/fixtures/mock-model";
13
12
 
@@ -171,7 +170,7 @@ describe("MCP Integration Tests", () => {
171
170
  toolkits: [toolkit],
172
171
  });
173
172
 
174
- const context = new Context({});
173
+ const context = new Context("test-namespace", {});
175
174
  const tools = await toolkit.list(context);
176
175
 
177
176
  // Should have 3 math tools only
@@ -208,7 +207,7 @@ describe("MCP Integration Tests", () => {
208
207
  toolkits: [toolkit],
209
208
  });
210
209
 
211
- const context = new Context({});
210
+ const context = new Context("test-namespace", {});
212
211
  const tools = await toolkit.list(context);
213
212
 
214
213
  // Should have only add and divide (multiply blocked by toolkit filter)
@@ -247,7 +246,7 @@ describe("MCP Integration Tests", () => {
247
246
  toolkits: [toolkit],
248
247
  });
249
248
 
250
- const context = new Context({ userId: "test-user" });
249
+ const context = new Context("test-namespace", { userId: "test-user" });
251
250
  await toolkit.list(context);
252
251
 
253
252
  // Verify context was passed correctly
@@ -281,7 +280,7 @@ describe("MCP Integration Tests", () => {
281
280
  toolkits: [mcpToolkit],
282
281
  });
283
282
 
284
- const context = new Context({});
283
+ const context = new Context("test-namespace", {});
285
284
  const tools = await agent.tools(context);
286
285
 
287
286
  expect(tools.length).toBe(6);
@@ -312,7 +311,7 @@ describe("MCP Integration Tests", () => {
312
311
  });
313
312
 
314
313
  // Populate toolkit cache
315
- const context = new Context({});
314
+ const context = new Context("test-namespace", {});
316
315
  await agent.tools(context);
317
316
 
318
317
  // Now get specific tool
@@ -343,7 +342,7 @@ describe("MCP Integration Tests", () => {
343
342
  toolkits: [mcpToolkit],
344
343
  });
345
344
 
346
- const context = new Context({});
345
+ const context = new Context("test-namespace", {});
347
346
  await agent.tools(context);
348
347
 
349
348
  const addTool = agent.tool("add");
@@ -401,7 +400,7 @@ describe("MCP Integration Tests", () => {
401
400
  toolkits: [mcpToolkit, functionToolkit],
402
401
  });
403
402
 
404
- const context = new Context({});
403
+ const context = new Context("test-namespace", {});
405
404
  const tools = await agent.tools(context);
406
405
 
407
406
  // Should have 7 tools (6 MCP + 1 local)
@@ -451,7 +450,7 @@ describe("MCP Integration Tests", () => {
451
450
  toolkits: [mcpToolkit, functionToolkit],
452
451
  });
453
452
 
454
- const context = new Context({});
453
+ const context = new Context("test-namespace", {});
455
454
 
456
455
  // Should throw error about duplicate tool IDs
457
456
  await expect(agent.tools(context)).rejects.toThrow(
@@ -95,7 +95,7 @@ describe("mcpToFunctionTool", () => {
95
95
  };
96
96
 
97
97
  const functionTool = mcpToFunctionTool(server, mcpTool);
98
- const ctx = new Context({});
98
+ const ctx = new Context("test-namespace", {});
99
99
  const input = { arg1: "value1" };
100
100
 
101
101
  await functionTool.invoke(ctx, JSON.stringify(input));
@@ -119,7 +119,7 @@ describe("mcpToFunctionTool", () => {
119
119
  };
120
120
 
121
121
  const functionTool = mcpToFunctionTool(server, mcpTool);
122
- const ctx = new Context({});
122
+ const ctx = new Context("test-namespace", {});
123
123
  const toolResult = await functionTool.invoke(ctx, JSON.stringify({}));
124
124
 
125
125
  expect(toolResult.state).toBe("completed");
@@ -144,7 +144,7 @@ describe("mcpToFunctionTool", () => {
144
144
  };
145
145
 
146
146
  const functionTool = mcpToFunctionTool(server, mcpTool);
147
- const ctx = new Context({});
147
+ const ctx = new Context("test-namespace", {});
148
148
  const toolResult = await functionTool.invoke(ctx, JSON.stringify({}));
149
149
 
150
150
  expect(toolResult.state).toBe("completed");
@@ -171,7 +171,7 @@ describe("mcpToFunctionTool", () => {
171
171
  const functionTool1 = mcpToFunctionTool(server, tool1);
172
172
  const functionTool2 = mcpToFunctionTool(server, tool2);
173
173
 
174
- const ctx = new Context({});
174
+ const ctx = new Context("test-namespace", {});
175
175
 
176
176
  await functionTool1.invoke(ctx, JSON.stringify({}));
177
177
  expect(server.callTool).toHaveBeenCalledWith("tool1", {});
@@ -199,7 +199,7 @@ describe("mcpToFunctionTool", () => {
199
199
  const functionTool = mcpToFunctionTool(server, mcpTool);
200
200
 
201
201
  // Invoke takes (context, params as JSON string) in that order
202
- const ctx = new Context({});
202
+ const ctx = new Context("test-namespace", {});
203
203
  const params = { foo: "bar" };
204
204
  await functionTool.invoke(ctx, JSON.stringify(params));
205
205
 
@@ -211,7 +211,7 @@ describe("mcpToFunctionTool", () => {
211
211
  describe("createMCPToolStaticFilter", () => {
212
212
  // Helper to create mock filter context
213
213
  const createMockFilterContext = (): MCPToolFilterContext => ({
214
- context: new Context({}),
214
+ context: new Context("test-namespace", {}),
215
215
  agent: {} as Agent,
216
216
  serverId: "test-server",
217
217
  });
package/src/mcp/http.ts CHANGED
@@ -28,7 +28,7 @@ export class MCPServerStreamableHttp extends BaseMCPServer {
28
28
  protected timeout: number;
29
29
  protected serverInitializeResult: InitializeResult | null = null;
30
30
 
31
- params: MCPServerStreamableHttpOptions;
31
+ options: MCPServerStreamableHttpOptions;
32
32
  private transport: any = null;
33
33
 
34
34
  constructor(options: MCPServerStreamableHttpOptions) {
@@ -40,8 +40,8 @@ export class MCPServerStreamableHttp extends BaseMCPServer {
40
40
  getLogger(DEFAULT_STREAMABLE_HTTP_MCP_CLIENT_LOGGER_NAME),
41
41
  });
42
42
 
43
- this.params = options;
44
- this.id = options.id || `streamable-http: ${this.params.url}`;
43
+ this.options = options;
44
+ this.id = options.id || `streamable-http: ${this.options.url}`;
45
45
  this.timeout = options.timeout ?? DEFAULT_REQUEST_TIMEOUT_MSEC;
46
46
  }
47
47
 
@@ -51,13 +51,13 @@ export class MCPServerStreamableHttp extends BaseMCPServer {
51
51
  async connect(): Promise<void> {
52
52
  try {
53
53
  this.transport = new StreamableHTTPClientTransport(
54
- new URL(this.params.url),
54
+ new URL(this.options.url),
55
55
  {
56
- authProvider: this.params.authProvider,
57
- requestInit: this.params.requestInit,
58
- fetch: this.params.fetch,
59
- reconnectionOptions: this.params.reconnectionOptions,
60
- sessionId: this.params.sessionId,
56
+ authProvider: this.options.authProvider,
57
+ requestInit: this.options.requestInit,
58
+ fetch: this.options.fetch,
59
+ reconnectionOptions: this.options.reconnectionOptions,
60
+ sessionId: this.options.sessionId,
61
61
  },
62
62
  );
63
63
 
package/src/mcp/sse.ts CHANGED
@@ -25,7 +25,7 @@ export class MCPServerSSE extends BaseMCPServer {
25
25
  protected timeout: number;
26
26
  protected serverInitializeResult: InitializeResult | null = null;
27
27
 
28
- params: MCPServerSSEOptions;
28
+ options: MCPServerSSEOptions;
29
29
  private transport: any = null;
30
30
 
31
31
  constructor(options: MCPServerSSEOptions) {
@@ -35,8 +35,8 @@ export class MCPServerSSE extends BaseMCPServer {
35
35
  logger: options.logger ?? getLogger(DEFAULT_SSE_MCP_CLIENT_LOGGER_NAME),
36
36
  });
37
37
 
38
- this.params = options;
39
- this.id = options.id || `sse: ${this.params.url}`;
38
+ this.options = options;
39
+ this.id = options.id || `sse: ${this.options.url}`;
40
40
  this.timeout = options.timeout ?? DEFAULT_REQUEST_TIMEOUT_MSEC;
41
41
  }
42
42
 
@@ -45,10 +45,10 @@ export class MCPServerSSE extends BaseMCPServer {
45
45
  */
46
46
  async connect(): Promise<void> {
47
47
  try {
48
- this.transport = new SSEClientTransport(new URL(this.params.url), {
49
- authProvider: this.params.authProvider,
50
- requestInit: this.params.requestInit,
51
- eventSourceInit: this.params.eventSourceInit,
48
+ this.transport = new SSEClientTransport(new URL(this.options.url), {
49
+ authProvider: this.options.authProvider,
50
+ requestInit: this.options.requestInit,
51
+ eventSourceInit: this.options.eventSourceInit,
52
52
  });
53
53
 
54
54
  this.session = new Client({
package/src/mcp/utils.ts CHANGED
@@ -15,11 +15,12 @@ export function mcpToFunctionTool(server: MCPServer, mcpTool: MCPTool) {
15
15
  return content.length === 1 ? content[0] : content;
16
16
  }
17
17
 
18
- // MCP tools accept an object with any properties based on their inputSchema
19
- // We use z.record(z.any()) to represent this flexible schema
20
- const parameters = mcpTool.inputSchema
21
- ? z.record(z.string(), z.any())
22
- : undefined;
18
+ const hasProperties =
19
+ mcpTool.inputSchema &&
20
+ Object.keys(mcpTool.inputSchema.properties || {}).length > 0;
21
+
22
+ // If tool has properties, use passthrough to accept any object, else empty object (matches AI SDK)
23
+ const parameters = hasProperties ? z.object({}).passthrough() : z.object({});
23
24
 
24
25
  return tool({
25
26
  id: mcpTool.name,