@sentry/junior 0.266.0 → 0.267.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 (75) hide show
  1. package/dist/{actor-tlxzqaRe.js → actor-DZSokpwj.js} +8 -1
  2. package/dist/{adapter-eRFA_naf.js → adapter-BybMEezj.js} +2 -2
  3. package/dist/{admin-tILpP51p.js → admin-DOs1_EiW.js} +1 -1
  4. package/dist/{agent-runner-BtYK7bht.js → agent-runner-DgNATN4D.js} +872 -226
  5. package/dist/api/schema.d.ts +198 -23
  6. package/dist/api/schema.js +5 -4
  7. package/dist/api.d.ts +6 -1
  8. package/dist/api.js +130 -1205
  9. package/dist/{app-Csbi9dW7.d.ts → app-DAB3fzyp.d.ts} +21 -3
  10. package/dist/app.d.ts +2 -2
  11. package/dist/app.js +1610 -353
  12. package/dist/{assistant-reply-UyzAfZQo.js → assistant-reply-CT7VcXQe.js} +1 -1
  13. package/dist/{automation-BKpY9LPa.js → automation-CmeFBSEh.js} +42 -14
  14. package/dist/{briefs-DgfWMU7e.js → briefs-CWKjka7v.js} +4 -4
  15. package/dist/{catalog-runtime-DAJjAbSx.js → catalog-runtime-cMlAI5LY.js} +1 -1
  16. package/dist/cli/chat.js +15 -15
  17. package/dist/cli/check.js +3 -3
  18. package/dist/cli/init.js +0 -1
  19. package/dist/cli/main.js +3 -3
  20. package/dist/cli/plugins.js +4 -4
  21. package/dist/cli/snapshot-create.js +4 -4
  22. package/dist/cli/upgrade.d.ts +1 -1
  23. package/dist/cli/upgrade.js +3 -3
  24. package/dist/{client-B0YZfxNy.js → client-BjgbMawj.js} +2 -2
  25. package/dist/{config-C0UwYqDK.js → config-CdB6yJj5.js} +32 -10
  26. package/dist/{connections-Bwu3VORi.js → connections-RE_65jzK.js} +13 -12
  27. package/dist/{conversation-DF4rUcjb.js → conversation-DSo310Ps.js} +8 -1
  28. package/dist/{conversation-privacy-CY7JVjxn.js → conversation-privacy-BzgJC5k0.js} +1 -1
  29. package/dist/{credential-sync-VGAMUTGp.js → credential-sync-DhEGEpgq.js} +15 -15
  30. package/dist/{credentialed-enF5Bf3y.js → credentialed-CIGwoLU2.js} +2905 -1024
  31. package/dist/{db-BnRqQ7G5.d.ts → db-Bg-zC3r5.d.ts} +1 -1
  32. package/dist/{executor-TnWbvL09.js → executor-VYrx_K4w.js} +7 -4
  33. package/dist/{images-BKQqSi5W.js → images-CecjXAAz.js} +3 -3
  34. package/dist/instrumentation.js +6 -2
  35. package/dist/{job-queue-DBpHmKnd.js → job-queue-C0BZSa7r.js} +128 -3
  36. package/dist/{web-input-B-bMjD1V.js → list-1XQP-o6K.js} +1374 -71
  37. package/dist/{logging-Ce0mXZ8J.js → logging-DuZ1A4ab.js} +11 -3
  38. package/dist/{message-VZ3DFpGb.js → message-NKSbbnA6.js} +4 -4
  39. package/dist/nitro.d.ts +1 -1
  40. package/dist/nitro.js +3 -3
  41. package/dist/{oauth-callback-server-CpqWLjVY.js → oauth-callback-server-qAHLPtml.js} +2 -2
  42. package/dist/{prompt-BcCGlmg2.js → prompt-BW9jFsqZ.js} +1 -1
  43. package/dist/{registry-1BEIPdbT.js → registry-FQutO926.js} +2 -2
  44. package/dist/{resolve-BSHHkEGE.js → resolve-Bk4yeuHy.js} +3 -3
  45. package/dist/{result-CwOpzqdh.js → result-B9e9ATOU.js} +9 -9
  46. package/dist/{runner-CEaX04kz.js → runner-C3S2ObH-.js} +11 -11
  47. package/dist/{sandbox-egress-signals-BwtGHwqa.js → sandbox-egress-signals-DqpGzzMB.js} +1 -1
  48. package/dist/{schema-RsaBHxRH.js → schema-X7Fj4fv1.js} +3 -2
  49. package/dist/{service-account-Dg4lIbHm.js → service-account-BQasl-qq.js} +3 -3
  50. package/dist/{service-account-6wC76eBZ.js → service-account-Do30HUNv.js} +3 -3
  51. package/dist/{session-stop-tZOw9AJD.js → session-stop-DkOjt46_.js} +45 -128
  52. package/dist/{skills-DzyGN7wd.js → skills-CQHrwfOa.js} +2 -2
  53. package/dist/{spawn-6rokq7l_.js → spawn-BHuqN14f.js} +2 -2
  54. package/dist/{store-DcKkzrdt.js → store-6EetVP-m.js} +3 -3
  55. package/dist/{store-CG0VJyye.d.ts → store-B8CABbmR.d.ts} +10 -2
  56. package/dist/store-DvNZIsCr.js +295 -0
  57. package/dist/{task-queue-Bg4RS2Gy.js → task-queue-B0DLgd2P.js} +10 -5
  58. package/dist/{task-runner-8N5LIkSg.js → task-runner-B-PD_JOj.js} +25 -13
  59. package/dist/{tasks-DDT-J3Rf.js → tasks-0ilmuCux.js} +1438 -44
  60. package/dist/{thread-state-cprEaxgl.js → thread-state-DRmdJ2QN.js} +5 -5
  61. package/dist/{turn-failure-response-C8sMdsdX.js → turn-failure-response-G11cs2gE.js} +9 -9
  62. package/dist/{turn-lifecycle-DaBVoz7h.js → turn-lifecycle-OzLIwvi1.js} +1 -1
  63. package/dist/{turn-session-routing-a9CHX-w6.js → turn-session-routing-Dyut9l7Y.js} +1 -1
  64. package/dist/user-input-request-BDFBdF8r.js +116 -0
  65. package/dist/{validation-C2lllinq.js → validation-CxEmt1id.js} +1 -1
  66. package/dist/{version-oaLfxxnf.js → version-Bapedn4A.js} +1 -1
  67. package/dist/version.js +1 -1
  68. package/dist/{viewer-BpE6Z3qf.js → viewer-DrN3oC2X.js} +21 -10
  69. package/dist/{work-VX1SHWha.js → work-DUQoNcqP.js} +10 -10
  70. package/dist/{worker-hook-y_Y.js → worker-D1l4Ugk0.js} +30 -19
  71. package/migrations/0064_any_resource_event_triggers.sql +2 -0
  72. package/migrations/meta/0064_snapshot.json +3505 -0
  73. package/migrations/meta/_journal.json +7 -0
  74. package/package.json +20 -5
  75. package/dist/store-FALy-JQb.js +0 -1424
@@ -1,8 +1,8 @@
1
- import { Z as persistConversationMessages, yn as createDurableLocationConfigurationService } from "./tasks-DDT-J3Rf.js";
2
- import { B as toOptionalNumber, V as toOptionalString, z as isRecord } from "./logging-Ce0mXZ8J.js";
3
- import { f as getDb } from "./viewer-BpE6Z3qf.js";
4
- import { ln as JUNIOR_THREAD_STATE_TTL_MS } from "./credentialed-enF5Bf3y.js";
5
- import { r as getStateAdapter } from "./adapter-eRFA_naf.js";
1
+ import { dt as persistConversationMessages, ur as createDurableLocationConfigurationService } from "./tasks-0ilmuCux.js";
2
+ import { B as isRecord, H as toOptionalString, V as toOptionalNumber } from "./logging-DuZ1A4ab.js";
3
+ import { p as getDb } from "./viewer-DrN3oC2X.js";
4
+ import { dn as JUNIOR_THREAD_STATE_TTL_MS } from "./credentialed-CIGwoLU2.js";
5
+ import { i as getStateAdapter } from "./adapter-BybMEezj.js";
6
6
  // src/chat/state/conversation.ts
7
7
  function defaultConversationState() {
8
8
  return {
@@ -1,12 +1,12 @@
1
- import { X as hydrateConversationMessages, cn as buildDeterministicTurnId, ut as markConversationMessage, wt as clearPendingAuth } from "./tasks-DDT-J3Rf.js";
2
- import { _ as getProviderErrorAttributes, g as findProviderError, m as ProviderError, v as getProviderErrorUserMessage } from "./client-B0YZfxNy.js";
3
- import { t as buildTurnFailureResponse, z as isRecord } from "./logging-Ce0mXZ8J.js";
4
- import { g as parseSlackMessageTs } from "./actor-tlxzqaRe.js";
5
- import { f as getDb, l as getConversationEventStore } from "./viewer-BpE6Z3qf.js";
6
- import { Zn as listConversationAnnotations } from "./credentialed-enF5Bf3y.js";
7
- import { F as readMessageCardRefs, I as removedCardSchema, L as resolveMessageCards } from "./conversation-DF4rUcjb.js";
8
- import { D as parseAgentInvocationResultMessageId, J as markTurnClosed, Y as markTurnCompleted, c as getAgentInvocation, m as getAgentInvocationTurnId } from "./store-DcKkzrdt.js";
9
- import { o as persistThreadStateById, r as getPersistedThreadState, s as coerceThreadConversationState } from "./thread-state-cprEaxgl.js";
1
+ import { $n as buildDeterministicTurnId, Rt as clearPendingAuth, ut as hydrateConversationMessages, wt as markConversationMessage } from "./tasks-0ilmuCux.js";
2
+ import { _ as getProviderErrorAttributes, g as findProviderError, m as ProviderError, v as getProviderErrorUserMessage } from "./client-BjgbMawj.js";
3
+ import { B as isRecord, t as buildTurnFailureResponse } from "./logging-DuZ1A4ab.js";
4
+ import { p as parseSlackMessageTs } from "./actor-DZSokpwj.js";
5
+ import { p as getDb, u as getConversationEventStore } from "./viewer-DrN3oC2X.js";
6
+ import { er as listConversationAnnotations } from "./credentialed-CIGwoLU2.js";
7
+ import { B as removedCardSchema, V as resolveMessageCards, z as readMessageCardRefs } from "./conversation-DSo310Ps.js";
8
+ import { D as parseAgentInvocationResultMessageId, J as markTurnClosed, Y as markTurnCompleted, c as getAgentInvocation, m as getAgentInvocationTurnId } from "./store-6EetVP-m.js";
9
+ import { o as persistThreadStateById, r as getPersistedThreadState, s as coerceThreadConversationState } from "./thread-state-DRmdJ2QN.js";
10
10
  // src/chat/conversations/pending-cards.ts
11
11
  /**
12
12
  * Add the cards that tool results selected since the last visible assistant
@@ -1,4 +1,4 @@
1
- import { l as getConversationEventStore } from "./viewer-BpE6Z3qf.js";
1
+ import { u as getConversationEventStore } from "./viewer-DrN3oC2X.js";
2
2
  // src/chat/conversations/turn-lifecycle.ts
3
3
  /** Persist correlated turn lifecycle facts with retry-safe terminal exclusion. */
4
4
  var ConversationTurnLifecycleService = class {
@@ -34,7 +34,7 @@ function slackSourceForDestination(args) {
34
34
  * Reads parent Conversations when this Conversation has no Destination.
35
35
  */
36
36
  async function resolveConversationRouting(args) {
37
- const conversationStore = args.conversationStore ?? (await import("./viewer-BpE6Z3qf.js").then((n) => n.c)).getConversationStore();
37
+ const conversationStore = args.conversationStore ?? (await import("./viewer-DrN3oC2X.js").then((n) => n.l)).getConversationStore();
38
38
  const chain = await loadConversationChain(args.conversationId, conversationStore);
39
39
  let destination;
40
40
  let source;
@@ -0,0 +1,116 @@
1
+ import { z } from "zod";
2
+ // src/chat/tools/runtime/user-input-request.ts
3
+ const USER_INPUT_LIMITS = {
4
+ maxButtonOptions: 5,
5
+ maxDescriptionChars: 200,
6
+ maxFields: 4,
7
+ maxLabelChars: 75,
8
+ maxOptions: 10,
9
+ maxTextChars: 3e3,
10
+ maxQuestionChars: 3e3,
11
+ minOptions: 2
12
+ };
13
+ const labelSchema = z.string().trim().min(1).max(USER_INPUT_LIMITS.maxLabelChars);
14
+ const descriptionSchema = z.string().trim().min(1).max(USER_INPUT_LIMITS.maxDescriptionChars).optional();
15
+ const optionSchema = z.object({
16
+ label: labelSchema.describe("Short choice text, such as `Accept` or `Decline`. The answer uses this exact text."),
17
+ description: descriptionSchema.describe("Optional short note about what this choice does.")
18
+ });
19
+ const fieldBase = {
20
+ id: z.string().regex(/^[a-z][a-z0-9_]{0,31}$/).describe("Stable key for this field, such as `approach`."),
21
+ label: labelSchema.describe("Short field name, such as `Approach`."),
22
+ description: descriptionSchema.describe("Optional short help text for this field.")
23
+ };
24
+ const optionsSchema = z.array(optionSchema).min(USER_INPUT_LIMITS.minOptions).max(USER_INPUT_LIMITS.maxOptions).describe("Choices in display order.");
25
+ const userInputFieldSchema = z.discriminatedUnion("kind", [
26
+ z.object({
27
+ ...fieldBase,
28
+ kind: z.literal("choice").describe("The person picks one option."),
29
+ options: optionsSchema
30
+ }),
31
+ z.object({
32
+ ...fieldBase,
33
+ kind: z.literal("multi_choice").describe("The person picks any number of options."),
34
+ options: optionsSchema
35
+ }),
36
+ z.object({
37
+ ...fieldBase,
38
+ kind: z.literal("text").describe("The person types a short answer.")
39
+ })
40
+ ]);
41
+ const userInputRequestSchema = z.object({
42
+ question: z.string().trim().min(1).max(USER_INPUT_LIMITS.maxQuestionChars).describe("The question, in markdown. Include the facts the person needs to decide."),
43
+ fields: z.array(userInputFieldSchema).min(1).max(USER_INPUT_LIMITS.maxFields).describe("What to ask, in display order. Use one `choice` field for a simple decision.")
44
+ }).superRefine((request, context) => {
45
+ const ids = /* @__PURE__ */ new Set();
46
+ for (const field of request.fields) {
47
+ if (ids.has(field.id)) context.addIssue({
48
+ code: "custom",
49
+ message: "Each field needs a different id."
50
+ });
51
+ ids.add(field.id);
52
+ if (field.kind === "text") continue;
53
+ const labels = field.options.map((option) => option.label.toLowerCase());
54
+ if (new Set(labels).size !== labels.length) context.addIssue({
55
+ code: "custom",
56
+ message: "Each choice of a field needs a different label."
57
+ });
58
+ }
59
+ });
60
+ /**
61
+ * Return the single choice field of a request that a surface can show as
62
+ * one row of buttons, where one click is the whole answer.
63
+ */
64
+ function buttonUserInputField(request) {
65
+ const [field, ...rest] = request.fields;
66
+ if (rest.length || field?.kind !== "choice") return void 0;
67
+ return field.options.length <= USER_INPUT_LIMITS.maxButtonOptions ? field : void 0;
68
+ }
69
+ /**
70
+ * Keep only answer values that match the request: known field ids, known
71
+ * option labels, one value for a `choice` field, and trimmed text.
72
+ */
73
+ function normalizeUserInputAnswer(request, answer) {
74
+ const values = {};
75
+ for (const field of request.fields) {
76
+ const raw = (answer.values[field.id] ?? []).map((value) => value.trim()).filter(Boolean);
77
+ if (field.kind === "text") {
78
+ const text = raw.join("\n").slice(0, USER_INPUT_LIMITS.maxTextChars);
79
+ if (text) values[field.id] = [text];
80
+ continue;
81
+ }
82
+ const picked = field.options.map((option) => option.label).filter((label) => raw.includes(label));
83
+ const kept = field.kind === "choice" ? picked.slice(0, 1) : picked;
84
+ if (kept.length) values[field.id] = kept;
85
+ }
86
+ const other = answer.other?.trim().slice(0, USER_INPUT_LIMITS.maxTextChars);
87
+ return {
88
+ requestId: answer.requestId,
89
+ values,
90
+ ...other ? { other } : void 0
91
+ };
92
+ }
93
+ /** Return true when an answer has no value and no free text. */
94
+ function isEmptyUserInputAnswer(answer) {
95
+ return !answer.other && Object.keys(answer.values).length === 0;
96
+ }
97
+ function answerLine(text) {
98
+ return text.split("\n").map((line) => line.trim()).filter(Boolean).join("\n");
99
+ }
100
+ /**
101
+ * Write an answer as the text of the person's message. Slack and the web
102
+ * dashboard both send this text, so the model reads one format. The first
103
+ * line names the request, and each field starts its own line.
104
+ */
105
+ function formatUserInputAnswer(request, answer) {
106
+ const normalized = normalizeUserInputAnswer(request, answer);
107
+ const lines = [`Answer to request ${normalized.requestId}:`];
108
+ for (const field of request.fields) {
109
+ const values = normalized.values[field.id];
110
+ const value = values?.length ? values.join(", ") : "(no answer)";
111
+ lines.push(answerLine(`${field.label} (${field.id}): ${value}`));
112
+ }
113
+ if (normalized.other) lines.push(answerLine(`Other: ${normalized.other}`));
114
+ return lines.join("\n");
115
+ }
116
+ export { normalizeUserInputAnswer as a, isEmptyUserInputAnswer as i, buttonUserInputField as n, userInputRequestSchema as o, formatUserInputAnswer as r, USER_INPUT_LIMITS as t };
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-nwUcYXjP.js";
2
- import { n as pluginCatalogRuntime } from "./catalog-runtime-DAJjAbSx.js";
2
+ import { n as pluginCatalogRuntime } from "./catalog-runtime-cMlAI5LY.js";
3
3
  import { isDeepStrictEqual } from "node:util";
4
4
  // src/chat/plugins/validation.ts
5
5
  var validation_exports = /* @__PURE__ */ __exportAll({
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "0.266.0";
2
+ var version = "0.267.0";
3
3
  // src/version.ts
4
4
  /** Installed Junior package version, or `unknown` when package metadata is unavailable. */
5
5
  const JUNIOR_VERSION = typeof version === "string" && version.trim() ? version : "unknown";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export { t as JUNIOR_VERSION } from "./version-oaLfxxnf.js";
1
+ export { t as JUNIOR_VERSION } from "./version-Bapedn4A.js";
@@ -1,9 +1,9 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-nwUcYXjP.js";
2
- import { i as getChatConfig } from "./config-C0UwYqDK.js";
3
- import { I as GOOGLE_IDENTITY_PROVIDER, R as normalizeIdentityEmail } from "./logging-Ce0mXZ8J.js";
4
- import { d as parseSlackTeamId, o as parseActorUserId, u as parseSlackChannelReferenceId } from "./actor-tlxzqaRe.js";
2
+ import { i as getChatConfig } from "./config-CdB6yJj5.js";
3
+ import { L as GOOGLE_IDENTITY_PROVIDER, z as normalizeIdentityEmail } from "./logging-DuZ1A4ab.js";
4
+ import { c as toStoredSlackActor, d as parseSlackTeamId, o as parseActorUserId, u as parseSlackChannelReferenceId } from "./actor-DZSokpwj.js";
5
5
  import { c as juniorIdentities, d as juniorDestinations, l as juniorUsers, o as conversationReadColumns, s as juniorConversations } from "./agent-invocations-CxKldAeB.js";
6
- import { _ as juniorConversationAnnotations, d as juniorConversationBindings, h as juniorConversationEvents, m as juniorConversationMetrics, p as CONVERSATION_METRICS, t as createJuniorSqlExecutor, u as juniorConversationParticipants } from "./executor-TnWbvL09.js";
6
+ import { _ as juniorConversationAnnotations, d as juniorConversationBindings, h as juniorConversationEvents, m as juniorConversationMetrics, p as CONVERSATION_METRICS, t as createJuniorSqlExecutor, u as juniorConversationParticipants } from "./executor-VYrx_K4w.js";
7
7
  import { c as newConversationEventSchema, h as usageSchema, l as encodeHistoryPayload, o as decodeStoredConversationEvent, r as conversationEventDataSchema, s as historyReplacementSchema } from "./history-C84mlAwO.js";
8
8
  import { randomUUID } from "node:crypto";
9
9
  import { and, asc, desc, eq, gt, gte, inArray, isNull, lt, lte, ne, or, sql } from "drizzle-orm";
@@ -476,6 +476,15 @@ function identityFromActor(actor) {
476
476
  metadata: { platform: "web" }
477
477
  };
478
478
  }
479
+ /**
480
+ * Build the identity observation for one runtime actor with the same key the
481
+ * Conversation write path stores. Local and system actors have no user
482
+ * identity.
483
+ */
484
+ function identityFromRuntimeActor(actor) {
485
+ if (actor.platform === "slack") return identityFromActor(toStoredSlackActor(actor));
486
+ if (actor.platform === "web") return identityFromActor(actor.email ? { email: actor.email } : void 0);
487
+ }
479
488
  /** Build a system identity when a conversation has no user actor. */
480
489
  function systemIdentityFromSource(source) {
481
490
  if (source === "scheduler") return {
@@ -817,6 +826,8 @@ var SqlStore = class {
817
826
  const incomingExecutionAt = args.execution.updatedAtMs ?? args.updatedAtMs;
818
827
  const incomingIsFresh = incomingExecutionAt >= (existing?.execution.updatedAtMs ?? existing?.updatedAtMs ?? 0);
819
828
  const execution = incomingIsFresh ? args.execution : existing?.execution ?? args.execution;
829
+ const actor = mergeActor(existing?.actor, args.actor);
830
+ const source = existing?.source ?? args.source;
820
831
  await this.upsertConversation({ conversation: {
821
832
  schemaVersion: 1,
822
833
  conversationId: args.conversationId,
@@ -827,8 +838,8 @@ var SqlStore = class {
827
838
  ...existing?.location ? { location: existing.location } : void 0,
828
839
  ...args.channelName ? { channelName: args.channelName } : void 0,
829
840
  ...args.destination ? { destination: args.destination } : void 0,
830
- ...args.actor ? { actor: args.actor } : void 0,
831
- ...args.source ? { source: args.source } : void 0,
841
+ ...actor ? { actor } : void 0,
842
+ ...source ? { source } : void 0,
832
843
  ...args.title ? { title: args.title } : void 0,
833
844
  ...args.visibility ? { visibility: args.visibility } : void 0,
834
845
  execution
@@ -1630,12 +1641,12 @@ async function listAdminUsersFromSql(db) {
1630
1641
  }
1631
1642
  /** Resolve the stored identity and linked user for one runtime actor. */
1632
1643
  async function readActorIdentityFromSql(db, actor) {
1633
- if (actor.platform === "system") return void 0;
1634
- const providerTenantId = actor.platform === "slack" ? actor.teamId : "";
1644
+ const key = identityFromRuntimeActor(actor);
1645
+ if (!key) return void 0;
1635
1646
  const row = (await db.select({
1636
1647
  identity: juniorIdentities,
1637
1648
  user: juniorUsers
1638
- }).from(juniorIdentities).leftJoin(juniorUsers, eq(juniorUsers.id, juniorIdentities.userId)).where(and(eq(juniorIdentities.kind, "user"), eq(juniorIdentities.provider, actor.platform), eq(juniorIdentities.providerTenantId, providerTenantId), eq(juniorIdentities.providerSubjectId, actor.userId))).limit(1))[0];
1649
+ }).from(juniorIdentities).leftJoin(juniorUsers, eq(juniorUsers.id, juniorIdentities.userId)).where(and(eq(juniorIdentities.kind, "user"), eq(juniorIdentities.provider, key.provider), eq(juniorIdentities.providerTenantId, key.providerTenantId ?? ""), eq(juniorIdentities.providerSubjectId, key.providerSubjectId))).limit(1))[0];
1639
1650
  if (!row) return void 0;
1640
1651
  return {
1641
1652
  identity: identityFromRow(row.identity),
@@ -1662,4 +1673,4 @@ async function readIdentityByIdFromSql(db, identityId) {
1662
1673
  async function readIdentityById(identityId) {
1663
1674
  return await readIdentityByIdFromSql(getDb(), identityId);
1664
1675
  }
1665
- export { deleteProviderIdentityForSlackUser as A, requireSlackDestination as B, parseSessionSource as C, agentTurnUsageSchema as D, agentTurnTotalTokens as E, saveUserTimezone as F, upsertIdentity as I, upsertLinkedIdentity as L, findUserByVerifiedEmails as M, readUserTimezone as N, hasAgentTurnUsage as O, recordGoogleSignIn as P, createSlackDestination as R, bindProviderConversation as S, agentTurnCostUsd as T, sameDestination as V, createSqlStore as _, resolveViewerUser as a, startLocationThread as b, db_exports as c, getConversationStore as d, getDb as f, loadConversationSlackTenantIds as g, withConversationEventLock as h, readIdentityById as i, deleteProviderIdentityForUser as j, resolveRootConversationId as k, getConversationEventStore as l, createSqlConversationEventStore as m, listAdminUsersFromSql as n, setUserAdminFromSql as o, getSqlExecutor as p, readActorIdentity as r, updateViewerDisplayName as s, findUserByEmail as t, getConversationMessageSearchStore as u, withConversationMutationLock as v, addAgentTurnUsage as w, identityFromActor as x, locationFromRow as y, parseDestination as z };
1676
+ export { resolveRootConversationId as A, parseDestination as B, bindProviderConversation as C, agentTurnTotalTokens as D, agentTurnCostUsd as E, recordGoogleSignIn as F, sameDestination as H, saveUserTimezone as I, upsertIdentity as L, deleteProviderIdentityForUser as M, findUserByVerifiedEmails as N, agentTurnUsageSchema as O, readUserTimezone as P, upsertLinkedIdentity as R, identityFromActor as S, addAgentTurnUsage as T, requireSlackDestination as V, loadConversationSlackTenantIds as _, resolveViewerUser as a, locationFromRow as b, closeDb as c, getConversationMessageSearchStore as d, getConversationStore as f, withConversationEventLock as g, createSqlConversationEventStore as h, readIdentityById as i, deleteProviderIdentityForSlackUser as j, hasAgentTurnUsage as k, db_exports as l, getSqlExecutor as m, listAdminUsersFromSql as n, setUserAdminFromSql as o, getDb as p, readActorIdentity as r, updateViewerDisplayName as s, findUserByEmail as t, getConversationEventStore as u, createSqlStore as v, parseSessionSource as w, startLocationThread as x, withConversationMutationLock as y, createSlackDestination as z };
@@ -1,15 +1,15 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-nwUcYXjP.js";
2
- import { At as abandonTurnRecord, Ht as isTurnExecutionLimitExceededError, Kt as getTerminalAssistantMessages, Mt as failTurnRecord, Nt as getTurnRecord, R as openConversationProjection, bt as AuthorizationFlowDisabledError, gt as PluginCredentialFailureError, kt as saveTurnCheckpoint } from "./tasks-DDT-J3Rf.js";
3
- import { n as botConfig } from "./config-C0UwYqDK.js";
4
- import { d as getConversationStore, l as getConversationEventStore } from "./viewer-BpE6Z3qf.js";
2
+ import { At as PluginCredentialFailureError, Kt as failTurnRecord, Ln as getTerminalAssistantMessages, Nn as isTurnExecutionLimitExceededError, Pt as AuthorizationFlowDisabledError, Q as openConversationProjection, Ut as saveTurnCheckpoint, Wt as abandonTurnRecord, qt as getTurnRecord } from "./tasks-0ilmuCux.js";
3
+ import { n as botConfig } from "./config-CdB6yJj5.js";
4
+ import { f as getConversationStore, u as getConversationEventStore } from "./viewer-DrN3oC2X.js";
5
5
  import { m as sameActorIdentity, u as agentInstructionProvenance } from "./history-C84mlAwO.js";
6
- import { B as stopChildAgentsOf, H as recordSubagentEnded, U as recordSubagentStarted, X as buildSteeringPiMessage, Z as withoutSavedSteeringMessages, tt as readBlockedReport } from "./agent-runner-BtYK7bht.js";
7
- import { E as markAgentInvocationSteered, H as TurnInputCommitLostError, K as isTurnInputCommitLostError, L as agentTypeInstructions, O as reportReplacedAgentInvocation, R as agentTypeStartsWithParentHistory, S as markAgentInvocationMailboxAppended, T as markAgentInvocationRunning, W as getConversationTurnBoundaryError, _ as getLatestAgentInvocationForConversation, c as getAgentInvocation, f as getAgentInvocationMessageId, m as getAgentInvocationTurnId, n as completeAgentInvocation, r as createAgentInvocation, s as getActiveAgentInvocationForConversation, w as markAgentInvocationPaused, y as isTerminalAgentInvocation } from "./store-DcKkzrdt.js";
8
- import { n as getAssistantReplyText } from "./assistant-reply-UyzAfZQo.js";
9
- import { F as recordFinishedTurnForAutomatedLimit, I as resetAutomatedTurnLimit, P as maybePostAutomatedTurnLimitNotice } from "./session-stop-tZOw9AJD.js";
10
- import { r as appendAndEnqueueInboundMessage } from "./store-FALy-JQb.js";
11
- import { t as ConversationTurnLifecycleService } from "./turn-lifecycle-DaBVoz7h.js";
12
- import { n as getPersistedSandboxState, o as persistThreadStateById, r as getPersistedThreadState } from "./thread-state-cprEaxgl.js";
6
+ import { Q as stopChildAgentsOf, ct as buildSteeringPiMessage, et as recordSubagentEnded, lt as withoutSavedSteeringMessages, pt as readBlockedReport, tt as recordSubagentStarted } from "./agent-runner-DgNATN4D.js";
7
+ import { E as markAgentInvocationSteered, H as TurnInputCommitLostError, K as isTurnInputCommitLostError, L as agentTypeInstructions, O as reportReplacedAgentInvocation, R as agentTypeStartsWithParentHistory, S as markAgentInvocationMailboxAppended, T as markAgentInvocationRunning, W as getConversationTurnBoundaryError, _ as getLatestAgentInvocationForConversation, c as getAgentInvocation, f as getAgentInvocationMessageId, m as getAgentInvocationTurnId, n as completeAgentInvocation, r as createAgentInvocation, s as getActiveAgentInvocationForConversation, w as markAgentInvocationPaused, y as isTerminalAgentInvocation } from "./store-6EetVP-m.js";
8
+ import { n as getAssistantReplyText } from "./assistant-reply-CT7VcXQe.js";
9
+ import { C as maybePostAutomatedTurnLimitNotice, T as resetAutomatedTurnLimit, w as recordFinishedTurnForAutomatedLimit } from "./session-stop-DkOjt46_.js";
10
+ import { r as appendAndEnqueueInboundMessage } from "./store-DvNZIsCr.js";
11
+ import { t as ConversationTurnLifecycleService } from "./turn-lifecycle-OzLIwvi1.js";
12
+ import { n as getPersistedSandboxState, o as persistThreadStateById, r as getPersistedThreadState } from "./thread-state-DRmdJ2QN.js";
13
13
  import { isDeepStrictEqual } from "node:util";
14
14
  import { z } from "zod";
15
15
  // src/chat/runtime/turn-execution.ts
@@ -1,34 +1,45 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-nwUcYXjP.js";
2
- import { y as isProviderRetryError } from "./client-B0YZfxNy.js";
3
- import { i as getChatConfig } from "./config-C0UwYqDK.js";
4
- import { f as logException, m as logWarn, p as logInfo, w as withLogContext, y as setSpanAttributes } from "./logging-Ce0mXZ8J.js";
5
- import { f as getTurnRequestDeadline, m as ConversationQueueMessageRejectedError } from "./job-queue-DBpHmKnd.js";
6
- import { C as requestAnotherSlice, M as isInvalidConversationRecordError, T as startConversationWork, b as recordConversationRetry, d as countPendingConversationMessages, f as deadLetterAttempt, g as getConversationWorkState, i as beginConversationResume, j as isFinalAttempt, k as hasConversationStop, l as completeConversationStop, m as ensureConversationWake, o as checkInConversationWork, p as drainConversationMailbox, s as clearConsumedConversationWake, t as ackMessages, u as completeConversationWork, x as releaseConversationWork, y as recordAttemptFailure } from "./store-FALy-JQb.js";
7
- // src/chat/task-execution/worker.ts
8
- var worker_exports = /* @__PURE__ */ __exportAll({
9
- CONVERSATION_WORK_DEFER_DELAY_MS: () => CONVERSATION_WORK_DEFER_DELAY_MS,
10
- processConversationWork: () => processConversationWork
11
- });
12
- const CONVERSATION_WORK_DEFER_DELAY_MS = 15e3;
13
- const CONVERSATION_STOP_CHECK_INTERVAL_MS = 500;
14
- function now(options) {
15
- return options.nowMs?.() ?? Date.now();
16
- }
2
+ import { fn as hasConversationStop, hn as isInvalidConversationRecordError, mn as isFinalAttempt } from "./tasks-0ilmuCux.js";
3
+ import { y as isProviderRetryError } from "./client-BjgbMawj.js";
4
+ import { i as getChatConfig } from "./config-CdB6yJj5.js";
5
+ import { T as withLogContext, b as setSpanAttributes, h as logWarn, m as logInfo, p as logException } from "./logging-DuZ1A4ab.js";
6
+ import { f as getTurnRequestDeadline, m as ConversationQueueMessageRejectedError } from "./job-queue-C0BZSa7r.js";
7
+ import { C as requestAnotherSlice, T as startConversationWork, b as recordConversationRetry, d as countPendingConversationMessages, f as deadLetterAttempt, g as getConversationWorkState, i as beginConversationResume, l as completeConversationStop, m as ensureConversationWake, o as checkInConversationWork, p as drainConversationMailbox, s as clearConsumedConversationWake, t as ackMessages, u as completeConversationWork, x as releaseConversationWork, y as recordAttemptFailure } from "./store-DvNZIsCr.js";
8
+ // src/chat/task-execution/attempt-selection.ts
17
9
  function selectContiguousTurnBatch(messages) {
18
10
  const first = messages[0];
19
11
  if (!first) return [];
20
12
  const nextTurnIndex = messages.findIndex((message) => message.input.authorId !== first.input.authorId || message.source !== first.source);
21
13
  return messages.slice(0, nextTurnIndex === -1 ? messages.length : nextTurnIndex);
22
14
  }
15
+ /**
16
+ * True when an interrupt can start its own attempt.
17
+ *
18
+ * A steered web message must not start a second Turn while a yielded Turn
19
+ * waits to resume. It stays pending for that Turn's drain or the next attempt.
20
+ */
21
+ function isAttemptInterrupt(message, work) {
22
+ return message.delivery === "interrupt" && !(work.execution.status === "paused" && message.source === "web");
23
+ }
23
24
  /** Prioritize interrupts while keeping each attempt to one Actor and Source. */
24
25
  function selectAttemptMessages(work) {
25
26
  const messages = work.messages;
26
- const interrupts = messages.filter((message) => message.delivery === "interrupt");
27
+ const interrupts = messages.filter((message) => isAttemptInterrupt(message, work));
27
28
  if (interrupts.length > 0) return selectContiguousTurnBatch(interrupts);
28
29
  if (work.execution.status === "paused") return [];
29
30
  const nonEventMessages = messages.filter((message) => message.source !== "event");
30
31
  return selectContiguousTurnBatch(nonEventMessages.length > 0 ? nonEventMessages : messages);
31
32
  }
33
+ // src/chat/task-execution/worker.ts
34
+ var worker_exports = /* @__PURE__ */ __exportAll({
35
+ CONVERSATION_WORK_DEFER_DELAY_MS: () => CONVERSATION_WORK_DEFER_DELAY_MS,
36
+ processConversationWork: () => processConversationWork
37
+ });
38
+ const CONVERSATION_WORK_DEFER_DELAY_MS = 15e3;
39
+ const CONVERSATION_STOP_CHECK_INTERVAL_MS = 500;
40
+ function now(options) {
41
+ return options.nowMs?.() ?? Date.now();
42
+ }
32
43
  function nudgeIdempotencyKey(reason, conversationId, nowMs) {
33
44
  return `${reason}:${conversationId}:${nowMs}`;
34
45
  }
@@ -248,7 +259,7 @@ async function processConversationWorkInContext(message, options) {
248
259
  const softYieldDeadlineMs = startedAtMs + (options.softYieldAfterMs ?? getChatConfig().conversationWorkSoftYieldAfterMs);
249
260
  let attemptMessageIds = [];
250
261
  let attemptSelectedMessageIds = /* @__PURE__ */ new Set();
251
- let attemptStartMessageIds = /* @__PURE__ */ new Set();
262
+ let attemptStartInterruptIds = /* @__PURE__ */ new Set();
252
263
  let failedWithoutProgress = false;
253
264
  let leaseLost = false;
254
265
  const markLeaseLost = () => {
@@ -269,7 +280,7 @@ async function processConversationWorkInContext(message, options) {
269
280
  leaseToken: lease.leaseToken,
270
281
  conversationStore: options.conversationStore,
271
282
  handle: async (messages) => {
272
- const candidates = drainOptions?.deferred ? messages : messages.filter((message) => message.delivery === "interrupt" && (attemptSelectedMessageIds.has(message.inboundMessageId) || !attemptStartMessageIds.has(message.inboundMessageId)));
283
+ const candidates = drainOptions?.deferred ? messages : messages.filter((message) => message.delivery === "interrupt" && (attemptSelectedMessageIds.has(message.inboundMessageId) || !attemptStartInterruptIds.has(message.inboundMessageId)));
273
284
  if (candidates.length === 0) return [];
274
285
  return await handle(candidates) ?? candidates.map((message) => message.inboundMessageId);
275
286
  },
@@ -337,7 +348,7 @@ async function processConversationWorkInContext(message, options) {
337
348
  const attemptMessages = selectAttemptMessages(leasedWork);
338
349
  const runId = leasedWork.execution.runId;
339
350
  if (!runId) throw new Error(`Conversation run is missing for ${conversationId}`);
340
- attemptStartMessageIds = new Set(leasedWork.messages.map((message) => message.inboundMessageId));
351
+ attemptStartInterruptIds = new Set(leasedWork.messages.filter((message) => isAttemptInterrupt(message, leasedWork)).map((message) => message.inboundMessageId));
341
352
  if (hasRun && shouldYield()) {
342
353
  if (resumePending) return await yieldWork();
343
354
  break;
@@ -0,0 +1,2 @@
1
+ ALTER TABLE "junior_automations" DROP CONSTRAINT "junior_automations_trigger_check";--> statement-breakpoint
2
+ ALTER TABLE "junior_automations" ADD CONSTRAINT "junior_automations_trigger_check" CHECK (("junior_automations"."kind" = 'scheduled' and "junior_automations"."namespace" is null and "junior_automations"."identifier" is null) or ("junior_automations"."kind" = 'event' and "junior_automations"."namespace" is not null and "junior_automations"."next_run_at_ms" is null and "junior_automations"."run_now_at_ms" is null and "junior_automations"."status" <> 'completed'));