@pikku/mongodb 0.12.17 → 0.12.18

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/CHANGELOG.md CHANGED
@@ -1,5 +1,77 @@
1
1
  # @pikku/mongodb
2
2
 
3
+ ## 0.12.18
4
+
5
+ ### Patch Changes
6
+
7
+ - 7406bfe: Rename the agent runtime from `AI*` to `Agent*` (#596)
8
+
9
+ `AI` described the model provider, not the thing being named. Every symbol that
10
+ belongs to the agent runtime now says `Agent`; the symbols that genuinely wrap a
11
+ model provider — `AIEmbeddingService`, `AIProviderOptions`, `AIEmbedParams`,
12
+ `AITranscriptionParams`, `AIGenerateImageParams` and their siblings, and the
13
+ `@pikku/ai-vercel` / `@pikku/ai-deepinfra` / `@pikku/ai-voice` packages — keep
14
+ their names.
15
+
16
+ **Wiring**
17
+ - `pikkuAIAgent` → `pikkuAgent`, `pikkuAIScorer` → `pikkuAgentScorer`,
18
+ `pikkuAIJudge` → `pikkuAgentJudge`
19
+ - `CoreAIAgent` → `CoreAgent`, `AIAgentInput` → `AgentInput`, `AIAgentStep` →
20
+ `AgentStep`, `AIMessage` → `AgentMessage`, and the rest of the agent types
21
+ - `AIAgentRunnerService` → `AgentRunnerService`, `AIStorageService` →
22
+ `AgentStorageService`, `AIRunStateService` → `AgentRunStateService`
23
+
24
+ **Entry points**
25
+
26
+ `@pikku/core/agent` → `@pikku/core/agent`, `@pikku/core/agent-scorer` →
27
+ `@pikku/core/agent-scorer`.
28
+
29
+ **Queues**
30
+
31
+ The scorer queues are now `agent-score-fast` and `agent-score-slow`. Drain the
32
+ old `ai-score-fast` / `ai-score-slow` queues before deploying — jobs still
33
+ sitting on them when the new workers start will never be picked up.
34
+
35
+ **Scaffolds**
36
+
37
+ The agent scaffold pikku wrote for your project — `<scaffold>/agent/agent.gen.ts`
38
+ and its schemas file — imports `@pikku/core/ai-agent`, which no longer exists. A
39
+ scaffold is normally written once and then left alone, so `pikku all` would find
40
+ it present and leave the broken import in place. It now deletes an agent scaffold
41
+ importing either removed entry point and regenerates it in the same run. Anything
42
+ you added to that file goes with it, so move local edits out first.
43
+
44
+ **Database**
45
+
46
+ The agent tables are renamed: `ai_threads`, `ai_message`, `ai_tool_call`,
47
+ `ai_working_memory`, `ai_run` and `ai_run_score` become `agent_threads`,
48
+ `agent_message`, `agent_tool_call`, `agent_working_memory`, `agent_run` and
49
+ `agent_run_score`, along with their indexes and the `ai_working_memory_pk`
50
+ constraint. The same rename applies to the MongoDB collections.
51
+
52
+ `ensurePikkuSchema` creates tables it cannot find, so an existing database will
53
+ get empty `agent_*` tables and leave the old data stranded in `ai_*`. Rename
54
+ them before the first boot on the new version:
55
+
56
+ ```sql
57
+ ALTER TABLE ai_threads RENAME TO agent_threads;
58
+ ALTER TABLE ai_message RENAME TO agent_message;
59
+ ALTER TABLE ai_tool_call RENAME TO agent_tool_call;
60
+ ALTER TABLE ai_working_memory RENAME TO agent_working_memory;
61
+ ALTER TABLE ai_run RENAME TO agent_run;
62
+ ALTER TABLE ai_run_score RENAME TO agent_run_score;
63
+ ```
64
+
65
+ - 6794681: Publish the ecosystem surface as per-area sub-barrels under `@pikku/core/ecosystem/*`, and point generated code, the CLI, the inspector and the runtime adapters at them.
66
+
67
+ 348 names that only generated code, the toolchain or a runtime adapter ever imports now have a second home on `@pikku/core/ecosystem/<area>` — one sub-barrel per area, matching how core already publishes its entrypoints, so no single barrel grows without bound and a consumer only pulls in the area it uses.
68
+
69
+ This step is additive: every name is still exported from the entrypoint it was published from before, so nothing downstream breaks. Removing them from the app-facing barrels is a later change, and needs a release carrying `./ecosystem/*` first.
70
+
71
+ - Updated dependencies [7406bfe]
72
+ - Updated dependencies [6794681]
73
+ - @pikku/core@0.12.84
74
+
3
75
  ## 0.12.17
4
76
 
5
77
  ### Patch Changes
@@ -4,9 +4,9 @@ export { MongoDBEventHubStore } from './mongodb-eventhub-store.js';
4
4
  export { MongoDBWorkflowService } from './mongodb-workflow-service.js';
5
5
  export { MongoDBWorkflowRunService } from './mongodb-workflow-run-service.js';
6
6
  export { MongoDBDeploymentService } from './mongodb-deployment-service.js';
7
- export { MongoDBAIStorageService } from './mongodb-ai-storage-service.js';
7
+ export { MongoDBAgentStorageService } from './mongodb-agent-storage-service.js';
8
8
  export { MongoDBAgentRunService } from './mongodb-agent-run-service.js';
9
9
  export { MongoDBSecretService } from './mongodb-secret-service.js';
10
- export type { WorkflowRunService } from '@pikku/core/workflow';
11
- export type { AgentRunService, AgentRunRow } from '@pikku/core/ai-agent';
10
+ export type { WorkflowRunService } from '@pikku/core/ecosystem/workflow';
11
+ export type { AgentRunService, AgentRunRow, } from '@pikku/core/ecosystem/agent';
12
12
  export { MongoDBSessionStore } from './mongodb-session-store.js';
package/dist/src/index.js CHANGED
@@ -4,7 +4,7 @@ export { MongoDBEventHubStore } from './mongodb-eventhub-store.js';
4
4
  export { MongoDBWorkflowService } from './mongodb-workflow-service.js';
5
5
  export { MongoDBWorkflowRunService } from './mongodb-workflow-run-service.js';
6
6
  export { MongoDBDeploymentService } from './mongodb-deployment-service.js';
7
- export { MongoDBAIStorageService } from './mongodb-ai-storage-service.js';
7
+ export { MongoDBAgentStorageService } from './mongodb-agent-storage-service.js';
8
8
  export { MongoDBAgentRunService } from './mongodb-agent-run-service.js';
9
9
  export { MongoDBSecretService } from './mongodb-secret-service.js';
10
10
  export { MongoDBSessionStore } from './mongodb-session-store.js';
@@ -1,4 +1,5 @@
1
- import type { AIThread, AIMessage, AgentRunRow, AgentRunService } from '@pikku/core/ai-agent';
1
+ import type { AgentThread, AgentMessage } from '@pikku/core/agent';
2
+ import type { AgentRunRow, AgentRunService } from '@pikku/core/ecosystem/agent';
2
3
  import type { Db } from 'mongodb';
3
4
  export declare class MongoDBAgentRunService implements AgentRunService {
4
5
  private threads;
@@ -12,9 +13,9 @@ export declare class MongoDBAgentRunService implements AgentRunService {
12
13
  owners?: string[];
13
14
  limit?: number;
14
15
  offset?: number;
15
- }): Promise<AIThread[]>;
16
- getThread(threadId: string): Promise<AIThread | null>;
17
- getThreadMessages(threadId: string): Promise<AIMessage[]>;
16
+ }): Promise<AgentThread[]>;
17
+ getThread(threadId: string): Promise<AgentThread | null>;
18
+ getThreadMessages(threadId: string): Promise<AgentMessage[]>;
18
19
  getThreadRuns(threadId: string): Promise<AgentRunRow[]>;
19
20
  deleteThread(threadId: string): Promise<boolean>;
20
21
  getDistinctAgentNames(): Promise<string[]>;
@@ -7,10 +7,10 @@ export class MongoDBAgentRunService {
7
7
  toolCalls;
8
8
  runs;
9
9
  constructor(db) {
10
- this.threads = db.collection('ai_threads');
11
- this.messages = db.collection('ai_message');
12
- this.toolCalls = db.collection('ai_tool_call');
13
- this.runs = db.collection('ai_run');
10
+ this.threads = db.collection('agent_threads');
11
+ this.messages = db.collection('agent_message');
12
+ this.toolCalls = db.collection('agent_tool_call');
13
+ this.runs = db.collection('agent_run');
14
14
  }
15
15
  async listThreads(options) {
16
16
  const { agentName, resourceId, owners, limit = 50, offset = 0, } = options ?? {};
@@ -0,0 +1,45 @@
1
+ import type { AgentStorageService, AgentRunStateService, CreateRunInput, SaveScoreInput } from '@pikku/core/services';
2
+ import type { AgentThread, AgentMessage, AgentRunState } from '@pikku/core/agent';
3
+ import type { AgentRunScore } from '@pikku/core/agent-scorer';
4
+ import type { Db } from 'mongodb';
5
+ export declare class MongoDBAgentStorageService implements AgentStorageService, AgentRunStateService {
6
+ private db;
7
+ private initialized;
8
+ private threads;
9
+ private agentMessages;
10
+ private toolCalls;
11
+ private workingMemory;
12
+ private agentRuns;
13
+ private agentRunScores;
14
+ constructor(db: Db);
15
+ init(): Promise<void>;
16
+ createThread(resourceId: string, options?: {
17
+ threadId?: string;
18
+ title?: string;
19
+ metadata?: Record<string, unknown>;
20
+ }): Promise<AgentThread>;
21
+ getThread(threadId: string): Promise<AgentThread>;
22
+ getThreads(resourceId: string): Promise<AgentThread[]>;
23
+ deleteThread(threadId: string): Promise<void>;
24
+ getMessages(threadId: string, options?: {
25
+ lastN?: number;
26
+ cursor?: string;
27
+ }): Promise<AgentMessage[]>;
28
+ saveMessages(threadId: string, messages: AgentMessage[]): Promise<void>;
29
+ getWorkingMemory(id: string, scope: 'resource' | 'thread'): Promise<Record<string, unknown> | null>;
30
+ saveWorkingMemory(id: string, scope: 'resource' | 'thread', data: Record<string, unknown>): Promise<void>;
31
+ createRun(run: CreateRunInput): Promise<string>;
32
+ updateRun(runId: string, updates: Partial<AgentRunState>): Promise<void>;
33
+ getRun(runId: string): Promise<AgentRunState | null>;
34
+ getRunsByThread(threadId: string): Promise<AgentRunState[]>;
35
+ private setApprovals;
36
+ private mapRunRow;
37
+ findRunByToolCallId(toolCallId: string): Promise<{
38
+ run: AgentRunState;
39
+ approval: NonNullable<AgentRunState['pendingApprovals']>[number];
40
+ } | null>;
41
+ resolveApproval(toolCallId: string, status: 'approved' | 'denied'): Promise<boolean>;
42
+ saveScore(score: SaveScoreInput): Promise<void>;
43
+ getScores(runId: string): Promise<AgentRunScore[]>;
44
+ close(): Promise<void>;
45
+ }
@@ -0,0 +1,440 @@
1
+ export class MongoDBAgentStorageService {
2
+ db;
3
+ initialized = false;
4
+ threads;
5
+ agentMessages;
6
+ toolCalls;
7
+ workingMemory;
8
+ agentRuns;
9
+ agentRunScores;
10
+ constructor(db) {
11
+ this.db = db;
12
+ }
13
+ async init() {
14
+ if (this.initialized)
15
+ return;
16
+ this.threads = this.db.collection('agent_threads');
17
+ this.agentMessages = this.db.collection('agent_message');
18
+ this.toolCalls = this.db.collection('agent_tool_call');
19
+ this.workingMemory = this.db.collection('agent_working_memory');
20
+ this.agentRuns = this.db.collection('agent_run');
21
+ this.agentRunScores =
22
+ this.db.collection('agent_run_score');
23
+ await this.threads.createIndex({ resourceId: 1 });
24
+ await this.agentMessages.createIndex({ threadId: 1, createdAt: 1 });
25
+ await this.toolCalls.createIndex({ threadId: 1 });
26
+ await this.toolCalls.createIndex({ messageId: 1 });
27
+ await this.workingMemory.createIndex({ id: 1, scope: 1 }, { unique: true });
28
+ await this.agentRuns.createIndex({ threadId: 1, createdAt: 1 });
29
+ await this.agentRunScores.createIndex({ runId: 1, createdAt: 1 });
30
+ this.initialized = true;
31
+ }
32
+ async createThread(resourceId, options) {
33
+ const id = options?.threadId ?? crypto.randomUUID();
34
+ const now = new Date();
35
+ await this.threads.insertOne({
36
+ _id: id,
37
+ resourceId,
38
+ title: options?.title ?? null,
39
+ metadata: options?.metadata ?? null,
40
+ createdAt: now,
41
+ updatedAt: now,
42
+ });
43
+ return {
44
+ id,
45
+ resourceId,
46
+ title: options?.title,
47
+ metadata: options?.metadata,
48
+ createdAt: now,
49
+ updatedAt: now,
50
+ };
51
+ }
52
+ async getThread(threadId) {
53
+ const row = await this.threads.findOne({ _id: threadId });
54
+ if (!row) {
55
+ throw new Error(`Thread not found: ${threadId}`);
56
+ }
57
+ return {
58
+ id: row._id,
59
+ resourceId: row.resourceId,
60
+ title: row.title ?? undefined,
61
+ metadata: row.metadata ?? undefined,
62
+ createdAt: new Date(row.createdAt),
63
+ updatedAt: new Date(row.updatedAt),
64
+ };
65
+ }
66
+ async getThreads(resourceId) {
67
+ const result = await this.threads
68
+ .find({ resourceId })
69
+ .sort({ updatedAt: -1 })
70
+ .toArray();
71
+ return result.map((row) => ({
72
+ id: row._id,
73
+ resourceId: row.resourceId,
74
+ title: row.title ?? undefined,
75
+ metadata: row.metadata ?? undefined,
76
+ createdAt: new Date(row.createdAt),
77
+ updatedAt: new Date(row.updatedAt),
78
+ }));
79
+ }
80
+ async deleteThread(threadId) {
81
+ await this.toolCalls.deleteMany({ threadId });
82
+ await this.agentMessages.deleteMany({ threadId });
83
+ await this.agentRuns.deleteMany({ threadId });
84
+ await this.threads.deleteOne({ _id: threadId });
85
+ }
86
+ async getMessages(threadId, options) {
87
+ let filter = { threadId };
88
+ if (options?.cursor) {
89
+ const cursorRow = await this.agentMessages.findOne({
90
+ _id: options.cursor,
91
+ });
92
+ if (cursorRow) {
93
+ filter.createdAt = { $lt: cursorRow.createdAt };
94
+ }
95
+ }
96
+ let msgResult;
97
+ if (options?.cursor || options?.lastN) {
98
+ const innerResult = await this.agentMessages
99
+ .find(filter)
100
+ .sort({ createdAt: -1 })
101
+ .limit(options?.lastN ?? 50)
102
+ .toArray();
103
+ innerResult.reverse();
104
+ msgResult = innerResult;
105
+ }
106
+ else {
107
+ msgResult = await this.agentMessages
108
+ .find(filter)
109
+ .sort({ createdAt: 1 })
110
+ .toArray();
111
+ }
112
+ const tcResult = await this.toolCalls
113
+ .find({ threadId })
114
+ .sort({ createdAt: 1 })
115
+ .toArray();
116
+ const tcByMessage = new Map();
117
+ for (const tc of tcResult) {
118
+ const msgId = tc.messageId;
119
+ if (!tcByMessage.has(msgId))
120
+ tcByMessage.set(msgId, []);
121
+ tcByMessage.get(msgId).push(tc);
122
+ }
123
+ const messages = [];
124
+ for (const row of msgResult) {
125
+ let parsedContent = row.content ?? undefined;
126
+ if (typeof row.content === 'string') {
127
+ try {
128
+ const parsed = JSON.parse(row.content);
129
+ if (Array.isArray(parsed)) {
130
+ parsedContent = parsed;
131
+ }
132
+ else if (typeof parsed === 'string') {
133
+ parsedContent = parsed;
134
+ }
135
+ }
136
+ catch {
137
+ // Not JSON, use raw string
138
+ }
139
+ }
140
+ const msg = {
141
+ id: row._id,
142
+ role: row.role,
143
+ content: parsedContent,
144
+ createdAt: new Date(row.createdAt),
145
+ };
146
+ const tcs = tcByMessage.get(msg.id);
147
+ if (tcs?.length) {
148
+ msg.toolCalls = tcs.map((tc) => ({
149
+ id: tc._id,
150
+ name: tc.toolName,
151
+ args: tc.args,
152
+ }));
153
+ const completed = tcs.filter((tc) => tc.result != null);
154
+ if (completed.length) {
155
+ messages.push(msg);
156
+ messages.push({
157
+ id: `tool-results-${msg.id}`,
158
+ role: 'tool',
159
+ toolResults: completed.map((tc) => ({
160
+ id: tc._id,
161
+ name: tc.toolName,
162
+ result: tc.result,
163
+ })),
164
+ createdAt: msg.createdAt,
165
+ });
166
+ continue;
167
+ }
168
+ }
169
+ messages.push(msg);
170
+ }
171
+ return messages;
172
+ }
173
+ async saveMessages(threadId, messages) {
174
+ if (messages.length === 0)
175
+ return;
176
+ const toolMessages = messages.filter((m) => m.role === 'tool');
177
+ const nonToolMessages = messages.filter((m) => m.role !== 'tool');
178
+ if (nonToolMessages.length > 0) {
179
+ await this.agentMessages.insertMany(nonToolMessages.map((msg) => ({
180
+ _id: msg.id,
181
+ threadId,
182
+ role: msg.role,
183
+ content: msg.content != null ? JSON.stringify(msg.content) : null,
184
+ createdAt: msg.createdAt ?? new Date(),
185
+ })));
186
+ }
187
+ const toolCallDocs = nonToolMessages.flatMap((msg) => msg.toolCalls?.map((tc) => ({ ...tc, messageId: msg.id })) ?? []);
188
+ if (toolCallDocs.length > 0) {
189
+ await this.toolCalls.insertMany(toolCallDocs.map((tc) => ({
190
+ _id: tc.id,
191
+ threadId,
192
+ messageId: tc.messageId,
193
+ runId: null,
194
+ toolName: tc.name,
195
+ args: tc.args,
196
+ result: null,
197
+ approvalStatus: null,
198
+ approvalType: null,
199
+ agentRunId: null,
200
+ displayToolName: null,
201
+ displayArgs: null,
202
+ createdAt: new Date(),
203
+ })));
204
+ }
205
+ for (const toolMsg of toolMessages) {
206
+ if (!toolMsg.toolResults)
207
+ continue;
208
+ for (const tr of toolMsg.toolResults) {
209
+ await this.toolCalls.updateOne({ _id: tr.id }, { $set: { result: tr.result } });
210
+ }
211
+ }
212
+ await this.threads.updateOne({ _id: threadId }, { $set: { updatedAt: new Date() } });
213
+ }
214
+ async getWorkingMemory(id, scope) {
215
+ const row = await this.workingMemory.findOne({ id, scope });
216
+ if (!row)
217
+ return null;
218
+ return row.data;
219
+ }
220
+ async saveWorkingMemory(id, scope, data) {
221
+ await this.workingMemory.updateOne({ id, scope }, {
222
+ $set: {
223
+ data,
224
+ updatedAt: new Date(),
225
+ },
226
+ $setOnInsert: {
227
+ id,
228
+ scope,
229
+ },
230
+ }, { upsert: true });
231
+ }
232
+ async createRun(run) {
233
+ const runId = crypto.randomUUID();
234
+ await this.agentRuns.insertOne({
235
+ _id: runId,
236
+ agentName: run.agentName,
237
+ threadId: run.threadId,
238
+ resourceId: run.resourceId,
239
+ status: run.status,
240
+ errorMessage: run.errorMessage ?? null,
241
+ suspendReason: run.suspendReason ?? null,
242
+ missingRpcs: run.missingRpcs ?? null,
243
+ usageInputTokens: run.usage.inputTokens,
244
+ usageOutputTokens: run.usage.outputTokens,
245
+ usageModel: run.usage.model,
246
+ createdAt: run.createdAt,
247
+ updatedAt: run.updatedAt,
248
+ });
249
+ if (run.pendingApprovals?.length) {
250
+ await this.setApprovals(runId, run.pendingApprovals);
251
+ }
252
+ return runId;
253
+ }
254
+ async updateRun(runId, updates) {
255
+ const setValues = { updatedAt: new Date() };
256
+ if (updates.status !== undefined) {
257
+ setValues.status = updates.status;
258
+ }
259
+ if (updates.errorMessage !== undefined) {
260
+ setValues.errorMessage = updates.errorMessage;
261
+ }
262
+ if (updates.suspendReason !== undefined) {
263
+ setValues.suspendReason = updates.suspendReason;
264
+ }
265
+ if (updates.missingRpcs !== undefined) {
266
+ setValues.missingRpcs = updates.missingRpcs;
267
+ }
268
+ if (updates.usage !== undefined) {
269
+ setValues.usageInputTokens = updates.usage.inputTokens;
270
+ setValues.usageOutputTokens = updates.usage.outputTokens;
271
+ setValues.usageModel = updates.usage.model;
272
+ }
273
+ await this.agentRuns.updateOne({ _id: runId }, { $set: setValues });
274
+ if (updates.pendingApprovals !== undefined) {
275
+ await this.toolCalls.updateMany({ runId, approvalStatus: { $ne: null } }, {
276
+ $set: {
277
+ approvalStatus: null,
278
+ runId: null,
279
+ approvalType: null,
280
+ agentRunId: null,
281
+ displayToolName: null,
282
+ displayArgs: null,
283
+ },
284
+ });
285
+ if (updates.pendingApprovals.length) {
286
+ await this.setApprovals(runId, updates.pendingApprovals);
287
+ }
288
+ }
289
+ }
290
+ async getRun(runId) {
291
+ const row = await this.agentRuns.findOne({ _id: runId });
292
+ if (!row)
293
+ return null;
294
+ const approvals = await this.toolCalls
295
+ .find({ runId, approvalStatus: 'pending' })
296
+ .toArray();
297
+ return this.mapRunRow(row, approvals);
298
+ }
299
+ async getRunsByThread(threadId) {
300
+ const result = await this.agentRuns
301
+ .find({ threadId })
302
+ .sort({ createdAt: -1 })
303
+ .toArray();
304
+ const runs = [];
305
+ for (const row of result) {
306
+ const approvals = await this.toolCalls
307
+ .find({ runId: row._id, approvalStatus: 'pending' })
308
+ .toArray();
309
+ runs.push(this.mapRunRow(row, approvals));
310
+ }
311
+ return runs;
312
+ }
313
+ async setApprovals(runId, approvals) {
314
+ for (const a of approvals) {
315
+ if (a.type === 'agent-call') {
316
+ await this.toolCalls.updateOne({ _id: a.toolCallId }, {
317
+ $set: {
318
+ approvalStatus: 'pending',
319
+ runId,
320
+ approvalType: 'agent-call',
321
+ agentRunId: a.agentRunId,
322
+ displayToolName: a.displayToolName,
323
+ displayArgs: a.displayArgs,
324
+ },
325
+ });
326
+ }
327
+ else {
328
+ await this.toolCalls.updateOne({ _id: a.toolCallId }, {
329
+ $set: {
330
+ approvalStatus: 'pending',
331
+ runId,
332
+ approvalType: 'tool-call',
333
+ },
334
+ });
335
+ }
336
+ }
337
+ }
338
+ mapRunRow(row, approvalRows) {
339
+ const pendingApprovals = approvalRows?.length
340
+ ? approvalRows.map((a) => {
341
+ if (a.approvalType === 'agent-call') {
342
+ return {
343
+ type: 'agent-call',
344
+ toolCallId: a._id,
345
+ agentName: a.toolName,
346
+ agentRunId: a.agentRunId,
347
+ displayToolName: a.displayToolName,
348
+ displayArgs: a.displayArgs,
349
+ };
350
+ }
351
+ return {
352
+ type: 'tool-call',
353
+ toolCallId: a._id,
354
+ toolName: a.toolName,
355
+ args: a.args,
356
+ };
357
+ })
358
+ : undefined;
359
+ return {
360
+ runId: row._id,
361
+ agentName: row.agentName,
362
+ threadId: row.threadId,
363
+ resourceId: row.resourceId,
364
+ status: row.status,
365
+ errorMessage: row.errorMessage ?? undefined,
366
+ suspendReason: row.suspendReason,
367
+ missingRpcs: row.missingRpcs ?? undefined,
368
+ pendingApprovals,
369
+ usage: {
370
+ inputTokens: Number(row.usageInputTokens),
371
+ outputTokens: Number(row.usageOutputTokens),
372
+ model: row.usageModel,
373
+ },
374
+ createdAt: new Date(row.createdAt),
375
+ updatedAt: new Date(row.updatedAt),
376
+ };
377
+ }
378
+ async findRunByToolCallId(toolCallId) {
379
+ const tc = await this.toolCalls.findOne({
380
+ _id: toolCallId,
381
+ approvalStatus: 'pending',
382
+ });
383
+ if (!tc || !tc.runId)
384
+ return null;
385
+ const run = await this.getRun(tc.runId);
386
+ if (!run)
387
+ return null;
388
+ let approval;
389
+ if (tc.approvalType === 'agent-call') {
390
+ approval = {
391
+ type: 'agent-call',
392
+ toolCallId: tc._id,
393
+ agentName: tc.toolName,
394
+ agentRunId: tc.agentRunId,
395
+ displayToolName: tc.displayToolName,
396
+ displayArgs: tc.displayArgs,
397
+ };
398
+ }
399
+ else {
400
+ approval = {
401
+ type: 'tool-call',
402
+ toolCallId: tc._id,
403
+ toolName: tc.toolName,
404
+ args: tc.args,
405
+ };
406
+ }
407
+ return { run, approval };
408
+ }
409
+ async resolveApproval(toolCallId, status) {
410
+ // Only the caller that moves the tool call off 'pending' has claimed it.
411
+ const result = await this.toolCalls.updateOne({ _id: toolCallId, approvalStatus: 'pending' }, { $set: { approvalStatus: status } });
412
+ return result.modifiedCount > 0;
413
+ }
414
+ async saveScore(score) {
415
+ await this.agentRunScores.insertOne({
416
+ _id: crypto.randomUUID(),
417
+ runId: score.runId,
418
+ scorerName: score.scorerName,
419
+ score: score.score,
420
+ reason: score.reason ?? null,
421
+ metadata: score.metadata ?? null,
422
+ createdAt: new Date(),
423
+ });
424
+ }
425
+ async getScores(runId) {
426
+ const rows = await this.agentRunScores
427
+ .find({ runId })
428
+ .sort({ createdAt: 1 })
429
+ .toArray();
430
+ return rows.map((row) => ({
431
+ runId: row.runId,
432
+ scorerName: row.scorerName,
433
+ score: row.score,
434
+ reason: row.reason ?? undefined,
435
+ metadata: row.metadata ?? undefined,
436
+ createdAt: row.createdAt,
437
+ }));
438
+ }
439
+ async close() { }
440
+ }
@@ -1,4 +1,4 @@
1
- import type { DeploymentService, DeploymentServiceConfig, DeploymentConfig } from '@pikku/core/services';
1
+ import type { DeploymentService, DeploymentServiceConfig, DeploymentConfig } from '@pikku/core/ecosystem/services';
2
2
  import type { JWTService, SecretService } from '@pikku/core/services';
3
3
  import type { Db } from 'mongodb';
4
4
  export declare class MongoDBDeploymentService implements DeploymentService {
@@ -1,5 +1,5 @@
1
- import { buildRemoteHeaders } from '@pikku/core/remote';
2
- import { getAllFunctionNames } from '@pikku/core/function';
1
+ import { buildRemoteHeaders } from '@pikku/core/ecosystem/remote';
2
+ import { getAllFunctionNames } from '@pikku/core/ecosystem/function';
3
3
  export class MongoDBDeploymentService {
4
4
  db;
5
5
  jwt;
@@ -1,4 +1,4 @@
1
- import { EventHubStore } from '@pikku/core/channel';
1
+ import { EventHubStore } from '@pikku/core/ecosystem/channel';
2
2
  import type { Db } from 'mongodb';
3
3
  export declare class MongoDBEventHubStore extends EventHubStore {
4
4
  private db;
@@ -1,4 +1,4 @@
1
- import { EventHubStore } from '@pikku/core/channel';
1
+ import { EventHubStore } from '@pikku/core/ecosystem/channel';
2
2
  export class MongoDBEventHubStore extends EventHubStore {
3
3
  db;
4
4
  initialized = false;
@@ -1,4 +1,4 @@
1
- import type { WorkflowRun, StepState, WorkflowRunService } from '@pikku/core/workflow';
1
+ import type { WorkflowRun, StepState, WorkflowRunService } from '@pikku/core/ecosystem/workflow';
2
2
  import type { Db } from 'mongodb';
3
3
  export declare class MongoDBWorkflowRunService implements WorkflowRunService {
4
4
  private runs;
@@ -1,5 +1,6 @@
1
- import type { SerializedError } from '@pikku/core';
2
- import { PikkuWorkflowService, type WorkflowPlannedStep, type WorkflowQueueOptions, type WorkflowRun, type WorkflowRunWire, type StepState, type StepStatus, type WorkflowStatus, type WorkflowVersionStatus } from '@pikku/core/workflow';
1
+ import type { SerializedError } from '@pikku/core/ecosystem/types';
2
+ import { PikkuWorkflowService } from '@pikku/core/workflow';
3
+ import type { WorkflowPlannedStep, WorkflowQueueOptions, WorkflowRun, WorkflowRunWire, StepState, StepStatus, WorkflowStatus, WorkflowVersionStatus } from '@pikku/core/ecosystem/workflow';
3
4
  import type { Db } from 'mongodb';
4
5
  export declare class MongoDBWorkflowService extends PikkuWorkflowService {
5
6
  private initialized;
@@ -1,4 +1,4 @@
1
- import { PikkuWorkflowService, } from '@pikku/core/workflow';
1
+ import { PikkuWorkflowService } from '@pikku/core/workflow';
2
2
  import { MongoDBWorkflowRunService } from './mongodb-workflow-run-service.js';
3
3
  export class MongoDBWorkflowService extends PikkuWorkflowService {
4
4
  initialized = false;
@@ -1 +1 @@
1
- {"root":["../src/index.ts","../src/mongodb-agent-run-service.ts","../src/mongodb-ai-storage-service.ts","../src/mongodb-channel-store.ts","../src/mongodb-deployment-service.ts","../src/mongodb-eventhub-store.ts","../src/mongodb-secret-service.ts","../src/mongodb-session-store.ts","../src/mongodb-workflow-run-service.ts","../src/mongodb-workflow-service.ts","../src/pikku-mongodb.ts"],"version":"6.0.3"}
1
+ {"root":["../src/index.ts","../src/mongodb-agent-run-service.ts","../src/mongodb-agent-storage-service.ts","../src/mongodb-channel-store.ts","../src/mongodb-deployment-service.ts","../src/mongodb-eventhub-store.ts","../src/mongodb-secret-service.ts","../src/mongodb-session-store.ts","../src/mongodb-workflow-run-service.ts","../src/mongodb-workflow-service.ts","../src/pikku-mongodb.ts"],"version":"6.0.3"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikku/mongodb",
3
- "version": "0.12.17",
3
+ "version": "0.12.18",
4
4
  "description": "MongoDB services for Pikku — workflow state, agent runs, secrets and channel stores",
5
5
  "author": "yasser.fadl@gmail.com",
6
6
  "license": "MIT",
@@ -18,7 +18,7 @@
18
18
  "prepublishOnly": "yarn build"
19
19
  },
20
20
  "peerDependencies": {
21
- "@pikku/core": "^0.12.82"
21
+ "@pikku/core": "^0.12.84"
22
22
  },
23
23
  "dependencies": {
24
24
  "mongodb": "^6.12.0"
package/src/index.ts CHANGED
@@ -5,10 +5,13 @@ export { MongoDBEventHubStore } from './mongodb-eventhub-store.js'
5
5
  export { MongoDBWorkflowService } from './mongodb-workflow-service.js'
6
6
  export { MongoDBWorkflowRunService } from './mongodb-workflow-run-service.js'
7
7
  export { MongoDBDeploymentService } from './mongodb-deployment-service.js'
8
- export { MongoDBAIStorageService } from './mongodb-ai-storage-service.js'
8
+ export { MongoDBAgentStorageService } from './mongodb-agent-storage-service.js'
9
9
  export { MongoDBAgentRunService } from './mongodb-agent-run-service.js'
10
10
  export { MongoDBSecretService } from './mongodb-secret-service.js'
11
11
 
12
- export type { WorkflowRunService } from '@pikku/core/workflow'
13
- export type { AgentRunService, AgentRunRow } from '@pikku/core/ai-agent'
12
+ export type { WorkflowRunService } from '@pikku/core/ecosystem/workflow'
13
+ export type {
14
+ AgentRunService,
15
+ AgentRunRow,
16
+ } from '@pikku/core/ecosystem/agent'
14
17
  export { MongoDBSessionStore } from './mongodb-session-store.js'
@@ -1,9 +1,8 @@
1
+ import type { AgentThread, AgentMessage } from '@pikku/core/agent'
1
2
  import type {
2
- AIThread,
3
- AIMessage,
4
3
  AgentRunRow,
5
4
  AgentRunService,
6
- } from '@pikku/core/ai-agent'
5
+ } from '@pikku/core/ecosystem/agent'
7
6
  import type { Db, Collection } from 'mongodb'
8
7
 
9
8
  // Owner ids are untrusted input to the regex, so metacharacters must not be
@@ -11,7 +10,7 @@ import type { Db, Collection } from 'mongodb'
11
10
  const escapeRegExp = (value: string) =>
12
11
  value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
13
12
 
14
- interface AIThreadDoc {
13
+ interface AgentThreadDoc {
15
14
  _id: string
16
15
  resourceId: string
17
16
  title: string | null
@@ -20,7 +19,7 @@ interface AIThreadDoc {
20
19
  updatedAt: Date
21
20
  }
22
21
 
23
- interface AIMessageDoc {
22
+ interface AgentMessageDoc {
24
23
  _id: string
25
24
  threadId: string
26
25
  role: string
@@ -28,7 +27,7 @@ interface AIMessageDoc {
28
27
  createdAt: Date
29
28
  }
30
29
 
31
- interface AIToolCallDoc {
30
+ interface AgentToolCallDoc {
32
31
  _id: string
33
32
  threadId: string
34
33
  messageId: string
@@ -44,7 +43,7 @@ interface AIToolCallDoc {
44
43
  createdAt: Date
45
44
  }
46
45
 
47
- interface AIRunDoc {
46
+ interface AgentRunDoc {
48
47
  _id: string
49
48
  agentName: string
50
49
  threadId: string
@@ -61,16 +60,16 @@ interface AIRunDoc {
61
60
  }
62
61
 
63
62
  export class MongoDBAgentRunService implements AgentRunService {
64
- private threads: Collection<AIThreadDoc>
65
- private messages: Collection<AIMessageDoc>
66
- private toolCalls: Collection<AIToolCallDoc>
67
- private runs: Collection<AIRunDoc>
63
+ private threads: Collection<AgentThreadDoc>
64
+ private messages: Collection<AgentMessageDoc>
65
+ private toolCalls: Collection<AgentToolCallDoc>
66
+ private runs: Collection<AgentRunDoc>
68
67
 
69
68
  constructor(db: Db) {
70
- this.threads = db.collection<AIThreadDoc>('ai_threads')
71
- this.messages = db.collection<AIMessageDoc>('ai_message')
72
- this.toolCalls = db.collection<AIToolCallDoc>('ai_tool_call')
73
- this.runs = db.collection<AIRunDoc>('ai_run')
69
+ this.threads = db.collection<AgentThreadDoc>('agent_threads')
70
+ this.messages = db.collection<AgentMessageDoc>('agent_message')
71
+ this.toolCalls = db.collection<AgentToolCallDoc>('agent_tool_call')
72
+ this.runs = db.collection<AgentRunDoc>('agent_run')
74
73
  }
75
74
 
76
75
  async listThreads(options?: {
@@ -79,7 +78,7 @@ export class MongoDBAgentRunService implements AgentRunService {
79
78
  owners?: string[]
80
79
  limit?: number
81
80
  offset?: number
82
- }): Promise<AIThread[]> {
81
+ }): Promise<AgentThread[]> {
83
82
  const {
84
83
  agentName,
85
84
  resourceId,
@@ -122,13 +121,13 @@ export class MongoDBAgentRunService implements AgentRunService {
122
121
  return result.map((row) => this.mapThreadRow(row))
123
122
  }
124
123
 
125
- async getThread(threadId: string): Promise<AIThread | null> {
124
+ async getThread(threadId: string): Promise<AgentThread | null> {
126
125
  const row = await this.threads.findOne({ _id: threadId })
127
126
  if (!row) return null
128
127
  return this.mapThreadRow(row)
129
128
  }
130
129
 
131
- async getThreadMessages(threadId: string): Promise<AIMessage[]> {
130
+ async getThreadMessages(threadId: string): Promise<AgentMessage[]> {
132
131
  const [msgResult, tcResult] = await Promise.all([
133
132
  this.messages.find({ threadId }).sort({ createdAt: 1 }).toArray(),
134
133
  this.toolCalls.find({ threadId }).sort({ createdAt: 1 }).toArray(),
@@ -141,11 +140,11 @@ export class MongoDBAgentRunService implements AgentRunService {
141
140
  tcByMessage.get(msgId)!.push(tc)
142
141
  }
143
142
 
144
- const messages: AIMessage[] = []
143
+ const messages: AgentMessage[] = []
145
144
  for (const row of msgResult) {
146
- const msg: AIMessage = {
145
+ const msg: AgentMessage = {
147
146
  id: row._id,
148
- role: row.role as AIMessage['role'],
147
+ role: row.role as AgentMessage['role'],
149
148
  content: row.content ?? undefined,
150
149
  createdAt: new Date(row.createdAt),
151
150
  }
@@ -203,7 +202,7 @@ export class MongoDBAgentRunService implements AgentRunService {
203
202
  return result.sort()
204
203
  }
205
204
 
206
- private mapThreadRow(row: AIThreadDoc): AIThread {
205
+ private mapThreadRow(row: AgentThreadDoc): AgentThread {
207
206
  return {
208
207
  id: row._id,
209
208
  resourceId: row.resourceId,
@@ -214,7 +213,7 @@ export class MongoDBAgentRunService implements AgentRunService {
214
213
  }
215
214
  }
216
215
 
217
- private mapRunRow(row: AIRunDoc): AgentRunRow {
216
+ private mapRunRow(row: AgentRunDoc): AgentRunRow {
218
217
  return {
219
218
  runId: row._id,
220
219
  agentName: row.agentName,
@@ -1,14 +1,18 @@
1
1
  import type {
2
- AIStorageService,
3
- AIRunStateService,
2
+ AgentStorageService,
3
+ AgentRunStateService,
4
4
  CreateRunInput,
5
5
  SaveScoreInput,
6
6
  } from '@pikku/core/services'
7
- import type { AIThread, AIMessage, AgentRunState } from '@pikku/core/ai-agent'
8
- import type { AIRunScore } from '@pikku/core/ai-scorer'
7
+ import type {
8
+ AgentThread,
9
+ AgentMessage,
10
+ AgentRunState,
11
+ } from '@pikku/core/agent'
12
+ import type { AgentRunScore } from '@pikku/core/agent-scorer'
9
13
  import type { Db, Collection } from 'mongodb'
10
14
 
11
- interface AIThreadDoc {
15
+ interface AgentThreadDoc {
12
16
  _id: string
13
17
  resourceId: string
14
18
  title: string | null
@@ -17,7 +21,7 @@ interface AIThreadDoc {
17
21
  updatedAt: Date
18
22
  }
19
23
 
20
- interface AIMessageDoc {
24
+ interface AgentMessageDoc {
21
25
  _id: string
22
26
  threadId: string
23
27
  role: string
@@ -25,7 +29,7 @@ interface AIMessageDoc {
25
29
  createdAt: Date
26
30
  }
27
31
 
28
- interface AIToolCallDoc {
32
+ interface AgentToolCallDoc {
29
33
  _id: string
30
34
  threadId: string
31
35
  messageId: string
@@ -41,14 +45,14 @@ interface AIToolCallDoc {
41
45
  createdAt: Date
42
46
  }
43
47
 
44
- interface AIWorkingMemoryDoc {
48
+ interface AgentWorkingMemoryDoc {
45
49
  id: string
46
50
  scope: string
47
51
  data: any
48
52
  updatedAt: Date
49
53
  }
50
54
 
51
- interface AIRunScoreDoc {
55
+ interface AgentRunScoreDoc {
52
56
  _id: string
53
57
  runId: string
54
58
  scorerName: string
@@ -58,7 +62,7 @@ interface AIRunScoreDoc {
58
62
  createdAt: Date
59
63
  }
60
64
 
61
- interface AIRunDoc {
65
+ interface AgentRunDoc {
62
66
  _id: string
63
67
  agentName: string
64
68
  threadId: string
@@ -74,42 +78,44 @@ interface AIRunDoc {
74
78
  updatedAt: Date
75
79
  }
76
80
 
77
- export class MongoDBAIStorageService
78
- implements AIStorageService, AIRunStateService
81
+ export class MongoDBAgentStorageService
82
+ implements AgentStorageService, AgentRunStateService
79
83
  {
80
84
  private initialized = false
81
- private threads!: Collection<AIThreadDoc>
82
- private aiMessages!: Collection<AIMessageDoc>
83
- private toolCalls!: Collection<AIToolCallDoc>
84
- private workingMemory!: Collection<AIWorkingMemoryDoc>
85
- private aiRuns!: Collection<AIRunDoc>
86
- private aiRunScores!: Collection<AIRunScoreDoc>
85
+ private threads!: Collection<AgentThreadDoc>
86
+ private agentMessages!: Collection<AgentMessageDoc>
87
+ private toolCalls!: Collection<AgentToolCallDoc>
88
+ private workingMemory!: Collection<AgentWorkingMemoryDoc>
89
+ private agentRuns!: Collection<AgentRunDoc>
90
+ private agentRunScores!: Collection<AgentRunScoreDoc>
87
91
 
88
92
  constructor(private db: Db) {}
89
93
 
90
94
  public async init(): Promise<void> {
91
95
  if (this.initialized) return
92
96
 
93
- this.threads = this.db.collection<AIThreadDoc>('ai_threads')
94
- this.aiMessages = this.db.collection<AIMessageDoc>('ai_message')
95
- this.toolCalls = this.db.collection<AIToolCallDoc>('ai_tool_call')
96
- this.workingMemory =
97
- this.db.collection<AIWorkingMemoryDoc>('ai_working_memory')
98
- this.aiRuns = this.db.collection<AIRunDoc>('ai_run')
99
- this.aiRunScores = this.db.collection<AIRunScoreDoc>('ai_run_score')
97
+ this.threads = this.db.collection<AgentThreadDoc>('agent_threads')
98
+ this.agentMessages = this.db.collection<AgentMessageDoc>('agent_message')
99
+ this.toolCalls = this.db.collection<AgentToolCallDoc>('agent_tool_call')
100
+ this.workingMemory = this.db.collection<AgentWorkingMemoryDoc>(
101
+ 'agent_working_memory'
102
+ )
103
+ this.agentRuns = this.db.collection<AgentRunDoc>('agent_run')
104
+ this.agentRunScores =
105
+ this.db.collection<AgentRunScoreDoc>('agent_run_score')
100
106
 
101
107
  await this.threads.createIndex({ resourceId: 1 })
102
108
 
103
- await this.aiMessages.createIndex({ threadId: 1, createdAt: 1 })
109
+ await this.agentMessages.createIndex({ threadId: 1, createdAt: 1 })
104
110
 
105
111
  await this.toolCalls.createIndex({ threadId: 1 })
106
112
  await this.toolCalls.createIndex({ messageId: 1 })
107
113
 
108
114
  await this.workingMemory.createIndex({ id: 1, scope: 1 }, { unique: true })
109
115
 
110
- await this.aiRuns.createIndex({ threadId: 1, createdAt: 1 })
116
+ await this.agentRuns.createIndex({ threadId: 1, createdAt: 1 })
111
117
 
112
- await this.aiRunScores.createIndex({ runId: 1, createdAt: 1 })
118
+ await this.agentRunScores.createIndex({ runId: 1, createdAt: 1 })
113
119
 
114
120
  this.initialized = true
115
121
  }
@@ -121,7 +127,7 @@ export class MongoDBAIStorageService
121
127
  title?: string
122
128
  metadata?: Record<string, unknown>
123
129
  }
124
- ): Promise<AIThread> {
130
+ ): Promise<AgentThread> {
125
131
  const id = options?.threadId ?? crypto.randomUUID()
126
132
  const now = new Date()
127
133
 
@@ -144,7 +150,7 @@ export class MongoDBAIStorageService
144
150
  }
145
151
  }
146
152
 
147
- async getThread(threadId: string): Promise<AIThread> {
153
+ async getThread(threadId: string): Promise<AgentThread> {
148
154
  const row = await this.threads.findOne({ _id: threadId })
149
155
 
150
156
  if (!row) {
@@ -161,7 +167,7 @@ export class MongoDBAIStorageService
161
167
  }
162
168
  }
163
169
 
164
- async getThreads(resourceId: string): Promise<AIThread[]> {
170
+ async getThreads(resourceId: string): Promise<AgentThread[]> {
165
171
  const result = await this.threads
166
172
  .find({ resourceId })
167
173
  .sort({ updatedAt: -1 })
@@ -179,19 +185,21 @@ export class MongoDBAIStorageService
179
185
 
180
186
  async deleteThread(threadId: string): Promise<void> {
181
187
  await this.toolCalls.deleteMany({ threadId })
182
- await this.aiMessages.deleteMany({ threadId })
183
- await this.aiRuns.deleteMany({ threadId })
188
+ await this.agentMessages.deleteMany({ threadId })
189
+ await this.agentRuns.deleteMany({ threadId })
184
190
  await this.threads.deleteOne({ _id: threadId })
185
191
  }
186
192
 
187
193
  async getMessages(
188
194
  threadId: string,
189
195
  options?: { lastN?: number; cursor?: string }
190
- ): Promise<AIMessage[]> {
196
+ ): Promise<AgentMessage[]> {
191
197
  let filter: Record<string, any> = { threadId }
192
198
 
193
199
  if (options?.cursor) {
194
- const cursorRow = await this.aiMessages.findOne({ _id: options.cursor })
200
+ const cursorRow = await this.agentMessages.findOne({
201
+ _id: options.cursor,
202
+ })
195
203
  if (cursorRow) {
196
204
  filter.createdAt = { $lt: cursorRow.createdAt }
197
205
  }
@@ -199,7 +207,7 @@ export class MongoDBAIStorageService
199
207
 
200
208
  let msgResult
201
209
  if (options?.cursor || options?.lastN) {
202
- const innerResult = await this.aiMessages
210
+ const innerResult = await this.agentMessages
203
211
  .find(filter)
204
212
  .sort({ createdAt: -1 })
205
213
  .limit(options?.lastN ?? 50)
@@ -207,7 +215,7 @@ export class MongoDBAIStorageService
207
215
  innerResult.reverse()
208
216
  msgResult = innerResult
209
217
  } else {
210
- msgResult = await this.aiMessages
218
+ msgResult = await this.agentMessages
211
219
  .find(filter)
212
220
  .sort({ createdAt: 1 })
213
221
  .toArray()
@@ -225,9 +233,9 @@ export class MongoDBAIStorageService
225
233
  tcByMessage.get(msgId)!.push(tc)
226
234
  }
227
235
 
228
- const messages: AIMessage[] = []
236
+ const messages: AgentMessage[] = []
229
237
  for (const row of msgResult) {
230
- let parsedContent: AIMessage['content'] = row.content ?? undefined
238
+ let parsedContent: AgentMessage['content'] = row.content ?? undefined
231
239
  if (typeof row.content === 'string') {
232
240
  try {
233
241
  const parsed = JSON.parse(row.content)
@@ -241,9 +249,9 @@ export class MongoDBAIStorageService
241
249
  }
242
250
  }
243
251
 
244
- const msg: AIMessage = {
252
+ const msg: AgentMessage = {
245
253
  id: row._id,
246
- role: row.role as AIMessage['role'],
254
+ role: row.role as AgentMessage['role'],
247
255
  content: parsedContent,
248
256
  createdAt: new Date(row.createdAt),
249
257
  }
@@ -279,14 +287,17 @@ export class MongoDBAIStorageService
279
287
  return messages
280
288
  }
281
289
 
282
- async saveMessages(threadId: string, messages: AIMessage[]): Promise<void> {
290
+ async saveMessages(
291
+ threadId: string,
292
+ messages: AgentMessage[]
293
+ ): Promise<void> {
283
294
  if (messages.length === 0) return
284
295
 
285
296
  const toolMessages = messages.filter((m) => m.role === 'tool')
286
297
  const nonToolMessages = messages.filter((m) => m.role !== 'tool')
287
298
 
288
299
  if (nonToolMessages.length > 0) {
289
- await this.aiMessages.insertMany(
300
+ await this.agentMessages.insertMany(
290
301
  nonToolMessages.map((msg) => ({
291
302
  _id: msg.id,
292
303
  threadId,
@@ -369,7 +380,7 @@ export class MongoDBAIStorageService
369
380
  async createRun(run: CreateRunInput): Promise<string> {
370
381
  const runId = crypto.randomUUID()
371
382
 
372
- await this.aiRuns.insertOne({
383
+ await this.agentRuns.insertOne({
373
384
  _id: runId,
374
385
  agentName: run.agentName,
375
386
  threadId: run.threadId,
@@ -416,7 +427,7 @@ export class MongoDBAIStorageService
416
427
  setValues.usageModel = updates.usage.model
417
428
  }
418
429
 
419
- await this.aiRuns.updateOne({ _id: runId }, { $set: setValues })
430
+ await this.agentRuns.updateOne({ _id: runId }, { $set: setValues })
420
431
 
421
432
  if (updates.pendingApprovals !== undefined) {
422
433
  await this.toolCalls.updateMany(
@@ -440,7 +451,7 @@ export class MongoDBAIStorageService
440
451
  }
441
452
 
442
453
  async getRun(runId: string): Promise<AgentRunState | null> {
443
- const row = await this.aiRuns.findOne({ _id: runId })
454
+ const row = await this.agentRuns.findOne({ _id: runId })
444
455
  if (!row) return null
445
456
 
446
457
  const approvals = await this.toolCalls
@@ -451,7 +462,7 @@ export class MongoDBAIStorageService
451
462
  }
452
463
 
453
464
  async getRunsByThread(threadId: string): Promise<AgentRunState[]> {
454
- const result = await this.aiRuns
465
+ const result = await this.agentRuns
455
466
  .find({ threadId })
456
467
  .sort({ createdAt: -1 })
457
468
  .toArray()
@@ -591,7 +602,7 @@ export class MongoDBAIStorageService
591
602
  }
592
603
 
593
604
  async saveScore(score: SaveScoreInput): Promise<void> {
594
- await this.aiRunScores.insertOne({
605
+ await this.agentRunScores.insertOne({
595
606
  _id: crypto.randomUUID(),
596
607
  runId: score.runId,
597
608
  scorerName: score.scorerName,
@@ -602,8 +613,8 @@ export class MongoDBAIStorageService
602
613
  })
603
614
  }
604
615
 
605
- async getScores(runId: string): Promise<AIRunScore[]> {
606
- const rows = await this.aiRunScores
616
+ async getScores(runId: string): Promise<AgentRunScore[]> {
617
+ const rows = await this.agentRunScores
607
618
  .find({ runId })
608
619
  .sort({ createdAt: 1 })
609
620
  .toArray()
@@ -1,11 +1,11 @@
1
- import { buildRemoteHeaders } from '@pikku/core/remote'
1
+ import { buildRemoteHeaders } from '@pikku/core/ecosystem/remote'
2
2
  import type {
3
3
  DeploymentService,
4
4
  DeploymentServiceConfig,
5
5
  DeploymentConfig,
6
- } from '@pikku/core/services'
6
+ } from '@pikku/core/ecosystem/services'
7
7
  import type { JWTService, SecretService } from '@pikku/core/services'
8
- import { getAllFunctionNames } from '@pikku/core/function'
8
+ import { getAllFunctionNames } from '@pikku/core/ecosystem/function'
9
9
  import type { Db, Collection } from 'mongodb'
10
10
 
11
11
  interface DeploymentDoc {
@@ -1,4 +1,4 @@
1
- import { EventHubStore } from '@pikku/core/channel'
1
+ import { EventHubStore } from '@pikku/core/ecosystem/channel'
2
2
  import type { Db, Collection } from 'mongodb'
3
3
 
4
4
  interface ChannelSubscriptionDoc {
@@ -2,14 +2,14 @@ import { describe, test, before, after } from 'node:test'
2
2
  import assert from 'node:assert/strict'
3
3
  import { MongoClient, type Db } from 'mongodb'
4
4
  import { MongoMemoryServer } from 'mongodb-memory-server'
5
- import { defineServiceTests } from '@pikku/core/testing'
5
+ import { defineServiceTests } from '@pikku/core/ecosystem/testing'
6
6
 
7
7
  import { MongoDBChannelStore } from './mongodb-channel-store.js'
8
8
  import { MongoDBEventHubStore } from './mongodb-eventhub-store.js'
9
9
  import { MongoDBWorkflowService } from './mongodb-workflow-service.js'
10
10
  import { MongoDBWorkflowRunService } from './mongodb-workflow-run-service.js'
11
11
  import { MongoDBDeploymentService } from './mongodb-deployment-service.js'
12
- import { MongoDBAIStorageService } from './mongodb-ai-storage-service.js'
12
+ import { MongoDBAgentStorageService } from './mongodb-agent-storage-service.js'
13
13
  import { MongoDBAgentRunService } from './mongodb-agent-run-service.js'
14
14
  import { MongoDBSecretService } from './mongodb-secret-service.js'
15
15
  import { MongoDBSessionStore } from './mongodb-session-store.js'
@@ -42,8 +42,8 @@ function registerTests(name: string, getDb: () => Db) {
42
42
  await s.init()
43
43
  return s
44
44
  },
45
- aiStorageService: async () => {
46
- const s = new MongoDBAIStorageService(getDb())
45
+ agentStorageService: async () => {
46
+ const s = new MongoDBAgentStorageService(getDb())
47
47
  await s.init()
48
48
  return s
49
49
  },
@@ -4,7 +4,7 @@ import type {
4
4
  StepState,
5
5
  WorkflowStatus,
6
6
  WorkflowRunService,
7
- } from '@pikku/core/workflow'
7
+ } from '@pikku/core/ecosystem/workflow'
8
8
  import type { Db, Collection } from 'mongodb'
9
9
 
10
10
  interface WorkflowRunDoc {
@@ -1,15 +1,6 @@
1
- import type { SerializedError } from '@pikku/core'
2
- import {
3
- PikkuWorkflowService,
4
- type WorkflowPlannedStep,
5
- type WorkflowQueueOptions,
6
- type WorkflowRun,
7
- type WorkflowRunWire,
8
- type StepState,
9
- type StepStatus,
10
- type WorkflowStatus,
11
- type WorkflowVersionStatus,
12
- } from '@pikku/core/workflow'
1
+ import type { SerializedError } from '@pikku/core/ecosystem/types'
2
+ import { PikkuWorkflowService } from '@pikku/core/workflow'
3
+ import type { WorkflowPlannedStep, WorkflowQueueOptions, WorkflowRun, WorkflowRunWire, StepState, StepStatus, WorkflowStatus, WorkflowVersionStatus } from '@pikku/core/ecosystem/workflow'
13
4
  import type { Db, Collection } from 'mongodb'
14
5
  import { MongoDBWorkflowRunService } from './mongodb-workflow-run-service.js'
15
6