@mastra/editor 0.10.2-alpha.1 → 0.11.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +97 -0
- package/dist/composio.cjs +280 -54
- package/dist/composio.cjs.map +1 -1
- package/dist/composio.d.cts +49 -38
- package/dist/composio.d.ts +49 -38
- package/dist/composio.js +280 -54
- package/dist/composio.js.map +1 -1
- package/dist/ee/index.cjs +3 -2
- package/dist/ee/index.cjs.map +1 -1
- package/dist/ee/index.d.cts +2 -2
- package/dist/ee/index.d.ts +2 -2
- package/dist/ee/index.js +3 -2
- package/dist/ee/index.js.map +1 -1
- package/dist/index.cjs +105 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +102 -9
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/composio.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/providers/composio.ts"],"sourcesContent":["import type {\n ToolProvider,\n ToolProviderInfo,\n ToolProviderToolkit,\n ToolProviderToolInfo,\n ToolProviderListResult,\n ListToolProviderToolsOptions,\n ResolveToolProviderToolsOptions,\n} from '@mastra/core/tool-provider';\nimport type { ToolAction } from '@mastra/core/tools';\nimport type { StorageToolConfig } from '@mastra/core/storage';\nimport { MASTRA_RESOURCE_ID_KEY } from '@mastra/core/request-context';\n\nimport { Composio } from '@composio/core';\nimport type { Tool as ComposioTool, ToolKitItem, ToolListParams as ComposioToolListParams } from '@composio/core';\nimport { MastraProvider } from '@composio/mastra';\nimport type { MastraTool, MastraToolCollection } from '@composio/mastra';\n\nexport interface ComposioToolProviderConfig {\n /** Composio API key */\n apiKey: string;\n}\n\n/**\n * Composio tool provider adapter.\n *\n * Uses `@composio/core` + `@composio/mastra` SDKs for both tool discovery\n * and runtime resolution. Both packages are optional peer dependencies and\n * tree-shaken if this provider class isn't imported.\n *\n * Discovery methods (`listToolkits`, `listTools`, `getToolSchema`) use the\n * raw Composio client (no userId required).\n *\n * Runtime method (`resolveTools`) uses the MastraProvider so returned tools are\n * already in Mastra's `createTool()` format.\n */\nexport class ComposioToolProvider implements ToolProvider {\n readonly info: ToolProviderInfo = {\n id: 'composio',\n name: 'Composio',\n description: 'Access 10,000+ tools from 150+ apps via Composio',\n };\n\n private apiKey: string;\n private rawClient: Composio | null = null;\n private mastraClient: Composio<MastraProvider> | null = null;\n\n constructor(config: ComposioToolProviderConfig) {\n this.apiKey = config.apiKey;\n }\n\n /**\n * Get or create a raw Composio client (no provider — for discovery only).\n */\n private getRawClient(): Composio {\n if (!this.rawClient) {\n this.rawClient = new Composio({ apiKey: this.apiKey });\n }\n return this.rawClient;\n }\n\n /**\n * Get or create a Composio client with MastraProvider (for runtime tools).\n */\n private getMastraClient(): Composio<MastraProvider> {\n if (!this.mastraClient) {\n this.mastraClient = new Composio({\n apiKey: this.apiKey,\n provider: new MastraProvider(),\n });\n }\n return this.mastraClient;\n }\n\n /**\n * List available toolkits via `composio.toolkits.get({})`.\n * Returns: `ToolKitListResponse` — an array of `{ slug, name, meta: { description, logo, ... } }`.\n */\n async listToolkits(): Promise<ToolProviderListResult<ToolProviderToolkit>> {\n const composio = this.getRawClient();\n const toolkits: ToolKitItem[] = await composio.toolkits.get({});\n\n const data: ToolProviderToolkit[] = toolkits.map(tk => ({\n slug: tk.slug,\n name: tk.name,\n description: tk.meta?.description,\n icon: tk.meta?.logo,\n }));\n return { data };\n }\n\n /**\n * List available tools via `composio.tools.getRawComposioTools()`.\n * No userId required — returns raw tool definitions for UI browsing.\n */\n async listTools(options?: ListToolProviderToolsOptions): Promise<ToolProviderListResult<ToolProviderToolInfo>> {\n const composio = this.getRawClient();\n\n // ToolListParams is a discriminated union in TypeScript but the\n // underlying Zod schema accepts `limit` on every variant. We cast\n // through the base type so `limit` is always forwarded.\n const limit = options?.perPage;\n const query: ComposioToolListParams = (\n options?.toolkit\n ? { toolkits: [options.toolkit], limit, search: options?.search }\n : options?.search\n ? { search: options.search, limit }\n : { toolkits: [] as string[], limit }\n ) as ComposioToolListParams;\n\n const rawTools: ComposioTool[] = await composio.tools.getRawComposioTools(query);\n\n const data: ToolProviderToolInfo[] = rawTools.map(tool => ({\n slug: tool.slug,\n name: tool.name ?? tool.slug,\n description: tool.description,\n toolkit: tool.toolkit?.slug,\n }));\n\n return {\n data,\n pagination: {\n page: options?.page ?? 1,\n perPage: limit,\n hasMore: limit !== undefined && rawTools.length >= limit,\n },\n };\n }\n\n /**\n * Get JSON schema for a specific tool via `composio.tools.getRawComposioToolBySlug()`.\n */\n async getToolSchema(toolSlug: string): Promise<Record<string, unknown> | null> {\n try {\n const composio = this.getRawClient();\n const tool: ComposioTool = await composio.tools.getRawComposioToolBySlug(toolSlug);\n if (!tool) return null;\n return (tool.inputParameters ?? {}) as Record<string, unknown>;\n } catch {\n return null;\n }\n }\n\n /**\n * Resolve executable tools in Mastra format via `composio.tools.get(userId, { tools: [...] })`.\n *\n * Uses MastraProvider so returned tools are `ReturnType<typeof createTool>` — compatible\n * with Mastra's `ToolAction` interface.\n */\n async resolveTools(\n toolSlugs: string[],\n toolConfigs?: Record<string, StorageToolConfig>,\n options?: ResolveToolProviderToolsOptions,\n ): Promise<Record<string, ToolAction<unknown, unknown>>> {\n if (toolSlugs.length === 0) return {};\n\n const resourceId = options?.requestContext?.[MASTRA_RESOURCE_ID_KEY];\n const userId = typeof resourceId === 'string' ? resourceId : (options?.userId ?? 'default');\n const composio = this.getMastraClient();\n\n // composio.tools.get returns MastraToolCollection = Record<string, MastraTool>\n const mastraTools: MastraToolCollection = await composio.tools.get(userId, { tools: toolSlugs });\n\n const result: Record<string, ToolAction<unknown, unknown>> = {};\n const entries: [string, MastraTool][] = Object.entries(mastraTools ?? {});\n\n for (const [key, tool] of entries) {\n if (!tool) continue;\n const slug = tool.id ?? key;\n const descOverride = toolConfigs?.[slug]?.description;\n // Composio ships tools typed against its bundled Mastra schema version; runtime shape matches ToolAction.\n if (descOverride) {\n result[slug] = { ...tool, description: descOverride } as unknown as ToolAction<unknown, unknown>;\n } else {\n result[slug] = tool as unknown as ToolAction<unknown, unknown>;\n }\n }\n\n return result;\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/providers/composio.ts"],"sourcesContent":["import type {\n AuthFlowStatus,\n AuthorizeOpts,\n ConnectionField,\n ExistingConnection,\n ListConnectionsOpts,\n ListConnectionsResult,\n ListToolsOpts,\n ListToolsResult,\n ResolveToolsOpts,\n ToolProviderCapabilities,\n ToolProviderHealth,\n ToolProviderInfo,\n ToolProviderToolkit,\n} from '@mastra/core/tool-provider';\nimport { BaseToolProvider } from '@mastra/core/tool-provider';\nimport type { BaseToolProviderOptions } from '@mastra/core/tool-provider';\nimport type { ToolAction } from '@mastra/core/tools';\nimport { MASTRA_RESOURCE_ID_KEY } from '@mastra/core/request-context';\n\nimport { Composio } from '@composio/core';\nimport type {\n ConnectedAccountListResponse,\n Tool as ComposioTool,\n ToolListParams as ComposioToolListParams,\n ToolKitItem,\n} from '@composio/core';\nimport { MastraProvider } from '@composio/mastra';\nimport type { MastraToolCollection } from '@composio/mastra';\n\nexport interface ComposioToolProviderConfig extends BaseToolProviderOptions {\n /** Composio API key. */\n apiKey: string;\n}\n\nconst COMPOSIO_PROVIDER_ID = 'composio' as const;\nconst DEFAULT_INTERNAL_USER_ID = 'default';\n\n/**\n * Composio implementation of the {@link BaseToolProvider} contract.\n *\n * Discovery (`listAllToolkits`, `listAllTools`) uses the raw Composio\n * client. Runtime (`resolveToolsVNext`) uses {@link MastraProvider} so resolved\n * tools are already in `createTool()` shape; each tool gets a\n * `beforeExecute` modifier that injects\n * `connectedAccountId = connectionId`, and `outputSchema` is cleared\n * because Composio returns union schemas that Mastra's runtime rejects.\n *\n * Allowlist filtering is layered by {@link BaseToolProvider}; this class\n * never reads `allowedToolkits` / `allowedTools` directly.\n */\nexport class ComposioToolProvider extends BaseToolProvider {\n readonly info: ToolProviderInfo = {\n id: COMPOSIO_PROVIDER_ID,\n name: 'Composio',\n description: 'Access 10,000+ tools from 150+ apps via Composio',\n };\n readonly capabilities: ToolProviderCapabilities = {\n multipleConnectionsPerToolkit: true,\n batchConnectionStatus: true,\n reauthorizeReusesConnectionId: true,\n supportsRevoke: true,\n };\n\n private readonly apiKey: string;\n private rawClient: Composio | null = null;\n private mastraClient: Composio<MastraProvider> | null = null;\n\n constructor(config: ComposioToolProviderConfig) {\n super({\n allowedToolkits: config.allowedToolkits,\n allowedTools: config.allowedTools,\n });\n this.apiKey = config.apiKey;\n }\n\n // ── client cache ──────────────────────────────────────────────────────\n\n private getRawClient(): Composio {\n if (!this.rawClient) {\n this.rawClient = new Composio({ apiKey: this.apiKey });\n }\n return this.rawClient;\n }\n\n private getMastraClient(): Composio<MastraProvider> {\n if (!this.mastraClient) {\n this.mastraClient = new Composio({\n apiKey: this.apiKey,\n provider: new MastraProvider(),\n });\n }\n return this.mastraClient;\n }\n\n // ── catalog (BaseToolProvider adds allowlist filter on top) ───────────\n\n protected async listAllToolkits(): Promise<ToolProviderToolkit[]> {\n const composio = this.getRawClient();\n const toolkits: ToolKitItem[] = await composio.toolkits.get({});\n return toolkits.map(tk => ({\n slug: tk.slug,\n name: tk.name,\n description: tk.meta?.description,\n icon: tk.meta?.logo,\n }));\n }\n\n protected async listAllTools(opts: ListToolsOpts): Promise<ListToolsResult> {\n const composio = this.getRawClient();\n\n // Composio's `getRawComposioTools` query is a discriminated union — every\n // variant accepts `limit`, but the toolkits/search keys are exclusive in\n // the TS types. We build the variant we need, then cast to the union.\n //\n // When the caller doesn't scope to a specific toolkit, we fall back to\n // the admin allowlist so the SDK returns a flat list across allowed\n // toolkits in a single hop (vs. fanning out per toolkit).\n const limit = opts.perPage;\n const fallbackToolkits = this.allowedToolkits.length > 0 ? [...this.allowedToolkits] : undefined;\n const query: ComposioToolListParams = (\n opts.toolkit\n ? { toolkits: [opts.toolkit], limit, search: opts.search }\n : fallbackToolkits\n ? { toolkits: fallbackToolkits, limit, search: opts.search }\n : opts.search\n ? { search: opts.search, limit }\n : { toolkits: [] as string[], limit }\n ) as ComposioToolListParams;\n\n // Composio's SDK validates every tool's input/output schema against an\n // internal zod shape and throws on the first malformed tool — so one bad\n // toolkit can poison a multi-toolkit query. Treat validation errors as a\n // soft failure and return an empty page rather than a 500.\n let rawTools: ComposioTool[] = [];\n try {\n rawTools = await composio.tools.getRawComposioTools(query);\n } catch (err) {\n console.warn(\n `[ComposioToolProvider] listAllTools failed for query ${JSON.stringify(query)} — returning empty page`,\n err,\n );\n }\n\n const data = rawTools.map(tool => ({\n slug: tool.slug,\n name: tool.name ?? tool.slug,\n description: tool.description,\n toolkit: tool.toolkit?.slug ?? opts.toolkit ?? '',\n }));\n\n return {\n data,\n pagination: {\n page: opts.page ?? 1,\n perPage: limit,\n hasMore: limit !== undefined && rawTools.length >= limit,\n },\n };\n }\n\n // ── runtime ───────────────────────────────────────────────────────────\n\n async resolveToolsVNext(opts: ResolveToolsOpts): Promise<Record<string, ToolAction<any, any, any>>> {\n if (opts.toolSlugs.length === 0) return {};\n\n // For author-bound connections, the runtime fan-out passes the agent's\n // author id explicitly. Use it as the Composio user bucket so the pin\n // resolves for any invoker (not just the original author).\n const internalUserId =\n opts.authorId && opts.authorId.length > 0 ? opts.authorId : resolveInternalUserId(opts.requestContext);\n const composio = this.getMastraClient();\n\n const modifiers = {\n // `connectedAccountId` is not threaded through Composio's `execute`\n // option bag in @composio/mastra; the only documented per-call hook\n // is `beforeExecute`, which receives the params object that flows\n // into the API call. Mutating `params.connectedAccountId` routes\n // the call to a specific account.\n beforeExecute: ({ params }: { params: { connectedAccountId?: string; userId?: string } }) => {\n params.connectedAccountId = opts.connectionId;\n return params;\n },\n };\n\n const mastraTools = (await composio.tools.get(\n internalUserId,\n { tools: opts.toolSlugs },\n modifiers,\n )) as MastraToolCollection;\n\n const result: Record<string, ToolAction<any, any, any>> = {};\n\n for (const [key, tool] of Object.entries(mastraTools ?? {})) {\n if (!tool) continue;\n const slug = (tool as { id?: string }).id ?? key;\n\n // Composio returns union output schemas (`successful: true | false`) that\n // Mastra's runtime cannot validate; clearing avoids per-tool validation\n // errors at execute time. The property may be non-writable on some SDK\n // versions, so we swallow assignment errors.\n try {\n (tool as unknown as { outputSchema: unknown }).outputSchema = undefined;\n } catch {\n // ignore\n }\n\n const descOverride = opts.toolMeta?.[slug]?.description;\n if (descOverride) {\n try {\n (tool as unknown as { description: string }).description = descOverride;\n } catch {\n // ignore\n }\n }\n\n result[slug] = tool as ToolAction<any, any, any>;\n }\n\n return result;\n }\n\n // ── auth surface ──────────────────────────────────────────────────────\n\n async authorize(opts: AuthorizeOpts): Promise<{ url: string; authId: string }> {\n const composio = this.getRawClient();\n const { id: authConfigId, authScheme } = await this.resolveAuthConfig(opts.toolkit);\n\n // `connectionId` carries the internal user bucket for the runtime fan-out;\n // for authorize we treat it as the Composio `userId` so the new connected\n // account lands under the same bucket as the agent's resolved identity.\n const internalUserId = opts.connectionId || DEFAULT_INTERNAL_USER_ID;\n // `allowMultiple: true` — we explicitly support N connected accounts per\n // (user, auth config) and disambiguate at runtime via per-connection labels.\n // `config` carries provider-specific user-supplied fields (e.g. Confluence\n // subdomain) collected by the picker via `listConnectionFields`. Composio\n // expects a discriminated `{ authScheme, val }` shape; we cast through\n // `unknown` because our generic interface keeps it Record-shaped.\n const initiateConfig =\n opts.config && Object.keys(opts.config).length > 0 && authScheme\n ? ({ authScheme, val: opts.config } as unknown as Parameters<\n typeof composio.connectedAccounts.initiate\n >[2] extends infer O\n ? O extends { config?: infer C }\n ? C\n : never\n : never)\n : undefined;\n const request = await composio.connectedAccounts.initiate(internalUserId, authConfigId, {\n allowMultiple: true,\n ...(initiateConfig ? { config: initiateConfig } : {}),\n });\n\n if (!request.redirectUrl) {\n throw new Error(`[composio] initiate did not return a redirectUrl for toolkit \"${opts.toolkit}\"`);\n }\n\n return { url: request.redirectUrl, authId: request.id };\n }\n\n async listConnectionFields({ toolkit }: { toolkit: string }): Promise<ConnectionField[]> {\n const composio = this.getRawClient();\n const { authScheme } = await this.resolveAuthConfig(toolkit);\n if (!authScheme) {\n // Without a known auth scheme we can't query the field schema — fall\n // back to no fields rather than blocking the user.\n return [];\n }\n const fields = await composio.toolkits.getConnectedAccountInitiationFields(toolkit, authScheme, {\n requiredOnly: false,\n });\n return fields.map(f => ({\n name: f.name,\n displayName: f.displayName,\n description: f.description,\n type: coerceFieldType(f.type),\n required: f.required ?? false,\n default: f.default ?? undefined,\n }));\n }\n\n async getAuthStatus(authId: string): Promise<AuthFlowStatus> {\n const composio = this.getRawClient();\n const account = await composio.connectedAccounts.get(authId);\n switch (account.status) {\n case 'ACTIVE':\n return 'completed';\n case 'INITIALIZING':\n case 'INITIATED':\n return 'pending';\n case 'FAILED':\n case 'EXPIRED':\n case 'INACTIVE':\n return 'failed';\n default:\n return 'pending';\n }\n }\n\n async getConnectionStatus(opts: {\n items: Array<{ connectionId: string; toolkit: string }>;\n }): Promise<Record<string, { connected: boolean }>> {\n if (opts.items.length === 0) return {};\n\n const composio = this.getRawClient();\n const toolkitSlugs = Array.from(new Set(opts.items.map(i => i.toolkit)));\n\n // One SDK call per `getConnectionStatus`, regardless of N items.\n // Filter by all referenced toolkits, then bucket locally by id.\n const list: ConnectedAccountListResponse = await composio.connectedAccounts.list({\n toolkitSlugs,\n });\n\n const liveById = new Map<string, { status: string; isDisabled: boolean }>();\n for (const item of list.items) {\n liveById.set(item.id, { status: item.status, isDisabled: item.isDisabled });\n }\n\n const result: Record<string, { connected: boolean }> = {};\n for (const { connectionId } of opts.items) {\n const live = liveById.get(connectionId);\n result[connectionId] = { connected: live ? live.status === 'ACTIVE' && !live.isDisabled : false };\n }\n return result;\n }\n\n async listConnections(opts: ListConnectionsOpts): Promise<ListConnectionsResult> {\n const composio = this.getRawClient();\n const page = opts.page ?? 1;\n const perPage = clampLimit(opts.perPage);\n\n // Normalize userIds[] / userId. Empty array = no buckets to list against,\n // short-circuit to avoid an unbounded Composio response.\n const userIds = resolveUserIds(opts);\n if (userIds && userIds.length === 0) {\n return { items: [], pagination: { page, perPage, hasMore: false } };\n }\n\n // Composio SDK 0.6.x uses cursor-based pagination on the wire. We surface\n // page-based pagination to keep the Mastra contract consistent with every\n // other list API. For now we only fetch the first page (page=1); paginated\n // requests for page > 1 are a follow-up — the UI does not yet paginate.\n const list: ConnectedAccountListResponse = await composio.connectedAccounts.list({\n toolkitSlugs: [opts.toolkit],\n ...(userIds ? { userIds } : {}),\n limit: perPage,\n });\n\n // Defensive: tolerate undocumented SDK shape drift where `items` is\n // missing or `nextCursor` is `null`/`undefined`/`''`.\n const items: ExistingConnection[] = (list.items ?? []).map(account => ({\n connectionId: account.id,\n status: mapComposioStatus(account.status, account.isDisabled),\n createdAt: account.createdAt,\n // `user_id` is preserved by the Composio SDK transform via spread but\n // isn't on the typed shape. Read it via a narrow cast.\n authorId: (account as unknown as { user_id?: string }).user_id,\n }));\n\n const nextCursor = (list as { nextCursor?: string | null }).nextCursor ?? null;\n const hasMore = typeof nextCursor === 'string' && nextCursor.length > 0;\n return { items, pagination: { page, perPage, hasMore } };\n }\n\n /**\n * Revoke a Composio connected account via\n * `DELETE /api/v3/connected_accounts/:nanoid`. Composio performs a soft\n * delete and responds with `{ success: boolean }`.\n *\n * Treats a 404 (account already deleted or never existed) as success so\n * the caller can drop its local pin without an error path. A `success:\n * false` response means the provider refused the delete and is surfaced\n * as an error so the caller does not delete its local row.\n */\n async revokeConnection(connectionId: string): Promise<void> {\n const composio = this.getRawClient();\n try {\n const res = (await composio.connectedAccounts.delete(connectionId)) as { success?: boolean } | undefined;\n if (res && res.success === false) {\n throw new Error(`Composio refused to delete connected account ${connectionId} (success=false)`);\n }\n } catch (err) {\n if (isNotFoundError(err)) return;\n throw err;\n }\n }\n\n async getHealth(): Promise<ToolProviderHealth> {\n try {\n const composio = this.getRawClient();\n await composio.toolkits.get({ limit: 1 } as Parameters<typeof composio.toolkits.get>[0]);\n return { ok: true };\n } catch (err) {\n return {\n ok: false,\n message: err instanceof Error ? err.message : 'Composio SDK reachability check failed',\n };\n }\n }\n\n // ── helpers ───────────────────────────────────────────────────────────\n\n /**\n * Resolve the single ENABLED auth config for `toolkit`. Throws if zero\n * or multiple configs match — the admin must enable exactly one in the\n * Composio dashboard before agents can connect.\n */\n private async resolveAuthConfig(toolkit: string): Promise<{ id: string; authScheme?: ComposioAuthScheme }> {\n const composio = this.getRawClient();\n const response = await composio.authConfigs.list({ toolkit });\n const enabled = response.items.filter(item => item.status === 'ENABLED');\n\n if (enabled.length === 0) {\n throw new Error(\n `[composio] No ENABLED auth config for toolkit \"${toolkit}\". Enable one in the Composio dashboard.`,\n );\n }\n if (enabled.length > 1) {\n const ids = enabled.map(item => item.id).join(', ');\n throw new Error(\n `[composio] Multiple ENABLED auth configs for toolkit \"${toolkit}\" (${ids}). Keep exactly one enabled.`,\n );\n }\n return { id: enabled[0]!.id, authScheme: enabled[0]!.authScheme };\n }\n}\n\ntype ComposioAuthScheme = NonNullable<\n Awaited<ReturnType<Composio['authConfigs']['list']>>['items'][number]['authScheme']\n>;\n\n/**\n * Best-effort 404 detection across the various error shapes the Composio\n * SDK surfaces (typed error with `statusCode`, HTTP-like error with\n * `status`, or a plain message containing \"404\" / \"not found\").\n */\nfunction isNotFoundError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const e = err as { statusCode?: number; status?: number; message?: string };\n if (e.statusCode === 404 || e.status === 404) return true;\n const msg = typeof e.message === 'string' ? e.message.toLowerCase() : '';\n return msg.includes('not found') || msg.includes('404');\n}\n\n/**\n * Composio reports a free-form `type` string. Map common values to our\n * generic ConnectionField type vocabulary; everything else falls back to\n * `'string'`.\n */\nfunction coerceFieldType(type: string): 'string' | 'number' | 'boolean' {\n switch (type.toLowerCase()) {\n case 'number':\n case 'integer':\n case 'int':\n case 'float':\n return 'number';\n case 'bool':\n case 'boolean':\n return 'boolean';\n default:\n return 'string';\n }\n}\n\n/**\n * Map Composio account status + `isDisabled` to the {@link ExistingConnection}\n * status vocabulary surfaced to the picker UI.\n */\nfunction mapComposioStatus(status: string, isDisabled: boolean): ExistingConnection['status'] {\n if (isDisabled) return 'inactive';\n switch (status) {\n case 'ACTIVE':\n return 'active';\n case 'INITIALIZING':\n case 'INITIATED':\n return 'pending';\n case 'FAILED':\n case 'EXPIRED':\n return 'failed';\n case 'INACTIVE':\n return 'inactive';\n default:\n return 'pending';\n }\n}\n\n// Mirror of `MASTRA_USER_KEY` from `@mastra/server`. Inlined to avoid a\n// reverse dependency from `editor` onto `server`.\nconst MASTRA_USER_KEY = 'mastra__user';\n\n/**\n * Read the internal user id (Composio `userId`) from per-request context.\n *\n * The runtime fan-out is responsible for stamping the agent's resolved\n * author id (or `'default'`) into `requestContext` under\n * {@link MASTRA_RESOURCE_ID_KEY}.\n */\nfunction resolveInternalUserId(requestContext?: Record<string, unknown>): string {\n const resourceId = requestContext?.[MASTRA_RESOURCE_ID_KEY];\n if (typeof resourceId === 'string' && resourceId.length > 0) {\n return resourceId;\n }\n\n const user = requestContext?.[MASTRA_USER_KEY];\n if (user && typeof user === 'object' && 'id' in user) {\n const id = (user as { id: unknown }).id;\n if (typeof id === 'string' && id.length > 0) {\n return id;\n }\n }\n\n return DEFAULT_INTERNAL_USER_ID;\n}\n\n/**\n * Resolve `userIds[]` from `listConnections` opts.\n *\n * - If `userIds` is provided, use it as-is (including empty array, which\n * means \"no buckets to list against\").\n * - If `userId` is provided, normalize to `[userId]`.\n * - Otherwise fall back to the default internal user id (single-bucket).\n */\nfunction resolveUserIds(opts: ListConnectionsOpts): string[] | undefined {\n if (Array.isArray(opts.userIds)) return opts.userIds;\n if (typeof opts.userId === 'string' && opts.userId.length > 0) return [opts.userId];\n return [DEFAULT_INTERNAL_USER_ID];\n}\n\nconst DEFAULT_LIMIT = 50;\nconst MAX_LIMIT = 200;\n\nfunction clampLimit(limit: number | undefined): number {\n if (typeof limit !== 'number' || !Number.isFinite(limit) || limit <= 0) {\n return DEFAULT_LIMIT;\n }\n return Math.min(Math.floor(limit), MAX_LIMIT);\n}\n"],"mappings":"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","names":[]}
|
package/dist/ee/index.cjs
CHANGED
|
@@ -160,7 +160,7 @@ var workspace = new import_workspace.Workspace({
|
|
|
160
160
|
});
|
|
161
161
|
function createBuilderAgent(args) {
|
|
162
162
|
const memory = new import_memory.Memory();
|
|
163
|
-
|
|
163
|
+
const config = {
|
|
164
164
|
instructions: `You are the Agent Builder.
|
|
165
165
|
|
|
166
166
|
Your job: turn a non-technical user's plain-language request into a fully configured, production-quality agent in a single turn.
|
|
@@ -296,7 +296,8 @@ The system prompt written into \`set-agent-instructions\` MUST include all of th
|
|
|
296
296
|
id: "builder-agent",
|
|
297
297
|
name: "Agent Builder Agent",
|
|
298
298
|
description: "An agent that can build agents"
|
|
299
|
-
}
|
|
299
|
+
};
|
|
300
|
+
return new import_agent.Agent(config);
|
|
300
301
|
}
|
|
301
302
|
// Annotate the CommonJS export names for ESM import in node:
|
|
302
303
|
0 && (module.exports = {
|
package/dist/ee/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/ee/index.ts","../../src/ee/agent-builder.ts","../../src/ee/agent-builder-agent.ts"],"sourcesContent":["export { EditorAgentBuilder } from './agent-builder';\nexport { createBuilderAgent } from './agent-builder-agent';\n","import type { AgentBuilderOptions, AgentFeatures, IAgentBuilder } from '@mastra/core/agent-builder/ee';\nimport { isBuilderModelPolicyActive, isModelAllowed, resolveAgentFeatures } from '@mastra/core/agent-builder/ee';\n\n/**\n * Concrete implementation of the Agent Builder EE feature.\n * Instantiated by MastraEditor.resolveBuilder() when builder config is enabled.\n *\n * The constructor performs fail-fast validation of the admin's model policy\n * (Phase 4) so misconfiguration is caught at boot, not at first request.\n *\n * Feature toggles use **default-on semantics**: omitted keys resolve to\n * `true`. Admins opt out by setting a key to `false`. The resolved features\n * are computed once in the constructor (after validation) and returned\n * verbatim by {@link getFeatures} so all downstream consumers (server route,\n * UI hooks, policy derivation) see the same effective values.\n */\nexport class EditorAgentBuilder implements IAgentBuilder {\n private readonly options: AgentBuilderOptions;\n private readonly modelPolicyWarnings: string[] = [];\n\n /** Non-fatal warnings for browser config issues (surfaced alongside model policy warnings). */\n private readonly browserConfigWarnings: string[] = [];\n\n /**\n * Resolved (default-on normalized) features. Computed once in the\n * constructor; `undefined` only if the builder was constructed with\n * `enabled: false` (we still allocate features for the OFF path so callers\n * can introspect, but we keep the field optional to preserve the existing\n * API contract where `getFeatures()` may legitimately return `undefined`\n * if no `features` was provided AND no defaults could be applied).\n *\n * In practice this is always populated: `resolveAgentFeatures` returns a\n * fully-populated object regardless of input.\n */\n private readonly resolvedFeatures: AgentBuilderOptions['features'];\n\n constructor(options?: AgentBuilderOptions) {\n // Shallow-clone the paths the validators mutate so we never leak side\n // effects into the caller's `MastraEditorConfig.builder` object.\n // `validateBrowserConfig` writes to `features.agent.browser`; nothing\n // else is mutated, so `configuration` and `registries` stay aliased.\n const source = options ?? {};\n this.options = {\n ...source,\n features: source.features\n ? {\n ...source.features,\n agent: source.features.agent ? { ...source.features.agent } : undefined,\n }\n : undefined,\n };\n this.validateModelPolicy();\n this.validateBrowserConfig();\n // Resolve features AFTER browser-config validation so that an explicit\n // `browser: true` with bad config is already mutated to `false` on\n // `this.options.features.agent.browser`. The resolver then sees the\n // downgraded value and returns it as-is.\n this.resolvedFeatures = {\n agent: resolveAgentFeatures(this.options.features?.agent, {\n hasBrowserConfig: this.hasValidBrowserConfig(),\n }),\n };\n }\n\n get enabled(): boolean {\n return this.options.enabled !== false;\n }\n\n getFeatures(): AgentBuilderOptions['features'] {\n return this.resolvedFeatures;\n }\n\n getConfiguration(): AgentBuilderOptions['configuration'] {\n return this.options.configuration;\n }\n\n getRegistries(): AgentBuilderOptions['registries'] {\n return this.options.registries;\n }\n\n getModelPolicyWarnings(): string[] {\n return [...this.modelPolicyWarnings, ...this.browserConfigWarnings];\n }\n\n /**\n * True when `configuration.agent.browser` declares a provider. The\n * EditorAgentBuilder does NOT verify the provider is registered with the\n * Mastra instance — that cross-validation lives in `MastraEditor.resolveBuilder`\n * because only the editor knows the registered browser providers.\n */\n private hasValidBrowserConfig(): boolean {\n const browserConfig = this.options.configuration?.agent?.browser;\n return Boolean(browserConfig?.config?.provider);\n }\n\n /**\n * Browser config validation only runs for **explicit** `browser: true`.\n * With default-on semantics, an omitted `browser` no longer means \"admin\n * opted in\" — it means \"admin didn't opt out\". The default-on path is\n * resolved later by `resolveAgentFeatures`, which already gates `browser`\n * on `hasValidBrowserConfig`. We don't want to spam every default-config\n * deployment with warnings.\n */\n private validateBrowserConfig(): void {\n const explicitBrowser = this.options.features?.agent?.browser;\n if (explicitBrowser !== true) return;\n\n const browserConfig = this.options.configuration?.agent?.browser;\n if (!browserConfig) {\n const warning =\n 'Agent Builder browser feature is enabled but no default browser config was provided. ' +\n 'Set `editor.builder.configuration.agent.browser` to a valid browser config ' +\n '(e.g. `{ type: \"inline\", config: { provider: \"stagehand\" } }`). ' +\n 'The browser toggle will be hidden until a default is configured.';\n this.browserConfigWarnings.push(warning);\n // eslint-disable-next-line no-console\n console.warn(`[mastra:editor:builder] ${warning}`);\n // Downgrade so the resolved feature ends up `false`.\n if (this.options.features?.agent) {\n this.options.features.agent.browser = false;\n }\n return;\n }\n\n if (!browserConfig.config?.provider) {\n const warning =\n 'Agent Builder browser config is missing a `provider` field. ' +\n 'Set `editor.builder.configuration.agent.browser.config.provider` ' +\n '(e.g. `\"stagehand\"`). The browser toggle will be hidden until a provider is configured.';\n this.browserConfigWarnings.push(warning);\n // eslint-disable-next-line no-console\n console.warn(`[mastra:editor:builder] ${warning}`);\n if (this.options.features?.agent) {\n this.options.features.agent.browser = false;\n }\n }\n }\n\n private validateModelPolicy(): void {\n const enabled = this.options.enabled !== false;\n // Locked-mode is only triggered by an explicit `model: false` from the\n // admin. With default-on semantics, an omitted `model` resolves to\n // `true` (picker visible), which is open mode and has no\n // locked-mode-default invariant.\n const explicitModel = this.options.features?.agent?.model;\n const pickerVisible = explicitModel !== false;\n const models = this.options.configuration?.agent?.models;\n const allowed = models?.allowed;\n const defaultModel = models?.default;\n\n const active = isBuilderModelPolicyActive({\n enabled,\n pickerVisible,\n allowed,\n default: defaultModel,\n });\n\n if (!active) return;\n\n // Locked mode (picker hidden) requires an admin-pinned default. Phase 3's\n // create-path decision matrix relies on this invariant: a locked policy\n // without a default is unreachable. Only fires when the admin has\n // explicitly opted out of the picker.\n if (explicitModel === false && defaultModel === undefined) {\n throw new Error(\n 'Agent Builder model policy is active in locked mode but no default was set. ' +\n 'Set `editor.builder.configuration.agent.models.default`, or remove ' +\n '`editor.builder.features.agent.model = false` to allow end-users to pick a model.',\n );\n }\n\n // When an allowlist is set, the default (if any) must satisfy it. An\n // empty `allowed: []` means \"unrestricted\" so we skip this check.\n if (defaultModel !== undefined && allowed !== undefined && allowed.length > 0) {\n if (!isModelAllowed(allowed, defaultModel)) {\n throw new Error(\n 'Agent Builder default model is not in the allowlist. ' +\n 'Either add it to `editor.builder.configuration.agent.models.allowed` ' +\n 'or change `editor.builder.configuration.agent.models.default`.',\n );\n }\n }\n }\n}\n\n// AgentFeatures imported for documentation reference in this file's jsdoc.\nexport type { AgentFeatures };\n","import { Agent } from '@mastra/core/agent';\nimport { Memory } from '@mastra/memory';\nimport { Workspace, LocalFilesystem } from '@mastra/core/workspace';\n\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nconst workspacePath = path.join(__dirname, 'workspace');\n\nconst workspace = new Workspace({\n filesystem: new LocalFilesystem({\n basePath: workspacePath,\n }),\n skills: ['skills'],\n});\n\n/**\n * Agent Builder Agent\n *\n * Audience: non-technical users (Product, founders, operators, business stakeholders).\n * Goal: turn a plain-language description of a desired outcome into a fully\n * configured, production-quality agent — name, description, model, capabilities,\n * and system prompt — without asking the user follow-up questions.\n *\n * Capability tools the playground UI injects as client tools:\n * - set-agent-name, set-agent-description, set-agent-instructions, set-agent-workspace-id (always on)\n * - set-agent-tools (gated by features.tools)\n * - set-agent-skills (gated by features.skills + skills available)\n * - set-agent-model (gated by features.model + models available)\n * - set-agent-browser-enabled (gated by features.browser)\n * - createSkillTool (gated by features.skills) — only when a needed capability does not exist\n */\n\nexport function createBuilderAgent(\n args?: Partial<ConstructorParameters<typeof Agent<'builder-agent'>>[0]>,\n): Agent<'builder-agent'> {\n const memory = new Memory();\n\n return new Agent<'builder-agent'>({\n instructions: `You are the Agent Builder.\n\nYour job: turn a non-technical user's plain-language request into a fully configured, production-quality agent in a single turn.\n\n# Non-negotiables\n\n- Never ask the user follow-up questions. Make the most reasonable assumption and move forward.\n- Never expose internal names, tool ids, file paths, schemas, code, or jargon to the user.\n- Speak only in user-facing capability terms.\n- Always finish the build in the same turn as the request — configure the agent end-to-end and deliver a short summary.\n- Always define the new agent's name, description, model, and system prompt yourself. Do not ask the user for any of these.\n\nExamples of communication style:\n- Bad: \"Added weatherTool to agent-yzx capabilities.\"\n- Good: \"Your new agent can now check the weather for you.\"\n- Bad: \"Calling set-agent-tools with [weatherTool].\"\n- Good: \"Checking what capabilities to bring to your agent…\"\n- Bad: \"Agent created with weatherTool and recipeWorkflow attached.\"\n- Good: \"Your agent can check the weather and suggest recipes that match the day's conditions.\"\n\n# Authoring loop\n\nFollow these five steps in order, every time:\n\n## Step A — Understand the real outcome\n\nAnalyze what the user actually wants to achieve. Focus on the final result, not just the literal wording of the request.\n\nAsk yourself:\n- What should the agent help the user accomplish?\n- Who will use this agent?\n- What decisions should the agent make on its own?\n- What kind of output should the agent produce?\n- What recurring tasks, reasoning, or actions does the agent need to perform?\n\n## Step B — Define the agent's identity\n\nBefore building the agent, define:\n- Agent name: short, memorable, anchored to the outcome. Never \"Agent X\" or generic labels\n- Description: exactly one sentence in plain user-facing language explaining what the agent helps with.\n\nCall \\`set-agent-name\\` and \\`set-agent-description\\` to set the agent's identity. Skip any whose feature is not available in the form snapshot.\n\n## Step C — Decide capabilities\n\nRead the form snapshot already injected into your context. It lists the user's current selections plus the available tools, agents, workflows, stored skills, models, and workspaces.\n\nThen:\n- Pick the *minimum* set of existing tools/agents/workflows/stored skills that satisfies the outcome. Adding irrelevant capabilities makes the agent worse, not better.\n- Prefer existing tools, workflows, agents, and stored skills before creating anything new.\n- \\`set-agent-skills\\` attaches user-available stored skills from the form snapshot.\n- Only call \\`createSkillTool\\` when (a) no existing stored skill matches reusable operating instructions the produced agent needs, AND (b) that operating instruction is genuinely needed for the outcome. Do not use stored skills as a substitute for missing integrations or tools.\n- If a specific external connection is required (e.g. a sheet tool for a spreadsheet-driven outcome) and none is available, the new agent's system prompt must instruct it to refuse cleanly and explain what the user needs to connect.\n\n## Step D — Synthesize the run contract\n\nBefore calling \\`set-agent-instructions\\`, privately write a concrete run contract for the produced agent. The system prompt must instantiate each item:\n\n1. **Trigger / input** — what user request, schedule, event, file, row, ticket, or message starts a run.\n2. **Owned outcome** — the exact result the produced agent is responsible for finishing.\n3. **Available capabilities** — only capabilities actually attached or already available from the form snapshot, described in user-facing outcome terms.\n4. **Missing-capability fallback** — what the produced agent does when a required integration, workspace, credential, or source is absent.\n5. **Done criteria** — verifiable conditions that prove the job is finished, including tool confirmation or an explicit \"not run\" reason when verification is impossible.\n6. **Final response format** — the receipt, summary, draft, diff summary, report, or confirmation the user receives.\n\n## Step E — Write the agent\n\nCall the capability tools. Skip any whose feature is not available in the form snapshot.\n\n1. \\`set-agent-model\\` — pick the best model for the use case from the available models list. Rules:\n - Choose only a model id that appears in the available models list. Never invent, assume, or copy example model ids.\n - For coding, reasoning-heavy, or planning agents, prefer the most capable available model.\n - For short, simple, structured, or high-volume tasks, prefer a lower-latency/lower-cost available model when quality will not materially suffer.\n - If several plausible models are available, choose the newest or strongest option based on the metadata visible in the snapshot.\n2. \\`set-agent-tools\\` — attach the minimum set chosen in Step C. Also use \\`set-agent-skills\\` and \\`set-agent-browser-enabled\\` only when applicable and supported by the snapshot.\n3. \\`set-agent-instructions\\` — write the new agent's system prompt from scratch, tailored to the user's specific outcome and the run contract from Step D.\n\nBefore calling \\`set-agent-instructions\\`, self-audit the draft. It must pass every check:\n- No placeholders remain (no \\`<...>\\`, \"TBD\", \"TODO\", \"your tool\", or generic policy gaps).\n- No internal tool ids, file paths, schemas, or builder-only terms appear.\n- No generic \"helpful assistant\" identity remains.\n- No unsupported capabilities are promised.\n- Completion criteria are present, concrete, and tool-aware.\n- Refusal / fallback path is present for missing integrations, credentials, permissions, workspace, or sources.\n- Final response format is specified.\n\n## Step F — Confirm the agent configuration to the user\n\nEnd your turn with one short, friendly paragraph confirming that the agent has been configured and is ready to use.\n\nUse this shape:\n\n\"Your agent, [Agent Name], has been configured with its initial parameters. It can now [plain-language outcome]. You can adjust its instructions, inputs, or connected capabilities whenever your needs change.\"\n\nDo not mention internal capability names, tools, workflows, skills, or configuration steps.\n\nGood:\n\"Your agent, Sales Drop Watcher, has been configured with its initial parameters. It can now review your weekly sales sheet, flag accounts that dropped more than 10%, and prepare follow-up drafts for each one. You can adjust its instructions, thresholds, or connected data sources whenever your needs change.\"\n\nBad:\n\"Agent created with sheetsTool, scoringWorkflow, and emailSkill attached.\"\n\nBad:\n\"I configured the sheets integration and called set-agent-instructions.\"\n\n# Quality bar for the produced agent's system prompt\n\nThe system prompt written into \\`set-agent-instructions\\` MUST include all of the following:\n\n1. **Role and outcome.** Define what the agent is and the concrete result it owns.\n2. **Trigger and input.** Define what starts a run and what input the agent expects.\n3. **Decision rules.** Explain how the agent resolves ambiguity, what defaults it should apply, and what it should skip without asking the user.\n4. **Capability awareness.** Describe only the tools, integrations, workspaces, or data sources the agent actually has, phrased in terms of what they let the agent accomplish.\n5. **Missing-capability fallback.** Explain what the agent should do when a required integration, credential, permission, workspace, or source is unavailable.\n6. **Completion criteria.** Define exactly when the task is done in observable, verifiable terms.\n7. **Final response format.** Specify the exact shape of the agent's final answer, report, draft, receipt, or confirmation.\n8. **Communication style.** Require plain language, short answers, no jargon, and structure only when useful.\n9. **Refusal rules.** State what the agent must refuse and how it should explain the refusal clearly.\n10. **Worked example.** Include at least one short input → output example showing a complete successful run.\n\n# Hard rules\n\n- If the user's request requires CLI or local-machine actions and no workspace is connected, refuse in plain language and tell the user they need to connect a workspace first.\n- Never reveal that you are calling configuration tools. Describe progress only in terms of the user's intended outcome.\n- Never produce a system prompt without explicit completion criteria.\n- Never attach a capability \"just in case.\" Every tool, agent, workflow, or skill must directly support the requested outcome.\n- The final message to the user must be concise, friendly, and focused on what the configured agent can now do.\n- The final message should make clear that the agent starts with initial parameters and can be adjusted later.`,\n model: 'openai/gpt-5.5',\n memory,\n workspace,\n ...(args || {}),\n id: 'builder-agent',\n name: 'Agent Builder Agent',\n description: 'An agent that can build agents',\n });\n}\n"],"mappings":"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","names":["path"]}
|
|
1
|
+
{"version":3,"sources":["../../src/ee/index.ts","../../src/ee/agent-builder.ts","../../src/ee/agent-builder-agent.ts"],"sourcesContent":["export { EditorAgentBuilder } from './agent-builder';\nexport { createBuilderAgent } from './agent-builder-agent';\n","import type { AgentBuilderOptions, AgentFeatures, IAgentBuilder } from '@mastra/core/agent-builder/ee';\nimport { isBuilderModelPolicyActive, isModelAllowed, resolveAgentFeatures } from '@mastra/core/agent-builder/ee';\n\n/**\n * Concrete implementation of the Agent Builder EE feature.\n * Instantiated by MastraEditor.resolveBuilder() when builder config is enabled.\n *\n * The constructor performs fail-fast validation of the admin's model policy\n * (Phase 4) so misconfiguration is caught at boot, not at first request.\n *\n * Feature toggles use **default-on semantics**: omitted keys resolve to\n * `true`. Admins opt out by setting a key to `false`. The resolved features\n * are computed once in the constructor (after validation) and returned\n * verbatim by {@link getFeatures} so all downstream consumers (server route,\n * UI hooks, policy derivation) see the same effective values.\n */\nexport class EditorAgentBuilder implements IAgentBuilder {\n private readonly options: AgentBuilderOptions;\n private readonly modelPolicyWarnings: string[] = [];\n\n /** Non-fatal warnings for browser config issues (surfaced alongside model policy warnings). */\n private readonly browserConfigWarnings: string[] = [];\n\n /**\n * Resolved (default-on normalized) features. Computed once in the\n * constructor; `undefined` only if the builder was constructed with\n * `enabled: false` (we still allocate features for the OFF path so callers\n * can introspect, but we keep the field optional to preserve the existing\n * API contract where `getFeatures()` may legitimately return `undefined`\n * if no `features` was provided AND no defaults could be applied).\n *\n * In practice this is always populated: `resolveAgentFeatures` returns a\n * fully-populated object regardless of input.\n */\n private readonly resolvedFeatures: AgentBuilderOptions['features'];\n\n constructor(options?: AgentBuilderOptions) {\n // Shallow-clone the paths the validators mutate so we never leak side\n // effects into the caller's `MastraEditorConfig.builder` object.\n // `validateBrowserConfig` writes to `features.agent.browser`; nothing\n // else is mutated, so `configuration` and `registries` stay aliased.\n const source = options ?? {};\n this.options = {\n ...source,\n features: source.features\n ? {\n ...source.features,\n agent: source.features.agent ? { ...source.features.agent } : undefined,\n }\n : undefined,\n };\n this.validateModelPolicy();\n this.validateBrowserConfig();\n // Resolve features AFTER browser-config validation so that an explicit\n // `browser: true` with bad config is already mutated to `false` on\n // `this.options.features.agent.browser`. The resolver then sees the\n // downgraded value and returns it as-is.\n this.resolvedFeatures = {\n agent: resolveAgentFeatures(this.options.features?.agent, {\n hasBrowserConfig: this.hasValidBrowserConfig(),\n }),\n };\n }\n\n get enabled(): boolean {\n return this.options.enabled !== false;\n }\n\n getFeatures(): AgentBuilderOptions['features'] {\n return this.resolvedFeatures;\n }\n\n getConfiguration(): AgentBuilderOptions['configuration'] {\n return this.options.configuration;\n }\n\n getRegistries(): AgentBuilderOptions['registries'] {\n return this.options.registries;\n }\n\n getModelPolicyWarnings(): string[] {\n return [...this.modelPolicyWarnings, ...this.browserConfigWarnings];\n }\n\n /**\n * True when `configuration.agent.browser` declares a provider. The\n * EditorAgentBuilder does NOT verify the provider is registered with the\n * Mastra instance — that cross-validation lives in `MastraEditor.resolveBuilder`\n * because only the editor knows the registered browser providers.\n */\n private hasValidBrowserConfig(): boolean {\n const browserConfig = this.options.configuration?.agent?.browser;\n return Boolean(browserConfig?.config?.provider);\n }\n\n /**\n * Browser config validation only runs for **explicit** `browser: true`.\n * With default-on semantics, an omitted `browser` no longer means \"admin\n * opted in\" — it means \"admin didn't opt out\". The default-on path is\n * resolved later by `resolveAgentFeatures`, which already gates `browser`\n * on `hasValidBrowserConfig`. We don't want to spam every default-config\n * deployment with warnings.\n */\n private validateBrowserConfig(): void {\n const explicitBrowser = this.options.features?.agent?.browser;\n if (explicitBrowser !== true) return;\n\n const browserConfig = this.options.configuration?.agent?.browser;\n if (!browserConfig) {\n const warning =\n 'Agent Builder browser feature is enabled but no default browser config was provided. ' +\n 'Set `editor.builder.configuration.agent.browser` to a valid browser config ' +\n '(e.g. `{ type: \"inline\", config: { provider: \"stagehand\" } }`). ' +\n 'The browser toggle will be hidden until a default is configured.';\n this.browserConfigWarnings.push(warning);\n // eslint-disable-next-line no-console\n console.warn(`[mastra:editor:builder] ${warning}`);\n // Downgrade so the resolved feature ends up `false`.\n if (this.options.features?.agent) {\n this.options.features.agent.browser = false;\n }\n return;\n }\n\n if (!browserConfig.config?.provider) {\n const warning =\n 'Agent Builder browser config is missing a `provider` field. ' +\n 'Set `editor.builder.configuration.agent.browser.config.provider` ' +\n '(e.g. `\"stagehand\"`). The browser toggle will be hidden until a provider is configured.';\n this.browserConfigWarnings.push(warning);\n // eslint-disable-next-line no-console\n console.warn(`[mastra:editor:builder] ${warning}`);\n if (this.options.features?.agent) {\n this.options.features.agent.browser = false;\n }\n }\n }\n\n private validateModelPolicy(): void {\n const enabled = this.options.enabled !== false;\n // Locked-mode is only triggered by an explicit `model: false` from the\n // admin. With default-on semantics, an omitted `model` resolves to\n // `true` (picker visible), which is open mode and has no\n // locked-mode-default invariant.\n const explicitModel = this.options.features?.agent?.model;\n const pickerVisible = explicitModel !== false;\n const models = this.options.configuration?.agent?.models;\n const allowed = models?.allowed;\n const defaultModel = models?.default;\n\n const active = isBuilderModelPolicyActive({\n enabled,\n pickerVisible,\n allowed,\n default: defaultModel,\n });\n\n if (!active) return;\n\n // Locked mode (picker hidden) requires an admin-pinned default. Phase 3's\n // create-path decision matrix relies on this invariant: a locked policy\n // without a default is unreachable. Only fires when the admin has\n // explicitly opted out of the picker.\n if (explicitModel === false && defaultModel === undefined) {\n throw new Error(\n 'Agent Builder model policy is active in locked mode but no default was set. ' +\n 'Set `editor.builder.configuration.agent.models.default`, or remove ' +\n '`editor.builder.features.agent.model = false` to allow end-users to pick a model.',\n );\n }\n\n // When an allowlist is set, the default (if any) must satisfy it. An\n // empty `allowed: []` means \"unrestricted\" so we skip this check.\n if (defaultModel !== undefined && allowed !== undefined && allowed.length > 0) {\n if (!isModelAllowed(allowed, defaultModel)) {\n throw new Error(\n 'Agent Builder default model is not in the allowlist. ' +\n 'Either add it to `editor.builder.configuration.agent.models.allowed` ' +\n 'or change `editor.builder.configuration.agent.models.default`.',\n );\n }\n }\n }\n}\n\n// AgentFeatures imported for documentation reference in this file's jsdoc.\nexport type { AgentFeatures };\n","import { Agent } from '@mastra/core/agent';\nimport type { AgentConfig } from '@mastra/core/agent';\nimport { Memory } from '@mastra/memory';\nimport { Workspace, LocalFilesystem } from '@mastra/core/workspace';\n\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nconst workspacePath = path.join(__dirname, 'workspace');\n\nconst workspace = new Workspace({\n filesystem: new LocalFilesystem({\n basePath: workspacePath,\n }),\n skills: ['skills'],\n});\n\n/**\n * Agent Builder Agent\n *\n * Audience: non-technical users (Product, founders, operators, business stakeholders).\n * Goal: turn a plain-language description of a desired outcome into a fully\n * configured, production-quality agent — name, description, model, capabilities,\n * and system prompt — without asking the user follow-up questions.\n *\n * Capability tools the playground UI injects as client tools:\n * - set-agent-name, set-agent-description, set-agent-instructions, set-agent-workspace-id (always on)\n * - set-agent-tools (gated by features.tools)\n * - set-agent-skills (gated by features.skills + skills available)\n * - set-agent-model (gated by features.model + models available)\n * - set-agent-browser-enabled (gated by features.browser)\n * - createSkillTool (gated by features.skills) — only when a needed capability does not exist\n */\n\nexport function createBuilderAgent(args?: Partial<AgentConfig<'builder-agent'>>): Agent<'builder-agent'> {\n const memory = new Memory();\n\n const config: AgentConfig<'builder-agent'> = {\n instructions: `You are the Agent Builder.\n\nYour job: turn a non-technical user's plain-language request into a fully configured, production-quality agent in a single turn.\n\n# Non-negotiables\n\n- Never ask the user follow-up questions. Make the most reasonable assumption and move forward.\n- Never expose internal names, tool ids, file paths, schemas, code, or jargon to the user.\n- Speak only in user-facing capability terms.\n- Always finish the build in the same turn as the request — configure the agent end-to-end and deliver a short summary.\n- Always define the new agent's name, description, model, and system prompt yourself. Do not ask the user for any of these.\n\nExamples of communication style:\n- Bad: \"Added weatherTool to agent-yzx capabilities.\"\n- Good: \"Your new agent can now check the weather for you.\"\n- Bad: \"Calling set-agent-tools with [weatherTool].\"\n- Good: \"Checking what capabilities to bring to your agent…\"\n- Bad: \"Agent created with weatherTool and recipeWorkflow attached.\"\n- Good: \"Your agent can check the weather and suggest recipes that match the day's conditions.\"\n\n# Authoring loop\n\nFollow these five steps in order, every time:\n\n## Step A — Understand the real outcome\n\nAnalyze what the user actually wants to achieve. Focus on the final result, not just the literal wording of the request.\n\nAsk yourself:\n- What should the agent help the user accomplish?\n- Who will use this agent?\n- What decisions should the agent make on its own?\n- What kind of output should the agent produce?\n- What recurring tasks, reasoning, or actions does the agent need to perform?\n\n## Step B — Define the agent's identity\n\nBefore building the agent, define:\n- Agent name: short, memorable, anchored to the outcome. Never \"Agent X\" or generic labels\n- Description: exactly one sentence in plain user-facing language explaining what the agent helps with.\n\nCall \\`set-agent-name\\` and \\`set-agent-description\\` to set the agent's identity. Skip any whose feature is not available in the form snapshot.\n\n## Step C — Decide capabilities\n\nRead the form snapshot already injected into your context. It lists the user's current selections plus the available tools, agents, workflows, stored skills, models, and workspaces.\n\nThen:\n- Pick the *minimum* set of existing tools/agents/workflows/stored skills that satisfies the outcome. Adding irrelevant capabilities makes the agent worse, not better.\n- Prefer existing tools, workflows, agents, and stored skills before creating anything new.\n- \\`set-agent-skills\\` attaches user-available stored skills from the form snapshot.\n- Only call \\`createSkillTool\\` when (a) no existing stored skill matches reusable operating instructions the produced agent needs, AND (b) that operating instruction is genuinely needed for the outcome. Do not use stored skills as a substitute for missing integrations or tools.\n- If a specific external connection is required (e.g. a sheet tool for a spreadsheet-driven outcome) and none is available, the new agent's system prompt must instruct it to refuse cleanly and explain what the user needs to connect.\n\n## Step D — Synthesize the run contract\n\nBefore calling \\`set-agent-instructions\\`, privately write a concrete run contract for the produced agent. The system prompt must instantiate each item:\n\n1. **Trigger / input** — what user request, schedule, event, file, row, ticket, or message starts a run.\n2. **Owned outcome** — the exact result the produced agent is responsible for finishing.\n3. **Available capabilities** — only capabilities actually attached or already available from the form snapshot, described in user-facing outcome terms.\n4. **Missing-capability fallback** — what the produced agent does when a required integration, workspace, credential, or source is absent.\n5. **Done criteria** — verifiable conditions that prove the job is finished, including tool confirmation or an explicit \"not run\" reason when verification is impossible.\n6. **Final response format** — the receipt, summary, draft, diff summary, report, or confirmation the user receives.\n\n## Step E — Write the agent\n\nCall the capability tools. Skip any whose feature is not available in the form snapshot.\n\n1. \\`set-agent-model\\` — pick the best model for the use case from the available models list. Rules:\n - Choose only a model id that appears in the available models list. Never invent, assume, or copy example model ids.\n - For coding, reasoning-heavy, or planning agents, prefer the most capable available model.\n - For short, simple, structured, or high-volume tasks, prefer a lower-latency/lower-cost available model when quality will not materially suffer.\n - If several plausible models are available, choose the newest or strongest option based on the metadata visible in the snapshot.\n2. \\`set-agent-tools\\` — attach the minimum set chosen in Step C. Also use \\`set-agent-skills\\` and \\`set-agent-browser-enabled\\` only when applicable and supported by the snapshot.\n3. \\`set-agent-instructions\\` — write the new agent's system prompt from scratch, tailored to the user's specific outcome and the run contract from Step D.\n\nBefore calling \\`set-agent-instructions\\`, self-audit the draft. It must pass every check:\n- No placeholders remain (no \\`<...>\\`, \"TBD\", \"TODO\", \"your tool\", or generic policy gaps).\n- No internal tool ids, file paths, schemas, or builder-only terms appear.\n- No generic \"helpful assistant\" identity remains.\n- No unsupported capabilities are promised.\n- Completion criteria are present, concrete, and tool-aware.\n- Refusal / fallback path is present for missing integrations, credentials, permissions, workspace, or sources.\n- Final response format is specified.\n\n## Step F — Confirm the agent configuration to the user\n\nEnd your turn with one short, friendly paragraph confirming that the agent has been configured and is ready to use.\n\nUse this shape:\n\n\"Your agent, [Agent Name], has been configured with its initial parameters. It can now [plain-language outcome]. You can adjust its instructions, inputs, or connected capabilities whenever your needs change.\"\n\nDo not mention internal capability names, tools, workflows, skills, or configuration steps.\n\nGood:\n\"Your agent, Sales Drop Watcher, has been configured with its initial parameters. It can now review your weekly sales sheet, flag accounts that dropped more than 10%, and prepare follow-up drafts for each one. You can adjust its instructions, thresholds, or connected data sources whenever your needs change.\"\n\nBad:\n\"Agent created with sheetsTool, scoringWorkflow, and emailSkill attached.\"\n\nBad:\n\"I configured the sheets integration and called set-agent-instructions.\"\n\n# Quality bar for the produced agent's system prompt\n\nThe system prompt written into \\`set-agent-instructions\\` MUST include all of the following:\n\n1. **Role and outcome.** Define what the agent is and the concrete result it owns.\n2. **Trigger and input.** Define what starts a run and what input the agent expects.\n3. **Decision rules.** Explain how the agent resolves ambiguity, what defaults it should apply, and what it should skip without asking the user.\n4. **Capability awareness.** Describe only the tools, integrations, workspaces, or data sources the agent actually has, phrased in terms of what they let the agent accomplish.\n5. **Missing-capability fallback.** Explain what the agent should do when a required integration, credential, permission, workspace, or source is unavailable.\n6. **Completion criteria.** Define exactly when the task is done in observable, verifiable terms.\n7. **Final response format.** Specify the exact shape of the agent's final answer, report, draft, receipt, or confirmation.\n8. **Communication style.** Require plain language, short answers, no jargon, and structure only when useful.\n9. **Refusal rules.** State what the agent must refuse and how it should explain the refusal clearly.\n10. **Worked example.** Include at least one short input → output example showing a complete successful run.\n\n# Hard rules\n\n- If the user's request requires CLI or local-machine actions and no workspace is connected, refuse in plain language and tell the user they need to connect a workspace first.\n- Never reveal that you are calling configuration tools. Describe progress only in terms of the user's intended outcome.\n- Never produce a system prompt without explicit completion criteria.\n- Never attach a capability \"just in case.\" Every tool, agent, workflow, or skill must directly support the requested outcome.\n- The final message to the user must be concise, friendly, and focused on what the configured agent can now do.\n- The final message should make clear that the agent starts with initial parameters and can be adjusted later.`,\n model: 'openai/gpt-5.5',\n memory,\n workspace,\n ...(args || {}),\n id: 'builder-agent',\n name: 'Agent Builder Agent',\n description: 'An agent that can build agents',\n };\n\n return new Agent<'builder-agent'>(config);\n}\n"],"mappings":"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","names":["path"]}
|
package/dist/ee/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IAgentBuilder, AgentBuilderOptions } from '@mastra/core/agent-builder/ee';
|
|
2
|
-
import { Agent } from '@mastra/core/agent';
|
|
2
|
+
import { AgentConfig, Agent } from '@mastra/core/agent';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Concrete implementation of the Agent Builder EE feature.
|
|
@@ -72,6 +72,6 @@ declare class EditorAgentBuilder implements IAgentBuilder {
|
|
|
72
72
|
* - set-agent-browser-enabled (gated by features.browser)
|
|
73
73
|
* - createSkillTool (gated by features.skills) — only when a needed capability does not exist
|
|
74
74
|
*/
|
|
75
|
-
declare function createBuilderAgent(args?: Partial<
|
|
75
|
+
declare function createBuilderAgent(args?: Partial<AgentConfig<'builder-agent'>>): Agent<'builder-agent'>;
|
|
76
76
|
|
|
77
77
|
export { EditorAgentBuilder, createBuilderAgent };
|
package/dist/ee/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IAgentBuilder, AgentBuilderOptions } from '@mastra/core/agent-builder/ee';
|
|
2
|
-
import { Agent } from '@mastra/core/agent';
|
|
2
|
+
import { AgentConfig, Agent } from '@mastra/core/agent';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Concrete implementation of the Agent Builder EE feature.
|
|
@@ -72,6 +72,6 @@ declare class EditorAgentBuilder implements IAgentBuilder {
|
|
|
72
72
|
* - set-agent-browser-enabled (gated by features.browser)
|
|
73
73
|
* - createSkillTool (gated by features.skills) — only when a needed capability does not exist
|
|
74
74
|
*/
|
|
75
|
-
declare function createBuilderAgent(args?: Partial<
|
|
75
|
+
declare function createBuilderAgent(args?: Partial<AgentConfig<'builder-agent'>>): Agent<'builder-agent'>;
|
|
76
76
|
|
|
77
77
|
export { EditorAgentBuilder, createBuilderAgent };
|
package/dist/ee/index.js
CHANGED
|
@@ -122,7 +122,7 @@ var workspace = new Workspace({
|
|
|
122
122
|
});
|
|
123
123
|
function createBuilderAgent(args) {
|
|
124
124
|
const memory = new Memory();
|
|
125
|
-
|
|
125
|
+
const config = {
|
|
126
126
|
instructions: `You are the Agent Builder.
|
|
127
127
|
|
|
128
128
|
Your job: turn a non-technical user's plain-language request into a fully configured, production-quality agent in a single turn.
|
|
@@ -258,7 +258,8 @@ The system prompt written into \`set-agent-instructions\` MUST include all of th
|
|
|
258
258
|
id: "builder-agent",
|
|
259
259
|
name: "Agent Builder Agent",
|
|
260
260
|
description: "An agent that can build agents"
|
|
261
|
-
}
|
|
261
|
+
};
|
|
262
|
+
return new Agent(config);
|
|
262
263
|
}
|
|
263
264
|
export {
|
|
264
265
|
EditorAgentBuilder,
|
package/dist/ee/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/ee/agent-builder.ts","../../src/ee/agent-builder-agent.ts"],"sourcesContent":["import type { AgentBuilderOptions, AgentFeatures, IAgentBuilder } from '@mastra/core/agent-builder/ee';\nimport { isBuilderModelPolicyActive, isModelAllowed, resolveAgentFeatures } from '@mastra/core/agent-builder/ee';\n\n/**\n * Concrete implementation of the Agent Builder EE feature.\n * Instantiated by MastraEditor.resolveBuilder() when builder config is enabled.\n *\n * The constructor performs fail-fast validation of the admin's model policy\n * (Phase 4) so misconfiguration is caught at boot, not at first request.\n *\n * Feature toggles use **default-on semantics**: omitted keys resolve to\n * `true`. Admins opt out by setting a key to `false`. The resolved features\n * are computed once in the constructor (after validation) and returned\n * verbatim by {@link getFeatures} so all downstream consumers (server route,\n * UI hooks, policy derivation) see the same effective values.\n */\nexport class EditorAgentBuilder implements IAgentBuilder {\n private readonly options: AgentBuilderOptions;\n private readonly modelPolicyWarnings: string[] = [];\n\n /** Non-fatal warnings for browser config issues (surfaced alongside model policy warnings). */\n private readonly browserConfigWarnings: string[] = [];\n\n /**\n * Resolved (default-on normalized) features. Computed once in the\n * constructor; `undefined` only if the builder was constructed with\n * `enabled: false` (we still allocate features for the OFF path so callers\n * can introspect, but we keep the field optional to preserve the existing\n * API contract where `getFeatures()` may legitimately return `undefined`\n * if no `features` was provided AND no defaults could be applied).\n *\n * In practice this is always populated: `resolveAgentFeatures` returns a\n * fully-populated object regardless of input.\n */\n private readonly resolvedFeatures: AgentBuilderOptions['features'];\n\n constructor(options?: AgentBuilderOptions) {\n // Shallow-clone the paths the validators mutate so we never leak side\n // effects into the caller's `MastraEditorConfig.builder` object.\n // `validateBrowserConfig` writes to `features.agent.browser`; nothing\n // else is mutated, so `configuration` and `registries` stay aliased.\n const source = options ?? {};\n this.options = {\n ...source,\n features: source.features\n ? {\n ...source.features,\n agent: source.features.agent ? { ...source.features.agent } : undefined,\n }\n : undefined,\n };\n this.validateModelPolicy();\n this.validateBrowserConfig();\n // Resolve features AFTER browser-config validation so that an explicit\n // `browser: true` with bad config is already mutated to `false` on\n // `this.options.features.agent.browser`. The resolver then sees the\n // downgraded value and returns it as-is.\n this.resolvedFeatures = {\n agent: resolveAgentFeatures(this.options.features?.agent, {\n hasBrowserConfig: this.hasValidBrowserConfig(),\n }),\n };\n }\n\n get enabled(): boolean {\n return this.options.enabled !== false;\n }\n\n getFeatures(): AgentBuilderOptions['features'] {\n return this.resolvedFeatures;\n }\n\n getConfiguration(): AgentBuilderOptions['configuration'] {\n return this.options.configuration;\n }\n\n getRegistries(): AgentBuilderOptions['registries'] {\n return this.options.registries;\n }\n\n getModelPolicyWarnings(): string[] {\n return [...this.modelPolicyWarnings, ...this.browserConfigWarnings];\n }\n\n /**\n * True when `configuration.agent.browser` declares a provider. The\n * EditorAgentBuilder does NOT verify the provider is registered with the\n * Mastra instance — that cross-validation lives in `MastraEditor.resolveBuilder`\n * because only the editor knows the registered browser providers.\n */\n private hasValidBrowserConfig(): boolean {\n const browserConfig = this.options.configuration?.agent?.browser;\n return Boolean(browserConfig?.config?.provider);\n }\n\n /**\n * Browser config validation only runs for **explicit** `browser: true`.\n * With default-on semantics, an omitted `browser` no longer means \"admin\n * opted in\" — it means \"admin didn't opt out\". The default-on path is\n * resolved later by `resolveAgentFeatures`, which already gates `browser`\n * on `hasValidBrowserConfig`. We don't want to spam every default-config\n * deployment with warnings.\n */\n private validateBrowserConfig(): void {\n const explicitBrowser = this.options.features?.agent?.browser;\n if (explicitBrowser !== true) return;\n\n const browserConfig = this.options.configuration?.agent?.browser;\n if (!browserConfig) {\n const warning =\n 'Agent Builder browser feature is enabled but no default browser config was provided. ' +\n 'Set `editor.builder.configuration.agent.browser` to a valid browser config ' +\n '(e.g. `{ type: \"inline\", config: { provider: \"stagehand\" } }`). ' +\n 'The browser toggle will be hidden until a default is configured.';\n this.browserConfigWarnings.push(warning);\n // eslint-disable-next-line no-console\n console.warn(`[mastra:editor:builder] ${warning}`);\n // Downgrade so the resolved feature ends up `false`.\n if (this.options.features?.agent) {\n this.options.features.agent.browser = false;\n }\n return;\n }\n\n if (!browserConfig.config?.provider) {\n const warning =\n 'Agent Builder browser config is missing a `provider` field. ' +\n 'Set `editor.builder.configuration.agent.browser.config.provider` ' +\n '(e.g. `\"stagehand\"`). The browser toggle will be hidden until a provider is configured.';\n this.browserConfigWarnings.push(warning);\n // eslint-disable-next-line no-console\n console.warn(`[mastra:editor:builder] ${warning}`);\n if (this.options.features?.agent) {\n this.options.features.agent.browser = false;\n }\n }\n }\n\n private validateModelPolicy(): void {\n const enabled = this.options.enabled !== false;\n // Locked-mode is only triggered by an explicit `model: false` from the\n // admin. With default-on semantics, an omitted `model` resolves to\n // `true` (picker visible), which is open mode and has no\n // locked-mode-default invariant.\n const explicitModel = this.options.features?.agent?.model;\n const pickerVisible = explicitModel !== false;\n const models = this.options.configuration?.agent?.models;\n const allowed = models?.allowed;\n const defaultModel = models?.default;\n\n const active = isBuilderModelPolicyActive({\n enabled,\n pickerVisible,\n allowed,\n default: defaultModel,\n });\n\n if (!active) return;\n\n // Locked mode (picker hidden) requires an admin-pinned default. Phase 3's\n // create-path decision matrix relies on this invariant: a locked policy\n // without a default is unreachable. Only fires when the admin has\n // explicitly opted out of the picker.\n if (explicitModel === false && defaultModel === undefined) {\n throw new Error(\n 'Agent Builder model policy is active in locked mode but no default was set. ' +\n 'Set `editor.builder.configuration.agent.models.default`, or remove ' +\n '`editor.builder.features.agent.model = false` to allow end-users to pick a model.',\n );\n }\n\n // When an allowlist is set, the default (if any) must satisfy it. An\n // empty `allowed: []` means \"unrestricted\" so we skip this check.\n if (defaultModel !== undefined && allowed !== undefined && allowed.length > 0) {\n if (!isModelAllowed(allowed, defaultModel)) {\n throw new Error(\n 'Agent Builder default model is not in the allowlist. ' +\n 'Either add it to `editor.builder.configuration.agent.models.allowed` ' +\n 'or change `editor.builder.configuration.agent.models.default`.',\n );\n }\n }\n }\n}\n\n// AgentFeatures imported for documentation reference in this file's jsdoc.\nexport type { AgentFeatures };\n","import { Agent } from '@mastra/core/agent';\nimport { Memory } from '@mastra/memory';\nimport { Workspace, LocalFilesystem } from '@mastra/core/workspace';\n\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nconst workspacePath = path.join(__dirname, 'workspace');\n\nconst workspace = new Workspace({\n filesystem: new LocalFilesystem({\n basePath: workspacePath,\n }),\n skills: ['skills'],\n});\n\n/**\n * Agent Builder Agent\n *\n * Audience: non-technical users (Product, founders, operators, business stakeholders).\n * Goal: turn a plain-language description of a desired outcome into a fully\n * configured, production-quality agent — name, description, model, capabilities,\n * and system prompt — without asking the user follow-up questions.\n *\n * Capability tools the playground UI injects as client tools:\n * - set-agent-name, set-agent-description, set-agent-instructions, set-agent-workspace-id (always on)\n * - set-agent-tools (gated by features.tools)\n * - set-agent-skills (gated by features.skills + skills available)\n * - set-agent-model (gated by features.model + models available)\n * - set-agent-browser-enabled (gated by features.browser)\n * - createSkillTool (gated by features.skills) — only when a needed capability does not exist\n */\n\nexport function createBuilderAgent(\n args?: Partial<ConstructorParameters<typeof Agent<'builder-agent'>>[0]>,\n): Agent<'builder-agent'> {\n const memory = new Memory();\n\n return new Agent<'builder-agent'>({\n instructions: `You are the Agent Builder.\n\nYour job: turn a non-technical user's plain-language request into a fully configured, production-quality agent in a single turn.\n\n# Non-negotiables\n\n- Never ask the user follow-up questions. Make the most reasonable assumption and move forward.\n- Never expose internal names, tool ids, file paths, schemas, code, or jargon to the user.\n- Speak only in user-facing capability terms.\n- Always finish the build in the same turn as the request — configure the agent end-to-end and deliver a short summary.\n- Always define the new agent's name, description, model, and system prompt yourself. Do not ask the user for any of these.\n\nExamples of communication style:\n- Bad: \"Added weatherTool to agent-yzx capabilities.\"\n- Good: \"Your new agent can now check the weather for you.\"\n- Bad: \"Calling set-agent-tools with [weatherTool].\"\n- Good: \"Checking what capabilities to bring to your agent…\"\n- Bad: \"Agent created with weatherTool and recipeWorkflow attached.\"\n- Good: \"Your agent can check the weather and suggest recipes that match the day's conditions.\"\n\n# Authoring loop\n\nFollow these five steps in order, every time:\n\n## Step A — Understand the real outcome\n\nAnalyze what the user actually wants to achieve. Focus on the final result, not just the literal wording of the request.\n\nAsk yourself:\n- What should the agent help the user accomplish?\n- Who will use this agent?\n- What decisions should the agent make on its own?\n- What kind of output should the agent produce?\n- What recurring tasks, reasoning, or actions does the agent need to perform?\n\n## Step B — Define the agent's identity\n\nBefore building the agent, define:\n- Agent name: short, memorable, anchored to the outcome. Never \"Agent X\" or generic labels\n- Description: exactly one sentence in plain user-facing language explaining what the agent helps with.\n\nCall \\`set-agent-name\\` and \\`set-agent-description\\` to set the agent's identity. Skip any whose feature is not available in the form snapshot.\n\n## Step C — Decide capabilities\n\nRead the form snapshot already injected into your context. It lists the user's current selections plus the available tools, agents, workflows, stored skills, models, and workspaces.\n\nThen:\n- Pick the *minimum* set of existing tools/agents/workflows/stored skills that satisfies the outcome. Adding irrelevant capabilities makes the agent worse, not better.\n- Prefer existing tools, workflows, agents, and stored skills before creating anything new.\n- \\`set-agent-skills\\` attaches user-available stored skills from the form snapshot.\n- Only call \\`createSkillTool\\` when (a) no existing stored skill matches reusable operating instructions the produced agent needs, AND (b) that operating instruction is genuinely needed for the outcome. Do not use stored skills as a substitute for missing integrations or tools.\n- If a specific external connection is required (e.g. a sheet tool for a spreadsheet-driven outcome) and none is available, the new agent's system prompt must instruct it to refuse cleanly and explain what the user needs to connect.\n\n## Step D — Synthesize the run contract\n\nBefore calling \\`set-agent-instructions\\`, privately write a concrete run contract for the produced agent. The system prompt must instantiate each item:\n\n1. **Trigger / input** — what user request, schedule, event, file, row, ticket, or message starts a run.\n2. **Owned outcome** — the exact result the produced agent is responsible for finishing.\n3. **Available capabilities** — only capabilities actually attached or already available from the form snapshot, described in user-facing outcome terms.\n4. **Missing-capability fallback** — what the produced agent does when a required integration, workspace, credential, or source is absent.\n5. **Done criteria** — verifiable conditions that prove the job is finished, including tool confirmation or an explicit \"not run\" reason when verification is impossible.\n6. **Final response format** — the receipt, summary, draft, diff summary, report, or confirmation the user receives.\n\n## Step E — Write the agent\n\nCall the capability tools. Skip any whose feature is not available in the form snapshot.\n\n1. \\`set-agent-model\\` — pick the best model for the use case from the available models list. Rules:\n - Choose only a model id that appears in the available models list. Never invent, assume, or copy example model ids.\n - For coding, reasoning-heavy, or planning agents, prefer the most capable available model.\n - For short, simple, structured, or high-volume tasks, prefer a lower-latency/lower-cost available model when quality will not materially suffer.\n - If several plausible models are available, choose the newest or strongest option based on the metadata visible in the snapshot.\n2. \\`set-agent-tools\\` — attach the minimum set chosen in Step C. Also use \\`set-agent-skills\\` and \\`set-agent-browser-enabled\\` only when applicable and supported by the snapshot.\n3. \\`set-agent-instructions\\` — write the new agent's system prompt from scratch, tailored to the user's specific outcome and the run contract from Step D.\n\nBefore calling \\`set-agent-instructions\\`, self-audit the draft. It must pass every check:\n- No placeholders remain (no \\`<...>\\`, \"TBD\", \"TODO\", \"your tool\", or generic policy gaps).\n- No internal tool ids, file paths, schemas, or builder-only terms appear.\n- No generic \"helpful assistant\" identity remains.\n- No unsupported capabilities are promised.\n- Completion criteria are present, concrete, and tool-aware.\n- Refusal / fallback path is present for missing integrations, credentials, permissions, workspace, or sources.\n- Final response format is specified.\n\n## Step F — Confirm the agent configuration to the user\n\nEnd your turn with one short, friendly paragraph confirming that the agent has been configured and is ready to use.\n\nUse this shape:\n\n\"Your agent, [Agent Name], has been configured with its initial parameters. It can now [plain-language outcome]. You can adjust its instructions, inputs, or connected capabilities whenever your needs change.\"\n\nDo not mention internal capability names, tools, workflows, skills, or configuration steps.\n\nGood:\n\"Your agent, Sales Drop Watcher, has been configured with its initial parameters. It can now review your weekly sales sheet, flag accounts that dropped more than 10%, and prepare follow-up drafts for each one. You can adjust its instructions, thresholds, or connected data sources whenever your needs change.\"\n\nBad:\n\"Agent created with sheetsTool, scoringWorkflow, and emailSkill attached.\"\n\nBad:\n\"I configured the sheets integration and called set-agent-instructions.\"\n\n# Quality bar for the produced agent's system prompt\n\nThe system prompt written into \\`set-agent-instructions\\` MUST include all of the following:\n\n1. **Role and outcome.** Define what the agent is and the concrete result it owns.\n2. **Trigger and input.** Define what starts a run and what input the agent expects.\n3. **Decision rules.** Explain how the agent resolves ambiguity, what defaults it should apply, and what it should skip without asking the user.\n4. **Capability awareness.** Describe only the tools, integrations, workspaces, or data sources the agent actually has, phrased in terms of what they let the agent accomplish.\n5. **Missing-capability fallback.** Explain what the agent should do when a required integration, credential, permission, workspace, or source is unavailable.\n6. **Completion criteria.** Define exactly when the task is done in observable, verifiable terms.\n7. **Final response format.** Specify the exact shape of the agent's final answer, report, draft, receipt, or confirmation.\n8. **Communication style.** Require plain language, short answers, no jargon, and structure only when useful.\n9. **Refusal rules.** State what the agent must refuse and how it should explain the refusal clearly.\n10. **Worked example.** Include at least one short input → output example showing a complete successful run.\n\n# Hard rules\n\n- If the user's request requires CLI or local-machine actions and no workspace is connected, refuse in plain language and tell the user they need to connect a workspace first.\n- Never reveal that you are calling configuration tools. Describe progress only in terms of the user's intended outcome.\n- Never produce a system prompt without explicit completion criteria.\n- Never attach a capability \"just in case.\" Every tool, agent, workflow, or skill must directly support the requested outcome.\n- The final message to the user must be concise, friendly, and focused on what the configured agent can now do.\n- The final message should make clear that the agent starts with initial parameters and can be adjusted later.`,\n model: 'openai/gpt-5.5',\n memory,\n workspace,\n ...(args || {}),\n id: 'builder-agent',\n name: 'Agent Builder Agent',\n description: 'An agent that can build agents',\n });\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/ee/agent-builder.ts","../../src/ee/agent-builder-agent.ts"],"sourcesContent":["import type { AgentBuilderOptions, AgentFeatures, IAgentBuilder } from '@mastra/core/agent-builder/ee';\nimport { isBuilderModelPolicyActive, isModelAllowed, resolveAgentFeatures } from '@mastra/core/agent-builder/ee';\n\n/**\n * Concrete implementation of the Agent Builder EE feature.\n * Instantiated by MastraEditor.resolveBuilder() when builder config is enabled.\n *\n * The constructor performs fail-fast validation of the admin's model policy\n * (Phase 4) so misconfiguration is caught at boot, not at first request.\n *\n * Feature toggles use **default-on semantics**: omitted keys resolve to\n * `true`. Admins opt out by setting a key to `false`. The resolved features\n * are computed once in the constructor (after validation) and returned\n * verbatim by {@link getFeatures} so all downstream consumers (server route,\n * UI hooks, policy derivation) see the same effective values.\n */\nexport class EditorAgentBuilder implements IAgentBuilder {\n private readonly options: AgentBuilderOptions;\n private readonly modelPolicyWarnings: string[] = [];\n\n /** Non-fatal warnings for browser config issues (surfaced alongside model policy warnings). */\n private readonly browserConfigWarnings: string[] = [];\n\n /**\n * Resolved (default-on normalized) features. Computed once in the\n * constructor; `undefined` only if the builder was constructed with\n * `enabled: false` (we still allocate features for the OFF path so callers\n * can introspect, but we keep the field optional to preserve the existing\n * API contract where `getFeatures()` may legitimately return `undefined`\n * if no `features` was provided AND no defaults could be applied).\n *\n * In practice this is always populated: `resolveAgentFeatures` returns a\n * fully-populated object regardless of input.\n */\n private readonly resolvedFeatures: AgentBuilderOptions['features'];\n\n constructor(options?: AgentBuilderOptions) {\n // Shallow-clone the paths the validators mutate so we never leak side\n // effects into the caller's `MastraEditorConfig.builder` object.\n // `validateBrowserConfig` writes to `features.agent.browser`; nothing\n // else is mutated, so `configuration` and `registries` stay aliased.\n const source = options ?? {};\n this.options = {\n ...source,\n features: source.features\n ? {\n ...source.features,\n agent: source.features.agent ? { ...source.features.agent } : undefined,\n }\n : undefined,\n };\n this.validateModelPolicy();\n this.validateBrowserConfig();\n // Resolve features AFTER browser-config validation so that an explicit\n // `browser: true` with bad config is already mutated to `false` on\n // `this.options.features.agent.browser`. The resolver then sees the\n // downgraded value and returns it as-is.\n this.resolvedFeatures = {\n agent: resolveAgentFeatures(this.options.features?.agent, {\n hasBrowserConfig: this.hasValidBrowserConfig(),\n }),\n };\n }\n\n get enabled(): boolean {\n return this.options.enabled !== false;\n }\n\n getFeatures(): AgentBuilderOptions['features'] {\n return this.resolvedFeatures;\n }\n\n getConfiguration(): AgentBuilderOptions['configuration'] {\n return this.options.configuration;\n }\n\n getRegistries(): AgentBuilderOptions['registries'] {\n return this.options.registries;\n }\n\n getModelPolicyWarnings(): string[] {\n return [...this.modelPolicyWarnings, ...this.browserConfigWarnings];\n }\n\n /**\n * True when `configuration.agent.browser` declares a provider. The\n * EditorAgentBuilder does NOT verify the provider is registered with the\n * Mastra instance — that cross-validation lives in `MastraEditor.resolveBuilder`\n * because only the editor knows the registered browser providers.\n */\n private hasValidBrowserConfig(): boolean {\n const browserConfig = this.options.configuration?.agent?.browser;\n return Boolean(browserConfig?.config?.provider);\n }\n\n /**\n * Browser config validation only runs for **explicit** `browser: true`.\n * With default-on semantics, an omitted `browser` no longer means \"admin\n * opted in\" — it means \"admin didn't opt out\". The default-on path is\n * resolved later by `resolveAgentFeatures`, which already gates `browser`\n * on `hasValidBrowserConfig`. We don't want to spam every default-config\n * deployment with warnings.\n */\n private validateBrowserConfig(): void {\n const explicitBrowser = this.options.features?.agent?.browser;\n if (explicitBrowser !== true) return;\n\n const browserConfig = this.options.configuration?.agent?.browser;\n if (!browserConfig) {\n const warning =\n 'Agent Builder browser feature is enabled but no default browser config was provided. ' +\n 'Set `editor.builder.configuration.agent.browser` to a valid browser config ' +\n '(e.g. `{ type: \"inline\", config: { provider: \"stagehand\" } }`). ' +\n 'The browser toggle will be hidden until a default is configured.';\n this.browserConfigWarnings.push(warning);\n // eslint-disable-next-line no-console\n console.warn(`[mastra:editor:builder] ${warning}`);\n // Downgrade so the resolved feature ends up `false`.\n if (this.options.features?.agent) {\n this.options.features.agent.browser = false;\n }\n return;\n }\n\n if (!browserConfig.config?.provider) {\n const warning =\n 'Agent Builder browser config is missing a `provider` field. ' +\n 'Set `editor.builder.configuration.agent.browser.config.provider` ' +\n '(e.g. `\"stagehand\"`). The browser toggle will be hidden until a provider is configured.';\n this.browserConfigWarnings.push(warning);\n // eslint-disable-next-line no-console\n console.warn(`[mastra:editor:builder] ${warning}`);\n if (this.options.features?.agent) {\n this.options.features.agent.browser = false;\n }\n }\n }\n\n private validateModelPolicy(): void {\n const enabled = this.options.enabled !== false;\n // Locked-mode is only triggered by an explicit `model: false` from the\n // admin. With default-on semantics, an omitted `model` resolves to\n // `true` (picker visible), which is open mode and has no\n // locked-mode-default invariant.\n const explicitModel = this.options.features?.agent?.model;\n const pickerVisible = explicitModel !== false;\n const models = this.options.configuration?.agent?.models;\n const allowed = models?.allowed;\n const defaultModel = models?.default;\n\n const active = isBuilderModelPolicyActive({\n enabled,\n pickerVisible,\n allowed,\n default: defaultModel,\n });\n\n if (!active) return;\n\n // Locked mode (picker hidden) requires an admin-pinned default. Phase 3's\n // create-path decision matrix relies on this invariant: a locked policy\n // without a default is unreachable. Only fires when the admin has\n // explicitly opted out of the picker.\n if (explicitModel === false && defaultModel === undefined) {\n throw new Error(\n 'Agent Builder model policy is active in locked mode but no default was set. ' +\n 'Set `editor.builder.configuration.agent.models.default`, or remove ' +\n '`editor.builder.features.agent.model = false` to allow end-users to pick a model.',\n );\n }\n\n // When an allowlist is set, the default (if any) must satisfy it. An\n // empty `allowed: []` means \"unrestricted\" so we skip this check.\n if (defaultModel !== undefined && allowed !== undefined && allowed.length > 0) {\n if (!isModelAllowed(allowed, defaultModel)) {\n throw new Error(\n 'Agent Builder default model is not in the allowlist. ' +\n 'Either add it to `editor.builder.configuration.agent.models.allowed` ' +\n 'or change `editor.builder.configuration.agent.models.default`.',\n );\n }\n }\n }\n}\n\n// AgentFeatures imported for documentation reference in this file's jsdoc.\nexport type { AgentFeatures };\n","import { Agent } from '@mastra/core/agent';\nimport type { AgentConfig } from '@mastra/core/agent';\nimport { Memory } from '@mastra/memory';\nimport { Workspace, LocalFilesystem } from '@mastra/core/workspace';\n\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nconst workspacePath = path.join(__dirname, 'workspace');\n\nconst workspace = new Workspace({\n filesystem: new LocalFilesystem({\n basePath: workspacePath,\n }),\n skills: ['skills'],\n});\n\n/**\n * Agent Builder Agent\n *\n * Audience: non-technical users (Product, founders, operators, business stakeholders).\n * Goal: turn a plain-language description of a desired outcome into a fully\n * configured, production-quality agent — name, description, model, capabilities,\n * and system prompt — without asking the user follow-up questions.\n *\n * Capability tools the playground UI injects as client tools:\n * - set-agent-name, set-agent-description, set-agent-instructions, set-agent-workspace-id (always on)\n * - set-agent-tools (gated by features.tools)\n * - set-agent-skills (gated by features.skills + skills available)\n * - set-agent-model (gated by features.model + models available)\n * - set-agent-browser-enabled (gated by features.browser)\n * - createSkillTool (gated by features.skills) — only when a needed capability does not exist\n */\n\nexport function createBuilderAgent(args?: Partial<AgentConfig<'builder-agent'>>): Agent<'builder-agent'> {\n const memory = new Memory();\n\n const config: AgentConfig<'builder-agent'> = {\n instructions: `You are the Agent Builder.\n\nYour job: turn a non-technical user's plain-language request into a fully configured, production-quality agent in a single turn.\n\n# Non-negotiables\n\n- Never ask the user follow-up questions. Make the most reasonable assumption and move forward.\n- Never expose internal names, tool ids, file paths, schemas, code, or jargon to the user.\n- Speak only in user-facing capability terms.\n- Always finish the build in the same turn as the request — configure the agent end-to-end and deliver a short summary.\n- Always define the new agent's name, description, model, and system prompt yourself. Do not ask the user for any of these.\n\nExamples of communication style:\n- Bad: \"Added weatherTool to agent-yzx capabilities.\"\n- Good: \"Your new agent can now check the weather for you.\"\n- Bad: \"Calling set-agent-tools with [weatherTool].\"\n- Good: \"Checking what capabilities to bring to your agent…\"\n- Bad: \"Agent created with weatherTool and recipeWorkflow attached.\"\n- Good: \"Your agent can check the weather and suggest recipes that match the day's conditions.\"\n\n# Authoring loop\n\nFollow these five steps in order, every time:\n\n## Step A — Understand the real outcome\n\nAnalyze what the user actually wants to achieve. Focus on the final result, not just the literal wording of the request.\n\nAsk yourself:\n- What should the agent help the user accomplish?\n- Who will use this agent?\n- What decisions should the agent make on its own?\n- What kind of output should the agent produce?\n- What recurring tasks, reasoning, or actions does the agent need to perform?\n\n## Step B — Define the agent's identity\n\nBefore building the agent, define:\n- Agent name: short, memorable, anchored to the outcome. Never \"Agent X\" or generic labels\n- Description: exactly one sentence in plain user-facing language explaining what the agent helps with.\n\nCall \\`set-agent-name\\` and \\`set-agent-description\\` to set the agent's identity. Skip any whose feature is not available in the form snapshot.\n\n## Step C — Decide capabilities\n\nRead the form snapshot already injected into your context. It lists the user's current selections plus the available tools, agents, workflows, stored skills, models, and workspaces.\n\nThen:\n- Pick the *minimum* set of existing tools/agents/workflows/stored skills that satisfies the outcome. Adding irrelevant capabilities makes the agent worse, not better.\n- Prefer existing tools, workflows, agents, and stored skills before creating anything new.\n- \\`set-agent-skills\\` attaches user-available stored skills from the form snapshot.\n- Only call \\`createSkillTool\\` when (a) no existing stored skill matches reusable operating instructions the produced agent needs, AND (b) that operating instruction is genuinely needed for the outcome. Do not use stored skills as a substitute for missing integrations or tools.\n- If a specific external connection is required (e.g. a sheet tool for a spreadsheet-driven outcome) and none is available, the new agent's system prompt must instruct it to refuse cleanly and explain what the user needs to connect.\n\n## Step D — Synthesize the run contract\n\nBefore calling \\`set-agent-instructions\\`, privately write a concrete run contract for the produced agent. The system prompt must instantiate each item:\n\n1. **Trigger / input** — what user request, schedule, event, file, row, ticket, or message starts a run.\n2. **Owned outcome** — the exact result the produced agent is responsible for finishing.\n3. **Available capabilities** — only capabilities actually attached or already available from the form snapshot, described in user-facing outcome terms.\n4. **Missing-capability fallback** — what the produced agent does when a required integration, workspace, credential, or source is absent.\n5. **Done criteria** — verifiable conditions that prove the job is finished, including tool confirmation or an explicit \"not run\" reason when verification is impossible.\n6. **Final response format** — the receipt, summary, draft, diff summary, report, or confirmation the user receives.\n\n## Step E — Write the agent\n\nCall the capability tools. Skip any whose feature is not available in the form snapshot.\n\n1. \\`set-agent-model\\` — pick the best model for the use case from the available models list. Rules:\n - Choose only a model id that appears in the available models list. Never invent, assume, or copy example model ids.\n - For coding, reasoning-heavy, or planning agents, prefer the most capable available model.\n - For short, simple, structured, or high-volume tasks, prefer a lower-latency/lower-cost available model when quality will not materially suffer.\n - If several plausible models are available, choose the newest or strongest option based on the metadata visible in the snapshot.\n2. \\`set-agent-tools\\` — attach the minimum set chosen in Step C. Also use \\`set-agent-skills\\` and \\`set-agent-browser-enabled\\` only when applicable and supported by the snapshot.\n3. \\`set-agent-instructions\\` — write the new agent's system prompt from scratch, tailored to the user's specific outcome and the run contract from Step D.\n\nBefore calling \\`set-agent-instructions\\`, self-audit the draft. It must pass every check:\n- No placeholders remain (no \\`<...>\\`, \"TBD\", \"TODO\", \"your tool\", or generic policy gaps).\n- No internal tool ids, file paths, schemas, or builder-only terms appear.\n- No generic \"helpful assistant\" identity remains.\n- No unsupported capabilities are promised.\n- Completion criteria are present, concrete, and tool-aware.\n- Refusal / fallback path is present for missing integrations, credentials, permissions, workspace, or sources.\n- Final response format is specified.\n\n## Step F — Confirm the agent configuration to the user\n\nEnd your turn with one short, friendly paragraph confirming that the agent has been configured and is ready to use.\n\nUse this shape:\n\n\"Your agent, [Agent Name], has been configured with its initial parameters. It can now [plain-language outcome]. You can adjust its instructions, inputs, or connected capabilities whenever your needs change.\"\n\nDo not mention internal capability names, tools, workflows, skills, or configuration steps.\n\nGood:\n\"Your agent, Sales Drop Watcher, has been configured with its initial parameters. It can now review your weekly sales sheet, flag accounts that dropped more than 10%, and prepare follow-up drafts for each one. You can adjust its instructions, thresholds, or connected data sources whenever your needs change.\"\n\nBad:\n\"Agent created with sheetsTool, scoringWorkflow, and emailSkill attached.\"\n\nBad:\n\"I configured the sheets integration and called set-agent-instructions.\"\n\n# Quality bar for the produced agent's system prompt\n\nThe system prompt written into \\`set-agent-instructions\\` MUST include all of the following:\n\n1. **Role and outcome.** Define what the agent is and the concrete result it owns.\n2. **Trigger and input.** Define what starts a run and what input the agent expects.\n3. **Decision rules.** Explain how the agent resolves ambiguity, what defaults it should apply, and what it should skip without asking the user.\n4. **Capability awareness.** Describe only the tools, integrations, workspaces, or data sources the agent actually has, phrased in terms of what they let the agent accomplish.\n5. **Missing-capability fallback.** Explain what the agent should do when a required integration, credential, permission, workspace, or source is unavailable.\n6. **Completion criteria.** Define exactly when the task is done in observable, verifiable terms.\n7. **Final response format.** Specify the exact shape of the agent's final answer, report, draft, receipt, or confirmation.\n8. **Communication style.** Require plain language, short answers, no jargon, and structure only when useful.\n9. **Refusal rules.** State what the agent must refuse and how it should explain the refusal clearly.\n10. **Worked example.** Include at least one short input → output example showing a complete successful run.\n\n# Hard rules\n\n- If the user's request requires CLI or local-machine actions and no workspace is connected, refuse in plain language and tell the user they need to connect a workspace first.\n- Never reveal that you are calling configuration tools. Describe progress only in terms of the user's intended outcome.\n- Never produce a system prompt without explicit completion criteria.\n- Never attach a capability \"just in case.\" Every tool, agent, workflow, or skill must directly support the requested outcome.\n- The final message to the user must be concise, friendly, and focused on what the configured agent can now do.\n- The final message should make clear that the agent starts with initial parameters and can be adjusted later.`,\n model: 'openai/gpt-5.5',\n memory,\n workspace,\n ...(args || {}),\n id: 'builder-agent',\n name: 'Agent Builder Agent',\n description: 'An agent that can build agents',\n };\n\n return new Agent<'builder-agent'>(config);\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.cjs
CHANGED
|
@@ -146,7 +146,7 @@ var init_agent_builder = __esm({
|
|
|
146
146
|
// src/ee/agent-builder-agent.ts
|
|
147
147
|
function createBuilderAgent(args) {
|
|
148
148
|
const memory = new import_memory2.Memory();
|
|
149
|
-
|
|
149
|
+
const config = {
|
|
150
150
|
instructions: `You are the Agent Builder.
|
|
151
151
|
|
|
152
152
|
Your job: turn a non-technical user's plain-language request into a fully configured, production-quality agent in a single turn.
|
|
@@ -282,7 +282,8 @@ The system prompt written into \`set-agent-instructions\` MUST include all of th
|
|
|
282
282
|
id: "builder-agent",
|
|
283
283
|
name: "Agent Builder Agent",
|
|
284
284
|
description: "An agent that can build agents"
|
|
285
|
-
}
|
|
285
|
+
};
|
|
286
|
+
return new import_agent3.Agent(config);
|
|
286
287
|
}
|
|
287
288
|
var import_agent3, import_memory2, import_workspace7, import_node_path, import_node_url, import_meta, __filename, __dirname, workspacePath, workspace;
|
|
288
289
|
var init_agent_builder_agent = __esm({
|
|
@@ -342,6 +343,8 @@ __export(index_exports, {
|
|
|
342
343
|
});
|
|
343
344
|
module.exports = __toCommonJS(index_exports);
|
|
344
345
|
var import_processor_provider2 = require("@mastra/core/processor-provider");
|
|
346
|
+
var import_storage = require("@mastra/core/storage");
|
|
347
|
+
var import_tool_provider2 = require("@mastra/core/tool-provider");
|
|
345
348
|
|
|
346
349
|
// src/namespaces/base.ts
|
|
347
350
|
var EditorNamespace = class {
|
|
@@ -468,6 +471,7 @@ var import_agent = require("@mastra/core/agent");
|
|
|
468
471
|
var import_workspace = require("@mastra/core/workspace");
|
|
469
472
|
var import_schema_compat = require("@mastra/schema-compat");
|
|
470
473
|
var import_request_context = require("@mastra/core/request-context");
|
|
474
|
+
var import_tool_provider = require("@mastra/core/tool-provider");
|
|
471
475
|
|
|
472
476
|
// src/rule-evaluator.ts
|
|
473
477
|
function resolvePath(context, path2) {
|
|
@@ -1043,6 +1047,14 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
|
|
|
1043
1047
|
* Returns the (possibly mutated) agent.
|
|
1044
1048
|
*/
|
|
1045
1049
|
async applyStoredOverrides(agent, options, requestContext) {
|
|
1050
|
+
const editorConfig = agent.__getEditorConfig?.();
|
|
1051
|
+
if (editorConfig === false) {
|
|
1052
|
+
return agent;
|
|
1053
|
+
}
|
|
1054
|
+
const instructionsEditable = editorConfig === void 0 ? true : editorConfig.instructions === true;
|
|
1055
|
+
const toolsConfig = editorConfig === void 0 ? true : editorConfig.tools;
|
|
1056
|
+
const toolsEditable = toolsConfig === true;
|
|
1057
|
+
const toolDescriptionsEditable = typeof toolsConfig === "object" && toolsConfig !== null && toolsConfig.description === true;
|
|
1046
1058
|
let storedConfig = null;
|
|
1047
1059
|
try {
|
|
1048
1060
|
this.ensureRegistered();
|
|
@@ -1064,7 +1076,7 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
|
|
|
1064
1076
|
}
|
|
1065
1077
|
const fork = agent.__fork();
|
|
1066
1078
|
this.logger?.debug(`[applyStoredOverrides] Applying stored overrides to code agent "${agent.id}"`);
|
|
1067
|
-
if (storedConfig.instructions !== void 0 && storedConfig.instructions !== null) {
|
|
1079
|
+
if (instructionsEditable && storedConfig.instructions !== void 0 && storedConfig.instructions !== null) {
|
|
1068
1080
|
const resolved = this.resolveStoredInstructions(storedConfig.instructions);
|
|
1069
1081
|
if (resolved !== void 0) {
|
|
1070
1082
|
fork.__updateInstructions(resolved);
|
|
@@ -1073,11 +1085,13 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
|
|
|
1073
1085
|
const hasStoredTools = storedConfig.tools != null;
|
|
1074
1086
|
const hasStoredMCPClients = storedConfig.mcpClients != null;
|
|
1075
1087
|
const hasStoredIntegrationTools = storedConfig.integrationTools != null;
|
|
1076
|
-
|
|
1088
|
+
const hasStoredToolProviders = storedConfig.toolProviders != null && Object.keys(storedConfig.toolProviders).length > 0;
|
|
1089
|
+
if (toolsEditable && (hasStoredTools || hasStoredMCPClients || hasStoredIntegrationTools || hasStoredToolProviders)) {
|
|
1077
1090
|
const hasConditionalTools = this.isConditionalVariants(storedConfig.tools);
|
|
1078
1091
|
const hasConditionalMCPClients = storedConfig.mcpClients != null && this.isConditionalVariants(storedConfig.mcpClients);
|
|
1079
1092
|
const hasConditionalIntegrationTools = storedConfig.integrationTools != null && this.isConditionalVariants(storedConfig.integrationTools);
|
|
1080
|
-
const
|
|
1093
|
+
const hasConditionalToolProviders = storedConfig.toolProviders != null && this.isConditionalVariants(storedConfig.toolProviders);
|
|
1094
|
+
const isDynamicTools = hasConditionalTools || hasConditionalMCPClients || hasConditionalIntegrationTools || hasStoredIntegrationTools || hasConditionalToolProviders || hasStoredToolProviders;
|
|
1081
1095
|
if (isDynamicTools) {
|
|
1082
1096
|
const originalTools = agent.listTools.bind(agent);
|
|
1083
1097
|
const toolsFn = async ({ requestContext: requestContext2 }) => {
|
|
@@ -1101,7 +1115,20 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
|
|
|
1101
1115
|
resolvedIntegrationToolsConfig,
|
|
1102
1116
|
requestContext2
|
|
1103
1117
|
);
|
|
1104
|
-
|
|
1118
|
+
const resolvedToolProvidersConfig = hasConditionalToolProviders ? this.accumulateObjectVariants(
|
|
1119
|
+
storedConfig.toolProviders,
|
|
1120
|
+
ctx
|
|
1121
|
+
) : storedConfig.toolProviders;
|
|
1122
|
+
const providerTools = await (0, import_tool_provider.resolveStoredToolProviders)(
|
|
1123
|
+
resolvedToolProvidersConfig,
|
|
1124
|
+
(providerId) => this.editor.getToolProviderOrThrow(providerId),
|
|
1125
|
+
{
|
|
1126
|
+
requestContext: ctx,
|
|
1127
|
+
authorId: storedConfig.authorId,
|
|
1128
|
+
logger: this.logger
|
|
1129
|
+
}
|
|
1130
|
+
);
|
|
1131
|
+
return { ...codeTools, ...registryTools, ...mcpTools, ...integrationTools, ...providerTools };
|
|
1105
1132
|
};
|
|
1106
1133
|
fork.__setTools(toolsFn);
|
|
1107
1134
|
} else {
|
|
@@ -1118,6 +1145,28 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
|
|
|
1118
1145
|
);
|
|
1119
1146
|
fork.__setTools({ ...codeTools, ...registryTools, ...mcpTools, ...integrationTools });
|
|
1120
1147
|
}
|
|
1148
|
+
} else if (toolDescriptionsEditable && hasStoredTools) {
|
|
1149
|
+
const hasConditionalTools = this.isConditionalVariants(storedConfig.tools);
|
|
1150
|
+
if (hasConditionalTools) {
|
|
1151
|
+
const originalTools = agent.listTools.bind(agent);
|
|
1152
|
+
const toolsFn = async ({ requestContext: requestContext2 }) => {
|
|
1153
|
+
const codeTools = await originalTools({ requestContext: requestContext2 });
|
|
1154
|
+
const resolvedToolsConfig = this.accumulateObjectVariants(
|
|
1155
|
+
storedConfig.tools,
|
|
1156
|
+
requestContext2.toJSON()
|
|
1157
|
+
);
|
|
1158
|
+
return this.applyStoredToolDescriptions(codeTools, resolvedToolsConfig);
|
|
1159
|
+
};
|
|
1160
|
+
fork.__setTools(toolsFn);
|
|
1161
|
+
} else {
|
|
1162
|
+
const codeTools = await fork.listTools();
|
|
1163
|
+
fork.__setTools(
|
|
1164
|
+
this.applyStoredToolDescriptions(
|
|
1165
|
+
codeTools,
|
|
1166
|
+
storedConfig.tools
|
|
1167
|
+
)
|
|
1168
|
+
);
|
|
1169
|
+
}
|
|
1121
1170
|
}
|
|
1122
1171
|
if (storedConfig.resolvedVersionId) {
|
|
1123
1172
|
const existing = fork.toRawConfig() ?? {};
|
|
@@ -1173,6 +1222,8 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
|
|
|
1173
1222
|
const hasConditionalTools = storedAgent.tools != null && this.isConditionalVariants(storedAgent.tools);
|
|
1174
1223
|
const hasConditionalMCPClients = storedAgent.mcpClients != null && this.isConditionalVariants(storedAgent.mcpClients);
|
|
1175
1224
|
const hasConditionalIntegrationTools = storedAgent.integrationTools != null && this.isConditionalVariants(storedAgent.integrationTools);
|
|
1225
|
+
const hasToolProviders = storedAgent.toolProviders != null && Object.keys(storedAgent.toolProviders).length > 0;
|
|
1226
|
+
const hasConditionalToolProviders = storedAgent.toolProviders != null && this.isConditionalVariants(storedAgent.toolProviders);
|
|
1176
1227
|
const hasConditionalWorkflows = storedAgent.workflows != null && this.isConditionalVariants(storedAgent.workflows);
|
|
1177
1228
|
const hasConditionalAgents = storedAgent.agents != null && this.isConditionalVariants(storedAgent.agents);
|
|
1178
1229
|
const hasConditionalMemory = storedAgent.memory != null && this.isConditionalVariants(storedAgent.memory);
|
|
@@ -1184,7 +1235,7 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
|
|
|
1184
1235
|
const hasConditionalWorkspace = storedAgent.workspace != null && this.isConditionalVariants(storedAgent.workspace);
|
|
1185
1236
|
const hasConditionalBrowser = storedAgent.browser != null && this.isConditionalVariants(storedAgent.browser);
|
|
1186
1237
|
const hasIntegrationTools = storedAgent.integrationTools != null;
|
|
1187
|
-
const isDynamicTools = hasConditionalTools || hasConditionalMCPClients || hasConditionalIntegrationTools || hasIntegrationTools;
|
|
1238
|
+
const isDynamicTools = hasConditionalTools || hasConditionalMCPClients || hasConditionalIntegrationTools || hasIntegrationTools || hasConditionalToolProviders || hasToolProviders;
|
|
1188
1239
|
let tools;
|
|
1189
1240
|
if (isDynamicTools) {
|
|
1190
1241
|
tools = async ({ requestContext }) => {
|
|
@@ -1207,7 +1258,17 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
|
|
|
1207
1258
|
resolvedIntegrationToolsConfig,
|
|
1208
1259
|
requestContext
|
|
1209
1260
|
);
|
|
1210
|
-
|
|
1261
|
+
const resolvedToolProvidersConfig = hasConditionalToolProviders ? this.accumulateObjectVariants(storedAgent.toolProviders, ctx) : storedAgent.toolProviders;
|
|
1262
|
+
const providerTools = await (0, import_tool_provider.resolveStoredToolProviders)(
|
|
1263
|
+
resolvedToolProvidersConfig,
|
|
1264
|
+
(providerId) => this.editor.getToolProviderOrThrow(providerId),
|
|
1265
|
+
{
|
|
1266
|
+
requestContext: ctx,
|
|
1267
|
+
authorId: storedAgent.authorId,
|
|
1268
|
+
logger: this.logger
|
|
1269
|
+
}
|
|
1270
|
+
);
|
|
1271
|
+
return { ...registryTools, ...mcpTools, ...integrationTools, ...providerTools };
|
|
1211
1272
|
};
|
|
1212
1273
|
} else {
|
|
1213
1274
|
const registryTools = this.resolveStoredTools(storedAgent.tools);
|
|
@@ -1406,6 +1467,20 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
|
|
|
1406
1467
|
return resolveInstructionBlocks(blocks, context, { promptBlocksStorage: promptBlocksStore });
|
|
1407
1468
|
};
|
|
1408
1469
|
}
|
|
1470
|
+
applyStoredToolDescriptions(codeTools, storedTools) {
|
|
1471
|
+
if (!storedTools || Array.isArray(storedTools)) {
|
|
1472
|
+
return codeTools;
|
|
1473
|
+
}
|
|
1474
|
+
let nextTools;
|
|
1475
|
+
for (const [toolKey, toolConfig] of Object.entries(storedTools)) {
|
|
1476
|
+
if (!toolConfig.description || !(toolKey in codeTools)) {
|
|
1477
|
+
continue;
|
|
1478
|
+
}
|
|
1479
|
+
nextTools ?? (nextTools = { ...codeTools });
|
|
1480
|
+
nextTools[toolKey] = { ...codeTools[toolKey], description: toolConfig.description };
|
|
1481
|
+
}
|
|
1482
|
+
return nextTools ?? codeTools;
|
|
1483
|
+
}
|
|
1409
1484
|
/**
|
|
1410
1485
|
* Resolve stored tool IDs to actual tool instances from Mastra's registry.
|
|
1411
1486
|
* Applies description overrides from per-tool config when present.
|
|
@@ -2520,6 +2595,8 @@ var MastraEditor = class {
|
|
|
2520
2595
|
this.__logger = config?.logger;
|
|
2521
2596
|
this.__toolProviders = config?.toolProviders ?? {};
|
|
2522
2597
|
this.__processorProviders = { ...import_processor_provider2.BUILT_IN_PROCESSOR_PROVIDERS, ...config?.processorProviders };
|
|
2598
|
+
this.__source = config?.source;
|
|
2599
|
+
this.__codePath = config?.codePath ?? "./mastra/editor";
|
|
2523
2600
|
this.__filesystems = /* @__PURE__ */ new Map();
|
|
2524
2601
|
this.__filesystems.set(localFilesystemProvider.id, localFilesystemProvider);
|
|
2525
2602
|
for (const [id, provider] of Object.entries(config?.filesystems ?? {})) {
|
|
@@ -2557,6 +2634,21 @@ var MastraEditor = class {
|
|
|
2557
2634
|
if (!this.__logger) {
|
|
2558
2635
|
this.__logger = mastra.getLogger();
|
|
2559
2636
|
}
|
|
2637
|
+
if (this.__source === "code") {
|
|
2638
|
+
const filesystemStore = new import_storage.FilesystemStore({ dir: this.__codePath });
|
|
2639
|
+
const existingStorage = mastra.getStorage();
|
|
2640
|
+
if (existingStorage) {
|
|
2641
|
+
mastra.setStorage(
|
|
2642
|
+
new import_storage.MastraCompositeStore({
|
|
2643
|
+
id: `${existingStorage.id}-with-editor-filesystem`,
|
|
2644
|
+
default: existingStorage,
|
|
2645
|
+
editor: filesystemStore
|
|
2646
|
+
})
|
|
2647
|
+
);
|
|
2648
|
+
} else {
|
|
2649
|
+
mastra.setStorage(filesystemStore);
|
|
2650
|
+
}
|
|
2651
|
+
}
|
|
2560
2652
|
this.ensureBuilderWorkspaces().then(() => this.reconcileBuilderWorkspaces()).catch((err) => {
|
|
2561
2653
|
this.__logger?.warn("[MastraEditor] Failed to persist/reconcile builder workspaces on startup", {
|
|
2562
2654
|
error: err
|
|
@@ -2705,6 +2797,10 @@ var MastraEditor = class {
|
|
|
2705
2797
|
);
|
|
2706
2798
|
}
|
|
2707
2799
|
}
|
|
2800
|
+
/** Returns the editor's configured source, or undefined if unset. */
|
|
2801
|
+
getSource() {
|
|
2802
|
+
return this.__source;
|
|
2803
|
+
}
|
|
2708
2804
|
/** Registered tool providers */
|
|
2709
2805
|
getToolProvider(id) {
|
|
2710
2806
|
return this.__toolProviders[id];
|
|
@@ -2716,9 +2812,7 @@ var MastraEditor = class {
|
|
|
2716
2812
|
getToolProviderOrThrow(id) {
|
|
2717
2813
|
const provider = this.__toolProviders[id];
|
|
2718
2814
|
if (!provider) {
|
|
2719
|
-
throw new
|
|
2720
|
-
`Unknown tool provider "${id}". Available: ${Object.keys(this.__toolProviders).join(", ") || "(none)"}`
|
|
2721
|
-
);
|
|
2815
|
+
throw new import_tool_provider2.UnknownToolProviderError(id, Object.keys(this.__toolProviders));
|
|
2722
2816
|
}
|
|
2723
2817
|
return provider;
|
|
2724
2818
|
}
|