@mastra/server 1.60.0-alpha.6 → 1.60.0-alpha.8

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 (173) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/dist/_types/@internal_voice/dist/_types/@internal_core/dist/request-context/index.d.ts +12 -1
  3. package/dist/{a2a-CUkzkdTZ.js → a2a-B5m54dOP.js} +2 -2
  4. package/dist/{a2a-CUkzkdTZ.js.map → a2a-B5m54dOP.js.map} +1 -1
  5. package/dist/{a2a-DzZHH3OH.cjs → a2a-Eeib3vfP.cjs} +2 -2
  6. package/dist/{a2a-DzZHH3OH.cjs.map → a2a-Eeib3vfP.cjs.map} +1 -1
  7. package/dist/{agents-uT8ZDE4k.js → agents-BetrUB_N.js} +7 -2
  8. package/dist/agents-BetrUB_N.js.map +1 -0
  9. package/dist/{agents-0Tw3kkD_.cjs → agents-CLv_RFQx.cjs} +18 -1
  10. package/dist/agents-CLv_RFQx.cjs.map +1 -0
  11. package/dist/{api-schema-manifest-BlxXMFWo.js → api-schema-manifest-BKTXRheC.js} +2 -2
  12. package/dist/{api-schema-manifest-BlxXMFWo.js.map → api-schema-manifest-BKTXRheC.js.map} +1 -1
  13. package/dist/{api-schema-manifest-iAEVS-Re.cjs → api-schema-manifest-BbNdh5Ck.cjs} +2 -2
  14. package/dist/{api-schema-manifest-iAEVS-Re.cjs.map → api-schema-manifest-BbNdh5Ck.cjs.map} +1 -1
  15. package/dist/{builder-registry-B8KyPAOP.js → builder-registry-CqLsr39q.js} +2 -2
  16. package/dist/{builder-registry-B8KyPAOP.js.map → builder-registry-CqLsr39q.js.map} +1 -1
  17. package/dist/{builder-registry-Dcou-kzd.cjs → builder-registry-CyaUg_iP.cjs} +2 -2
  18. package/dist/{builder-registry-Dcou-kzd.cjs.map → builder-registry-CyaUg_iP.cjs.map} +1 -1
  19. package/dist/{channels-B9yt3a2P.js → channels-BnFQESMf.js} +2 -2
  20. package/dist/{channels-B9yt3a2P.js.map → channels-BnFQESMf.js.map} +1 -1
  21. package/dist/{channels-BRoq3VKR.cjs → channels-Dzy6VM3w.cjs} +2 -2
  22. package/dist/{channels-BRoq3VKR.cjs.map → channels-Dzy6VM3w.cjs.map} +1 -1
  23. package/dist/{constants-ChBaIptn.cjs → constants-CXPpy-Ef.cjs} +7 -1
  24. package/dist/constants-CXPpy-Ef.cjs.map +1 -0
  25. package/dist/{constants-Cp1x-6sJ.js → constants-CutMu4A_.js} +7 -1
  26. package/dist/constants-CutMu4A_.js.map +1 -0
  27. package/dist/{dist-BJ9n8vHL.cjs → dist-CpaK1qK1.cjs} +12 -8
  28. package/dist/dist-CpaK1qK1.cjs.map +1 -0
  29. package/dist/{dist-Bpz9F_9G.js → dist-CpxQhZED.js} +12 -8
  30. package/dist/dist-CpxQhZED.js.map +1 -0
  31. package/dist/docs/SKILL.md +2 -2
  32. package/dist/docs/assets/SOURCE_MAP.json +1 -1
  33. package/dist/docs/references/{docs-agents-a2a.md → docs-connections-a2a.md} +2 -2
  34. package/dist/docs/references/docs-server-custom-api-routes.md +2 -2
  35. package/dist/{editor-builder-DT7ypWfa.cjs → editor-builder-1L3OIY4K.cjs} +2 -2
  36. package/dist/{editor-builder-DT7ypWfa.cjs.map → editor-builder-1L3OIY4K.cjs.map} +1 -1
  37. package/dist/{editor-builder-DJUxdzC8.js → editor-builder-BDEm-gZe.js} +2 -2
  38. package/dist/{editor-builder-DJUxdzC8.js.map → editor-builder-BDEm-gZe.js.map} +1 -1
  39. package/dist/{editor-builder-C3ZvffGu.cjs → editor-builder-DNRVszU-.cjs} +2 -2
  40. package/dist/{editor-builder-C3ZvffGu.cjs.map → editor-builder-DNRVszU-.cjs.map} +1 -1
  41. package/dist/{editor-builder-Byg6wbi6.js → editor-builder-EP9FAtQm.js} +2 -2
  42. package/dist/{editor-builder-Byg6wbi6.js.map → editor-builder-EP9FAtQm.js.map} +1 -1
  43. package/dist/{helpers-TmTGZi8e.cjs → helpers-C54OMiDG.cjs} +2 -2
  44. package/dist/{helpers-TmTGZi8e.cjs.map → helpers-C54OMiDG.cjs.map} +1 -1
  45. package/dist/{helpers-GyeAi5YN.js → helpers-Da9nPOFL.js} +2 -2
  46. package/dist/{helpers-GyeAi5YN.js.map → helpers-Da9nPOFL.js.map} +1 -1
  47. package/dist/{routes-BpOjCX2F.js → routes-iUe0w9eL.js} +7 -5
  48. package/dist/routes-iUe0w9eL.js.map +1 -0
  49. package/dist/{routes-BBRC9gg2.cjs → routes-mK_LlDMo.cjs} +7 -5
  50. package/dist/routes-mK_LlDMo.cjs.map +1 -0
  51. package/dist/server/auth/index.cjs +2 -2
  52. package/dist/server/auth/index.js +2 -2
  53. package/dist/server/constants.d.ts +5 -0
  54. package/dist/server/constants.d.ts.map +1 -1
  55. package/dist/server/handlers/a2a.cjs +1 -1
  56. package/dist/server/handlers/a2a.js +1 -1
  57. package/dist/server/handlers/agent-builder.cjs +3 -3
  58. package/dist/server/handlers/agent-builder.js +3 -3
  59. package/dist/server/handlers/agent-controller.cjs +32 -4
  60. package/dist/server/handlers/agent-controller.cjs.map +1 -1
  61. package/dist/server/handlers/agent-controller.d.ts +18 -0
  62. package/dist/server/handlers/agent-controller.d.ts.map +1 -1
  63. package/dist/server/handlers/agent-controller.js +32 -4
  64. package/dist/server/handlers/agent-controller.js.map +1 -1
  65. package/dist/server/handlers/agent-versions.cjs +1 -1
  66. package/dist/server/handlers/agent-versions.js +1 -1
  67. package/dist/server/handlers/agents.cjs +4 -4
  68. package/dist/server/handlers/agents.js +4 -4
  69. package/dist/server/handlers/auth.cjs +2 -2
  70. package/dist/server/handlers/auth.js +2 -2
  71. package/dist/server/handlers/authorship.cjs +1 -1
  72. package/dist/server/handlers/authorship.js +1 -1
  73. package/dist/server/handlers/builder-registry.cjs +1 -1
  74. package/dist/server/handlers/builder-registry.js +1 -1
  75. package/dist/server/handlers/channels.cjs +1 -1
  76. package/dist/server/handlers/channels.js +1 -1
  77. package/dist/server/handlers/conversations.cjs +1 -1
  78. package/dist/server/handlers/conversations.js +1 -1
  79. package/dist/server/handlers/datasets.cjs +1 -1
  80. package/dist/server/handlers/datasets.js +1 -1
  81. package/dist/server/handlers/editor-builder.cjs +1 -1
  82. package/dist/server/handlers/editor-builder.js +1 -1
  83. package/dist/server/handlers/favorites-enrichment.cjs +1 -1
  84. package/dist/server/handlers/favorites-enrichment.js +1 -1
  85. package/dist/server/handlers/logs.cjs +1 -1
  86. package/dist/server/handlers/logs.js +1 -1
  87. package/dist/server/handlers/mcp-client-versions.cjs +1 -1
  88. package/dist/server/handlers/mcp-client-versions.js +1 -1
  89. package/dist/server/handlers/mcp.cjs.map +1 -1
  90. package/dist/server/handlers/mcp.d.ts +6 -0
  91. package/dist/server/handlers/mcp.d.ts.map +1 -1
  92. package/dist/server/handlers/mcp.js.map +1 -1
  93. package/dist/server/handlers/memory.cjs +1 -1
  94. package/dist/server/handlers/memory.js +1 -1
  95. package/dist/server/handlers/plans.cjs +64 -0
  96. package/dist/server/handlers/plans.cjs.map +1 -0
  97. package/dist/server/handlers/plans.d.ts +43 -0
  98. package/dist/server/handlers/plans.d.ts.map +1 -0
  99. package/dist/server/handlers/plans.js +57 -0
  100. package/dist/server/handlers/plans.js.map +1 -0
  101. package/dist/server/handlers/prompt-block-versions.cjs +1 -1
  102. package/dist/server/handlers/prompt-block-versions.js +1 -1
  103. package/dist/server/handlers/responses.adapter.cjs +1 -1
  104. package/dist/server/handlers/responses.adapter.js +1 -1
  105. package/dist/server/handlers/responses.cjs +1 -1
  106. package/dist/server/handlers/responses.js +1 -1
  107. package/dist/server/handlers/responses.storage.cjs +1 -1
  108. package/dist/server/handlers/responses.storage.js +1 -1
  109. package/dist/server/handlers/scorer-versions.cjs +1 -1
  110. package/dist/server/handlers/scorer-versions.js +1 -1
  111. package/dist/server/handlers/stored-agent-favorites.cjs +2 -2
  112. package/dist/server/handlers/stored-agent-favorites.js +2 -2
  113. package/dist/server/handlers/stored-agents.cjs +2 -2
  114. package/dist/server/handlers/stored-agents.js +2 -2
  115. package/dist/server/handlers/stored-mcp-clients.cjs +1 -1
  116. package/dist/server/handlers/stored-mcp-clients.js +1 -1
  117. package/dist/server/handlers/stored-prompt-blocks.cjs +1 -1
  118. package/dist/server/handlers/stored-prompt-blocks.js +1 -1
  119. package/dist/server/handlers/stored-scorers.cjs +1 -1
  120. package/dist/server/handlers/stored-scorers.js +1 -1
  121. package/dist/server/handlers/stored-skill-favorites.cjs +2 -2
  122. package/dist/server/handlers/stored-skill-favorites.js +2 -2
  123. package/dist/server/handlers/stored-skills.cjs +2 -2
  124. package/dist/server/handlers/stored-skills.js +2 -2
  125. package/dist/server/handlers/stored-workspaces.cjs +1 -1
  126. package/dist/server/handlers/stored-workspaces.js +1 -1
  127. package/dist/server/handlers/system.cjs +1 -1
  128. package/dist/server/handlers/system.js +1 -1
  129. package/dist/server/handlers/tool-providers.cjs +1 -1
  130. package/dist/server/handlers/tool-providers.js +1 -1
  131. package/dist/server/handlers/tools.cjs +3 -3
  132. package/dist/server/handlers/tools.js +3 -3
  133. package/dist/server/handlers/utils.cjs +1 -1
  134. package/dist/server/handlers/utils.js +1 -1
  135. package/dist/server/handlers/validate-agent-instructions.cjs +1 -1
  136. package/dist/server/handlers/validate-agent-instructions.js +1 -1
  137. package/dist/server/handlers/workflows.cjs +3 -3
  138. package/dist/server/handlers/workflows.js +3 -3
  139. package/dist/server/handlers.cjs +8 -1
  140. package/dist/server/handlers.d.ts +1 -0
  141. package/dist/server/handlers.d.ts.map +1 -1
  142. package/dist/server/handlers.js +3 -2
  143. package/dist/server/schemas/agents.d.ts +12 -0
  144. package/dist/server/schemas/agents.d.ts.map +1 -1
  145. package/dist/server/schemas/index.cjs +4 -2
  146. package/dist/server/schemas/index.js +3 -3
  147. package/dist/server/server-adapter/index.cjs +66 -4
  148. package/dist/server/server-adapter/index.cjs.map +1 -1
  149. package/dist/server/server-adapter/index.d.ts +12 -0
  150. package/dist/server/server-adapter/index.d.ts.map +1 -1
  151. package/dist/server/server-adapter/index.js +65 -5
  152. package/dist/server/server-adapter/index.js.map +1 -1
  153. package/dist/server/server-adapter/mcp-auth.d.ts +43 -0
  154. package/dist/server/server-adapter/mcp-auth.d.ts.map +1 -0
  155. package/dist/server/server-adapter/routes/agents.d.ts +2 -0
  156. package/dist/server/server-adapter/routes/agents.d.ts.map +1 -1
  157. package/dist/{utils-Bna_JCkb.cjs → utils-BkPZAGxS.cjs} +2 -2
  158. package/dist/{utils-Bna_JCkb.cjs.map → utils-BkPZAGxS.cjs.map} +1 -1
  159. package/dist/{utils-wTwyTjg3.cjs → utils-CXbhpYYv.cjs} +2 -2
  160. package/dist/{utils-wTwyTjg3.cjs.map → utils-CXbhpYYv.cjs.map} +1 -1
  161. package/dist/{utils-QXKhjIm6.js → utils-CljhO7OY.js} +2 -2
  162. package/dist/{utils-QXKhjIm6.js.map → utils-CljhO7OY.js.map} +1 -1
  163. package/dist/{utils-CmHd1Sgh.js → utils-qMLbyf2U.js} +2 -2
  164. package/dist/{utils-CmHd1Sgh.js.map → utils-qMLbyf2U.js.map} +1 -1
  165. package/package.json +6 -6
  166. package/dist/agents-0Tw3kkD_.cjs.map +0 -1
  167. package/dist/agents-uT8ZDE4k.js.map +0 -1
  168. package/dist/constants-ChBaIptn.cjs.map +0 -1
  169. package/dist/constants-Cp1x-6sJ.js.map +0 -1
  170. package/dist/dist-BJ9n8vHL.cjs.map +0 -1
  171. package/dist/dist-Bpz9F_9G.js.map +0 -1
  172. package/dist/routes-BBRC9gg2.cjs.map +0 -1
  173. package/dist/routes-BpOjCX2F.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"builder-registry-Dcou-kzd.cjs","names":["z","HTTPException","assertSafeFilePath","createRoute","handleError","skillsShSearchResponseSchema","searchSkillsSh","skillsShListResponseSchema","getPopularSkillsSh","skillsShPreviewResponseSchema","previewSkillsSh","fetchSkillFiles","assertSafeSkillName","toSlug","getCallerAuthorId"],"sources":["../src/server/schemas/builder-registry.ts","../src/server/handlers/builder-registry.ts"],"sourcesContent":["/**\n * Builder Registry Schemas\n *\n * Schemas for the Agent Builder skill registry routes. These are distinct from\n * the workspace skills.sh proxy schemas because:\n * - Builder routes are not scoped to a workspace.\n * - Builder install does not accept a `mount` field.\n * - Builder install body carries visibility + the resolved registry id.\n * - Builder install response returns the created stored skill id.\n *\n * The upstream skills.sh proxy response shapes are reused via the shared\n * `skillsShSearchResponseSchema`, `skillsShListResponseSchema`, and\n * `skillsShPreviewResponseSchema` since the wire shape from skills.sh is\n * registry-independent.\n */\n\nimport { z } from 'zod/v4';\n\n// =============================================================================\n// Registry list\n// =============================================================================\n\n/** Single entry in the registries list. */\nexport const builderRegistryEntrySchema = z.object({\n id: z.literal('skills-sh').describe('Stable registry identifier'),\n enabled: z.boolean().describe('Whether this registry is enabled in the running deployment'),\n label: z.string().describe('Human-readable registry name'),\n});\n\n/** Response for `GET /editor/builder/registries`. */\nexport const builderRegistriesResponseSchema = z.object({\n registries: z.array(builderRegistryEntrySchema),\n});\n\n// =============================================================================\n// Search / popular / preview\n// =============================================================================\n\n/** Path params used by every per-registry route. */\nexport const builderRegistryPathParams = z.object({\n registryId: z.string().describe('Registry identifier (e.g. \"skills-sh\")'),\n});\n\nexport const builderRegistrySearchQuerySchema = z.object({\n q: z.string().describe('Search query'),\n limit: z.coerce.number().int().min(1).max(100).optional().default(10).describe('Maximum number of results (1-100)'),\n});\n\nexport const builderRegistryPopularQuerySchema = z\n .object({\n limit: z.coerce.number().int().min(1).max(100).optional().default(10).describe('Maximum number of results (1-100)'),\n offset: z.coerce\n .number()\n .int()\n .min(0)\n .optional()\n .default(0)\n .describe('Offset for pagination (must be a multiple of `limit`)'),\n })\n .refine(args => args.offset % args.limit === 0, {\n message: 'offset must be a multiple of limit (the upstream registry pages by `limit`)',\n path: ['offset'],\n });\n\nexport const builderRegistryPreviewQuerySchema = z.object({\n owner: z.string().describe('GitHub repository owner'),\n repo: z.string().describe('GitHub repository name'),\n path: z.string().describe('Skill name within repo'),\n});\n\n// =============================================================================\n// Install\n// =============================================================================\n\n/**\n * Body for `POST /editor/builder/registries/:registryId/install`.\n *\n * Visibility behaves like the standard stored-skill create flow: optional,\n * defaults to private when the caller is authenticated.\n */\nexport const builderRegistryInstallBodySchema = z.object({\n owner: z.string().describe('GitHub repository owner'),\n repo: z.string().describe('GitHub repository name'),\n skillName: z.string().describe('Skill name from the registry'),\n visibility: z.enum(['private', 'public']).optional().describe('Visibility for the new stored skill'),\n});\n\n/** Response for the install route. Mirrors stored-skill identity fields. */\nexport const builderRegistryInstallResponseSchema = z.object({\n storedSkillId: z.string().describe('Id of the newly created stored skill'),\n name: z.string().describe('Resolved skill name'),\n filesWritten: z.number().describe('Number of files materialized into the skill version snapshot'),\n});\n\nexport type BuilderRegistryEntry = z.infer<typeof builderRegistryEntrySchema>;\nexport type BuilderRegistriesResponse = z.infer<typeof builderRegistriesResponseSchema>;\nexport type BuilderRegistryInstallBody = z.infer<typeof builderRegistryInstallBodySchema>;\nexport type BuilderRegistryInstallResponse = z.infer<typeof builderRegistryInstallResponseSchema>;\n","/**\n * Builder Registry Handlers\n *\n * Routes that let admins browse and install skills from configured external\n * registries (currently just skills.sh) directly into the Builder's stored\n * skills DB. Distinct from the workspace skills.sh routes, which write to a\n * workspace filesystem and never touch storage.\n *\n * Registry availability is driven by `AgentBuilderOptions.registries`. When\n * the requested registry is disabled (or the builder is missing entirely),\n * the routes 404 instead of leaking the surface.\n */\n\nimport type { Mastra } from '@mastra/core';\nimport type { StorageSkillFileNode } from '@mastra/core/storage';\n\nimport { HTTPException } from '../http-exception';\nimport {\n builderRegistriesResponseSchema,\n builderRegistryInstallBodySchema,\n builderRegistryInstallResponseSchema,\n builderRegistryPathParams,\n builderRegistryPopularQuerySchema,\n builderRegistryPreviewQuerySchema,\n builderRegistrySearchQuerySchema,\n} from '../schemas/builder-registry';\nimport {\n skillsShListResponseSchema,\n skillsShPreviewResponseSchema,\n skillsShSearchResponseSchema,\n} from '../schemas/workspace';\nimport { createRoute } from '../server-adapter/routes/route-builder';\nimport { toSlug } from '../utils';\nimport { getCallerAuthorId } from './authorship';\nimport { handleError } from './error';\nimport {\n assertSafeFilePath,\n assertSafeSkillName,\n fetchSkillFiles,\n getPopularSkillsSh,\n previewSkillsSh,\n searchSkillsSh,\n} from './skills-sh-shared';\n\n// =============================================================================\n// Registry resolution\n// =============================================================================\n\n/** Stable identifiers + display labels for every supported registry. */\nconst REGISTRY_LABELS: Record<string, string> = {\n 'skills-sh': 'skills.sh',\n};\n\ninterface RegistryStatus {\n id: 'skills-sh';\n enabled: boolean;\n label: string;\n}\n\n/**\n * Resolve which registries are enabled for the running deployment by reading\n * the builder's `registries` config. Returns a list with all known registries\n * (so the frontend can render an empty/disabled state) plus their enabled\n * flag.\n */\nasync function resolveRegistries(mastra: Mastra): Promise<RegistryStatus[]> {\n const editor = mastra.getEditor();\n if (!editor || typeof editor.resolveBuilder !== 'function') {\n return [{ id: 'skills-sh', enabled: false, label: REGISTRY_LABELS['skills-sh']! }];\n }\n const builder = await editor.resolveBuilder();\n const registries = builder?.getRegistries?.();\n return [\n {\n id: 'skills-sh',\n enabled: registries?.skillsSh?.enabled === true,\n label: REGISTRY_LABELS['skills-sh']!,\n },\n ];\n}\n\n/**\n * Hard-gate: throws 404 when the requested registry is unknown or disabled.\n * Mirrors `requireBuilderFeature` semantics — no surface leak for OFF registries.\n */\nasync function requireEnabledRegistry(mastra: Mastra, registryId: string): Promise<void> {\n const list = await resolveRegistries(mastra);\n const match = list.find(r => r.id === registryId);\n if (!match || !match.enabled) {\n throw new HTTPException(404, { message: 'Registry not found' });\n }\n}\n\n// =============================================================================\n// File-tree helpers\n// =============================================================================\n\n/**\n * Convert a flat list of `{ path, content, encoding }` entries into the\n * `StorageSkillFileNode` tree shape expected by the stored-skills create path.\n *\n * Each path is validated via `assertSafeFilePath` to prevent traversal from\n * upstream-controlled responses. Folder nodes are created on demand.\n */\nfunction buildFileTree(\n files: Array<{ path: string; content: string; encoding: 'utf-8' | 'base64' }>,\n): StorageSkillFileNode[] {\n const root: StorageSkillFileNode[] = [];\n\n for (const file of files) {\n const safePath = assertSafeFilePath(file.path);\n const segments = safePath.split('/').filter(Boolean);\n if (segments.length === 0) continue;\n\n let cursor = root;\n for (let i = 0; i < segments.length - 1; i++) {\n const segment = segments[i]!;\n let folder = cursor.find(node => node.type === 'folder' && node.name === segment);\n if (!folder) {\n folder = { name: segment, type: 'folder', children: [] };\n cursor.push(folder);\n }\n if (!folder.children) folder.children = [];\n cursor = folder.children;\n }\n\n const fileName = segments[segments.length - 1]!;\n const content = file.encoding === 'base64' ? Buffer.from(file.content, 'base64').toString('utf-8') : file.content;\n cursor.push({ name: fileName, type: 'file', content });\n }\n\n return root;\n}\n\n/**\n * Locally-bound SKILL.md frontmatter parser.\n *\n * Mirrors `parseSkillSnapshotFromFiles` from `@mastra/core/workspace`, but\n * inlined here because the server package's `@mastra/core` peer floor\n * (>=1.32.0) predates that helper. Once the floor is bumped to a release\n * containing the helper, this can be replaced by the shared core import.\n *\n * Only SKILL.md is consulted — frontmatter is split from the body using a\n * minimal YAML key:value reader sufficient for the fields registries\n * actually use (name, description). The body is everything after the\n * second `---` line, trimmed.\n */\ntype ParsedSkillSnapshot = {\n name?: string;\n description?: string;\n instructions: string;\n};\n\nfunction parseSkillSnapshot(\n files: Array<{ path: string; content: string; encoding: 'utf-8' | 'base64' }>,\n): ParsedSkillSnapshot | null {\n const skillMd = files.find(f => f.path === 'SKILL.md');\n if (!skillMd) return null;\n\n const raw =\n skillMd.encoding === 'base64' ? Buffer.from(skillMd.content, 'base64').toString('utf-8') : skillMd.content;\n\n const fmMatch = raw.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?([\\s\\S]*)$/);\n if (!fmMatch) {\n return { instructions: raw.trim() };\n }\n\n const fmBlock = fmMatch[1] ?? '';\n const body = fmMatch[2] ?? '';\n const frontmatter: Record<string, string> = {};\n for (const line of fmBlock.split(/\\r?\\n/)) {\n const m = line.match(/^([A-Za-z0-9_-]+)\\s*:\\s*(.*)$/);\n if (!m) continue;\n const key = m[1];\n const value = m[2] ?? '';\n if (!key) continue;\n // Strip surrounding quotes, leave the rest as-is. Registry SKILL.md\n // frontmatter is consistently flat string fields in practice.\n frontmatter[key] = value.trim().replace(/^[\"'](.*)[\"']$/, '$1');\n }\n\n return {\n name: frontmatter.name,\n description: frontmatter.description,\n instructions: body.trim(),\n };\n}\n\n// =============================================================================\n// Routes\n// =============================================================================\n\n/**\n * GET /editor/builder/registries\n *\n * Lists every known registry and whether it's enabled in this deployment.\n * Used by the Builder UI to decide whether to show the \"Browse registry\"\n * entry point at all.\n */\nexport const LIST_BUILDER_REGISTRIES_ROUTE = createRoute({\n method: 'GET',\n path: '/editor/builder/registries',\n responseType: 'json',\n responseSchema: builderRegistriesResponseSchema,\n summary: 'List available skill registries',\n description: 'Returns the configured external skill registries and their enabled state.',\n tags: ['Editor'],\n requiresAuth: true,\n requiresPermission: 'stored-skills:read',\n handler: async ({ mastra }) => {\n try {\n const registries = await resolveRegistries(mastra);\n return { registries };\n } catch (error) {\n return handleError(error, 'Error listing builder registries');\n }\n },\n});\n\n/**\n * GET /editor/builder/registries/:registryId/search\n *\n * Proxies a search query to the underlying registry. Currently only\n * registryId=\"skills-sh\" is supported.\n */\nexport const BUILDER_REGISTRY_SEARCH_ROUTE = createRoute({\n method: 'GET',\n path: '/editor/builder/registries/:registryId/search',\n responseType: 'json',\n pathParamSchema: builderRegistryPathParams,\n queryParamSchema: builderRegistrySearchQuerySchema,\n responseSchema: skillsShSearchResponseSchema,\n summary: 'Search skills in a registry',\n description: 'Proxies a search request to the configured registry to avoid CORS issues.',\n tags: ['Editor', 'Skills'],\n requiresAuth: true,\n requiresPermission: 'stored-skills:read',\n handler: async ({ mastra, registryId, q, limit }) => {\n try {\n await requireEnabledRegistry(mastra, registryId);\n return await searchSkillsSh({ q, limit });\n } catch (error) {\n if (error instanceof HTTPException) throw error;\n return handleError(error, 'Error searching registry');\n }\n },\n});\n\n/**\n * GET /editor/builder/registries/:registryId/popular\n *\n * Returns the most popular skills in a registry.\n */\nexport const BUILDER_REGISTRY_POPULAR_ROUTE = createRoute({\n method: 'GET',\n path: '/editor/builder/registries/:registryId/popular',\n responseType: 'json',\n pathParamSchema: builderRegistryPathParams,\n queryParamSchema: builderRegistryPopularQuerySchema,\n responseSchema: skillsShListResponseSchema,\n summary: 'Get popular skills from a registry',\n description: 'Proxies a popular-skills request to the configured registry to avoid CORS issues.',\n tags: ['Editor', 'Skills'],\n requiresAuth: true,\n requiresPermission: 'stored-skills:read',\n handler: async ({ mastra, registryId, limit, offset }) => {\n try {\n await requireEnabledRegistry(mastra, registryId);\n return await getPopularSkillsSh({ limit, offset });\n } catch (error) {\n if (error instanceof HTTPException) throw error;\n return handleError(error, 'Error fetching popular skills');\n }\n },\n});\n\n/**\n * GET /editor/builder/registries/:registryId/preview\n *\n * Returns the rendered SKILL.md content for a single skill in the registry.\n */\nexport const BUILDER_REGISTRY_PREVIEW_ROUTE = createRoute({\n method: 'GET',\n path: '/editor/builder/registries/:registryId/preview',\n responseType: 'json',\n pathParamSchema: builderRegistryPathParams,\n queryParamSchema: builderRegistryPreviewQuerySchema,\n responseSchema: skillsShPreviewResponseSchema,\n summary: 'Preview a skill from a registry',\n description: 'Fetches the SKILL.md content for a single skill in the configured registry.',\n tags: ['Editor', 'Skills'],\n requiresAuth: true,\n requiresPermission: 'stored-skills:read',\n handler: async ({ mastra, registryId, owner, repo, path: skillName }) => {\n try {\n await requireEnabledRegistry(mastra, registryId);\n return await previewSkillsSh({ owner, repo, skillName });\n } catch (error) {\n if (error instanceof HTTPException) throw error;\n return handleError(error, 'Error fetching skill preview');\n }\n },\n});\n\n/**\n * POST /editor/builder/registries/:registryId/install\n *\n * Fetches the full file tree for a skill from the registry, parses the\n * SKILL.md frontmatter for name/description, and persists everything as a\n * new stored skill. The registry origin is recorded under `metadata.origin`\n * so the UI can surface \"imported from skills.sh\" badges and re-resolve the\n * source later.\n *\n * Collisions (a stored skill with the derived id already exists) return 409\n * so the UI can offer an \"Open existing\" link instead of silently\n * overwriting.\n */\nexport const BUILDER_REGISTRY_INSTALL_ROUTE = createRoute({\n method: 'POST',\n path: '/editor/builder/registries/:registryId/install',\n responseType: 'json',\n pathParamSchema: builderRegistryPathParams,\n bodySchema: builderRegistryInstallBodySchema,\n responseSchema: builderRegistryInstallResponseSchema,\n summary: 'Install a registry skill into stored skills',\n description: 'Fetches a skill from the configured registry and persists it as a new stored skill.',\n tags: ['Editor', 'Skills'],\n requiresAuth: true,\n requiresPermission: 'stored-skills:write',\n handler: async ({ mastra, requestContext, registryId, owner, repo, skillName, visibility: bodyVisibility }) => {\n try {\n await requireEnabledRegistry(mastra, registryId);\n\n const storage = mastra.getStorage();\n if (!storage) {\n throw new HTTPException(500, { message: 'Storage is not configured' });\n }\n const skillStore = await storage.getStore('skills');\n if (!skillStore) {\n throw new HTTPException(500, { message: 'Skills storage domain is not available' });\n }\n\n // Pull files from the registry\n const result = await fetchSkillFiles(owner, repo, skillName);\n if (!result || result.files.length === 0) {\n throw new HTTPException(404, {\n message: `Could not find skill \"${skillName}\" in ${owner}/${repo}.`,\n });\n }\n\n const safeSkillId = assertSafeSkillName(result.skillId);\n const files = buildFileTree(result.files);\n\n // Parse SKILL.md frontmatter into structured fields. Splitting\n // frontmatter (name/description) from the markdown body keeps the\n // body as the agent-facing `instructions` instead of polluting it\n // with raw YAML metadata. SKILL.md missing or unparseable simply\n // yields a null snapshot — registry-provided values then fill in.\n const snapshot = parseSkillSnapshot(result.files);\n\n const resolvedName = snapshot?.name ?? safeSkillId;\n const description = snapshot?.description ?? `Imported from ${owner}/${repo}`;\n const id = toSlug(resolvedName) || safeSkillId;\n\n if (!id) {\n throw new HTTPException(400, {\n message: 'Could not derive skill ID from registry skill metadata.',\n });\n }\n\n // Reject collisions instead of silently overwriting; UI offers \"Open existing\".\n const existing = await skillStore.getById(id);\n if (existing) {\n throw new HTTPException(409, {\n message: `Skill with id \"${id}\" already exists.`,\n // Surface the existing id so the client can deep-link.\n cause: { storedSkillId: id },\n });\n }\n\n // Match the standard create flow: no caller = always public, otherwise default private.\n const authorId = getCallerAuthorId(requestContext) ?? undefined;\n const visibility: 'private' | 'public' = authorId ? (bodyVisibility ?? 'private') : 'public';\n\n // Use the SKILL.md body (post-frontmatter) as instructions. Frontmatter\n // values are already lifted into structured columns above, so re-storing\n // them in `instructions` would both duplicate metadata and feed YAML\n // into the agent's prompt. Fall back to description when no usable body\n // exists so `resolved.snapshot.instructions` stays non-empty.\n const instructions = snapshot?.instructions?.trim() ? snapshot.instructions : description;\n\n await skillStore.create({\n skill: {\n id,\n authorId,\n visibility,\n name: resolvedName,\n description,\n instructions,\n files,\n metadata: {\n origin: {\n type: 'skills-sh',\n owner,\n repo,\n skillName,\n },\n },\n },\n });\n\n return {\n storedSkillId: id,\n name: resolvedName,\n filesWritten: result.files.length,\n };\n } catch (error) {\n if (error instanceof HTTPException) throw error;\n return handleError(error, 'Error installing registry skill');\n }\n },\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"builder-registry-CyaUg_iP.cjs","names":["z","HTTPException","assertSafeFilePath","createRoute","handleError","skillsShSearchResponseSchema","searchSkillsSh","skillsShListResponseSchema","getPopularSkillsSh","skillsShPreviewResponseSchema","previewSkillsSh","fetchSkillFiles","assertSafeSkillName","toSlug","getCallerAuthorId"],"sources":["../src/server/schemas/builder-registry.ts","../src/server/handlers/builder-registry.ts"],"sourcesContent":["/**\n * Builder Registry Schemas\n *\n * Schemas for the Agent Builder skill registry routes. These are distinct from\n * the workspace skills.sh proxy schemas because:\n * - Builder routes are not scoped to a workspace.\n * - Builder install does not accept a `mount` field.\n * - Builder install body carries visibility + the resolved registry id.\n * - Builder install response returns the created stored skill id.\n *\n * The upstream skills.sh proxy response shapes are reused via the shared\n * `skillsShSearchResponseSchema`, `skillsShListResponseSchema`, and\n * `skillsShPreviewResponseSchema` since the wire shape from skills.sh is\n * registry-independent.\n */\n\nimport { z } from 'zod/v4';\n\n// =============================================================================\n// Registry list\n// =============================================================================\n\n/** Single entry in the registries list. */\nexport const builderRegistryEntrySchema = z.object({\n id: z.literal('skills-sh').describe('Stable registry identifier'),\n enabled: z.boolean().describe('Whether this registry is enabled in the running deployment'),\n label: z.string().describe('Human-readable registry name'),\n});\n\n/** Response for `GET /editor/builder/registries`. */\nexport const builderRegistriesResponseSchema = z.object({\n registries: z.array(builderRegistryEntrySchema),\n});\n\n// =============================================================================\n// Search / popular / preview\n// =============================================================================\n\n/** Path params used by every per-registry route. */\nexport const builderRegistryPathParams = z.object({\n registryId: z.string().describe('Registry identifier (e.g. \"skills-sh\")'),\n});\n\nexport const builderRegistrySearchQuerySchema = z.object({\n q: z.string().describe('Search query'),\n limit: z.coerce.number().int().min(1).max(100).optional().default(10).describe('Maximum number of results (1-100)'),\n});\n\nexport const builderRegistryPopularQuerySchema = z\n .object({\n limit: z.coerce.number().int().min(1).max(100).optional().default(10).describe('Maximum number of results (1-100)'),\n offset: z.coerce\n .number()\n .int()\n .min(0)\n .optional()\n .default(0)\n .describe('Offset for pagination (must be a multiple of `limit`)'),\n })\n .refine(args => args.offset % args.limit === 0, {\n message: 'offset must be a multiple of limit (the upstream registry pages by `limit`)',\n path: ['offset'],\n });\n\nexport const builderRegistryPreviewQuerySchema = z.object({\n owner: z.string().describe('GitHub repository owner'),\n repo: z.string().describe('GitHub repository name'),\n path: z.string().describe('Skill name within repo'),\n});\n\n// =============================================================================\n// Install\n// =============================================================================\n\n/**\n * Body for `POST /editor/builder/registries/:registryId/install`.\n *\n * Visibility behaves like the standard stored-skill create flow: optional,\n * defaults to private when the caller is authenticated.\n */\nexport const builderRegistryInstallBodySchema = z.object({\n owner: z.string().describe('GitHub repository owner'),\n repo: z.string().describe('GitHub repository name'),\n skillName: z.string().describe('Skill name from the registry'),\n visibility: z.enum(['private', 'public']).optional().describe('Visibility for the new stored skill'),\n});\n\n/** Response for the install route. Mirrors stored-skill identity fields. */\nexport const builderRegistryInstallResponseSchema = z.object({\n storedSkillId: z.string().describe('Id of the newly created stored skill'),\n name: z.string().describe('Resolved skill name'),\n filesWritten: z.number().describe('Number of files materialized into the skill version snapshot'),\n});\n\nexport type BuilderRegistryEntry = z.infer<typeof builderRegistryEntrySchema>;\nexport type BuilderRegistriesResponse = z.infer<typeof builderRegistriesResponseSchema>;\nexport type BuilderRegistryInstallBody = z.infer<typeof builderRegistryInstallBodySchema>;\nexport type BuilderRegistryInstallResponse = z.infer<typeof builderRegistryInstallResponseSchema>;\n","/**\n * Builder Registry Handlers\n *\n * Routes that let admins browse and install skills from configured external\n * registries (currently just skills.sh) directly into the Builder's stored\n * skills DB. Distinct from the workspace skills.sh routes, which write to a\n * workspace filesystem and never touch storage.\n *\n * Registry availability is driven by `AgentBuilderOptions.registries`. When\n * the requested registry is disabled (or the builder is missing entirely),\n * the routes 404 instead of leaking the surface.\n */\n\nimport type { Mastra } from '@mastra/core';\nimport type { StorageSkillFileNode } from '@mastra/core/storage';\n\nimport { HTTPException } from '../http-exception';\nimport {\n builderRegistriesResponseSchema,\n builderRegistryInstallBodySchema,\n builderRegistryInstallResponseSchema,\n builderRegistryPathParams,\n builderRegistryPopularQuerySchema,\n builderRegistryPreviewQuerySchema,\n builderRegistrySearchQuerySchema,\n} from '../schemas/builder-registry';\nimport {\n skillsShListResponseSchema,\n skillsShPreviewResponseSchema,\n skillsShSearchResponseSchema,\n} from '../schemas/workspace';\nimport { createRoute } from '../server-adapter/routes/route-builder';\nimport { toSlug } from '../utils';\nimport { getCallerAuthorId } from './authorship';\nimport { handleError } from './error';\nimport {\n assertSafeFilePath,\n assertSafeSkillName,\n fetchSkillFiles,\n getPopularSkillsSh,\n previewSkillsSh,\n searchSkillsSh,\n} from './skills-sh-shared';\n\n// =============================================================================\n// Registry resolution\n// =============================================================================\n\n/** Stable identifiers + display labels for every supported registry. */\nconst REGISTRY_LABELS: Record<string, string> = {\n 'skills-sh': 'skills.sh',\n};\n\ninterface RegistryStatus {\n id: 'skills-sh';\n enabled: boolean;\n label: string;\n}\n\n/**\n * Resolve which registries are enabled for the running deployment by reading\n * the builder's `registries` config. Returns a list with all known registries\n * (so the frontend can render an empty/disabled state) plus their enabled\n * flag.\n */\nasync function resolveRegistries(mastra: Mastra): Promise<RegistryStatus[]> {\n const editor = mastra.getEditor();\n if (!editor || typeof editor.resolveBuilder !== 'function') {\n return [{ id: 'skills-sh', enabled: false, label: REGISTRY_LABELS['skills-sh']! }];\n }\n const builder = await editor.resolveBuilder();\n const registries = builder?.getRegistries?.();\n return [\n {\n id: 'skills-sh',\n enabled: registries?.skillsSh?.enabled === true,\n label: REGISTRY_LABELS['skills-sh']!,\n },\n ];\n}\n\n/**\n * Hard-gate: throws 404 when the requested registry is unknown or disabled.\n * Mirrors `requireBuilderFeature` semantics — no surface leak for OFF registries.\n */\nasync function requireEnabledRegistry(mastra: Mastra, registryId: string): Promise<void> {\n const list = await resolveRegistries(mastra);\n const match = list.find(r => r.id === registryId);\n if (!match || !match.enabled) {\n throw new HTTPException(404, { message: 'Registry not found' });\n }\n}\n\n// =============================================================================\n// File-tree helpers\n// =============================================================================\n\n/**\n * Convert a flat list of `{ path, content, encoding }` entries into the\n * `StorageSkillFileNode` tree shape expected by the stored-skills create path.\n *\n * Each path is validated via `assertSafeFilePath` to prevent traversal from\n * upstream-controlled responses. Folder nodes are created on demand.\n */\nfunction buildFileTree(\n files: Array<{ path: string; content: string; encoding: 'utf-8' | 'base64' }>,\n): StorageSkillFileNode[] {\n const root: StorageSkillFileNode[] = [];\n\n for (const file of files) {\n const safePath = assertSafeFilePath(file.path);\n const segments = safePath.split('/').filter(Boolean);\n if (segments.length === 0) continue;\n\n let cursor = root;\n for (let i = 0; i < segments.length - 1; i++) {\n const segment = segments[i]!;\n let folder = cursor.find(node => node.type === 'folder' && node.name === segment);\n if (!folder) {\n folder = { name: segment, type: 'folder', children: [] };\n cursor.push(folder);\n }\n if (!folder.children) folder.children = [];\n cursor = folder.children;\n }\n\n const fileName = segments[segments.length - 1]!;\n const content = file.encoding === 'base64' ? Buffer.from(file.content, 'base64').toString('utf-8') : file.content;\n cursor.push({ name: fileName, type: 'file', content });\n }\n\n return root;\n}\n\n/**\n * Locally-bound SKILL.md frontmatter parser.\n *\n * Mirrors `parseSkillSnapshotFromFiles` from `@mastra/core/workspace`, but\n * inlined here because the server package's `@mastra/core` peer floor\n * (>=1.32.0) predates that helper. Once the floor is bumped to a release\n * containing the helper, this can be replaced by the shared core import.\n *\n * Only SKILL.md is consulted — frontmatter is split from the body using a\n * minimal YAML key:value reader sufficient for the fields registries\n * actually use (name, description). The body is everything after the\n * second `---` line, trimmed.\n */\ntype ParsedSkillSnapshot = {\n name?: string;\n description?: string;\n instructions: string;\n};\n\nfunction parseSkillSnapshot(\n files: Array<{ path: string; content: string; encoding: 'utf-8' | 'base64' }>,\n): ParsedSkillSnapshot | null {\n const skillMd = files.find(f => f.path === 'SKILL.md');\n if (!skillMd) return null;\n\n const raw =\n skillMd.encoding === 'base64' ? Buffer.from(skillMd.content, 'base64').toString('utf-8') : skillMd.content;\n\n const fmMatch = raw.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?([\\s\\S]*)$/);\n if (!fmMatch) {\n return { instructions: raw.trim() };\n }\n\n const fmBlock = fmMatch[1] ?? '';\n const body = fmMatch[2] ?? '';\n const frontmatter: Record<string, string> = {};\n for (const line of fmBlock.split(/\\r?\\n/)) {\n const m = line.match(/^([A-Za-z0-9_-]+)\\s*:\\s*(.*)$/);\n if (!m) continue;\n const key = m[1];\n const value = m[2] ?? '';\n if (!key) continue;\n // Strip surrounding quotes, leave the rest as-is. Registry SKILL.md\n // frontmatter is consistently flat string fields in practice.\n frontmatter[key] = value.trim().replace(/^[\"'](.*)[\"']$/, '$1');\n }\n\n return {\n name: frontmatter.name,\n description: frontmatter.description,\n instructions: body.trim(),\n };\n}\n\n// =============================================================================\n// Routes\n// =============================================================================\n\n/**\n * GET /editor/builder/registries\n *\n * Lists every known registry and whether it's enabled in this deployment.\n * Used by the Builder UI to decide whether to show the \"Browse registry\"\n * entry point at all.\n */\nexport const LIST_BUILDER_REGISTRIES_ROUTE = createRoute({\n method: 'GET',\n path: '/editor/builder/registries',\n responseType: 'json',\n responseSchema: builderRegistriesResponseSchema,\n summary: 'List available skill registries',\n description: 'Returns the configured external skill registries and their enabled state.',\n tags: ['Editor'],\n requiresAuth: true,\n requiresPermission: 'stored-skills:read',\n handler: async ({ mastra }) => {\n try {\n const registries = await resolveRegistries(mastra);\n return { registries };\n } catch (error) {\n return handleError(error, 'Error listing builder registries');\n }\n },\n});\n\n/**\n * GET /editor/builder/registries/:registryId/search\n *\n * Proxies a search query to the underlying registry. Currently only\n * registryId=\"skills-sh\" is supported.\n */\nexport const BUILDER_REGISTRY_SEARCH_ROUTE = createRoute({\n method: 'GET',\n path: '/editor/builder/registries/:registryId/search',\n responseType: 'json',\n pathParamSchema: builderRegistryPathParams,\n queryParamSchema: builderRegistrySearchQuerySchema,\n responseSchema: skillsShSearchResponseSchema,\n summary: 'Search skills in a registry',\n description: 'Proxies a search request to the configured registry to avoid CORS issues.',\n tags: ['Editor', 'Skills'],\n requiresAuth: true,\n requiresPermission: 'stored-skills:read',\n handler: async ({ mastra, registryId, q, limit }) => {\n try {\n await requireEnabledRegistry(mastra, registryId);\n return await searchSkillsSh({ q, limit });\n } catch (error) {\n if (error instanceof HTTPException) throw error;\n return handleError(error, 'Error searching registry');\n }\n },\n});\n\n/**\n * GET /editor/builder/registries/:registryId/popular\n *\n * Returns the most popular skills in a registry.\n */\nexport const BUILDER_REGISTRY_POPULAR_ROUTE = createRoute({\n method: 'GET',\n path: '/editor/builder/registries/:registryId/popular',\n responseType: 'json',\n pathParamSchema: builderRegistryPathParams,\n queryParamSchema: builderRegistryPopularQuerySchema,\n responseSchema: skillsShListResponseSchema,\n summary: 'Get popular skills from a registry',\n description: 'Proxies a popular-skills request to the configured registry to avoid CORS issues.',\n tags: ['Editor', 'Skills'],\n requiresAuth: true,\n requiresPermission: 'stored-skills:read',\n handler: async ({ mastra, registryId, limit, offset }) => {\n try {\n await requireEnabledRegistry(mastra, registryId);\n return await getPopularSkillsSh({ limit, offset });\n } catch (error) {\n if (error instanceof HTTPException) throw error;\n return handleError(error, 'Error fetching popular skills');\n }\n },\n});\n\n/**\n * GET /editor/builder/registries/:registryId/preview\n *\n * Returns the rendered SKILL.md content for a single skill in the registry.\n */\nexport const BUILDER_REGISTRY_PREVIEW_ROUTE = createRoute({\n method: 'GET',\n path: '/editor/builder/registries/:registryId/preview',\n responseType: 'json',\n pathParamSchema: builderRegistryPathParams,\n queryParamSchema: builderRegistryPreviewQuerySchema,\n responseSchema: skillsShPreviewResponseSchema,\n summary: 'Preview a skill from a registry',\n description: 'Fetches the SKILL.md content for a single skill in the configured registry.',\n tags: ['Editor', 'Skills'],\n requiresAuth: true,\n requiresPermission: 'stored-skills:read',\n handler: async ({ mastra, registryId, owner, repo, path: skillName }) => {\n try {\n await requireEnabledRegistry(mastra, registryId);\n return await previewSkillsSh({ owner, repo, skillName });\n } catch (error) {\n if (error instanceof HTTPException) throw error;\n return handleError(error, 'Error fetching skill preview');\n }\n },\n});\n\n/**\n * POST /editor/builder/registries/:registryId/install\n *\n * Fetches the full file tree for a skill from the registry, parses the\n * SKILL.md frontmatter for name/description, and persists everything as a\n * new stored skill. The registry origin is recorded under `metadata.origin`\n * so the UI can surface \"imported from skills.sh\" badges and re-resolve the\n * source later.\n *\n * Collisions (a stored skill with the derived id already exists) return 409\n * so the UI can offer an \"Open existing\" link instead of silently\n * overwriting.\n */\nexport const BUILDER_REGISTRY_INSTALL_ROUTE = createRoute({\n method: 'POST',\n path: '/editor/builder/registries/:registryId/install',\n responseType: 'json',\n pathParamSchema: builderRegistryPathParams,\n bodySchema: builderRegistryInstallBodySchema,\n responseSchema: builderRegistryInstallResponseSchema,\n summary: 'Install a registry skill into stored skills',\n description: 'Fetches a skill from the configured registry and persists it as a new stored skill.',\n tags: ['Editor', 'Skills'],\n requiresAuth: true,\n requiresPermission: 'stored-skills:write',\n handler: async ({ mastra, requestContext, registryId, owner, repo, skillName, visibility: bodyVisibility }) => {\n try {\n await requireEnabledRegistry(mastra, registryId);\n\n const storage = mastra.getStorage();\n if (!storage) {\n throw new HTTPException(500, { message: 'Storage is not configured' });\n }\n const skillStore = await storage.getStore('skills');\n if (!skillStore) {\n throw new HTTPException(500, { message: 'Skills storage domain is not available' });\n }\n\n // Pull files from the registry\n const result = await fetchSkillFiles(owner, repo, skillName);\n if (!result || result.files.length === 0) {\n throw new HTTPException(404, {\n message: `Could not find skill \"${skillName}\" in ${owner}/${repo}.`,\n });\n }\n\n const safeSkillId = assertSafeSkillName(result.skillId);\n const files = buildFileTree(result.files);\n\n // Parse SKILL.md frontmatter into structured fields. Splitting\n // frontmatter (name/description) from the markdown body keeps the\n // body as the agent-facing `instructions` instead of polluting it\n // with raw YAML metadata. SKILL.md missing or unparseable simply\n // yields a null snapshot — registry-provided values then fill in.\n const snapshot = parseSkillSnapshot(result.files);\n\n const resolvedName = snapshot?.name ?? safeSkillId;\n const description = snapshot?.description ?? `Imported from ${owner}/${repo}`;\n const id = toSlug(resolvedName) || safeSkillId;\n\n if (!id) {\n throw new HTTPException(400, {\n message: 'Could not derive skill ID from registry skill metadata.',\n });\n }\n\n // Reject collisions instead of silently overwriting; UI offers \"Open existing\".\n const existing = await skillStore.getById(id);\n if (existing) {\n throw new HTTPException(409, {\n message: `Skill with id \"${id}\" already exists.`,\n // Surface the existing id so the client can deep-link.\n cause: { storedSkillId: id },\n });\n }\n\n // Match the standard create flow: no caller = always public, otherwise default private.\n const authorId = getCallerAuthorId(requestContext) ?? undefined;\n const visibility: 'private' | 'public' = authorId ? (bodyVisibility ?? 'private') : 'public';\n\n // Use the SKILL.md body (post-frontmatter) as instructions. Frontmatter\n // values are already lifted into structured columns above, so re-storing\n // them in `instructions` would both duplicate metadata and feed YAML\n // into the agent's prompt. Fall back to description when no usable body\n // exists so `resolved.snapshot.instructions` stays non-empty.\n const instructions = snapshot?.instructions?.trim() ? snapshot.instructions : description;\n\n await skillStore.create({\n skill: {\n id,\n authorId,\n visibility,\n name: resolvedName,\n description,\n instructions,\n files,\n metadata: {\n origin: {\n type: 'skills-sh',\n owner,\n repo,\n skillName,\n },\n },\n },\n });\n\n return {\n storedSkillId: id,\n name: resolvedName,\n filesWritten: result.files.length,\n };\n } catch (error) {\n if (error instanceof HTTPException) throw error;\n return handleError(error, 'Error installing registry skill');\n }\n },\n});\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { t as HTTPException } from "./http-exception-CyfxZB6W.js";
2
2
  import { n as createRoute } from "./route-builder-YQ_gLIvW.js";
3
- import "./constants-Cp1x-6sJ.js";
3
+ import "./constants-CutMu4A_.js";
4
4
  import { handleError } from "./server/handlers/error.js";
5
5
  import { assertWriteAccess, getCallerAuthorId, hasAdminBypass, hasScopedPermission } from "./server/handlers/authorship.js";
6
6
  import { z } from "zod/v4";
@@ -204,4 +204,4 @@ const DISCONNECT_CHANNEL_ROUTE = createRoute({
204
204
  //#endregion
205
205
  export { LIST_CHANNEL_PLATFORMS_ROUTE as i, DISCONNECT_CHANNEL_ROUTE as n, LIST_CHANNEL_INSTALLATIONS_ROUTE as r, CONNECT_CHANNEL_ROUTE as t };
206
206
 
207
- //# sourceMappingURL=channels-B9yt3a2P.js.map
207
+ //# sourceMappingURL=channels-BnFQESMf.js.map
@@ -1 +1 @@
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
+ {"version":3,"file":"channels-BnFQESMf.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,6 +1,6 @@
1
1
  const require_http_exception = require("./http-exception-CKDHupKw.cjs");
2
2
  const require_route_builder = require("./route-builder-BAAedfru.cjs");
3
- require("./constants-ChBaIptn.cjs");
3
+ require("./constants-CXPpy-Ef.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");
6
6
  let zod_v4 = require("zod/v4");
@@ -227,4 +227,4 @@ Object.defineProperty(exports, "LIST_CHANNEL_PLATFORMS_ROUTE", {
227
227
  }
228
228
  });
229
229
 
230
- //# sourceMappingURL=channels-BRoq3VKR.cjs.map
230
+ //# sourceMappingURL=channels-Dzy6VM3w.cjs.map
@@ -1 +1 @@
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":"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"}
1
+ {"version":3,"file":"channels-Dzy6VM3w.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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"}
@@ -14,6 +14,11 @@ const MASTRA_USER_ROLES_KEY = "mastra__userRoles";
14
14
  const MASTRA_AUTH_TOKEN_KEY = "mastra__authToken";
15
15
  const MASTRA_IS_STUDIO_KEY = "mastra__isStudio";
16
16
  /**
17
+ * Carries a delegating agent's memory into a delegated sub-agent run. Set only
18
+ * by the delegation path inside a single process.
19
+ */
20
+ const MASTRA_INHERITED_MEMORY_KEY = "mastra__inheritedMemory";
21
+ /**
17
22
  * Tracks which auth mode was used for the current request.
18
23
  * Set to 'studio' when studio auth was used, 'server' when server auth was used.
19
24
  * Used to determine which RBAC/FGA provider to use for permission checks.
@@ -30,6 +35,7 @@ const RESERVED_CONTEXT_KEYS = /* @__PURE__ */ new Set([
30
35
  MASTRA_AUTH_TOKEN_KEY,
31
36
  MASTRA_IS_STUDIO_KEY,
32
37
  MASTRA_AUTH_MODE_KEY,
38
+ MASTRA_INHERITED_MEMORY_KEY,
33
39
  "organizationId"
34
40
  ]);
35
41
  function isReservedRequestContextKey(key) {
@@ -185,4 +191,4 @@ Object.defineProperty(exports, "resolveToolConfig", {
185
191
  }
186
192
  });
187
193
 
188
- //# sourceMappingURL=constants-ChBaIptn.cjs.map
194
+ //# sourceMappingURL=constants-CXPpy-Ef.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants-CXPpy-Ef.cjs","names":[],"sources":["../src/server/constants.ts"],"sourcesContent":["/**\n * Constants inlined from @mastra/core to avoid import compatibility\n * issues with older core versions that don't export them yet.\n *\n * - Reserved RequestContext keys are inlined from @mastra/core/request-context.\n * - Workspace tool constants are inlined from @mastra/core/workspace.\n */\n\nexport const MASTRA_RESOURCE_ID_KEY = 'mastra__resourceId';\n\nexport const MASTRA_THREAD_ID_KEY = 'mastra__threadId';\n\nexport const MASTRA_USER_KEY = 'mastra__user';\n\nexport const MASTRA_USER_PERMISSIONS_KEY = 'mastra__userPermissions';\n\nexport const MASTRA_USER_ROLES_KEY = 'mastra__userRoles';\n\nexport const MASTRA_AUTH_TOKEN_KEY = 'mastra__authToken';\n\nexport const MASTRA_IS_STUDIO_KEY = 'mastra__isStudio';\n\n/**\n * Carries a delegating agent's memory into a delegated sub-agent run. Set only\n * by the delegation path inside a single process.\n */\nexport const MASTRA_INHERITED_MEMORY_KEY = 'mastra__inheritedMemory';\n\n/**\n * Tracks which auth mode was used for the current request.\n * Set to 'studio' when studio auth was used, 'server' when server auth was used.\n * Used to determine which RBAC/FGA provider to use for permission checks.\n */\nexport const MASTRA_AUTH_MODE_KEY = 'mastra__authMode';\n\nexport type MastraAuthMode = 'studio' | 'server';\n\nexport const MASTRA_CLIENT_TYPE_HEADER = 'x-mastra-client-type';\n\nexport const MASTRA_STUDIO_CLIENT_TYPE = 'studio';\n\nconst RESERVED_CONTEXT_KEYS = new Set([\n MASTRA_RESOURCE_ID_KEY,\n MASTRA_THREAD_ID_KEY,\n MASTRA_USER_KEY,\n MASTRA_USER_PERMISSIONS_KEY,\n MASTRA_USER_ROLES_KEY,\n MASTRA_AUTH_TOKEN_KEY,\n MASTRA_IS_STUDIO_KEY,\n MASTRA_AUTH_MODE_KEY,\n // Delegation stores a live memory instance here. A body-supplied value would\n // be handed to the agent as its memory and throw on the first memory call.\n MASTRA_INHERITED_MEMORY_KEY,\n // Tenant scope must be established server-side, never self-asserted by a\n // client. The trusted-actor FGA gate keys off `organizationId`, so a\n // body-supplied value must not be merged into the request context.\n 'organizationId',\n]);\n\nexport function isReservedRequestContextKey(key: string): boolean {\n return RESERVED_CONTEXT_KEYS.has(key);\n}\n\nexport function isStudioClientTypeHeader(value: string | undefined): boolean {\n return value?.toLowerCase() === MASTRA_STUDIO_CLIENT_TYPE;\n}\n\nexport const WORKSPACE_TOOLS_PREFIX = 'mastra_workspace' as const;\n\nexport const WORKSPACE_TOOLS = {\n FILESYSTEM: {\n READ_FILE: `${WORKSPACE_TOOLS_PREFIX}_read_file` as const,\n WRITE_FILE: `${WORKSPACE_TOOLS_PREFIX}_write_file` as const,\n EDIT_FILE: `${WORKSPACE_TOOLS_PREFIX}_edit_file` as const,\n LIST_FILES: `${WORKSPACE_TOOLS_PREFIX}_list_files` as const,\n DELETE: `${WORKSPACE_TOOLS_PREFIX}_delete` as const,\n FILE_STAT: `${WORKSPACE_TOOLS_PREFIX}_file_stat` as const,\n MKDIR: `${WORKSPACE_TOOLS_PREFIX}_mkdir` as const,\n GREP: `${WORKSPACE_TOOLS_PREFIX}_grep` as const,\n },\n SANDBOX: {\n EXECUTE_COMMAND: `${WORKSPACE_TOOLS_PREFIX}_execute_command` as const,\n },\n SEARCH: {\n SEARCH: `${WORKSPACE_TOOLS_PREFIX}_search` as const,\n INDEX: `${WORKSPACE_TOOLS_PREFIX}_index` as const,\n },\n} as const;\n\nexport type WorkspaceToolName =\n | (typeof WORKSPACE_TOOLS.FILESYSTEM)[keyof typeof WORKSPACE_TOOLS.FILESYSTEM]\n | (typeof WORKSPACE_TOOLS.SEARCH)[keyof typeof WORKSPACE_TOOLS.SEARCH]\n | (typeof WORKSPACE_TOOLS.SANDBOX)[keyof typeof WORKSPACE_TOOLS.SANDBOX];\n\n/**\n * A tool config value that may be a static boolean or a dynamic function.\n * Inlined from @mastra/core/workspace for compatibility.\n *\n * Uses `(...args: any[]) => any` for the function branch so it stays\n * assignable from all core context variants (ToolConfigContext,\n * ToolConfigWithArgsContext) without importing them.\n */\n\ntype DynamicToolConfigValue = boolean | ((...args: any[]) => any);\n\n/**\n * Configuration for a single workspace tool.\n */\nexport interface WorkspaceToolConfig {\n enabled?: DynamicToolConfigValue;\n requireApproval?: DynamicToolConfigValue;\n requireReadBeforeWrite?: DynamicToolConfigValue;\n}\n\n/**\n * Configuration for workspace tools.\n */\nexport type WorkspaceToolsConfig = {\n enabled?: DynamicToolConfigValue;\n requireApproval?: DynamicToolConfigValue;\n} & Partial<Record<WorkspaceToolName, WorkspaceToolConfig>>;\n\n/**\n * Safely resolve a dynamic config value (boolean or async function) to a boolean.\n * Falls back to `safeDefault` when no context is available or the function throws.\n */\nasync function resolveDynamicValue(\n value: DynamicToolConfigValue | undefined,\n context: { workspace: object; requestContext: Record<string, unknown> } | undefined,\n safeDefault: boolean,\n): Promise<boolean> {\n if (value === undefined) return safeDefault;\n if (typeof value === 'boolean') return value;\n if (!context) return safeDefault;\n try {\n return await value(context);\n } catch (error) {\n console.warn('[Workspace Tools] Dynamic config function threw, using safe default:', error);\n return safeDefault;\n }\n}\n\n/**\n * Resolve the effective configuration for a workspace tool.\n * Inlined from @mastra/core/workspace for compatibility.\n *\n * Dynamic function values are resolved by calling them with the provided\n * workspace and requestContext. If a function throws, safe defaults are used\n * (enabled → false, requireApproval → true, requireReadBeforeWrite → true).\n */\nexport async function resolveToolConfig(\n toolsConfig: WorkspaceToolsConfig | undefined,\n toolName: WorkspaceToolName,\n context?: { workspace: object; requestContext: Record<string, unknown> },\n): Promise<{ enabled: boolean; requireApproval: boolean; requireReadBeforeWrite?: boolean }> {\n let enabled: DynamicToolConfigValue = true;\n let requireApproval: DynamicToolConfigValue = false;\n let requireReadBeforeWrite: DynamicToolConfigValue | undefined;\n\n if (toolsConfig) {\n if (toolsConfig.enabled !== undefined) {\n enabled = toolsConfig.enabled;\n }\n if (toolsConfig.requireApproval !== undefined) {\n requireApproval = toolsConfig.requireApproval;\n }\n\n const perToolConfig = toolsConfig[toolName];\n if (perToolConfig) {\n if (perToolConfig.enabled !== undefined) {\n enabled = perToolConfig.enabled;\n }\n if (perToolConfig.requireApproval !== undefined) {\n requireApproval = perToolConfig.requireApproval;\n }\n if (perToolConfig.requireReadBeforeWrite !== undefined) {\n requireReadBeforeWrite = perToolConfig.requireReadBeforeWrite;\n }\n }\n }\n\n return {\n enabled: await resolveDynamicValue(enabled, context, false),\n requireApproval: await resolveDynamicValue(requireApproval, context, true),\n requireReadBeforeWrite:\n requireReadBeforeWrite !== undefined\n ? await resolveDynamicValue(requireReadBeforeWrite, context, true)\n : undefined,\n };\n}\n"],"mappings":";;;;;;;;AAQA,MAAa,yBAAyB;AAEtC,MAAa,uBAAuB;AAEpC,MAAa,kBAAkB;AAE/B,MAAa,8BAA8B;AAE3C,MAAa,wBAAwB;AAErC,MAAa,wBAAwB;AAErC,MAAa,uBAAuB;;;;;AAMpC,MAAa,8BAA8B;;;;;;AAO3C,MAAa,uBAAuB;AAIpC,MAAa,4BAA4B;AAEzC,MAAa,4BAA4B;AAEzC,MAAM,wCAAwB,IAAI,IAAI;CACpC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAGA;CAIA;AACF,CAAC;AAED,SAAgB,4BAA4B,KAAsB;CAChE,OAAO,sBAAsB,IAAI,GAAG;AACtC;AAEA,SAAgB,yBAAyB,OAAoC;CAC3E,OAAO,OAAO,YAAY,MAAM;AAClC;AAEA,MAAa,yBAAyB;AAEtC,MAAa,kBAAkB;CAC7B,YAAY;EACV,WAAW,GAAG,uBAAuB;EACrC,YAAY,GAAG,uBAAuB;EACtC,WAAW,GAAG,uBAAuB;EACrC,YAAY,GAAG,uBAAuB;EACtC,QAAQ,GAAG,uBAAuB;EAClC,WAAW,GAAG,uBAAuB;EACrC,OAAO,GAAG,uBAAuB;EACjC,MAAM,GAAG,uBAAuB;CAClC;CACA,SAAS,EACP,iBAAiB,GAAG,uBAAuB,kBAC7C;CACA,QAAQ;EACN,QAAQ,GAAG,uBAAuB;EAClC,OAAO,GAAG,uBAAuB;CACnC;AACF;;;;;AAuCA,eAAe,oBACb,OACA,SACA,aACkB;CAClB,IAAI,UAAU,KAAA,GAAW,OAAO;CAChC,IAAI,OAAO,UAAU,WAAW,OAAO;CACvC,IAAI,CAAC,SAAS,OAAO;CACrB,IAAI;EACF,OAAO,MAAM,MAAM,OAAO;CAC5B,SAAS,OAAO;EACd,QAAQ,KAAK,wEAAwE,KAAK;EAC1F,OAAO;CACT;AACF;;;;;;;;;AAUA,eAAsB,kBACpB,aACA,UACA,SAC2F;CAC3F,IAAI,UAAkC;CACtC,IAAI,kBAA0C;CAC9C,IAAI;CAEJ,IAAI,aAAa;EACf,IAAI,YAAY,YAAY,KAAA,GAC1B,UAAU,YAAY;EAExB,IAAI,YAAY,oBAAoB,KAAA,GAClC,kBAAkB,YAAY;EAGhC,MAAM,gBAAgB,YAAY;EAClC,IAAI,eAAe;GACjB,IAAI,cAAc,YAAY,KAAA,GAC5B,UAAU,cAAc;GAE1B,IAAI,cAAc,oBAAoB,KAAA,GACpC,kBAAkB,cAAc;GAElC,IAAI,cAAc,2BAA2B,KAAA,GAC3C,yBAAyB,cAAc;EAE3C;CACF;CAEA,OAAO;EACL,SAAS,MAAM,oBAAoB,SAAS,SAAS,KAAK;EAC1D,iBAAiB,MAAM,oBAAoB,iBAAiB,SAAS,IAAI;EACzE,wBACE,2BAA2B,KAAA,IACvB,MAAM,oBAAoB,wBAAwB,SAAS,IAAI,IAC/D,KAAA;CACR;AACF"}
@@ -14,6 +14,11 @@ const MASTRA_USER_ROLES_KEY = "mastra__userRoles";
14
14
  const MASTRA_AUTH_TOKEN_KEY = "mastra__authToken";
15
15
  const MASTRA_IS_STUDIO_KEY = "mastra__isStudio";
16
16
  /**
17
+ * Carries a delegating agent's memory into a delegated sub-agent run. Set only
18
+ * by the delegation path inside a single process.
19
+ */
20
+ const MASTRA_INHERITED_MEMORY_KEY = "mastra__inheritedMemory";
21
+ /**
17
22
  * Tracks which auth mode was used for the current request.
18
23
  * Set to 'studio' when studio auth was used, 'server' when server auth was used.
19
24
  * Used to determine which RBAC/FGA provider to use for permission checks.
@@ -30,6 +35,7 @@ const RESERVED_CONTEXT_KEYS = /* @__PURE__ */ new Set([
30
35
  MASTRA_AUTH_TOKEN_KEY,
31
36
  MASTRA_IS_STUDIO_KEY,
32
37
  MASTRA_AUTH_MODE_KEY,
38
+ MASTRA_INHERITED_MEMORY_KEY,
33
39
  "organizationId"
34
40
  ]);
35
41
  function isReservedRequestContextKey(key) {
@@ -102,4 +108,4 @@ async function resolveToolConfig(toolsConfig, toolName, context) {
102
108
  //#endregion
103
109
  export { MASTRA_RESOURCE_ID_KEY as a, MASTRA_USER_KEY as c, WORKSPACE_TOOLS as d, isReservedRequestContextKey as f, MASTRA_IS_STUDIO_KEY as i, MASTRA_USER_PERMISSIONS_KEY as l, resolveToolConfig as m, MASTRA_AUTH_TOKEN_KEY as n, MASTRA_STUDIO_CLIENT_TYPE as o, isStudioClientTypeHeader as p, MASTRA_CLIENT_TYPE_HEADER as r, MASTRA_THREAD_ID_KEY as s, MASTRA_AUTH_MODE_KEY as t, MASTRA_USER_ROLES_KEY as u };
104
110
 
105
- //# sourceMappingURL=constants-Cp1x-6sJ.js.map
111
+ //# sourceMappingURL=constants-CutMu4A_.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants-CutMu4A_.js","names":[],"sources":["../src/server/constants.ts"],"sourcesContent":["/**\n * Constants inlined from @mastra/core to avoid import compatibility\n * issues with older core versions that don't export them yet.\n *\n * - Reserved RequestContext keys are inlined from @mastra/core/request-context.\n * - Workspace tool constants are inlined from @mastra/core/workspace.\n */\n\nexport const MASTRA_RESOURCE_ID_KEY = 'mastra__resourceId';\n\nexport const MASTRA_THREAD_ID_KEY = 'mastra__threadId';\n\nexport const MASTRA_USER_KEY = 'mastra__user';\n\nexport const MASTRA_USER_PERMISSIONS_KEY = 'mastra__userPermissions';\n\nexport const MASTRA_USER_ROLES_KEY = 'mastra__userRoles';\n\nexport const MASTRA_AUTH_TOKEN_KEY = 'mastra__authToken';\n\nexport const MASTRA_IS_STUDIO_KEY = 'mastra__isStudio';\n\n/**\n * Carries a delegating agent's memory into a delegated sub-agent run. Set only\n * by the delegation path inside a single process.\n */\nexport const MASTRA_INHERITED_MEMORY_KEY = 'mastra__inheritedMemory';\n\n/**\n * Tracks which auth mode was used for the current request.\n * Set to 'studio' when studio auth was used, 'server' when server auth was used.\n * Used to determine which RBAC/FGA provider to use for permission checks.\n */\nexport const MASTRA_AUTH_MODE_KEY = 'mastra__authMode';\n\nexport type MastraAuthMode = 'studio' | 'server';\n\nexport const MASTRA_CLIENT_TYPE_HEADER = 'x-mastra-client-type';\n\nexport const MASTRA_STUDIO_CLIENT_TYPE = 'studio';\n\nconst RESERVED_CONTEXT_KEYS = new Set([\n MASTRA_RESOURCE_ID_KEY,\n MASTRA_THREAD_ID_KEY,\n MASTRA_USER_KEY,\n MASTRA_USER_PERMISSIONS_KEY,\n MASTRA_USER_ROLES_KEY,\n MASTRA_AUTH_TOKEN_KEY,\n MASTRA_IS_STUDIO_KEY,\n MASTRA_AUTH_MODE_KEY,\n // Delegation stores a live memory instance here. A body-supplied value would\n // be handed to the agent as its memory and throw on the first memory call.\n MASTRA_INHERITED_MEMORY_KEY,\n // Tenant scope must be established server-side, never self-asserted by a\n // client. The trusted-actor FGA gate keys off `organizationId`, so a\n // body-supplied value must not be merged into the request context.\n 'organizationId',\n]);\n\nexport function isReservedRequestContextKey(key: string): boolean {\n return RESERVED_CONTEXT_KEYS.has(key);\n}\n\nexport function isStudioClientTypeHeader(value: string | undefined): boolean {\n return value?.toLowerCase() === MASTRA_STUDIO_CLIENT_TYPE;\n}\n\nexport const WORKSPACE_TOOLS_PREFIX = 'mastra_workspace' as const;\n\nexport const WORKSPACE_TOOLS = {\n FILESYSTEM: {\n READ_FILE: `${WORKSPACE_TOOLS_PREFIX}_read_file` as const,\n WRITE_FILE: `${WORKSPACE_TOOLS_PREFIX}_write_file` as const,\n EDIT_FILE: `${WORKSPACE_TOOLS_PREFIX}_edit_file` as const,\n LIST_FILES: `${WORKSPACE_TOOLS_PREFIX}_list_files` as const,\n DELETE: `${WORKSPACE_TOOLS_PREFIX}_delete` as const,\n FILE_STAT: `${WORKSPACE_TOOLS_PREFIX}_file_stat` as const,\n MKDIR: `${WORKSPACE_TOOLS_PREFIX}_mkdir` as const,\n GREP: `${WORKSPACE_TOOLS_PREFIX}_grep` as const,\n },\n SANDBOX: {\n EXECUTE_COMMAND: `${WORKSPACE_TOOLS_PREFIX}_execute_command` as const,\n },\n SEARCH: {\n SEARCH: `${WORKSPACE_TOOLS_PREFIX}_search` as const,\n INDEX: `${WORKSPACE_TOOLS_PREFIX}_index` as const,\n },\n} as const;\n\nexport type WorkspaceToolName =\n | (typeof WORKSPACE_TOOLS.FILESYSTEM)[keyof typeof WORKSPACE_TOOLS.FILESYSTEM]\n | (typeof WORKSPACE_TOOLS.SEARCH)[keyof typeof WORKSPACE_TOOLS.SEARCH]\n | (typeof WORKSPACE_TOOLS.SANDBOX)[keyof typeof WORKSPACE_TOOLS.SANDBOX];\n\n/**\n * A tool config value that may be a static boolean or a dynamic function.\n * Inlined from @mastra/core/workspace for compatibility.\n *\n * Uses `(...args: any[]) => any` for the function branch so it stays\n * assignable from all core context variants (ToolConfigContext,\n * ToolConfigWithArgsContext) without importing them.\n */\n\ntype DynamicToolConfigValue = boolean | ((...args: any[]) => any);\n\n/**\n * Configuration for a single workspace tool.\n */\nexport interface WorkspaceToolConfig {\n enabled?: DynamicToolConfigValue;\n requireApproval?: DynamicToolConfigValue;\n requireReadBeforeWrite?: DynamicToolConfigValue;\n}\n\n/**\n * Configuration for workspace tools.\n */\nexport type WorkspaceToolsConfig = {\n enabled?: DynamicToolConfigValue;\n requireApproval?: DynamicToolConfigValue;\n} & Partial<Record<WorkspaceToolName, WorkspaceToolConfig>>;\n\n/**\n * Safely resolve a dynamic config value (boolean or async function) to a boolean.\n * Falls back to `safeDefault` when no context is available or the function throws.\n */\nasync function resolveDynamicValue(\n value: DynamicToolConfigValue | undefined,\n context: { workspace: object; requestContext: Record<string, unknown> } | undefined,\n safeDefault: boolean,\n): Promise<boolean> {\n if (value === undefined) return safeDefault;\n if (typeof value === 'boolean') return value;\n if (!context) return safeDefault;\n try {\n return await value(context);\n } catch (error) {\n console.warn('[Workspace Tools] Dynamic config function threw, using safe default:', error);\n return safeDefault;\n }\n}\n\n/**\n * Resolve the effective configuration for a workspace tool.\n * Inlined from @mastra/core/workspace for compatibility.\n *\n * Dynamic function values are resolved by calling them with the provided\n * workspace and requestContext. If a function throws, safe defaults are used\n * (enabled → false, requireApproval → true, requireReadBeforeWrite → true).\n */\nexport async function resolveToolConfig(\n toolsConfig: WorkspaceToolsConfig | undefined,\n toolName: WorkspaceToolName,\n context?: { workspace: object; requestContext: Record<string, unknown> },\n): Promise<{ enabled: boolean; requireApproval: boolean; requireReadBeforeWrite?: boolean }> {\n let enabled: DynamicToolConfigValue = true;\n let requireApproval: DynamicToolConfigValue = false;\n let requireReadBeforeWrite: DynamicToolConfigValue | undefined;\n\n if (toolsConfig) {\n if (toolsConfig.enabled !== undefined) {\n enabled = toolsConfig.enabled;\n }\n if (toolsConfig.requireApproval !== undefined) {\n requireApproval = toolsConfig.requireApproval;\n }\n\n const perToolConfig = toolsConfig[toolName];\n if (perToolConfig) {\n if (perToolConfig.enabled !== undefined) {\n enabled = perToolConfig.enabled;\n }\n if (perToolConfig.requireApproval !== undefined) {\n requireApproval = perToolConfig.requireApproval;\n }\n if (perToolConfig.requireReadBeforeWrite !== undefined) {\n requireReadBeforeWrite = perToolConfig.requireReadBeforeWrite;\n }\n }\n }\n\n return {\n enabled: await resolveDynamicValue(enabled, context, false),\n requireApproval: await resolveDynamicValue(requireApproval, context, true),\n requireReadBeforeWrite:\n requireReadBeforeWrite !== undefined\n ? await resolveDynamicValue(requireReadBeforeWrite, context, true)\n : undefined,\n };\n}\n"],"mappings":";;;;;;;;AAQA,MAAa,yBAAyB;AAEtC,MAAa,uBAAuB;AAEpC,MAAa,kBAAkB;AAE/B,MAAa,8BAA8B;AAE3C,MAAa,wBAAwB;AAErC,MAAa,wBAAwB;AAErC,MAAa,uBAAuB;;;;;AAMpC,MAAa,8BAA8B;;;;;;AAO3C,MAAa,uBAAuB;AAIpC,MAAa,4BAA4B;AAEzC,MAAa,4BAA4B;AAEzC,MAAM,wCAAwB,IAAI,IAAI;CACpC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAGA;CAIA;AACF,CAAC;AAED,SAAgB,4BAA4B,KAAsB;CAChE,OAAO,sBAAsB,IAAI,GAAG;AACtC;AAEA,SAAgB,yBAAyB,OAAoC;CAC3E,OAAO,OAAO,YAAY,MAAM;AAClC;AAEA,MAAa,yBAAyB;AAEtC,MAAa,kBAAkB;CAC7B,YAAY;EACV,WAAW,GAAG,uBAAuB;EACrC,YAAY,GAAG,uBAAuB;EACtC,WAAW,GAAG,uBAAuB;EACrC,YAAY,GAAG,uBAAuB;EACtC,QAAQ,GAAG,uBAAuB;EAClC,WAAW,GAAG,uBAAuB;EACrC,OAAO,GAAG,uBAAuB;EACjC,MAAM,GAAG,uBAAuB;CAClC;CACA,SAAS,EACP,iBAAiB,GAAG,uBAAuB,kBAC7C;CACA,QAAQ;EACN,QAAQ,GAAG,uBAAuB;EAClC,OAAO,GAAG,uBAAuB;CACnC;AACF;;;;;AAuCA,eAAe,oBACb,OACA,SACA,aACkB;CAClB,IAAI,UAAU,KAAA,GAAW,OAAO;CAChC,IAAI,OAAO,UAAU,WAAW,OAAO;CACvC,IAAI,CAAC,SAAS,OAAO;CACrB,IAAI;EACF,OAAO,MAAM,MAAM,OAAO;CAC5B,SAAS,OAAO;EACd,QAAQ,KAAK,wEAAwE,KAAK;EAC1F,OAAO;CACT;AACF;;;;;;;;;AAUA,eAAsB,kBACpB,aACA,UACA,SAC2F;CAC3F,IAAI,UAAkC;CACtC,IAAI,kBAA0C;CAC9C,IAAI;CAEJ,IAAI,aAAa;EACf,IAAI,YAAY,YAAY,KAAA,GAC1B,UAAU,YAAY;EAExB,IAAI,YAAY,oBAAoB,KAAA,GAClC,kBAAkB,YAAY;EAGhC,MAAM,gBAAgB,YAAY;EAClC,IAAI,eAAe;GACjB,IAAI,cAAc,YAAY,KAAA,GAC5B,UAAU,cAAc;GAE1B,IAAI,cAAc,oBAAoB,KAAA,GACpC,kBAAkB,cAAc;GAElC,IAAI,cAAc,2BAA2B,KAAA,GAC3C,yBAAyB,cAAc;EAE3C;CACF;CAEA,OAAO;EACL,SAAS,MAAM,oBAAoB,SAAS,SAAS,KAAK;EAC1D,iBAAiB,MAAM,oBAAoB,iBAAiB,SAAS,IAAI;EACzE,wBACE,2BAA2B,KAAA,IACvB,MAAM,oBAAoB,wBAAwB,SAAS,IAAI,IAC/D,KAAA;CACR;AACF"}
@@ -12,9 +12,9 @@ let _mastra_core_memory = require("@mastra/core/memory");
12
12
  let _mastra_core_agent = require("@mastra/core/agent");
13
13
  let _mastra_core_error = require("@mastra/core/error");
14
14
  let _mastra_core_llm = require("@mastra/core/llm");
15
+ let _mastra_core_tools = require("@mastra/core/tools");
15
16
  let util = require("util");
16
17
  let crypto$1 = require("crypto");
17
- let _mastra_core_tools = require("@mastra/core/tools");
18
18
  let _mastra_core_utils = require("@mastra/core/utils");
19
19
  let _mastra_core_storage = require("@mastra/core/storage");
20
20
  let _mastra_core_features = require("@mastra/core/features");
@@ -4693,7 +4693,7 @@ function splitLines(text) {
4693
4693
  return result;
4694
4694
  }
4695
4695
  //#endregion
4696
- //#region ../memory/dist/src-BUlG9vaB.js
4696
+ //#region ../memory/dist/src-BKRU-0Fx.js
4697
4697
  var __defProp$3 = Object.defineProperty;
4698
4698
  var __exportAll = (all, no_symbols) => {
4699
4699
  let target = {};
@@ -24465,21 +24465,22 @@ const SET_WORKING_MEMORY_TOOL_NAME = "setWorkingMemory";
24465
24465
  /**
24466
24466
  * Deep merges two objects, with special handling for null values (delete) and arrays (replace).
24467
24467
  * - Object properties are recursively merged
24468
- * - null values in the update will delete the corresponding property
24468
+ * - null values in the update will delete the corresponding property, even when the property
24469
+ * or its parent object does not exist yet (so padded nulls never get stored literally)
24469
24470
  * - Arrays are replaced entirely (not merged element-by-element)
24470
24471
  * - Primitive values are overwritten
24472
+ * - The returned object is always newly constructed and never aliases `update`
24471
24473
  */
24472
24474
  function deepMergeWorkingMemory(existing, update) {
24473
24475
  if (!update || typeof update !== "object" || Object.keys(update).length === 0) return existing && typeof existing === "object" ? { ...existing } : {};
24474
- if (!existing || typeof existing !== "object") return update;
24475
- const result = { ...existing };
24476
+ const result = { ...existing && typeof existing === "object" && !Array.isArray(existing) ? existing : {} };
24476
24477
  for (const key of Object.keys(update)) {
24477
24478
  const updateValue = update[key];
24478
24479
  const existingValue = result[key];
24479
24480
  if (updateValue === void 0) continue;
24480
24481
  if (updateValue === null) delete result[key];
24481
24482
  else if (Array.isArray(updateValue)) result[key] = updateValue;
24482
- else if (typeof updateValue === "object" && updateValue !== null && typeof existingValue === "object" && existingValue !== null && !Array.isArray(existingValue)) result[key] = deepMergeWorkingMemory(existingValue, updateValue);
24483
+ else if (typeof updateValue === "object") result[key] = deepMergeWorkingMemory(existingValue && typeof existingValue === "object" && !Array.isArray(existingValue) ? existingValue : void 0, updateValue);
24483
24484
  else result[key] = updateValue;
24484
24485
  }
24485
24486
  return result;
@@ -30053,7 +30054,10 @@ ${formattedMessages}
30053
30054
  }
30054
30055
  };
30055
30056
  omDebug(`[OM:status] step=${stepNumber} msgs=${pendingTokens}/${threshold} obs=${currentObservationTokens}/${effectiveObservationTokensThreshold} gen=${record.generationCount}`);
30056
- await writer.custom(statusPart).catch(() => {});
30057
+ await writer.custom({
30058
+ ...statusPart,
30059
+ transient: true
30060
+ }).catch(() => {});
30057
30061
  }
30058
30062
  }
30059
30063
  /**
@@ -43686,4 +43690,4 @@ const agentBuilderWorkflows = {
43686
43690
  //#endregion
43687
43691
  exports.agentBuilderWorkflows = agentBuilderWorkflows;
43688
43692
 
43689
- //# sourceMappingURL=dist-BJ9n8vHL.cjs.map
43693
+ //# sourceMappingURL=dist-CpaK1qK1.cjs.map