@sentry/junior 0.106.0 → 0.107.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/dist/{agent-hooks-KR5BCWOK.js → agent-hooks-ICPIJAFY.js} +9 -7
  2. package/dist/api/conversations/detail.d.ts +1 -1
  3. package/dist/api/conversations/events.d.ts +14 -0
  4. package/dist/api/conversations/schema.d.ts +196 -463
  5. package/dist/api/schema.d.ts +2 -7
  6. package/dist/api/schema.js +10 -8
  7. package/dist/api.js +377 -810
  8. package/dist/app.js +3586 -3614
  9. package/dist/{catalog-runtime-5CVM2DOF.js → catalog-runtime-FOFNPR3P.js} +3 -2
  10. package/dist/chat/agent/prompt.d.ts +1 -1
  11. package/dist/chat/agent/request.d.ts +28 -29
  12. package/dist/chat/agent/resume.d.ts +7 -7
  13. package/dist/chat/agent/session.d.ts +5 -6
  14. package/dist/chat/agent/tools.d.ts +3 -3
  15. package/dist/chat/agent-dispatch/runner.d.ts +2 -0
  16. package/dist/chat/config.d.ts +2 -2
  17. package/dist/chat/conversations/history.d.ts +582 -167
  18. package/dist/chat/conversations/message-projection.d.ts +6 -0
  19. package/dist/chat/conversations/message-summaries.d.ts +9 -0
  20. package/dist/chat/conversations/messages.d.ts +13 -27
  21. package/dist/chat/conversations/projection.d.ts +30 -53
  22. package/dist/chat/conversations/provenance.d.ts +42 -0
  23. package/dist/chat/conversations/search.d.ts +2 -2
  24. package/dist/chat/conversations/sql/conversation-row.d.ts +1 -1
  25. package/dist/chat/conversations/sql/event-lock.d.ts +3 -0
  26. package/dist/chat/conversations/sql/history.d.ts +3 -3
  27. package/dist/chat/conversations/sql/privacy.d.ts +27 -0
  28. package/dist/chat/conversations/sql/purge.d.ts +2 -10
  29. package/dist/chat/conversations/sql/store.d.ts +0 -5
  30. package/dist/chat/conversations/store.d.ts +8 -13
  31. package/dist/chat/conversations/turn-lifecycle.d.ts +41 -0
  32. package/dist/chat/db.d.ts +4 -10
  33. package/dist/chat/model-profile.d.ts +10 -0
  34. package/dist/chat/oauth-flow.d.ts +0 -5
  35. package/dist/chat/pi/conversation-events.d.ts +33 -0
  36. package/dist/chat/pi/sql-model-usage.d.ts +10 -0
  37. package/dist/chat/plugins/agent-hooks.d.ts +4 -2
  38. package/dist/chat/resource-events/ingest.d.ts +0 -13
  39. package/dist/chat/runtime/delivered-turn-state.d.ts +1 -1
  40. package/dist/chat/runtime/generated-artifacts.d.ts +1 -1
  41. package/dist/chat/runtime/reply-executor.d.ts +2 -0
  42. package/dist/chat/runtime/slack-resume.d.ts +23 -28
  43. package/dist/chat/runtime/slack-runtime.d.ts +2 -0
  44. package/dist/chat/runtime/turn.d.ts +14 -1
  45. package/dist/chat/services/context-compaction-marker.d.ts +0 -1
  46. package/dist/chat/services/context-compaction.d.ts +1 -0
  47. package/dist/chat/services/conversation-memory.d.ts +9 -0
  48. package/dist/chat/services/plugin-auth-orchestration.d.ts +1 -4
  49. package/dist/chat/services/subscribed-decision.d.ts +1 -1
  50. package/dist/chat/services/turn-failure-response.d.ts +10 -3
  51. package/dist/chat/services/turn-result.d.ts +7 -12
  52. package/dist/chat/services/{turn-reasoning-level.d.ts → turn-router.d.ts} +12 -8
  53. package/dist/chat/services/turn-session-record.d.ts +15 -16
  54. package/dist/chat/slack/adapter.d.ts +2 -2
  55. package/dist/chat/slack/errors.d.ts +2 -0
  56. package/dist/chat/slack/outbound.d.ts +0 -1
  57. package/dist/chat/slack/reply.d.ts +2 -8
  58. package/dist/chat/slack/tools/channel-capabilities.d.ts +2 -2
  59. package/dist/chat/slack/tools/{send-message.d.ts → send-files.d.ts} +27 -19
  60. package/dist/chat/state/conversation.d.ts +4 -4
  61. package/dist/chat/state/turn-id.d.ts +2 -0
  62. package/dist/chat/state/turn-session-keys.d.ts +6 -0
  63. package/dist/chat/state/turn-session.d.ts +11 -9
  64. package/dist/chat/task-execution/state.d.ts +6 -1
  65. package/dist/chat/task-execution/store.d.ts +1 -1
  66. package/dist/chat/tool-support/pi-tool-adapter.d.ts +1 -1
  67. package/dist/chat/tool-support/tool-execution-report.d.ts +1 -0
  68. package/dist/chat/tools/handoff/tool.d.ts +2 -2
  69. package/dist/chat/tools/sandbox/file-uploads.d.ts +28 -6
  70. package/dist/chat/tools/types.d.ts +6 -9
  71. package/dist/chat/tools/web/image-generate.d.ts +4 -6
  72. package/dist/{chunk-DDRQ4U7I.js → chunk-4YF7Z6IA.js} +390 -270
  73. package/dist/{chunk-AZ5OMSN5.js → chunk-AUUOHQAT.js} +2 -2
  74. package/dist/chunk-B2Z2H66D.js +250 -0
  75. package/dist/{chunk-4W4O4DCV.js → chunk-CQ7KSO2B.js} +75 -45
  76. package/dist/{chunk-MJSJAHBW.js → chunk-DY7TRYB5.js} +1 -1
  77. package/dist/{chunk-GPPUTY5M.js → chunk-EDLNHZH3.js} +861 -891
  78. package/dist/{chunk-R5BFYK2O.js → chunk-IGHMVDWI.js} +134 -18
  79. package/dist/chunk-MU6HHZEN.js +99 -0
  80. package/dist/{chunk-XTKJPSMF.js → chunk-NVOTGWYX.js} +458 -684
  81. package/dist/{chunk-AEWZ7F65.js → chunk-O24R4DCK.js} +2 -179
  82. package/dist/{chunk-CCFROYAV.js → chunk-PUAMO4PI.js} +115 -125
  83. package/dist/{chunk-ZMRLBBD5.js → chunk-RMVOAJRL.js} +30 -13
  84. package/dist/{chunk-3NYUCBLE.js → chunk-SPUAJVVH.js} +6 -4
  85. package/dist/{chunk-4UYIRWDW.js → chunk-SS67LUOK.js} +41 -290
  86. package/dist/{chunk-FXFQNHRU.js → chunk-VFUK3X5B.js} +4 -2
  87. package/dist/{chunk-3MPPVPGZ.js → chunk-VH6KWKG2.js} +2 -2
  88. package/dist/chunk-VIXFG2VC.js +182 -0
  89. package/dist/{chunk-BKM4UXUD.js → chunk-YFQ7CQDE.js} +669 -18
  90. package/dist/{chunk-77LHNQK4.js → chunk-YIPD3L6L.js} +4 -2
  91. package/dist/{chunk-3OUSJPR7.js → chunk-YNP2ATQX.js} +6 -4
  92. package/dist/{chunk-WR7H7VLJ.js → chunk-YT72TOEK.js} +2 -2
  93. package/dist/cli/chat.js +21 -20
  94. package/dist/cli/check.js +4 -3
  95. package/dist/cli/plugins.js +11 -9
  96. package/dist/cli/snapshot-warmup.js +7 -5
  97. package/dist/cli/upgrade.js +2041 -105
  98. package/dist/db/schema/{agent-steps.d.ts → conversation-events.d.ts} +37 -21
  99. package/dist/db/schema.d.ts +28 -159
  100. package/dist/{db-S33LFWG2.js → db-DIGO4TGW.js} +6 -8
  101. package/dist/{runner-HA5XAL6K.js → runner-ACR2HAIC.js} +209 -101
  102. package/dist/{skills-722AXRV5.js → skills-ITNHBARB.js} +4 -3
  103. package/dist/{validation-EUI2UFRM.js → validation-AGQ46ZGV.js} +4 -3
  104. package/migrations/0005_conversation_events.sql +122 -0
  105. package/migrations/README.md +23 -10
  106. package/migrations/meta/0005_snapshot.json +948 -0
  107. package/migrations/meta/_journal.json +7 -0
  108. package/package.json +5 -5
  109. package/dist/api/conversations/activity.d.ts +0 -40
  110. package/dist/api/conversations/detail-projection.d.ts +0 -11
  111. package/dist/api/conversations/detail.query.d.ts +0 -3
  112. package/dist/api/conversations/subagent.d.ts +0 -10
  113. package/dist/api/conversations/transcript.d.ts +0 -28
  114. package/dist/chat/conversations/legacy-advisor-session.d.ts +0 -7
  115. package/dist/chat/conversations/legacy-import.d.ts +0 -38
  116. package/dist/chat/conversations/sql/legacy-history-import.d.ts +0 -55
  117. package/dist/chat/conversations/sql/messages.d.ts +0 -4
  118. package/dist/chat/conversations/visible-compactions.d.ts +0 -11
  119. package/dist/chat/conversations/visible-messages.d.ts +0 -47
  120. package/dist/chat/services/reply-delivery-plan.d.ts +0 -5
  121. package/dist/chat/state/session-log.d.ts +0 -384
  122. package/dist/chunk-P4P7O5WG.js +0 -1072
  123. package/dist/chunk-XIMUQ4IU.js +0 -147
  124. package/dist/db/schema/conversation-messages.d.ts +0 -153
  125. package/dist/handlers/github-webhook/check-suite.d.ts +0 -3
  126. package/dist/handlers/github-webhook/issue-comment.d.ts +0 -3
  127. package/dist/handlers/github-webhook/pull-request-review-comment.d.ts +0 -3
  128. package/dist/handlers/github-webhook/pull-request-review.d.ts +0 -3
  129. package/dist/handlers/github-webhook/pull-request.d.ts +0 -3
  130. package/dist/handlers/github-webhook/resource.d.ts +0 -10
  131. package/dist/handlers/github-webhook.d.ts +0 -15
  132. package/dist/legacy-import-TMJISRKO.js +0 -18
@@ -0,0 +1,6 @@
1
+ import type { ConversationEvent } from "./history";
2
+ import type { ConversationMessage } from "@/chat/state/conversation";
3
+ /** Reduce canonical message facts into destination-facing history. */
4
+ export declare function projectConversationMessages(events: ConversationEvent[], options?: {
5
+ historyFromSeq?: number;
6
+ }): ConversationMessage[];
@@ -0,0 +1,9 @@
1
+ import type { ConversationEvent } from "./history";
2
+ import type { ConversationCompaction, ThreadConversationState } from "@/chat/state/conversation";
3
+ /** Project the latest source-message summary snapshot from event history. */
4
+ export declare function projectConversationMessageSummaries(events: ConversationEvent[]): ConversationCompaction[];
5
+ /** Persist a changed source-message summary snapshot in event history. */
6
+ export declare function persistConversationMessageSummaries(args: {
7
+ conversation: ThreadConversationState;
8
+ conversationId: string;
9
+ }): Promise<void>;
@@ -1,9 +1,4 @@
1
- /**
2
- * Visible conversation message port.
3
- *
4
- * Messages are immutable source facts recorded idempotently by source identity;
5
- * the only mutable bookkeeping is the `replied_at` delivery mark.
6
- */
1
+ import type { ConversationMessage, ThreadConversationState } from "@/chat/state/conversation";
7
2
  /** Author role of a visible conversation message. */
8
3
  export type ConversationMessageRole = "user" | "assistant" | "system";
9
4
  /** A source message to record; identity is `(conversationId, messageId)`. */
@@ -15,25 +10,16 @@ export interface NewConversationMessage {
15
10
  meta?: Record<string, unknown>;
16
11
  createdAtMs: number;
17
12
  }
18
- /** A visible message read back from storage. */
19
- export interface ConversationMessage {
20
- conversationId: string;
21
- messageId: string;
22
- role: ConversationMessageRole;
23
- text: string;
24
- authorIdentityId?: string;
25
- meta?: Record<string, unknown>;
13
+ /** Serialize one in-memory message into its event-backed write shape. */
14
+ export declare function toStoredConversationMessage(message: ConversationMessage): NewConversationMessage;
15
+ /** Hydrate the current message working set from canonical conversation events. */
16
+ export declare function hydrateConversationMessages(args: {
17
+ conversation: ThreadConversationState;
18
+ conversationId: string | undefined;
19
+ }): Promise<void>;
20
+ /** Append new messages and handled markers idempotently. */
21
+ export declare function persistConversationMessages(args: {
22
+ conversation: ThreadConversationState;
23
+ conversationId: string | undefined;
26
24
  repliedAtMs?: number;
27
- createdAtMs: number;
28
- }
29
- /** Persist and read the visible per-conversation message transcript. */
30
- export interface ConversationMessageStore {
31
- /** Record source messages idempotently by `(conversation_id, message_id)`. */
32
- record(conversationId: string, messages: NewConversationMessage[]): Promise<void>;
33
- /** Set the mutable `replied_at` mark; content columns are never touched. */
34
- markReplied(conversationId: string, messageId: string, repliedAtMs: number): Promise<void>;
35
- /** List messages in `created_at` order. */
36
- list(conversationId: string, opts?: {
37
- limit?: number;
38
- }): Promise<ConversationMessage[]>;
39
- }
25
+ }): Promise<void>;
@@ -1,46 +1,24 @@
1
- import type { PiMessage } from "@/chat/pi/messages";
2
- import { type AuthorizationKind, type PiMessageProvenance, type SessionProjection } from "@/chat/state/session-log";
3
- import type { StoredAgentStep } from "@/chat/conversations/history";
4
- import type { ModelProfile } from "@/chat/model-profile";
5
- /** Current conversation context with its authoritative model binding. */
6
- export interface ConversationProjection extends SessionProjection {
7
- /** Model profile bound to this projection. */
8
- modelProfile: ModelProfile;
9
- /** Audit snapshot; runtime model selection remains profile-driven. */
10
- modelId: string | undefined;
11
- }
12
- /** Aligned step projection: `provenance[i]` and `seqs[i]` describe `messages[i]`. */
13
- export interface StepProjection extends ConversationProjection {
14
- /** The `seq` of the step each projected message came from. */
15
- seqs: number[];
16
- }
17
- /**
18
- * Materialize Pi messages with aligned provenance and source seqs from one
19
- * epoch's steps. Steps above `maxSeq` (when given) are excluded so a terminal
20
- * turn record reproduces exactly the boundary it committed.
21
- */
22
- export declare function projectSteps(steps: StoredAgentStep[], opts?: {
23
- maxSeq?: number;
24
- }): StepProjection;
1
+ import { type PiMessage } from "@/chat/pi/messages";
2
+ import { type ConversationMessageProvenance } from "@/chat/conversations/provenance";
3
+ import type { AuthorizationKind } from "@/chat/conversations/history";
4
+ import type { JuniorSqlDatabase } from "@/db/db";
5
+ import { type PiConversationEventProjection, type PiConversationProjection } from "@/chat/pi/conversation-events";
25
6
  interface ScopedConversation {
26
7
  conversationId: string;
27
8
  }
28
- /** Load the current-epoch Pi projection for a conversation. */
9
+ /** Load the current Pi agent history for a conversation. */
29
10
  export declare function loadProjection(args: ScopedConversation): Promise<PiMessage[]>;
30
- /** Load the current-epoch Pi projection with aligned per-message provenance. */
31
- export declare function loadConversationProjection(args: ScopedConversation): Promise<ConversationProjection>;
32
- /** Open a standard initial epoch before a conversation's first model request. */
33
- export declare function openConversationProjection(args: ScopedConversation & {
34
- modelId: string;
35
- }): Promise<ConversationProjection>;
11
+ /** Load current Pi context with aligned provenance and source event sequences. */
12
+ export declare function loadConversationProjection(args: ScopedConversation): Promise<PiConversationEventProjection>;
13
+ /** Load the active Pi projection before a conversation's next request. */
14
+ export declare function openConversationProjection(args: ScopedConversation): Promise<PiConversationProjection>;
36
15
  /**
37
- * Load a turn's committed Pi projection from the durable step store.
16
+ * Load a turn's committed Pi projection from the durable event store.
38
17
  *
39
- * The record stays pinned to the epoch containing its committed boundary, so a
40
- * later rollback or compaction cannot silently rewrite what a stale record
41
- * resumes from. Unfinished records (`includeTail`) also see that epoch's tail
42
- * so parked input appended after the last safe boundary is model-visible; for
43
- * a live run the committed epoch is the current epoch. Terminal records
18
+ * The record stays pinned to the history version containing its committed
19
+ * boundary, so later compaction cannot rewrite what a stale record resumes
20
+ * from. Unfinished records (`includeTail`) also see that version's tail so
21
+ * parked input appended after the last safe boundary is model-visible. Terminal records
44
22
  * reproduce exactly the boundary they committed by cutting at `committedSeq`.
45
23
  * Returns undefined when the committed boundary no longer exists (purged
46
24
  * history) so callers fail closed.
@@ -49,33 +27,33 @@ export declare function loadTurnProjection(args: {
49
27
  conversationId: string;
50
28
  committedSeq: number;
51
29
  includeTail: boolean;
52
- }): Promise<StepProjection | undefined>;
53
- /** Load MCP providers durably connected in this conversation's current epoch. */
30
+ }): Promise<PiConversationEventProjection | undefined>;
31
+ /** Load MCP providers connected in the current agent-history version. */
54
32
  export declare function loadConnectedMcpProviders(args: ScopedConversation): Promise<string[]>;
55
33
  /**
56
- * Commit the turn's Pi history: append when it advanced the committed
57
- * projection normally, or open a `rollback` epoch when it diverged (a
58
- * provider-retry trim regenerated trailing assistant output). Returns the
59
- * resolved provenance, the per-message step seqs, and the `seq` boundary that
60
- * reproduces exactly the committed messages. A first commit atomically opens
61
- * the standard initial epoch; the run boundary opens it earlier when a model
62
- * may act before any session checkpoint, such as recordless handoff.
34
+ * Append newly stable agent steps. A shorter or changed prefix indicates
35
+ * that a caller persisted volatile Pi state; only compaction and handoff may
36
+ * intentionally replace active model history.
63
37
  */
64
38
  export declare function commitMessages(args: {
65
39
  conversationId: string;
66
- /** Exact model selected for this write; persisted for epoch audit only. */
67
- modelId: string;
68
40
  messages: PiMessage[];
69
41
  /** Explicit per-message provenance aligned one-to-one with `messages`. */
70
- provenance?: PiMessageProvenance[];
42
+ provenance?: ConversationMessageProvenance[];
71
43
  /** Explicit provenance for the trailing newly committed messages. */
72
- trailingMessageProvenance?: PiMessageProvenance[];
44
+ trailingMessageProvenance?: ConversationMessageProvenance[];
73
45
  /** Default applied to the last new user message when no explicit array. */
74
- newMessageProvenance?: PiMessageProvenance;
46
+ newMessageProvenance?: ConversationMessageProvenance;
47
+ /** SQL authority for the atomic commit; defaults to the process executor. */
48
+ executor?: JuniorSqlDatabase;
75
49
  }): Promise<{
76
50
  committedSeq: number;
51
+ historyVersion: number;
52
+ /** Event sequence for every projected agent step. */
77
53
  messageSeqs: number[];
78
- provenance: PiMessageProvenance[];
54
+ /** Normalized durable messages after volatile runtime context is removed. */
55
+ messages: PiMessage[];
56
+ provenance: ConversationMessageProvenance[];
79
57
  }>;
80
58
  /** Record a successful MCP provider connection without duplicating the fact. */
81
59
  export declare function recordMcpProviderConnected(args: {
@@ -102,7 +80,6 @@ export declare function recordAuthorizationCompleted(args: {
102
80
  /** Record a host-observed parent tool start without adding it to Pi replay. */
103
81
  export declare function recordToolExecutionStarted(args: {
104
82
  conversationId: string;
105
- args?: unknown;
106
83
  createdAtMs?: number;
107
84
  toolCallId: string;
108
85
  toolName: string;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Durable message attribution shared by storage and projections.
3
+ * Attribution never grants credential authority.
4
+ */
5
+ import { type Actor } from "@sentry/junior-plugin-api";
6
+ import { z } from "zod";
7
+ declare const conversationMessageAuthoritySchema: z.ZodUnion<readonly [z.ZodLiteral<"instruction">, z.ZodLiteral<"context">]>;
8
+ /** Canonical authority and actor metadata for one durable message event. */
9
+ export declare const conversationMessageProvenanceSchema: z.ZodObject<{
10
+ authority: z.ZodUnion<readonly [z.ZodLiteral<"instruction">, z.ZodLiteral<"context">]>;
11
+ actor: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
12
+ platform: z.ZodLiteral<"slack">;
13
+ teamId: z.ZodString;
14
+ email: z.ZodOptional<z.ZodString>;
15
+ fullName: z.ZodOptional<z.ZodString>;
16
+ userId: z.ZodString;
17
+ userName: z.ZodOptional<z.ZodString>;
18
+ }, z.core.$strict>, z.ZodObject<{
19
+ platform: z.ZodLiteral<"local">;
20
+ email: z.ZodOptional<z.ZodString>;
21
+ fullName: z.ZodOptional<z.ZodString>;
22
+ userId: z.ZodString;
23
+ userName: z.ZodOptional<z.ZodString>;
24
+ }, z.core.$strict>, z.ZodObject<{
25
+ platform: z.ZodLiteral<"system">;
26
+ name: z.ZodString;
27
+ }, z.core.$strict>], "platform">>;
28
+ }, z.core.$strict>;
29
+ /** Whether a message is a durable instruction or ambient conversation context. */
30
+ export type ConversationMessageAuthority = z.output<typeof conversationMessageAuthoritySchema>;
31
+ /** Actor and authority metadata aligned with one durable message event. */
32
+ export type ConversationMessageProvenance = z.output<typeof conversationMessageProvenanceSchema>;
33
+ /** Build instruction provenance for an optional actor. */
34
+ export declare function instructionProvenanceFor(actor: Actor | undefined): ConversationMessageProvenance;
35
+ /** Unattributed ambient-context provenance for non-instruction messages. */
36
+ export declare const contextProvenance: ConversationMessageProvenance;
37
+ /**
38
+ * Return distinct instruction actors in first-seen order for attribution only.
39
+ * Never use this list as credential authority.
40
+ */
41
+ export declare function instructionActors(provenance: ConversationMessageProvenance[]): Actor[];
42
+ export {};
@@ -1,4 +1,4 @@
1
- /** One relevant visible-message match from a prior conversation. */
1
+ /** One relevant chat-message match from a prior conversation. */
2
2
  export interface ConversationSearchResult {
3
3
  conversationId: string;
4
4
  excerpt: string;
@@ -13,7 +13,7 @@ export interface ConversationSearchScope {
13
13
  provider: "slack";
14
14
  providerTenantId: string;
15
15
  }
16
- /** Search retained public visible messages within an authorized workspace. */
16
+ /** Search retained public messages within an authorized workspace. */
17
17
  export interface ConversationSearchStore {
18
18
  search(args: {
19
19
  currentConversationId: string;
@@ -1,7 +1,7 @@
1
1
  import type { JuniorSqlDatabase } from "@/db/db";
2
2
  /**
3
3
  * Establish the conversation metadata row on first contact for content writes
4
- * (agent steps, visible transcript) that can land before activity recording has
4
+ * (conversation events, visible transcript) that can land before activity has
5
5
  * created the row, and whose tables FK to it.
6
6
  *
7
7
  * First contact creates the row; every later content write advances the
@@ -0,0 +1,3 @@
1
+ import type { JuniorSqlDatabase } from "@/db/db";
2
+ /** Serialize all event sequence allocation and visible projection writes. */
3
+ export declare function withConversationEventLock<T>(executor: JuniorSqlDatabase, conversationId: string, callback: () => Promise<T>): Promise<T>;
@@ -1,4 +1,4 @@
1
1
  import type { JuniorSqlDatabase } from "@/db/db";
2
- import { type AgentStepStore } from "../history";
3
- /** Create a SQL-backed agent step store. */
4
- export declare function createSqlAgentStepStore(executor: JuniorSqlDatabase): AgentStepStore;
2
+ import { type ConversationEventStore } from "../history";
3
+ /** Create a SQL-backed canonical conversation event store. */
4
+ export declare function createSqlConversationEventStore(executor: JuniorSqlDatabase): ConversationEventStore;
@@ -0,0 +1,27 @@
1
+ import type { JuniorSqlDatabase } from "@/db/db";
2
+ import { juniorConversationEvents } from "@/db/schema";
3
+ import type { JuniorDestinationVisibility } from "@/db/schema/destinations";
4
+ /** Root conversation identity and its normalized destination visibility. */
5
+ export interface RootConversationVisibility {
6
+ rootConversationId: string;
7
+ visibility: JuniorDestinationVisibility | null;
8
+ }
9
+ type ConversationEventPrivacySnapshot = RootConversationVisibility & {
10
+ events: Array<typeof juniorConversationEvents.$inferSelect>;
11
+ };
12
+ /**
13
+ * Read selected event rows and their root privacy authority in one SQL snapshot.
14
+ */
15
+ export declare function readConversationEventPrivacySnapshot(executor: JuniorSqlDatabase, args: {
16
+ conversationId: string;
17
+ eventTypes: readonly string[];
18
+ }): Promise<ConversationEventPrivacySnapshot | undefined>;
19
+ /**
20
+ * Resolve a conversation's privacy authority from its persisted root.
21
+ *
22
+ * Parent links are immutable after insertion. Missing, cyclic, or over-depth
23
+ * lineage fails closed, while the root destination is locked so callers that
24
+ * keep the transaction open receive a stable visibility decision.
25
+ */
26
+ export declare function resolveRootVisibility(executor: JuniorSqlDatabase, conversationId: string): Promise<RootConversationVisibility>;
27
+ export {};
@@ -28,7 +28,7 @@ export declare function selectExpiredRoots(executor: JuniorSqlDatabase, args: {
28
28
  }): Promise<ExpiredRoot[]>;
29
29
  /**
30
30
  * Purge one conversation tree in a single transaction: delete all message and
31
- * step rows for the given conversation and every descendant, stamp
31
+ * event rows for the given conversation and every descendant, stamp
32
32
  * `transcript_purged_at`, and — for non-public content — null the raw-payload
33
33
  * metadata (`title`, `channel_name`, legacy actor JSON) so purged private
34
34
  * conversations keep only safe metadata. The metadata rows themselves survive.
@@ -36,18 +36,10 @@ export declare function selectExpiredRoots(executor: JuniorSqlDatabase, args: {
36
36
  export declare function purgeConversationTree(executor: JuniorSqlDatabase, args: {
37
37
  rootConversationId: string;
38
38
  scrubMetadata?: boolean;
39
+ scrubMetadataFromRootVisibility?: boolean;
39
40
  nowMs: number;
40
41
  retention?: {
41
42
  privateWindowMs: number;
42
43
  publicWindowMs: number;
43
44
  };
44
45
  }): Promise<PurgeTreeResult>;
45
- /**
46
- * Walk `parent_conversation_id` to the root and return the root's destination
47
- * visibility. Retention resolves visibility at purge time rather than storing an
48
- * expiry, so a public↔private flip takes effect on the next pass.
49
- */
50
- export declare function resolveRootVisibility(executor: JuniorSqlDatabase, conversationId: string): Promise<{
51
- rootConversationId: string;
52
- visibility: JuniorDestinationVisibility | null;
53
- }>;
@@ -38,11 +38,6 @@ export declare class SqlStore implements ConversationStore {
38
38
  updatedAtMs: number;
39
39
  visibility?: ConversationPrivacy;
40
40
  }): Promise<void>;
41
- ensureChildConversation(args: {
42
- conversationId: string;
43
- parentConversationId: string;
44
- nowMs?: number;
45
- }): Promise<void>;
46
41
  /** Copy one conversation record and retained metrics into SQL during backfill. */
47
42
  backfillConversation(sourceConversation: Conversation, metrics?: {
48
43
  durationMs: number;
@@ -11,6 +11,10 @@ export interface ConversationExecution {
11
11
  status: ConversationStatus;
12
12
  updatedAtMs?: number;
13
13
  }
14
+ /** Immutable parent correlation for a child conversation. */
15
+ export interface ConversationLineage {
16
+ parentConversationId: string;
17
+ }
14
18
  export interface Conversation {
15
19
  archivedAtMs?: number;
16
20
  channelName?: string;
@@ -19,6 +23,7 @@ export interface Conversation {
19
23
  destination?: Destination;
20
24
  execution: ConversationExecution;
21
25
  lastActivityAtMs: number;
26
+ lineage?: ConversationLineage;
22
27
  actor?: StoredSlackActor;
23
28
  schemaVersion: 1;
24
29
  source?: ConversationSource;
@@ -26,7 +31,7 @@ export interface Conversation {
26
31
  updatedAtMs: number;
27
32
  /**
28
33
  * When retention purged this conversation's content. Set means messages and
29
- * steps were deleted wholesale; reporting presents the transcript as expired
34
+ * events were deleted wholesale; reporting presents the transcript as expired
30
35
  * rather than privacy-redacted (`../../../../../policies/data-redaction.md`).
31
36
  */
32
37
  transcriptPurgedAtMs?: number;
@@ -57,19 +62,9 @@ export interface ConversationStore {
57
62
  visibility?: ConversationPrivacy;
58
63
  }): Promise<void>;
59
64
  /**
60
- * Establish a subagent child conversation row linked to its parent.
61
- *
62
- * Subagent histories live under their own child `conversation_id` with
63
- * `parent_conversation_id` set; the child carries no destination and is
64
- * excluded from top-level listings. Idempotent: it links a bare row a step
65
- * append may have created first without clobbering it.
65
+ * Materialize execution and usage aggregates beside canonical metadata.
66
+ * These fields serve reporting and runtime control, never history hydration.
66
67
  */
67
- ensureChildConversation(args: {
68
- conversationId: string;
69
- parentConversationId: string;
70
- nowMs?: number;
71
- }): Promise<void>;
72
- /** Store task-execution metadata for long-term conversation history. */
73
68
  recordExecution(args: {
74
69
  channelName?: string;
75
70
  conversationId: string;
@@ -0,0 +1,41 @@
1
+ import type { ConversationEventStore, ConversationTurnFailureCode } from "./history";
2
+ /** Product-owned inputs for opening one correlated conversation turn. */
3
+ export interface StartConversationTurnInput {
4
+ conversationId: string;
5
+ createdAtMs: number;
6
+ inputMessageIds: string[];
7
+ surface: "slack" | "api" | "scheduler" | "internal";
8
+ turnId: string;
9
+ }
10
+ /** Product-owned inputs for closing one correlated conversation turn. */
11
+ export interface CompleteConversationTurnInput {
12
+ conversationId: string;
13
+ createdAtMs: number;
14
+ outcome: "success" | "no_reply";
15
+ turnId: string;
16
+ }
17
+ /** Privacy-safe inputs for failing one correlated conversation turn. */
18
+ export interface FailConversationTurnInput {
19
+ conversationId: string;
20
+ createdAtMs: number;
21
+ eventId?: string;
22
+ failureCode: ConversationTurnFailureCode;
23
+ turnId: string;
24
+ }
25
+ /** Runtime port for correlated canonical turn lifecycle persistence. */
26
+ export interface ConversationTurnLifecycle {
27
+ start(input: StartConversationTurnInput): Promise<void>;
28
+ complete(input: CompleteConversationTurnInput): Promise<void>;
29
+ fail(input: FailConversationTurnInput): Promise<void>;
30
+ }
31
+ /** Persist correlated turn lifecycle facts with retry-safe terminal exclusion. */
32
+ export declare class ConversationTurnLifecycleService implements ConversationTurnLifecycle {
33
+ private readonly events;
34
+ constructor(events: ConversationEventStore);
35
+ /** Record the turn start once after every input message is durable. */
36
+ start(input: StartConversationTurnInput): Promise<void>;
37
+ /** Record successful or intentional-silence completion once. */
38
+ complete(input: CompleteConversationTurnInput): Promise<void>;
39
+ /** Record a classified failure once without accepting raw error details. */
40
+ fail(input: FailConversationTurnInput): Promise<void>;
41
+ }
package/dist/chat/db.d.ts CHANGED
@@ -1,21 +1,15 @@
1
1
  import type { ConversationStore } from "@/chat/conversations/store";
2
- import type { AgentStepStore } from "@/chat/conversations/history";
3
- import type { ConversationMessageStore } from "@/chat/conversations/messages";
2
+ import type { ConversationEventStore } from "@/chat/conversations/history";
4
3
  import type { ConversationSearchStore } from "@/chat/conversations/search";
5
4
  import type { JuniorDatabase, JuniorSqlExecutor } from "@/db/db";
6
- /**
7
- * Return the process SQL executor. Exposed for the one-time legacy import
8
- * writer, which needs explicit-`seq`/epoch inserts the step-store port omits.
9
- */
5
+ /** Return the process SQL executor for SQL-specific queries and transactions. */
10
6
  export declare function getSqlExecutor(): JuniorSqlExecutor;
11
7
  /** Return the process Drizzle database. */
12
8
  export declare function getDb(): JuniorDatabase;
13
9
  /** Return the SQL-backed conversation store. */
14
10
  export declare function getConversationStore(): ConversationStore;
15
- /** Return the SQL-backed durable agent step store. */
16
- export declare function getAgentStepStore(): AgentStepStore;
17
- /** Return the SQL-backed visible conversation message store. */
18
- export declare function getConversationMessageStore(): ConversationMessageStore;
11
+ /** Return the canonical SQL-backed conversation event store. */
12
+ export declare function getConversationEventStore(): ConversationEventStore;
19
13
  /** Return the SQL-backed public provider-tenant conversation search store. */
20
14
  export declare function getConversationSearchStore(): ConversationSearchStore;
21
15
  /** Close the process SQL database when it has been opened. */
@@ -1,14 +1,24 @@
1
1
  import { z } from "zod";
2
2
  import type { BotConfig } from "@/chat/config";
3
+ import type { TurnReasoningLevel } from "@/chat/reasoning-level";
3
4
  export declare const STANDARD_MODEL_PROFILE = "standard";
4
5
  export declare const DEFAULT_HANDOFF_MODEL_PROFILE = "handoff";
5
6
  /** Keep durable profile names stable and safe to expose in tool schemas. */
6
7
  export declare const modelProfileSchema: z.ZodString;
7
8
  /** A configured model role rather than a provider-specific model id. */
8
9
  export type ModelProfile = z.output<typeof modelProfileSchema>;
10
+ /** Runtime configuration for one named execution profile. */
11
+ export interface ExecutionProfileConfig {
12
+ modelId: string;
13
+ reasoningLevel?: TurnReasoningLevel;
14
+ }
9
15
  /** Identify durable profile bindings that the current host cannot resolve. */
10
16
  export declare class ModelProfileNotConfiguredError extends Error {
11
17
  constructor(profile: ModelProfile);
12
18
  }
13
19
  /** Resolve a stable model profile through the host-owned model catalog. */
14
20
  export declare function modelIdForProfile(config: BotConfig, profile: ModelProfile): string;
21
+ /** Resolve the standard execution profile's model. */
22
+ export declare function standardModelId(config: BotConfig): string;
23
+ /** Resolve a stable model profile through the host-owned profile catalog. */
24
+ export declare function profileConfig(config: BotConfig, profile: ModelProfile): ExecutionProfileConfig;
@@ -1,5 +1,4 @@
1
1
  import { type Destination, type Source } from "@sentry/junior-plugin-api";
2
- import type { ChannelConfigurationService } from "@/chat/configuration/types";
3
2
  type PrivateDeliveryResult = "in_context" | "fallback_dm" | false;
4
3
  export type OAuthStatePayload = {
5
4
  userId: string;
@@ -8,8 +7,6 @@ export type OAuthStatePayload = {
8
7
  destination?: Destination;
9
8
  source?: Source;
10
9
  threadTs?: string;
11
- pendingMessage?: string;
12
- configuration?: Record<string, unknown>;
13
10
  resumeConversationId?: string;
14
11
  resumeSessionId?: string;
15
12
  scope?: string;
@@ -20,8 +17,6 @@ type OAuthFlowInput = {
20
17
  destination?: Destination;
21
18
  source?: Source;
22
19
  threadTs?: string;
23
- userMessage?: string;
24
- channelConfiguration?: ChannelConfigurationService;
25
20
  activeSkillName?: string;
26
21
  resumeConversationId?: string;
27
22
  resumeSessionId?: string;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Pi adapter for Junior conversation events.
3
+ *
4
+ * Conversation storage owns the ordered event log. This module turns its
5
+ * stored messages into the active Pi context.
6
+ */
7
+ import type { ModelProfile } from "@/chat/model-profile";
8
+ import type { ConversationEvent } from "@/chat/conversations/history";
9
+ import { type PiMessage } from "@/chat/pi/messages";
10
+ import { type ConversationMessageProvenance } from "@/chat/conversations/provenance";
11
+ /** Pi context projected from one Junior model-history version. */
12
+ export interface PiConversationProjection {
13
+ messages: PiMessage[];
14
+ provenance: ConversationMessageProvenance[];
15
+ modelProfile: ModelProfile;
16
+ modelId: string | undefined;
17
+ }
18
+ /** Pi context with the source event sequence for every projected message. */
19
+ export interface PiConversationEventProjection extends PiConversationProjection {
20
+ seqs: number[];
21
+ }
22
+ /**
23
+ * Project ordered Junior events into Pi context.
24
+ *
25
+ * Compaction and handoff start with replacement history. Later agent-step
26
+ * events append after it.
27
+ *
28
+ * Host-only events are filtered, completed authorization becomes a synthetic
29
+ * observation, and `maxSeq` reproduces an exact committed boundary.
30
+ */
31
+ export declare function projectConversationEvents(events: ConversationEvent[], options?: {
32
+ maxSeq?: number;
33
+ }): PiConversationEventProjection;
@@ -0,0 +1,10 @@
1
+ import type { JuniorSqlDatabase } from "@/db/db";
2
+ import { type AgentTurnUsage } from "@/chat/usage";
3
+ /**
4
+ * Aggregate real assistant calls by provider/model in SQL. Replayed history is
5
+ * not another call; its tokens appear in the next call's input usage.
6
+ */
7
+ export declare function readConversationModelUsageFromSql(executor: JuniorSqlDatabase, conversationId: string): Promise<Array<{
8
+ modelId: string;
9
+ usage: AgentTurnUsage;
10
+ }>>;
@@ -1,4 +1,4 @@
1
- import type { PluginRoute, PluginOperationalReport, PluginRouteApp, SlackConversationLink, PluginRegistration } from "@sentry/junior-plugin-api";
1
+ import type { PluginRoute, PluginOperationalReport, PluginRouteApp, ResourceEventPublisher, SlackConversationLink, PluginRegistration } from "@sentry/junior-plugin-api";
2
2
  import type { PluginPromptContributionContext } from "@/chat/plugins/prompt";
3
3
  import type { AnyToolDefinition } from "@/chat/tools/definition";
4
4
  import type { ToolRuntimeContext } from "@/chat/tools/types";
@@ -42,7 +42,9 @@ export declare function getPluginUserPromptContributions(args: {
42
42
  /** Collect turn-scoped tools exposed by plugins. */
43
43
  export declare function getPluginTools(context: ToolRuntimeContext): Record<string, AnyToolDefinition>;
44
44
  /** Collect route handlers exposed by plugins for app-level mounting. */
45
- export declare function getPluginRoutes(): PluginRouteRegistration[];
45
+ export declare function getPluginRoutes(options: {
46
+ resourceEvents: ResourceEventPublisher;
47
+ }): PluginRouteRegistration[];
46
48
  /** Collect authenticated product API route apps exposed by plugins. */
47
49
  export declare function getPluginApiRoutes(): PluginApiRouteRegistration[];
48
50
  /** Resolve the first plugin conversation URL for finalized Slack footers. */
@@ -1,17 +1,5 @@
1
1
  import type { StateAdapter } from "chat";
2
- import { z } from "zod";
3
2
  import type { ConversationWorkQueue } from "@/chat/task-execution/queue";
4
- declare const ingestResourceEventInputSchema: z.ZodObject<{
5
- eventKey: z.ZodString;
6
- eventType: z.ZodString;
7
- occurredAtMs: z.ZodNumber;
8
- provider: z.ZodString;
9
- resourceRef: z.ZodString;
10
- terminal: z.ZodOptional<z.ZodBoolean>;
11
- trustedSummary: z.ZodString;
12
- untrustedText: z.ZodOptional<z.ZodString>;
13
- }, z.core.$strict>;
14
- export type IngestResourceEventInput = z.output<typeof ingestResourceEventInputSchema>;
15
3
  /** Match a normalized provider event and enqueue notifications into conversations. */
16
4
  export declare function ingestResourceEvent(input: unknown, options: {
17
5
  nowMs?: number;
@@ -20,4 +8,3 @@ export declare function ingestResourceEvent(input: unknown, options: {
20
8
  }): Promise<{
21
9
  enqueued: number;
22
10
  }>;
23
- export {};
@@ -2,7 +2,7 @@ import type { AgentRunResult } from "@/chat/services/turn-result";
2
2
  import type { ThreadConversationState } from "@/chat/state/conversation";
3
3
  import type { ThreadArtifactsState } from "@/chat/state/artifacts";
4
4
  import { type ThreadStatePatch } from "@/chat/runtime/thread-state";
5
- /** Build the canonical thread-state patch after final Slack delivery succeeds. */
5
+ /** Build state after destination delivery or intentional no-reply completion. */
6
6
  export declare function buildDeliveredTurnStatePatch(args: {
7
7
  artifactStatePatch?: Partial<ThreadArtifactsState>;
8
8
  artifacts: ThreadArtifactsState;
@@ -1,5 +1,5 @@
1
1
  import type { FileUpload } from "chat";
2
- import type { GeneratedArtifactFileRef } from "@/chat/tools/types";
2
+ import { type GeneratedArtifactFileRef } from "@/chat/tools/sandbox/file-uploads";
3
3
  import type { SandboxCommandResult } from "@/chat/sandbox/workspace";
4
4
  /** Sandbox operations needed to make generated artifacts visible to later tools. */
5
5
  export interface GeneratedArtifactSandbox {
@@ -16,6 +16,7 @@ import { type ConversationMemoryService } from "@/chat/services/conversation-mem
16
16
  import type { ContextCompactor } from "@/chat/services/context-compaction";
17
17
  import { lookupSlackUser } from "@/chat/slack/user";
18
18
  import type { AgentContinueRequest } from "@/chat/services/agent-continue";
19
+ import type { ConversationTurnLifecycle } from "@/chat/conversations/turn-lifecycle";
19
20
  export interface ReplyExecutorServices {
20
21
  agentRunner: AgentRunner;
21
22
  contextCompactor: ContextCompactor;
@@ -25,6 +26,7 @@ export interface ReplyExecutorServices {
25
26
  sessionId: string;
26
27
  }) => Promise<AgentContinueRequest | undefined>;
27
28
  lookupSlackUser: typeof lookupSlackUser;
29
+ turnLifecycle: ConversationTurnLifecycle;
28
30
  scheduleAgentContinue: (request: AgentContinueRequest) => Promise<void>;
29
31
  scheduleSessionCompletedPluginTasks: (params: {
30
32
  conversationId: string;