@sentry/junior-plugin-api 0.267.0 → 0.269.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,185 +1,11 @@
1
1
  # @sentry/junior-plugin-api
2
2
 
3
- This package defines the public contract between Junior and code plugins. The
4
- exported TypeScript types and runtime validators are authoritative.
3
+ Types and helpers for Junior code plugins. Use `defineJuniorPlugin()` to
4
+ declare a manifest, hooks, tasks, CLI commands, user pages, and conversation
5
+ events.
5
6
 
6
- ## Registration
7
+ ```bash
8
+ pnpm add @sentry/junior-plugin-api
9
+ ```
7
10
 
8
- Use
9
- `defineJuniorPlugin({ manifest, hooks, tasks, cli, model, conversationEvents })`.
10
- A plugin name is a lowercase identifier and is unique within the enabled app
11
- plugin set.
12
-
13
- Packages with JavaScript registration export one callable factory named
14
- `<domain>Plugin`, such as `githubPlugin(options?)`. Do not use a public
15
- `create<Domain>Plugin` alias or export a prebuilt registration. Call the factory
16
- even when it accepts no options.
17
-
18
- A plugin may instead be a declarative `plugin.yaml` package when it has no
19
- host-executed hooks. Do not combine an inline manifest with a second YAML
20
- definition for the same plugin.
21
-
22
- ## Manifest
23
-
24
- The manifest declares runtime metadata such as:
25
-
26
- - plugin identity and description;
27
- - skill roots and MCP tool sources;
28
- - provider domains, grants, OAuth, API-header transformations, and safe command
29
- environment placeholders;
30
- - runtime dependencies and snapshot installation steps;
31
- - configuration fields;
32
- - signed-in user pages backed by core-owned discovery and read routes.
33
-
34
- Manifest values are validated before runtime activation. Secret deployment
35
- values remain host-only; sandbox-exposed command environment must be explicitly
36
- safe.
37
-
38
- ## Hooks
39
-
40
- Plugins may contribute tools, prompt messages, lifecycle work, operational
41
- reports, and other typed hook surfaces exported by this package.
42
-
43
- - Hook context carries the active source, actor, conversation, plugin metadata,
44
- database, logging, and only the host capabilities required by that hook.
45
- - Source uses `kind` to state what produced the input. Events,
46
- scheduled automations, event automations, Plugin dispatches, and Agent invocations do not
47
- name a provider. Actor and Destination still use `platform` to name one.
48
- - Prompt hooks return bounded structured prompt messages rather than mutate the
49
- core prompt.
50
- - `formatMarkdown` is a pure text rewrite into ordinary Markdown before delivery.
51
- - `conversationTitleContext` returns short facts about objects that the first
52
- human message refers to, such as an issue number and title. The hook gets the
53
- plugin's config values, such as a default repository. It must read provider
54
- data through `ctx.egress`, which uses Junior's system identity and never
55
- starts authorization. Only the title model sees the facts. Junior bounds the
56
- wait and ignores a failed hook.
57
- - User prompt hooks for durable turns may emit registered structured events
58
- through `ctx.events` for auxiliary work completed while building context.
59
- - Tool hooks return model-visible schemas aligned with their executor inputs.
60
- - Tool registration hooks may use `ctx.sandbox` for plugin-owned workspace
61
- files and commands; Junior still owns sandbox lifecycle, cancellation,
62
- provider egress, and authorization recovery.
63
- - Host-owned structured model and embedding calls do not expose provider
64
- credentials to plugins. Both return a best-effort provider cost estimate when
65
- one is available.
66
- - Operational report and authenticated API hooks may aggregate `costUsd` from
67
- their own registered conversation events through `ctx.eventStats`. Core
68
- binds the plugin namespace and owns access to the conversation event log.
69
- Event `costUsd` is additive operation cost and must not duplicate cost
70
- already recorded in the conversation's agent model usage.
71
- - Profile report hooks return the same bounded operational report content for
72
- one subject user on a person profile. Core owns viewer authorization,
73
- collection, sanitization, and browser rendering.
74
- - Tool hooks may resolve the active Actor's Identity and User through
75
- `ctx.users.resolveActor()`, and the Actor's timezone through
76
- `ctx.users.resolveTimezone()`.
77
- - Authenticated API route hooks receive `ctx.users.resolve(email)` for lazy
78
- User lookup. Routes that do not need User data do not query identity storage.
79
- - User page readers receive the signed-in `User`. Plugins return limited data.
80
- They do not mount their own page routes or browser code.
81
-
82
- ## User Pages
83
-
84
- Register signed-in pages through `userPages` beside `hooks`, `tasks`, and `cli`.
85
- Each definition owns its navigation metadata and `read(ctx, input)` function,
86
- so a page cannot be advertised without an implementation. List readers receive
87
- validated search and cursor input and may return an opaque continuation cursor.
88
- Set `navigation: "primary"` for a top-level dashboard navigation item. The
89
- default `profile` placement keeps account-oriented pages in the signed-in user
90
- menu. Junior always renders core System navigation after plugin pages.
91
- Set `navigation: "admin"` for setup that only Junior admins may use. Core lists
92
- these pages on the dashboard Admin page and serves them only to admins. Core
93
- reads the admin role from the user record on every request.
94
- Records may expose bounded `DELETE` actions inside their own authenticated
95
- plugin API namespace. Records may also expose `GET` actions. The dashboard opens
96
- them as normal browser links, for example to start an OAuth sign-in. Core owns
97
- discovery, authentication, user resolution, routing, response validation,
98
- rendering, confirmation, and query state.
99
-
100
- Authenticated plugin API routes receive `context.auth.user.isAdmin`. Core sets
101
- it from the stored user on every request. Admin-only routes must check it on
102
- the server, because a hidden link does not protect a route.
103
-
104
- ## Durable Work
105
-
106
- - Heartbeat hooks perform bounded periodic maintenance and must be safe to run
107
- repeatedly.
108
- - Background tasks are registered by name, receive validated parameters, and
109
- execute through the host queue/callback lifecycle.
110
- - Conversation-bound background tasks may emit registered structured events
111
- through `ctx.events`. Define each version with `defineConversationEvent()`;
112
- the host supplies the plugin namespace, conversation, turn, ordering, and
113
- timestamps without treating background work as new conversation activity.
114
- Event definitions return bounded transcript presentation data, while Junior
115
- owns browser rendering.
116
- - `ctx.agent.dispatch` creates durable agent work with an explicit actor,
117
- destination, source, metadata, and idempotency identity.
118
- - Dispatches may include compact `replyAttribution` for destination-visible
119
- context about what produced the reply. Core owns platform rendering; opaque
120
- dispatch metadata remains internal.
121
- - Delegated credential subjects declare the narrow action that authorized them.
122
- Core owns runtime bindings; scheduler task subjects are accepted only from the
123
- scheduler plugin and are bound to the exact task id.
124
- - Completed dispatch and task projections are durable plugin inputs, not an
125
- invitation to inspect unrestricted conversation state.
126
-
127
- ## Conversation Events
128
-
129
- Register plugin-owned event definitions through `conversationEvents`. A
130
- definition owns one local name, version, content schema, and `renderEvent()`
131
- projection. A renderer may return `undefined` when an event should remain
132
- durable without producing a transcript row. The active plugin context supplies
133
- the namespace, so plugins cannot emit native events or impersonate another
134
- plugin. The `junior` plugin name is reserved for host-owned native events.
135
- Versions of the same event name share one operation idempotency identity,
136
- so keep previous definitions registered when evolving an event. Stored events
137
- remain durable when a plugin is removed, but normal transcript projection skips
138
- definitions that are not currently registered.
139
-
140
- ## Database
141
-
142
- - Packaged migrations create plugin-owned tables through the host migration
143
- runner.
144
- - Generate migration artifacts from the package schema; do not hand-maintain a
145
- second schema contract.
146
- - Runtime hooks and CLI actions use host-provided `ctx.db`.
147
- - Migrations are expand-first, deterministic, ordered by plugin name, and safe
148
- to retry. A failure blocks upgrade rather than partially enabling the plugin.
149
- - Cross-plugin or core-table access is a review boundary for trusted app code;
150
- introduce a facade only when a concrete security or lifecycle boundary
151
- requires it.
152
-
153
- ## CLI
154
-
155
- Code plugins may register one namespaced host CLI command with one or more
156
- subcommands. Core command names win. Actions use the host action wrapper and
157
- receive plugin metadata, configuration, database, safe output writers, and
158
- logging—not model, Slack, sandbox, or provider credential context.
159
-
160
- ## Security
161
-
162
- Plugins and skills follow `../../policies/security.md`,
163
- `../../policies/data-redaction.md`, and
164
- `../../policies/provider-boundaries.md`. Skills explain capability use; they do
165
- not bootstrap runtimes or credentials.
166
-
167
- ## Object annotations
168
-
169
- A tool can return `objectAnnotations` through `pluginToolOutputSchema` to save
170
- object facts and attach a card to the next visible reply. The host assigns the
171
- plugin owner. Use a stable `key` within the plugin, a compact `label`, a `title`,
172
- a verified HTTP(S) `url` (or null), and an `objectType`: `task`, `code_change`,
173
- `automation`, or `item`. Status and description are optional. Automations also
174
- use `trigger` and `warning`. Do not send Slack layout JSON or infer facts that
175
- the provider did not return.
176
-
177
- Show at most four fact attributes plus status. Hide code-change size counts
178
- and source update times without removing them from saved annotations.
179
-
180
- The `afterMcpTool` hook can return `{ objectAnnotations }` after a successful
181
- hosted tool call. Use `ctx.annotations.upsert` instead when facts must change
182
- without selecting a reply card, such as a background webhook update. Only return
183
- facts that can be shared with the current Conversation. Message cards reference
184
- the latest saved annotation. Tool results remain immutable for agent history.
185
- Neither cards nor annotations grant access to the provider.
11
+ Build a plugin: https://junior.sentry.dev/extend/build-a-plugin/
package/dist/index.d.ts CHANGED
@@ -9,7 +9,7 @@ import { Command } from "commander";
9
9
  * selects the fields it needs; preview rules must not remove saved facts.
10
10
  *
11
11
  * Keep raw responses, diffs, logs, credentials, and comments out of this schema.
12
- * See "Object facts" in packages/junior/src/chat/conversations/README.md.
12
+ * See "Object annotations and Message cards" in packages/junior/src/chat/conversations/AGENTS.md.
13
13
  */
14
14
  export declare const objectAnnotationSchema: z.ZodObject<{
15
15
  kind: z.ZodLiteral<"object">;
@@ -1869,6 +1869,44 @@ export interface IssueCredentialHookContext extends PluginContext {
1869
1869
  grant: PluginGrant;
1870
1870
  tokens: PluginTokenStore;
1871
1871
  }
1872
+ /** A notice that a plugin puts on the review desk. */
1873
+ export interface PluginReviewNotice {
1874
+ /** Junior assigns the User linked to each Identity. */
1875
+ assigneeIdentityIds: string[];
1876
+ /** Markdown details for the person. */
1877
+ body: string;
1878
+ /**
1879
+ * Stable key for what the notice is about. A plugin has at most one open
1880
+ * item for each key.
1881
+ */
1882
+ dedupeKey: string;
1883
+ /** What the notice is about, such as a pull request. Search matches `id`. */
1884
+ subject?: {
1885
+ id: string;
1886
+ title?: string;
1887
+ url?: string;
1888
+ };
1889
+ title: string;
1890
+ }
1891
+ /**
1892
+ * Review items that a plugin adds and closes from its own events. Each item
1893
+ * belongs to one Conversation. Core owns visibility, assignment rules, and
1894
+ * the Slack cards.
1895
+ */
1896
+ export interface PluginReviewItems {
1897
+ /** Add an open notice, or replace the content of the open one with the key. */
1898
+ upsert(notice: PluginReviewNotice): Promise<void>;
1899
+ /** Close the open item with the key. Do nothing when no item is open. */
1900
+ close(input: {
1901
+ dedupeKey: string;
1902
+ reason: string;
1903
+ status: "done" | "dismissed";
1904
+ }): Promise<void>;
1905
+ }
1906
+ /** Review items of a plugin, for the Conversation that each item belongs to. */
1907
+ export interface PluginConversationReviewItems {
1908
+ forConversation(conversationId: string): PluginReviewItems;
1909
+ }
1872
1910
  export interface HeartbeatHookContext extends PluginContext {
1873
1911
  agent: {
1874
1912
  dispatch(options: DispatchOptions): Promise<DispatchResult>;
@@ -1988,6 +2026,8 @@ export interface RouteRegistrationHookContext extends PluginContext {
1988
2026
  codeChanges: CodeChangePublisher;
1989
2027
  /** Core-owned delivery boundary for provider webhook events. */
1990
2028
  events: EventPublisher;
2029
+ /** Review desk items that the plugin adds and closes from its events. */
2030
+ reviewItems: PluginConversationReviewItems;
1991
2031
  users: {
1992
2032
  /**
1993
2033
  * Read one stored identity and the user it links to now, with every
@@ -2534,6 +2574,11 @@ export interface PluginHooks {
2534
2574
  * that changes per request in `userPrompt`. See `policies/system-prompt.md`.
2535
2575
  */
2536
2576
  systemPrompt?(ctx: SystemPromptContext): Promise<PromptMessage[]> | PromptMessage[];
2577
+ /**
2578
+ * Return per-request context for a new prompt, such as recalled memories.
2579
+ * Junior runs this hook at the same time as Turn routing and sandbox setup,
2580
+ * so it must not depend on either.
2581
+ */
2537
2582
  userPrompt?(ctx: UserPromptContext): Promise<UserPromptContribution[] | undefined> | UserPromptContribution[] | undefined;
2538
2583
  beforeToolExecute?(ctx: BeforeToolExecuteHookContext): Promise<void> | void;
2539
2584
  /**
package/dist/index.js CHANGED
@@ -157,7 +157,7 @@ function objectIconPath(icon) {
157
157
  * selects the fields it needs; preview rules must not remove saved facts.
158
158
  *
159
159
  * Keep raw responses, diffs, logs, credentials, and comments out of this schema.
160
- * See "Object facts" in packages/junior/src/chat/conversations/README.md.
160
+ * See "Object annotations and Message cards" in packages/junior/src/chat/conversations/AGENTS.md.
161
161
  */
162
162
  const objectAnnotationSchema = z.object({
163
163
  kind: z.literal("object"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/junior-plugin-api",
3
- "version": "0.267.0",
3
+ "version": "0.269.0",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"