/** * Workspace Class * * A Workspace combines a Filesystem and a Sandbox to provide agents * with a complete environment for storing files and executing code. * * Users pass provider instances directly to the Workspace constructor. * * @example * ```typescript * import { Workspace } from '@mastra/core'; * import { LocalFilesystem } from '@mastra/workspace-fs-local'; * import { AgentFS } from '@mastra/workspace-fs-agentfs'; * import { ComputeSDKSandbox } from '@mastra/workspace-sandbox-computesdk'; * * // Simple workspace with local filesystem * const workspace = new Workspace({ * filesystem: new LocalFilesystem({ basePath: './workspace' }), * }); * * // Full workspace with AgentFS and cloud sandbox * const fullWorkspace = new Workspace({ * filesystem: new AgentFS({ path: './agent.db' }), * sandbox: new ComputeSDKSandbox({ provider: 'e2b' }), * }); * * await fullWorkspace.init(); * await fullWorkspace.filesystem?.writeFile('/code/app.py', 'print("Hello!")'); * const result = await fullWorkspace.sandbox?.executeCommand?.('python3', ['app.py'], { cwd: '/code' }); * ``` */ import type { IMastraLogger } from '../logger/index.js'; import type { RequestContext } from '../request-context/index.js'; import type { MastraVector } from '../vector/index.js'; import { CompositeFilesystem } from './filesystem/index.js'; import type { WorkspaceFilesystem, FilesystemInfo } from './filesystem/index.js'; import { LSPManager } from './lsp/index.js'; import type { LSPConfig } from './lsp/types.js'; import type { WorkspaceSandbox, OnMountHook } from './sandbox/index.js'; import type { BM25Config, Embedder, SearchOptions, SearchResult } from './search/index.js'; import type { WorkspaceSkills, SkillsResolver, SkillSource } from './skills/index.js'; import type { WorkspaceToolsConfig } from './tools/index.js'; import type { WorkspaceStatus } from './types.js'; /** * Configuration for creating a Workspace. * Users pass provider instances directly. * * Generic type parameters allow the workspace to preserve the concrete types * of filesystem and sandbox providers, so accessors return the exact type * you passed in. */ export interface WorkspaceConfig | undefined = undefined> { /** Unique identifier (auto-generated if not provided) */ id?: string; /** Human-readable name */ name?: string; /** * Filesystem provider instance. * Use LocalFilesystem for a folder on disk, or AgentFS for Turso-backed storage. * Extend MastraFilesystem for automatic logger integration. */ filesystem?: TFilesystem; /** * Sandbox provider instance. * Use ComputeSDKSandbox to access E2B, Modal, Docker, etc. * Extend MastraSandbox for automatic logger integration. */ sandbox?: TSandbox; /** * Mount multiple filesystems at different paths. * Creates a CompositeFilesystem that routes operations based on path. * * When a sandbox is configured, filesystems are automatically mounted * into the sandbox at their respective paths during init(). * * Use the `onMount` hook to skip or customize mounting for specific filesystems. * * The concrete mount types are preserved — use `workspace.filesystem.mounts.get()` * for typed access to individual mounts. * * @example * ```typescript * const workspace = new Workspace({ * sandbox: new E2BSandbox({ timeout: 60000 }), * mounts: { * '/data': new S3Filesystem({ bucket: 'my-data', ... }), * '/skills': new S3Filesystem({ bucket: 'skills', readOnly: true, ... }), * }, * }); * * await workspace.init(); * workspace.filesystem // CompositeFilesystem<{ '/data': S3Filesystem, '/skills': S3Filesystem }> * workspace.filesystem.mounts.get('/data') // S3Filesystem * ``` */ mounts?: TMounts; /** * Hook called before mounting each filesystem into the sandbox. * * Return values: * - `false` - Skip mount entirely (don't mount this filesystem) * - `{ success: true }` - Hook handled the mount successfully * - `{ success: false, error?: string }` - Hook attempted mount but failed * - `undefined` / no return - Use provider's default mount behavior * * This is useful for: * - Skipping specific filesystems (e.g., local filesystems in remote sandbox) * - Custom mount implementations * - Syncing files instead of FUSE mounting * * Note: If your hook handles the mount, you're responsible for the entire * implementation. The sandbox provider won't do any additional tracking. * * @example Skip local filesystems * ```typescript * const workspace = new Workspace({ * sandbox: new E2BSandbox(), * mounts: { * '/data': new S3Filesystem({ bucket: 'data', ... }), * '/local': new LocalFilesystem({ basePath: './data' }), * }, * onMount: ({ filesystem }) => { * if (filesystem.provider === 'local') return false; * }, * }); * ``` * * @example Custom mount implementation * ```typescript * onMount: async ({ filesystem, mountPath, config, sandbox }) => { * if (config?.type === 's3') { * await sandbox.executeCommand?.('my-s3-mount', [mountPath]); * return { success: true }; * } * } * ``` */ onMount?: OnMountHook; /** * Vector store for semantic search. * When provided along with embedder, enables vector and hybrid search. */ vectorStore?: MastraVector; /** * Embedder function for generating vectors. * Required when vectorStore is provided. */ embedder?: Embedder; /** * Enable BM25 keyword search. * Pass true for defaults, or a BM25Config object for custom parameters. */ bm25?: boolean | BM25Config; /** * Custom index name for the vector store. * If not provided, defaults to a sanitized version of `${id}_search`. * * Must be a valid SQL identifier for SQL-based stores (PgVector, LibSQL): * - Start with a letter or underscore * - Contain only letters, numbers, or underscores * - Maximum 63 characters * * @example 'my_workspace_vectors' */ searchIndexName?: string; /** * Paths to auto-index on init(). * Files in these directories will be indexed for search. * @example ['docs', 'support'] */ autoIndexPaths?: string[]; /** * Paths where skills are located. * Workspace will discover SKILL.md files in these directories. * * Can be a static array of paths or a function that returns paths * dynamically based on request context (e.g., user tier, tenant). * * @example Static paths * ```typescript * skills: ['skills', 'node_modules/@myorg/skills'] * ``` * * @example Dynamic paths * ```typescript * skills: (ctx) => { * const tier = ctx.requestContext?.get('userTier'); * return tier === 'premium' * ? ['skills/basic', 'skills/premium'] * : ['skills/basic']; * } * ``` */ skills?: SkillsResolver; /** * Custom SkillSource to use for skill discovery. * When provided, this source is used instead of the workspace filesystem or LocalSkillSource. * * Use `VersionedSkillSource` to read skills from the content-addressable blob store, * serving a specific published version without touching the live filesystem. * * @example * ```typescript * import { VersionedSkillSource } from '@mastra/core/workspace'; * * const workspace = new Workspace({ * skills: ['skills'], * skillSource: new VersionedSkillSource(tree, blobStore, versionCreatedAt), * }); * ``` */ skillSource?: SkillSource; /** * Enable LSP diagnostics for edit tools. * * When enabled, edit tools (edit_file, write_file, ast_edit) will append * type errors, warnings, and other diagnostics from language servers after edits. * * LSP requires a sandbox with a process manager (`sandbox.processes`) to spawn * language server processes. It works with any sandbox backend (local, E2B, etc.). * * Requires optional peer dependencies: `vscode-jsonrpc`, `vscode-languageserver-protocol`, * and the relevant language server (e.g. `typescript-language-server` for TypeScript). * * - `true` — Enable with defaults * - `LSPConfig` object — Enable with custom timeouts/settings * * @default undefined (disabled) */ lsp?: boolean | LSPConfig; /** * Per-tool configuration for workspace tools. * Controls which tools are enabled and their safety settings. * * This replaces the provider-level `requireApproval` and `requireReadBeforeWrite` * settings, allowing more granular control per tool. * * @example * ```typescript * tools: { * mastra_workspace_read_file: { * enabled: true, * requireApproval: false, * }, * mastra_workspace_write_file: { * enabled: true, * requireApproval: true, * requireReadBeforeWrite: true, * }, * mastra_workspace_execute_command: { * enabled: true, * requireApproval: true, * }, * } * ``` */ tools?: WorkspaceToolsConfig; /** Auto-sync between fs and sandbox (default: false) */ autoSync?: boolean; /** Timeout for individual operations in milliseconds */ operationTimeout?: number; } export type { WorkspaceStatus } from './types.js'; /** * A Workspace with any combination of filesystem, sandbox, and mounts. * Use this when you need to accept any Workspace regardless of its generic parameters. */ export type AnyWorkspace = Workspace; /** A workspace entry in the Mastra registry, enriched with source metadata. */ export interface RegisteredWorkspace { workspace: Workspace; source: 'mastra' | 'agent'; agentId?: string; agentName?: string; } /** * Information about how filesystem and sandbox paths relate. * Used by agents to understand how to access workspace files from sandbox code. */ export interface PathContext { /** Filesystem details (if available) */ filesystem?: { provider: string; /** Absolute base path on disk (for local filesystems) */ basePath?: string; }; /** Sandbox details (if available) */ sandbox?: { provider: string; /** Working directory for command execution */ workingDirectory?: string; }; /** * Human-readable instructions for how to access filesystem files from sandbox code. * Combined from filesystem and sandbox provider instructions. */ instructions: string; } export interface WorkspaceInfo { id: string; name: string; status: WorkspaceStatus; createdAt: Date; lastAccessedAt: Date; /** Filesystem info (if available) */ filesystem?: FilesystemInfo & { totalFiles?: number; totalSize?: number; }; /** Sandbox info (if available) */ sandbox?: { provider: string; status: string; resources?: { memoryMB?: number; memoryUsedMB?: number; cpuCores?: number; cpuPercent?: number; diskMB?: number; diskUsedMB?: number; }; }; } /** * Workspace provides agents with filesystem and execution capabilities. * * At minimum, a workspace has either a filesystem or a sandbox (or both). * Users pass instantiated provider objects to the constructor. */ export declare class Workspace | undefined = undefined> { readonly id: string; readonly name: string; readonly createdAt: Date; lastAccessedAt: Date; private _status; private readonly _fs?; private readonly _sandbox?; private readonly _config; private readonly _searchEngine?; private _skills?; private _lsp?; private _logger?; constructor(config: WorkspaceConfig); private generateId; private hasSkillsConfig; get status(): WorkspaceStatus; /** * The filesystem provider (if configured). * * Returns the concrete type you passed to the constructor. * When `mounts` is used instead of `filesystem`, returns `CompositeFilesystem` * parameterized with the concrete mount types. */ get filesystem(): [TMounts] extends [Record] ? CompositeFilesystem : TFilesystem; /** * The sandbox provider (if configured). * * Returns the concrete type you passed to the constructor. */ get sandbox(): TSandbox; /** * Get the per-tool configuration for this workspace. * Returns undefined if no tools config was provided. */ getToolsConfig(): WorkspaceToolsConfig | undefined; /** * The LSP manager (if configured, initialized, and a process manager is available). * Returns undefined if LSP is not configured, deps are missing, or sandbox has no process manager. */ get lsp(): LSPManager | undefined; /** * Update the per-tool configuration for this workspace. * Takes effect on the next `createWorkspaceTools()` call. * * @example * ```typescript * // Disable write tools for read-only mode * workspace.setToolsConfig({ * mastra_workspace_write_file: { enabled: false }, * mastra_workspace_edit_file: { enabled: false }, * }); * * // Re-enable all tools * workspace.setToolsConfig(undefined); * ``` */ setToolsConfig(config: WorkspaceToolsConfig | undefined): void; /** * Access skills stored in this workspace. * Skills are SKILL.md files discovered from the configured skillPaths. * * Returns undefined if no skillPaths are configured. * * @example * ```typescript * const skills = await workspace.skills?.list(); * const skill = await workspace.skills?.get('skills/brand-guidelines'); * const results = await workspace.skills?.search('brand colors'); * ``` */ get skills(): WorkspaceSkills | undefined; /** * Check if BM25 keyword search is available. */ get canBM25(): boolean; /** * Check if vector semantic search is available. */ get canVector(): boolean; /** * Check if hybrid search is available. */ get canHybrid(): boolean; /** * Index content for search. * The path becomes the document ID in search results. * * @param path - File path (used as document ID) * @param content - Text content to index * @param options - Index options (metadata, type hints) * @throws {SearchNotAvailableError} if search is not configured */ index(path: string, content: string, options?: { type?: 'text' | 'image' | 'file'; mimeType?: string; metadata?: Record; startLineOffset?: number; }): Promise; /** * Search indexed content. * * @param query - Search query string * @param options - Search options (topK, mode, filters) * @returns Array of search results * @throws {SearchNotAvailableError} if search is not configured */ search(query: string, options?: SearchOptions): Promise; /** * Rebuild the search index from filesystem paths. * Used internally for auto-indexing on init. * * Paths can be plain directories, single files, or glob patterns. * Uses resolvePathPattern for unified resolution: file matches are * indexed directly, directory matches are recursed. */ private rebuildSearchIndex; /** * Index a single file for search. Skips files that can't be read as text. */ private indexFileForSearch; private getAllFiles; /** * Initialize the workspace. * Starts the sandbox, initializes the filesystem, and auto-mounts filesystems. */ init(): Promise; /** * Destroy the workspace and clean up all resources. */ destroy(): Promise; /** * Get workspace information. * @param options.includeFileCount - Whether to count total files (can be slow for large workspaces) */ getInfo(options?: { includeFileCount?: boolean; }): Promise; /** * Get human-readable instructions describing the workspace environment. * * When both a sandbox with mounts and a filesystem exist, each mount path * is classified as sandbox-accessible (state === 'mounted') or * workspace-only (pending / mounting / error / unsupported). When there's * no sandbox or no mounts, falls back to provider-level instructions. * * @param opts - Optional options including request context for per-request customisation * @returns Combined instructions string (may be empty) */ getInstructions(opts?: { requestContext?: RequestContext; }): string; /** * Get information about how filesystem and sandbox paths relate. * Useful for understanding how to access workspace files from sandbox code. * * @deprecated Use {@link getInstructions} instead. `getInstructions()` is * mount-state-aware and feeds into the system message via * `WorkspaceInstructionsProcessor`. * * @returns PathContext with paths and instructions from providers */ getPathContext(): PathContext; /** * Set the logger for this workspace and propagate to providers. * Called by Mastra when the logger is set. * @internal */ __setLogger(logger: IMastraLogger): void; } //# sourceMappingURL=workspace.d.ts.map