@sentry/junior 0.267.0 → 0.269.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 (95) hide show
  1. package/README.md +2 -9
  2. package/dist/{actor-DZSokpwj.js → actor-CP9K2Idu.js} +2 -1
  3. package/dist/{adapter-BybMEezj.js → adapter-2-CG25be.js} +3 -51
  4. package/dist/{admin-DOs1_EiW.js → admin-DSs8S5Uy.js} +1 -1
  5. package/dist/{agent-invocations-CxKldAeB.js → agent-invocations-C1RNOCs8.js} +2 -0
  6. package/dist/{agent-runner-DgNATN4D.js → agent-runner-CrDrPUtY.js} +3411 -1640
  7. package/dist/api/schema.d.ts +2 -5630
  8. package/dist/api/schema.js +7 -7
  9. package/dist/api.d.ts +3 -1
  10. package/dist/api.js +268 -287
  11. package/dist/{app-DAB3fzyp.d.ts → app-BrMMzjYm.d.ts} +10 -3
  12. package/dist/app.d.ts +1 -1
  13. package/dist/app.js +371 -223
  14. package/dist/{automation-CmeFBSEh.js → automation-p87hg_AV.js} +74 -74
  15. package/dist/{briefs-CWKjka7v.js → briefs-PtODdLNu.js} +4 -4
  16. package/dist/{catalog-runtime-cMlAI5LY.js → catalog-runtime-BsoSmTM0.js} +1 -1
  17. package/dist/cli/chat.js +16 -26
  18. package/dist/cli/check.js +3 -3
  19. package/dist/cli/main.js +5 -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-BjgbMawj.js → client-Cqf4TboL.js} +20 -15
  25. package/dist/{config-CdB6yJj5.js → config-CPsE4T5L.js} +2 -2
  26. package/dist/{connections-RE_65jzK.js → connections-upFXLmhG.js} +10 -11
  27. package/dist/{conversation-DSo310Ps.js → conversation-CTpD_PGk.js} +7 -84
  28. package/dist/{conversation-privacy-BzgJC5k0.js → conversation-privacy-D6zJc8ff.js} +1 -1
  29. package/dist/{credential-sync-DhEGEpgq.js → credential-sync-CS_6IC-f.js} +30 -34
  30. package/dist/{credentialed-CIGwoLU2.js → credentialed-BU-OW7HP.js} +577 -74
  31. package/dist/{store-B8CABbmR.d.ts → db-BzOCzVb1.d.ts} +17 -7
  32. package/dist/{executor-VYrx_K4w.js → executor-CNS7ONt-.js} +78 -4
  33. package/dist/instrumentation.js +2 -2
  34. package/dist/{assistant-reply-CT7VcXQe.js → interruption-marker-g6Xup3Fk.js} +8 -2
  35. package/dist/{job-queue-C0BZSa7r.js → job-queue-DI-k-Bbk.js} +2 -2
  36. package/dist/{list-1XQP-o6K.js → list-CGoQdXTp.js} +429 -1401
  37. package/dist/locks-D-0h111u.js +48 -0
  38. package/dist/{logging-DuZ1A4ab.js → logging-n7knse-O.js} +1 -1
  39. package/dist/{history-C84mlAwO.js → media-85PDJxO_.js} +83 -1
  40. package/dist/{message-NKSbbnA6.js → message-BpaWd8TT.js} +4 -4
  41. package/dist/nitro.d.ts +1 -1
  42. package/dist/nitro.js +3 -3
  43. package/dist/{oauth-callback-server-qAHLPtml.js → oauth-callback-server-CpGmEw_i.js} +2 -2
  44. package/dist/{prompt-BW9jFsqZ.js → prompt-BlQB0QQt.js} +1 -1
  45. package/dist/{registry-FQutO926.js → registry-By36_xsm.js} +2 -2
  46. package/dist/reporting-schema-CZREhYc-.js +104 -0
  47. package/dist/reporting-window-CVarfId9.js +255 -0
  48. package/dist/{resolve-Bk4yeuHy.js → resolve-CUIBcdPd.js} +3 -3
  49. package/dist/{result-B9e9ATOU.js → result-BemsOMOO.js} +31 -12
  50. package/dist/{runner-C3S2ObH-.js → runner-BVok7PAA.js} +12 -11
  51. package/dist/{sandbox-egress-signals-DqpGzzMB.js → sandbox-egress-signals-BSUWQI95.js} +1 -1
  52. package/dist/{schema-X7Fj4fv1.js → schema-ChnFo5f2.js} +98 -6
  53. package/dist/schema-jK4-1u_H.d.ts +5927 -0
  54. package/dist/{service-account-Do30HUNv.js → service-account-DHvlLnZw.js} +4 -3
  55. package/dist/{service-account-BQasl-qq.js → service-account-hMmESDcr.js} +3 -3
  56. package/dist/{session-stop-DkOjt46_.js → session-stop-BQW_iFcd.js} +499 -23
  57. package/dist/{skills-CQHrwfOa.js → skills-DmJJIuLF.js} +2 -2
  58. package/dist/{spawn-BHuqN14f.js → spawn-ChCm46i-.js} +2 -2
  59. package/dist/{store-6EetVP-m.js → store-1DVhoKOL.js} +4 -4
  60. package/dist/{store-DvNZIsCr.js → store-DCo2n5iJ.js} +3 -3
  61. package/dist/{task-queue-B0DLgd2P.js → task-queue-HMC4QjFm.js} +3 -3
  62. package/dist/task-runner-cA6yjn_E.js +269 -0
  63. package/dist/{thread-state-DRmdJ2QN.js → thread-state-CHy8LS0C.js} +8 -18
  64. package/dist/{turn-failure-response-G11cs2gE.js → turn-failure-response-Dr7erLWs.js} +11 -16
  65. package/dist/{turn-lifecycle-OzLIwvi1.js → turn-lifecycle-bf2fIYi_.js} +1 -1
  66. package/dist/{tasks-0ilmuCux.js → turn-session-routing-BqO0qXLk.js} +959 -44
  67. package/dist/{validation-CxEmt1id.js → validation-DHR1ivfh.js} +1 -1
  68. package/dist/{version-Bapedn4A.js → version-CXCHLgWm.js} +1 -1
  69. package/dist/version.js +1 -1
  70. package/dist/{viewer-DrN3oC2X.js → viewer-DSbD6DF6.js} +503 -241
  71. package/dist/{work-DUQoNcqP.js → work-BE_qTYGi.js} +17 -36
  72. package/dist/{worker-D1l4Ugk0.js → worker-Cm9_sWXg.js} +15 -7
  73. package/migrations/0065_user_customization.sql +1 -0
  74. package/migrations/0066_review_items.sql +53 -0
  75. package/migrations/0067_review_item_dedupe_tenant.sql +2 -0
  76. package/migrations/0068_review_item_slack_cards.sql +10 -0
  77. package/migrations/0069_system_identity.sql +25 -0
  78. package/migrations/0070_review_item_foreign_keys.sql +5 -0
  79. package/migrations/AGENTS.md +17 -0
  80. package/migrations/meta/0065_snapshot.json +3511 -0
  81. package/migrations/meta/0066_snapshot.json +4099 -0
  82. package/migrations/meta/0067_snapshot.json +3921 -0
  83. package/migrations/meta/0068_snapshot.json +4176 -0
  84. package/migrations/meta/0069_snapshot.json +3979 -0
  85. package/migrations/meta/0070_snapshot.json +3997 -0
  86. package/migrations/meta/_journal.json +42 -0
  87. package/package.json +5 -5
  88. package/dist/db-Bg-zC3r5.d.ts +0 -5
  89. package/dist/history-BgI33Kie.d.ts +0 -78
  90. package/dist/images-CecjXAAz.js +0 -64
  91. package/dist/task-runner-B-PD_JOj.js +0 -1074
  92. package/dist/turn-session-routing-Dyut9l7Y.js +0 -76
  93. package/dist/user-input-request-BDFBdF8r.js +0 -116
  94. package/dist/web-message-id-CJSUiksE.js +0 -236
  95. package/migrations/README.md +0 -30
@@ -1,5 +1,5 @@
1
- import { h as logWarn } from "./logging-DuZ1A4ab.js";
2
- import { c as QUEUE_SIGNATURE_MAX_AGE_MS, d as getQueueProvider, l as signQueueMessage, p as runWithTurnRequestDeadline, u as verifyQueueMessage } from "./job-queue-C0BZSa7r.js";
1
+ import { h as logWarn } from "./logging-n7knse-O.js";
2
+ import { c as QUEUE_SIGNATURE_MAX_AGE_MS, d as getQueueProvider, l as signQueueMessage, p as runWithTurnRequestDeadline, u as verifyQueueMessage } from "./job-queue-DI-k-Bbk.js";
3
3
  import { z } from "zod";
4
4
  import { createHash } from "node:crypto";
5
5
  // src/chat/queue/callback.ts
@@ -110,7 +110,7 @@ function pluginTaskCallback() {
110
110
  maxDeliveries: PLUGIN_TASK_MAX_DELIVERIES,
111
111
  onRejected: logPluginTaskQueueMessageRejected,
112
112
  run: async (message) => {
113
- const { processPluginTask } = await import("./task-runner-B-PD_JOj.js").then((n) => n.r);
113
+ const { processPluginTask } = await import("./task-runner-cA6yjn_E.js").then((n) => n.r);
114
114
  await processPluginTask(message);
115
115
  },
116
116
  topic: PLUGIN_TASK_QUEUE_TOPIC,
@@ -0,0 +1,269 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-nwUcYXjP.js";
2
+ import { Er as normalizeToolNameFromResult, Gt as hydrateConversationMessages, On as getTurnRecord, Or as stripRuntimeTurnContext, Tr as isToolResultMessage, _r as getPiMessageRole, t as resolveConversationRouting, u as getDispatchRecord, wr as isToolResultError, xr as instructionTextForProjection } from "./turn-session-routing-BqO0qXLk.js";
3
+ import { m as parseSlackMessageTs } from "./actor-CP9K2Idu.js";
4
+ import { S as getDb, i as readActorIdentity, x as getConversationStore } from "./viewer-DSbD6DF6.js";
5
+ import { _ as sameActorIdentity } from "./media-85PDJxO_.js";
6
+ import { ar as createPluginLogger, g as coreTaskRegistrations, hr as createPluginConversationEvents, ir as createPluginModel, jr as createPluginCache, nr as createPluginState, p as getPlugins, rr as createPluginEmbedder } from "./credentialed-BU-OW7HP.js";
7
+ import { r as getStateAdapter } from "./adapter-2-CG25be.js";
8
+ import { o as coerceThreadConversationState, r as getPersistedThreadState } from "./thread-state-CHy8LS0C.js";
9
+ import { i as pluginTaskParamsSchema, r as pluginTaskId, s as sendVercelPluginTask } from "./task-queue-HMC4QjFm.js";
10
+ import { pluginRunContextSchema } from "@sentry/junior-plugin-api";
11
+ // src/chat/plugins/task-runner.ts
12
+ /**
13
+ * Plugin background-task orchestration.
14
+ *
15
+ * Core schedules tasks from completed sessions and exposes plugins only a
16
+ * bounded run projection rather than live runtime internals or queue
17
+ * payloads.
18
+ */
19
+ var task_runner_exports = /* @__PURE__ */ __exportAll({
20
+ processPluginTask: () => processPluginTask,
21
+ scheduleSessionCompletedPluginTasks: () => scheduleSessionCompletedPluginTasks
22
+ });
23
+ const PLUGIN_TASK_LOCK_TTL_MS = 3e5;
24
+ function isRecord(value) {
25
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
26
+ }
27
+ function textPart(value) {
28
+ if (isRecord(value) && value.type === "text" && typeof value.text === "string") return value.text;
29
+ }
30
+ function messageText(message) {
31
+ const content = message.content;
32
+ if (typeof content === "string") return sanitizeText(content);
33
+ if (!Array.isArray(content)) return "";
34
+ return sanitizeText(content.map(textPart).filter(Boolean).join("\n"));
35
+ }
36
+ function toolResultText(message) {
37
+ const record = message;
38
+ return sanitizeText([
39
+ messageText(message),
40
+ record.output,
41
+ record.result,
42
+ record.stdout,
43
+ record.stderr,
44
+ record.toolResult
45
+ ].filter((value) => typeof value === "string" && value.length > 0).join("\n"));
46
+ }
47
+ function sanitizeText(text) {
48
+ return text.replace(/<data_base64>[\s\S]*?<\/data_base64>/g, "<data_base64>[omitted]</data_base64>").replace(/data:image\/[a-z0-9.+-]+;base64,[a-z0-9+/=]+/gi, "[image data omitted]").replaceAll("\0", " ").trim();
49
+ }
50
+ /** Build the transcript provenance for a user message from its Pi provenance. */
51
+ function messageProvenance(provenance) {
52
+ return {
53
+ authority: provenance.authority,
54
+ ...provenance.actor ? { actor: provenance.actor } : void 0
55
+ };
56
+ }
57
+ function runTranscriptEntry(message, provenance, runActor) {
58
+ const role = getPiMessageRole(message);
59
+ if (role === "user" || role === "assistant") {
60
+ const text = role === "user" ? instructionTextForProjection(messageText(message)) : messageText(message);
61
+ if (!text) return;
62
+ if (role === "assistant") return {
63
+ type: "message",
64
+ role,
65
+ text
66
+ };
67
+ return {
68
+ type: "message",
69
+ role,
70
+ text,
71
+ provenance: messageProvenance(provenance),
72
+ isRunActor: sameActorIdentity(provenance.actor, runActor)
73
+ };
74
+ }
75
+ if (!isToolResultMessage(message)) return;
76
+ const toolName = normalizeToolNameFromResult(message);
77
+ if (!toolName) return;
78
+ const text = toolResultText(message);
79
+ return {
80
+ type: "toolResult",
81
+ toolName,
82
+ isError: isToolResultError(message),
83
+ ...text ? { text } : void 0
84
+ };
85
+ }
86
+ /**
87
+ * Slice the current turn's Pi messages with their aligned provenance and strip
88
+ * runtime turn context, keeping each surviving message paired with the exact
89
+ * provenance recorded for it. Stripping can drop or rewrite messages, so the
90
+ * pairing is applied per message rather than by post-strip index.
91
+ */
92
+ function turnMessagesWithProvenance(record) {
93
+ const startIndex = record.turnStartMessageIndex ?? 0;
94
+ const messages = record.piMessages.slice(startIndex);
95
+ const provenance = record.piMessageProvenance.slice(startIndex);
96
+ const paired = [];
97
+ for (const [index, message] of messages.entries()) for (const stripped of stripRuntimeTurnContext([message])) paired.push({
98
+ message: stripped,
99
+ provenance: provenance[index] ?? { authority: "context" }
100
+ });
101
+ return paired;
102
+ }
103
+ /** Recover the Slack context author identity from a persisted thread message. */
104
+ function slackContextAuthor(location, message) {
105
+ const userId = message.author?.userId?.trim();
106
+ if (!userId) return;
107
+ return {
108
+ platform: "slack",
109
+ teamId: location.teamId,
110
+ userId,
111
+ ...message.author?.userName ? { userName: message.author.userName } : void 0,
112
+ ...message.author?.fullName ? { fullName: message.author.fullName } : void 0
113
+ };
114
+ }
115
+ function slackTimestampMs(value) {
116
+ const timestamp = parseSlackMessageTs(value);
117
+ if (!timestamp) return;
118
+ const timestampMs = Number(timestamp) * 1e3;
119
+ return Number.isFinite(timestampMs) ? timestampMs : void 0;
120
+ }
121
+ function conversationMessageTimestampMs(message) {
122
+ if (message.meta?.slackTs !== void 0) return slackTimestampMs(message.meta.slackTs);
123
+ return Number.isFinite(message.createdAtMs) ? message.createdAtMs : void 0;
124
+ }
125
+ function messageExistedAtRunCompletion(message, completedAtMs) {
126
+ const messageTimestampMs = conversationMessageTimestampMs(message);
127
+ return messageTimestampMs !== void 0 && messageTimestampMs <= completedAtMs;
128
+ }
129
+ /**
130
+ * Project bounded public-thread context into the run transcript.
131
+ *
132
+ * Prior public Slack messages from the current Conversation are durable
133
+ * evidence a completed run may have acted on, so passive consumers can cite
134
+ * them. They are always context authority (never instruction), and private or
135
+ * local Conversations add nothing here.
136
+ */
137
+ async function loadConversationContextTranscriptEntries(record, location, visibility, runActor) {
138
+ if (location?.provider !== "slack" || visibility !== "public") return [];
139
+ const state = await getPersistedThreadState(record.conversationId);
140
+ const conversation = coerceThreadConversationState(state);
141
+ await hydrateConversationMessages({
142
+ conversation,
143
+ conversationId: record.conversationId
144
+ });
145
+ const entries = [];
146
+ for (const message of conversation.messages) {
147
+ if (message.role !== "user") continue;
148
+ if (!messageExistedAtRunCompletion(message, record.updatedAtMs)) continue;
149
+ const text = sanitizeText(message.text);
150
+ if (!text) continue;
151
+ const author = slackContextAuthor(location, message);
152
+ entries.push({
153
+ type: "message",
154
+ role: "user",
155
+ text,
156
+ provenance: {
157
+ authority: "context",
158
+ ...author ? { actor: author } : void 0
159
+ },
160
+ isRunActor: sameActorIdentity(author, runActor)
161
+ });
162
+ }
163
+ return entries;
164
+ }
165
+ async function withPluginTaskLock(taskId, callback) {
166
+ const state = getStateAdapter();
167
+ await state.connect();
168
+ const lock = await state.acquireLock(`plugin:task:${taskId}`, PLUGIN_TASK_LOCK_TTL_MS);
169
+ if (!lock) throw new Error(`Could not acquire plugin task lock for ${taskId}`);
170
+ try {
171
+ return await callback();
172
+ } finally {
173
+ await state.releaseLock(lock);
174
+ }
175
+ }
176
+ /** Load the bounded completed-run projection exposed to plugin tasks. */
177
+ async function loadPluginRun(params) {
178
+ const record = await getTurnRecord(params.conversationId, params.sessionId);
179
+ if (!record) throw new Error("Completed plugin task session record is unavailable");
180
+ if (record.state !== "completed") throw new Error("Completed plugin task session record is not completed");
181
+ const conversationStore = getConversationStore();
182
+ const routing = await resolveConversationRouting({
183
+ conversationId: params.conversationId,
184
+ conversationStore
185
+ });
186
+ if (!routing) throw new Error(`Conversation ${params.conversationId} is missing durable routing metadata`);
187
+ const source = record.source ?? routing.source;
188
+ if (!source) throw new Error("Completed plugin task session record is missing Source");
189
+ const conversation = await conversationStore.get({ conversationId: params.conversationId });
190
+ const runActor = record.actor ?? record.actors[0] ?? (record.dispatchId ? (await getDispatchRecord(record.dispatchId))?.actor : void 0);
191
+ const actorUser = runActor ? (await readActorIdentity(runActor))?.user : void 0;
192
+ const runEntries = turnMessagesWithProvenance(record).map(({ message, provenance }) => runTranscriptEntry(message, provenance, runActor)).filter((entry) => Boolean(entry));
193
+ const runMessageTexts = new Set(runEntries.filter((entry) => entry.type === "message").map((entry) => entry.text));
194
+ const contextEntries = (await loadConversationContextTranscriptEntries(record, conversation?.location, conversation?.visibility, runActor)).filter((entry) => entry.type !== "message" || !runMessageTexts.has(entry.text));
195
+ return pluginRunContextSchema.parse({
196
+ ...actorUser ? { actorUserId: actorUser.id } : void 0,
197
+ completedAtMs: record.updatedAtMs,
198
+ conversationId: record.conversationId,
199
+ destination: routing.destination,
200
+ ...routing.location ? { locationId: routing.location.id } : void 0,
201
+ actors: record.actors,
202
+ ...runActor ? { actor: runActor } : void 0,
203
+ runId: record.turnId,
204
+ source,
205
+ transcript: [...contextEntries, ...runEntries]
206
+ });
207
+ }
208
+ /** Build the plugin-facing context for one claimed task attempt. */
209
+ function taskPluginContext(plugin, message, options = {}) {
210
+ const pluginName = plugin.manifest.name;
211
+ const sessionParams = pluginTaskParamsSchema.parse(message.params);
212
+ return {
213
+ db: getDb(),
214
+ embedder: createPluginEmbedder(pluginName, { signal: options.signal }),
215
+ events: createPluginConversationEvents({
216
+ conversationId: sessionParams.conversationId,
217
+ operationId: pluginTaskId(message),
218
+ plugin,
219
+ turnId: sessionParams.sessionId
220
+ }),
221
+ id: pluginTaskId(message),
222
+ log: createPluginLogger(pluginName),
223
+ model: createPluginModel(pluginName, plugin.model, { signal: options.signal }),
224
+ name: message.name,
225
+ plugin: { name: pluginName },
226
+ cache: createPluginCache(pluginName),
227
+ run: { async load() {
228
+ return await loadPluginRun(sessionParams);
229
+ } },
230
+ state: createPluginState(pluginName)
231
+ };
232
+ }
233
+ function findPluginTask(message) {
234
+ const plugin = [...coreTaskRegistrations(), ...getPlugins()].find((candidate) => candidate.manifest.name === message.plugin);
235
+ if (!plugin?.tasks || !Object.hasOwn(plugin.tasks, message.name)) return;
236
+ return {
237
+ plugin,
238
+ task: plugin.tasks[message.name]
239
+ };
240
+ }
241
+ /** Schedule all plugin tasks interested in a completed agent-run session. */
242
+ async function scheduleSessionCompletedPluginTasks(params, options = {}) {
243
+ const coreParams = pluginTaskParamsSchema.parse(params);
244
+ const taskRegistrations = [...getPlugins(), ...coreTaskRegistrations()].flatMap((plugin) => Object.keys(plugin.tasks ?? {}).map((name) => ({
245
+ name,
246
+ plugin
247
+ })));
248
+ if (taskRegistrations.length === 0) return;
249
+ const record = await getTurnRecord(coreParams.conversationId, coreParams.sessionId);
250
+ if (!record || record.state !== "completed") throw new Error("Completed plugin task session record is not ready");
251
+ const send = options.send ?? sendVercelPluginTask;
252
+ const messages = taskRegistrations.map(({ name, plugin }) => ({
253
+ name,
254
+ params: coreParams,
255
+ plugin: plugin.manifest.name
256
+ }));
257
+ await Promise.all(messages.map(async (message) => {
258
+ await send(message);
259
+ }));
260
+ }
261
+ /** Execute one parsed plugin task request. */
262
+ async function processPluginTask(message, options = {}) {
263
+ await withPluginTaskLock(pluginTaskId(message), async () => {
264
+ const resolved = findPluginTask(message);
265
+ if (!resolved?.task) throw new Error(`Plugin task "${message.plugin}.${message.name}" is not registered`);
266
+ await resolved.task.run(taskPluginContext(resolved.plugin, message, options));
267
+ });
268
+ }
269
+ export { scheduleSessionCompletedPluginTasks as n, task_runner_exports as r, processPluginTask as t };
@@ -1,8 +1,8 @@
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";
1
+ import { Gr as createDurableLocationConfigurationService, Kt as persistConversationMessages } from "./turn-session-routing-BqO0qXLk.js";
2
+ import { B as isRecord, H as toOptionalString, V as toOptionalNumber } from "./logging-n7knse-O.js";
3
+ import { S as getDb } from "./viewer-DSbD6DF6.js";
4
+ import { In as JUNIOR_THREAD_STATE_TTL_MS } from "./credentialed-BU-OW7HP.js";
5
+ import { r as getStateAdapter } from "./adapter-2-CG25be.js";
6
6
  // src/chat/state/conversation.ts
7
7
  function defaultConversationState() {
8
8
  return {
@@ -134,19 +134,9 @@ function getPersistedSandboxState(state) {
134
134
  ...workspaceId ? { workspaceId } : void 0
135
135
  };
136
136
  }
137
- /** Persist a thread-state patch for a Chat thread handle. */
138
- async function persistThreadState(thread, patch) {
139
- if (patch.conversation) await persistConversationMessages({
140
- conversation: patch.conversation,
141
- conversationId: toOptionalString(thread.id) ?? toOptionalString(thread.runId)
142
- });
143
- await persistThreadRuntimeState(thread, patch);
144
- }
145
137
  /** Persist only the Redis-backed runtime scratch in a thread-state patch. */
146
- async function persistThreadRuntimeState(thread, patch) {
147
- const threadId = toOptionalString(thread.id) ?? toOptionalString(thread.runId);
148
- if (!threadId) throw new Error("thread id is required to persist runtime scratch");
149
- await mergePersistedState(threadStateKey(threadId), buildThreadStatePayload(patch));
138
+ async function persistThreadRuntimeState(conversationId, patch) {
139
+ await mergePersistedState(threadStateKey(conversationId), buildThreadStatePayload(patch));
150
140
  }
151
141
  /** Load the persisted state payload for a thread without requiring a Chat singleton. */
152
142
  async function getPersistedThreadState(threadId) {
@@ -181,4 +171,4 @@ function getLocationConfigurationService(destination) {
181
171
  loadLegacy: async () => await getLegacyChannelState(destination.channelId)
182
172
  });
183
173
  }
184
- export { persistThreadState as a, persistThreadRuntimeState as i, getPersistedSandboxState as n, persistThreadStateById as o, getPersistedThreadState as r, coerceThreadConversationState as s, getLocationConfigurationService as t };
174
+ export { persistThreadStateById as a, persistThreadRuntimeState as i, getPersistedSandboxState as n, coerceThreadConversationState as o, getPersistedThreadState as r, getLocationConfigurationService as t };
@@ -1,12 +1,13 @@
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";
1
+ import { Gt as hydrateConversationMessages, Pr as buildDeterministicTurnId, an as markConversationMessage, yn as clearPendingAuth } from "./turn-session-routing-BqO0qXLk.js";
2
+ import { _ as getProviderErrorAttributes, g as findProviderError, m as ProviderError, v as getProviderErrorUserMessage } from "./client-Cqf4TboL.js";
3
+ import { B as isRecord, t as buildTurnFailureResponse } from "./logging-n7knse-O.js";
4
+ import { m as parseSlackMessageTs } from "./actor-CP9K2Idu.js";
5
+ import { S as getDb, y as getConversationEventStore } from "./viewer-DSbD6DF6.js";
6
+ import { Er as listConversationAnnotations } from "./credentialed-BU-OW7HP.js";
7
+ import { B as removedCardSchema, V as resolveMessageCards, z as readMessageCardRefs } from "./conversation-CTpD_PGk.js";
8
+ import { D as parseAgentInvocationResultMessageId, J as markTurnClosed, Y as markTurnCompleted, c as getAgentInvocation, m as getAgentInvocationTurnId } from "./store-1DVhoKOL.js";
9
+ import { t as getInterruptionMarker } from "./interruption-marker-g6Xup3Fk.js";
10
+ import { a as persistThreadStateById, o as coerceThreadConversationState, r as getPersistedThreadState } from "./thread-state-CHy8LS0C.js";
10
11
  // src/chat/conversations/pending-cards.ts
11
12
  /**
12
13
  * Add the cards that tool results selected since the last visible assistant
@@ -66,12 +67,6 @@ async function loadPendingMessageCards(conversationId) {
66
67
  if (selection.cards.size === 0) return [];
67
68
  return resolveMessageCards([...selection.cards.values()].reverse(), await listConversationAnnotations(getDb(), conversationId));
68
69
  }
69
- // src/chat/interruption-marker.ts
70
- const INTERRUPTED_MARKER = "\n\n[Response interrupted before completion]";
71
- /** Return the marker added when a visible reply ended mid-execution. */
72
- function getInterruptionMarker() {
73
- return INTERRUPTED_MARKER;
74
- }
75
70
  // src/chat/runtime/delivered-turn-state.ts
76
71
  /** Build state after destination delivery or intentional no-reply completion. */
77
72
  function buildDeliveredTurnStatePatch(args) {
@@ -222,4 +217,4 @@ function finalizeFailedTurnReplyWithEvent(args) {
222
217
  }
223
218
  };
224
219
  }
225
- export { persistAuthPauseTurnState as a, getTurnUserSlackMessageTs as c, loadPendingMessageCards as d, completeAuthPauseTurn as i, buildDeliveredTurnStatePatch as l, getAgentTurnDiagnosticsAttributes as n, getTurnUserMessage as o, requireTurnFailureEventId as r, getTurnUserReplyAttachmentContext as s, finalizeFailedTurnReplyWithEvent as t, getInterruptionMarker as u };
220
+ export { persistAuthPauseTurnState as a, getTurnUserSlackMessageTs as c, completeAuthPauseTurn as i, buildDeliveredTurnStatePatch as l, getAgentTurnDiagnosticsAttributes as n, getTurnUserMessage as o, requireTurnFailureEventId as r, getTurnUserReplyAttachmentContext as s, finalizeFailedTurnReplyWithEvent as t, loadPendingMessageCards as u };
@@ -1,4 +1,4 @@
1
- import { u as getConversationEventStore } from "./viewer-DrN3oC2X.js";
1
+ import { y as getConversationEventStore } from "./viewer-DSbD6DF6.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 {