@sentry/junior 0.96.0 → 0.97.1
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/{agent-hooks-5URSMY3O.js → agent-hooks-XSUIVRQS.js} +8 -6
- package/dist/{reporting → api}/conversations/activity.d.ts +1 -1
- package/dist/api/conversations/detail-projection.d.ts +10 -0
- package/dist/api/conversations/detail.d.ts +3 -0
- package/dist/api/conversations/detail.query.d.ts +3 -0
- package/dist/api/conversations/list.d.ts +3 -0
- package/dist/api/conversations/list.query.d.ts +94 -0
- package/dist/api/conversations/projection.d.ts +14 -0
- package/dist/api/conversations/schema.d.ts +683 -0
- package/dist/{reporting → api}/conversations/shared.d.ts +1 -5
- package/dist/api/conversations/stats.d.ts +3 -0
- package/dist/api/conversations/stats.query.d.ts +3 -0
- package/dist/api/conversations/subagent.d.ts +3 -0
- package/dist/{reporting → api}/conversations/transcript.d.ts +4 -4
- package/dist/api/people/list.d.ts +1 -2
- package/dist/api/people/list.query.d.ts +3 -4
- package/dist/api/people/profile.d.ts +1 -2
- package/dist/api/people/profile.query.d.ts +3 -4
- package/dist/api/people/schema.d.ts +193 -0
- package/dist/api/people/shared.d.ts +31 -9
- package/dist/api/schema.d.ts +20 -0
- package/dist/api/schema.js +50 -0
- package/dist/api-reference.d.ts +4 -3
- package/dist/api.d.ts +3 -0
- package/dist/api.js +156 -0
- package/dist/app.d.ts +1 -4
- package/dist/app.js +101 -367
- package/dist/build/virtual-config.d.ts +2 -2
- package/dist/{catalog-runtime-MSMAYYIK.js → catalog-runtime-PFHVMHDR.js} +3 -2
- package/dist/chat/agent/resume.d.ts +3 -1
- package/dist/chat/agent/tools.d.ts +2 -1
- package/dist/chat/config.d.ts +1 -8
- package/dist/chat/conversations/history.d.ts +241 -27
- package/dist/chat/conversations/legacy-advisor-session.d.ts +7 -0
- package/dist/chat/conversations/legacy-import.d.ts +2 -2
- package/dist/chat/conversations/projection.d.ts +19 -3
- package/dist/chat/conversations/sql/legacy-history-import.d.ts +1 -1
- package/dist/chat/conversations/sql/store.d.ts +15 -9
- package/dist/chat/conversations/store.d.ts +9 -4
- package/dist/chat/model-profile.d.ts +14 -0
- package/dist/chat/pi/transcript.d.ts +5 -3
- package/dist/chat/resource-events/store.d.ts +2 -2
- package/dist/chat/services/context-compaction.d.ts +15 -0
- package/dist/chat/services/turn-result.d.ts +1 -0
- package/dist/chat/services/turn-session-record.d.ts +6 -6
- package/dist/chat/state/turn-session.d.ts +16 -5
- package/dist/chat/task-execution/store.d.ts +2 -2
- package/dist/chat/tools/handoff/tool.d.ts +45 -0
- package/dist/chat/tools/types.d.ts +7 -2
- package/dist/chat/usage.d.ts +25 -25
- package/dist/{chunk-RITD7E5L.js → chunk-35BNLDOJ.js} +338 -577
- package/dist/{chunk-PMNN6ST4.js → chunk-3ECW2K2O.js} +7 -2
- package/dist/{chunk-5C6XTTFI.js → chunk-3F4OPKGF.js} +89 -55
- package/dist/chunk-3V7OFJZC.js +264 -0
- package/dist/chunk-4ZNGQH7C.js +25 -0
- package/dist/{chunk-S5KZ5LPG.js → chunk-5HLDPVYS.js} +14 -447
- package/dist/{chunk-DZENG5ML.js → chunk-6U26PYI5.js} +24 -14
- package/dist/chunk-AUUCAFDE.js +546 -0
- package/dist/{chunk-6APU57E6.js → chunk-B3IT5END.js} +41 -260
- package/dist/chunk-CEA3A3UA.js +86 -0
- package/dist/{chunk-YDT7SNCN.js → chunk-D5KZYS4T.js} +1 -1
- package/dist/{chunk-YDVEH3SB.js → chunk-EEZCY5WX.js} +78 -28
- package/dist/{chunk-2NAZZPPS.js → chunk-EOWXRY5E.js} +1 -1
- package/dist/{chunk-GQ3GK22G.js → chunk-FBHZJFHI.js} +2 -2
- package/dist/{chunk-CZEX6KIQ.js → chunk-G3E7SCME.js} +0 -23
- package/dist/chunk-GUAP3H7O.js +319 -0
- package/dist/{chunk-BYZWPRJA.js → chunk-H66UCBPW.js} +6 -4
- package/dist/{chunk-L7CDEIVJ.js → chunk-LMJPRYHP.js} +4 -2
- package/dist/chunk-LUAE4MGW.js +199 -0
- package/dist/{chunk-GY34VGP5.js → chunk-LVA4I4H7.js} +3 -1
- package/dist/chunk-LVUKF5CE.js +63 -0
- package/dist/{chunk-AAZXTVJT.js → chunk-NG2AV7IB.js} +2 -72
- package/dist/chunk-ON6YKIQ7.js +260 -0
- package/dist/chunk-PDO5BLNM.js +22 -0
- package/dist/chunk-QNVHH5PU.js +20 -0
- package/dist/{chunk-P3YFQLEN.js → chunk-T533JLM3.js} +8 -10
- package/dist/chunk-UAMKJPDF.js +11 -0
- package/dist/chunk-VFH4ZKZT.js +66 -0
- package/dist/{chunk-UKHVMPX5.js → chunk-WGXMTFNU.js} +15 -17
- package/dist/{chunk-MNTINMWR.js → chunk-WJOSZOON.js} +184 -300
- package/dist/chunk-WTYEKPXU.js +451 -0
- package/dist/{chunk-IYM2SIVG.js → chunk-XIRPQQVE.js} +605 -363
- package/dist/cli/chat.js +24 -21
- package/dist/cli/check.js +4 -3
- package/dist/cli/init.js +12 -0
- package/dist/cli/plugins.js +12 -9
- package/dist/cli/snapshot-warmup.js +8 -6
- package/dist/cli/upgrade.js +265 -137
- package/dist/db/db.d.ts +4 -0
- package/dist/db/schema/conversations.d.ts +128 -0
- package/dist/db/schema.d.ts +129 -60
- package/dist/{db-2D6RMG67.js → db-BWXYIKFQ.js} +3 -3
- package/dist/detail-GA6NXWQJ.js +43 -0
- package/dist/discovery-RMHYSRL7.js +43 -0
- package/dist/handlers/health.d.ts +3 -0
- package/dist/instrumentation.js +1 -1
- package/dist/{legacy-import-VZ2MEGP7.js → legacy-import-3NQJVGQL.js} +4 -4
- package/dist/{api/people/list.js → list-A3WFRIYX.js} +26 -16
- package/dist/list-UXJI5Q5X.js +27 -0
- package/dist/nitro.d.ts +1 -1
- package/dist/nitro.js +2 -1
- package/dist/plugin-conversations-DDNGC35A.js +36 -0
- package/dist/{api/people/profile.js → profile-4RYDXWTF.js} +33 -18
- package/dist/reporting/plugin-conversations.d.ts +3 -0
- package/dist/reporting-schema.d.ts +140 -0
- package/dist/reporting.d.ts +12 -81
- package/dist/{runner-JZBRQP4F.js → runner-JALSYH2P.js} +17 -12
- package/dist/skills-MAZXZ2KE.js +26 -0
- package/dist/stats-XKXH3PTY.js +217 -0
- package/dist/subagent-TZ55XY37.js +48 -0
- package/dist/usage-schema.d.ts +25 -0
- package/dist/{validation-6XOOQGME.js → validation-FMEAEKCY.js} +4 -3
- package/migrations/0000_initial.sql +115 -0
- package/migrations/0001_conversation_metrics.sql +4 -0
- package/migrations/README.md +12 -30
- package/migrations/meta/0000_snapshot.json +1 -33
- package/migrations/meta/0001_snapshot.json +972 -0
- package/migrations/meta/_journal.json +9 -2
- package/package.json +13 -17
- package/dist/api/people/types.d.ts +0 -85
- package/dist/chat/advisor-request.d.ts +0 -4
- package/dist/chat/conversations/sql/migrations.d.ts +0 -22
- package/dist/chat/tools/advisor/session-store.d.ts +0 -9
- package/dist/chat/tools/advisor/tool.d.ts +0 -72
- package/dist/chunk-RAIB6WSG.js +0 -142
- package/dist/chunk-WM6KHPBQ.js +0 -48
- package/dist/db/schema/migrations.d.ts +0 -58
- package/dist/reporting/conversations/context.d.ts +0 -8
- package/dist/reporting/conversations/details.d.ts +0 -6
- package/dist/reporting/conversations/index.d.ts +0 -4
- package/dist/reporting/conversations/statistics.d.ts +0 -4
- package/dist/reporting/conversations/summaries.d.ts +0 -20
- package/dist/reporting/conversations/types.d.ts +0 -191
- package/dist/reporting/conversations.d.ts +0 -1
- package/dist/reporting.js +0 -1155
package/dist/cli/upgrade.js
CHANGED
|
@@ -4,47 +4,50 @@ import {
|
|
|
4
4
|
recordConversationActivity,
|
|
5
5
|
recordConversationExecution,
|
|
6
6
|
requestConversationWork
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-FBHZJFHI.js";
|
|
8
8
|
import {
|
|
9
9
|
defineJuniorPlugins,
|
|
10
10
|
pluginCatalogConfigFromEnv,
|
|
11
11
|
pluginCatalogConfigFromPluginSet,
|
|
12
12
|
pluginRuntimeRegistrationsFromPluginSet
|
|
13
13
|
} from "../chunk-SG5WAA7H.js";
|
|
14
|
-
import {
|
|
15
|
-
coerceThreadConversationState
|
|
16
|
-
} from "../chunk-RAIB6WSG.js";
|
|
17
14
|
import {
|
|
18
15
|
JUNIOR_THREAD_STATE_TTL_MS,
|
|
16
|
+
addAgentTurnUsage,
|
|
17
|
+
coerceThreadConversationState,
|
|
18
|
+
listAgentTurnSessionSummariesForConversations
|
|
19
|
+
} from "../chunk-WJOSZOON.js";
|
|
20
|
+
import "../chunk-GUAP3H7O.js";
|
|
21
|
+
import {
|
|
19
22
|
importConversationFromLegacy
|
|
20
|
-
} from "../chunk-
|
|
23
|
+
} from "../chunk-3F4OPKGF.js";
|
|
24
|
+
import "../chunk-PDO5BLNM.js";
|
|
21
25
|
import {
|
|
22
26
|
loadAppPluginSet
|
|
23
27
|
} from "../chunk-Y2CM7HXH.js";
|
|
24
28
|
import {
|
|
25
29
|
createPluginLogger,
|
|
26
30
|
createPluginState
|
|
27
|
-
} from "../chunk-
|
|
31
|
+
} from "../chunk-EOWXRY5E.js";
|
|
28
32
|
import {
|
|
29
33
|
createJuniorSqlExecutor,
|
|
30
34
|
createSqlConversationMessageStore,
|
|
31
35
|
createSqlStore,
|
|
32
|
-
getDb
|
|
33
|
-
|
|
34
|
-
} from "../chunk-RITD7E5L.js";
|
|
36
|
+
getDb
|
|
37
|
+
} from "../chunk-35BNLDOJ.js";
|
|
35
38
|
import {
|
|
36
39
|
disconnectStateAdapter,
|
|
37
40
|
getChatConfig,
|
|
38
41
|
getConnectedStateContext
|
|
39
|
-
} from "../chunk-
|
|
40
|
-
import "../chunk-
|
|
42
|
+
} from "../chunk-EEZCY5WX.js";
|
|
43
|
+
import "../chunk-LVA4I4H7.js";
|
|
41
44
|
import {
|
|
42
45
|
parseDestination,
|
|
43
46
|
sameDestination
|
|
44
47
|
} from "../chunk-B7PUBQQM.js";
|
|
45
48
|
import {
|
|
46
49
|
pluginCatalogRuntime
|
|
47
|
-
} from "../chunk-
|
|
50
|
+
} from "../chunk-LMJPRYHP.js";
|
|
48
51
|
import "../chunk-I35CTGPO.js";
|
|
49
52
|
import {
|
|
50
53
|
isRecord,
|
|
@@ -52,28 +55,14 @@ import {
|
|
|
52
55
|
toOptionalString
|
|
53
56
|
} from "../chunk-OB42YVAE.js";
|
|
54
57
|
import "../chunk-6GWA276C.js";
|
|
55
|
-
import "../chunk-
|
|
58
|
+
import "../chunk-B3IT5END.js";
|
|
56
59
|
import "../chunk-7FBGKXPE.js";
|
|
60
|
+
import "../chunk-3V7OFJZC.js";
|
|
57
61
|
import "../chunk-MLKGABMK.js";
|
|
58
62
|
|
|
59
63
|
// src/cli/upgrade.ts
|
|
60
64
|
import { createJiti } from "jiti";
|
|
61
65
|
|
|
62
|
-
// src/chat/conversations/sql/backfill.ts
|
|
63
|
-
async function backfillToSql(args) {
|
|
64
|
-
const limit = Math.max(0, args.limit ?? 500);
|
|
65
|
-
const conversations = await args.source.listByActivity({
|
|
66
|
-
limit
|
|
67
|
-
});
|
|
68
|
-
await args.target.migrate();
|
|
69
|
-
for (const conversation of conversations) {
|
|
70
|
-
await args.target.backfillConversation(conversation);
|
|
71
|
-
}
|
|
72
|
-
return {
|
|
73
|
-
copiedCount: conversations.length
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
|
|
77
66
|
// src/chat/conversations/state.ts
|
|
78
67
|
function createStateConversationStore(state) {
|
|
79
68
|
return {
|
|
@@ -81,8 +70,8 @@ function createStateConversationStore(state) {
|
|
|
81
70
|
// Task-execution state has no destination records, so visibility is never
|
|
82
71
|
// source-confirmed here and cross-context reads fail closed to private.
|
|
83
72
|
getDestinationVisibility: async () => void 0,
|
|
84
|
-
//
|
|
85
|
-
//
|
|
73
|
+
// Child conversations are a SQL-only concept and never use this legacy
|
|
74
|
+
// metadata path.
|
|
86
75
|
ensureChildConversation: async () => void 0,
|
|
87
76
|
recordActivity: (args) => recordConversationActivity({ ...args, state }),
|
|
88
77
|
recordExecution: (args) => recordConversationExecution({ ...args, state }),
|
|
@@ -107,16 +96,58 @@ async function migrateConversationsToSql(context, options = {}) {
|
|
|
107
96
|
}
|
|
108
97
|
const limit = Math.max(1, options.batchSize ?? CONVERSATION_BACKFILL_LIMIT);
|
|
109
98
|
try {
|
|
110
|
-
const
|
|
111
|
-
limit,
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
99
|
+
const [stateConversations, sqlConversations] = await Promise.all([
|
|
100
|
+
source.listByActivity({ limit }),
|
|
101
|
+
target.listByActivity({ limit })
|
|
102
|
+
]);
|
|
103
|
+
const byId = new Map(
|
|
104
|
+
sqlConversations.map((conversation) => [
|
|
105
|
+
conversation.conversationId,
|
|
106
|
+
conversation
|
|
107
|
+
])
|
|
108
|
+
);
|
|
109
|
+
for (const conversation of stateConversations) {
|
|
110
|
+
const existing = byId.get(conversation.conversationId);
|
|
111
|
+
const existingExecutionAt = existing?.execution.updatedAtMs ?? existing?.updatedAtMs ?? 0;
|
|
112
|
+
const stateExecutionAt = conversation.execution.updatedAtMs ?? conversation.updatedAtMs;
|
|
113
|
+
if (!existing || stateExecutionAt >= existingExecutionAt) {
|
|
114
|
+
byId.set(conversation.conversationId, conversation);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
const conversations = [...byId.values()].sort(
|
|
118
|
+
(left, right) => right.lastActivityAtMs - left.lastActivityAtMs || left.conversationId.localeCompare(right.conversationId)
|
|
119
|
+
).slice(0, limit);
|
|
120
|
+
const summaries = await listAgentTurnSessionSummariesForConversations(
|
|
121
|
+
context.stateAdapter,
|
|
122
|
+
conversations.map((conversation) => conversation.conversationId)
|
|
123
|
+
);
|
|
124
|
+
for (const conversation of conversations) {
|
|
125
|
+
const conversationSummaries = summaries.get(conversation.conversationId) ?? [];
|
|
126
|
+
const executionSummary = conversation.execution.runId ? conversationSummaries.find(
|
|
127
|
+
(summary) => summary.sessionId === conversation.execution.runId
|
|
128
|
+
) : void 0;
|
|
129
|
+
await target.backfillConversation(
|
|
130
|
+
conversation,
|
|
131
|
+
conversationSummaries.length > 0 ? {
|
|
132
|
+
durationMs: conversationSummaries.reduce(
|
|
133
|
+
(total, summary) => total + summary.cumulativeDurationMs,
|
|
134
|
+
0
|
|
135
|
+
),
|
|
136
|
+
usage: addAgentTurnUsage(
|
|
137
|
+
...conversationSummaries.map(
|
|
138
|
+
(summary) => summary.cumulativeUsage
|
|
139
|
+
)
|
|
140
|
+
),
|
|
141
|
+
executionDurationMs: executionSummary?.cumulativeDurationMs ?? 0,
|
|
142
|
+
executionUsage: executionSummary?.cumulativeUsage
|
|
143
|
+
} : void 0
|
|
144
|
+
);
|
|
145
|
+
}
|
|
115
146
|
return {
|
|
116
147
|
existing: 0,
|
|
117
|
-
migrated:
|
|
148
|
+
migrated: conversations.length,
|
|
118
149
|
missing: 0,
|
|
119
|
-
scanned:
|
|
150
|
+
scanned: conversations.length
|
|
120
151
|
};
|
|
121
152
|
} finally {
|
|
122
153
|
await closeTarget?.();
|
|
@@ -127,6 +158,107 @@ var sqlConversationMigration = {
|
|
|
127
158
|
run: migrateConversationsToSql
|
|
128
159
|
};
|
|
129
160
|
|
|
161
|
+
// src/chat/conversations/sql/migrations.ts
|
|
162
|
+
import { basename, dirname, join, resolve } from "path";
|
|
163
|
+
import { fileURLToPath } from "url";
|
|
164
|
+
import { readMigrationFiles } from "drizzle-orm/migrator";
|
|
165
|
+
var LEGACY_CORE_MIGRATION_IDS = [
|
|
166
|
+
"0001_conversation_core",
|
|
167
|
+
"0002_slack_destination_visibility_backfill",
|
|
168
|
+
"0003_user_identities",
|
|
169
|
+
"0004_actor_cutover",
|
|
170
|
+
"0005_conversation_transcripts"
|
|
171
|
+
];
|
|
172
|
+
var LEGACY_METRICS_MIGRATION_ID = "0006_conversation_metrics";
|
|
173
|
+
var MIGRATIONS_TABLE = "__drizzle_junior_core";
|
|
174
|
+
function migrationFolder() {
|
|
175
|
+
const moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
176
|
+
const packageRoot = basename(moduleDir) === "dist" ? dirname(moduleDir) : basename(dirname(moduleDir)) === "dist" ? resolve(moduleDir, "../..") : resolve(moduleDir, "../../../..");
|
|
177
|
+
return join(packageRoot, "migrations");
|
|
178
|
+
}
|
|
179
|
+
async function adoptLegacyMigrationState(executor, migrationsFolder) {
|
|
180
|
+
const [tables] = await executor.query(`
|
|
181
|
+
SELECT
|
|
182
|
+
to_regclass('drizzle.__drizzle_junior_core')::text AS "drizzleTable",
|
|
183
|
+
to_regclass('public.junior_schema_migrations')::text AS "legacyTable"
|
|
184
|
+
`);
|
|
185
|
+
if (!tables?.legacyTable || tables.drizzleTable) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
const migrations = readMigrationFiles({ migrationsFolder });
|
|
189
|
+
const [metrics] = await executor.query(`
|
|
190
|
+
SELECT count(*) = 4 AS complete
|
|
191
|
+
FROM information_schema.columns
|
|
192
|
+
WHERE table_schema = 'public'
|
|
193
|
+
AND table_name = 'junior_conversations'
|
|
194
|
+
AND column_name IN (
|
|
195
|
+
'duration_ms',
|
|
196
|
+
'usage_json',
|
|
197
|
+
'execution_duration_ms',
|
|
198
|
+
'execution_usage_json'
|
|
199
|
+
)
|
|
200
|
+
`);
|
|
201
|
+
const legacyRecords = await executor.query("SELECT id, checksum FROM junior_schema_migrations");
|
|
202
|
+
const expectedIds = metrics?.complete ? [...LEGACY_CORE_MIGRATION_IDS, LEGACY_METRICS_MIGRATION_ID] : [...LEGACY_CORE_MIGRATION_IDS];
|
|
203
|
+
const validIds = new Set(
|
|
204
|
+
legacyRecords.filter((record) => record.checksum.trim().length > 0).map((record) => record.id)
|
|
205
|
+
);
|
|
206
|
+
const missingIds = expectedIds.filter((id) => !validIds.has(id));
|
|
207
|
+
if (missingIds.length > 0) {
|
|
208
|
+
throw new Error(
|
|
209
|
+
`Cannot adopt partial legacy core migration state; missing: ${missingIds.join(", ")}`
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
const migration = metrics?.complete ? migrations.at(-1) : migrations[0];
|
|
213
|
+
if (!migration) {
|
|
214
|
+
throw new Error("No core Drizzle migrations were packaged");
|
|
215
|
+
}
|
|
216
|
+
await executor.transaction(async () => {
|
|
217
|
+
await executor.execute("CREATE SCHEMA IF NOT EXISTS drizzle");
|
|
218
|
+
await executor.execute(`
|
|
219
|
+
CREATE TABLE IF NOT EXISTS drizzle.__drizzle_junior_core (
|
|
220
|
+
id SERIAL PRIMARY KEY,
|
|
221
|
+
hash TEXT NOT NULL,
|
|
222
|
+
created_at BIGINT
|
|
223
|
+
)
|
|
224
|
+
`);
|
|
225
|
+
await executor.execute(
|
|
226
|
+
`INSERT INTO drizzle.__drizzle_junior_core (hash, created_at)
|
|
227
|
+
VALUES ($1, $2)`,
|
|
228
|
+
[migration.hash, migration.folderMillis]
|
|
229
|
+
);
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
async function migrateSchema(executor) {
|
|
233
|
+
const migrationsFolder = migrationFolder();
|
|
234
|
+
await executor.withMigrationLock(MIGRATIONS_TABLE, async () => {
|
|
235
|
+
await adoptLegacyMigrationState(executor, migrationsFolder);
|
|
236
|
+
await executor.migrate({
|
|
237
|
+
migrationsFolder,
|
|
238
|
+
migrationsTable: MIGRATIONS_TABLE
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// src/cli/upgrade/migrations/core-sql.ts
|
|
244
|
+
async function migrateCoreSqlSchema(_context) {
|
|
245
|
+
const { sql } = getChatConfig();
|
|
246
|
+
const executor = createJuniorSqlExecutor({
|
|
247
|
+
connectionString: sql.databaseUrl,
|
|
248
|
+
driver: sql.driver
|
|
249
|
+
});
|
|
250
|
+
try {
|
|
251
|
+
await migrateSchema(executor);
|
|
252
|
+
return { existing: 0, migrated: 0, missing: 0, scanned: 0 };
|
|
253
|
+
} finally {
|
|
254
|
+
await executor.close();
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
var coreSqlSchemaMigration = {
|
|
258
|
+
name: "core-sql-schema",
|
|
259
|
+
run: migrateCoreSqlSchema
|
|
260
|
+
};
|
|
261
|
+
|
|
130
262
|
// src/cli/upgrade/migrations/conversations-history-sql.ts
|
|
131
263
|
var HISTORY_BACKFILL_LIMIT = 1e4;
|
|
132
264
|
async function migrateConversationHistoryToSql(context, options = {}) {
|
|
@@ -143,7 +275,6 @@ async function migrateConversationHistoryToSql(context, options = {}) {
|
|
|
143
275
|
}
|
|
144
276
|
const limit = Math.max(1, options.batchSize ?? HISTORY_BACKFILL_LIMIT);
|
|
145
277
|
try {
|
|
146
|
-
await migrateSchema(executor);
|
|
147
278
|
const messageStore = createSqlConversationMessageStore(executor);
|
|
148
279
|
const conversations = await source.listByActivity({ limit });
|
|
149
280
|
let migrated = 0;
|
|
@@ -313,122 +444,116 @@ var pluginStorageMigration = {
|
|
|
313
444
|
run: runPluginStorageMigrations
|
|
314
445
|
};
|
|
315
446
|
|
|
316
|
-
// src/chat/plugins/
|
|
447
|
+
// src/chat/plugins/migrations.ts
|
|
317
448
|
import { createHash } from "crypto";
|
|
318
|
-
import {
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
var migrationRecordSchema = z.object({
|
|
324
|
-
id: z.string().min(1),
|
|
325
|
-
checksum: z.string().min(1)
|
|
326
|
-
}).strict();
|
|
327
|
-
function checksumSql(sql) {
|
|
328
|
-
return createHash("sha256").update(sql).digest("hex");
|
|
449
|
+
import { readMigrationFiles as readMigrationFiles2 } from "drizzle-orm/migrator";
|
|
450
|
+
function migrationTable(pluginName) {
|
|
451
|
+
const label = pluginName.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 32);
|
|
452
|
+
const hash = createHash("sha256").update(pluginName).digest("hex").slice(0, 8);
|
|
453
|
+
return `__drizzle_${label}_${hash}`;
|
|
329
454
|
}
|
|
330
|
-
function
|
|
331
|
-
|
|
455
|
+
async function appliedMigrationTime(executor, table) {
|
|
456
|
+
const [exists] = await executor.query(
|
|
457
|
+
`SELECT to_regclass($1)::text AS "tableName"`,
|
|
458
|
+
[`drizzle.${table}`]
|
|
459
|
+
);
|
|
460
|
+
if (!exists?.tableName) {
|
|
461
|
+
return void 0;
|
|
462
|
+
}
|
|
463
|
+
const [row] = await executor.query(
|
|
464
|
+
`SELECT created_at::text AS "createdAt"
|
|
465
|
+
FROM drizzle.${table}
|
|
466
|
+
ORDER BY created_at DESC
|
|
467
|
+
LIMIT 1`
|
|
468
|
+
);
|
|
469
|
+
return row?.createdAt === null || row?.createdAt === void 0 ? void 0 : Number(row.createdAt);
|
|
332
470
|
}
|
|
333
|
-
function
|
|
334
|
-
|
|
335
|
-
|
|
471
|
+
async function legacyMigrationHashes(executor, pluginName) {
|
|
472
|
+
const [exists] = await executor.query(
|
|
473
|
+
`SELECT to_regclass('public.junior_schema_migrations')::text AS "tableName"`
|
|
474
|
+
);
|
|
475
|
+
if (!exists?.tableName) {
|
|
476
|
+
return /* @__PURE__ */ new Set();
|
|
336
477
|
}
|
|
478
|
+
const rows = await executor.query(
|
|
479
|
+
`SELECT checksum
|
|
480
|
+
FROM junior_schema_migrations
|
|
481
|
+
WHERE id LIKE $1
|
|
482
|
+
ORDER BY id ASC`,
|
|
483
|
+
[`plugin:${pluginName}/%`]
|
|
484
|
+
);
|
|
485
|
+
return new Set(rows.map((row) => row.checksum));
|
|
337
486
|
}
|
|
338
|
-
function
|
|
339
|
-
|
|
487
|
+
function adoptedMigration(migrations, legacyHashes) {
|
|
488
|
+
let adopted;
|
|
340
489
|
for (const migration of migrations) {
|
|
341
|
-
if (
|
|
342
|
-
|
|
490
|
+
if (!legacyHashes.has(migration.hash)) {
|
|
491
|
+
break;
|
|
343
492
|
}
|
|
344
|
-
|
|
493
|
+
adopted = migration;
|
|
345
494
|
}
|
|
495
|
+
if (!adopted && migrations.length === 1 && legacyHashes.size > 0) {
|
|
496
|
+
return migrations[0];
|
|
497
|
+
}
|
|
498
|
+
return adopted;
|
|
346
499
|
}
|
|
347
|
-
function
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
return `
|
|
352
|
-
CREATE TABLE IF NOT EXISTS junior_schema_migrations (
|
|
353
|
-
id TEXT PRIMARY KEY,
|
|
354
|
-
checksum TEXT NOT NULL,
|
|
355
|
-
applied_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
356
|
-
)
|
|
357
|
-
`;
|
|
358
|
-
}
|
|
359
|
-
async function listAppliedMigrations(executor) {
|
|
360
|
-
const rows = await executor.query(
|
|
361
|
-
"SELECT id, checksum FROM junior_schema_migrations ORDER BY id ASC"
|
|
500
|
+
async function adoptLegacyMigrationState2(args) {
|
|
501
|
+
const legacyHashes = await legacyMigrationHashes(
|
|
502
|
+
args.executor,
|
|
503
|
+
args.pluginName
|
|
362
504
|
);
|
|
363
|
-
const
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
records.set(record.id, record);
|
|
505
|
+
const migration = adoptedMigration(args.migrations, legacyHashes);
|
|
506
|
+
if (!migration) {
|
|
507
|
+
return void 0;
|
|
367
508
|
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
509
|
+
await args.executor.transaction(async () => {
|
|
510
|
+
await args.executor.execute("CREATE SCHEMA IF NOT EXISTS drizzle");
|
|
511
|
+
await args.executor.execute(`
|
|
512
|
+
CREATE TABLE IF NOT EXISTS drizzle.${args.table} (
|
|
513
|
+
id SERIAL PRIMARY KEY,
|
|
514
|
+
hash TEXT NOT NULL,
|
|
515
|
+
created_at BIGINT
|
|
516
|
+
)
|
|
517
|
+
`);
|
|
518
|
+
await args.executor.execute(
|
|
519
|
+
`INSERT INTO drizzle.${args.table} (hash, created_at) VALUES ($1, $2)`,
|
|
520
|
+
[migration.hash, migration.folderMillis]
|
|
376
521
|
);
|
|
377
522
|
});
|
|
523
|
+
return migration.folderMillis;
|
|
378
524
|
}
|
|
379
|
-
function
|
|
380
|
-
|
|
381
|
-
let stat;
|
|
382
|
-
try {
|
|
383
|
-
stat = statSync(migrationsDir);
|
|
384
|
-
} catch {
|
|
385
|
-
return [];
|
|
386
|
-
}
|
|
387
|
-
if (!stat.isDirectory()) {
|
|
388
|
-
throw new Error(
|
|
389
|
-
`Plugin "${root.pluginName}" migrations path is not a directory`
|
|
390
|
-
);
|
|
391
|
-
}
|
|
392
|
-
return readdirSync(migrationsDir).filter((filename) => filename.endsWith(".sql")).sort((left, right) => left.localeCompare(right)).map((filename) => {
|
|
393
|
-
assertMigrationFilename(filename);
|
|
394
|
-
const sql = readFileSync(path.join(migrationsDir, filename), "utf8");
|
|
395
|
-
if (!sql.trim()) {
|
|
396
|
-
throw new Error(
|
|
397
|
-
`Plugin "${root.pluginName}" migration "${filename}" is empty`
|
|
398
|
-
);
|
|
399
|
-
}
|
|
400
|
-
return {
|
|
401
|
-
checksum: checksumSql(sql),
|
|
402
|
-
filename,
|
|
403
|
-
id: migrationId(root.pluginName, filename),
|
|
404
|
-
pluginName: root.pluginName,
|
|
405
|
-
sql
|
|
406
|
-
};
|
|
407
|
-
});
|
|
525
|
+
function appliedCount(migrations, createdAt) {
|
|
526
|
+
return createdAt === void 0 ? 0 : migrations.filter((migration) => migration.folderMillis <= createdAt).length;
|
|
408
527
|
}
|
|
409
|
-
async function migratePluginSchemas(executor,
|
|
410
|
-
assertUniqueMigrationIds(migrations);
|
|
528
|
+
async function migratePluginSchemas(executor, roots) {
|
|
411
529
|
const result = {
|
|
412
530
|
existing: 0,
|
|
413
531
|
migrated: 0,
|
|
414
|
-
scanned:
|
|
532
|
+
scanned: 0
|
|
415
533
|
};
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
534
|
+
const orderedRoots = [...roots].sort(
|
|
535
|
+
(left, right) => left.pluginName.localeCompare(right.pluginName)
|
|
536
|
+
);
|
|
537
|
+
for (const root of orderedRoots) {
|
|
538
|
+
const migrations = readMigrationFiles2({ migrationsFolder: root.dir });
|
|
539
|
+
const table = migrationTable(root.pluginName);
|
|
540
|
+
await executor.withMigrationLock(table, async () => {
|
|
541
|
+
const currentTime = await appliedMigrationTime(executor, table) ?? await adoptLegacyMigrationState2({
|
|
542
|
+
executor,
|
|
543
|
+
migrations,
|
|
544
|
+
pluginName: root.pluginName,
|
|
545
|
+
table
|
|
546
|
+
});
|
|
547
|
+
const existing = appliedCount(migrations, currentTime);
|
|
548
|
+
await executor.migrate({
|
|
549
|
+
migrationsFolder: root.dir,
|
|
550
|
+
migrationsTable: table
|
|
551
|
+
});
|
|
552
|
+
result.scanned += migrations.length;
|
|
553
|
+
result.existing += existing;
|
|
554
|
+
result.migrated += migrations.length - existing;
|
|
555
|
+
});
|
|
556
|
+
}
|
|
432
557
|
return result;
|
|
433
558
|
}
|
|
434
559
|
|
|
@@ -442,8 +567,10 @@ async function migratePluginsToSql(context) {
|
|
|
442
567
|
driver: sql.driver
|
|
443
568
|
});
|
|
444
569
|
try {
|
|
445
|
-
const
|
|
446
|
-
|
|
570
|
+
const result = await migratePluginSchemas(
|
|
571
|
+
executor,
|
|
572
|
+
pluginCatalogRuntime.getMigrationRoots()
|
|
573
|
+
);
|
|
447
574
|
return {
|
|
448
575
|
existing: result.existing,
|
|
449
576
|
migrated: result.migrated,
|
|
@@ -999,6 +1126,7 @@ var DEFAULT_IO = {
|
|
|
999
1126
|
var localPluginLoader = createJiti(import.meta.url, { moduleCache: false });
|
|
1000
1127
|
var MIGRATIONS = [
|
|
1001
1128
|
redisConversationStateMigration,
|
|
1129
|
+
coreSqlSchemaMigration,
|
|
1002
1130
|
sqlConversationMigration,
|
|
1003
1131
|
sqlConversationHistoryMigration,
|
|
1004
1132
|
sqlPluginMigration,
|
package/dist/db/db.d.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import type { PgDatabase } from "drizzle-orm/pg-core";
|
|
9
9
|
import type { PgQueryResultHKT } from "drizzle-orm/pg-core/session";
|
|
10
|
+
import type { MigrationConfig } from "drizzle-orm/migrator";
|
|
10
11
|
import type { juniorSqlSchema } from "./schema";
|
|
11
12
|
export type JuniorDatabase = PgDatabase<PgQueryResultHKT, typeof juniorSqlSchema>;
|
|
12
13
|
export interface JuniorSqlDatabase {
|
|
@@ -16,7 +17,10 @@ export interface JuniorSqlDatabase {
|
|
|
16
17
|
}
|
|
17
18
|
export interface JuniorSqlMigrationExecutor extends JuniorSqlDatabase {
|
|
18
19
|
execute(statement: string, params?: readonly unknown[]): Promise<void>;
|
|
20
|
+
migrate(config: MigrationConfig): Promise<void>;
|
|
19
21
|
query<T = unknown>(statement: string, params?: readonly unknown[]): Promise<T[]>;
|
|
22
|
+
/** Serialize adoption and migration for one Drizzle journal. */
|
|
23
|
+
withMigrationLock<T>(migrationTable: string, callback: () => Promise<T>): Promise<T>;
|
|
20
24
|
}
|
|
21
25
|
export interface JuniorSqlExecutor extends JuniorSqlMigrationExecutor {
|
|
22
26
|
close(): Promise<void>;
|
|
@@ -447,6 +447,134 @@ export declare const juniorConversations: import("drizzle-orm/pg-core").PgTableW
|
|
|
447
447
|
identity: undefined;
|
|
448
448
|
generated: undefined;
|
|
449
449
|
}, {}, {}>;
|
|
450
|
+
durationMs: import("drizzle-orm/pg-core").PgColumn<{
|
|
451
|
+
name: "duration_ms";
|
|
452
|
+
tableName: "junior_conversations";
|
|
453
|
+
dataType: "number";
|
|
454
|
+
columnType: "PgInteger";
|
|
455
|
+
data: number;
|
|
456
|
+
driverParam: string | number;
|
|
457
|
+
notNull: true;
|
|
458
|
+
hasDefault: true;
|
|
459
|
+
isPrimaryKey: false;
|
|
460
|
+
isAutoincrement: false;
|
|
461
|
+
hasRuntimeDefault: false;
|
|
462
|
+
enumValues: undefined;
|
|
463
|
+
baseColumn: never;
|
|
464
|
+
identity: undefined;
|
|
465
|
+
generated: undefined;
|
|
466
|
+
}, {}, {}>;
|
|
467
|
+
usage: import("drizzle-orm/pg-core").PgColumn<{
|
|
468
|
+
name: "usage_json";
|
|
469
|
+
tableName: "junior_conversations";
|
|
470
|
+
dataType: "json";
|
|
471
|
+
columnType: "PgJsonb";
|
|
472
|
+
data: {
|
|
473
|
+
inputTokens?: number | undefined;
|
|
474
|
+
outputTokens?: number | undefined;
|
|
475
|
+
cachedInputTokens?: number | undefined;
|
|
476
|
+
cacheCreationTokens?: number | undefined;
|
|
477
|
+
reasoningTokens?: number | undefined;
|
|
478
|
+
totalTokens?: number | undefined;
|
|
479
|
+
cost?: {
|
|
480
|
+
input?: number | undefined;
|
|
481
|
+
output?: number | undefined;
|
|
482
|
+
cacheRead?: number | undefined;
|
|
483
|
+
cacheWrite?: number | undefined;
|
|
484
|
+
total?: number | undefined;
|
|
485
|
+
} | undefined;
|
|
486
|
+
};
|
|
487
|
+
driverParam: unknown;
|
|
488
|
+
notNull: false;
|
|
489
|
+
hasDefault: false;
|
|
490
|
+
isPrimaryKey: false;
|
|
491
|
+
isAutoincrement: false;
|
|
492
|
+
hasRuntimeDefault: false;
|
|
493
|
+
enumValues: undefined;
|
|
494
|
+
baseColumn: never;
|
|
495
|
+
identity: undefined;
|
|
496
|
+
generated: undefined;
|
|
497
|
+
}, {}, {
|
|
498
|
+
$type: {
|
|
499
|
+
inputTokens?: number | undefined;
|
|
500
|
+
outputTokens?: number | undefined;
|
|
501
|
+
cachedInputTokens?: number | undefined;
|
|
502
|
+
cacheCreationTokens?: number | undefined;
|
|
503
|
+
reasoningTokens?: number | undefined;
|
|
504
|
+
totalTokens?: number | undefined;
|
|
505
|
+
cost?: {
|
|
506
|
+
input?: number | undefined;
|
|
507
|
+
output?: number | undefined;
|
|
508
|
+
cacheRead?: number | undefined;
|
|
509
|
+
cacheWrite?: number | undefined;
|
|
510
|
+
total?: number | undefined;
|
|
511
|
+
} | undefined;
|
|
512
|
+
};
|
|
513
|
+
}>;
|
|
514
|
+
executionDurationMs: import("drizzle-orm/pg-core").PgColumn<{
|
|
515
|
+
name: "execution_duration_ms";
|
|
516
|
+
tableName: "junior_conversations";
|
|
517
|
+
dataType: "number";
|
|
518
|
+
columnType: "PgInteger";
|
|
519
|
+
data: number;
|
|
520
|
+
driverParam: string | number;
|
|
521
|
+
notNull: true;
|
|
522
|
+
hasDefault: true;
|
|
523
|
+
isPrimaryKey: false;
|
|
524
|
+
isAutoincrement: false;
|
|
525
|
+
hasRuntimeDefault: false;
|
|
526
|
+
enumValues: undefined;
|
|
527
|
+
baseColumn: never;
|
|
528
|
+
identity: undefined;
|
|
529
|
+
generated: undefined;
|
|
530
|
+
}, {}, {}>;
|
|
531
|
+
executionUsage: import("drizzle-orm/pg-core").PgColumn<{
|
|
532
|
+
name: "execution_usage_json";
|
|
533
|
+
tableName: "junior_conversations";
|
|
534
|
+
dataType: "json";
|
|
535
|
+
columnType: "PgJsonb";
|
|
536
|
+
data: {
|
|
537
|
+
inputTokens?: number | undefined;
|
|
538
|
+
outputTokens?: number | undefined;
|
|
539
|
+
cachedInputTokens?: number | undefined;
|
|
540
|
+
cacheCreationTokens?: number | undefined;
|
|
541
|
+
reasoningTokens?: number | undefined;
|
|
542
|
+
totalTokens?: number | undefined;
|
|
543
|
+
cost?: {
|
|
544
|
+
input?: number | undefined;
|
|
545
|
+
output?: number | undefined;
|
|
546
|
+
cacheRead?: number | undefined;
|
|
547
|
+
cacheWrite?: number | undefined;
|
|
548
|
+
total?: number | undefined;
|
|
549
|
+
} | undefined;
|
|
550
|
+
};
|
|
551
|
+
driverParam: unknown;
|
|
552
|
+
notNull: false;
|
|
553
|
+
hasDefault: false;
|
|
554
|
+
isPrimaryKey: false;
|
|
555
|
+
isAutoincrement: false;
|
|
556
|
+
hasRuntimeDefault: false;
|
|
557
|
+
enumValues: undefined;
|
|
558
|
+
baseColumn: never;
|
|
559
|
+
identity: undefined;
|
|
560
|
+
generated: undefined;
|
|
561
|
+
}, {}, {
|
|
562
|
+
$type: {
|
|
563
|
+
inputTokens?: number | undefined;
|
|
564
|
+
outputTokens?: number | undefined;
|
|
565
|
+
cachedInputTokens?: number | undefined;
|
|
566
|
+
cacheCreationTokens?: number | undefined;
|
|
567
|
+
reasoningTokens?: number | undefined;
|
|
568
|
+
totalTokens?: number | undefined;
|
|
569
|
+
cost?: {
|
|
570
|
+
input?: number | undefined;
|
|
571
|
+
output?: number | undefined;
|
|
572
|
+
cacheRead?: number | undefined;
|
|
573
|
+
cacheWrite?: number | undefined;
|
|
574
|
+
total?: number | undefined;
|
|
575
|
+
} | undefined;
|
|
576
|
+
};
|
|
577
|
+
}>;
|
|
450
578
|
};
|
|
451
579
|
dialect: "pg";
|
|
452
580
|
}>;
|