agent-worker 0.13.0 → 0.15.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.
package/dist/index.mjs CHANGED
@@ -1,15 +1,459 @@
1
- import { M as SUPPORTED_PROVIDERS, N as createModel, P as createModelAsync, a as createMockBackend, d as CodexBackend, f as ClaudeCodeBackend, i as MockAIBackend, j as FRONTIER_MODELS, n as createBackend, o as SdkBackend, r as listBackends, t as checkBackends, u as CursorBackend } from "./backends-CziIqKRg.mjs";
2
- import { t as AgentWorker } from "./worker-DBJ8136Q.mjs";
3
- import { jsonSchema, tool } from "ai";
1
+ import { F as createModelWithProvider, M as SUPPORTED_PROVIDERS, N as createModel, P as createModelAsync, a as createMockBackend, d as CodexBackend, f as ClaudeCodeBackend, i as MockAIBackend, j as FRONTIER_MODELS, n as createBackend, o as SdkBackend, r as listBackends, t as checkBackends, u as CursorBackend } from "./backends-C7pQwuAx.mjs";
2
+ import { t as createTool } from "./create-tool-gcUuI1FD.mjs";
3
+ import { ToolLoopAgent, stepCountIs } from "ai";
4
4
  import { createBashTool } from "bash-tool";
5
5
  import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
6
6
  import { join, normalize } from "node:path";
7
- import { parse } from "yaml";
8
7
  import { mkdir, readFile, readdir, rm, stat } from "node:fs/promises";
8
+ import { parse } from "yaml";
9
9
  import { z } from "zod";
10
10
  import { tmpdir } from "node:os";
11
11
  import { spawn } from "node:child_process";
12
12
 
13
+ //#region src/agent/worker.ts
14
+ /**
15
+ * AgentWorker - Stateful worker for controlled agent execution
16
+ *
17
+ * Uses ToolLoopAgent internally for multi-step reasoning loops.
18
+ * Maintains conversation state across multiple send() calls,
19
+ * enabling improvisational testing where you observe responses
20
+ * and decide next actions.
21
+ *
22
+ * Tools are AI SDK tool() objects passed as Record<name, tool()>.
23
+ * Approval is configured separately via Record<name, check>.
24
+ */
25
+ var AgentWorker = class {
26
+ id;
27
+ model;
28
+ system;
29
+ createdAt;
30
+ tools;
31
+ approval;
32
+ maxTokens;
33
+ maxSteps;
34
+ messages = [];
35
+ totalUsage = {
36
+ input: 0,
37
+ output: 0,
38
+ total: 0
39
+ };
40
+ pendingApprovals = [];
41
+ backend;
42
+ provider;
43
+ cachedAgent = null;
44
+ toolsChanged = false;
45
+ /**
46
+ * Whether this session supports tool management (SDK backend only)
47
+ */
48
+ get supportsTools() {
49
+ return this.backend === null;
50
+ }
51
+ /**
52
+ * Convert AgentMessage[] to ModelMessage[] for AI SDK
53
+ */
54
+ toModelMessages() {
55
+ return this.messages.filter((m) => m.status !== "responding").map((m) => ({
56
+ role: m.role,
57
+ content: m.content
58
+ }));
59
+ }
60
+ constructor(config, restore) {
61
+ if (restore) {
62
+ this.id = restore.id;
63
+ this.createdAt = restore.createdAt;
64
+ this.messages = [...restore.messages];
65
+ this.totalUsage = { ...restore.totalUsage };
66
+ this.pendingApprovals = [...restore.pendingApprovals ?? []];
67
+ } else {
68
+ this.id = crypto.randomUUID();
69
+ this.createdAt = (/* @__PURE__ */ new Date()).toISOString();
70
+ }
71
+ this.model = config.model;
72
+ this.system = config.system;
73
+ this.tools = config.tools ? { ...config.tools } : {};
74
+ this.approval = config.approval ? { ...config.approval } : {};
75
+ this.maxTokens = config.maxTokens ?? 4096;
76
+ this.maxSteps = config.maxSteps ?? 200;
77
+ this.backend = config.backend ?? null;
78
+ this.provider = config.provider;
79
+ }
80
+ /**
81
+ * Check if a tool needs approval for given arguments
82
+ */
83
+ checkApproval(name, args) {
84
+ const check = this.approval[name];
85
+ if (!check) return false;
86
+ if (typeof check === "function") return check(args);
87
+ return check;
88
+ }
89
+ /**
90
+ * Build tools with approval wrapping for ToolLoopAgent
91
+ */
92
+ buildTools(autoApprove) {
93
+ if (Object.keys(this.tools).length === 0) return void 0;
94
+ if (autoApprove || Object.keys(this.approval).length === 0) return this.tools;
95
+ const wrapped = {};
96
+ for (const [name, t] of Object.entries(this.tools)) {
97
+ if (!this.approval[name]) {
98
+ wrapped[name] = t;
99
+ continue;
100
+ }
101
+ wrapped[name] = {
102
+ ...t,
103
+ execute: async (args, options) => {
104
+ if (this.checkApproval(name, args)) {
105
+ const approval = {
106
+ id: crypto.randomUUID(),
107
+ toolName: name,
108
+ toolCallId: crypto.randomUUID(),
109
+ arguments: args,
110
+ requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
111
+ status: "pending"
112
+ };
113
+ this.pendingApprovals.push(approval);
114
+ return {
115
+ __approvalRequired: true,
116
+ approvalId: approval.id
117
+ };
118
+ }
119
+ return t.execute?.(args, options);
120
+ }
121
+ };
122
+ }
123
+ return wrapped;
124
+ }
125
+ /**
126
+ * Get or create cached agent, rebuild if tools changed
127
+ */
128
+ async getAgent(autoApprove) {
129
+ if (!this.cachedAgent || this.toolsChanged || !autoApprove) {
130
+ this.cachedAgent = new ToolLoopAgent({
131
+ model: this.provider ? await createModelWithProvider(this.model, this.provider) : await createModelAsync(this.model),
132
+ instructions: this.system,
133
+ tools: this.buildTools(autoApprove),
134
+ maxOutputTokens: this.maxTokens,
135
+ stopWhen: stepCountIs(this.maxSteps)
136
+ });
137
+ if (autoApprove) this.toolsChanged = false;
138
+ }
139
+ return this.cachedAgent;
140
+ }
141
+ /**
142
+ * Send a message via CLI backend (non-SDK path)
143
+ */
144
+ async sendViaBackend(content) {
145
+ const startTime = performance.now();
146
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
147
+ this.messages.push({
148
+ role: "user",
149
+ content,
150
+ status: "complete",
151
+ timestamp
152
+ });
153
+ const result = await this.backend.send(content, { system: this.system });
154
+ const latency = Math.round(performance.now() - startTime);
155
+ this.messages.push({
156
+ role: "assistant",
157
+ content: result.content,
158
+ status: "complete",
159
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
160
+ });
161
+ const usage = {
162
+ input: result.usage?.input ?? 0,
163
+ output: result.usage?.output ?? 0,
164
+ total: result.usage?.total ?? 0
165
+ };
166
+ this.totalUsage.input += usage.input;
167
+ this.totalUsage.output += usage.output;
168
+ this.totalUsage.total += usage.total;
169
+ const toolCalls = (result.toolCalls ?? []).map((tc) => ({
170
+ name: tc.name,
171
+ arguments: tc.arguments,
172
+ result: tc.result,
173
+ timing: 0
174
+ }));
175
+ return {
176
+ content: result.content,
177
+ toolCalls,
178
+ pendingApprovals: [],
179
+ usage,
180
+ latency
181
+ };
182
+ }
183
+ /**
184
+ * Send a message and get the agent's response
185
+ */
186
+ async send(content, options = {}) {
187
+ if (this.backend) return this.sendViaBackend(content);
188
+ const { autoApprove = true, onStepFinish } = options;
189
+ const startTime = performance.now();
190
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
191
+ this.messages.push({
192
+ role: "user",
193
+ content,
194
+ status: "complete",
195
+ timestamp
196
+ });
197
+ const agent = await this.getAgent(autoApprove);
198
+ const allToolCalls = [];
199
+ let stepNumber = 0;
200
+ const result = await agent.generate({
201
+ messages: this.toModelMessages(),
202
+ onStepFinish: async ({ usage, toolCalls, toolResults }) => {
203
+ stepNumber++;
204
+ const stepToolCalls = [];
205
+ if (toolCalls) for (const tc of toolCalls) {
206
+ const toolResult = toolResults?.find((tr) => tr.toolCallId === tc.toolCallId);
207
+ const toolCall = {
208
+ name: tc.toolName,
209
+ arguments: tc.input,
210
+ result: toolResult?.output ?? null,
211
+ timing: 0
212
+ };
213
+ stepToolCalls.push(toolCall);
214
+ allToolCalls.push(toolCall);
215
+ }
216
+ if (onStepFinish) {
217
+ const stepUsage = {
218
+ input: usage?.inputTokens ?? 0,
219
+ output: usage?.outputTokens ?? 0,
220
+ total: (usage?.inputTokens ?? 0) + (usage?.outputTokens ?? 0)
221
+ };
222
+ await onStepFinish({
223
+ stepNumber,
224
+ toolCalls: stepToolCalls,
225
+ usage: stepUsage
226
+ });
227
+ }
228
+ }
229
+ });
230
+ const latency = Math.round(performance.now() - startTime);
231
+ this.messages.push({
232
+ role: "assistant",
233
+ content: result.text,
234
+ status: "complete",
235
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
236
+ });
237
+ const usage = {
238
+ input: result.usage?.inputTokens ?? 0,
239
+ output: result.usage?.outputTokens ?? 0,
240
+ total: (result.usage?.inputTokens ?? 0) + (result.usage?.outputTokens ?? 0)
241
+ };
242
+ this.totalUsage.input += usage.input;
243
+ this.totalUsage.output += usage.output;
244
+ this.totalUsage.total += usage.total;
245
+ if (this.maxSteps > 0 && stepNumber >= this.maxSteps && allToolCalls.length > 0) console.warn(`⚠️ Agent reached maxSteps limit (${this.maxSteps}) but wanted to continue. Consider increasing maxSteps or removing the limit.`);
246
+ const currentPending = this.pendingApprovals.filter((p) => p.status === "pending");
247
+ return {
248
+ content: result.text,
249
+ toolCalls: allToolCalls,
250
+ pendingApprovals: currentPending,
251
+ usage,
252
+ latency
253
+ };
254
+ }
255
+ /**
256
+ * Send a message and stream the response
257
+ */
258
+ async *sendStream(content, options = {}) {
259
+ if (this.backend) {
260
+ const response = await this.sendViaBackend(content);
261
+ yield response.content;
262
+ return response;
263
+ }
264
+ const { autoApprove = true, onStepFinish } = options;
265
+ const startTime = performance.now();
266
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
267
+ this.messages.push({
268
+ role: "user",
269
+ content,
270
+ status: "complete",
271
+ timestamp
272
+ });
273
+ const assistantMsg = {
274
+ role: "assistant",
275
+ content: "",
276
+ status: "responding",
277
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
278
+ };
279
+ this.messages.push(assistantMsg);
280
+ const agent = await this.getAgent(autoApprove);
281
+ const allToolCalls = [];
282
+ let stepNumber = 0;
283
+ const result = await agent.stream({
284
+ messages: this.toModelMessages(),
285
+ onStepFinish: async ({ usage, toolCalls, toolResults }) => {
286
+ stepNumber++;
287
+ const stepToolCalls = [];
288
+ if (toolCalls) for (const tc of toolCalls) {
289
+ const toolResult = toolResults?.find((tr) => tr.toolCallId === tc.toolCallId);
290
+ const toolCall = {
291
+ name: tc.toolName,
292
+ arguments: tc.input,
293
+ result: toolResult?.output ?? null,
294
+ timing: 0
295
+ };
296
+ stepToolCalls.push(toolCall);
297
+ allToolCalls.push(toolCall);
298
+ }
299
+ if (onStepFinish) {
300
+ const stepUsage = {
301
+ input: usage?.inputTokens ?? 0,
302
+ output: usage?.outputTokens ?? 0,
303
+ total: (usage?.inputTokens ?? 0) + (usage?.outputTokens ?? 0)
304
+ };
305
+ await onStepFinish({
306
+ stepNumber,
307
+ toolCalls: stepToolCalls,
308
+ usage: stepUsage
309
+ });
310
+ }
311
+ }
312
+ });
313
+ for await (const chunk of result.textStream) {
314
+ assistantMsg.content += chunk;
315
+ yield chunk;
316
+ }
317
+ const latency = Math.round(performance.now() - startTime);
318
+ const text = await result.text;
319
+ assistantMsg.content = text;
320
+ assistantMsg.status = "complete";
321
+ const finalUsage = await result.usage;
322
+ const usage = {
323
+ input: finalUsage?.inputTokens ?? 0,
324
+ output: finalUsage?.outputTokens ?? 0,
325
+ total: (finalUsage?.inputTokens ?? 0) + (finalUsage?.outputTokens ?? 0)
326
+ };
327
+ this.totalUsage.input += usage.input;
328
+ this.totalUsage.output += usage.output;
329
+ this.totalUsage.total += usage.total;
330
+ return {
331
+ content: text,
332
+ toolCalls: allToolCalls,
333
+ pendingApprovals: this.pendingApprovals.filter((p) => p.status === "pending"),
334
+ usage,
335
+ latency
336
+ };
337
+ }
338
+ /**
339
+ * Add an AI SDK tool
340
+ * Only supported for SDK backends (ToolLoopAgent)
341
+ */
342
+ addTool(name, t) {
343
+ if (this.backend) throw new Error("Tool management not supported for CLI backends");
344
+ this.tools[name] = t;
345
+ this.toolsChanged = true;
346
+ this.cachedAgent = null;
347
+ }
348
+ /**
349
+ * Set approval requirement for a tool
350
+ */
351
+ setApproval(name, check) {
352
+ this.approval[name] = check;
353
+ }
354
+ /**
355
+ * Replace a tool's execute function (for testing)
356
+ */
357
+ mockTool(name, mockFn) {
358
+ if (this.backend) throw new Error("Tool management not supported for CLI backends");
359
+ const t = this.tools[name];
360
+ if (!t) throw new Error(`Tool not found: ${name}`);
361
+ this.tools[name] = {
362
+ ...t,
363
+ execute: mockFn
364
+ };
365
+ this.toolsChanged = true;
366
+ this.cachedAgent = null;
367
+ }
368
+ /**
369
+ * Set a static mock response for an existing tool
370
+ */
371
+ setMockResponse(name, response) {
372
+ if (this.backend) throw new Error("Tool management not supported for CLI backends");
373
+ const t = this.tools[name];
374
+ if (!t) throw new Error(`Tool not found: ${name}`);
375
+ this.tools[name] = {
376
+ ...t,
377
+ execute: () => response
378
+ };
379
+ this.toolsChanged = true;
380
+ this.cachedAgent = null;
381
+ }
382
+ /**
383
+ * Get tool info (names, descriptions, approval status)
384
+ */
385
+ getTools() {
386
+ return Object.entries(this.tools).map(([name, t]) => {
387
+ return {
388
+ name,
389
+ description: t?.description,
390
+ needsApproval: !!this.approval[name]
391
+ };
392
+ });
393
+ }
394
+ history() {
395
+ return [...this.messages];
396
+ }
397
+ stats() {
398
+ return {
399
+ messageCount: this.messages.length,
400
+ usage: { ...this.totalUsage }
401
+ };
402
+ }
403
+ export() {
404
+ return {
405
+ sessionId: this.id,
406
+ model: this.model,
407
+ system: this.system,
408
+ messages: [...this.messages],
409
+ totalUsage: { ...this.totalUsage },
410
+ createdAt: this.createdAt
411
+ };
412
+ }
413
+ getState() {
414
+ return {
415
+ id: this.id,
416
+ createdAt: this.createdAt,
417
+ messages: [...this.messages],
418
+ totalUsage: { ...this.totalUsage },
419
+ pendingApprovals: [...this.pendingApprovals]
420
+ };
421
+ }
422
+ getPendingApprovals() {
423
+ return this.pendingApprovals.filter((p) => p.status === "pending");
424
+ }
425
+ async approve(approvalId) {
426
+ const approval = this.pendingApprovals.find((p) => p.id === approvalId);
427
+ if (!approval) throw new Error(`Approval not found: ${approvalId}`);
428
+ if (approval.status !== "pending") throw new Error(`Approval already ${approval.status}: ${approvalId}`);
429
+ const t = this.tools[approval.toolName];
430
+ if (!t) throw new Error(`Tool not found: ${approval.toolName}`);
431
+ let result;
432
+ const tool = t;
433
+ if (typeof tool.execute === "function") result = await tool.execute(approval.arguments);
434
+ else result = { error: "No implementation provided" };
435
+ approval.status = "approved";
436
+ return result;
437
+ }
438
+ deny(approvalId, reason) {
439
+ const approval = this.pendingApprovals.find((p) => p.id === approvalId);
440
+ if (!approval) throw new Error(`Approval not found: ${approvalId}`);
441
+ if (approval.status !== "pending") throw new Error(`Approval already ${approval.status}: ${approvalId}`);
442
+ approval.status = "denied";
443
+ approval.denyReason = reason;
444
+ }
445
+ clear() {
446
+ this.messages = [];
447
+ this.totalUsage = {
448
+ input: 0,
449
+ output: 0,
450
+ total: 0
451
+ };
452
+ this.pendingApprovals = [];
453
+ }
454
+ };
455
+
456
+ //#endregion
13
457
  //#region src/agent/tools/bash.ts
14
458
  /**
15
459
  * Integration with Vercel's bash-tool for file system operations
@@ -36,41 +480,41 @@ async function createBashTools(options = {}) {
36
480
  const { includeReadFile = true, includeWriteFile = true, ...bashOptions } = options;
37
481
  const toolkit = await createBashTool(bashOptions);
38
482
  const tools = {};
39
- tools.bash = tool({
483
+ tools.bash = createTool({
40
484
  description: "Execute bash commands in a sandboxed environment. Returns stdout, stderr, and exit code.",
41
- inputSchema: jsonSchema({
485
+ schema: {
42
486
  type: "object",
43
487
  properties: { command: {
44
488
  type: "string",
45
489
  description: "The bash command to execute"
46
490
  } },
47
491
  required: ["command"]
48
- }),
492
+ },
49
493
  execute: async (args) => {
50
494
  const bashTool = toolkit.tools.bash;
51
495
  if (!bashTool?.execute) throw new Error("Bash tool not available");
52
496
  return bashTool.execute(args, {});
53
497
  }
54
498
  });
55
- if (includeReadFile) tools.readFile = tool({
499
+ if (includeReadFile) tools.readFile = createTool({
56
500
  description: "Read the contents of a file from the sandbox filesystem.",
57
- inputSchema: jsonSchema({
501
+ schema: {
58
502
  type: "object",
59
503
  properties: { path: {
60
504
  type: "string",
61
505
  description: "The path to the file to read"
62
506
  } },
63
507
  required: ["path"]
64
- }),
508
+ },
65
509
  execute: async (args) => {
66
510
  const readFileTool = toolkit.tools.readFile;
67
511
  if (!readFileTool?.execute) throw new Error("ReadFile tool not available");
68
512
  return readFileTool.execute(args, {});
69
513
  }
70
514
  });
71
- if (includeWriteFile) tools.writeFile = tool({
515
+ if (includeWriteFile) tools.writeFile = createTool({
72
516
  description: "Write content to a file in the sandbox filesystem. Creates parent directories if needed.",
73
- inputSchema: jsonSchema({
517
+ schema: {
74
518
  type: "object",
75
519
  properties: {
76
520
  path: {
@@ -83,7 +527,7 @@ async function createBashTools(options = {}) {
83
527
  }
84
528
  },
85
529
  required: ["path", "content"]
86
- }),
530
+ },
87
531
  execute: async (args) => {
88
532
  const writeFileTool = toolkit.tools.writeFile;
89
533
  if (!writeFileTool?.execute) throw new Error("WriteFile tool not available");
@@ -152,9 +596,9 @@ function createFeedbackTool(options = {}) {
152
596
  const { onFeedback, maxEntries = 50 } = options;
153
597
  const entries = [];
154
598
  return {
155
- tool: tool({
599
+ tool: createTool({
156
600
  description: "Report a workflow improvement need. Use when you hit something inconvenient — a missing tool, an awkward step, or a capability you wished you had.",
157
- inputSchema: jsonSchema({
601
+ schema: {
158
602
  type: "object",
159
603
  properties: {
160
604
  target: {
@@ -184,7 +628,7 @@ function createFeedbackTool(options = {}) {
184
628
  "type",
185
629
  "description"
186
630
  ]
187
- }),
631
+ },
188
632
  execute: async (args) => {
189
633
  const validTypes = [
190
634
  "missing",
@@ -220,7 +664,7 @@ const frontmatterSchema = z.object({
220
664
  description: z.string().min(1).max(1024),
221
665
  license: z.string().optional(),
222
666
  compatibility: z.string().max(500).optional(),
223
- metadata: z.record(z.string()).optional(),
667
+ metadata: z.record(z.string(), z.string()).optional(),
224
668
  "allowed-tools": z.string().optional()
225
669
  });
226
670
  var SkillsProvider = class {
@@ -374,9 +818,9 @@ var SkillsProvider = class {
374
818
  * Create a Skills tool as an AI SDK tool() object
375
819
  */
376
820
  function createSkillsTool(provider) {
377
- return tool({
821
+ return createTool({
378
822
  description: "Interact with available agent skills. Use \"list\" to see all skills with their descriptions, \"view\" to read a complete SKILL.md file, \"readFile\" to read files within a skill directory (e.g., references/, scripts/, assets/).",
379
- inputSchema: jsonSchema({
823
+ schema: {
380
824
  type: "object",
381
825
  properties: {
382
826
  operation: {
@@ -398,7 +842,7 @@ function createSkillsTool(provider) {
398
842
  }
399
843
  },
400
844
  required: ["operation"]
401
- }),
845
+ },
402
846
  execute: async (args) => {
403
847
  const operation = args.operation;
404
848
  const skillName = args.skillName;
@@ -664,4 +1108,4 @@ var SkillImporter = class {
664
1108
  };
665
1109
 
666
1110
  //#endregion
667
- export { AgentWorker as AgentSession, AgentWorker, ClaudeCodeBackend, CodexBackend, CursorBackend, FEEDBACK_PROMPT, FRONTIER_MODELS, MockAIBackend, SUPPORTED_PROVIDERS, SdkBackend, SkillImporter, SkillsProvider, buildGitUrl, checkBackends, createBackend, createBashTool, createBashTools, createBashToolsFromDirectory, createBashToolsFromFiles, createFeedbackTool, createMockBackend, createModel, createModelAsync, createSkillsTool, getSpecDisplayName, listBackends, parseImportSpec };
1111
+ export { AgentWorker, ClaudeCodeBackend, CodexBackend, CursorBackend, FEEDBACK_PROMPT, FRONTIER_MODELS, MockAIBackend, SUPPORTED_PROVIDERS, SdkBackend, SkillImporter, SkillsProvider, buildGitUrl, checkBackends, createBackend, createBashTool, createBashTools, createBashToolsFromDirectory, createBashToolsFromFiles, createFeedbackTool, createMockBackend, createModel, createModelAsync, createSkillsTool, getSpecDisplayName, listBackends, parseImportSpec };
@@ -1,16 +1,21 @@
1
- import { o as MemoryStorage, s as ContextProviderImpl } from "./cli/index.mjs";
1
+ import { C as DefaultDocumentStore, D as MemoryStorage, O as ContextProviderImpl, S as DefaultResourceStore, T as DefaultChannelStore, w as DefaultInboxStore, x as DefaultStatusStore } from "./cli/index.mjs";
2
2
 
3
3
  //#region src/workflow/context/memory-provider.ts
4
4
  /**
5
5
  * In-memory ContextProvider for testing.
6
- * All domain logic is inherited from ContextProviderImpl;
6
+ * All domain logic is in the composed stores;
7
7
  * this class adds test helpers for inspection and cleanup.
8
8
  */
9
9
  var MemoryContextProvider = class extends ContextProviderImpl {
10
10
  memoryStorage;
11
11
  constructor(validAgents) {
12
12
  const storage = new MemoryStorage();
13
- super(storage, validAgents);
13
+ const channel = new DefaultChannelStore(storage, validAgents);
14
+ const inbox = new DefaultInboxStore(channel, storage);
15
+ const documents = new DefaultDocumentStore(storage);
16
+ const resources = new DefaultResourceStore(storage);
17
+ const status = new DefaultStatusStore(storage);
18
+ super(channel, inbox, documents, resources, status, validAgents);
14
19
  this.memoryStorage = storage;
15
20
  }
16
21
  /** Get underlying MemoryStorage (for testing) */