@sentry/junior 0.67.2 → 0.68.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
|
@@ -47,7 +47,7 @@ import {
|
|
|
47
47
|
validateAgentPlugins,
|
|
48
48
|
verifySlackDirectCredentialSubject,
|
|
49
49
|
withSlackRetries
|
|
50
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-UQQSW7QB.js";
|
|
51
51
|
import {
|
|
52
52
|
discoverSkills,
|
|
53
53
|
findSkillByName,
|
|
@@ -12762,51 +12762,6 @@ function escapeSlackMrkdwn(text) {
|
|
|
12762
12762
|
function escapeSlackLinkUrl(url) {
|
|
12763
12763
|
return url.replaceAll("&", "&").replaceAll("<", "%3C").replaceAll(">", "%3E");
|
|
12764
12764
|
}
|
|
12765
|
-
function formatSlackTokenCount(value) {
|
|
12766
|
-
if (value >= 1e6) {
|
|
12767
|
-
const millions = value / 1e6;
|
|
12768
|
-
return `${parseFloat(millions.toFixed(2))}m`;
|
|
12769
|
-
}
|
|
12770
|
-
if (value >= 1e3) {
|
|
12771
|
-
const thousands = value / 1e3;
|
|
12772
|
-
return `${parseFloat(thousands.toFixed(1))}k`;
|
|
12773
|
-
}
|
|
12774
|
-
return `${value}`;
|
|
12775
|
-
}
|
|
12776
|
-
function formatSlackDuration(durationMs) {
|
|
12777
|
-
if (durationMs < 1e3) {
|
|
12778
|
-
return `${durationMs}ms`;
|
|
12779
|
-
}
|
|
12780
|
-
const totalSeconds = Math.round(durationMs / 1e3);
|
|
12781
|
-
if (totalSeconds < 10) {
|
|
12782
|
-
const precise = durationMs / 1e3;
|
|
12783
|
-
return `${precise.toFixed(1).replace(/\.0$/, "")}s`;
|
|
12784
|
-
}
|
|
12785
|
-
if (totalSeconds < 60) {
|
|
12786
|
-
return `${totalSeconds}s`;
|
|
12787
|
-
}
|
|
12788
|
-
const minutes = Math.floor(totalSeconds / 60);
|
|
12789
|
-
const seconds = totalSeconds % 60;
|
|
12790
|
-
if (seconds === 0) {
|
|
12791
|
-
return `${minutes}m`;
|
|
12792
|
-
}
|
|
12793
|
-
return `${minutes}m${seconds}s`;
|
|
12794
|
-
}
|
|
12795
|
-
function resolveTotalTokens(usage) {
|
|
12796
|
-
if (!usage) {
|
|
12797
|
-
return void 0;
|
|
12798
|
-
}
|
|
12799
|
-
const components = [
|
|
12800
|
-
usage.inputTokens,
|
|
12801
|
-
usage.outputTokens,
|
|
12802
|
-
usage.cachedInputTokens,
|
|
12803
|
-
usage.cacheCreationTokens
|
|
12804
|
-
].filter((value) => value !== void 0);
|
|
12805
|
-
if (components.length > 0) {
|
|
12806
|
-
return components.reduce((sum, value) => sum + value, 0);
|
|
12807
|
-
}
|
|
12808
|
-
return usage.totalTokens;
|
|
12809
|
-
}
|
|
12810
12765
|
function buildSlackReplyFooter(args) {
|
|
12811
12766
|
const items = [];
|
|
12812
12767
|
const conversationId = args.conversationId?.trim();
|
|
@@ -12821,26 +12776,6 @@ function buildSlackReplyFooter(args) {
|
|
|
12821
12776
|
}
|
|
12822
12777
|
items.push(idItem);
|
|
12823
12778
|
}
|
|
12824
|
-
const totalTokens = resolveTotalTokens(args.usage);
|
|
12825
|
-
if (totalTokens !== void 0) {
|
|
12826
|
-
items.push({
|
|
12827
|
-
label: "Tokens",
|
|
12828
|
-
value: formatSlackTokenCount(totalTokens)
|
|
12829
|
-
});
|
|
12830
|
-
}
|
|
12831
|
-
if (typeof args.durationMs === "number" && Number.isFinite(args.durationMs)) {
|
|
12832
|
-
const durationMs = Math.max(0, Math.floor(args.durationMs));
|
|
12833
|
-
items.push({
|
|
12834
|
-
label: "Time",
|
|
12835
|
-
value: formatSlackDuration(durationMs)
|
|
12836
|
-
});
|
|
12837
|
-
}
|
|
12838
|
-
if (args.thinkingLevel) {
|
|
12839
|
-
items.push({
|
|
12840
|
-
label: "Thinking",
|
|
12841
|
-
value: args.thinkingLevel
|
|
12842
|
-
});
|
|
12843
|
-
}
|
|
12844
12779
|
return items.length > 0 ? { items } : void 0;
|
|
12845
12780
|
}
|
|
12846
12781
|
function buildSlackReplyBlocks(text, footer) {
|
|
@@ -13585,10 +13520,7 @@ async function runAgentDispatchSlice(callback, deps = {}) {
|
|
|
13585
13520
|
channelId: dispatch.destination.channelId,
|
|
13586
13521
|
posts: planSlackReplyPosts({ reply: deliveryReply }),
|
|
13587
13522
|
footer: buildSlackReplyFooter({
|
|
13588
|
-
conversationId
|
|
13589
|
-
durationMs: deliveryReply.diagnostics.durationMs,
|
|
13590
|
-
thinkingLevel: deliveryReply.diagnostics.thinkingLevel,
|
|
13591
|
-
usage: deliveryReply.diagnostics.usage
|
|
13523
|
+
conversationId
|
|
13592
13524
|
}),
|
|
13593
13525
|
fileUploadFailureMode: "strict"
|
|
13594
13526
|
});
|
|
@@ -15821,10 +15753,6 @@ async function resumeSlackTurn(args) {
|
|
|
15821
15753
|
status.start();
|
|
15822
15754
|
const generateReply = runArgs.generateReply ?? generateAssistantReply;
|
|
15823
15755
|
const replyContext = createResumeReplyContext(runArgs, status);
|
|
15824
|
-
const priorSessionRecord = replyContext.correlation?.conversationId && replyContext.correlation?.turnId ? await getAgentTurnSessionRecord(
|
|
15825
|
-
replyContext.correlation.conversationId,
|
|
15826
|
-
replyContext.correlation.turnId
|
|
15827
|
-
) : void 0;
|
|
15828
15756
|
const replyPromise = generateReply(runArgs.messageText, replyContext);
|
|
15829
15757
|
const replyTimeoutMs = resolveReplyTimeoutMs(runArgs.replyTimeoutMs);
|
|
15830
15758
|
let reply = typeof replyTimeoutMs === "number" ? await Promise.race([
|
|
@@ -15847,13 +15775,7 @@ async function resumeSlackTurn(args) {
|
|
|
15847
15775
|
});
|
|
15848
15776
|
await status.stop();
|
|
15849
15777
|
const footer = buildSlackReplyFooter({
|
|
15850
|
-
conversationId: runArgs.replyContext?.correlation?.conversationId ?? lockKey
|
|
15851
|
-
durationMs: typeof priorSessionRecord?.cumulativeDurationMs === "number" || typeof reply.diagnostics.durationMs === "number" ? (priorSessionRecord?.cumulativeDurationMs ?? 0) + (reply.diagnostics.durationMs ?? 0) : void 0,
|
|
15852
|
-
thinkingLevel: reply.diagnostics.thinkingLevel,
|
|
15853
|
-
usage: addAgentTurnUsage(
|
|
15854
|
-
priorSessionRecord?.cumulativeUsage,
|
|
15855
|
-
reply.diagnostics.usage
|
|
15856
|
-
) ?? reply.diagnostics.usage
|
|
15778
|
+
conversationId: runArgs.replyContext?.correlation?.conversationId ?? lockKey
|
|
15857
15779
|
});
|
|
15858
15780
|
await postSlackApiReplyPosts({
|
|
15859
15781
|
channelId: runArgs.channelId,
|
|
@@ -20416,10 +20338,7 @@ function createReplyToThread(deps) {
|
|
|
20416
20338
|
);
|
|
20417
20339
|
const plannedPosts = planSlackReplyPosts({ reply });
|
|
20418
20340
|
const replyFooter = buildSlackReplyFooter({
|
|
20419
|
-
conversationId
|
|
20420
|
-
durationMs: reply.diagnostics.durationMs,
|
|
20421
|
-
thinkingLevel: reply.diagnostics.thinkingLevel,
|
|
20422
|
-
usage: reply.diagnostics.usage
|
|
20341
|
+
conversationId
|
|
20423
20342
|
});
|
|
20424
20343
|
const shouldUseSlackFooter = Boolean(replyFooter) && Boolean(channelId && threadTs) && thread.adapter?.name === "slack";
|
|
20425
20344
|
if (plannedPosts.length > 0) {
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import type { TurnThinkingSelection } from "@/chat/services/turn-thinking-level";
|
|
2
|
-
import type { AgentTurnUsage } from "@/chat/usage";
|
|
3
1
|
interface SlackMrkdwnTextObject {
|
|
4
2
|
text: string;
|
|
5
3
|
type: "mrkdwn";
|
|
@@ -27,15 +25,12 @@ export interface SlackReplyFooter {
|
|
|
27
25
|
items: SlackReplyFooterItem[];
|
|
28
26
|
}
|
|
29
27
|
/**
|
|
30
|
-
* Build
|
|
28
|
+
* Build the compact conversation footer for the finalized Slack reply.
|
|
31
29
|
*
|
|
32
|
-
*
|
|
30
|
+
* Detailed turn metrics stay in the dashboard instead of Slack-visible copy.
|
|
33
31
|
*/
|
|
34
32
|
export declare function buildSlackReplyFooter(args: {
|
|
35
33
|
conversationId?: string;
|
|
36
|
-
durationMs?: number;
|
|
37
|
-
thinkingLevel?: TurnThinkingSelection["thinkingLevel"];
|
|
38
|
-
usage?: AgentTurnUsage;
|
|
39
34
|
}): SlackReplyFooter | undefined;
|
|
40
35
|
/** Build Slack blocks for a reply chunk using the Slack-flavored markdown block for the body. */
|
|
41
36
|
export declare function buildSlackReplyBlocks(text: string, footer: SlackReplyFooter | undefined): SlackMessageBlock[] | undefined;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/** Insert blank lines between content blocks so Slack renders them with visual separation. */
|
|
2
2
|
export declare function ensureBlockSpacing(text: string): string;
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Normalize model-authored Slack markdown for delivery via `markdown_text`
|
|
5
|
+
* or `{ type: "markdown" }` blocks.
|
|
5
6
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Pre-wraps bare URLs as Slack explicit links to prevent Slack's auto-linker
|
|
8
|
+
* from consuming adjacent formatting markers. Slack reply delivery owns
|
|
9
|
+
* chunking and continuation markers separately.
|
|
9
10
|
*/
|
|
10
|
-
export declare function
|
|
11
|
+
export declare function normalizeSlackReplyMarkdown(text: string): string;
|
|
11
12
|
/** Normalize assistant status text before handing it to Slack. */
|
|
12
13
|
export declare function normalizeSlackStatusText(text: string): string;
|
|
@@ -1095,6 +1095,145 @@ function truncateStatusText(text) {
|
|
|
1095
1095
|
}
|
|
1096
1096
|
|
|
1097
1097
|
// src/chat/slack/mrkdwn.ts
|
|
1098
|
+
function readInlineCodeSpan(line, start) {
|
|
1099
|
+
if (line[start] !== "`") {
|
|
1100
|
+
return void 0;
|
|
1101
|
+
}
|
|
1102
|
+
let n = 1;
|
|
1103
|
+
while (line[start + n] === "`") {
|
|
1104
|
+
n++;
|
|
1105
|
+
}
|
|
1106
|
+
const marker = "`".repeat(n);
|
|
1107
|
+
let search = start + n;
|
|
1108
|
+
while (search < line.length) {
|
|
1109
|
+
const close = line.indexOf(marker, search);
|
|
1110
|
+
if (close === -1) {
|
|
1111
|
+
return void 0;
|
|
1112
|
+
}
|
|
1113
|
+
const after = close + n;
|
|
1114
|
+
if (line[after] !== "`") {
|
|
1115
|
+
return { text: line.slice(start, after), end: after };
|
|
1116
|
+
}
|
|
1117
|
+
search = after + 1;
|
|
1118
|
+
}
|
|
1119
|
+
return void 0;
|
|
1120
|
+
}
|
|
1121
|
+
function readExistingSlackAngleToken(line, start) {
|
|
1122
|
+
if (line[start] !== "<") {
|
|
1123
|
+
return void 0;
|
|
1124
|
+
}
|
|
1125
|
+
const close = line.indexOf(">", start + 1);
|
|
1126
|
+
if (close === -1) {
|
|
1127
|
+
return void 0;
|
|
1128
|
+
}
|
|
1129
|
+
const body = line.slice(start + 1, close);
|
|
1130
|
+
if (/^(?:https?:\/\/|@|#|!)/.test(body)) {
|
|
1131
|
+
return { text: line.slice(start, close + 1), end: close + 1 };
|
|
1132
|
+
}
|
|
1133
|
+
return void 0;
|
|
1134
|
+
}
|
|
1135
|
+
function readMarkdownLink(line, start) {
|
|
1136
|
+
if (line[start] !== "[") {
|
|
1137
|
+
return void 0;
|
|
1138
|
+
}
|
|
1139
|
+
const labelEnd = line.indexOf("](", start + 1);
|
|
1140
|
+
if (labelEnd === -1) {
|
|
1141
|
+
return void 0;
|
|
1142
|
+
}
|
|
1143
|
+
const destStart = labelEnd + 2;
|
|
1144
|
+
if (!line.startsWith("http://", destStart) && !line.startsWith("https://", destStart)) {
|
|
1145
|
+
return void 0;
|
|
1146
|
+
}
|
|
1147
|
+
const closeParens = line.indexOf(")", destStart);
|
|
1148
|
+
if (closeParens === -1) {
|
|
1149
|
+
return void 0;
|
|
1150
|
+
}
|
|
1151
|
+
return { text: line.slice(start, closeParens + 1), end: closeParens + 1 };
|
|
1152
|
+
}
|
|
1153
|
+
function hasUnmatchedClosingParen(text) {
|
|
1154
|
+
let balance = 0;
|
|
1155
|
+
for (const ch of text) {
|
|
1156
|
+
if (ch === "(") balance++;
|
|
1157
|
+
else if (ch === ")") balance--;
|
|
1158
|
+
}
|
|
1159
|
+
return balance < 0;
|
|
1160
|
+
}
|
|
1161
|
+
function readBareUrl(line, start) {
|
|
1162
|
+
let end = start;
|
|
1163
|
+
while (end < line.length) {
|
|
1164
|
+
const ch = line[end];
|
|
1165
|
+
if (/\s/.test(ch) || ch === "<" || ch === ">" || ch === '"' || ch === "`" || ch === "|" || ch === "*") {
|
|
1166
|
+
break;
|
|
1167
|
+
}
|
|
1168
|
+
end++;
|
|
1169
|
+
}
|
|
1170
|
+
if (end === start) {
|
|
1171
|
+
return void 0;
|
|
1172
|
+
}
|
|
1173
|
+
let raw = line.slice(start, end);
|
|
1174
|
+
let suffix = "";
|
|
1175
|
+
const peel = () => {
|
|
1176
|
+
suffix = raw.slice(-1) + suffix;
|
|
1177
|
+
raw = raw.slice(0, -1);
|
|
1178
|
+
};
|
|
1179
|
+
const shouldPeel = () => raw.endsWith("_") || /[.,!?;:]$/.test(raw) || raw.endsWith(")") && hasUnmatchedClosingParen(raw);
|
|
1180
|
+
while (raw.length > 0 && shouldPeel()) {
|
|
1181
|
+
peel();
|
|
1182
|
+
}
|
|
1183
|
+
if (!/^https?:\/\/.+/.test(raw)) {
|
|
1184
|
+
return void 0;
|
|
1185
|
+
}
|
|
1186
|
+
return { url: raw, suffix, end };
|
|
1187
|
+
}
|
|
1188
|
+
function wrapBareUrlsOnLine(line) {
|
|
1189
|
+
let result = "";
|
|
1190
|
+
let i = 0;
|
|
1191
|
+
while (i < line.length) {
|
|
1192
|
+
const codeSpan = readInlineCodeSpan(line, i);
|
|
1193
|
+
if (codeSpan) {
|
|
1194
|
+
result += codeSpan.text;
|
|
1195
|
+
i = codeSpan.end;
|
|
1196
|
+
continue;
|
|
1197
|
+
}
|
|
1198
|
+
const angleToken = readExistingSlackAngleToken(line, i);
|
|
1199
|
+
if (angleToken) {
|
|
1200
|
+
result += angleToken.text;
|
|
1201
|
+
i = angleToken.end;
|
|
1202
|
+
continue;
|
|
1203
|
+
}
|
|
1204
|
+
const mdLink = readMarkdownLink(line, i);
|
|
1205
|
+
if (mdLink) {
|
|
1206
|
+
result += mdLink.text;
|
|
1207
|
+
i = mdLink.end;
|
|
1208
|
+
continue;
|
|
1209
|
+
}
|
|
1210
|
+
if (line.startsWith("https://", i) || line.startsWith("http://", i)) {
|
|
1211
|
+
const parsed = readBareUrl(line, i);
|
|
1212
|
+
if (parsed) {
|
|
1213
|
+
result += `<${parsed.url}>${parsed.suffix}`;
|
|
1214
|
+
i = parsed.end;
|
|
1215
|
+
continue;
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
result += line[i];
|
|
1219
|
+
i++;
|
|
1220
|
+
}
|
|
1221
|
+
return result;
|
|
1222
|
+
}
|
|
1223
|
+
function wrapBareUrls(text) {
|
|
1224
|
+
const lines = text.split("\n");
|
|
1225
|
+
const out = [];
|
|
1226
|
+
let inCodeBlock = false;
|
|
1227
|
+
for (const line of lines) {
|
|
1228
|
+
if (line.trimStart().startsWith("```")) {
|
|
1229
|
+
inCodeBlock = !inCodeBlock;
|
|
1230
|
+
out.push(line);
|
|
1231
|
+
continue;
|
|
1232
|
+
}
|
|
1233
|
+
out.push(inCodeBlock ? line : wrapBareUrlsOnLine(line));
|
|
1234
|
+
}
|
|
1235
|
+
return out.join("\n");
|
|
1236
|
+
}
|
|
1098
1237
|
function ensureBlockSpacing(text) {
|
|
1099
1238
|
const codeBlockPattern = /^```/;
|
|
1100
1239
|
const listItemPattern = /^[-*•]\s|^\d+\.\s/;
|
|
@@ -1127,8 +1266,9 @@ function ensureBlockSpacing(text) {
|
|
|
1127
1266
|
}
|
|
1128
1267
|
return result.join("\n");
|
|
1129
1268
|
}
|
|
1130
|
-
function
|
|
1269
|
+
function normalizeSlackReplyMarkdown(text) {
|
|
1131
1270
|
let normalized = text.replace(/\r\n?/g, "\n").replace(/[ \t]+$/gm, "");
|
|
1271
|
+
normalized = wrapBareUrls(normalized);
|
|
1132
1272
|
normalized = ensureBlockSpacing(normalized);
|
|
1133
1273
|
return normalized.replace(/\n{3,}/g, "\n\n").trim();
|
|
1134
1274
|
}
|
|
@@ -1302,7 +1442,7 @@ function takeSlackInlinePrefix(text, options) {
|
|
|
1302
1442
|
};
|
|
1303
1443
|
}
|
|
1304
1444
|
function splitSlackReplyText(text, options) {
|
|
1305
|
-
const normalized =
|
|
1445
|
+
const normalized = normalizeSlackReplyMarkdown(text);
|
|
1306
1446
|
if (!normalized) {
|
|
1307
1447
|
return [];
|
|
1308
1448
|
}
|
|
@@ -1333,7 +1473,7 @@ function getSlackContinuationBudget() {
|
|
|
1333
1473
|
return reserveInlineBudgetForSuffix(CONTINUED_MARKER);
|
|
1334
1474
|
}
|
|
1335
1475
|
function buildSlackOutputMessage(text, files) {
|
|
1336
|
-
const normalized =
|
|
1476
|
+
const normalized = normalizeSlackReplyMarkdown(text);
|
|
1337
1477
|
const fileCount = files?.length ?? 0;
|
|
1338
1478
|
if (!normalized) {
|
|
1339
1479
|
if (fileCount > 0) {
|
package/dist/reporting.js
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
listAgentTurnSessionSummaries,
|
|
10
10
|
listAgentTurnSessionSummariesForConversation,
|
|
11
11
|
resolveSlackConversationContextFromThreadId
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-UQQSW7QB.js";
|
|
13
13
|
import {
|
|
14
14
|
discoverSkills
|
|
15
15
|
} from "./chunk-V47RLIO2.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentry/junior",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.68.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"node-html-markdown": "^2.0.0",
|
|
66
66
|
"yaml": "^2.9.0",
|
|
67
67
|
"zod": "^4.4.3",
|
|
68
|
-
"@sentry/junior-plugin-api": "0.
|
|
68
|
+
"@sentry/junior-plugin-api": "0.68.0"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@types/node": "^25.9.1",
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"typescript": "^6.0.3",
|
|
78
78
|
"vercel": "^54.4.0",
|
|
79
79
|
"vitest": "^4.1.7",
|
|
80
|
-
"@sentry/junior-scheduler": "0.
|
|
80
|
+
"@sentry/junior-scheduler": "0.68.0"
|
|
81
81
|
},
|
|
82
82
|
"scripts": {
|
|
83
83
|
"build": "tsup && tsc -p tsconfig.build.json --emitDeclarationOnly",
|