@sentry/junior 0.150.1 → 0.152.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-G4LEACQB.js → agent-hooks-U66Q3X2P.js} +10 -10
- package/dist/api/schema/conversation.d.ts +35 -4
- package/dist/api/schema.d.ts +1 -1
- package/dist/api/schema.js +3 -1
- package/dist/api.js +81 -38
- package/dist/app.js +129 -206
- package/dist/{catalog-runtime-ZRSNE2MH.js → catalog-runtime-CVCR7SND.js} +5 -5
- package/dist/chat/agent/skills.d.ts +5 -4
- package/dist/chat/agent/tools.d.ts +5 -5
- package/dist/chat/api-turns/authorization.d.ts +23 -0
- package/dist/chat/conversations/history.d.ts +12 -3
- package/dist/chat/conversations/projection.d.ts +7 -3
- package/dist/chat/mcp/tool-manager.d.ts +0 -4
- package/dist/chat/runtime/agent-run-outcome.d.ts +4 -0
- package/dist/chat/tools/search-conversation-events.d.ts +1 -1
- package/dist/chat/tools/skill/call-mcp-tool.d.ts +0 -1
- package/dist/chat/tools/skill/load-skill.d.ts +2 -5
- package/dist/chat/tools/types.d.ts +1 -2
- package/dist/{chunk-2AWDPNP7.js → chunk-3PCKG4BT.js} +16 -10
- package/dist/{chunk-2Z7YX5PI.js → chunk-3UJ3QYRV.js} +156 -19
- package/dist/{chunk-IQW6RFXG.js → chunk-5LDOQV7Y.js} +72 -218
- package/dist/{chunk-JBYWR6FW.js → chunk-67VR4BJK.js} +5 -5
- package/dist/{chunk-5NOHC2Z4.js → chunk-732P2RBQ.js} +1 -1
- package/dist/{chunk-3WIFZBJL.js → chunk-7TZM33YX.js} +1 -1
- package/dist/{chunk-JVOLC6JZ.js → chunk-AYPU5T5L.js} +4 -4
- package/dist/{chunk-TZRYLW3R.js → chunk-CLX3T7Q3.js} +1 -1
- package/dist/{chunk-JUBPTYNO.js → chunk-ELAVLP7Z.js} +1 -1
- package/dist/{chunk-LSI3EKZQ.js → chunk-ETXLHT3S.js} +4 -4
- package/dist/{chunk-N6QJAPZS.js → chunk-I4LR7MS2.js} +45 -11
- package/dist/{chunk-6ZYGORV4.js → chunk-KC47ZY6Q.js} +2 -2
- package/dist/{chunk-6A24WEKX.js → chunk-KC5XZBRB.js} +4 -4
- package/dist/{chunk-D2PVJU5E.js → chunk-KTYC3GDO.js} +3 -3
- package/dist/{chunk-AD6N2KNE.js → chunk-KW2MGCW5.js} +5 -5
- package/dist/{chunk-QO3OSJDS.js → chunk-LETPYIDF.js} +1 -1
- package/dist/{chunk-6IWDFUXW.js → chunk-M6PWM3OK.js} +1 -1
- package/dist/{chunk-LWFHRWJI.js → chunk-N2472SQK.js} +8 -8
- package/dist/{chunk-QNSV46AW.js → chunk-NF733C66.js} +6 -6
- package/dist/{chunk-FGP5W3NS.js → chunk-OEECXAGT.js} +2 -2
- package/dist/{chunk-SZ74ECCC.js → chunk-QKPIW2CY.js} +6 -6
- package/dist/{chunk-4JV7GUUH.js → chunk-RCBAXKMB.js} +1 -1
- package/dist/{chunk-QZGYKKH6.js → chunk-SDMVFTH4.js} +173 -70
- package/dist/chunk-SFYDSI34.js +89 -0
- package/dist/{chunk-W3FQZAX5.js → chunk-TSQMITMQ.js} +6 -6
- package/dist/{chunk-IZE2EGCX.js → chunk-UFKSILED.js} +5 -5
- package/dist/{chunk-3JVUWLR7.js → chunk-UG5UCHHJ.js} +15 -1
- package/dist/{chunk-OWLJZ6I7.js → chunk-VD6CRYCT.js} +1 -1
- package/dist/{chunk-2DIRU2C2.js → chunk-WZN4RQ64.js} +1 -1
- package/dist/{chunk-KFHJQYKQ.js → chunk-X4RM4TBW.js} +1 -1
- package/dist/{chunk-B2YA2G26.js → chunk-X6JP6AMX.js} +1 -1
- package/dist/{chunk-GZ25ZSTX.js → chunk-XTLF7C4I.js} +11 -4
- package/dist/{chunk-R53UTQ2Q.js → chunk-Z5WLTGME.js} +1 -1
- package/dist/cli/chat.js +30 -30
- 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-WRA5ZHYE.js → db-HQAZQASY.js} +7 -7
- package/dist/handlers/mcp-oauth-callback.d.ts +3 -0
- package/dist/handlers/oauth-callback.d.ts +3 -0
- package/dist/instrumentation.js +4 -4
- package/dist/nitro.js +2 -2
- package/dist/{oauth-callback-server-QWAYG3MI.js → oauth-callback-server-OJONZ7T3.js} +23 -24
- package/dist/{runner-5JQ54J6P.js → runner-BIJAVQDX.js} +14 -16
- package/dist/{skills-3YD55WPO.js → skills-SIPNY4AT.js} +6 -6
- package/dist/spawn-ABDIBQT6.js +38 -0
- package/dist/{validation-ZXE3IRSB.js → validation-KRPOY5RQ.js} +6 -6
- package/dist/version.js +1 -1
- package/dist/{work-7G2U64WI.js → work-KS3JOEI2.js} +17 -17
- package/dist/{worker-HJM2FZNI.js → worker-CZ5KNZUI.js} +11 -11
- package/migrations/0025_mcp_credential_subject.sql +8 -0
- package/migrations/meta/0025_snapshot.json +2275 -0
- package/migrations/meta/_journal.json +7 -0
- package/package.json +5 -5
- package/dist/chat/pi/derived-state.d.ts +0 -5
- package/dist/chunk-4CODA7P5.js +0 -43
- package/dist/chunk-XED3H34M.js +0 -48
- package/dist/spawn-OOO26XDL.js +0 -38
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { OAuthAuthorizationRequest } from "@/chat/oauth-authorization";
|
|
2
|
+
export interface WebAuthorizationState extends OAuthAuthorizationRequest {
|
|
3
|
+
actorId: string;
|
|
4
|
+
conversationId: string;
|
|
5
|
+
}
|
|
6
|
+
/** Build authorization delivery for one web turn. */
|
|
7
|
+
export declare function createWebAuthorization(args: {
|
|
8
|
+
actorId: string;
|
|
9
|
+
conversationId: string;
|
|
10
|
+
}): {
|
|
11
|
+
createState: () => Promise<`${string}-${string}-${string}-${string}-${string}`>;
|
|
12
|
+
deliver: (request: OAuthAuthorizationRequest) => Promise<void>;
|
|
13
|
+
};
|
|
14
|
+
/** Read the pending authorization request for one web actor. */
|
|
15
|
+
export declare function getWebAuthorization(args: {
|
|
16
|
+
actorId: string;
|
|
17
|
+
conversationId: string;
|
|
18
|
+
}): Promise<WebAuthorizationState | undefined>;
|
|
19
|
+
/** Remove a web authorization request after the parked turn continues. */
|
|
20
|
+
export declare function deleteWebAuthorization(args: {
|
|
21
|
+
actorId: string;
|
|
22
|
+
conversationId: string;
|
|
23
|
+
}): Promise<void>;
|
|
@@ -230,6 +230,7 @@ export declare const conversationEventDataSchema: z.ZodUnion<readonly [z.ZodUnio
|
|
|
230
230
|
}, z.core.$loose>], "type">, z.ZodObject<{
|
|
231
231
|
type: z.ZodLiteral<"mcp_provider_connected">;
|
|
232
232
|
provider: z.ZodString;
|
|
233
|
+
credentialSubjectId: z.ZodString;
|
|
233
234
|
}, z.core.$strict>, z.ZodObject<{
|
|
234
235
|
type: z.ZodLiteral<"authorization_requested">;
|
|
235
236
|
kind: z.ZodUnion<readonly [z.ZodLiteral<"plugin">, z.ZodLiteral<"mcp">]>;
|
|
@@ -455,11 +456,14 @@ export declare const conversationEventDataSchema: z.ZodUnion<readonly [z.ZodUnio
|
|
|
455
456
|
}, z.core.$loose>], "type">;
|
|
456
457
|
sourceEventSeq: z.ZodOptional<z.ZodNumber>;
|
|
457
458
|
}, z.core.$strict>>;
|
|
458
|
-
}, z.core.$strict>], "type"
|
|
459
|
+
}, z.core.$strict>], "type">, z.ZodObject<{
|
|
460
|
+
type: z.ZodLiteral<"mcp_provider_connected_unowned">;
|
|
461
|
+
provider: z.ZodString;
|
|
462
|
+
}, z.core.$strict>]>;
|
|
459
463
|
/** One durable conversation event's validated data. */
|
|
460
464
|
export type ConversationEventData = z.output<typeof conversationEventDataSchema>;
|
|
461
465
|
/** Event type names recognized by current readers and observational queries. */
|
|
462
|
-
export declare const KNOWN_CONVERSATION_EVENT_TYPES: readonly ["message", "message_updated", "user_message", "assistant_message", "tool_result", "mcp_provider_connected", "authorization_requested", "authorization_completed", "tool_execution_started", "guardian_action_reviewed", "message_handled", "messages_summarized", "turn_started", "turn_context", "structured_event", "turn_routed", "turn_completed", "turn_failed", "subagent_started", "subagent_ended", "handoff", "compaction"];
|
|
466
|
+
export declare const KNOWN_CONVERSATION_EVENT_TYPES: readonly ["message", "message_updated", "user_message", "assistant_message", "tool_result", "mcp_provider_connected", "mcp_provider_connected_unowned", "authorization_requested", "authorization_completed", "tool_execution_started", "guardian_action_reviewed", "message_handled", "messages_summarized", "turn_started", "turn_context", "structured_event", "turn_routed", "turn_completed", "turn_failed", "subagent_started", "subagent_ended", "handoff", "compaction"];
|
|
463
467
|
/** One known durable conversation event type name. */
|
|
464
468
|
export type KnownConversationEventType = (typeof KNOWN_CONVERSATION_EVENT_TYPES)[number];
|
|
465
469
|
declare const unknownConversationEventDataSchema: z.ZodObject<{
|
|
@@ -531,6 +535,7 @@ export declare const conversationEventSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
531
535
|
}, z.core.$loose>], "type">, z.ZodObject<{
|
|
532
536
|
type: z.ZodLiteral<"mcp_provider_connected">;
|
|
533
537
|
provider: z.ZodString;
|
|
538
|
+
credentialSubjectId: z.ZodString;
|
|
534
539
|
}, z.core.$strict>, z.ZodObject<{
|
|
535
540
|
type: z.ZodLiteral<"authorization_requested">;
|
|
536
541
|
kind: z.ZodUnion<readonly [z.ZodLiteral<"plugin">, z.ZodLiteral<"mcp">]>;
|
|
@@ -756,7 +761,10 @@ export declare const conversationEventSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
756
761
|
}, z.core.$loose>], "type">;
|
|
757
762
|
sourceEventSeq: z.ZodOptional<z.ZodNumber>;
|
|
758
763
|
}, z.core.$strict>>;
|
|
759
|
-
}, z.core.$strict>], "type"
|
|
764
|
+
}, z.core.$strict>], "type">, z.ZodObject<{
|
|
765
|
+
type: z.ZodLiteral<"mcp_provider_connected_unowned">;
|
|
766
|
+
provider: z.ZodString;
|
|
767
|
+
}, z.core.$strict>]>;
|
|
760
768
|
}, z.core.$strict>, z.ZodObject<{
|
|
761
769
|
schemaVersion: z.ZodNumber;
|
|
762
770
|
seq: z.ZodNumber;
|
|
@@ -855,6 +863,7 @@ export declare const newConversationEventSchema: z.ZodObject<{
|
|
|
855
863
|
}, z.core.$loose>], "type">, z.ZodObject<{
|
|
856
864
|
type: z.ZodLiteral<"mcp_provider_connected">;
|
|
857
865
|
provider: z.ZodString;
|
|
866
|
+
credentialSubjectId: z.ZodString;
|
|
858
867
|
}, z.core.$strict>, z.ZodObject<{
|
|
859
868
|
type: z.ZodLiteral<"authorization_requested">;
|
|
860
869
|
kind: z.ZodUnion<readonly [z.ZodLiteral<"plugin">, z.ZodLiteral<"mcp">]>;
|
|
@@ -39,8 +39,11 @@ export declare function loadTurnProjection(args: {
|
|
|
39
39
|
committedSeq: number;
|
|
40
40
|
includeTail: boolean;
|
|
41
41
|
}): Promise<PiConversationEventProjection | undefined>;
|
|
42
|
-
/** Load MCP providers connected in
|
|
43
|
-
export declare function loadConnectedMcpProviders(args:
|
|
42
|
+
/** Load MCP providers the credential subject connected in this conversation. */
|
|
43
|
+
export declare function loadConnectedMcpProviders(args: {
|
|
44
|
+
conversationId: string;
|
|
45
|
+
credentialSubjectId: string;
|
|
46
|
+
}): Promise<string[]>;
|
|
44
47
|
/**
|
|
45
48
|
* Append newly stable native history items.
|
|
46
49
|
*
|
|
@@ -90,10 +93,11 @@ export declare function commitAcceptedReply(args: {
|
|
|
90
93
|
providerConversationBindings?: Array<Omit<ProviderConversationBinding, "conversationId">>;
|
|
91
94
|
repliedAtMs?: number;
|
|
92
95
|
}): Promise<void>;
|
|
93
|
-
/** Record a successful MCP provider connection without duplicating
|
|
96
|
+
/** Record a successful MCP provider connection for one credential subject without duplicating it. */
|
|
94
97
|
export declare function recordMcpProviderConnected(args: {
|
|
95
98
|
conversationId: string;
|
|
96
99
|
provider: string;
|
|
100
|
+
credentialSubjectId: string;
|
|
97
101
|
}): Promise<void>;
|
|
98
102
|
/** Record that an OAuth/MCP authorization link was delivered or reused. */
|
|
99
103
|
export declare function recordAuthorizationRequested(args: {
|
|
@@ -10,7 +10,6 @@ import type { ImageContent, TextContent } from "@earendil-works/pi-ai";
|
|
|
10
10
|
import type { OAuthClientProvider } from "@modelcontextprotocol/sdk/client/auth.js";
|
|
11
11
|
import { type PluginMcpToolResult, type ToolAnnotations } from "@sentry/junior-plugin-api";
|
|
12
12
|
import type { ConversationPrivacy } from "@/chat/conversation-privacy";
|
|
13
|
-
import type { SkillMetadata } from "@/chat/skills";
|
|
14
13
|
import type { PluginDefinition } from "@/chat/plugins/types";
|
|
15
14
|
import { McpAuthorizationRequiredError } from "./client";
|
|
16
15
|
export interface McpToolSuccessHookInput {
|
|
@@ -50,7 +49,6 @@ export interface ManagedMcpToolDescriptor {
|
|
|
50
49
|
annotations?: ToolAnnotations;
|
|
51
50
|
provider: string;
|
|
52
51
|
}
|
|
53
|
-
type ActiveMcpSkill = Pick<SkillMetadata, "name" | "pluginProvider">;
|
|
54
52
|
export interface ManagedMcpTool extends ManagedMcpToolDescriptor {
|
|
55
53
|
execute: (args: Record<string, unknown>, options?: {
|
|
56
54
|
conversationPrivacy?: ConversationPrivacy;
|
|
@@ -73,7 +71,6 @@ export declare class McpToolManager {
|
|
|
73
71
|
description: string;
|
|
74
72
|
active: boolean;
|
|
75
73
|
}>;
|
|
76
|
-
activateForSkill(skill: ActiveMcpSkill): Promise<boolean>;
|
|
77
74
|
activateProvider(provider: string): Promise<boolean>;
|
|
78
75
|
close(): Promise<void>;
|
|
79
76
|
/** Return descriptors for all active MCP provider tools, optionally filtered by provider. */
|
|
@@ -96,4 +93,3 @@ export declare class McpToolManager {
|
|
|
96
93
|
}): Promise<PluginMcpToolResult>;
|
|
97
94
|
private toToolDescriptor;
|
|
98
95
|
}
|
|
99
|
-
export {};
|
|
@@ -8,11 +8,15 @@ import type { AgentTurnUsage } from "@/chat/usage";
|
|
|
8
8
|
* the session record's optimistic-concurrency version. `awaiting_auth` means
|
|
9
9
|
* the run parked for user authorization.
|
|
10
10
|
*/
|
|
11
|
+
/** Why a run parked at a safe boundary and may continue. */
|
|
12
|
+
export type AgentSuspensionReason = "timeout" | "yield" | "retry";
|
|
11
13
|
export type AgentRunOutcome = {
|
|
12
14
|
status: "completed";
|
|
13
15
|
result: AgentRunResult;
|
|
14
16
|
} | {
|
|
15
17
|
status: "suspended";
|
|
18
|
+
/** Why this slice stopped. Callers use this to choose wake vs yield. */
|
|
19
|
+
reason: AgentSuspensionReason;
|
|
16
20
|
resumeVersion: number;
|
|
17
21
|
usage?: AgentTurnUsage;
|
|
18
22
|
} | {
|
|
@@ -9,7 +9,7 @@ export declare function createSearchConversationEventsTool(context: ToolRuntimeC
|
|
|
9
9
|
after_seq?: number | null | undefined;
|
|
10
10
|
before_seq?: number | null | undefined;
|
|
11
11
|
limit?: number | null | undefined;
|
|
12
|
-
types?: ("message" | "message_handled" | "assistant_message" | "turn_routed" | "guardian_action_reviewed" | "turn_context" | "structured_event" | "compaction" | "handoff" | "user_message" | "tool_result" | "mcp_provider_connected" | "authorization_requested" | "authorization_completed" | "tool_execution_started" | "message_updated" | "messages_summarized" | "turn_started" | "turn_completed" | "turn_failed" | "subagent_started" | "subagent_ended")[] | null | undefined;
|
|
12
|
+
types?: ("message" | "message_handled" | "assistant_message" | "turn_routed" | "guardian_action_reviewed" | "turn_context" | "structured_event" | "compaction" | "handoff" | "user_message" | "tool_result" | "mcp_provider_connected" | "mcp_provider_connected_unowned" | "authorization_requested" | "authorization_completed" | "tool_execution_started" | "message_updated" | "messages_summarized" | "turn_started" | "turn_completed" | "turn_failed" | "subagent_started" | "subagent_ended")[] | null | undefined;
|
|
13
13
|
};
|
|
14
14
|
execute?: ((input: unknown, options: import("./definition").ToolExecuteOptions) => {
|
|
15
15
|
[x: string]: unknown;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { ManagedMcpTool } from "@/chat/mcp/tool-manager";
|
|
2
2
|
interface CallMcpToolManager {
|
|
3
|
-
activateProvider(provider: string): Promise<boolean>;
|
|
4
3
|
getResolvedActiveTools(): ManagedMcpTool[];
|
|
5
4
|
}
|
|
6
5
|
/** Create the stable dispatcher for active MCP provider tools. */
|
|
@@ -7,13 +7,10 @@ export type LoadSkillResult = {
|
|
|
7
7
|
location?: string;
|
|
8
8
|
path_resolution?: string;
|
|
9
9
|
instructions?: string;
|
|
10
|
-
mcp_provider?: string;
|
|
11
|
-
available_tool_count?: number;
|
|
12
10
|
} & Record<string, unknown>;
|
|
13
|
-
|
|
14
|
-
/** Create the skill-loading tool that injects skill instructions and activates provider catalogs. */
|
|
11
|
+
/** Create the tool that loads skill instructions for the current turn. */
|
|
15
12
|
export declare function createLoadSkillTool(availableSkills: SkillMetadata[], options?: {
|
|
16
|
-
onSkillLoaded?: (skill: Skill) => void |
|
|
13
|
+
onSkillLoaded?: (skill: Skill) => void | Promise<void>;
|
|
17
14
|
}): Omit<import("../definition").AnyToolDefinition, "inputSchema" | "outputSchema" | "prepareArguments" | "execute"> & {
|
|
18
15
|
inputSchema: import("../definition").JsonSchemaObject;
|
|
19
16
|
outputSchema: import("../definition").JsonSchemaObject;
|
|
@@ -4,7 +4,6 @@ import type { McpToolManager } from "@/chat/mcp/tool-manager";
|
|
|
4
4
|
import type { SandboxWorkspace } from "@/chat/sandbox/workspace";
|
|
5
5
|
import type { AgentTurnSurface } from "@/chat/task-execution/checkpoint";
|
|
6
6
|
import type { Skill } from "@/chat/skills";
|
|
7
|
-
import type { LoadSkillMetadata } from "@/chat/tools/skill/load-skill";
|
|
8
7
|
import type { JuniorToolOutput } from "@/chat/tool-support/structured-result";
|
|
9
8
|
import type { WebActor, LocalActor, Actor, SlackActor } from "@/chat/actor";
|
|
10
9
|
import type { SlackActionToken } from "@/chat/slack/action-token";
|
|
@@ -44,7 +43,7 @@ export interface ToolHooks {
|
|
|
44
43
|
* generating tool reports success.
|
|
45
44
|
*/
|
|
46
45
|
writeGeneratedArtifacts?: (files: FileUpload[]) => GeneratedArtifactFileRef[] | Promise<GeneratedArtifactFileRef[]>;
|
|
47
|
-
onSkillLoaded?: (skill: Skill) => void |
|
|
46
|
+
onSkillLoaded?: (skill: Skill) => void | Promise<void>;
|
|
48
47
|
toolOverrides?: {
|
|
49
48
|
imageGenerate?: ImageGenerateToolDeps;
|
|
50
49
|
viewImage?: ViewImageToolDeps;
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
instructionProvenanceFor,
|
|
14
14
|
sanitizePostgresJson,
|
|
15
15
|
withConversationEventLock
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-XTLF7C4I.js";
|
|
17
17
|
import {
|
|
18
18
|
SANDBOX_WORKSPACE_ROOT,
|
|
19
19
|
sleep
|
|
@@ -23,14 +23,14 @@ import {
|
|
|
23
23
|
fenceLock,
|
|
24
24
|
getStateAdapter,
|
|
25
25
|
withLock
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-X6JP6AMX.js";
|
|
27
27
|
import {
|
|
28
28
|
botConfig,
|
|
29
29
|
completeText,
|
|
30
30
|
escapeXml,
|
|
31
31
|
resolveGatewayModel,
|
|
32
32
|
unwrapCurrentInstruction
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-OEECXAGT.js";
|
|
34
34
|
import {
|
|
35
35
|
toStoredSlackActor
|
|
36
36
|
} from "./chunk-HZF5P5UN.js";
|
|
@@ -42,7 +42,7 @@ import {
|
|
|
42
42
|
logException,
|
|
43
43
|
logWarn,
|
|
44
44
|
setSpanAttributes
|
|
45
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-7TZM33YX.js";
|
|
46
46
|
|
|
47
47
|
// src/chat/turn-context-tag.ts
|
|
48
48
|
var TURN_CONTEXT_TAG = "runtime-turn-context";
|
|
@@ -1142,10 +1142,10 @@ function projectConversationEvents(events, options) {
|
|
|
1142
1142
|
}
|
|
1143
1143
|
|
|
1144
1144
|
// src/chat/conversations/projection.ts
|
|
1145
|
-
function connectedMcpProvidersFromEvents(events) {
|
|
1145
|
+
function connectedMcpProvidersFromEvents(events, credentialSubjectId) {
|
|
1146
1146
|
const providers = /* @__PURE__ */ new Set();
|
|
1147
1147
|
for (const event of events) {
|
|
1148
|
-
if (event.data.type === "mcp_provider_connected") {
|
|
1148
|
+
if (event.data.type === "mcp_provider_connected" && event.data.credentialSubjectId === credentialSubjectId) {
|
|
1149
1149
|
providers.add(event.data.provider);
|
|
1150
1150
|
}
|
|
1151
1151
|
}
|
|
@@ -1285,10 +1285,10 @@ async function loadTurnProjection(args) {
|
|
|
1285
1285
|
return projectConversationEvents(historyEvents);
|
|
1286
1286
|
}
|
|
1287
1287
|
async function loadConnectedMcpProviders(args) {
|
|
1288
|
-
const events = await getConversationEventStore().
|
|
1288
|
+
const events = await getConversationEventStore().loadHistory(
|
|
1289
1289
|
args.conversationId
|
|
1290
1290
|
);
|
|
1291
|
-
return connectedMcpProvidersFromEvents(events);
|
|
1291
|
+
return connectedMcpProvidersFromEvents(events, args.credentialSubjectId);
|
|
1292
1292
|
}
|
|
1293
1293
|
function messageTimestamp2(message) {
|
|
1294
1294
|
const timestamp = message.timestamp;
|
|
@@ -1404,12 +1404,18 @@ async function commitMessagesLocked(args, executor) {
|
|
|
1404
1404
|
async function recordMcpProviderConnected(args) {
|
|
1405
1405
|
const eventStore = getConversationEventStore();
|
|
1406
1406
|
const events = await eventStore.loadCurrentHistory(args.conversationId);
|
|
1407
|
-
if (connectedMcpProvidersFromEvents(events).includes(
|
|
1407
|
+
if (connectedMcpProvidersFromEvents(events, args.credentialSubjectId).includes(
|
|
1408
|
+
args.provider
|
|
1409
|
+
)) {
|
|
1408
1410
|
return;
|
|
1409
1411
|
}
|
|
1410
1412
|
await eventStore.append(args.conversationId, [
|
|
1411
1413
|
{
|
|
1412
|
-
data: {
|
|
1414
|
+
data: {
|
|
1415
|
+
type: "mcp_provider_connected",
|
|
1416
|
+
provider: args.provider,
|
|
1417
|
+
credentialSubjectId: args.credentialSubjectId
|
|
1418
|
+
},
|
|
1413
1419
|
createdAtMs: Date.now()
|
|
1414
1420
|
}
|
|
1415
1421
|
]);
|
|
@@ -1,28 +1,34 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createWebAuthorization,
|
|
3
|
+
deleteWebAuthorization
|
|
4
|
+
} from "./chunk-SFYDSI34.js";
|
|
1
5
|
import {
|
|
2
6
|
appendAndEnqueueInboundMessage
|
|
3
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-AYPU5T5L.js";
|
|
4
8
|
import {
|
|
5
9
|
buildDeliveredTurnStatePatch,
|
|
10
|
+
completeAuthPauseTurn,
|
|
6
11
|
finalizeFailedTurnReplyWithEvent,
|
|
7
12
|
getTurnUserMessage,
|
|
8
13
|
processPluginTask,
|
|
9
14
|
scheduleSessionCompletedPluginTasks
|
|
10
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-I4LR7MS2.js";
|
|
11
16
|
import {
|
|
12
17
|
ConversationTurnLifecycleService,
|
|
13
18
|
coerceThreadConversationState,
|
|
14
19
|
getPersistedSandboxState,
|
|
15
20
|
getPersistedThreadState,
|
|
16
21
|
persistThreadStateById
|
|
17
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-67VR4BJK.js";
|
|
18
23
|
import {
|
|
19
24
|
healthReportSchema
|
|
20
25
|
} from "./chunk-UTL3MHPC.js";
|
|
21
26
|
import {
|
|
22
27
|
parseSlackThreadId
|
|
23
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-RCBAXKMB.js";
|
|
24
29
|
import {
|
|
25
30
|
TurnInputCommitLostError,
|
|
31
|
+
abandonTurnRecord,
|
|
26
32
|
buildConversationContext,
|
|
27
33
|
buildDeterministicTurnId,
|
|
28
34
|
getAssistantReplyText,
|
|
@@ -33,6 +39,7 @@ import {
|
|
|
33
39
|
listTurnSummaries,
|
|
34
40
|
loadProjection,
|
|
35
41
|
markConversationMessage,
|
|
42
|
+
markTurnClosed,
|
|
36
43
|
markTurnFailed,
|
|
37
44
|
normalizeConversationText,
|
|
38
45
|
persistConversationMessages,
|
|
@@ -41,22 +48,26 @@ import {
|
|
|
41
48
|
saveTurnCheckpoint,
|
|
42
49
|
startActiveTurn,
|
|
43
50
|
upsertConversationMessage
|
|
44
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-3PCKG4BT.js";
|
|
45
52
|
import {
|
|
46
53
|
normalizeSlackConversationId
|
|
47
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-KTYC3GDO.js";
|
|
48
55
|
import {
|
|
49
56
|
getConversationEventStore,
|
|
50
57
|
getConversationStore
|
|
51
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-XTLF7C4I.js";
|
|
59
|
+
import {
|
|
60
|
+
getSlackBotToken
|
|
61
|
+
} from "./chunk-OEECXAGT.js";
|
|
52
62
|
import {
|
|
53
63
|
credentialContextForActor
|
|
54
64
|
} from "./chunk-RUIXF3YQ.js";
|
|
55
65
|
import {
|
|
56
66
|
logException,
|
|
67
|
+
logWarn,
|
|
57
68
|
setTags,
|
|
58
69
|
withLogContext
|
|
59
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-7TZM33YX.js";
|
|
60
71
|
|
|
61
72
|
// src/handlers/health.ts
|
|
62
73
|
function readHealthReport() {
|
|
@@ -70,20 +81,105 @@ function GET() {
|
|
|
70
81
|
return Response.json(readHealthReport());
|
|
71
82
|
}
|
|
72
83
|
|
|
84
|
+
// src/chat/slack/user.ts
|
|
85
|
+
import { z } from "zod";
|
|
86
|
+
var slackUserInfoSchema = z.object({
|
|
87
|
+
ok: z.literal(true),
|
|
88
|
+
user: z.object({
|
|
89
|
+
name: z.string().nullish(),
|
|
90
|
+
profile: z.object({
|
|
91
|
+
email: z.string().nullish(),
|
|
92
|
+
real_name: z.string().nullish()
|
|
93
|
+
}).optional()
|
|
94
|
+
})
|
|
95
|
+
});
|
|
96
|
+
var USER_CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
97
|
+
var userCache = /* @__PURE__ */ new Map();
|
|
98
|
+
function userCacheKey(teamId, userId) {
|
|
99
|
+
return `${teamId}:${userId}`;
|
|
100
|
+
}
|
|
101
|
+
function readFromCache(teamId, userId) {
|
|
102
|
+
const hit = userCache.get(userCacheKey(teamId, userId));
|
|
103
|
+
if (!hit) return null;
|
|
104
|
+
if (hit.expiresAt < Date.now()) {
|
|
105
|
+
userCache.delete(userCacheKey(teamId, userId));
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
return hit.value;
|
|
109
|
+
}
|
|
110
|
+
function writeToCache(teamId, userId, value) {
|
|
111
|
+
userCache.set(userCacheKey(teamId, userId), {
|
|
112
|
+
value,
|
|
113
|
+
expiresAt: Date.now() + USER_CACHE_TTL_MS
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
async function lookupSlackUser(teamId, userId) {
|
|
117
|
+
if (!teamId || !userId) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
const cached = readFromCache(teamId, userId);
|
|
121
|
+
if (cached) {
|
|
122
|
+
return cached;
|
|
123
|
+
}
|
|
124
|
+
const token = getSlackBotToken();
|
|
125
|
+
if (!token) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
try {
|
|
129
|
+
const response = await fetch(
|
|
130
|
+
`https://slack.com/api/users.info?user=${encodeURIComponent(userId)}`,
|
|
131
|
+
{
|
|
132
|
+
headers: {
|
|
133
|
+
authorization: `Bearer ${token}`
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
);
|
|
137
|
+
if (!response.ok) {
|
|
138
|
+
logWarn("slack.user.lookup.failed", {
|
|
139
|
+
"enduser.id": userId,
|
|
140
|
+
"app.slack.team_id": teamId,
|
|
141
|
+
"http.response.status_code": response.status
|
|
142
|
+
});
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
const parsed = slackUserInfoSchema.safeParse(await response.json());
|
|
146
|
+
if (!parsed.success) {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
const payload = parsed.data;
|
|
150
|
+
const userName = payload.user.name?.trim() || void 0;
|
|
151
|
+
const fullName = payload.user.profile?.real_name?.trim() || void 0;
|
|
152
|
+
const result = {
|
|
153
|
+
userName,
|
|
154
|
+
fullName,
|
|
155
|
+
email: payload.user.profile?.email?.trim() || void 0
|
|
156
|
+
};
|
|
157
|
+
writeToCache(teamId, userId, result);
|
|
158
|
+
return result;
|
|
159
|
+
} catch (error) {
|
|
160
|
+
logWarn("slack.user.lookup.failed", {
|
|
161
|
+
"enduser.id": userId,
|
|
162
|
+
"app.slack.team_id": teamId,
|
|
163
|
+
"exception.message": error instanceof Error ? error.message : String(error)
|
|
164
|
+
});
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
73
169
|
// src/chat/api-turns/work.ts
|
|
74
170
|
import { createHash } from "crypto";
|
|
75
|
-
import { z } from "zod";
|
|
171
|
+
import { z as z2 } from "zod";
|
|
76
172
|
import {
|
|
77
173
|
createWebSource,
|
|
78
174
|
localDestinationSchema
|
|
79
175
|
} from "@sentry/junior-plugin-api";
|
|
80
|
-
var apiTurnMailboxMetadataSchema =
|
|
81
|
-
authorEmail:
|
|
82
|
-
authorFullName:
|
|
83
|
-
authorUserId:
|
|
84
|
-
authorUserName:
|
|
85
|
-
kind:
|
|
86
|
-
messageId:
|
|
176
|
+
var apiTurnMailboxMetadataSchema = z2.object({
|
|
177
|
+
authorEmail: z2.string().email(),
|
|
178
|
+
authorFullName: z2.string().min(1).optional(),
|
|
179
|
+
authorUserId: z2.string().min(1),
|
|
180
|
+
authorUserName: z2.string().min(1).optional(),
|
|
181
|
+
kind: z2.literal("api_turn"),
|
|
182
|
+
messageId: z2.string().min(1)
|
|
87
183
|
}).strict();
|
|
88
184
|
function normalizeEmail(email) {
|
|
89
185
|
return email.trim().toLowerCase();
|
|
@@ -438,6 +534,27 @@ function createApiTurnWorker(options) {
|
|
|
438
534
|
startedAtMs = userMessage.createdAtMs;
|
|
439
535
|
inputMessageIds = [userMessageId];
|
|
440
536
|
} else {
|
|
537
|
+
const authParked = (await listTurnSummaries(context.conversationId)).filter(
|
|
538
|
+
(summary) => summary.surface === "api" && !summary.dispatchId && summary.state === "paused" && summary.resumeReason === "auth"
|
|
539
|
+
);
|
|
540
|
+
for (const parked of authParked) {
|
|
541
|
+
await abandonTurnRecord({
|
|
542
|
+
conversationId: context.conversationId,
|
|
543
|
+
turnId: parked.turnId,
|
|
544
|
+
errorMessage: "Auth-parked session superseded by a new user message"
|
|
545
|
+
});
|
|
546
|
+
markTurnClosed({
|
|
547
|
+
conversation,
|
|
548
|
+
nowMs: Date.now(),
|
|
549
|
+
sessionId: parked.turnId
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
if (authParked.length > 0) {
|
|
553
|
+
await deleteWebAuthorization({
|
|
554
|
+
actorId: actor.userId,
|
|
555
|
+
conversationId: context.conversationId
|
|
556
|
+
});
|
|
557
|
+
}
|
|
441
558
|
upsertConversationMessage(conversation, {
|
|
442
559
|
id: userMessageId,
|
|
443
560
|
role: "user",
|
|
@@ -535,7 +652,10 @@ function createApiTurnWorker(options) {
|
|
|
535
652
|
publishExternally: false,
|
|
536
653
|
source,
|
|
537
654
|
surface: "api",
|
|
538
|
-
|
|
655
|
+
authorization: createWebAuthorization({
|
|
656
|
+
actorId: actor.userId,
|
|
657
|
+
conversationId: context.conversationId
|
|
658
|
+
}),
|
|
539
659
|
state: {
|
|
540
660
|
pendingAuth: conversation.processing.pendingAuth,
|
|
541
661
|
sandboxRef
|
|
@@ -550,14 +670,30 @@ function createApiTurnWorker(options) {
|
|
|
550
670
|
conversation,
|
|
551
671
|
sandboxRef
|
|
552
672
|
});
|
|
673
|
+
},
|
|
674
|
+
recordPendingAuth: async (pendingAuth) => {
|
|
675
|
+
conversation.processing.pendingAuth = pendingAuth;
|
|
676
|
+
await persistThreadStateById(context.conversationId, {
|
|
677
|
+
conversation,
|
|
678
|
+
sandboxRef
|
|
679
|
+
});
|
|
553
680
|
}
|
|
554
681
|
}
|
|
555
682
|
});
|
|
556
683
|
if (outcome.status === "suspended") {
|
|
557
684
|
return { status: "yielded" };
|
|
558
685
|
}
|
|
559
|
-
if (outcome.status
|
|
560
|
-
|
|
686
|
+
if (outcome.status === "awaiting_auth") {
|
|
687
|
+
completeAuthPauseTurn({
|
|
688
|
+
conversation,
|
|
689
|
+
sessionId: turnId
|
|
690
|
+
});
|
|
691
|
+
await persistThreadStateById(context.conversationId, {
|
|
692
|
+
conversation,
|
|
693
|
+
sandboxRef
|
|
694
|
+
});
|
|
695
|
+
await acknowledge();
|
|
696
|
+
return { status: "completed" };
|
|
561
697
|
}
|
|
562
698
|
reply = outcome.result;
|
|
563
699
|
modelFailureCaptureAttempted = reply.diagnostics.outcome !== "success";
|
|
@@ -789,6 +925,7 @@ function formatSlackConversationRedactedLabel(context) {
|
|
|
789
925
|
export {
|
|
790
926
|
readHealthReport,
|
|
791
927
|
GET,
|
|
928
|
+
lookupSlackUser,
|
|
792
929
|
conversationVisibilityFromSlackChannelType,
|
|
793
930
|
resolveSlackChannelTypeFromMessage,
|
|
794
931
|
resolveSlackConversationContext,
|