@mastra/factory 0.17.3-alpha.2 → 0.17.3-alpha.4

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 (29) hide show
  1. package/dist/integrations/github/issue-reconciler.d.ts +5 -3
  2. package/dist/integrations/github/issue-reconciler.d.ts.map +1 -1
  3. package/dist/integrations/github/issue-reconciler.js +24 -4
  4. package/dist/integrations/github/issue-reconciler.js.map +1 -1
  5. package/dist/integrations/github/rules.d.ts +15 -0
  6. package/dist/integrations/github/rules.d.ts.map +1 -1
  7. package/dist/integrations/github/rules.js +14 -1
  8. package/dist/integrations/github/rules.js.map +1 -1
  9. package/dist/integrations/incidentio/integration.d.ts.map +1 -1
  10. package/dist/integrations/incidentio/integration.js +1 -0
  11. package/dist/integrations/incidentio/integration.js.map +1 -1
  12. package/dist/integrations/incidentio/routes.d.ts +5 -0
  13. package/dist/integrations/incidentio/routes.d.ts.map +1 -1
  14. package/dist/integrations/incidentio/routes.js +5 -1
  15. package/dist/integrations/incidentio/routes.js.map +1 -1
  16. package/dist/integrations/platform/connect/routes.d.ts.map +1 -1
  17. package/dist/integrations/platform/connect/routes.js +4 -0
  18. package/dist/integrations/platform/connect/routes.js.map +1 -1
  19. package/dist/integrations/platform/github/event-worker.d.ts.map +1 -1
  20. package/dist/integrations/platform/github/event-worker.js +15 -0
  21. package/dist/integrations/platform/github/event-worker.js.map +1 -1
  22. package/dist/integrations/platform/github/integration.d.ts +6 -0
  23. package/dist/integrations/platform/github/integration.d.ts.map +1 -1
  24. package/dist/integrations/platform/github/integration.js +26 -1
  25. package/dist/integrations/platform/github/integration.js.map +1 -1
  26. package/dist/integrations/platform/incidentio/integration.d.ts.map +1 -1
  27. package/dist/integrations/platform/incidentio/integration.js +1 -0
  28. package/dist/integrations/platform/incidentio/integration.js.map +1 -1
  29. package/package.json +8 -8
@@ -1 +1 @@
1
- {"version":3,"file":"integration.js","names":["#clientConfig","#platformClient","#endpointHost","#intakeByConnectionId","#rules","#orgIdByResourceId","#projects","#auth","#intakeStorage","#activeConnections","#connectionContexts","#connectionIntake","#intakeForConnection","#resolveIntakeDispatch","#listSources","#listItems","#listIssues","#getIssue","#createComment","#updateIssue","#scopeResolvedDispatch","#withBaseSource"],"sources":["../../../../src/integrations/platform/incidentio/integration.ts"],"sourcesContent":["import type { RequestContext } from '@mastra/core/request-context';\nimport type { ApiRoute } from '@mastra/core/server';\nimport type { MastraWorker } from '@mastra/core/worker';\n\nimport type { IntegrationConnection } from '../../../capabilities/connection.js';\nimport type {\n CreateIntakeCommentInput,\n CreatedIntakeComment,\n GetIntakeIssueInput,\n Intake,\n IntakeIssue,\n IntakeIssueDetail,\n IntakeItemPage,\n IntakeSource,\n ListIntakeIssuesInput,\n ListIntakeItemsInput,\n ResolveIntakeDispatchInput,\n ResolvedIntakeDispatch,\n UpdateIntakeIssueInput,\n} from '../../../capabilities/intake.js';\nimport type { RouteAuth } from '../../../routes/route.js';\nimport type { IntakeStorage } from '../../../storage/domains/intake/base.js';\nimport type { FactoryProjectsStorage } from '../../../storage/domains/projects/base.js';\nimport type { FactoryIntegration, IntegrationContext, IntegrationTools } from '../../base.js';\nimport { buildIncidentioAgentTools } from '../../incidentio/agent-tools.js';\nimport { IncidentioApiClient, IncidentioApiError } from '../../incidentio/api.js';\nimport { resolveIncidentioRules } from '../../incidentio/default-rules.js';\nimport type { IncidentioEventRules, IncidentioRuleOverrides } from '../../incidentio/default-rules.js';\nimport {\n createIncidentioIntake,\n INCIDENTIO_FOLLOW_UPS_SOURCE_ID,\n INCIDENTIO_INCIDENTS_SOURCE_ID,\n} from '../../incidentio/intake.js';\nimport { attachIncidentioIssueReconciler } from '../../incidentio/issue-reconciler.js';\nimport {\n incidentioReconciliationEnabled,\n incidentioReconciliationInterval,\n} from '../../incidentio/reconciliation-config.js';\nimport { buildIncidentioRoutes } from '../../incidentio/routes.js';\nimport { attachIncidentioRules } from '../../incidentio/rules.js';\nimport { IssueReconcileWorker } from '../../issue-reconcile-worker.js';\nimport { PlatformApiClient, platformApiClientConfigFromEnv, type PlatformApiClientConfig } from '../api-client.js';\n\nexport interface PlatformIncidentioIntegrationConfig {\n clientConfig?: PlatformApiClientConfig;\n /** Per-event replacements for the default Factory incident.io rules. */\n rules?: IncidentioRuleOverrides;\n}\n\n/**\n * Provider config key registered for incident.io in Mastra Platform's\n * integrations catalog. Connections are discovered at runtime — no\n * deploy-time connection ID wiring.\n */\nconst PLATFORM_INCIDENTIO_PROVIDER_CONFIG_KEY = 'incident-io';\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 CONNECTION_TOKEN_PREFIX = 'incidentio-connection:';\nconst SCOPED_SOURCE_PREFIX = 'incidentio-source:';\nconst BASE_SOURCE_IDS = [INCIDENTIO_INCIDENTS_SOURCE_ID, INCIDENTIO_FOLLOW_UPS_SOURCE_ID] as const;\n\ninterface PlatformIntegrationConnection {\n id: string;\n integrationId: string;\n status: 'active' | 'needs_reauth';\n accountLabel: string | null;\n}\n\ninterface ScopedSourceId {\n connectionId: string;\n sourceId: string;\n}\n\n/** An intake plus the exact inner connection it was resolved for, so operations discover active connections once. */\ninterface ResolvedIncidentioIntake {\n intake: Intake;\n connection: IntegrationConnection;\n}\n\ninterface AggregatePageCursor {\n /** Connection ID the cursor points at; keyed by ID so the active list can change between pages. */\n connectionId: string;\n inner?: string;\n}\n\nexport function encodeScopedSourceId(connectionId: string, sourceId: string): string {\n return `${SCOPED_SOURCE_PREFIX}${Buffer.from(JSON.stringify({ connectionId, sourceId })).toString('base64url')}`;\n}\n\nexport function decodeScopedSourceId(value: string): ScopedSourceId | null {\n if (!value.startsWith(SCOPED_SOURCE_PREFIX)) return null;\n try {\n const parsed = JSON.parse(\n Buffer.from(value.slice(SCOPED_SOURCE_PREFIX.length), 'base64url').toString('utf8'),\n ) as Record<string, unknown>;\n return typeof parsed.connectionId === 'string' && typeof parsed.sourceId === 'string'\n ? { connectionId: parsed.connectionId, sourceId: parsed.sourceId }\n : null;\n } catch {\n return null;\n }\n}\n\nfunction incidentioConnection(connectionId: string): IntegrationConnection {\n return { type: 'oauth', accessToken: `${CONNECTION_TOKEN_PREFIX}${connectionId}` };\n}\n\nfunction connectionIdFromConnection(connection: IntegrationConnection): string | null {\n if (connection.type !== 'oauth' || !connection.accessToken.startsWith(CONNECTION_TOKEN_PREFIX)) return null;\n return connection.accessToken.slice(CONNECTION_TOKEN_PREFIX.length) || null;\n}\n\n/**\n * Base (per-connection) source ids selected for a connection. Scoped ids\n * select their own connection; legacy unscoped ids (`incidentio:incidents`)\n * from pre-discovery deploys apply to every connection.\n */\nfunction baseSourceIdsFor(connectionId: string, sourceIds: string[]): string[] {\n const selected = new Set<string>();\n for (const sourceId of sourceIds) {\n const scoped = decodeScopedSourceId(sourceId);\n if (scoped) {\n if (scoped.connectionId === connectionId) selected.add(scoped.sourceId);\n continue;\n }\n if ((BASE_SOURCE_IDS as readonly string[]).includes(sourceId)) selected.add(sourceId);\n }\n return [...selected];\n}\n\nfunction encodePageCursor(cursor: AggregatePageCursor): string {\n return Buffer.from(JSON.stringify(cursor)).toString('base64url');\n}\n\nfunction decodePageCursor(cursor: string | undefined): AggregatePageCursor | null {\n if (!cursor) return null;\n try {\n const parsed = JSON.parse(Buffer.from(cursor, 'base64url').toString('utf8')) as Partial<AggregatePageCursor>;\n if (typeof parsed.connectionId !== 'string' || !parsed.connectionId) return null;\n return {\n connectionId: parsed.connectionId,\n ...(typeof parsed.inner === 'string' && parsed.inner ? { inner: parsed.inner } : {}),\n };\n } catch {\n return null;\n }\n}\n\ninterface IncidentioConnectionContext {\n connection: PlatformIntegrationConnection;\n intake: Intake;\n}\n\nexport class PlatformIncidentioIntegration implements FactoryIntegration {\n readonly id = 'incidentio';\n readonly #clientConfig: PlatformApiClientConfig;\n readonly #platformClient: PlatformApiClient;\n readonly #endpointHost: string;\n readonly #intakeByConnectionId = new Map<string, Intake>();\n readonly #rules: IncidentioEventRules;\n\n /** Bound once by the factory via `initialize()` before any surface is used. */\n #projects: FactoryProjectsStorage | undefined;\n #auth: RouteAuth | undefined;\n #intakeStorage: IntakeStorage | undefined;\n readonly #orgIdByResourceId = new Map<string, string | null>();\n\n constructor(config: PlatformIncidentioIntegrationConfig = {}) {\n this.#clientConfig = config.clientConfig ?? platformApiClientConfigFromEnv();\n this.#platformClient = new PlatformApiClient(this.#clientConfig);\n this.#endpointHost = new URL(this.#clientConfig.baseUrl).host;\n this.#rules = resolveIncidentioRules(config.rules);\n }\n\n /** Event rules driving automatic follow-up materialization and close handling. */\n get rules(): IncidentioEventRules {\n return this.#rules;\n }\n\n initialize({\n projects,\n auth,\n intake,\n }: {\n projects: FactoryProjectsStorage;\n auth: RouteAuth;\n intake: IntakeStorage;\n }): void {\n this.#projects = projects;\n this.#auth = auth;\n this.#intakeStorage = intake;\n }\n\n /** Cross-integration intake selection/binding domain — agent-tool authorization. */\n get intakeStorage(): IntakeStorage {\n if (!this.#intakeStorage) {\n throw new Error('PlatformIncidentioIntegration is not initialized — the factory binds storage during prepare().');\n }\n return this.#intakeStorage;\n }\n\n /** Factory projects domain — maps a session's resourceId to its owning org. */\n get projects(): FactoryProjectsStorage {\n if (!this.#projects) {\n throw new Error('PlatformIncidentioIntegration is not initialized — the factory binds storage during prepare().');\n }\n return this.#projects;\n }\n\n /** Whether the host runs with web auth enabled; every surface is inert without it. */\n get authEnabled(): boolean {\n return this.#auth?.enabled() ?? false;\n }\n\n /**\n * Map a session's resourceId (the factory project id) to its owning org.\n * Same caching semantics as the Jira integration: definitive misses are\n * cached, transient database failures are not.\n */\n async resolveOrgId(resourceId: string): Promise<string | null> {\n const cached = this.#orgIdByResourceId.get(resourceId);\n if (cached !== undefined) return cached;\n if (!UUID_RE.test(resourceId)) {\n this.#orgIdByResourceId.set(resourceId, null);\n return null;\n }\n let orgId: string | null;\n try {\n await this.projects.ensureReady();\n const project = await this.projects.getById({ id: resourceId });\n orgId = project?.orgId ?? null;\n } catch {\n // Transient database failure: skip the tools for this request but don't\n // cache the miss, so the next request retries the lookup.\n return null;\n }\n this.#orgIdByResourceId.set(resourceId, orgId);\n return orgId;\n }\n\n /**\n * Org-scoped agent tools: the read-only follow-up detail tool for sessions\n * whose resource is a factory project with an active Platform-managed\n * incident.io connection.\n */\n async agentTools(args: { requestContext: RequestContext }): Promise<IntegrationTools> {\n if (!(await this.hasActiveConnections())) return {};\n return buildIncidentioAgentTools({ requestContext: args.requestContext, incidentio: this });\n }\n\n async listConnections(): Promise<PlatformIntegrationConnection[]> {\n const providerKey = encodeURIComponent(PLATFORM_INCIDENTIO_PROVIDER_CONFIG_KEY);\n const result = await this.#platformClient.request<{ connections: PlatformIntegrationConnection[] }>(\n 'GET',\n `/v2/connections?providerKey=${providerKey}`,\n );\n return result.connections;\n }\n\n async hasActiveConnections(): Promise<boolean> {\n return (await this.#activeConnections()).length > 0;\n }\n\n clearCaches(): void {\n this.#intakeByConnectionId.clear();\n this.#orgIdByResourceId.clear();\n }\n\n async #activeConnections(): Promise<PlatformIntegrationConnection[]> {\n const connections = (await this.listConnections()).filter(connection => connection.status === 'active');\n // Stable ordering keeps aggregate page cursors valid across requests.\n return connections.slice().sort((left, right) => left.id.localeCompare(right.id));\n }\n\n #connectionIntake(connectionId: string): Intake {\n const cached = this.#intakeByConnectionId.get(connectionId);\n if (cached) return cached;\n const proxyBaseUrl = `${this.#clientConfig.baseUrl.replace(/\\/+$/, '')}/v2/connections/${encodeURIComponent(\n connectionId,\n )}/proxy`;\n const intake = createIncidentioIntake({\n api: new IncidentioApiClient({\n baseUrl: proxyBaseUrl,\n accessToken: this.#clientConfig.accessToken,\n ...(this.#clientConfig.fetchImpl ? { fetchImpl: this.#clientConfig.fetchImpl } : {}),\n }),\n connection: incidentioConnection(connectionId),\n });\n this.#intakeByConnectionId.set(connectionId, intake);\n return intake;\n }\n\n async #connectionContexts(): Promise<IncidentioConnectionContext[]> {\n return (await this.#activeConnections()).map(connection => ({\n connection,\n intake: this.#connectionIntake(connection.id),\n }));\n }\n\n /**\n * Resolve the intake for an explicit connection token, or fall back to the\n * sole active connection so legacy single-connection callers keep working.\n *\n * A caller-supplied connection token is only a claim: the id it carries\n * must match a connection the deployment actually discovered as active\n * before any proxy request is minted with the Platform credential.\n */\n async #intakeForConnection(connection: IntegrationConnection): Promise<ResolvedIncidentioIntake> {\n const connectionId = connectionIdFromConnection(connection);\n const active = await this.#activeConnections();\n if (connectionId) {\n if (!active.some(candidate => candidate.id === connectionId)) {\n throw new IncidentioApiError('incident.io connection is unavailable or requires reauthentication.', 401);\n }\n return { intake: this.#connectionIntake(connectionId), connection: incidentioConnection(connectionId) };\n }\n if (active.length === 1) {\n const soleId = active[0]!.id;\n return { intake: this.#connectionIntake(soleId), connection: incidentioConnection(soleId) };\n }\n throw new IncidentioApiError(\n active.length === 0\n ? 'incident.io connection is unavailable or requires reauthentication.'\n : 'incident.io request must identify a connection when multiple accounts are connected.',\n active.length === 0 ? 401 : 400,\n );\n }\n\n readonly intake: Intake = {\n resolveIntakeDispatch: input => this.#resolveIntakeDispatch(input),\n listSources: () => this.#listSources(),\n listItems: input => this.#listItems(input),\n listIssues: input => this.#listIssues(input),\n getIssue: input => this.#getIssue(input),\n createComment: input => this.#createComment(input),\n updateIssue: input => this.#updateIssue(input),\n };\n\n async #resolveIntakeDispatch(input: ResolveIntakeDispatchInput): Promise<ResolvedIntakeDispatch | null> {\n if (input.externalSource.type !== 'issue') return null;\n const externalId = input.externalSource.externalId;\n const contexts = await this.#connectionContexts();\n if (contexts.length === 0) return null;\n if (contexts.length === 1) {\n const resolved = await contexts[0]!.intake.resolveIntakeDispatch?.(input);\n return resolved ? this.#scopeResolvedDispatch(contexts[0]!.connection.id, resolved) : null;\n }\n // Multiple accounts: item references carry no connection id, so probe\n // each connection for the item — first account that knows it wins\n // (incident.io ids are globally unique ULIDs, collisions are not a\n // practical concern and this capability is read-mostly).\n let firstError: unknown;\n for (const context of contexts) {\n try {\n const issue = await context.intake.getIssue({\n connection: incidentioConnection(context.connection.id),\n issueId: externalId,\n });\n if (!issue) continue;\n const resolved = await context.intake.resolveIntakeDispatch?.(input);\n return resolved ? this.#scopeResolvedDispatch(context.connection.id, resolved) : null;\n } catch (error) {\n if (error instanceof IncidentioApiError && error.status === 404) continue;\n firstError ??= error;\n }\n }\n if (firstError !== undefined) throw firstError;\n return null;\n }\n\n #scopeResolvedDispatch(connectionId: string, resolved: ResolvedIntakeDispatch): ResolvedIntakeDispatch {\n return {\n ...resolved,\n connection: incidentioConnection(connectionId),\n ...(resolved.sourceId ? { sourceId: encodeScopedSourceId(connectionId, resolved.sourceId) } : {}),\n };\n }\n\n async #listSources(): Promise<IntakeSource[]> {\n const contexts = await this.#connectionContexts();\n const sources: IntakeSource[] = [];\n for (const context of contexts) {\n const account = context.connection.accountLabel;\n const inner = await context.intake.listSources({ orgId: '', userId: '' });\n for (const source of inner) {\n sources.push({\n ...source,\n id: encodeScopedSourceId(context.connection.id, source.id),\n name: contexts.length > 1 && account ? `${source.name} (${account})` : source.name,\n metadata: {\n ...(source.metadata ?? {}),\n connectionId: context.connection.id,\n ...(account ? { account } : {}),\n },\n });\n }\n }\n return sources;\n }\n\n async #listItems(input: ListIntakeItemsInput): Promise<IntakeItemPage> {\n if (input.sourceIds.length === 0) return { items: [], nextCursor: null };\n const contexts = await this.#connectionContexts();\n const cursor = decodePageCursor(input.cursor);\n\n // Resume by connection ID: the active list can change between pages, so an\n // index would replay or skip connections. When the cursor's connection is\n // gone, resume at its sorted successor and drop the inner cursor.\n let startIndex = 0;\n let exactMatch = false;\n if (cursor) {\n const index = contexts.findIndex(context => context.connection.id === cursor.connectionId);\n exactMatch = index !== -1;\n startIndex = exactMatch\n ? index\n : contexts.findIndex(context => context.connection.id.localeCompare(cursor.connectionId) > 0);\n if (startIndex === -1) return { items: [], nextCursor: null };\n }\n\n for (let index = startIndex; index < contexts.length; index++) {\n const context = contexts[index]!;\n const baseSourceIds = baseSourceIdsFor(context.connection.id, input.sourceIds);\n if (baseSourceIds.length === 0) continue;\n const page = await context.intake.listItems({\n orgId: input.orgId,\n userId: input.userId,\n sourceIds: baseSourceIds,\n ...(index === startIndex && exactMatch && cursor?.inner ? { cursor: cursor.inner } : {}),\n });\n const nextCursor = page.nextCursor\n ? encodePageCursor({ connectionId: context.connection.id, inner: page.nextCursor })\n : index + 1 < contexts.length\n ? encodePageCursor({ connectionId: contexts[index + 1]!.connection.id })\n : null;\n return {\n items: page.items.map(item => ({\n ...item,\n sourceId: encodeScopedSourceId(context.connection.id, item.sourceId),\n metadata: { ...(item.metadata ?? {}), connectionId: context.connection.id },\n })),\n nextCursor,\n };\n }\n return { items: [], nextCursor: null };\n }\n\n async #listIssues(input: ListIntakeIssuesInput): Promise<{ issues: IntakeIssue[]; nextCursor: string | null }> {\n const resolved = await this.#intakeForConnection(input.connection);\n // Scope to the connection that was actually resolved (which may be the\n // sole-connection fallback), so a source id scoped to a different\n // connection is dropped instead of being read against this one.\n const connectionId = connectionIdFromConnection(resolved.connection);\n const baseSourceIds = connectionId\n ? baseSourceIdsFor(connectionId, input.sourceIds)\n : input.sourceIds.map(sourceId => decodeScopedSourceId(sourceId)?.sourceId ?? sourceId);\n return resolved.intake.listIssues({\n ...input,\n connection: resolved.connection,\n sourceIds: baseSourceIds,\n });\n }\n\n async #getIssue(input: GetIntakeIssueInput): Promise<IntakeIssueDetail | null> {\n const resolved = await this.#intakeForConnection(input.connection);\n return resolved.intake.getIssue({\n ...this.#withBaseSource(input),\n connection: resolved.connection,\n });\n }\n\n async #createComment(input: CreateIntakeCommentInput): Promise<CreatedIntakeComment | null> {\n const resolved = await this.#intakeForConnection(input.connection);\n return resolved.intake.createComment({\n ...this.#withBaseSource(input),\n connection: resolved.connection,\n });\n }\n\n async #updateIssue(input: UpdateIntakeIssueInput): Promise<IntakeIssue | null> {\n const resolved = await this.#intakeForConnection(input.connection);\n return resolved.intake.updateIssue({\n ...this.#withBaseSource(input),\n connection: resolved.connection,\n });\n }\n\n #withBaseSource<T extends { sourceId?: string }>(input: T): T {\n if (!input.sourceId) return input;\n const scoped = decodeScopedSourceId(input.sourceId);\n return scoped ? { ...input, sourceId: scoped.sourceId } : input;\n }\n\n workers(ctx: IntegrationContext): MastraWorker[] {\n if (!incidentioReconciliationEnabled()) return [];\n const reconcile = attachIncidentioIssueReconciler(this, ctx);\n if (!reconcile) return [];\n const intervalMs = incidentioReconciliationInterval();\n return [\n new IssueReconcileWorker({\n integrationId: this.id,\n reconcile,\n ...(intervalMs ? { intervalMs } : {}),\n }),\n ];\n }\n\n /**\n * The integration's HTTP surface: `/web/incidentio/*` Mastra `apiRoutes`\n * (status + follow-up listing/detail for Intake), aggregated across every\n * discovered Platform connection. A board-scoped listing also feeds the\n * incident.io event rules.\n */\n routes(ctx: IntegrationContext): ApiRoute[] {\n return buildIncidentioRoutes({\n incidentio: this,\n auth: ctx.auth,\n intake: ctx.storage.intake,\n ingestFactoryIssues: attachIncidentioRules(this, ctx),\n });\n }\n\n diagnostics(): Record<string, unknown> {\n return { configured: true, mode: 'platform', endpointHost: this.#endpointHost };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"integration.js","names":["#clientConfig","#platformClient","#endpointHost","#intakeByConnectionId","#rules","#orgIdByResourceId","#projects","#auth","#intakeStorage","#activeConnections","#connectionContexts","#connectionIntake","#intakeForConnection","#resolveIntakeDispatch","#listSources","#listItems","#listIssues","#getIssue","#createComment","#updateIssue","#scopeResolvedDispatch","#withBaseSource"],"sources":["../../../../src/integrations/platform/incidentio/integration.ts"],"sourcesContent":["import type { RequestContext } from '@mastra/core/request-context';\nimport type { ApiRoute } from '@mastra/core/server';\nimport type { MastraWorker } from '@mastra/core/worker';\n\nimport type { IntegrationConnection } from '../../../capabilities/connection.js';\nimport type {\n CreateIntakeCommentInput,\n CreatedIntakeComment,\n GetIntakeIssueInput,\n Intake,\n IntakeIssue,\n IntakeIssueDetail,\n IntakeItemPage,\n IntakeSource,\n ListIntakeIssuesInput,\n ListIntakeItemsInput,\n ResolveIntakeDispatchInput,\n ResolvedIntakeDispatch,\n UpdateIntakeIssueInput,\n} from '../../../capabilities/intake.js';\nimport type { RouteAuth } from '../../../routes/route.js';\nimport type { IntakeStorage } from '../../../storage/domains/intake/base.js';\nimport type { FactoryProjectsStorage } from '../../../storage/domains/projects/base.js';\nimport type { FactoryIntegration, IntegrationContext, IntegrationTools } from '../../base.js';\nimport { buildIncidentioAgentTools } from '../../incidentio/agent-tools.js';\nimport { IncidentioApiClient, IncidentioApiError } from '../../incidentio/api.js';\nimport { resolveIncidentioRules } from '../../incidentio/default-rules.js';\nimport type { IncidentioEventRules, IncidentioRuleOverrides } from '../../incidentio/default-rules.js';\nimport {\n createIncidentioIntake,\n INCIDENTIO_FOLLOW_UPS_SOURCE_ID,\n INCIDENTIO_INCIDENTS_SOURCE_ID,\n} from '../../incidentio/intake.js';\nimport { attachIncidentioIssueReconciler } from '../../incidentio/issue-reconciler.js';\nimport {\n incidentioReconciliationEnabled,\n incidentioReconciliationInterval,\n} from '../../incidentio/reconciliation-config.js';\nimport { buildIncidentioRoutes } from '../../incidentio/routes.js';\nimport { attachIncidentioRules } from '../../incidentio/rules.js';\nimport { IssueReconcileWorker } from '../../issue-reconcile-worker.js';\nimport { PlatformApiClient, platformApiClientConfigFromEnv, type PlatformApiClientConfig } from '../api-client.js';\n\nexport interface PlatformIncidentioIntegrationConfig {\n clientConfig?: PlatformApiClientConfig;\n /** Per-event replacements for the default Factory incident.io rules. */\n rules?: IncidentioRuleOverrides;\n}\n\n/**\n * Provider config key registered for incident.io in Mastra Platform's\n * integrations catalog. Connections are discovered at runtime — no\n * deploy-time connection ID wiring.\n */\nconst PLATFORM_INCIDENTIO_PROVIDER_CONFIG_KEY = 'incident-io';\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 CONNECTION_TOKEN_PREFIX = 'incidentio-connection:';\nconst SCOPED_SOURCE_PREFIX = 'incidentio-source:';\nconst BASE_SOURCE_IDS = [INCIDENTIO_INCIDENTS_SOURCE_ID, INCIDENTIO_FOLLOW_UPS_SOURCE_ID] as const;\n\ninterface PlatformIntegrationConnection {\n id: string;\n integrationId: string;\n status: 'active' | 'needs_reauth';\n accountLabel: string | null;\n}\n\ninterface ScopedSourceId {\n connectionId: string;\n sourceId: string;\n}\n\n/** An intake plus the exact inner connection it was resolved for, so operations discover active connections once. */\ninterface ResolvedIncidentioIntake {\n intake: Intake;\n connection: IntegrationConnection;\n}\n\ninterface AggregatePageCursor {\n /** Connection ID the cursor points at; keyed by ID so the active list can change between pages. */\n connectionId: string;\n inner?: string;\n}\n\nexport function encodeScopedSourceId(connectionId: string, sourceId: string): string {\n return `${SCOPED_SOURCE_PREFIX}${Buffer.from(JSON.stringify({ connectionId, sourceId })).toString('base64url')}`;\n}\n\nexport function decodeScopedSourceId(value: string): ScopedSourceId | null {\n if (!value.startsWith(SCOPED_SOURCE_PREFIX)) return null;\n try {\n const parsed = JSON.parse(\n Buffer.from(value.slice(SCOPED_SOURCE_PREFIX.length), 'base64url').toString('utf8'),\n ) as Record<string, unknown>;\n return typeof parsed.connectionId === 'string' && typeof parsed.sourceId === 'string'\n ? { connectionId: parsed.connectionId, sourceId: parsed.sourceId }\n : null;\n } catch {\n return null;\n }\n}\n\nfunction incidentioConnection(connectionId: string): IntegrationConnection {\n return { type: 'oauth', accessToken: `${CONNECTION_TOKEN_PREFIX}${connectionId}` };\n}\n\nfunction connectionIdFromConnection(connection: IntegrationConnection): string | null {\n if (connection.type !== 'oauth' || !connection.accessToken.startsWith(CONNECTION_TOKEN_PREFIX)) return null;\n return connection.accessToken.slice(CONNECTION_TOKEN_PREFIX.length) || null;\n}\n\n/**\n * Base (per-connection) source ids selected for a connection. Scoped ids\n * select their own connection; legacy unscoped ids (`incidentio:incidents`)\n * from pre-discovery deploys apply to every connection.\n */\nfunction baseSourceIdsFor(connectionId: string, sourceIds: string[]): string[] {\n const selected = new Set<string>();\n for (const sourceId of sourceIds) {\n const scoped = decodeScopedSourceId(sourceId);\n if (scoped) {\n if (scoped.connectionId === connectionId) selected.add(scoped.sourceId);\n continue;\n }\n if ((BASE_SOURCE_IDS as readonly string[]).includes(sourceId)) selected.add(sourceId);\n }\n return [...selected];\n}\n\nfunction encodePageCursor(cursor: AggregatePageCursor): string {\n return Buffer.from(JSON.stringify(cursor)).toString('base64url');\n}\n\nfunction decodePageCursor(cursor: string | undefined): AggregatePageCursor | null {\n if (!cursor) return null;\n try {\n const parsed = JSON.parse(Buffer.from(cursor, 'base64url').toString('utf8')) as Partial<AggregatePageCursor>;\n if (typeof parsed.connectionId !== 'string' || !parsed.connectionId) return null;\n return {\n connectionId: parsed.connectionId,\n ...(typeof parsed.inner === 'string' && parsed.inner ? { inner: parsed.inner } : {}),\n };\n } catch {\n return null;\n }\n}\n\ninterface IncidentioConnectionContext {\n connection: PlatformIntegrationConnection;\n intake: Intake;\n}\n\nexport class PlatformIncidentioIntegration implements FactoryIntegration {\n readonly id = 'incidentio';\n readonly #clientConfig: PlatformApiClientConfig;\n readonly #platformClient: PlatformApiClient;\n readonly #endpointHost: string;\n readonly #intakeByConnectionId = new Map<string, Intake>();\n readonly #rules: IncidentioEventRules;\n\n /** Bound once by the factory via `initialize()` before any surface is used. */\n #projects: FactoryProjectsStorage | undefined;\n #auth: RouteAuth | undefined;\n #intakeStorage: IntakeStorage | undefined;\n readonly #orgIdByResourceId = new Map<string, string | null>();\n\n constructor(config: PlatformIncidentioIntegrationConfig = {}) {\n this.#clientConfig = config.clientConfig ?? platformApiClientConfigFromEnv();\n this.#platformClient = new PlatformApiClient(this.#clientConfig);\n this.#endpointHost = new URL(this.#clientConfig.baseUrl).host;\n this.#rules = resolveIncidentioRules(config.rules);\n }\n\n /** Event rules driving automatic follow-up materialization and close handling. */\n get rules(): IncidentioEventRules {\n return this.#rules;\n }\n\n initialize({\n projects,\n auth,\n intake,\n }: {\n projects: FactoryProjectsStorage;\n auth: RouteAuth;\n intake: IntakeStorage;\n }): void {\n this.#projects = projects;\n this.#auth = auth;\n this.#intakeStorage = intake;\n }\n\n /** Cross-integration intake selection/binding domain — agent-tool authorization. */\n get intakeStorage(): IntakeStorage {\n if (!this.#intakeStorage) {\n throw new Error('PlatformIncidentioIntegration is not initialized — the factory binds storage during prepare().');\n }\n return this.#intakeStorage;\n }\n\n /** Factory projects domain — maps a session's resourceId to its owning org. */\n get projects(): FactoryProjectsStorage {\n if (!this.#projects) {\n throw new Error('PlatformIncidentioIntegration is not initialized — the factory binds storage during prepare().');\n }\n return this.#projects;\n }\n\n /** Whether the host runs with web auth enabled; every surface is inert without it. */\n get authEnabled(): boolean {\n return this.#auth?.enabled() ?? false;\n }\n\n /**\n * Map a session's resourceId (the factory project id) to its owning org.\n * Same caching semantics as the Jira integration: definitive misses are\n * cached, transient database failures are not.\n */\n async resolveOrgId(resourceId: string): Promise<string | null> {\n const cached = this.#orgIdByResourceId.get(resourceId);\n if (cached !== undefined) return cached;\n if (!UUID_RE.test(resourceId)) {\n this.#orgIdByResourceId.set(resourceId, null);\n return null;\n }\n let orgId: string | null;\n try {\n await this.projects.ensureReady();\n const project = await this.projects.getById({ id: resourceId });\n orgId = project?.orgId ?? null;\n } catch {\n // Transient database failure: skip the tools for this request but don't\n // cache the miss, so the next request retries the lookup.\n return null;\n }\n this.#orgIdByResourceId.set(resourceId, orgId);\n return orgId;\n }\n\n /**\n * Org-scoped agent tools: the read-only follow-up detail tool for sessions\n * whose resource is a factory project with an active Platform-managed\n * incident.io connection.\n */\n async agentTools(args: { requestContext: RequestContext }): Promise<IntegrationTools> {\n if (!(await this.hasActiveConnections())) return {};\n return buildIncidentioAgentTools({ requestContext: args.requestContext, incidentio: this });\n }\n\n async listConnections(): Promise<PlatformIntegrationConnection[]> {\n const providerKey = encodeURIComponent(PLATFORM_INCIDENTIO_PROVIDER_CONFIG_KEY);\n const result = await this.#platformClient.request<{ connections: PlatformIntegrationConnection[] }>(\n 'GET',\n `/v2/connections?providerKey=${providerKey}`,\n );\n return result.connections;\n }\n\n async hasActiveConnections(): Promise<boolean> {\n return (await this.#activeConnections()).length > 0;\n }\n\n clearCaches(): void {\n this.#intakeByConnectionId.clear();\n this.#orgIdByResourceId.clear();\n }\n\n async #activeConnections(): Promise<PlatformIntegrationConnection[]> {\n const connections = (await this.listConnections()).filter(connection => connection.status === 'active');\n // Stable ordering keeps aggregate page cursors valid across requests.\n return connections.slice().sort((left, right) => left.id.localeCompare(right.id));\n }\n\n #connectionIntake(connectionId: string): Intake {\n const cached = this.#intakeByConnectionId.get(connectionId);\n if (cached) return cached;\n const proxyBaseUrl = `${this.#clientConfig.baseUrl.replace(/\\/+$/, '')}/v2/connections/${encodeURIComponent(\n connectionId,\n )}/proxy`;\n const intake = createIncidentioIntake({\n api: new IncidentioApiClient({\n baseUrl: proxyBaseUrl,\n accessToken: this.#clientConfig.accessToken,\n ...(this.#clientConfig.fetchImpl ? { fetchImpl: this.#clientConfig.fetchImpl } : {}),\n }),\n connection: incidentioConnection(connectionId),\n });\n this.#intakeByConnectionId.set(connectionId, intake);\n return intake;\n }\n\n async #connectionContexts(): Promise<IncidentioConnectionContext[]> {\n return (await this.#activeConnections()).map(connection => ({\n connection,\n intake: this.#connectionIntake(connection.id),\n }));\n }\n\n /**\n * Resolve the intake for an explicit connection token, or fall back to the\n * sole active connection so legacy single-connection callers keep working.\n *\n * A caller-supplied connection token is only a claim: the id it carries\n * must match a connection the deployment actually discovered as active\n * before any proxy request is minted with the Platform credential.\n */\n async #intakeForConnection(connection: IntegrationConnection): Promise<ResolvedIncidentioIntake> {\n const connectionId = connectionIdFromConnection(connection);\n const active = await this.#activeConnections();\n if (connectionId) {\n if (!active.some(candidate => candidate.id === connectionId)) {\n throw new IncidentioApiError('incident.io connection is unavailable or requires reauthentication.', 401);\n }\n return { intake: this.#connectionIntake(connectionId), connection: incidentioConnection(connectionId) };\n }\n if (active.length === 1) {\n const soleId = active[0]!.id;\n return { intake: this.#connectionIntake(soleId), connection: incidentioConnection(soleId) };\n }\n throw new IncidentioApiError(\n active.length === 0\n ? 'incident.io connection is unavailable or requires reauthentication.'\n : 'incident.io request must identify a connection when multiple accounts are connected.',\n active.length === 0 ? 401 : 400,\n );\n }\n\n readonly intake: Intake = {\n resolveIntakeDispatch: input => this.#resolveIntakeDispatch(input),\n listSources: () => this.#listSources(),\n listItems: input => this.#listItems(input),\n listIssues: input => this.#listIssues(input),\n getIssue: input => this.#getIssue(input),\n createComment: input => this.#createComment(input),\n updateIssue: input => this.#updateIssue(input),\n };\n\n async #resolveIntakeDispatch(input: ResolveIntakeDispatchInput): Promise<ResolvedIntakeDispatch | null> {\n if (input.externalSource.type !== 'issue') return null;\n const externalId = input.externalSource.externalId;\n const contexts = await this.#connectionContexts();\n if (contexts.length === 0) return null;\n if (contexts.length === 1) {\n const resolved = await contexts[0]!.intake.resolveIntakeDispatch?.(input);\n return resolved ? this.#scopeResolvedDispatch(contexts[0]!.connection.id, resolved) : null;\n }\n // Multiple accounts: item references carry no connection id, so probe\n // each connection for the item — first account that knows it wins\n // (incident.io ids are globally unique ULIDs, collisions are not a\n // practical concern and this capability is read-mostly).\n let firstError: unknown;\n for (const context of contexts) {\n try {\n const issue = await context.intake.getIssue({\n connection: incidentioConnection(context.connection.id),\n issueId: externalId,\n });\n if (!issue) continue;\n const resolved = await context.intake.resolveIntakeDispatch?.(input);\n return resolved ? this.#scopeResolvedDispatch(context.connection.id, resolved) : null;\n } catch (error) {\n if (error instanceof IncidentioApiError && error.status === 404) continue;\n firstError ??= error;\n }\n }\n if (firstError !== undefined) throw firstError;\n return null;\n }\n\n #scopeResolvedDispatch(connectionId: string, resolved: ResolvedIntakeDispatch): ResolvedIntakeDispatch {\n return {\n ...resolved,\n connection: incidentioConnection(connectionId),\n ...(resolved.sourceId ? { sourceId: encodeScopedSourceId(connectionId, resolved.sourceId) } : {}),\n };\n }\n\n async #listSources(): Promise<IntakeSource[]> {\n const contexts = await this.#connectionContexts();\n const sources: IntakeSource[] = [];\n for (const context of contexts) {\n const account = context.connection.accountLabel;\n const inner = await context.intake.listSources({ orgId: '', userId: '' });\n for (const source of inner) {\n sources.push({\n ...source,\n id: encodeScopedSourceId(context.connection.id, source.id),\n name: contexts.length > 1 && account ? `${source.name} (${account})` : source.name,\n metadata: {\n ...(source.metadata ?? {}),\n connectionId: context.connection.id,\n ...(account ? { account } : {}),\n },\n });\n }\n }\n return sources;\n }\n\n async #listItems(input: ListIntakeItemsInput): Promise<IntakeItemPage> {\n if (input.sourceIds.length === 0) return { items: [], nextCursor: null };\n const contexts = await this.#connectionContexts();\n const cursor = decodePageCursor(input.cursor);\n\n // Resume by connection ID: the active list can change between pages, so an\n // index would replay or skip connections. When the cursor's connection is\n // gone, resume at its sorted successor and drop the inner cursor.\n let startIndex = 0;\n let exactMatch = false;\n if (cursor) {\n const index = contexts.findIndex(context => context.connection.id === cursor.connectionId);\n exactMatch = index !== -1;\n startIndex = exactMatch\n ? index\n : contexts.findIndex(context => context.connection.id.localeCompare(cursor.connectionId) > 0);\n if (startIndex === -1) return { items: [], nextCursor: null };\n }\n\n for (let index = startIndex; index < contexts.length; index++) {\n const context = contexts[index]!;\n const baseSourceIds = baseSourceIdsFor(context.connection.id, input.sourceIds);\n if (baseSourceIds.length === 0) continue;\n const page = await context.intake.listItems({\n orgId: input.orgId,\n userId: input.userId,\n sourceIds: baseSourceIds,\n ...(index === startIndex && exactMatch && cursor?.inner ? { cursor: cursor.inner } : {}),\n });\n const nextCursor = page.nextCursor\n ? encodePageCursor({ connectionId: context.connection.id, inner: page.nextCursor })\n : index + 1 < contexts.length\n ? encodePageCursor({ connectionId: contexts[index + 1]!.connection.id })\n : null;\n return {\n items: page.items.map(item => ({\n ...item,\n sourceId: encodeScopedSourceId(context.connection.id, item.sourceId),\n metadata: { ...(item.metadata ?? {}), connectionId: context.connection.id },\n })),\n nextCursor,\n };\n }\n return { items: [], nextCursor: null };\n }\n\n async #listIssues(input: ListIntakeIssuesInput): Promise<{ issues: IntakeIssue[]; nextCursor: string | null }> {\n const resolved = await this.#intakeForConnection(input.connection);\n // Scope to the connection that was actually resolved (which may be the\n // sole-connection fallback), so a source id scoped to a different\n // connection is dropped instead of being read against this one.\n const connectionId = connectionIdFromConnection(resolved.connection);\n const baseSourceIds = connectionId\n ? baseSourceIdsFor(connectionId, input.sourceIds)\n : input.sourceIds.map(sourceId => decodeScopedSourceId(sourceId)?.sourceId ?? sourceId);\n return resolved.intake.listIssues({\n ...input,\n connection: resolved.connection,\n sourceIds: baseSourceIds,\n });\n }\n\n async #getIssue(input: GetIntakeIssueInput): Promise<IntakeIssueDetail | null> {\n const resolved = await this.#intakeForConnection(input.connection);\n return resolved.intake.getIssue({\n ...this.#withBaseSource(input),\n connection: resolved.connection,\n });\n }\n\n async #createComment(input: CreateIntakeCommentInput): Promise<CreatedIntakeComment | null> {\n const resolved = await this.#intakeForConnection(input.connection);\n return resolved.intake.createComment({\n ...this.#withBaseSource(input),\n connection: resolved.connection,\n });\n }\n\n async #updateIssue(input: UpdateIntakeIssueInput): Promise<IntakeIssue | null> {\n const resolved = await this.#intakeForConnection(input.connection);\n return resolved.intake.updateIssue({\n ...this.#withBaseSource(input),\n connection: resolved.connection,\n });\n }\n\n #withBaseSource<T extends { sourceId?: string }>(input: T): T {\n if (!input.sourceId) return input;\n const scoped = decodeScopedSourceId(input.sourceId);\n return scoped ? { ...input, sourceId: scoped.sourceId } : input;\n }\n\n workers(ctx: IntegrationContext): MastraWorker[] {\n if (!incidentioReconciliationEnabled()) return [];\n const reconcile = attachIncidentioIssueReconciler(this, ctx);\n if (!reconcile) return [];\n const intervalMs = incidentioReconciliationInterval();\n return [\n new IssueReconcileWorker({\n integrationId: this.id,\n reconcile,\n ...(intervalMs ? { intervalMs } : {}),\n }),\n ];\n }\n\n /**\n * The integration's HTTP surface: `/web/incidentio/*` Mastra `apiRoutes`\n * (status + follow-up listing/detail for Intake), aggregated across every\n * discovered Platform connection. A board-scoped listing also feeds the\n * incident.io event rules.\n */\n routes(ctx: IntegrationContext): ApiRoute[] {\n return buildIncidentioRoutes({\n incidentio: this,\n mode: 'platform',\n auth: ctx.auth,\n intake: ctx.storage.intake,\n ingestFactoryIssues: attachIncidentioRules(this, ctx),\n });\n }\n\n diagnostics(): Record<string, unknown> {\n return { configured: true, mode: 'platform', endpointHost: this.#endpointHost };\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/factory",
3
- "version": "0.17.3-alpha.2",
3
+ "version": "0.17.3-alpha.4",
4
4
  "description": "Mastra Software Factory module: the server core behind the Mastra Software Factory — storage domains, integrations, and surfaces for agent-powered software delivery",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -57,11 +57,11 @@
57
57
  "hono": "^4.13.7",
58
58
  "posthog-node": "^5.46.1",
59
59
  "zod": "^4.6.4",
60
- "@mastra/auth-studio": "1.3.7",
61
60
  "@mastra/auth-workos": "1.6.5",
62
- "@mastra/core": "1.72.0-alpha.2",
61
+ "@mastra/auth-studio": "1.3.7",
63
62
  "@mastra/slack": "1.7.0-alpha.0",
64
- "@mastra/code-sdk": "1.8.4-alpha.2"
63
+ "@mastra/code-sdk": "1.8.4-alpha.4",
64
+ "@mastra/core": "1.72.0-alpha.4"
65
65
  },
66
66
  "devDependencies": {
67
67
  "@types/node": "22.20.1",
@@ -70,11 +70,11 @@
70
70
  "typescript": "^6.0.3",
71
71
  "typescript-eslint": "^8.57.0",
72
72
  "vitest": "4.1.11",
73
- "@mastra/libsql": "1.23.4-alpha.0",
74
- "@mastra/pg": "1.27.2-alpha.1",
75
- "@internal/lint": "0.0.137",
73
+ "@mastra/libsql": "1.24.0-alpha.1",
76
74
  "@internal/types-builder": "0.0.112",
77
- "@internal/workspace": "0.0.9"
75
+ "@internal/workspace": "0.0.9",
76
+ "@internal/lint": "0.0.137",
77
+ "@mastra/pg": "1.28.0-alpha.2"
78
78
  },
79
79
  "engines": {
80
80
  "node": ">=22.19.0"