@sentry/junior 0.11.1 → 0.12.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/app.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  logCapabilityCatalogLoadedOnce,
8
8
  parseSkillInvocation,
9
9
  stripFrontmatter
10
- } from "./chunk-WELSSJJU.js";
10
+ } from "./chunk-IH4T747D.js";
11
11
  import {
12
12
  SANDBOX_SKILLS_ROOT,
13
13
  SANDBOX_WORKSPACE_ROOT,
@@ -26,18 +26,22 @@ import {
26
26
  runNonInteractiveCommand,
27
27
  sandboxSkillDir,
28
28
  toOptionalTrimmed
29
- } from "./chunk-IRE2LOEJ.js";
29
+ } from "./chunk-SCG4PCEG.js";
30
30
  import {
31
31
  CredentialUnavailableError,
32
+ aboutPathCandidates,
32
33
  buildOAuthTokenRequest,
33
34
  createPluginBroker,
34
35
  createRequestContext,
36
+ discoverInstalledPluginPackageContent,
35
37
  extractGenAiUsageAttributes,
36
38
  getPluginDefinition,
37
39
  getPluginMcpProviders,
38
40
  getPluginOAuthConfig,
39
41
  getPluginProviders,
42
+ homeDir,
40
43
  isPluginProvider,
44
+ isRecord,
41
45
  logError,
42
46
  logException,
43
47
  logInfo,
@@ -46,21 +50,17 @@ import {
46
50
  resolveAuthTokenPlaceholder,
47
51
  resolveErrorReference,
48
52
  serializeGenAiAttribute,
53
+ setPluginPackages,
49
54
  setSpanAttributes,
50
55
  setSpanStatus,
51
56
  setTags,
57
+ soulPathCandidates,
58
+ toOptionalNumber,
52
59
  toOptionalString,
53
60
  withContext,
54
61
  withSpan
55
- } from "./chunk-ZYB3U7Q4.js";
62
+ } from "./chunk-Y2LVMCQ3.js";
56
63
  import "./chunk-Z3YD6NHK.js";
57
- import {
58
- aboutPathCandidates,
59
- discoverInstalledPluginPackageContent,
60
- homeDir,
61
- setPluginPackages,
62
- soulPathCandidates
63
- } from "./chunk-XH7TV4JS.js";
64
64
  import "./chunk-2KG3PWR4.js";
65
65
 
66
66
  // src/app.ts
@@ -106,24 +106,15 @@ function GET2() {
106
106
  import { Buffer as Buffer2 } from "buffer";
107
107
 
108
108
  // src/chat/state/conversation.ts
109
- function isRecord(value) {
110
- return Boolean(value) && typeof value === "object";
111
- }
112
- function toOptionalString2(value) {
113
- return typeof value === "string" && value.trim().length > 0 ? value : void 0;
114
- }
115
- function toOptionalNumber(value) {
116
- return typeof value === "number" && Number.isFinite(value) ? value : void 0;
117
- }
118
109
  function coerceRole(value) {
119
110
  return value === "assistant" || value === "system" || value === "user" ? value : "user";
120
111
  }
121
112
  function coerceAuthor(value) {
122
113
  if (!isRecord(value)) return void 0;
123
114
  const author = {
124
- fullName: toOptionalString2(value.fullName),
125
- userId: toOptionalString2(value.userId),
126
- userName: toOptionalString2(value.userName)
115
+ fullName: toOptionalString(value.fullName),
116
+ userId: toOptionalString(value.userId),
117
+ userName: toOptionalString(value.userName)
127
118
  };
128
119
  if (typeof value.isBot === "boolean") {
129
120
  author.isBot = value.isBot;
@@ -194,8 +185,8 @@ function coerceThreadConversationState(value) {
194
185
  const messages = [];
195
186
  for (const item of rawMessages) {
196
187
  if (!isRecord(item)) continue;
197
- const id = toOptionalString2(item.id);
198
- const text = toOptionalString2(item.text);
188
+ const id = toOptionalString(item.id);
189
+ const text = toOptionalString(item.text);
199
190
  const createdAtMs = toOptionalNumber(item.createdAtMs);
200
191
  if (!id || !text || !createdAtMs) continue;
201
192
  messages.push({
@@ -211,8 +202,8 @@ function coerceThreadConversationState(value) {
211
202
  const compactions = [];
212
203
  for (const item of rawCompactions) {
213
204
  if (!isRecord(item)) continue;
214
- const id = toOptionalString2(item.id);
215
- const summary = toOptionalString2(item.summary);
205
+ const id = toOptionalString(item.id);
206
+ const summary = toOptionalString(item.summary);
216
207
  const createdAtMs = toOptionalNumber(item.createdAtMs);
217
208
  if (!id || !summary || !createdAtMs) continue;
218
209
  const coveredMessageIds = Array.isArray(item.coveredMessageIds) ? item.coveredMessageIds.filter(
@@ -232,7 +223,7 @@ function coerceThreadConversationState(value) {
232
223
  };
233
224
  const rawProcessing = isRecord(rawConversation.processing) ? rawConversation.processing : {};
234
225
  const processing = {
235
- activeTurnId: toOptionalString2(rawProcessing.activeTurnId),
226
+ activeTurnId: toOptionalString(rawProcessing.activeTurnId),
236
227
  lastCompletedAtMs: toOptionalNumber(rawProcessing.lastCompletedAtMs)
237
228
  };
238
229
  const rawStats = isRecord(rawConversation.stats) ? rawConversation.stats : {};
@@ -248,7 +239,7 @@ function coerceThreadConversationState(value) {
248
239
  for (const [fileId, value2] of Object.entries(rawVisionByFileId)) {
249
240
  if (typeof fileId !== "string" || fileId.trim().length === 0) continue;
250
241
  if (!isRecord(value2)) continue;
251
- const summary = toOptionalString2(value2.summary);
242
+ const summary = toOptionalString(value2.summary);
252
243
  const analyzedAtMs = toOptionalNumber(value2.analyzedAtMs);
253
244
  if (!summary || !analyzedAtMs) continue;
254
245
  byFileId[fileId] = {
@@ -303,9 +294,6 @@ function sessionIndexKey(userId, provider) {
303
294
  function serverSessionKey(userId, provider) {
304
295
  return `${MCP_SERVER_SESSION_PREFIX}:${userId}:${provider}`;
305
296
  }
306
- function isRecord2(value) {
307
- return typeof value === "object" && value !== null;
308
- }
309
297
  function parseSessionIndex(value) {
310
298
  if (typeof value !== "string") {
311
299
  return [];
@@ -328,7 +316,7 @@ function parseMcpAuthSession(value) {
328
316
  }
329
317
  try {
330
318
  const parsed = JSON.parse(value);
331
- if (!isRecord2(parsed)) {
319
+ if (!isRecord(parsed)) {
332
320
  return void 0;
333
321
  }
334
322
  if (typeof parsed.authSessionId !== "string" || typeof parsed.provider !== "string" || typeof parsed.userId !== "string" || typeof parsed.conversationId !== "string" || typeof parsed.sessionId !== "string" || typeof parsed.userMessage !== "string" || typeof parsed.createdAtMs !== "number" || typeof parsed.updatedAtMs !== "number") {
@@ -346,8 +334,8 @@ function parseMcpAuthSession(value) {
346
334
  ...typeof parsed.channelId === "string" ? { channelId: parsed.channelId } : {},
347
335
  ...typeof parsed.threadTs === "string" ? { threadTs: parsed.threadTs } : {},
348
336
  ...typeof parsed.toolChannelId === "string" ? { toolChannelId: parsed.toolChannelId } : {},
349
- ...isRecord2(parsed.configuration) ? { configuration: parsed.configuration } : {},
350
- ...isRecord2(parsed.artifactState) ? { artifactState: parsed.artifactState } : {},
337
+ ...isRecord(parsed.configuration) ? { configuration: parsed.configuration } : {},
338
+ ...isRecord(parsed.artifactState) ? { artifactState: parsed.artifactState } : {},
351
339
  ...typeof parsed.authorizationUrl === "string" ? { authorizationUrl: parsed.authorizationUrl } : {},
352
340
  ...typeof parsed.codeVerifier === "string" ? { codeVerifier: parsed.codeVerifier } : {}
353
341
  };
@@ -361,7 +349,7 @@ function parseServerSession(value) {
361
349
  }
362
350
  try {
363
351
  const parsed = JSON.parse(value);
364
- if (!isRecord2(parsed) || typeof parsed.sessionId !== "string" || typeof parsed.updatedAtMs !== "number") {
352
+ if (!isRecord(parsed) || typeof parsed.sessionId !== "string" || typeof parsed.updatedAtMs !== "number") {
365
353
  return void 0;
366
354
  }
367
355
  return {
@@ -378,17 +366,17 @@ function parseStoredCredentials(value) {
378
366
  }
379
367
  try {
380
368
  const parsed = JSON.parse(value);
381
- if (!isRecord2(parsed)) {
369
+ if (!isRecord(parsed)) {
382
370
  return void 0;
383
371
  }
384
372
  return {
385
- ...isRecord2(parsed.clientInformation) ? {
373
+ ...isRecord(parsed.clientInformation) ? {
386
374
  clientInformation: parsed.clientInformation
387
375
  } : {},
388
- ...isRecord2(parsed.discoveryState) ? {
376
+ ...isRecord(parsed.discoveryState) ? {
389
377
  discoveryState: parsed.discoveryState
390
378
  } : {},
391
- ...isRecord2(parsed.tokens) ? { tokens: parsed.tokens } : {}
379
+ ...isRecord(parsed.tokens) ? { tokens: parsed.tokens } : {}
392
380
  };
393
381
  } catch {
394
382
  return void 0;
@@ -887,6 +875,204 @@ async function downloadPrivateSlackFile(url) {
887
875
  return Buffer.from(await response.arrayBuffer());
888
876
  }
889
877
 
878
+ // src/chat/respond-helpers.ts
879
+ var MAX_INLINE_ATTACHMENT_BASE64_CHARS = 12e4;
880
+ function getSessionIdentifiers(context) {
881
+ return {
882
+ conversationId: context.correlation?.conversationId ?? context.correlation?.threadId ?? context.correlation?.runId,
883
+ sessionId: context.correlation?.turnId
884
+ };
885
+ }
886
+ function isExecutionDeferralResponse(text) {
887
+ return /\b(want me to proceed|do you want me to proceed|shall i proceed|can i proceed|should i proceed|let me do that now|give me a moment|tag me again|fresh invocation)\b/i.test(
888
+ text
889
+ );
890
+ }
891
+ function isToolAccessDisclaimerResponse(text) {
892
+ return /\b(i (don't|do not) have access to (active )?tool|tool results came back empty|prior results .* empty|cannot access .*tool|need to (run|load) .*tool .* first)\b/i.test(
893
+ text
894
+ );
895
+ }
896
+ function isExecutionEscapeResponse(text) {
897
+ const trimmed = text.trim();
898
+ if (!trimmed) return false;
899
+ return isExecutionDeferralResponse(trimmed) || isToolAccessDisclaimerResponse(trimmed);
900
+ }
901
+ function parseJsonCandidate(text) {
902
+ const trimmed = text.trim();
903
+ if (!trimmed) return void 0;
904
+ try {
905
+ return JSON.parse(trimmed);
906
+ } catch {
907
+ const fenced = trimmed.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/i);
908
+ if (!fenced) return void 0;
909
+ try {
910
+ return JSON.parse(fenced[1]);
911
+ } catch {
912
+ return void 0;
913
+ }
914
+ }
915
+ }
916
+ function isToolPayloadShape(payload) {
917
+ if (!payload || typeof payload !== "object") return false;
918
+ const record = payload;
919
+ const type = typeof record.type === "string" ? record.type.toLowerCase() : "";
920
+ if (type.startsWith("tool-")) return true;
921
+ if (type === "tool_use" || type === "tool_call" || type === "tool_result" || type === "tool_error")
922
+ return true;
923
+ const hasToolName = typeof record.toolName === "string" || typeof record.name === "string";
924
+ const hasToolInput = Object.prototype.hasOwnProperty.call(record, "input") || Object.prototype.hasOwnProperty.call(record, "args");
925
+ if (hasToolName && hasToolInput) return true;
926
+ return false;
927
+ }
928
+ function isRawToolPayloadResponse(text) {
929
+ const parsed = parseJsonCandidate(text);
930
+ if (Array.isArray(parsed)) {
931
+ return parsed.some((entry) => isToolPayloadShape(entry));
932
+ }
933
+ if (isToolPayloadShape(parsed)) {
934
+ return true;
935
+ }
936
+ const compact = text.replace(/\s+/g, " ");
937
+ return /"type"\s*:\s*"tool[-_](use|call|result|error)"/i.test(compact);
938
+ }
939
+ function toObservablePromptPart(part) {
940
+ if (part.type === "text") {
941
+ return {
942
+ type: "text",
943
+ text: part.text
944
+ };
945
+ }
946
+ return {
947
+ type: "image",
948
+ mimeType: part.mimeType,
949
+ data: `[omitted:${part.data.length}]`
950
+ };
951
+ }
952
+ function summarizeMessageText(text) {
953
+ const normalized = text.trim().replace(/\s+/g, " ");
954
+ if (!normalized) {
955
+ return "[empty]";
956
+ }
957
+ return normalized.length > 1200 ? `${normalized.slice(0, 1200)}...` : normalized;
958
+ }
959
+ function buildUserTurnText(userInput, conversationContext) {
960
+ const trimmedContext = conversationContext?.trim();
961
+ if (!trimmedContext) {
962
+ return userInput;
963
+ }
964
+ return [
965
+ "<current-message>",
966
+ userInput,
967
+ "</current-message>",
968
+ "",
969
+ "<thread-conversation-context>",
970
+ "Use this context for continuity across prior thread turns.",
971
+ trimmedContext,
972
+ "</thread-conversation-context>"
973
+ ].join("\n");
974
+ }
975
+ function encodeNonImageAttachmentForPrompt(attachment) {
976
+ const base64 = attachment.data.toString("base64");
977
+ const wasTruncated = base64.length > MAX_INLINE_ATTACHMENT_BASE64_CHARS;
978
+ const encodedPayload = wasTruncated ? `${base64.slice(0, MAX_INLINE_ATTACHMENT_BASE64_CHARS)}...` : base64;
979
+ return [
980
+ "<attachment>",
981
+ `filename: ${attachment.filename ?? "unnamed"}`,
982
+ `media_type: ${attachment.mediaType}`,
983
+ "encoding: base64",
984
+ `truncated: ${wasTruncated ? "true" : "false"}`,
985
+ "<data_base64>",
986
+ encodedPayload,
987
+ "</data_base64>",
988
+ "</attachment>"
989
+ ].join("\n");
990
+ }
991
+ function buildExecutionFailureMessage(toolErrorCount) {
992
+ if (toolErrorCount > 0) {
993
+ return "I couldn't complete this because one or more required tools failed in this turn. I've logged the failure details.";
994
+ }
995
+ return "I couldn't complete this request in this turn due to an execution failure. I've logged the details for debugging.";
996
+ }
997
+ function isToolResultMessage(value) {
998
+ return typeof value === "object" && value !== null && value.role === "toolResult";
999
+ }
1000
+ function normalizeToolNameFromResult(result) {
1001
+ if (!result || typeof result !== "object") return void 0;
1002
+ const record = result;
1003
+ if (typeof record.toolName === "string" && record.toolName.length > 0) {
1004
+ return record.toolName;
1005
+ }
1006
+ if (typeof record.name === "string" && record.name.length > 0) {
1007
+ return record.name;
1008
+ }
1009
+ return void 0;
1010
+ }
1011
+ function isToolResultError(result) {
1012
+ if (!result || typeof result !== "object") return false;
1013
+ return Boolean(result.isError);
1014
+ }
1015
+ function isAssistantMessage(value) {
1016
+ return typeof value === "object" && value !== null && value.role === "assistant";
1017
+ }
1018
+ function getPiMessageRole(value) {
1019
+ if (!value || typeof value !== "object") {
1020
+ return void 0;
1021
+ }
1022
+ const role = value.role;
1023
+ return typeof role === "string" ? role : void 0;
1024
+ }
1025
+ function extractAssistantText(message) {
1026
+ const content = message.content ?? [];
1027
+ return content.filter(
1028
+ (part) => part.type === "text" && typeof part.text === "string"
1029
+ ).map((part) => part.text).join("\n");
1030
+ }
1031
+ function hasCompletedAssistantTurn(messages) {
1032
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
1033
+ const message = messages[index];
1034
+ if (!isAssistantMessage(message)) {
1035
+ continue;
1036
+ }
1037
+ const stopReason = message.stopReason;
1038
+ return typeof stopReason === "string" && stopReason !== "error";
1039
+ }
1040
+ return false;
1041
+ }
1042
+ function upsertActiveSkill(activeSkills, next) {
1043
+ const existing = activeSkills.find((skill) => skill.name === next.name);
1044
+ if (existing) {
1045
+ existing.body = next.body;
1046
+ existing.description = next.description;
1047
+ existing.skillPath = next.skillPath;
1048
+ existing.allowedTools = next.allowedTools;
1049
+ existing.requiresCapabilities = next.requiresCapabilities;
1050
+ existing.usesConfig = next.usesConfig;
1051
+ existing.pluginProvider = next.pluginProvider;
1052
+ return;
1053
+ }
1054
+ activeSkills.push(next);
1055
+ }
1056
+ function collectRelevantConfigurationKeys(activeSkills, explicitSkill) {
1057
+ const keys = /* @__PURE__ */ new Set();
1058
+ for (const skill of [
1059
+ ...activeSkills,
1060
+ ...explicitSkill ? [explicitSkill] : []
1061
+ ]) {
1062
+ for (const key of skill.usesConfig ?? []) {
1063
+ keys.add(key);
1064
+ }
1065
+ }
1066
+ return [...keys].sort((a, b) => a.localeCompare(b));
1067
+ }
1068
+ function trimTrailingAssistantMessages(messages) {
1069
+ let end = messages.length;
1070
+ while (end > 0 && getPiMessageRole(messages[end - 1]) === "assistant") {
1071
+ end -= 1;
1072
+ }
1073
+ return end === messages.length ? [...messages] : messages.slice(0, end);
1074
+ }
1075
+
890
1076
  // src/chat/oauth-flow.ts
891
1077
  var OAUTH_STATE_TTL_MS = 10 * 60 * 1e3;
892
1078
  function formatProviderLabel(provider) {
@@ -1037,36 +1223,6 @@ async function startOAuthFlow(provider, input) {
1037
1223
  })
1038
1224
  };
1039
1225
  }
1040
- function parseJsonCandidate(text) {
1041
- const trimmed = text.trim();
1042
- if (!trimmed) return void 0;
1043
- try {
1044
- return JSON.parse(trimmed);
1045
- } catch {
1046
- const fenced = trimmed.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/i);
1047
- if (!fenced) return void 0;
1048
- try {
1049
- return JSON.parse(fenced[1]);
1050
- } catch {
1051
- return void 0;
1052
- }
1053
- }
1054
- }
1055
- function normalizeToolNameFromResult(result) {
1056
- if (!result || typeof result !== "object") return void 0;
1057
- const record = result;
1058
- if (typeof record.toolName === "string" && record.toolName.length > 0) {
1059
- return record.toolName;
1060
- }
1061
- if (typeof record.name === "string" && record.name.length > 0) {
1062
- return record.name;
1063
- }
1064
- return void 0;
1065
- }
1066
- function isToolResultError(result) {
1067
- if (!result || typeof result !== "object") return false;
1068
- return Boolean(result.isError);
1069
- }
1070
1226
  function extractOAuthStartedPayload(value) {
1071
1227
  if (typeof value === "string") {
1072
1228
  const parsed = parseJsonCandidate(value);
@@ -1441,12 +1597,6 @@ function validateConfigValue(value) {
1441
1597
  }
1442
1598
 
1443
1599
  // src/chat/configuration/service.ts
1444
- function isRecord3(value) {
1445
- return Boolean(value) && typeof value === "object";
1446
- }
1447
- function toOptionalString3(value) {
1448
- return typeof value === "string" && value.trim().length > 0 ? value : void 0;
1449
- }
1450
1600
  function defaultState() {
1451
1601
  return {
1452
1602
  schemaVersion: 1,
@@ -1454,17 +1604,17 @@ function defaultState() {
1454
1604
  };
1455
1605
  }
1456
1606
  function sanitizeEntry(value) {
1457
- if (!isRecord3(value)) {
1607
+ if (!isRecord(value)) {
1458
1608
  return void 0;
1459
1609
  }
1460
- const key = toOptionalString3(value.key);
1610
+ const key = toOptionalString(value.key);
1461
1611
  if (!key) {
1462
1612
  return void 0;
1463
1613
  }
1464
1614
  if (validateConfigKey(key)) {
1465
1615
  return void 0;
1466
1616
  }
1467
- const updatedAt = toOptionalString3(value.updatedAt);
1617
+ const updatedAt = toOptionalString(value.updatedAt);
1468
1618
  if (!updatedAt) {
1469
1619
  return void 0;
1470
1620
  }
@@ -1477,17 +1627,17 @@ function sanitizeEntry(value) {
1477
1627
  value: value.value,
1478
1628
  scope,
1479
1629
  updatedAt,
1480
- updatedBy: toOptionalString3(value.updatedBy),
1481
- source: toOptionalString3(value.source),
1482
- expiresAt: toOptionalString3(value.expiresAt)
1630
+ updatedBy: toOptionalString(value.updatedBy),
1631
+ source: toOptionalString(value.source),
1632
+ expiresAt: toOptionalString(value.expiresAt)
1483
1633
  };
1484
1634
  }
1485
1635
  function coerceState(raw) {
1486
- if (!isRecord3(raw)) {
1636
+ if (!isRecord(raw)) {
1487
1637
  return defaultState();
1488
1638
  }
1489
- const rawConfig = isRecord3(raw.configuration) ? raw.configuration : {};
1490
- const rawEntries = isRecord3(rawConfig.entries) ? rawConfig.entries : {};
1639
+ const rawConfig = isRecord(raw.configuration) ? raw.configuration : {};
1640
+ const rawEntries = isRecord(rawConfig.entries) ? rawConfig.entries : {};
1491
1641
  const entries = {};
1492
1642
  for (const [key, value] of Object.entries(rawEntries)) {
1493
1643
  const entry = sanitizeEntry(value);
@@ -1533,9 +1683,9 @@ function createChannelConfigurationService(storage) {
1533
1683
  value: input.value,
1534
1684
  scope: "conversation",
1535
1685
  updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
1536
- updatedBy: toOptionalString3(input.updatedBy),
1537
- source: toOptionalString3(input.source),
1538
- expiresAt: toOptionalString3(input.expiresAt)
1686
+ updatedBy: toOptionalString(input.updatedBy),
1687
+ source: toOptionalString(input.source),
1688
+ expiresAt: toOptionalString(input.expiresAt)
1539
1689
  };
1540
1690
  state.entries[normalizedKey] = nextEntry;
1541
1691
  await saveState(state);
@@ -7825,16 +7975,13 @@ var AGENT_TURN_SESSION_TTL_MS = 24 * 60 * 60 * 1e3;
7825
7975
  function agentTurnSessionKey(conversationId, sessionId) {
7826
7976
  return `${AGENT_TURN_SESSION_PREFIX}:${conversationId}:${sessionId}`;
7827
7977
  }
7828
- function isRecord4(value) {
7829
- return typeof value === "object" && value !== null;
7830
- }
7831
7978
  function parseAgentTurnSessionCheckpoint(value) {
7832
7979
  if (typeof value !== "string") {
7833
7980
  return void 0;
7834
7981
  }
7835
7982
  try {
7836
7983
  const parsed = JSON.parse(value);
7837
- if (!isRecord4(parsed)) {
7984
+ if (!isRecord(parsed)) {
7838
7985
  return void 0;
7839
7986
  }
7840
7987
  const status = parsed.state;
@@ -8458,14 +8605,7 @@ Note: No file was attached in this turn. I need to attach the file before claimi
8458
8605
  }
8459
8606
 
8460
8607
  // src/chat/respond.ts
8461
- var MAX_INLINE_ATTACHMENT_BASE64_CHARS = 12e4;
8462
8608
  var startupDiscoveryLogged = false;
8463
- function getSessionIdentifiers(context) {
8464
- return {
8465
- conversationId: context.correlation?.conversationId ?? context.correlation?.threadId ?? context.correlation?.runId,
8466
- sessionId: context.correlation?.turnId
8467
- };
8468
- }
8469
8609
  var McpAuthorizationPauseError = class extends Error {
8470
8610
  provider;
8471
8611
  constructor(provider) {
@@ -8489,195 +8629,6 @@ async function runAgentContinuation(agent) {
8489
8629
  }
8490
8630
  return await resumable.continue();
8491
8631
  }
8492
- function trimTrailingAssistantMessages(messages) {
8493
- let end = messages.length;
8494
- while (end > 0 && getPiMessageRole(messages[end - 1]) === "assistant") {
8495
- end -= 1;
8496
- }
8497
- return end === messages.length ? [...messages] : messages.slice(0, end);
8498
- }
8499
- function isExecutionDeferralResponse(text) {
8500
- return /\b(want me to proceed|do you want me to proceed|shall i proceed|can i proceed|should i proceed|let me do that now|give me a moment|tag me again|fresh invocation)\b/i.test(
8501
- text
8502
- );
8503
- }
8504
- function isToolAccessDisclaimerResponse(text) {
8505
- return /\b(i (don't|do not) have access to (active )?tool|tool results came back empty|prior results .* empty|cannot access .*tool|need to (run|load) .*tool .* first)\b/i.test(
8506
- text
8507
- );
8508
- }
8509
- function isExecutionEscapeResponse(text) {
8510
- const trimmed = text.trim();
8511
- if (!trimmed) return false;
8512
- return isExecutionDeferralResponse(trimmed) || isToolAccessDisclaimerResponse(trimmed);
8513
- }
8514
- function parseJsonCandidate3(text) {
8515
- const trimmed = text.trim();
8516
- if (!trimmed) return void 0;
8517
- try {
8518
- return JSON.parse(trimmed);
8519
- } catch {
8520
- const fenced = trimmed.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/i);
8521
- if (!fenced) return void 0;
8522
- try {
8523
- return JSON.parse(fenced[1]);
8524
- } catch {
8525
- return void 0;
8526
- }
8527
- }
8528
- }
8529
- function isToolPayloadShape(payload) {
8530
- if (!payload || typeof payload !== "object") return false;
8531
- const record = payload;
8532
- const type = typeof record.type === "string" ? record.type.toLowerCase() : "";
8533
- if (type.startsWith("tool-")) return true;
8534
- if (type === "tool_use" || type === "tool_call" || type === "tool_result" || type === "tool_error")
8535
- return true;
8536
- const hasToolName = typeof record.toolName === "string" || typeof record.name === "string";
8537
- const hasToolInput = Object.prototype.hasOwnProperty.call(record, "input") || Object.prototype.hasOwnProperty.call(record, "args");
8538
- if (hasToolName && hasToolInput) return true;
8539
- return false;
8540
- }
8541
- function isRawToolPayloadResponse(text) {
8542
- const parsed = parseJsonCandidate3(text);
8543
- if (Array.isArray(parsed)) {
8544
- return parsed.some((entry) => isToolPayloadShape(entry));
8545
- }
8546
- if (isToolPayloadShape(parsed)) {
8547
- return true;
8548
- }
8549
- const compact = text.replace(/\s+/g, " ");
8550
- return /"type"\s*:\s*"tool[-_](use|call|result|error)"/i.test(compact);
8551
- }
8552
- function toObservablePromptPart(part) {
8553
- if (part.type === "text") {
8554
- return {
8555
- type: "text",
8556
- text: part.text
8557
- };
8558
- }
8559
- return {
8560
- type: "image",
8561
- mimeType: part.mimeType,
8562
- data: `[omitted:${part.data.length}]`
8563
- };
8564
- }
8565
- function summarizeMessageText(text) {
8566
- const normalized = text.trim().replace(/\s+/g, " ");
8567
- if (!normalized) {
8568
- return "[empty]";
8569
- }
8570
- return normalized.length > 1200 ? `${normalized.slice(0, 1200)}...` : normalized;
8571
- }
8572
- function buildUserTurnText(userInput, conversationContext) {
8573
- const trimmedContext = conversationContext?.trim();
8574
- if (!trimmedContext) {
8575
- return userInput;
8576
- }
8577
- return [
8578
- "<current-message>",
8579
- userInput,
8580
- "</current-message>",
8581
- "",
8582
- "<thread-conversation-context>",
8583
- "Use this context for continuity across prior thread turns.",
8584
- trimmedContext,
8585
- "</thread-conversation-context>"
8586
- ].join("\n");
8587
- }
8588
- function encodeNonImageAttachmentForPrompt(attachment) {
8589
- const base64 = attachment.data.toString("base64");
8590
- const wasTruncated = base64.length > MAX_INLINE_ATTACHMENT_BASE64_CHARS;
8591
- const encodedPayload = wasTruncated ? `${base64.slice(0, MAX_INLINE_ATTACHMENT_BASE64_CHARS)}...` : base64;
8592
- return [
8593
- "<attachment>",
8594
- `filename: ${attachment.filename ?? "unnamed"}`,
8595
- `media_type: ${attachment.mediaType}`,
8596
- "encoding: base64",
8597
- `truncated: ${wasTruncated ? "true" : "false"}`,
8598
- "<data_base64>",
8599
- encodedPayload,
8600
- "</data_base64>",
8601
- "</attachment>"
8602
- ].join("\n");
8603
- }
8604
- function buildExecutionFailureMessage(toolErrorCount) {
8605
- if (toolErrorCount > 0) {
8606
- return "I couldn\u2019t complete this because one or more required tools failed in this turn. I\u2019ve logged the failure details.";
8607
- }
8608
- return "I couldn\u2019t complete this request in this turn due to an execution failure. I\u2019ve logged the details for debugging.";
8609
- }
8610
- function isToolResultMessage(value) {
8611
- return typeof value === "object" && value !== null && value.role === "toolResult";
8612
- }
8613
- function normalizeToolNameFromResult2(result) {
8614
- if (!result || typeof result !== "object") return void 0;
8615
- const record = result;
8616
- if (typeof record.toolName === "string" && record.toolName.length > 0) {
8617
- return record.toolName;
8618
- }
8619
- if (typeof record.name === "string" && record.name.length > 0) {
8620
- return record.name;
8621
- }
8622
- return void 0;
8623
- }
8624
- function isToolResultError2(result) {
8625
- if (!result || typeof result !== "object") return false;
8626
- return Boolean(result.isError);
8627
- }
8628
- function isAssistantMessage(value) {
8629
- return typeof value === "object" && value !== null && value.role === "assistant";
8630
- }
8631
- function getPiMessageRole(value) {
8632
- if (!value || typeof value !== "object") {
8633
- return void 0;
8634
- }
8635
- const role = value.role;
8636
- return typeof role === "string" ? role : void 0;
8637
- }
8638
- function extractAssistantText(message) {
8639
- const content = message.content ?? [];
8640
- return content.filter(
8641
- (part) => part.type === "text" && typeof part.text === "string"
8642
- ).map((part) => part.text).join("\n");
8643
- }
8644
- function hasCompletedAssistantTurn(messages) {
8645
- for (let index = messages.length - 1; index >= 0; index -= 1) {
8646
- const message = messages[index];
8647
- if (!isAssistantMessage(message)) {
8648
- continue;
8649
- }
8650
- const stopReason = message.stopReason;
8651
- return typeof stopReason === "string" && stopReason !== "error";
8652
- }
8653
- return false;
8654
- }
8655
- function upsertActiveSkill(activeSkills, next) {
8656
- const existing = activeSkills.find((skill) => skill.name === next.name);
8657
- if (existing) {
8658
- existing.body = next.body;
8659
- existing.description = next.description;
8660
- existing.skillPath = next.skillPath;
8661
- existing.allowedTools = next.allowedTools;
8662
- existing.requiresCapabilities = next.requiresCapabilities;
8663
- existing.usesConfig = next.usesConfig;
8664
- existing.pluginProvider = next.pluginProvider;
8665
- return;
8666
- }
8667
- activeSkills.push(next);
8668
- }
8669
- function collectRelevantConfigurationKeys(activeSkills, explicitSkill) {
8670
- const keys = /* @__PURE__ */ new Set();
8671
- for (const skill of [
8672
- ...activeSkills,
8673
- ...explicitSkill ? [explicitSkill] : []
8674
- ]) {
8675
- for (const key of skill.usesConfig ?? []) {
8676
- keys.add(key);
8677
- }
8678
- }
8679
- return [...keys].sort((a, b) => a.localeCompare(b));
8680
- }
8681
8632
  async function generateAssistantReply(messageText, context = {}) {
8682
8633
  let timeoutResumeConversationId;
8683
8634
  let timeoutResumeSessionId;
@@ -9175,7 +9126,7 @@ async function generateAssistantReply(messageText, context = {}) {
9175
9126
  ).length;
9176
9127
  const explicitChannelPostIntent = isExplicitChannelPostIntent(userInput);
9177
9128
  const successfulToolNames = new Set(
9178
- toolResults.filter((result) => !isToolResultError2(result)).map((result) => normalizeToolNameFromResult2(result)).filter((value) => Boolean(value))
9129
+ toolResults.filter((result) => !isToolResultError(result)).map((result) => normalizeToolNameFromResult(result)).filter((value) => Boolean(value))
9179
9130
  );
9180
9131
  const channelPostPerformed = successfulToolNames.has(
9181
9132
  "slackChannelPostMessage"
@@ -10470,11 +10421,12 @@ async function decideSubscribedThreadReply(args) {
10470
10421
  }
10471
10422
 
10472
10423
  // src/chat/slack/context.ts
10473
- function toOptionalString4(value) {
10474
- return typeof value === "string" && value.trim() ? value.trim() : void 0;
10424
+ function toTrimmedSlackString(value) {
10425
+ const normalized = toOptionalString(value);
10426
+ return normalized?.trim() || void 0;
10475
10427
  }
10476
10428
  function parseSlackThreadId(threadId) {
10477
- const normalizedThreadId = toOptionalString4(threadId);
10429
+ const normalizedThreadId = toTrimmedSlackString(threadId);
10478
10430
  if (!normalizedThreadId) {
10479
10431
  return void 0;
10480
10432
  }
@@ -10482,8 +10434,8 @@ function parseSlackThreadId(threadId) {
10482
10434
  if (parts.length !== 3 || parts[0] !== "slack") {
10483
10435
  return void 0;
10484
10436
  }
10485
- const channelId = toOptionalString4(parts[1]);
10486
- const threadTs = toOptionalString4(parts[2]);
10437
+ const channelId = toTrimmedSlackString(parts[1]);
10438
+ const threadTs = toTrimmedSlackString(parts[2]);
10487
10439
  if (!channelId || !threadTs) {
10488
10440
  return void 0;
10489
10441
  }
@@ -10493,7 +10445,7 @@ function resolveSlackChannelIdFromThreadId(threadId) {
10493
10445
  return parseSlackThreadId(threadId)?.channelId;
10494
10446
  }
10495
10447
  function resolveSlackChannelIdFromMessage(message) {
10496
- const messageChannelId = toOptionalString4(
10448
+ const messageChannelId = toTrimmedSlackString(
10497
10449
  message.channelId
10498
10450
  );
10499
10451
  if (messageChannelId) {
@@ -10501,12 +10453,14 @@ function resolveSlackChannelIdFromMessage(message) {
10501
10453
  }
10502
10454
  const raw = message.raw;
10503
10455
  if (raw && typeof raw === "object") {
10504
- const rawChannel = toOptionalString4(raw.channel);
10456
+ const rawChannel = toTrimmedSlackString(
10457
+ raw.channel
10458
+ );
10505
10459
  if (rawChannel) {
10506
10460
  return rawChannel;
10507
10461
  }
10508
10462
  }
10509
- const threadId = toOptionalString4(
10463
+ const threadId = toTrimmedSlackString(
10510
10464
  message.threadId
10511
10465
  );
10512
10466
  return resolveSlackChannelIdFromThreadId(threadId);
@@ -10573,26 +10527,6 @@ function getSlackApiErrorCode(error) {
10573
10527
  }
10574
10528
  return void 0;
10575
10529
  }
10576
- function getSlackHeaderString(headers, name) {
10577
- if (!headers || typeof headers !== "object") {
10578
- return void 0;
10579
- }
10580
- const normalizedName = name.toLowerCase();
10581
- const record = headers;
10582
- for (const [key, value] of Object.entries(record)) {
10583
- if (key.toLowerCase() !== normalizedName) {
10584
- continue;
10585
- }
10586
- if (typeof value === "string") {
10587
- return value;
10588
- }
10589
- if (Array.isArray(value)) {
10590
- const first = value.find((entry) => typeof entry === "string");
10591
- return typeof first === "string" ? first : void 0;
10592
- }
10593
- }
10594
- return void 0;
10595
- }
10596
10530
  function getSlackErrorObservabilityAttributes(error) {
10597
10531
  if (!error || typeof error !== "object") {
10598
10532
  return {};
@@ -10605,7 +10539,7 @@ function getSlackErrorObservabilityAttributes(error) {
10605
10539
  if (typeof candidate.data?.error === "string" && candidate.data.error.trim().length > 0) {
10606
10540
  attributes["app.slack.api_error"] = candidate.data.error;
10607
10541
  }
10608
- const requestId = getSlackHeaderString(candidate.headers, "x-slack-req-id");
10542
+ const requestId = getHeaderString(candidate.headers, "x-slack-req-id");
10609
10543
  if (requestId) {
10610
10544
  attributes["app.slack.request_id"] = requestId;
10611
10545
  }