@sentry/junior 0.66.3 → 0.67.1
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 +408 -818
- package/dist/chat/config.d.ts +3 -0
- package/dist/chat/ingress/slash-command.d.ts +1 -1
- package/dist/chat/plugins/agent-hooks.d.ts +3 -1
- package/dist/chat/respond.d.ts +2 -0
- package/dist/chat/services/message-actor-identity.d.ts +8 -0
- package/dist/chat/services/requester-identity.d.ts +19 -0
- package/dist/chat/services/turn-session-record.d.ts +6 -1
- package/dist/chat/slack/user.d.ts +3 -0
- package/dist/chat/state/turn-session.d.ts +4 -0
- package/dist/chat/task-execution/slack-work.d.ts +2 -0
- package/dist/{chunk-DG2I6GXC.js → chunk-5UIDU7XR.js} +1805 -1016
- package/dist/{chunk-SAYCFF7O.js → chunk-MT23VNOH.js} +50 -2
- package/dist/{chunk-6QWWMZCK.js → chunk-OIIXZOOC.js} +101 -6
- package/dist/{chunk-YL5G5YC4.js → chunk-V47RLIO2.js} +1 -1
- package/dist/{chunk-JA5QR3N4.js → chunk-YGGH2742.js} +2 -2
- package/dist/cli/check.js +2 -2
- package/dist/cli/init.js +1 -0
- package/dist/cli/snapshot-warmup.js +3 -3
- package/dist/reporting.d.ts +45 -2
- package/dist/reporting.js +303 -13
- package/package.json +3 -3
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
setSpanAttributes,
|
|
7
7
|
toOptionalString,
|
|
8
8
|
withSpan
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-OIIXZOOC.js";
|
|
10
10
|
|
|
11
11
|
// src/chat/slack/context.ts
|
|
12
12
|
function toTrimmedSlackString(value) {
|
|
@@ -496,10 +496,24 @@ async function completeObject(params) {
|
|
|
496
496
|
};
|
|
497
497
|
}
|
|
498
498
|
|
|
499
|
+
// src/chat/slack/emoji.ts
|
|
500
|
+
var SLACK_EMOJI_NAME_RE = /^(?:[a-z0-9_+-]+)(?:::(?:skin-tone-[2-6]))?$/;
|
|
501
|
+
function normalizeSlackEmojiName(value) {
|
|
502
|
+
const trimmed = value.trim().toLowerCase();
|
|
503
|
+
if (!trimmed) {
|
|
504
|
+
return null;
|
|
505
|
+
}
|
|
506
|
+
const normalized = trimmed.startsWith(":") && trimmed.endsWith(":") ? trimmed.slice(1, -1) : trimmed;
|
|
507
|
+
return SLACK_EMOJI_NAME_RE.test(normalized) ? normalized : null;
|
|
508
|
+
}
|
|
509
|
+
|
|
499
510
|
// src/chat/config.ts
|
|
500
511
|
var MIN_AGENT_TURN_TIMEOUT_MS = 10 * 1e3;
|
|
501
512
|
var DEFAULT_AGENT_TURN_TIMEOUT_MS = 12 * 60 * 1e3;
|
|
502
513
|
var DEFAULT_FUNCTION_MAX_DURATION_SECONDS = 300;
|
|
514
|
+
var DEFAULT_SLACK_SLASH_COMMAND = "/jr";
|
|
515
|
+
var DEFAULT_PROCESSING_REACTION_EMOJI = "eyes";
|
|
516
|
+
var DEFAULT_COMPLETED_REACTION_EMOJI = "white_check_mark";
|
|
503
517
|
var ADVISOR_THINKING_LEVELS = [
|
|
504
518
|
"minimal",
|
|
505
519
|
"low",
|
|
@@ -589,6 +603,15 @@ function parseOptionalPositiveInteger(envName, rawValue) {
|
|
|
589
603
|
}
|
|
590
604
|
return value;
|
|
591
605
|
}
|
|
606
|
+
function parseSlashCommand(rawValue) {
|
|
607
|
+
const command = toOptionalTrimmed(rawValue) ?? DEFAULT_SLACK_SLASH_COMMAND;
|
|
608
|
+
if (!command.startsWith("/") || /\s/.test(command)) {
|
|
609
|
+
throw new Error(
|
|
610
|
+
"JUNIOR_SLASH_COMMAND must start with / and contain no whitespace"
|
|
611
|
+
);
|
|
612
|
+
}
|
|
613
|
+
return command;
|
|
614
|
+
}
|
|
592
615
|
var DEFAULT_MODEL_ID = getModel("vercel-ai-gateway", "openai/gpt-5.4").id;
|
|
593
616
|
var DEFAULT_FAST_MODEL_ID = getModel(
|
|
594
617
|
"vercel-ai-gateway",
|
|
@@ -610,6 +633,19 @@ function readAdvisorConfig(env) {
|
|
|
610
633
|
thinkingLevel: parseAdvisorThinkingLevel(env.AI_ADVISOR_THINKING_LEVEL)
|
|
611
634
|
};
|
|
612
635
|
}
|
|
636
|
+
function parseReactionEmoji(envName, rawValue, defaultEmoji) {
|
|
637
|
+
const trimmed = toOptionalTrimmed(rawValue);
|
|
638
|
+
if (trimmed === void 0) {
|
|
639
|
+
return defaultEmoji;
|
|
640
|
+
}
|
|
641
|
+
const normalized = normalizeSlackEmojiName(trimmed);
|
|
642
|
+
if (!normalized) {
|
|
643
|
+
throw new Error(
|
|
644
|
+
`${envName} must be a valid Slack emoji name (for example "eyes" or ":white_check_mark:")`
|
|
645
|
+
);
|
|
646
|
+
}
|
|
647
|
+
return normalized;
|
|
648
|
+
}
|
|
613
649
|
function readBotConfig(env) {
|
|
614
650
|
const functionMaxDurationSeconds = resolveFunctionMaxDurationSeconds(env);
|
|
615
651
|
const maxTurnTimeoutMs = resolveMaxTurnTimeoutMs(functionMaxDurationSeconds);
|
|
@@ -622,6 +658,16 @@ function readBotConfig(env) {
|
|
|
622
658
|
),
|
|
623
659
|
fastModelId: validateGatewayModelId(env.AI_FAST_MODEL ?? env.AI_MODEL) ?? DEFAULT_FAST_MODEL_ID,
|
|
624
660
|
loadingMessages: parseLoadingMessages(env.JUNIOR_LOADING_MESSAGES),
|
|
661
|
+
processingReactionEmoji: parseReactionEmoji(
|
|
662
|
+
"JUNIOR_PROCESSING_REACTION",
|
|
663
|
+
env.JUNIOR_PROCESSING_REACTION,
|
|
664
|
+
DEFAULT_PROCESSING_REACTION_EMOJI
|
|
665
|
+
),
|
|
666
|
+
completedReactionEmoji: parseReactionEmoji(
|
|
667
|
+
"JUNIOR_COMPLETED_REACTION",
|
|
668
|
+
env.JUNIOR_COMPLETED_REACTION,
|
|
669
|
+
DEFAULT_COMPLETED_REACTION_EMOJI
|
|
670
|
+
),
|
|
625
671
|
visionModelId: validateGatewayModelId(env.AI_VISION_MODEL),
|
|
626
672
|
turnTimeoutMs: parseAgentTurnTimeoutMs(
|
|
627
673
|
env.AGENT_TURN_TIMEOUT_MS,
|
|
@@ -638,7 +684,8 @@ function readChatConfig(env = process.env) {
|
|
|
638
684
|
botToken: toOptionalTrimmed(env.SLACK_BOT_TOKEN) ?? toOptionalTrimmed(env.SLACK_BOT_USER_TOKEN),
|
|
639
685
|
signingSecret: toOptionalTrimmed(env.SLACK_SIGNING_SECRET),
|
|
640
686
|
clientId: toOptionalTrimmed(env.SLACK_CLIENT_ID),
|
|
641
|
-
clientSecret: toOptionalTrimmed(env.SLACK_CLIENT_SECRET)
|
|
687
|
+
clientSecret: toOptionalTrimmed(env.SLACK_CLIENT_SECRET),
|
|
688
|
+
slashCommand: parseSlashCommand(env.JUNIOR_SLASH_COMMAND)
|
|
642
689
|
},
|
|
643
690
|
state: {
|
|
644
691
|
adapter: env.JUNIOR_STATE_ADAPTER?.trim().toLowerCase() === "memory" ? "memory" : "redis",
|
|
@@ -938,6 +985,7 @@ export {
|
|
|
938
985
|
resolveGatewayModel,
|
|
939
986
|
completeText,
|
|
940
987
|
completeObject,
|
|
988
|
+
normalizeSlackEmojiName,
|
|
941
989
|
FUNCTION_TIMEOUT_BUFFER_SECONDS,
|
|
942
990
|
getChatConfig,
|
|
943
991
|
botConfig,
|
|
@@ -2858,6 +2858,90 @@ var CredentialUnavailableError = class extends Error {
|
|
|
2858
2858
|
}
|
|
2859
2859
|
};
|
|
2860
2860
|
|
|
2861
|
+
// src/chat/services/requester-identity.ts
|
|
2862
|
+
var SLACK_USER_ID_PATTERN = /^[UW][A-Z0-9]{5,}$/;
|
|
2863
|
+
var EMAIL_PATTERN = /^[^\s@<>]+@[^\s@<>]+\.[^\s@<>]+$/;
|
|
2864
|
+
function clean(value) {
|
|
2865
|
+
const trimmed = value?.trim();
|
|
2866
|
+
return trimmed ? trimmed : void 0;
|
|
2867
|
+
}
|
|
2868
|
+
function isSyntheticActorUserId(value) {
|
|
2869
|
+
return value.toLowerCase() === "unknown";
|
|
2870
|
+
}
|
|
2871
|
+
function parseActorUserId(value) {
|
|
2872
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
2873
|
+
return void 0;
|
|
2874
|
+
}
|
|
2875
|
+
if (value !== value.trim() || isSyntheticActorUserId(value)) {
|
|
2876
|
+
return void 0;
|
|
2877
|
+
}
|
|
2878
|
+
return value;
|
|
2879
|
+
}
|
|
2880
|
+
function isActorUserId(value) {
|
|
2881
|
+
return parseActorUserId(value) === value;
|
|
2882
|
+
}
|
|
2883
|
+
function isSlackUserId(value) {
|
|
2884
|
+
return SLACK_USER_ID_PATTERN.test(value);
|
|
2885
|
+
}
|
|
2886
|
+
function cleanActorDisplayName(value, userId) {
|
|
2887
|
+
const displayName = clean(value);
|
|
2888
|
+
if (!displayName) {
|
|
2889
|
+
return void 0;
|
|
2890
|
+
}
|
|
2891
|
+
if (displayName.toLowerCase() === "unknown") {
|
|
2892
|
+
return void 0;
|
|
2893
|
+
}
|
|
2894
|
+
if (userId && displayName === userId) {
|
|
2895
|
+
return void 0;
|
|
2896
|
+
}
|
|
2897
|
+
return isSlackUserId(displayName) ? void 0 : displayName;
|
|
2898
|
+
}
|
|
2899
|
+
function cleanActorEmail(value) {
|
|
2900
|
+
const email = clean(value);
|
|
2901
|
+
return email && EMAIL_PATTERN.test(email) ? email : void 0;
|
|
2902
|
+
}
|
|
2903
|
+
function buildActorIdentity(requester, requesterId) {
|
|
2904
|
+
const contextUserId = parseActorUserId(requesterId);
|
|
2905
|
+
if (requesterId !== void 0 && !contextUserId) {
|
|
2906
|
+
return void 0;
|
|
2907
|
+
}
|
|
2908
|
+
const requesterUserId = parseActorUserId(requester?.userId);
|
|
2909
|
+
if (requester?.userId !== void 0 && !requesterUserId) {
|
|
2910
|
+
return void 0;
|
|
2911
|
+
}
|
|
2912
|
+
const userId = contextUserId ?? requesterUserId;
|
|
2913
|
+
const canUseRequesterIdentity = !contextUserId || !requesterUserId || contextUserId === requesterUserId;
|
|
2914
|
+
const email = canUseRequesterIdentity ? cleanActorEmail(requester?.email) : void 0;
|
|
2915
|
+
const fullName = canUseRequesterIdentity ? cleanActorDisplayName(requester?.fullName, userId) : void 0;
|
|
2916
|
+
const userName = canUseRequesterIdentity ? cleanActorDisplayName(requester?.userName, userId) : void 0;
|
|
2917
|
+
const identity = {
|
|
2918
|
+
...email ? { email } : {},
|
|
2919
|
+
...fullName ? { fullName } : {},
|
|
2920
|
+
...userId ? { userId } : {},
|
|
2921
|
+
...userName ? { userName } : {}
|
|
2922
|
+
};
|
|
2923
|
+
return Object.keys(identity).length > 0 ? identity : void 0;
|
|
2924
|
+
}
|
|
2925
|
+
function slackActorIdentity(userId, profile) {
|
|
2926
|
+
const actorUserId = parseActorUserId(userId);
|
|
2927
|
+
if (!actorUserId) {
|
|
2928
|
+
throw new Error("Slack actor identity requires a user id");
|
|
2929
|
+
}
|
|
2930
|
+
const identity = buildActorIdentity(
|
|
2931
|
+
{
|
|
2932
|
+
email: profile?.email,
|
|
2933
|
+
fullName: profile?.fullName,
|
|
2934
|
+
userId: actorUserId,
|
|
2935
|
+
userName: profile?.userName
|
|
2936
|
+
},
|
|
2937
|
+
actorUserId
|
|
2938
|
+
);
|
|
2939
|
+
if (!identity?.userId) {
|
|
2940
|
+
throw new Error("Slack actor identity requires a user id");
|
|
2941
|
+
}
|
|
2942
|
+
return identity;
|
|
2943
|
+
}
|
|
2944
|
+
|
|
2861
2945
|
// src/chat/credentials/context.ts
|
|
2862
2946
|
function credentialUserSubjectId(context) {
|
|
2863
2947
|
if (context.actor.type === "user") {
|
|
@@ -2895,11 +2979,15 @@ function parseCredentialContext(value) {
|
|
|
2895
2979
|
function parseActor(value) {
|
|
2896
2980
|
if (value && typeof value === "object") {
|
|
2897
2981
|
const record = value;
|
|
2898
|
-
|
|
2899
|
-
|
|
2982
|
+
const userId = parseActorUserId(
|
|
2983
|
+
typeof record.userId === "string" ? record.userId : void 0
|
|
2984
|
+
);
|
|
2985
|
+
if (record.type === "user" && userId) {
|
|
2986
|
+
return { type: "user", userId };
|
|
2900
2987
|
}
|
|
2901
|
-
|
|
2902
|
-
|
|
2988
|
+
const systemId = typeof record.id === "string" && record.id.length > 0 && record.id === record.id.trim() && record.id.toLowerCase() !== "unknown" ? record.id : void 0;
|
|
2989
|
+
if (record.type === "system" && systemId) {
|
|
2990
|
+
return { type: "system", id: systemId };
|
|
2903
2991
|
}
|
|
2904
2992
|
}
|
|
2905
2993
|
return void 0;
|
|
@@ -2907,7 +2995,10 @@ function parseActor(value) {
|
|
|
2907
2995
|
function parseSubject(value) {
|
|
2908
2996
|
if (value && typeof value === "object") {
|
|
2909
2997
|
const record = value;
|
|
2910
|
-
|
|
2998
|
+
const userId = parseActorUserId(
|
|
2999
|
+
typeof record.userId === "string" ? record.userId : void 0
|
|
3000
|
+
);
|
|
3001
|
+
if (record.type === "user" && userId && record.allowedWhen === "private-direct-conversation") {
|
|
2911
3002
|
if (!record.binding || typeof record.binding !== "object") {
|
|
2912
3003
|
return void 0;
|
|
2913
3004
|
}
|
|
@@ -2917,7 +3008,7 @@ function parseSubject(value) {
|
|
|
2917
3008
|
}
|
|
2918
3009
|
return {
|
|
2919
3010
|
type: "user",
|
|
2920
|
-
userId
|
|
3011
|
+
userId,
|
|
2921
3012
|
allowedWhen: "private-direct-conversation",
|
|
2922
3013
|
binding: {
|
|
2923
3014
|
type: "slack-direct-conversation",
|
|
@@ -3618,6 +3709,10 @@ export {
|
|
|
3618
3709
|
parsePluginManifest,
|
|
3619
3710
|
parseInlinePluginManifest,
|
|
3620
3711
|
CredentialUnavailableError,
|
|
3712
|
+
parseActorUserId,
|
|
3713
|
+
isActorUserId,
|
|
3714
|
+
buildActorIdentity,
|
|
3715
|
+
slackActorIdentity,
|
|
3621
3716
|
parseCredentialContext,
|
|
3622
3717
|
hasRequiredOAuthScope,
|
|
3623
3718
|
buildOAuthTokenRequest,
|
|
@@ -2,12 +2,12 @@ import {
|
|
|
2
2
|
SANDBOX_WORKSPACE_ROOT,
|
|
3
3
|
getStateAdapter,
|
|
4
4
|
toOptionalTrimmed
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-MT23VNOH.js";
|
|
6
6
|
import {
|
|
7
7
|
getPluginRuntimeDependencies,
|
|
8
8
|
getPluginRuntimePostinstall,
|
|
9
9
|
withSpan
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-OIIXZOOC.js";
|
|
11
11
|
|
|
12
12
|
// src/chat/sandbox/runtime-dependency-snapshots.ts
|
|
13
13
|
import { createHash } from "crypto";
|
package/dist/cli/check.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
parseSkillFile
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-V47RLIO2.js";
|
|
4
4
|
import {
|
|
5
5
|
parseInlinePluginManifest,
|
|
6
6
|
parsePluginManifest
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-OIIXZOOC.js";
|
|
8
8
|
import "../chunk-Z3YD6NHK.js";
|
|
9
9
|
import {
|
|
10
10
|
JUNIOR_CONVERSATION_WORK_CALLBACK_ROUTE,
|
package/dist/cli/init.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveRuntimeDependencySnapshot
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-YGGH2742.js";
|
|
4
4
|
import {
|
|
5
5
|
disconnectStateAdapter
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-MT23VNOH.js";
|
|
7
7
|
import {
|
|
8
8
|
getPluginProviders,
|
|
9
9
|
getPluginRuntimeDependencies,
|
|
10
10
|
getPluginRuntimePostinstall
|
|
11
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-OIIXZOOC.js";
|
|
12
12
|
import "../chunk-Z3YD6NHK.js";
|
|
13
13
|
import "../chunk-KVZL5NZS.js";
|
|
14
14
|
import "../chunk-2KG3PWR4.js";
|
package/dist/reporting.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { getPluginPackageContent } from "@/chat/plugins/registry";
|
|
2
|
+
import { type AgentTurnSurface } from "@/chat/state/turn-session";
|
|
3
|
+
import type { PluginOperationalReport } from "@sentry/junior-plugin-api";
|
|
2
4
|
export interface HealthReport {
|
|
3
5
|
status: "ok";
|
|
4
6
|
service: string;
|
|
@@ -20,7 +22,7 @@ export interface RuntimeInfoReport {
|
|
|
20
22
|
packagedContent: ReturnType<typeof getPluginPackageContent>;
|
|
21
23
|
}
|
|
22
24
|
export type DashboardSessionStatus = "active" | "completed" | "failed" | "hung" | "superseded";
|
|
23
|
-
export type DashboardSurface =
|
|
25
|
+
export type DashboardSurface = AgentTurnSurface;
|
|
24
26
|
export interface DashboardTurnUsage {
|
|
25
27
|
inputTokens?: number;
|
|
26
28
|
outputTokens?: number;
|
|
@@ -99,6 +101,40 @@ export interface DashboardSessionFeed {
|
|
|
99
101
|
source: "turn_session_records";
|
|
100
102
|
generatedAt: string;
|
|
101
103
|
}
|
|
104
|
+
export interface DashboardConversationStatsItem {
|
|
105
|
+
active: number;
|
|
106
|
+
conversations: number;
|
|
107
|
+
durationMs: number;
|
|
108
|
+
failed: number;
|
|
109
|
+
hung: number;
|
|
110
|
+
label: string;
|
|
111
|
+
tokens?: number;
|
|
112
|
+
turns: number;
|
|
113
|
+
}
|
|
114
|
+
export interface DashboardConversationStatsReport {
|
|
115
|
+
active: number;
|
|
116
|
+
conversations: number;
|
|
117
|
+
durationMs: number;
|
|
118
|
+
failed: number;
|
|
119
|
+
generatedAt: string;
|
|
120
|
+
hung: number;
|
|
121
|
+
locations: DashboardConversationStatsItem[];
|
|
122
|
+
requesters: DashboardConversationStatsItem[];
|
|
123
|
+
sampleLimit: number;
|
|
124
|
+
sampleSize: number;
|
|
125
|
+
source: "turn_session_records";
|
|
126
|
+
tokens?: number;
|
|
127
|
+
truncated: boolean;
|
|
128
|
+
turns: number;
|
|
129
|
+
windowEnd: string;
|
|
130
|
+
windowStart: string;
|
|
131
|
+
}
|
|
132
|
+
export type { PluginOperationalReport } from "@sentry/junior-plugin-api";
|
|
133
|
+
export interface PluginOperationalReportFeed {
|
|
134
|
+
generatedAt: string;
|
|
135
|
+
reports: PluginOperationalReport[];
|
|
136
|
+
source: "trusted_plugins";
|
|
137
|
+
}
|
|
102
138
|
export interface JuniorReporting {
|
|
103
139
|
/** Read the public runtime health snapshot without exposing discovery data. */
|
|
104
140
|
getHealth(): Promise<HealthReport>;
|
|
@@ -115,6 +151,10 @@ export interface JuniorReporting {
|
|
|
115
151
|
* actor, route, usage, and links that can later be reconstructed from spans.
|
|
116
152
|
*/
|
|
117
153
|
getSessions(): Promise<DashboardSessionFeed>;
|
|
154
|
+
/** Read aggregate conversation stats for authenticated dashboard views. */
|
|
155
|
+
getConversationStats?(): Promise<DashboardConversationStatsReport>;
|
|
156
|
+
/** Read sanitized operational summaries contributed by trusted plugins. */
|
|
157
|
+
getPluginOperationalReports?(): Promise<PluginOperationalReportFeed>;
|
|
118
158
|
/**
|
|
119
159
|
* Read one conversation transcript for the dashboard.
|
|
120
160
|
*
|
|
@@ -125,4 +165,7 @@ export interface JuniorReporting {
|
|
|
125
165
|
getConversation(conversationId: string): Promise<DashboardConversationReport>;
|
|
126
166
|
}
|
|
127
167
|
/** Create the read-only reporting boundary used by authenticated dashboard routes. */
|
|
128
|
-
export declare function createJuniorReporting(): JuniorReporting
|
|
168
|
+
export declare function createJuniorReporting(): JuniorReporting & {
|
|
169
|
+
getConversationStats(): Promise<DashboardConversationStatsReport>;
|
|
170
|
+
getPluginOperationalReports(): Promise<PluginOperationalReportFeed>;
|
|
171
|
+
};
|