Skip to content

feat: virtual file system#2114

Draft
Tomas2D wants to merge 1 commit intomainfrom
feat/virtual-fs-s3
Draft

feat: virtual file system#2114
Tomas2D wants to merge 1 commit intomainfrom
feat/virtual-fs-s3

Conversation

@Tomas2D
Copy link
Collaborator

@Tomas2D Tomas2D commented Feb 18, 2026

Summary

Linked Issues

Documentation

  • No Docs Needed:

If this PR adds new feature or changes existing. Make sure documentation is adjusted accordingly. If the docs is not needed, please explain why.

Signed-off-by: Tomas Dvorak <toomas2d@gmail.com>
@Tomas2D Tomas2D marked this pull request as draft February 18, 2026 09:08
@dosubot dosubot bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Feb 18, 2026
@Tomas2D Tomas2D changed the title feat: wip feat: virtual file system Feb 18, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @Tomas2D, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the AgentStack SDK by integrating an fsspec-compatible filesystem extension. This integration allows agents to interact with the AgentStack Files API using a unified and flexible interface, streamlining data access and manipulation. The changes encompass adding essential dependencies, implementing the core filesystem logic, and providing a clear demonstration agent to showcase its utility. This improvement aims to provide a more robust and developer-friendly experience for agents requiring file operations within the AgentStack ecosystem.

Highlights

  • New FileSystem Extension: Introduced a new FileSystemExtension in the AgentStack SDK to provide fsspec-compatible access to the AgentStack Files API, enabling standardized file operations.
  • Dependency Updates: Added fsspec as a core dependency across various AgentStack components to support the new filesystem capabilities. Also included numba, llvmlite, and numpy for the deepagents content builder.
  • New Example Agent: A new example agent named 'My Agent' was added to demonstrate the practical usage of the FileSystemExtensionServer for reading CSV files.
  • Tooling and Versioning Adjustments: Updated the SDK project version, replaced pyrefly with pyright for development dependencies, and adjusted linting configurations accordingly.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • agents/deepagents_content_builder/pyproject.toml
    • Added numba dependency.
  • agents/deepagents_content_builder/src/content_builder/agent.py
    • Added a new example agent named "My Agent" demonstrating file system extension usage.
  • agents/deepagents_content_builder/uv.lock
    • Added fsspec dependency.
    • Added llvmlite dependency.
    • Added numba dependency.
    • Added numpy dependency.
  • apps/agentstack-cli/uv.lock
    • Added fsspec dependency.
  • apps/agentstack-sdk-py/pyproject.toml
    • Updated project version from 0.6.3 to 0.6.1.
    • Removed typing-extensions, opentelemetry-instrumentation-httpx, and opentelemetry-instrumentation-openai dependencies.
    • Added fsspec dependency.
    • Replaced pyrefly with pyright in development dependencies.
    • Updated linting ignore rule for F403 to reflect the use of Pyright.
    • Replaced [tool.pyrefly] configuration with [tool.pyright] configuration.
  • apps/agentstack-sdk-py/src/agentstack_sdk/a2a/extensions/services/init.py
    • Imported the new filesystem module.
  • apps/agentstack-sdk-py/src/agentstack_sdk/a2a/extensions/services/filesystem.py
    • Added a new module implementing FileSystemExtensionSpec and FileSystemExtensionServer for fsspec-compatible access to AgentStack Files API.
  • apps/agentstack-sdk-py/tests/unit/test_filesystem_extension.py
    • Added unit tests for the new FileSystemExtension.
  • apps/agentstack-sdk-py/uv.lock
    • Added fsspec dependency.
  • apps/agentstack-server/uv.lock
    • Added fsspec dependency.
Activity
  • No activity has been recorded for this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

The pull request introduces a Virtual File System (VFS) extension for AgentStack, enabling fsspec-compatible access to the Files API. While this is a valuable feature, it contains a high-severity path traversal vulnerability in the path normalization logic, allowing for bypassing the prefix restriction and potentially leading to unauthorized file access or modification. Furthermore, several code-related issues need addressing, such as a version regression in the SDK's pyproject.toml, missing imports and invalid method calls in the example agent, and potential performance bottlenecks in the VFS implementation due to eager file loading and inefficient async-to-sync bridging.

Comment on lines +50 to +51
path = path.lstrip("/")
return f"{self._prefix}/{path}" if self._prefix else path
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

The _normalize_path method is vulnerable to path traversal. It prepends a prefix to a user-supplied path but only strips leading slashes, failing to handle .. components. An attacker or a malicious LLM agent could use paths like ../../etc/passwd to escape the intended _prefix and access, modify, or delete unauthorized files in the AgentStack platform.

To fix this, use os.path.normpath to resolve relative path components and verify that the resulting path still starts with the allowed prefix.

Suggested change
path = path.lstrip("/")
return f"{self._prefix}/{path}" if self._prefix else path
import os
path = path.lstrip("/")
if not self._prefix:
return path
full_path = os.path.normpath(os.path.join(self._prefix, path))
if not full_path.startswith(self._prefix):
raise ValueError("Access denied: path is outside the allowed prefix")
return full_path

[project]
name = "agentstack-sdk"
version = "0.6.3"
version = "0.6.1"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The version of agentstack-sdk is being downgraded from 0.6.3 to 0.6.1. This appears to be an accidental regression and should be corrected to reflect the next version.

Comment on lines +67 to +68
df = pd.read_csv(f, sep="|", header=None)
yield df.text()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

There are two issues in this snippet:

  1. The pd alias is used but pandas is not imported in this file.
  2. pandas.DataFrame does not have a text() method. You likely intended to use df.to_string() or access a specific column.

self._platform = platform
self._agentstack_fs = fs # Store reference for our use

data = self._load_content() if "r" in mode else None
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current implementation eagerly loads the entire file content into memory upon opening in read mode. For large files, this will lead to high memory consumption and potential MemoryError. Consider implementing lazy loading or a buffered reader by inheriting from fsspec.spec.AbstractBufferedFile instead of MemoryFile.


async def _commit():
async with platform.use_client() as client:
ct = "text/plain" if self.path.endswith(".txt") else "text/csv" if self.path.endswith(".csv") else "application/json" if self.path.endswith(".json") else "application/octet-stream"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Hardcoding mimetypes based on a few extensions is fragile. It's better to use the standard mimetypes library to determine the content type dynamically.

Suggested change
ct = "text/plain" if self.path.endswith(".txt") else "text/csv" if self.path.endswith(".csv") else "application/json" if self.path.endswith(".json") else "application/octet-stream"
import mimetypes
ct, _ = mimetypes.guess_type(self.path)
ct = ct or "application/octet-stream"

if loop and loop.is_running():
import concurrent.futures

with concurrent.futures.ThreadPoolExecutor() as executor:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Creating a new ThreadPoolExecutor for every synchronous call to an asynchronous operation is inefficient as it involves significant overhead for thread creation and teardown. Consider using a shared class-level or module-level executor to improve performance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L This PR changes 100-499 lines, ignoring generated files.

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant