@sentry/junior 0.93.0 → 0.95.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.
- package/dist/{agent-hooks-ZG7IDOIN.js → agent-hooks-FTQ5EGPO.js} +9 -10
- package/dist/api/people/list.js +7 -7
- package/dist/api/people/profile.js +7 -7
- package/dist/api/people/shared.d.ts +2 -2
- package/dist/api-reference.d.ts +1 -1
- package/dist/app.js +474 -231
- package/dist/{catalog-runtime-NZHMSMYC.js → catalog-runtime-2D7IVKUT.js} +3 -3
- package/dist/chat/advisor-request.d.ts +4 -0
- package/dist/chat/agent/request.d.ts +2 -0
- package/dist/chat/agent/resume.d.ts +2 -0
- package/dist/chat/conversations/history.d.ts +128 -0
- package/dist/chat/conversations/legacy-import.d.ts +38 -0
- package/dist/chat/conversations/messages.d.ts +39 -0
- package/dist/chat/conversations/projection.d.ts +94 -0
- package/dist/chat/conversations/retention.d.ts +36 -0
- package/dist/chat/conversations/sql/conversation-row.d.ts +14 -0
- package/dist/chat/conversations/sql/history.d.ts +4 -0
- package/dist/chat/conversations/sql/legacy-history-import.d.ts +55 -0
- package/dist/chat/conversations/sql/messages.d.ts +4 -0
- package/dist/chat/conversations/sql/migrations.d.ts +14 -3
- package/dist/chat/conversations/sql/purge.d.ts +53 -0
- package/dist/chat/conversations/sql/store.d.ts +7 -2
- package/dist/chat/conversations/store.d.ts +19 -0
- package/dist/chat/conversations/visible-compactions.d.ts +11 -0
- package/dist/chat/conversations/visible-messages.d.ts +47 -0
- package/dist/chat/db.d.ts +12 -1
- package/dist/chat/egress/credentialed.d.ts +1 -1
- package/dist/chat/identities/sql.d.ts +1 -1
- package/dist/chat/logging.d.ts +2 -1
- package/dist/chat/resource-events/store.d.ts +2 -1
- package/dist/chat/runtime/reply-executor.d.ts +8 -0
- package/dist/chat/runtime/thread-state.d.ts +2 -0
- package/dist/chat/sandbox/egress/schemas.d.ts +4 -0
- package/dist/chat/sandbox/egress/session.d.ts +2 -2
- package/dist/chat/sandbox/resources.d.ts +4 -0
- package/dist/chat/services/mcp-auth-orchestration.d.ts +8 -0
- package/dist/chat/services/plugin-auth-orchestration.d.ts +12 -0
- package/dist/chat/services/turn-session-record.d.ts +14 -2
- package/dist/chat/sleep.d.ts +2 -0
- package/dist/chat/state/conversation.d.ts +7 -4
- package/dist/chat/state/session-log.d.ts +23 -1
- package/dist/chat/state/turn-session.d.ts +6 -0
- package/dist/chat/tool-support/private-trace-result.d.ts +4 -0
- package/dist/chat/tool-support/zod-tool.d.ts +1 -0
- package/dist/chat/tools/advisor/tool.d.ts +9 -4
- package/dist/chat/tools/definition.d.ts +2 -0
- package/dist/chat/tools/execution/tool-error-handler.d.ts +2 -2
- package/dist/chat/tools/system-time.d.ts +8 -0
- package/dist/chat/xml.d.ts +2 -0
- package/dist/{chunk-NYWPISSO.js → chunk-2XXEKR44.js} +1 -1
- package/dist/{chunk-QGEWC27H.js → chunk-5XMNOD3S.js} +5 -7
- package/dist/{chunk-NFXSLTYG.js → chunk-6ONME5IG.js} +864 -62
- package/dist/{chunk-LFLTJQVR.js → chunk-7FBGKXPE.js} +4 -0
- package/dist/{chunk-MC4ZZE4Q.js → chunk-AYP4ERVZ.js} +1 -1
- package/dist/{chunk-GHGPTPBL.js → chunk-B7PUBQQM.js} +1 -1
- package/dist/chunk-CM5EZD5F.js +17 -0
- package/dist/chunk-CRRBJ3JP.js +1037 -0
- package/dist/{chunk-G3E7SCME.js → chunk-CZEX6KIQ.js} +23 -0
- package/dist/{chunk-TNUUATT7.js → chunk-E3E2XNCN.js} +2 -2
- package/dist/{chunk-LNCREA5Z.js → chunk-EKNJM5IG.js} +3 -127
- package/dist/{chunk-NAPITCZ6.js → chunk-GUE7HTNR.js} +251 -6
- package/dist/{chunk-BTH37NCU.js → chunk-GVOUCI2O.js} +1 -1
- package/dist/{chunk-YYBX2BD5.js → chunk-GY34VGP5.js} +1 -1
- package/dist/{chunk-JJUJ4CO2.js → chunk-HCXXB35T.js} +1489 -360
- package/dist/{chunk-YTNPU7I2.js → chunk-HDTO3A74.js} +2 -2
- package/dist/{chunk-YJ4OPVNA.js → chunk-HZNJLKKI.js} +1 -1
- package/dist/{chunk-HDNWZMUN.js → chunk-KDPCGVIT.js} +116 -51
- package/dist/chunk-N4RNJ32C.js +48 -0
- package/dist/{chunk-UUB3D2XI.js → chunk-NSCHU54X.js} +8 -10
- package/dist/{chunk-PFXC67GJ.js → chunk-RAIB6WSG.js} +6 -80
- package/dist/chunk-WAGQ377B.js +724 -0
- package/dist/{chunk-6H4PP63X.js → chunk-WCMQJE4F.js} +24 -14
- package/dist/{chunk-S6QKIGRM.js → chunk-WPOJ443W.js} +15 -25
- package/dist/{chunk-MAVOJ54A.js → chunk-XX4N4E6C.js} +25 -388
- package/dist/cli/chat.js +24 -23
- package/dist/cli/check.js +4 -4
- package/dist/cli/plugins.js +11 -12
- package/dist/cli/snapshot-warmup.js +7 -8
- package/dist/cli/upgrade.js +78 -17
- package/dist/db/schema/agent-steps.d.ts +134 -0
- package/dist/db/schema/conversation-messages.d.ts +153 -0
- package/dist/{chat/conversations/sql → db}/schema/conversations.d.ts +34 -0
- package/dist/{chat/conversations/sql → db}/schema.d.ts +319 -8
- package/dist/db-W55B74OP.js +24 -0
- package/dist/deployment.d.ts +2 -0
- package/dist/handlers/retention.d.ts +6 -0
- package/dist/instrumentation.js +16 -3
- package/dist/legacy-import-ZPLGLAFD.js +17 -0
- package/dist/nitro.js +14 -4
- package/dist/reporting/conversations/activity.d.ts +40 -0
- package/dist/reporting/conversations/context.d.ts +8 -0
- package/dist/reporting/conversations/details.d.ts +6 -0
- package/dist/reporting/conversations/index.d.ts +4 -0
- package/dist/reporting/conversations/shared.d.ts +9 -0
- package/dist/reporting/conversations/statistics.d.ts +4 -0
- package/dist/reporting/conversations/summaries.d.ts +17 -0
- package/dist/reporting/conversations/transcript.d.ts +28 -0
- package/dist/reporting/conversations/types.d.ts +178 -0
- package/dist/reporting/conversations.d.ts +1 -178
- package/dist/reporting.d.ts +4 -3
- package/dist/reporting.js +603 -827
- package/dist/{runner-XAZPJNAQ.js → runner-OOSBDYRK.js} +35 -41
- package/dist/{validation-KYAWETI4.js → validation-QCGRFRFZ.js} +4 -4
- package/migrations/README.md +32 -0
- package/migrations/meta/0000_snapshot.json +978 -0
- package/migrations/meta/_journal.json +13 -0
- package/package.json +9 -6
- package/dist/chat/sql/schema.d.ts +0 -1049
- package/dist/chat/state/conversation-details.d.ts +0 -47
- package/dist/chunk-7STN2ZSK.js +0 -250
- package/dist/chunk-LE5ANBUZ.js +0 -1040
- package/dist/chunk-QL66APYJ.js +0 -1377
- package/dist/db-YDN6AFJH.js +0 -18
- /package/dist/{chat/sql → db}/db.d.ts +0 -0
- /package/dist/{chat/sql → db}/executor.d.ts +0 -0
- /package/dist/{chat/sql → db}/neon.d.ts +0 -0
- /package/dist/{chat/sql → db}/postgres.d.ts +0 -0
- /package/dist/{chat/conversations/sql → db}/schema/destinations.d.ts +0 -0
- /package/dist/{chat/conversations/sql → db}/schema/identities.d.ts +0 -0
- /package/dist/{chat/conversations/sql → db}/schema/migrations.d.ts +0 -0
- /package/dist/{chat/conversations/sql → db}/schema/timestamps.d.ts +0 -0
- /package/dist/{chat/conversations/sql → db}/schema/users.d.ts +0 -0
package/dist/app.js
CHANGED
|
@@ -1,23 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
|
-
buildConversationContext,
|
|
3
2
|
buildDeliveredTurnStatePatch,
|
|
4
|
-
createConversationMemoryService,
|
|
5
|
-
estimateTextTokens,
|
|
6
3
|
finalizeFailedTurnReply,
|
|
7
|
-
generateConversationId,
|
|
8
|
-
getAgentContextCompactionTriggerTokens,
|
|
9
4
|
getAgentTurnDiagnosticsAttributes,
|
|
10
|
-
getConversationMessageSlackTs,
|
|
11
|
-
getThreadTitleSourceMessage,
|
|
12
|
-
isHumanConversationMessage,
|
|
13
|
-
markConversationMessage,
|
|
14
|
-
normalizeConversationText,
|
|
15
5
|
processPluginTask,
|
|
16
6
|
requireTurnFailureEventId,
|
|
17
|
-
scheduleSessionCompletedPluginTasks
|
|
18
|
-
|
|
19
|
-
upsertConversationMessage
|
|
20
|
-
} from "./chunk-MAVOJ54A.js";
|
|
7
|
+
scheduleSessionCompletedPluginTasks
|
|
8
|
+
} from "./chunk-XX4N4E6C.js";
|
|
21
9
|
import {
|
|
22
10
|
CONVERSATION_WORK_CHECK_IN_INTERVAL_MS,
|
|
23
11
|
CONVERSATION_WORK_STALE_ENQUEUE_MS,
|
|
@@ -41,12 +29,12 @@ import {
|
|
|
41
29
|
requestConversationContinuation,
|
|
42
30
|
requestConversationWork,
|
|
43
31
|
startConversationWork
|
|
44
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-5XMNOD3S.js";
|
|
45
33
|
import {
|
|
46
34
|
getVercelConversationWorkQueue,
|
|
47
35
|
resolveConversationWorkQueueTopic,
|
|
48
36
|
verifyConversationQueueMessage
|
|
49
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-2XXEKR44.js";
|
|
50
38
|
import {
|
|
51
39
|
PLUGIN_TASK_QUEUE_TOPIC,
|
|
52
40
|
createVercelQueueClient,
|
|
@@ -56,15 +44,13 @@ import {
|
|
|
56
44
|
GET,
|
|
57
45
|
buildSentryConversationUrl,
|
|
58
46
|
conversationVisibilityFromSlackChannelType,
|
|
59
|
-
initConversationContext,
|
|
60
47
|
resolveSlackChannelTypeFromMessage,
|
|
61
|
-
resolveSlackConversationContext
|
|
62
|
-
|
|
63
|
-
} from "./chunk-LNCREA5Z.js";
|
|
48
|
+
resolveSlackConversationContext
|
|
49
|
+
} from "./chunk-EKNJM5IG.js";
|
|
64
50
|
import {
|
|
65
51
|
validatePluginEgressCredentialHooks,
|
|
66
52
|
validatePluginRegistrations
|
|
67
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-AYP4ERVZ.js";
|
|
68
54
|
import {
|
|
69
55
|
defineJuniorPlugins,
|
|
70
56
|
pluginCatalogConfigFromEnv,
|
|
@@ -77,6 +63,7 @@ import {
|
|
|
77
63
|
SANDBOX_EGRESS_PROXY_PATH,
|
|
78
64
|
addReactionToMessage,
|
|
79
65
|
appendSlackLegacyAttachmentText,
|
|
66
|
+
buildSlackOutputMessage,
|
|
80
67
|
buildSteeringPiMessage,
|
|
81
68
|
createAgentRunner,
|
|
82
69
|
createUserTokenStore,
|
|
@@ -85,15 +72,18 @@ import {
|
|
|
85
72
|
deleteMcpServerSessionId,
|
|
86
73
|
deleteMcpStoredOAuthCredentials,
|
|
87
74
|
deliverResourceEventSubscription,
|
|
75
|
+
escapeSlackMrkdwnText,
|
|
88
76
|
executeAgentRun,
|
|
89
77
|
executeCredentialedEgressRequest,
|
|
90
78
|
finalizeMcpAuthorization,
|
|
91
79
|
findMatchingResourceEventSubscriptions,
|
|
92
80
|
formatProviderLabel,
|
|
81
|
+
formatSlackLink,
|
|
93
82
|
getConfigDefaults,
|
|
94
83
|
getMcpStoredOAuthCredentials,
|
|
95
84
|
listThreadReplies,
|
|
96
85
|
normalizeSandboxEgressTracePropagationDomains,
|
|
86
|
+
normalizeSlackStatusText,
|
|
97
87
|
parseOAuthStatePayload,
|
|
98
88
|
parseSandboxEgressCredentialToken,
|
|
99
89
|
postSlackMessage,
|
|
@@ -105,8 +95,10 @@ import {
|
|
|
105
95
|
setConfigDefaults,
|
|
106
96
|
shouldEmitDevAgentTrace,
|
|
107
97
|
shouldPropagateSandboxEgressTrace,
|
|
108
|
-
|
|
109
|
-
|
|
98
|
+
splitSlackReplyText,
|
|
99
|
+
startOAuthFlow,
|
|
100
|
+
truncateStatusText
|
|
101
|
+
} from "./chunk-HCXXB35T.js";
|
|
110
102
|
import {
|
|
111
103
|
CooperativeTurnYieldError,
|
|
112
104
|
TurnInputCommitLostError,
|
|
@@ -129,37 +121,48 @@ import {
|
|
|
129
121
|
markTurnFailed,
|
|
130
122
|
mergeArtifactsState,
|
|
131
123
|
persistCompletedSessionRecord,
|
|
124
|
+
persistThreadRuntimeState,
|
|
132
125
|
persistThreadState,
|
|
133
126
|
persistThreadStateById,
|
|
127
|
+
persistWithRetry,
|
|
134
128
|
persistYieldSessionRecord,
|
|
135
129
|
startActiveTurn
|
|
136
|
-
} from "./chunk-
|
|
130
|
+
} from "./chunk-KDPCGVIT.js";
|
|
137
131
|
import {
|
|
138
|
-
JUNIOR_THREAD_STATE_TTL_MS,
|
|
139
132
|
coerceThreadConversationState
|
|
140
|
-
} from "./chunk-
|
|
141
|
-
import "./chunk-
|
|
142
|
-
import
|
|
143
|
-
|
|
144
|
-
escapeSlackMrkdwnText,
|
|
145
|
-
formatSlackLink,
|
|
146
|
-
normalizeSlackStatusText,
|
|
147
|
-
splitSlackReplyText,
|
|
148
|
-
truncateStatusText
|
|
149
|
-
} from "./chunk-LE5ANBUZ.js";
|
|
133
|
+
} from "./chunk-RAIB6WSG.js";
|
|
134
|
+
import "./chunk-WCMQJE4F.js";
|
|
135
|
+
import "./chunk-CM5EZD5F.js";
|
|
136
|
+
import "./chunk-N4RNJ32C.js";
|
|
150
137
|
import {
|
|
151
138
|
abandonAgentTurnSessionRecord,
|
|
152
139
|
commitMessages,
|
|
153
|
-
contextProvenance,
|
|
154
140
|
failAgentTurnSessionRecord,
|
|
155
141
|
getAgentTurnSessionRecord,
|
|
156
|
-
instructionProvenanceFor,
|
|
157
142
|
listAgentTurnSessionSummariesForConversation,
|
|
158
143
|
loadProjection,
|
|
159
144
|
loadProjectionWithProvenance,
|
|
160
145
|
recordAgentTurnSessionSummary,
|
|
161
146
|
recordAuthorizationCompleted
|
|
162
|
-
} from "./chunk-
|
|
147
|
+
} from "./chunk-WAGQ377B.js";
|
|
148
|
+
import {
|
|
149
|
+
JUNIOR_THREAD_STATE_TTL_MS,
|
|
150
|
+
buildConversationContext,
|
|
151
|
+
createConversationMemoryService,
|
|
152
|
+
estimateTextTokens,
|
|
153
|
+
generateConversationId,
|
|
154
|
+
getAgentContextCompactionTriggerTokens,
|
|
155
|
+
getConversationMessageSlackTs,
|
|
156
|
+
getThreadTitleSourceMessage,
|
|
157
|
+
hydrateConversationMessages,
|
|
158
|
+
isHumanConversationMessage,
|
|
159
|
+
markConversationMessage,
|
|
160
|
+
normalizeConversationText,
|
|
161
|
+
persistConversationCompactions,
|
|
162
|
+
persistConversationMessages,
|
|
163
|
+
updateConversationStats,
|
|
164
|
+
upsertConversationMessage
|
|
165
|
+
} from "./chunk-CRRBJ3JP.js";
|
|
163
166
|
import {
|
|
164
167
|
SlackActionError,
|
|
165
168
|
bindSlackDirectCredentialSubject,
|
|
@@ -178,22 +181,29 @@ import {
|
|
|
178
181
|
setPlugins,
|
|
179
182
|
validatePlugins,
|
|
180
183
|
verifySlackDirectCredentialSubject
|
|
181
|
-
} from "./chunk-
|
|
184
|
+
} from "./chunk-NSCHU54X.js";
|
|
182
185
|
import {
|
|
183
186
|
createPluginLogger,
|
|
184
187
|
createPluginState
|
|
185
|
-
} from "./chunk-
|
|
186
|
-
import "./chunk-G3E7SCME.js";
|
|
188
|
+
} from "./chunk-E3E2XNCN.js";
|
|
187
189
|
import {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
} from "./chunk-7STN2ZSK.js";
|
|
190
|
+
sleep
|
|
191
|
+
} from "./chunk-CZEX6KIQ.js";
|
|
191
192
|
import {
|
|
193
|
+
contextProvenance,
|
|
194
|
+
getAgentStepStore,
|
|
192
195
|
getConversationStore,
|
|
193
|
-
getDb
|
|
194
|
-
|
|
196
|
+
getDb,
|
|
197
|
+
getSqlExecutor,
|
|
198
|
+
instructionProvenanceFor,
|
|
199
|
+
juniorAgentSteps,
|
|
200
|
+
juniorConversationMessages,
|
|
201
|
+
juniorConversations,
|
|
202
|
+
juniorDestinations
|
|
203
|
+
} from "./chunk-6ONME5IG.js";
|
|
195
204
|
import {
|
|
196
205
|
FUNCTION_TIMEOUT_BUFFER_SECONDS,
|
|
206
|
+
acquireActiveLock,
|
|
197
207
|
botConfig,
|
|
198
208
|
completeObject,
|
|
199
209
|
completeText,
|
|
@@ -205,35 +215,36 @@ import {
|
|
|
205
215
|
getSlackClientSecret,
|
|
206
216
|
getSlackReactionConfig,
|
|
207
217
|
getSlackSigningSecret,
|
|
218
|
+
getStateAdapter,
|
|
208
219
|
isProviderRetryError,
|
|
209
220
|
normalizeSlackEmojiName,
|
|
210
221
|
setSlackReactionConfig,
|
|
211
222
|
stripRuntimeTurnContext,
|
|
212
223
|
trimTrailingAssistantMessages,
|
|
213
224
|
unwrapCurrentInstruction
|
|
214
|
-
} from "./chunk-
|
|
225
|
+
} from "./chunk-GUE7HTNR.js";
|
|
215
226
|
import {
|
|
216
227
|
parseSlackThreadId,
|
|
217
228
|
readSlackRawMessageContext,
|
|
218
229
|
resolveSlackChannelIdFromMessage,
|
|
219
230
|
resolveSlackChannelIdFromThreadId
|
|
220
|
-
} from "./chunk-
|
|
231
|
+
} from "./chunk-GY34VGP5.js";
|
|
221
232
|
import {
|
|
222
233
|
createSlackDestination,
|
|
223
234
|
destinationKey,
|
|
224
235
|
parseDestination,
|
|
225
236
|
requireSlackDestination,
|
|
226
237
|
sameDestination
|
|
227
|
-
} from "./chunk-
|
|
238
|
+
} from "./chunk-B7PUBQQM.js";
|
|
228
239
|
import {
|
|
229
240
|
discoverSkills
|
|
230
|
-
} from "./chunk-
|
|
241
|
+
} from "./chunk-HDTO3A74.js";
|
|
231
242
|
import {
|
|
232
243
|
buildOAuthTokenRequest,
|
|
233
244
|
hasRequiredOAuthScope,
|
|
234
245
|
parseOAuthTokenResponse,
|
|
235
246
|
pluginCatalogRuntime
|
|
236
|
-
} from "./chunk-
|
|
247
|
+
} from "./chunk-GVOUCI2O.js";
|
|
237
248
|
import {
|
|
238
249
|
buildTurnFailureResponse,
|
|
239
250
|
createActor,
|
|
@@ -253,10 +264,9 @@ import {
|
|
|
253
264
|
setSpanAttributes,
|
|
254
265
|
setSpanStatus,
|
|
255
266
|
setTags,
|
|
256
|
-
toStoredSlackActor,
|
|
257
267
|
withContext,
|
|
258
268
|
withSpan
|
|
259
|
-
} from "./chunk-
|
|
269
|
+
} from "./chunk-WPOJ443W.js";
|
|
260
270
|
import {
|
|
261
271
|
toOptionalString
|
|
262
272
|
} from "./chunk-OB42YVAE.js";
|
|
@@ -270,7 +280,7 @@ import {
|
|
|
270
280
|
JUNIOR_PLUGIN_TASK_CALLBACK_ROUTE,
|
|
271
281
|
parseSlackChannelId,
|
|
272
282
|
parseSlackMessageTs
|
|
273
|
-
} from "./chunk-
|
|
283
|
+
} from "./chunk-7FBGKXPE.js";
|
|
274
284
|
import "./chunk-MLKGABMK.js";
|
|
275
285
|
|
|
276
286
|
// src/app.ts
|
|
@@ -449,27 +459,6 @@ async function postSlackApiReplyPosts(args) {
|
|
|
449
459
|
return lastPostedMessageTs;
|
|
450
460
|
}
|
|
451
461
|
|
|
452
|
-
// src/chat/services/persist-retry.ts
|
|
453
|
-
var PERSIST_ATTEMPTS = 3;
|
|
454
|
-
function sleep(ms) {
|
|
455
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
456
|
-
}
|
|
457
|
-
async function persistWithRetry(persist) {
|
|
458
|
-
let lastError;
|
|
459
|
-
for (let attempt = 1; attempt <= PERSIST_ATTEMPTS; attempt += 1) {
|
|
460
|
-
try {
|
|
461
|
-
await persist();
|
|
462
|
-
return;
|
|
463
|
-
} catch (error) {
|
|
464
|
-
lastError = error;
|
|
465
|
-
if (attempt < PERSIST_ATTEMPTS) {
|
|
466
|
-
await sleep(attempt * 100);
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
throw lastError;
|
|
471
|
-
}
|
|
472
|
-
|
|
473
462
|
// src/chat/agent-dispatch/signing.ts
|
|
474
463
|
import { createHmac, timingSafeEqual } from "crypto";
|
|
475
464
|
var DISPATCH_CALLBACK_PATH = "/api/internal/agent-dispatch";
|
|
@@ -970,6 +959,7 @@ async function runAgentDispatchSlice(callback, deps) {
|
|
|
970
959
|
dispatch = startedDispatch;
|
|
971
960
|
const persisted = await getPersistedThreadState(conversationId);
|
|
972
961
|
const conversation = coerceThreadConversationState(persisted);
|
|
962
|
+
await hydrateConversationMessages({ conversation, conversationId });
|
|
973
963
|
const deliveredMessage = conversation.messages.find(
|
|
974
964
|
(message) => message.id === getAssistantMessageId(dispatch) && message.meta?.replied === true && typeof message.meta.slackTs === "string"
|
|
975
965
|
);
|
|
@@ -993,6 +983,7 @@ async function runAgentDispatchSlice(callback, deps) {
|
|
|
993
983
|
dispatch,
|
|
994
984
|
nowMs
|
|
995
985
|
});
|
|
986
|
+
await persistConversationMessages({ conversation, conversationId });
|
|
996
987
|
const conversationContext = buildConversationContext(conversation, {
|
|
997
988
|
excludeMessageId: userMessageId
|
|
998
989
|
});
|
|
@@ -1000,7 +991,9 @@ async function runAgentDispatchSlice(callback, deps) {
|
|
|
1000
991
|
input: {
|
|
1001
992
|
messageText: dispatch.input,
|
|
1002
993
|
conversationContext,
|
|
1003
|
-
|
|
994
|
+
// Pi history for redelivered dispatch slices comes from the SQL
|
|
995
|
+
// step-store projection, not a thread-state mirror.
|
|
996
|
+
piMessages: await loadProjection({ conversationId })
|
|
1004
997
|
},
|
|
1005
998
|
routing: {
|
|
1006
999
|
credentialContext: {
|
|
@@ -1147,6 +1140,7 @@ async function runAgentDispatchSlice(callback, deps) {
|
|
|
1147
1140
|
messages: reply.piMessages,
|
|
1148
1141
|
durationMs: reply.diagnostics.durationMs,
|
|
1149
1142
|
usage: reply.diagnostics.usage,
|
|
1143
|
+
reasoningLevel: reply.diagnostics.thinkingLevel,
|
|
1150
1144
|
destination: dispatch.destination,
|
|
1151
1145
|
source: dispatch.source,
|
|
1152
1146
|
actor: dispatch.actor,
|
|
@@ -1262,42 +1256,31 @@ function now() {
|
|
|
1262
1256
|
return Date.now();
|
|
1263
1257
|
}
|
|
1264
1258
|
async function recordExecutionMetadata(args) {
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
return;
|
|
1272
|
-
}
|
|
1273
|
-
await metadataStore(args).recordExecution({
|
|
1274
|
-
channelName: conversation.channelName,
|
|
1275
|
-
conversationId: conversation.conversationId,
|
|
1276
|
-
createdAtMs: conversation.createdAtMs,
|
|
1277
|
-
destination: conversation.destination,
|
|
1278
|
-
execution: {
|
|
1279
|
-
lastCheckpointAtMs: conversation.execution.lastCheckpointAtMs,
|
|
1280
|
-
lastEnqueuedAtMs: conversation.execution.lastEnqueuedAtMs,
|
|
1281
|
-
runId: conversation.execution.runId,
|
|
1282
|
-
status: conversation.execution.status,
|
|
1283
|
-
updatedAtMs: conversation.execution.updatedAtMs
|
|
1284
|
-
},
|
|
1285
|
-
lastActivityAtMs: conversation.lastActivityAtMs,
|
|
1286
|
-
actor: conversation.actor,
|
|
1287
|
-
source: conversation.source,
|
|
1288
|
-
title: conversation.title,
|
|
1289
|
-
updatedAtMs: conversation.updatedAtMs
|
|
1290
|
-
});
|
|
1291
|
-
} catch (error) {
|
|
1292
|
-
logWarn(
|
|
1293
|
-
"conversation_execution_metadata_update_failed",
|
|
1294
|
-
{ conversationId: args.conversationId },
|
|
1295
|
-
{
|
|
1296
|
-
"exception.message": error instanceof Error ? error.message : String(error)
|
|
1297
|
-
},
|
|
1298
|
-
"Failed to update conversation execution metadata"
|
|
1299
|
-
);
|
|
1259
|
+
const conversation = await getConversation({
|
|
1260
|
+
conversationId: args.conversationId,
|
|
1261
|
+
state: args.state
|
|
1262
|
+
});
|
|
1263
|
+
if (!conversation) {
|
|
1264
|
+
return;
|
|
1300
1265
|
}
|
|
1266
|
+
await metadataStore(args).recordExecution({
|
|
1267
|
+
channelName: conversation.channelName,
|
|
1268
|
+
conversationId: conversation.conversationId,
|
|
1269
|
+
createdAtMs: conversation.createdAtMs,
|
|
1270
|
+
destination: conversation.destination,
|
|
1271
|
+
execution: {
|
|
1272
|
+
lastCheckpointAtMs: conversation.execution.lastCheckpointAtMs,
|
|
1273
|
+
lastEnqueuedAtMs: conversation.execution.lastEnqueuedAtMs,
|
|
1274
|
+
runId: conversation.execution.runId,
|
|
1275
|
+
status: conversation.execution.status,
|
|
1276
|
+
updatedAtMs: conversation.execution.updatedAtMs
|
|
1277
|
+
},
|
|
1278
|
+
lastActivityAtMs: conversation.lastActivityAtMs,
|
|
1279
|
+
actor: conversation.actor,
|
|
1280
|
+
source: conversation.source,
|
|
1281
|
+
title: conversation.title,
|
|
1282
|
+
updatedAtMs: conversation.updatedAtMs
|
|
1283
|
+
});
|
|
1301
1284
|
}
|
|
1302
1285
|
async function getConversationWorkState2(args) {
|
|
1303
1286
|
return await getConversationWorkState(args);
|
|
@@ -1354,13 +1337,26 @@ async function appendAndEnqueueInboundMessage(args) {
|
|
|
1354
1337
|
conversationId: args.message.conversationId,
|
|
1355
1338
|
state: args.state
|
|
1356
1339
|
});
|
|
1357
|
-
if (!conversation
|
|
1340
|
+
if (!conversation) {
|
|
1341
|
+
return appendResult;
|
|
1342
|
+
}
|
|
1343
|
+
if (hasRecentEnqueueMarker(conversation, nowMs)) {
|
|
1344
|
+
await recordExecutionMetadata({
|
|
1345
|
+
conversationId: args.message.conversationId,
|
|
1346
|
+
conversationStore: args.conversationStore,
|
|
1347
|
+
state: args.state
|
|
1348
|
+
});
|
|
1358
1349
|
return appendResult;
|
|
1359
1350
|
}
|
|
1360
1351
|
const duplicateStillPending = conversation.execution.pendingMessages.some(
|
|
1361
1352
|
(message) => message.inboundMessageId === args.message.inboundMessageId
|
|
1362
1353
|
);
|
|
1363
1354
|
if (!duplicateStillPending) {
|
|
1355
|
+
await recordExecutionMetadata({
|
|
1356
|
+
conversationId: args.message.conversationId,
|
|
1357
|
+
conversationStore: args.conversationStore,
|
|
1358
|
+
state: args.state
|
|
1359
|
+
});
|
|
1364
1360
|
return appendResult;
|
|
1365
1361
|
}
|
|
1366
1362
|
idempotencyKey = duplicateInboundNudgeIdempotencyKey(args.message, nowMs);
|
|
@@ -2184,6 +2180,7 @@ async function ingestResourceEvent(input, options) {
|
|
|
2184
2180
|
});
|
|
2185
2181
|
let enqueued = 0;
|
|
2186
2182
|
const errors = [];
|
|
2183
|
+
const waitDeadlineMs = Date.now() + 1e4;
|
|
2187
2184
|
for (const subscription of subscriptions) {
|
|
2188
2185
|
try {
|
|
2189
2186
|
const delivered = await deliverResourceEventSubscription({
|
|
@@ -2194,6 +2191,7 @@ async function ingestResourceEvent(input, options) {
|
|
|
2194
2191
|
nowMs,
|
|
2195
2192
|
state: options.state,
|
|
2196
2193
|
subscription,
|
|
2194
|
+
waitDeadlineMs,
|
|
2197
2195
|
deliver: async (current) => {
|
|
2198
2196
|
const result = await enqueueResourceEventNotification({
|
|
2199
2197
|
event,
|
|
@@ -3042,8 +3040,210 @@ async function GET2(request, waitUntil, options = {}) {
|
|
|
3042
3040
|
return new Response("Accepted", { status: 202 });
|
|
3043
3041
|
}
|
|
3044
3042
|
|
|
3045
|
-
// src/handlers/
|
|
3046
|
-
import {
|
|
3043
|
+
// src/handlers/retention.ts
|
|
3044
|
+
import { timingSafeEqual as timingSafeEqual4 } from "crypto";
|
|
3045
|
+
|
|
3046
|
+
// src/chat/conversations/sql/purge.ts
|
|
3047
|
+
import { and, asc, eq, inArray, isNull, sql } from "drizzle-orm";
|
|
3048
|
+
async function conversationTreeIds(executor, rootConversationId) {
|
|
3049
|
+
const all = /* @__PURE__ */ new Set([rootConversationId]);
|
|
3050
|
+
let frontier = [rootConversationId];
|
|
3051
|
+
while (frontier.length > 0) {
|
|
3052
|
+
const children = await executor.db().select({ id: juniorConversations.conversationId }).from(juniorConversations).where(inArray(juniorConversations.parentConversationId, frontier));
|
|
3053
|
+
frontier = [];
|
|
3054
|
+
for (const child of children) {
|
|
3055
|
+
if (!all.has(child.id)) {
|
|
3056
|
+
all.add(child.id);
|
|
3057
|
+
frontier.push(child.id);
|
|
3058
|
+
}
|
|
3059
|
+
}
|
|
3060
|
+
}
|
|
3061
|
+
return [...all];
|
|
3062
|
+
}
|
|
3063
|
+
async function selectExpiredRoots(executor, args) {
|
|
3064
|
+
const publicCutoff = new Date(args.nowMs - args.publicWindowMs).toISOString();
|
|
3065
|
+
const privateCutoff = new Date(
|
|
3066
|
+
args.nowMs - args.privateWindowMs
|
|
3067
|
+
).toISOString();
|
|
3068
|
+
const cutoff = sql`case when ${juniorDestinations.visibility} = 'public' then ${publicCutoff}::timestamptz else ${privateCutoff}::timestamptz end`;
|
|
3069
|
+
const hasTreeWork = sql`exists (
|
|
3070
|
+
with recursive conversation_tree(conversation_id) as (
|
|
3071
|
+
select ${juniorConversations.conversationId}
|
|
3072
|
+
union all
|
|
3073
|
+
select child.conversation_id
|
|
3074
|
+
from junior_conversations child
|
|
3075
|
+
join conversation_tree parent on child.parent_conversation_id = parent.conversation_id
|
|
3076
|
+
)
|
|
3077
|
+
select 1
|
|
3078
|
+
from conversation_tree tree
|
|
3079
|
+
where exists (
|
|
3080
|
+
select 1 from junior_agent_steps steps
|
|
3081
|
+
where steps.conversation_id = tree.conversation_id
|
|
3082
|
+
)
|
|
3083
|
+
or exists (
|
|
3084
|
+
select 1 from junior_conversation_messages messages
|
|
3085
|
+
where messages.conversation_id = tree.conversation_id
|
|
3086
|
+
)
|
|
3087
|
+
or (
|
|
3088
|
+
${juniorDestinations.visibility} is distinct from 'public'
|
|
3089
|
+
and exists (
|
|
3090
|
+
select 1 from junior_conversations metadata
|
|
3091
|
+
where metadata.conversation_id = tree.conversation_id
|
|
3092
|
+
and (
|
|
3093
|
+
metadata.title is not null
|
|
3094
|
+
or metadata.channel_name is not null
|
|
3095
|
+
or metadata.actor_json is not null
|
|
3096
|
+
)
|
|
3097
|
+
)
|
|
3098
|
+
)
|
|
3099
|
+
)`;
|
|
3100
|
+
const rows = await executor.db().select({
|
|
3101
|
+
conversationId: juniorConversations.conversationId,
|
|
3102
|
+
visibility: juniorDestinations.visibility
|
|
3103
|
+
}).from(juniorConversations).leftJoin(
|
|
3104
|
+
juniorDestinations,
|
|
3105
|
+
eq(juniorDestinations.id, juniorConversations.destinationId)
|
|
3106
|
+
).where(
|
|
3107
|
+
and(
|
|
3108
|
+
isNull(juniorConversations.parentConversationId),
|
|
3109
|
+
sql`${juniorConversations.lastActivityAt} < ${cutoff}`,
|
|
3110
|
+
hasTreeWork
|
|
3111
|
+
)
|
|
3112
|
+
).orderBy(
|
|
3113
|
+
asc(juniorConversations.lastActivityAt),
|
|
3114
|
+
asc(juniorConversations.conversationId)
|
|
3115
|
+
).limit(Math.max(0, args.limit));
|
|
3116
|
+
return rows.map((row) => ({
|
|
3117
|
+
conversationId: row.conversationId,
|
|
3118
|
+
visibility: row.visibility
|
|
3119
|
+
}));
|
|
3120
|
+
}
|
|
3121
|
+
async function purgeConversationTree(executor, args) {
|
|
3122
|
+
return await executor.transaction(async () => {
|
|
3123
|
+
const roots = await executor.db().select({
|
|
3124
|
+
destinationId: juniorConversations.destinationId,
|
|
3125
|
+
lastActivityAt: juniorConversations.lastActivityAt,
|
|
3126
|
+
parentConversationId: juniorConversations.parentConversationId
|
|
3127
|
+
}).from(juniorConversations).where(eq(juniorConversations.conversationId, args.rootConversationId)).for("update");
|
|
3128
|
+
const root = roots[0];
|
|
3129
|
+
if (!root || args.retention && root.parentConversationId !== null) {
|
|
3130
|
+
return { purged: false, conversations: 0 };
|
|
3131
|
+
}
|
|
3132
|
+
const destinations = root.destinationId ? await executor.db().select({ visibility: juniorDestinations.visibility }).from(juniorDestinations).where(eq(juniorDestinations.id, root.destinationId)) : [];
|
|
3133
|
+
const isPublic = destinations[0]?.visibility === "public";
|
|
3134
|
+
if (args.retention) {
|
|
3135
|
+
const windowMs = isPublic ? args.retention.publicWindowMs : args.retention.privateWindowMs;
|
|
3136
|
+
if (root.lastActivityAt.getTime() >= args.nowMs - windowMs) {
|
|
3137
|
+
return { purged: false, conversations: 0 };
|
|
3138
|
+
}
|
|
3139
|
+
}
|
|
3140
|
+
const ids = await conversationTreeIds(executor, args.rootConversationId);
|
|
3141
|
+
await executor.db().delete(juniorAgentSteps).where(inArray(juniorAgentSteps.conversationId, ids));
|
|
3142
|
+
await executor.db().delete(juniorConversationMessages).where(inArray(juniorConversationMessages.conversationId, ids));
|
|
3143
|
+
await executor.db().update(juniorConversations).set({
|
|
3144
|
+
transcriptPurgedAt: new Date(args.nowMs),
|
|
3145
|
+
...(args.retention ? !isPublic : args.scrubMetadata) ? { title: null, channelName: null, actor: null } : {}
|
|
3146
|
+
}).where(inArray(juniorConversations.conversationId, ids));
|
|
3147
|
+
return { purged: true, conversations: ids.length };
|
|
3148
|
+
});
|
|
3149
|
+
}
|
|
3150
|
+
|
|
3151
|
+
// src/chat/conversations/retention.ts
|
|
3152
|
+
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
3153
|
+
var CONTENT_RETENTION_MS = {
|
|
3154
|
+
public: 90 * DAY_MS,
|
|
3155
|
+
private: 14 * DAY_MS
|
|
3156
|
+
};
|
|
3157
|
+
var RETENTION_BATCH_LIMIT = 200;
|
|
3158
|
+
async function runRetentionPurge(executor, args) {
|
|
3159
|
+
const limit = args.limit ?? RETENTION_BATCH_LIMIT;
|
|
3160
|
+
const startedAtMs = Date.now();
|
|
3161
|
+
const roots = await selectExpiredRoots(executor, {
|
|
3162
|
+
nowMs: args.nowMs,
|
|
3163
|
+
publicWindowMs: CONTENT_RETENTION_MS.public,
|
|
3164
|
+
privateWindowMs: CONTENT_RETENTION_MS.private,
|
|
3165
|
+
limit
|
|
3166
|
+
});
|
|
3167
|
+
let purged = 0;
|
|
3168
|
+
let failed = 0;
|
|
3169
|
+
let conversations = 0;
|
|
3170
|
+
for (const root of roots) {
|
|
3171
|
+
try {
|
|
3172
|
+
const result = await purgeConversationTree(executor, {
|
|
3173
|
+
rootConversationId: root.conversationId,
|
|
3174
|
+
nowMs: args.nowMs,
|
|
3175
|
+
retention: {
|
|
3176
|
+
publicWindowMs: CONTENT_RETENTION_MS.public,
|
|
3177
|
+
privateWindowMs: CONTENT_RETENTION_MS.private
|
|
3178
|
+
}
|
|
3179
|
+
});
|
|
3180
|
+
if (result.purged) {
|
|
3181
|
+
purged += 1;
|
|
3182
|
+
conversations += result.conversations;
|
|
3183
|
+
}
|
|
3184
|
+
} catch (error) {
|
|
3185
|
+
failed += 1;
|
|
3186
|
+
logException(
|
|
3187
|
+
error,
|
|
3188
|
+
"retention_purge_tree_failed",
|
|
3189
|
+
{ conversationId: root.conversationId },
|
|
3190
|
+
{},
|
|
3191
|
+
"Retention purge failed for one conversation tree"
|
|
3192
|
+
);
|
|
3193
|
+
}
|
|
3194
|
+
}
|
|
3195
|
+
logInfo(
|
|
3196
|
+
"retention_purge_completed",
|
|
3197
|
+
{},
|
|
3198
|
+
{
|
|
3199
|
+
"app.retention.scanned": roots.length,
|
|
3200
|
+
"app.retention.purged": purged,
|
|
3201
|
+
"app.retention.failed": failed,
|
|
3202
|
+
"app.retention.conversations": conversations,
|
|
3203
|
+
"app.retention.duration_ms": Date.now() - startedAtMs
|
|
3204
|
+
},
|
|
3205
|
+
"Retention purge batch completed"
|
|
3206
|
+
);
|
|
3207
|
+
return { scanned: roots.length, purged, failed, conversations };
|
|
3208
|
+
}
|
|
3209
|
+
|
|
3210
|
+
// src/handlers/retention.ts
|
|
3211
|
+
function getRetentionSecret() {
|
|
3212
|
+
return process.env.JUNIOR_SCHEDULER_SECRET?.trim() || process.env.CRON_SECRET?.trim();
|
|
3213
|
+
}
|
|
3214
|
+
function verifyRetentionRequest(request) {
|
|
3215
|
+
const secret = getRetentionSecret();
|
|
3216
|
+
if (!secret) {
|
|
3217
|
+
return false;
|
|
3218
|
+
}
|
|
3219
|
+
const authorization = request.headers.get("authorization")?.trim();
|
|
3220
|
+
if (!authorization?.startsWith("Bearer ")) {
|
|
3221
|
+
return false;
|
|
3222
|
+
}
|
|
3223
|
+
const actual = Buffer.from(authorization.slice("Bearer ".length));
|
|
3224
|
+
const expected = Buffer.from(secret);
|
|
3225
|
+
return actual.length === expected.length && timingSafeEqual4(actual, expected);
|
|
3226
|
+
}
|
|
3227
|
+
async function GET3(request) {
|
|
3228
|
+
if (!verifyRetentionRequest(request)) {
|
|
3229
|
+
return new Response("Unauthorized", { status: 401 });
|
|
3230
|
+
}
|
|
3231
|
+
try {
|
|
3232
|
+
const result = await runRetentionPurge(getSqlExecutor(), {
|
|
3233
|
+
nowMs: Date.now()
|
|
3234
|
+
});
|
|
3235
|
+
return Response.json(result, { status: 200 });
|
|
3236
|
+
} catch (error) {
|
|
3237
|
+
logException(
|
|
3238
|
+
error,
|
|
3239
|
+
"retention_run_failed",
|
|
3240
|
+
{},
|
|
3241
|
+
{},
|
|
3242
|
+
"Retention purge run failed"
|
|
3243
|
+
);
|
|
3244
|
+
return new Response("Retention purge failed", { status: 500 });
|
|
3245
|
+
}
|
|
3246
|
+
}
|
|
3047
3247
|
|
|
3048
3248
|
// src/chat/runtime/turn-user-message.ts
|
|
3049
3249
|
function getTurnUserMessage(conversation, sessionId) {
|
|
@@ -3916,24 +4116,28 @@ async function resumeSlackTurn(args) {
|
|
|
3916
4116
|
}
|
|
3917
4117
|
const activeReplyContext = runArgs.replyContext;
|
|
3918
4118
|
if (!activeReplyContext) {
|
|
3919
|
-
throw new Error(
|
|
3920
|
-
"Resumed turn requires replyContext.routing.actor.userId"
|
|
3921
|
-
);
|
|
3922
|
-
}
|
|
3923
|
-
const resumeActor = activeReplyContext.routing.actor;
|
|
3924
|
-
if (!isUserActor(resumeActor)) {
|
|
3925
|
-
throw new Error(
|
|
3926
|
-
"Resumed turn requires replyContext.routing.actor.userId"
|
|
3927
|
-
);
|
|
4119
|
+
throw new Error("Resumed turn requires replyContext");
|
|
3928
4120
|
}
|
|
3929
4121
|
const credentialContext = activeReplyContext.routing.credentialContext;
|
|
3930
4122
|
if (!credentialContext) {
|
|
3931
4123
|
throw new Error("Resumed turn requires replyContext.credentialContext");
|
|
3932
4124
|
}
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
)
|
|
4125
|
+
const routingActor = activeReplyContext.routing.actor;
|
|
4126
|
+
let resumeActor;
|
|
4127
|
+
if ("type" in credentialContext.actor) {
|
|
4128
|
+
if (!isUserActor(routingActor) || credentialContext.actor.userId !== routingActor.userId) {
|
|
4129
|
+
throw new Error(
|
|
4130
|
+
"Resumed turn credential actor must match replyContext.routing.actor.userId"
|
|
4131
|
+
);
|
|
4132
|
+
}
|
|
4133
|
+
resumeActor = routingActor;
|
|
4134
|
+
} else {
|
|
4135
|
+
if (routingActor && (routingActor.platform !== "system" || routingActor.name !== credentialContext.actor.name)) {
|
|
4136
|
+
throw new Error(
|
|
4137
|
+
"Resumed turn system credential actor must match replyContext.routing.actor"
|
|
4138
|
+
);
|
|
4139
|
+
}
|
|
4140
|
+
resumeActor = credentialContext.actor;
|
|
3937
4141
|
}
|
|
3938
4142
|
if (runArgs.messageTs) {
|
|
3939
4143
|
processingReaction = await startSlackProcessingReactionForMessage({
|
|
@@ -3975,7 +4179,7 @@ async function resumeSlackTurn(args) {
|
|
|
3975
4179
|
deferredPauseKind = "auth";
|
|
3976
4180
|
deferredAuthInfo = {
|
|
3977
4181
|
providerDisplayName: outcome.providerDisplayName,
|
|
3978
|
-
actorId: resumeActor.userId
|
|
4182
|
+
actorId: isUserActor(resumeActor) ? resumeActor.userId : void 0
|
|
3979
4183
|
};
|
|
3980
4184
|
deferredPauseHandler = async () => {
|
|
3981
4185
|
await onAuthPause({
|
|
@@ -4027,7 +4231,7 @@ async function resumeSlackTurn(args) {
|
|
|
4027
4231
|
currentUsage: reply.diagnostics.usage,
|
|
4028
4232
|
destination: replyContext.routing.destination,
|
|
4029
4233
|
source: replyContext.routing.source,
|
|
4030
|
-
actor:
|
|
4234
|
+
actor: resumeActor,
|
|
4031
4235
|
surface: "slack",
|
|
4032
4236
|
logContext: {
|
|
4033
4237
|
threadId: replyContext.routing.correlation.threadId,
|
|
@@ -4180,6 +4384,10 @@ function completeAuthPauseTurn(args) {
|
|
|
4180
4384
|
async function persistAuthPauseTurnState(args) {
|
|
4181
4385
|
const currentState = await getPersistedThreadState(args.threadStateId);
|
|
4182
4386
|
const conversation = coerceThreadConversationState(currentState);
|
|
4387
|
+
await hydrateConversationMessages({
|
|
4388
|
+
conversation,
|
|
4389
|
+
conversationId: args.threadStateId
|
|
4390
|
+
});
|
|
4183
4391
|
completeAuthPauseTurn({
|
|
4184
4392
|
conversation,
|
|
4185
4393
|
sessionId: args.sessionId
|
|
@@ -4288,6 +4496,7 @@ async function persistCompletedReplyState(channelId, threadTs, sessionId, reply)
|
|
|
4288
4496
|
const threadId = `slack:${channelId}:${threadTs}`;
|
|
4289
4497
|
const currentState = await getPersistedThreadState(threadId);
|
|
4290
4498
|
const conversation = coerceThreadConversationState(currentState);
|
|
4499
|
+
await hydrateConversationMessages({ conversation, conversationId: threadId });
|
|
4291
4500
|
const artifacts = coerceThreadArtifactsState(currentState);
|
|
4292
4501
|
const userMessage2 = getTurnUserMessage(conversation, sessionId);
|
|
4293
4502
|
const statePatch = buildDeliveredTurnStatePatch({
|
|
@@ -4326,6 +4535,7 @@ async function persistFailedReplyState(channelId, threadTs, sessionId, expectedV
|
|
|
4326
4535
|
const threadId = `slack:${channelId}:${threadTs}`;
|
|
4327
4536
|
const currentState = await getPersistedThreadState(threadId);
|
|
4328
4537
|
const conversation = coerceThreadConversationState(currentState);
|
|
4538
|
+
await hydrateConversationMessages({ conversation, conversationId: threadId });
|
|
4329
4539
|
clearPendingAuth(conversation, sessionId);
|
|
4330
4540
|
markTurnFailed({
|
|
4331
4541
|
conversation,
|
|
@@ -4357,6 +4567,7 @@ async function resumeAuthorizedMcpTurn(args) {
|
|
|
4357
4567
|
const threadId = `slack:${authSession.channelId}:${authSession.threadTs}`;
|
|
4358
4568
|
const currentState = await getPersistedThreadState(threadId);
|
|
4359
4569
|
const conversation = coerceThreadConversationState(currentState);
|
|
4570
|
+
await hydrateConversationMessages({ conversation, conversationId: threadId });
|
|
4360
4571
|
const pendingAuth = getConversationPendingAuth({
|
|
4361
4572
|
conversation,
|
|
4362
4573
|
kind: "mcp",
|
|
@@ -4393,6 +4604,10 @@ async function resumeAuthorizedMcpTurn(args) {
|
|
|
4393
4604
|
beforeStart: async () => {
|
|
4394
4605
|
const lockedState = await getPersistedThreadState(threadId);
|
|
4395
4606
|
const lockedConversation = coerceThreadConversationState(lockedState);
|
|
4607
|
+
await hydrateConversationMessages({
|
|
4608
|
+
conversation: lockedConversation,
|
|
4609
|
+
conversationId: threadId
|
|
4610
|
+
});
|
|
4396
4611
|
const lockedArtifacts = coerceThreadArtifactsState(lockedState);
|
|
4397
4612
|
const lockedPendingAuth = getConversationPendingAuth({
|
|
4398
4613
|
conversation: lockedConversation,
|
|
@@ -4476,8 +4691,7 @@ async function resumeAuthorizedMcpTurn(args) {
|
|
|
4476
4691
|
authorizationId: mcpAuthorizationId({
|
|
4477
4692
|
provider,
|
|
4478
4693
|
sessionId: lockedSessionId
|
|
4479
|
-
})
|
|
4480
|
-
ttlMs: THREAD_STATE_TTL_MS
|
|
4694
|
+
})
|
|
4481
4695
|
});
|
|
4482
4696
|
const lockedMessageTs = getTurnUserSlackMessageTs(lockedUserMessage);
|
|
4483
4697
|
return {
|
|
@@ -4486,7 +4700,9 @@ async function resumeAuthorizedMcpTurn(args) {
|
|
|
4486
4700
|
replyContext: {
|
|
4487
4701
|
input: {
|
|
4488
4702
|
conversationContext: lockedConversationContext,
|
|
4489
|
-
|
|
4703
|
+
// Pi history is SQL-authoritative: the resumed run reads its
|
|
4704
|
+
// session record first and falls back to the step projection.
|
|
4705
|
+
piMessages: await loadProjection({ conversationId: threadId }),
|
|
4490
4706
|
...getTurnUserReplyAttachmentContext(lockedUserMessage)
|
|
4491
4707
|
},
|
|
4492
4708
|
routing: {
|
|
@@ -4585,7 +4801,7 @@ async function resumeAuthorizedMcpTurn(args) {
|
|
|
4585
4801
|
}
|
|
4586
4802
|
});
|
|
4587
4803
|
}
|
|
4588
|
-
async function
|
|
4804
|
+
async function GET4(request, provider, waitUntil, options) {
|
|
4589
4805
|
const url = new URL(request.url);
|
|
4590
4806
|
const state = url.searchParams.get("state")?.trim();
|
|
4591
4807
|
const code = url.searchParams.get("code")?.trim();
|
|
@@ -4632,9 +4848,6 @@ async function GET3(request, provider, waitUntil, options) {
|
|
|
4632
4848
|
}
|
|
4633
4849
|
}
|
|
4634
4850
|
|
|
4635
|
-
// src/handlers/oauth-callback.ts
|
|
4636
|
-
import { THREAD_STATE_TTL_MS as THREAD_STATE_TTL_MS2 } from "chat";
|
|
4637
|
-
|
|
4638
4851
|
// src/chat/slack/app-home.ts
|
|
4639
4852
|
import fs from "fs";
|
|
4640
4853
|
import path from "path";
|
|
@@ -4797,6 +5010,10 @@ function htmlErrorResponse(title, message, status) {
|
|
|
4797
5010
|
async function persistCompletedOAuthReplyState(args) {
|
|
4798
5011
|
const currentState = await getPersistedThreadState(args.conversationId);
|
|
4799
5012
|
const conversation = coerceThreadConversationState(currentState);
|
|
5013
|
+
await hydrateConversationMessages({
|
|
5014
|
+
conversation,
|
|
5015
|
+
conversationId: args.conversationId
|
|
5016
|
+
});
|
|
4800
5017
|
const artifacts = coerceThreadArtifactsState(currentState);
|
|
4801
5018
|
const userMessage2 = getTurnUserMessage(conversation, args.sessionId);
|
|
4802
5019
|
const statePatch = buildDeliveredTurnStatePatch({
|
|
@@ -4837,6 +5054,10 @@ async function failSessionRecordBestEffort2(args) {
|
|
|
4837
5054
|
async function persistFailedOAuthReplyState(args) {
|
|
4838
5055
|
const currentState = await getPersistedThreadState(args.conversationId);
|
|
4839
5056
|
const conversation = coerceThreadConversationState(currentState);
|
|
5057
|
+
await hydrateConversationMessages({
|
|
5058
|
+
conversation,
|
|
5059
|
+
conversationId: args.conversationId
|
|
5060
|
+
});
|
|
4840
5061
|
clearPendingAuth(conversation, args.sessionId);
|
|
4841
5062
|
markTurnFailed({
|
|
4842
5063
|
conversation,
|
|
@@ -4868,6 +5089,10 @@ async function resumeOAuthSessionRecordTurn(stored, options) {
|
|
|
4868
5089
|
stored.resumeConversationId
|
|
4869
5090
|
);
|
|
4870
5091
|
const conversation = coerceThreadConversationState(currentState);
|
|
5092
|
+
await hydrateConversationMessages({
|
|
5093
|
+
conversation,
|
|
5094
|
+
conversationId: stored.resumeConversationId
|
|
5095
|
+
});
|
|
4871
5096
|
const pendingAuth = getConversationPendingAuth({
|
|
4872
5097
|
conversation,
|
|
4873
5098
|
kind: "plugin",
|
|
@@ -4923,6 +5148,10 @@ async function resumeOAuthSessionRecordTurn(stored, options) {
|
|
|
4923
5148
|
stored.resumeConversationId
|
|
4924
5149
|
);
|
|
4925
5150
|
const lockedConversation = coerceThreadConversationState(lockedState);
|
|
5151
|
+
await hydrateConversationMessages({
|
|
5152
|
+
conversation: lockedConversation,
|
|
5153
|
+
conversationId: stored.resumeConversationId
|
|
5154
|
+
});
|
|
4926
5155
|
const lockedArtifacts = coerceThreadArtifactsState(lockedState);
|
|
4927
5156
|
const lockedPendingAuth = getConversationPendingAuth({
|
|
4928
5157
|
conversation: lockedConversation,
|
|
@@ -5007,8 +5236,7 @@ async function resumeOAuthSessionRecordTurn(stored, options) {
|
|
|
5007
5236
|
authorizationId: pluginAuthorizationId({
|
|
5008
5237
|
provider: stored.provider,
|
|
5009
5238
|
sessionId: lockedSessionId
|
|
5010
|
-
})
|
|
5011
|
-
ttlMs: THREAD_STATE_TTL_MS2
|
|
5239
|
+
})
|
|
5012
5240
|
});
|
|
5013
5241
|
const lockedMessageTs = getTurnUserSlackMessageTs(lockedUserMessage);
|
|
5014
5242
|
return {
|
|
@@ -5017,7 +5245,11 @@ async function resumeOAuthSessionRecordTurn(stored, options) {
|
|
|
5017
5245
|
replyContext: {
|
|
5018
5246
|
input: {
|
|
5019
5247
|
conversationContext: lockedConversationContext,
|
|
5020
|
-
|
|
5248
|
+
// Pi history is SQL-authoritative: the resumed run reads its
|
|
5249
|
+
// session record first and falls back to the step projection.
|
|
5250
|
+
piMessages: await loadProjection({
|
|
5251
|
+
conversationId: stored.resumeConversationId
|
|
5252
|
+
}),
|
|
5021
5253
|
...getTurnUserReplyAttachmentContext(lockedUserMessage)
|
|
5022
5254
|
},
|
|
5023
5255
|
routing: {
|
|
@@ -5120,6 +5352,7 @@ async function resumePendingOAuthMessage(stored, options) {
|
|
|
5120
5352
|
const conversation = coerceThreadConversationState(
|
|
5121
5353
|
await getPersistedThreadState(threadId)
|
|
5122
5354
|
);
|
|
5355
|
+
await hydrateConversationMessages({ conversation, conversationId: threadId });
|
|
5123
5356
|
const latestUserMessage = [...conversation.messages].reverse().find((message) => message.role === "user");
|
|
5124
5357
|
const conversationContext = buildConversationContext(conversation, {
|
|
5125
5358
|
excludeMessageId: latestUserMessage?.id
|
|
@@ -5140,7 +5373,8 @@ async function resumePendingOAuthMessage(stored, options) {
|
|
|
5140
5373
|
replyContext: {
|
|
5141
5374
|
input: {
|
|
5142
5375
|
conversationContext,
|
|
5143
|
-
|
|
5376
|
+
// Pi history is SQL-authoritative via the step-store projection.
|
|
5377
|
+
piMessages: await loadProjection({ conversationId: threadId })
|
|
5144
5378
|
},
|
|
5145
5379
|
routing: {
|
|
5146
5380
|
credentialContext: {
|
|
@@ -5174,7 +5408,7 @@ async function resumePendingOAuthMessage(stored, options) {
|
|
|
5174
5408
|
}
|
|
5175
5409
|
});
|
|
5176
5410
|
}
|
|
5177
|
-
async function
|
|
5411
|
+
async function GET5(request, provider, waitUntil, options) {
|
|
5178
5412
|
const providerConfig = pluginCatalogRuntime.getOAuthConfig(provider);
|
|
5179
5413
|
if (!providerConfig) {
|
|
5180
5414
|
return htmlErrorResponse(
|
|
@@ -8301,7 +8535,6 @@ function createSlackTurnRuntime(deps) {
|
|
|
8301
8535
|
}
|
|
8302
8536
|
|
|
8303
8537
|
// src/chat/services/context-compaction.ts
|
|
8304
|
-
import { THREAD_STATE_TTL_MS as THREAD_STATE_TTL_MS3 } from "chat";
|
|
8305
8538
|
import {
|
|
8306
8539
|
estimateContextTokens,
|
|
8307
8540
|
estimateTokens
|
|
@@ -8359,6 +8592,10 @@ function userMessage(text) {
|
|
|
8359
8592
|
timestamp: Date.now()
|
|
8360
8593
|
};
|
|
8361
8594
|
}
|
|
8595
|
+
function piMessageTimestamp(message) {
|
|
8596
|
+
const timestamp = message.timestamp;
|
|
8597
|
+
return typeof timestamp === "number" ? timestamp : Date.now();
|
|
8598
|
+
}
|
|
8362
8599
|
function selectRetainedUserMessageEntries(messages, maxTokens = RETAINED_USER_MESSAGE_TOKENS) {
|
|
8363
8600
|
const selected = [];
|
|
8364
8601
|
let remaining = maxTokens;
|
|
@@ -8541,6 +8778,7 @@ async function maybeCompactWithDeps(args, deps) {
|
|
|
8541
8778
|
});
|
|
8542
8779
|
}
|
|
8543
8780
|
async function writeCompactedThreadContext(args, sourceMessages, summary, context) {
|
|
8781
|
+
const stepStore = getAgentStepStore();
|
|
8544
8782
|
const sourceProjection = await loadProjectionWithProvenance({
|
|
8545
8783
|
conversationId: args.conversationId
|
|
8546
8784
|
});
|
|
@@ -8552,14 +8790,17 @@ async function writeCompactedThreadContext(args, sourceMessages, summary, contex
|
|
|
8552
8790
|
userMessage(`${COMPACTION_SUMMARY_PREFIX}
|
|
8553
8791
|
${summary}`)
|
|
8554
8792
|
];
|
|
8555
|
-
|
|
8556
|
-
|
|
8557
|
-
|
|
8558
|
-
|
|
8559
|
-
|
|
8560
|
-
|
|
8561
|
-
|
|
8562
|
-
|
|
8793
|
+
const replacementProvenance = buildReplacementProvenance({
|
|
8794
|
+
retained,
|
|
8795
|
+
sourceProvenance: sourceProjection.provenance
|
|
8796
|
+
});
|
|
8797
|
+
await stepStore.startEpoch(args.conversationId, {
|
|
8798
|
+
reason: "compaction",
|
|
8799
|
+
messages: replacement.map((message, index) => ({
|
|
8800
|
+
message,
|
|
8801
|
+
createdAtMs: piMessageTimestamp(message),
|
|
8802
|
+
provenance: replacementProvenance[index]
|
|
8803
|
+
}))
|
|
8563
8804
|
});
|
|
8564
8805
|
updateConversationStats(args.conversation);
|
|
8565
8806
|
setSpanAttributes({
|
|
@@ -9179,7 +9420,6 @@ function createJuniorRuntimeServices(overrides = {}) {
|
|
|
9179
9420
|
}
|
|
9180
9421
|
|
|
9181
9422
|
// src/chat/runtime/reply-executor.ts
|
|
9182
|
-
import { THREAD_STATE_TTL_MS as THREAD_STATE_TTL_MS4 } from "chat";
|
|
9183
9423
|
import { createSlackSource } from "@sentry/junior-plugin-api";
|
|
9184
9424
|
|
|
9185
9425
|
// src/chat/slack/message.ts
|
|
@@ -9307,8 +9547,8 @@ async function maybeApplyProviderDefaultConfigRequest(args) {
|
|
|
9307
9547
|
}
|
|
9308
9548
|
|
|
9309
9549
|
// src/chat/runtime/reply-executor.ts
|
|
9310
|
-
async function
|
|
9311
|
-
await persistWithRetry(() =>
|
|
9550
|
+
async function persistThreadRuntimeStateWithRetry(thread, patch) {
|
|
9551
|
+
await persistWithRetry(() => persistThreadRuntimeState(thread, patch));
|
|
9312
9552
|
}
|
|
9313
9553
|
function collectCanvasUrls(artifacts) {
|
|
9314
9554
|
return new Set(
|
|
@@ -9318,9 +9558,6 @@ function collectCanvasUrls(artifacts) {
|
|
|
9318
9558
|
].filter((url) => typeof url === "string" && url !== "")
|
|
9319
9559
|
);
|
|
9320
9560
|
}
|
|
9321
|
-
function turnActor(actor) {
|
|
9322
|
-
return toStoredSlackActor(actor);
|
|
9323
|
-
}
|
|
9324
9561
|
function parkedInputKey(message) {
|
|
9325
9562
|
if (message.role !== "user") {
|
|
9326
9563
|
return void 0;
|
|
@@ -9433,9 +9670,8 @@ function collectTurnAttachments(message, queuedMessages) {
|
|
|
9433
9670
|
];
|
|
9434
9671
|
}
|
|
9435
9672
|
async function loadPiMessagesForTurn(args) {
|
|
9436
|
-
const fallback = args.fallback.length > 0 ? [...args.fallback] : void 0;
|
|
9437
9673
|
if (!args.conversationId) {
|
|
9438
|
-
return {
|
|
9674
|
+
return {};
|
|
9439
9675
|
}
|
|
9440
9676
|
if (args.activeTurnId) {
|
|
9441
9677
|
const sessionRecord = await getAgentTurnSessionRecord(
|
|
@@ -9459,7 +9695,7 @@ async function loadPiMessagesForTurn(args) {
|
|
|
9459
9695
|
piMessages: projection
|
|
9460
9696
|
};
|
|
9461
9697
|
}
|
|
9462
|
-
return {
|
|
9698
|
+
return {};
|
|
9463
9699
|
}
|
|
9464
9700
|
function createReplyToThread(deps) {
|
|
9465
9701
|
return async function replyToThread(thread, message, options) {
|
|
@@ -9536,7 +9772,6 @@ function createReplyToThread(deps) {
|
|
|
9536
9772
|
deps.services.lookupSlackUser
|
|
9537
9773
|
) : void 0;
|
|
9538
9774
|
const executionActor = "type" in credentialContext.actor ? actor : credentialContext.actor;
|
|
9539
|
-
const storedActor = actor ? turnActor(actor) : void 0;
|
|
9540
9775
|
const slackActorId = actor?.userId;
|
|
9541
9776
|
const preparedState = options.preparedState ?? await deps.prepareTurnState({
|
|
9542
9777
|
thread,
|
|
@@ -9672,8 +9907,7 @@ function createReplyToThread(deps) {
|
|
|
9672
9907
|
provenance: [
|
|
9673
9908
|
...projection.provenance,
|
|
9674
9909
|
...missing.map((pair) => pair.provenance)
|
|
9675
|
-
]
|
|
9676
|
-
ttlMs: THREAD_STATE_TTL_MS4
|
|
9910
|
+
]
|
|
9677
9911
|
});
|
|
9678
9912
|
return true;
|
|
9679
9913
|
} finally {
|
|
@@ -9836,7 +10070,7 @@ function createReplyToThread(deps) {
|
|
|
9836
10070
|
startedAtMs: turnStartedAtMs,
|
|
9837
10071
|
state: "running",
|
|
9838
10072
|
surface: "slack",
|
|
9839
|
-
actor,
|
|
10073
|
+
actor: executionActor,
|
|
9840
10074
|
destination,
|
|
9841
10075
|
destinationVisibility,
|
|
9842
10076
|
source,
|
|
@@ -9850,37 +10084,6 @@ function createReplyToThread(deps) {
|
|
|
9850
10084
|
"Failed to record running turn summary"
|
|
9851
10085
|
);
|
|
9852
10086
|
});
|
|
9853
|
-
void initConversationContext(conversationId, {
|
|
9854
|
-
channelName,
|
|
9855
|
-
originSurface: "slack",
|
|
9856
|
-
originActor: storedActor,
|
|
9857
|
-
startedAtMs: turnStartedAtMs
|
|
9858
|
-
}).catch((error) => {
|
|
9859
|
-
logException(
|
|
9860
|
-
error,
|
|
9861
|
-
"conversation_details_context_init_failed",
|
|
9862
|
-
turnTraceContext,
|
|
9863
|
-
{ "app.agent.turn.state": "running" },
|
|
9864
|
-
"Failed to init conversation context at turn start"
|
|
9865
|
-
);
|
|
9866
|
-
});
|
|
9867
|
-
const existingAssistantTitle = preparedState.artifacts.assistantTitle?.trim();
|
|
9868
|
-
if (existingAssistantTitle) {
|
|
9869
|
-
void setConversationTitle(conversationId, {
|
|
9870
|
-
displayTitle: existingAssistantTitle,
|
|
9871
|
-
...preparedState.artifacts.assistantTitleSourceMessageId ? {
|
|
9872
|
-
titleSourceMessageId: preparedState.artifacts.assistantTitleSourceMessageId
|
|
9873
|
-
} : {}
|
|
9874
|
-
}).catch((error) => {
|
|
9875
|
-
logException(
|
|
9876
|
-
error,
|
|
9877
|
-
"conversation_details_title_refresh_failed",
|
|
9878
|
-
turnTraceContext,
|
|
9879
|
-
{ "app.agent.turn.state": "running" },
|
|
9880
|
-
"Failed to refresh conversation title from artifacts"
|
|
9881
|
-
);
|
|
9882
|
-
});
|
|
9883
|
-
}
|
|
9884
10087
|
}
|
|
9885
10088
|
setTags({
|
|
9886
10089
|
conversationId
|
|
@@ -9963,8 +10166,7 @@ function createReplyToThread(deps) {
|
|
|
9963
10166
|
try {
|
|
9964
10167
|
const loadedPiMessages = await loadPiMessagesForTurn({
|
|
9965
10168
|
conversationId,
|
|
9966
|
-
activeTurnId
|
|
9967
|
-
fallback: preparedState.conversation.piMessages
|
|
10169
|
+
activeTurnId
|
|
9968
10170
|
});
|
|
9969
10171
|
let piMessages = loadedPiMessages.piMessages;
|
|
9970
10172
|
if (conversationId && loadedPiMessages.canCompact && piMessages?.length) {
|
|
@@ -10039,17 +10241,19 @@ function createReplyToThread(deps) {
|
|
|
10039
10241
|
};
|
|
10040
10242
|
if (conversationId && titleUpdateResult.title) {
|
|
10041
10243
|
try {
|
|
10042
|
-
await
|
|
10043
|
-
|
|
10044
|
-
|
|
10244
|
+
await getConversationStore().recordActivity({
|
|
10245
|
+
activityAtMs: message.metadata.dateSent.getTime(),
|
|
10246
|
+
conversationId,
|
|
10247
|
+
nowMs: Date.now(),
|
|
10248
|
+
title: titleUpdateResult.title
|
|
10045
10249
|
});
|
|
10046
10250
|
} catch (error) {
|
|
10047
10251
|
logException(
|
|
10048
10252
|
error,
|
|
10049
|
-
"
|
|
10253
|
+
"conversation_title_persist_failed",
|
|
10050
10254
|
turnTraceContext,
|
|
10051
10255
|
{},
|
|
10052
|
-
"Failed to
|
|
10256
|
+
"Failed to persist generated conversation title"
|
|
10053
10257
|
);
|
|
10054
10258
|
}
|
|
10055
10259
|
}
|
|
@@ -10365,6 +10569,7 @@ function createReplyToThread(deps) {
|
|
|
10365
10569
|
conversationId,
|
|
10366
10570
|
durationMs: reply.diagnostics.durationMs,
|
|
10367
10571
|
usage: reply.diagnostics.usage,
|
|
10572
|
+
reasoningLevel: reply.diagnostics.thinkingLevel,
|
|
10368
10573
|
destination,
|
|
10369
10574
|
destinationVisibility,
|
|
10370
10575
|
source,
|
|
@@ -10399,11 +10604,15 @@ function createReplyToThread(deps) {
|
|
|
10399
10604
|
traceId: getActiveTraceId()
|
|
10400
10605
|
});
|
|
10401
10606
|
}
|
|
10402
|
-
await
|
|
10403
|
-
|
|
10404
|
-
|
|
10607
|
+
await persistWithRetry(
|
|
10608
|
+
() => persistConversationMessages({
|
|
10609
|
+
conversation: completedState.conversation,
|
|
10610
|
+
conversationId
|
|
10611
|
+
})
|
|
10612
|
+
);
|
|
10613
|
+
await persistThreadRuntimeStateWithRetry(thread, completedState);
|
|
10405
10614
|
if (completedState.artifacts && (assistantTitleArtifacts.assistantTitle !== void 0 || assistantTitleArtifacts.assistantTitleSourceMessageId !== void 0) && (completedState.artifacts.assistantTitle !== assistantTitleArtifacts.assistantTitle || completedState.artifacts.assistantTitleSourceMessageId !== assistantTitleArtifacts.assistantTitleSourceMessageId)) {
|
|
10406
|
-
await
|
|
10615
|
+
await persistThreadRuntimeStateWithRetry(thread, {
|
|
10407
10616
|
artifacts: latestArtifacts
|
|
10408
10617
|
});
|
|
10409
10618
|
}
|
|
@@ -10751,6 +10960,8 @@ function createPrepareTurnState(deps) {
|
|
|
10751
10960
|
) : void 0;
|
|
10752
10961
|
const artifacts = coerceThreadArtifactsState(existingState);
|
|
10753
10962
|
const conversation = coerceThreadConversationState(existingState);
|
|
10963
|
+
const conversationId = args.context.threadId ?? args.context.runId;
|
|
10964
|
+
await hydrateConversationMessages({ conversation, conversationId });
|
|
10754
10965
|
const channelConfiguration = getChannelConfigurationService(args.thread);
|
|
10755
10966
|
const configuration = await channelConfiguration.resolveValues();
|
|
10756
10967
|
await seedConversationBackfill(args.thread, conversation, {
|
|
@@ -10790,12 +11001,16 @@ function createPrepareTurnState(deps) {
|
|
|
10790
11001
|
threadTs: getThreadTs(args.context.threadId)
|
|
10791
11002
|
});
|
|
10792
11003
|
}
|
|
11004
|
+
await persistConversationMessages({ conversation, conversationId });
|
|
10793
11005
|
await deps.compactConversationIfNeeded(conversation, {
|
|
10794
11006
|
threadId: args.context.threadId,
|
|
10795
11007
|
channelId: args.context.channelId,
|
|
10796
11008
|
actorId: args.context.actorId,
|
|
10797
11009
|
runId: args.context.runId
|
|
10798
11010
|
});
|
|
11011
|
+
if (conversationId) {
|
|
11012
|
+
await persistConversationCompactions({ conversation, conversationId });
|
|
11013
|
+
}
|
|
10799
11014
|
const conversationContext = buildConversationContext(conversation, {
|
|
10800
11015
|
excludeMessageId: userMessageId
|
|
10801
11016
|
});
|
|
@@ -10990,14 +11205,15 @@ function createJuniorSlackAdapter(config) {
|
|
|
10990
11205
|
|
|
10991
11206
|
// src/chat/runtime/agent-continue-runner.ts
|
|
10992
11207
|
var AGENT_CONTINUE_LOCK_RETRY_DELAYS_MS = [250, 1e3, 2e3];
|
|
10993
|
-
function sleep2(ms) {
|
|
10994
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
10995
|
-
}
|
|
10996
11208
|
async function persistCompletedReplyState2(args) {
|
|
10997
11209
|
const currentState = await getPersistedThreadState(
|
|
10998
11210
|
args.sessionRecord.conversationId
|
|
10999
11211
|
);
|
|
11000
11212
|
const conversation = coerceThreadConversationState(currentState);
|
|
11213
|
+
await hydrateConversationMessages({
|
|
11214
|
+
conversation,
|
|
11215
|
+
conversationId: args.sessionRecord.conversationId
|
|
11216
|
+
});
|
|
11001
11217
|
const artifacts = coerceThreadArtifactsState(currentState);
|
|
11002
11218
|
const userMessage2 = getTurnUserMessage(
|
|
11003
11219
|
conversation,
|
|
@@ -11040,6 +11256,10 @@ async function persistFailedReplyState2(sessionRecord) {
|
|
|
11040
11256
|
sessionRecord.conversationId
|
|
11041
11257
|
);
|
|
11042
11258
|
const conversation = coerceThreadConversationState(currentState);
|
|
11259
|
+
await hydrateConversationMessages({
|
|
11260
|
+
conversation,
|
|
11261
|
+
conversationId: sessionRecord.conversationId
|
|
11262
|
+
});
|
|
11043
11263
|
clearPendingAuth(conversation, sessionRecord.sessionId);
|
|
11044
11264
|
markTurnFailed({
|
|
11045
11265
|
conversation,
|
|
@@ -11141,6 +11361,10 @@ async function continueSlackAgentRun(payload, options) {
|
|
|
11141
11361
|
payload.conversationId
|
|
11142
11362
|
);
|
|
11143
11363
|
const conversation = coerceThreadConversationState(currentState);
|
|
11364
|
+
await hydrateConversationMessages({
|
|
11365
|
+
conversation,
|
|
11366
|
+
conversationId: payload.conversationId
|
|
11367
|
+
});
|
|
11144
11368
|
const artifacts = coerceThreadArtifactsState(currentState);
|
|
11145
11369
|
const userMessage2 = getTurnUserMessage(conversation, payload.sessionId);
|
|
11146
11370
|
if (!userMessage2?.author?.userId) {
|
|
@@ -11162,19 +11386,32 @@ async function continueSlackAgentRun(payload, options) {
|
|
|
11162
11386
|
payload.destination,
|
|
11163
11387
|
"Slack continuation"
|
|
11164
11388
|
);
|
|
11165
|
-
const
|
|
11166
|
-
|
|
11167
|
-
|
|
11168
|
-
|
|
11169
|
-
|
|
11170
|
-
}
|
|
11171
|
-
|
|
11172
|
-
await failStrandedSessionWithFallback({
|
|
11389
|
+
const systemActor = activeSessionRecord.actor?.platform === "system" ? activeSessionRecord.actor : void 0;
|
|
11390
|
+
let actor;
|
|
11391
|
+
let credentialContext;
|
|
11392
|
+
if (systemActor) {
|
|
11393
|
+
credentialContext = { actor: systemActor };
|
|
11394
|
+
} else {
|
|
11395
|
+
actor = await resolveContinuationActor({
|
|
11173
11396
|
conversationId: payload.conversationId,
|
|
11174
|
-
|
|
11175
|
-
|
|
11397
|
+
sessionRecordActor: activeSessionRecord.actor,
|
|
11398
|
+
teamId: destination.teamId,
|
|
11399
|
+
userId: userMessage2.author.userId
|
|
11176
11400
|
});
|
|
11177
|
-
|
|
11401
|
+
if (!actor) {
|
|
11402
|
+
await failStrandedSessionWithFallback({
|
|
11403
|
+
conversationId: payload.conversationId,
|
|
11404
|
+
errorMessage: "Stored Slack actor missing for continuation",
|
|
11405
|
+
sessionRecord: activeSessionRecord
|
|
11406
|
+
});
|
|
11407
|
+
return false;
|
|
11408
|
+
}
|
|
11409
|
+
credentialContext = {
|
|
11410
|
+
actor: {
|
|
11411
|
+
type: "user",
|
|
11412
|
+
userId: actor.userId
|
|
11413
|
+
}
|
|
11414
|
+
};
|
|
11178
11415
|
}
|
|
11179
11416
|
if (!activeSessionRecord.source) {
|
|
11180
11417
|
await failAgentTurnSessionRecord({
|
|
@@ -11191,17 +11428,16 @@ async function continueSlackAgentRun(payload, options) {
|
|
|
11191
11428
|
replyContext: {
|
|
11192
11429
|
input: {
|
|
11193
11430
|
conversationContext,
|
|
11194
|
-
|
|
11431
|
+
// Pi history is SQL-authoritative: the resumed run reads its
|
|
11432
|
+
// session record first and falls back to the step projection.
|
|
11433
|
+
piMessages: await loadProjection({
|
|
11434
|
+
conversationId: payload.conversationId
|
|
11435
|
+
}),
|
|
11195
11436
|
...getTurnUserReplyAttachmentContext(userMessage2)
|
|
11196
11437
|
},
|
|
11197
11438
|
routing: {
|
|
11198
|
-
credentialContext
|
|
11199
|
-
|
|
11200
|
-
type: "user",
|
|
11201
|
-
userId: actor.userId
|
|
11202
|
-
}
|
|
11203
|
-
},
|
|
11204
|
-
actor,
|
|
11439
|
+
credentialContext,
|
|
11440
|
+
...actor ? { actor } : {},
|
|
11205
11441
|
destination: payload.destination,
|
|
11206
11442
|
source: activeSessionRecord.source,
|
|
11207
11443
|
correlation: {
|
|
@@ -11209,7 +11445,7 @@ async function continueSlackAgentRun(payload, options) {
|
|
|
11209
11445
|
turnId: payload.sessionId,
|
|
11210
11446
|
channelId: thread.channelId,
|
|
11211
11447
|
threadTs: thread.threadTs,
|
|
11212
|
-
actorId: actor.userId
|
|
11448
|
+
...actor ? { actorId: actor.userId } : {}
|
|
11213
11449
|
},
|
|
11214
11450
|
toolChannelId: artifacts.assistantContextChannelId ?? thread.channelId
|
|
11215
11451
|
},
|
|
@@ -11295,6 +11531,10 @@ async function failStrandedSessionWithFallback(args) {
|
|
|
11295
11531
|
});
|
|
11296
11532
|
const currentState = await getPersistedThreadState(args.conversationId);
|
|
11297
11533
|
const conversation = coerceThreadConversationState(currentState);
|
|
11534
|
+
await hydrateConversationMessages({
|
|
11535
|
+
conversation,
|
|
11536
|
+
conversationId: args.conversationId
|
|
11537
|
+
});
|
|
11298
11538
|
markTurnFailed({
|
|
11299
11539
|
conversation,
|
|
11300
11540
|
nowMs: Date.now(),
|
|
@@ -11464,7 +11704,7 @@ async function continueSlackAgentRunWithLockRetry(payload, options) {
|
|
|
11464
11704
|
},
|
|
11465
11705
|
"Agent continuation lock was busy; retrying"
|
|
11466
11706
|
);
|
|
11467
|
-
await
|
|
11707
|
+
await sleep(delayMs);
|
|
11468
11708
|
}
|
|
11469
11709
|
}
|
|
11470
11710
|
return true;
|
|
@@ -11888,12 +12128,12 @@ async function createApp(options) {
|
|
|
11888
12128
|
app.get("/", () => GET());
|
|
11889
12129
|
app.get("/health", () => GET());
|
|
11890
12130
|
app.get("/api/oauth/callback/mcp/:provider", (c) => {
|
|
11891
|
-
return
|
|
12131
|
+
return GET4(c.req.raw, c.req.param("provider"), waitUntil, {
|
|
11892
12132
|
agentRunner
|
|
11893
12133
|
});
|
|
11894
12134
|
});
|
|
11895
12135
|
app.get("/api/oauth/callback/:provider", (c) => {
|
|
11896
|
-
return
|
|
12136
|
+
return GET5(c.req.raw, c.req.param("provider"), waitUntil, {
|
|
11897
12137
|
agentRunner
|
|
11898
12138
|
});
|
|
11899
12139
|
});
|
|
@@ -11928,6 +12168,9 @@ async function createApp(options) {
|
|
|
11928
12168
|
app.get("/api/internal/heartbeat", (c) => {
|
|
11929
12169
|
return GET2(c.req.raw, waitUntil);
|
|
11930
12170
|
});
|
|
12171
|
+
app.get("/api/internal/retention", (c) => {
|
|
12172
|
+
return GET3(c.req.raw);
|
|
12173
|
+
});
|
|
11931
12174
|
app.post("/api/webhooks/slack", (c) => {
|
|
11932
12175
|
return POST3(c.req.raw, waitUntil, slackWebhookServices);
|
|
11933
12176
|
});
|