@sentry/junior 0.263.0 → 0.265.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 (67) hide show
  1. package/README.md +1 -1
  2. package/dist/{adapter-BIacI0Bt.js → adapter-cUkPH3Om.js} +1 -1
  3. package/dist/{admin-C7vUk7s9.js → admin-Cf0rDmWV.js} +1 -1
  4. package/dist/{agent-runner-BUBas7Yy.js → agent-runner-C6MwHJEs.js} +296 -238
  5. package/dist/api/schema.d.ts +213 -16
  6. package/dist/api/schema.js +3 -3
  7. package/dist/api.js +107 -40
  8. package/dist/{app-Bo0kB987.d.ts → app-Csbi9dW7.d.ts} +4 -3
  9. package/dist/app.d.ts +1 -1
  10. package/dist/app.js +101 -393
  11. package/dist/{assistant-reply-BFmjgJjD.js → assistant-reply-UPA8vKlC.js} +1 -1
  12. package/dist/{automation-CWX0qL8U.js → automation-2RbKzpMT.js} +30 -9
  13. package/dist/{briefs-h55v5lX9.js → briefs-DRjx8kQ9.js} +3 -3
  14. package/dist/{catalog-runtime-Suf-aLlh.js → catalog-runtime-D3qbJlYz.js} +1 -1
  15. package/dist/cli/chat.js +15 -15
  16. package/dist/cli/check.js +3 -3
  17. package/dist/cli/init.js +4 -18
  18. package/dist/cli/main.js +4 -4
  19. package/dist/cli/plugins.js +4 -4
  20. package/dist/cli/snapshot-create.js +4 -4
  21. package/dist/cli/upgrade.js +3 -3
  22. package/dist/{client-DZBCBj1M.js → client-DX34VNtH.js} +3 -8
  23. package/dist/{config-Dnv8KmNs.js → config-BayQ9hHH.js} +100 -3
  24. package/dist/{connections-Br0_xv27.js → connections-mpN5Lsnj.js} +11 -10
  25. package/dist/{conversation-privacy-FY8yc2q3.js → conversation-privacy-frjQCJa9.js} +1 -1
  26. package/dist/{credential-sync-BvkiyWF5.js → credential-sync-CZmyDNdR.js} +20 -20
  27. package/dist/{agent-hooks-CqnZfuCt.js → credentialed-C6pKlB1p.js} +3197 -66
  28. package/dist/{executor-J9k2sp9m.js → executor-CAr7xQr2.js} +10 -300
  29. package/dist/{images-DV2FlEGL.js → images-B2yA3HWE.js} +2 -2
  30. package/dist/instrumentation.js +41 -25
  31. package/dist/{job-queue-B4yTgklN.js → job-queue-Cjo6Yg_b.js} +53 -14
  32. package/dist/{logging-Dk_FpF36.js → logging-D2QBriUo.js} +19 -32
  33. package/dist/{message-BzseAFH1.js → message-C9ymnpBS.js} +4 -4
  34. package/dist/nitro.d.ts +17 -2
  35. package/dist/nitro.js +26 -27
  36. package/dist/{oauth-callback-server-bTspTMCC.js → oauth-callback-server-BtMf3TPZ.js} +2 -2
  37. package/dist/{prompt-CxatQVaj.js → prompt-CvaDdSX3.js} +1 -1
  38. package/dist/{registry-BFzQFV_y.js → registry-COTeZ2cV.js} +1 -1
  39. package/dist/{resolve-CnRHib0U.js → resolve-g9PKz9pH.js} +7 -106
  40. package/dist/{result-DczfmNBa.js → result-COnC42GR.js} +8 -8
  41. package/dist/{runner-CJd9Wec-.js → runner-BnTNS7x_.js} +10 -10
  42. package/dist/{sandbox-egress-signals-DUmVkOx4.js → sandbox-egress-signals-C_IIdLFk.js} +1 -1
  43. package/dist/{schema-QidbykYl.js → schema-D5Amlzkp.js} +44 -3
  44. package/dist/{sentry-BBUlHih9.js → sentry-MDkYAVPV.js} +3 -6
  45. package/dist/{service-account-BI2kQDrb.js → service-account-CwvToidT.js} +3 -3
  46. package/dist/{service-account-x2QZXm4X.js → service-account-YdYftwV2.js} +5 -5
  47. package/dist/{session-stop-CtyJsnEj.js → session-stop-CpCUy1ZJ.js} +121 -81
  48. package/dist/{skills-Dbzx9-rS.js → skills-Bb2KaJ3m.js} +2 -2
  49. package/dist/{spawn-D8WU99UV.js → spawn-mbTcrLb3.js} +2 -2
  50. package/dist/{store-TKg1HVKx.js → store-CqRnaZSq.js} +3 -3
  51. package/dist/{store-UlOrW6JC.js → store-DdT74Lvq.js} +18 -9
  52. package/dist/{task-queue-BRB49H-J.js → task-queue-8XjDIORF.js} +14 -19
  53. package/dist/{task-runner-C575f2Dd.js → task-runner-6mLmG6g_.js} +46 -28
  54. package/dist/{tasks-LOItiYgL.js → tasks-DGbrur6x.js} +14 -2075
  55. package/dist/{thread-state-IDHdZA7R.js → thread-state-D45lz-oC.js} +5 -5
  56. package/dist/{turn-failure-response-h_LSXJ-M.js → turn-failure-response-CaEPLSBn.js} +7 -7
  57. package/dist/{turn-lifecycle-Cvi6Sb8Y.js → turn-lifecycle-C35IyRGp.js} +1 -1
  58. package/dist/{turn-session-routing-5Nyv4fso.js → turn-session-routing-BKx6rfVd.js} +1 -1
  59. package/dist/{validation-BeTriWC2.js → validation-C0X3CX51.js} +1 -1
  60. package/dist/{version-BQX_hLDC.js → version-BPHgJwnm.js} +1 -1
  61. package/dist/version.js +1 -1
  62. package/dist/{viewer-DmNRM88V.js → viewer-B2wXNspU.js} +21 -5
  63. package/dist/{web-input-BHcGXSox.js → web-input-Y6aXvmfa.js} +145 -46
  64. package/dist/{work-DLJMV02b.js → work-DMbqK0kT.js} +10 -10
  65. package/dist/{worker-vfG2ESg1.js → worker-B-rDJ3XN.js} +8 -6
  66. package/package.json +10 -9
  67. package/dist/profile-Dq5I7TV1.js +0 -582
@@ -425,13 +425,18 @@ const scheduledAutomationSummarySchema = automationSummaryBaseSchema.extend({
425
425
  "completed"
426
426
  ])
427
427
  }).strict();
428
- const eventAutomationSummarySchema = automationSummaryBaseSchema.extend({
428
+ /** An Event trigger in plain words, the same in the dashboard and Slack. */
429
+ const eventTriggerDescriptionSchema = z.object({
429
430
  events: z.array(z.string().min(1)).min(1),
430
- match: eventMatchSchema.optional(),
431
+ filters: z.array(z.string().min(1)),
432
+ /** Why the trigger cannot work. The trigger is available when empty. */
433
+ problems: z.array(z.string().min(1))
434
+ }).strict();
435
+ const eventAutomationSummarySchema = automationSummaryBaseSchema.extend({
436
+ trigger: eventTriggerDescriptionSchema,
431
437
  kind: z.literal("event"),
432
438
  resource: z.string().min(1),
433
439
  source: z.string().min(1),
434
- triggerAvailable: z.boolean(),
435
440
  statusReason: z.string().optional(),
436
441
  status: z.enum([
437
442
  "active",
@@ -509,13 +514,22 @@ const automationExecutionStatusSchema = z.enum([
509
514
  "failed"
510
515
  ]);
511
516
  const automationExecutionSchema = z.object({
517
+ /** Automation version that the run dispatched, when recorded. */
518
+ automationVersion: z.number().int().positive().optional(),
512
519
  conversationId: z.string().min(1).optional(),
513
520
  /** Estimated model cost for the linked conversation, when known. */
514
521
  costUsd: z.number().finite().nonnegative().optional(),
522
+ /** Accounts that the dispatched version could use. */
523
+ credentialMode: z.enum(["creator", "system"]).optional(),
515
524
  /** Cumulative conversation runtime in milliseconds, when known. */
516
525
  durationMs: z.number().finite().nonnegative().optional(),
526
+ /** Reason that the run failed or was blocked, when recorded. */
527
+ error: z.string().min(1).optional(),
517
528
  executedAt: z.string().datetime(),
518
529
  executionId: z.string().min(1),
530
+ /** Planned occurrence of a Scheduled automation run. */
531
+ scheduledFor: z.string().datetime().optional(),
532
+ startedAt: z.string().datetime().optional(),
519
533
  status: automationExecutionStatusSchema,
520
534
  title: z.string().min(1).optional(),
521
535
  /** Cumulative conversation token total, when known. */
@@ -555,8 +569,7 @@ const automationVersionFields = {
555
569
  /** Null for versions saved by the upgrade, because the editor is unknown. */
556
570
  editedBy: eventAutomationPrincipalSchema.nullable()
557
571
  };
558
- /** One saved Automation definition. Newer versions have larger numbers. */
559
- const automationVersionSchema = z.discriminatedUnion("kind", [z.object({
572
+ const scheduledAutomationVersionSchema = z.object({
560
573
  ...automationVersionFields,
561
574
  kind: z.literal("scheduled"),
562
575
  definition: scheduledAutomationSchema.pick({
@@ -565,7 +578,8 @@ const automationVersionSchema = z.discriminatedUnion("kind", [z.object({
565
578
  outcomes: true,
566
579
  schedule: true
567
580
  }).extend(automationDefinitionFields).strict()
568
- }).strict(), z.object({
581
+ }).strict();
582
+ const eventAutomationVersionSchema = z.object({
569
583
  ...automationVersionFields,
570
584
  kind: z.literal("event"),
571
585
  definition: eventAutomationSchema.pick({
@@ -574,10 +588,18 @@ const automationVersionSchema = z.discriminatedUnion("kind", [z.object({
574
588
  outcomes: true,
575
589
  trigger: true
576
590
  }).extend(automationDefinitionFields).strict()
577
- }).strict()]);
591
+ }).strict();
592
+ /** One saved Automation definition. Newer versions have larger numbers. */
593
+ const automationVersionSchema = z.discriminatedUnion("kind", [scheduledAutomationVersionSchema, eventAutomationVersionSchema]);
594
+ /**
595
+ * One version in the version history. An Event version also has its saved
596
+ * trigger in plain words. The definition stays as saved, so it can be made
597
+ * active again.
598
+ */
599
+ const listedAutomationVersionSchema = z.discriminatedUnion("kind", [scheduledAutomationVersionSchema, eventAutomationVersionSchema.extend({ trigger: eventTriggerDescriptionSchema }).strict()]);
578
600
  /** Newest versions first. */
579
601
  const automationVersionListSchema = z.object({
580
- versions: z.array(automationVersionSchema),
602
+ versions: z.array(listedAutomationVersionSchema),
581
603
  /** Newest version that matches the current definition. Null when none match. */
582
604
  activeVersion: z.number().int().positive().nullable(),
583
605
  truncated: z.boolean()
@@ -617,7 +639,6 @@ const automationEditSchema = z.discriminatedUnion("kind", [automationEditBaseSch
617
639
  }).strict(), automationEditBaseSchema.extend({
618
640
  kind: z.literal("event"),
619
641
  trigger: eventAutomationTriggerSchema,
620
- triggerAvailable: z.boolean(),
621
642
  status: z.enum([
622
643
  "active",
623
644
  "blocked",
@@ -1,7 +1,7 @@
1
- import { i as completeObject } from "./client-DZBCBj1M.js";
1
+ import { i as completeObject } from "./client-DX34VNtH.js";
2
2
  import { r as defaultModelId } from "./model-profile-Bg8EoCKD.js";
3
3
  import { J as parseBriefInput, W as briefCodeChangeSchema, d as conversationDetailReportSchema, p as conversationEventPageSchema } from "./conversation-B0baEwoA.js";
4
- import { n as briefEntriesFromReportEvents, s as generateBrief, t as BRIEF_PROMPT } from "./prompt-CxatQVaj.js";
4
+ import { n as briefEntriesFromReportEvents, s as generateBrief, t as BRIEF_PROMPT } from "./prompt-CvaDdSX3.js";
5
5
  import { CLI_USAGE } from "./cli/run.js";
6
6
  import path from "node:path";
7
7
  import { z } from "zod";
@@ -267,7 +267,7 @@ async function parseRunOptions(argv) {
267
267
  * `DATABASE_URL` at import, and `briefs pull` must work with only a token.
268
268
  */
269
269
  async function configuredDefaultModelId() {
270
- const { botConfig } = await import("./config-Dnv8KmNs.js").then((n) => n.r);
270
+ const { botConfig } = await import("./config-BayQ9hHH.js").then((n) => n.r);
271
271
  return defaultModelId(botConfig);
272
272
  }
273
273
  function apiUrl(baseUrl, pathname) {
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-nwUcYXjP.js";
2
- import { t as createPluginCatalogRuntime } from "./registry-BFzQFV_y.js";
2
+ import { t as createPluginCatalogRuntime } from "./registry-COTeZ2cV.js";
3
3
  // src/chat/plugins/catalog-runtime.ts
4
4
  var catalog_runtime_exports = /* @__PURE__ */ __exportAll({ pluginCatalogRuntime: () => pluginCatalogRuntime });
5
5
  const pluginCatalogRuntime = createPluginCatalogRuntime();
package/dist/cli/chat.js CHANGED
@@ -1,4 +1,4 @@
1
- import { n as executeAgentRun, t as createAgentRunner } from "../agent-runner-BUBas7Yy.js";
1
+ import { n as executeAgentRun, t as createAgentRunner } from "../agent-runner-C6MwHJEs.js";
2
2
  import { t as loadAppPluginSet } from "../plugin-module-Cf5gVPWP.js";
3
3
  import path from "node:path";
4
4
  import { createHash, randomUUID } from "node:crypto";
@@ -99,10 +99,10 @@ async function loadLocalPluginSet() {
99
99
  async function configureLocalChatPlugins(pluginSet) {
100
100
  const [pluginsModule, agentHooksModule, catalogRuntimeModule, validationModule, databaseModule] = await Promise.all([
101
101
  import("../plugins-DOm9Y6qI.js").then((n) => n.o),
102
- import("../agent-hooks-CqnZfuCt.js").then((n) => n.t),
103
- import("../catalog-runtime-Suf-aLlh.js").then((n) => n.t),
104
- import("../validation-BeTriWC2.js").then((n) => n.r),
105
- import("../viewer-DmNRM88V.js").then((n) => n.s)
102
+ import("../credentialed-C6pKlB1p.js").then((n) => n.a),
103
+ import("../catalog-runtime-D3qbJlYz.js").then((n) => n.t),
104
+ import("../validation-C0X3CX51.js").then((n) => n.r),
105
+ import("../viewer-B2wXNspU.js").then((n) => n.c)
106
106
  ]);
107
107
  const resolvedPluginSet = pluginSet === void 0 ? await loadLocalPluginSet() : pluginSet ?? void 0;
108
108
  const plugins = pluginsModule.pluginRuntimeRegistrationsFromPluginSet(resolvedPluginSet);
@@ -152,19 +152,19 @@ function localDevServerUrl() {
152
152
  async function prepareLocalChatRun(io, pluginSet) {
153
153
  defaultStateAdapterForLocalChat();
154
154
  await configureLocalChatPlugins(pluginSet);
155
- const { setBriefsConfig } = await import("../agent-hooks-CqnZfuCt.js").then((n) => n.m);
155
+ const { setBriefsConfig } = await import("../credentialed-C6pKlB1p.js").then((n) => n._);
156
156
  setBriefsConfig({ enabled: true });
157
- const { runLocalAgentTurn } = await import("../runner-CJd9Wec-.js");
158
- const { startLocalOAuthCallbackServer } = await import("../oauth-callback-server-bTspTMCC.js");
157
+ const { runLocalAgentTurn } = await import("../runner-BnTNS7x_.js");
158
+ const { startLocalOAuthCallbackServer } = await import("../oauth-callback-server-BtMf3TPZ.js");
159
159
  const { createLocalOAuthState } = await import("../oauth-relay-CTygMkNx.js").then((n) => n.t);
160
- const { createLocalSandboxEgressSignalTransport } = await import("../sandbox-egress-signals-DUmVkOx4.js");
161
- const { bindSpawnAgent } = await import("../spawn-D8WU99UV.js").then((n) => n.n);
162
- const { bindMessageAgent } = await import("../message-BzseAFH1.js").then((n) => n.n);
163
- const { createAgentInvocationWorker, routeAgentInvocationWork } = await import("../work-DLJMV02b.js").then((n) => n.a);
164
- const { startAgentInvocationsForChildInput } = await import("../result-DczfmNBa.js").then((n) => n.r);
165
- const { skipInputBeforeConversationStop } = await import("../session-stop-CtyJsnEj.js").then((n) => n.r);
160
+ const { createLocalSandboxEgressSignalTransport } = await import("../sandbox-egress-signals-C_IIdLFk.js");
161
+ const { bindSpawnAgent } = await import("../spawn-mbTcrLb3.js").then((n) => n.n);
162
+ const { bindMessageAgent } = await import("../message-C9ymnpBS.js").then((n) => n.n);
163
+ const { createAgentInvocationWorker, routeAgentInvocationWork } = await import("../work-DMbqK0kT.js").then((n) => n.a);
164
+ const { startAgentInvocationsForChildInput } = await import("../result-COnC42GR.js").then((n) => n.r);
165
+ const { skipInputBeforeConversationStop } = await import("../session-stop-CpCUy1ZJ.js").then((n) => n.r);
166
166
  const { createLocalConversationWork } = await import("../conversation-work-BaT_T6EB.js");
167
- const { processConversationWork } = await import("../worker-vfG2ESg1.js").then((n) => n.n);
167
+ const { processConversationWork } = await import("../worker-B-rDJ3XN.js").then((n) => n.n);
168
168
  let agentRunner;
169
169
  const localConversationWork = createLocalConversationWork(async (message) => {
170
170
  if (!agentRunner) throw new Error("Local agent runner is not ready");
package/dist/cli/check.js CHANGED
@@ -1,6 +1,6 @@
1
- import { E as JUNIOR_CONVERSATION_WORK_CALLBACK_ROUTE, N as LEGACY_JUNIOR_CONVERSATION_WORK_FUNCTION, O as JUNIOR_HEARTBEAT_ROUTE } from "../logging-Dk_FpF36.js";
2
- import { v as parseInlinePluginManifest, y as parsePluginManifest } from "../registry-BFzQFV_y.js";
3
- import { i as parseSkillFile } from "../skills-Dbzx9-rS.js";
1
+ import { E as JUNIOR_CONVERSATION_WORK_CALLBACK_ROUTE, N as LEGACY_JUNIOR_CONVERSATION_WORK_FUNCTION, O as JUNIOR_HEARTBEAT_ROUTE } from "../logging-D2QBriUo.js";
2
+ import { v as parseInlinePluginManifest, y as parsePluginManifest } from "../registry-COTeZ2cV.js";
3
+ import { i as parseSkillFile } from "../skills-Bb2KaJ3m.js";
4
4
  import path from "node:path";
5
5
  import fs from "node:fs/promises";
6
6
  import { pathToFileURL } from "node:url";
package/dist/cli/init.js CHANGED
@@ -24,12 +24,6 @@ const app = await createApp({
24
24
  export default app;
25
25
  `);
26
26
  }
27
- function writeInstrumentFile(targetDir) {
28
- fs.writeFileSync(path.join(targetDir, "instrument.mjs"), `import { initSentry } from "@sentry/junior/instrumentation";
29
-
30
- initSentry();
31
- `);
32
- }
33
27
  function writePluginsFile(targetDir) {
34
28
  fs.writeFileSync(path.join(targetDir, "plugins.ts"), `import { defineJuniorPlugins } from "@sentry/junior";
35
29
  import { memoryPlugin } from "@sentry/junior-memory";
@@ -41,9 +35,8 @@ export const plugins = defineJuniorPlugins([
41
35
  `);
42
36
  }
43
37
  function writeNitroConfig(targetDir) {
44
- fs.writeFileSync(path.join(targetDir, "nitro.config.ts"), `import { withSentryConfig } from "@sentry/nitro";
45
- import { defineConfig } from "nitro";
46
- import { juniorNitro } from "@sentry/junior/nitro";
38
+ fs.writeFileSync(path.join(targetDir, "nitro.config.ts"), `import { defineConfig } from "nitro";
39
+ import { juniorNitro, withSentryConfig } from "@sentry/junior/nitro";
47
40
 
48
41
  const config = defineConfig({
49
42
  preset: "vercel",
@@ -74,8 +67,6 @@ function writePnpmWorkspace(targetDir) {
74
67
  fs.writeFileSync(path.join(targetDir, "pnpm-workspace.yaml"), `minimumReleaseAge: 1440
75
68
  minimumReleaseAgeExclude:
76
69
  - "@sentry/*"
77
- allowBuilds:
78
- "@sentry/cli": true
79
70
  `);
80
71
  }
81
72
  function writeVercelJson(targetDir) {
@@ -123,24 +114,20 @@ async function runInit(dir, log = console.log) {
123
114
  private: true,
124
115
  type: "module",
125
116
  scripts: {
126
- dev: "cross-env NODE_OPTIONS=--import=./instrument.mjs nitro dev",
117
+ dev: "nitro dev",
127
118
  check: "junior check",
128
119
  build: "junior snapshot create && nitro build",
129
- preview: "cross-env NODE_OPTIONS=--import=./instrument.mjs nitro preview",
120
+ preview: "nitro preview",
130
121
  typecheck: "tsc --noEmit"
131
122
  },
132
123
  dependencies: {
133
- "@opentelemetry/api": "1.9.1",
134
- "@opentelemetry/core": "2.9.0",
135
124
  "@sentry/junior": "latest",
136
125
  "@sentry/junior-memory": "latest",
137
126
  "@sentry/junior-maintenance": "latest",
138
- "@sentry/nitro": "10.65.0",
139
127
  hono: "^4.13.11"
140
128
  },
141
129
  devDependencies: {
142
130
  "@types/node": "^25.9.1",
143
- "cross-env": "^10.1.0",
144
131
  jiti: "^2.7.0",
145
132
  nitro: "3.0.260522-beta",
146
133
  typescript: "^7.0.2"
@@ -194,7 +181,6 @@ SENTRY_PROJECT=
194
181
  SENTRY_AUTH_TOKEN=
195
182
  `);
196
183
  writeServerEntry(target);
197
- writeInstrumentFile(target);
198
184
  writePluginsFile(target);
199
185
  writeNitroConfig(target);
200
186
  writeTsConfig(target);
package/dist/cli/main.js CHANGED
@@ -4,7 +4,7 @@ import { pathToFileURL } from "node:url";
4
4
  // src/cli/main.ts
5
5
  const SENTRY_FLUSH_TIMEOUT_MS = 2e3;
6
6
  async function flushSentry() {
7
- await (await import("../sentry-BBUlHih9.js").then((n) => n.u)).flush(SENTRY_FLUSH_TIMEOUT_MS);
7
+ await (await import("../sentry-MDkYAVPV.js").then((n) => n.u)).flush(SENTRY_FLUSH_TIMEOUT_MS);
8
8
  }
9
9
  async function initSentry() {
10
10
  (await import("../instrumentation.js")).initSentry();
@@ -25,13 +25,13 @@ async function runChat(argv, pluginSet) {
25
25
  return await (await import("./chat.js")).runChat(argv, void 0, { pluginSet });
26
26
  }
27
27
  async function runAdmin(argv) {
28
- return await (await import("../admin-C7vUk7s9.js")).runAdmin(argv);
28
+ return await (await import("../admin-Cf0rDmWV.js")).runAdmin(argv);
29
29
  }
30
30
  async function runServiceAccount(argv) {
31
- return await (await import("../service-account-BI2kQDrb.js")).runServiceAccount(argv);
31
+ return await (await import("../service-account-CwvToidT.js")).runServiceAccount(argv);
32
32
  }
33
33
  async function runBriefs(argv) {
34
- return await (await import("../briefs-h55v5lX9.js")).runBriefs(argv);
34
+ return await (await import("../briefs-DRjx8kQ9.js")).runBriefs(argv);
35
35
  }
36
36
  function topLevelCommand(argv) {
37
37
  return (argv[0] === "--" ? argv.slice(1) : argv)[0];
@@ -1,7 +1,7 @@
1
- import { d as getDb } from "../viewer-DmNRM88V.js";
2
- import { n as pluginCatalogRuntime } from "../catalog-runtime-Suf-aLlh.js";
3
- import { Et as createPluginLogger, d as setPlugins, f as validatePlugins } from "../agent-hooks-CqnZfuCt.js";
4
- import { n as validatePluginRegistrations, t as validatePluginEgressCredentialHooks } from "../validation-BeTriWC2.js";
1
+ import { f as getDb } from "../viewer-B2wXNspU.js";
2
+ import { n as pluginCatalogRuntime } from "../catalog-runtime-D3qbJlYz.js";
3
+ import { An as createPluginLogger, h as validatePlugins, m as setPlugins } from "../credentialed-C6pKlB1p.js";
4
+ import { n as validatePluginRegistrations, t as validatePluginEgressCredentialHooks } from "../validation-C0X3CX51.js";
5
5
  import { a as pluginRuntimeRegistrationsFromPluginSet, i as pluginCliRegistrationsFromPluginSet, r as pluginCatalogConfigFromPluginSet } from "../plugins-DOm9Y6qI.js";
6
6
  import { t as loadAppPluginSet } from "../plugin-module-Cf5gVPWP.js";
7
7
  import { stderr, stdout } from "node:process";
@@ -1,7 +1,7 @@
1
- import { n as pluginCatalogRuntime } from "../catalog-runtime-Suf-aLlh.js";
2
- import { t as disconnectStateAdapter } from "../adapter-BIacI0Bt.js";
3
- import { t as create } from "../profile-Dq5I7TV1.js";
4
- import { r as resolve } from "../resolve-CnRHib0U.js";
1
+ import { n as pluginCatalogRuntime } from "../catalog-runtime-D3qbJlYz.js";
2
+ import { M as create } from "../credentialed-C6pKlB1p.js";
3
+ import { t as disconnectStateAdapter } from "../adapter-cUkPH3Om.js";
4
+ import { n as resolve } from "../resolve-g9PKz9pH.js";
5
5
  // src/cli/snapshot-create.ts
6
6
  const DEFAULT_RUNTIME = "node22";
7
7
  const DEFAULT_TIMEOUT_MS = 6e5;
@@ -1,6 +1,6 @@
1
- import { i as getChatConfig } from "../config-Dnv8KmNs.js";
2
- import { t as createJuniorSqlExecutor } from "../executor-J9k2sp9m.js";
3
- import { t as createPluginCatalogRuntime } from "../registry-BFzQFV_y.js";
1
+ import { i as getChatConfig } from "../config-BayQ9hHH.js";
2
+ import { t as createJuniorSqlExecutor } from "../executor-CAr7xQr2.js";
3
+ import { t as createPluginCatalogRuntime } from "../registry-COTeZ2cV.js";
4
4
  import { n as pluginCatalogConfigFromEnv, r as pluginCatalogConfigFromPluginSet, t as defineJuniorPlugins } from "../plugins-DOm9Y6qI.js";
5
5
  import { t as loadAppPluginSet } from "../plugin-module-Cf5gVPWP.js";
6
6
  import { basename, dirname, join, resolve } from "node:path";
@@ -1,5 +1,5 @@
1
- import { T as withSpan, _ as serializeGenAiAttribute, f as logException, h as normalizeGenAiFinishReason, i as extractGenAiUsageAttributes, m as logWarn } from "./logging-Dk_FpF36.js";
2
- import { a as toCanonicalInputMessage, n as getCurrentConversationPrivacy, o as toCanonicalOutputMessage, s as toGenAiMessagesTraceAttributes } from "./conversation-privacy-FY8yc2q3.js";
1
+ import { T as withSpan, _ as serializeGenAiAttribute, f as logException, h as normalizeGenAiFinishReason, i as extractGenAiUsageAttributes, m as logWarn } from "./logging-D2QBriUo.js";
2
+ import { a as toCanonicalInputMessage, n as getCurrentConversationPrivacy, o as toCanonicalOutputMessage, s as toGenAiMessagesTraceAttributes } from "./conversation-privacy-frjQCJa9.js";
3
3
  import { calculateCost, completeSimple, getEnvApiKey, getModels, registerApiProvider } from "@earendil-works/pi-ai/compat";
4
4
  import { stream as streamAnthropic, streamSimple as streamSimpleAnthropic } from "@earendil-works/pi-ai/api/anthropic-messages";
5
5
  import { createGatewayProvider } from "@ai-sdk/gateway";
@@ -202,7 +202,7 @@ function getProviderErrorUserMessage(error) {
202
202
  case "timeout":
203
203
  case "network":
204
204
  case "server": return "The model provider had a temporary connection problem. Please try again.";
205
- case "auth": return "The model provider rejected Junior's credentials. This needs an administrator or configuration fix.";
205
+ case "auth": return "The model provider rejected the configured credentials. This needs an administrator or configuration fix.";
206
206
  case "permission": return "The model provider denied access to this model or request. Ask an administrator to check model access, organization policy, and region availability.";
207
207
  case "quota": return "The model provider's usage quota has been exhausted. This needs an administrator or billing configuration fix.";
208
208
  case "content_policy": return "The model provider blocked this request under its content policy. Please revise the request and try again.";
@@ -577,11 +577,6 @@ async function completeObject(params) {
577
577
  ...params.system !== void 0 ? { system: params.system } : void 0,
578
578
  ...params.temperature !== void 0 ? { temperature: params.temperature } : void 0,
579
579
  ...params.maxTokens !== void 0 ? { maxOutputTokens: params.maxTokens } : void 0,
580
- ...params.recordTelemetryPayloads === false ? { experimental_telemetry: {
581
- isEnabled: true,
582
- recordInputs: false,
583
- recordOutputs: false
584
- } } : void 0,
585
580
  ...params.signal !== void 0 ? { abortSignal: params.signal } : void 0
586
581
  });
587
582
  setSpanAttributes({
@@ -1,7 +1,103 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-nwUcYXjP.js";
2
- import { C as toOptionalTrimmed, s as resolveGatewayModel } from "./client-DZBCBj1M.js";
3
- import { m as logWarn } from "./logging-Dk_FpF36.js";
2
+ import { C as toOptionalTrimmed, s as resolveGatewayModel } from "./client-DX34VNtH.js";
3
+ import { m as logWarn } from "./logging-D2QBriUo.js";
4
4
  import { l as TURN_REASONING_LEVELS, s as modelProfileSchema, t as DEFAULT_MODEL_PROFILES, u as parseTurnReasoningLevel } from "./model-profile-Bg8EoCKD.js";
5
+ import { AwsClient } from "aws4fetch";
6
+ // src/chat/attachments/s3.ts
7
+ function readRequiredSetting(env, name) {
8
+ const value = toOptionalTrimmed(env[name]);
9
+ if (value === void 0) throw new Error(`${name} is required when JUNIOR_ATTACHMENT_STORAGE_PROVIDER is s3`);
10
+ return value;
11
+ }
12
+ /** Read S3 settings from `JUNIOR_S3_*` environment variables. */
13
+ function readS3StorageConfig(env) {
14
+ return {
15
+ accessKeyId: readRequiredSetting(env, "JUNIOR_S3_ACCESS_KEY_ID"),
16
+ bucket: readRequiredSetting(env, "JUNIOR_S3_BUCKET"),
17
+ endpoint: readRequiredSetting(env, "JUNIOR_S3_ENDPOINT"),
18
+ region: toOptionalTrimmed(env.JUNIOR_S3_REGION) ?? "us-east-1",
19
+ secretAccessKey: readRequiredSetting(env, "JUNIOR_S3_SECRET_ACCESS_KEY")
20
+ };
21
+ }
22
+ /**
23
+ * Path-style object URL. Local S3 servers and AWS S3 both accept it.
24
+ *
25
+ * URL parsing removes `.` and `..` segments, also in `%2e` form. A key with
26
+ * such a segment would address a different object, so reject it.
27
+ */
28
+ function objectUrl(config, key) {
29
+ const endpoint = config.endpoint.replace(/\/+$/, "");
30
+ const segments = key.split("/");
31
+ if (segments.some((segment) => segment === "." || segment === "..")) throw new Error("S3 object keys cannot contain . or .. path segments");
32
+ const path = segments.map(encodeURIComponent).join("/");
33
+ return `${endpoint}/${encodeURIComponent(config.bucket)}/${path}`;
34
+ }
35
+ /**
36
+ * Read a small S3 response body to the end so the connection is released.
37
+ *
38
+ * Error and empty bodies are small. `body.cancel()` can hang under the test
39
+ * HTTP interceptor, so read the body instead.
40
+ */
41
+ async function drain(response) {
42
+ await response.arrayBuffer();
43
+ }
44
+ /** Throw on a failed S3 response, and release the response body. */
45
+ async function expectOk(response, operation) {
46
+ await drain(response);
47
+ if (!response.ok) throw new Error(`S3 ${operation} failed with status ${response.status}`);
48
+ }
49
+ /** Store private conversation attachments in an S3-compatible bucket. */
50
+ function createS3AttachmentStorage(config) {
51
+ const client = new AwsClient({
52
+ accessKeyId: config.accessKeyId,
53
+ region: config.region,
54
+ secretAccessKey: config.secretAccessKey,
55
+ service: "s3"
56
+ });
57
+ return {
58
+ provider: "s3",
59
+ async put(input) {
60
+ await expectOk(await client.fetch(objectUrl(config, input.key), {
61
+ body: new Uint8Array(input.body),
62
+ headers: { "content-type": input.contentType },
63
+ method: "PUT"
64
+ }), "put");
65
+ },
66
+ async get(key) {
67
+ const response = await client.fetch(objectUrl(config, key));
68
+ if (response.status === 404) {
69
+ await drain(response);
70
+ return null;
71
+ }
72
+ if (!response.ok) await expectOk(response, "get");
73
+ return response.body;
74
+ },
75
+ async delete(keys) {
76
+ await Promise.all(keys.map(async (key) => {
77
+ const response = await client.fetch(objectUrl(config, key), { method: "DELETE" });
78
+ if (response.status === 404) {
79
+ await drain(response);
80
+ return;
81
+ }
82
+ await expectOk(response, "delete");
83
+ }));
84
+ }
85
+ };
86
+ }
87
+ // src/chat/attachments/config.ts
88
+ /** Read attachment storage settings from environment variables. */
89
+ function readAttachmentStorageConfig(env) {
90
+ const provider = toOptionalTrimmed(env.JUNIOR_ATTACHMENT_STORAGE_PROVIDER) ?? "vercel-blob";
91
+ switch (provider) {
92
+ case "vercel-blob":
93
+ case "memory": return { provider };
94
+ case "s3": return {
95
+ provider,
96
+ s3: readS3StorageConfig(env)
97
+ };
98
+ default: throw new Error("JUNIOR_ATTACHMENT_STORAGE_PROVIDER must be vercel-blob, s3, or memory");
99
+ }
100
+ }
5
101
  // src/chat/slack/emoji.ts
6
102
  const SLACK_EMOJI_NAME_RE = /^(?:[a-z0-9_+-]+)(?:::(?:skin-tone-[2-6]))?$/;
7
103
  function normalizeSlackEmojiName(value) {
@@ -314,6 +410,7 @@ function readChatConfig(env = process.env, functionMaxDurationSeconds = DEFAULT_
314
410
  warnDeprecatedProfileEnv(env);
315
411
  const resolvedFunctionMaxDurationSeconds = resolveFunctionMaxDurationSeconds(functionMaxDurationSeconds);
316
412
  return {
413
+ attachmentStorage: readAttachmentStorageConfig(env),
317
414
  bot: readBotConfig(env, resolvedFunctionMaxDurationSeconds),
318
415
  functionMaxDurationSeconds: resolvedFunctionMaxDurationSeconds,
319
416
  conversationWorkEnabled: parseConversationWorkEnabled(env.JUNIOR_CONVERSATION_WORK_ENABLED),
@@ -447,4 +544,4 @@ function setSlackReactionConfig(overrides) {
447
544
  if (overrides.processingReactionEmoji !== void 0) chatConfig.slack.processingReactionEmoji = parseReactionEmoji("processingReactionEmoji", overrides.processingReactionEmoji, chatConfig.slack.processingReactionEmoji);
448
545
  if (overrides.completedReactionEmoji !== void 0) chatConfig.slack.completedReactionEmoji = parseReactionEmoji("completedReactionEmoji", overrides.completedReactionEmoji, chatConfig.slack.completedReactionEmoji);
449
546
  }
450
- export { snapshotRuntimeConfig as _, getRuntimeMetadata as a, getSlackClientSecret as c, restoreRuntimeConfig as d, setBotModelConfig as f, setSlackReactionConfig as g, setRuntimeLimits as h, getChatConfig as i, getSlackSigningSecret as l, setProfiles as m, botConfig as n, getSlackBotToken as o, setCrossActorMidRunMode as p, config_exports as r, getSlackClientId as s, DEFAULT_SQL_STATEMENT_TIMEOUT_MS as t, resetRuntimeConfig as u, normalizeSlackEmojiName as v };
547
+ export { snapshotRuntimeConfig as _, getRuntimeMetadata as a, getSlackClientSecret as c, restoreRuntimeConfig as d, setBotModelConfig as f, setSlackReactionConfig as g, setRuntimeLimits as h, getChatConfig as i, getSlackSigningSecret as l, setProfiles as m, botConfig as n, getSlackBotToken as o, setCrossActorMidRunMode as p, config_exports as r, getSlackClientId as s, DEFAULT_SQL_STATEMENT_TIMEOUT_MS as t, resetRuntimeConfig as u, normalizeSlackEmojiName as v, createS3AttachmentStorage as y };
@@ -1,13 +1,14 @@
1
- import { Ln as startOAuthFlow, Mt as failTurnRecord, Nt as getTurnRecord, Ot as loadTurnCheckpoint } from "./tasks-LOItiYgL.js";
2
- import { n as botConfig } from "./config-Dnv8KmNs.js";
3
- import { A as deleteProviderIdentityForUser, c as getConversationEventStore, f as getSqlExecutor, k as deleteProviderIdentityForSlackUser } from "./viewer-DmNRM88V.js";
4
- import { u as hasRequiredOAuthScope } from "./registry-BFzQFV_y.js";
5
- import { n as pluginCatalogRuntime } from "./catalog-runtime-Suf-aLlh.js";
6
- import { c as deleteMcpServerSessionId, l as deleteMcpStoredOAuthCredentials, s as deleteMcpAuthSessionsForUserProvider } from "./agent-runner-BUBas7Yy.js";
7
- import { r as getStateAdapter } from "./adapter-BIacI0Bt.js";
8
- import { a as getVercelConversationWorkQueue } from "./job-queue-B4yTgklN.js";
9
- import { m as ensureConversationWake, w as requestConversationWork } from "./store-UlOrW6JC.js";
10
- import { n as resolveTurnSessionRouting } from "./turn-session-routing-5Nyv4fso.js";
1
+ import { Mt as failTurnRecord, Nt as getTurnRecord, Ot as loadTurnCheckpoint } from "./tasks-DGbrur6x.js";
2
+ import { n as botConfig } from "./config-BayQ9hHH.js";
3
+ import { A as deleteProviderIdentityForSlackUser, j as deleteProviderIdentityForUser, l as getConversationEventStore, p as getSqlExecutor } from "./viewer-B2wXNspU.js";
4
+ import { u as hasRequiredOAuthScope } from "./registry-COTeZ2cV.js";
5
+ import { n as pluginCatalogRuntime } from "./catalog-runtime-D3qbJlYz.js";
6
+ import { c as deleteMcpServerSessionId, l as deleteMcpStoredOAuthCredentials, s as deleteMcpAuthSessionsForUserProvider } from "./agent-runner-C6MwHJEs.js";
7
+ import { ct as startOAuthFlow } from "./credentialed-C6pKlB1p.js";
8
+ import { r as getStateAdapter } from "./adapter-cUkPH3Om.js";
9
+ import { a as getVercelConversationWorkQueue } from "./job-queue-Cjo6Yg_b.js";
10
+ import { m as ensureConversationWake, w as requestConversationWork } from "./store-DdT74Lvq.js";
11
+ import { n as resolveTurnSessionRouting } from "./turn-session-routing-BKx6rfVd.js";
11
12
  import { z } from "zod";
12
13
  import { randomBytes, randomUUID } from "node:crypto";
13
14
  // src/chat/task-execution/authorized-turn.ts
@@ -1,4 +1,4 @@
1
- import { m as logWarn } from "./logging-Dk_FpF36.js";
1
+ import { m as logWarn } from "./logging-D2QBriUo.js";
2
2
  import { AsyncLocalStorage } from "node:async_hooks";
3
3
  // src/chat/conversation-privacy.ts
4
4
  const SAFE_METADATA_KEY_LIMIT = 20;
@@ -1,19 +1,19 @@
1
- import { $n as resolvePluginOAuthAccount, Fn as parseOAuthStatePayload, H as recordAuthorizationCompleted, In as resolveBaseUrl, Nt as getTurnRecord, Pn as formatProviderLabel, Tt as getConversationPendingAuth, V as recordAuthenticationLinked, bn as createUserTokenStore, qn as postSlackMessage } from "./tasks-LOItiYgL.js";
2
- import { p as escapeXml } from "./client-DZBCBj1M.js";
3
- import { L as isNativeIdentityProvider, f as logException, g as runBestEffort, m as logWarn } from "./logging-Dk_FpF36.js";
4
- import { a as getRuntimeMetadata, n as botConfig } from "./config-Dnv8KmNs.js";
1
+ import { H as recordAuthorizationCompleted, Nt as getTurnRecord, Tt as getConversationPendingAuth, V as recordAuthenticationLinked } from "./tasks-DGbrur6x.js";
2
+ import { p as escapeXml } from "./client-DX34VNtH.js";
3
+ import { a as getRuntimeMetadata, n as botConfig } from "./config-BayQ9hHH.js";
4
+ import { L as isNativeIdentityProvider, f as logException, g as runBestEffort, m as logWarn } from "./logging-D2QBriUo.js";
5
5
  import { f as parseSlackUserId } from "./actor-tlxzqaRe.js";
6
- import { F as upsertIdentity, I as upsertLinkedIdentity, b as identityFromActor, f as getSqlExecutor, j as findUserByVerifiedEmails } from "./viewer-DmNRM88V.js";
6
+ import { I as upsertIdentity, L as upsertLinkedIdentity, M as findUserByVerifiedEmails, p as getSqlExecutor, x as identityFromActor } from "./viewer-B2wXNspU.js";
7
7
  import { i as homeDir } from "./package-discovery-DJBompdd.js";
8
- import { n as buildOAuthTokenRequest, r as parseOAuthTokenResponse, u as hasRequiredOAuthScope } from "./registry-BFzQFV_y.js";
9
- import { n as pluginCatalogRuntime } from "./catalog-runtime-Suf-aLlh.js";
10
- import { t as discoverSkills } from "./skills-Dbzx9-rS.js";
11
- import { a as finalizeMcpAuthorization, d as getMcpStoredOAuthCredentials, f as putMcpStoredOAuthCredentials, o as deleteMcpAuthSession, u as getMcpAuthSession, v as lookupSlackUserProfile } from "./agent-runner-BUBas7Yy.js";
12
- import { ct as getSlackClient } from "./agent-hooks-CqnZfuCt.js";
13
- import { a as acquireActiveLock, r as getStateAdapter } from "./adapter-BIacI0Bt.js";
14
- import { _ as getMcpProviderErrorAttributes } from "./service-account-x2QZXm4X.js";
15
- import { r as getPersistedThreadState, s as coerceThreadConversationState } from "./thread-state-IDHdZA7R.js";
16
- import { c as deleteWebAuthorization, i as readConnectedOAuthTokens, m as wakePausedTurn, p as wakeAuthorizedTurn, u as htmlCallbackResponse } from "./connections-Br0_xv27.js";
8
+ import { n as buildOAuthTokenRequest, r as parseOAuthTokenResponse, u as hasRequiredOAuthScope } from "./registry-COTeZ2cV.js";
9
+ import { n as pluginCatalogRuntime } from "./catalog-runtime-D3qbJlYz.js";
10
+ import { t as discoverSkills } from "./skills-Bb2KaJ3m.js";
11
+ import { a as finalizeMcpAuthorization, d as getMcpStoredOAuthCredentials, f as putMcpStoredOAuthCredentials, o as deleteMcpAuthSession, u as getMcpAuthSession, v as lookupSlackUserProfile } from "./agent-runner-C6MwHJEs.js";
12
+ import { at as formatProviderLabel, en as getSlackClient, i as resolvePluginOAuthAccount, n as createUserTokenStore, ot as parseOAuthStatePayload, st as resolveBaseUrl, vt as postSlackMessage } from "./credentialed-C6pKlB1p.js";
13
+ import { a as acquireActiveLock, r as getStateAdapter } from "./adapter-cUkPH3Om.js";
14
+ import { _ as getMcpProviderErrorAttributes } from "./service-account-YdYftwV2.js";
15
+ import { r as getPersistedThreadState, s as coerceThreadConversationState } from "./thread-state-D45lz-oC.js";
16
+ import { c as deleteWebAuthorization, i as readConnectedOAuthTokens, m as wakePausedTurn, p as wakeAuthorizedTurn, u as htmlCallbackResponse } from "./connections-mpN5Lsnj.js";
17
17
  import { n as relayLocalOAuthCallback } from "./oauth-relay-CTygMkNx.js";
18
18
  import path from "node:path";
19
19
  import { z } from "zod";
@@ -319,7 +319,7 @@ async function buildHomeView(userId, userTokenStore) {
319
319
  type: "header",
320
320
  text: {
321
321
  type: "plain_text",
322
- text: "Junior"
322
+ text: botConfig.userName
323
323
  }
324
324
  },
325
325
  {
@@ -481,14 +481,14 @@ async function GET(request, provider, waitUntil, options) {
481
481
  const state = url.searchParams.get("state");
482
482
  if (errorParam) {
483
483
  if (state) await getStateAdapter().delete(`oauth-state:${state}`);
484
- if (errorParam === "access_denied") return htmlErrorResponse("Authorization declined", `You declined the ${providerLabel} authorization request. Return to Junior and connect your ${providerLabel} account again if you change your mind.`, 400);
485
- return htmlErrorResponse("Authorization failed", `${providerLabel} returned an error: ${errorParam}. Return to Junior and try again.`, 400);
484
+ if (errorParam === "access_denied") return htmlErrorResponse("Authorization declined", `You declined the ${providerLabel} authorization request. Return to the conversation and connect your ${providerLabel} account again if you change your mind.`, 400);
485
+ return htmlErrorResponse("Authorization failed", `${providerLabel} returned an error: ${errorParam}. Return to the conversation and try again.`, 400);
486
486
  }
487
487
  if (!code || !state) return htmlErrorResponse("Invalid request", "This authorization link is missing required parameters.", 400);
488
488
  const stateAdapter = getStateAdapter();
489
489
  const stateKey = `oauth-state:${state}`;
490
490
  const stored = parseOAuthStatePayload(await stateAdapter.get(stateKey));
491
- if (!stored) return htmlErrorResponse("Link expired", `This authorization link has expired (links are valid for 10 minutes). Return to Junior and connect your ${providerLabel} account again to get a new link.`, 400);
491
+ if (!stored) return htmlErrorResponse("Link expired", `This authorization link has expired (links are valid for 10 minutes). Return to the conversation and connect your ${providerLabel} account again to get a new link.`, 400);
492
492
  if (stored.provider !== provider) return htmlErrorResponse("Provider mismatch", "This authorization link does not match the expected provider.", 400);
493
493
  await stateAdapter.delete(stateKey);
494
494
  const clientId = process.env[providerConfig.clientIdEnv]?.trim();
@@ -533,7 +533,7 @@ async function GET(request, provider, waitUntil, options) {
533
533
  logWarn("oauth.token_exchange.failed", oauthTokenErrorAttributes(provider, providerConfig.tokenEndpoint, tokenResponse.status));
534
534
  return htmlErrorResponse("Connection failed", "The provider returned an incomplete token response. Please try again.", 500);
535
535
  }
536
- if (!hasRequiredOAuthScope(parsedTokenResponse.scope, requestedScope)) return htmlErrorResponse("Connection failed", `The ${providerLabel} authorization did not grant the access Junior requires. Return to Junior and connect your ${providerLabel} account again.`, 400);
536
+ if (!hasRequiredOAuthScope(parsedTokenResponse.scope, requestedScope)) return htmlErrorResponse("Connection failed", `The ${providerLabel} authorization did not grant the required access. Return to the conversation and connect your ${providerLabel} account again.`, 400);
537
537
  const userTokenStore = createUserTokenStore();
538
538
  let account;
539
539
  let verifiedEmails = [];
@@ -549,7 +549,7 @@ async function GET(request, provider, waitUntil, options) {
549
549
  verifiedEmails = emails ?? [];
550
550
  }
551
551
  } catch {
552
- return htmlErrorResponse("Connection failed", `Junior could not verify the connected ${providerLabel} account. Please try again.`, 500);
552
+ return htmlErrorResponse("Connection failed", `The connected ${providerLabel} account could not be verified. Please try again.`, 500);
553
553
  }
554
554
  await userTokenStore.set(stored.userId, provider, {
555
555
  ...parsedTokenResponse,