@mastra/factory 0.16.0-alpha.6 → 0.16.0-alpha.7

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 (87) hide show
  1. package/README.md +2 -1
  2. package/dist/boards/work.d.ts.map +1 -1
  3. package/dist/boards/work.js +20 -3
  4. package/dist/boards/work.js.map +1 -1
  5. package/dist/factory.d.ts +5 -3
  6. package/dist/factory.d.ts.map +1 -1
  7. package/dist/factory.js +13 -5
  8. package/dist/factory.js.map +1 -1
  9. package/dist/integrations/jira/adf.d.ts +26 -0
  10. package/dist/integrations/jira/adf.d.ts.map +1 -0
  11. package/dist/integrations/jira/adf.js +73 -0
  12. package/dist/integrations/jira/adf.js.map +1 -0
  13. package/dist/integrations/jira/agent-tools.d.ts +45 -0
  14. package/dist/integrations/jira/agent-tools.d.ts.map +1 -0
  15. package/dist/integrations/jira/agent-tools.js +87 -0
  16. package/dist/integrations/jira/agent-tools.js.map +1 -0
  17. package/dist/integrations/jira/api.d.ts +157 -0
  18. package/dist/integrations/jira/api.d.ts.map +1 -0
  19. package/dist/integrations/jira/api.js +141 -0
  20. package/dist/integrations/jira/api.js.map +1 -0
  21. package/dist/integrations/jira/claim.d.ts +9 -0
  22. package/dist/integrations/jira/claim.d.ts.map +1 -0
  23. package/dist/integrations/jira/claim.js +15 -0
  24. package/dist/integrations/jira/claim.js.map +1 -0
  25. package/dist/integrations/jira/default-rules.d.ts +47 -0
  26. package/dist/integrations/jira/default-rules.d.ts.map +1 -0
  27. package/dist/integrations/jira/default-rules.js +67 -0
  28. package/dist/integrations/jira/default-rules.js.map +1 -0
  29. package/dist/integrations/jira/integration.d.ts +114 -0
  30. package/dist/integrations/jira/integration.d.ts.map +1 -0
  31. package/dist/integrations/jira/integration.js +401 -0
  32. package/dist/integrations/jira/integration.js.map +1 -0
  33. package/dist/integrations/jira/issue-reconciler.d.ts +10 -0
  34. package/dist/integrations/jira/issue-reconciler.d.ts.map +1 -0
  35. package/dist/integrations/jira/issue-reconciler.js +70 -0
  36. package/dist/integrations/jira/issue-reconciler.js.map +1 -0
  37. package/dist/integrations/jira/reconciliation-config.d.ts +3 -0
  38. package/dist/integrations/jira/reconciliation-config.d.ts.map +1 -0
  39. package/dist/integrations/jira/reconciliation-config.js +17 -0
  40. package/dist/integrations/jira/reconciliation-config.js.map +1 -0
  41. package/dist/integrations/jira/routes.d.ts +54 -0
  42. package/dist/integrations/jira/routes.d.ts.map +1 -0
  43. package/dist/integrations/jira/routes.js +260 -0
  44. package/dist/integrations/jira/routes.js.map +1 -0
  45. package/dist/integrations/jira/rules.d.ts +57 -0
  46. package/dist/integrations/jira/rules.d.ts.map +1 -0
  47. package/dist/integrations/jira/rules.js +175 -0
  48. package/dist/integrations/jira/rules.js.map +1 -0
  49. package/dist/integrations/platform/connect/routes.d.ts +39 -0
  50. package/dist/integrations/platform/connect/routes.d.ts.map +1 -0
  51. package/dist/integrations/platform/connect/routes.js +123 -0
  52. package/dist/integrations/platform/connect/routes.js.map +1 -0
  53. package/dist/integrations/platform/github/event-worker.js +1 -1
  54. package/dist/integrations/platform/github/integration.js +1 -1
  55. package/dist/integrations/platform/jira/agent-tools.d.ts +36 -0
  56. package/dist/integrations/platform/jira/agent-tools.d.ts.map +1 -0
  57. package/dist/integrations/platform/jira/agent-tools.js +85 -0
  58. package/dist/integrations/platform/jira/agent-tools.js.map +1 -0
  59. package/dist/integrations/platform/jira/integration.d.ts +65 -0
  60. package/dist/integrations/platform/jira/integration.d.ts.map +1 -0
  61. package/dist/integrations/platform/jira/integration.js +540 -0
  62. package/dist/integrations/platform/jira/integration.js.map +1 -0
  63. package/dist/integrations/platform/jira/routes.d.ts +55 -0
  64. package/dist/integrations/platform/jira/routes.d.ts.map +1 -0
  65. package/dist/integrations/platform/jira/routes.js +274 -0
  66. package/dist/integrations/platform/jira/routes.js.map +1 -0
  67. package/dist/routes/surface.d.ts.map +1 -1
  68. package/dist/routes/surface.js +24 -4
  69. package/dist/routes/surface.js.map +1 -1
  70. package/dist/rules/dispatcher.d.ts.map +1 -1
  71. package/dist/rules/dispatcher.js +1 -1
  72. package/dist/rules/dispatcher.js.map +1 -1
  73. package/dist/rules/index.d.ts +2 -2
  74. package/dist/rules/index.d.ts.map +1 -1
  75. package/dist/rules/index.js +2 -2
  76. package/dist/rules/types.d.ts +30 -3
  77. package/dist/rules/types.d.ts.map +1 -1
  78. package/dist/rules/types.js +5 -1
  79. package/dist/rules/types.js.map +1 -1
  80. package/dist/rules/validation.d.ts.map +1 -1
  81. package/dist/rules/validation.js +1 -0
  82. package/dist/rules/validation.js.map +1 -1
  83. package/dist/work-item-branch.d.ts +1 -1
  84. package/dist/work-item-branch.d.ts.map +1 -1
  85. package/dist/work-item-branch.js +3 -2
  86. package/dist/work-item-branch.js.map +1 -1
  87. package/package.json +8 -8
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Mastra `apiRoutes` for the Jira intake feature.
3
+ *
4
+ * Registered alongside the other `/web/*` routes, behind the host auth gate.
5
+ * Jira connections are owned by the caller's Mastra Platform organization;
6
+ * provider requests stay server-side and flow through the integrations v2
7
+ * proxy. Every route re-resolves the authenticated user and scopes intake
8
+ * selections by the caller's org.
9
+ *
10
+ * When the feature is disabled (no auth, or no intake storage),
11
+ * `buildPlatformJiraRoutes` returns only `GET /web/jira/status`, which reports
12
+ * `enabled:false` so the SPA can cleanly hide all Jira UI.
13
+ */
14
+ import type { ApiRoute } from '@mastra/core/server';
15
+ import type { RouteAuth } from '../../../routes/route.js';
16
+ import type { IntakeStorage } from '../../../storage/domains/intake/base.js';
17
+ import type { JiraRulesIngress } from '../../jira/rules.js';
18
+ import type { PlatformJiraIntegration } from './integration.js';
19
+ /**
20
+ * Non-secret diagnostic snapshot of every Jira feature gate, mirroring the
21
+ * Linear diagnostics shape. Only booleans — never values.
22
+ */
23
+ export interface JiraFeatureDiagnostics {
24
+ jiraConfigured: boolean;
25
+ factoryAuthEnabled: boolean;
26
+ appDbConfigured: boolean;
27
+ }
28
+ export interface MountJiraRoutesOptions {
29
+ /**
30
+ * The integration instance providing REST access. Required for everything
31
+ * beyond the disabled `status` route.
32
+ */
33
+ jira?: PlatformJiraIntegration;
34
+ /** Host auth seam. Intake selections are org-owned, so the feature is inert without it. */
35
+ auth: RouteAuth;
36
+ /**
37
+ * Cross-integration intake selection domain. Required for the issues route's
38
+ * project filter; when absent, only the disabled `status` route is served.
39
+ */
40
+ intake?: IntakeStorage;
41
+ /** Whether the host configured the application database backing intake state. */
42
+ appDbConfigured: boolean;
43
+ /**
44
+ * Factory rules ingress for observed issues. When present, a board-scoped
45
+ * issue listing also materializes new cards through the Jira event rules —
46
+ * the same automatic intake Linear has.
47
+ */
48
+ ingestFactoryIssues?: (input: JiraRulesIngress) => Promise<unknown>;
49
+ }
50
+ /**
51
+ * Build the Jira routes as Mastra `apiRoutes`. When the feature is disabled,
52
+ * returns only the `status` route so the SPA can detect the disabled state.
53
+ */
54
+ export declare function buildPlatformJiraRoutes(options: MountJiraRoutesOptions): ApiRoute[];
55
+ //# sourceMappingURL=routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../../src/integrations/platform/jira/routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAIpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAE7E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAYhE;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC,cAAc,EAAE,OAAO,CAAC;IACxB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,IAAI,CAAC,EAAE,uBAAuB,CAAC;IAC/B,2FAA2F;IAC3F,IAAI,EAAE,SAAS,CAAC;IAChB;;;OAGG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,iFAAiF;IACjF,eAAe,EAAE,OAAO,CAAC;IACzB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACrE;AAqFD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,sBAAsB,GAAG,QAAQ,EAAE,CA0OnF"}
@@ -0,0 +1,274 @@
1
+ import { JiraApiError } from "../../jira/api.js";
2
+ import { registerApiRoute } from "@mastra/core/server";
3
+ //#region src/integrations/platform/jira/routes.ts
4
+ const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
5
+ const ISSUE_KEY_RE = /^[A-Za-z][A-Za-z0-9_]*-\d+$/;
6
+ /** Erase a route handler's path-parameterized context to a plain `Context`. */
7
+ function loose(c) {
8
+ return c;
9
+ }
10
+ /**
11
+ * Narrow the caller's selected Jira projects to the ones that feed this
12
+ * Factory project.
13
+ *
14
+ * A Jira issue carries no Factory project of its own, so without a binding
15
+ * every board view would show every selected project's issues on whichever
16
+ * Factory happened to be on screen. Only sources explicitly bound to a board
17
+ * of this Factory pass — nothing is routed implicitly. Mirrors the Linear
18
+ * routes' scoping semantics locally — the generic binding storage is
19
+ * provider-neutral.
20
+ */
21
+ async function scopeSourceIdsToProject({ intake, orgId, factoryProjectId, selectedIds }) {
22
+ const selected = new Set(selectedIds);
23
+ const intakeBoards = {};
24
+ for (const binding of await intake.listBindings({
25
+ orgId,
26
+ integrationId: "jira"
27
+ })) if (binding.factoryProjectId === factoryProjectId && binding.board && selected.has(binding.sourceId)) intakeBoards[binding.sourceId] = binding.board;
28
+ return intakeBoards;
29
+ }
30
+ /**
31
+ * Resolve the org-scoped tenant for a Jira request. Intake selections are
32
+ * org-owned, so it requires both a signed-in user and an organization — same
33
+ * tenancy rules as the Linear routes.
34
+ */
35
+ async function resolveOrgTenant(c, auth) {
36
+ await auth.ensureUser(c);
37
+ const tenant = auth.tenant(c);
38
+ if (!tenant) return { response: c.json({ error: "unauthorized" }, 401) };
39
+ if (!tenant.orgId) return { response: c.json({
40
+ error: "organization_required",
41
+ message: "Jira intake requires an organization. Personal accounts cannot use Jira intake."
42
+ }, 403) };
43
+ return { tenant: {
44
+ orgId: tenant.orgId,
45
+ userId: tenant.userId
46
+ } };
47
+ }
48
+ /**
49
+ * Validate an opaque Jira pagination cursor from the query string. Cursors are
50
+ * server-issued (`nextPageToken`), so anything outside a conservative
51
+ * charset/length is rejected rather than forwarded to Jira.
52
+ */
53
+ function parseAfterCursor(raw) {
54
+ if (raw === void 0 || raw === "") return void 0;
55
+ if (raw.length > 512 || !/^[\w+/=.:-]+$/.test(raw)) return null;
56
+ return raw;
57
+ }
58
+ /** Map a Jira read failure to the API response for the SPA. */
59
+ function jiraFetchError(c, err) {
60
+ if (err instanceof JiraApiError && err.code === "jira_auth_failed") return c.json({
61
+ error: "jira_auth_failed",
62
+ message: "Jira rejected the connected account. Reconnect it in Mastra Platform."
63
+ }, 409);
64
+ return c.json({
65
+ error: "jira_fetch_failed",
66
+ message: err instanceof Error ? err.message : String(err)
67
+ }, 502);
68
+ }
69
+ /**
70
+ * Build the Jira routes as Mastra `apiRoutes`. When the feature is disabled,
71
+ * returns only the `status` route so the SPA can detect the disabled state.
72
+ */
73
+ function buildPlatformJiraRoutes(options) {
74
+ const routes = [];
75
+ const { jira, auth, intake } = options;
76
+ const enabled = Boolean(jira) && auth.enabled();
77
+ const diagnostics = () => ({
78
+ jiraConfigured: Boolean(jira),
79
+ factoryAuthEnabled: auth.enabled(),
80
+ appDbConfigured: options.appDbConfigured
81
+ });
82
+ routes.push(registerApiRoute("/web/jira/status", {
83
+ method: "GET",
84
+ requiresAuth: false,
85
+ handler: async (c) => {
86
+ if (!enabled || !jira || !intake) return c.json({
87
+ enabled: false,
88
+ configured: Boolean(jira),
89
+ mode: "platform",
90
+ site: null,
91
+ reason: "missing_config",
92
+ diagnostics: diagnostics()
93
+ });
94
+ await auth.ensureUser(loose(c));
95
+ const tenant = auth.tenant(loose(c));
96
+ if (!tenant) return c.json({
97
+ error: "unauthorized",
98
+ reason: "auth_required"
99
+ }, 401);
100
+ if (!tenant.orgId) return c.json({
101
+ enabled: true,
102
+ configured: false,
103
+ mode: "platform",
104
+ organizationRequired: true,
105
+ site: null,
106
+ sites: [],
107
+ connections: [],
108
+ reason: "organization_required",
109
+ diagnostics: diagnostics()
110
+ });
111
+ try {
112
+ const connections = await jira.listConnections();
113
+ const active = connections.filter((connection) => connection.status === "active");
114
+ const sites = active.flatMap((connection) => connection.accountLabel ? [connection.accountLabel] : []);
115
+ return c.json({
116
+ enabled: true,
117
+ configured: active.length > 0,
118
+ mode: "platform",
119
+ site: sites.length === 1 ? sites[0] : null,
120
+ sites,
121
+ connections,
122
+ reason: active.length > 0 ? "ready" : "not_connected",
123
+ diagnostics: diagnostics()
124
+ });
125
+ } catch (err) {
126
+ return jiraFetchError(loose(c), err);
127
+ }
128
+ }
129
+ }));
130
+ if (!enabled || !jira || !intake) return routes;
131
+ routes.push(registerApiRoute("/web/jira/projects", {
132
+ method: "GET",
133
+ requiresAuth: false,
134
+ handler: async (c) => {
135
+ const resolved = await resolveOrgTenant(loose(c), auth);
136
+ if ("response" in resolved) return resolved.response;
137
+ try {
138
+ const sources = await jira.intake.listSources(resolved.tenant);
139
+ return c.json({ projects: sources.map((source) => ({
140
+ id: source.id,
141
+ name: source.name,
142
+ key: typeof source.metadata?.key === "string" ? source.metadata.key : null,
143
+ connectionId: typeof source.metadata?.connectionId === "string" ? source.metadata.connectionId : null,
144
+ site: typeof source.metadata?.site === "string" ? source.metadata.site : null
145
+ })) });
146
+ } catch (err) {
147
+ return jiraFetchError(loose(c), err);
148
+ }
149
+ }
150
+ }));
151
+ routes.push(registerApiRoute("/web/jira/issues", {
152
+ method: "GET",
153
+ requiresAuth: false,
154
+ handler: async (c) => {
155
+ const resolved = await resolveOrgTenant(loose(c), auth);
156
+ if ("response" in resolved) return resolved.response;
157
+ const after = parseAfterCursor(c.req.query("after"));
158
+ if (after === null) return c.json({ error: "invalid_cursor" }, 400);
159
+ const factoryProjectId = c.req.query("factoryProjectId");
160
+ if (factoryProjectId && !UUID_RE.test(factoryProjectId)) return c.json({ error: "invalid_factory_project_id" }, 400);
161
+ await intake.ensureReady();
162
+ const selection = (await intake.getConfig({
163
+ orgId: resolved.tenant.orgId,
164
+ integrationIds: ["jira"]
165
+ })).jira;
166
+ if (!selection.enabled) return c.json({
167
+ error: "jira_intake_disabled",
168
+ message: "Jira intake is turned off in Settings."
169
+ }, 404);
170
+ const selectedIds = selection.sourceIds ?? [];
171
+ const intakeBoards = factoryProjectId ? await scopeSourceIdsToProject({
172
+ intake,
173
+ orgId: resolved.tenant.orgId,
174
+ factoryProjectId,
175
+ selectedIds
176
+ }) : null;
177
+ const projectIds = intakeBoards ? Object.keys(intakeBoards) : selectedIds;
178
+ if (projectIds.length === 0) return c.json({
179
+ issues: [],
180
+ nextCursor: null
181
+ });
182
+ try {
183
+ const { issues, nextCursor } = await jira.listActiveIssues(after, projectIds);
184
+ const issuePayload = issues.map((issue) => ({
185
+ id: issue.externalId,
186
+ identifier: issue.identifier,
187
+ title: issue.title,
188
+ url: issue.url,
189
+ author: issue.author,
190
+ state: issue.state ?? "",
191
+ stateType: issue.stateType ?? "",
192
+ priorityLabel: issue.priority ?? "",
193
+ assignee: issue.assignee,
194
+ project: issue.source,
195
+ site: issue.site,
196
+ labels: issue.labels,
197
+ createdAt: issue.createdAt,
198
+ updatedAt: issue.updatedAt,
199
+ sourceId: issue.sourceId || null
200
+ }));
201
+ if (factoryProjectId && intakeBoards && options.ingestFactoryIssues) await options.ingestFactoryIssues({
202
+ orgId: resolved.tenant.orgId,
203
+ userId: resolved.tenant.userId,
204
+ factoryProjectId,
205
+ issues: issuePayload.map((issue) => ({
206
+ ...issue,
207
+ site: issue.site ?? null
208
+ })),
209
+ intakeBoards
210
+ });
211
+ return c.json({
212
+ issues: issuePayload,
213
+ nextCursor
214
+ });
215
+ } catch (err) {
216
+ return jiraFetchError(loose(c), err);
217
+ }
218
+ }
219
+ }));
220
+ routes.push(registerApiRoute("/web/jira/issues/:identifier", {
221
+ method: "GET",
222
+ requiresAuth: false,
223
+ handler: async (c) => {
224
+ const resolved = await resolveOrgTenant(loose(c), auth);
225
+ if ("response" in resolved) return resolved.response;
226
+ const identifier = c.req.param("identifier");
227
+ const factoryProjectId = c.req.query("factoryProjectId");
228
+ const issueRef = c.req.query("issueRef");
229
+ if (!ISSUE_KEY_RE.test(identifier)) return c.json({ error: "invalid_issue_identifier" }, 400);
230
+ if (!factoryProjectId || !UUID_RE.test(factoryProjectId)) return c.json({ error: "invalid_factory_project_id" }, 400);
231
+ if (!issueRef || issueRef.length > 2048) return c.json({ error: "invalid_issue_ref" }, 400);
232
+ await intake.ensureReady();
233
+ const selection = (await intake.getConfig({
234
+ orgId: resolved.tenant.orgId,
235
+ integrationIds: ["jira"]
236
+ })).jira;
237
+ if (!selection.enabled) return c.json({
238
+ error: "jira_intake_disabled",
239
+ message: "Jira intake is turned off in Settings."
240
+ }, 404);
241
+ const intakeBoards = await scopeSourceIdsToProject({
242
+ intake,
243
+ orgId: resolved.tenant.orgId,
244
+ factoryProjectId,
245
+ selectedIds: selection.sourceIds ?? []
246
+ });
247
+ const dispatch = await jira.intake.resolveIntakeDispatch?.({
248
+ orgId: resolved.tenant.orgId,
249
+ externalSource: {
250
+ type: "issue",
251
+ externalId: issueRef
252
+ }
253
+ });
254
+ if (!dispatch?.sourceId || !(dispatch.sourceId in intakeBoards)) return c.json({ error: "issue_not_found" }, 404);
255
+ try {
256
+ const issue = await jira.intake.getIssue(dispatch);
257
+ if (!issue || issue.identifier.toUpperCase() !== identifier.toUpperCase()) return c.json({ error: "issue_not_found" }, 404);
258
+ return c.json({
259
+ identifier: issue.identifier,
260
+ title: issue.title,
261
+ url: issue.url,
262
+ description: issue.description
263
+ });
264
+ } catch (err) {
265
+ return jiraFetchError(loose(c), err);
266
+ }
267
+ }
268
+ }));
269
+ return routes;
270
+ }
271
+ //#endregion
272
+ export { buildPlatformJiraRoutes };
273
+
274
+ //# sourceMappingURL=routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.js","names":[],"sources":["../../../../src/integrations/platform/jira/routes.ts"],"sourcesContent":["/**\n * Mastra `apiRoutes` for the Jira intake feature.\n *\n * Registered alongside the other `/web/*` routes, behind the host auth gate.\n * Jira connections are owned by the caller's Mastra Platform organization;\n * provider requests stay server-side and flow through the integrations v2\n * proxy. Every route re-resolves the authenticated user and scopes intake\n * selections by the caller's org.\n *\n * When the feature is disabled (no auth, or no intake storage),\n * `buildPlatformJiraRoutes` returns only `GET /web/jira/status`, which reports\n * `enabled:false` so the SPA can cleanly hide all Jira UI.\n */\n\nimport type { ApiRoute } from '@mastra/core/server';\nimport { registerApiRoute } from '@mastra/core/server';\nimport type { Context } from 'hono';\n\nimport type { RouteAuth } from '../../../routes/route.js';\nimport type { IntakeStorage } from '../../../storage/domains/intake/base.js';\nimport { JiraApiError } from '../../jira/api.js';\nimport type { JiraRulesIngress } from '../../jira/rules.js';\nimport type { PlatformJiraIntegration } from './integration.js';\n\ntype RouteContext = Context;\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nconst ISSUE_KEY_RE = /^[A-Za-z][A-Za-z0-9_]*-\\d+$/;\n\n/** Erase a route handler's path-parameterized context to a plain `Context`. */\nfunction loose(c: unknown): RouteContext {\n return c as RouteContext;\n}\n\n/**\n * Non-secret diagnostic snapshot of every Jira feature gate, mirroring the\n * Linear diagnostics shape. Only booleans — never values.\n */\nexport interface JiraFeatureDiagnostics {\n jiraConfigured: boolean;\n factoryAuthEnabled: boolean;\n appDbConfigured: boolean;\n}\n\nexport interface MountJiraRoutesOptions {\n /**\n * The integration instance providing REST access. Required for everything\n * beyond the disabled `status` route.\n */\n jira?: PlatformJiraIntegration;\n /** Host auth seam. Intake selections are org-owned, so the feature is inert without it. */\n auth: RouteAuth;\n /**\n * Cross-integration intake selection domain. Required for the issues route's\n * project filter; when absent, only the disabled `status` route is served.\n */\n intake?: IntakeStorage;\n /** Whether the host configured the application database backing intake state. */\n appDbConfigured: boolean;\n /**\n * Factory rules ingress for observed issues. When present, a board-scoped\n * issue listing also materializes new cards through the Jira event rules —\n * the same automatic intake Linear has.\n */\n ingestFactoryIssues?: (input: JiraRulesIngress) => Promise<unknown>;\n}\n\n/**\n * Narrow the caller's selected Jira projects to the ones that feed this\n * Factory project.\n *\n * A Jira issue carries no Factory project of its own, so without a binding\n * every board view would show every selected project's issues on whichever\n * Factory happened to be on screen. Only sources explicitly bound to a board\n * of this Factory pass — nothing is routed implicitly. Mirrors the Linear\n * routes' scoping semantics locally — the generic binding storage is\n * provider-neutral.\n */\nasync function scopeSourceIdsToProject({\n intake,\n orgId,\n factoryProjectId,\n selectedIds,\n}: {\n intake: IntakeStorage;\n orgId: string;\n factoryProjectId: string;\n selectedIds: string[];\n}): Promise<Record<string, string>> {\n const selected = new Set(selectedIds);\n const intakeBoards: Record<string, string> = {};\n for (const binding of await intake.listBindings({ orgId, integrationId: 'jira' })) {\n if (binding.factoryProjectId === factoryProjectId && binding.board && selected.has(binding.sourceId)) {\n intakeBoards[binding.sourceId] = binding.board;\n }\n }\n return intakeBoards;\n}\n\n/**\n * Resolve the org-scoped tenant for a Jira request. Intake selections are\n * org-owned, so it requires both a signed-in user and an organization — same\n * tenancy rules as the Linear routes.\n */\nasync function resolveOrgTenant(\n c: RouteContext,\n auth: RouteAuth,\n): Promise<{ tenant: { orgId: string; userId: string } } | { response: Response }> {\n await auth.ensureUser(c);\n const tenant = auth.tenant(c);\n if (!tenant) return { response: c.json({ error: 'unauthorized' }, 401) };\n if (!tenant.orgId) {\n return {\n response: c.json(\n {\n error: 'organization_required',\n message: 'Jira intake requires an organization. Personal accounts cannot use Jira intake.',\n },\n 403,\n ),\n };\n }\n return { tenant: { orgId: tenant.orgId, userId: tenant.userId } };\n}\n\n/**\n * Validate an opaque Jira pagination cursor from the query string. Cursors are\n * server-issued (`nextPageToken`), so anything outside a conservative\n * charset/length is rejected rather than forwarded to Jira.\n */\nfunction parseAfterCursor(raw: string | undefined): string | undefined | null {\n if (raw === undefined || raw === '') return undefined;\n if (raw.length > 512 || !/^[\\w+/=.:-]+$/.test(raw)) return null;\n return raw;\n}\n\n/** Map a Jira read failure to the API response for the SPA. */\nfunction jiraFetchError(c: RouteContext, err: unknown) {\n if (err instanceof JiraApiError && err.code === 'jira_auth_failed') {\n return c.json(\n {\n error: 'jira_auth_failed',\n message: 'Jira rejected the connected account. Reconnect it in Mastra Platform.',\n },\n 409,\n );\n }\n return c.json({ error: 'jira_fetch_failed', message: err instanceof Error ? err.message : String(err) }, 502);\n}\n\n/**\n * Build the Jira routes as Mastra `apiRoutes`. When the feature is disabled,\n * returns only the `status` route so the SPA can detect the disabled state.\n */\nexport function buildPlatformJiraRoutes(options: MountJiraRoutesOptions): ApiRoute[] {\n const routes: ApiRoute[] = [];\n const { jira, auth, intake } = options;\n const enabled = Boolean(jira) && auth.enabled();\n const diagnostics = (): JiraFeatureDiagnostics => ({\n jiraConfigured: Boolean(jira),\n factoryAuthEnabled: auth.enabled(),\n appDbConfigured: options.appDbConfigured,\n });\n\n // The status route is always registered so the SPA can detect the disabled state.\n routes.push(\n registerApiRoute('/web/jira/status', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n if (!enabled || !jira || !intake) {\n return c.json({\n enabled: false,\n configured: Boolean(jira),\n mode: 'platform',\n site: null,\n reason: 'missing_config',\n diagnostics: diagnostics(),\n });\n }\n await auth.ensureUser(loose(c));\n const tenant = auth.tenant(loose(c));\n if (!tenant) return c.json({ error: 'unauthorized', reason: 'auth_required' }, 401);\n\n if (!tenant.orgId) {\n return c.json({\n enabled: true,\n configured: false,\n mode: 'platform',\n organizationRequired: true,\n site: null,\n sites: [],\n connections: [],\n reason: 'organization_required',\n diagnostics: diagnostics(),\n });\n }\n\n try {\n const connections = await jira.listConnections();\n const active = connections.filter(connection => connection.status === 'active');\n const sites = active.flatMap(connection => (connection.accountLabel ? [connection.accountLabel] : []));\n return c.json({\n enabled: true,\n configured: active.length > 0,\n mode: 'platform',\n site: sites.length === 1 ? sites[0] : null,\n sites,\n connections,\n reason: active.length > 0 ? 'ready' : 'not_connected',\n diagnostics: diagnostics(),\n });\n } catch (err) {\n return jiraFetchError(loose(c), err);\n }\n },\n }),\n );\n\n // Without the integration instance or the intake domain the feature can't\n // serve org-scoped data — serve only the disabled `status` route.\n if (!enabled || !jira || !intake) {\n return routes;\n }\n\n // ── List the site's projects (Settings intake-source picker) ────────────\n routes.push(\n registerApiRoute('/web/jira/projects', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n\n try {\n const sources = await jira.intake.listSources(resolved.tenant);\n return c.json({\n projects: sources.map(source => ({\n id: source.id,\n name: source.name,\n key: typeof source.metadata?.key === 'string' ? source.metadata.key : null,\n connectionId: typeof source.metadata?.connectionId === 'string' ? source.metadata.connectionId : null,\n site: typeof source.metadata?.site === 'string' ? source.metadata.site : null,\n })),\n });\n } catch (err) {\n return jiraFetchError(loose(c), err);\n }\n },\n }),\n );\n\n // ── List the site's active issues (cursor-paged) ────────────────────────\n // Respects the caller's intake config: disabled Jira intake 404s the\n // source, and an explicit project selection narrows the issue filter.\n routes.push(\n registerApiRoute('/web/jira/issues', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n\n const after = parseAfterCursor(c.req.query('after'));\n if (after === null) return c.json({ error: 'invalid_cursor' }, 400);\n const factoryProjectId = c.req.query('factoryProjectId');\n if (factoryProjectId && !UUID_RE.test(factoryProjectId)) {\n return c.json({ error: 'invalid_factory_project_id' }, 400);\n }\n\n await intake.ensureReady();\n const config = await intake.getConfig({ orgId: resolved.tenant.orgId, integrationIds: ['jira'] });\n const selection = config.jira!;\n if (!selection.enabled) {\n return c.json({ error: 'jira_intake_disabled', message: 'Jira intake is turned off in Settings.' }, 404);\n }\n\n // No projects selected means nothing is synced — don't fan out to Jira.\n const selectedIds = selection.sourceIds ?? [];\n // A board request only ever sees the projects routed to a board of\n // that Factory project; unscoped listing stays available to callers\n // that don't view a specific board.\n const intakeBoards = factoryProjectId\n ? await scopeSourceIdsToProject({\n intake,\n orgId: resolved.tenant.orgId,\n factoryProjectId,\n selectedIds,\n })\n : null;\n const projectIds = intakeBoards ? Object.keys(intakeBoards) : selectedIds;\n if (projectIds.length === 0) {\n return c.json({ issues: [], nextCursor: null });\n }\n\n try {\n const { issues, nextCursor } = await jira.listActiveIssues(after, projectIds);\n const issuePayload = issues.map(issue => ({\n id: issue.externalId,\n identifier: issue.identifier,\n title: issue.title,\n url: issue.url,\n author: issue.author,\n state: issue.state ?? '',\n stateType: issue.stateType ?? '',\n priorityLabel: issue.priority ?? '',\n assignee: issue.assignee,\n project: issue.source,\n site: issue.site,\n labels: issue.labels,\n createdAt: issue.createdAt,\n updatedAt: issue.updatedAt,\n sourceId: issue.sourceId || null,\n }));\n if (factoryProjectId && intakeBoards && options.ingestFactoryIssues) {\n await options.ingestFactoryIssues({\n orgId: resolved.tenant.orgId,\n userId: resolved.tenant.userId,\n factoryProjectId,\n issues: issuePayload.map(issue => ({ ...issue, site: issue.site ?? null })),\n intakeBoards,\n });\n }\n return c.json({ issues: issuePayload, nextCursor });\n } catch (err) {\n return jiraFetchError(loose(c), err);\n }\n },\n }),\n );\n\n routes.push(\n registerApiRoute('/web/jira/issues/:identifier', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n\n const identifier = c.req.param('identifier');\n const factoryProjectId = c.req.query('factoryProjectId');\n const issueRef = c.req.query('issueRef');\n if (!ISSUE_KEY_RE.test(identifier)) return c.json({ error: 'invalid_issue_identifier' }, 400);\n if (!factoryProjectId || !UUID_RE.test(factoryProjectId)) {\n return c.json({ error: 'invalid_factory_project_id' }, 400);\n }\n if (!issueRef || issueRef.length > 2_048) return c.json({ error: 'invalid_issue_ref' }, 400);\n\n await intake.ensureReady();\n const config = await intake.getConfig({ orgId: resolved.tenant.orgId, integrationIds: ['jira'] });\n const selection = config.jira!;\n if (!selection.enabled) {\n return c.json({ error: 'jira_intake_disabled', message: 'Jira intake is turned off in Settings.' }, 404);\n }\n\n const intakeBoards = await scopeSourceIdsToProject({\n intake,\n orgId: resolved.tenant.orgId,\n factoryProjectId,\n selectedIds: selection.sourceIds ?? [],\n });\n const dispatch = await jira.intake.resolveIntakeDispatch?.({\n orgId: resolved.tenant.orgId,\n externalSource: { type: 'issue', externalId: issueRef },\n });\n if (!dispatch?.sourceId || !(dispatch.sourceId in intakeBoards)) {\n return c.json({ error: 'issue_not_found' }, 404);\n }\n\n try {\n const issue = await jira.intake.getIssue(dispatch);\n if (!issue || issue.identifier.toUpperCase() !== identifier.toUpperCase()) {\n return c.json({ error: 'issue_not_found' }, 404);\n }\n return c.json({\n identifier: issue.identifier,\n title: issue.title,\n url: issue.url,\n description: issue.description,\n });\n } catch (err) {\n return jiraFetchError(loose(c), err);\n }\n },\n }),\n );\n\n return routes;\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"surface.d.ts","sourceRoot":"","sources":["../../src/routes/surface.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"surface.d.ts","sourceRoot":"","sources":["../../src/routes/surface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAEtF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAG/E,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AACxE,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAC1E,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAQhF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACtF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6CAA6C,CAAC;AAC1F,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qCAAqC,CAAC;AACnF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AACtF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6CAA6C,CAAC;AAC1F,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAClF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4CAA4C,CAAC;AACxF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAClF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAClF,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,uCAAuC,CAAC;AAS/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAe5C,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,kBAAkB,CAAC;IAChC,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,eAAe,CAAC,eAAe,CAAC,CAAC;IAC7C,+FAA+F;IAC/F,YAAY,EAAE,YAAY,CAAC;IAC3B,qEAAqE;IACrE,IAAI,EAAE,SAAS,CAAC;IAChB,kFAAkF;IAClF,KAAK,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,SAAS,GAAG,UAAU,CAAC,CAAC;IACpD,WAAW,EAAE,WAAW,CAAC;IACzB,KAAK,EAAE,YAAY,GAAG,aAAa,CAAC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,qEAAqE;IACrE,OAAO,CAAC,EAAE,0BAA0B,CAAC;IACrC,4EAA4E;IAC5E,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,oBAAoB,EAAE,oBAAoB,CAAC;IAC3C,mFAAmF;IACnF,OAAO,EAAE;QACP,MAAM,EAAE,aAAa,CAAC;QACtB,gBAAgB,EAAE,uBAAuB,CAAC;QAC1C,cAAc,EAAE,qBAAqB,CAAC;QACtC,eAAe,EAAE,sBAAsB,CAAC;QACxC,UAAU,EAAE,iBAAiB,CAAC;QAC9B,UAAU,EAAE,iBAAiB,CAAC;QAC9B,QAAQ,EAAE,sBAAsB,CAAC;QACjC,WAAW,EAAE,kBAAkB,CAAC;QAChC,SAAS,EAAE,gBAAgB,CAAC;QAC5B,eAAe,EAAE,sBAAsB,CAAC;QACxC,QAAQ,EAAE,uBAAuB,CAAC;KACnC,CAAC;IACF,YAAY,CAAC,EAAE,uBAAuB,EAAE,CAAC;IACzC,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,OAAO,CAAC;IACtB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,8EAA8E;IAC9E,aAAa,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,aAAa,EAAE,aAAa,CAAC;IAC7B,oFAAoF;IACpF,IAAI,EAAE,cAAc,CAAC;IACrB,wBAAwB,CAAC,EAAE,wBAAwB,CAAC;IACpD,iBAAiB,CAAC,EAAE,OAAO,kCAAkC,EAAE,4BAA4B,CAAC;IAC5F,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE;QAC3B,iBAAiB,EAAE,wBAAwB,CAAC;QAC5C,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,8BAA8B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KAC3E,KAAK,IAAI,CAAC;CACZ;AAkFD;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,iBAAiB,EACzB,WAAW,EAAE,IAAI,CAAC,uBAAuB,EAAE,SAAS,CAAC,EACrD,QAAQ,EAAE,sBAAsB,EAChC,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,8BAA8B,GACpC,OAAO,CAAC,IAAI,CAAC,CA+Ef;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,IAAI,CACR,oBAAoB,EAClB,YAAY,GACZ,cAAc,GACd,MAAM,GACN,SAAS,GACT,OAAO,GACP,gBAAgB,GAChB,oBAAoB,GACpB,sBAAsB,CACzB,GAAG;IACF,WAAW,EAAE,WAAW,CAAC;IACzB,SAAS,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,aAAa,CAAC;IAC7B,YAAY,EAAE,OAAO,CAAC;IACtB,qFAAqF;IACrF,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,IAAI,CACX,oBAAoB,CAAC,SAAS,CAAC,EAC/B,UAAU,GAAG,QAAQ,GAAG,WAAW,GAAG,iBAAiB,GAAG,gBAAgB,CAC3E,CAAC;IACF;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,EACD,aAAa,EAAE,MAAM,GACpB,kBAAkB,CA4BpB;AAiGD;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,oBAAoB,GAAG,QAAQ,EAAE,CAwJ/E"}
@@ -197,9 +197,10 @@ function buildIntegrationContext(deps, integrationId) {
197
197
  }
198
198
  /**
199
199
  * Disabled-status stub for the well-known integration ids. The SPA polls
200
- * `/web/github/status` and `/web/linear/status` unconditionally, so when an
201
- * integration is absent (or not ready) the status contract must still hold.
202
- * Unknown custom ids get no stub — the SPA doesn't poll them.
200
+ * `/web/github/status`, `/web/linear/status`, and `/web/jira/status`
201
+ * unconditionally, so when an integration is absent (or not ready) the status
202
+ * contract must still hold. Unknown custom ids get no stub — the SPA doesn't
203
+ * poll them.
203
204
  */
204
205
  function disabledIntegrationStatusRoutes(deps, id, configured = false) {
205
206
  if (id === "github") return [registerApiRoute("/web/github/status", {
@@ -234,6 +235,21 @@ function disabledIntegrationStatusRoutes(deps, id, configured = false) {
234
235
  }
235
236
  })
236
237
  })];
238
+ if (id === "jira") return [registerApiRoute("/web/jira/status", {
239
+ method: "GET",
240
+ requiresAuth: false,
241
+ handler: (c) => c.json({
242
+ enabled: false,
243
+ configured,
244
+ site: null,
245
+ reason: "missing_config",
246
+ diagnostics: {
247
+ jiraConfigured: configured,
248
+ factoryAuthEnabled: deps.auth.enabled(),
249
+ appDbConfigured: deps.factoryStorage !== void 0
250
+ }
251
+ })
252
+ })];
237
253
  return [];
238
254
  }
239
255
  /**
@@ -286,7 +302,11 @@ function assembleFactoryApiRoutes(deps) {
286
302
  routes: integration.routes(context)
287
303
  });
288
304
  });
289
- const absentStubs = ["github", "linear"].filter((id) => !registrations.some(({ integration }) => integration.id === id)).flatMap((id) => disabledIntegrationStatusRoutes(deps, id));
305
+ const absentStubs = [
306
+ "github",
307
+ "linear",
308
+ "jira"
309
+ ].filter((id) => !registrations.some(({ integration }) => integration.id === id)).flatMap((id) => disabledIntegrationStatusRoutes(deps, id));
290
310
  const slackAbsentStubs = registrations.some(({ integration }) => integration.id === "slack") ? [] : absentSlackChannelAccountsRoutes();
291
311
  const transitionService = deps.factoryReady ? deps.factoryTransitionService ?? new FactoryTransitionService({
292
312
  configVersion: deps.configVersion,
@@ -1 +1 @@
1
- {"version":3,"file":"surface.js","names":[],"sources":["../../src/routes/surface.ts"],"sourcesContent":["import type { AuthStorage } from '@mastra/code-sdk/auth/storage';\nimport type { MastraCodeState } from '@mastra/code-sdk/schema';\nimport type { AgentController } from '@mastra/core/agent-controller';\nimport type { ApiRoute, IUserProvider } from '@mastra/core/server';\nimport { registerApiRoute } from '@mastra/core/server';\nimport type { FactoryStorage } from '@mastra/core/storage';\n\nimport { boardForWorkItem } from '../boards/index.js';\nimport type { BoardRegistry } from '../boards/index.js';\nimport type { FactoryIntegration, IntegrationContext } from '../integrations/base.js';\nimport { getGithubFeatureDiagnostics } from '../integrations/github/config.js';\nimport type { GithubIntegration } from '../integrations/github/integration.js';\nimport { MaterializeError } from '../integrations/github/sandbox.js';\nimport { FactoryDispatchError } from '../rules/dispatch-errors.js';\nimport type { FactoryBindingPreparationInput } from '../rules/dispatcher.js';\nimport { FactoryStartCoordinator } from '../rules/start-coordinator.js';\nimport { FactoryTransitionService } from '../rules/transition-service.js';\nimport type { MastraFactorySandboxConfig } from '../sandbox/session-sandbox.js';\nimport {\n ensureFactorySourceSession,\n FactorySourceSessionResolutionError,\n resolveFactoryDefaultModelId,\n resolveFactoryProjectForSession,\n} from '../session/factory-session.js';\nimport type { EnsuredFactorySourceSession } from '../session/factory-session.js';\nimport type { LiveSessions } from '../session/live-sessions.js';\nimport type { StateSigner } from '../state-signing.js';\nimport type { AuditEmitter, AuditRecorder } from '../storage/domains/audit/domain.js';\nimport type { ChannelIdentityStorage } from '../storage/domains/channel-identity/base.js';\nimport type { WorkItemCommentsStorage } from '../storage/domains/comments/base.js';\nimport type { CommentsDomain } from '../storage/domains/comments/domain.js';\nimport type { ModelCredentialsStorage } from '../storage/domains/credentials/base.js';\nimport type { CustomProvidersStorage } from '../storage/domains/custom-providers/base.js';\nimport type { FilesystemStorage } from '../storage/domains/filesystem/base.js';\nimport type { IntakeStorage } from '../storage/domains/intake/base.js';\nimport type { IntegrationStorage } from '../storage/domains/integrations/base.js';\nimport type { MemorySettingsStorage } from '../storage/domains/memory-settings/base.js';\nimport type { ModelPacksStorage } from '../storage/domains/model-packs/base.js';\nimport type { FactoryProjectsStorage } from '../storage/domains/projects/base.js';\nimport type { QueueHealthStorage } from '../storage/domains/queue-health/base.js';\nimport {\n SourceControlConnectionNotFoundError,\n type SourceControlStorage,\n} from '../storage/domains/source-control/base.js';\nimport {\n isAgentActor,\n type FactoryDispatchFailureCode,\n type WorkItemsStorage,\n} from '../storage/domains/work-items/base.js';\nimport { workItemBranch, workItemBranchSource, workItemThreadTitle } from '../work-item-branch.js';\nimport { buildAutomationRunRoutes } from './automation-runs.js';\nimport { ConfigRoutes } from './config.js';\nimport { invalidateCustomProvidersSnapshots } from './custom-provider-source.js';\nimport { buildFsRoutes } from './fs.js';\nimport { IntakeRoutes } from './intake.js';\nimport { KnowledgeRoutes } from './knowledge.js';\nimport { OAuthRoutes } from './oauth.js';\nimport type { RouteAuth } from './route.js';\nimport { SkillRoutes } from './skills.js';\nimport { invalidateTenantCredentialSnapshots } from './tenant-credentials.js';\nimport { WorkItemRoutes } from './work-items.js';\n\nconst MATERIALIZE_FAILURE_CODE = {\n 'git-missing': 'repository_git_missing',\n 'egress-blocked': 'repository_egress_blocked',\n 'clone-failed': 'repository_clone_failed',\n 'pull-failed': 'repository_pull_failed',\n 'push-failed': 'repository_push_failed',\n 'commit-failed': 'repository_commit_failed',\n 'gh-missing': 'repository_cli_missing',\n 'pr-failed': 'repository_pr_failed',\n} satisfies Record<MaterializeError['code'], FactoryDispatchFailureCode>;\nexport interface IntegrationRegistration {\n integration: FactoryIntegration;\n ready: boolean;\n ensureReady: () => Promise<void>;\n}\n\nexport interface FactoryApiRoutesDeps {\n controllerId: string;\n controller: AgentController<MastraCodeState>;\n /** Registry of the sessions this process holds, owned by the host so it can watch them too. */\n liveSessions: LiveSessions;\n /** Request-auth seam threaded from the host (no service locator). */\n auth: RouteAuth;\n /** Optional user directory for resolving persisted owners to display profiles. */\n users?: Pick<IUserProvider, 'getUser' | 'getUsers'>;\n authStorage: AuthStorage;\n audit: AuditEmitter & AuditRecorder;\n fsRoot?: string;\n publicOrigin: string;\n stateSigner?: StateSigner;\n /** Sandbox surface (enablement, provider label, create callback). */\n sandbox?: MastraFactorySandboxConfig;\n /** Root factory storage backend (distributed locks, app-db diagnostics). */\n factoryStorage?: FactoryStorage;\n integrationStorage: IntegrationStorage;\n sourceControlStorage: SourceControlStorage;\n /** App-table domain handles, registered and owned by `MastraFactory.prepare()`. */\n domains: {\n intake: IntakeStorage;\n modelCredentials: ModelCredentialsStorage;\n memorySettings: MemorySettingsStorage;\n customProviders: CustomProvidersStorage;\n filesystem: FilesystemStorage;\n modelPacks: ModelPacksStorage;\n projects: FactoryProjectsStorage;\n queueHealth: QueueHealthStorage;\n workItems: WorkItemsStorage;\n channelIdentity: ChannelIdentityStorage;\n comments: WorkItemCommentsStorage;\n };\n integrations?: IntegrationRegistration[];\n intakeReady: boolean;\n factoryReady: boolean;\n knowledgeEnabled: boolean;\n /** Resolved Factory rule set, threaded from the host (no service locator). */\n configVersion: string;\n /** Boards installed for this Factory instance. */\n boardRegistry: BoardRegistry;\n /** Work-item feed service, handed to integrations that ingest platform messages. */\n feed: CommentsDomain;\n factoryTransitionService?: FactoryTransitionService;\n sessionRetirement?: import('../sandbox/session-retirement.js').SessionRetirementCoordinator;\n onFactoryRuntime?: (runtime: {\n transitionService: FactoryTransitionService;\n prepareBinding?: (input: FactoryBindingPreparationInput) => Promise<void>;\n }) => void;\n}\n\nfunction guardIntegrationRoutes({\n integration,\n ready,\n ensureReady,\n routes,\n}: IntegrationRegistration & { routes: ApiRoute[] }): ApiRoute[] {\n if (ready) return routes;\n return routes.map(route => {\n if ('handler' in route) {\n const handler = route.handler;\n return {\n ...route,\n handler: async (context: Parameters<typeof handler>[0]) => {\n try {\n await ensureReady();\n } catch {\n return context.json(\n { error: 'integration_unavailable', message: `${integration.id} integration is unavailable.` },\n 503,\n );\n }\n return handler(context, async () => {});\n },\n };\n }\n\n const createHandler = route.createHandler;\n return {\n ...route,\n createHandler: async (args: Parameters<typeof createHandler>[0]) => {\n const handler = await createHandler(args);\n return async (context: Parameters<typeof handler>[0]) => {\n try {\n await ensureReady();\n } catch {\n return context.json(\n { error: 'integration_unavailable', message: `${integration.id} integration is unavailable.` },\n 503,\n );\n }\n return handler(context);\n };\n },\n };\n });\n}\n\n/**\n * Resolve the source-control session the work item already holds for this role,\n * when it still resolves to the item's org and factory project. Returns\n * `undefined` when there is no ref or the ref no longer resolves, so the caller\n * falls back to minting one.\n */\nasync function reuseBoundSession(\n sourceControl: GithubIntegration['sourceControlStorage'],\n input: FactoryBindingPreparationInput,\n): Promise<EnsuredFactorySourceSession | undefined> {\n const ref = input.item.sessions[input.role];\n if (!ref) return undefined;\n // At least as strict as the coordinator's resolveSourceSession: a ref it\n // would reject must fall through to minting, not hard-fail the run.\n const resolved = await resolveFactoryProjectForSession({ sourceControl, sessionId: ref.sessionId });\n if (\n !resolved ||\n resolved.orgId !== input.record.orgId ||\n resolved.factoryProjectId !== input.record.factoryProjectId\n ) {\n return undefined;\n }\n const session = await sourceControl.sessions.getBySessionId(ref.sessionId);\n if (!session) return undefined;\n return {\n sessionId: session.sessionId,\n userId: session.userId,\n projectRepositoryId: session.projectRepositoryId,\n branch: session.branch,\n baseBranch: session.baseBranch,\n };\n}\n\n/**\n * Start a factory run for a rule binding: ensure the source-control session the\n * coordinator requires, then hand it to `prepare` along with the factory's\n * default model. Exported for tests — this is the autonomous entry point with no\n * browser and no interactive user, so nothing else would catch a regression in\n * what it forwards.\n */\nexport async function prepareFactoryRuleBinding(\n github: GithubIntegration,\n coordinator: Pick<FactoryStartCoordinator, 'prepare'>,\n projects: FactoryProjectsStorage,\n boards: BoardRegistry,\n input: FactoryBindingPreparationInput,\n): Promise<void> {\n try {\n const source = workItemBranchSource(input.item.externalSource);\n const branch = workItemBranch({ id: input.item.id, source, metadata: input.item.metadata });\n // Only leaving a resting phase derives a lane from the role: roles don't own lanes,\n // and the Done close-out running in the triage seat must not drag the card back.\n // Both the current phase and the role's lane come from the installed board; an\n // unknown board or phase yields no destination rather than a guessed one.\n const board = boards.get(boardForWorkItem(input.item));\n const currentStage = input.item.stages.length === 1 ? input.item.stages[0] : undefined;\n const currentKind = currentStage === undefined ? undefined : board?.phaseKind(currentStage);\n const destinationStage =\n currentKind === undefined\n ? undefined\n : currentKind === 'resting'\n ? board?.phaseForRole(input.role)\n : currentStage;\n if (!destinationStage) {\n throw new FactoryDispatchError(\n 'unsupported_provider_item',\n `Factory skill invocation has no destination lane (role \"${input.role}\", stages [${input.item.stages.join(', ')}]).`,\n );\n }\n const repositorySlug =\n typeof input.item.metadata?.repository === 'string' ? input.item.metadata.repository : undefined;\n // Re-preparing a binding (server restart, retired controller session) must\n // land in the role's existing session: minting a replacement would repoint\n // the work item, flip the session's owner to the approver, and orphan the\n // previous sandbox.\n const approver = input.record.approvedBy ?? undefined;\n const preparedSession =\n (await reuseBoundSession(github.sourceControlStorage, input)) ??\n (await ensureFactorySourceSession({\n sourceControl: github.sourceControlStorage,\n orgId: input.record.orgId,\n factoryProjectId: input.record.factoryProjectId,\n repositorySlug,\n branch,\n // A person who approved the run is its interactive user: attribute it to\n // them, not the repo connector. An agent's pre-approval names no person.\n attributeToUserId: isAgentActor(approver) ? undefined : approver,\n }));\n\n await coordinator.prepare({\n orgId: input.record.orgId,\n userId: preparedSession.userId,\n factoryProjectId: input.record.factoryProjectId,\n sessionId: preparedSession.sessionId,\n defaultModelId: await resolveFactoryDefaultModelId(projects, input.record.factoryProjectId),\n threadTitle: workItemThreadTitle({ source, title: input.item.title, metadata: input.item.metadata }),\n kickoffKey: input.record.id,\n destinationStage,\n workItem: {\n id: input.item.id,\n role: input.role,\n input: {\n externalSource: input.item.externalSource,\n parentWorkItemId: input.item.parentWorkItemId,\n title: input.item.title,\n stages: ['intake'],\n sessions: input.item.sessions,\n metadata: input.item.metadata,\n },\n },\n });\n } catch (error) {\n if (error instanceof FactoryDispatchError) throw error;\n if (error instanceof FactorySourceSessionResolutionError) {\n const code = error.reason === 'connection' ? 'source_control_missing' : 'source_repository_missing';\n throw new FactoryDispatchError(code, error.message, { cause: error });\n }\n if (error instanceof SourceControlConnectionNotFoundError) {\n throw new FactoryDispatchError('source_control_missing', error.message, { cause: error });\n }\n if (error instanceof MaterializeError) {\n throw new FactoryDispatchError(MATERIALIZE_FAILURE_CODE[error.code], error.message, { cause: error });\n }\n throw error;\n }\n}\n\n/**\n * Build the {@link IntegrationContext} handed to an integration when the\n * factory collects its capabilities (routes, workers). One shape everywhere:\n * `assembleFactoryApiRoutes` uses it per registration, and `MastraFactory` uses it\n * when collecting integration workers at finalize.\n */\nexport function buildIntegrationContext(\n deps: Pick<\n FactoryApiRoutesDeps,\n | 'controller'\n | 'publicOrigin'\n | 'auth'\n | 'sandbox'\n | 'users'\n | 'factoryStorage'\n | 'integrationStorage'\n | 'sourceControlStorage'\n > & {\n stateSigner: StateSigner;\n emitAudit?: AuditEmitter['emit'];\n configVersion: string;\n boardRegistry: BoardRegistry;\n factoryReady: boolean;\n /** Work-item feed service, so a channel integration can ingest platform messages. */\n feed: CommentsDomain;\n domains: Pick<\n FactoryApiRoutesDeps['domains'],\n 'projects' | 'intake' | 'workItems' | 'channelIdentity' | 'memorySettings'\n >;\n /**\n * Stable id of the registered source-control-owning integration (today:\n * `'github'` when registered). Every call site must derive and pass it so\n * `routes()`, `channels()`, and `workers()` all see the same context shape.\n */\n sourceControlOwnerId?: string;\n },\n integrationId: string,\n): IntegrationContext {\n return {\n auth: deps.auth,\n sandbox: deps.sandbox,\n ...(deps.users ? { users: deps.users } : {}),\n factoryStorage: deps.factoryStorage,\n baseUrl: deps.publicOrigin,\n controller: deps.controller,\n stateSigner: deps.stateSigner,\n storage: {\n generic: deps.integrationStorage.forIntegration(integrationId),\n sourceControl: deps.sourceControlStorage.forIntegration(integrationId),\n ...(deps.sourceControlOwnerId\n ? { sourceControlOwner: deps.sourceControlStorage.forIntegration(deps.sourceControlOwnerId) }\n : {}),\n projects: deps.domains.projects,\n intake: deps.domains.intake,\n channelIdentity: deps.domains.channelIdentity,\n memorySettings: deps.domains.memorySettings,\n },\n ...(deps.factoryReady ? { workItems: deps.domains.workItems, feed: deps.feed } : {}),\n ...(deps.factoryReady\n ? {\n runtime: { configVersion: deps.configVersion, workItems: deps.domains.workItems, boards: deps.boardRegistry },\n }\n : {}),\n ...(deps.emitAudit ? { hooks: { emitAudit: deps.emitAudit } } : {}),\n };\n}\n\n/**\n * Disabled-status stub for the well-known integration ids. The SPA polls\n * `/web/github/status` and `/web/linear/status` unconditionally, so when an\n * integration is absent (or not ready) the status contract must still hold.\n * Unknown custom ids get no stub — the SPA doesn't poll them.\n */\nfunction disabledIntegrationStatusRoutes(deps: FactoryApiRoutesDeps, id: string, configured = false): ApiRoute[] {\n if (id === 'github') {\n return [\n registerApiRoute('/web/github/status', {\n method: 'GET',\n requiresAuth: false,\n handler: c =>\n c.json({\n enabled: false,\n connected: false,\n installations: [],\n reason: 'missing_config',\n diagnostics: getGithubFeatureDiagnostics({\n github: undefined,\n auth: deps.auth,\n appDbConfigured: deps.factoryStorage !== undefined,\n stateSigner: deps.stateSigner,\n sandbox: deps.sandbox,\n }),\n }),\n }),\n ];\n }\n if (id === 'linear') {\n return [\n registerApiRoute('/web/linear/status', {\n method: 'GET',\n requiresAuth: false,\n handler: c =>\n c.json({\n enabled: false,\n connected: false,\n workspace: null,\n reason: 'missing_config',\n diagnostics: {\n linearAppConfigured: configured,\n factoryAuthEnabled: deps.auth.enabled(),\n appDbConfigured: true,\n },\n }),\n }),\n ];\n }\n return [];\n}\n\n/**\n * Stub for `GET /web/channel-accounts` when NO Slack integration is\n * registered. The SPA's Connections section polls the path unconditionally;\n * without a stub the SPA fallback serves HTML, which the UI can only read as\n * \"old server / unknown\". The machine-readable reason lets it say the truth:\n * the integration isn't registered.\n *\n * Mounted only for ABSENT slack — a registered integration owns the path via\n * its connect routes (or, when the state signer is unstable, gets no routes\n * at all and the UI falls back to the generic copy). Static payload, leaks\n * nothing → no auth needed, same posture as the github/linear stubs.\n */\nfunction absentSlackChannelAccountsRoutes(): ApiRoute[] {\n return [\n registerApiRoute('/web/channel-accounts', {\n method: 'GET',\n requiresAuth: false,\n handler: c => c.json({ accounts: [], canConnect: false, reason: 'not_registered' }),\n }),\n ];\n}\n\n/**\n * Assemble the custom `/web/*` API routes as Mastra `server.apiRoutes`:\n * - fs browser routes (project picker), confined to `fsRoot`\n * - config routes (provider/API-key/model-pack/OM management)\n * - every registered integration's `routes()` surface (full set when ready,\n * disabled-status stub otherwise), plus stubs for absent known ids\n */\nexport function assembleFactoryApiRoutes(deps: FactoryApiRoutesDeps): ApiRoute[] {\n const emitAudit: AuditEmitter['emit'] = args => deps.audit.emit(args);\n const registrations = deps.integrations ?? [];\n const githubRegistration = registrations.find(({ integration }) => integration.id === 'github');\n const githubStorage = githubRegistration ? deps.sourceControlStorage.forIntegration('github') : undefined;\n const githubIntegration = githubRegistration?.integration as GithubIntegration | undefined;\n\n const integrationRoutes = registrations.flatMap(registration => {\n const { integration } = registration;\n if (!deps.stateSigner) return disabledIntegrationStatusRoutes(deps, integration.id, true);\n const context = buildIntegrationContext(\n {\n ...deps,\n stateSigner: deps.stateSigner,\n emitAudit,\n ...(githubRegistration ? { sourceControlOwnerId: 'github' } : {}),\n },\n integration.id,\n );\n return guardIntegrationRoutes({ ...registration, routes: integration.routes(context) });\n });\n // Absent known integrations still get their disabled-status stub.\n const absentStubs = ['github', 'linear']\n .filter(id => !registrations.some(({ integration }) => integration.id === id))\n .flatMap(id => disabledIntegrationStatusRoutes(deps, id));\n // Absent slack gets the channel-accounts not-registered stub (registered\n // slack owns the path via its own connect routes).\n const slackAbsentStubs = registrations.some(({ integration }) => integration.id === 'slack')\n ? []\n : absentSlackChannelAccountsRoutes();\n\n const transitionService = deps.factoryReady\n ? (deps.factoryTransitionService ??\n new FactoryTransitionService({\n configVersion: deps.configVersion,\n boards: deps.boardRegistry,\n storage: deps.domains.workItems,\n audit: deps.audit,\n }))\n : undefined;\n const startCoordinator = transitionService\n ? new FactoryStartCoordinator(\n deps.controller,\n deps.domains.workItems,\n transitionService,\n githubIntegration?.sourceControlStorage,\n deps.domains.memorySettings,\n )\n : undefined;\n if (transitionService && startCoordinator) {\n deps.onFactoryRuntime?.({\n transitionService,\n ...(githubIntegration\n ? {\n prepareBinding: (input: FactoryBindingPreparationInput) =>\n prepareFactoryRuleBinding(\n githubIntegration,\n startCoordinator,\n deps.domains.projects,\n deps.boardRegistry,\n input,\n ),\n }\n : {}),\n });\n }\n\n return [\n ...buildFsRoutes({\n root: deps.fsRoot,\n sessionFs: {\n auth: deps.auth,\n sessions: deps.sourceControlStorage.forIntegration('github').sessions,\n filesystem: deps.domains.filesystem,\n },\n }),\n ...new ConfigRoutes({\n auth: deps.auth,\n controller: deps.controller,\n authStorage: deps.authStorage,\n modelCredentials: deps.domains.modelCredentials,\n modelPacks: deps.domains.modelPacks,\n sourceControlSessions: deps.sourceControlStorage.forIntegration('github').sessions,\n memorySettings: deps.domains.memorySettings,\n factoryProjects: deps.domains.projects,\n customProviders: deps.domains.customProviders,\n features: { knowledge: deps.knowledgeEnabled },\n onCredentialsChanged: invalidateTenantCredentialSnapshots,\n onCustomProvidersChanged: invalidateCustomProvidersSnapshots,\n }).routes(),\n ...new OAuthRoutes({\n auth: deps.auth,\n authStorage: deps.authStorage,\n modelCredentials: deps.domains.modelCredentials,\n memorySettings: deps.domains.memorySettings,\n onCredentialsChanged: invalidateTenantCredentialSnapshots,\n }).routes(),\n ...new SkillRoutes({\n auth: deps.auth,\n controllerId: deps.controllerId,\n controller: deps.controller,\n sourceControlStorage: githubStorage,\n ensureSourceControlReady: githubRegistration?.ensureReady,\n }).routes(),\n ...integrationRoutes,\n ...absentStubs,\n ...slackAbsentStubs,\n ...(deps.intakeReady\n ? new IntakeRoutes({\n auth: deps.auth,\n audit: deps.audit,\n intake: deps.domains.intake,\n projects: deps.domains.projects,\n boardRegistry: deps.boardRegistry,\n // Relocation reads and writes work items, which init fail-soft separately from intake.\n ...(deps.factoryReady ? { workItems: deps.domains.workItems } : {}),\n integrations: (deps.integrations ?? []).flatMap(({ integration }) =>\n integration.intake ? [{ id: integration.id, intake: integration.intake }] : [],\n ),\n }).routes()\n : []),\n ...(deps.factoryReady && deps.knowledgeEnabled\n ? new KnowledgeRoutes({\n auth: deps.auth,\n projects: deps.domains.projects,\n knowledge: async () => deps.factoryStorage?.getMastraStorage().getStore('knowledge'),\n }).routes()\n : []),\n ...(deps.factoryReady\n ? new WorkItemRoutes({\n auth: deps.auth,\n audit: deps.audit,\n projects: deps.domains.projects,\n workItems: deps.domains.workItems,\n boardRegistry: deps.boardRegistry,\n comments: deps.domains.comments,\n queueHealth: deps.domains.queueHealth,\n transitionService,\n startCoordinator,\n liveSessions: deps.liveSessions,\n }).routes()\n : []),\n ...(deps.factoryReady\n ? buildAutomationRunRoutes({\n auth: deps.auth,\n audit: deps.audit,\n projects: deps.domains.projects,\n workItems: deps.domains.workItems,\n configVersion: deps.configVersion,\n })\n : []),\n ];\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"surface.js","names":[],"sources":["../../src/routes/surface.ts"],"sourcesContent":["import type { AuthStorage } from '@mastra/code-sdk/auth/storage';\nimport type { MastraCodeState } from '@mastra/code-sdk/schema';\nimport type { AgentController } from '@mastra/core/agent-controller';\nimport type { ApiRoute, IUserProvider } from '@mastra/core/server';\nimport { registerApiRoute } from '@mastra/core/server';\nimport type { FactoryStorage } from '@mastra/core/storage';\n\nimport { boardForWorkItem } from '../boards/index.js';\nimport type { BoardRegistry } from '../boards/index.js';\nimport type { FactoryIntegration, IntegrationContext } from '../integrations/base.js';\nimport { getGithubFeatureDiagnostics } from '../integrations/github/config.js';\nimport type { GithubIntegration } from '../integrations/github/integration.js';\nimport { MaterializeError } from '../integrations/github/sandbox.js';\nimport { FactoryDispatchError } from '../rules/dispatch-errors.js';\nimport type { FactoryBindingPreparationInput } from '../rules/dispatcher.js';\nimport { FactoryStartCoordinator } from '../rules/start-coordinator.js';\nimport { FactoryTransitionService } from '../rules/transition-service.js';\nimport type { MastraFactorySandboxConfig } from '../sandbox/session-sandbox.js';\nimport {\n ensureFactorySourceSession,\n FactorySourceSessionResolutionError,\n resolveFactoryDefaultModelId,\n resolveFactoryProjectForSession,\n} from '../session/factory-session.js';\nimport type { EnsuredFactorySourceSession } from '../session/factory-session.js';\nimport type { LiveSessions } from '../session/live-sessions.js';\nimport type { StateSigner } from '../state-signing.js';\nimport type { AuditEmitter, AuditRecorder } from '../storage/domains/audit/domain.js';\nimport type { ChannelIdentityStorage } from '../storage/domains/channel-identity/base.js';\nimport type { WorkItemCommentsStorage } from '../storage/domains/comments/base.js';\nimport type { CommentsDomain } from '../storage/domains/comments/domain.js';\nimport type { ModelCredentialsStorage } from '../storage/domains/credentials/base.js';\nimport type { CustomProvidersStorage } from '../storage/domains/custom-providers/base.js';\nimport type { FilesystemStorage } from '../storage/domains/filesystem/base.js';\nimport type { IntakeStorage } from '../storage/domains/intake/base.js';\nimport type { IntegrationStorage } from '../storage/domains/integrations/base.js';\nimport type { MemorySettingsStorage } from '../storage/domains/memory-settings/base.js';\nimport type { ModelPacksStorage } from '../storage/domains/model-packs/base.js';\nimport type { FactoryProjectsStorage } from '../storage/domains/projects/base.js';\nimport type { QueueHealthStorage } from '../storage/domains/queue-health/base.js';\nimport {\n SourceControlConnectionNotFoundError,\n type SourceControlStorage,\n} from '../storage/domains/source-control/base.js';\nimport {\n isAgentActor,\n type FactoryDispatchFailureCode,\n type WorkItemsStorage,\n} from '../storage/domains/work-items/base.js';\nimport { workItemBranch, workItemBranchSource, workItemThreadTitle } from '../work-item-branch.js';\nimport { buildAutomationRunRoutes } from './automation-runs.js';\nimport { ConfigRoutes } from './config.js';\nimport { invalidateCustomProvidersSnapshots } from './custom-provider-source.js';\nimport { buildFsRoutes } from './fs.js';\nimport { IntakeRoutes } from './intake.js';\nimport { KnowledgeRoutes } from './knowledge.js';\nimport { OAuthRoutes } from './oauth.js';\nimport type { RouteAuth } from './route.js';\nimport { SkillRoutes } from './skills.js';\nimport { invalidateTenantCredentialSnapshots } from './tenant-credentials.js';\nimport { WorkItemRoutes } from './work-items.js';\n\nconst MATERIALIZE_FAILURE_CODE = {\n 'git-missing': 'repository_git_missing',\n 'egress-blocked': 'repository_egress_blocked',\n 'clone-failed': 'repository_clone_failed',\n 'pull-failed': 'repository_pull_failed',\n 'push-failed': 'repository_push_failed',\n 'commit-failed': 'repository_commit_failed',\n 'gh-missing': 'repository_cli_missing',\n 'pr-failed': 'repository_pr_failed',\n} satisfies Record<MaterializeError['code'], FactoryDispatchFailureCode>;\nexport interface IntegrationRegistration {\n integration: FactoryIntegration;\n ready: boolean;\n ensureReady: () => Promise<void>;\n}\n\nexport interface FactoryApiRoutesDeps {\n controllerId: string;\n controller: AgentController<MastraCodeState>;\n /** Registry of the sessions this process holds, owned by the host so it can watch them too. */\n liveSessions: LiveSessions;\n /** Request-auth seam threaded from the host (no service locator). */\n auth: RouteAuth;\n /** Optional user directory for resolving persisted owners to display profiles. */\n users?: Pick<IUserProvider, 'getUser' | 'getUsers'>;\n authStorage: AuthStorage;\n audit: AuditEmitter & AuditRecorder;\n fsRoot?: string;\n publicOrigin: string;\n stateSigner?: StateSigner;\n /** Sandbox surface (enablement, provider label, create callback). */\n sandbox?: MastraFactorySandboxConfig;\n /** Root factory storage backend (distributed locks, app-db diagnostics). */\n factoryStorage?: FactoryStorage;\n integrationStorage: IntegrationStorage;\n sourceControlStorage: SourceControlStorage;\n /** App-table domain handles, registered and owned by `MastraFactory.prepare()`. */\n domains: {\n intake: IntakeStorage;\n modelCredentials: ModelCredentialsStorage;\n memorySettings: MemorySettingsStorage;\n customProviders: CustomProvidersStorage;\n filesystem: FilesystemStorage;\n modelPacks: ModelPacksStorage;\n projects: FactoryProjectsStorage;\n queueHealth: QueueHealthStorage;\n workItems: WorkItemsStorage;\n channelIdentity: ChannelIdentityStorage;\n comments: WorkItemCommentsStorage;\n };\n integrations?: IntegrationRegistration[];\n intakeReady: boolean;\n factoryReady: boolean;\n knowledgeEnabled: boolean;\n /** Resolved Factory rule set, threaded from the host (no service locator). */\n configVersion: string;\n /** Boards installed for this Factory instance. */\n boardRegistry: BoardRegistry;\n /** Work-item feed service, handed to integrations that ingest platform messages. */\n feed: CommentsDomain;\n factoryTransitionService?: FactoryTransitionService;\n sessionRetirement?: import('../sandbox/session-retirement.js').SessionRetirementCoordinator;\n onFactoryRuntime?: (runtime: {\n transitionService: FactoryTransitionService;\n prepareBinding?: (input: FactoryBindingPreparationInput) => Promise<void>;\n }) => void;\n}\n\nfunction guardIntegrationRoutes({\n integration,\n ready,\n ensureReady,\n routes,\n}: IntegrationRegistration & { routes: ApiRoute[] }): ApiRoute[] {\n if (ready) return routes;\n return routes.map(route => {\n if ('handler' in route) {\n const handler = route.handler;\n return {\n ...route,\n handler: async (context: Parameters<typeof handler>[0]) => {\n try {\n await ensureReady();\n } catch {\n return context.json(\n { error: 'integration_unavailable', message: `${integration.id} integration is unavailable.` },\n 503,\n );\n }\n return handler(context, async () => {});\n },\n };\n }\n\n const createHandler = route.createHandler;\n return {\n ...route,\n createHandler: async (args: Parameters<typeof createHandler>[0]) => {\n const handler = await createHandler(args);\n return async (context: Parameters<typeof handler>[0]) => {\n try {\n await ensureReady();\n } catch {\n return context.json(\n { error: 'integration_unavailable', message: `${integration.id} integration is unavailable.` },\n 503,\n );\n }\n return handler(context);\n };\n },\n };\n });\n}\n\n/**\n * Resolve the source-control session the work item already holds for this role,\n * when it still resolves to the item's org and factory project. Returns\n * `undefined` when there is no ref or the ref no longer resolves, so the caller\n * falls back to minting one.\n */\nasync function reuseBoundSession(\n sourceControl: GithubIntegration['sourceControlStorage'],\n input: FactoryBindingPreparationInput,\n): Promise<EnsuredFactorySourceSession | undefined> {\n const ref = input.item.sessions[input.role];\n if (!ref) return undefined;\n // At least as strict as the coordinator's resolveSourceSession: a ref it\n // would reject must fall through to minting, not hard-fail the run.\n const resolved = await resolveFactoryProjectForSession({ sourceControl, sessionId: ref.sessionId });\n if (\n !resolved ||\n resolved.orgId !== input.record.orgId ||\n resolved.factoryProjectId !== input.record.factoryProjectId\n ) {\n return undefined;\n }\n const session = await sourceControl.sessions.getBySessionId(ref.sessionId);\n if (!session) return undefined;\n return {\n sessionId: session.sessionId,\n userId: session.userId,\n projectRepositoryId: session.projectRepositoryId,\n branch: session.branch,\n baseBranch: session.baseBranch,\n };\n}\n\n/**\n * Start a factory run for a rule binding: ensure the source-control session the\n * coordinator requires, then hand it to `prepare` along with the factory's\n * default model. Exported for tests — this is the autonomous entry point with no\n * browser and no interactive user, so nothing else would catch a regression in\n * what it forwards.\n */\nexport async function prepareFactoryRuleBinding(\n github: GithubIntegration,\n coordinator: Pick<FactoryStartCoordinator, 'prepare'>,\n projects: FactoryProjectsStorage,\n boards: BoardRegistry,\n input: FactoryBindingPreparationInput,\n): Promise<void> {\n try {\n const source = workItemBranchSource(input.item.externalSource);\n const branch = workItemBranch({ id: input.item.id, source, metadata: input.item.metadata });\n // Only leaving a resting phase derives a lane from the role: roles don't own lanes,\n // and the Done close-out running in the triage seat must not drag the card back.\n // Both the current phase and the role's lane come from the installed board; an\n // unknown board or phase yields no destination rather than a guessed one.\n const board = boards.get(boardForWorkItem(input.item));\n const currentStage = input.item.stages.length === 1 ? input.item.stages[0] : undefined;\n const currentKind = currentStage === undefined ? undefined : board?.phaseKind(currentStage);\n const destinationStage =\n currentKind === undefined\n ? undefined\n : currentKind === 'resting'\n ? board?.phaseForRole(input.role)\n : currentStage;\n if (!destinationStage) {\n throw new FactoryDispatchError(\n 'unsupported_provider_item',\n `Factory skill invocation has no destination lane (role \"${input.role}\", stages [${input.item.stages.join(', ')}]).`,\n );\n }\n const repositorySlug =\n typeof input.item.metadata?.repository === 'string' ? input.item.metadata.repository : undefined;\n // Re-preparing a binding (server restart, retired controller session) must\n // land in the role's existing session: minting a replacement would repoint\n // the work item, flip the session's owner to the approver, and orphan the\n // previous sandbox.\n const approver = input.record.approvedBy ?? undefined;\n const preparedSession =\n (await reuseBoundSession(github.sourceControlStorage, input)) ??\n (await ensureFactorySourceSession({\n sourceControl: github.sourceControlStorage,\n orgId: input.record.orgId,\n factoryProjectId: input.record.factoryProjectId,\n repositorySlug,\n branch,\n // A person who approved the run is its interactive user: attribute it to\n // them, not the repo connector. An agent's pre-approval names no person.\n attributeToUserId: isAgentActor(approver) ? undefined : approver,\n }));\n\n await coordinator.prepare({\n orgId: input.record.orgId,\n userId: preparedSession.userId,\n factoryProjectId: input.record.factoryProjectId,\n sessionId: preparedSession.sessionId,\n defaultModelId: await resolveFactoryDefaultModelId(projects, input.record.factoryProjectId),\n threadTitle: workItemThreadTitle({ source, title: input.item.title, metadata: input.item.metadata }),\n kickoffKey: input.record.id,\n destinationStage,\n workItem: {\n id: input.item.id,\n role: input.role,\n input: {\n externalSource: input.item.externalSource,\n parentWorkItemId: input.item.parentWorkItemId,\n title: input.item.title,\n stages: ['intake'],\n sessions: input.item.sessions,\n metadata: input.item.metadata,\n },\n },\n });\n } catch (error) {\n if (error instanceof FactoryDispatchError) throw error;\n if (error instanceof FactorySourceSessionResolutionError) {\n const code = error.reason === 'connection' ? 'source_control_missing' : 'source_repository_missing';\n throw new FactoryDispatchError(code, error.message, { cause: error });\n }\n if (error instanceof SourceControlConnectionNotFoundError) {\n throw new FactoryDispatchError('source_control_missing', error.message, { cause: error });\n }\n if (error instanceof MaterializeError) {\n throw new FactoryDispatchError(MATERIALIZE_FAILURE_CODE[error.code], error.message, { cause: error });\n }\n throw error;\n }\n}\n\n/**\n * Build the {@link IntegrationContext} handed to an integration when the\n * factory collects its capabilities (routes, workers). One shape everywhere:\n * `assembleFactoryApiRoutes` uses it per registration, and `MastraFactory` uses it\n * when collecting integration workers at finalize.\n */\nexport function buildIntegrationContext(\n deps: Pick<\n FactoryApiRoutesDeps,\n | 'controller'\n | 'publicOrigin'\n | 'auth'\n | 'sandbox'\n | 'users'\n | 'factoryStorage'\n | 'integrationStorage'\n | 'sourceControlStorage'\n > & {\n stateSigner: StateSigner;\n emitAudit?: AuditEmitter['emit'];\n configVersion: string;\n boardRegistry: BoardRegistry;\n factoryReady: boolean;\n /** Work-item feed service, so a channel integration can ingest platform messages. */\n feed: CommentsDomain;\n domains: Pick<\n FactoryApiRoutesDeps['domains'],\n 'projects' | 'intake' | 'workItems' | 'channelIdentity' | 'memorySettings'\n >;\n /**\n * Stable id of the registered source-control-owning integration (today:\n * `'github'` when registered). Every call site must derive and pass it so\n * `routes()`, `channels()`, and `workers()` all see the same context shape.\n */\n sourceControlOwnerId?: string;\n },\n integrationId: string,\n): IntegrationContext {\n return {\n auth: deps.auth,\n sandbox: deps.sandbox,\n ...(deps.users ? { users: deps.users } : {}),\n factoryStorage: deps.factoryStorage,\n baseUrl: deps.publicOrigin,\n controller: deps.controller,\n stateSigner: deps.stateSigner,\n storage: {\n generic: deps.integrationStorage.forIntegration(integrationId),\n sourceControl: deps.sourceControlStorage.forIntegration(integrationId),\n ...(deps.sourceControlOwnerId\n ? { sourceControlOwner: deps.sourceControlStorage.forIntegration(deps.sourceControlOwnerId) }\n : {}),\n projects: deps.domains.projects,\n intake: deps.domains.intake,\n channelIdentity: deps.domains.channelIdentity,\n memorySettings: deps.domains.memorySettings,\n },\n ...(deps.factoryReady ? { workItems: deps.domains.workItems, feed: deps.feed } : {}),\n ...(deps.factoryReady\n ? {\n runtime: { configVersion: deps.configVersion, workItems: deps.domains.workItems, boards: deps.boardRegistry },\n }\n : {}),\n ...(deps.emitAudit ? { hooks: { emitAudit: deps.emitAudit } } : {}),\n };\n}\n\n/**\n * Disabled-status stub for the well-known integration ids. The SPA polls\n * `/web/github/status`, `/web/linear/status`, and `/web/jira/status`\n * unconditionally, so when an integration is absent (or not ready) the status\n * contract must still hold. Unknown custom ids get no stub — the SPA doesn't\n * poll them.\n */\nfunction disabledIntegrationStatusRoutes(deps: FactoryApiRoutesDeps, id: string, configured = false): ApiRoute[] {\n if (id === 'github') {\n return [\n registerApiRoute('/web/github/status', {\n method: 'GET',\n requiresAuth: false,\n handler: c =>\n c.json({\n enabled: false,\n connected: false,\n installations: [],\n reason: 'missing_config',\n diagnostics: getGithubFeatureDiagnostics({\n github: undefined,\n auth: deps.auth,\n appDbConfigured: deps.factoryStorage !== undefined,\n stateSigner: deps.stateSigner,\n sandbox: deps.sandbox,\n }),\n }),\n }),\n ];\n }\n if (id === 'linear') {\n return [\n registerApiRoute('/web/linear/status', {\n method: 'GET',\n requiresAuth: false,\n handler: c =>\n c.json({\n enabled: false,\n connected: false,\n workspace: null,\n reason: 'missing_config',\n diagnostics: {\n linearAppConfigured: configured,\n factoryAuthEnabled: deps.auth.enabled(),\n appDbConfigured: true,\n },\n }),\n }),\n ];\n }\n if (id === 'jira') {\n return [\n registerApiRoute('/web/jira/status', {\n method: 'GET',\n requiresAuth: false,\n handler: c =>\n c.json({\n enabled: false,\n configured,\n site: null,\n reason: 'missing_config',\n diagnostics: {\n jiraConfigured: configured,\n factoryAuthEnabled: deps.auth.enabled(),\n appDbConfigured: deps.factoryStorage !== undefined,\n },\n }),\n }),\n ];\n }\n return [];\n}\n\n/**\n * Stub for `GET /web/channel-accounts` when NO Slack integration is\n * registered. The SPA's Connections section polls the path unconditionally;\n * without a stub the SPA fallback serves HTML, which the UI can only read as\n * \"old server / unknown\". The machine-readable reason lets it say the truth:\n * the integration isn't registered.\n *\n * Mounted only for ABSENT slack — a registered integration owns the path via\n * its connect routes (or, when the state signer is unstable, gets no routes\n * at all and the UI falls back to the generic copy). Static payload, leaks\n * nothing → no auth needed, same posture as the github/linear stubs.\n */\nfunction absentSlackChannelAccountsRoutes(): ApiRoute[] {\n return [\n registerApiRoute('/web/channel-accounts', {\n method: 'GET',\n requiresAuth: false,\n handler: c => c.json({ accounts: [], canConnect: false, reason: 'not_registered' }),\n }),\n ];\n}\n\n/**\n * Assemble the custom `/web/*` API routes as Mastra `server.apiRoutes`:\n * - fs browser routes (project picker), confined to `fsRoot`\n * - config routes (provider/API-key/model-pack/OM management)\n * - every registered integration's `routes()` surface (full set when ready,\n * disabled-status stub otherwise), plus stubs for absent known ids\n */\nexport function assembleFactoryApiRoutes(deps: FactoryApiRoutesDeps): ApiRoute[] {\n const emitAudit: AuditEmitter['emit'] = args => deps.audit.emit(args);\n const registrations = deps.integrations ?? [];\n const githubRegistration = registrations.find(({ integration }) => integration.id === 'github');\n const githubStorage = githubRegistration ? deps.sourceControlStorage.forIntegration('github') : undefined;\n const githubIntegration = githubRegistration?.integration as GithubIntegration | undefined;\n\n const integrationRoutes = registrations.flatMap(registration => {\n const { integration } = registration;\n if (!deps.stateSigner) return disabledIntegrationStatusRoutes(deps, integration.id, true);\n const context = buildIntegrationContext(\n {\n ...deps,\n stateSigner: deps.stateSigner,\n emitAudit,\n ...(githubRegistration ? { sourceControlOwnerId: 'github' } : {}),\n },\n integration.id,\n );\n return guardIntegrationRoutes({ ...registration, routes: integration.routes(context) });\n });\n // Absent known integrations still get their disabled-status stub.\n const absentStubs = ['github', 'linear', 'jira']\n .filter(id => !registrations.some(({ integration }) => integration.id === id))\n .flatMap(id => disabledIntegrationStatusRoutes(deps, id));\n // Absent slack gets the channel-accounts not-registered stub (registered\n // slack owns the path via its own connect routes).\n const slackAbsentStubs = registrations.some(({ integration }) => integration.id === 'slack')\n ? []\n : absentSlackChannelAccountsRoutes();\n\n const transitionService = deps.factoryReady\n ? (deps.factoryTransitionService ??\n new FactoryTransitionService({\n configVersion: deps.configVersion,\n boards: deps.boardRegistry,\n storage: deps.domains.workItems,\n audit: deps.audit,\n }))\n : undefined;\n const startCoordinator = transitionService\n ? new FactoryStartCoordinator(\n deps.controller,\n deps.domains.workItems,\n transitionService,\n githubIntegration?.sourceControlStorage,\n deps.domains.memorySettings,\n )\n : undefined;\n if (transitionService && startCoordinator) {\n deps.onFactoryRuntime?.({\n transitionService,\n ...(githubIntegration\n ? {\n prepareBinding: (input: FactoryBindingPreparationInput) =>\n prepareFactoryRuleBinding(\n githubIntegration,\n startCoordinator,\n deps.domains.projects,\n deps.boardRegistry,\n input,\n ),\n }\n : {}),\n });\n }\n\n return [\n ...buildFsRoutes({\n root: deps.fsRoot,\n sessionFs: {\n auth: deps.auth,\n sessions: deps.sourceControlStorage.forIntegration('github').sessions,\n filesystem: deps.domains.filesystem,\n },\n }),\n ...new ConfigRoutes({\n auth: deps.auth,\n controller: deps.controller,\n authStorage: deps.authStorage,\n modelCredentials: deps.domains.modelCredentials,\n modelPacks: deps.domains.modelPacks,\n sourceControlSessions: deps.sourceControlStorage.forIntegration('github').sessions,\n memorySettings: deps.domains.memorySettings,\n factoryProjects: deps.domains.projects,\n customProviders: deps.domains.customProviders,\n features: { knowledge: deps.knowledgeEnabled },\n onCredentialsChanged: invalidateTenantCredentialSnapshots,\n onCustomProvidersChanged: invalidateCustomProvidersSnapshots,\n }).routes(),\n ...new OAuthRoutes({\n auth: deps.auth,\n authStorage: deps.authStorage,\n modelCredentials: deps.domains.modelCredentials,\n memorySettings: deps.domains.memorySettings,\n onCredentialsChanged: invalidateTenantCredentialSnapshots,\n }).routes(),\n ...new SkillRoutes({\n auth: deps.auth,\n controllerId: deps.controllerId,\n controller: deps.controller,\n sourceControlStorage: githubStorage,\n ensureSourceControlReady: githubRegistration?.ensureReady,\n }).routes(),\n ...integrationRoutes,\n ...absentStubs,\n ...slackAbsentStubs,\n ...(deps.intakeReady\n ? new IntakeRoutes({\n auth: deps.auth,\n audit: deps.audit,\n intake: deps.domains.intake,\n projects: deps.domains.projects,\n boardRegistry: deps.boardRegistry,\n // Relocation reads and writes work items, which init fail-soft separately from intake.\n ...(deps.factoryReady ? { workItems: deps.domains.workItems } : {}),\n integrations: (deps.integrations ?? []).flatMap(({ integration }) =>\n integration.intake ? [{ id: integration.id, intake: integration.intake }] : [],\n ),\n }).routes()\n : []),\n ...(deps.factoryReady && deps.knowledgeEnabled\n ? new KnowledgeRoutes({\n auth: deps.auth,\n projects: deps.domains.projects,\n knowledge: async () => deps.factoryStorage?.getMastraStorage().getStore('knowledge'),\n }).routes()\n : []),\n ...(deps.factoryReady\n ? new WorkItemRoutes({\n auth: deps.auth,\n audit: deps.audit,\n projects: deps.domains.projects,\n workItems: deps.domains.workItems,\n boardRegistry: deps.boardRegistry,\n comments: deps.domains.comments,\n queueHealth: deps.domains.queueHealth,\n transitionService,\n startCoordinator,\n liveSessions: deps.liveSessions,\n }).routes()\n : []),\n ...(deps.factoryReady\n ? buildAutomationRunRoutes({\n auth: deps.auth,\n audit: deps.audit,\n projects: deps.domains.projects,\n workItems: deps.domains.workItems,\n configVersion: deps.configVersion,\n })\n : []),\n ];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA8DA,MAAM,2BAA2B;CAC/B,eAAe;CACf,kBAAkB;CAClB,gBAAgB;CAChB,eAAe;CACf,eAAe;CACf,iBAAiB;CACjB,cAAc;CACd,aAAa;AACf;AA2DA,SAAS,uBAAuB,EAC9B,aACA,OACA,aACA,UAC+D;CAC/D,IAAI,OAAO,OAAO;CAClB,OAAO,OAAO,KAAI,UAAS;EACzB,IAAI,aAAa,OAAO;GACtB,MAAM,UAAU,MAAM;GACtB,OAAO;IACL,GAAG;IACH,SAAS,OAAO,YAA2C;KACzD,IAAI;MACF,MAAM,YAAY;KACpB,QAAQ;MACN,OAAO,QAAQ,KACb;OAAE,OAAO;OAA2B,SAAS,GAAG,YAAY,GAAG;MAA8B,GAC7F,GACF;KACF;KACA,OAAO,QAAQ,SAAS,YAAY,CAAC,CAAC;IACxC;GACF;EACF;EAEA,MAAM,gBAAgB,MAAM;EAC5B,OAAO;GACL,GAAG;GACH,eAAe,OAAO,SAA8C;IAClE,MAAM,UAAU,MAAM,cAAc,IAAI;IACxC,OAAO,OAAO,YAA2C;KACvD,IAAI;MACF,MAAM,YAAY;KACpB,QAAQ;MACN,OAAO,QAAQ,KACb;OAAE,OAAO;OAA2B,SAAS,GAAG,YAAY,GAAG;MAA8B,GAC7F,GACF;KACF;KACA,OAAO,QAAQ,OAAO;IACxB;GACF;EACF;CACF,CAAC;AACH;;;;;;;AAQA,eAAe,kBACb,eACA,OACkD;CAClD,MAAM,MAAM,MAAM,KAAK,SAAS,MAAM;CACtC,IAAI,CAAC,KAAK,OAAO,KAAA;CAGjB,MAAM,WAAW,MAAM,gCAAgC;EAAE;EAAe,WAAW,IAAI;CAAU,CAAC;CAClG,IACE,CAAC,YACD,SAAS,UAAU,MAAM,OAAO,SAChC,SAAS,qBAAqB,MAAM,OAAO,kBAE3C;CAEF,MAAM,UAAU,MAAM,cAAc,SAAS,eAAe,IAAI,SAAS;CACzE,IAAI,CAAC,SAAS,OAAO,KAAA;CACrB,OAAO;EACL,WAAW,QAAQ;EACnB,QAAQ,QAAQ;EAChB,qBAAqB,QAAQ;EAC7B,QAAQ,QAAQ;EAChB,YAAY,QAAQ;CACtB;AACF;;;;;;;;AASA,eAAsB,0BACpB,QACA,aACA,UACA,QACA,OACe;CACf,IAAI;EACF,MAAM,SAAS,qBAAqB,MAAM,KAAK,cAAc;EAC7D,MAAM,SAAS,eAAe;GAAE,IAAI,MAAM,KAAK;GAAI;GAAQ,UAAU,MAAM,KAAK;EAAS,CAAC;EAK1F,MAAM,QAAQ,OAAO,IAAI,iBAAiB,MAAM,IAAI,CAAC;EACrD,MAAM,eAAe,MAAM,KAAK,OAAO,WAAW,IAAI,MAAM,KAAK,OAAO,KAAK,KAAA;EAC7E,MAAM,cAAc,iBAAiB,KAAA,IAAY,KAAA,IAAY,OAAO,UAAU,YAAY;EAC1F,MAAM,mBACJ,gBAAgB,KAAA,IACZ,KAAA,IACA,gBAAgB,YACd,OAAO,aAAa,MAAM,IAAI,IAC9B;EACR,IAAI,CAAC,kBACH,MAAM,IAAI,qBACR,6BACA,2DAA2D,MAAM,KAAK,aAAa,MAAM,KAAK,OAAO,KAAK,IAAI,EAAE,IAClH;EAEF,MAAM,iBACJ,OAAO,MAAM,KAAK,UAAU,eAAe,WAAW,MAAM,KAAK,SAAS,aAAa,KAAA;EAKzF,MAAM,WAAW,MAAM,OAAO,cAAc,KAAA;EAC5C,MAAM,kBACH,MAAM,kBAAkB,OAAO,sBAAsB,KAAK,KAC1D,MAAM,2BAA2B;GAChC,eAAe,OAAO;GACtB,OAAO,MAAM,OAAO;GACpB,kBAAkB,MAAM,OAAO;GAC/B;GACA;GAGA,mBAAmB,aAAa,QAAQ,IAAI,KAAA,IAAY;EAC1D,CAAC;EAEH,MAAM,YAAY,QAAQ;GACxB,OAAO,MAAM,OAAO;GACpB,QAAQ,gBAAgB;GACxB,kBAAkB,MAAM,OAAO;GAC/B,WAAW,gBAAgB;GAC3B,gBAAgB,MAAM,6BAA6B,UAAU,MAAM,OAAO,gBAAgB;GAC1F,aAAa,oBAAoB;IAAE;IAAQ,OAAO,MAAM,KAAK;IAAO,UAAU,MAAM,KAAK;GAAS,CAAC;GACnG,YAAY,MAAM,OAAO;GACzB;GACA,UAAU;IACR,IAAI,MAAM,KAAK;IACf,MAAM,MAAM;IACZ,OAAO;KACL,gBAAgB,MAAM,KAAK;KAC3B,kBAAkB,MAAM,KAAK;KAC7B,OAAO,MAAM,KAAK;KAClB,QAAQ,CAAC,QAAQ;KACjB,UAAU,MAAM,KAAK;KACrB,UAAU,MAAM,KAAK;IACvB;GACF;EACF,CAAC;CACH,SAAS,OAAO;EACd,IAAI,iBAAiB,sBAAsB,MAAM;EACjD,IAAI,iBAAiB,qCAEnB,MAAM,IAAI,qBADG,MAAM,WAAW,eAAe,2BAA2B,6BACnC,MAAM,SAAS,EAAE,OAAO,MAAM,CAAC;EAEtE,IAAI,iBAAiB,sCACnB,MAAM,IAAI,qBAAqB,0BAA0B,MAAM,SAAS,EAAE,OAAO,MAAM,CAAC;EAE1F,IAAI,iBAAiB,kBACnB,MAAM,IAAI,qBAAqB,yBAAyB,MAAM,OAAO,MAAM,SAAS,EAAE,OAAO,MAAM,CAAC;EAEtG,MAAM;CACR;AACF;;;;;;;AAQA,SAAgB,wBACd,MA6BA,eACoB;CACpB,OAAO;EACL,MAAM,KAAK;EACX,SAAS,KAAK;EACd,GAAI,KAAK,QAAQ,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;EAC1C,gBAAgB,KAAK;EACrB,SAAS,KAAK;EACd,YAAY,KAAK;EACjB,aAAa,KAAK;EAClB,SAAS;GACP,SAAS,KAAK,mBAAmB,eAAe,aAAa;GAC7D,eAAe,KAAK,qBAAqB,eAAe,aAAa;GACrE,GAAI,KAAK,uBACL,EAAE,oBAAoB,KAAK,qBAAqB,eAAe,KAAK,oBAAoB,EAAE,IAC1F,CAAC;GACL,UAAU,KAAK,QAAQ;GACvB,QAAQ,KAAK,QAAQ;GACrB,iBAAiB,KAAK,QAAQ;GAC9B,gBAAgB,KAAK,QAAQ;EAC/B;EACA,GAAI,KAAK,eAAe;GAAE,WAAW,KAAK,QAAQ;GAAW,MAAM,KAAK;EAAK,IAAI,CAAC;EAClF,GAAI,KAAK,eACL,EACE,SAAS;GAAE,eAAe,KAAK;GAAe,WAAW,KAAK,QAAQ;GAAW,QAAQ,KAAK;EAAc,EAC9G,IACA,CAAC;EACL,GAAI,KAAK,YAAY,EAAE,OAAO,EAAE,WAAW,KAAK,UAAU,EAAE,IAAI,CAAC;CACnE;AACF;;;;;;;;AASA,SAAS,gCAAgC,MAA4B,IAAY,aAAa,OAAmB;CAC/G,IAAI,OAAO,UACT,OAAO,CACL,iBAAiB,sBAAsB;EACrC,QAAQ;EACR,cAAc;EACd,UAAS,MACP,EAAE,KAAK;GACL,SAAS;GACT,WAAW;GACX,eAAe,CAAC;GAChB,QAAQ;GACR,aAAa,4BAA4B;IACvC,QAAQ,KAAA;IACR,MAAM,KAAK;IACX,iBAAiB,KAAK,mBAAmB,KAAA;IACzC,aAAa,KAAK;IAClB,SAAS,KAAK;GAChB,CAAC;EACH,CAAC;CACL,CAAC,CACH;CAEF,IAAI,OAAO,UACT,OAAO,CACL,iBAAiB,sBAAsB;EACrC,QAAQ;EACR,cAAc;EACd,UAAS,MACP,EAAE,KAAK;GACL,SAAS;GACT,WAAW;GACX,WAAW;GACX,QAAQ;GACR,aAAa;IACX,qBAAqB;IACrB,oBAAoB,KAAK,KAAK,QAAQ;IACtC,iBAAiB;GACnB;EACF,CAAC;CACL,CAAC,CACH;CAEF,IAAI,OAAO,QACT,OAAO,CACL,iBAAiB,oBAAoB;EACnC,QAAQ;EACR,cAAc;EACd,UAAS,MACP,EAAE,KAAK;GACL,SAAS;GACT;GACA,MAAM;GACN,QAAQ;GACR,aAAa;IACX,gBAAgB;IAChB,oBAAoB,KAAK,KAAK,QAAQ;IACtC,iBAAiB,KAAK,mBAAmB,KAAA;GAC3C;EACF,CAAC;CACL,CAAC,CACH;CAEF,OAAO,CAAC;AACV;;;;;;;;;;;;;AAcA,SAAS,mCAA+C;CACtD,OAAO,CACL,iBAAiB,yBAAyB;EACxC,QAAQ;EACR,cAAc;EACd,UAAS,MAAK,EAAE,KAAK;GAAE,UAAU,CAAC;GAAG,YAAY;GAAO,QAAQ;EAAiB,CAAC;CACpF,CAAC,CACH;AACF;;;;;;;;AASA,SAAgB,yBAAyB,MAAwC;CAC/E,MAAM,aAAkC,SAAQ,KAAK,MAAM,KAAK,IAAI;CACpE,MAAM,gBAAgB,KAAK,gBAAgB,CAAC;CAC5C,MAAM,qBAAqB,cAAc,MAAM,EAAE,kBAAkB,YAAY,OAAO,QAAQ;CAC9F,MAAM,gBAAgB,qBAAqB,KAAK,qBAAqB,eAAe,QAAQ,IAAI,KAAA;CAChG,MAAM,oBAAoB,oBAAoB;CAE9C,MAAM,oBAAoB,cAAc,SAAQ,iBAAgB;EAC9D,MAAM,EAAE,gBAAgB;EACxB,IAAI,CAAC,KAAK,aAAa,OAAO,gCAAgC,MAAM,YAAY,IAAI,IAAI;EACxF,MAAM,UAAU,wBACd;GACE,GAAG;GACH,aAAa,KAAK;GAClB;GACA,GAAI,qBAAqB,EAAE,sBAAsB,SAAS,IAAI,CAAC;EACjE,GACA,YAAY,EACd;EACA,OAAO,uBAAuB;GAAE,GAAG;GAAc,QAAQ,YAAY,OAAO,OAAO;EAAE,CAAC;CACxF,CAAC;CAED,MAAM,cAAc;EAAC;EAAU;EAAU;CAAM,CAAC,CAC7C,QAAO,OAAM,CAAC,cAAc,MAAM,EAAE,kBAAkB,YAAY,OAAO,EAAE,CAAC,CAAC,CAC7E,SAAQ,OAAM,gCAAgC,MAAM,EAAE,CAAC;CAG1D,MAAM,mBAAmB,cAAc,MAAM,EAAE,kBAAkB,YAAY,OAAO,OAAO,IACvF,CAAC,IACD,iCAAiC;CAErC,MAAM,oBAAoB,KAAK,eAC1B,KAAK,4BACN,IAAI,yBAAyB;EAC3B,eAAe,KAAK;EACpB,QAAQ,KAAK;EACb,SAAS,KAAK,QAAQ;EACtB,OAAO,KAAK;CACd,CAAC,IACD,KAAA;CACJ,MAAM,mBAAmB,oBACrB,IAAI,wBACF,KAAK,YACL,KAAK,QAAQ,WACb,mBACA,mBAAmB,sBACnB,KAAK,QAAQ,cACf,IACA,KAAA;CACJ,IAAI,qBAAqB,kBACvB,KAAK,mBAAmB;EACtB;EACA,GAAI,oBACA,EACE,iBAAiB,UACf,0BACE,mBACA,kBACA,KAAK,QAAQ,UACb,KAAK,eACL,KACF,EACJ,IACA,CAAC;CACP,CAAC;CAGH,OAAO;EACL,GAAG,cAAc;GACf,MAAM,KAAK;GACX,WAAW;IACT,MAAM,KAAK;IACX,UAAU,KAAK,qBAAqB,eAAe,QAAQ,CAAC,CAAC;IAC7D,YAAY,KAAK,QAAQ;GAC3B;EACF,CAAC;EACD,GAAG,IAAI,aAAa;GAClB,MAAM,KAAK;GACX,YAAY,KAAK;GACjB,aAAa,KAAK;GAClB,kBAAkB,KAAK,QAAQ;GAC/B,YAAY,KAAK,QAAQ;GACzB,uBAAuB,KAAK,qBAAqB,eAAe,QAAQ,CAAC,CAAC;GAC1E,gBAAgB,KAAK,QAAQ;GAC7B,iBAAiB,KAAK,QAAQ;GAC9B,iBAAiB,KAAK,QAAQ;GAC9B,UAAU,EAAE,WAAW,KAAK,iBAAiB;GAC7C,sBAAsB;GACtB,0BAA0B;EAC5B,CAAC,CAAC,CAAC,OAAO;EACV,GAAG,IAAI,YAAY;GACjB,MAAM,KAAK;GACX,aAAa,KAAK;GAClB,kBAAkB,KAAK,QAAQ;GAC/B,gBAAgB,KAAK,QAAQ;GAC7B,sBAAsB;EACxB,CAAC,CAAC,CAAC,OAAO;EACV,GAAG,IAAI,YAAY;GACjB,MAAM,KAAK;GACX,cAAc,KAAK;GACnB,YAAY,KAAK;GACjB,sBAAsB;GACtB,0BAA0B,oBAAoB;EAChD,CAAC,CAAC,CAAC,OAAO;EACV,GAAG;EACH,GAAG;EACH,GAAG;EACH,GAAI,KAAK,cACL,IAAI,aAAa;GACf,MAAM,KAAK;GACX,OAAO,KAAK;GACZ,QAAQ,KAAK,QAAQ;GACrB,UAAU,KAAK,QAAQ;GACvB,eAAe,KAAK;GAEpB,GAAI,KAAK,eAAe,EAAE,WAAW,KAAK,QAAQ,UAAU,IAAI,CAAC;GACjE,eAAe,KAAK,gBAAgB,CAAC,EAAA,CAAG,SAAS,EAAE,kBACjD,YAAY,SAAS,CAAC;IAAE,IAAI,YAAY;IAAI,QAAQ,YAAY;GAAO,CAAC,IAAI,CAAC,CAC/E;EACF,CAAC,CAAC,CAAC,OAAO,IACV,CAAC;EACL,GAAI,KAAK,gBAAgB,KAAK,mBAC1B,IAAI,gBAAgB;GAClB,MAAM,KAAK;GACX,UAAU,KAAK,QAAQ;GACvB,WAAW,YAAY,KAAK,gBAAgB,iBAAiB,CAAC,CAAC,SAAS,WAAW;EACrF,CAAC,CAAC,CAAC,OAAO,IACV,CAAC;EACL,GAAI,KAAK,eACL,IAAI,eAAe;GACjB,MAAM,KAAK;GACX,OAAO,KAAK;GACZ,UAAU,KAAK,QAAQ;GACvB,WAAW,KAAK,QAAQ;GACxB,eAAe,KAAK;GACpB,UAAU,KAAK,QAAQ;GACvB,aAAa,KAAK,QAAQ;GAC1B;GACA;GACA,cAAc,KAAK;EACrB,CAAC,CAAC,CAAC,OAAO,IACV,CAAC;EACL,GAAI,KAAK,eACL,yBAAyB;GACvB,MAAM,KAAK;GACX,OAAO,KAAK;GACZ,UAAU,KAAK,QAAQ;GACvB,WAAW,KAAK,QAAQ;GACxB,eAAe,KAAK;EACtB,CAAC,IACD,CAAC;CACP;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/rules/dispatcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/rules/dispatcher.ts"],"names":[],"mappings":"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"}