@sentry/junior-plugin-api 0.256.0 → 0.258.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 (3) hide show
  1. package/dist/index.d.ts +2087 -2107
  2. package/dist/index.js +1093 -1260
  3. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -1,1406 +1,1239 @@
1
- // src/object-annotations.ts
2
- import { z as z3 } from "zod";
3
-
4
- // src/object-facts.ts
5
1
  import { z } from "zod";
6
- var text = z.string().trim().min(1).max(160);
7
- var count = z.number().int().nonnegative();
8
- var objectFactsSchema = z.discriminatedUnion("type", [
9
- // Code changes: keep lifecycle, review, and checks separate.
10
- z.strictObject({
11
- type: z.literal("code_change"),
12
- author: text.optional(),
13
- sourceBranch: text.optional(),
14
- targetBranch: text.optional(),
15
- reviewers: z.array(text).max(5).optional(),
16
- review: z.enum(["required", "approved", "changes_requested"]).optional(),
17
- checks: z.strictObject({ passed: count, failed: count, pending: count }).optional(),
18
- mergeable: z.boolean().optional(),
19
- changedFiles: count.optional(),
20
- additions: count.optional(),
21
- deletions: count.optional()
22
- }),
23
- // Tasks: ownership and priority first; planning context comes next.
24
- z.strictObject({
25
- type: z.literal("task"),
26
- assignees: z.array(text).max(5).optional(),
27
- priority: text.optional(),
28
- project: text.optional(),
29
- cycle: text.optional(),
30
- dueDate: z.iso.date().optional(),
31
- labels: z.array(text).max(5).optional()
32
- }),
33
- // Deployments: never copy environment values or logs.
34
- z.strictObject({
35
- type: z.literal("deployment"),
36
- project: text.optional(),
37
- environment: text.optional(),
38
- revision: text.optional(),
39
- branch: text.optional()
40
- }),
41
- // Calendar events: the owner formats the time for the requester's time zone.
42
- z.strictObject({
43
- type: z.literal("calendar_event"),
44
- when: text.optional(),
45
- attendees: z.array(text).max(5).optional()
46
- })
2
+ // src/object-facts.ts
3
+ const text = z.string().trim().min(1).max(160);
4
+ const count = z.number().int().nonnegative();
5
+ /** Small, provider-neutral facts. Missing values mean unknown, not success. */
6
+ const objectFactsSchema = z.discriminatedUnion("type", [
7
+ z.strictObject({
8
+ type: z.literal("code_change"),
9
+ author: text.optional(),
10
+ sourceBranch: text.optional(),
11
+ targetBranch: text.optional(),
12
+ reviewers: z.array(text).max(5).optional(),
13
+ review: z.enum([
14
+ "required",
15
+ "approved",
16
+ "changes_requested"
17
+ ]).optional(),
18
+ checks: z.strictObject({
19
+ passed: count,
20
+ failed: count,
21
+ pending: count
22
+ }).optional(),
23
+ mergeable: z.boolean().optional(),
24
+ changedFiles: count.optional(),
25
+ additions: count.optional(),
26
+ deletions: count.optional()
27
+ }),
28
+ z.strictObject({
29
+ type: z.literal("task"),
30
+ assignees: z.array(text).max(5).optional(),
31
+ priority: text.optional(),
32
+ project: text.optional(),
33
+ cycle: text.optional(),
34
+ dueDate: z.iso.date().optional(),
35
+ labels: z.array(text).max(5).optional()
36
+ }),
37
+ z.strictObject({
38
+ type: z.literal("deployment"),
39
+ project: text.optional(),
40
+ environment: text.optional(),
41
+ revision: text.optional(),
42
+ branch: text.optional()
43
+ }),
44
+ z.strictObject({
45
+ type: z.literal("calendar_event"),
46
+ when: text.optional(),
47
+ attendees: z.array(text).max(5).optional()
48
+ })
47
49
  ]);
50
+ /** Show at most four card attributes, in priority order, on every surface. */
48
51
  function objectFactFields(facts) {
49
- if (!facts) return [];
50
- const fields = [];
51
- const list = (values) => values?.length ? `${values.join(", ")}${values.length === 5 ? " (up to 5 shown)" : ""}` : void 0;
52
- function add(key, label, value) {
53
- if (value !== void 0 && value !== "")
54
- fields.push({ key, label, value: String(value) });
55
- }
56
- switch (facts.type) {
57
- case "code_change":
58
- add("sourceBranch", "Branch", facts.sourceBranch);
59
- break;
60
- case "task":
61
- add(
62
- "assignees",
63
- "Assignees",
64
- facts.assignees?.length === 0 ? "Unassigned" : list(facts.assignees)
65
- );
66
- add("priority", "Priority", facts.priority);
67
- add("project", "Project", facts.project);
68
- add("cycle", "Cycle", facts.cycle);
69
- add("dueDate", "Due", facts.dueDate);
70
- add("labels", "Labels", list(facts.labels));
71
- break;
72
- case "deployment":
73
- add("environment", "Environment", facts.environment);
74
- add("project", "Project", facts.project);
75
- add("revision", "Revision", facts.revision);
76
- add("branch", "Branch", facts.branch);
77
- break;
78
- case "calendar_event":
79
- add("when", "When", facts.when);
80
- add("attendees", "Attendees", list(facts.attendees));
81
- break;
82
- }
83
- return fields.slice(0, 4);
52
+ if (!facts) return [];
53
+ const fields = [];
54
+ const list = (values) => values?.length ? `${values.join(", ")}${values.length === 5 ? " (up to 5 shown)" : ""}` : void 0;
55
+ function add(key, label, value) {
56
+ if (value !== void 0 && value !== "") fields.push({
57
+ key,
58
+ label,
59
+ value: String(value)
60
+ });
61
+ }
62
+ switch (facts.type) {
63
+ case "code_change":
64
+ add("sourceBranch", "Branch", facts.sourceBranch);
65
+ break;
66
+ case "task":
67
+ add("assignees", "Assignees", facts.assignees?.length === 0 ? "Unassigned" : list(facts.assignees));
68
+ add("priority", "Priority", facts.priority);
69
+ add("project", "Project", facts.project);
70
+ add("cycle", "Cycle", facts.cycle);
71
+ add("dueDate", "Due", facts.dueDate);
72
+ add("labels", "Labels", list(facts.labels));
73
+ break;
74
+ case "deployment":
75
+ add("environment", "Environment", facts.environment);
76
+ add("project", "Project", facts.project);
77
+ add("revision", "Revision", facts.revision);
78
+ add("branch", "Branch", facts.branch);
79
+ break;
80
+ case "calendar_event":
81
+ add("when", "When", facts.when);
82
+ add("attendees", "Attendees", list(facts.attendees));
83
+ }
84
+ return fields.slice(0, 4);
84
85
  }
85
-
86
86
  // src/object-presentation.ts
87
- import { z as z2 } from "zod";
88
- var objectTypeSchema = z2.enum([
89
- "task",
90
- "code_change",
91
- "automation",
92
- "deployment",
93
- "calendar_event",
94
- "item"
87
+ /** Native object types. `task` is the stored name for a Ticket. */
88
+ const objectTypeSchema = z.enum([
89
+ "task",
90
+ "code_change",
91
+ "automation",
92
+ "deployment",
93
+ "calendar_event",
94
+ "item"
95
95
  ]);
96
- var objectTypeLabels = {
97
- task: "Ticket",
98
- code_change: "Code change",
99
- automation: "Automation",
100
- deployment: "Deployment",
101
- calendar_event: "Calendar event",
102
- item: "Item"
96
+ const objectTypeLabels = {
97
+ task: "Ticket",
98
+ code_change: "Code change",
99
+ automation: "Automation",
100
+ deployment: "Deployment",
101
+ calendar_event: "Calendar event",
102
+ item: "Item"
103
103
  };
104
+ /** Resolve identity and state without replacing the type icon with a warning. */
104
105
  function objectPresentation(object) {
105
- const type = object.objectType === "item" && object.facts?.type === "deployment" ? "deployment" : object.objectType;
106
- const status = object.status?.toLowerCase();
107
- let icon = {
108
- task: "issue-opened",
109
- code_change: "git-pull-request",
110
- automation: "workflow",
111
- deployment: "rocket",
112
- calendar_event: "calendar",
113
- item: "package"
114
- }[type];
115
- let tone = type === "automation" ? "info" : "neutral";
116
- if (type === "code_change") {
117
- if (status === "draft") icon = "git-pull-request-draft";
118
- if (status === "closed") {
119
- icon = "git-pull-request-closed";
120
- tone = "danger";
121
- }
122
- if (status === "merged") {
123
- icon = "git-merge";
124
- tone = "accent";
125
- }
126
- if (status === "open") tone = "success";
127
- } else if (type === "task") {
128
- if (status === "closed") {
129
- icon = "issue-closed";
130
- tone = "accent";
131
- }
132
- if (status === "open") tone = "success";
133
- } else if (type === "deployment") {
134
- if (status === "ready" || status === "succeeded") tone = "success";
135
- if (status === "error" || status === "failed") tone = "danger";
136
- if (status === "building" || status === "in_progress") tone = "info";
137
- }
138
- if (status === "warning" || status === "blocked") tone = "warning";
139
- return { icon, tone, label: objectTypeLabels[type] };
106
+ const type = object.objectType === "item" && object.facts?.type === "deployment" ? "deployment" : object.objectType;
107
+ const status = object.status?.toLowerCase();
108
+ let icon = {
109
+ task: "issue-opened",
110
+ code_change: "git-pull-request",
111
+ automation: "workflow",
112
+ deployment: "rocket",
113
+ calendar_event: "calendar",
114
+ item: "package"
115
+ }[type];
116
+ let tone = type === "automation" ? "info" : "neutral";
117
+ if (type === "code_change") {
118
+ if (status === "draft") icon = "git-pull-request-draft";
119
+ if (status === "closed") {
120
+ icon = "git-pull-request-closed";
121
+ tone = "danger";
122
+ }
123
+ if (status === "merged") {
124
+ icon = "git-merge";
125
+ tone = "accent";
126
+ }
127
+ if (status === "open") tone = "success";
128
+ } else if (type === "task") {
129
+ if (status === "closed") {
130
+ icon = "issue-closed";
131
+ tone = "accent";
132
+ }
133
+ if (status === "open") tone = "success";
134
+ } else if (type === "deployment") {
135
+ if (status === "ready" || status === "succeeded") tone = "success";
136
+ if (status === "error" || status === "failed") tone = "danger";
137
+ if (status === "building" || status === "in_progress") tone = "info";
138
+ }
139
+ if (status === "warning" || status === "blocked") tone = "warning";
140
+ return {
141
+ icon,
142
+ tone,
143
+ label: objectTypeLabels[type]
144
+ };
140
145
  }
146
+ /** Public, versioned asset path shared by Slack delivery and the web host. */
141
147
  function objectIconPath(icon) {
142
- return `/_junior/dashboard/object-icons/v1/${icon}.png`;
148
+ return `/_junior/dashboard/object-icons/v1/${icon}.png`;
143
149
  }
144
-
145
150
  // src/object-annotations.ts
146
- var objectAnnotationSchema = z3.object({
147
- kind: z3.literal("object"),
148
- key: z3.string().trim().min(1).max(256),
149
- label: z3.string().trim().min(1).max(256),
150
- objectType: objectTypeSchema,
151
- title: z3.string().trim().min(1).max(512),
152
- url: z3.url().max(2048).refine((value) => ["http:", "https:"].includes(new URL(value).protocol)).nullable(),
153
- description: z3.string().max(4e3).optional(),
154
- status: z3.string().trim().min(1).max(100).optional(),
155
- trigger: z3.string().max(4e3).optional(),
156
- warning: z3.string().max(1e3).optional(),
157
- displayType: z3.string().trim().min(1).max(80).optional(),
158
- sourceUpdatedAt: z3.iso.datetime({ offset: true }).optional(),
159
- facts: objectFactsSchema.refine(
160
- (facts) => new TextEncoder().encode(JSON.stringify(facts)).length <= 4096,
161
- "Object facts must not exceed 4 KiB"
162
- ).optional()
163
- }).strict().refine(
164
- (annotation) => !annotation.facts || (annotation.facts.type === "deployment" ? annotation.objectType === "deployment" || annotation.objectType === "item" : annotation.facts.type === annotation.objectType),
165
- "Object facts must match the object type"
166
- );
167
- var ownedObjectAnnotationSchema = objectAnnotationSchema.safeExtend({
168
- plugin: z3.string().min(1)
169
- });
170
-
151
+ /**
152
+ * Verified facts shared by Conversation annotations and Message cards.
153
+ * Plugins select small facts from responses they already have. Each surface owns
154
+ * its layout. Omit unknown facts; do not infer approval or passing checks.
155
+ *
156
+ * These facts support both compact previews and full details. Each surface
157
+ * selects the fields it needs; preview rules must not remove saved facts.
158
+ *
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.
161
+ */
162
+ const objectAnnotationSchema = z.object({
163
+ kind: z.literal("object"),
164
+ key: z.string().trim().min(1).max(256),
165
+ label: z.string().trim().min(1).max(256),
166
+ objectType: objectTypeSchema,
167
+ title: z.string().trim().min(1).max(512),
168
+ url: z.url().max(2048).refine((value) => ["http:", "https:"].includes(new URL(value).protocol)).nullable(),
169
+ description: z.string().max(4e3).optional(),
170
+ status: z.string().trim().min(1).max(100).optional(),
171
+ trigger: z.string().max(4e3).optional(),
172
+ warning: z.string().max(1e3).optional(),
173
+ displayType: z.string().trim().min(1).max(80).optional(),
174
+ sourceUpdatedAt: z.iso.datetime({ offset: true }).optional(),
175
+ facts: objectFactsSchema.refine((facts) => new TextEncoder().encode(JSON.stringify(facts)).length <= 4096, "Object facts must not exceed 4 KiB").optional()
176
+ }).strict().refine((annotation) => !annotation.facts || (annotation.facts.type === "deployment" ? annotation.objectType === "deployment" || annotation.objectType === "item" : annotation.facts.type === annotation.objectType), "Object facts must match the object type");
177
+ /** A saved object snapshot with its trusted owner. */
178
+ const ownedObjectAnnotationSchema = objectAnnotationSchema.safeExtend({ plugin: z.string().min(1) });
171
179
  // src/object-icons.ts
172
- var objectIconPaths = {
173
- "issue-opened": [
174
- "M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z",
175
- "M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Z"
176
- ],
177
- "issue-closed": [
178
- "M11.28 6.78a.75.75 0 0 0-1.06-1.06L7.25 8.69 5.78 7.22a.75.75 0 0 0-1.06 1.06l2 2a.75.75 0 0 0 1.06 0l3.5-3.5Z",
179
- "M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0Zm-1.5 0a6.5 6.5 0 1 0-13 0 6.5 6.5 0 0 0 13 0Z"
180
- ],
181
- "git-pull-request": [
182
- "M1.5 3.25a2.25 2.25 0 1 1 3 2.122v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.25 2.25 0 0 1 1.5 3.25Zm5.677-.177L9.573.677A.25.25 0 0 1 10 .854V2.5h1A2.5 2.5 0 0 1 13.5 5v5.628a2.251 2.251 0 1 1-1.5 0V5a1 1 0 0 0-1-1h-1v1.646a.25.25 0 0 1-.427.177L7.177 3.427a.25.25 0 0 1 0-.354ZM3.75 2.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm0 9.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm8.25.75a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Z"
183
- ],
184
- "git-pull-request-draft": [
185
- "M3.25 1A2.25 2.25 0 0 1 4 5.372v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.251 2.251 0 0 1 3.25 1Zm9.5 14a2.25 2.25 0 1 1 0-4.5 2.25 2.25 0 0 1 0 4.5ZM2.5 3.25a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0ZM3.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm9.5 0a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5ZM14 7.5a1.25 1.25 0 1 1-2.5 0 1.25 1.25 0 0 1 2.5 0Zm0-4.25a1.25 1.25 0 1 1-2.5 0 1.25 1.25 0 0 1 2.5 0Z"
186
- ],
187
- "git-pull-request-closed": [
188
- "M3.25 1A2.25 2.25 0 0 1 4 5.372v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.251 2.251 0 0 1 3.25 1Zm9.5 5.5a.75.75 0 0 1 .75.75v3.378a2.251 2.251 0 1 1-1.5 0V7.25a.75.75 0 0 1 .75-.75Zm-2.03-5.273a.75.75 0 0 1 1.06 0l.97.97.97-.97a.748.748 0 0 1 1.265.332.75.75 0 0 1-.205.729l-.97.97.97.97a.751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018l-.97-.97-.97.97a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734l.97-.97-.97-.97a.75.75 0 0 1 0-1.06ZM2.5 3.25a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0ZM3.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm9.5 0a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z"
189
- ],
190
- "git-merge": [
191
- "M5.45 5.154A4.25 4.25 0 0 0 9.25 7.5h1.378a2.251 2.251 0 1 1 0 1.5H9.25A5.734 5.734 0 0 1 5 7.123v3.505a2.25 2.25 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.95-.218ZM4.25 13.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Zm8.5-4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5ZM5 3.25a.75.75 0 1 0 0 .005V3.25Z"
192
- ],
193
- workflow: [
194
- "M0 1.75C0 .784.784 0 1.75 0h3.5C6.216 0 7 .784 7 1.75v3.5A1.75 1.75 0 0 1 5.25 7H4v4a1 1 0 0 0 1 1h4v-1.25C9 9.784 9.784 9 10.75 9h3.5c.966 0 1.75.784 1.75 1.75v3.5A1.75 1.75 0 0 1 14.25 16h-3.5A1.75 1.75 0 0 1 9 14.25v-.75H5A2.5 2.5 0 0 1 2.5 11V7h-.75A1.75 1.75 0 0 1 0 5.25Zm1.75-.25a.25.25 0 0 0-.25.25v3.5c0 .138.112.25.25.25h3.5a.25.25 0 0 0 .25-.25v-3.5a.25.25 0 0 0-.25-.25Zm9 9a.25.25 0 0 0-.25.25v3.5c0 .138.112.25.25.25h3.5a.25.25 0 0 0 .25-.25v-3.5a.25.25 0 0 0-.25-.25Z"
195
- ],
196
- rocket: [
197
- "M14.064 0h.186C15.216 0 16 .784 16 1.75v.186a8.752 8.752 0 0 1-2.564 6.186l-.458.459c-.314.314-.641.616-.979.904v3.207c0 .608-.315 1.172-.833 1.49l-2.774 1.707a.749.749 0 0 1-1.11-.418l-.954-3.102a1.214 1.214 0 0 1-.145-.125L3.754 9.816a1.218 1.218 0 0 1-.124-.145L.528 8.717a.749.749 0 0 1-.418-1.11l1.71-2.774A1.748 1.748 0 0 1 3.31 4h3.204c.288-.338.59-.665.904-.979l.459-.458A8.749 8.749 0 0 1 14.064 0ZM8.938 3.623h-.002l-.458.458c-.76.76-1.437 1.598-2.02 2.5l-1.5 2.317 2.143 2.143 2.317-1.5c.902-.583 1.74-1.26 2.499-2.02l.459-.458a7.25 7.25 0 0 0 2.123-5.127V1.75a.25.25 0 0 0-.25-.25h-.186a7.249 7.249 0 0 0-5.125 2.123ZM3.56 14.56c-.732.732-2.334 1.045-3.005 1.148a.234.234 0 0 1-.201-.064.234.234 0 0 1-.064-.201c.103-.671.416-2.273 1.15-3.003a1.502 1.502 0 1 1 2.12 2.12Zm6.94-3.935c-.088.06-.177.118-.266.175l-2.35 1.521.548 1.783 1.949-1.2a.25.25 0 0 0 .119-.213ZM3.678 8.116 5.2 5.766c.058-.09.117-.178.176-.266H3.309a.25.25 0 0 0-.213.119l-1.2 1.95ZM12 5a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"
198
- ],
199
- calendar: [
200
- "M4.75 0a.75.75 0 0 1 .75.75V2h5V.75a.75.75 0 0 1 1.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 0 1 4.75 0ZM2.5 7.5v6.75c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25V7.5Zm10.75-4H2.75a.25.25 0 0 0-.25.25V6h11V3.75a.25.25 0 0 0-.25-.25Z"
201
- ],
202
- package: [
203
- "m8.878.392 5.25 3.045c.54.314.872.89.872 1.514v6.098a1.75 1.75 0 0 1-.872 1.514l-5.25 3.045a1.75 1.75 0 0 1-1.756 0l-5.25-3.045A1.75 1.75 0 0 1 1 11.049V4.951c0-.624.332-1.201.872-1.514L7.122.392a1.75 1.75 0 0 1 1.756 0ZM7.875 1.69l-4.63 2.685L8 7.133l4.755-2.758-4.63-2.685a.248.248 0 0 0-.25 0ZM2.5 5.677v5.372c0 .09.047.171.125.216l4.625 2.683V8.432Zm6.25 8.271 4.625-2.683a.25.25 0 0 0 .125-.216V5.677L8.75 8.432Z"
204
- ]
180
+ /** Original Octicons paths, shared by web and Slack image assets. */
181
+ const objectIconPaths = {
182
+ "issue-opened": ["M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z", "M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Z"],
183
+ "issue-closed": ["M11.28 6.78a.75.75 0 0 0-1.06-1.06L7.25 8.69 5.78 7.22a.75.75 0 0 0-1.06 1.06l2 2a.75.75 0 0 0 1.06 0l3.5-3.5Z", "M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0Zm-1.5 0a6.5 6.5 0 1 0-13 0 6.5 6.5 0 0 0 13 0Z"],
184
+ "git-pull-request": ["M1.5 3.25a2.25 2.25 0 1 1 3 2.122v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.25 2.25 0 0 1 1.5 3.25Zm5.677-.177L9.573.677A.25.25 0 0 1 10 .854V2.5h1A2.5 2.5 0 0 1 13.5 5v5.628a2.251 2.251 0 1 1-1.5 0V5a1 1 0 0 0-1-1h-1v1.646a.25.25 0 0 1-.427.177L7.177 3.427a.25.25 0 0 1 0-.354ZM3.75 2.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm0 9.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm8.25.75a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Z"],
185
+ "git-pull-request-draft": ["M3.25 1A2.25 2.25 0 0 1 4 5.372v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.251 2.251 0 0 1 3.25 1Zm9.5 14a2.25 2.25 0 1 1 0-4.5 2.25 2.25 0 0 1 0 4.5ZM2.5 3.25a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0ZM3.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm9.5 0a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5ZM14 7.5a1.25 1.25 0 1 1-2.5 0 1.25 1.25 0 0 1 2.5 0Zm0-4.25a1.25 1.25 0 1 1-2.5 0 1.25 1.25 0 0 1 2.5 0Z"],
186
+ "git-pull-request-closed": ["M3.25 1A2.25 2.25 0 0 1 4 5.372v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.251 2.251 0 0 1 3.25 1Zm9.5 5.5a.75.75 0 0 1 .75.75v3.378a2.251 2.251 0 1 1-1.5 0V7.25a.75.75 0 0 1 .75-.75Zm-2.03-5.273a.75.75 0 0 1 1.06 0l.97.97.97-.97a.748.748 0 0 1 1.265.332.75.75 0 0 1-.205.729l-.97.97.97.97a.751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018l-.97-.97-.97.97a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734l.97-.97-.97-.97a.75.75 0 0 1 0-1.06ZM2.5 3.25a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0ZM3.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm9.5 0a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z"],
187
+ "git-merge": ["M5.45 5.154A4.25 4.25 0 0 0 9.25 7.5h1.378a2.251 2.251 0 1 1 0 1.5H9.25A5.734 5.734 0 0 1 5 7.123v3.505a2.25 2.25 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.95-.218ZM4.25 13.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Zm8.5-4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5ZM5 3.25a.75.75 0 1 0 0 .005V3.25Z"],
188
+ workflow: ["M0 1.75C0 .784.784 0 1.75 0h3.5C6.216 0 7 .784 7 1.75v3.5A1.75 1.75 0 0 1 5.25 7H4v4a1 1 0 0 0 1 1h4v-1.25C9 9.784 9.784 9 10.75 9h3.5c.966 0 1.75.784 1.75 1.75v3.5A1.75 1.75 0 0 1 14.25 16h-3.5A1.75 1.75 0 0 1 9 14.25v-.75H5A2.5 2.5 0 0 1 2.5 11V7h-.75A1.75 1.75 0 0 1 0 5.25Zm1.75-.25a.25.25 0 0 0-.25.25v3.5c0 .138.112.25.25.25h3.5a.25.25 0 0 0 .25-.25v-3.5a.25.25 0 0 0-.25-.25Zm9 9a.25.25 0 0 0-.25.25v3.5c0 .138.112.25.25.25h3.5a.25.25 0 0 0 .25-.25v-3.5a.25.25 0 0 0-.25-.25Z"],
189
+ rocket: ["M14.064 0h.186C15.216 0 16 .784 16 1.75v.186a8.752 8.752 0 0 1-2.564 6.186l-.458.459c-.314.314-.641.616-.979.904v3.207c0 .608-.315 1.172-.833 1.49l-2.774 1.707a.749.749 0 0 1-1.11-.418l-.954-3.102a1.214 1.214 0 0 1-.145-.125L3.754 9.816a1.218 1.218 0 0 1-.124-.145L.528 8.717a.749.749 0 0 1-.418-1.11l1.71-2.774A1.748 1.748 0 0 1 3.31 4h3.204c.288-.338.59-.665.904-.979l.459-.458A8.749 8.749 0 0 1 14.064 0ZM8.938 3.623h-.002l-.458.458c-.76.76-1.437 1.598-2.02 2.5l-1.5 2.317 2.143 2.143 2.317-1.5c.902-.583 1.74-1.26 2.499-2.02l.459-.458a7.25 7.25 0 0 0 2.123-5.127V1.75a.25.25 0 0 0-.25-.25h-.186a7.249 7.249 0 0 0-5.125 2.123ZM3.56 14.56c-.732.732-2.334 1.045-3.005 1.148a.234.234 0 0 1-.201-.064.234.234 0 0 1-.064-.201c.103-.671.416-2.273 1.15-3.003a1.502 1.502 0 1 1 2.12 2.12Zm6.94-3.935c-.088.06-.177.118-.266.175l-2.35 1.521.548 1.783 1.949-1.2a.25.25 0 0 0 .119-.213ZM3.678 8.116 5.2 5.766c.058-.09.117-.178.176-.266H3.309a.25.25 0 0 0-.213.119l-1.2 1.95ZM12 5a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"],
190
+ calendar: ["M4.75 0a.75.75 0 0 1 .75.75V2h5V.75a.75.75 0 0 1 1.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 0 1 4.75 0ZM2.5 7.5v6.75c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25V7.5Zm10.75-4H2.75a.25.25 0 0 0-.25.25V6h11V3.75a.25.25 0 0 0-.25-.25Z"],
191
+ package: ["m8.878.392 5.25 3.045c.54.314.872.89.872 1.514v6.098a1.75 1.75 0 0 1-.872 1.514l-5.25 3.045a1.75 1.75 0 0 1-1.756 0l-5.25-3.045A1.75 1.75 0 0 1 1 11.049V4.951c0-.624.332-1.201.872-1.514L7.122.392a1.75 1.75 0 0 1 1.756 0ZM7.875 1.69l-4.63 2.685L8 7.133l4.755-2.758-4.63-2.685a.248.248 0 0 0-.25 0ZM2.5 5.677v5.372c0 .09.047.171.125.216l4.625 2.683V8.432Zm6.25 8.271 4.625-2.683a.25.25 0 0 0 .125-.216V5.677L8.75 8.432Z"]
205
192
  };
206
-
207
193
  // src/annotations.ts
208
- import { z as z4 } from "zod";
209
194
  function usesHttpProtocol(value) {
210
- try {
211
- const protocol = new URL(value).protocol;
212
- return protocol === "http:" || protocol === "https:";
213
- } catch {
214
- return false;
215
- }
195
+ try {
196
+ const protocol = new URL(value).protocol;
197
+ return protocol === "http:" || protocol === "https:";
198
+ } catch {
199
+ return false;
200
+ }
216
201
  }
217
- var resourceLinkAnnotationSchema = z4.object({
218
- kind: z4.literal("resource_link"),
219
- objectType: objectTypeSchema.optional(),
220
- key: z4.string().trim().min(1).max(256),
221
- label: z4.string().trim().min(1).max(256),
222
- url: z4.string().url().max(2048).refine(usesHttpProtocol, "URL must use HTTP or HTTPS."),
223
- description: z4.string().trim().min(1).max(512).optional(),
224
- status: z4.enum(["open", "draft", "closed", "merged", "warning"]).optional()
202
+ /**
203
+ * Link an object to a Conversation when the owner has no typed object preview.
204
+ * Keep a stable key, compact label, source URL, and optional short context or
205
+ * status. Do not fetch a full object merely to save a link. Rich preview intent
206
+ * belongs to objectAnnotationSchema, not a second set of resource-link fields.
207
+ */
208
+ const resourceLinkAnnotationSchema = z.object({
209
+ kind: z.literal("resource_link"),
210
+ objectType: objectTypeSchema.optional(),
211
+ key: z.string().trim().min(1).max(256),
212
+ label: z.string().trim().min(1).max(256),
213
+ url: z.string().url().max(2048).refine(usesHttpProtocol, "URL must use HTTP or HTTPS."),
214
+ description: z.string().trim().min(1).max(512).optional(),
215
+ status: z.enum([
216
+ "open",
217
+ "draft",
218
+ "closed",
219
+ "merged",
220
+ "warning"
221
+ ]).optional()
225
222
  }).strict();
226
- var conversationAnnotationInputSchema = z4.discriminatedUnion("kind", [
227
- resourceLinkAnnotationSchema,
228
- objectAnnotationSchema
229
- ]);
230
- var conversationSidebarIconSchema = z4.enum([
231
- "circle-dot",
232
- "circle-dashed",
233
- "circle-x",
234
- "git-merge",
235
- "git-pull-request",
236
- "triangle-alert"
223
+ /** Core-known annotation shapes that plugins may attach to a conversation. */
224
+ const conversationAnnotationInputSchema = z.discriminatedUnion("kind", [resourceLinkAnnotationSchema, objectAnnotationSchema]);
225
+ const conversationSidebarIconSchema = z.enum([
226
+ "circle-dot",
227
+ "circle-dashed",
228
+ "circle-x",
229
+ "git-merge",
230
+ "git-pull-request",
231
+ "triangle-alert"
237
232
  ]);
238
- var conversationSidebarAnnotationSchema = z4.object({
239
- icon: conversationSidebarIconSchema.optional(),
240
- objectType: objectTypeSchema.optional(),
241
- status: z4.string().trim().min(1).max(100).optional(),
242
- key: z4.string().trim().min(1).max(256),
243
- label: z4.string().trim().min(1).max(256)
233
+ const conversationSidebarAnnotationSchema = z.object({
234
+ icon: conversationSidebarIconSchema.optional(),
235
+ objectType: objectTypeSchema.optional(),
236
+ status: z.string().trim().min(1).max(100).optional(),
237
+ key: z.string().trim().min(1).max(256),
238
+ label: z.string().trim().min(1).max(256)
244
239
  }).strict();
245
-
246
240
  // src/code.ts
247
- import { z as z5 } from "zod";
248
- var codeChangeStateSchema = z5.enum(["closed", "merged", "open"]);
249
- var codeChangeInputSchema = z5.object({
250
- closedAt: z5.date().optional(),
251
- conversationIds: z5.array(z5.string().min(1)).default([]),
252
- mergedAt: z5.date().optional(),
253
- number: z5.number().int().positive(),
254
- openedAt: z5.date(),
255
- providerId: z5.string().min(1),
256
- repository: z5.object({
257
- name: z5.string().min(1),
258
- providerId: z5.string().min(1),
259
- url: z5.string().url().optional()
260
- }).strict(),
261
- state: codeChangeStateSchema,
262
- title: z5.string().min(1).optional(),
263
- updatedAt: z5.date(),
264
- url: z5.string().url().optional()
241
+ const codeChangeStateSchema = z.enum([
242
+ "closed",
243
+ "merged",
244
+ "open"
245
+ ]);
246
+ const codeChangeInputSchema = z.object({
247
+ closedAt: z.date().optional(),
248
+ conversationIds: z.array(z.string().min(1)).default([]),
249
+ mergedAt: z.date().optional(),
250
+ number: z.number().int().positive(),
251
+ openedAt: z.date(),
252
+ providerId: z.string().min(1),
253
+ repository: z.object({
254
+ name: z.string().min(1),
255
+ providerId: z.string().min(1),
256
+ url: z.string().url().optional()
257
+ }).strict(),
258
+ state: codeChangeStateSchema,
259
+ title: z.string().min(1).optional(),
260
+ updatedAt: z.date(),
261
+ url: z.string().url().optional()
265
262
  }).strict();
266
-
267
263
  // src/conversation-events.ts
268
- import { z as z6 } from "zod";
269
- var conversationEventNameSchema = z6.string().trim().min(1).max(64).regex(/^[a-z][a-z0-9_]*$/);
270
- var conversationEventIconSchema = z6.enum([
271
- "activity",
272
- "brain",
273
- "calendar",
274
- "check",
275
- "database",
276
- "info",
277
- "key",
278
- "link",
279
- "sparkles",
280
- "warning"
264
+ const conversationEventNameSchema = z.string().trim().min(1).max(64).regex(/^[a-z][a-z0-9_]*$/);
265
+ const conversationEventIconSchema = z.enum([
266
+ "activity",
267
+ "brain",
268
+ "calendar",
269
+ "check",
270
+ "database",
271
+ "info",
272
+ "key",
273
+ "link",
274
+ "sparkles",
275
+ "warning"
281
276
  ]);
282
- var conversationEventDetailSchema = z6.object({
283
- content: z6.string().min(1).max(32 * 1024).optional(),
284
- description: z6.string().trim().min(1).max(2e3).optional(),
285
- metadata: z6.array(z6.string().trim().min(1).max(120)).max(8).optional(),
286
- title: z6.string().trim().min(1).max(4e3)
277
+ const conversationEventDetailSchema = z.object({
278
+ content: z.string().min(1).max(32768).optional(),
279
+ description: z.string().trim().min(1).max(2e3).optional(),
280
+ metadata: z.array(z.string().trim().min(1).max(120)).max(8).optional(),
281
+ title: z.string().trim().min(1).max(4e3)
287
282
  }).strict();
288
- var conversationEventPresentationSchema = z6.object({
289
- details: z6.array(conversationEventDetailSchema).max(100).optional(),
290
- icon: conversationEventIconSchema.optional(),
291
- preview: z6.string().trim().min(1).max(500).optional(),
292
- title: z6.string().trim().min(1).max(120)
283
+ /** Safe, core-rendered presentation for one plugin conversation event. */
284
+ const conversationEventPresentationSchema = z.object({
285
+ details: z.array(conversationEventDetailSchema).max(100).optional(),
286
+ icon: conversationEventIconSchema.optional(),
287
+ preview: z.string().trim().min(1).max(500).optional(),
288
+ title: z.string().trim().min(1).max(120)
293
289
  }).strict();
290
+ /** Define one typed, versioned plugin-owned conversation event. */
294
291
  function defineConversationEvent(definition) {
295
- const identity = z6.object({
296
- name: conversationEventNameSchema,
297
- version: z6.number().int().positive()
298
- }).strict().parse({ name: definition.name, version: definition.version });
299
- let eventDefinition;
300
- const createEvent = (data) => ({
301
- data: definition.schema.parse(data),
302
- definition: eventDefinition
303
- });
304
- eventDefinition = Object.assign(createEvent, {
305
- eventName: identity.name,
306
- version: identity.version,
307
- parse(data) {
308
- return definition.schema.parse(data);
309
- },
310
- renderEvent(data) {
311
- const parsed = definition.schema.parse(data);
312
- const presentation = definition.renderEvent(parsed);
313
- return presentation === void 0 ? void 0 : conversationEventPresentationSchema.parse(presentation);
314
- }
315
- });
316
- return eventDefinition;
292
+ const identity = z.object({
293
+ name: conversationEventNameSchema,
294
+ version: z.number().int().positive()
295
+ }).strict().parse({
296
+ name: definition.name,
297
+ version: definition.version
298
+ });
299
+ let eventDefinition;
300
+ const createEvent = (data) => ({
301
+ data: definition.schema.parse(data),
302
+ definition: eventDefinition
303
+ });
304
+ eventDefinition = Object.assign(createEvent, {
305
+ eventName: identity.name,
306
+ version: identity.version,
307
+ parse(data) {
308
+ return definition.schema.parse(data);
309
+ },
310
+ renderEvent(data) {
311
+ const parsed = definition.schema.parse(data);
312
+ const presentation = definition.renderEvent(parsed);
313
+ return presentation === void 0 ? void 0 : conversationEventPresentationSchema.parse(presentation);
314
+ }
315
+ });
316
+ return eventDefinition;
317
317
  }
318
-
319
318
  // src/schemas.ts
320
- import { z as z7 } from "zod";
321
- var slackTeamIdSchema = z7.string().regex(/^T[A-Z0-9]+$/);
322
- var slackConversationIdSchema = z7.string().regex(/^(C|G|D)[A-Z0-9]+$/);
323
- var localConversationIdSchema = z7.string().regex(/^local:[a-z0-9_-]+:[a-z0-9][a-z0-9_-]*$/);
324
- var actorUserIdSchema = z7.string().min(1).refine(
325
- (value) => value === value.trim() && value.toLowerCase() !== "unknown"
326
- );
327
- var exactActorUserIdSchema = actorUserIdSchema;
328
- var nonBlankStringSchema = z7.string().refine((value) => value.trim().length > 0);
329
- var exactNonBlankStringSchema = nonBlankStringSchema.refine(
330
- (value) => value === value.trim()
331
- );
332
- var baseLocationSchema = z7.object({
333
- /** Stable SQL identity used by Location configuration and reporting. */
334
- id: nonBlankStringSchema,
335
- provider: exactNonBlankStringSchema
319
+ const slackTeamIdSchema = z.string().regex(/^T[A-Z0-9]+$/);
320
+ const slackConversationIdSchema = z.string().regex(/^(C|G|D)[A-Z0-9]+$/);
321
+ const localConversationIdSchema = z.string().regex(/^local:[a-z0-9_-]+:[a-z0-9][a-z0-9_-]*$/);
322
+ /** Exact non-blank actor user id that rejects the sentinel "unknown". */
323
+ const actorUserIdSchema = z.string().min(1).refine((value) => value === value.trim() && value.toLowerCase() !== "unknown");
324
+ const exactActorUserIdSchema = actorUserIdSchema;
325
+ const nonBlankStringSchema = z.string().refine((value) => value.trim().length > 0);
326
+ const exactNonBlankStringSchema = nonBlankStringSchema.refine((value) => value === value.trim());
327
+ /** Complete Slack Location associated with a Conversation. */
328
+ const slackLocationSchema = z.object({
329
+ /** Stable SQL identity used by Location configuration and reporting. */
330
+ id: nonBlankStringSchema,
331
+ provider: exactNonBlankStringSchema
332
+ }).strict().extend({
333
+ provider: z.literal("slack"),
334
+ teamId: slackTeamIdSchema,
335
+ channelId: slackConversationIdSchema,
336
+ threadTs: exactNonBlankStringSchema.optional()
336
337
  }).strict();
337
- var slackLocationSchema = baseLocationSchema.extend({
338
- provider: z7.literal("slack"),
339
- teamId: slackTeamIdSchema,
340
- channelId: slackConversationIdSchema,
341
- threadTs: exactNonBlankStringSchema.optional()
338
+ /** Complete Location types supported by Junior. */
339
+ const locationSchema = z.discriminatedUnion("provider", [slackLocationSchema]);
340
+ /** Runtime platform names supported by plugin public contracts. */
341
+ const platformSchema = z.enum(["slack", "local"]);
342
+ /** Runtime source visibility visible to plugins. */
343
+ const sourceVisibilitySchema = z.enum(["public", "private"]);
344
+ /** Provider-neutral visibility of a routed destination. */
345
+ const destinationVisibilitySchema = z.enum(["public", "private"]);
346
+ /** Runtime-owned Slack address for routing future work or side effects. */
347
+ const slackDestinationSchema = z.object({
348
+ platform: z.literal("slack"),
349
+ teamId: slackTeamIdSchema,
350
+ channelId: slackConversationIdSchema,
351
+ threadTs: exactNonBlankStringSchema.optional()
342
352
  }).strict();
343
- var locationSchema = z7.discriminatedUnion("provider", [
344
- slackLocationSchema
345
- ]);
346
- var platformSchema = z7.enum(["slack", "local"]);
347
- var sourceVisibilitySchema = z7.enum(["public", "private"]);
348
- var destinationVisibilitySchema = z7.enum(["public", "private"]);
349
- var slackAddressSchema = z7.object({
350
- platform: z7.literal("slack"),
351
- teamId: slackTeamIdSchema,
352
- channelId: slackConversationIdSchema,
353
- threadTs: exactNonBlankStringSchema.optional()
353
+ /** Runtime-owned local CLI conversation address. */
354
+ const localDestinationSchema = z.object({
355
+ platform: z.literal("local"),
356
+ conversationId: localConversationIdSchema
354
357
  }).strict();
355
- var slackDestinationSchema = slackAddressSchema;
356
- var localDestinationSchema = z7.object({
357
- platform: z7.literal("local"),
358
- conversationId: localConversationIdSchema
358
+ /** Runtime-owned provider-neutral address for routing future work or side effects. */
359
+ const destinationSchema = z.discriminatedUnion("platform", [slackDestinationSchema, localDestinationSchema]);
360
+ /** One visible effect after successful automated work. */
361
+ const taskOutcomeSchema = z.object({
362
+ action: z.literal("send_message"),
363
+ destination: slackDestinationSchema
359
364
  }).strict();
360
- var destinationSchema = z7.discriminatedUnion("platform", [
361
- slackDestinationSchema,
362
- localDestinationSchema
363
- ]);
364
- var taskOutcomeSchema = z7.object({
365
- action: z7.literal("send_message"),
366
- destination: slackDestinationSchema
365
+ /** Runtime-owned Slack input Source. */
366
+ const slackSourceSchema = z.object({
367
+ kind: z.literal("slack"),
368
+ teamId: slackTeamIdSchema,
369
+ channelId: slackConversationIdSchema,
370
+ visibility: sourceVisibilitySchema,
371
+ messageTs: nonBlankStringSchema.optional(),
372
+ threadTs: nonBlankStringSchema.optional()
367
373
  }).strict();
368
- var slackSourceSchema = z7.object({
369
- kind: z7.literal("slack"),
370
- teamId: slackTeamIdSchema,
371
- channelId: slackConversationIdSchema,
372
- visibility: sourceVisibilitySchema,
373
- messageTs: nonBlankStringSchema.optional(),
374
- threadTs: nonBlankStringSchema.optional()
374
+ /** Runtime-owned local CLI input Source. */
375
+ const localSourceSchema = z.object({
376
+ kind: z.literal("local"),
377
+ visibility: z.literal("private"),
378
+ conversationId: localConversationIdSchema
375
379
  }).strict();
376
- var localSourceSchema = z7.object({
377
- kind: z7.literal("local"),
378
- visibility: z7.literal("private"),
379
- conversationId: localConversationIdSchema
380
+ /** Runtime-owned dashboard input Source. */
381
+ const webSourceSchema = z.object({
382
+ kind: z.literal("web"),
383
+ visibility: sourceVisibilitySchema,
384
+ conversationId: exactNonBlankStringSchema
380
385
  }).strict();
381
- var webSourceSchema = z7.object({
382
- kind: z7.literal("web"),
383
- visibility: sourceVisibilitySchema,
384
- // Web can continue any existing conversation id, including Slack roots.
385
- conversationId: exactNonBlankStringSchema
386
+ /** Runtime-owned Event input Source. */
387
+ const eventSourceSchema = z.object({
388
+ kind: z.literal("event"),
389
+ eventKey: exactNonBlankStringSchema,
390
+ eventType: exactNonBlankStringSchema,
391
+ identifier: exactNonBlankStringSchema,
392
+ namespace: exactNonBlankStringSchema
393
+ }).strict();
394
+ const automationSourceFields = {
395
+ automationId: exactNonBlankStringSchema.optional(),
396
+ automationRunId: exactNonBlankStringSchema.optional()
397
+ };
398
+ /** Runtime-owned Scheduled automation input Source. */
399
+ const scheduledAutomationSourceSchema = z.object({
400
+ kind: z.literal("scheduled_automation"),
401
+ ...automationSourceFields
386
402
  }).strict();
387
- var eventSourceSchema = z7.object({
388
- kind: z7.literal("event"),
389
- eventKey: exactNonBlankStringSchema,
390
- eventType: exactNonBlankStringSchema,
391
- identifier: exactNonBlankStringSchema,
392
- namespace: exactNonBlankStringSchema
403
+ /** Runtime-owned Event automation input Source. */
404
+ const eventAutomationSourceSchema = z.object({
405
+ kind: z.literal("event_automation"),
406
+ ...automationSourceFields
393
407
  }).strict();
394
- var scheduledAutomationSourceSchema = z7.object({ kind: z7.literal("scheduled_automation") }).strict();
395
- var eventAutomationSourceSchema = z7.object({ kind: z7.literal("event_automation") }).strict();
396
- var pluginDispatchSourceSchema = z7.object({ kind: z7.literal("plugin_dispatch") }).strict();
397
- var agentInvocationSourceSchema = z7.object({ kind: z7.literal("agent_invocation") }).strict();
398
- var currentSourceSchema = z7.discriminatedUnion("kind", [
399
- slackSourceSchema,
400
- localSourceSchema,
401
- webSourceSchema,
402
- eventSourceSchema,
403
- scheduledAutomationSourceSchema,
404
- eventAutomationSourceSchema,
405
- pluginDispatchSourceSchema,
406
- agentInvocationSourceSchema
408
+ /** Runtime-owned Plugin dispatch input Source. */
409
+ const pluginDispatchSourceSchema = z.object({ kind: z.literal("plugin_dispatch") }).strict();
410
+ /** Runtime-owned Agent invocation input Source. */
411
+ const agentInvocationSourceSchema = z.object({ kind: z.literal("agent_invocation") }).strict();
412
+ const currentSourceSchema = z.discriminatedUnion("kind", [
413
+ slackSourceSchema,
414
+ localSourceSchema,
415
+ webSourceSchema,
416
+ eventSourceSchema,
417
+ scheduledAutomationSourceSchema,
418
+ eventAutomationSourceSchema,
419
+ pluginDispatchSourceSchema,
420
+ agentInvocationSourceSchema
407
421
  ]);
408
422
  function normalizeStoredSource(value) {
409
- if (!value || typeof value !== "object" || Array.isArray(value)) {
410
- return value;
411
- }
412
- const source = value;
413
- if ("kind" in source) {
414
- const legacyKinds = {
415
- event_task: "event_automation",
416
- resource_event: "event",
417
- scheduled_task: "scheduled_automation"
418
- };
419
- const kind2 = typeof source.kind === "string" ? legacyKinds[source.kind] : void 0;
420
- return kind2 ? { ...source, kind: kind2 } : value;
421
- }
422
- if (source.platform !== "slack" && source.platform !== "local" && source.platform !== "web") {
423
- return value;
424
- }
425
- const { location: _location, platform: kind, ...fields } = source;
426
- return { ...fields, kind };
423
+ if (!value || typeof value !== "object" || Array.isArray(value)) return value;
424
+ const source = value;
425
+ if ("kind" in source) {
426
+ const kind = typeof source.kind === "string" ? {
427
+ event_task: "event_automation",
428
+ resource_event: "event",
429
+ scheduled_task: "scheduled_automation"
430
+ }[source.kind] : void 0;
431
+ return kind ? {
432
+ ...source,
433
+ kind
434
+ } : value;
435
+ }
436
+ if (source.platform !== "slack" && source.platform !== "local" && source.platform !== "web") return value;
437
+ const { location: _location, platform: kind, ...fields } = source;
438
+ return {
439
+ ...fields,
440
+ kind
441
+ };
427
442
  }
428
- var sourceSchema = z7.preprocess(
429
- normalizeStoredSource,
430
- currentSourceSchema
431
- );
432
- var pluginCredentialSubjectSchema = z7.discriminatedUnion(
433
- "allowedWhen",
434
- [
435
- z7.object({
436
- type: z7.literal("user"),
437
- userId: exactActorUserIdSchema,
438
- allowedWhen: z7.literal("private-direct-conversation")
439
- }).strict(),
440
- z7.object({
441
- type: z7.literal("user"),
442
- userId: exactActorUserIdSchema,
443
- allowedWhen: z7.literal("scheduled-automation"),
444
- taskId: exactNonBlankStringSchema
445
- }).strict()
446
- ]
447
- );
448
- var actorProfileSchema = {
449
- email: nonBlankStringSchema.optional(),
450
- fullName: nonBlankStringSchema.optional(),
451
- userId: exactActorUserIdSchema,
452
- userName: nonBlankStringSchema.optional()
443
+ /** Runtime-owned input Source. Stored `platform` and Location fields normalize on read. */
444
+ const sourceSchema = z.preprocess(normalizeStoredSource, currentSourceSchema);
445
+ /** Stable user credential subject shape accepted from plugins. */
446
+ const pluginCredentialSubjectSchema = z.discriminatedUnion("allowedWhen", [z.object({
447
+ type: z.literal("user"),
448
+ userId: exactActorUserIdSchema,
449
+ allowedWhen: z.literal("private-direct-conversation")
450
+ }).strict(), z.object({
451
+ type: z.literal("user"),
452
+ userId: exactActorUserIdSchema,
453
+ allowedWhen: z.literal("scheduled-automation"),
454
+ taskId: exactNonBlankStringSchema
455
+ }).strict()]);
456
+ /** Shared exact actor profile fields for platform-scoped actors. */
457
+ const actorProfileSchema = {
458
+ email: nonBlankStringSchema.optional(),
459
+ fullName: nonBlankStringSchema.optional(),
460
+ userId: exactActorUserIdSchema,
461
+ userName: nonBlankStringSchema.optional()
453
462
  };
454
- var slackActorSchema = z7.object({
455
- ...actorProfileSchema,
456
- platform: z7.literal("slack"),
457
- teamId: slackTeamIdSchema
463
+ const slackActorSchema = z.object({
464
+ ...actorProfileSchema,
465
+ platform: z.literal("slack"),
466
+ teamId: slackTeamIdSchema
458
467
  }).strict();
459
- var localActorSchema = z7.object({
460
- ...actorProfileSchema,
461
- platform: z7.literal("local")
468
+ const localActorSchema = z.object({
469
+ ...actorProfileSchema,
470
+ platform: z.literal("local")
462
471
  }).strict();
463
- var webActorSchema = z7.object({
464
- ...actorProfileSchema,
465
- platform: z7.literal("web")
472
+ const webActorSchema = z.object({
473
+ ...actorProfileSchema,
474
+ platform: z.literal("web")
466
475
  }).strict();
467
- var systemActorSchema = z7.object({
468
- platform: z7.literal("system"),
469
- name: exactActorUserIdSchema
476
+ const systemActorSchema = z.object({
477
+ platform: z.literal("system"),
478
+ name: exactActorUserIdSchema
470
479
  }).strict();
471
- var actorSchema = z7.discriminatedUnion("platform", [
472
- slackActorSchema,
473
- localActorSchema,
474
- webActorSchema,
475
- systemActorSchema
480
+ /** Runtime-provided actor identity visible to plugin hooks. */
481
+ const actorSchema = z.discriminatedUnion("platform", [
482
+ slackActorSchema,
483
+ localActorSchema,
484
+ webActorSchema,
485
+ systemActorSchema
476
486
  ]);
477
- var identitySchema = z7.object({
478
- displayName: nonBlankStringSchema.optional(),
479
- handle: nonBlankStringSchema.optional(),
480
- id: exactNonBlankStringSchema,
481
- provider: exactNonBlankStringSchema,
482
- providerSubjectId: exactNonBlankStringSchema,
483
- providerTenantId: exactNonBlankStringSchema.optional()
487
+ /** Core-owned provider account linked to a user when verified. */
488
+ const identitySchema = z.object({
489
+ displayName: nonBlankStringSchema.optional(),
490
+ handle: nonBlankStringSchema.optional(),
491
+ id: exactNonBlankStringSchema,
492
+ provider: exactNonBlankStringSchema,
493
+ providerSubjectId: exactNonBlankStringSchema,
494
+ providerTenantId: exactNonBlankStringSchema.optional()
484
495
  }).strict();
485
- var userSchema = z7.object({
486
- displayName: nonBlankStringSchema.optional(),
487
- email: nonBlankStringSchema.max(320),
488
- id: exactNonBlankStringSchema,
489
- identities: z7.array(identitySchema).max(100),
490
- /** True only for Junior admins. Missing means not an admin. */
491
- isAdmin: z7.literal(true).optional()
496
+ /** Core-owned person with every linked provider identity. */
497
+ const userSchema = z.object({
498
+ displayName: nonBlankStringSchema.optional(),
499
+ email: nonBlankStringSchema.max(320),
500
+ id: exactNonBlankStringSchema,
501
+ identities: z.array(identitySchema).max(100),
502
+ /** True only for Junior admins. Missing means not an admin. */
503
+ isAdmin: z.literal(true).optional()
492
504
  }).strict();
493
- var dispatchMetadataSchema = z7.record(z7.string(), z7.string()).superRefine((metadata, ctx) => {
494
- const entries = Object.entries(metadata);
495
- if (entries.length > 20) {
496
- ctx.addIssue({
497
- code: z7.ZodIssueCode.custom,
498
- message: "Dispatch metadata has too many keys"
499
- });
500
- return;
501
- }
502
- for (const [key, value] of entries) {
503
- if (!key.trim()) {
504
- ctx.addIssue({
505
- code: z7.ZodIssueCode.custom,
506
- message: "Dispatch metadata values must be strings",
507
- path: [key]
508
- });
509
- continue;
510
- }
511
- if (key.length > 128) {
512
- ctx.addIssue({
513
- code: z7.ZodIssueCode.custom,
514
- message: "Dispatch metadata key exceeds the maximum length",
515
- path: [key]
516
- });
517
- }
518
- if (/[\r\n]/.test(key)) {
519
- ctx.addIssue({
520
- code: z7.ZodIssueCode.custom,
521
- message: "Dispatch metadata keys must be single-line strings",
522
- path: [key]
523
- });
524
- }
525
- if (/[\r\n]/.test(value)) {
526
- ctx.addIssue({
527
- code: z7.ZodIssueCode.custom,
528
- message: "Dispatch metadata values must be single-line strings",
529
- path: [key]
530
- });
531
- }
532
- if (value.length > 512) {
533
- ctx.addIssue({
534
- code: z7.ZodIssueCode.custom,
535
- message: "Dispatch metadata value exceeds the maximum length",
536
- path: [key]
537
- });
538
- }
539
- }
505
+ const dispatchMetadataSchema = z.record(z.string(), z.string()).superRefine((metadata, ctx) => {
506
+ const entries = Object.entries(metadata);
507
+ if (entries.length > 20) {
508
+ ctx.addIssue({
509
+ code: z.ZodIssueCode.custom,
510
+ message: "Dispatch metadata has too many keys"
511
+ });
512
+ return;
513
+ }
514
+ for (const [key, value] of entries) {
515
+ if (!key.trim()) {
516
+ ctx.addIssue({
517
+ code: z.ZodIssueCode.custom,
518
+ message: "Dispatch metadata values must be strings",
519
+ path: [key]
520
+ });
521
+ continue;
522
+ }
523
+ if (key.length > 128) ctx.addIssue({
524
+ code: z.ZodIssueCode.custom,
525
+ message: "Dispatch metadata key exceeds the maximum length",
526
+ path: [key]
527
+ });
528
+ if (/[\r\n]/.test(key)) ctx.addIssue({
529
+ code: z.ZodIssueCode.custom,
530
+ message: "Dispatch metadata keys must be single-line strings",
531
+ path: [key]
532
+ });
533
+ if (/[\r\n]/.test(value)) ctx.addIssue({
534
+ code: z.ZodIssueCode.custom,
535
+ message: "Dispatch metadata values must be single-line strings",
536
+ path: [key]
537
+ });
538
+ if (value.length > 512) ctx.addIssue({
539
+ code: z.ZodIssueCode.custom,
540
+ message: "Dispatch metadata value exceeds the maximum length",
541
+ path: [key]
542
+ });
543
+ }
540
544
  });
541
- var replyAttributionSchema = z7.object({
542
- label: exactNonBlankStringSchema.pipe(z7.string().max(48)).refine((value) => !/[\r\n]/.test(value)),
543
- detail: exactNonBlankStringSchema.pipe(z7.string().max(128)).refine((value) => !/[\r\n]/.test(value)).optional()
545
+ /** Compact destination-visible context explaining what produced a reply. */
546
+ const replyAttributionSchema = z.object({
547
+ label: exactNonBlankStringSchema.pipe(z.string().max(48)).refine((value) => !/[\r\n]/.test(value)),
548
+ detail: exactNonBlankStringSchema.pipe(z.string().max(128)).refine((value) => !/[\r\n]/.test(value)).optional()
544
549
  }).strict();
545
- var dispatchOptionsSchema = z7.object({
546
- idempotencyKey: nonBlankStringSchema.pipe(z7.string().max(512)),
547
- credentialSubject: pluginCredentialSubjectSchema.optional(),
548
- destination: slackDestinationSchema,
549
- destinationVisibility: destinationVisibilitySchema,
550
- input: nonBlankStringSchema.pipe(z7.string().max(32e3)),
551
- metadata: dispatchMetadataSchema.optional(),
552
- replyAttribution: replyAttributionSchema.optional()
550
+ /** Plugin dispatch request accepted by Junior core. */
551
+ const dispatchOptionsSchema = z.object({
552
+ idempotencyKey: nonBlankStringSchema.pipe(z.string().max(512)),
553
+ credentialSubject: pluginCredentialSubjectSchema.optional(),
554
+ destination: slackDestinationSchema,
555
+ destinationVisibility: destinationVisibilitySchema,
556
+ input: nonBlankStringSchema.pipe(z.string().max(32e3)),
557
+ metadata: dispatchMetadataSchema.optional(),
558
+ replyAttribution: replyAttributionSchema.optional()
553
559
  }).strict();
554
-
555
560
  // src/context.ts
561
+ /** Build a normalized Slack source from runtime-owned Slack coordinates. */
556
562
  function createSlackSource(input) {
557
- return {
558
- kind: "slack",
559
- visibility: input.visibility,
560
- teamId: input.teamId,
561
- channelId: input.channelId,
562
- ...input.messageTs ? { messageTs: input.messageTs } : void 0,
563
- ...input.threadTs ? { threadTs: input.threadTs } : void 0
564
- };
563
+ return {
564
+ kind: "slack",
565
+ visibility: input.visibility,
566
+ teamId: input.teamId,
567
+ channelId: input.channelId,
568
+ ...input.messageTs ? { messageTs: input.messageTs } : void 0,
569
+ ...input.threadTs ? { threadTs: input.threadTs } : void 0
570
+ };
565
571
  }
572
+ /** Build a normalized local source from a local conversation id. */
566
573
  function createLocalSource(conversationId) {
567
- return {
568
- kind: "local",
569
- visibility: "private",
570
- conversationId
571
- };
574
+ return {
575
+ kind: "local",
576
+ visibility: "private",
577
+ conversationId
578
+ };
572
579
  }
580
+ /** Build a normalized web/dashboard source from a conversation id. */
573
581
  function createWebSource(conversationId, visibility = "public") {
574
- return {
575
- kind: "web",
576
- visibility,
577
- conversationId
578
- };
582
+ return {
583
+ kind: "web",
584
+ visibility,
585
+ conversationId
586
+ };
579
587
  }
588
+ /** Build a normalized Event Source from one matched event. */
580
589
  function createEventSource(input) {
581
- return {
582
- kind: "event",
583
- eventKey: input.eventKey,
584
- eventType: input.eventType,
585
- identifier: input.identifier,
586
- namespace: input.namespace
587
- };
590
+ return {
591
+ kind: "event",
592
+ eventKey: input.eventKey,
593
+ eventType: input.eventType,
594
+ identifier: input.identifier,
595
+ namespace: input.namespace
596
+ };
588
597
  }
598
+ /** Return whether a source is private to a person or restricted group. */
589
599
  function isPrivateSource(source) {
590
- return "visibility" in source && source.visibility === "private";
600
+ return "visibility" in source && source.visibility === "private";
591
601
  }
602
+ /** Return the stable source identity used for idempotency and attribution. */
592
603
  function getSourceKey(source) {
593
- switch (source.kind) {
594
- case "web":
595
- case "local":
596
- return source.conversationId;
597
- case "slack": {
598
- const messageKey = source.threadTs ?? source.messageTs;
599
- if (!messageKey) {
600
- return void 0;
601
- }
602
- return `slack:${source.teamId}:${source.channelId}:${messageKey}`;
603
- }
604
- case "event":
605
- return `event:${source.namespace}:${source.eventKey}`;
606
- case "scheduled_automation":
607
- case "event_automation":
608
- case "plugin_dispatch":
609
- case "agent_invocation":
610
- return void 0;
611
- }
604
+ switch (source.kind) {
605
+ case "web":
606
+ case "local": return source.conversationId;
607
+ case "slack": {
608
+ const messageKey = source.threadTs ?? source.messageTs;
609
+ if (!messageKey) return;
610
+ return `slack:${source.teamId}:${source.channelId}:${messageKey}`;
611
+ }
612
+ case "event": return `event:${source.namespace}:${source.eventKey}`;
613
+ case "scheduled_automation":
614
+ case "event_automation":
615
+ case "plugin_dispatch":
616
+ case "agent_invocation": return;
617
+ }
612
618
  }
619
+ /** Narrow a runtime destination to the Slack-specific address shape. */
613
620
  function isSlackDestination(destination) {
614
- return destination?.platform === "slack";
621
+ return destination?.platform === "slack";
615
622
  }
616
-
617
623
  // src/prompt.ts
618
- import { z as z8 } from "zod";
619
- var promptContextKindSchema = z8.string().trim().min(1).max(64).regex(/^[a-z][a-z0-9_-]*$/);
620
- var promptMessageSchema = z8.object({
621
- text: z8.string().trim().min(1).max(8e3)
622
- }).strict();
623
- var promptContextSchema = z8.object({
624
- kind: promptContextKindSchema,
625
- version: z8.number().int().positive(),
626
- content: z8.record(z8.string(), z8.unknown())
624
+ const promptContextKindSchema = z.string().trim().min(1).max(64).regex(/^[a-z][a-z0-9_-]*$/);
625
+ const promptMessageSchema = z.object({ text: z.string().trim().min(1).max(8e3) }).strict();
626
+ const promptContextSchema = z.object({
627
+ kind: promptContextKindSchema,
628
+ version: z.number().int().positive(),
629
+ content: z.record(z.string(), z.unknown())
627
630
  }).strict();
631
+ /** Define one typed, versioned plugin context contribution. */
628
632
  function definePromptContext(definition) {
629
- const identity = promptContextSchema.pick({ kind: true, version: true }).parse({ kind: definition.kind, version: definition.version });
630
- return (content) => {
631
- const parsed = definition.schema.parse(content);
632
- return {
633
- context: { ...identity, content: parsed },
634
- renderPrompt: () => definition.renderPrompt(parsed)
635
- };
636
- };
633
+ const identity = promptContextSchema.pick({
634
+ kind: true,
635
+ version: true
636
+ }).parse({
637
+ kind: definition.kind,
638
+ version: definition.version
639
+ });
640
+ return (content) => {
641
+ const parsed = definition.schema.parse(content);
642
+ return {
643
+ context: {
644
+ ...identity,
645
+ content: parsed
646
+ },
647
+ renderPrompt: () => definition.renderPrompt(parsed)
648
+ };
649
+ };
637
650
  }
638
-
639
651
  // src/events.ts
640
- import { z as z9 } from "zod";
641
- var EVENT_SUMMARY_MAX_LENGTH = 4e3;
642
- var EVENT_TEXT_MAX_LENGTH = 8e3;
643
- var EVENT_DATA_MAX_KEYS = 32;
644
- var EVENT_DATA_MAX_JSON_BYTES = 4e3;
645
- var EVENT_GUIDANCE_MAX_LENGTH = 1e3;
646
- var eventDataSchema = z9.record(z9.string(), z9.unknown()).superRefine((value, context) => {
647
- const keys = Object.keys(value);
648
- if (keys.length > EVENT_DATA_MAX_KEYS) {
649
- context.addIssue({
650
- code: "custom",
651
- message: `Event data may include at most ${EVENT_DATA_MAX_KEYS} keys.`
652
- });
653
- }
654
- const jsonBytes = new TextEncoder().encode(
655
- JSON.stringify(value)
656
- ).byteLength;
657
- if (jsonBytes > EVENT_DATA_MAX_JSON_BYTES) {
658
- context.addIssue({
659
- code: "custom",
660
- message: `Event data may be at most ${EVENT_DATA_MAX_JSON_BYTES} JSON bytes.`
661
- });
662
- }
652
+ const EVENT_SUMMARY_MAX_LENGTH = 4e3;
653
+ const EVENT_TEXT_MAX_LENGTH = 8e3;
654
+ const EVENT_DATA_MAX_KEYS = 32;
655
+ const EVENT_DATA_MAX_JSON_BYTES = 4e3;
656
+ const EVENT_GUIDANCE_MAX_LENGTH = 1e3;
657
+ /** Small trusted data from the plugin. The agent should not look these up again. */
658
+ const eventDataSchema = z.record(z.string(), z.unknown()).superRefine((value, context) => {
659
+ if (Object.keys(value).length > 32) context.addIssue({
660
+ code: "custom",
661
+ message: `Event data may include at most 32 keys.`
662
+ });
663
+ if (new TextEncoder().encode(JSON.stringify(value)).byteLength > 4e3) context.addIssue({
664
+ code: "custom",
665
+ message: `Event data may be at most ${EVENT_DATA_MAX_JSON_BYTES} JSON bytes.`
666
+ });
663
667
  });
664
- var eventTypeSchema = z9.string().regex(/^[a-z][a-z0-9_-]*(?:\.[a-z][a-z0-9_-]*)+$/).describe(
665
- "Canonical dotted event type, such as issue.closed or pull_request.review.changes_requested."
666
- );
667
- var resourceTypeSchema = z9.string().regex(/^[a-z][a-z0-9_]*$/).describe(
668
- "Canonical plugin-defined resource type, such as issue or pull_request."
669
- );
670
- var EVENT_MATCH_FIELD_NAME = /^[a-z][a-zA-Z0-9]*$/;
671
- var eventMatchFieldSchema = z9.object({
672
- kind: z9.enum(["boolean", "string", "number"]),
673
- description: z9.string().trim().min(1).max(200),
674
- enum: z9.array(z9.string().min(1)).min(1).optional()
668
+ /** Canonical dotted event type published and selected across plugins. */
669
+ const eventTypeSchema = z.string().regex(/^[a-z][a-z0-9_-]*(?:\.[a-z][a-z0-9_-]*)+$/).describe("Canonical dotted event type, such as issue.closed or pull_request.review.changes_requested.");
670
+ const resourceTypeSchema = z.string().regex(/^[a-z][a-z0-9_]*$/).describe("Canonical plugin-defined resource type, such as issue or pull_request.");
671
+ const EVENT_MATCH_FIELD_NAME = /^[a-z][a-zA-Z0-9]*$/;
672
+ /** One exact value a watch or event automation may require on trusted event data. */
673
+ const eventMatchFieldSchema = z.object({
674
+ kind: z.enum([
675
+ "boolean",
676
+ "string",
677
+ "number"
678
+ ]),
679
+ description: z.string().trim().min(1).max(200),
680
+ enum: z.array(z.string().min(1)).min(1).optional()
675
681
  }).strict().superRefine((field, context) => {
676
- if (field.enum && field.kind !== "string") {
677
- context.addIssue({
678
- code: "custom",
679
- message: 'Event match field enum requires kind "string".',
680
- path: ["enum"]
681
- });
682
- }
682
+ if (field.enum && field.kind !== "string") context.addIssue({
683
+ code: "custom",
684
+ message: "Event match field enum requires kind \"string\".",
685
+ path: ["enum"]
686
+ });
683
687
  });
684
- var eventMatchFieldsSchema = z9.record(z9.string().regex(EVENT_MATCH_FIELD_NAME), eventMatchFieldSchema).superRefine((fields, context) => {
685
- if (Object.keys(fields).length > EVENT_DATA_MAX_KEYS) {
686
- context.addIssue({
687
- code: "custom",
688
- message: `Event match keys may include at most ${EVENT_DATA_MAX_KEYS} keys.`
689
- });
690
- }
688
+ const eventMatchFieldsSchema = z.record(z.string().regex(EVENT_MATCH_FIELD_NAME), eventMatchFieldSchema).superRefine((fields, context) => {
689
+ if (Object.keys(fields).length > 32) context.addIssue({
690
+ code: "custom",
691
+ message: `Event match keys may include at most 32 keys.`
692
+ });
691
693
  });
692
- var eventMatchSchema = z9.record(
693
- z9.string().regex(EVENT_MATCH_FIELD_NAME),
694
- z9.union([
695
- z9.boolean(),
696
- z9.number().finite(),
697
- z9.string().min(1),
698
- z9.array(z9.union([z9.number().finite(), z9.string().min(1)])).min(1)
699
- ])
700
- ).superRefine((match, context) => {
701
- if (Object.keys(match).length > EVENT_DATA_MAX_KEYS) {
702
- context.addIssue({
703
- code: "custom",
704
- message: `Event match may include at most ${EVENT_DATA_MAX_KEYS} keys.`
705
- });
706
- }
707
- for (const [key, value] of Object.entries(match)) {
708
- if (!Array.isArray(value)) continue;
709
- if (value.some((entry) => typeof entry === "boolean")) {
710
- context.addIssue({
711
- code: "custom",
712
- message: `Event match field "${key}" cannot use a boolean list.`,
713
- path: [key]
714
- });
715
- }
716
- }
694
+ /** Exact trusted values required before a watch or event automation runs. */
695
+ const eventMatchSchema = z.record(z.string().regex(EVENT_MATCH_FIELD_NAME), z.union([
696
+ z.boolean(),
697
+ z.number().finite(),
698
+ z.string().min(1),
699
+ z.array(z.union([z.number().finite(), z.string().min(1)])).min(1)
700
+ ])).superRefine((match, context) => {
701
+ if (Object.keys(match).length > 32) context.addIssue({
702
+ code: "custom",
703
+ message: `Event match may include at most 32 keys.`
704
+ });
705
+ for (const [key, value] of Object.entries(match)) {
706
+ if (!Array.isArray(value)) continue;
707
+ if (value.some((entry) => typeof entry === "boolean")) context.addIssue({
708
+ code: "custom",
709
+ message: `Event match field "${key}" cannot use a boolean list.`,
710
+ path: [key]
711
+ });
712
+ }
717
713
  });
718
714
  function stableMatchValue(value) {
719
- if (!Array.isArray(value)) return value;
720
- return [...value].sort((left, right) => {
721
- if (typeof left === "number" && typeof right === "number") {
722
- return left - right;
723
- }
724
- return String(left).localeCompare(String(right));
725
- });
715
+ if (!Array.isArray(value)) return value;
716
+ return [...value].sort((left, right) => {
717
+ if (typeof left === "number" && typeof right === "number") return left - right;
718
+ return String(left).localeCompare(String(right));
719
+ });
726
720
  }
721
+ /** Stable JSON for one match object. List order does not matter. */
727
722
  function stableEventMatchKey(match) {
728
- if (!match || Object.keys(match).length === 0) return "";
729
- return JSON.stringify(
730
- Object.fromEntries(
731
- Object.entries(match).sort(([left], [right]) => left.localeCompare(right)).map(([key, value]) => [key, stableMatchValue(value)])
732
- )
733
- );
723
+ if (!match || Object.keys(match).length === 0) return "";
724
+ return JSON.stringify(Object.fromEntries(Object.entries(match).sort(([left], [right]) => left.localeCompare(right)).map(([key, value]) => [key, stableMatchValue(value)])));
734
725
  }
726
+ /** Return whether trusted event data matches one exact match object. */
735
727
  function eventMatches(match, data) {
736
- if (!match || Object.keys(match).length === 0) return true;
737
- if (!data) return false;
738
- for (const [key, expected] of Object.entries(match)) {
739
- const actual = data[key];
740
- if (actual === void 0) return false;
741
- if (Array.isArray(expected)) {
742
- if (!expected.some((value) => Object.is(value, actual))) return false;
743
- continue;
744
- }
745
- if (!Object.is(expected, actual)) return false;
746
- }
747
- return true;
728
+ if (!match || Object.keys(match).length === 0) return true;
729
+ if (!data) return false;
730
+ for (const [key, expected] of Object.entries(match)) {
731
+ const actual = data[key];
732
+ if (actual === void 0) return false;
733
+ if (Array.isArray(expected)) {
734
+ if (!expected.some((value) => Object.is(value, actual))) return false;
735
+ continue;
736
+ }
737
+ if (!Object.is(expected, actual)) return false;
738
+ }
739
+ return true;
748
740
  }
749
- var eventIdentifierSchema = z9.object({
750
- /** Shown to the agent, such as "owner/repo#number". */
751
- format: z9.string().trim().min(1).max(200),
752
- /** Matches a normalized identifier of this resource type. */
753
- pattern: z9.instanceof(RegExp)
741
+ /** The identifier shape of one resource type. */
742
+ const eventIdentifierSchema = z.object({
743
+ /** Shown to the agent, such as "owner/repo#number". */
744
+ format: z.string().trim().min(1).max(200),
745
+ /** Matches a normalized identifier of this resource type. */
746
+ pattern: z.instanceof(RegExp)
754
747
  }).strict();
755
- var pluginEventTypeSchema = z9.object({
756
- type: resourceTypeSchema,
757
- identifier: eventIdentifierSchema.optional(),
758
- supportedEvents: z9.array(eventTypeSchema).min(1),
759
- suggestedEvents: z9.array(eventTypeSchema).optional(),
760
- matchFields: eventMatchFieldsSchema.optional(),
761
- guidance: z9.record(
762
- eventTypeSchema,
763
- z9.string().trim().min(1).max(EVENT_GUIDANCE_MAX_LENGTH)
764
- ).optional()
748
+ const pluginEventTypeSchema = z.object({
749
+ type: resourceTypeSchema,
750
+ identifier: eventIdentifierSchema.optional(),
751
+ supportedEvents: z.array(eventTypeSchema).min(1),
752
+ suggestedEvents: z.array(eventTypeSchema).optional(),
753
+ matchFields: eventMatchFieldsSchema.optional(),
754
+ guidance: z.record(eventTypeSchema, z.string().trim().min(1).max(EVENT_GUIDANCE_MAX_LENGTH)).optional()
765
755
  }).strict().superRefine((resourceType, context) => {
766
- const supported = /* @__PURE__ */ new Set();
767
- resourceType.supportedEvents.forEach((eventType, index) => {
768
- if (supported.has(eventType)) {
769
- context.addIssue({
770
- code: "custom",
771
- message: `Duplicate supported event type "${eventType}".`,
772
- path: ["supportedEvents", index]
773
- });
774
- }
775
- supported.add(eventType);
776
- });
777
- for (const eventType of Object.keys(resourceType.guidance ?? {})) {
778
- if (!supported.has(eventType)) {
779
- context.addIssue({
780
- code: "custom",
781
- message: `Guidance event type "${eventType}" is not supported.`,
782
- path: ["guidance", eventType]
783
- });
784
- }
785
- }
786
- const suggested = /* @__PURE__ */ new Set();
787
- resourceType.suggestedEvents?.forEach((eventType, index) => {
788
- if (suggested.has(eventType)) {
789
- context.addIssue({
790
- code: "custom",
791
- message: `Duplicate suggested event type "${eventType}".`,
792
- path: ["suggestedEvents", index]
793
- });
794
- }
795
- if (!supported.has(eventType)) {
796
- context.addIssue({
797
- code: "custom",
798
- message: `Suggested event type "${eventType}" is not supported.`,
799
- path: ["suggestedEvents", index]
800
- });
801
- }
802
- suggested.add(eventType);
803
- });
756
+ const supported = /* @__PURE__ */ new Set();
757
+ resourceType.supportedEvents.forEach((eventType, index) => {
758
+ if (supported.has(eventType)) context.addIssue({
759
+ code: "custom",
760
+ message: `Duplicate supported event type "${eventType}".`,
761
+ path: ["supportedEvents", index]
762
+ });
763
+ supported.add(eventType);
764
+ });
765
+ for (const eventType of Object.keys(resourceType.guidance ?? {})) if (!supported.has(eventType)) context.addIssue({
766
+ code: "custom",
767
+ message: `Guidance event type "${eventType}" is not supported.`,
768
+ path: ["guidance", eventType]
769
+ });
770
+ const suggested = /* @__PURE__ */ new Set();
771
+ resourceType.suggestedEvents?.forEach((eventType, index) => {
772
+ if (suggested.has(eventType)) context.addIssue({
773
+ code: "custom",
774
+ message: `Duplicate suggested event type "${eventType}".`,
775
+ path: ["suggestedEvents", index]
776
+ });
777
+ if (!supported.has(eventType)) context.addIssue({
778
+ code: "custom",
779
+ message: `Suggested event type "${eventType}" is not supported.`,
780
+ path: ["suggestedEvents", index]
781
+ });
782
+ suggested.add(eventType);
783
+ });
804
784
  });
805
- var pluginEventsSchema = z9.object({
806
- resourceTypes: z9.array(pluginEventTypeSchema).min(1),
807
- isEnabled: z9.function({ input: [], output: z9.boolean() }).optional(),
808
- normalizeIdentifier: z9.function({ input: [z9.string()], output: z9.string() }).optional()
785
+ const pluginEventsSchema = z.object({
786
+ resourceTypes: z.array(pluginEventTypeSchema).min(1),
787
+ isEnabled: z.function({
788
+ input: [],
789
+ output: z.boolean()
790
+ }).optional(),
791
+ normalizeIdentifier: z.function({
792
+ input: [z.string()],
793
+ output: z.string()
794
+ }).optional()
809
795
  }).strict().superRefine((registration, context) => {
810
- const seen = /* @__PURE__ */ new Set();
811
- registration.resourceTypes.forEach((resourceType, index) => {
812
- if (seen.has(resourceType.type)) {
813
- context.addIssue({
814
- code: "custom",
815
- message: `Duplicate resource type "${resourceType.type}".`,
816
- path: ["resourceTypes", index, "type"]
817
- });
818
- }
819
- seen.add(resourceType.type);
820
- });
796
+ const seen = /* @__PURE__ */ new Set();
797
+ registration.resourceTypes.forEach((resourceType, index) => {
798
+ if (seen.has(resourceType.type)) context.addIssue({
799
+ code: "custom",
800
+ message: `Duplicate resource type "${resourceType.type}".`,
801
+ path: [
802
+ "resourceTypes",
803
+ index,
804
+ "type"
805
+ ]
806
+ });
807
+ seen.add(resourceType.type);
808
+ });
821
809
  });
810
+ /** Apply a plugin's identifier convention at event boundaries. */
822
811
  function normalizeEventIdentifier(registration, identifier) {
823
- const trimmed = identifier.trim();
824
- const normalized = (registration?.normalizeIdentifier?.(trimmed) ?? trimmed).trim();
825
- if (!normalized) {
826
- throw new Error("Event identifier must not normalize to empty");
827
- }
828
- return normalized;
812
+ const trimmed = identifier.trim();
813
+ const normalized = (registration?.normalizeIdentifier?.(trimmed) ?? trimmed).trim();
814
+ if (!normalized) throw new Error("Event identifier must not normalize to empty");
815
+ return normalized;
829
816
  }
830
- var subscribableResourceSchema = z9.object({
831
- identifier: z9.string().min(1),
832
- label: z9.string().min(1),
833
- namespace: z9.string().min(1),
834
- suggestedEvents: z9.array(eventTypeSchema).optional(),
835
- supportedEvents: z9.array(eventTypeSchema),
836
- type: resourceTypeSchema
817
+ const subscribableResourceSchema = z.object({
818
+ identifier: z.string().min(1),
819
+ label: z.string().min(1),
820
+ namespace: z.string().min(1),
821
+ suggestedEvents: z.array(eventTypeSchema).optional(),
822
+ supportedEvents: z.array(eventTypeSchema),
823
+ type: resourceTypeSchema
837
824
  }).strict();
838
- var watchResultSchema = z9.object({
839
- events: z9.array(eventTypeSchema).min(1),
840
- id: z9.string().min(1)
825
+ /** Result returned after a temporary watch is created. */
826
+ const watchResultSchema = z.object({
827
+ events: z.array(eventTypeSchema).min(1),
828
+ id: z.string().min(1)
841
829
  }).strict();
842
- var eventPersonSchema = z9.union([
843
- z9.object({
844
- provider: z9.string().min(1),
845
- handle: z9.string().min(1)
846
- }).strict(),
847
- z9.object({ email: z9.string().trim().min(3) }).strict()
848
- ]);
849
- var eventInputSchema = z9.object({
850
- objectType: objectTypeSchema.optional(),
851
- eventKey: z9.string().min(1),
852
- eventType: eventTypeSchema,
853
- identifier: z9.string().min(1),
854
- occurredAtMs: z9.number().finite(),
855
- terminal: z9.boolean().optional(),
856
- trustedSummary: z9.string().min(1).transform((value) => value.slice(0, EVENT_SUMMARY_MAX_LENGTH)),
857
- /** Trusted structured facts. Prefer ids and urls over long prose. */
858
- data: eventDataSchema.optional(),
859
- untrustedText: z9.string().transform((value) => value.slice(0, EVENT_TEXT_MAX_LENGTH)).optional(),
860
- /** People involved in the change. Watch Events list them as mentions. */
861
- people: z9.array(eventPersonSchema).max(20).optional()
830
+ /**
831
+ * One person involved in an Event, named by a provider identity or an email.
832
+ * Core resolves linked people to mentions. It drops people it cannot resolve.
833
+ */
834
+ const eventPersonSchema = z.union([z.object({
835
+ provider: z.string().min(1),
836
+ handle: z.string().min(1)
837
+ }).strict(), z.object({ email: z.string().trim().min(3) }).strict()]);
838
+ const eventInputSchema = z.object({
839
+ objectType: objectTypeSchema.optional(),
840
+ eventKey: z.string().min(1),
841
+ eventType: eventTypeSchema,
842
+ identifier: z.string().min(1),
843
+ occurredAtMs: z.number().finite(),
844
+ terminal: z.boolean().optional(),
845
+ trustedSummary: z.string().min(1).transform((value) => value.slice(0, EVENT_SUMMARY_MAX_LENGTH)),
846
+ /** Trusted structured facts. Prefer ids and urls over long prose. */
847
+ data: eventDataSchema.optional(),
848
+ untrustedText: z.string().transform((value) => value.slice(0, EVENT_TEXT_MAX_LENGTH)).optional(),
849
+ /** People involved in the change. Watch Events list them as mentions. */
850
+ people: z.array(eventPersonSchema).max(20).optional()
862
851
  }).strict();
863
- var eventSchema = eventInputSchema.extend({
864
- namespace: z9.string().min(1)
865
- });
866
-
852
+ const eventSchema = eventInputSchema.extend({ namespace: z.string().min(1) });
867
853
  // src/tasks.ts
868
- import { z as z10 } from "zod";
869
- var pluginRunTranscriptProvenanceSchema = z10.object({
870
- authority: z10.enum(["instruction", "context"]),
871
- actor: actorSchema.optional()
854
+ /**
855
+ * Public plugin background-task contracts.
856
+ *
857
+ * Plugins register small task handlers. Junior core owns scheduling, delivery,
858
+ * retries, and the bounded run projection.
859
+ */
860
+ /**
861
+ * Runtime-owned provenance for a transcript message: whether it is a durable
862
+ * instruction or ambient context, plus the actor identity when known. Missing
863
+ * provenance on an entry means unattributed context.
864
+ */
865
+ const pluginRunTranscriptProvenanceSchema = z.object({
866
+ authority: z.enum(["instruction", "context"]),
867
+ actor: actorSchema.optional()
872
868
  }).strict();
873
- var pluginRunTranscriptEntrySchema = z10.discriminatedUnion("type", [
874
- z10.object({
875
- type: z10.literal("message"),
876
- role: z10.enum(["user", "assistant"]),
877
- text: z10.string().min(1),
878
- provenance: pluginRunTranscriptProvenanceSchema.optional(),
879
- isRunActor: z10.boolean().optional()
880
- }).strict(),
881
- z10.object({
882
- type: z10.literal("toolResult"),
883
- toolName: z10.string().min(1),
884
- isError: z10.boolean(),
885
- text: z10.string().min(1).optional()
886
- }).strict()
887
- ]);
888
- var pluginRunContextSchema = z10.object({
889
- /** User linked to the Actor, when known. */
890
- actorUserId: z10.string().min(1).optional(),
891
- completedAtMs: z10.number().finite(),
892
- conversationId: z10.string().min(1),
893
- destination: destinationSchema,
894
- /** Location associated with this Conversation. */
895
- locationId: z10.string().min(1).optional(),
896
- /**
897
- * All distinct actors annotated on this run's committed instruction-authority
898
- * messages, in first-seen order. Attribution provenance only, never an
899
- * authority source: a plugin must not treat membership here as credential,
900
- * subject, or scope ownership. Derived from full-run provenance, so it can
901
- * exceed the actors visible in the transcript slice. Usually `[run.actor]`;
902
- * possibly empty for system runs with no human instructions.
903
- */
904
- actors: z10.array(actorSchema),
905
- /**
906
- * The single actor this run executes as. Absent only for actor-less legacy
907
- * system records, so authority-sensitive plugins must fail closed.
908
- */
909
- actor: actorSchema.optional(),
910
- runId: z10.string().min(1),
911
- source: sourceSchema,
912
- transcript: z10.array(pluginRunTranscriptEntrySchema)
869
+ /** One normalized transcript entry from the completed run exposed to plugin tasks. */
870
+ const pluginRunTranscriptEntrySchema = z.discriminatedUnion("type", [z.object({
871
+ type: z.literal("message"),
872
+ role: z.enum(["user", "assistant"]),
873
+ text: z.string().min(1),
874
+ provenance: pluginRunTranscriptProvenanceSchema.optional(),
875
+ isRunActor: z.boolean().optional()
876
+ }).strict(), z.object({
877
+ type: z.literal("toolResult"),
878
+ toolName: z.string().min(1),
879
+ isError: z.boolean(),
880
+ text: z.string().min(1).optional()
881
+ }).strict()]);
882
+ /** Runtime-owned completed-run projection exposed to plugin tasks. */
883
+ const pluginRunContextSchema = z.object({
884
+ /** User linked to the Actor, when known. */
885
+ actorUserId: z.string().min(1).optional(),
886
+ completedAtMs: z.number().finite(),
887
+ conversationId: z.string().min(1),
888
+ destination: destinationSchema,
889
+ /** Location associated with this Conversation. */
890
+ locationId: z.string().min(1).optional(),
891
+ /**
892
+ * All distinct actors annotated on this run's committed instruction-authority
893
+ * messages, in first-seen order. Attribution provenance only, never an
894
+ * authority source: a plugin must not treat membership here as credential,
895
+ * subject, or scope ownership. Derived from full-run provenance, so it can
896
+ * exceed the actors visible in the transcript slice. Usually `[run.actor]`;
897
+ * possibly empty for system runs with no human instructions.
898
+ */
899
+ actors: z.array(actorSchema),
900
+ /**
901
+ * The single actor this run executes as. Absent only for actor-less legacy
902
+ * system records, so authority-sensitive plugins must fail closed.
903
+ */
904
+ actor: actorSchema.optional(),
905
+ runId: z.string().min(1),
906
+ source: sourceSchema,
907
+ transcript: z.array(pluginRunTranscriptEntrySchema)
913
908
  }).strict();
914
-
915
909
  // src/tools.ts
916
- import { z as z11 } from "zod";
910
+ /** Thrown when a plugin tool rejects invalid model or user input. */
917
911
  var PluginToolInputError = class extends Error {
918
- constructor(message, options) {
919
- super(message, options);
920
- this.name = "PluginToolInputError";
921
- }
912
+ constructor(message, options) {
913
+ super(message, options);
914
+ this.name = "PluginToolInputError";
915
+ }
922
916
  };
923
- var pluginToolContentSchema = z11.discriminatedUnion("type", [
924
- z11.object({ type: z11.literal("text"), text: z11.string() }).strict(),
925
- z11.object({
926
- type: z11.literal("image"),
927
- data: z11.string(),
928
- mimeType: z11.string()
929
- }).strict()
930
- ]);
931
- var pluginToolContinuationSchema = z11.object({
932
- arguments: z11.record(z11.string(), z11.unknown()),
933
- reason: z11.string().min(1).optional()
917
+ const pluginToolContentSchema = z.discriminatedUnion("type", [z.object({
918
+ type: z.literal("text"),
919
+ text: z.string()
920
+ }).strict(), z.object({
921
+ type: z.literal("image"),
922
+ data: z.string(),
923
+ mimeType: z.string()
924
+ }).strict()]);
925
+ const pluginToolContinuationSchema = z.object({
926
+ arguments: z.record(z.string(), z.unknown()),
927
+ reason: z.string().min(1).optional()
934
928
  }).strict();
935
- var pluginToolOutputSchema = z11.object({
936
- /** Object results to save and show with the next reply. Omit for silent updates. */
937
- objectAnnotations: z11.array(objectAnnotationSchema).optional(),
938
- target: z11.string().min(1).optional(),
939
- truncated: z11.boolean().optional(),
940
- continuation: pluginToolContinuationSchema.optional()
929
+ /** Shared optional fields for canonical plugin tool outputs. */
930
+ const pluginToolOutputSchema = z.object({
931
+ /** Object results to save and show with the next reply. Omit for silent updates. */
932
+ objectAnnotations: z.array(objectAnnotationSchema).optional(),
933
+ target: z.string().min(1).optional(),
934
+ truncated: z.boolean().optional(),
935
+ continuation: pluginToolContinuationSchema.optional()
941
936
  }).passthrough();
942
- var toolApprovalModeSchema = z11.enum(["auto", "review", "approve"]);
943
- var REQUIRED_TOOL_ANNOTATION_KEYS = [
944
- "destructiveHint",
945
- "idempotentHint",
946
- "openWorldHint",
947
- "readOnlyHint"
937
+ /**
938
+ * Tool-declared approval mode.
939
+ *
940
+ * `auto` delegates to core policy, `review` enters Guardian review, and
941
+ * `approve` permits execution without review. Plugin tool helpers normalize
942
+ * omission to `auto`.
943
+ *
944
+ * Core resolves the effective mode immediately before execution.
945
+ */
946
+ const toolApprovalModeSchema = z.enum([
947
+ "auto",
948
+ "review",
949
+ "approve"
950
+ ]);
951
+ const REQUIRED_TOOL_ANNOTATION_KEYS = [
952
+ "destructiveHint",
953
+ "idempotentHint",
954
+ "openWorldHint",
955
+ "readOnlyHint"
948
956
  ];
957
+ /** Return behavioral annotation keys that a tool did not declare. */
949
958
  function missingToolAnnotationKeys(annotations) {
950
- return REQUIRED_TOOL_ANNOTATION_KEYS.filter(
951
- (key) => typeof annotations?.[key] !== "boolean"
952
- );
959
+ return REQUIRED_TOOL_ANNOTATION_KEYS.filter((key) => typeof annotations?.[key] !== "boolean");
953
960
  }
954
961
  function isPluginToolOutputEnvelope(value) {
955
- return value !== null && typeof value === "object" && Array.isArray(value.content) && "details" in value;
962
+ return value !== null && typeof value === "object" && Array.isArray(value.content) && "details" in value;
956
963
  }
957
964
  function formatZodPath(path) {
958
- return path.length > 0 ? path.map(String).join(".") : "root";
965
+ return path.length > 0 ? path.map(String).join(".") : "root";
959
966
  }
960
967
  function formatPluginToolInputError(error) {
961
- const details = error.issues.slice(0, 5).map((issue) => `${formatZodPath(issue.path)}: ${issue.message}`).join("; ");
962
- return `Invalid tool arguments: ${details || "input did not match schema"}`;
968
+ return `Invalid tool arguments: ${error.issues.slice(0, 5).map((issue) => `${formatZodPath(issue.path)}: ${issue.message}`).join("; ") || "input did not match schema"}`;
963
969
  }
964
970
  function parsePluginToolInput(schema, args) {
965
- const result = schema.safeParse(args);
966
- if (!result.success) {
967
- throw new PluginToolInputError(formatPluginToolInputError(result.error), {
968
- cause: result.error
969
- });
970
- }
971
- return result.data;
971
+ const result = schema.safeParse(args);
972
+ if (!result.success) throw new PluginToolInputError(formatPluginToolInputError(result.error), { cause: result.error });
973
+ return result.data;
972
974
  }
973
975
  function createZodTool(definition, helperName) {
974
- const { inputSchema, outputSchema, prepareArguments, execute, ...tool } = definition;
975
- let modelInputSchema;
976
- let modelOutputSchema;
977
- try {
978
- modelInputSchema = z11.toJSONSchema(inputSchema);
979
- } catch (error) {
980
- throw new TypeError(
981
- `${helperName}() inputSchema must be representable as JSON Schema.`,
982
- { cause: error }
983
- );
984
- }
985
- try {
986
- modelOutputSchema = z11.toJSONSchema(outputSchema);
987
- } catch (error) {
988
- throw new TypeError(
989
- `${helperName}() outputSchema must be representable as JSON Schema.`,
990
- { cause: error }
991
- );
992
- }
993
- return {
994
- ...tool,
995
- approvalMode: tool.approvalMode ?? "auto",
996
- inputSchema: modelInputSchema,
997
- outputSchema: modelOutputSchema,
998
- prepareArguments(args) {
999
- return parsePluginToolInput(
1000
- inputSchema,
1001
- prepareArguments ? prepareArguments(args) : args
1002
- );
1003
- },
1004
- ...execute ? {
1005
- async execute(input, options) {
1006
- const result = await execute(
1007
- input,
1008
- options
1009
- );
1010
- if (isPluginToolOutputEnvelope(result)) {
1011
- return {
1012
- content: z11.array(pluginToolContentSchema).parse(result.content),
1013
- details: outputSchema.parse(result.details)
1014
- };
1015
- }
1016
- return outputSchema.parse(result);
1017
- }
1018
- } : void 0
1019
- };
976
+ const { inputSchema, outputSchema, prepareArguments, execute, ...tool } = definition;
977
+ let modelInputSchema;
978
+ let modelOutputSchema;
979
+ try {
980
+ modelInputSchema = z.toJSONSchema(inputSchema);
981
+ } catch (error) {
982
+ throw new TypeError(`${helperName}() inputSchema must be representable as JSON Schema.`, { cause: error });
983
+ }
984
+ try {
985
+ modelOutputSchema = z.toJSONSchema(outputSchema);
986
+ } catch (error) {
987
+ throw new TypeError(`${helperName}() outputSchema must be representable as JSON Schema.`, { cause: error });
988
+ }
989
+ return {
990
+ ...tool,
991
+ approvalMode: tool.approvalMode ?? "auto",
992
+ inputSchema: modelInputSchema,
993
+ outputSchema: modelOutputSchema,
994
+ prepareArguments(args) {
995
+ return parsePluginToolInput(inputSchema, prepareArguments ? prepareArguments(args) : args);
996
+ },
997
+ ...execute ? { async execute(input, options) {
998
+ const result = await execute(input, options);
999
+ if (isPluginToolOutputEnvelope(result)) return {
1000
+ content: z.array(pluginToolContentSchema).parse(result.content),
1001
+ details: outputSchema.parse(result.details)
1002
+ };
1003
+ return outputSchema.parse(result);
1004
+ } } : void 0
1005
+ };
1020
1006
  }
1007
+ /** Define a plugin tool with Zod input parsing and validated structured results. */
1021
1008
  function zodTool(definition) {
1022
- return createZodTool(definition, "zodTool");
1009
+ return createZodTool(definition, "zodTool");
1023
1010
  }
1011
+ /** Define a plugin tool with Zod input parsing and the structured result contract. */
1024
1012
  function definePluginTool(definition) {
1025
- return createZodTool(definition, "definePluginTool");
1013
+ return createZodTool(definition, "definePluginTool");
1026
1014
  }
1027
-
1028
1015
  // src/operations.ts
1029
- import { z as z12 } from "zod";
1030
- var pluginApiRouteRequestContextSchema = z12.object({
1031
- auth: z12.object({
1032
- user: z12.object({
1033
- email: z12.string().nullable().optional(),
1034
- emailVerified: z12.boolean().optional(),
1035
- /** Junior-wide admin role, read from the user record on each request. */
1036
- isAdmin: z12.boolean(),
1037
- name: z12.string().nullable().optional()
1038
- }).strict()
1039
- }).strict(),
1040
- pluginName: nonBlankStringSchema
1016
+ /** Per-request context Junior passes to authenticated plugin product API routes. */
1017
+ const pluginApiRouteRequestContextSchema = z.object({
1018
+ auth: z.object({ user: z.object({
1019
+ email: z.string().nullable().optional(),
1020
+ emailVerified: z.boolean().optional(),
1021
+ /** Junior-wide admin role, read from the user record on each request. */
1022
+ isAdmin: z.boolean(),
1023
+ name: z.string().nullable().optional()
1024
+ }).strict() }).strict(),
1025
+ pluginName: nonBlankStringSchema
1041
1026
  }).strict();
1042
-
1043
1027
  // src/credentials.ts
1044
- import { z as z13 } from "zod";
1045
- var pluginProviderNameSchema = z13.string().regex(/^[a-z][a-z0-9-]*$/);
1046
- var pluginGrantNameSchema = z13.string().regex(/^[a-z][a-z0-9.-]*$/);
1047
- var pluginGrantAccessSchema = z13.union([
1048
- z13.literal("read"),
1049
- z13.literal("write")
1050
- ]);
1051
- var pluginAuthorizationSchema = z13.object({
1052
- provider: pluginProviderNameSchema,
1053
- scope: nonBlankStringSchema.optional(),
1054
- type: z13.literal("oauth")
1028
+ const pluginProviderNameSchema = z.string().regex(/^[a-z][a-z0-9-]*$/);
1029
+ const pluginGrantNameSchema = z.string().regex(/^[a-z][a-z0-9.-]*$/);
1030
+ const pluginGrantAccessSchema = z.union([z.literal("read"), z.literal("write")]);
1031
+ /** Runtime schema for provider authorization a plugin may request. */
1032
+ const pluginAuthorizationSchema = z.object({
1033
+ provider: pluginProviderNameSchema,
1034
+ scope: nonBlankStringSchema.optional(),
1035
+ type: z.literal("oauth")
1055
1036
  }).strict();
1056
- var pluginProviderAccountSchema = z13.object({
1057
- displayName: nonBlankStringSchema.optional(),
1058
- handle: nonBlankStringSchema.optional(),
1059
- id: nonBlankStringSchema,
1060
- label: nonBlankStringSchema.optional(),
1061
- url: nonBlankStringSchema.optional()
1037
+ /** Runtime schema for a provider account attached to stored OAuth tokens. */
1038
+ const pluginProviderAccountSchema = z.object({
1039
+ displayName: nonBlankStringSchema.optional(),
1040
+ handle: nonBlankStringSchema.optional(),
1041
+ id: nonBlankStringSchema,
1042
+ label: nonBlankStringSchema.optional(),
1043
+ url: nonBlankStringSchema.optional(),
1044
+ /**
1045
+ * Email addresses that the provider verified for this account. Junior
1046
+ * uses them only to link the account to a person and does not store them
1047
+ * with the tokens.
1048
+ */
1049
+ verifiedEmails: z.array(nonBlankStringSchema).optional()
1062
1050
  }).strict();
1063
- var pluginStoredTokensSchema = z13.object({
1064
- account: pluginProviderAccountSchema.optional(),
1065
- accessToken: nonBlankStringSchema,
1066
- expiresAt: z13.number().finite().optional(),
1067
- refreshToken: nonBlankStringSchema,
1068
- refreshTokenExpiresAt: z13.number().finite().optional(),
1069
- scope: nonBlankStringSchema.optional()
1051
+ /** Runtime schema for OAuth tokens stored by the host for plugin credentials. */
1052
+ const pluginStoredTokensSchema = z.object({
1053
+ account: pluginProviderAccountSchema.optional(),
1054
+ accessToken: nonBlankStringSchema,
1055
+ expiresAt: z.number().finite().optional(),
1056
+ refreshToken: nonBlankStringSchema,
1057
+ refreshTokenExpiresAt: z.number().finite().optional(),
1058
+ scope: nonBlankStringSchema.optional()
1070
1059
  }).strict();
1071
- var pluginGrantSchema = z13.object({
1072
- access: pluginGrantAccessSchema,
1073
- leaseScope: nonBlankStringSchema.optional(),
1074
- name: pluginGrantNameSchema,
1075
- reason: nonBlankStringSchema.optional(),
1076
- requirements: z13.array(nonBlankStringSchema).min(1).optional()
1060
+ /** Runtime schema for a plugin-defined outbound credential grant. */
1061
+ const pluginGrantSchema = z.object({
1062
+ access: pluginGrantAccessSchema,
1063
+ leaseScope: nonBlankStringSchema.optional(),
1064
+ name: pluginGrantNameSchema,
1065
+ reason: nonBlankStringSchema.optional(),
1066
+ requirements: z.array(nonBlankStringSchema).min(1).optional()
1077
1067
  }).strict();
1078
- var pluginCredentialHeaderTransformSchema = z13.object({
1079
- domain: z13.string().min(1),
1080
- headers: z13.record(z13.string(), z13.string()).refine((headers) => Object.keys(headers).length > 0)
1068
+ /** Runtime schema for plugin-issued header mutations. */
1069
+ const pluginCredentialHeaderTransformSchema = z.object({
1070
+ domain: z.string().min(1),
1071
+ headers: z.record(z.string(), z.string()).refine((headers) => Object.keys(headers).length > 0)
1081
1072
  }).strict();
1082
- var pluginCredentialLeaseSchema = z13.object({
1083
- account: pluginProviderAccountSchema.optional(),
1084
- authorization: pluginAuthorizationSchema.optional(),
1085
- expiresAt: z13.string().refine((value) => Number.isFinite(Date.parse(value))),
1086
- headerTransforms: z13.array(pluginCredentialHeaderTransformSchema).min(1)
1073
+ /** Runtime schema for a short-lived plugin-issued credential lease. */
1074
+ const pluginCredentialLeaseSchema = z.object({
1075
+ account: pluginProviderAccountSchema.optional(),
1076
+ authorization: pluginAuthorizationSchema.optional(),
1077
+ expiresAt: z.string().refine((value) => Number.isFinite(Date.parse(value))),
1078
+ headerTransforms: z.array(pluginCredentialHeaderTransformSchema).min(1)
1087
1079
  }).strict();
1088
- var pluginCredentialResultSchema = z13.discriminatedUnion("type", [
1089
- z13.object({
1090
- lease: pluginCredentialLeaseSchema,
1091
- type: z13.literal("lease")
1092
- }).strict(),
1093
- z13.object({
1094
- authorization: pluginAuthorizationSchema.optional(),
1095
- message: nonBlankStringSchema,
1096
- type: z13.literal("needed")
1097
- }).strict(),
1098
- z13.object({
1099
- message: nonBlankStringSchema,
1100
- type: z13.literal("unavailable")
1101
- }).strict()
1080
+ /** Runtime schema for the result returned by a plugin credential hook. */
1081
+ const pluginCredentialResultSchema = z.discriminatedUnion("type", [
1082
+ z.object({
1083
+ lease: pluginCredentialLeaseSchema,
1084
+ type: z.literal("lease")
1085
+ }).strict(),
1086
+ z.object({
1087
+ authorization: pluginAuthorizationSchema.optional(),
1088
+ message: nonBlankStringSchema,
1089
+ type: z.literal("needed")
1090
+ }).strict(),
1091
+ z.object({
1092
+ message: nonBlankStringSchema,
1093
+ type: z.literal("unavailable")
1094
+ }).strict()
1102
1095
  ]);
1096
+ /** Interrupt sandbox egress so Junior can start provider authorization. */
1103
1097
  var EgressAuthRequired = class extends Error {
1104
- authorization;
1105
- constructor(message, options) {
1106
- super(message, { cause: options?.cause });
1107
- this.name = "EgressAuthRequired";
1108
- this.authorization = options?.authorization;
1109
- }
1098
+ authorization;
1099
+ constructor(message, options) {
1100
+ super(message, { cause: options?.cause });
1101
+ this.name = "EgressAuthRequired";
1102
+ this.authorization = options?.authorization;
1103
+ }
1110
1104
  };
1105
+ /** Deny provider egress before Junior issues credentials for a disallowed operation. */
1111
1106
  var EgressPolicyDenied = class extends Error {
1112
- constructor(message, options) {
1113
- super(message, { cause: options?.cause });
1114
- this.name = "EgressPolicyDenied";
1115
- }
1107
+ constructor(message, options) {
1108
+ super(message, { cause: options?.cause });
1109
+ this.name = "EgressPolicyDenied";
1110
+ }
1116
1111
  };
1117
-
1118
1112
  // src/egress-policy.ts
1113
+ /**
1114
+ * Deny provider egress when a plugin policy does not allow the request.
1115
+ *
1116
+ * Call from a plugin `grantForEgress` hook before returning a write grant.
1117
+ */
1119
1118
  function enforceEgressPolicy(input) {
1120
- if (!input.allowed) {
1121
- throw new EgressPolicyDenied(input.denialMessage);
1122
- }
1119
+ if (!input.allowed) throw new EgressPolicyDenied(input.denialMessage);
1123
1120
  }
1124
-
1125
1121
  // src/registration.ts
1126
- var PLUGIN_NAME_RE = /^[a-z][a-z0-9-]*$/;
1127
- var USER_PAGE_ID_RE = /^[a-z][a-z0-9-]*$/;
1122
+ const PLUGIN_NAME_RE = /^[a-z][a-z0-9-]*$/;
1123
+ const USER_PAGE_ID_RE = /^[a-z][a-z0-9-]*$/;
1124
+ /** Define one Junior plugin registration for app and build-time wiring. */
1128
1125
  function defineJuniorPlugin(plugin) {
1129
- if ("pluginConfig" in plugin) {
1130
- throw new Error(
1131
- "pluginConfig is no longer supported. Put runtime metadata in manifest or plugin registration fields."
1132
- );
1133
- }
1134
- if ("name" in plugin) {
1135
- throw new Error("defineJuniorPlugin() uses manifest.name for identity.");
1136
- }
1137
- const manifest = plugin.manifest;
1138
- if (!manifest) {
1139
- throw new Error(
1140
- "defineJuniorPlugin() requires a manifest. Use a package name string in defineJuniorPlugins([...]) for plugin.yaml packages."
1141
- );
1142
- }
1143
- const name = manifest.name;
1144
- if (!name) {
1145
- throw new Error("Junior plugin manifest.name is required.");
1146
- }
1147
- if (!PLUGIN_NAME_RE.test(name)) {
1148
- throw new Error(
1149
- `Junior plugin registration name "${name}" must be a lowercase plugin identifier.`
1150
- );
1151
- }
1152
- if (name === "junior") {
1153
- throw new Error(
1154
- 'Junior plugin registration name "junior" is reserved for native host events.'
1155
- );
1156
- }
1157
- if (typeof manifest.displayName !== "string" || !manifest.displayName.trim()) {
1158
- throw new Error(
1159
- `Junior plugin "${name}" manifest.displayName is required.`
1160
- );
1161
- }
1162
- if (typeof manifest.description !== "string" || !manifest.description.trim()) {
1163
- throw new Error(
1164
- `Junior plugin "${name}" manifest.description is required.`
1165
- );
1166
- }
1167
- if (plugin.userPages !== void 0 && !Array.isArray(plugin.userPages)) {
1168
- throw new Error(`Junior plugin "${name}" userPages must be an array.`);
1169
- }
1170
- if (plugin.conversationEvents !== void 0 && !Array.isArray(plugin.conversationEvents)) {
1171
- throw new Error(
1172
- `Junior plugin "${name}" conversationEvents must be an array.`
1173
- );
1174
- }
1175
- if (plugin.events !== void 0) {
1176
- const parsed = pluginEventsSchema.safeParse(plugin.events);
1177
- if (!parsed.success) {
1178
- throw new Error(`Junior plugin "${name}" events is invalid.`, {
1179
- cause: parsed.error
1180
- });
1181
- }
1182
- }
1183
- const conversationEventIds = /* @__PURE__ */ new Set();
1184
- for (const event of plugin.conversationEvents ?? []) {
1185
- if (!event || typeof event !== "object" && typeof event !== "function" || typeof event.parse !== "function" || typeof event.renderEvent !== "function") {
1186
- throw new Error(
1187
- `Junior plugin "${name}" conversation event definitions must be created with defineConversationEvent().`
1188
- );
1189
- }
1190
- const id = `${event.eventName}@${event.version}`;
1191
- if (conversationEventIds.has(id)) {
1192
- throw new Error(
1193
- `Junior plugin "${name}" has duplicate conversation event "${id}".`
1194
- );
1195
- }
1196
- conversationEventIds.add(id);
1197
- }
1198
- const userPageIds = /* @__PURE__ */ new Set();
1199
- for (const page of plugin.userPages ?? []) {
1200
- if (!page || typeof page !== "object") {
1201
- throw new Error(`Junior plugin "${name}" user pages must be objects.`);
1202
- }
1203
- if (typeof page.id !== "string" || page.id.length > 64 || !USER_PAGE_ID_RE.test(page.id)) {
1204
- throw new Error(
1205
- `Junior plugin "${name}" user page id "${page.id}" must be a lowercase identifier.`
1206
- );
1207
- }
1208
- if (userPageIds.has(page.id)) {
1209
- throw new Error(
1210
- `Junior plugin "${name}" has duplicate user page id "${page.id}".`
1211
- );
1212
- }
1213
- if (typeof page.label !== "string" || !page.label.trim() || page.label.length > 80 || typeof page.description !== "string" || !page.description.trim() || page.description.length > 500) {
1214
- throw new Error(
1215
- `Junior plugin "${name}" user page "${page.id}" requires label and description.`
1216
- );
1217
- }
1218
- if (page.navigation !== void 0 && page.navigation !== "primary" && page.navigation !== "profile" && page.navigation !== "admin") {
1219
- throw new Error(
1220
- `Junior plugin "${name}" user page "${page.id}" navigation must be "primary", "profile", or "admin".`
1221
- );
1222
- }
1223
- if (typeof page.read !== "function") {
1224
- throw new Error(
1225
- `Junior plugin "${name}" user page "${page.id}" requires a read function.`
1226
- );
1227
- }
1228
- userPageIds.add(page.id);
1229
- }
1230
- return {
1231
- ...plugin
1232
- };
1126
+ if ("pluginConfig" in plugin) throw new Error("pluginConfig is no longer supported. Put runtime metadata in manifest or plugin registration fields.");
1127
+ if ("name" in plugin) throw new Error("defineJuniorPlugin() uses manifest.name for identity.");
1128
+ const manifest = plugin.manifest;
1129
+ if (!manifest) throw new Error("defineJuniorPlugin() requires a manifest. Use a package name string in defineJuniorPlugins([...]) for plugin.yaml packages.");
1130
+ const name = manifest.name;
1131
+ if (!name) throw new Error("Junior plugin manifest.name is required.");
1132
+ if (!PLUGIN_NAME_RE.test(name)) throw new Error(`Junior plugin registration name "${name}" must be a lowercase plugin identifier.`);
1133
+ if (name === "junior") throw new Error("Junior plugin registration name \"junior\" is reserved for native host events.");
1134
+ if (typeof manifest.displayName !== "string" || !manifest.displayName.trim()) throw new Error(`Junior plugin "${name}" manifest.displayName is required.`);
1135
+ if (typeof manifest.description !== "string" || !manifest.description.trim()) throw new Error(`Junior plugin "${name}" manifest.description is required.`);
1136
+ if (plugin.userPages !== void 0 && !Array.isArray(plugin.userPages)) throw new Error(`Junior plugin "${name}" userPages must be an array.`);
1137
+ if (plugin.conversationEvents !== void 0 && !Array.isArray(plugin.conversationEvents)) throw new Error(`Junior plugin "${name}" conversationEvents must be an array.`);
1138
+ if (plugin.events !== void 0) {
1139
+ const parsed = pluginEventsSchema.safeParse(plugin.events);
1140
+ if (!parsed.success) throw new Error(`Junior plugin "${name}" events is invalid.`, { cause: parsed.error });
1141
+ }
1142
+ const conversationEventIds = /* @__PURE__ */ new Set();
1143
+ for (const event of plugin.conversationEvents ?? []) {
1144
+ if (!event || typeof event !== "object" && typeof event !== "function" || typeof event.parse !== "function" || typeof event.renderEvent !== "function") throw new Error(`Junior plugin "${name}" conversation event definitions must be created with defineConversationEvent().`);
1145
+ const id = `${event.eventName}@${event.version}`;
1146
+ if (conversationEventIds.has(id)) throw new Error(`Junior plugin "${name}" has duplicate conversation event "${id}".`);
1147
+ conversationEventIds.add(id);
1148
+ }
1149
+ const userPageIds = /* @__PURE__ */ new Set();
1150
+ for (const page of plugin.userPages ?? []) {
1151
+ if (!page || typeof page !== "object") throw new Error(`Junior plugin "${name}" user pages must be objects.`);
1152
+ if (typeof page.id !== "string" || page.id.length > 64 || !USER_PAGE_ID_RE.test(page.id)) throw new Error(`Junior plugin "${name}" user page id "${page.id}" must be a lowercase identifier.`);
1153
+ if (userPageIds.has(page.id)) throw new Error(`Junior plugin "${name}" has duplicate user page id "${page.id}".`);
1154
+ if (typeof page.label !== "string" || !page.label.trim() || page.label.length > 80 || typeof page.description !== "string" || !page.description.trim() || page.description.length > 500) throw new Error(`Junior plugin "${name}" user page "${page.id}" requires label and description.`);
1155
+ if (page.navigation !== void 0 && page.navigation !== "primary" && page.navigation !== "profile" && page.navigation !== "admin") throw new Error(`Junior plugin "${name}" user page "${page.id}" navigation must be "primary", "profile", or "admin".`);
1156
+ if (typeof page.read !== "function") throw new Error(`Junior plugin "${name}" user page "${page.id}" requires a read function.`);
1157
+ userPageIds.add(page.id);
1158
+ }
1159
+ return { ...plugin };
1233
1160
  }
1234
-
1235
1161
  // src/user-pages.ts
1236
- import { z as z14 } from "zod";
1237
- var userPageIdSchema = nonBlankStringSchema.max(64).regex(/^[a-z][a-z0-9-]*$/);
1238
- var userPageLabelSchema = nonBlankStringSchema.max(80);
1239
- var userPageDescriptionSchema = nonBlankStringSchema.max(500);
1240
- var userPageNavigationSchema = z14.enum(["primary", "profile", "admin"]);
1241
- var pluginUserPageMetricSchema = z14.object({
1242
- detail: nonBlankStringSchema.max(500).optional(),
1243
- label: nonBlankStringSchema.max(80),
1244
- tone: z14.enum(["good", "neutral", "warning"]).optional(),
1245
- value: nonBlankStringSchema.max(120)
1162
+ /**
1163
+ * Core-rendered plugin user pages.
1164
+ *
1165
+ * Plugins own bounded data projection; Junior owns viewer authorization,
1166
+ * routing, response validation, and browser rendering.
1167
+ */
1168
+ const userPageIdSchema = nonBlankStringSchema.max(64).regex(/^[a-z][a-z0-9-]*$/);
1169
+ const userPageLabelSchema = nonBlankStringSchema.max(80);
1170
+ const userPageDescriptionSchema = nonBlankStringSchema.max(500);
1171
+ const userPageNavigationSchema = z.enum([
1172
+ "primary",
1173
+ "profile",
1174
+ "admin"
1175
+ ]);
1176
+ const pluginUserPageMetricSchema = z.object({
1177
+ detail: nonBlankStringSchema.max(500).optional(),
1178
+ label: nonBlankStringSchema.max(80),
1179
+ tone: z.enum([
1180
+ "good",
1181
+ "neutral",
1182
+ "warning"
1183
+ ]).optional(),
1184
+ value: nonBlankStringSchema.max(120)
1246
1185
  }).strict();
1247
- var pluginUserPageMetadataSchema = z14.object({
1248
- label: nonBlankStringSchema.max(80),
1249
- value: nonBlankStringSchema.max(500)
1186
+ const pluginUserPageMetadataSchema = z.object({
1187
+ label: nonBlankStringSchema.max(80),
1188
+ value: nonBlankStringSchema.max(500)
1250
1189
  }).strict();
1251
- var pluginUserPageActionSchema = z14.object({
1252
- confirmation: nonBlankStringSchema.max(500).optional(),
1253
- href: nonBlankStringSchema.max(500).regex(/^\/api\/plugins\/[a-z][a-z0-9-]*(?:\/|$)/),
1254
- label: nonBlankStringSchema.max(80),
1255
- /**
1256
- * `DELETE` sends a request and refreshes the page. `GET` opens the plugin
1257
- * route in the browser, for flows such as an OAuth redirect.
1258
- */
1259
- method: z14.enum(["DELETE", "GET"]),
1260
- tone: z14.enum(["danger", "neutral"]).optional()
1190
+ const pluginUserPageActionSchema = z.object({
1191
+ confirmation: nonBlankStringSchema.max(500).optional(),
1192
+ href: nonBlankStringSchema.max(500).regex(/^\/api\/plugins\/[a-z][a-z0-9-]*(?:\/|$)/),
1193
+ label: nonBlankStringSchema.max(80),
1194
+ /**
1195
+ * `DELETE` sends a request and refreshes the page. `GET` opens the plugin
1196
+ * route in the browser, for flows such as an OAuth redirect.
1197
+ */
1198
+ method: z.enum(["DELETE", "GET"]),
1199
+ tone: z.enum(["danger", "neutral"]).optional()
1261
1200
  }).strict();
1262
- var pluginUserPageRecordSchema = z14.object({
1263
- actions: z14.array(pluginUserPageActionSchema).max(4).optional(),
1264
- description: nonBlankStringSchema.max(1e3).optional(),
1265
- id: nonBlankStringSchema.max(128),
1266
- metadata: z14.array(pluginUserPageMetadataSchema).max(8).optional(),
1267
- title: nonBlankStringSchema.max(4e3)
1201
+ const pluginUserPageRecordSchema = z.object({
1202
+ actions: z.array(pluginUserPageActionSchema).max(4).optional(),
1203
+ description: nonBlankStringSchema.max(1e3).optional(),
1204
+ id: nonBlankStringSchema.max(128),
1205
+ metadata: z.array(pluginUserPageMetadataSchema).max(8).optional(),
1206
+ title: nonBlankStringSchema.max(4e3)
1268
1207
  }).strict();
1269
- var pluginUserPageContentSchema = z14.object({
1270
- emptyText: nonBlankStringSchema.max(500).optional(),
1271
- metrics: z14.array(pluginUserPageMetricSchema).max(6).optional(),
1272
- nextCursor: nonBlankStringSchema.max(1e3).optional(),
1273
- records: z14.array(pluginUserPageRecordSchema).max(100),
1274
- searchPlaceholder: nonBlankStringSchema.max(120).optional(),
1275
- type: z14.literal("list")
1208
+ /** Bounded list content returned by a plugin-owned user page. */
1209
+ const pluginUserPageContentSchema = z.object({
1210
+ emptyText: nonBlankStringSchema.max(500).optional(),
1211
+ metrics: z.array(pluginUserPageMetricSchema).max(6).optional(),
1212
+ nextCursor: nonBlankStringSchema.max(1e3).optional(),
1213
+ records: z.array(pluginUserPageRecordSchema).max(100),
1214
+ searchPlaceholder: nonBlankStringSchema.max(120).optional(),
1215
+ type: z.literal("list")
1276
1216
  }).strict();
1277
- var pluginUserPageLinkSchema = z14.object({
1278
- description: userPageDescriptionSchema,
1279
- id: userPageIdSchema,
1280
- label: userPageLabelSchema,
1281
- navigation: userPageNavigationSchema,
1282
- pluginDisplayName: nonBlankStringSchema.max(200),
1283
- pluginName: nonBlankStringSchema.max(100)
1217
+ const pluginUserPageLinkSchema = z.object({
1218
+ description: userPageDescriptionSchema,
1219
+ id: userPageIdSchema,
1220
+ label: userPageLabelSchema,
1221
+ navigation: userPageNavigationSchema,
1222
+ pluginDisplayName: nonBlankStringSchema.max(200),
1223
+ pluginName: nonBlankStringSchema.max(100)
1284
1224
  }).strict();
1285
- var pluginUserPageLinksSchema = z14.array(pluginUserPageLinkSchema);
1286
- var pluginUserPageCursorSchema = nonBlankStringSchema.max(1e3).optional();
1287
- var pluginUserPageFilterSchema = nonBlankStringSchema.max(64).optional();
1288
- var pluginUserPageQuerySchema = z14.string().trim().max(200).optional();
1289
- var pluginUserPageInputSchema = z14.object({
1290
- cursor: pluginUserPageCursorSchema,
1291
- filter: pluginUserPageFilterSchema,
1292
- limit: z14.number().int().min(1).max(50),
1293
- query: pluginUserPageQuerySchema
1225
+ const pluginUserPageLinksSchema = z.array(pluginUserPageLinkSchema);
1226
+ /** Optional cursor token for one plugin user page reader. */
1227
+ const pluginUserPageCursorSchema = nonBlankStringSchema.max(1e3).optional();
1228
+ /** Optional filter token for one plugin user page reader. */
1229
+ const pluginUserPageFilterSchema = nonBlankStringSchema.max(64).optional();
1230
+ /** Optional free-text query for one plugin user page reader. */
1231
+ const pluginUserPageQuerySchema = z.string().trim().max(200).optional();
1232
+ /** Validated query state passed to one plugin user page reader. */
1233
+ const pluginUserPageInputSchema = z.object({
1234
+ cursor: pluginUserPageCursorSchema,
1235
+ filter: pluginUserPageFilterSchema,
1236
+ limit: z.number().int().min(1).max(50),
1237
+ query: pluginUserPageQuerySchema
1294
1238
  }).strict();
1295
- export {
1296
- EVENT_DATA_MAX_JSON_BYTES,
1297
- EVENT_DATA_MAX_KEYS,
1298
- EVENT_GUIDANCE_MAX_LENGTH,
1299
- EVENT_SUMMARY_MAX_LENGTH,
1300
- EVENT_TEXT_MAX_LENGTH,
1301
- EgressAuthRequired,
1302
- EgressPolicyDenied,
1303
- PluginToolInputError,
1304
- REQUIRED_TOOL_ANNOTATION_KEYS,
1305
- actorSchema,
1306
- actorUserIdSchema,
1307
- agentInvocationSourceSchema,
1308
- codeChangeInputSchema,
1309
- codeChangeStateSchema,
1310
- conversationAnnotationInputSchema,
1311
- conversationEventIconSchema,
1312
- conversationEventPresentationSchema,
1313
- conversationSidebarAnnotationSchema,
1314
- conversationSidebarIconSchema,
1315
- createEventSource,
1316
- createLocalSource,
1317
- createSlackSource,
1318
- createWebSource,
1319
- defineConversationEvent,
1320
- defineJuniorPlugin,
1321
- definePluginTool,
1322
- definePromptContext,
1323
- destinationSchema,
1324
- destinationVisibilitySchema,
1325
- dispatchOptionsSchema,
1326
- enforceEgressPolicy,
1327
- eventAutomationSourceSchema,
1328
- eventDataSchema,
1329
- eventIdentifierSchema,
1330
- eventInputSchema,
1331
- eventMatchFieldSchema,
1332
- eventMatchFieldsSchema,
1333
- eventMatchSchema,
1334
- eventMatches,
1335
- eventPersonSchema,
1336
- eventSchema,
1337
- eventSourceSchema,
1338
- eventTypeSchema,
1339
- getSourceKey,
1340
- identitySchema,
1341
- isPrivateSource,
1342
- isSlackDestination,
1343
- localActorSchema,
1344
- localDestinationSchema,
1345
- localSourceSchema,
1346
- locationSchema,
1347
- missingToolAnnotationKeys,
1348
- nonBlankStringSchema,
1349
- normalizeEventIdentifier,
1350
- objectAnnotationSchema,
1351
- objectFactFields,
1352
- objectFactsSchema,
1353
- objectIconPath,
1354
- objectIconPaths,
1355
- objectPresentation,
1356
- objectTypeSchema,
1357
- ownedObjectAnnotationSchema,
1358
- platformSchema,
1359
- pluginApiRouteRequestContextSchema,
1360
- pluginAuthorizationSchema,
1361
- pluginCredentialHeaderTransformSchema,
1362
- pluginCredentialLeaseSchema,
1363
- pluginCredentialResultSchema,
1364
- pluginCredentialSubjectSchema,
1365
- pluginDispatchSourceSchema,
1366
- pluginEventTypeSchema,
1367
- pluginEventsSchema,
1368
- pluginGrantSchema,
1369
- pluginProviderAccountSchema,
1370
- pluginRunContextSchema,
1371
- pluginRunTranscriptEntrySchema,
1372
- pluginRunTranscriptProvenanceSchema,
1373
- pluginStoredTokensSchema,
1374
- pluginToolContentSchema,
1375
- pluginToolContinuationSchema,
1376
- pluginToolOutputSchema,
1377
- pluginUserPageContentSchema,
1378
- pluginUserPageCursorSchema,
1379
- pluginUserPageFilterSchema,
1380
- pluginUserPageInputSchema,
1381
- pluginUserPageLinkSchema,
1382
- pluginUserPageLinksSchema,
1383
- pluginUserPageQuerySchema,
1384
- promptContextSchema,
1385
- promptMessageSchema,
1386
- replyAttributionSchema,
1387
- resourceLinkAnnotationSchema,
1388
- resourceTypeSchema,
1389
- scheduledAutomationSourceSchema,
1390
- slackActorSchema,
1391
- slackDestinationSchema,
1392
- slackLocationSchema,
1393
- slackSourceSchema,
1394
- sourceSchema,
1395
- sourceVisibilitySchema,
1396
- stableEventMatchKey,
1397
- subscribableResourceSchema,
1398
- systemActorSchema,
1399
- taskOutcomeSchema,
1400
- toolApprovalModeSchema,
1401
- userSchema,
1402
- watchResultSchema,
1403
- webActorSchema,
1404
- webSourceSchema,
1405
- zodTool
1406
- };
1239
+ export { EVENT_DATA_MAX_JSON_BYTES, EVENT_DATA_MAX_KEYS, EVENT_GUIDANCE_MAX_LENGTH, EVENT_SUMMARY_MAX_LENGTH, EVENT_TEXT_MAX_LENGTH, EgressAuthRequired, EgressPolicyDenied, PluginToolInputError, REQUIRED_TOOL_ANNOTATION_KEYS, actorSchema, actorUserIdSchema, agentInvocationSourceSchema, codeChangeInputSchema, codeChangeStateSchema, conversationAnnotationInputSchema, conversationEventIconSchema, conversationEventPresentationSchema, conversationSidebarAnnotationSchema, conversationSidebarIconSchema, createEventSource, createLocalSource, createSlackSource, createWebSource, defineConversationEvent, defineJuniorPlugin, definePluginTool, definePromptContext, destinationSchema, destinationVisibilitySchema, dispatchOptionsSchema, enforceEgressPolicy, eventAutomationSourceSchema, eventDataSchema, eventIdentifierSchema, eventInputSchema, eventMatchFieldSchema, eventMatchFieldsSchema, eventMatchSchema, eventMatches, eventPersonSchema, eventSchema, eventSourceSchema, eventTypeSchema, getSourceKey, identitySchema, isPrivateSource, isSlackDestination, localActorSchema, localDestinationSchema, localSourceSchema, locationSchema, missingToolAnnotationKeys, nonBlankStringSchema, normalizeEventIdentifier, objectAnnotationSchema, objectFactFields, objectFactsSchema, objectIconPath, objectIconPaths, objectPresentation, objectTypeSchema, ownedObjectAnnotationSchema, platformSchema, pluginApiRouteRequestContextSchema, pluginAuthorizationSchema, pluginCredentialHeaderTransformSchema, pluginCredentialLeaseSchema, pluginCredentialResultSchema, pluginCredentialSubjectSchema, pluginDispatchSourceSchema, pluginEventTypeSchema, pluginEventsSchema, pluginGrantSchema, pluginProviderAccountSchema, pluginRunContextSchema, pluginRunTranscriptEntrySchema, pluginRunTranscriptProvenanceSchema, pluginStoredTokensSchema, pluginToolContentSchema, pluginToolContinuationSchema, pluginToolOutputSchema, pluginUserPageContentSchema, pluginUserPageCursorSchema, pluginUserPageFilterSchema, pluginUserPageInputSchema, pluginUserPageLinkSchema, pluginUserPageLinksSchema, pluginUserPageQuerySchema, promptContextSchema, promptMessageSchema, replyAttributionSchema, resourceLinkAnnotationSchema, resourceTypeSchema, scheduledAutomationSourceSchema, slackActorSchema, slackDestinationSchema, slackLocationSchema, slackSourceSchema, sourceSchema, sourceVisibilitySchema, stableEventMatchKey, subscribableResourceSchema, systemActorSchema, taskOutcomeSchema, toolApprovalModeSchema, userSchema, watchResultSchema, webActorSchema, webSourceSchema, zodTool };