@sentry/junior 0.74.0 → 0.75.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.
Files changed (73) hide show
  1. package/dist/agent-hooks-2HEB4C3Q.js +33 -0
  2. package/dist/api-reference.d.ts +1 -1
  3. package/dist/app.js +5211 -5316
  4. package/dist/build/copy-build-content.d.ts +1 -1
  5. package/dist/chat/agent-dispatch/context.d.ts +2 -3
  6. package/dist/chat/agent-dispatch/types.d.ts +2 -1
  7. package/dist/chat/config.d.ts +2 -0
  8. package/dist/chat/conversations/configured.d.ts +2 -0
  9. package/dist/chat/credentials/subject.d.ts +3 -3
  10. package/dist/chat/plugins/agent-hooks.d.ts +13 -13
  11. package/dist/chat/plugins/credential-hooks.d.ts +6 -6
  12. package/dist/chat/plugins/db.d.ts +31 -0
  13. package/dist/chat/plugins/logging.d.ts +2 -2
  14. package/dist/chat/plugins/package-discovery.d.ts +2 -1
  15. package/dist/chat/plugins/registry.d.ts +4 -0
  16. package/dist/chat/plugins/state.d.ts +3 -5
  17. package/dist/chat/plugins/types.d.ts +1 -0
  18. package/dist/chat/plugins/validation.d.ts +5 -0
  19. package/dist/chat/prompt.d.ts +11 -1
  20. package/dist/chat/respond.d.ts +10 -1
  21. package/dist/chat/runtime/slack-runtime.d.ts +6 -1
  22. package/dist/chat/sandbox/egress-credentials.d.ts +8 -8
  23. package/dist/chat/sandbox/sandbox.d.ts +2 -2
  24. package/dist/chat/sql/db.d.ts +3 -0
  25. package/dist/chat/sql/executor.d.ts +7 -0
  26. package/dist/chat/sql/neon.d.ts +2 -4
  27. package/dist/chat/sql/postgres.d.ts +6 -0
  28. package/dist/chat/task-execution/state.d.ts +7 -2
  29. package/dist/chat/task-execution/worker.d.ts +1 -1
  30. package/dist/chat/tools/agent-tools.d.ts +2 -2
  31. package/dist/chat/tools/types.d.ts +3 -0
  32. package/dist/{chunk-7Q5YOUUT.js → chunk-2RWFUS5F.js} +47 -10
  33. package/dist/{chunk-YRDS7VKO.js → chunk-62FUNJYS.js} +3 -54
  34. package/dist/{chunk-M4FLLXXD.js → chunk-74HO27II.js} +1 -1
  35. package/dist/chunk-BNJIEFQC.js +115 -0
  36. package/dist/{chunk-YOHFWWBV.js → chunk-C3AM4Z4J.js} +1 -103
  37. package/dist/chunk-D7NFH5GD.js +570 -0
  38. package/dist/chunk-EE6PJWY4.js +130 -0
  39. package/dist/{chunk-CYUI7JU5.js → chunk-EIYL7I4S.js} +1 -1
  40. package/dist/{chunk-GM7HTXYC.js → chunk-FCZO7LAR.js} +13 -2
  41. package/dist/{chunk-2LUZA3LY.js → chunk-JEELK46E.js} +5 -5
  42. package/dist/chunk-MCMROINU.js +12 -0
  43. package/dist/chunk-NPVUAXUE.js +694 -0
  44. package/dist/{chunk-OR6NQJ5E.js → chunk-OJODNL2P.js} +3 -3
  45. package/dist/{chunk-3BYAPS6B.js → chunk-OK4KKR7B.js} +1 -11
  46. package/dist/chunk-OZSPLAQ4.js +71 -0
  47. package/dist/{chunk-KVZL5NZS.js → chunk-Q3XNY442.js} +17 -7
  48. package/dist/{chunk-SQGMG7OD.js → chunk-TQ74BATR.js} +100 -58
  49. package/dist/{chunk-JL2SLRAT.js → chunk-UJ7OTHPO.js} +76 -312
  50. package/dist/{chunk-HYHKTFG2.js → chunk-VNTLUFTY.js} +80 -843
  51. package/dist/chunk-WBZ4M5N5.js +59 -0
  52. package/dist/{chunk-6UP2Z2RZ.js → chunk-XJHDZUGD.js} +7 -7
  53. package/dist/chunk-Y2CM7HXH.js +111 -0
  54. package/dist/{chunk-F6HWCPOC.js → chunk-ZNNTSPNF.js} +1 -1
  55. package/dist/cli/chat.js +52 -2
  56. package/dist/cli/check.js +6 -5
  57. package/dist/cli/snapshot-warmup.js +10 -9
  58. package/dist/cli/upgrade.js +256 -16
  59. package/dist/db-A3ILH67H.js +20 -0
  60. package/dist/handlers/sandbox-egress-route.d.ts +4 -0
  61. package/dist/handlers/slack-webhook.d.ts +4 -0
  62. package/dist/handlers/webhooks.d.ts +6 -13
  63. package/dist/nitro.js +34 -89
  64. package/dist/plugin-module.d.ts +21 -0
  65. package/dist/plugins-OMJKLRJ2.js +13 -0
  66. package/dist/plugins.d.ts +6 -4
  67. package/dist/registry-NLZFIW23.js +46 -0
  68. package/dist/reporting/conversations.d.ts +3 -3
  69. package/dist/reporting.d.ts +6 -5
  70. package/dist/reporting.js +23 -17
  71. package/dist/{runner-27NP2TEO.js → runner-LUQZ5G67.js} +18 -13
  72. package/dist/validation-VMCPP3YO.js +15 -0
  73. package/package.json +11 -9
@@ -1,4 +1,4 @@
1
- /** Copy app directory and plugin manifests into the server output. */
1
+ /** Copy app and declared plugin package content into the server output. */
2
2
  export declare function copyAppAndPluginContent(cwd: string, serverRoot: string, packageNames?: unknown): void;
3
3
  /** Copy extra file patterns into server output for files the bundler cannot trace. */
4
4
  export declare function copyIncludedFiles(cwd: string, serverRoot: string, patterns?: unknown): void;
@@ -1,7 +1,6 @@
1
- import type { HeartbeatHookContext } from "@sentry/junior-plugin-api";
1
+ import type { HeartbeatHookContext, PluginRegistration } from "@sentry/junior-plugin-api";
2
2
  /** Build the plugin-scoped heartbeat context that gates durable dispatch access. */
3
3
  export declare function createHeartbeatContext(args: {
4
- legacyStatePrefixes?: string[];
5
4
  nowMs: number;
6
- plugin: string;
5
+ plugin: string | PluginRegistration;
7
6
  }): HeartbeatHookContext;
@@ -1,4 +1,4 @@
1
- import type { DispatchOptions, SlackDestination } from "@sentry/junior-plugin-api";
1
+ import type { DispatchOptions, Source, SlackDestination } from "@sentry/junior-plugin-api";
2
2
  import type { CredentialSubject, CredentialSystemActor } from "@/chat/credentials/context";
3
3
  export type DispatchStatus = "pending" | "running" | "awaiting_resume" | "completed" | "failed" | "blocked";
4
4
  export type SlackDispatchOptions = Omit<DispatchOptions, "destination"> & {
@@ -23,6 +23,7 @@ export interface DispatchRecord {
23
23
  metadata?: Record<string, string>;
24
24
  plugin: string;
25
25
  resultMessageTs?: string;
26
+ source: Source;
26
27
  status: DispatchStatus;
27
28
  updatedAtMs: number;
28
29
  version: number;
@@ -19,11 +19,13 @@ export interface AdvisorConfig {
19
19
  modelId: string;
20
20
  thinkingLevel: AdvisorThinkingLevel;
21
21
  }
22
+ export type SqlDriver = "neon" | "postgres";
22
23
  export interface ChatConfig {
23
24
  bot: BotConfig;
24
25
  functionMaxDurationSeconds: number;
25
26
  sql: {
26
27
  databaseUrl?: string;
28
+ driver: SqlDriver;
27
29
  };
28
30
  slack: {
29
31
  botToken?: string;
@@ -3,3 +3,5 @@ import type { ConversationStore } from "./store";
3
3
  export declare function getConfiguredConversationStore(): ConversationStore;
4
4
  /** Return whether conversation records use the configured SQL store. */
5
5
  export declare function hasConfiguredSqlConversationStore(): boolean;
6
+ /** Close the configured SQL conversation store if one has been created. */
7
+ export declare function closeConfiguredConversationStore(): Promise<void>;
@@ -1,15 +1,15 @@
1
- import type { AgentPluginCredentialSubject } from "@sentry/junior-plugin-api";
1
+ import type { PluginCredentialSubject } from "@sentry/junior-plugin-api";
2
2
  import type { CredentialSubject } from "@/chat/credentials/context";
3
3
  /** Create a delegated user credential subject for a verified Slack DM turn. */
4
4
  export declare function createSlackDirectCredentialSubject(input: {
5
5
  channelId: string | undefined;
6
6
  teamId: string | undefined;
7
7
  userId: string | undefined;
8
- }): AgentPluginCredentialSubject | undefined;
8
+ }): PluginCredentialSubject | undefined;
9
9
  /** Bind a delegated user subject to the Slack DM destination being dispatched. */
10
10
  export declare function bindSlackDirectCredentialSubject(input: {
11
11
  channelId: string;
12
- subject: AgentPluginCredentialSubject;
12
+ subject: PluginCredentialSubject;
13
13
  teamId: string;
14
14
  }): CredentialSubject | undefined;
15
15
  /** Verify that a delegated subject was signed for the dispatch destination. */
@@ -1,10 +1,10 @@
1
- import type { AgentPluginConversations, AgentPluginRoute, PluginOperationalReport, SlackConversationLink, JuniorPluginRegistration } from "@sentry/junior-plugin-api";
1
+ import type { PluginConversations, PluginRoute, PluginOperationalReport, SlackConversationLink, PluginRegistration } from "@sentry/junior-plugin-api";
2
2
  import type { ToolDefinition } from "@/chat/tools/definition";
3
3
  import type { ToolRuntimeContext } from "@/chat/tools/types";
4
4
  import type { SandboxInstance } from "@/chat/sandbox/workspace";
5
5
  import type { Requester } from "@/chat/requester";
6
6
  /** Signal that a plugin intentionally denied a tool execution. */
7
- export declare class AgentPluginHookDeniedError extends Error {
7
+ export declare class PluginHookDeniedError extends Error {
8
8
  constructor(message: string);
9
9
  }
10
10
  export interface ToolHookInput {
@@ -15,28 +15,28 @@ export interface ToolHookResult {
15
15
  env: Record<string, string>;
16
16
  input: Record<string, unknown>;
17
17
  }
18
- export interface AgentPluginRouteRegistration extends AgentPluginRoute {
18
+ export interface PluginRouteRegistration extends PluginRoute {
19
19
  pluginName: string;
20
20
  }
21
- export interface AgentPluginHookRunner {
21
+ export interface PluginHookRunner {
22
22
  beforeToolExecute(input: ToolHookInput): Promise<ToolHookResult>;
23
23
  prepareSandbox(sandbox: SandboxInstance): Promise<void>;
24
24
  }
25
25
  /** Validate plugin identity before it can affect process-wide hooks. */
26
- export declare function validateAgentPlugins(plugins: JuniorPluginRegistration[]): void;
26
+ export declare function validatePlugins(plugins: PluginRegistration[]): void;
27
27
  /** Replace runtime hook plugins and return the previous list for rollback. */
28
- export declare function setAgentPlugins(plugins: JuniorPluginRegistration[]): JuniorPluginRegistration[];
28
+ export declare function setPlugins(nextPlugins: PluginRegistration[]): PluginRegistration[];
29
29
  /** Return the current runtime hook plugins without exposing mutable state. */
30
- export declare function getAgentPlugins(): JuniorPluginRegistration[];
30
+ export declare function getPlugins(): PluginRegistration[];
31
31
  /** Collect turn-scoped tools exposed by plugins. */
32
- export declare function getAgentPluginTools(context: ToolRuntimeContext): Record<string, ToolDefinition<any>>;
32
+ export declare function getPluginTools(context: ToolRuntimeContext): Record<string, ToolDefinition<any>>;
33
33
  /** Collect route handlers exposed by plugins for app-level mounting. */
34
- export declare function getAgentPluginRoutes(): AgentPluginRouteRegistration[];
34
+ export declare function getPluginRoutes(): PluginRouteRegistration[];
35
35
  /** Resolve the first plugin conversation URL for finalized Slack footers. */
36
- export declare function getAgentPluginSlackConversationLink(conversationId: string): SlackConversationLink | undefined;
36
+ export declare function getPluginSlackConversationLink(conversationId: string): SlackConversationLink | undefined;
37
37
  /** Collect read-only operational summaries exposed by plugins. */
38
- export declare function getAgentPluginOperationalReports(nowMs: number, conversations: AgentPluginConversations): Promise<PluginOperationalReport[]>;
38
+ export declare function getPluginOperationalReports(nowMs: number, conversations: PluginConversations): Promise<PluginOperationalReport[]>;
39
39
  /** Create one runner over runtime hook plugins registered by the app. */
40
- export declare function createAgentPluginHookRunner(input?: {
40
+ export declare function createPluginHookRunner(input?: {
41
41
  requester?: Requester;
42
- }): AgentPluginHookRunner;
42
+ }): PluginHookRunner;
@@ -1,4 +1,4 @@
1
- import { type AgentPluginCredentialResult, type AgentPluginGrant, type AgentPluginProviderAccount } from "@sentry/junior-plugin-api";
1
+ import { type PluginCredentialResult, type PluginGrant, type PluginProviderAccount } from "@sentry/junior-plugin-api";
2
2
  import type { StoredTokens, UserTokenStore } from "@/chat/credentials/user-token-store";
3
3
  export interface EgressGrantInput {
4
4
  bodyText?: string;
@@ -7,9 +7,9 @@ export interface EgressGrantInput {
7
7
  upstreamUrl: URL;
8
8
  }
9
9
  /** Ask a plugin which grant an outbound request needs. */
10
- export declare function selectPluginGrant(input: EgressGrantInput): Promise<AgentPluginGrant | undefined>;
10
+ export declare function selectPluginGrant(input: EgressGrantInput): Promise<PluginGrant | undefined>;
11
11
  export interface EgressResponseInput {
12
- grant: AgentPluginGrant;
12
+ grant: PluginGrant;
13
13
  method: string;
14
14
  provider: string;
15
15
  response: {
@@ -40,7 +40,7 @@ export interface IssueCredentialInput {
40
40
  type: "user";
41
41
  userId: string;
42
42
  };
43
- grant: AgentPluginGrant;
43
+ grant: PluginGrant;
44
44
  provider: string;
45
45
  userTokenStore: UserTokenStore;
46
46
  }
@@ -48,6 +48,6 @@ export interface IssueCredentialInput {
48
48
  export declare function resolvePluginOAuthAccount(input: {
49
49
  provider: string;
50
50
  tokens: StoredTokens;
51
- }): Promise<AgentPluginProviderAccount | undefined>;
51
+ }): Promise<PluginProviderAccount | undefined>;
52
52
  /** Ask a plugin to issue headers or describe why the selected grant is unavailable. */
53
- export declare function issuePluginCredential(input: IssueCredentialInput): Promise<AgentPluginCredentialResult>;
53
+ export declare function issuePluginCredential(input: IssueCredentialInput): Promise<PluginCredentialResult>;
@@ -0,0 +1,31 @@
1
+ import type { PluginDb, PluginRegistration } from "@sentry/junior-plugin-api";
2
+ import type { JuniorSqlMigrationExecutor } from "@/chat/sql/db";
3
+ export interface PluginMigration {
4
+ checksum: string;
5
+ filename: string;
6
+ id: string;
7
+ pluginName: string;
8
+ sql: string;
9
+ }
10
+ export interface PluginMigrationRoot {
11
+ /** Absolute path to the plugin's migrations directory. */
12
+ dir: string;
13
+ pluginName: string;
14
+ }
15
+ export interface PluginMigrationResult {
16
+ existing: number;
17
+ migrated: number;
18
+ scanned: number;
19
+ }
20
+ /** Close the configured plugin DB executor if one has been created. */
21
+ export declare function closeConfiguredPluginDb(): Promise<void>;
22
+ /** Adapt the shared Junior SQL executor to the plugin-facing DB surface. */
23
+ export declare function createPluginDbForExecutor(executor: JuniorSqlMigrationExecutor): PluginDb;
24
+ /** Return a configured plugin DB only for plugins that declare database usage. */
25
+ export declare function getPluginDbForRegistration(registration: PluginRegistration): PluginDb | undefined;
26
+ /** Fail early when a plugin declares DB access without SQL config. */
27
+ export declare function validatePluginDatabaseRequirements(registrations: PluginRegistration[]): void;
28
+ /** Read committed SQL migration artifacts for one enabled plugin root. */
29
+ export declare function readPluginMigrations(root: PluginMigrationRoot): PluginMigration[];
30
+ /** Apply plugin-owned SQL migrations after core Junior migrations. */
31
+ export declare function migratePluginSchemas(executor: JuniorSqlMigrationExecutor, migrations: readonly PluginMigration[]): Promise<PluginMigrationResult>;
@@ -1,3 +1,3 @@
1
- import type { AgentPluginLogger } from "@sentry/junior-plugin-api";
1
+ import type { PluginLogger } from "@sentry/junior-plugin-api";
2
2
  /** Create the host logger exposed to plugin hooks. */
3
- export declare function createAgentPluginLogger(plugin: string): AgentPluginLogger;
3
+ export declare function createPluginLogger(plugin: string): PluginLogger;
@@ -2,8 +2,9 @@ export interface InstalledPluginPackageContent {
2
2
  packageNames: string[];
3
3
  packages: {
4
4
  dir: string;
5
+ hasMigrationsDir: boolean;
5
6
  hasSkillsDir: boolean;
6
- name: string;
7
+ packageName: string;
7
8
  }[];
8
9
  manifestRoots: string[];
9
10
  skillRoots: string[];
@@ -10,6 +10,10 @@ export declare function getPluginPackageContent(): InstalledPluginPackageContent
10
10
  export declare function getPluginCatalogSignature(): string;
11
11
  export declare function getPluginCapabilityProviders(): CapabilityProviderDefinition[];
12
12
  export declare function getPluginProviders(): PluginDefinition[];
13
+ export declare function getPluginMigrationRoots(): {
14
+ dir: string;
15
+ pluginName: string;
16
+ }[];
13
17
  export declare function getPluginMcpProviders(): PluginDefinition[];
14
18
  export declare function getPluginRuntimeDependencies(): PluginRuntimeDependency[];
15
19
  export declare function getPluginRuntimePostinstall(): PluginRuntimePostinstallCommand[];
@@ -1,6 +1,4 @@
1
- import type { AgentPluginState } from "@sentry/junior-plugin-api";
2
- export interface PluginStateOptions {
3
- legacyStatePrefixes?: string[];
4
- }
1
+ import type { PluginState } from "@sentry/junior-plugin-api";
2
+ import type { StateAdapter } from "chat";
5
3
  /** Create a durable state namespace scoped to one plugin. */
6
- export declare function createPluginState(plugin: string, options?: PluginStateOptions): AgentPluginState;
4
+ export declare function createPluginState(plugin: string, adapter?: StateAdapter): PluginState;
@@ -143,6 +143,7 @@ export interface PluginBrokerDeps {
143
143
  export interface PluginDefinition {
144
144
  manifest: PluginManifest;
145
145
  dir: string;
146
+ migrationsDir?: string;
146
147
  skillsDir?: string;
147
148
  }
148
149
  export interface InlinePluginManifestDefinition {
@@ -0,0 +1,5 @@
1
+ import type { PluginRegistration } from "@sentry/junior-plugin-api";
2
+ /** Validate hook registrations against the loaded plugin manifest catalog. */
3
+ export declare function validatePluginRegistrations(registrations: PluginRegistration[]): void;
4
+ /** Validate credential hook registrations against the loaded plugin manifests. */
5
+ export declare function validatePluginEgressCredentialHooks(registrations: PluginRegistration[]): void;
@@ -2,7 +2,7 @@ import type { SlackConversationContext } from "@/chat/slack/conversation-context
2
2
  import type { ThreadArtifactsState } from "@/chat/state/artifacts";
3
3
  import type { SkillMetadata, SkillInvocation } from "@/chat/skills";
4
4
  import type { ActiveMcpCatalogSummary } from "@/chat/tools/skill/mcp-tool-summary";
5
- import type { Source } from "@sentry/junior-plugin-api";
5
+ import type { Destination, Source } from "@sentry/junior-plugin-api";
6
6
  export declare const JUNIOR_PERSONALITY: string;
7
7
  export declare const JUNIOR_WORLD: string | null;
8
8
  interface ToolPromptContext {
@@ -19,6 +19,16 @@ type TurnContextPromptInput = {
19
19
  conversationId?: string;
20
20
  slackConversation?: SlackConversationContext;
21
21
  };
22
+ dispatch?: {
23
+ actor?: {
24
+ id: string;
25
+ type: string;
26
+ };
27
+ destination: Destination;
28
+ metadata?: Record<string, string>;
29
+ plugin?: string;
30
+ source: Source;
31
+ };
22
32
  invocation: SkillInvocation | null;
23
33
  requester?: {
24
34
  userName?: string;
@@ -1,4 +1,4 @@
1
- import type { Destination } from "@sentry/junior-plugin-api";
1
+ import type { Destination, Source } from "@sentry/junior-plugin-api";
2
2
  import type { ChannelConfigurationService } from "@/chat/configuration/types";
3
3
  import type { ThreadArtifactsState } from "@/chat/state/artifacts";
4
4
  import type { ConversationPendingAuthState } from "@/chat/state/conversation";
@@ -18,9 +18,18 @@ export interface ReplyRequestContext {
18
18
  skillDirs?: string[];
19
19
  credentialContext?: CredentialContext;
20
20
  requester?: Requester;
21
+ source?: Source;
21
22
  slackConversation?: SlackConversationContext;
22
23
  destination: Destination;
23
24
  surface?: AgentTurnSurface;
25
+ dispatch?: {
26
+ actor?: {
27
+ id: string;
28
+ type: string;
29
+ };
30
+ metadata?: Record<string, string>;
31
+ plugin?: string;
32
+ };
24
33
  correlation?: {
25
34
  conversationId?: string;
26
35
  threadId?: string;
@@ -19,9 +19,14 @@ export interface AssistantLifecycleEvent {
19
19
  threadTs: string;
20
20
  userId?: string;
21
21
  }
22
+ export interface SteeringCandidateMessage {
23
+ activeRequest: boolean;
24
+ inboundMessageId: string;
25
+ message: Message;
26
+ }
22
27
  export interface ReplyHooks {
23
28
  beforeFirstResponsePost?: () => Promise<void>;
24
- drainSteeringMessages?: (inject: (messages: Message[]) => Promise<void>) => Promise<Message[]>;
29
+ drainSteeringMessages?: (inject: (messages: SteeringCandidateMessage[]) => Promise<readonly string[] | void>) => Promise<void>;
25
30
  messageContext?: MessageContext;
26
31
  onInputCommitted?: () => Promise<void>;
27
32
  onToolInvocation?: (invocation: TurnToolInvocation) => void;
@@ -1,22 +1,22 @@
1
- import type { AgentPluginAuthorization, AgentPluginGrant } from "@sentry/junior-plugin-api";
1
+ import type { PluginAuthorization, PluginGrant } from "@sentry/junior-plugin-api";
2
2
  import { type SandboxEgressCredentialContext, type SandboxEgressCredentialLease } from "@/chat/sandbox/egress-session";
3
3
  export type SandboxEgressGrantSelection = {
4
- grant: AgentPluginGrant;
4
+ grant: PluginGrant;
5
5
  source: "plugin";
6
6
  } | {
7
- grant: AgentPluginGrant;
7
+ grant: PluginGrant;
8
8
  source: "broker";
9
9
  };
10
10
  export type SandboxEgressCredentialErrorKind = "auth_required" | "unavailable";
11
11
  /** Signals that egress selected a grant but could not issue credential headers. */
12
12
  export declare class SandboxEgressCredentialError extends Error {
13
- readonly authorization?: AgentPluginAuthorization;
14
- readonly grant: AgentPluginGrant;
13
+ readonly authorization?: PluginAuthorization;
14
+ readonly grant: PluginGrant;
15
15
  readonly kind: SandboxEgressCredentialErrorKind;
16
16
  readonly provider: string;
17
17
  constructor(input: {
18
- authorization?: AgentPluginAuthorization;
19
- grant: AgentPluginGrant;
18
+ authorization?: PluginAuthorization;
19
+ grant: PluginGrant;
20
20
  kind: SandboxEgressCredentialErrorKind;
21
21
  message: string;
22
22
  provider: string;
@@ -30,7 +30,7 @@ export declare function selectSandboxEgressGrant(input: {
30
30
  upstreamUrl: URL;
31
31
  }): Promise<SandboxEgressGrantSelection>;
32
32
  /** Resolve the authorization flow attached to a broker-selected egress grant. */
33
- export declare function authorizationForSandboxEgressGrant(provider: string, selection: SandboxEgressGrantSelection): AgentPluginAuthorization | undefined;
33
+ export declare function authorizationForSandboxEgressGrant(provider: string, selection: SandboxEgressGrantSelection): PluginAuthorization | undefined;
34
34
  /** Return a cached or newly issued credential lease for a selected grant. */
35
35
  export declare function sandboxEgressCredentialLease(provider: string, selection: SandboxEgressGrantSelection, context: SandboxEgressCredentialContext): Promise<SandboxEgressCredentialLease>;
36
36
  /** Return whether a credential lease can modify requests to the target host. */
@@ -2,7 +2,7 @@ import { type LogContext } from "@/chat/logging";
2
2
  import { type SandboxEgressAuthRequiredSignal, type SandboxEgressPermissionDeniedSignal } from "@/chat/sandbox/egress-session";
3
3
  import type { SandboxEgressTracePropagationConfig } from "@/chat/sandbox/egress-tracing";
4
4
  import type { CredentialContext } from "@/chat/credentials/context";
5
- import type { AgentPluginHookRunner } from "@/chat/plugins/agent-hooks";
5
+ import type { PluginHookRunner } from "@/chat/plugins/agent-hooks";
6
6
  import type { SandboxInstance } from "@/chat/sandbox/workspace";
7
7
  import type { SkillMetadata } from "@/chat/skills";
8
8
  interface SandboxExecutionInput {
@@ -49,7 +49,7 @@ export declare function createSandboxExecutor(options?: {
49
49
  traceContext?: LogContext;
50
50
  tracePropagation?: SandboxEgressTracePropagationConfig;
51
51
  credentialEgress?: CredentialContext;
52
- agentHooks?: AgentPluginHookRunner;
52
+ agentHooks?: PluginHookRunner;
53
53
  onSandboxAcquired?: (sandbox: SandboxAcquiredState) => void | Promise<void>;
54
54
  runBashCustomCommand?: (command: string) => Promise<{
55
55
  handled: boolean;
@@ -18,3 +18,6 @@ export interface JuniorSqlMigrationExecutor extends JuniorSqlDatabase {
18
18
  execute(statement: string, params?: readonly unknown[]): Promise<void>;
19
19
  query<T = unknown>(statement: string, params?: readonly unknown[]): Promise<T[]>;
20
20
  }
21
+ export interface JuniorSqlExecutor extends JuniorSqlMigrationExecutor {
22
+ close(): Promise<void>;
23
+ }
@@ -0,0 +1,7 @@
1
+ import type { JuniorSqlExecutor } from "./db";
2
+ import type { SqlDriver } from "@/chat/config";
3
+ /** Create the SQL executor appropriate for the configured database URL. */
4
+ export declare function createJuniorSqlExecutor(args: {
5
+ connectionString: string;
6
+ driver: SqlDriver;
7
+ }): JuniorSqlExecutor;
@@ -1,8 +1,6 @@
1
- import type { JuniorSqlMigrationExecutor } from "./db";
1
+ import type { JuniorSqlExecutor } from "./db";
2
2
  /** Neon-backed SQL executor with an owned connection pool lifecycle. */
3
- export interface NeonJuniorSqlExecutor extends JuniorSqlMigrationExecutor {
4
- close(): Promise<void>;
5
- }
3
+ export type NeonJuniorSqlExecutor = JuniorSqlExecutor;
6
4
  /** Create the shared Neon-backed Junior SQL executor. */
7
5
  export declare function createNeonJuniorSqlExecutor(args: {
8
6
  connectionString: string;
@@ -0,0 +1,6 @@
1
+ import type { JuniorSqlExecutor } from "./db";
2
+ /** Create the shared Node Postgres-backed Junior SQL executor. */
3
+ export declare function createPostgresJuniorSqlExecutor(args: {
4
+ applicationName?: string;
5
+ connectionString: string;
6
+ }): JuniorSqlExecutor;
@@ -146,10 +146,15 @@ export declare function checkInConversationWork(args: {
146
146
  nowMs?: number;
147
147
  state?: StateAdapter;
148
148
  }): Promise<boolean>;
149
- /** Drain pending mailbox entries after the caller has durably injected them. */
149
+ /**
150
+ * Drain pending mailbox entries after the caller acknowledges durable handling.
151
+ *
152
+ * Returning ids acknowledges only that subset; returning nothing acknowledges
153
+ * every offered pending entry.
154
+ */
150
155
  export declare function drainConversationMailbox(args: {
151
156
  conversationId: string;
152
- inject: (messages: InboundMessage[]) => Promise<void>;
157
+ inject: (messages: InboundMessage[]) => Promise<readonly string[] | void>;
153
158
  leaseToken: string;
154
159
  nowMs?: number;
155
160
  state?: StateAdapter;
@@ -9,7 +9,7 @@ export interface ConversationWorkerContext {
9
9
  checkIn(): Promise<boolean>;
10
10
  conversationId: string;
11
11
  destination: Destination;
12
- drainMailbox(inject: (messages: InboundMessage[]) => Promise<void>): Promise<InboundMessage[]>;
12
+ drainMailbox(inject: (messages: InboundMessage[]) => Promise<readonly string[] | void>): Promise<InboundMessage[]>;
13
13
  leaseToken: string;
14
14
  shouldYield(): boolean;
15
15
  }
@@ -6,6 +6,6 @@ import type { AssistantStatusSpec } from "@/chat/slack/assistant-thread/status";
6
6
  import type { SandboxExecutor } from "@/chat/sandbox/sandbox";
7
7
  import type { SkillSandbox } from "@/chat/sandbox/skill-sandbox";
8
8
  import type { ToolDefinition } from "@/chat/tools/definition";
9
- import type { AgentPluginHookRunner } from "@/chat/plugins/agent-hooks";
9
+ import type { PluginHookRunner } from "@/chat/plugins/agent-hooks";
10
10
  /** Wrap tool definitions into Pi Agent tool objects with logging, validation, and sandbox execution. */
11
- export declare function createAgentTools(tools: Record<string, ToolDefinition<any>>, sandbox: SkillSandbox, spanContext: LogContext, onStatus?: (status: AssistantStatusSpec) => void | Promise<void>, sandboxExecutor?: SandboxExecutor, pluginAuthOrchestration?: PluginAuthOrchestration, onToolCall?: (toolName: string, params: Record<string, unknown>) => void, agentHooks?: AgentPluginHookRunner, conversationPrivacy?: ConversationPrivacy): AgentTool[];
11
+ export declare function createAgentTools(tools: Record<string, ToolDefinition<any>>, sandbox: SkillSandbox, spanContext: LogContext, onStatus?: (status: AssistantStatusSpec) => void | Promise<void>, sandboxExecutor?: SandboxExecutor, pluginAuthOrchestration?: PluginAuthOrchestration, onToolCall?: (toolName: string, params: Record<string, unknown>) => void, agentHooks?: PluginHookRunner, conversationPrivacy?: ConversationPrivacy): AgentTool[];
@@ -2,6 +2,7 @@ import type { FileUpload } from "chat";
2
2
  import type { Destination, LocalDestination, LocalSource, SlackDestination, SlackSource, Source } from "@sentry/junior-plugin-api";
3
3
  import type { McpToolManager } from "@/chat/mcp/tool-manager";
4
4
  import type { SandboxWorkspace } from "@/chat/sandbox/workspace";
5
+ import type { AgentTurnSurface } from "@/chat/state/turn-session";
5
6
  import type { ThreadArtifactsState } from "@/chat/state/artifacts";
6
7
  import type { Skill } from "@/chat/skills";
7
8
  import type { LoadSkillMetadata } from "@/chat/tools/skill/load-skill";
@@ -48,6 +49,8 @@ interface BaseToolRuntimeContext {
48
49
  requester?: Requester;
49
50
  /** Runtime-owned source where this invocation came from. */
50
51
  source: Source;
52
+ /** Runtime surface that owns final delivery semantics for this turn. */
53
+ surface?: AgentTurnSurface;
51
54
  userText?: string;
52
55
  artifactState?: ThreadArtifactsState;
53
56
  configuration?: Record<string, unknown>;
@@ -2,15 +2,19 @@ import {
2
2
  discoverInstalledPluginPackageContent,
3
3
  normalizePluginPackageNames,
4
4
  pluginRoots
5
- } from "./chunk-KVZL5NZS.js";
5
+ } from "./chunk-Q3XNY442.js";
6
6
  import {
7
7
  parseActorUserId
8
- } from "./chunk-CYUI7JU5.js";
8
+ } from "./chunk-EIYL7I4S.js";
9
9
  import {
10
10
  logInfo,
11
11
  logWarn,
12
12
  setSpanAttributes
13
- } from "./chunk-3BYAPS6B.js";
13
+ } from "./chunk-OK4KKR7B.js";
14
+
15
+ // src/chat/plugins/registry.ts
16
+ import { readFileSync, readdirSync, statSync } from "fs";
17
+ import path from "path";
14
18
 
15
19
  // src/chat/plugins/manifest.ts
16
20
  import { z } from "zod";
@@ -1064,10 +1068,6 @@ function parseInlinePluginManifest(manifest, dir, config) {
1064
1068
  });
1065
1069
  }
1066
1070
 
1067
- // src/chat/plugins/registry.ts
1068
- import { readFileSync, readdirSync, statSync } from "fs";
1069
- import path from "path";
1070
-
1071
1071
  // src/chat/plugins/auth/oauth-bearer-broker.ts
1072
1072
  import { randomUUID as randomUUID2 } from "crypto";
1073
1073
 
@@ -1523,6 +1523,7 @@ function createLoadedPluginState(signature) {
1523
1523
  return {
1524
1524
  signature,
1525
1525
  pluginDefinitions: [],
1526
+ pluginMigrationRoots: /* @__PURE__ */ new Map(),
1526
1527
  capabilityToPlugin: /* @__PURE__ */ new Map(),
1527
1528
  domainToPlugin: /* @__PURE__ */ new Map(),
1528
1529
  pluginConfigKeys: /* @__PURE__ */ new Set(),
@@ -1538,7 +1539,7 @@ function providerDomains(manifest) {
1538
1539
  ])
1539
1540
  ].sort((left, right) => left.localeCompare(right));
1540
1541
  }
1541
- function registerPluginManifest(state, manifest, pluginDir, skillsDir) {
1542
+ function registerPluginManifest(state, manifest, pluginDir, skillsDir, migrationsDir) {
1542
1543
  if (state.pluginsByName.has(manifest.name)) {
1543
1544
  throw new Error(`Duplicate plugin name "${manifest.name}"`);
1544
1545
  }
@@ -1560,10 +1561,14 @@ function registerPluginManifest(state, manifest, pluginDir, skillsDir) {
1560
1561
  const definition = {
1561
1562
  manifest,
1562
1563
  dir: pluginDir,
1564
+ ...migrationsDir ? { migrationsDir } : {},
1563
1565
  ...skillsDir ? { skillsDir } : {}
1564
1566
  };
1565
1567
  state.pluginDefinitions.push(definition);
1566
1568
  state.pluginsByName.set(manifest.name, definition);
1569
+ if (definition.migrationsDir) {
1570
+ state.pluginMigrationRoots.set(manifest.name, definition.migrationsDir);
1571
+ }
1567
1572
  for (const cap of manifest.capabilities) {
1568
1573
  state.capabilityToPlugin.set(cap, definition);
1569
1574
  }
@@ -1613,6 +1618,14 @@ function getPluginCatalogSource() {
1613
1618
  signature: JSON.stringify({
1614
1619
  inlineManifests,
1615
1620
  manifestRoots,
1621
+ packages: packagedContent.packages.map((pkg) => ({
1622
+ dir: path.resolve(pkg.dir),
1623
+ hasMigrationsDir: pkg.hasMigrationsDir,
1624
+ hasSkillsDir: pkg.hasSkillsDir,
1625
+ packageName: pkg.packageName
1626
+ })).sort(
1627
+ (left, right) => left.packageName.localeCompare(right.packageName)
1628
+ ),
1616
1629
  packagedSkillRoots,
1617
1630
  packageNames: [...packagedContent.packageNames].sort(),
1618
1631
  pluginConfig: pluginConfig ?? {}
@@ -1640,19 +1653,34 @@ function clonePluginCatalogConfig(config) {
1640
1653
  };
1641
1654
  }
1642
1655
  function packageContentByName(packagedContent, packageName) {
1643
- return packagedContent.packages.find((pkg) => pkg.name === packageName);
1656
+ return packagedContent.packages.find(
1657
+ (pkg) => pkg.packageName === packageName
1658
+ );
1644
1659
  }
1645
1660
  function registerInlineManifests(state, source) {
1661
+ const migrationOwners = /* @__PURE__ */ new Map();
1646
1662
  for (const definition of source.inlineManifests) {
1647
1663
  const pkg = definition.packageName ? packageContentByName(source.packagedContent, definition.packageName) : void 0;
1648
1664
  const dir = pkg?.dir ?? process.cwd();
1649
1665
  const skillsDir = pkg?.hasSkillsDir ? path.join(pkg.dir, "skills") : void 0;
1666
+ const migrationsDir = pkg?.hasMigrationsDir && statSync(path.join(pkg.dir, "migrations"), {
1667
+ throwIfNoEntry: false
1668
+ })?.isDirectory() ? path.join(pkg.dir, "migrations") : void 0;
1650
1669
  const manifest = parseInlinePluginManifest(
1651
1670
  definition.manifest,
1652
1671
  dir,
1653
1672
  pluginConfig
1654
1673
  );
1655
- registerPluginManifest(state, manifest, dir, skillsDir);
1674
+ if (migrationsDir) {
1675
+ const owner = migrationOwners.get(migrationsDir);
1676
+ if (owner) {
1677
+ throw new Error(
1678
+ `Plugin "${manifest.name}" cannot share migrations directory with plugin "${owner}"`
1679
+ );
1680
+ }
1681
+ migrationOwners.set(migrationsDir, manifest.name);
1682
+ }
1683
+ registerPluginManifest(state, manifest, dir, skillsDir, migrationsDir);
1656
1684
  }
1657
1685
  }
1658
1686
  function discoverConfiguredPluginPackageContent() {
@@ -1801,6 +1829,10 @@ function getPluginCapabilityProviders() {
1801
1829
  function getPluginProviders() {
1802
1830
  return [...ensurePluginsLoaded().pluginDefinitions];
1803
1831
  }
1832
+ function getPluginMigrationRoots() {
1833
+ const state = ensurePluginsLoaded();
1834
+ return [...state.pluginMigrationRoots.entries()].map(([pluginName, dir]) => ({ pluginName, dir })).sort((left, right) => left.pluginName.localeCompare(right.pluginName));
1835
+ }
1804
1836
  function getPluginMcpProviders() {
1805
1837
  return ensurePluginsLoaded().pluginDefinitions.filter(
1806
1838
  (plugin) => Boolean(plugin.manifest.mcp)
@@ -1897,6 +1929,9 @@ function getPluginDisplayName(provider) {
1897
1929
  function isPluginProvider(provider) {
1898
1930
  return ensurePluginsLoaded().pluginsByName.has(provider);
1899
1931
  }
1932
+ function isPluginCapability(capability) {
1933
+ return ensurePluginsLoaded().capabilityToPlugin.has(capability);
1934
+ }
1900
1935
  function isPluginConfigKey(key) {
1901
1936
  return ensurePluginsLoaded().pluginConfigKeys.has(key);
1902
1937
  }
@@ -1940,6 +1975,7 @@ export {
1940
1975
  getPluginCatalogSignature,
1941
1976
  getPluginCapabilityProviders,
1942
1977
  getPluginProviders,
1978
+ getPluginMigrationRoots,
1943
1979
  getPluginMcpProviders,
1944
1980
  getPluginRuntimeDependencies,
1945
1981
  getPluginRuntimePostinstall,
@@ -1949,6 +1985,7 @@ export {
1949
1985
  getPluginDefinition,
1950
1986
  getPluginDisplayName,
1951
1987
  isPluginProvider,
1988
+ isPluginCapability,
1952
1989
  isPluginConfigKey,
1953
1990
  createPluginBroker
1954
1991
  };