@amaster.ai/pi-storage 0.1.0-beta.0 → 0.1.2-beta.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 (55) hide show
  1. package/dist/artifact-stores.d.ts +1 -1
  2. package/dist/artifact-stores.d.ts.map +1 -1
  3. package/dist/artifact-stores.js +2 -2
  4. package/dist/artifact-stores.js.map +1 -1
  5. package/dist/db-migrations.js +24 -24
  6. package/dist/db-migrations.js.map +1 -1
  7. package/dist/db-runtime-storage.d.ts +1 -1
  8. package/dist/db-runtime-storage.d.ts.map +1 -1
  9. package/dist/db-runtime-storage.js +138 -115
  10. package/dist/db-runtime-storage.js.map +1 -1
  11. package/dist/db.d.ts +2 -2
  12. package/dist/db.d.ts.map +1 -1
  13. package/dist/db.js +2 -2
  14. package/dist/db.js.map +1 -1
  15. package/dist/event-stores.d.ts +1 -1
  16. package/dist/event-stores.d.ts.map +1 -1
  17. package/dist/event-stores.js +3 -2
  18. package/dist/event-stores.js.map +1 -1
  19. package/dist/index.d.ts +2 -2
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +1 -1
  22. package/dist/index.js.map +1 -1
  23. package/dist/internal.d.ts +3 -3
  24. package/dist/internal.js +3 -3
  25. package/dist/json-file.d.ts +7 -0
  26. package/dist/json-file.d.ts.map +1 -1
  27. package/dist/json-file.js +6 -6
  28. package/dist/json-file.js.map +1 -1
  29. package/dist/json.d.ts +4 -4
  30. package/dist/json.d.ts.map +1 -1
  31. package/dist/json.js +4 -4
  32. package/dist/json.js.map +1 -1
  33. package/dist/migration-main.js +4 -4
  34. package/dist/redis-locks.js +7 -7
  35. package/dist/runtime-scope.d.ts +1 -1
  36. package/dist/runtime-scope.d.ts.map +1 -1
  37. package/dist/runtime-storage.d.ts +2 -2
  38. package/dist/runtime-storage.d.ts.map +1 -1
  39. package/dist/runtime-storage.js +20 -20
  40. package/dist/runtime-storage.js.map +1 -1
  41. package/dist/scheduled-task-stores.d.ts +1 -1
  42. package/dist/scheduled-task-stores.d.ts.map +1 -1
  43. package/dist/scheduled-task-stores.js +40 -40
  44. package/dist/scheduled-task-stores.js.map +1 -1
  45. package/dist/scheduler.d.ts +1 -1
  46. package/dist/scheduler.js +1 -1
  47. package/dist/session-stores.d.ts +1 -1
  48. package/dist/session-stores.d.ts.map +1 -1
  49. package/dist/session-stores.js +30 -24
  50. package/dist/session-stores.js.map +1 -1
  51. package/dist/subagent-store.d.ts +2 -2
  52. package/dist/subagent-store.d.ts.map +1 -1
  53. package/dist/subagent-store.js +18 -18
  54. package/dist/subagent-store.js.map +1 -1
  55. package/package.json +3 -3
@@ -5,23 +5,23 @@
5
5
  * packages/storage/prisma/schema.prisma. JSON mode remains the local developer
6
6
  * adapter; DB mode uses these stores directly and never falls back silently.
7
7
  */
8
- import { createHash, randomUUID } from "node:crypto";
9
- import { Prisma, PrismaClient } from "@prisma/client";
10
- import { isTerminalSubagentStatus, } from "./subagent-store.js";
11
- import { RedisLockManager } from "./redis-locks.js";
8
+ import { createHash, randomUUID } from 'node:crypto';
9
+ import { Prisma, PrismaClient } from '@prisma/client';
10
+ import { RedisLockManager } from './redis-locks.js';
11
+ import { isTerminalSubagentStatus } from './subagent-store.js';
12
12
  const REQUIRED_DB_TABLES = [
13
- "pi_agent_sessions",
14
- "pi_agent_turns",
15
- "pi_agent_messages",
16
- "pi_agent_turn_queue",
17
- "pi_agent_turn_signals",
18
- "pi_agent_events",
19
- "pi_agent_subagent_runs",
20
- "pi_agent_approvals",
21
- "pi_agent_memory",
22
- "pi_agent_scheduled_tasks",
23
- "pi_agent_task_runs",
24
- "pi_agent_artifacts",
13
+ 'pi_agent_sessions',
14
+ 'pi_agent_turns',
15
+ 'pi_agent_messages',
16
+ 'pi_agent_turn_queue',
17
+ 'pi_agent_turn_signals',
18
+ 'pi_agent_events',
19
+ 'pi_agent_subagent_runs',
20
+ 'pi_agent_approvals',
21
+ 'pi_agent_memory',
22
+ 'pi_agent_scheduled_tasks',
23
+ 'pi_agent_task_runs',
24
+ 'pi_agent_artifacts',
25
25
  ];
26
26
  export function createDbRuntimeStores(databaseUrl, redisUrl) {
27
27
  const context = new DbRuntimeContext(databaseUrl, redisUrl);
@@ -48,8 +48,8 @@ export async function verifyDbRuntimeSchema(databaseUrl) {
48
48
  const found = new Set(rows.map((row) => row.table_name));
49
49
  const missing = REQUIRED_DB_TABLES.filter((table) => !found.has(table));
50
50
  if (missing.length > 0) {
51
- throw new Error(`STORAGE_MODE=db schema is missing required table(s): ${missing.join(", ")}. ` +
52
- "Apply the pi runtime DB migration before starting server.");
51
+ throw new Error(`STORAGE_MODE=db schema is missing required table(s): ${missing.join(', ')}. ` +
52
+ 'Apply the pi runtime DB migration before starting server.');
53
53
  }
54
54
  }
55
55
  finally {
@@ -70,18 +70,18 @@ class DbRuntimeContext {
70
70
  async resolveIdentity(sessionId, tx = this.prisma) {
71
71
  const row = await tx.piAgentSession.findFirst({
72
72
  where: { sessionId: { in: identityLookupSessionIds(sessionId) }, deletedAt: null },
73
- orderBy: { updatedAt: "desc" },
73
+ orderBy: { updatedAt: 'desc' },
74
74
  select: { tenantId: true, userId: true, workspaceId: true },
75
75
  });
76
76
  return {
77
- tenantId: row?.tenantId ?? "default",
78
- userId: row?.userId ?? "system",
77
+ tenantId: row?.tenantId ?? 'default',
78
+ userId: row?.userId ?? 'system',
79
79
  ...(row?.workspaceId ? { workspaceId: row.workspaceId } : {}),
80
80
  };
81
81
  }
82
82
  }
83
83
  function identityLookupSessionIds(sessionId) {
84
- const subagentMarker = ":subagent:";
84
+ const subagentMarker = ':subagent:';
85
85
  const markerIndex = sessionId.indexOf(subagentMarker);
86
86
  if (markerIndex <= 0) {
87
87
  return [sessionId];
@@ -96,15 +96,15 @@ class DbRuntimeSessionStore {
96
96
  async getRuntimeSession(scope, sessionId) {
97
97
  const row = await this.db.prisma.piAgentSession.findFirst({
98
98
  where: { sessionId, deletedAt: null, ...sessionScopeWhere(scope) },
99
- orderBy: { updatedAt: "desc" },
99
+ orderBy: { updatedAt: 'desc' },
100
100
  });
101
101
  return row ? sessionFromPrisma(row) : undefined;
102
102
  }
103
103
  async saveRuntimeSession(session) {
104
104
  const now = new Date().toISOString();
105
- const tenantId = session.tenantId ?? "default";
106
- const userId = session.userId ?? "system";
107
- const rowId = stableRowId("session", tenantId, session.sessionId);
105
+ const tenantId = session.tenantId ?? 'default';
106
+ const userId = session.userId ?? 'system';
107
+ const rowId = stableRowId('session', tenantId, session.sessionId);
108
108
  await this.db.prisma.piAgentSession.upsert({
109
109
  where: { id: rowId },
110
110
  create: {
@@ -119,8 +119,8 @@ class DbRuntimeSessionStore {
119
119
  taskRunId: session.taskRunId ?? null,
120
120
  runId: session.runId ?? null,
121
121
  spawnBatchId: session.spawnBatchId ?? null,
122
- triggerType: "user",
123
- status: "active",
122
+ triggerType: 'user',
123
+ status: 'active',
124
124
  modelProvider: session.model.provider,
125
125
  modelName: session.model.model,
126
126
  thinkingLevel: session.model.thinkingLevel ?? null,
@@ -159,7 +159,7 @@ class DbRuntimeSessionStore {
159
159
  async listRuntimeSessions(scope) {
160
160
  const rows = await this.db.prisma.piAgentSession.findMany({
161
161
  where: { deletedAt: null, ...sessionScopeWhere(scope) },
162
- orderBy: [{ lastMessageAt: "desc" }, { updatedAt: "desc" }],
162
+ orderBy: [{ lastMessageAt: 'desc' }, { updatedAt: 'desc' }],
163
163
  });
164
164
  return rows.map(sessionFromPrisma);
165
165
  }
@@ -181,11 +181,11 @@ class DbTranscriptStore {
181
181
  nextBigIntSeq(tx.piAgentTurn.aggregate({
182
182
  where: { tenantId: identity.tenantId, sessionId: turn.sessionId },
183
183
  _max: { turnSeq: true },
184
- }), "turnSeq"),
184
+ }), 'turnSeq'),
185
185
  nextBigIntSeq(tx.piAgentMessage.aggregate({
186
186
  where: { tenantId: identity.tenantId, sessionId: turn.sessionId },
187
187
  _max: { messageSeq: true },
188
- }), "messageSeq"),
188
+ }), 'messageSeq'),
189
189
  ]);
190
190
  await tx.piAgentTurn.create({
191
191
  data: {
@@ -197,8 +197,8 @@ class DbTranscriptStore {
197
197
  conversationId: turn.conversationId,
198
198
  traceId: turn.traceId ?? null,
199
199
  turnSeq,
200
- sourceType: "user",
201
- status: "completed",
200
+ sourceType: 'user',
201
+ status: 'completed',
202
202
  inputText: turn.userMessage,
203
203
  outputText: turn.assistantMessage,
204
204
  modelJson: jsonInput(turn.model),
@@ -209,8 +209,8 @@ class DbTranscriptStore {
209
209
  });
210
210
  await tx.piAgentMessage.createMany({
211
211
  data: [
212
- messageCreateInput(identity, turn, `${turn.id}:user`, "user", turn.userMessage, messageSeq),
213
- messageCreateInput(identity, turn, `${turn.id}:assistant`, "assistant", turn.assistantMessage, messageSeq + 1n),
212
+ messageCreateInput(identity, turn, `${turn.id}:user`, 'user', turn.userMessage, messageSeq),
213
+ messageCreateInput(identity, turn, `${turn.id}:assistant`, 'assistant', turn.assistantMessage, messageSeq + 1n),
214
214
  ],
215
215
  });
216
216
  await tx.piAgentSession.updateMany({
@@ -233,7 +233,7 @@ class DbTranscriptStore {
233
233
  async listTurns(scope, sessionId) {
234
234
  const rows = await this.db.prisma.piAgentTurn.findMany({
235
235
  where: { ...(sessionId ? { sessionId } : {}), ...sessionScopeWhere(scope) },
236
- orderBy: [{ createdAt: "asc" }, { turnSeq: "asc" }],
236
+ orderBy: [{ createdAt: 'asc' }, { turnSeq: 'asc' }],
237
237
  });
238
238
  return rows.map(turnFromPrisma);
239
239
  }
@@ -241,16 +241,14 @@ class DbTranscriptStore {
241
241
  const [rows, turns] = await Promise.all([
242
242
  this.db.prisma.piAgentMessage.findMany({
243
243
  where: { sessionId, deletedAt: null, ...sessionScopeWhere(scope) },
244
- orderBy: { messageSeq: "asc" },
244
+ orderBy: { messageSeq: 'asc' },
245
245
  }),
246
246
  this.db.prisma.piAgentTurn.findMany({
247
247
  where: { sessionId, ...sessionScopeWhere(scope) },
248
248
  select: { id: true, traceId: true },
249
249
  }),
250
250
  ]);
251
- const traceIdsByTurnId = new Map(turns
252
- .filter((turn) => Boolean(turn.traceId))
253
- .map((turn) => [turn.id, turn.traceId]));
251
+ const traceIdsByTurnId = new Map(turns.filter((turn) => Boolean(turn.traceId)).map((turn) => [turn.id, turn.traceId]));
254
252
  return rows.map((row) => messageFromPrisma(row, traceIdsByTurnId));
255
253
  }
256
254
  async listSessionSummaries(scope, sessions) {
@@ -278,7 +276,10 @@ class DbRuntimeTimelineEventStore {
278
276
  timeoutMs: 5_000,
279
277
  task: async () => {
280
278
  await this.db.prisma.$transaction(async (tx) => {
281
- const existing = await tx.piAgentEvent.findUnique({ where: { id: event.eventId }, select: { id: true } });
279
+ const existing = await tx.piAgentEvent.findUnique({
280
+ where: { id: event.eventId },
281
+ select: { id: true },
282
+ });
282
283
  if (existing) {
283
284
  return;
284
285
  }
@@ -299,7 +300,7 @@ class DbRuntimeTimelineEventStore {
299
300
  eventSource: event.eventSource,
300
301
  eventType: event.eventType,
301
302
  eventName: event.eventName,
302
- severity: "info",
303
+ severity: 'info',
303
304
  payloadJson: jsonInput(event.payload),
304
305
  createdAt: toDate(event.createdAt),
305
306
  },
@@ -312,7 +313,7 @@ class DbRuntimeTimelineEventStore {
312
313
  const limit = positiveLimit(input.limit);
313
314
  const rows = await this.db.prisma.piAgentEvent.findMany({
314
315
  where: timelineWhere(input),
315
- orderBy: [{ createdAt: "desc" }, { id: "desc" }],
316
+ orderBy: [{ createdAt: 'desc' }, { id: 'desc' }],
316
317
  take: limit,
317
318
  });
318
319
  return rows.map(timelineEventFromPrisma).reverse();
@@ -324,7 +325,7 @@ class DbRuntimeTimelineEventStore {
324
325
  ...timelineWhere(input),
325
326
  ...(input.eventType ? { eventType: input.eventType } : {}),
326
327
  },
327
- orderBy: [{ eventSeq: "desc" }, { createdAt: "desc" }],
328
+ orderBy: [{ eventSeq: 'desc' }, { createdAt: 'desc' }],
328
329
  take: positiveLimit(input.limit),
329
330
  });
330
331
  return rows.map(timelineEventFromPrisma).reverse();
@@ -339,7 +340,7 @@ class DbRuntimeEventStore {
339
340
  await this.timeline.append(runtimeEventToTimeline(event));
340
341
  }
341
342
  async list(input = {}) {
342
- const events = await this.timeline.listBySource("runtime", runtimeListInput(input));
343
+ const events = await this.timeline.listBySource('runtime', runtimeListInput(input));
343
344
  return events.map((event) => event.payload);
344
345
  }
345
346
  }
@@ -352,7 +353,7 @@ class DbToolEventStore {
352
353
  await this.timeline.append(toolEventToTimeline(event));
353
354
  }
354
355
  async list(input = {}) {
355
- const events = await this.timeline.listBySource("tool", timelineListInput(input));
356
+ const events = await this.timeline.listBySource('tool', timelineListInput(input));
356
357
  return events.map((event) => event.payload);
357
358
  }
358
359
  }
@@ -365,7 +366,7 @@ class DbLlmGenerationEventStore {
365
366
  await this.timeline.append(llmEventToTimeline(event));
366
367
  }
367
368
  async list(input = {}) {
368
- const events = await this.timeline.listBySource("llm", timelineListInput(input));
369
+ const events = await this.timeline.listBySource('llm', timelineListInput(input));
369
370
  return events.map((event) => event.payload);
370
371
  }
371
372
  }
@@ -391,7 +392,7 @@ class DbMemoryStore {
391
392
  userId: identity.userId,
392
393
  workspaceId: identity.workspaceId ?? null,
393
394
  sessionId: input.sessionId,
394
- scope: "session",
395
+ scope: 'session',
395
396
  text: input.text,
396
397
  tagsJson: jsonInput(input.tags ?? []),
397
398
  metadataJson: jsonInput(input.metadata ?? {}),
@@ -411,7 +412,7 @@ class DbMemoryStore {
411
412
  deletedAt: null,
412
413
  ...(query ? { text: { contains: query } } : {}),
413
414
  },
414
- orderBy: { createdAt: "desc" },
415
+ orderBy: { createdAt: 'desc' },
415
416
  take: positiveLimit(input.limit),
416
417
  });
417
418
  return rows.map(memoryFromPrisma);
@@ -442,7 +443,7 @@ class DbSubagentRunStore {
442
443
  task: input.task,
443
444
  ...(input.agent ? { agent: input.agent } : {}),
444
445
  ...(input.label ? { label: input.label } : {}),
445
- status: "pending",
446
+ status: 'pending',
446
447
  depth: input.depth,
447
448
  model: input.model,
448
449
  toolPolicyProfile: input.toolPolicyProfile,
@@ -450,13 +451,13 @@ class DbSubagentRunStore {
450
451
  createdAt: now,
451
452
  updatedAt: now,
452
453
  events: [
453
- { type: "subagent_spawning", at: now },
454
- { type: "subagent_spawned", at: now },
454
+ { type: 'subagent_spawning', at: now },
455
+ { type: 'subagent_spawned', at: now },
455
456
  ],
456
457
  };
457
458
  await this.db.prisma.piAgentSubagentRun.create({
458
459
  data: {
459
- id: stableRowId("subagent", identity.tenantId, runId),
460
+ id: stableRowId('subagent', identity.tenantId, runId),
460
461
  tenantId: identity.tenantId,
461
462
  userId: identity.userId,
462
463
  workspaceId: identity.workspaceId ?? null,
@@ -483,81 +484,85 @@ class DbSubagentRunStore {
483
484
  async list(scope, parentSessionId) {
484
485
  const rows = await this.db.prisma.piAgentSubagentRun.findMany({
485
486
  where: { ...sessionScopeWhere(scope), ...(parentSessionId ? { parentSessionId } : {}) },
486
- orderBy: { createdAt: "asc" },
487
+ orderBy: { createdAt: 'asc' },
487
488
  });
488
489
  return rows.map(subagentFromPrisma);
489
490
  }
490
491
  async get(scope, runId) {
491
492
  const row = await this.db.prisma.piAgentSubagentRun.findFirst({
492
493
  where: { runId, ...sessionScopeWhere(scope) },
493
- orderBy: { updatedAt: "desc" },
494
+ orderBy: { updatedAt: 'desc' },
494
495
  });
495
496
  return row ? subagentFromPrisma(row) : undefined;
496
497
  }
497
498
  async getDepthForSession(scope, sessionId) {
498
499
  const row = await this.db.prisma.piAgentSubagentRun.findFirst({
499
500
  where: { childSessionId: sessionId, ...sessionScopeWhere(scope) },
500
- orderBy: { updatedAt: "desc" },
501
+ orderBy: { updatedAt: 'desc' },
501
502
  select: { depth: true },
502
503
  });
503
504
  return row?.depth ?? 0;
504
505
  }
505
506
  async countActiveChildren(scope, parentSessionId) {
506
507
  return await this.db.prisma.piAgentSubagentRun.count({
507
- where: { parentSessionId, status: { in: ["pending", "running"] }, ...sessionScopeWhere(scope) },
508
+ where: {
509
+ parentSessionId,
510
+ status: { in: ['pending', 'running'] },
511
+ ...sessionScopeWhere(scope),
512
+ },
508
513
  });
509
514
  }
510
515
  async markRunning(scope, runId) {
511
516
  return await this.patch(scope, runId, (run, now) => ({
512
517
  ...run,
513
- status: "running",
518
+ status: 'running',
514
519
  startedAt: run.startedAt ?? now,
515
520
  updatedAt: now,
516
- events: [...run.events, { type: "subagent_started", at: now }],
521
+ events: [...run.events, { type: 'subagent_started', at: now }],
517
522
  }));
518
523
  }
519
524
  async markCompleted(scope, runId, result) {
520
525
  return await this.patch(scope, runId, (run, now) => {
521
- if (run.status === "cancelled") {
526
+ if (run.status === 'cancelled') {
522
527
  return run;
523
528
  }
524
529
  return {
525
530
  ...omitSubagentError(run),
526
- status: "completed",
531
+ status: 'completed',
527
532
  result,
528
533
  endedAt: now,
529
534
  updatedAt: now,
530
- events: [...run.events, { type: "subagent_ended", at: now, reason: "completed" }],
535
+ events: [...run.events, { type: 'subagent_ended', at: now, reason: 'completed' }],
531
536
  };
532
537
  });
533
538
  }
534
539
  async markFailed(scope, runId, error) {
535
540
  return await this.patch(scope, runId, (run, now) => {
536
- if (run.status === "cancelled") {
541
+ if (run.status === 'cancelled') {
537
542
  return run;
538
543
  }
539
544
  return {
540
545
  ...run,
541
- status: "failed",
546
+ status: 'failed',
542
547
  error,
543
548
  endedAt: now,
544
549
  updatedAt: now,
545
- events: [...run.events, { type: "subagent_ended", at: now, reason: "failed" }],
550
+ events: [...run.events, { type: 'subagent_ended', at: now, reason: 'failed' }],
546
551
  };
547
552
  });
548
553
  }
549
- async markCancelled(scope, runId, reason = "cancelled") {
554
+ async markCancelled(scope, runId, reason = 'cancelled') {
550
555
  return await this.patch(scope, runId, (run, now) => {
551
556
  if (isTerminalSubagentStatus(run.status)) {
552
557
  return run;
553
558
  }
554
559
  return {
555
560
  ...run,
556
- status: "cancelled",
561
+ status: 'cancelled',
557
562
  error: reason,
558
563
  endedAt: now,
559
564
  updatedAt: now,
560
- events: [...run.events, { type: "subagent_ended", at: now, reason: "cancelled" }],
565
+ events: [...run.events, { type: 'subagent_ended', at: now, reason: 'cancelled' }],
561
566
  };
562
567
  });
563
568
  }
@@ -592,7 +597,9 @@ class DbArtifactStore {
592
597
  id: input.id ?? randomUUID(),
593
598
  tenantId: input.tenantId ?? identity.tenantId,
594
599
  userId: input.userId ?? identity.userId,
595
- ...(input.workspaceId ?? identity.workspaceId ? { workspaceId: input.workspaceId ?? identity.workspaceId } : {}),
600
+ ...((input.workspaceId ?? identity.workspaceId)
601
+ ? { workspaceId: input.workspaceId ?? identity.workspaceId }
602
+ : {}),
596
603
  sessionId: input.sessionId,
597
604
  ...(input.turnId ? { turnId: input.turnId } : {}),
598
605
  ...(input.toolCallId ? { toolCallId: input.toolCallId } : {}),
@@ -609,8 +616,8 @@ class DbArtifactStore {
609
616
  await this.db.prisma.piAgentArtifact.create({
610
617
  data: {
611
618
  id: artifact.id,
612
- tenantId: artifact.tenantId ?? "default",
613
- userId: artifact.userId ?? "system",
619
+ tenantId: artifact.tenantId ?? 'default',
620
+ userId: artifact.userId ?? 'system',
614
621
  workspaceId: artifact.workspaceId ?? null,
615
622
  sessionId: artifact.sessionId,
616
623
  turnId: artifact.turnId ?? null,
@@ -643,7 +650,7 @@ class DbArtifactStore {
643
650
  ...(input.turnId ? { turnId: input.turnId } : {}),
644
651
  ...(input.toolCallId ? { toolCallId: input.toolCallId } : {}),
645
652
  },
646
- orderBy: { createdAt: "desc" },
653
+ orderBy: { createdAt: 'desc' },
647
654
  take: positiveLimit(input.limit),
648
655
  });
649
656
  return rows.map(artifactFromPrisma).reverse();
@@ -657,7 +664,7 @@ class DbArtifactStore {
657
664
  }
658
665
  }
659
666
  async function nextBigIntSeq(aggregatePromise, key) {
660
- const aggregate = await aggregatePromise;
667
+ const aggregate = (await aggregatePromise);
661
668
  return (aggregate._max?.[key] ?? 0n) + 1n;
662
669
  }
663
670
  function messageCreateInput(identity, turn, id, role, text, messageSeq) {
@@ -685,8 +692,8 @@ function timelineWhere(input) {
685
692
  clauses.push({
686
693
  OR: [
687
694
  { sessionId: input.sessionId },
688
- { payloadJson: { path: "$.parentSessionId", equals: input.sessionId } },
689
- { payloadJson: { path: "$.childSessionId", equals: input.sessionId } },
695
+ { payloadJson: { path: '$.parentSessionId', equals: input.sessionId } },
696
+ { payloadJson: { path: '$.childSessionId', equals: input.sessionId } },
690
697
  ],
691
698
  });
692
699
  }
@@ -744,7 +751,9 @@ function sessionFromPrisma(row) {
744
751
  provider: row.modelProvider,
745
752
  model: row.modelName,
746
753
  ...(row.thinkingLevel ? { thinkingLevel: row.thinkingLevel } : {}),
747
- ...(typeof metadataModel.authProfileId === "string" ? { authProfileId: metadataModel.authProfileId } : {}),
754
+ ...(typeof metadataModel.authProfileId === 'string'
755
+ ? { authProfileId: metadataModel.authProfileId }
756
+ : {}),
748
757
  ...(metadataModel.reasoning === true ? { reasoning: true } : {}),
749
758
  },
750
759
  ...(row.piSessionRef ? { piSessionFile: row.piSessionRef } : {}),
@@ -769,8 +778,8 @@ function turnFromPrisma(row) {
769
778
  id: row.id,
770
779
  sessionId: row.sessionId,
771
780
  conversationId: row.conversationId,
772
- userMessage: row.inputText ?? "",
773
- assistantMessage: row.outputText ?? "",
781
+ userMessage: row.inputText ?? '',
782
+ assistantMessage: row.outputText ?? '',
774
783
  model: parseModel(row.modelJson),
775
784
  ...(row.traceId ? { traceId: row.traceId } : {}),
776
785
  createdAt: toIso(row.createdAt),
@@ -788,7 +797,7 @@ function messageFromPrisma(row, traceIdsByTurnId = new Map()) {
788
797
  conversationId: row.conversationId,
789
798
  ...(row.turnId ? { turnId: row.turnId } : {}),
790
799
  role: row.role,
791
- text: row.contentText ?? "",
800
+ text: row.contentText ?? '',
792
801
  ...(model ? { model } : {}),
793
802
  ...(traceId ? { traceId } : {}),
794
803
  createdAt: toIso(row.createdAt),
@@ -807,13 +816,23 @@ function timelineEventFromPrisma(row) {
807
816
  sessionId: row.sessionId,
808
817
  ...(row.turnId ? { turnId: row.turnId } : {}),
809
818
  ...(row.traceId ? { traceId: row.traceId } : {}),
810
- ...(typeof payloadObject.conversationId === "string" ? { conversationId: payloadObject.conversationId } : {}),
811
- ...(typeof payloadObject.toolCallId === "string" ? { toolCallId: payloadObject.toolCallId } : {}),
812
- ...(typeof payloadObject.parentSessionId === "string" ? { parentSessionId: payloadObject.parentSessionId } : {}),
813
- ...(typeof payloadObject.childSessionId === "string" ? { childSessionId: payloadObject.childSessionId } : {}),
814
- ...(typeof payloadObject.runId === "string" ? { runId: payloadObject.runId } : {}),
815
- ...(typeof payloadObject.spawnBatchId === "string" ? { spawnBatchId: payloadObject.spawnBatchId } : {}),
816
- ...(typeof payloadObject.taskRunId === "string" ? { taskRunId: payloadObject.taskRunId } : {}),
819
+ ...(typeof payloadObject.conversationId === 'string'
820
+ ? { conversationId: payloadObject.conversationId }
821
+ : {}),
822
+ ...(typeof payloadObject.toolCallId === 'string'
823
+ ? { toolCallId: payloadObject.toolCallId }
824
+ : {}),
825
+ ...(typeof payloadObject.parentSessionId === 'string'
826
+ ? { parentSessionId: payloadObject.parentSessionId }
827
+ : {}),
828
+ ...(typeof payloadObject.childSessionId === 'string'
829
+ ? { childSessionId: payloadObject.childSessionId }
830
+ : {}),
831
+ ...(typeof payloadObject.runId === 'string' ? { runId: payloadObject.runId } : {}),
832
+ ...(typeof payloadObject.spawnBatchId === 'string'
833
+ ? { spawnBatchId: payloadObject.spawnBatchId }
834
+ : {}),
835
+ ...(typeof payloadObject.taskRunId === 'string' ? { taskRunId: payloadObject.taskRunId } : {}),
817
836
  createdAt: toIso(row.createdAt),
818
837
  payload,
819
838
  };
@@ -845,14 +864,14 @@ function subagentFromPrisma(row) {
845
864
  status: row.status,
846
865
  depth: row.depth,
847
866
  model: parseModel(row.modelJson),
848
- toolPolicyProfile: row.toolPolicyProfile ?? "default",
849
- context: "isolated",
867
+ toolPolicyProfile: row.toolPolicyProfile ?? 'default',
868
+ context: 'isolated',
850
869
  createdAt: toIso(row.createdAt),
851
870
  updatedAt: toIso(row.updatedAt),
852
871
  ...(row.startedAt ? { startedAt: toIso(row.startedAt) } : {}),
853
872
  ...(row.endedAt ? { endedAt: toIso(row.endedAt) } : {}),
854
873
  ...(row.resultText ? { result: row.resultText } : {}),
855
- ...(typeof error.message === "string" ? { error: error.message } : {}),
874
+ ...(typeof error.message === 'string' ? { error: error.message } : {}),
856
875
  events: subagentLifecycleEvents(row.status, row.createdAt, row.startedAt, row.endedAt),
857
876
  };
858
877
  }
@@ -869,7 +888,9 @@ function artifactFromPrisma(row) {
869
888
  artifactType: row.artifactType,
870
889
  ...(row.name ? { name: row.name } : {}),
871
890
  ...(row.mimeType ? { mimeType: row.mimeType } : {}),
872
- ...(row.sizeBytes !== null && row.sizeBytes !== undefined ? { sizeBytes: Number(row.sizeBytes) } : {}),
891
+ ...(row.sizeBytes !== null && row.sizeBytes !== undefined
892
+ ? { sizeBytes: Number(row.sizeBytes) }
893
+ : {}),
873
894
  ...(row.sha256 ? { sha256: row.sha256 } : {}),
874
895
  storageUri: row.storageUri,
875
896
  ...(row.previewUri ? { previewUri: row.previewUri } : {}),
@@ -880,24 +901,24 @@ function artifactFromPrisma(row) {
880
901
  function subagentLifecycleEvents(status, createdAt, startedAt, endedAt) {
881
902
  const created = toIso(createdAt);
882
903
  const events = [
883
- { type: "subagent_spawning", at: created },
884
- { type: "subagent_spawned", at: created },
904
+ { type: 'subagent_spawning', at: created },
905
+ { type: 'subagent_spawned', at: created },
885
906
  ];
886
907
  if (startedAt) {
887
- events.push({ type: "subagent_started", at: toIso(startedAt) });
908
+ events.push({ type: 'subagent_started', at: toIso(startedAt) });
888
909
  }
889
910
  if (endedAt) {
890
- const reason = isTerminalSubagentStatus(status) ? status : "completed";
891
- events.push({ type: "subagent_ended", at: toIso(endedAt), reason });
911
+ const reason = isTerminalSubagentStatus(status) ? status : 'completed';
912
+ events.push({ type: 'subagent_ended', at: toIso(endedAt), reason });
892
913
  }
893
914
  return events;
894
915
  }
895
916
  function runtimeEventToTimeline(event) {
896
917
  return {
897
918
  eventId: event.id,
898
- eventName: "runtime_event",
919
+ eventName: 'runtime_event',
899
920
  eventType: event.type,
900
- eventSource: "runtime",
921
+ eventSource: 'runtime',
901
922
  sessionId: event.sessionId,
902
923
  ...(event.conversationId ? { conversationId: event.conversationId } : {}),
903
924
  ...(event.traceId ? { traceId: event.traceId } : {}),
@@ -915,7 +936,7 @@ function toolEventToTimeline(event) {
915
936
  eventId: event.id,
916
937
  eventName: `tool_call_${event.status}`,
917
938
  eventType: event.status,
918
- eventSource: "tool",
939
+ eventSource: 'tool',
919
940
  sessionId: event.sessionId,
920
941
  conversationId: event.conversationId,
921
942
  ...(event.traceId ? { traceId: event.traceId } : {}),
@@ -934,7 +955,7 @@ function llmEventToTimeline(event) {
934
955
  eventId: event.id,
935
956
  eventName: `llm_generation_${event.status}`,
936
957
  eventType: event.status,
937
- eventSource: "llm",
958
+ eventSource: 'llm',
938
959
  sessionId: event.sessionId,
939
960
  conversationId: event.conversationId,
940
961
  ...(event.traceId ? { traceId: event.traceId } : {}),
@@ -965,27 +986,27 @@ function runtimeListInput(input) {
965
986
  function parseModel(value) {
966
987
  const model = parseJsonObject(value);
967
988
  return {
968
- provider: typeof model.provider === "string" ? model.provider : "unknown",
969
- model: typeof model.model === "string" ? model.model : "unknown",
989
+ provider: typeof model.provider === 'string' ? model.provider : 'unknown',
990
+ model: typeof model.model === 'string' ? model.model : 'unknown',
970
991
  ...(isThinkingLevel(model.thinkingLevel) ? { thinkingLevel: model.thinkingLevel } : {}),
971
- ...(typeof model.authProfileId === "string" ? { authProfileId: model.authProfileId } : {}),
992
+ ...(typeof model.authProfileId === 'string' ? { authProfileId: model.authProfileId } : {}),
972
993
  ...(model.reasoning === true ? { reasoning: true } : {}),
973
994
  };
974
995
  }
975
996
  function isThinkingLevel(value) {
976
- return (value === "off" ||
977
- value === "minimal" ||
978
- value === "low" ||
979
- value === "medium" ||
980
- value === "high" ||
981
- value === "xhigh");
997
+ return (value === 'off' ||
998
+ value === 'minimal' ||
999
+ value === 'low' ||
1000
+ value === 'medium' ||
1001
+ value === 'high' ||
1002
+ value === 'xhigh');
982
1003
  }
983
1004
  function parseJsonObject(value) {
984
1005
  const parsed = parseJsonValue(value);
985
1006
  return isJsonObject(parsed) ? parsed : {};
986
1007
  }
987
1008
  function parseJsonValue(value) {
988
- if (typeof value === "string") {
1009
+ if (typeof value === 'string') {
989
1010
  try {
990
1011
  return JSON.parse(value);
991
1012
  }
@@ -997,24 +1018,26 @@ function parseJsonValue(value) {
997
1018
  }
998
1019
  function parseStringArray(value) {
999
1020
  const parsed = parseJsonValue(value);
1000
- return Array.isArray(parsed) ? parsed.filter((entry) => typeof entry === "string") : [];
1021
+ return Array.isArray(parsed)
1022
+ ? parsed.filter((entry) => typeof entry === 'string')
1023
+ : [];
1001
1024
  }
1002
1025
  function parseStringRecord(value) {
1003
1026
  const parsed = parseJsonValue(value);
1004
1027
  if (!isJsonObject(parsed)) {
1005
1028
  return {};
1006
1029
  }
1007
- return Object.fromEntries(Object.entries(parsed).filter((entry) => typeof entry[1] === "string"));
1030
+ return Object.fromEntries(Object.entries(parsed).filter((entry) => typeof entry[1] === 'string'));
1008
1031
  }
1009
1032
  function isJsonObject(value) {
1010
- return typeof value === "object" && value !== null && !Array.isArray(value);
1033
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
1011
1034
  }
1012
1035
  function isJsonValue(value) {
1013
1036
  if (value === null) {
1014
1037
  return true;
1015
1038
  }
1016
1039
  const type = typeof value;
1017
- if (type === "string" || type === "number" || type === "boolean") {
1040
+ if (type === 'string' || type === 'number' || type === 'boolean') {
1018
1041
  return true;
1019
1042
  }
1020
1043
  if (Array.isArray(value)) {
@@ -1035,10 +1058,10 @@ function toIso(value) {
1035
1058
  return value instanceof Date ? value.toISOString() : value;
1036
1059
  }
1037
1060
  function firstLine(value) {
1038
- return value.trim().split(/\r?\n/, 1)[0]?.slice(0, 120) ?? "";
1061
+ return value.trim().split(/\r?\n/, 1)[0]?.slice(0, 120) ?? '';
1039
1062
  }
1040
1063
  function stableRowId(prefix, ...parts) {
1041
- const hash = createHash("sha256").update(parts.join("\0")).digest("hex").slice(0, 48);
1064
+ const hash = createHash('sha256').update(parts.join('\0')).digest('hex').slice(0, 48);
1042
1065
  return `${prefix}_${hash}`.slice(0, 64);
1043
1066
  }
1044
1067
  function positiveLimit(limit) {