@sentry/junior 0.144.0 → 0.146.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-GCUTGKY3.js → agent-hooks-SLJADYE5.js} +10 -10
- package/dist/api/conversations/detail.d.ts +1 -0
- package/dist/api/schema/conversation.d.ts +2 -0
- package/dist/api/schema.js +1 -1
- package/dist/api.js +40 -22
- package/dist/app.js +400 -461
- package/dist/{catalog-runtime-DWVYKDC6.js → catalog-runtime-RQIMSDPR.js} +5 -5
- package/dist/chat/agent/request.d.ts +1 -1
- package/dist/chat/agent/resume.d.ts +6 -18
- package/dist/chat/agent/skills.d.ts +0 -1
- package/dist/chat/agent/tools.d.ts +1 -2
- package/dist/chat/agent-dispatch/types.d.ts +1 -1
- package/dist/chat/app/conversation-work.d.ts +24 -0
- package/dist/chat/conversations/message-search.d.ts +32 -0
- package/dist/chat/conversations/projection.d.ts +11 -3
- package/dist/chat/conversations/sql/message-search.d.ts +4 -0
- package/dist/chat/conversations/store.d.ts +1 -1
- package/dist/chat/conversations/tool-source.d.ts +5 -0
- package/dist/chat/db.d.ts +2 -2
- package/dist/chat/runtime/agent-run-outcome.d.ts +1 -1
- package/dist/chat/runtime/reply-executor.d.ts +5 -5
- package/dist/chat/runtime/slack-resume.d.ts +12 -4
- package/dist/chat/slack/message/attachments.d.ts +2 -0
- package/dist/chat/slack/message/blocks.d.ts +2 -0
- package/dist/chat/slack/message/content.d.ts +18 -0
- package/dist/chat/slack/message/identity.d.ts +7 -0
- package/dist/chat/slack/tools/{conversation-search.d.ts → conversation-message-search.d.ts} +21 -14
- package/dist/chat/slack/tools/user-lookup.d.ts +2 -1
- package/dist/chat/state/locks.d.ts +28 -0
- package/dist/chat/task-execution/checkpoint.d.ts +84 -0
- package/dist/chat/task-execution/paused-turn.d.ts +29 -0
- package/dist/chat/task-execution/queue-signing.d.ts +1 -0
- package/dist/chat/task-execution/queue.d.ts +7 -1
- package/dist/chat/task-execution/slack-work.d.ts +1 -1
- package/dist/chat/task-execution/state.d.ts +4 -4
- package/dist/chat/task-execution/store.d.ts +2 -2
- package/dist/chat/task-execution/turn-cursor-keys.d.ts +6 -0
- package/dist/chat/{state/turn-session.d.ts → task-execution/turn-cursor.d.ts} +52 -51
- package/dist/chat/task-execution/turn-wake.d.ts +29 -0
- package/dist/chat/tools/{query-conversation-events.d.ts → search-conversation-events.d.ts} +3 -3
- package/dist/chat/tools/types.d.ts +1 -1
- package/dist/{chunk-SBZP2J5Q.js → chunk-37EVZP66.js} +48 -35
- package/dist/{chunk-A67GZN73.js → chunk-37JJDS4H.js} +1 -1
- package/dist/{chunk-BBCWYXHB.js → chunk-47OSH2ZO.js} +7 -7
- package/dist/{chunk-4X5KM7Z6.js → chunk-AISNSNDV.js} +14 -14
- package/dist/{chunk-RIFJUJSI.js → chunk-B63BF443.js} +1 -1
- package/dist/{chunk-SSDTQDYQ.js → chunk-BLETMLRX.js} +566 -268
- package/dist/{chunk-I44JB7HQ.js → chunk-F7REGDKO.js} +1 -1
- package/dist/{chunk-DVO5VKYQ.js → chunk-FEKQHPVA.js} +5 -5
- package/dist/{chunk-SUK7NC5A.js → chunk-FGHADGIC.js} +2 -2
- package/dist/{chunk-7KAW7UF4.js → chunk-FXDDDSPL.js} +4 -4
- package/dist/{chunk-BEGGFVFR.js → chunk-GDQEU4I7.js} +414 -542
- package/dist/{chunk-UDQMY6RS.js → chunk-GYEKOX7N.js} +43 -1
- package/dist/{chunk-W7JFV5SB.js → chunk-H6U2U3EP.js} +14 -17
- package/dist/{chunk-WTX2RFJG.js → chunk-HQE6EJS5.js} +1 -1
- package/dist/{chunk-IUFM5JWV.js → chunk-JAL3CH4G.js} +3 -0
- package/dist/{chunk-E7HCWOHG.js → chunk-JLMVCNXL.js} +2 -1
- package/dist/{chunk-PELZ2ZSY.js → chunk-JUA6VU2Z.js} +33 -63
- package/dist/{chunk-SHEEZSLY.js → chunk-LVW7BLLT.js} +2 -2
- package/dist/{chunk-GKA74DRA.js → chunk-M6ZWP4RI.js} +1 -1
- package/dist/{chunk-HNO2E5WB.js → chunk-MCFIXAV5.js} +1 -1
- package/dist/{chunk-3GU4PWA3.js → chunk-MKRIZ4VG.js} +29 -30
- package/dist/{chunk-QUZJDAQQ.js → chunk-OFPYOC3M.js} +93 -90
- package/dist/{chunk-ZF3N3JD6.js → chunk-PB222GIA.js} +1 -1
- package/dist/{chunk-PKH6762I.js → chunk-PH4Q3A6W.js} +1 -1
- package/dist/{chunk-STFCL3K4.js → chunk-QG7OOKIN.js} +1 -1
- package/dist/{chunk-WSOLZJJS.js → chunk-QSXZ42KX.js} +3 -3
- package/dist/{chunk-44RJWAND.js → chunk-SCGVWUZX.js} +6 -6
- package/dist/{chunk-CNTWB2SM.js → chunk-T5GXFFLA.js} +1 -1
- package/dist/{chunk-LDWNYCZ6.js → chunk-TCEJ7XXM.js} +1 -1
- package/dist/{chunk-QE3TICD4.js → chunk-V6SRLKUB.js} +2 -2
- package/dist/{chunk-54JMYQYS.js → chunk-W65V465O.js} +2 -2
- package/dist/{chunk-KCBZSJRU.js → chunk-WR76IVA5.js} +5 -2
- package/dist/{chunk-ZZCTGAIT.js → chunk-X22KCSCO.js} +4 -4
- package/dist/{chunk-HD6BHR25.js → chunk-X2WMBTS3.js} +32 -34
- package/dist/{chunk-KQBXT5B7.js → chunk-ZDGHGY74.js} +6 -6
- package/dist/cli/chat.js +32 -32
- package/dist/cli/check.js +6 -6
- package/dist/cli/plugins.js +13 -13
- package/dist/cli/snapshot-create.js +9 -9
- package/dist/cli/upgrade.js +7 -7
- package/dist/{db-EFLHTBU6.js → db-WWOMXWTT.js} +9 -9
- package/dist/instrumentation.js +4 -4
- package/dist/nitro.js +4 -4
- package/dist/{oauth-callback-server-RO3IQKWM.js → oauth-callback-server-A6ZZX74U.js} +25 -25
- package/dist/{runner-LOWW7JKA.js → runner-KSGB2UAV.js} +19 -20
- package/dist/{skills-ZLMUG7AE.js → skills-26QPWKVS.js} +6 -6
- package/dist/spawn-5LAJXZ2P.js +39 -0
- package/dist/{validation-MAKEZNTS.js → validation-OPSRGFGH.js} +6 -6
- package/dist/version.js +1 -1
- package/dist/{work-5OAGC3I4.js → work-VMSW7STJ.js} +17 -16
- package/dist/worker-2JNFB7C7.js +24 -0
- package/package.json +5 -5
- package/dist/chat/agent/session.d.ts +0 -19
- package/dist/chat/conversations/search.d.ts +0 -24
- package/dist/chat/conversations/sql/search.d.ts +0 -4
- package/dist/chat/runtime/agent-continue-runner.d.ts +0 -37
- package/dist/chat/services/agent-continue.d.ts +0 -29
- package/dist/chat/services/turn-session-record.d.ts +0 -164
- package/dist/chat/slack/legacy-attachments.d.ts +0 -4
- package/dist/chat/slack/message.d.ts +0 -12
- package/dist/chat/state/turn-session-keys.d.ts +0 -6
- package/dist/spawn-R3LUV6RF.js +0 -38
- package/dist/worker-KTGGRTTP.js +0 -24
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
PluginCredentialFailureError,
|
|
8
8
|
agentNameSchema,
|
|
9
9
|
createPluginAuthOrchestration
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-FEKQHPVA.js";
|
|
11
11
|
import {
|
|
12
12
|
authorizationId
|
|
13
13
|
} from "./chunk-DIB4GX3G.js";
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
patchMcpAuthSession,
|
|
29
29
|
selectPluginGrant,
|
|
30
30
|
toMcpProviderError
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-47OSH2ZO.js";
|
|
32
32
|
import {
|
|
33
33
|
RetryableDeliveryError,
|
|
34
34
|
actorFromRouting,
|
|
@@ -44,12 +44,12 @@ import {
|
|
|
44
44
|
getSlackMessagePermalink,
|
|
45
45
|
resolveBaseUrl,
|
|
46
46
|
uploadFilesToConversation
|
|
47
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-ZDGHGY74.js";
|
|
48
48
|
import {
|
|
49
49
|
estimateTextTokens,
|
|
50
50
|
getAgentContextCompactionTriggerTokens,
|
|
51
51
|
getAgentContextInputLimitTokens
|
|
52
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-T5GXFFLA.js";
|
|
53
53
|
import {
|
|
54
54
|
AGENTS_REMOVAL_NOTICE,
|
|
55
55
|
AGENTS_REPLACEMENT_NOTICE,
|
|
@@ -66,6 +66,7 @@ import {
|
|
|
66
66
|
canReusePendingAuthLink,
|
|
67
67
|
collectFiles,
|
|
68
68
|
containsNoReplyMarker,
|
|
69
|
+
continuableMessages,
|
|
69
70
|
decideReply,
|
|
70
71
|
extractAssistantText,
|
|
71
72
|
findSingleRepositoryDirectory,
|
|
@@ -86,17 +87,13 @@ import {
|
|
|
86
87
|
isTurnInputCommitLostError,
|
|
87
88
|
loadConnectedMcpProviders,
|
|
88
89
|
loadConversationProjection,
|
|
90
|
+
loadTurnCheckpoint,
|
|
89
91
|
loadTurnRoute,
|
|
90
|
-
loadTurnSessionRecord,
|
|
91
92
|
mergeArtifactsState,
|
|
92
93
|
missingPathSearchResult,
|
|
93
94
|
normalizeToLf,
|
|
94
95
|
normalizeToolNameFromResult,
|
|
95
96
|
openConversationProjection,
|
|
96
|
-
persistAuthPauseSessionRecord,
|
|
97
|
-
persistContinuationSessionRecord,
|
|
98
|
-
persistRunningSessionRecord,
|
|
99
|
-
persistYieldSessionRecord,
|
|
100
97
|
piMessageFromHistoryItem,
|
|
101
98
|
positiveInteger,
|
|
102
99
|
recordAgentsInstructionsUpdated,
|
|
@@ -110,10 +107,11 @@ import {
|
|
|
110
107
|
resolveWorkspacePath,
|
|
111
108
|
retainRuntimeTurnContext,
|
|
112
109
|
sanitizeAssistantText,
|
|
110
|
+
saveTurnCheckpoint,
|
|
113
111
|
stripRuntimeTurnContext,
|
|
114
112
|
trimTrailingAssistantMessages,
|
|
115
113
|
truncateText
|
|
116
|
-
} from "./chunk-
|
|
114
|
+
} from "./chunk-GDQEU4I7.js";
|
|
117
115
|
import {
|
|
118
116
|
JUNIOR_THREAD_STATE_TTL_MS
|
|
119
117
|
} from "./chunk-3Y47VMHV.js";
|
|
@@ -145,7 +143,7 @@ import {
|
|
|
145
143
|
runNonInteractiveCommand,
|
|
146
144
|
throwSandboxOperationError,
|
|
147
145
|
wrapSandboxSetupError
|
|
148
|
-
} from "./chunk-
|
|
146
|
+
} from "./chunk-FXDDDSPL.js";
|
|
149
147
|
import {
|
|
150
148
|
SCHEDULED_TASK_SYSTEM_ACTOR,
|
|
151
149
|
compactEventTask,
|
|
@@ -177,15 +175,15 @@ import {
|
|
|
177
175
|
saveEventTask,
|
|
178
176
|
scheduledTaskAttributes,
|
|
179
177
|
writableEventTask
|
|
180
|
-
} from "./chunk-
|
|
178
|
+
} from "./chunk-X22KCSCO.js";
|
|
181
179
|
import {
|
|
182
180
|
parseSlackThreadId
|
|
183
|
-
} from "./chunk-
|
|
181
|
+
} from "./chunk-PH4Q3A6W.js";
|
|
184
182
|
import {
|
|
185
183
|
SHORT_TITLE_MAX_LENGTH,
|
|
186
184
|
generateShortTitle,
|
|
187
185
|
resolveTaskTitle
|
|
188
|
-
} from "./chunk-
|
|
186
|
+
} from "./chunk-W65V465O.js";
|
|
189
187
|
import {
|
|
190
188
|
ToolInputError,
|
|
191
189
|
addAgentTurnUsage,
|
|
@@ -203,7 +201,7 @@ import {
|
|
|
203
201
|
getSlackToolContext,
|
|
204
202
|
readActorIdentity,
|
|
205
203
|
resolveChannelCapabilities
|
|
206
|
-
} from "./chunk-
|
|
204
|
+
} from "./chunk-SCGVWUZX.js";
|
|
207
205
|
import {
|
|
208
206
|
SlackActionError,
|
|
209
207
|
downloadPrivateSlackFile,
|
|
@@ -212,18 +210,23 @@ import {
|
|
|
212
210
|
isConversationScopedChannel,
|
|
213
211
|
normalizeSlackConversationId,
|
|
214
212
|
withSlackRetries
|
|
215
|
-
} from "./chunk-
|
|
213
|
+
} from "./chunk-V6SRLKUB.js";
|
|
216
214
|
import {
|
|
217
215
|
KNOWN_CONVERSATION_EVENT_TYPES,
|
|
218
216
|
contextProvenance,
|
|
219
217
|
getConversationEventStore,
|
|
220
|
-
|
|
218
|
+
getConversationMessageSearchStore,
|
|
221
219
|
getConversationStore,
|
|
222
220
|
getDb,
|
|
221
|
+
getSqlExecutor,
|
|
223
222
|
instructionActors,
|
|
224
223
|
instructionProvenanceFor,
|
|
225
|
-
sameActorIdentity
|
|
226
|
-
|
|
224
|
+
sameActorIdentity,
|
|
225
|
+
upsertIdentity
|
|
226
|
+
} from "./chunk-37EVZP66.js";
|
|
227
|
+
import {
|
|
228
|
+
juniorIdentities
|
|
229
|
+
} from "./chunk-MCFIXAV5.js";
|
|
227
230
|
import {
|
|
228
231
|
SANDBOX_DATA_ROOT,
|
|
229
232
|
SANDBOX_SKILLS_ROOT,
|
|
@@ -235,7 +238,7 @@ import {
|
|
|
235
238
|
} from "./chunk-EM225ITJ.js";
|
|
236
239
|
import {
|
|
237
240
|
getStateAdapter
|
|
238
|
-
} from "./chunk-
|
|
241
|
+
} from "./chunk-GYEKOX7N.js";
|
|
239
242
|
import {
|
|
240
243
|
ACTIVE_TURN_COMPACTION_SUMMARY_PREFIX,
|
|
241
244
|
COMPACTION_SUMMARY_PREFIX,
|
|
@@ -263,13 +266,12 @@ import {
|
|
|
263
266
|
modelIdForProfile,
|
|
264
267
|
modelProfileSchema,
|
|
265
268
|
normalizeSlackEmojiName,
|
|
266
|
-
parseTurnReasoningLevel,
|
|
267
269
|
profileConfig,
|
|
268
270
|
renderCurrentInstruction,
|
|
269
271
|
resolveGatewayCredential,
|
|
270
272
|
resolveGatewayModel,
|
|
271
273
|
unwrapCurrentInstruction
|
|
272
|
-
} from "./chunk-
|
|
274
|
+
} from "./chunk-MKRIZ4VG.js";
|
|
273
275
|
import {
|
|
274
276
|
canExposeConversationPayload,
|
|
275
277
|
resolveConversationPrivacy,
|
|
@@ -279,16 +281,16 @@ import {
|
|
|
279
281
|
toGenAiMessagesTraceAttributes,
|
|
280
282
|
toGenAiPayloadMetadata,
|
|
281
283
|
toGenAiPayloadTraceAttributes
|
|
282
|
-
} from "./chunk-
|
|
284
|
+
} from "./chunk-QG7OOKIN.js";
|
|
283
285
|
import {
|
|
284
286
|
discoverSkills,
|
|
285
287
|
findSkillByName,
|
|
286
288
|
loadSkillsByName,
|
|
287
289
|
parseSkillInvocation
|
|
288
|
-
} from "./chunk-
|
|
290
|
+
} from "./chunk-FGHADGIC.js";
|
|
289
291
|
import {
|
|
290
292
|
pluginCatalogRuntime
|
|
291
|
-
} from "./chunk-
|
|
293
|
+
} from "./chunk-PB222GIA.js";
|
|
292
294
|
import {
|
|
293
295
|
CredentialUnavailableError,
|
|
294
296
|
OAuthProviderError,
|
|
@@ -296,7 +298,7 @@ import {
|
|
|
296
298
|
getOAuthProviderErrorAttributes,
|
|
297
299
|
resolveAuthTokenPlaceholder,
|
|
298
300
|
resolvePluginCommandEnv
|
|
299
|
-
} from "./chunk-
|
|
301
|
+
} from "./chunk-37JJDS4H.js";
|
|
300
302
|
import {
|
|
301
303
|
credentialUserSubjectId
|
|
302
304
|
} from "./chunk-RUIXF3YQ.js";
|
|
@@ -318,6 +320,7 @@ import {
|
|
|
318
320
|
logInfo,
|
|
319
321
|
logWarn,
|
|
320
322
|
normalizeGenAiFinishReason,
|
|
323
|
+
normalizeIdentityEmail,
|
|
321
324
|
serializeGenAiAttribute,
|
|
322
325
|
setSpanAttributes,
|
|
323
326
|
setSpanStatus,
|
|
@@ -325,7 +328,7 @@ import {
|
|
|
325
328
|
summarizeMessageText,
|
|
326
329
|
withLogContext,
|
|
327
330
|
withSpan
|
|
328
|
-
} from "./chunk-
|
|
331
|
+
} from "./chunk-B63BF443.js";
|
|
329
332
|
import {
|
|
330
333
|
startInactiveSpan,
|
|
331
334
|
withActiveSpan
|
|
@@ -1404,21 +1407,6 @@ function actionConfirmationRetryMessages(messages) {
|
|
|
1404
1407
|
return retryMessages;
|
|
1405
1408
|
}
|
|
1406
1409
|
|
|
1407
|
-
// src/chat/agent/session.ts
|
|
1408
|
-
async function restoreSessionRecord(args) {
|
|
1409
|
-
const sessionRecordState = await loadTurnSessionRecord({
|
|
1410
|
-
conversationId: args.conversationId,
|
|
1411
|
-
sessionId: args.turnId
|
|
1412
|
-
});
|
|
1413
|
-
const { resumedFromSessionRecord, currentSliceId, existingSessionRecord } = sessionRecordState;
|
|
1414
|
-
return {
|
|
1415
|
-
currentSliceId,
|
|
1416
|
-
existingSessionRecord,
|
|
1417
|
-
resumedFromSessionRecord,
|
|
1418
|
-
sessionRecordState
|
|
1419
|
-
};
|
|
1420
|
-
}
|
|
1421
|
-
|
|
1422
1410
|
// src/chat/mcp/tool-name.ts
|
|
1423
1411
|
function parseMcpProviderFromToolName(toolName) {
|
|
1424
1412
|
if (!toolName.startsWith("mcp__")) return void 0;
|
|
@@ -1590,7 +1578,6 @@ async function restoreSkillRuntime(args) {
|
|
|
1590
1578
|
const restoredSkill = await args.skillSandbox.loadSkill(skillName);
|
|
1591
1579
|
if (restoredSkill) {
|
|
1592
1580
|
upsertActiveSkill(args.activeSkills, restoredSkill);
|
|
1593
|
-
args.syncLoadedSkillNamesForResume();
|
|
1594
1581
|
}
|
|
1595
1582
|
}
|
|
1596
1583
|
if (args.invokedSkill) {
|
|
@@ -1599,7 +1586,6 @@ async function restoreSkillRuntime(args) {
|
|
|
1599
1586
|
);
|
|
1600
1587
|
if (restoredSkill) {
|
|
1601
1588
|
upsertActiveSkill(args.activeSkills, restoredSkill);
|
|
1602
|
-
args.syncLoadedSkillNamesForResume();
|
|
1603
1589
|
}
|
|
1604
1590
|
}
|
|
1605
1591
|
}
|
|
@@ -8149,7 +8135,7 @@ function createSearchResourceEventTypesTool(catalog) {
|
|
|
8149
8135
|
outputSchema: outputSchema2,
|
|
8150
8136
|
async execute({ query, namespace, maxResults }) {
|
|
8151
8137
|
const normalizedQuery = normalizeSearchText(query ?? "");
|
|
8152
|
-
const
|
|
8138
|
+
const terms2 = normalizedQuery.split(/\s+/).filter(Boolean);
|
|
8153
8139
|
const matches = searchableResourceTypes(catalog).filter(
|
|
8154
8140
|
(resourceType) => {
|
|
8155
8141
|
if (namespace && resourceType.namespace !== namespace) return false;
|
|
@@ -8161,7 +8147,7 @@ function createSearchResourceEventTypesTool(catalog) {
|
|
|
8161
8147
|
...resourceType.suggestedEvents ?? []
|
|
8162
8148
|
].join(" ")
|
|
8163
8149
|
);
|
|
8164
|
-
return
|
|
8150
|
+
return terms2.every((term) => text.includes(term));
|
|
8165
8151
|
}
|
|
8166
8152
|
);
|
|
8167
8153
|
const resourceTypes = matches.slice(
|
|
@@ -9833,32 +9819,63 @@ function createSlackChannelListMessagesTool(context) {
|
|
|
9833
9819
|
});
|
|
9834
9820
|
}
|
|
9835
9821
|
|
|
9836
|
-
// src/chat/slack/tools/conversation-search.ts
|
|
9822
|
+
// src/chat/slack/tools/conversation-message-search.ts
|
|
9837
9823
|
import { z as z37 } from "zod";
|
|
9824
|
+
|
|
9825
|
+
// src/chat/conversations/tool-source.ts
|
|
9826
|
+
var CONVERSATIONS_TOOL_SOURCE = {
|
|
9827
|
+
id: "conversations",
|
|
9828
|
+
description: "Search messages and events in retained Junior conversations."
|
|
9829
|
+
};
|
|
9830
|
+
|
|
9831
|
+
// src/chat/slack/tools/conversation-message-search.ts
|
|
9838
9832
|
var DEFAULT_LIMIT = 5;
|
|
9839
|
-
var
|
|
9840
|
-
|
|
9833
|
+
var conversationMessageSearchOutputSchema = juniorToolOutputSchema.extend({
|
|
9834
|
+
channel_id: z37.string().min(1).optional(),
|
|
9841
9835
|
count: z37.number().int().nonnegative(),
|
|
9842
|
-
|
|
9836
|
+
query: z37.string().optional(),
|
|
9837
|
+
matches: z37.array(
|
|
9843
9838
|
z37.object({
|
|
9839
|
+
channel_id: z37.string().min(1),
|
|
9840
|
+
channel_name: z37.string().min(1).optional(),
|
|
9844
9841
|
conversation_id: z37.string().min(1),
|
|
9845
|
-
|
|
9842
|
+
excerpt: z37.string(),
|
|
9846
9843
|
message_id: z37.string().min(1),
|
|
9847
9844
|
message_role: z37.enum(["assistant", "user"]),
|
|
9848
9845
|
message_timestamp: z37.string().datetime(),
|
|
9849
|
-
|
|
9850
|
-
|
|
9846
|
+
permalink: z37.string().url().optional(),
|
|
9847
|
+
thread_ts: z37.string().min(1)
|
|
9851
9848
|
}).strict()
|
|
9852
9849
|
)
|
|
9853
9850
|
});
|
|
9854
|
-
function
|
|
9851
|
+
function resolveSearchFilters(input) {
|
|
9852
|
+
const query = input.query?.trim() || void 0;
|
|
9853
|
+
let channelId;
|
|
9854
|
+
if (input.channel_id != null) {
|
|
9855
|
+
const parsed = parseRequiredSlackChannelIdParam(
|
|
9856
|
+
"channel_id",
|
|
9857
|
+
input.channel_id
|
|
9858
|
+
);
|
|
9859
|
+
if (!parsed.ok) {
|
|
9860
|
+
throw new ToolInputError(parsed.error);
|
|
9861
|
+
}
|
|
9862
|
+
channelId = parsed.value;
|
|
9863
|
+
}
|
|
9864
|
+
if (!query && !channelId) {
|
|
9865
|
+
throw new ToolInputError(
|
|
9866
|
+
"Provide at least one of `query` or `channel_id`."
|
|
9867
|
+
);
|
|
9868
|
+
}
|
|
9869
|
+
return {
|
|
9870
|
+
...channelId ? { channelId } : {},
|
|
9871
|
+
...query ? { query } : {}
|
|
9872
|
+
};
|
|
9873
|
+
}
|
|
9874
|
+
function createSlackConversationMessageSearchTool(scope, currentConversationId, deps = {}) {
|
|
9855
9875
|
return zodTool({
|
|
9856
|
-
description: "Search
|
|
9876
|
+
description: "Search retained user and assistant messages in public Junior conversations across the current Slack workspace. Excludes the current conversation.",
|
|
9857
9877
|
exposure: "deferred",
|
|
9858
|
-
source:
|
|
9859
|
-
id: "conversation-history",
|
|
9860
|
-
description: "Search retained public Junior conversation threads in the current Slack workspace."
|
|
9861
|
-
},
|
|
9878
|
+
source: CONVERSATIONS_TOOL_SOURCE,
|
|
9862
9879
|
annotations: {
|
|
9863
9880
|
destructiveHint: false,
|
|
9864
9881
|
idempotentHint: true,
|
|
@@ -9866,20 +9883,24 @@ function createSlackConversationSearchTool(scope, currentConversationId, deps =
|
|
|
9866
9883
|
readOnlyHint: true
|
|
9867
9884
|
},
|
|
9868
9885
|
inputSchema: z37.object({
|
|
9869
|
-
|
|
9870
|
-
|
|
9871
|
-
|
|
9872
|
-
|
|
9873
|
-
|
|
9874
|
-
|
|
9886
|
+
channel_id: slackChannelIdParam(
|
|
9887
|
+
"Destination Slack channel ID; no active-channel default."
|
|
9888
|
+
).nullable().optional(),
|
|
9889
|
+
query: z37.string().trim().min(1).max(200).nullable().describe("Words or phrase to match in message text.").optional(),
|
|
9890
|
+
limit: z37.number().int().min(1).max(10).describe(`Maximum matches. Default ${DEFAULT_LIMIT}; max 10.`).nullable().optional()
|
|
9891
|
+
}).strict(),
|
|
9892
|
+
outputSchema: conversationMessageSearchOutputSchema,
|
|
9893
|
+
execute: async (input) => {
|
|
9894
|
+
const filters = resolveSearchFilters(input);
|
|
9895
|
+
const store = deps.store ?? getConversationMessageSearchStore();
|
|
9875
9896
|
const matches = await store.search({
|
|
9876
9897
|
currentConversationId,
|
|
9877
|
-
|
|
9878
|
-
|
|
9898
|
+
filters,
|
|
9899
|
+
limit: input.limit ?? DEFAULT_LIMIT,
|
|
9879
9900
|
scope
|
|
9880
9901
|
});
|
|
9881
9902
|
const getPermalink = deps.getPermalink ?? getSlackMessagePermalink;
|
|
9882
|
-
const
|
|
9903
|
+
const matchesOutput = await Promise.all(
|
|
9883
9904
|
matches.map(async (match) => {
|
|
9884
9905
|
const reference = parseSlackThreadId(match.conversationId);
|
|
9885
9906
|
if (!reference || reference.channelId !== match.providerDestinationId) {
|
|
@@ -9898,14 +9919,17 @@ function createSlackConversationSearchTool(scope, currentConversationId, deps =
|
|
|
9898
9919
|
message_role: match.role,
|
|
9899
9920
|
message_timestamp: new Date(match.messageCreatedAtMs).toISOString(),
|
|
9900
9921
|
excerpt: match.excerpt,
|
|
9922
|
+
channel_id: match.providerDestinationId,
|
|
9923
|
+
...match.channelName ? { channel_name: match.channelName } : {},
|
|
9901
9924
|
...permalink ? { permalink } : {}
|
|
9902
9925
|
};
|
|
9903
9926
|
})
|
|
9904
9927
|
);
|
|
9905
9928
|
return {
|
|
9906
|
-
query,
|
|
9907
|
-
|
|
9908
|
-
|
|
9929
|
+
...filters.query ? { query: filters.query } : {},
|
|
9930
|
+
...filters.channelId ? { channel_id: filters.channelId } : {},
|
|
9931
|
+
count: matchesOutput.length,
|
|
9932
|
+
matches: matchesOutput
|
|
9909
9933
|
};
|
|
9910
9934
|
}
|
|
9911
9935
|
});
|
|
@@ -11311,7 +11335,100 @@ function parseSlackMessageReference(input) {
|
|
|
11311
11335
|
};
|
|
11312
11336
|
}
|
|
11313
11337
|
|
|
11314
|
-
// src/chat/slack/
|
|
11338
|
+
// src/chat/slack/message/blocks.ts
|
|
11339
|
+
var MAX_BLOCKS = 50;
|
|
11340
|
+
var MAX_CHILDREN = 50;
|
|
11341
|
+
var MAX_DEPTH = 16;
|
|
11342
|
+
var MAX_NODES = 5e3;
|
|
11343
|
+
var CHILD_KEYS = [
|
|
11344
|
+
"blocks",
|
|
11345
|
+
"elements",
|
|
11346
|
+
"fields",
|
|
11347
|
+
"accessory",
|
|
11348
|
+
"element",
|
|
11349
|
+
"rows",
|
|
11350
|
+
"cells"
|
|
11351
|
+
];
|
|
11352
|
+
function toText(value) {
|
|
11353
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
11354
|
+
}
|
|
11355
|
+
function readText(value) {
|
|
11356
|
+
if (typeof value === "string") return toText(value);
|
|
11357
|
+
if (!value || typeof value !== "object") return void 0;
|
|
11358
|
+
return toText(value.text);
|
|
11359
|
+
}
|
|
11360
|
+
function parseChildren(value, budget, depth) {
|
|
11361
|
+
if (Array.isArray(value)) {
|
|
11362
|
+
return value.slice(0, MAX_CHILDREN).flatMap((child) => parseChildren(child, budget, depth));
|
|
11363
|
+
}
|
|
11364
|
+
return parseElement(value, budget, depth);
|
|
11365
|
+
}
|
|
11366
|
+
function parseElement(value, budget, depth) {
|
|
11367
|
+
if (!value || typeof value !== "object" || depth > MAX_DEPTH || budget.remainingNodes <= 0) {
|
|
11368
|
+
return [];
|
|
11369
|
+
}
|
|
11370
|
+
budget.remainingNodes -= 1;
|
|
11371
|
+
const element = value;
|
|
11372
|
+
const type = toText(element.type);
|
|
11373
|
+
const text = readText(element.text);
|
|
11374
|
+
if (type === "link") {
|
|
11375
|
+
const url = toText(element.url);
|
|
11376
|
+
return [
|
|
11377
|
+
text && url && text !== url ? `${text} (${url})` : text || url
|
|
11378
|
+
].filter((part) => Boolean(part));
|
|
11379
|
+
}
|
|
11380
|
+
if (type === "button") {
|
|
11381
|
+
const url = toText(element.url);
|
|
11382
|
+
return [text && url ? `${text} (${url})` : text].filter(
|
|
11383
|
+
(part) => Boolean(part)
|
|
11384
|
+
);
|
|
11385
|
+
}
|
|
11386
|
+
if (type === "emoji") {
|
|
11387
|
+
const name = toText(element.name);
|
|
11388
|
+
return name ? [`:${name}:`] : [];
|
|
11389
|
+
}
|
|
11390
|
+
if (type === "user") {
|
|
11391
|
+
const userId = toText(element.user_id);
|
|
11392
|
+
return userId ? [`<@${userId}>`] : [];
|
|
11393
|
+
}
|
|
11394
|
+
if (type === "channel") {
|
|
11395
|
+
const channelId = toText(element.channel_id);
|
|
11396
|
+
return channelId ? [`<#${channelId}>`] : [];
|
|
11397
|
+
}
|
|
11398
|
+
if (type === "usergroup") {
|
|
11399
|
+
const usergroupId = toText(element.usergroup_id);
|
|
11400
|
+
return usergroupId ? [`<!subteam^${usergroupId}>`] : [];
|
|
11401
|
+
}
|
|
11402
|
+
if (type === "broadcast") {
|
|
11403
|
+
const range = toText(element.range);
|
|
11404
|
+
return range ? [`<!${range}>`] : [];
|
|
11405
|
+
}
|
|
11406
|
+
const parts = [
|
|
11407
|
+
text,
|
|
11408
|
+
readText(element.title),
|
|
11409
|
+
readText(element.description),
|
|
11410
|
+
readText(element.label),
|
|
11411
|
+
readText(element.hint),
|
|
11412
|
+
readText(element.placeholder),
|
|
11413
|
+
toText(element.alt_text),
|
|
11414
|
+
toText(element.provider_name),
|
|
11415
|
+
toText(element.fallback)
|
|
11416
|
+
].filter((part) => Boolean(part));
|
|
11417
|
+
for (const key of CHILD_KEYS) {
|
|
11418
|
+
parts.push(...parseChildren(element[key], budget, depth + 1));
|
|
11419
|
+
}
|
|
11420
|
+
if (type === "checkboxes" || type === "radio_buttons") {
|
|
11421
|
+
parts.push(...parseChildren(element.options, budget, depth + 1));
|
|
11422
|
+
}
|
|
11423
|
+
return parts;
|
|
11424
|
+
}
|
|
11425
|
+
function renderBlockText(value) {
|
|
11426
|
+
if (!Array.isArray(value)) return "";
|
|
11427
|
+
const budget = { remainingNodes: MAX_NODES };
|
|
11428
|
+
return value.slice(0, MAX_BLOCKS).flatMap((block) => parseElement(block, budget, 0)).join("\n");
|
|
11429
|
+
}
|
|
11430
|
+
|
|
11431
|
+
// src/chat/slack/message/attachments.ts
|
|
11315
11432
|
var MAX_ATTACHMENTS = 10;
|
|
11316
11433
|
var MAX_FIELDS_PER_ATTACHMENT = 20;
|
|
11317
11434
|
var MAX_FIELD_CHARS = 1e3;
|
|
@@ -11349,6 +11466,7 @@ function renderAttachment(raw) {
|
|
|
11349
11466
|
const text = toStr(obj.text);
|
|
11350
11467
|
const footer = toStr(obj.footer);
|
|
11351
11468
|
const fields = Array.isArray(obj.fields) ? obj.fields : [];
|
|
11469
|
+
const blockText = renderBlockText(obj.blocks);
|
|
11352
11470
|
const add = (value) => {
|
|
11353
11471
|
if (!value) return;
|
|
11354
11472
|
const normalized = normalizeAttachmentText(value);
|
|
@@ -11356,7 +11474,7 @@ function renderAttachment(raw) {
|
|
|
11356
11474
|
seen.add(normalized);
|
|
11357
11475
|
parts.push(normalized);
|
|
11358
11476
|
};
|
|
11359
|
-
const hasRichContent = pretext || title || text;
|
|
11477
|
+
const hasRichContent = pretext || title || text || blockText;
|
|
11360
11478
|
if (!hasRichContent) {
|
|
11361
11479
|
add(fallback);
|
|
11362
11480
|
}
|
|
@@ -11372,28 +11490,19 @@ function renderAttachment(raw) {
|
|
|
11372
11490
|
for (const field of fields.slice(0, MAX_FIELDS_PER_ATTACHMENT)) {
|
|
11373
11491
|
add(renderField(field));
|
|
11374
11492
|
}
|
|
11493
|
+
add(blockText);
|
|
11375
11494
|
add(footer);
|
|
11376
11495
|
return parts.join("\n");
|
|
11377
11496
|
}
|
|
11378
|
-
function
|
|
11497
|
+
function renderAttachmentText(input) {
|
|
11379
11498
|
const rendered = getAttachmentPayload(input).slice(0, MAX_ATTACHMENTS).map(renderAttachment).filter((line) => line.length > 0).map((line) => `[attachment] ${line}`).join("\n");
|
|
11380
11499
|
return rendered.slice(0, MAX_ATTACHMENT_TEXT_CHARS);
|
|
11381
11500
|
}
|
|
11382
|
-
function appendSlackLegacyAttachmentText(baseText, rawMessageOrAttachments) {
|
|
11383
|
-
const base = baseText?.trim() ?? "";
|
|
11384
|
-
const attachmentText = renderSlackLegacyAttachmentText(
|
|
11385
|
-
rawMessageOrAttachments
|
|
11386
|
-
);
|
|
11387
|
-
if (!attachmentText) return base;
|
|
11388
|
-
if (!base) return attachmentText;
|
|
11389
|
-
return `${base}
|
|
11390
|
-
${attachmentText}`;
|
|
11391
|
-
}
|
|
11392
11501
|
|
|
11393
11502
|
// src/chat/slack/tools/thread-read.ts
|
|
11394
11503
|
var MAX_THREAD_READ_CHARS = 4e4;
|
|
11395
11504
|
function sanitizeMessage(msg) {
|
|
11396
|
-
const attachmentText =
|
|
11505
|
+
const attachmentText = renderAttachmentText(msg.attachments);
|
|
11397
11506
|
return {
|
|
11398
11507
|
ts: msg.ts,
|
|
11399
11508
|
user: msg.user,
|
|
@@ -11534,6 +11643,10 @@ function createSlackThreadReadTool(context, deps = {}) {
|
|
|
11534
11643
|
});
|
|
11535
11644
|
}
|
|
11536
11645
|
|
|
11646
|
+
// src/chat/slack/tools/user-lookup.ts
|
|
11647
|
+
import { and, eq } from "drizzle-orm";
|
|
11648
|
+
import { z as z50 } from "zod";
|
|
11649
|
+
|
|
11537
11650
|
// src/chat/slack/users.ts
|
|
11538
11651
|
function normalizeUser(raw) {
|
|
11539
11652
|
const rawFields = raw.profile?.fields;
|
|
@@ -11674,7 +11787,6 @@ async function searchSlackUsers(options) {
|
|
|
11674
11787
|
}
|
|
11675
11788
|
|
|
11676
11789
|
// src/chat/slack/tools/user-lookup.ts
|
|
11677
|
-
import { z as z50 } from "zod";
|
|
11678
11790
|
function explicitUserLookupError(error) {
|
|
11679
11791
|
if (error.apiError === "user_not_found") {
|
|
11680
11792
|
return "No Slack user found for the supplied user ID.";
|
|
@@ -11693,9 +11805,52 @@ function explicitUserLookupError(error) {
|
|
|
11693
11805
|
}
|
|
11694
11806
|
return void 0;
|
|
11695
11807
|
}
|
|
11696
|
-
function
|
|
11808
|
+
function slackMention(userId) {
|
|
11809
|
+
return `<@${userId}>`;
|
|
11810
|
+
}
|
|
11811
|
+
async function storeProfile(teamId, profile) {
|
|
11812
|
+
await upsertIdentity(getSqlExecutor(), {
|
|
11813
|
+
kind: profile.is_bot ? "service" : "user",
|
|
11814
|
+
provider: "slack",
|
|
11815
|
+
providerTenantId: teamId,
|
|
11816
|
+
providerSubjectId: profile.id,
|
|
11817
|
+
...profile.real_name || profile.display_name ? { displayName: profile.real_name || profile.display_name } : {},
|
|
11818
|
+
...profile.name ? { handle: profile.name } : {},
|
|
11819
|
+
...profile.email ? { email: profile.email, emailVerified: true } : {}
|
|
11820
|
+
});
|
|
11821
|
+
}
|
|
11822
|
+
async function storedUserByEmail(teamId, email) {
|
|
11823
|
+
const emailNormalized = normalizeIdentityEmail(email);
|
|
11824
|
+
if (!emailNormalized) return void 0;
|
|
11825
|
+
const identities = await getSqlExecutor().db().select().from(juniorIdentities).where(
|
|
11826
|
+
and(
|
|
11827
|
+
eq(juniorIdentities.provider, "slack"),
|
|
11828
|
+
eq(juniorIdentities.providerTenantId, teamId),
|
|
11829
|
+
eq(juniorIdentities.kind, "user"),
|
|
11830
|
+
eq(juniorIdentities.emailVerified, true),
|
|
11831
|
+
eq(juniorIdentities.emailNormalized, emailNormalized)
|
|
11832
|
+
)
|
|
11833
|
+
).limit(2);
|
|
11834
|
+
if (identities.length > 1) {
|
|
11835
|
+
throw new Error(
|
|
11836
|
+
`Multiple Slack users share verified email ${emailNormalized} in workspace ${teamId}`
|
|
11837
|
+
);
|
|
11838
|
+
}
|
|
11839
|
+
const identity = identities[0];
|
|
11840
|
+
if (!identity) return void 0;
|
|
11841
|
+
return {
|
|
11842
|
+
id: identity.providerSubjectId,
|
|
11843
|
+
...identity.handle ? { name: identity.handle } : {},
|
|
11844
|
+
...identity.displayName ? { real_name: identity.displayName } : {},
|
|
11845
|
+
...identity.displayName ? { display_name: identity.displayName } : {},
|
|
11846
|
+
...identity.email ? { email: identity.email } : {},
|
|
11847
|
+
is_bot: false,
|
|
11848
|
+
is_deleted: false
|
|
11849
|
+
};
|
|
11850
|
+
}
|
|
11851
|
+
function createSlackUserLookupTool(teamId) {
|
|
11697
11852
|
return zodTool({
|
|
11698
|
-
description: "Look up Slack user profiles by user ID, email, or name search.
|
|
11853
|
+
description: "Look up Slack user profiles by user ID, email, or name search. Returns Slack `mention` values (`<@U\u2026>`). Use a mention only when one person clearly matches; otherwise ask which person the user means.",
|
|
11699
11854
|
annotations: {
|
|
11700
11855
|
destructiveHint: false,
|
|
11701
11856
|
idempotentHint: true,
|
|
@@ -11718,20 +11873,33 @@ function createSlackUserLookupTool() {
|
|
|
11718
11873
|
if (!parsedUserId.ok) {
|
|
11719
11874
|
throw new ToolInputError(parsedUserId.error);
|
|
11720
11875
|
}
|
|
11876
|
+
const user = await lookupSlackUserProfile(parsedUserId.value);
|
|
11877
|
+
await storeProfile(teamId, user);
|
|
11721
11878
|
return {
|
|
11722
11879
|
mode: "user_id",
|
|
11723
|
-
|
|
11880
|
+
mention: slackMention(user.id),
|
|
11881
|
+
user
|
|
11724
11882
|
};
|
|
11725
11883
|
}
|
|
11726
11884
|
if (mode === "email") {
|
|
11885
|
+
const stored = await storedUserByEmail(teamId, value);
|
|
11886
|
+
if (stored) {
|
|
11887
|
+
return {
|
|
11888
|
+
mode: "email",
|
|
11889
|
+
mention: slackMention(stored.id),
|
|
11890
|
+
user: stored
|
|
11891
|
+
};
|
|
11892
|
+
}
|
|
11727
11893
|
const profile = await lookupSlackUserByEmail(value);
|
|
11728
11894
|
if (!profile) {
|
|
11729
11895
|
throw new ToolInputError(
|
|
11730
11896
|
`No Slack user found with email address ${value}.`
|
|
11731
11897
|
);
|
|
11732
11898
|
}
|
|
11899
|
+
await storeProfile(teamId, profile);
|
|
11733
11900
|
return {
|
|
11734
11901
|
mode: "email",
|
|
11902
|
+
mention: slackMention(profile.id),
|
|
11735
11903
|
user: profile
|
|
11736
11904
|
};
|
|
11737
11905
|
}
|
|
@@ -11741,6 +11909,9 @@ function createSlackUserLookupTool() {
|
|
|
11741
11909
|
maxPages: 3,
|
|
11742
11910
|
includeBots: false
|
|
11743
11911
|
});
|
|
11912
|
+
if (result.users.length === 1) {
|
|
11913
|
+
await storeProfile(teamId, result.users[0]);
|
|
11914
|
+
}
|
|
11744
11915
|
return {
|
|
11745
11916
|
mode: "query",
|
|
11746
11917
|
query: value,
|
|
@@ -11748,7 +11919,10 @@ function createSlackUserLookupTool() {
|
|
|
11748
11919
|
searched_pages: result.searched_pages,
|
|
11749
11920
|
searched_user_count: result.searched_user_count,
|
|
11750
11921
|
truncated: result.truncated,
|
|
11751
|
-
users: result.users
|
|
11922
|
+
users: result.users.map((user) => ({
|
|
11923
|
+
...user,
|
|
11924
|
+
mention: slackMention(user.id)
|
|
11925
|
+
}))
|
|
11752
11926
|
};
|
|
11753
11927
|
} catch (error) {
|
|
11754
11928
|
if (error instanceof SlackActionError) {
|
|
@@ -11854,7 +12028,7 @@ function getTimeZoneOffsetMinutes(timestampMs, timezone) {
|
|
|
11854
12028
|
return Math.round((timestampMs - asUtcMs) / 6e4);
|
|
11855
12029
|
}
|
|
11856
12030
|
|
|
11857
|
-
// src/chat/tools/
|
|
12031
|
+
// src/chat/tools/search-conversation-events.ts
|
|
11858
12032
|
import { z as z52 } from "zod";
|
|
11859
12033
|
var DEFAULT_LIMIT3 = 25;
|
|
11860
12034
|
var MAX_LIMIT = 100;
|
|
@@ -11862,40 +12036,26 @@ var MAX_EVENT_DATA_BYTES = 4e3;
|
|
|
11862
12036
|
var MAX_EVENTS_JSON_BYTES = 2e4;
|
|
11863
12037
|
var MAX_IDENTITY_CHARS = 256;
|
|
11864
12038
|
var textEncoder = new TextEncoder();
|
|
11865
|
-
var CONVERSATION_EVENTS_TOOL_SOURCE = {
|
|
11866
|
-
id: "conversation-events",
|
|
11867
|
-
description: "Inspect Junior's durable conversation event log for debugging runtime behavior."
|
|
11868
|
-
};
|
|
11869
12039
|
var knownEventTypeSchema = z52.enum(KNOWN_CONVERSATION_EVENT_TYPES);
|
|
11870
12040
|
var projectedEventSchema = z52.object({
|
|
11871
|
-
seq: z52.number().int().nonnegative().describe("Stable event position
|
|
11872
|
-
history_version: z52.number().int().nonnegative().describe(
|
|
11873
|
-
"Model-history generation. It increments when handoff or compaction replaces active model context."
|
|
11874
|
-
),
|
|
12041
|
+
seq: z52.number().int().nonnegative().describe("Stable event position for pagination."),
|
|
12042
|
+
history_version: z52.number().int().nonnegative().describe("Agent history generation after replacement."),
|
|
11875
12043
|
created_at: z52.iso.datetime().describe("When the event was recorded."),
|
|
11876
|
-
idempotency_key: z52.string().min(1).optional().describe("Retry-stable event identity, when
|
|
11877
|
-
data: z52.record(z52.string(), z52.unknown()).describe(
|
|
11878
|
-
"Event data. Oversized payloads are replaced by identifying fields, payload_omitted, and payload_json_bytes."
|
|
11879
|
-
)
|
|
12044
|
+
idempotency_key: z52.string().min(1).optional().describe("Retry-stable event identity, when assigned."),
|
|
12045
|
+
data: z52.record(z52.string(), z52.unknown()).describe("Bounded event data.")
|
|
11880
12046
|
}).strict();
|
|
11881
|
-
var
|
|
12047
|
+
var searchConversationEventsOutputSchema = juniorToolOutputSchema.extend({
|
|
11882
12048
|
conversation_id: z52.string().min(1),
|
|
11883
12049
|
events: z52.array(projectedEventSchema),
|
|
11884
|
-
has_older: z52.boolean().describe(
|
|
11885
|
-
|
|
11886
|
-
)
|
|
11887
|
-
has_newer: z52.boolean().describe(
|
|
11888
|
-
"Whether matching events exist after this page; request them with after_seq set to the last returned seq."
|
|
11889
|
-
),
|
|
11890
|
-
omitted_event_count: z52.number().int().nonnegative().optional().describe(
|
|
11891
|
-
"Fetched events omitted to keep this response bounded. Continue with the pagination cursor for the omitted direction."
|
|
11892
|
-
)
|
|
12050
|
+
has_older: z52.boolean().describe("Whether matching older events exist."),
|
|
12051
|
+
has_newer: z52.boolean().describe("Whether matching newer events exist."),
|
|
12052
|
+
omitted_event_count: z52.number().int().nonnegative().optional().describe("Events omitted by the response byte limit.")
|
|
11893
12053
|
});
|
|
11894
|
-
function
|
|
12054
|
+
function createSearchConversationEventsTool(context) {
|
|
11895
12055
|
return zodTool({
|
|
11896
|
-
description: "
|
|
12056
|
+
description: "Search the durable event log for one conversation, including messages, agent history, tool results, handoffs, and compactions. Defaults to the current conversation. Outside the current conversation tree, only retained public conversations in the current Slack workspace are accessible.",
|
|
11897
12057
|
exposure: "deferred",
|
|
11898
|
-
source:
|
|
12058
|
+
source: CONVERSATIONS_TOOL_SOURCE,
|
|
11899
12059
|
annotations: {
|
|
11900
12060
|
destructiveHint: false,
|
|
11901
12061
|
idempotentHint: true,
|
|
@@ -11903,31 +12063,25 @@ function createQueryConversationEventsTool(context) {
|
|
|
11903
12063
|
readOnlyHint: true
|
|
11904
12064
|
},
|
|
11905
12065
|
inputSchema: z52.object({
|
|
11906
|
-
conversation_id: z52.string().trim().min(1).describe(
|
|
11907
|
-
"Conversation ID to
|
|
11908
|
-
),
|
|
11909
|
-
after_seq: z52.number().int().nonnegative().nullable().describe(
|
|
11910
|
-
"Exclusive lower bound on event seq. When set, returns the next newer page in ascending order."
|
|
11911
|
-
).optional(),
|
|
11912
|
-
before_seq: z52.number().int().nonnegative().nullable().describe(
|
|
11913
|
-
"Exclusive upper bound on event seq. Combine with defaults or after_seq to page older or bounded ranges."
|
|
12066
|
+
conversation_id: z52.string().trim().min(1).nullable().describe(
|
|
12067
|
+
"Conversation ID to search. Omit or null for the current conversation."
|
|
11914
12068
|
).optional(),
|
|
12069
|
+
after_seq: z52.number().int().nonnegative().nullable().describe("Exclusive event sequence lower bound; returns ascending.").optional(),
|
|
12070
|
+
before_seq: z52.number().int().nonnegative().nullable().describe("Exclusive event sequence upper bound.").optional(),
|
|
11915
12071
|
limit: z52.number().int().min(1).max(MAX_LIMIT).nullable().describe(
|
|
11916
|
-
`Maximum events
|
|
12072
|
+
`Maximum events. Default ${DEFAULT_LIMIT3}; max ${MAX_LIMIT}.`
|
|
11917
12073
|
).optional(),
|
|
11918
|
-
types: z52.array(knownEventTypeSchema).min(1).nullable().describe(
|
|
11919
|
-
"Optional event-type filter. Omit to return every durable event type."
|
|
11920
|
-
).optional()
|
|
12074
|
+
types: z52.array(knownEventTypeSchema).min(1).nullable().describe("Event types to include; omit for all types.").optional()
|
|
11921
12075
|
}).strict(),
|
|
11922
|
-
outputSchema:
|
|
12076
|
+
outputSchema: searchConversationEventsOutputSchema,
|
|
11923
12077
|
execute: async (input) => {
|
|
11924
12078
|
const currentConversationId = context.conversationId?.trim();
|
|
11925
12079
|
if (!currentConversationId) {
|
|
11926
12080
|
throw new ToolInputError(
|
|
11927
|
-
"
|
|
12081
|
+
"searchConversationEvents requires an active conversation"
|
|
11928
12082
|
);
|
|
11929
12083
|
}
|
|
11930
|
-
const conversationId = input.conversation_id;
|
|
12084
|
+
const conversationId = input.conversation_id?.trim() || currentConversationId;
|
|
11931
12085
|
const afterSeq = input.after_seq ?? void 0;
|
|
11932
12086
|
const beforeSeq = input.before_seq ?? void 0;
|
|
11933
12087
|
const limit = input.limit ?? DEFAULT_LIMIT3;
|
|
@@ -11960,7 +12114,7 @@ function createQueryConversationEventsTool(context) {
|
|
|
11960
12114
|
const targetRoot = targetRootConversationId === conversationId ? target : await conversationStore.get({
|
|
11961
12115
|
conversationId: targetRootConversationId
|
|
11962
12116
|
});
|
|
11963
|
-
|
|
12117
|
+
assertCanSearchConversationEvents({
|
|
11964
12118
|
accessScope,
|
|
11965
12119
|
targetConversationId: conversationId,
|
|
11966
12120
|
targetRootConversationId,
|
|
@@ -12038,7 +12192,7 @@ async function resolveRootConversationId(conversationStore, conversationId, pare
|
|
|
12038
12192
|
}
|
|
12039
12193
|
return conversationId;
|
|
12040
12194
|
}
|
|
12041
|
-
function
|
|
12195
|
+
function assertCanSearchConversationEvents(args) {
|
|
12042
12196
|
const {
|
|
12043
12197
|
accessScope,
|
|
12044
12198
|
targetConversationId,
|
|
@@ -12865,7 +13019,7 @@ function createTools(availableSkills, hooks = {}, context, options = {}) {
|
|
|
12865
13019
|
...createScheduledTaskTools(context)
|
|
12866
13020
|
};
|
|
12867
13021
|
if (context.conversationId) {
|
|
12868
|
-
tools.
|
|
13022
|
+
tools.searchConversationEvents = createSearchConversationEventsTool(context);
|
|
12869
13023
|
}
|
|
12870
13024
|
if (context.supportsImageInput) {
|
|
12871
13025
|
tools.viewImage = createViewImageTool(
|
|
@@ -12902,7 +13056,7 @@ function createTools(availableSkills, hooks = {}, context, options = {}) {
|
|
|
12902
13056
|
tools.slackCanvasWrite = createSlackCanvasWriteTool(state);
|
|
12903
13057
|
tools.slackThreadRead = createSlackThreadReadTool(slackContext);
|
|
12904
13058
|
if (context.conversationId && slackContext.source.visibility === "public") {
|
|
12905
|
-
tools.
|
|
13059
|
+
tools.searchConversationMessages = createSlackConversationMessageSearchTool(
|
|
12906
13060
|
{
|
|
12907
13061
|
kind: "public_provider_tenant",
|
|
12908
13062
|
provider: "slack",
|
|
@@ -12916,7 +13070,7 @@ function createTools(availableSkills, hooks = {}, context, options = {}) {
|
|
|
12916
13070
|
context.slackActionToken
|
|
12917
13071
|
);
|
|
12918
13072
|
}
|
|
12919
|
-
tools.slackUserLookup = createSlackUserLookupTool();
|
|
13073
|
+
tools.slackUserLookup = createSlackUserLookupTool(slackContext.teamId);
|
|
12920
13074
|
tools.slackListCreate = createSlackListCreateTool(state);
|
|
12921
13075
|
tools.slackListAddItems = createSlackListAddItemsTool(state);
|
|
12922
13076
|
tools.slackListGetItems = createSlackListGetItemsTool(state);
|
|
@@ -13561,6 +13715,46 @@ var SEARCH_TOOLS_NAME = "searchTools";
|
|
|
13561
13715
|
var DEFAULT_MAX_RESULTS2 = 5;
|
|
13562
13716
|
var MAX_RESULTS3 = 20;
|
|
13563
13717
|
var MODEL_VISIBLE_DESCRIPTION_CAP = 180;
|
|
13718
|
+
var SEARCH_FIELD_WEIGHTS = [8, 4, 1];
|
|
13719
|
+
var BM25_K1 = 1.2;
|
|
13720
|
+
var BM25_B = 0.75;
|
|
13721
|
+
var SEARCH_STOP_WORDS = /* @__PURE__ */ new Set([
|
|
13722
|
+
"a",
|
|
13723
|
+
"an",
|
|
13724
|
+
"and",
|
|
13725
|
+
"are",
|
|
13726
|
+
"as",
|
|
13727
|
+
"at",
|
|
13728
|
+
"be",
|
|
13729
|
+
"by",
|
|
13730
|
+
"do",
|
|
13731
|
+
"for",
|
|
13732
|
+
"from",
|
|
13733
|
+
"how",
|
|
13734
|
+
"i",
|
|
13735
|
+
"in",
|
|
13736
|
+
"is",
|
|
13737
|
+
"it",
|
|
13738
|
+
"me",
|
|
13739
|
+
"my",
|
|
13740
|
+
"of",
|
|
13741
|
+
"on",
|
|
13742
|
+
"or",
|
|
13743
|
+
"please",
|
|
13744
|
+
"that",
|
|
13745
|
+
"the",
|
|
13746
|
+
"this",
|
|
13747
|
+
"to",
|
|
13748
|
+
"use",
|
|
13749
|
+
"we",
|
|
13750
|
+
"what",
|
|
13751
|
+
"when",
|
|
13752
|
+
"where",
|
|
13753
|
+
"which",
|
|
13754
|
+
"with",
|
|
13755
|
+
"you",
|
|
13756
|
+
"your"
|
|
13757
|
+
]);
|
|
13564
13758
|
var searchToolsSourceSchema = z58.object({
|
|
13565
13759
|
id: z58.string(),
|
|
13566
13760
|
description: z58.string()
|
|
@@ -13585,8 +13779,26 @@ var searchToolsOutputSchema = juniorToolOutputSchema.extend({
|
|
|
13585
13779
|
execution_tool: z58.literal("executeTool"),
|
|
13586
13780
|
tools: z58.array(searchToolsToolSchema)
|
|
13587
13781
|
}).strict();
|
|
13588
|
-
function
|
|
13589
|
-
|
|
13782
|
+
function terms(value) {
|
|
13783
|
+
const chunks = value.match(/[\p{L}\p{N}]+/gu) ?? [];
|
|
13784
|
+
const result = [];
|
|
13785
|
+
for (const chunk of chunks) {
|
|
13786
|
+
result.push(chunk.toLowerCase());
|
|
13787
|
+
const expanded = chunk.replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").toLowerCase().split(/\s+/);
|
|
13788
|
+
if (expanded.length > 1) {
|
|
13789
|
+
result.push(...expanded);
|
|
13790
|
+
}
|
|
13791
|
+
}
|
|
13792
|
+
return result;
|
|
13793
|
+
}
|
|
13794
|
+
function queryTerms(query) {
|
|
13795
|
+
return [
|
|
13796
|
+
...new Set(
|
|
13797
|
+
terms(query).filter(
|
|
13798
|
+
(term) => term.length >= 2 && !SEARCH_STOP_WORDS.has(term)
|
|
13799
|
+
)
|
|
13800
|
+
)
|
|
13801
|
+
];
|
|
13590
13802
|
}
|
|
13591
13803
|
function summarizeModelVisibleDescription(description) {
|
|
13592
13804
|
const paragraph = description.split(/\n\s*\n/).map((part) => part.trim()).find(Boolean) ?? "";
|
|
@@ -13603,36 +13815,114 @@ function schemaText(schema) {
|
|
|
13603
13815
|
return "";
|
|
13604
13816
|
}
|
|
13605
13817
|
}
|
|
13606
|
-
function
|
|
13607
|
-
return
|
|
13608
|
-
|
|
13609
|
-
|
|
13610
|
-
|
|
13611
|
-
|
|
13612
|
-
|
|
13613
|
-
|
|
13614
|
-
|
|
13615
|
-
|
|
13616
|
-
|
|
13617
|
-
|
|
13618
|
-
|
|
13619
|
-
|
|
13620
|
-
|
|
13818
|
+
function searchableToolFields(name, definition) {
|
|
13819
|
+
return [
|
|
13820
|
+
terms(
|
|
13821
|
+
[
|
|
13822
|
+
name,
|
|
13823
|
+
definition.identity?.id,
|
|
13824
|
+
definition.identity?.name,
|
|
13825
|
+
definition.identity?.plugin
|
|
13826
|
+
].filter(Boolean).join(" ")
|
|
13827
|
+
),
|
|
13828
|
+
terms(
|
|
13829
|
+
[
|
|
13830
|
+
definition.description,
|
|
13831
|
+
definition.promptSnippet,
|
|
13832
|
+
...definition.promptGuidelines ?? []
|
|
13833
|
+
].filter(Boolean).join(" ")
|
|
13834
|
+
),
|
|
13835
|
+
terms(
|
|
13836
|
+
[
|
|
13837
|
+
definition.source?.id,
|
|
13838
|
+
definition.source?.description,
|
|
13839
|
+
schemaText(definition.inputSchema),
|
|
13840
|
+
schemaText(definition.annotations ?? {})
|
|
13841
|
+
].filter(Boolean).join(" ")
|
|
13842
|
+
)
|
|
13843
|
+
];
|
|
13844
|
+
}
|
|
13845
|
+
function prepareSearchDocuments(tools, source) {
|
|
13846
|
+
return Object.entries(tools).filter(
|
|
13847
|
+
([, definition]) => source ? definition.source?.id === source : true
|
|
13848
|
+
).map(([name, definition]) => ({
|
|
13849
|
+
name,
|
|
13850
|
+
fields: searchableToolFields(name, definition)
|
|
13851
|
+
}));
|
|
13852
|
+
}
|
|
13853
|
+
function averageFieldLengths(documents) {
|
|
13854
|
+
if (documents.length === 0) {
|
|
13855
|
+
return SEARCH_FIELD_WEIGHTS.map(() => 0);
|
|
13856
|
+
}
|
|
13857
|
+
return SEARCH_FIELD_WEIGHTS.map(
|
|
13858
|
+
(_, fieldIndex) => documents.reduce(
|
|
13859
|
+
(total, document) => total + document.fields[fieldIndex].length,
|
|
13860
|
+
0
|
|
13861
|
+
) / documents.length
|
|
13621
13862
|
);
|
|
13622
13863
|
}
|
|
13864
|
+
function documentFrequencies(documents) {
|
|
13865
|
+
const frequencies = /* @__PURE__ */ new Map();
|
|
13866
|
+
for (const document of documents) {
|
|
13867
|
+
const uniqueTerms = new Set(document.fields.flat());
|
|
13868
|
+
for (const term of uniqueTerms) {
|
|
13869
|
+
frequencies.set(term, (frequencies.get(term) ?? 0) + 1);
|
|
13870
|
+
}
|
|
13871
|
+
}
|
|
13872
|
+
return frequencies;
|
|
13873
|
+
}
|
|
13874
|
+
function scoreSearchDocument(document, query, frequencies, documentCount, averageLengths) {
|
|
13875
|
+
return query.reduce((score, term) => {
|
|
13876
|
+
const documentFrequency = frequencies.get(term) ?? 0;
|
|
13877
|
+
if (documentFrequency === 0) {
|
|
13878
|
+
return score;
|
|
13879
|
+
}
|
|
13880
|
+
const weightedTermFrequency = document.fields.reduce(
|
|
13881
|
+
(weighted, field, fieldIndex) => {
|
|
13882
|
+
const termFrequency = field.filter(
|
|
13883
|
+
(candidate) => candidate === term
|
|
13884
|
+
).length;
|
|
13885
|
+
if (termFrequency === 0) {
|
|
13886
|
+
return weighted;
|
|
13887
|
+
}
|
|
13888
|
+
const averageLength = averageLengths[fieldIndex] ?? 0;
|
|
13889
|
+
const lengthRatio = averageLength === 0 ? 1 : field.length / averageLength;
|
|
13890
|
+
return weighted + SEARCH_FIELD_WEIGHTS[fieldIndex] * (termFrequency / (1 - BM25_B + BM25_B * lengthRatio));
|
|
13891
|
+
},
|
|
13892
|
+
0
|
|
13893
|
+
);
|
|
13894
|
+
if (weightedTermFrequency === 0) {
|
|
13895
|
+
return score;
|
|
13896
|
+
}
|
|
13897
|
+
const inverseDocumentFrequency = Math.log(
|
|
13898
|
+
1 + (documentCount - documentFrequency + 0.5) / (documentFrequency + 0.5)
|
|
13899
|
+
);
|
|
13900
|
+
return score + inverseDocumentFrequency * weightedTermFrequency * (BM25_K1 + 1) / (weightedTermFrequency + BM25_K1);
|
|
13901
|
+
}, 0);
|
|
13902
|
+
}
|
|
13623
13903
|
function searchCatalogTools(tools, query, source) {
|
|
13624
|
-
const
|
|
13625
|
-
|
|
13626
|
-
|
|
13627
|
-
|
|
13628
|
-
|
|
13629
|
-
|
|
13904
|
+
const documents = prepareSearchDocuments(tools, source);
|
|
13905
|
+
if (!query.trim()) {
|
|
13906
|
+
return documents.map(({ name }) => name).sort((left, right) => left.localeCompare(right));
|
|
13907
|
+
}
|
|
13908
|
+
const searchTerms = queryTerms(query);
|
|
13909
|
+
if (searchTerms.length === 0) {
|
|
13910
|
+
return [];
|
|
13630
13911
|
}
|
|
13631
|
-
const
|
|
13632
|
-
|
|
13633
|
-
|
|
13634
|
-
|
|
13635
|
-
|
|
13912
|
+
const averageLengths = averageFieldLengths(documents);
|
|
13913
|
+
const frequencies = documentFrequencies(documents);
|
|
13914
|
+
return documents.map((document) => ({
|
|
13915
|
+
name: document.name,
|
|
13916
|
+
score: scoreSearchDocument(
|
|
13917
|
+
document,
|
|
13918
|
+
searchTerms,
|
|
13919
|
+
frequencies,
|
|
13920
|
+
documents.length,
|
|
13921
|
+
averageLengths
|
|
13922
|
+
)
|
|
13923
|
+
})).filter(({ score }) => score > 0).sort(
|
|
13924
|
+
(left, right) => right.score - left.score || left.name.localeCompare(right.name)
|
|
13925
|
+
).map(({ name }) => name);
|
|
13636
13926
|
}
|
|
13637
13927
|
function callNotes(definition) {
|
|
13638
13928
|
return [
|
|
@@ -15468,7 +15758,6 @@ async function wireAgentTools(args) {
|
|
|
15468
15758
|
);
|
|
15469
15759
|
const effective = resolvedSkill ?? loadedSkill;
|
|
15470
15760
|
upsertActiveSkill(args.activeSkills, effective);
|
|
15471
|
-
args.syncLoadedSkillNamesForResume();
|
|
15472
15761
|
if (await mcpToolManager.activateForSkill(effective)) {
|
|
15473
15762
|
await args.recordConnectedMcpProvider(effective.pluginProvider);
|
|
15474
15763
|
}
|
|
@@ -15599,6 +15888,18 @@ function extractSliceUsage(messages, beforeMessageCount) {
|
|
|
15599
15888
|
);
|
|
15600
15889
|
return hasAgentTurnUsage(usage) ? usage : void 0;
|
|
15601
15890
|
}
|
|
15891
|
+
function boundaryKey(messages) {
|
|
15892
|
+
return messages.map((message) => {
|
|
15893
|
+
const record2 = message;
|
|
15894
|
+
const content = typeof record2.content === "string" ? record2.content : JSON.stringify(record2.content ?? null);
|
|
15895
|
+
return [
|
|
15896
|
+
String(record2.role ?? ""),
|
|
15897
|
+
String(record2.timestamp ?? ""),
|
|
15898
|
+
String(record2.toolCallId ?? ""),
|
|
15899
|
+
content
|
|
15900
|
+
].join("");
|
|
15901
|
+
}).join("");
|
|
15902
|
+
}
|
|
15602
15903
|
function createResumeState(args) {
|
|
15603
15904
|
let beforeMessageCount = 0;
|
|
15604
15905
|
let inputCommitted = false;
|
|
@@ -15607,19 +15908,26 @@ function createResumeState(args) {
|
|
|
15607
15908
|
let resumeMessages = [];
|
|
15608
15909
|
let turnContexts = [];
|
|
15609
15910
|
let turnStartMessageIndex;
|
|
15610
|
-
|
|
15611
|
-
|
|
15612
|
-
|
|
15613
|
-
|
|
15911
|
+
let advancedPastResume = !args.checkpoint.resumed;
|
|
15912
|
+
let resumedBoundaryKey = "";
|
|
15913
|
+
if (args.checkpoint.resumed && args.checkpoint.record.piMessages.length) {
|
|
15914
|
+
const prior = args.checkpoint.record;
|
|
15915
|
+
latestSafeBoundaryMessages = [...prior.piMessages];
|
|
15916
|
+
resumeMessages = [...prior.piMessages];
|
|
15917
|
+
resumedBoundaryKey = boundaryKey(
|
|
15918
|
+
continuableMessages(prior.piMessages, prior.piMessages)
|
|
15919
|
+
);
|
|
15920
|
+
}
|
|
15921
|
+
const currentSliceId = args.checkpoint.sliceId;
|
|
15922
|
+
const durationMs = () => Date.now() - args.startedAtMs;
|
|
15923
|
+
const writeBase = () => ({
|
|
15614
15924
|
conversationId: args.conversationId,
|
|
15925
|
+
turnId: args.turnId,
|
|
15926
|
+
channelName: args.channelName,
|
|
15615
15927
|
destination: args.destination,
|
|
15616
|
-
|
|
15617
|
-
|
|
15928
|
+
destinationVisibility: args.destinationVisibility,
|
|
15929
|
+
dispatchId: args.dispatchId,
|
|
15618
15930
|
source: args.runSource,
|
|
15619
|
-
sessionId: args.turnId,
|
|
15620
|
-
loadedSkillNames: args.getLoadedSkillNames(),
|
|
15621
|
-
modelId: args.getModelId(),
|
|
15622
|
-
...args.getReasoningLevel() ? { reasoningLevel: args.getReasoningLevel() } : {},
|
|
15623
15931
|
actor: args.actor,
|
|
15624
15932
|
surface: args.surface
|
|
15625
15933
|
});
|
|
@@ -15642,7 +15950,7 @@ function createResumeState(args) {
|
|
|
15642
15950
|
setTurnContexts(contexts) {
|
|
15643
15951
|
turnContexts = contexts;
|
|
15644
15952
|
},
|
|
15645
|
-
/**
|
|
15953
|
+
/** Use an already committed boundary as the resume baseline. */
|
|
15646
15954
|
adoptCommittedBoundary(messages) {
|
|
15647
15955
|
latestSafeBoundaryMessages = [...messages];
|
|
15648
15956
|
resumeMessages = [...messages];
|
|
@@ -15664,18 +15972,23 @@ function createResumeState(args) {
|
|
|
15664
15972
|
inputCommitted = true;
|
|
15665
15973
|
},
|
|
15666
15974
|
async persistSafeBoundary(messages, trailingMessageProvenance) {
|
|
15667
|
-
const
|
|
15668
|
-
|
|
15975
|
+
const saved = await saveTurnCheckpoint({
|
|
15976
|
+
mode: "running",
|
|
15977
|
+
...writeBase(),
|
|
15669
15978
|
sliceId: currentSliceId,
|
|
15670
15979
|
messages,
|
|
15671
|
-
|
|
15672
|
-
|
|
15673
|
-
|
|
15980
|
+
trailingMessageProvenance,
|
|
15981
|
+
turnContexts: turnContexts.length > 0 ? turnContexts : void 0,
|
|
15982
|
+
turnStartMessageIndex
|
|
15674
15983
|
});
|
|
15675
|
-
if (!
|
|
15984
|
+
if (!saved) {
|
|
15676
15985
|
return false;
|
|
15677
15986
|
}
|
|
15678
15987
|
latestSafeBoundaryMessages = [...messages];
|
|
15988
|
+
const persistedKey = boundaryKey(continuableMessages(messages, messages));
|
|
15989
|
+
if (resumedBoundaryKey.length === 0 || persistedKey !== resumedBoundaryKey) {
|
|
15990
|
+
advancedPastResume = true;
|
|
15991
|
+
}
|
|
15679
15992
|
return true;
|
|
15680
15993
|
},
|
|
15681
15994
|
async requireDurableInputCheckpoint(messages, trailingMessageProvenance) {
|
|
@@ -15690,34 +16003,34 @@ function createResumeState(args) {
|
|
|
15690
16003
|
}
|
|
15691
16004
|
return persisted;
|
|
15692
16005
|
},
|
|
15693
|
-
/** Prepare a cooperative yield at the current durable boundary. */
|
|
15694
16006
|
prepareYieldIfDue(currentMessages) {
|
|
15695
16007
|
if (!args.durability.shouldYield?.()) {
|
|
15696
16008
|
return void 0;
|
|
15697
16009
|
}
|
|
15698
|
-
const
|
|
15699
|
-
if (!isContinuablePiBoundary(
|
|
16010
|
+
const next = this.getResumeSnapshot(currentMessages);
|
|
16011
|
+
if (!isContinuablePiBoundary(next)) {
|
|
15700
16012
|
return void 0;
|
|
15701
16013
|
}
|
|
15702
|
-
resumeMessages =
|
|
16014
|
+
resumeMessages = next;
|
|
15703
16015
|
return new CooperativeTurnYieldError(
|
|
15704
|
-
`Agent turn yielded at a safe boundary after ${
|
|
16016
|
+
`Agent turn yielded at a safe boundary after ${durationMs()}ms`
|
|
15705
16017
|
);
|
|
15706
16018
|
},
|
|
15707
|
-
/** Persist an auth pause; only a durable pause may return `awaiting_auth`. */
|
|
15708
16019
|
async parkForAuth(pause, currentUsage) {
|
|
15709
16020
|
const usage = currentUsage ?? (resumeMessages.length > 0 ? extractSliceUsage(resumeMessages, beforeMessageCount) : void 0);
|
|
15710
16021
|
try {
|
|
15711
16022
|
await args.recordActiveMcpProviders();
|
|
15712
|
-
const
|
|
15713
|
-
|
|
15714
|
-
|
|
15715
|
-
|
|
15716
|
-
|
|
16023
|
+
const record2 = await saveTurnCheckpoint({
|
|
16024
|
+
mode: "paused",
|
|
16025
|
+
reason: "auth",
|
|
16026
|
+
...writeBase(),
|
|
16027
|
+
sliceId: currentSliceId,
|
|
16028
|
+
durationMs: durationMs(),
|
|
16029
|
+
usage,
|
|
15717
16030
|
messages: resumeMessages,
|
|
15718
16031
|
errorMessage: pause.message
|
|
15719
16032
|
});
|
|
15720
|
-
if (!
|
|
16033
|
+
if (!record2) {
|
|
15721
16034
|
throw new AuthPausePersistenceError(args.conversationId, args.turnId);
|
|
15722
16035
|
}
|
|
15723
16036
|
return {
|
|
@@ -15727,7 +16040,7 @@ function createResumeState(args) {
|
|
|
15727
16040
|
...usage ? { usage } : {}
|
|
15728
16041
|
};
|
|
15729
16042
|
} catch (error) {
|
|
15730
|
-
if (error instanceof AuthPausePersistenceError) {
|
|
16043
|
+
if (error instanceof AuthPausePersistenceError || error instanceof TurnSliceLimitExceededError) {
|
|
15731
16044
|
throw error;
|
|
15732
16045
|
}
|
|
15733
16046
|
throw new AuthPausePersistenceError(
|
|
@@ -15737,62 +16050,61 @@ function createResumeState(args) {
|
|
|
15737
16050
|
);
|
|
15738
16051
|
}
|
|
15739
16052
|
},
|
|
15740
|
-
/** Persist a yield, retry, or timeout as a suspended run. */
|
|
15741
16053
|
async translateSuspension(ending) {
|
|
15742
16054
|
const { error } = ending;
|
|
15743
|
-
|
|
15744
|
-
|
|
15745
|
-
|
|
15746
|
-
|
|
15747
|
-
|
|
15748
|
-
|
|
15749
|
-
|
|
15750
|
-
|
|
15751
|
-
|
|
15752
|
-
|
|
16055
|
+
const reason = error instanceof CooperativeTurnYieldError ? "yield" : error instanceof RetryableDeliveryError ? "retry" : timedOut ? "timeout" : void 0;
|
|
16056
|
+
if (!reason) {
|
|
16057
|
+
return void 0;
|
|
16058
|
+
}
|
|
16059
|
+
if (reason === "retry") {
|
|
16060
|
+
resumeMessages = [...latestSafeBoundaryMessages];
|
|
16061
|
+
}
|
|
16062
|
+
const parkMessages = reason === "yield" ? [...resumeMessages] : continuableMessages(resumeMessages, latestSafeBoundaryMessages);
|
|
16063
|
+
const parkKey = boundaryKey(parkMessages);
|
|
16064
|
+
if (!advancedPastResume && resumedBoundaryKey.length > 0 && parkKey === resumedBoundaryKey) {
|
|
16065
|
+
logWarn("agent.turn.no_progress_fail", {
|
|
16066
|
+
"app.ai.resume_conversation_id": args.conversationId,
|
|
16067
|
+
"app.ai.resume_session_id": args.turnId,
|
|
16068
|
+
"app.ai.resume_slice_id": currentSliceId,
|
|
16069
|
+
"app.ai.resume_reason": reason
|
|
15753
16070
|
});
|
|
15754
|
-
|
|
15755
|
-
|
|
15756
|
-
|
|
15757
|
-
|
|
15758
|
-
|
|
16071
|
+
await saveTurnCheckpoint({
|
|
16072
|
+
mode: "failed",
|
|
16073
|
+
...writeBase(),
|
|
16074
|
+
sliceId: currentSliceId,
|
|
16075
|
+
durationMs: durationMs(),
|
|
16076
|
+
messages: parkMessages,
|
|
16077
|
+
errorMessage: "Turn made no progress: continue parked at the same boundary"
|
|
16078
|
+
});
|
|
16079
|
+
throw new Error(
|
|
16080
|
+
`Turn made no progress for conversation=${args.conversationId} turn=${args.turnId}`
|
|
16081
|
+
);
|
|
16082
|
+
}
|
|
16083
|
+
const usage = ending.currentUsage ?? extractSliceUsage(parkMessages, beforeMessageCount);
|
|
16084
|
+
await args.recordActiveMcpProviders();
|
|
16085
|
+
const record2 = await saveTurnCheckpoint({
|
|
16086
|
+
mode: "paused",
|
|
16087
|
+
reason,
|
|
16088
|
+
...writeBase(),
|
|
16089
|
+
sliceId: currentSliceId,
|
|
16090
|
+
durationMs: durationMs(),
|
|
16091
|
+
usage,
|
|
16092
|
+
messages: parkMessages,
|
|
16093
|
+
errorMessage: error instanceof Error ? error.message : String(error)
|
|
16094
|
+
});
|
|
16095
|
+
if (!record2) {
|
|
16096
|
+
throw new Error(
|
|
16097
|
+
`Failed to persist continuation for conversation=${args.conversationId} turn=${args.turnId}`
|
|
16098
|
+
);
|
|
16099
|
+
}
|
|
16100
|
+
if (record2.state === "paused") {
|
|
15759
16101
|
return {
|
|
15760
16102
|
status: "suspended",
|
|
15761
|
-
resumeVersion:
|
|
16103
|
+
resumeVersion: record2.version,
|
|
15762
16104
|
...usage ? { usage } : {}
|
|
15763
16105
|
};
|
|
15764
16106
|
}
|
|
15765
|
-
|
|
15766
|
-
if (resumeReason) {
|
|
15767
|
-
if (resumeReason === "retry") {
|
|
15768
|
-
resumeMessages = [...latestSafeBoundaryMessages];
|
|
15769
|
-
}
|
|
15770
|
-
const usage = ending.currentUsage ?? extractSliceUsage(resumeMessages, beforeMessageCount);
|
|
15771
|
-
await args.recordActiveMcpProviders();
|
|
15772
|
-
const sessionRecord = await persistContinuationSessionRecord({
|
|
15773
|
-
...sessionRecordBase(),
|
|
15774
|
-
currentSliceId,
|
|
15775
|
-
currentDurationMs: currentDurationMs(),
|
|
15776
|
-
currentUsage: usage,
|
|
15777
|
-
messages: resumeMessages,
|
|
15778
|
-
errorMessage: error instanceof Error ? error.message : String(error),
|
|
15779
|
-
resumeReason
|
|
15780
|
-
});
|
|
15781
|
-
if (!sessionRecord) {
|
|
15782
|
-
throw new Error(
|
|
15783
|
-
`Failed to persist continuation for conversation=${args.conversationId} turn=${args.turnId}`
|
|
15784
|
-
);
|
|
15785
|
-
}
|
|
15786
|
-
if (sessionRecord.state === "awaiting_resume") {
|
|
15787
|
-
return {
|
|
15788
|
-
status: "suspended",
|
|
15789
|
-
resumeVersion: sessionRecord.version,
|
|
15790
|
-
...usage ? { usage } : {}
|
|
15791
|
-
};
|
|
15792
|
-
}
|
|
15793
|
-
throw new TurnSliceLimitExceededError(botConfig.maxSlicesPerTurn);
|
|
15794
|
-
}
|
|
15795
|
-
return void 0;
|
|
16107
|
+
throw new TurnSliceLimitExceededError(botConfig.maxSlicesPerTurn);
|
|
15796
16108
|
}
|
|
15797
16109
|
};
|
|
15798
16110
|
}
|
|
@@ -16482,20 +16794,11 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
16482
16794
|
const skillInvocation = parseSkillInvocation(userInput, availableSkills);
|
|
16483
16795
|
const invokedSkill = skillInvocation ? findSkillByName(skillInvocation.skillName, availableSkills) : null;
|
|
16484
16796
|
const activeSkills = [];
|
|
16485
|
-
let loadedSkillNamesForResume = [];
|
|
16486
|
-
const syncLoadedSkillNamesForResume = () => {
|
|
16487
|
-
loadedSkillNamesForResume = activeSkills.map((skill) => skill.name);
|
|
16488
|
-
};
|
|
16489
16797
|
const skillSandbox = new SkillSandbox(availableSkills, activeSkills);
|
|
16490
|
-
const {
|
|
16491
|
-
|
|
16492
|
-
|
|
16493
|
-
|
|
16494
|
-
existingSessionRecord
|
|
16495
|
-
} = await restoreSessionRecord({
|
|
16496
|
-
conversationId,
|
|
16497
|
-
turnId
|
|
16498
|
-
});
|
|
16798
|
+
const checkpoint = await loadTurnCheckpoint({ conversationId, turnId });
|
|
16799
|
+
const resumedFromSessionRecord = checkpoint.resumed;
|
|
16800
|
+
const currentSliceId = checkpoint.sliceId;
|
|
16801
|
+
const existingSessionRecord = checkpoint.record;
|
|
16499
16802
|
const committedInstructionProvenance = [
|
|
16500
16803
|
...existingSessionRecord?.piMessageProvenance ?? [],
|
|
16501
16804
|
...(existingSessionRecord?.actors ?? []).map(instructionProvenanceFor),
|
|
@@ -16525,15 +16828,12 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
16525
16828
|
...routing.destinationVisibility ? { destinationVisibility: routing.destinationVisibility } : {},
|
|
16526
16829
|
...routing.dispatch?.id ? { dispatchId: routing.dispatch.id } : {},
|
|
16527
16830
|
durability,
|
|
16528
|
-
getLoadedSkillNames: () => loadedSkillNamesForResume,
|
|
16529
|
-
getReasoningLevel: () => turnRoute?.reasoningLevel,
|
|
16530
|
-
getModelId: () => activeModelId,
|
|
16531
16831
|
recordActiveMcpProviders,
|
|
16532
16832
|
actor,
|
|
16533
16833
|
runSource,
|
|
16534
16834
|
conversationId,
|
|
16535
16835
|
turnId,
|
|
16536
|
-
|
|
16836
|
+
checkpoint,
|
|
16537
16837
|
startedAtMs: replyStartedAtMs,
|
|
16538
16838
|
surface
|
|
16539
16839
|
});
|
|
@@ -16565,8 +16865,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
16565
16865
|
activeSkills,
|
|
16566
16866
|
invokedSkill,
|
|
16567
16867
|
priorPiMessages,
|
|
16568
|
-
skillSandbox
|
|
16569
|
-
syncLoadedSkillNamesForResume
|
|
16868
|
+
skillSandbox
|
|
16570
16869
|
});
|
|
16571
16870
|
const explicitSkill = invokedSkill ? activeSkills.find((skill) => skill.name === invokedSkill.name) ?? null : null;
|
|
16572
16871
|
const { contextContentParts, routerBlocks, userContentParts } = buildPromptInput(input);
|
|
@@ -16580,10 +16879,9 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
16580
16879
|
botConfig,
|
|
16581
16880
|
activeModelProfile
|
|
16582
16881
|
);
|
|
16583
|
-
const resumedReasoningLevel = existingSessionRecord?.reasoningLevel ? parseTurnReasoningLevel(existingSessionRecord.reasoningLevel) : void 0;
|
|
16584
16882
|
turnRoute = {
|
|
16585
16883
|
profile: activeModelProfile,
|
|
16586
|
-
reasoningLevel: activeProfileConfig.reasoningLevel ??
|
|
16884
|
+
reasoningLevel: activeProfileConfig.reasoningLevel ?? storedTurnRoute.reasoningLevel,
|
|
16587
16885
|
reason: `resumed_handoff:${storedTurnRoute.modelProfile}:${activeModelProfile}`
|
|
16588
16886
|
};
|
|
16589
16887
|
} else {
|
|
@@ -16793,7 +17091,6 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
16793
17091
|
state,
|
|
16794
17092
|
supportsImageInput: () => resolveGatewayModel(activeModelId).input.includes("image"),
|
|
16795
17093
|
surface,
|
|
16796
|
-
syncLoadedSkillNamesForResume,
|
|
16797
17094
|
toolCalls,
|
|
16798
17095
|
userInput
|
|
16799
17096
|
});
|
|
@@ -17134,6 +17431,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
17134
17431
|
runResume.setTurnStartMessageIndex(
|
|
17135
17432
|
existingSessionRecord.turnStartMessageIndex
|
|
17136
17433
|
);
|
|
17434
|
+
runResume.adoptCommittedBoundary([...agent.state.messages]);
|
|
17137
17435
|
} else if (promptHistoryMessages.length > 0) {
|
|
17138
17436
|
agent.state.messages = [...promptHistoryMessages];
|
|
17139
17437
|
}
|
|
@@ -17458,7 +17756,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
17458
17756
|
throw error.originalError;
|
|
17459
17757
|
}
|
|
17460
17758
|
const runError = error instanceof AssistantMessageDeliveryError ? error.originalError : error;
|
|
17461
|
-
if (runError instanceof AuthPausePersistenceError) {
|
|
17759
|
+
if (runError instanceof AuthPausePersistenceError || runError instanceof TurnSliceLimitExceededError) {
|
|
17462
17760
|
throw runError;
|
|
17463
17761
|
}
|
|
17464
17762
|
if (resume && runError instanceof AuthorizationPauseError) {
|
|
@@ -17572,8 +17870,8 @@ export {
|
|
|
17572
17870
|
deliverResourceEventSubscription,
|
|
17573
17871
|
sanitizeScheduledTaskPrincipal,
|
|
17574
17872
|
listThreadReplies,
|
|
17575
|
-
|
|
17576
|
-
|
|
17873
|
+
renderBlockText,
|
|
17874
|
+
renderAttachmentText,
|
|
17577
17875
|
latestReportedProgress,
|
|
17578
17876
|
executeCredentialedEgressRequest,
|
|
17579
17877
|
createContextCompactor,
|