@mastra/server 1.58.0-alpha.12 → 1.58.0-alpha.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/dist/{a2a-B9X-RdWt.js → a2a-CUkzkdTZ.js} +2 -2
- package/dist/{a2a-B9X-RdWt.js.map → a2a-CUkzkdTZ.js.map} +1 -1
- package/dist/{a2a-D1t2fS2L.cjs → a2a-DzZHH3OH.cjs} +2 -2
- package/dist/{a2a-D1t2fS2L.cjs.map → a2a-DzZHH3OH.cjs.map} +1 -1
- package/dist/{api-schema-manifest-CFLB0MBA.cjs → api-schema-manifest-BPk3u4B-.cjs} +3 -3
- package/dist/{api-schema-manifest-CFLB0MBA.cjs.map → api-schema-manifest-BPk3u4B-.cjs.map} +1 -1
- package/dist/{api-schema-manifest-BLv_Z-sd.js → api-schema-manifest-DSelT9XK.js} +3 -3
- package/dist/{api-schema-manifest-BLv_Z-sd.js.map → api-schema-manifest-DSelT9XK.js.map} +1 -1
- package/dist/{background-tasks-Bzl2tNJq.js → background-tasks-BtWM0sZs.js} +2 -2
- package/dist/{background-tasks-Bzl2tNJq.js.map → background-tasks-BtWM0sZs.js.map} +1 -1
- package/dist/{background-tasks-DXns62Go.cjs → background-tasks-C5G2jJax.cjs} +2 -2
- package/dist/{background-tasks-DXns62Go.cjs.map → background-tasks-C5G2jJax.cjs.map} +1 -1
- package/dist/{builder-registry-QAeqpQKB.js → builder-registry-B8KyPAOP.js} +2 -2
- package/dist/{builder-registry-QAeqpQKB.js.map → builder-registry-B8KyPAOP.js.map} +1 -1
- package/dist/{builder-registry-CTQyg5l5.cjs → builder-registry-Dcou-kzd.cjs} +2 -2
- package/dist/{builder-registry-CTQyg5l5.cjs.map → builder-registry-Dcou-kzd.cjs.map} +1 -1
- package/dist/{channels-CPTIswT2.js → channels-B9yt3a2P.js} +2 -2
- package/dist/{channels-CPTIswT2.js.map → channels-B9yt3a2P.js.map} +1 -1
- package/dist/{channels-FoIf30Hv.cjs → channels-BRoq3VKR.cjs} +2 -2
- package/dist/{channels-FoIf30Hv.cjs.map → channels-BRoq3VKR.cjs.map} +1 -1
- package/dist/docs/SKILL.md +2 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-server-custom-api-routes.md +375 -0
- package/dist/docs/references/reference-server-create-route.md +27 -1
- package/dist/{dynamic-workflows-CQs6_anZ.js → dynamic-workflows-B0TE8mjA.js} +2 -2
- package/dist/{dynamic-workflows-CQs6_anZ.js.map → dynamic-workflows-B0TE8mjA.js.map} +1 -1
- package/dist/{dynamic-workflows-CrvwGZj8.cjs → dynamic-workflows-C-6vmau5.cjs} +2 -2
- package/dist/{dynamic-workflows-CrvwGZj8.cjs.map → dynamic-workflows-C-6vmau5.cjs.map} +1 -1
- package/dist/{editor-builder-D5lhXbvj.js → editor-builder-Byg6wbi6.js} +2 -2
- package/dist/{editor-builder-D5lhXbvj.js.map → editor-builder-Byg6wbi6.js.map} +1 -1
- package/dist/{editor-builder-DG5-7x6V.cjs → editor-builder-DT7ypWfa.cjs} +2 -2
- package/dist/{editor-builder-DG5-7x6V.cjs.map → editor-builder-DT7ypWfa.cjs.map} +1 -1
- package/dist/{observability-new-endpoints-D4AWoyDe.cjs → observability-new-endpoints-BC-dasRY.cjs} +2 -2
- package/dist/{observability-new-endpoints-D4AWoyDe.cjs.map → observability-new-endpoints-BC-dasRY.cjs.map} +1 -1
- package/dist/{observability-new-endpoints-6HLxLS-H.js → observability-new-endpoints-Drx0C8uc.js} +2 -2
- package/dist/{observability-new-endpoints-6HLxLS-H.js.map → observability-new-endpoints-Drx0C8uc.js.map} +1 -1
- package/dist/{route-builder-BBovb2TE.cjs → route-builder-BAAedfru.cjs} +10 -1
- package/dist/{route-builder-BBovb2TE.cjs.map → route-builder-BAAedfru.cjs.map} +1 -1
- package/dist/{route-builder-CQkb7tQY.js → route-builder-YQ_gLIvW.js} +10 -1
- package/dist/{route-builder-CQkb7tQY.js.map → route-builder-YQ_gLIvW.js.map} +1 -1
- package/dist/{routes-CzvDlbRt.cjs → routes-0BEh3stO.cjs} +10 -10
- package/dist/{routes-CzvDlbRt.cjs.map → routes-0BEh3stO.cjs.map} +1 -1
- package/dist/{routes-D_-O6SS5.js → routes-BsMPy5bu.js} +10 -10
- package/dist/{routes-D_-O6SS5.js.map → routes-BsMPy5bu.js.map} +1 -1
- package/dist/{schedules-CfNABln2.cjs → schedules-DOK225ZZ.cjs} +2 -2
- package/dist/{schedules-CfNABln2.cjs.map → schedules-DOK225ZZ.cjs.map} +1 -1
- package/dist/{schedules-DSkYO_Nl.js → schedules-RjPcNOmY.js} +2 -2
- package/dist/{schedules-DSkYO_Nl.js.map → schedules-RjPcNOmY.js.map} +1 -1
- package/dist/server/handlers/a2a.cjs +1 -1
- package/dist/server/handlers/a2a.d.ts +545 -505
- package/dist/server/handlers/a2a.d.ts.map +1 -1
- package/dist/server/handlers/a2a.js +1 -1
- package/dist/server/handlers/agent-builder.cjs +1 -1
- package/dist/server/handlers/agent-builder.d.ts +1069 -764
- package/dist/server/handlers/agent-builder.d.ts.map +1 -1
- package/dist/server/handlers/agent-builder.js +1 -1
- package/dist/server/handlers/agent-controller.cjs +1 -1
- package/dist/server/handlers/agent-controller.d.ts +1547 -893
- package/dist/server/handlers/agent-controller.d.ts.map +1 -1
- package/dist/server/handlers/agent-controller.js +1 -1
- package/dist/server/handlers/agent-versions.cjs +1 -1
- package/dist/server/handlers/agent-versions.d.ts +8476 -8356
- package/dist/server/handlers/agent-versions.d.ts.map +1 -1
- package/dist/server/handlers/agent-versions.js +1 -1
- package/dist/server/handlers/agents.cjs +1 -1
- package/dist/server/handlers/agents.d.ts +9502 -9386
- package/dist/server/handlers/agents.d.ts.map +1 -1
- package/dist/server/handlers/agents.js +1 -1
- package/dist/server/handlers/auth.cjs +1 -1
- package/dist/server/handlers/auth.d.ts +693 -297
- package/dist/server/handlers/auth.d.ts.map +1 -1
- package/dist/server/handlers/auth.js +1 -1
- package/dist/server/handlers/background-tasks.cjs +1 -1
- package/dist/server/handlers/background-tasks.d.ts +190 -130
- package/dist/server/handlers/background-tasks.d.ts.map +1 -1
- package/dist/server/handlers/background-tasks.js +1 -1
- package/dist/server/handlers/builder-registry.cjs +1 -1
- package/dist/server/handlers/builder-registry.d.ts +218 -121
- package/dist/server/handlers/builder-registry.d.ts.map +1 -1
- package/dist/server/handlers/builder-registry.js +1 -1
- package/dist/server/handlers/channels.cjs +1 -1
- package/dist/server/handlers/channels.d.ts +157 -77
- package/dist/server/handlers/channels.d.ts.map +1 -1
- package/dist/server/handlers/channels.js +1 -1
- package/dist/server/handlers/conversations.cjs +1 -1
- package/dist/server/handlers/conversations.d.ts +221 -141
- package/dist/server/handlers/conversations.d.ts.map +1 -1
- package/dist/server/handlers/conversations.js +1 -1
- package/dist/server/handlers/datasets.cjs +1 -1
- package/dist/server/handlers/datasets.d.ts +2669 -2234
- package/dist/server/handlers/datasets.d.ts.map +1 -1
- package/dist/server/handlers/datasets.js +1 -1
- package/dist/server/handlers/dynamic-workflows.cjs +1 -1
- package/dist/server/handlers/dynamic-workflows.d.ts +506 -426
- package/dist/server/handlers/dynamic-workflows.d.ts.map +1 -1
- package/dist/server/handlers/dynamic-workflows.js +1 -1
- package/dist/server/handlers/editor-builder.cjs +1 -1
- package/dist/server/handlers/editor-builder.d.ts +305 -245
- package/dist/server/handlers/editor-builder.d.ts.map +1 -1
- package/dist/server/handlers/editor-builder.js +1 -1
- package/dist/server/handlers/favorites-enrichment.cjs +1 -1
- package/dist/server/handlers/favorites-enrichment.js +1 -1
- package/dist/server/handlers/logs.cjs +1 -1
- package/dist/server/handlers/logs.d.ts +245 -185
- package/dist/server/handlers/logs.d.ts.map +1 -1
- package/dist/server/handlers/logs.js +1 -1
- package/dist/server/handlers/mcp-client-versions.cjs +1 -1
- package/dist/server/handlers/mcp-client-versions.d.ts +447 -307
- package/dist/server/handlers/mcp-client-versions.d.ts.map +1 -1
- package/dist/server/handlers/mcp-client-versions.js +1 -1
- package/dist/server/handlers/mcp.cjs +1 -1
- package/dist/server/handlers/mcp.d.ts +357 -156
- package/dist/server/handlers/mcp.d.ts.map +1 -1
- package/dist/server/handlers/mcp.js +1 -1
- package/dist/server/handlers/memory.cjs +1 -1
- package/dist/server/handlers/memory.d.ts +1723 -1223
- package/dist/server/handlers/memory.d.ts.map +1 -1
- package/dist/server/handlers/memory.js +1 -1
- package/dist/server/handlers/observability-new-endpoints.cjs +1 -1
- package/dist/server/handlers/observability-new-endpoints.d.ts +3239 -2158
- package/dist/server/handlers/observability-new-endpoints.d.ts.map +1 -1
- package/dist/server/handlers/observability-new-endpoints.js +1 -1
- package/dist/server/handlers/observability-shared.cjs +1 -1
- package/dist/server/handlers/observability-shared.js +1 -1
- package/dist/server/handlers/observability.cjs +2 -2
- package/dist/server/handlers/observability.d.ts +267 -149
- package/dist/server/handlers/observability.d.ts.map +1 -1
- package/dist/server/handlers/observability.js +2 -2
- package/dist/server/handlers/processor-providers.cjs +1 -1
- package/dist/server/handlers/processor-providers.d.ts +74 -34
- package/dist/server/handlers/processor-providers.d.ts.map +1 -1
- package/dist/server/handlers/processor-providers.js +1 -1
- package/dist/server/handlers/processors.cjs +1 -1
- package/dist/server/handlers/processors.d.ts +222 -173
- package/dist/server/handlers/processors.d.ts.map +1 -1
- package/dist/server/handlers/processors.js +1 -1
- package/dist/server/handlers/prompt-block-versions.cjs +1 -1
- package/dist/server/handlers/prompt-block-versions.d.ts +646 -506
- package/dist/server/handlers/prompt-block-versions.d.ts.map +1 -1
- package/dist/server/handlers/prompt-block-versions.js +1 -1
- package/dist/server/handlers/responses.cjs +1 -1
- package/dist/server/handlers/responses.d.ts +352 -362
- package/dist/server/handlers/responses.d.ts.map +1 -1
- package/dist/server/handlers/responses.js +1 -1
- package/dist/server/handlers/schedules.cjs +1 -1
- package/dist/server/handlers/schedules.d.ts +1190 -1028
- package/dist/server/handlers/schedules.d.ts.map +1 -1
- package/dist/server/handlers/schedules.js +1 -1
- package/dist/server/handlers/scorer-versions.cjs +1 -1
- package/dist/server/handlers/scorer-versions.d.ts +551 -411
- package/dist/server/handlers/scorer-versions.d.ts.map +1 -1
- package/dist/server/handlers/scorer-versions.js +1 -1
- package/dist/server/handlers/scores.cjs +1 -1
- package/dist/server/handlers/scores.d.ts +287 -167
- package/dist/server/handlers/scores.d.ts.map +1 -1
- package/dist/server/handlers/scores.js +1 -1
- package/dist/server/handlers/stored-agent-favorites.cjs +2 -2
- package/dist/server/handlers/stored-agent-favorites.d.ts +62 -22
- package/dist/server/handlers/stored-agent-favorites.d.ts.map +1 -1
- package/dist/server/handlers/stored-agent-favorites.js +2 -2
- package/dist/server/handlers/stored-agents.cjs +2 -2
- package/dist/server/handlers/stored-agents.d.ts +12248 -16428
- package/dist/server/handlers/stored-agents.d.ts.map +1 -1
- package/dist/server/handlers/stored-agents.js +2 -2
- package/dist/server/handlers/stored-mcp-clients.cjs +1 -1
- package/dist/server/handlers/stored-mcp-clients.d.ts +417 -324
- package/dist/server/handlers/stored-mcp-clients.d.ts.map +1 -1
- package/dist/server/handlers/stored-mcp-clients.js +1 -1
- package/dist/server/handlers/stored-prompt-blocks.cjs +1 -1
- package/dist/server/handlers/stored-prompt-blocks.d.ts +603 -555
- package/dist/server/handlers/stored-prompt-blocks.d.ts.map +1 -1
- package/dist/server/handlers/stored-prompt-blocks.js +1 -1
- package/dist/server/handlers/stored-scorers.cjs +1 -1
- package/dist/server/handlers/stored-scorers.d.ts +556 -472
- package/dist/server/handlers/stored-scorers.d.ts.map +1 -1
- package/dist/server/handlers/stored-scorers.js +1 -1
- package/dist/server/handlers/stored-skill-favorites.cjs +2 -2
- package/dist/server/handlers/stored-skill-favorites.d.ts +62 -22
- package/dist/server/handlers/stored-skill-favorites.d.ts.map +1 -1
- package/dist/server/handlers/stored-skill-favorites.js +2 -2
- package/dist/server/handlers/stored-skills.cjs +2 -2
- package/dist/server/handlers/stored-skills.d.ts +632 -515
- package/dist/server/handlers/stored-skills.d.ts.map +1 -1
- package/dist/server/handlers/stored-skills.js +2 -2
- package/dist/server/handlers/stored-workspaces.cjs +1 -1
- package/dist/server/handlers/stored-workspaces.d.ts +646 -546
- package/dist/server/handlers/stored-workspaces.d.ts.map +1 -1
- package/dist/server/handlers/stored-workspaces.js +1 -1
- package/dist/server/handlers/system.cjs +2 -2
- package/dist/server/handlers/system.d.ts +146 -106
- package/dist/server/handlers/system.d.ts.map +1 -1
- package/dist/server/handlers/system.js +2 -2
- package/dist/server/handlers/tool-providers.cjs +1 -1
- package/dist/server/handlers/tool-providers.d.ts +580 -331
- package/dist/server/handlers/tool-providers.d.ts.map +1 -1
- package/dist/server/handlers/tool-providers.js +1 -1
- package/dist/server/handlers/tools.cjs +1 -1
- package/dist/server/handlers/tools.d.ts +177 -77
- package/dist/server/handlers/tools.d.ts.map +1 -1
- package/dist/server/handlers/tools.js +1 -1
- package/dist/server/handlers/vector.cjs +1 -1
- package/dist/server/handlers/vector.d.ts +282 -126
- package/dist/server/handlers/vector.d.ts.map +1 -1
- package/dist/server/handlers/vector.js +1 -1
- package/dist/server/handlers/workflows.cjs +1 -1
- package/dist/server/handlers/workflows.d.ts +1703 -1181
- package/dist/server/handlers/workflows.d.ts.map +1 -1
- package/dist/server/handlers/workflows.js +1 -1
- package/dist/server/handlers/workspace.cjs +1 -1
- package/dist/server/handlers/workspace.d.ts +1936 -1150
- package/dist/server/handlers/workspace.d.ts.map +1 -1
- package/dist/server/handlers/workspace.js +1 -1
- package/dist/server/handlers.cjs +2 -2
- package/dist/server/handlers.js +2 -2
- package/dist/server/server-adapter/index.cjs +27 -6
- package/dist/server/server-adapter/index.cjs.map +1 -1
- package/dist/server/server-adapter/index.d.ts +14 -1
- package/dist/server/server-adapter/index.d.ts.map +1 -1
- package/dist/server/server-adapter/index.js +27 -6
- package/dist/server/server-adapter/index.js.map +1 -1
- package/dist/server/server-adapter/openapi-utils.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/a2a.d.ts +544 -504
- package/dist/server/server-adapter/routes/a2a.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/agent-builder.d.ts +1054 -749
- package/dist/server/server-adapter/routes/agent-builder.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/channels.d.ts +153 -73
- package/dist/server/server-adapter/routes/channels.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/conversations.d.ts +218 -138
- package/dist/server/server-adapter/routes/conversations.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/datasets.d.ts +2312 -1877
- package/dist/server/server-adapter/routes/datasets.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/editor-builder.d.ts +506 -349
- package/dist/server/server-adapter/routes/editor-builder.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/legacy.d.ts +615 -629
- package/dist/server/server-adapter/routes/legacy.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/logs.d.ts +243 -183
- package/dist/server/server-adapter/routes/logs.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/mcp.d.ts +347 -147
- package/dist/server/server-adapter/routes/mcp.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/memory.d.ts +1699 -1199
- package/dist/server/server-adapter/routes/memory.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/observability.d.ts +2761 -2103
- package/dist/server/server-adapter/routes/observability.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/processor-providers.d.ts +70 -30
- package/dist/server/server-adapter/routes/processor-providers.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/processors.d.ts +220 -171
- package/dist/server/server-adapter/routes/processors.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/responses.d.ts +350 -360
- package/dist/server/server-adapter/routes/responses.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/route-builder.d.ts +6 -2
- package/dist/server/server-adapter/routes/route-builder.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/scorers.d.ts +282 -162
- package/dist/server/server-adapter/routes/scorers.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/stored-mcp-clients.d.ts +821 -588
- package/dist/server/server-adapter/routes/stored-mcp-clients.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/stored-prompt-blocks.d.ts +1252 -1064
- package/dist/server/server-adapter/routes/stored-prompt-blocks.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/stored-scorers.d.ts +1046 -822
- package/dist/server/server-adapter/routes/stored-scorers.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/stored-skills.d.ts +683 -526
- package/dist/server/server-adapter/routes/stored-skills.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/stored-workspaces.d.ts +637 -537
- package/dist/server/server-adapter/routes/stored-workspaces.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/system.d.ts +145 -105
- package/dist/server/server-adapter/routes/system.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/tool-providers.d.ts +566 -317
- package/dist/server/server-adapter/routes/tool-providers.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/tools.d.ts +103 -43
- package/dist/server/server-adapter/routes/tools.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/vectors.d.ts +275 -119
- package/dist/server/server-adapter/routes/vectors.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/workflows.d.ts +1586 -1104
- package/dist/server/server-adapter/routes/workflows.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/workspace.d.ts +1026 -613
- package/dist/server/server-adapter/routes/workspace.d.ts.map +1 -1
- package/package.json +6 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channels-CPTIswT2.js","names":[],"sources":["../src/server/schemas/channels.ts","../src/server/handlers/channels.ts"],"sourcesContent":["import { z } from 'zod/v4';\n\n// ============================================================================\n// Path Parameter Schemas\n// ============================================================================\n\nexport const channelPlatformPathParams = z.object({\n platform: z.string().describe('Channel platform identifier (e.g., \"slack\")'),\n});\n\nexport const channelAgentPathParams = z.object({\n platform: z.string().describe('Channel platform identifier (e.g., \"slack\")'),\n agentId: z.string().describe('Agent identifier'),\n});\n\n// ============================================================================\n// Body Parameter Schemas\n// ============================================================================\n\nexport const connectChannelBodySchema = z.object({\n agentId: z.string().describe('Agent identifier to connect'),\n options: z.record(z.string(), z.unknown()).optional().describe('Platform-specific connection options'),\n});\n\n// ============================================================================\n// Response Schemas\n// ============================================================================\n\nconst channelPlatformInfoSchema = z.object({\n id: z.string().describe('Platform identifier'),\n name: z.string().describe('Human-readable platform name'),\n isConfigured: z.boolean().describe('Whether the platform is ready to connect agents'),\n connectOptionsSchema: z.record(z.string(), z.unknown()).optional().describe('JSON Schema for connect options'),\n});\n\nconst channelInstallationInfoSchema = z.object({\n id: z.string().describe('Installation identifier'),\n platform: z.string().describe('Platform identifier'),\n agentId: z.string().describe('Connected agent identifier'),\n status: z.enum(['active', 'pending']).describe('Installation status'),\n displayName: z.string().optional().describe('Platform-specific display name'),\n installedAt: z.coerce.date().optional().describe('Installation timestamp'),\n});\n\nconst channelConnectOAuthSchema = z.object({\n type: z.literal('oauth').describe('OAuth-based connection requiring browser redirect'),\n authorizationUrl: z.string().describe('OAuth authorization URL for user redirect'),\n installationId: z.string().describe('Installation identifier'),\n});\n\nconst channelConnectDeepLinkSchema = z.object({\n type: z.literal('deep_link').describe('Deep-link connection requiring native app interaction'),\n url: z.string().describe('Deep link URL to open in platform app'),\n installationId: z.string().describe('Installation identifier'),\n});\n\nconst channelConnectImmediateSchema = z.object({\n type: z.literal('immediate').describe('Immediate connection with no user interaction needed'),\n installationId: z.string().describe('Installation identifier'),\n});\n\nconst channelConnectResultSchema = z.discriminatedUnion('type', [\n channelConnectOAuthSchema,\n channelConnectDeepLinkSchema,\n channelConnectImmediateSchema,\n]);\n\nexport const listChannelPlatformsResponseSchema = z.array(channelPlatformInfoSchema);\n\nexport const listChannelInstallationsResponseSchema = z.array(channelInstallationInfoSchema);\n\nexport const connectChannelResponseSchema = channelConnectResultSchema;\n\nexport const disconnectChannelResponseSchema = z.object({\n success: z.boolean(),\n});\n","import type { Mastra } from '@mastra/core';\nimport type { ChannelProvider } from '@mastra/core/channels';\nimport type { RequestContext } from '@mastra/core/di';\nimport { coreFeatures } from '@mastra/core/features';\n\nimport { MASTRA_USER_KEY } from '../constants';\nimport { HTTPException } from '../http-exception';\nimport {\n channelPlatformPathParams,\n channelAgentPathParams,\n connectChannelBodySchema,\n listChannelPlatformsResponseSchema,\n listChannelInstallationsResponseSchema,\n connectChannelResponseSchema,\n disconnectChannelResponseSchema,\n} from '../schemas/channels';\nimport { createRoute } from '../server-adapter/routes/route-builder';\n\nimport { assertWriteAccess, getCallerAuthorId, hasAdminBypass, hasScopedPermission } from './authorship';\nimport { handleError } from './error';\n\n// ============================================================================\n// Feature gate + helpers\n// ============================================================================\n\nfunction assertChannelsAvailable(): void {\n if (!coreFeatures.has('channels')) {\n throw new HTTPException(501, { message: 'Channels require a newer version of @mastra/core' });\n }\n}\n\nfunction getChannelOrThrow(mastra: Mastra, platform: string): ChannelProvider {\n const channels = Object.values(mastra.channels ?? {});\n const channel = channels.find(c => c.id === platform);\n if (!channel) {\n const available = channels.map(c => c.id).join(', ');\n throw new HTTPException(404, {\n message: `Channel \"${platform}\" is not registered. Available: ${available || 'none'}`,\n });\n }\n return channel;\n}\n\n/**\n * Unified connect/disconnect authorization.\n *\n * - Stored agent exists → same write access as editing the agent record.\n * - Code-defined agent (no stored record) → route's `requiresAuth` is the gate.\n * - Agent doesn't exist anywhere:\n * - connect → 404 (can't connect a channel to a non-existent agent)\n * - disconnect → orphan cleanup, gated on `channels:write`\n */\nasync function assertChannelAgentWriteAccess(\n mastra: Mastra,\n requestContext: RequestContext,\n agentId: string,\n action: 'connect' | 'disconnect',\n): Promise<void> {\n const storage = mastra.getStorage();\n const agentsStore = storage ? await storage.getStore('agents') : null;\n const stored = agentsStore ? await agentsStore.getById(agentId) : null;\n\n if (stored) {\n assertWriteAccess({\n requestContext,\n resource: 'agents',\n resourceId: agentId,\n action: 'edit',\n record: stored,\n });\n return;\n }\n\n // Not in stored-agents (or storage doesn't support it). Check the runtime\n // registry for a code-defined agent.\n const codeDefined = mastra.getAgentById(agentId);\n if (codeDefined) {\n // Code-defined agents have no owner/ACL — route's requiresAuth /\n // requiresPermission is the gate. Pass-through.\n return;\n }\n\n if (action === 'connect') {\n throw new HTTPException(404, { message: `Agent \"${agentId}\" not found` });\n }\n\n // Disconnect against an unknown agentId = orphan cleanup (stored agent was\n // deleted but the channel installation row is still around). Allow it, but\n // gate on channels:write so this isn't an \"any authenticated user\" backdoor.\n // Follow the same no-auth-configured pass-through as assertWriteAccess.\n const callerAuthorId = getCallerAuthorId(requestContext);\n if (!callerAuthorId && !requestContext.get(MASTRA_USER_KEY)) return;\n if (hasAdminBypass(requestContext, 'channels')) return;\n if (hasScopedPermission({ requestContext, resource: 'channels', action: 'write' })) return;\n\n throw new HTTPException(404, { message: 'Not found' });\n}\n\n// ============================================================================\n// Route Definitions\n// ============================================================================\n\n/**\n * GET /channels/platforms - List available channel platforms\n */\nexport const LIST_CHANNEL_PLATFORMS_ROUTE = createRoute({\n method: 'GET',\n path: '/channels/platforms',\n responseType: 'json',\n responseSchema: listChannelPlatformsResponseSchema,\n summary: 'List channel platforms',\n description: 'Returns available channel platforms and their configuration status',\n tags: ['Channels'],\n requiresAuth: true,\n handler: async ({ mastra }) => {\n assertChannelsAvailable();\n try {\n const channels = Object.values(mastra.channels ?? {});\n return channels.map(channel => {\n if (channel.getInfo) {\n return channel.getInfo();\n }\n return {\n id: channel.id,\n name: channel.id.charAt(0).toUpperCase() + channel.id.slice(1),\n isConfigured: true,\n };\n });\n } catch (error) {\n return handleError(error, 'Error listing channel platforms');\n }\n },\n});\n\n/**\n * GET /channels/:platform/installations - List installations for a platform\n */\nexport const LIST_CHANNEL_INSTALLATIONS_ROUTE = createRoute({\n method: 'GET',\n path: '/channels/:platform/installations',\n responseType: 'json',\n pathParamSchema: channelPlatformPathParams,\n responseSchema: listChannelInstallationsResponseSchema,\n summary: 'List channel installations',\n description: 'Returns all active and pending installations for a channel platform',\n tags: ['Channels'],\n requiresAuth: true,\n handler: async ({ mastra, platform }) => {\n assertChannelsAvailable();\n try {\n const channel = getChannelOrThrow(mastra, platform);\n\n if (!channel.listInstallations) {\n return [];\n }\n\n return await channel.listInstallations();\n } catch (error) {\n return handleError(error, 'Error listing channel installations');\n }\n },\n});\n\n/**\n * POST /channels/:platform/connect - Connect an agent to a platform\n */\nexport const CONNECT_CHANNEL_ROUTE = createRoute({\n method: 'POST',\n path: '/channels/:platform/connect',\n responseType: 'json',\n pathParamSchema: channelPlatformPathParams,\n bodySchema: connectChannelBodySchema,\n responseSchema: connectChannelResponseSchema,\n summary: 'Connect agent to channel',\n description: 'Creates a platform app for the agent and returns an OAuth authorization URL',\n tags: ['Channels'],\n requiresAuth: true,\n handler: async ({ mastra, requestContext, platform, agentId, options }) => {\n assertChannelsAvailable();\n try {\n const channel = getChannelOrThrow(mastra, platform);\n\n if (!channel.connect) {\n throw new HTTPException(400, {\n message: `Channel \"${platform}\" does not support programmatic connection`,\n });\n }\n\n await assertChannelAgentWriteAccess(mastra, requestContext, agentId, 'connect');\n\n return await channel.connect(agentId, options);\n } catch (error) {\n return handleError(error, 'Error connecting agent to channel');\n }\n },\n});\n\n/**\n * POST /channels/:platform/:agentId/disconnect - Disconnect an agent from a platform\n */\nexport const DISCONNECT_CHANNEL_ROUTE = createRoute({\n method: 'POST',\n path: '/channels/:platform/:agentId/disconnect',\n responseType: 'json',\n pathParamSchema: channelAgentPathParams,\n responseSchema: disconnectChannelResponseSchema,\n summary: 'Disconnect agent from channel',\n description: 'Deletes the platform app and cleans up the installation',\n tags: ['Channels'],\n requiresAuth: true,\n handler: async ({ mastra, requestContext, platform, agentId }) => {\n assertChannelsAvailable();\n try {\n const channel = getChannelOrThrow(mastra, platform);\n\n if (!channel.disconnect) {\n throw new HTTPException(400, {\n message: `Channel \"${platform}\" does not support programmatic disconnection`,\n });\n }\n\n await assertChannelAgentWriteAccess(mastra, requestContext, agentId, 'disconnect');\n\n await channel.disconnect(agentId);\n return { success: true };\n } catch (error) {\n return handleError(error, 'Error disconnecting agent from channel');\n }\n },\n});\n"],"mappings":";;;;;;;;AAMA,MAAa,4BAA4B,EAAE,OAAO,EAChD,UAAU,EAAE,OAAO,CAAC,CAAC,SAAS,+CAA6C,EAC7E,CAAC;AAED,MAAa,yBAAyB,EAAE,OAAO;CAC7C,UAAU,EAAE,OAAO,CAAC,CAAC,SAAS,+CAA6C;CAC3E,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS,kBAAkB;AACjD,CAAC;AAMD,MAAa,2BAA2B,EAAE,OAAO;CAC/C,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS,6BAA6B;CAC1D,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,sCAAsC;AACvG,CAAC;AAMD,MAAM,4BAA4B,EAAE,OAAO;CACzC,IAAI,EAAE,OAAO,CAAC,CAAC,SAAS,qBAAqB;CAC7C,MAAM,EAAE,OAAO,CAAC,CAAC,SAAS,8BAA8B;CACxD,cAAc,EAAE,QAAQ,CAAC,CAAC,SAAS,iDAAiD;CACpF,sBAAsB,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,iCAAiC;AAC/G,CAAC;AAED,MAAM,gCAAgC,EAAE,OAAO;CAC7C,IAAI,EAAE,OAAO,CAAC,CAAC,SAAS,yBAAyB;CACjD,UAAU,EAAE,OAAO,CAAC,CAAC,SAAS,qBAAqB;CACnD,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS,4BAA4B;CACzD,QAAQ,EAAE,KAAK,CAAC,UAAU,SAAS,CAAC,CAAC,CAAC,SAAS,qBAAqB;CACpE,aAAa,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,gCAAgC;CAC5E,aAAa,EAAE,OAAO,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,wBAAwB;AAC3E,CAAC;AAED,MAAM,4BAA4B,EAAE,OAAO;CACzC,MAAM,EAAE,QAAQ,OAAO,CAAC,CAAC,SAAS,mDAAmD;CACrF,kBAAkB,EAAE,OAAO,CAAC,CAAC,SAAS,2CAA2C;CACjF,gBAAgB,EAAE,OAAO,CAAC,CAAC,SAAS,yBAAyB;AAC/D,CAAC;AAED,MAAM,+BAA+B,EAAE,OAAO;CAC5C,MAAM,EAAE,QAAQ,WAAW,CAAC,CAAC,SAAS,uDAAuD;CAC7F,KAAK,EAAE,OAAO,CAAC,CAAC,SAAS,uCAAuC;CAChE,gBAAgB,EAAE,OAAO,CAAC,CAAC,SAAS,yBAAyB;AAC/D,CAAC;AAED,MAAM,gCAAgC,EAAE,OAAO;CAC7C,MAAM,EAAE,QAAQ,WAAW,CAAC,CAAC,SAAS,sDAAsD;CAC5F,gBAAgB,EAAE,OAAO,CAAC,CAAC,SAAS,yBAAyB;AAC/D,CAAC;AAED,MAAM,6BAA6B,EAAE,mBAAmB,QAAQ;CAC9D;CACA;CACA;AACF,CAAC;AAED,MAAa,qCAAqC,EAAE,MAAM,yBAAyB;AAEnF,MAAa,yCAAyC,EAAE,MAAM,6BAA6B;AAE3F,MAAa,+BAA+B;AAE5C,MAAa,kCAAkC,EAAE,OAAO,EACtD,SAAS,EAAE,QAAQ,EACrB,CAAC;;;AClDD,SAAS,0BAAgC;CACvC,IAAI,CAAC,aAAa,IAAI,UAAU,GAC9B,MAAM,IAAI,cAAc,KAAK,EAAE,SAAS,mDAAmD,CAAC;AAEhG;AAEA,SAAS,kBAAkB,QAAgB,UAAmC;CAC5E,MAAM,WAAW,OAAO,OAAO,OAAO,YAAY,CAAC,CAAC;CACpD,MAAM,UAAU,SAAS,MAAK,MAAK,EAAE,OAAO,QAAQ;CACpD,IAAI,CAAC,SAEH,MAAM,IAAI,cAAc,KAAK,EAC3B,SAAS,YAAY,SAAS,kCAFd,SAAS,KAAI,MAAK,EAAE,EAAE,CAAC,CAAC,KAAK,IAE2B,KAAK,SAC/E,CAAC;CAEH,OAAO;AACT;;;;;;;;;;AAWA,eAAe,8BACb,QACA,gBACA,SACA,QACe;CACf,MAAM,UAAU,OAAO,WAAW;CAClC,MAAM,cAAc,UAAU,MAAM,QAAQ,SAAS,QAAQ,IAAI;CACjE,MAAM,SAAS,cAAc,MAAM,YAAY,QAAQ,OAAO,IAAI;CAElE,IAAI,QAAQ;EACV,kBAAkB;GAChB;GACA,UAAU;GACV,YAAY;GACZ,QAAQ;GACR,QAAQ;EACV,CAAC;EACD;CACF;CAKA,IADoB,OAAO,aAAa,OAC1B,GAGZ;CAGF,IAAI,WAAW,WACb,MAAM,IAAI,cAAc,KAAK,EAAE,SAAS,UAAU,QAAQ,aAAa,CAAC;CAQ1E,IAAI,CADmB,kBAAkB,cACvB,KAAK,CAAC,eAAe,IAAA,cAAmB,GAAG;CAC7D,IAAI,eAAe,gBAAgB,UAAU,GAAG;CAChD,IAAI,oBAAoB;EAAE;EAAgB,UAAU;EAAY,QAAQ;CAAQ,CAAC,GAAG;CAEpF,MAAM,IAAI,cAAc,KAAK,EAAE,SAAS,YAAY,CAAC;AACvD;;;;AASA,MAAa,+BAA+B,YAAY;CACtD,QAAQ;CACR,MAAM;CACN,cAAc;CACd,gBAAgB;CAChB,SAAS;CACT,aAAa;CACb,MAAM,CAAC,UAAU;CACjB,cAAc;CACd,SAAS,OAAO,EAAE,aAAa;EAC7B,wBAAwB;EACxB,IAAI;GAEF,OADiB,OAAO,OAAO,OAAO,YAAY,CAAC,CACrC,CAAC,CAAC,KAAI,YAAW;IAC7B,IAAI,QAAQ,SACV,OAAO,QAAQ,QAAQ;IAEzB,OAAO;KACL,IAAI,QAAQ;KACZ,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,QAAQ,GAAG,MAAM,CAAC;KAC7D,cAAc;IAChB;GACF,CAAC;EACH,SAAS,OAAO;GACd,OAAO,YAAY,OAAO,iCAAiC;EAC7D;CACF;AACF,CAAC;;;;AAKD,MAAa,mCAAmC,YAAY;CAC1D,QAAQ;CACR,MAAM;CACN,cAAc;CACd,iBAAiB;CACjB,gBAAgB;CAChB,SAAS;CACT,aAAa;CACb,MAAM,CAAC,UAAU;CACjB,cAAc;CACd,SAAS,OAAO,EAAE,QAAQ,eAAe;EACvC,wBAAwB;EACxB,IAAI;GACF,MAAM,UAAU,kBAAkB,QAAQ,QAAQ;GAElD,IAAI,CAAC,QAAQ,mBACX,OAAO,CAAC;GAGV,OAAO,MAAM,QAAQ,kBAAkB;EACzC,SAAS,OAAO;GACd,OAAO,YAAY,OAAO,qCAAqC;EACjE;CACF;AACF,CAAC;;;;AAKD,MAAa,wBAAwB,YAAY;CAC/C,QAAQ;CACR,MAAM;CACN,cAAc;CACd,iBAAiB;CACjB,YAAY;CACZ,gBAAgB;CAChB,SAAS;CACT,aAAa;CACb,MAAM,CAAC,UAAU;CACjB,cAAc;CACd,SAAS,OAAO,EAAE,QAAQ,gBAAgB,UAAU,SAAS,cAAc;EACzE,wBAAwB;EACxB,IAAI;GACF,MAAM,UAAU,kBAAkB,QAAQ,QAAQ;GAElD,IAAI,CAAC,QAAQ,SACX,MAAM,IAAI,cAAc,KAAK,EAC3B,SAAS,YAAY,SAAS,4CAChC,CAAC;GAGH,MAAM,8BAA8B,QAAQ,gBAAgB,SAAS,SAAS;GAE9E,OAAO,MAAM,QAAQ,QAAQ,SAAS,OAAO;EAC/C,SAAS,OAAO;GACd,OAAO,YAAY,OAAO,mCAAmC;EAC/D;CACF;AACF,CAAC;;;;AAKD,MAAa,2BAA2B,YAAY;CAClD,QAAQ;CACR,MAAM;CACN,cAAc;CACd,iBAAiB;CACjB,gBAAgB;CAChB,SAAS;CACT,aAAa;CACb,MAAM,CAAC,UAAU;CACjB,cAAc;CACd,SAAS,OAAO,EAAE,QAAQ,gBAAgB,UAAU,cAAc;EAChE,wBAAwB;EACxB,IAAI;GACF,MAAM,UAAU,kBAAkB,QAAQ,QAAQ;GAElD,IAAI,CAAC,QAAQ,YACX,MAAM,IAAI,cAAc,KAAK,EAC3B,SAAS,YAAY,SAAS,+CAChC,CAAC;GAGH,MAAM,8BAA8B,QAAQ,gBAAgB,SAAS,YAAY;GAEjF,MAAM,QAAQ,WAAW,OAAO;GAChC,OAAO,EAAE,SAAS,KAAK;EACzB,SAAS,OAAO;GACd,OAAO,YAAY,OAAO,wCAAwC;EACpE;CACF;AACF,CAAC"}
|
|
1
|
+
{"version":3,"file":"channels-B9yt3a2P.js","names":[],"sources":["../src/server/schemas/channels.ts","../src/server/handlers/channels.ts"],"sourcesContent":["import { z } from 'zod/v4';\n\n// ============================================================================\n// Path Parameter Schemas\n// ============================================================================\n\nexport const channelPlatformPathParams = z.object({\n platform: z.string().describe('Channel platform identifier (e.g., \"slack\")'),\n});\n\nexport const channelAgentPathParams = z.object({\n platform: z.string().describe('Channel platform identifier (e.g., \"slack\")'),\n agentId: z.string().describe('Agent identifier'),\n});\n\n// ============================================================================\n// Body Parameter Schemas\n// ============================================================================\n\nexport const connectChannelBodySchema = z.object({\n agentId: z.string().describe('Agent identifier to connect'),\n options: z.record(z.string(), z.unknown()).optional().describe('Platform-specific connection options'),\n});\n\n// ============================================================================\n// Response Schemas\n// ============================================================================\n\nconst channelPlatformInfoSchema = z.object({\n id: z.string().describe('Platform identifier'),\n name: z.string().describe('Human-readable platform name'),\n isConfigured: z.boolean().describe('Whether the platform is ready to connect agents'),\n connectOptionsSchema: z.record(z.string(), z.unknown()).optional().describe('JSON Schema for connect options'),\n});\n\nconst channelInstallationInfoSchema = z.object({\n id: z.string().describe('Installation identifier'),\n platform: z.string().describe('Platform identifier'),\n agentId: z.string().describe('Connected agent identifier'),\n status: z.enum(['active', 'pending']).describe('Installation status'),\n displayName: z.string().optional().describe('Platform-specific display name'),\n installedAt: z.coerce.date().optional().describe('Installation timestamp'),\n});\n\nconst channelConnectOAuthSchema = z.object({\n type: z.literal('oauth').describe('OAuth-based connection requiring browser redirect'),\n authorizationUrl: z.string().describe('OAuth authorization URL for user redirect'),\n installationId: z.string().describe('Installation identifier'),\n});\n\nconst channelConnectDeepLinkSchema = z.object({\n type: z.literal('deep_link').describe('Deep-link connection requiring native app interaction'),\n url: z.string().describe('Deep link URL to open in platform app'),\n installationId: z.string().describe('Installation identifier'),\n});\n\nconst channelConnectImmediateSchema = z.object({\n type: z.literal('immediate').describe('Immediate connection with no user interaction needed'),\n installationId: z.string().describe('Installation identifier'),\n});\n\nconst channelConnectResultSchema = z.discriminatedUnion('type', [\n channelConnectOAuthSchema,\n channelConnectDeepLinkSchema,\n channelConnectImmediateSchema,\n]);\n\nexport const listChannelPlatformsResponseSchema = z.array(channelPlatformInfoSchema);\n\nexport const listChannelInstallationsResponseSchema = z.array(channelInstallationInfoSchema);\n\nexport const connectChannelResponseSchema = channelConnectResultSchema;\n\nexport const disconnectChannelResponseSchema = z.object({\n success: z.boolean(),\n});\n","import type { Mastra } from '@mastra/core';\nimport type { ChannelProvider } from '@mastra/core/channels';\nimport type { RequestContext } from '@mastra/core/di';\nimport { coreFeatures } from '@mastra/core/features';\n\nimport { MASTRA_USER_KEY } from '../constants';\nimport { HTTPException } from '../http-exception';\nimport {\n channelPlatformPathParams,\n channelAgentPathParams,\n connectChannelBodySchema,\n listChannelPlatformsResponseSchema,\n listChannelInstallationsResponseSchema,\n connectChannelResponseSchema,\n disconnectChannelResponseSchema,\n} from '../schemas/channels';\nimport { createRoute } from '../server-adapter/routes/route-builder';\n\nimport { assertWriteAccess, getCallerAuthorId, hasAdminBypass, hasScopedPermission } from './authorship';\nimport { handleError } from './error';\n\n// ============================================================================\n// Feature gate + helpers\n// ============================================================================\n\nfunction assertChannelsAvailable(): void {\n if (!coreFeatures.has('channels')) {\n throw new HTTPException(501, { message: 'Channels require a newer version of @mastra/core' });\n }\n}\n\nfunction getChannelOrThrow(mastra: Mastra, platform: string): ChannelProvider {\n const channels = Object.values(mastra.channels ?? {});\n const channel = channels.find(c => c.id === platform);\n if (!channel) {\n const available = channels.map(c => c.id).join(', ');\n throw new HTTPException(404, {\n message: `Channel \"${platform}\" is not registered. Available: ${available || 'none'}`,\n });\n }\n return channel;\n}\n\n/**\n * Unified connect/disconnect authorization.\n *\n * - Stored agent exists → same write access as editing the agent record.\n * - Code-defined agent (no stored record) → route's `requiresAuth` is the gate.\n * - Agent doesn't exist anywhere:\n * - connect → 404 (can't connect a channel to a non-existent agent)\n * - disconnect → orphan cleanup, gated on `channels:write`\n */\nasync function assertChannelAgentWriteAccess(\n mastra: Mastra,\n requestContext: RequestContext,\n agentId: string,\n action: 'connect' | 'disconnect',\n): Promise<void> {\n const storage = mastra.getStorage();\n const agentsStore = storage ? await storage.getStore('agents') : null;\n const stored = agentsStore ? await agentsStore.getById(agentId) : null;\n\n if (stored) {\n assertWriteAccess({\n requestContext,\n resource: 'agents',\n resourceId: agentId,\n action: 'edit',\n record: stored,\n });\n return;\n }\n\n // Not in stored-agents (or storage doesn't support it). Check the runtime\n // registry for a code-defined agent.\n const codeDefined = mastra.getAgentById(agentId);\n if (codeDefined) {\n // Code-defined agents have no owner/ACL — route's requiresAuth /\n // requiresPermission is the gate. Pass-through.\n return;\n }\n\n if (action === 'connect') {\n throw new HTTPException(404, { message: `Agent \"${agentId}\" not found` });\n }\n\n // Disconnect against an unknown agentId = orphan cleanup (stored agent was\n // deleted but the channel installation row is still around). Allow it, but\n // gate on channels:write so this isn't an \"any authenticated user\" backdoor.\n // Follow the same no-auth-configured pass-through as assertWriteAccess.\n const callerAuthorId = getCallerAuthorId(requestContext);\n if (!callerAuthorId && !requestContext.get(MASTRA_USER_KEY)) return;\n if (hasAdminBypass(requestContext, 'channels')) return;\n if (hasScopedPermission({ requestContext, resource: 'channels', action: 'write' })) return;\n\n throw new HTTPException(404, { message: 'Not found' });\n}\n\n// ============================================================================\n// Route Definitions\n// ============================================================================\n\n/**\n * GET /channels/platforms - List available channel platforms\n */\nexport const LIST_CHANNEL_PLATFORMS_ROUTE = createRoute({\n method: 'GET',\n path: '/channels/platforms',\n responseType: 'json',\n responseSchema: listChannelPlatformsResponseSchema,\n summary: 'List channel platforms',\n description: 'Returns available channel platforms and their configuration status',\n tags: ['Channels'],\n requiresAuth: true,\n handler: async ({ mastra }) => {\n assertChannelsAvailable();\n try {\n const channels = Object.values(mastra.channels ?? {});\n return channels.map(channel => {\n if (channel.getInfo) {\n return channel.getInfo();\n }\n return {\n id: channel.id,\n name: channel.id.charAt(0).toUpperCase() + channel.id.slice(1),\n isConfigured: true,\n };\n });\n } catch (error) {\n return handleError(error, 'Error listing channel platforms');\n }\n },\n});\n\n/**\n * GET /channels/:platform/installations - List installations for a platform\n */\nexport const LIST_CHANNEL_INSTALLATIONS_ROUTE = createRoute({\n method: 'GET',\n path: '/channels/:platform/installations',\n responseType: 'json',\n pathParamSchema: channelPlatformPathParams,\n responseSchema: listChannelInstallationsResponseSchema,\n summary: 'List channel installations',\n description: 'Returns all active and pending installations for a channel platform',\n tags: ['Channels'],\n requiresAuth: true,\n handler: async ({ mastra, platform }) => {\n assertChannelsAvailable();\n try {\n const channel = getChannelOrThrow(mastra, platform);\n\n if (!channel.listInstallations) {\n return [];\n }\n\n return await channel.listInstallations();\n } catch (error) {\n return handleError(error, 'Error listing channel installations');\n }\n },\n});\n\n/**\n * POST /channels/:platform/connect - Connect an agent to a platform\n */\nexport const CONNECT_CHANNEL_ROUTE = createRoute({\n method: 'POST',\n path: '/channels/:platform/connect',\n responseType: 'json',\n pathParamSchema: channelPlatformPathParams,\n bodySchema: connectChannelBodySchema,\n responseSchema: connectChannelResponseSchema,\n summary: 'Connect agent to channel',\n description: 'Creates a platform app for the agent and returns an OAuth authorization URL',\n tags: ['Channels'],\n requiresAuth: true,\n handler: async ({ mastra, requestContext, platform, agentId, options }) => {\n assertChannelsAvailable();\n try {\n const channel = getChannelOrThrow(mastra, platform);\n\n if (!channel.connect) {\n throw new HTTPException(400, {\n message: `Channel \"${platform}\" does not support programmatic connection`,\n });\n }\n\n await assertChannelAgentWriteAccess(mastra, requestContext, agentId, 'connect');\n\n return await channel.connect(agentId, options);\n } catch (error) {\n return handleError(error, 'Error connecting agent to channel');\n }\n },\n});\n\n/**\n * POST /channels/:platform/:agentId/disconnect - Disconnect an agent from a platform\n */\nexport const DISCONNECT_CHANNEL_ROUTE = createRoute({\n method: 'POST',\n path: '/channels/:platform/:agentId/disconnect',\n responseType: 'json',\n pathParamSchema: channelAgentPathParams,\n responseSchema: disconnectChannelResponseSchema,\n summary: 'Disconnect agent from channel',\n description: 'Deletes the platform app and cleans up the installation',\n tags: ['Channels'],\n requiresAuth: true,\n handler: async ({ mastra, requestContext, platform, agentId }) => {\n assertChannelsAvailable();\n try {\n const channel = getChannelOrThrow(mastra, platform);\n\n if (!channel.disconnect) {\n throw new HTTPException(400, {\n message: `Channel \"${platform}\" does not support programmatic disconnection`,\n });\n }\n\n await assertChannelAgentWriteAccess(mastra, requestContext, agentId, 'disconnect');\n\n await channel.disconnect(agentId);\n return { success: true };\n } catch (error) {\n return handleError(error, 'Error disconnecting agent from channel');\n }\n },\n});\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_http_exception = require("./http-exception-CKDHupKw.cjs");
|
|
2
|
-
const require_route_builder = require("./route-builder-
|
|
2
|
+
const require_route_builder = require("./route-builder-BAAedfru.cjs");
|
|
3
3
|
require("./constants-ChBaIptn.cjs");
|
|
4
4
|
const require_server_handlers_error = require("./server/handlers/error.cjs");
|
|
5
5
|
const require_server_handlers_authorship = require("./server/handlers/authorship.cjs");
|
|
@@ -227,4 +227,4 @@ Object.defineProperty(exports, "LIST_CHANNEL_PLATFORMS_ROUTE", {
|
|
|
227
227
|
}
|
|
228
228
|
});
|
|
229
229
|
|
|
230
|
-
//# sourceMappingURL=channels-
|
|
230
|
+
//# sourceMappingURL=channels-BRoq3VKR.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channels-FoIf30Hv.cjs","names":["z","coreFeatures","HTTPException","getCallerAuthorId","hasAdminBypass","hasScopedPermission","createRoute","handleError"],"sources":["../src/server/schemas/channels.ts","../src/server/handlers/channels.ts"],"sourcesContent":["import { z } from 'zod/v4';\n\n// ============================================================================\n// Path Parameter Schemas\n// ============================================================================\n\nexport const channelPlatformPathParams = z.object({\n platform: z.string().describe('Channel platform identifier (e.g., \"slack\")'),\n});\n\nexport const channelAgentPathParams = z.object({\n platform: z.string().describe('Channel platform identifier (e.g., \"slack\")'),\n agentId: z.string().describe('Agent identifier'),\n});\n\n// ============================================================================\n// Body Parameter Schemas\n// ============================================================================\n\nexport const connectChannelBodySchema = z.object({\n agentId: z.string().describe('Agent identifier to connect'),\n options: z.record(z.string(), z.unknown()).optional().describe('Platform-specific connection options'),\n});\n\n// ============================================================================\n// Response Schemas\n// ============================================================================\n\nconst channelPlatformInfoSchema = z.object({\n id: z.string().describe('Platform identifier'),\n name: z.string().describe('Human-readable platform name'),\n isConfigured: z.boolean().describe('Whether the platform is ready to connect agents'),\n connectOptionsSchema: z.record(z.string(), z.unknown()).optional().describe('JSON Schema for connect options'),\n});\n\nconst channelInstallationInfoSchema = z.object({\n id: z.string().describe('Installation identifier'),\n platform: z.string().describe('Platform identifier'),\n agentId: z.string().describe('Connected agent identifier'),\n status: z.enum(['active', 'pending']).describe('Installation status'),\n displayName: z.string().optional().describe('Platform-specific display name'),\n installedAt: z.coerce.date().optional().describe('Installation timestamp'),\n});\n\nconst channelConnectOAuthSchema = z.object({\n type: z.literal('oauth').describe('OAuth-based connection requiring browser redirect'),\n authorizationUrl: z.string().describe('OAuth authorization URL for user redirect'),\n installationId: z.string().describe('Installation identifier'),\n});\n\nconst channelConnectDeepLinkSchema = z.object({\n type: z.literal('deep_link').describe('Deep-link connection requiring native app interaction'),\n url: z.string().describe('Deep link URL to open in platform app'),\n installationId: z.string().describe('Installation identifier'),\n});\n\nconst channelConnectImmediateSchema = z.object({\n type: z.literal('immediate').describe('Immediate connection with no user interaction needed'),\n installationId: z.string().describe('Installation identifier'),\n});\n\nconst channelConnectResultSchema = z.discriminatedUnion('type', [\n channelConnectOAuthSchema,\n channelConnectDeepLinkSchema,\n channelConnectImmediateSchema,\n]);\n\nexport const listChannelPlatformsResponseSchema = z.array(channelPlatformInfoSchema);\n\nexport const listChannelInstallationsResponseSchema = z.array(channelInstallationInfoSchema);\n\nexport const connectChannelResponseSchema = channelConnectResultSchema;\n\nexport const disconnectChannelResponseSchema = z.object({\n success: z.boolean(),\n});\n","import type { Mastra } from '@mastra/core';\nimport type { ChannelProvider } from '@mastra/core/channels';\nimport type { RequestContext } from '@mastra/core/di';\nimport { coreFeatures } from '@mastra/core/features';\n\nimport { MASTRA_USER_KEY } from '../constants';\nimport { HTTPException } from '../http-exception';\nimport {\n channelPlatformPathParams,\n channelAgentPathParams,\n connectChannelBodySchema,\n listChannelPlatformsResponseSchema,\n listChannelInstallationsResponseSchema,\n connectChannelResponseSchema,\n disconnectChannelResponseSchema,\n} from '../schemas/channels';\nimport { createRoute } from '../server-adapter/routes/route-builder';\n\nimport { assertWriteAccess, getCallerAuthorId, hasAdminBypass, hasScopedPermission } from './authorship';\nimport { handleError } from './error';\n\n// ============================================================================\n// Feature gate + helpers\n// ============================================================================\n\nfunction assertChannelsAvailable(): void {\n if (!coreFeatures.has('channels')) {\n throw new HTTPException(501, { message: 'Channels require a newer version of @mastra/core' });\n }\n}\n\nfunction getChannelOrThrow(mastra: Mastra, platform: string): ChannelProvider {\n const channels = Object.values(mastra.channels ?? {});\n const channel = channels.find(c => c.id === platform);\n if (!channel) {\n const available = channels.map(c => c.id).join(', ');\n throw new HTTPException(404, {\n message: `Channel \"${platform}\" is not registered. Available: ${available || 'none'}`,\n });\n }\n return channel;\n}\n\n/**\n * Unified connect/disconnect authorization.\n *\n * - Stored agent exists → same write access as editing the agent record.\n * - Code-defined agent (no stored record) → route's `requiresAuth` is the gate.\n * - Agent doesn't exist anywhere:\n * - connect → 404 (can't connect a channel to a non-existent agent)\n * - disconnect → orphan cleanup, gated on `channels:write`\n */\nasync function assertChannelAgentWriteAccess(\n mastra: Mastra,\n requestContext: RequestContext,\n agentId: string,\n action: 'connect' | 'disconnect',\n): Promise<void> {\n const storage = mastra.getStorage();\n const agentsStore = storage ? await storage.getStore('agents') : null;\n const stored = agentsStore ? await agentsStore.getById(agentId) : null;\n\n if (stored) {\n assertWriteAccess({\n requestContext,\n resource: 'agents',\n resourceId: agentId,\n action: 'edit',\n record: stored,\n });\n return;\n }\n\n // Not in stored-agents (or storage doesn't support it). Check the runtime\n // registry for a code-defined agent.\n const codeDefined = mastra.getAgentById(agentId);\n if (codeDefined) {\n // Code-defined agents have no owner/ACL — route's requiresAuth /\n // requiresPermission is the gate. Pass-through.\n return;\n }\n\n if (action === 'connect') {\n throw new HTTPException(404, { message: `Agent \"${agentId}\" not found` });\n }\n\n // Disconnect against an unknown agentId = orphan cleanup (stored agent was\n // deleted but the channel installation row is still around). Allow it, but\n // gate on channels:write so this isn't an \"any authenticated user\" backdoor.\n // Follow the same no-auth-configured pass-through as assertWriteAccess.\n const callerAuthorId = getCallerAuthorId(requestContext);\n if (!callerAuthorId && !requestContext.get(MASTRA_USER_KEY)) return;\n if (hasAdminBypass(requestContext, 'channels')) return;\n if (hasScopedPermission({ requestContext, resource: 'channels', action: 'write' })) return;\n\n throw new HTTPException(404, { message: 'Not found' });\n}\n\n// ============================================================================\n// Route Definitions\n// ============================================================================\n\n/**\n * GET /channels/platforms - List available channel platforms\n */\nexport const LIST_CHANNEL_PLATFORMS_ROUTE = createRoute({\n method: 'GET',\n path: '/channels/platforms',\n responseType: 'json',\n responseSchema: listChannelPlatformsResponseSchema,\n summary: 'List channel platforms',\n description: 'Returns available channel platforms and their configuration status',\n tags: ['Channels'],\n requiresAuth: true,\n handler: async ({ mastra }) => {\n assertChannelsAvailable();\n try {\n const channels = Object.values(mastra.channels ?? {});\n return channels.map(channel => {\n if (channel.getInfo) {\n return channel.getInfo();\n }\n return {\n id: channel.id,\n name: channel.id.charAt(0).toUpperCase() + channel.id.slice(1),\n isConfigured: true,\n };\n });\n } catch (error) {\n return handleError(error, 'Error listing channel platforms');\n }\n },\n});\n\n/**\n * GET /channels/:platform/installations - List installations for a platform\n */\nexport const LIST_CHANNEL_INSTALLATIONS_ROUTE = createRoute({\n method: 'GET',\n path: '/channels/:platform/installations',\n responseType: 'json',\n pathParamSchema: channelPlatformPathParams,\n responseSchema: listChannelInstallationsResponseSchema,\n summary: 'List channel installations',\n description: 'Returns all active and pending installations for a channel platform',\n tags: ['Channels'],\n requiresAuth: true,\n handler: async ({ mastra, platform }) => {\n assertChannelsAvailable();\n try {\n const channel = getChannelOrThrow(mastra, platform);\n\n if (!channel.listInstallations) {\n return [];\n }\n\n return await channel.listInstallations();\n } catch (error) {\n return handleError(error, 'Error listing channel installations');\n }\n },\n});\n\n/**\n * POST /channels/:platform/connect - Connect an agent to a platform\n */\nexport const CONNECT_CHANNEL_ROUTE = createRoute({\n method: 'POST',\n path: '/channels/:platform/connect',\n responseType: 'json',\n pathParamSchema: channelPlatformPathParams,\n bodySchema: connectChannelBodySchema,\n responseSchema: connectChannelResponseSchema,\n summary: 'Connect agent to channel',\n description: 'Creates a platform app for the agent and returns an OAuth authorization URL',\n tags: ['Channels'],\n requiresAuth: true,\n handler: async ({ mastra, requestContext, platform, agentId, options }) => {\n assertChannelsAvailable();\n try {\n const channel = getChannelOrThrow(mastra, platform);\n\n if (!channel.connect) {\n throw new HTTPException(400, {\n message: `Channel \"${platform}\" does not support programmatic connection`,\n });\n }\n\n await assertChannelAgentWriteAccess(mastra, requestContext, agentId, 'connect');\n\n return await channel.connect(agentId, options);\n } catch (error) {\n return handleError(error, 'Error connecting agent to channel');\n }\n },\n});\n\n/**\n * POST /channels/:platform/:agentId/disconnect - Disconnect an agent from a platform\n */\nexport const DISCONNECT_CHANNEL_ROUTE = createRoute({\n method: 'POST',\n path: '/channels/:platform/:agentId/disconnect',\n responseType: 'json',\n pathParamSchema: channelAgentPathParams,\n responseSchema: disconnectChannelResponseSchema,\n summary: 'Disconnect agent from channel',\n description: 'Deletes the platform app and cleans up the installation',\n tags: ['Channels'],\n requiresAuth: true,\n handler: async ({ mastra, requestContext, platform, agentId }) => {\n assertChannelsAvailable();\n try {\n const channel = getChannelOrThrow(mastra, platform);\n\n if (!channel.disconnect) {\n throw new HTTPException(400, {\n message: `Channel \"${platform}\" does not support programmatic disconnection`,\n });\n }\n\n await assertChannelAgentWriteAccess(mastra, requestContext, agentId, 'disconnect');\n\n await channel.disconnect(agentId);\n return { success: true };\n } catch (error) {\n return handleError(error, 'Error disconnecting agent from channel');\n }\n },\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"channels-BRoq3VKR.cjs","names":["z","coreFeatures","HTTPException","getCallerAuthorId","hasAdminBypass","hasScopedPermission","createRoute","handleError"],"sources":["../src/server/schemas/channels.ts","../src/server/handlers/channels.ts"],"sourcesContent":["import { z } from 'zod/v4';\n\n// ============================================================================\n// Path Parameter Schemas\n// ============================================================================\n\nexport const channelPlatformPathParams = z.object({\n platform: z.string().describe('Channel platform identifier (e.g., \"slack\")'),\n});\n\nexport const channelAgentPathParams = z.object({\n platform: z.string().describe('Channel platform identifier (e.g., \"slack\")'),\n agentId: z.string().describe('Agent identifier'),\n});\n\n// ============================================================================\n// Body Parameter Schemas\n// ============================================================================\n\nexport const connectChannelBodySchema = z.object({\n agentId: z.string().describe('Agent identifier to connect'),\n options: z.record(z.string(), z.unknown()).optional().describe('Platform-specific connection options'),\n});\n\n// ============================================================================\n// Response Schemas\n// ============================================================================\n\nconst channelPlatformInfoSchema = z.object({\n id: z.string().describe('Platform identifier'),\n name: z.string().describe('Human-readable platform name'),\n isConfigured: z.boolean().describe('Whether the platform is ready to connect agents'),\n connectOptionsSchema: z.record(z.string(), z.unknown()).optional().describe('JSON Schema for connect options'),\n});\n\nconst channelInstallationInfoSchema = z.object({\n id: z.string().describe('Installation identifier'),\n platform: z.string().describe('Platform identifier'),\n agentId: z.string().describe('Connected agent identifier'),\n status: z.enum(['active', 'pending']).describe('Installation status'),\n displayName: z.string().optional().describe('Platform-specific display name'),\n installedAt: z.coerce.date().optional().describe('Installation timestamp'),\n});\n\nconst channelConnectOAuthSchema = z.object({\n type: z.literal('oauth').describe('OAuth-based connection requiring browser redirect'),\n authorizationUrl: z.string().describe('OAuth authorization URL for user redirect'),\n installationId: z.string().describe('Installation identifier'),\n});\n\nconst channelConnectDeepLinkSchema = z.object({\n type: z.literal('deep_link').describe('Deep-link connection requiring native app interaction'),\n url: z.string().describe('Deep link URL to open in platform app'),\n installationId: z.string().describe('Installation identifier'),\n});\n\nconst channelConnectImmediateSchema = z.object({\n type: z.literal('immediate').describe('Immediate connection with no user interaction needed'),\n installationId: z.string().describe('Installation identifier'),\n});\n\nconst channelConnectResultSchema = z.discriminatedUnion('type', [\n channelConnectOAuthSchema,\n channelConnectDeepLinkSchema,\n channelConnectImmediateSchema,\n]);\n\nexport const listChannelPlatformsResponseSchema = z.array(channelPlatformInfoSchema);\n\nexport const listChannelInstallationsResponseSchema = z.array(channelInstallationInfoSchema);\n\nexport const connectChannelResponseSchema = channelConnectResultSchema;\n\nexport const disconnectChannelResponseSchema = z.object({\n success: z.boolean(),\n});\n","import type { Mastra } from '@mastra/core';\nimport type { ChannelProvider } from '@mastra/core/channels';\nimport type { RequestContext } from '@mastra/core/di';\nimport { coreFeatures } from '@mastra/core/features';\n\nimport { MASTRA_USER_KEY } from '../constants';\nimport { HTTPException } from '../http-exception';\nimport {\n channelPlatformPathParams,\n channelAgentPathParams,\n connectChannelBodySchema,\n listChannelPlatformsResponseSchema,\n listChannelInstallationsResponseSchema,\n connectChannelResponseSchema,\n disconnectChannelResponseSchema,\n} from '../schemas/channels';\nimport { createRoute } from '../server-adapter/routes/route-builder';\n\nimport { assertWriteAccess, getCallerAuthorId, hasAdminBypass, hasScopedPermission } from './authorship';\nimport { handleError } from './error';\n\n// ============================================================================\n// Feature gate + helpers\n// ============================================================================\n\nfunction assertChannelsAvailable(): void {\n if (!coreFeatures.has('channels')) {\n throw new HTTPException(501, { message: 'Channels require a newer version of @mastra/core' });\n }\n}\n\nfunction getChannelOrThrow(mastra: Mastra, platform: string): ChannelProvider {\n const channels = Object.values(mastra.channels ?? {});\n const channel = channels.find(c => c.id === platform);\n if (!channel) {\n const available = channels.map(c => c.id).join(', ');\n throw new HTTPException(404, {\n message: `Channel \"${platform}\" is not registered. Available: ${available || 'none'}`,\n });\n }\n return channel;\n}\n\n/**\n * Unified connect/disconnect authorization.\n *\n * - Stored agent exists → same write access as editing the agent record.\n * - Code-defined agent (no stored record) → route's `requiresAuth` is the gate.\n * - Agent doesn't exist anywhere:\n * - connect → 404 (can't connect a channel to a non-existent agent)\n * - disconnect → orphan cleanup, gated on `channels:write`\n */\nasync function assertChannelAgentWriteAccess(\n mastra: Mastra,\n requestContext: RequestContext,\n agentId: string,\n action: 'connect' | 'disconnect',\n): Promise<void> {\n const storage = mastra.getStorage();\n const agentsStore = storage ? await storage.getStore('agents') : null;\n const stored = agentsStore ? await agentsStore.getById(agentId) : null;\n\n if (stored) {\n assertWriteAccess({\n requestContext,\n resource: 'agents',\n resourceId: agentId,\n action: 'edit',\n record: stored,\n });\n return;\n }\n\n // Not in stored-agents (or storage doesn't support it). Check the runtime\n // registry for a code-defined agent.\n const codeDefined = mastra.getAgentById(agentId);\n if (codeDefined) {\n // Code-defined agents have no owner/ACL — route's requiresAuth /\n // requiresPermission is the gate. Pass-through.\n return;\n }\n\n if (action === 'connect') {\n throw new HTTPException(404, { message: `Agent \"${agentId}\" not found` });\n }\n\n // Disconnect against an unknown agentId = orphan cleanup (stored agent was\n // deleted but the channel installation row is still around). Allow it, but\n // gate on channels:write so this isn't an \"any authenticated user\" backdoor.\n // Follow the same no-auth-configured pass-through as assertWriteAccess.\n const callerAuthorId = getCallerAuthorId(requestContext);\n if (!callerAuthorId && !requestContext.get(MASTRA_USER_KEY)) return;\n if (hasAdminBypass(requestContext, 'channels')) return;\n if (hasScopedPermission({ requestContext, resource: 'channels', action: 'write' })) return;\n\n throw new HTTPException(404, { message: 'Not found' });\n}\n\n// ============================================================================\n// Route Definitions\n// ============================================================================\n\n/**\n * GET /channels/platforms - List available channel platforms\n */\nexport const LIST_CHANNEL_PLATFORMS_ROUTE = createRoute({\n method: 'GET',\n path: '/channels/platforms',\n responseType: 'json',\n responseSchema: listChannelPlatformsResponseSchema,\n summary: 'List channel platforms',\n description: 'Returns available channel platforms and their configuration status',\n tags: ['Channels'],\n requiresAuth: true,\n handler: async ({ mastra }) => {\n assertChannelsAvailable();\n try {\n const channels = Object.values(mastra.channels ?? {});\n return channels.map(channel => {\n if (channel.getInfo) {\n return channel.getInfo();\n }\n return {\n id: channel.id,\n name: channel.id.charAt(0).toUpperCase() + channel.id.slice(1),\n isConfigured: true,\n };\n });\n } catch (error) {\n return handleError(error, 'Error listing channel platforms');\n }\n },\n});\n\n/**\n * GET /channels/:platform/installations - List installations for a platform\n */\nexport const LIST_CHANNEL_INSTALLATIONS_ROUTE = createRoute({\n method: 'GET',\n path: '/channels/:platform/installations',\n responseType: 'json',\n pathParamSchema: channelPlatformPathParams,\n responseSchema: listChannelInstallationsResponseSchema,\n summary: 'List channel installations',\n description: 'Returns all active and pending installations for a channel platform',\n tags: ['Channels'],\n requiresAuth: true,\n handler: async ({ mastra, platform }) => {\n assertChannelsAvailable();\n try {\n const channel = getChannelOrThrow(mastra, platform);\n\n if (!channel.listInstallations) {\n return [];\n }\n\n return await channel.listInstallations();\n } catch (error) {\n return handleError(error, 'Error listing channel installations');\n }\n },\n});\n\n/**\n * POST /channels/:platform/connect - Connect an agent to a platform\n */\nexport const CONNECT_CHANNEL_ROUTE = createRoute({\n method: 'POST',\n path: '/channels/:platform/connect',\n responseType: 'json',\n pathParamSchema: channelPlatformPathParams,\n bodySchema: connectChannelBodySchema,\n responseSchema: connectChannelResponseSchema,\n summary: 'Connect agent to channel',\n description: 'Creates a platform app for the agent and returns an OAuth authorization URL',\n tags: ['Channels'],\n requiresAuth: true,\n handler: async ({ mastra, requestContext, platform, agentId, options }) => {\n assertChannelsAvailable();\n try {\n const channel = getChannelOrThrow(mastra, platform);\n\n if (!channel.connect) {\n throw new HTTPException(400, {\n message: `Channel \"${platform}\" does not support programmatic connection`,\n });\n }\n\n await assertChannelAgentWriteAccess(mastra, requestContext, agentId, 'connect');\n\n return await channel.connect(agentId, options);\n } catch (error) {\n return handleError(error, 'Error connecting agent to channel');\n }\n },\n});\n\n/**\n * POST /channels/:platform/:agentId/disconnect - Disconnect an agent from a platform\n */\nexport const DISCONNECT_CHANNEL_ROUTE = createRoute({\n method: 'POST',\n path: '/channels/:platform/:agentId/disconnect',\n responseType: 'json',\n pathParamSchema: channelAgentPathParams,\n responseSchema: disconnectChannelResponseSchema,\n summary: 'Disconnect agent from channel',\n description: 'Deletes the platform app and cleans up the installation',\n tags: ['Channels'],\n requiresAuth: true,\n handler: async ({ mastra, requestContext, platform, agentId }) => {\n assertChannelsAvailable();\n try {\n const channel = getChannelOrThrow(mastra, platform);\n\n if (!channel.disconnect) {\n throw new HTTPException(400, {\n message: `Channel \"${platform}\" does not support programmatic disconnection`,\n });\n }\n\n await assertChannelAgentWriteAccess(mastra, requestContext, agentId, 'disconnect');\n\n await channel.disconnect(agentId);\n return { success: true };\n } catch (error) {\n return handleError(error, 'Error disconnecting agent from channel');\n }\n },\n});\n"],"mappings":";;;;;;;;AAMA,MAAa,4BAA4BA,OAAAA,EAAE,OAAO,EAChD,UAAUA,OAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,+CAA6C,EAC7E,CAAC;AAED,MAAa,yBAAyBA,OAAAA,EAAE,OAAO;CAC7C,UAAUA,OAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,+CAA6C;CAC3E,SAASA,OAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,kBAAkB;AACjD,CAAC;AAMD,MAAa,2BAA2BA,OAAAA,EAAE,OAAO;CAC/C,SAASA,OAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,6BAA6B;CAC1D,SAASA,OAAAA,EAAE,OAAOA,OAAAA,EAAE,OAAO,GAAGA,OAAAA,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,sCAAsC;AACvG,CAAC;AAMD,MAAM,4BAA4BA,OAAAA,EAAE,OAAO;CACzC,IAAIA,OAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,qBAAqB;CAC7C,MAAMA,OAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,8BAA8B;CACxD,cAAcA,OAAAA,EAAE,QAAQ,CAAC,CAAC,SAAS,iDAAiD;CACpF,sBAAsBA,OAAAA,EAAE,OAAOA,OAAAA,EAAE,OAAO,GAAGA,OAAAA,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,iCAAiC;AAC/G,CAAC;AAED,MAAM,gCAAgCA,OAAAA,EAAE,OAAO;CAC7C,IAAIA,OAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,yBAAyB;CACjD,UAAUA,OAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,qBAAqB;CACnD,SAASA,OAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,4BAA4B;CACzD,QAAQA,OAAAA,EAAE,KAAK,CAAC,UAAU,SAAS,CAAC,CAAC,CAAC,SAAS,qBAAqB;CACpE,aAAaA,OAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,gCAAgC;CAC5E,aAAaA,OAAAA,EAAE,OAAO,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,wBAAwB;AAC3E,CAAC;AAED,MAAM,4BAA4BA,OAAAA,EAAE,OAAO;CACzC,MAAMA,OAAAA,EAAE,QAAQ,OAAO,CAAC,CAAC,SAAS,mDAAmD;CACrF,kBAAkBA,OAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,2CAA2C;CACjF,gBAAgBA,OAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,yBAAyB;AAC/D,CAAC;AAED,MAAM,+BAA+BA,OAAAA,EAAE,OAAO;CAC5C,MAAMA,OAAAA,EAAE,QAAQ,WAAW,CAAC,CAAC,SAAS,uDAAuD;CAC7F,KAAKA,OAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,uCAAuC;CAChE,gBAAgBA,OAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,yBAAyB;AAC/D,CAAC;AAED,MAAM,gCAAgCA,OAAAA,EAAE,OAAO;CAC7C,MAAMA,OAAAA,EAAE,QAAQ,WAAW,CAAC,CAAC,SAAS,sDAAsD;CAC5F,gBAAgBA,OAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,yBAAyB;AAC/D,CAAC;AAED,MAAM,6BAA6BA,OAAAA,EAAE,mBAAmB,QAAQ;CAC9D;CACA;CACA;AACF,CAAC;AAED,MAAa,qCAAqCA,OAAAA,EAAE,MAAM,yBAAyB;AAEnF,MAAa,yCAAyCA,OAAAA,EAAE,MAAM,6BAA6B;AAE3F,MAAa,+BAA+B;AAE5C,MAAa,kCAAkCA,OAAAA,EAAE,OAAO,EACtD,SAASA,OAAAA,EAAE,QAAQ,EACrB,CAAC;;;AClDD,SAAS,0BAAgC;CACvC,IAAI,CAACC,sBAAAA,aAAa,IAAI,UAAU,GAC9B,MAAM,IAAIC,uBAAAA,cAAc,KAAK,EAAE,SAAS,mDAAmD,CAAC;AAEhG;AAEA,SAAS,kBAAkB,QAAgB,UAAmC;CAC5E,MAAM,WAAW,OAAO,OAAO,OAAO,YAAY,CAAC,CAAC;CACpD,MAAM,UAAU,SAAS,MAAK,MAAK,EAAE,OAAO,QAAQ;CACpD,IAAI,CAAC,SAEH,MAAM,IAAIA,uBAAAA,cAAc,KAAK,EAC3B,SAAS,YAAY,SAAS,kCAFd,SAAS,KAAI,MAAK,EAAE,EAAE,CAAC,CAAC,KAAK,IAE2B,KAAK,SAC/E,CAAC;CAEH,OAAO;AACT;;;;;;;;;;AAWA,eAAe,8BACb,QACA,gBACA,SACA,QACe;CACf,MAAM,UAAU,OAAO,WAAW;CAClC,MAAM,cAAc,UAAU,MAAM,QAAQ,SAAS,QAAQ,IAAI;CACjE,MAAM,SAAS,cAAc,MAAM,YAAY,QAAQ,OAAO,IAAI;CAElE,IAAI,QAAQ;EACV,mCAAA,kBAAkB;GAChB;GACA,UAAU;GACV,YAAY;GACZ,QAAQ;GACR,QAAQ;EACV,CAAC;EACD;CACF;CAKA,IADoB,OAAO,aAAa,OAC1B,GAGZ;CAGF,IAAI,WAAW,WACb,MAAM,IAAIA,uBAAAA,cAAc,KAAK,EAAE,SAAS,UAAU,QAAQ,aAAa,CAAC;CAQ1E,IAAI,CADmBC,mCAAAA,kBAAkB,cACvB,KAAK,CAAC,eAAe,IAAA,cAAmB,GAAG;CAC7D,IAAIC,mCAAAA,eAAe,gBAAgB,UAAU,GAAG;CAChD,IAAIC,mCAAAA,oBAAoB;EAAE;EAAgB,UAAU;EAAY,QAAQ;CAAQ,CAAC,GAAG;CAEpF,MAAM,IAAIH,uBAAAA,cAAc,KAAK,EAAE,SAAS,YAAY,CAAC;AACvD;;;;AASA,MAAa,+BAA+BI,sBAAAA,YAAY;CACtD,QAAQ;CACR,MAAM;CACN,cAAc;CACd,gBAAgB;CAChB,SAAS;CACT,aAAa;CACb,MAAM,CAAC,UAAU;CACjB,cAAc;CACd,SAAS,OAAO,EAAE,aAAa;EAC7B,wBAAwB;EACxB,IAAI;GAEF,OADiB,OAAO,OAAO,OAAO,YAAY,CAAC,CACrC,CAAC,CAAC,KAAI,YAAW;IAC7B,IAAI,QAAQ,SACV,OAAO,QAAQ,QAAQ;IAEzB,OAAO;KACL,IAAI,QAAQ;KACZ,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,QAAQ,GAAG,MAAM,CAAC;KAC7D,cAAc;IAChB;GACF,CAAC;EACH,SAAS,OAAO;GACd,OAAOC,8BAAAA,YAAY,OAAO,iCAAiC;EAC7D;CACF;AACF,CAAC;;;;AAKD,MAAa,mCAAmCD,sBAAAA,YAAY;CAC1D,QAAQ;CACR,MAAM;CACN,cAAc;CACd,iBAAiB;CACjB,gBAAgB;CAChB,SAAS;CACT,aAAa;CACb,MAAM,CAAC,UAAU;CACjB,cAAc;CACd,SAAS,OAAO,EAAE,QAAQ,eAAe;EACvC,wBAAwB;EACxB,IAAI;GACF,MAAM,UAAU,kBAAkB,QAAQ,QAAQ;GAElD,IAAI,CAAC,QAAQ,mBACX,OAAO,CAAC;GAGV,OAAO,MAAM,QAAQ,kBAAkB;EACzC,SAAS,OAAO;GACd,OAAOC,8BAAAA,YAAY,OAAO,qCAAqC;EACjE;CACF;AACF,CAAC;;;;AAKD,MAAa,wBAAwBD,sBAAAA,YAAY;CAC/C,QAAQ;CACR,MAAM;CACN,cAAc;CACd,iBAAiB;CACjB,YAAY;CACZ,gBAAgB;CAChB,SAAS;CACT,aAAa;CACb,MAAM,CAAC,UAAU;CACjB,cAAc;CACd,SAAS,OAAO,EAAE,QAAQ,gBAAgB,UAAU,SAAS,cAAc;EACzE,wBAAwB;EACxB,IAAI;GACF,MAAM,UAAU,kBAAkB,QAAQ,QAAQ;GAElD,IAAI,CAAC,QAAQ,SACX,MAAM,IAAIJ,uBAAAA,cAAc,KAAK,EAC3B,SAAS,YAAY,SAAS,4CAChC,CAAC;GAGH,MAAM,8BAA8B,QAAQ,gBAAgB,SAAS,SAAS;GAE9E,OAAO,MAAM,QAAQ,QAAQ,SAAS,OAAO;EAC/C,SAAS,OAAO;GACd,OAAOK,8BAAAA,YAAY,OAAO,mCAAmC;EAC/D;CACF;AACF,CAAC;;;;AAKD,MAAa,2BAA2BD,sBAAAA,YAAY;CAClD,QAAQ;CACR,MAAM;CACN,cAAc;CACd,iBAAiB;CACjB,gBAAgB;CAChB,SAAS;CACT,aAAa;CACb,MAAM,CAAC,UAAU;CACjB,cAAc;CACd,SAAS,OAAO,EAAE,QAAQ,gBAAgB,UAAU,cAAc;EAChE,wBAAwB;EACxB,IAAI;GACF,MAAM,UAAU,kBAAkB,QAAQ,QAAQ;GAElD,IAAI,CAAC,QAAQ,YACX,MAAM,IAAIJ,uBAAAA,cAAc,KAAK,EAC3B,SAAS,YAAY,SAAS,+CAChC,CAAC;GAGH,MAAM,8BAA8B,QAAQ,gBAAgB,SAAS,YAAY;GAEjF,MAAM,QAAQ,WAAW,OAAO;GAChC,OAAO,EAAE,SAAS,KAAK;EACzB,SAAS,OAAO;GACd,OAAOK,8BAAAA,YAAY,OAAO,wCAAwC;EACpE;CACF;AACF,CAAC"}
|
package/dist/docs/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: mastra-server
|
|
|
3
3
|
description: Documentation for @mastra/server. Use when working with @mastra/server APIs, configuration, or implementation.
|
|
4
4
|
metadata:
|
|
5
5
|
package: "@mastra/server"
|
|
6
|
-
version: "1.58.0-alpha.
|
|
6
|
+
version: "1.58.0-alpha.13"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## When to use
|
|
@@ -18,6 +18,7 @@ Read the individual reference documents for detailed explanations and code examp
|
|
|
18
18
|
|
|
19
19
|
- [A2A](references/docs-agents-a2a.md) - Expose and call remote Mastra agents over the Agent-to-Agent protocol.
|
|
20
20
|
- [Custom adapters](references/docs-server-custom-adapters.md) - Create a custom server adapter for frameworks other than Hono or Express.
|
|
21
|
+
- [Custom API routes](references/docs-server-custom-api-routes.md) - Expose additional HTTP endpoints from your Mastra server.
|
|
21
22
|
- [Middleware](references/docs-server-middleware.md) - Apply custom middleware functions to intercept requests.
|
|
22
23
|
|
|
23
24
|
### Reference
|
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
> Discover all available pages from the documentation index: https://mastra.ai/llms.txt
|
|
2
|
+
|
|
3
|
+
# Custom API routes
|
|
4
|
+
|
|
5
|
+
By default, Mastra automatically exposes registered agents and workflows via its server. For additional behavior you can define your own HTTP routes.
|
|
6
|
+
|
|
7
|
+
Routes are provided with a helper `registerApiRoute()` from `@mastra/core/server`. Routes can live in the same file as the `Mastra` instance but separating them helps keep configuration concise.
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import { Mastra } from '@mastra/core'
|
|
11
|
+
import { registerApiRoute } from '@mastra/core/server'
|
|
12
|
+
|
|
13
|
+
export const mastra = new Mastra({
|
|
14
|
+
server: {
|
|
15
|
+
apiRoutes: [
|
|
16
|
+
registerApiRoute('/my-custom-route', {
|
|
17
|
+
method: 'GET',
|
|
18
|
+
handler: async c => {
|
|
19
|
+
const mastra = c.get('mastra')
|
|
20
|
+
const agent = await mastra.getAgent('my-agent')
|
|
21
|
+
|
|
22
|
+
return c.json({ message: 'Custom route' })
|
|
23
|
+
},
|
|
24
|
+
}),
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
})
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Once registered, a custom route will be accessible from the root of the server. For example:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
curl http://localhost:4111/my-custom-route
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Each route's handler receives the Hono `Context`. Within the handler you can access the `Mastra` instance to fetch or call agents and workflows.
|
|
37
|
+
|
|
38
|
+
## Schema validation
|
|
39
|
+
|
|
40
|
+
Use [`createRoute()`](https://mastra.ai/reference/server/create-route) in `apiRoutes` to parse and validate path parameters, query parameters, and request bodies with Zod. The schemas also infer the handler parameters and generate OpenAPI metadata.
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
import { Mastra } from '@mastra/core'
|
|
44
|
+
import { createRoute } from '@mastra/server/server-adapter'
|
|
45
|
+
import { z } from 'zod'
|
|
46
|
+
|
|
47
|
+
const createItemRoute = createRoute({
|
|
48
|
+
method: 'POST',
|
|
49
|
+
path: '/items',
|
|
50
|
+
responseType: 'json',
|
|
51
|
+
bodySchema: z.object({
|
|
52
|
+
name: z.string().min(1),
|
|
53
|
+
}),
|
|
54
|
+
responseSchema: z.object({
|
|
55
|
+
id: z.string(),
|
|
56
|
+
name: z.string(),
|
|
57
|
+
}),
|
|
58
|
+
handler: async ({ name }) => ({
|
|
59
|
+
id: crypto.randomUUID(),
|
|
60
|
+
name,
|
|
61
|
+
}),
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
export const mastra = new Mastra({
|
|
65
|
+
server: {
|
|
66
|
+
apiRoutes: [createItemRoute],
|
|
67
|
+
},
|
|
68
|
+
})
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
By default, Mastra returns a `400` response when validation fails. The `onValidationError` callback can override the status and response body. Validated values and the `Mastra` server context are passed directly to the handler.
|
|
72
|
+
|
|
73
|
+
## Middleware
|
|
74
|
+
|
|
75
|
+
To add route-specific middleware pass a `middleware` array when calling `registerApiRoute()`.
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
import { Mastra } from '@mastra/core'
|
|
79
|
+
import { registerApiRoute } from '@mastra/core/server'
|
|
80
|
+
|
|
81
|
+
export const mastra = new Mastra({
|
|
82
|
+
server: {
|
|
83
|
+
apiRoutes: [
|
|
84
|
+
registerApiRoute('/my-custom-route', {
|
|
85
|
+
method: 'GET',
|
|
86
|
+
middleware: [
|
|
87
|
+
async (c, next) => {
|
|
88
|
+
console.log(`${c.req.method} ${c.req.url}`)
|
|
89
|
+
await next()
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
handler: async c => {
|
|
93
|
+
return c.json({ message: 'Custom route with middleware' })
|
|
94
|
+
},
|
|
95
|
+
}),
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
})
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## OpenAPI documentation
|
|
102
|
+
|
|
103
|
+
Custom routes can include OpenAPI metadata to appear in the Swagger UI alongside Mastra server routes. You can access the OpenAPI spec at `/api/openapi.json`, where both custom routes and built-in routes are listed. Pass an `openapi` option with standard OpenAPI operation fields.
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
import { Mastra } from '@mastra/core'
|
|
107
|
+
import { registerApiRoute } from '@mastra/core/server'
|
|
108
|
+
import { z } from 'zod'
|
|
109
|
+
|
|
110
|
+
export const mastra = new Mastra({
|
|
111
|
+
server: {
|
|
112
|
+
apiRoutes: [
|
|
113
|
+
registerApiRoute('/items/:itemId', {
|
|
114
|
+
method: 'GET',
|
|
115
|
+
openapi: {
|
|
116
|
+
summary: 'Get item by ID',
|
|
117
|
+
description: 'Retrieves a single item by its unique identifier',
|
|
118
|
+
tags: ['Items'],
|
|
119
|
+
parameters: [
|
|
120
|
+
{
|
|
121
|
+
name: 'itemId',
|
|
122
|
+
in: 'path',
|
|
123
|
+
required: true,
|
|
124
|
+
description: 'The item ID',
|
|
125
|
+
schema: { type: 'string' },
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
responses: {
|
|
129
|
+
200: {
|
|
130
|
+
description: 'Item found',
|
|
131
|
+
content: {
|
|
132
|
+
'application/json': {
|
|
133
|
+
schema: {
|
|
134
|
+
type: 'object',
|
|
135
|
+
properties: {
|
|
136
|
+
id: { type: 'string' },
|
|
137
|
+
name: { type: 'string' },
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
404: {
|
|
144
|
+
description: 'Item not found',
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
handler: async c => {
|
|
149
|
+
const itemId = c.req.param('itemId')
|
|
150
|
+
return c.json({ id: itemId, name: 'Example Item' })
|
|
151
|
+
},
|
|
152
|
+
}),
|
|
153
|
+
],
|
|
154
|
+
},
|
|
155
|
+
})
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Using Zod Schemas
|
|
159
|
+
|
|
160
|
+
Zod schemas in the `openapi` configuration are converted to JSON Schema when the OpenAPI document is generated:
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
import { Mastra } from '@mastra/core'
|
|
164
|
+
import { registerApiRoute } from '@mastra/core/server'
|
|
165
|
+
import { z } from 'zod'
|
|
166
|
+
|
|
167
|
+
const ItemSchema = z.object({
|
|
168
|
+
id: z.string(),
|
|
169
|
+
name: z.string(),
|
|
170
|
+
price: z.number(),
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
const CreateItemSchema = z.object({
|
|
174
|
+
name: z.string().min(1),
|
|
175
|
+
price: z.number().positive(),
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
export const mastra = new Mastra({
|
|
179
|
+
server: {
|
|
180
|
+
apiRoutes: [
|
|
181
|
+
registerApiRoute('/items', {
|
|
182
|
+
method: 'POST',
|
|
183
|
+
openapi: {
|
|
184
|
+
summary: 'Create a new item',
|
|
185
|
+
tags: ['Items'],
|
|
186
|
+
requestBody: {
|
|
187
|
+
required: true,
|
|
188
|
+
content: {
|
|
189
|
+
'application/json': {
|
|
190
|
+
schema: CreateItemSchema,
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
responses: {
|
|
195
|
+
201: {
|
|
196
|
+
description: 'Item created',
|
|
197
|
+
content: {
|
|
198
|
+
'application/json': {
|
|
199
|
+
schema: ItemSchema,
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
handler: async c => {
|
|
206
|
+
const body = await c.req.json()
|
|
207
|
+
return c.json({ id: 'new-id', ...body }, 201)
|
|
208
|
+
},
|
|
209
|
+
}),
|
|
210
|
+
],
|
|
211
|
+
},
|
|
212
|
+
})
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Viewing in Swagger UI
|
|
216
|
+
|
|
217
|
+
When running in development mode (`mastra dev`) or with `swaggerUI: true` in build options, your custom routes appear in the Swagger UI at `/swagger-ui`.
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
export const mastra = new Mastra({
|
|
221
|
+
server: {
|
|
222
|
+
build: {
|
|
223
|
+
swaggerUI: true, // Enable in production builds
|
|
224
|
+
},
|
|
225
|
+
apiRoutes: [
|
|
226
|
+
// Your routes...
|
|
227
|
+
],
|
|
228
|
+
},
|
|
229
|
+
})
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Authentication
|
|
233
|
+
|
|
234
|
+
When authentication is configured on your Mastra server, custom API routes require authentication by default. To make a route publicly accessible, set `requiresAuth: false`:
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
import { Mastra } from '@mastra/core'
|
|
238
|
+
import { registerApiRoute } from '@mastra/core/server'
|
|
239
|
+
import { MastraJwtAuth } from '@mastra/auth'
|
|
240
|
+
|
|
241
|
+
export const mastra = new Mastra({
|
|
242
|
+
server: {
|
|
243
|
+
auth: new MastraJwtAuth({
|
|
244
|
+
secret: process.env.MASTRA_JWT_SECRET,
|
|
245
|
+
}),
|
|
246
|
+
apiRoutes: [
|
|
247
|
+
// Protected route (default behavior)
|
|
248
|
+
registerApiRoute('/protected-data', {
|
|
249
|
+
method: 'GET',
|
|
250
|
+
handler: async c => {
|
|
251
|
+
// Access authenticated user from request context
|
|
252
|
+
const user = c.get('requestContext').get('user')
|
|
253
|
+
return c.json({ message: 'Authenticated user', user })
|
|
254
|
+
},
|
|
255
|
+
}),
|
|
256
|
+
|
|
257
|
+
// Public route (no authentication required)
|
|
258
|
+
registerApiRoute('/webhooks/github', {
|
|
259
|
+
method: 'POST',
|
|
260
|
+
requiresAuth: false, // Explicitly opt out of authentication
|
|
261
|
+
handler: async c => {
|
|
262
|
+
const payload = await c.req.json()
|
|
263
|
+
// Process webhook without authentication
|
|
264
|
+
return c.json({ received: true })
|
|
265
|
+
},
|
|
266
|
+
}),
|
|
267
|
+
],
|
|
268
|
+
},
|
|
269
|
+
})
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Authentication behavior
|
|
273
|
+
|
|
274
|
+
- **No auth configured**: All routes (built-in and custom) are public
|
|
275
|
+
|
|
276
|
+
- **Auth configured**:
|
|
277
|
+
|
|
278
|
+
- Mastra-provided routes (`/api/agents/*`, `/api/workflows/*`, etc.) require authentication
|
|
279
|
+
- Custom routes require authentication by default
|
|
280
|
+
- Custom routes can opt out with `requiresAuth: false`
|
|
281
|
+
|
|
282
|
+
### Accessing user information
|
|
283
|
+
|
|
284
|
+
When a request is authenticated, the user object is available in the request context:
|
|
285
|
+
|
|
286
|
+
```typescript
|
|
287
|
+
registerApiRoute('/user-profile', {
|
|
288
|
+
method: 'GET',
|
|
289
|
+
handler: async c => {
|
|
290
|
+
const requestContext = c.get('requestContext')
|
|
291
|
+
const user = requestContext.get('user')
|
|
292
|
+
|
|
293
|
+
return c.json({ user })
|
|
294
|
+
},
|
|
295
|
+
})
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
For more information about authentication providers, see the [Auth documentation](https://mastra.ai/docs/server/auth).
|
|
299
|
+
|
|
300
|
+
## Continue generation after client disconnect
|
|
301
|
+
|
|
302
|
+
Built-in streaming helpers such as [`chatRoute()`](https://mastra.ai/reference/ai-sdk/chat-route) forward the incoming request's `AbortSignal` to `agent.stream()`. That's the right default when a browser disconnect should cancel the model call.
|
|
303
|
+
|
|
304
|
+
For custom streaming routes that should stop when the client disconnects, pass `c.req.raw.signal` to long-running work such as `agent.stream()`. Mastra's Node-based adapters also stop reading streamed `Response` bodies from custom routes when the client connection closes. Streamed response body errors that aren't caused by client disconnects still propagate through the adapter's normal error handling. In Hono, disconnect behavior depends on the host runtime forwarding connection closes to `request.signal`.
|
|
305
|
+
|
|
306
|
+
```typescript
|
|
307
|
+
registerApiRoute('/stream', {
|
|
308
|
+
method: 'GET',
|
|
309
|
+
handler: async c => {
|
|
310
|
+
const stream = await agent.stream(prompt, {
|
|
311
|
+
abortSignal: c.req.raw.signal,
|
|
312
|
+
})
|
|
313
|
+
|
|
314
|
+
return stream.toTextStreamResponse()
|
|
315
|
+
},
|
|
316
|
+
})
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
If you want the server to keep generating and persist the final response even after the client disconnects, build a custom route around the underlying `MastraModelOutput`. Start the agent stream without forwarding `c.req.raw.signal`, then call `consumeStream()` in the background so generation continues server-side.
|
|
320
|
+
|
|
321
|
+
```typescript
|
|
322
|
+
import {
|
|
323
|
+
createUIMessageStream,
|
|
324
|
+
createUIMessageStreamResponse,
|
|
325
|
+
InferUIMessageChunk,
|
|
326
|
+
UIMessage,
|
|
327
|
+
} from 'ai'
|
|
328
|
+
import { toAISdkStream } from '@mastra/ai-sdk'
|
|
329
|
+
import { Mastra } from '@mastra/core'
|
|
330
|
+
import { registerApiRoute } from '@mastra/core/server'
|
|
331
|
+
|
|
332
|
+
export const mastra = new Mastra({
|
|
333
|
+
server: {
|
|
334
|
+
apiRoutes: [
|
|
335
|
+
registerApiRoute('/chat/persist/:agentId', {
|
|
336
|
+
method: 'POST',
|
|
337
|
+
handler: async c => {
|
|
338
|
+
const { messages, memory } = await c.req.json()
|
|
339
|
+
const mastra = c.get('mastra')
|
|
340
|
+
const agent = mastra.getAgent(c.req.param('agentId'))
|
|
341
|
+
|
|
342
|
+
const stream = await agent.stream(messages, {
|
|
343
|
+
memory,
|
|
344
|
+
// Do not pass c.req.raw.signal if this route should keep running
|
|
345
|
+
// after the client disconnects.
|
|
346
|
+
})
|
|
347
|
+
|
|
348
|
+
void stream.consumeStream().catch(error => {
|
|
349
|
+
mastra.getLogger()?.error('Background stream consumption failed', { error })
|
|
350
|
+
})
|
|
351
|
+
|
|
352
|
+
const uiStream = createUIMessageStream({
|
|
353
|
+
originalMessages: messages,
|
|
354
|
+
execute: async ({ writer }) => {
|
|
355
|
+
for await (const part of toAISdkStream(stream, { from: 'agent' })) {
|
|
356
|
+
writer.write(part as InferUIMessageChunk<UIMessage>)
|
|
357
|
+
}
|
|
358
|
+
},
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
return createUIMessageStreamResponse({ stream: uiStream })
|
|
362
|
+
},
|
|
363
|
+
}),
|
|
364
|
+
],
|
|
365
|
+
},
|
|
366
|
+
})
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
> **Note:** Use this pattern only when you intentionally want work to continue after the HTTP client is gone. If you want disconnects to cancel generation, keep using `chatRoute()` or forward the request `AbortSignal` yourself.
|
|
370
|
+
|
|
371
|
+
## Related
|
|
372
|
+
|
|
373
|
+
- [registerApiRoute() Reference](https://mastra.ai/reference/server/register-api-route): Full API reference
|
|
374
|
+
- [Server Middleware](https://mastra.ai/docs/server/middleware): Global middleware configuration
|
|
375
|
+
- [Mastra Server](https://mastra.ai/docs/server/mastra-server): Server configuration options
|
|
@@ -72,10 +72,36 @@ handler: async params => {
|
|
|
72
72
|
|
|
73
73
|
## Return value
|
|
74
74
|
|
|
75
|
-
Returns a `ServerRoute` object that can be registered with an adapter.
|
|
75
|
+
Returns a `ServerRoute` object that can be registered with an adapter or passed to `server.apiRoutes` on the `Mastra` instance.
|
|
76
76
|
|
|
77
77
|
## Examples
|
|
78
78
|
|
|
79
|
+
### Register through `server.apiRoutes`
|
|
80
|
+
|
|
81
|
+
Routes created with `createRoute()` can be passed to `server.apiRoutes`. The adapter registers them with runtime validation, typed handler parameters, and generated OpenAPI metadata. See [Custom API routes](https://mastra.ai/docs/server/custom-api-routes) for details.
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
import { Mastra } from '@mastra/core'
|
|
85
|
+
import { createRoute } from '@mastra/server/server-adapter'
|
|
86
|
+
import { z } from 'zod'
|
|
87
|
+
|
|
88
|
+
const createItemRoute = createRoute({
|
|
89
|
+
method: 'POST',
|
|
90
|
+
path: '/items',
|
|
91
|
+
responseType: 'json',
|
|
92
|
+
bodySchema: z.object({
|
|
93
|
+
name: z.string(),
|
|
94
|
+
}),
|
|
95
|
+
handler: async ({ name }) => ({ id: 'new-id', name }),
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
export const mastra = new Mastra({
|
|
99
|
+
server: {
|
|
100
|
+
apiRoutes: [createItemRoute],
|
|
101
|
+
},
|
|
102
|
+
})
|
|
103
|
+
```
|
|
104
|
+
|
|
79
105
|
### GET route with path params
|
|
80
106
|
|
|
81
107
|
```typescript
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as __exportAll } from "./rolldown-runtime-DuvcJU0W.js";
|
|
2
2
|
import { t as HTTPException } from "./http-exception-CyfxZB6W.js";
|
|
3
|
-
import { n as createRoute } from "./route-builder-
|
|
3
|
+
import { n as createRoute } from "./route-builder-YQ_gLIvW.js";
|
|
4
4
|
import { handleError } from "./server/handlers/error.js";
|
|
5
5
|
import { z } from "zod/v4";
|
|
6
6
|
//#region src/server/schemas/dynamic-workflows.ts
|
|
@@ -335,4 +335,4 @@ const DELETE_DYNAMIC_WORKFLOW_ROUTE = createRoute({
|
|
|
335
335
|
//#endregion
|
|
336
336
|
export { dynamic_workflows_exports as a, UPSERT_DYNAMIC_WORKFLOW_ROUTE as i, GET_DYNAMIC_WORKFLOW_ROUTE as n, LIST_DYNAMIC_WORKFLOWS_ROUTE as r, DELETE_DYNAMIC_WORKFLOW_ROUTE as t };
|
|
337
337
|
|
|
338
|
-
//# sourceMappingURL=dynamic-workflows-
|
|
338
|
+
//# sourceMappingURL=dynamic-workflows-B0TE8mjA.js.map
|