@sentry/junior 0.74.1 → 0.76.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 (121) hide show
  1. package/README.md +1 -1
  2. package/bin/junior.mjs +4 -66
  3. package/dist/agent-hooks-ZOE7RIED.js +37 -0
  4. package/dist/api-reference.d.ts +3 -1
  5. package/dist/app.js +5516 -5422
  6. package/dist/build/copy-build-content.d.ts +1 -1
  7. package/dist/build/virtual-config.d.ts +2 -2
  8. package/dist/chat/agent-dispatch/context.d.ts +2 -3
  9. package/dist/chat/agent-dispatch/runner.d.ts +2 -0
  10. package/dist/chat/agent-dispatch/types.d.ts +2 -1
  11. package/dist/chat/config.d.ts +3 -0
  12. package/dist/chat/credentials/state-adapter-token-store.d.ts +2 -0
  13. package/dist/chat/credentials/subject.d.ts +3 -3
  14. package/dist/chat/credentials/user-token-store.d.ts +17 -12
  15. package/dist/chat/db.d.ts +8 -0
  16. package/dist/chat/mcp/auth-store.d.ts +2 -1
  17. package/dist/chat/mcp/oauth.d.ts +2 -1
  18. package/dist/chat/oauth-flow.d.ts +3 -1
  19. package/dist/chat/pi/client.d.ts +15 -7
  20. package/dist/chat/plugins/agent-hooks.d.ts +20 -13
  21. package/dist/chat/plugins/auth/oauth-request.d.ts +11 -7
  22. package/dist/chat/plugins/credential-hooks.d.ts +6 -6
  23. package/dist/chat/plugins/logging.d.ts +2 -2
  24. package/dist/chat/plugins/model.d.ts +9 -0
  25. package/dist/chat/plugins/package-discovery.d.ts +2 -1
  26. package/dist/chat/plugins/prompt.d.ts +5 -0
  27. package/dist/chat/plugins/registry.d.ts +4 -0
  28. package/dist/chat/plugins/state.d.ts +3 -5
  29. package/dist/chat/plugins/task-callback.d.ts +5 -0
  30. package/dist/chat/plugins/task-message.d.ts +23 -0
  31. package/dist/chat/plugins/task-queue.d.ts +5 -0
  32. package/dist/chat/plugins/task-runner.d.ts +12 -0
  33. package/dist/chat/plugins/task-signing.d.ts +31 -0
  34. package/dist/chat/plugins/types.d.ts +1 -0
  35. package/dist/chat/plugins/validation.d.ts +5 -0
  36. package/dist/chat/prompt.d.ts +15 -1
  37. package/dist/chat/requester.d.ts +6 -5
  38. package/dist/chat/respond-helpers.d.ts +2 -0
  39. package/dist/chat/respond.d.ts +13 -2
  40. package/dist/chat/runtime/agent-continue-runner.d.ts +4 -0
  41. package/dist/chat/runtime/reply-executor.d.ts +5 -1
  42. package/dist/chat/runtime/slack-resume.d.ts +10 -2
  43. package/dist/chat/runtime/slack-runtime.d.ts +6 -1
  44. package/dist/chat/sandbox/egress-credentials.d.ts +8 -8
  45. package/dist/chat/sandbox/sandbox.d.ts +2 -2
  46. package/dist/chat/sentry.d.ts +1 -0
  47. package/dist/chat/services/mcp-auth-orchestration.d.ts +2 -1
  48. package/dist/chat/services/plugin-auth-orchestration.d.ts +2 -1
  49. package/dist/chat/services/subscribed-decision.d.ts +2 -2
  50. package/dist/chat/services/turn-session-record.d.ts +11 -7
  51. package/dist/chat/sql/db.d.ts +3 -0
  52. package/dist/chat/sql/executor.d.ts +7 -0
  53. package/dist/chat/sql/neon.d.ts +2 -4
  54. package/dist/chat/sql/postgres.d.ts +6 -0
  55. package/dist/chat/state/turn-session.d.ts +8 -5
  56. package/dist/chat/task-execution/state.d.ts +7 -2
  57. package/dist/chat/task-execution/worker.d.ts +1 -1
  58. package/dist/chat/tools/agent-tools.d.ts +9 -2
  59. package/dist/chat/tools/slack/context.d.ts +2 -2
  60. package/dist/chat/tools/types.d.ts +7 -4
  61. package/dist/chat/vercel-queue-client.d.ts +3 -0
  62. package/dist/{chunk-YOHFWWBV.js → chunk-2ECJXSVQ.js} +5 -107
  63. package/dist/{chunk-OR6NQJ5E.js → chunk-4SCWV7TJ.js} +3 -3
  64. package/dist/chunk-4UO6FK4G.js +64 -0
  65. package/dist/chunk-56TBVRJG.js +115 -0
  66. package/dist/{chunk-3BYAPS6B.js → chunk-EJN6G5A2.js} +17 -11
  67. package/dist/{chunk-SQGMG7OD.js → chunk-HHDUKWVG.js} +508 -149
  68. package/dist/{chunk-6UP2Z2RZ.js → chunk-JBASI5VV.js} +7 -7
  69. package/dist/chunk-KNFROR7R.js +127 -0
  70. package/dist/{chunk-HYHKTFG2.js → chunk-KOIMO7S3.js} +186 -910
  71. package/dist/chunk-MLKGABMK.js +9 -0
  72. package/dist/chunk-NFTMTIP3.js +964 -0
  73. package/dist/chunk-NYKJ3KON.js +1082 -0
  74. package/dist/{chunk-SJHUF3DP.js → chunk-OJ53FYVG.js} +2 -10
  75. package/dist/{chunk-KVZL5NZS.js → chunk-Q3XNY442.js} +17 -7
  76. package/dist/{chunk-YRDS7VKO.js → chunk-Q6XFTRV5.js} +2 -2
  77. package/dist/chunk-R6Z5XWY3.js +1076 -0
  78. package/dist/chunk-RV5RYIJW.js +56 -0
  79. package/dist/chunk-SG5WAA7H.js +132 -0
  80. package/dist/chunk-ST6YNAXG.js +54 -0
  81. package/dist/{chunk-GM7HTXYC.js → chunk-T77LUIX3.js} +148 -151
  82. package/dist/{chunk-CYUI7JU5.js → chunk-VALUBQ7R.js} +22 -30
  83. package/dist/chunk-XBBC6W45.js +71 -0
  84. package/dist/chunk-Y2CM7HXH.js +111 -0
  85. package/dist/{chunk-F6HWCPOC.js → chunk-Y5OFBCBZ.js} +1 -1
  86. package/dist/{chunk-M4FLLXXD.js → chunk-Z4CIQ3EB.js} +5 -1
  87. package/dist/{chunk-7Q5YOUUT.js → chunk-ZLMBNBUG.js} +146 -52
  88. package/dist/{chunk-2LUZA3LY.js → chunk-ZQB37HUX.js} +11 -11
  89. package/dist/cli/chat.js +87 -8
  90. package/dist/cli/check.js +8 -7
  91. package/dist/cli/env.js +4 -53
  92. package/dist/cli/init.js +6 -1
  93. package/dist/cli/main.js +84 -0
  94. package/dist/cli/plugins.js +244 -0
  95. package/dist/cli/run.js +5 -52
  96. package/dist/cli/snapshot-warmup.js +12 -11
  97. package/dist/cli/upgrade.js +385 -26
  98. package/dist/db-7A7PFRGL.js +17 -0
  99. package/dist/deployment.d.ts +1 -0
  100. package/dist/handlers/sandbox-egress-route.d.ts +4 -0
  101. package/dist/handlers/slack-webhook.d.ts +4 -0
  102. package/dist/handlers/webhooks.d.ts +6 -13
  103. package/dist/instrumentation.js +14 -18
  104. package/dist/nitro.d.ts +1 -1
  105. package/dist/nitro.js +67 -101
  106. package/dist/plugin-module.d.ts +21 -0
  107. package/dist/plugins-PZMDS7AT.js +15 -0
  108. package/dist/plugins.d.ts +9 -5
  109. package/dist/registry-OIPAJU2O.js +46 -0
  110. package/dist/reporting/conversations.d.ts +3 -3
  111. package/dist/reporting.d.ts +6 -5
  112. package/dist/reporting.js +42 -28
  113. package/dist/{runner-27NP2TEO.js → runner-KPLNHDCV.js} +77 -19
  114. package/dist/sentry-4CP5NNQ5.js +31 -0
  115. package/dist/validation-SLA6IGF7.js +15 -0
  116. package/dist/vercel.js +1 -1
  117. package/package.json +14 -11
  118. package/dist/chat/conversations/configured.d.ts +0 -5
  119. package/dist/chat/conversations/state.d.ts +0 -4
  120. package/dist/chunk-2KG3PWR4.js +0 -17
  121. package/dist/chunk-JL2SLRAT.js +0 -1970
package/dist/cli/run.js CHANGED
@@ -1,55 +1,8 @@
1
- import "../chunk-2KG3PWR4.js";
2
-
3
- // src/cli/run.ts
4
- var CLI_USAGE = "usage: junior init <dir>\n junior snapshot create\n junior check [dir]\n junior upgrade\n junior chat\n junior chat -p <message>";
5
- var DEFAULT_IO = {
6
- error: console.error
7
- };
8
- function normalizeCliArgv(argv) {
9
- return argv[0] === "--" ? argv.slice(1) : argv;
10
- }
11
- async function runCli(argv, handlers, io = DEFAULT_IO) {
12
- const [command, subcommand, ...rest] = normalizeCliArgv(argv);
13
- if (command === "chat") {
14
- return await handlers.runChat(
15
- subcommand === void 0 ? [] : [subcommand, ...rest]
16
- );
17
- }
18
- if (command === "init") {
19
- if (!subcommand || rest.length > 0) {
20
- io.error(CLI_USAGE);
21
- return 1;
22
- }
23
- await handlers.runInit(subcommand);
24
- return 0;
25
- }
26
- if (command === "snapshot" && subcommand === "create") {
27
- if (rest.length > 0) {
28
- io.error(CLI_USAGE);
29
- return 1;
30
- }
31
- await handlers.runSnapshotCreate();
32
- return 0;
33
- }
34
- if (command === "check") {
35
- if (rest.length > 0) {
36
- io.error(CLI_USAGE);
37
- return 1;
38
- }
39
- await handlers.runCheck(subcommand);
40
- return 0;
41
- }
42
- if (command === "upgrade") {
43
- if (subcommand || rest.length > 0) {
44
- io.error(CLI_USAGE);
45
- return 1;
46
- }
47
- await handlers.runUpgrade();
48
- return 0;
49
- }
50
- io.error(CLI_USAGE);
51
- return 1;
52
- }
1
+ import {
2
+ CLI_USAGE,
3
+ runCli
4
+ } from "../chunk-4UO6FK4G.js";
5
+ import "../chunk-MLKGABMK.js";
53
6
  export {
54
7
  CLI_USAGE,
55
8
  runCli
@@ -1,21 +1,22 @@
1
1
  import {
2
2
  resolveRuntimeDependencySnapshot
3
- } from "../chunk-6UP2Z2RZ.js";
3
+ } from "../chunk-JBASI5VV.js";
4
4
  import "../chunk-G3E7SCME.js";
5
+ import {
6
+ disconnectStateAdapter
7
+ } from "../chunk-Y5OFBCBZ.js";
8
+ import "../chunk-T77LUIX3.js";
5
9
  import {
6
10
  getPluginProviders,
7
11
  getPluginRuntimeDependencies,
8
12
  getPluginRuntimePostinstall
9
- } from "../chunk-7Q5YOUUT.js";
10
- import "../chunk-KVZL5NZS.js";
11
- import {
12
- disconnectStateAdapter
13
- } from "../chunk-F6HWCPOC.js";
14
- import "../chunk-GM7HTXYC.js";
15
- import "../chunk-CYUI7JU5.js";
16
- import "../chunk-3BYAPS6B.js";
17
- import "../chunk-SJHUF3DP.js";
18
- import "../chunk-2KG3PWR4.js";
13
+ } from "../chunk-ZLMBNBUG.js";
14
+ import "../chunk-VALUBQ7R.js";
15
+ import "../chunk-Q3XNY442.js";
16
+ import "../chunk-EJN6G5A2.js";
17
+ import "../chunk-OJ53FYVG.js";
18
+ import "../chunk-ST6YNAXG.js";
19
+ import "../chunk-MLKGABMK.js";
19
20
 
20
21
  // src/cli/snapshot-warmup.ts
21
22
  var DEFAULT_RUNTIME = "node22";
@@ -1,33 +1,59 @@
1
1
  import {
2
- coerceThreadConversationState
3
- } from "../chunk-M4FLLXXD.js";
4
- import {
5
- JUNIOR_THREAD_STATE_TTL_MS,
6
- createNeonJuniorSqlExecutor,
7
- createSqlStore,
8
- createStateConversationStore,
9
2
  getConversation,
3
+ listConversationsByActivity,
4
+ recordConversationActivity,
10
5
  requestConversationWork
11
- } from "../chunk-JL2SLRAT.js";
6
+ } from "../chunk-R6Z5XWY3.js";
12
7
  import {
13
- parseDestination,
14
- sameDestination
15
- } from "../chunk-YRDS7VKO.js";
8
+ JUNIOR_THREAD_STATE_TTL_MS,
9
+ coerceThreadConversationState
10
+ } from "../chunk-Z4CIQ3EB.js";
11
+ import {
12
+ defineJuniorPlugins,
13
+ pluginCatalogConfigFromEnv,
14
+ pluginCatalogConfigFromPluginSet,
15
+ pluginRuntimeRegistrationsFromPluginSet
16
+ } from "../chunk-SG5WAA7H.js";
17
+ import {
18
+ createPluginLogger,
19
+ createPluginState
20
+ } from "../chunk-56TBVRJG.js";
21
+ import {
22
+ createJuniorSqlExecutor,
23
+ createSqlStore,
24
+ getDb
25
+ } from "../chunk-NYKJ3KON.js";
16
26
  import {
17
27
  disconnectStateAdapter,
18
28
  getConnectedStateContext
19
- } from "../chunk-F6HWCPOC.js";
29
+ } from "../chunk-Y5OFBCBZ.js";
30
+ import {
31
+ parseDestination,
32
+ sameDestination
33
+ } from "../chunk-Q6XFTRV5.js";
20
34
  import {
21
35
  getChatConfig
22
- } from "../chunk-GM7HTXYC.js";
23
- import "../chunk-CYUI7JU5.js";
36
+ } from "../chunk-T77LUIX3.js";
37
+ import {
38
+ loadAppPluginSet
39
+ } from "../chunk-Y2CM7HXH.js";
40
+ import {
41
+ getPluginMigrationRoots,
42
+ setPluginCatalogConfig
43
+ } from "../chunk-ZLMBNBUG.js";
44
+ import "../chunk-VALUBQ7R.js";
45
+ import "../chunk-Q3XNY442.js";
24
46
  import {
25
47
  isRecord,
26
48
  toOptionalNumber,
27
49
  toOptionalString
28
- } from "../chunk-3BYAPS6B.js";
29
- import "../chunk-SJHUF3DP.js";
30
- import "../chunk-2KG3PWR4.js";
50
+ } from "../chunk-EJN6G5A2.js";
51
+ import "../chunk-OJ53FYVG.js";
52
+ import "../chunk-ST6YNAXG.js";
53
+ import "../chunk-MLKGABMK.js";
54
+
55
+ // src/cli/upgrade.ts
56
+ import { createJiti } from "jiti";
31
57
 
32
58
  // src/chat/conversations/sql/backfill.ts
33
59
  async function backfillToSql(args) {
@@ -44,6 +70,17 @@ async function backfillToSql(args) {
44
70
  };
45
71
  }
46
72
 
73
+ // src/chat/conversations/state.ts
74
+ function createStateConversationStore(state) {
75
+ return {
76
+ get: (args) => getConversation({ ...args, state }),
77
+ recordActivity: (args) => recordConversationActivity({ ...args, state }),
78
+ recordExecution: async () => {
79
+ },
80
+ listByActivity: (args) => listConversationsByActivity({ ...args, state })
81
+ };
82
+ }
83
+
47
84
  // src/cli/upgrade/migrations/conversations-sql.ts
48
85
  var CONVERSATION_BACKFILL_LIMIT = 1e4;
49
86
  var REQUIRED_SQL_DATABASE_URL_MESSAGE = "Junior SQL database URL is required for conversation metadata upgrade. Set JUNIOR_DATABASE_URL or DATABASE_URL.";
@@ -60,8 +97,9 @@ async function migrateConversationsToSql(context, options = {}) {
60
97
  let closeTarget;
61
98
  if (!target) {
62
99
  const databaseUrl = requireConversationSqlDatabaseUrl(context);
63
- const executor = createNeonJuniorSqlExecutor({
64
- connectionString: databaseUrl
100
+ const executor = createJuniorSqlExecutor({
101
+ connectionString: databaseUrl,
102
+ driver: context.sqlDriver ?? getChatConfig().sql.driver
65
103
  });
66
104
  target = createSqlStore(executor);
67
105
  closeTarget = () => executor.close();
@@ -88,6 +126,294 @@ var sqlConversationMigration = {
88
126
  run: migrateConversationsToSql
89
127
  };
90
128
 
129
+ // src/cli/upgrade/migrations/upgrade-plugins.ts
130
+ function unique(values) {
131
+ return [...new Set(values)];
132
+ }
133
+ function baseCatalogConfig(context) {
134
+ return context.pluginCatalogConfig ?? (context.pluginSet ? pluginCatalogConfigFromPluginSet(context.pluginSet) : pluginCatalogConfigFromEnv());
135
+ }
136
+ function inlinePluginName(definition) {
137
+ return definition.manifest.name;
138
+ }
139
+ function mergeInlineManifests(left, right) {
140
+ const merged = /* @__PURE__ */ new Map();
141
+ for (const definition of [...left ?? [], ...right ?? []]) {
142
+ merged.set(inlinePluginName(definition), definition);
143
+ }
144
+ return merged.size > 0 ? [...merged.values()] : void 0;
145
+ }
146
+ function mergeCatalogConfig(base, added) {
147
+ if (!base) {
148
+ return added;
149
+ }
150
+ if (!added) {
151
+ return base;
152
+ }
153
+ const inlineManifests = mergeInlineManifests(
154
+ base.inlineManifests,
155
+ added.inlineManifests
156
+ );
157
+ const packages = unique([
158
+ ...base.packages ?? [],
159
+ ...added.packages ?? []
160
+ ]);
161
+ const manifests = base.manifests || added.manifests ? { ...base.manifests, ...added.manifests } : void 0;
162
+ return {
163
+ ...inlineManifests ? { inlineManifests } : {},
164
+ ...packages.length > 0 ? { packages } : {},
165
+ ...manifests ? { manifests } : {}
166
+ };
167
+ }
168
+ function packageNamesFromContext(context, catalog) {
169
+ return unique([
170
+ ...context.pluginSet?.packageNames ?? [],
171
+ ...catalog?.packages ?? []
172
+ ]);
173
+ }
174
+ async function resolveUpgradePlugins(context) {
175
+ const catalog = baseCatalogConfig(context);
176
+ const packageNames = packageNamesFromContext(context, catalog);
177
+ const registrations = context.pluginSet?.registrations ?? [];
178
+ const manifests = context.pluginSet?.manifests || catalog?.manifests ? {
179
+ ...catalog?.manifests,
180
+ ...context.pluginSet?.manifests
181
+ } : void 0;
182
+ const pluginSet = packageNames.length > 0 || registrations.length > 0 || context.pluginSet ? defineJuniorPlugins(
183
+ [...packageNames, ...registrations],
184
+ manifests ? { manifests } : {}
185
+ ) : void 0;
186
+ return {
187
+ pluginCatalogConfig: mergeCatalogConfig(
188
+ catalog,
189
+ pluginCatalogConfigFromPluginSet(pluginSet)
190
+ ),
191
+ ...pluginSet ? { pluginSet } : {}
192
+ };
193
+ }
194
+
195
+ // src/cli/upgrade/migrations/plugin-storage.ts
196
+ function emptyResult() {
197
+ return {
198
+ existing: 0,
199
+ migrated: 0,
200
+ missing: 0,
201
+ scanned: 0
202
+ };
203
+ }
204
+ function addResult(left, right) {
205
+ return {
206
+ existing: left.existing + right.existing,
207
+ migrated: left.migrated + right.migrated,
208
+ missing: left.missing + right.missing,
209
+ scanned: left.scanned + right.scanned,
210
+ ...left.skipped !== void 0 || right.skipped !== void 0 ? { skipped: (left.skipped ?? 0) + (right.skipped ?? 0) } : {}
211
+ };
212
+ }
213
+ function dbForPlugin(context, sqlUrlDb) {
214
+ return context.db ?? sqlUrlDb ?? getDb();
215
+ }
216
+ async function runPluginStorageMigrations(context) {
217
+ const { pluginCatalogConfig, pluginSet } = await resolveUpgradePlugins(context);
218
+ if (!pluginSet) {
219
+ return emptyResult();
220
+ }
221
+ const previousConfig = setPluginCatalogConfig(pluginCatalogConfig);
222
+ const ownedExecutor = context.db || !context.sqlDatabaseUrl ? void 0 : createJuniorSqlExecutor({
223
+ connectionString: context.sqlDatabaseUrl,
224
+ driver: context.sqlDriver ?? getChatConfig().sql.driver
225
+ });
226
+ const sqlUrlDb = ownedExecutor ? ownedExecutor.db() : void 0;
227
+ try {
228
+ let result = emptyResult();
229
+ const plugins = pluginRuntimeRegistrationsFromPluginSet(pluginSet).filter((plugin) => plugin.hooks?.migrateStorage).sort(
230
+ (left, right) => left.manifest.name.localeCompare(right.manifest.name)
231
+ );
232
+ for (const plugin of plugins) {
233
+ const pluginName = plugin.manifest.name;
234
+ const hook = plugin.hooks?.migrateStorage;
235
+ if (!hook) {
236
+ continue;
237
+ }
238
+ const db = dbForPlugin(context, sqlUrlDb);
239
+ const pluginResult = await hook({
240
+ db,
241
+ log: createPluginLogger(pluginName),
242
+ plugin: { name: pluginName },
243
+ state: createPluginState(pluginName, context.stateAdapter)
244
+ });
245
+ if (pluginResult) {
246
+ result = addResult(result, pluginResult);
247
+ }
248
+ }
249
+ return result;
250
+ } finally {
251
+ setPluginCatalogConfig(previousConfig);
252
+ await ownedExecutor?.close();
253
+ }
254
+ }
255
+ var pluginStorageMigration = {
256
+ name: "run-plugin-storage-migrations",
257
+ run: runPluginStorageMigrations
258
+ };
259
+
260
+ // src/chat/plugins/db.ts
261
+ import { createHash } from "crypto";
262
+ import { readdirSync, readFileSync, statSync } from "fs";
263
+ import path from "path";
264
+ import { z } from "zod";
265
+ var PLUGIN_SCHEMA_LOCK_NAME = "junior_plugin_schema";
266
+ var MIGRATION_FILENAME_RE = /^[0-9]{4}_[a-z0-9_]+\.sql$/;
267
+ var migrationRecordSchema = z.object({
268
+ id: z.string().min(1),
269
+ checksum: z.string().min(1)
270
+ }).strict();
271
+ function checksumSql(sql) {
272
+ return createHash("sha256").update(sql).digest("hex");
273
+ }
274
+ function parseStoredMigrationRecord(value) {
275
+ return migrationRecordSchema.parse(value);
276
+ }
277
+ function assertMigrationFilename(filename) {
278
+ if (!filename || filename !== path.basename(filename) || !MIGRATION_FILENAME_RE.test(filename)) {
279
+ throw new Error(`Plugin migration filename "${filename}" is invalid`);
280
+ }
281
+ }
282
+ function assertUniqueMigrationIds(migrations) {
283
+ const seen = /* @__PURE__ */ new Set();
284
+ for (const migration of migrations) {
285
+ if (seen.has(migration.id)) {
286
+ throw new Error(`Duplicate plugin migration id ${migration.id}`);
287
+ }
288
+ seen.add(migration.id);
289
+ }
290
+ }
291
+ function migrationId(pluginName, filename) {
292
+ return `plugin:${pluginName}/${filename}`;
293
+ }
294
+ function createMigrationTableSql() {
295
+ return `
296
+ CREATE TABLE IF NOT EXISTS junior_schema_migrations (
297
+ id TEXT PRIMARY KEY,
298
+ checksum TEXT NOT NULL,
299
+ applied_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
300
+ )
301
+ `;
302
+ }
303
+ async function listAppliedMigrations(executor) {
304
+ const rows = await executor.query(
305
+ "SELECT id, checksum FROM junior_schema_migrations ORDER BY id ASC"
306
+ );
307
+ const records = /* @__PURE__ */ new Map();
308
+ for (const row of rows) {
309
+ const record = parseStoredMigrationRecord(row);
310
+ records.set(record.id, record);
311
+ }
312
+ return records;
313
+ }
314
+ async function applyPluginMigration(executor, migration) {
315
+ await executor.transaction(async () => {
316
+ await executor.execute(migration.sql);
317
+ await executor.execute(
318
+ "INSERT INTO junior_schema_migrations (id, checksum) VALUES ($1, $2)",
319
+ [migration.id, migration.checksum]
320
+ );
321
+ });
322
+ }
323
+ function readPluginMigrations(root) {
324
+ const migrationsDir = root.dir;
325
+ let stat;
326
+ try {
327
+ stat = statSync(migrationsDir);
328
+ } catch {
329
+ return [];
330
+ }
331
+ if (!stat.isDirectory()) {
332
+ throw new Error(
333
+ `Plugin "${root.pluginName}" migrations path is not a directory`
334
+ );
335
+ }
336
+ return readdirSync(migrationsDir).filter((filename) => filename.endsWith(".sql")).sort((left, right) => left.localeCompare(right)).map((filename) => {
337
+ assertMigrationFilename(filename);
338
+ const sql = readFileSync(path.join(migrationsDir, filename), "utf8");
339
+ if (!sql.trim()) {
340
+ throw new Error(
341
+ `Plugin "${root.pluginName}" migration "${filename}" is empty`
342
+ );
343
+ }
344
+ return {
345
+ checksum: checksumSql(sql),
346
+ filename,
347
+ id: migrationId(root.pluginName, filename),
348
+ pluginName: root.pluginName,
349
+ sql
350
+ };
351
+ });
352
+ }
353
+ async function migratePluginSchemas(executor, migrations) {
354
+ assertUniqueMigrationIds(migrations);
355
+ const result = {
356
+ existing: 0,
357
+ migrated: 0,
358
+ scanned: migrations.length
359
+ };
360
+ await executor.withLock(PLUGIN_SCHEMA_LOCK_NAME, async () => {
361
+ await executor.execute(createMigrationTableSql());
362
+ const applied = await listAppliedMigrations(executor);
363
+ for (const migration of migrations) {
364
+ const existing = applied.get(migration.id);
365
+ if (existing) {
366
+ if (existing.checksum !== migration.checksum) {
367
+ throw new Error(`Plugin migration ${migration.id} checksum changed`);
368
+ }
369
+ result.existing++;
370
+ continue;
371
+ }
372
+ await applyPluginMigration(executor, migration);
373
+ result.migrated++;
374
+ }
375
+ });
376
+ return result;
377
+ }
378
+
379
+ // src/cli/upgrade/migrations/plugin-sql.ts
380
+ var REQUIRED_SQL_DATABASE_URL_MESSAGE2 = "Junior SQL database URL is required for plugin schema migration. Set JUNIOR_DATABASE_URL or DATABASE_URL.";
381
+ function requirePluginSqlDatabaseUrl(context) {
382
+ const databaseUrl = context.sqlDatabaseUrl ?? getChatConfig().sql.databaseUrl;
383
+ if (!databaseUrl) {
384
+ throw new Error(REQUIRED_SQL_DATABASE_URL_MESSAGE2);
385
+ }
386
+ return databaseUrl;
387
+ }
388
+ async function migratePluginsToSql(context) {
389
+ const databaseUrl = requirePluginSqlDatabaseUrl(context);
390
+ const { pluginCatalogConfig } = await resolveUpgradePlugins(context);
391
+ const previousConfig = setPluginCatalogConfig(pluginCatalogConfig);
392
+ const executor = createJuniorSqlExecutor({
393
+ connectionString: databaseUrl,
394
+ driver: context.sqlDriver ?? getChatConfig().sql.driver
395
+ });
396
+ try {
397
+ const migrations = getPluginMigrationRoots().flatMap(
398
+ (root) => readPluginMigrations(root)
399
+ );
400
+ const result = await migratePluginSchemas(executor, migrations);
401
+ return {
402
+ existing: result.existing,
403
+ migrated: result.migrated,
404
+ missing: 0,
405
+ scanned: result.scanned
406
+ };
407
+ } finally {
408
+ setPluginCatalogConfig(previousConfig);
409
+ await executor.close();
410
+ }
411
+ }
412
+ var sqlPluginMigration = {
413
+ name: "migrate-plugin-sql",
414
+ run: migratePluginsToSql
415
+ };
416
+
91
417
  // src/cli/upgrade/migrations/redis-conversation-state.ts
92
418
  var CONVERSATION_PREFIX = "junior:conversation";
93
419
  var CONVERSATION_SCHEMA_VERSION = 1;
@@ -624,10 +950,34 @@ var redisConversationStateMigration = {
624
950
  var DEFAULT_IO = {
625
951
  info: console.log
626
952
  };
953
+ var localPluginLoader = createJiti(import.meta.url, { moduleCache: false });
627
954
  var MIGRATIONS = [
628
955
  redisConversationStateMigration,
629
- sqlConversationMigration
956
+ sqlConversationMigration,
957
+ sqlPluginMigration,
958
+ pluginStorageMigration
630
959
  ];
960
+ function isMissingVirtualConfig(error) {
961
+ if (!(error instanceof Error)) {
962
+ return false;
963
+ }
964
+ const code = error.code;
965
+ return (code === "ERR_PACKAGE_IMPORT_NOT_DEFINED" || code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND") && error.message.includes("#junior/config");
966
+ }
967
+ async function resolveUpgradePluginSet() {
968
+ try {
969
+ const mod = await import("#junior/config");
970
+ return mod.pluginSet;
971
+ } catch (error) {
972
+ if (!isMissingVirtualConfig(error)) {
973
+ throw error;
974
+ }
975
+ }
976
+ return await loadAppPluginSet(
977
+ process.cwd(),
978
+ async (moduleRef) => localPluginLoader.import(moduleRef.importPath)
979
+ );
980
+ }
631
981
  function formatMigrationResult(result) {
632
982
  const fields = [
633
983
  `scanned=${result.scanned}`,
@@ -641,29 +991,38 @@ function formatMigrationResult(result) {
641
991
  return fields.join(" ");
642
992
  }
643
993
  async function runUpgradeMigrations(context) {
644
- requireConversationSqlDatabaseUrl(context);
994
+ const plugins = await resolveUpgradePlugins(context);
995
+ const migrationContext = { ...context, ...plugins };
996
+ migrationContext.sqlDatabaseUrl ??= requireConversationSqlDatabaseUrl(migrationContext);
645
997
  const results = [];
646
998
  for (const migration of MIGRATIONS) {
647
- context.io.info(`Running migration ${migration.name}...`);
648
- const result = await migration.run(context);
649
- context.io.info(
999
+ migrationContext.io.info(`Running migration ${migration.name}...`);
1000
+ const result = await migration.run(migrationContext);
1001
+ migrationContext.io.info(
650
1002
  `Finished migration ${migration.name}: ${formatMigrationResult(result)}`
651
1003
  );
652
1004
  results.push(result);
653
1005
  }
654
1006
  return results;
655
1007
  }
656
- async function runUpgrade(io = DEFAULT_IO) {
1008
+ async function runUpgrade(io = DEFAULT_IO, options = {}) {
657
1009
  try {
658
1010
  const { redisStateAdapter, stateAdapter } = await getConnectedStateContext();
1011
+ const pluginSet = options.pluginSet === void 0 ? await resolveUpgradePluginSet() : options.pluginSet ?? void 0;
659
1012
  io.info("Running Junior upgrade migrations...");
660
- await runUpgradeMigrations({ io, redisStateAdapter, stateAdapter });
1013
+ await runUpgradeMigrations({
1014
+ io,
1015
+ pluginSet,
1016
+ redisStateAdapter,
1017
+ stateAdapter
1018
+ });
661
1019
  io.info("Junior upgrade complete.");
662
1020
  } finally {
663
1021
  await disconnectStateAdapter();
664
1022
  }
665
1023
  }
666
1024
  export {
1025
+ resolveUpgradePluginSet,
667
1026
  runUpgrade,
668
1027
  runUpgradeMigrations
669
1028
  };
@@ -0,0 +1,17 @@
1
+ import {
2
+ closeDb,
3
+ getConversationStore,
4
+ getDb
5
+ } from "./chunk-NYKJ3KON.js";
6
+ import "./chunk-Q6XFTRV5.js";
7
+ import "./chunk-T77LUIX3.js";
8
+ import "./chunk-VALUBQ7R.js";
9
+ import "./chunk-EJN6G5A2.js";
10
+ import "./chunk-OJ53FYVG.js";
11
+ import "./chunk-ST6YNAXG.js";
12
+ import "./chunk-MLKGABMK.js";
13
+ export {
14
+ closeDb,
15
+ getConversationStore,
16
+ getDb
17
+ };
@@ -1,6 +1,7 @@
1
1
  export declare const JUNIOR_HEARTBEAT_ROUTE = "/api/internal/heartbeat";
2
2
  export declare const JUNIOR_HEARTBEAT_CRON_SCHEDULE = "* * * * *";
3
3
  export declare const JUNIOR_CONVERSATION_WORK_CALLBACK_ROUTE = "/api/internal/agent/continue";
4
+ export declare const JUNIOR_PLUGIN_TASK_CALLBACK_ROUTE = "/api/internal/plugin/tasks";
4
5
  export declare const LEGACY_JUNIOR_CONVERSATION_WORK_FUNCTION = "api/internal/agent/continue.ts";
5
6
  /** Resolve the deployment version used for release and telemetry correlation. */
6
7
  export declare function getDeploymentServiceVersion(): string | undefined;
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Route authenticated sandbox egress proxy traffic before ordinary app routes.
3
+ */
4
+ export declare function handleSandboxEgressRoute(request: Request, tracePropagationDomains: string[], next: () => Promise<void>): Promise<Response | void>;
@@ -0,0 +1,4 @@
1
+ import { type SlackWebhookServices } from "@/chat/ingress/slack-webhook";
2
+ import type { WaitUntilFn } from "@/handlers/types";
3
+ /** Handle the production Slack webhook route. */
4
+ export declare function POST(request: Request, waitUntil: WaitUntilFn, services: SlackWebhookServices): Promise<Response>;
@@ -1,19 +1,12 @@
1
1
  import type { SlackAdapter } from "@chat-adapter/slack";
2
- import { type SlackWebhookServices } from "@/chat/ingress/slack-webhook";
3
2
  import { JuniorChat } from "@/chat/ingress/junior-chat";
4
3
  import type { WaitUntilFn } from "@/handlers/types";
5
- type LegacyChatSdkBot = JuniorChat<{
4
+ type ChatSdkBot = JuniorChat<{
6
5
  slack: SlackAdapter;
7
6
  }>;
8
- /**
9
- * Handles `POST /api/webhooks/:platform`.
10
- *
11
- * Slack production ingress persists messages into the durable conversation
12
- * mailbox and wakes the queue worker. The optional `legacyBot` parameter is
13
- * kept for integration tests that still exercise Chat SDK fixtures directly.
14
- * The optional `services` parameter carries app-scoped runtime services.
15
- */
16
- export declare function handlePlatformWebhook(request: Request, platform: string, waitUntil: WaitUntilFn, legacyBot?: LegacyChatSdkBot, services?: SlackWebhookServices): Promise<Response>;
17
- /** Handle a platform webhook request from the app route. */
18
- export declare function POST(request: Request, platform: string, waitUntil: WaitUntilFn, services?: SlackWebhookServices): Promise<Response>;
7
+ type WebhookRunner = () => Promise<Response>;
8
+ /** Run a platform webhook with shared request tracing and error logging. */
9
+ export declare function handleWebhookRequest(request: Request, platform: string, run: WebhookRunner): Promise<Response>;
10
+ /** Handle a Chat SDK webhook fixture through the shared webhook wrapper. */
11
+ export declare function handleChatSdkPlatformWebhook(request: Request, platform: string, waitUntil: WaitUntilFn, chat: ChatSdkBot): Promise<Response>;
19
12
  export {};