refactor(instance-ai): use native daytona filesystem base

This commit is contained in:
Oleg Ivaniv 2026-05-05 11:11:01 +02:00
parent d961b9466e
commit 2179ae6479
No known key found for this signature in database
3 changed files with 17 additions and 12 deletions

View File

@ -258,7 +258,7 @@ export class BuilderSandboxFactory {
const workspace = new Workspace({
sandbox: daytonaSandbox,
filesystem: new DaytonaFilesystem(daytonaSandbox),
filesystem: new DaytonaFilesystem(daytonaSandbox) as unknown as LocalFilesystem,
});
await workspace.init();

View File

@ -123,6 +123,6 @@ export function createWorkspace(
return new Workspace({
sandbox,
filesystem: new DaytonaFilesystem(sandbox),
filesystem: new DaytonaFilesystem(sandbox) as unknown as LocalFilesystem,
});
}

View File

@ -1,14 +1,13 @@
/**
* Daytona Filesystem Adapter
*
* Implements MastraFilesystem backed by the Daytona SDK's FileSystem API.
* This gives Daytona workspaces all built-in Mastra workspace tools:
* Implements a native agents filesystem backed by the Daytona SDK's FileSystem API.
* This gives Daytona workspaces all built-in workspace tools:
* read_file, write_file, edit_file, list_files, grep, ast_edit, etc.
*
* Without this adapter, Daytona workspaces only get sandbox tools (execute_command).
*/
import { FileNotFoundError, MastraFilesystem } from '@mastra/core/workspace';
import type {
FileContent,
FileStat,
@ -19,21 +18,22 @@ import type {
RemoveOptions,
CopyOptions,
ProviderStatus,
} from '@mastra/core/workspace';
} from '@n8n/agents';
import { BaseFilesystem } from '@n8n/agents';
import type { DaytonaSandbox } from '@mastra/daytona';
/**
* A MastraFilesystem implementation that delegates to the Daytona SDK's
* A native agents filesystem implementation that delegates to the Daytona SDK's
* sandbox.instance.fs API for all file operations.
*/
export class DaytonaFilesystem extends MastraFilesystem {
export class DaytonaFilesystem extends BaseFilesystem {
readonly id: string;
readonly name = 'DaytonaFilesystem';
readonly provider = 'daytona';
status: ProviderStatus = 'pending';
constructor(private readonly sandbox: DaytonaSandbox) {
super({ name: 'DaytonaFilesystem' });
super();
this.id = `daytona-fs-${sandbox.id}`;
}
@ -133,10 +133,8 @@ export class DaytonaFilesystem extends MastraFilesystem {
try {
info = await this.fs.getFileDetails(path);
} catch (error: unknown) {
// Translate Daytona's 404 into Mastra's FileNotFoundError so that
// callers like wrapWithReadTracker can handle missing files correctly.
if (isDaytona404(error)) {
throw new FileNotFoundError(path);
throw new DaytonaFileNotFoundError(path);
}
throw error;
}
@ -151,6 +149,13 @@ export class DaytonaFilesystem extends MastraFilesystem {
}
}
class DaytonaFileNotFoundError extends Error {
constructor(path: string) {
super(`File not found: ${path}`);
this.name = 'DaytonaFileNotFoundError';
}
}
function isDaytona404(error: unknown): boolean {
return (
error instanceof Error &&