@sentry/junior 0.182.0 → 0.184.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 (98) hide show
  1. package/dist/{agent-hooks-3S25UIHO.js → agent-hooks-XTZVALGQ.js} +11 -11
  2. package/dist/api/acp/auth.d.ts +46 -0
  3. package/dist/api/acp/authorization-page.d.ts +11 -0
  4. package/dist/api/acp/conversations.d.ts +70 -0
  5. package/dist/api/acp/errors.d.ts +6 -0
  6. package/dist/api/acp/route.d.ts +16 -0
  7. package/dist/api/acp/schema.d.ts +97 -0
  8. package/dist/api/acp/sleep.d.ts +2 -0
  9. package/dist/api/acp/state.d.ts +22 -0
  10. package/dist/api/acp/transport.d.ts +113 -0
  11. package/dist/api/code/overview.d.ts +35 -0
  12. package/dist/api/code/routes.d.ts +4 -0
  13. package/dist/api/schema/code.d.ts +75 -0
  14. package/dist/api/schema.d.ts +2 -0
  15. package/dist/api/schema.js +9 -1
  16. package/dist/api.js +258 -134
  17. package/dist/app.d.ts +0 -4
  18. package/dist/app.js +2171 -220
  19. package/dist/{catalog-runtime-ESLMBQBV.js → catalog-runtime-5357XR4F.js} +4 -4
  20. package/dist/chat/agent-invocations/store.d.ts +4 -2
  21. package/dist/chat/agent-invocations/work.d.ts +1 -3
  22. package/dist/chat/app/factory.d.ts +3 -3
  23. package/dist/chat/app/services.d.ts +3 -3
  24. package/dist/chat/code/publisher.d.ts +3 -0
  25. package/dist/chat/code/store.d.ts +9 -0
  26. package/dist/chat/event-tasks/store.d.ts +10 -0
  27. package/dist/chat/ingress/slack-webhook.d.ts +1 -1
  28. package/dist/chat/plugins/agent-hooks.d.ts +5 -0
  29. package/dist/chat/{runtime/slack-runtime.d.ts → providers/slack/runtime.d.ts} +2 -2
  30. package/dist/chat/{runtime/reply-executor.d.ts → providers/slack/turn.d.ts} +10 -9
  31. package/dist/chat/resource-events/store.d.ts +12 -0
  32. package/dist/chat/runtime/turn-execution.d.ts +30 -0
  33. package/dist/chat/slack/dispatch-turn.d.ts +12 -14
  34. package/dist/chat/task-execution/slack-work.d.ts +1 -1
  35. package/dist/{chunk-SXOZIG5X.js → chunk-2ZQPVX7C.js} +6 -6
  36. package/dist/{chunk-UQP54CXZ.js → chunk-3S7ULUWW.js} +1 -1
  37. package/dist/{chunk-2CEOXDG2.js → chunk-4CNDGK25.js} +174 -6
  38. package/dist/{chunk-3THPTNN6.js → chunk-4RONS3WR.js} +4 -4
  39. package/dist/{chunk-LHQK5XCU.js → chunk-6UDPINOX.js} +2 -2
  40. package/dist/{chunk-BZD4ADQH.js → chunk-6VOYP4M6.js} +2 -3
  41. package/dist/{chunk-QHALFHZA.js → chunk-6WGC3SO4.js} +9 -9
  42. package/dist/{chunk-BDDWVY32.js → chunk-ACPDVEJO.js} +22 -20
  43. package/dist/{chunk-44BQ3TSK.js → chunk-BCHYQS4B.js} +233 -173
  44. package/dist/{chunk-SVFSYQMT.js → chunk-BHYRYYLY.js} +1 -1
  45. package/dist/{chunk-LT4QYGKM.js → chunk-BT53RIGJ.js} +160 -97
  46. package/dist/{chunk-Z7ALSQS3.js → chunk-DUKIDPF6.js} +1 -1
  47. package/dist/{chunk-PQES5LB5.js → chunk-E57WPXWY.js} +5 -5
  48. package/dist/{chunk-GGYA5NPN.js → chunk-FKEZZMXS.js} +8 -8
  49. package/dist/{chunk-LB4FWMCV.js → chunk-HIPUIPJM.js} +183 -155
  50. package/dist/{chunk-3NFHI2NA.js → chunk-HUXFMDBZ.js} +1 -1
  51. package/dist/{chunk-6TSWXBTQ.js → chunk-IZDYYYGP.js} +3 -3
  52. package/dist/{chunk-YHL2L2ZZ.js → chunk-JA43DV4Y.js} +1 -1
  53. package/dist/{chunk-V5UZCCNW.js → chunk-JM2COLGC.js} +6 -6
  54. package/dist/{chunk-A7THOQ6N.js → chunk-JNO2GUDS.js} +21 -21
  55. package/dist/{chunk-KGMHUDVF.js → chunk-K7VDC2QW.js} +6 -6
  56. package/dist/{chunk-CVBIM4Z3.js → chunk-LCP4EDKR.js} +1 -1
  57. package/dist/{chunk-4DZ62L36.js → chunk-LHXIZLFF.js} +1 -1
  58. package/dist/{chunk-D6OHGAIO.js → chunk-M5YWNMTE.js} +5 -5
  59. package/dist/{chunk-3ENUMZNG.js → chunk-MAPJFUMV.js} +3 -3
  60. package/dist/{chunk-UUMBHORH.js → chunk-MLSQX2EX.js} +1 -1
  61. package/dist/{chunk-WOIALVN2.js → chunk-PJPRXO2T.js} +1 -1
  62. package/dist/{chunk-VHMAFMHB.js → chunk-QABCY33S.js} +1 -1
  63. package/dist/{chunk-UKIHNBBD.js → chunk-SHJK75Z2.js} +3 -3
  64. package/dist/{chunk-S35OZMSL.js → chunk-UBOIHNTH.js} +13 -13
  65. package/dist/{chunk-DZR3L74W.js → chunk-UF6BUA5W.js} +3 -3
  66. package/dist/{chunk-JIOKUIAS.js → chunk-WQFEWULF.js} +2 -2
  67. package/dist/chunk-WVIA7V3M.js +975 -0
  68. package/dist/{chunk-MJISSOWB.js → chunk-YKX6MTLU.js} +1 -1
  69. package/dist/{chunk-TEFNHMO2.js → chunk-Z3QAXJR7.js} +4 -4
  70. package/dist/cli/chat.js +33 -35
  71. package/dist/cli/check.js +5 -5
  72. package/dist/cli/plugins.js +12 -12
  73. package/dist/cli/snapshot-create.js +9 -9
  74. package/dist/cli/upgrade.js +6 -6
  75. package/dist/db/schema/code.d.ts +367 -0
  76. package/dist/db/schema.d.ts +367 -1
  77. package/dist/{db-NYIWZ4L5.js → db-MA52H62H.js} +6 -6
  78. package/dist/instrumentation.js +3 -3
  79. package/dist/nitro.js +6 -6
  80. package/dist/{oauth-callback-server-A2YTPVVX.js → oauth-callback-server-DXGHKN6S.js} +25 -25
  81. package/dist/{runner-VKAEU52J.js → runner-4IXUAQNK.js} +18 -18
  82. package/dist/{skills-52GMXUTY.js → skills-X3DY7AXO.js} +5 -5
  83. package/dist/spawn-43WGS6CH.js +37 -0
  84. package/dist/task-runner-VDRKITPV.js +32 -0
  85. package/dist/{validation-VD2YQX2W.js → validation-Z6JXSTJS.js} +5 -5
  86. package/dist/version.js +1 -1
  87. package/dist/{work-ZWBTGEQP.js → work-OKWRFBDW.js} +18 -18
  88. package/dist/worker-B236AE72.js +22 -0
  89. package/migrations/0036_complex_rage.sql +32 -0
  90. package/migrations/meta/0036_snapshot.json +3186 -0
  91. package/migrations/meta/_journal.json +8 -1
  92. package/package.json +6 -7
  93. package/dist/app-adapter.d.ts +0 -85
  94. package/dist/chat/api-turns/adapter-conversations.d.ts +0 -15
  95. package/dist/chunk-CZYNWPWD.js +0 -930
  96. package/dist/spawn-GSS4EBLR.js +0 -37
  97. package/dist/task-runner-DUGDWF5O.js +0 -32
  98. package/dist/worker-XUWD5WS7.js +0 -22
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  pluginCatalogRuntime
3
- } from "./chunk-WOIALVN2.js";
4
- import "./chunk-4DZ62L36.js";
3
+ } from "./chunk-PJPRXO2T.js";
4
+ import "./chunk-LHXIZLFF.js";
5
5
  import "./chunk-CEMMLV5L.js";
6
6
  import "./chunk-N7TMSOZH.js";
7
7
  import "./chunk-DWPN6SCH.js";
8
8
  import "./chunk-TXKUKMVO.js";
9
- import "./chunk-UQP54CXZ.js";
9
+ import "./chunk-3S7ULUWW.js";
10
10
  import "./chunk-PEQXYSSE.js";
11
- import "./chunk-BZD4ADQH.js";
11
+ import "./chunk-6VOYP4M6.js";
12
12
  export {
13
13
  pluginCatalogRuntime
14
14
  };
@@ -40,5 +40,7 @@ export declare function completeAgentInvocation(args: {
40
40
  status: "blocked" | "failed";
41
41
  nowMs?: number;
42
42
  }): Promise<AgentInvocation | undefined>;
43
- /** Return whether an invocation already owns its immutable terminal result. */
44
- export declare function isTerminalAgentInvocation(invocation: AgentInvocation): boolean;
43
+ /** Return whether an agent invocation has finished. */
44
+ export declare function isTerminalAgentInvocation(invocation: AgentInvocation): invocation is Extract<AgentInvocation, {
45
+ status: "blocked" | "completed" | "failed";
46
+ }>;
@@ -20,9 +20,7 @@ export declare function createAndEnqueueAgentInvocation(input: CreateAgentInvoca
20
20
  /** Resolve invocation execution from mailbox input or durable active state. */
21
21
  export declare function resolveAgentInvocationId(context: ConversationWorkerContext): Promise<string | undefined>;
22
22
  /** Build the invocation consumer that advances work through the shared runner. */
23
- export declare function createAgentInvocationWorker(options: {
24
- agentRunner: AgentRunner;
25
- }): (context: ConversationWorkerContext, invocationId: string) => Promise<ConversationWorkerResult>;
23
+ export declare function createAgentInvocationWorker(agentRunner: AgentRunner): (context: ConversationWorkerContext, invocationId: string) => Promise<ConversationWorkerResult>;
26
24
  /** Route invocation-backed work before falling through to existing consumers. */
27
25
  export declare function routeAgentInvocationWork(options: {
28
26
  fallbackWorker: (context: ConversationWorkerContext) => Promise<ConversationWorkerResult>;
@@ -1,6 +1,6 @@
1
1
  import type { SlackAdapter } from "@chat-adapter/slack";
2
2
  import type { Message } from "chat";
3
- import { type AssistantLifecycleEvent } from "@/chat/runtime/slack-runtime";
3
+ import { type AssistantLifecycleEvent } from "@/chat/providers/slack/runtime";
4
4
  import type { JuniorRuntimeServiceOverrides } from "@/chat/app/services";
5
5
  export interface CreateSlackRuntimeOptions {
6
6
  getSlackAdapter: () => SlackAdapter;
@@ -14,6 +14,6 @@ export declare function createSlackRuntime(options: CreateSlackRuntimeOptions):
14
14
  }) => Promise<import("../agent-dispatch/types").DispatchTurnResult>;
15
15
  handleAssistantContextChanged: (event: AssistantLifecycleEvent) => Promise<void>;
16
16
  handleAssistantThreadStarted: (event: AssistantLifecycleEvent) => Promise<void>;
17
- handleNewMention: (thread: import("chat").Thread, message: Message, hooks: import("@/chat/runtime/slack-runtime").SlackTurnOptions) => Promise<void>;
18
- handleSubscribedMessage: (thread: import("chat").Thread, message: Message, hooks: import("@/chat/runtime/slack-runtime").SlackTurnOptions) => Promise<void>;
17
+ handleNewMention: (thread: import("chat").Thread, message: Message, hooks: import("@/chat/providers/slack/runtime").SlackTurnOptions) => Promise<void>;
18
+ handleSubscribedMessage: (thread: import("chat").Thread, message: Message, hooks: import("@/chat/providers/slack/runtime").SlackTurnOptions) => Promise<void>;
19
19
  };
@@ -2,19 +2,19 @@ import type { SandboxEgressTracePropagationConfig } from "@/chat/sandbox/egress/
2
2
  import { type ConversationMemoryDeps, type ConversationMemoryService } from "@/chat/services/conversation-memory";
3
3
  import { type ContextCompactor, type ContextCompactorDeps } from "@/chat/services/context-compaction";
4
4
  import { type SubscribedReplyPolicy, type SubscribedReplyPolicyDeps } from "@/chat/services/subscribed-reply-policy";
5
- import type { ReplyExecutorServices } from "@/chat/runtime/reply-executor";
5
+ import type { SlackTurnServices } from "@/chat/providers/slack/turn";
6
6
  import { type VisionContextDeps, type VisionContextService } from "@/chat/slack/vision-context";
7
7
  export interface JuniorRuntimeServices {
8
8
  conversationMemory: ConversationMemoryService;
9
9
  contextCompactor: ContextCompactor;
10
- replyExecutor: ReplyExecutorServices;
10
+ replyExecutor: SlackTurnServices;
11
11
  subscribedReplyPolicy: SubscribedReplyPolicy;
12
12
  visionContext: VisionContextService;
13
13
  }
14
14
  export interface JuniorRuntimeServiceOverrides {
15
15
  conversationMemory?: Partial<ConversationMemoryDeps>;
16
16
  contextCompactor?: Partial<ContextCompactorDeps>;
17
- replyExecutor?: Partial<ReplyExecutorServices>;
17
+ replyExecutor?: Partial<SlackTurnServices>;
18
18
  subscribedReplyPolicy?: Partial<SubscribedReplyPolicyDeps>;
19
19
  sandbox?: {
20
20
  tracePropagation?: SandboxEgressTracePropagationConfig;
@@ -0,0 +1,3 @@
1
+ import type { CodeChangePublisher } from "@sentry/junior-plugin-api";
2
+ /** Connect a plugin to Junior's code records. */
3
+ export declare function createCodeChangePublisher(provider: string): CodeChangePublisher;
@@ -0,0 +1,9 @@
1
+ import { type CodeChangeInput } from "@sentry/junior-plugin-api";
2
+ import type { JuniorDatabase } from "@/db/db";
3
+ /** Record the latest details for one code change created by Junior. */
4
+ export declare function recordCodeChange(db: JuniorDatabase, provider: string, input: CodeChangeInput): Promise<void>;
5
+ /** Add conversation links to an existing code change. */
6
+ export declare function associateCodeChangeConversations(db: JuniorDatabase, provider: string, input: {
7
+ conversationIds: string[];
8
+ providerId: string;
9
+ }): Promise<void>;
@@ -17,5 +17,15 @@ export declare function eventTaskBelongsToUser(task: EventTask, user: User): boo
17
17
  export declare function listEventTasksCreatedBy(db: JuniorDatabase, user: User, limit: number): Promise<EventTask[]>;
18
18
  /** List event tasks whose current Slack destination is public. */
19
19
  export declare function listPublicEventTasksForTeams(db: JuniorDatabase, teamIds: string[], limit: number): Promise<EventTask[]>;
20
+ /**
21
+ * Collect match keys from event tasks for these identifiers and event types.
22
+ * Does not evaluate match values — only reports keys that filters use.
23
+ */
24
+ export declare function collectEventTaskMatchKeys(db: JuniorDatabase, input: {
25
+ eventTypes: string[];
26
+ identifiers: string[];
27
+ namespace: string;
28
+ teamId: string;
29
+ }): Promise<string[]>;
20
30
  /** Find every task matching one normalized resource event. */
21
31
  export declare function findMatchingEventTasks(db: JuniorDatabase, event: ResourceEvent, teamId: string): Promise<EventTask[]>;
@@ -1,6 +1,6 @@
1
1
  import type { SlackAdapter } from "@chat-adapter/slack";
2
2
  import { type StateAdapter } from "chat";
3
- import type { SlackTurnRuntime } from "@/chat/runtime/slack-runtime";
3
+ import type { SlackTurnRuntime } from "@/chat/providers/slack/runtime";
4
4
  import type { ConversationStore } from "@/chat/conversations/store";
5
5
  import type { ConversationWorkQueue } from "@/chat/task-execution/queue";
6
6
  import type { UserTokenStore } from "@/chat/credentials/user-token-store";
@@ -61,6 +61,11 @@ export declare function getPluginTools(context: ToolRuntimeContext, sandbox?: Pl
61
61
  /** Collect route handlers exposed by plugins for app-level mounting. */
62
62
  export declare function getPluginRoutes(options: {
63
63
  resourceEvents: {
64
+ neededMatchKeys?(input: {
65
+ eventTypes: string[];
66
+ identifiers: string[];
67
+ namespace: string;
68
+ }): Promise<string[]>;
64
69
  publish(event: ResourceEvent): Promise<void>;
65
70
  };
66
71
  }): PluginRouteRegistration[];
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Slack event runtime.
2
+ * Slack provider runtime.
3
3
  *
4
4
  * This module owns inbound Slack routing decisions for mentions, subscribed
5
5
  * messages, assistant lifecycle events, and retryable turn pauses. It should
@@ -93,7 +93,7 @@ export interface SlackTurnRuntimeDependencies<TPreparedState> {
93
93
  thread: Thread;
94
94
  }) => Promise<void>;
95
95
  prepareTurnState: (args: PrepareTurnStateInput) => Promise<TPreparedState>;
96
- replyToThread: (thread: Thread, message: Message, options: {
96
+ executeSlackTurn: (thread: Thread, message: Message, options: {
97
97
  beforeFirstResponsePost?: () => Promise<void>;
98
98
  conversationId?: string;
99
99
  destination: Destination;
@@ -1,10 +1,10 @@
1
1
  /**
2
- * Slack reply execution boundary.
2
+ * Add Slack provider behavior around one native agent Turn.
3
3
  *
4
- * This module bridges prepared Slack thread state into the agent runner
5
- * and commits the resulting Slack-visible delivery/state updates. It is where
6
- * queued messages, compaction, status updates, and Slack posting meet; agent
7
- * internals stay behind the runner seam.
4
+ * This module prepares Slack input and owns Slack status, delivery, and saved
5
+ * Slack state. Native execution concerns that remain here must move behind a
6
+ * provider-neutral runtime contract. Agent execution stays behind
7
+ * `AgentRunner`.
8
8
  */
9
9
  import type { Message, Thread } from "chat";
10
10
  import type { SlackAdapter } from "@chat-adapter/slack";
@@ -17,7 +17,7 @@ import { lookupSlackUser } from "@/chat/slack/user";
17
17
  import type { PausedTurnRequest } from "@/chat/task-execution/turn-wake";
18
18
  import type { ConversationTurnLifecycle } from "@/chat/conversations/turn-lifecycle";
19
19
  import type { DispatchTurnContext, DispatchTurnResult } from "@/chat/agent-dispatch/types";
20
- export interface ReplyExecutorServices {
20
+ export interface SlackTurnServices {
21
21
  agentRunner: AgentRunner;
22
22
  contextCompactor: ContextCompactor;
23
23
  getPausedTurnRequest: (args: {
@@ -32,7 +32,7 @@ export interface ReplyExecutorServices {
32
32
  sessionId: string;
33
33
  }) => Promise<void>;
34
34
  }
35
- interface ReplyExecutorDeps {
35
+ interface SlackTurnDeps {
36
36
  getSlackAdapter: () => SlackAdapter;
37
37
  resolveUserAttachments: (attachments: Message["attachments"] | undefined, context: {
38
38
  threadId?: string;
@@ -48,9 +48,10 @@ interface ReplyExecutorDeps {
48
48
  promptText?: string;
49
49
  }>>;
50
50
  prepareTurnState: (args: PrepareTurnStateInput) => Promise<PreparedTurnState>;
51
- services: ReplyExecutorServices;
51
+ services: SlackTurnServices;
52
52
  }
53
- export declare function createReplyToThread(deps: ReplyExecutorDeps): (thread: Thread, message: Message, options: {
53
+ /** Build the Slack caller that prepares input and delivers output for a Turn. */
54
+ export declare function createSlackTurn(deps: SlackTurnDeps): (thread: Thread, message: Message, options: {
54
55
  beforeFirstResponsePost?: () => Promise<void>;
55
56
  conversationId?: string;
56
57
  destination: Destination;
@@ -65,6 +65,18 @@ export declare function cancelSubscriptions(input: {
65
65
  nowMs?: number;
66
66
  state?: StateAdapter;
67
67
  }): Promise<void>;
68
+ /**
69
+ * Collect match keys from active watches for these identifiers and event types.
70
+ * Does not evaluate match values — only reports keys that filters use.
71
+ */
72
+ export declare function collectResourceEventMatchKeys(input: {
73
+ eventTypes: string[];
74
+ identifiers: string[];
75
+ namespace: string;
76
+ nowMs?: number;
77
+ state?: StateAdapter;
78
+ teamId: string;
79
+ }): Promise<string[]>;
68
80
  /** Find active subscriptions interested in a normalized resource event. */
69
81
  export declare function findMatchingResourceEventSubscriptions(input: {
70
82
  data?: ResourceEventData;
@@ -0,0 +1,30 @@
1
+ import type { AgentRun } from "@/chat/agent/types";
2
+ import type { CompleteConversationTurnInput, FailConversationTurnInput } from "@/chat/conversations/turn-lifecycle";
3
+ import type { AgentRunOutcome } from "@/chat/runtime/agent-run-outcome";
4
+ import type { AgentRunner } from "@/chat/runtime/agent-runner";
5
+ import type { AgentRunResult } from "@/chat/services/turn-result";
6
+ type SavedTurnResult = {
7
+ finishedAtMs?: number;
8
+ outcome: CompleteConversationTurnInput["outcome"];
9
+ } | {
10
+ finishedAtMs?: number;
11
+ failureCode: FailConversationTurnInput["failureCode"];
12
+ outcome: "failed";
13
+ };
14
+ type TurnExecutionOutcome = Exclude<AgentRunOutcome, {
15
+ status: "completed";
16
+ }> | {
17
+ status: "completed";
18
+ };
19
+ /** An error thrown while the agent advances a Run. */
20
+ export declare class AgentRunError extends Error {
21
+ constructor(cause: unknown);
22
+ }
23
+ /**
24
+ * Run the agent and finish the Turn after the caller saves its result.
25
+ *
26
+ * A paused Run, or a Run waiting for authorization, leaves the Turn open. A
27
+ * save error also leaves the Turn open so the worker can retry or recover it.
28
+ */
29
+ export declare function executeTurn(agentRunner: AgentRunner, run: AgentRun, saveResult: (result: AgentRunResult) => Promise<SavedTurnResult>): Promise<TurnExecutionOutcome>;
30
+ export {};
@@ -2,24 +2,22 @@ import { Message, ThreadImpl } from "chat";
2
2
  import type { SlackAdapter } from "@chat-adapter/slack";
3
3
  import type { DispatchTurnContext, DispatchTurnResult } from "@/chat/agent-dispatch/types";
4
4
  import type { DispatchRecord } from "@/chat/agent-dispatch/types";
5
- interface DispatchReplyToThread {
6
- (thread: ThreadImpl, message: Message, options: {
7
- ack?: () => Promise<void>;
8
- conversationId?: string;
9
- destination: DispatchRecord["destination"];
10
- execution: DispatchTurnContext;
11
- publishExternally?: boolean;
12
- onTurnDeliveryAccepted?: (messageId?: string) => void;
13
- onTurnOutcome?: (result: DispatchTurnResult) => void;
14
- shouldYield?: () => boolean;
15
- skipBackfill?: boolean;
16
- }): Promise<void>;
17
- }
5
+ type ExecuteSlackTurn = (thread: ThreadImpl, message: Message, options: {
6
+ ack?: () => Promise<void>;
7
+ conversationId?: string;
8
+ destination: DispatchRecord["destination"];
9
+ execution: DispatchTurnContext;
10
+ publishExternally?: boolean;
11
+ onTurnDeliveryAccepted?: (messageId?: string) => void;
12
+ onTurnOutcome?: (result: DispatchTurnResult) => void;
13
+ shouldYield?: () => boolean;
14
+ skipBackfill?: boolean;
15
+ }) => Promise<void>;
18
16
  /** Build the Slack provider adapter for agent-dispatched conversation turns. */
19
17
  export declare function createSlackDispatchTurnRunner(options: {
20
18
  getLocationConfiguration: (destination: DispatchRecord["destination"]) => DispatchTurnContext["locationConfiguration"];
21
19
  getSlackAdapter: () => SlackAdapter;
22
- replyToThread: DispatchReplyToThread;
20
+ executeSlackTurn: ExecuteSlackTurn;
23
21
  }): (dispatch: DispatchRecord, hooks: {
24
22
  ack: () => Promise<void>;
25
23
  shouldYield?: () => boolean;
@@ -1,7 +1,7 @@
1
1
  import type { SlackAdapter } from "@chat-adapter/slack";
2
2
  import { Message, ThreadImpl, type StateAdapter } from "chat";
3
3
  import { z } from "zod";
4
- import type { SlackTurnOptions } from "@/chat/runtime/slack-runtime";
4
+ import type { SlackTurnOptions } from "@/chat/providers/slack/runtime";
5
5
  import type { ConversationStore } from "@/chat/conversations/store";
6
6
  import type { InboundMessage } from "@/chat/task-execution/store";
7
7
  import type { ConversationWorkerContext, ConversationWorkerResult } from "@/chat/task-execution/worker";
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-PDO5BLNM.js";
4
4
  import {
5
5
  ToolInputError
6
- } from "./chunk-2CEOXDG2.js";
6
+ } from "./chunk-4CNDGK25.js";
7
7
  import {
8
8
  agentHistoryItemSchema,
9
9
  bindProviderConversation,
@@ -16,25 +16,25 @@ import {
16
16
  instructionProvenanceFor,
17
17
  sanitizePostgresJson,
18
18
  withConversationEventLock
19
- } from "./chunk-6TSWXBTQ.js";
19
+ } from "./chunk-IZDYYYGP.js";
20
20
  import {
21
21
  SANDBOX_REPOS_ROOT,
22
22
  SANDBOX_WORKSPACE_ROOT,
23
23
  sleep
24
- } from "./chunk-UKIHNBBD.js";
24
+ } from "./chunk-SHJK75Z2.js";
25
25
  import {
26
26
  MUTATION_LOCK_TTL_MS,
27
27
  fenceLock,
28
28
  getStateAdapter,
29
29
  withLock
30
- } from "./chunk-Z7ALSQS3.js";
30
+ } from "./chunk-DUKIDPF6.js";
31
31
  import {
32
32
  botConfig,
33
33
  completeText,
34
34
  escapeXml,
35
35
  resolveGatewayModel,
36
36
  unwrapCurrentInstruction
37
- } from "./chunk-LHQK5XCU.js";
37
+ } from "./chunk-6UDPINOX.js";
38
38
  import {
39
39
  parseSlackMessageTs,
40
40
  toStoredSlackActor
@@ -44,7 +44,7 @@ import {
44
44
  logException,
45
45
  logWarn,
46
46
  setSpanAttributes
47
- } from "./chunk-UQP54CXZ.js";
47
+ } from "./chunk-3S7ULUWW.js";
48
48
 
49
49
  // src/chat/turn-context-tag.ts
50
50
  var TURN_CONTEXT_TAG = "runtime-turn-context";
@@ -12,7 +12,7 @@ import {
12
12
  } from "./chunk-PEQXYSSE.js";
13
13
  import {
14
14
  JUNIOR_VERSION
15
- } from "./chunk-BZD4ADQH.js";
15
+ } from "./chunk-6VOYP4M6.js";
16
16
 
17
17
  // src/deployment.ts
18
18
  var JUNIOR_HEARTBEAT_ROUTE = "/api/internal/heartbeat";
@@ -5,8 +5,10 @@ import {
5
5
  getConversationEventStore,
6
6
  getDb,
7
7
  getSqlExecutor
8
- } from "./chunk-6TSWXBTQ.js";
8
+ } from "./chunk-IZDYYYGP.js";
9
9
  import {
10
+ juniorCodeChanges,
11
+ juniorCodeRepositories,
10
12
  juniorConversationAnnotations,
11
13
  juniorConversationEvents,
12
14
  juniorIdentities,
@@ -14,7 +16,7 @@ import {
14
16
  juniorUsers,
15
17
  juniorWorkspaceRepos,
16
18
  juniorWorkspaces
17
- } from "./chunk-44BQ3TSK.js";
19
+ } from "./chunk-BCHYQS4B.js";
18
20
  import {
19
21
  SANDBOX_WORKSPACE_ROOT,
20
22
  getVercelSandboxCredentials,
@@ -22,17 +24,17 @@ import {
22
24
  isSandboxMissingError,
23
25
  runNonInteractiveCommand,
24
26
  sleep
25
- } from "./chunk-UKIHNBBD.js";
27
+ } from "./chunk-SHJK75Z2.js";
26
28
  import {
27
29
  getStateAdapter
28
- } from "./chunk-Z7ALSQS3.js";
30
+ } from "./chunk-DUKIDPF6.js";
29
31
  import {
30
32
  botConfig,
31
33
  completeObject,
32
34
  defaultModelId,
33
35
  embedTexts,
34
36
  getSlackBotToken
35
- } from "./chunk-LHQK5XCU.js";
37
+ } from "./chunk-6UDPINOX.js";
36
38
  import {
37
39
  isActorUserId,
38
40
  parseActorUserId,
@@ -48,7 +50,7 @@ import {
48
50
  setSpanAttributes,
49
51
  setSpanStatus,
50
52
  withSpan
51
- } from "./chunk-UQP54CXZ.js";
53
+ } from "./chunk-3S7ULUWW.js";
52
54
 
53
55
  // src/chat/plugins/agent-hooks.ts
54
56
  import {
@@ -1218,6 +1220,42 @@ async function cancelSubscriptions(input) {
1218
1220
  });
1219
1221
  }
1220
1222
  }
1223
+ async function collectResourceEventMatchKeys(input) {
1224
+ const state = input.state ?? getStateAdapter();
1225
+ await state.connect();
1226
+ const nowMs = input.nowMs ?? Date.now();
1227
+ const eventTypes = new Set(
1228
+ input.eventTypes.map((eventType) => eventType.trim()).filter(Boolean)
1229
+ );
1230
+ if (eventTypes.size === 0) return [];
1231
+ const keys = /* @__PURE__ */ new Set();
1232
+ const identifiers = new Set(
1233
+ input.identifiers.map((value) => value.trim()).filter(Boolean)
1234
+ );
1235
+ for (const identifier of identifiers) {
1236
+ const ids = await readSubscriptionIdIndex(
1237
+ state,
1238
+ resourceIndexKey(input.teamId, input.namespace, identifier)
1239
+ );
1240
+ const records = await Promise.all(
1241
+ ids.map(
1242
+ async (id) => parseSubscription(await state.get(subscriptionKey(id)))
1243
+ )
1244
+ );
1245
+ for (const record of records) {
1246
+ if (!record) continue;
1247
+ if (record.namespace !== input.namespace) continue;
1248
+ if (record.identifier !== identifier) continue;
1249
+ if (subscriptionTeamId(record.destination) !== input.teamId) continue;
1250
+ if (!activeAt(record, nowMs)) continue;
1251
+ if (!record.events.some((eventType) => eventTypes.has(eventType))) continue;
1252
+ for (const key of Object.keys(record.match ?? {})) {
1253
+ keys.add(key);
1254
+ }
1255
+ }
1256
+ }
1257
+ return [...keys].sort();
1258
+ }
1221
1259
  async function findMatchingResourceEventSubscriptions(input) {
1222
1260
  const state = input.state ?? getStateAdapter();
1223
1261
  await state.connect();
@@ -2178,6 +2216,113 @@ async function deleteWorkspace(id) {
2178
2216
  return result.deleted;
2179
2217
  }
2180
2218
 
2219
+ // src/chat/code/store.ts
2220
+ import { randomUUID as randomUUID3 } from "crypto";
2221
+ import { and as and6, eq as eq6, lte, sql as sql3 } from "drizzle-orm";
2222
+ import {
2223
+ codeChangeInputSchema
2224
+ } from "@sentry/junior-plugin-api";
2225
+ async function recordCodeChange(db, provider, input) {
2226
+ const change = codeChangeInputSchema.parse(input);
2227
+ const repositories = await db.insert(juniorCodeRepositories).values({
2228
+ id: randomUUID3(),
2229
+ name: change.repository.name,
2230
+ provider,
2231
+ providerId: change.repository.providerId,
2232
+ url: change.repository.url,
2233
+ updatedAt: change.updatedAt
2234
+ }).onConflictDoUpdate({
2235
+ target: [
2236
+ juniorCodeRepositories.provider,
2237
+ juniorCodeRepositories.providerId
2238
+ ],
2239
+ set: {
2240
+ name: change.repository.name,
2241
+ ...change.repository.url ? { url: change.repository.url } : void 0,
2242
+ updatedAt: change.updatedAt
2243
+ },
2244
+ where: lte(juniorCodeRepositories.updatedAt, change.updatedAt)
2245
+ }).returning({ id: juniorCodeRepositories.id });
2246
+ const existingRepositories = repositories[0] ? [] : await db.select({ id: juniorCodeRepositories.id }).from(juniorCodeRepositories).where(
2247
+ and6(
2248
+ eq6(juniorCodeRepositories.provider, provider),
2249
+ eq6(juniorCodeRepositories.providerId, change.repository.providerId)
2250
+ )
2251
+ ).limit(1);
2252
+ const repositoryId = repositories[0]?.id ?? existingRepositories[0]?.id;
2253
+ if (!repositoryId) {
2254
+ throw new Error("Code repository upsert returned no row");
2255
+ }
2256
+ const conversationIds = sql3.join(
2257
+ change.conversationIds.map((conversationId) => sql3`${conversationId}`),
2258
+ sql3`, `
2259
+ );
2260
+ const values = {
2261
+ closedAt: change.closedAt ?? null,
2262
+ conversationIds: change.conversationIds.length > 0 ? sql3`ARRAY(
2263
+ SELECT DISTINCT value
2264
+ FROM unnest(
2265
+ ${juniorCodeChanges.conversationIds}
2266
+ || ARRAY[${conversationIds}]::text[]
2267
+ ) AS value
2268
+ ORDER BY value
2269
+ )` : juniorCodeChanges.conversationIds,
2270
+ mergedAt: change.mergedAt ?? null,
2271
+ number: change.number,
2272
+ openedAt: change.openedAt,
2273
+ repositoryId,
2274
+ state: change.state,
2275
+ ...change.title ? { title: change.title } : void 0,
2276
+ updatedAt: change.updatedAt,
2277
+ url: change.url ?? null
2278
+ };
2279
+ await db.insert(juniorCodeChanges).values({
2280
+ ...values,
2281
+ conversationIds: change.conversationIds,
2282
+ id: randomUUID3(),
2283
+ provider,
2284
+ providerId: change.providerId
2285
+ }).onConflictDoUpdate({
2286
+ target: [juniorCodeChanges.provider, juniorCodeChanges.providerId],
2287
+ set: values,
2288
+ where: lte(juniorCodeChanges.updatedAt, change.updatedAt)
2289
+ });
2290
+ }
2291
+ async function associateCodeChangeConversations(db, provider, input) {
2292
+ if (input.conversationIds.length === 0) return;
2293
+ const conversationIds = sql3.join(
2294
+ input.conversationIds.map((conversationId) => sql3`${conversationId}`),
2295
+ sql3`, `
2296
+ );
2297
+ await db.update(juniorCodeChanges).set({
2298
+ conversationIds: sql3`ARRAY(
2299
+ SELECT DISTINCT value
2300
+ FROM unnest(
2301
+ ${juniorCodeChanges.conversationIds}
2302
+ || ARRAY[${conversationIds}]::text[]
2303
+ ) AS value
2304
+ ORDER BY value
2305
+ )`
2306
+ }).where(
2307
+ and6(
2308
+ eq6(juniorCodeChanges.provider, provider),
2309
+ eq6(juniorCodeChanges.providerId, input.providerId)
2310
+ )
2311
+ );
2312
+ }
2313
+
2314
+ // src/chat/code/publisher.ts
2315
+ function createCodeChangePublisher(provider) {
2316
+ return {
2317
+ async associateConversations(input) {
2318
+ await associateCodeChangeConversations(getDb(), provider, input);
2319
+ },
2320
+ async record(input) {
2321
+ await recordCodeChange(getDb(), provider, input);
2322
+ }
2323
+ };
2324
+ }
2325
+
2181
2326
  // src/chat/plugins/agent-hooks.ts
2182
2327
  var PluginHookDeniedError = class extends Error {
2183
2328
  constructor(message) {
@@ -2790,7 +2935,29 @@ function getPluginRoutes(options) {
2790
2935
  plugin: pluginName
2791
2936
  })
2792
2937
  },
2938
+ codeChanges: createCodeChangePublisher(pluginName),
2793
2939
  resourceEvents: {
2940
+ async neededMatchKeys(input) {
2941
+ if (!options.resourceEvents.neededMatchKeys) return [];
2942
+ const identifiers = [
2943
+ ...new Set(
2944
+ input.identifiers.map(
2945
+ (identifier) => normalizeResourceEventIdentifier(
2946
+ plugin.resourceEvents,
2947
+ identifier
2948
+ )
2949
+ ).filter(Boolean)
2950
+ )
2951
+ ];
2952
+ if (identifiers.length === 0 || input.eventTypes.length === 0) {
2953
+ return [];
2954
+ }
2955
+ return await options.resourceEvents.neededMatchKeys({
2956
+ eventTypes: input.eventTypes,
2957
+ identifiers,
2958
+ namespace: pluginName
2959
+ });
2960
+ },
2794
2961
  async publish(event) {
2795
2962
  const parsed = resourceEventInputSchema.parse(event);
2796
2963
  requirePublishedResourceEvent(plugin, parsed.eventType);
@@ -3438,6 +3605,7 @@ export {
3438
3605
  listResourceEventSubscriptions,
3439
3606
  cancelResourceEventSubscription,
3440
3607
  cancelSubscriptions,
3608
+ collectResourceEventMatchKeys,
3441
3609
  findMatchingResourceEventSubscriptions,
3442
3610
  deliverResourceEventSubscription,
3443
3611
  RESOURCE_SUBSCRIPTION_DEFAULT_TTL_MS,
@@ -19,23 +19,23 @@ import {
19
19
  releaseConversationWork,
20
20
  requestAnotherSlice,
21
21
  startConversationWork
22
- } from "./chunk-TEFNHMO2.js";
22
+ } from "./chunk-Z3QAXJR7.js";
23
23
  import {
24
24
  ConversationQueueMessageRejectedError
25
25
  } from "./chunk-JAL3CH4G.js";
26
26
  import {
27
27
  getTurnRequestDeadline
28
- } from "./chunk-UUMBHORH.js";
28
+ } from "./chunk-MLSQX2EX.js";
29
29
  import {
30
30
  getChatConfig,
31
31
  isProviderRetryError
32
- } from "./chunk-LHQK5XCU.js";
32
+ } from "./chunk-6UDPINOX.js";
33
33
  import {
34
34
  logException,
35
35
  logInfo,
36
36
  logWarn,
37
37
  withLogContext
38
- } from "./chunk-UQP54CXZ.js";
38
+ } from "./chunk-3S7ULUWW.js";
39
39
 
40
40
  // src/chat/task-execution/worker.ts
41
41
  var CONVERSATION_WORK_DEFER_DELAY_MS = 15e3;
@@ -3,7 +3,7 @@ import {
3
3
  toCanonicalInputMessage,
4
4
  toCanonicalOutputMessage,
5
5
  toGenAiMessagesTraceAttributes
6
- } from "./chunk-SVFSYQMT.js";
6
+ } from "./chunk-BHYRYYLY.js";
7
7
  import {
8
8
  extractGenAiUsageAttributes,
9
9
  logException,
@@ -11,7 +11,7 @@ import {
11
11
  normalizeGenAiFinishReason,
12
12
  serializeGenAiAttribute,
13
13
  withSpan
14
- } from "./chunk-UQP54CXZ.js";
14
+ } from "./chunk-3S7ULUWW.js";
15
15
 
16
16
  // src/chat/services/provider-error.ts
17
17
  var ProviderError = class extends Error {