@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.
- package/dist/artifact-stores.d.ts +1 -1
- package/dist/artifact-stores.d.ts.map +1 -1
- package/dist/artifact-stores.js +2 -2
- package/dist/artifact-stores.js.map +1 -1
- package/dist/db-migrations.js +24 -24
- package/dist/db-migrations.js.map +1 -1
- package/dist/db-runtime-storage.d.ts +1 -1
- package/dist/db-runtime-storage.d.ts.map +1 -1
- package/dist/db-runtime-storage.js +138 -115
- package/dist/db-runtime-storage.js.map +1 -1
- package/dist/db.d.ts +2 -2
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +2 -2
- package/dist/db.js.map +1 -1
- package/dist/event-stores.d.ts +1 -1
- package/dist/event-stores.d.ts.map +1 -1
- package/dist/event-stores.js +3 -2
- package/dist/event-stores.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +3 -3
- package/dist/internal.js +3 -3
- package/dist/json-file.d.ts +7 -0
- package/dist/json-file.d.ts.map +1 -1
- package/dist/json-file.js +6 -6
- package/dist/json-file.js.map +1 -1
- package/dist/json.d.ts +4 -4
- package/dist/json.d.ts.map +1 -1
- package/dist/json.js +4 -4
- package/dist/json.js.map +1 -1
- package/dist/migration-main.js +4 -4
- package/dist/redis-locks.js +7 -7
- package/dist/runtime-scope.d.ts +1 -1
- package/dist/runtime-scope.d.ts.map +1 -1
- package/dist/runtime-storage.d.ts +2 -2
- package/dist/runtime-storage.d.ts.map +1 -1
- package/dist/runtime-storage.js +20 -20
- package/dist/runtime-storage.js.map +1 -1
- package/dist/scheduled-task-stores.d.ts +1 -1
- package/dist/scheduled-task-stores.d.ts.map +1 -1
- package/dist/scheduled-task-stores.js +40 -40
- package/dist/scheduled-task-stores.js.map +1 -1
- package/dist/scheduler.d.ts +1 -1
- package/dist/scheduler.js +1 -1
- package/dist/session-stores.d.ts +1 -1
- package/dist/session-stores.d.ts.map +1 -1
- package/dist/session-stores.js +30 -24
- package/dist/session-stores.js.map +1 -1
- package/dist/subagent-store.d.ts +2 -2
- package/dist/subagent-store.d.ts.map +1 -1
- package/dist/subagent-store.js +18 -18
- package/dist/subagent-store.js.map +1 -1
- 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
|
|
9
|
-
import { Prisma, PrismaClient } from
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
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:
|
|
73
|
+
orderBy: { updatedAt: 'desc' },
|
|
74
74
|
select: { tenantId: true, userId: true, workspaceId: true },
|
|
75
75
|
});
|
|
76
76
|
return {
|
|
77
|
-
tenantId: row?.tenantId ??
|
|
78
|
-
userId: row?.userId ??
|
|
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 =
|
|
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:
|
|
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 ??
|
|
106
|
-
const userId = session.userId ??
|
|
107
|
-
const rowId = stableRowId(
|
|
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:
|
|
123
|
-
status:
|
|
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:
|
|
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
|
-
}),
|
|
184
|
+
}), 'turnSeq'),
|
|
185
185
|
nextBigIntSeq(tx.piAgentMessage.aggregate({
|
|
186
186
|
where: { tenantId: identity.tenantId, sessionId: turn.sessionId },
|
|
187
187
|
_max: { messageSeq: true },
|
|
188
|
-
}),
|
|
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:
|
|
201
|
-
status:
|
|
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`,
|
|
213
|
-
messageCreateInput(identity, turn, `${turn.id}:assistant`,
|
|
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:
|
|
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:
|
|
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({
|
|
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:
|
|
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:
|
|
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:
|
|
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(
|
|
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(
|
|
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(
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
454
|
-
{ type:
|
|
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(
|
|
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:
|
|
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:
|
|
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:
|
|
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: {
|
|
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:
|
|
518
|
+
status: 'running',
|
|
514
519
|
startedAt: run.startedAt ?? now,
|
|
515
520
|
updatedAt: now,
|
|
516
|
-
events: [...run.events, { type:
|
|
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 ===
|
|
526
|
+
if (run.status === 'cancelled') {
|
|
522
527
|
return run;
|
|
523
528
|
}
|
|
524
529
|
return {
|
|
525
530
|
...omitSubagentError(run),
|
|
526
|
-
status:
|
|
531
|
+
status: 'completed',
|
|
527
532
|
result,
|
|
528
533
|
endedAt: now,
|
|
529
534
|
updatedAt: now,
|
|
530
|
-
events: [...run.events, { type:
|
|
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 ===
|
|
541
|
+
if (run.status === 'cancelled') {
|
|
537
542
|
return run;
|
|
538
543
|
}
|
|
539
544
|
return {
|
|
540
545
|
...run,
|
|
541
|
-
status:
|
|
546
|
+
status: 'failed',
|
|
542
547
|
error,
|
|
543
548
|
endedAt: now,
|
|
544
549
|
updatedAt: now,
|
|
545
|
-
events: [...run.events, { type:
|
|
550
|
+
events: [...run.events, { type: 'subagent_ended', at: now, reason: 'failed' }],
|
|
546
551
|
};
|
|
547
552
|
});
|
|
548
553
|
}
|
|
549
|
-
async markCancelled(scope, runId, reason =
|
|
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:
|
|
561
|
+
status: 'cancelled',
|
|
557
562
|
error: reason,
|
|
558
563
|
endedAt: now,
|
|
559
564
|
updatedAt: now,
|
|
560
|
-
events: [...run.events, { type:
|
|
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
|
|
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 ??
|
|
613
|
-
userId: artifact.userId ??
|
|
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:
|
|
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:
|
|
689
|
-
{ payloadJson: { path:
|
|
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 ===
|
|
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 ===
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
...(typeof payloadObject.
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
...(typeof payloadObject.
|
|
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 ??
|
|
849
|
-
context:
|
|
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 ===
|
|
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
|
|
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:
|
|
884
|
-
{ type:
|
|
904
|
+
{ type: 'subagent_spawning', at: created },
|
|
905
|
+
{ type: 'subagent_spawned', at: created },
|
|
885
906
|
];
|
|
886
907
|
if (startedAt) {
|
|
887
|
-
events.push({ type:
|
|
908
|
+
events.push({ type: 'subagent_started', at: toIso(startedAt) });
|
|
888
909
|
}
|
|
889
910
|
if (endedAt) {
|
|
890
|
-
const reason = isTerminalSubagentStatus(status) ? status :
|
|
891
|
-
events.push({ type:
|
|
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:
|
|
919
|
+
eventName: 'runtime_event',
|
|
899
920
|
eventType: event.type,
|
|
900
|
-
eventSource:
|
|
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:
|
|
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:
|
|
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 ===
|
|
969
|
-
model: typeof model.model ===
|
|
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 ===
|
|
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 ===
|
|
977
|
-
value ===
|
|
978
|
-
value ===
|
|
979
|
-
value ===
|
|
980
|
-
value ===
|
|
981
|
-
value ===
|
|
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 ===
|
|
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)
|
|
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] ===
|
|
1030
|
+
return Object.fromEntries(Object.entries(parsed).filter((entry) => typeof entry[1] === 'string'));
|
|
1008
1031
|
}
|
|
1009
1032
|
function isJsonObject(value) {
|
|
1010
|
-
return typeof 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 ===
|
|
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(
|
|
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) {
|