43e8a67180
fix(os): route every path-taking os verb through the workspace
521 lines
15 KiB
TOML
521 lines
15 KiB
TOML
[project]
|
|
name = "mirage-ai"
|
|
version = "0.0.5"
|
|
description = "A unified virtual filesystem for AI agents. Mount S3, Google Drive, Slack, Gmail, GitHub, Linear, Notion, Postgres, MongoDB, SSH, and more behind one filesystem so agents read, write, and pipe across services with familiar shell commands."
|
|
readme = "README.md"
|
|
license = "Apache-2.0"
|
|
license-files = ["LICENSE"]
|
|
requires-python = ">=3.11"
|
|
authors = [
|
|
{ name = "Zecheng Zhang", email = "zecheng@strukto.ai" },
|
|
]
|
|
keywords = [
|
|
"ai-agents",
|
|
"filesystem",
|
|
"vfs",
|
|
"fuse",
|
|
"s3",
|
|
"google-drive",
|
|
"slack",
|
|
"agent-tools",
|
|
"shell",
|
|
"rag",
|
|
]
|
|
classifiers = [
|
|
"Development Status :: 3 - Alpha",
|
|
"Intended Audience :: Developers",
|
|
"Operating System :: POSIX :: Linux",
|
|
"Operating System :: MacOS :: MacOS X",
|
|
"Programming Language :: Python :: 3",
|
|
"Programming Language :: Python :: 3.11",
|
|
"Programming Language :: Python :: 3.12",
|
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
"Topic :: System :: Filesystems",
|
|
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
]
|
|
|
|
dependencies = [
|
|
"aiofiles>=24.1.0",
|
|
"aiohttp>=3.14.2",
|
|
"fastapi>=0.135.1",
|
|
"httpx>=0.28.1",
|
|
"python-multipart>=0.0.27",
|
|
"orjson>=3.11",
|
|
"pyyaml>=6.0.3",
|
|
"tree-sitter>=0.25.2",
|
|
"tree-sitter-bash>=0.25.1",
|
|
"typer>=0.12.0",
|
|
"uvicorn[standard]>=0.41.0",
|
|
"jq>=1.11.0",
|
|
"pyjwt[crypto]>=2.13.0",
|
|
"dulwich>=1.2.5",
|
|
"tenacity>=9.1.4",
|
|
"mcp>=1.28.1",
|
|
]
|
|
|
|
[project.urls]
|
|
Homepage = "https://www.strukto.ai/"
|
|
Repository = "https://github.com/strukto-ai/mirage"
|
|
Documentation = "https://docs.mirage.strukto.ai"
|
|
Issues = "https://github.com/strukto-ai/mirage/issues"
|
|
|
|
[project.scripts]
|
|
mirage = "mirage.cli.main:main"
|
|
|
|
[build-system]
|
|
requires = ["setuptools>=68"]
|
|
build-backend = "setuptools.build_meta"
|
|
|
|
[tool.setuptools.packages.find]
|
|
include = ["mirage*"]
|
|
|
|
[tool.setuptools.package-data]
|
|
# py.typed is PEP 561 consent: without the marker a type checker refuses
|
|
# to read an installed package's annotations and every mirage import
|
|
# resolves to Any, so our own gated-at-zero mypy proves nothing to anyone
|
|
# downstream. It caught the 0.0.5 build_resource break in one line.
|
|
mirage = ["**/*.lua", "py.typed"]
|
|
|
|
[project.optional-dependencies]
|
|
# --- python runtime (sandboxed python3 default) ---
|
|
# Pinned exactly: monty's API is still moving fast (0.0.19 replaced the whole
|
|
# execution model), and upstream pins its own worker binary the same way.
|
|
monty = ["pydantic-monty==0.0.19"]
|
|
wasi = ["wasmtime>=46"]
|
|
quickjs = ["wasmtime>=46"]
|
|
|
|
# --- storage / object stores ---
|
|
s3 = ["aioboto3>=13.0"]
|
|
r2 = ["aioboto3>=13.0"]
|
|
gcs = ["aioboto3>=13.0"]
|
|
oci = ["aioboto3>=13.0"]
|
|
databricks = ["databricks-sdk>=0.72.0"]
|
|
|
|
# --- network / remote ---
|
|
ssh = ["asyncssh>=2.23.0"]
|
|
nextcloud = ["opendal>=0.47.1"]
|
|
|
|
# --- huggingface ---
|
|
hf = ["opendal>=0.47.1"]
|
|
|
|
# --- mount ---
|
|
fuse = ["mfusepy>=1.0.0"]
|
|
|
|
# --- mongodb ---
|
|
mongodb = ["pymongo>=4.9"]
|
|
|
|
# --- gridfs ---
|
|
gridfs = ["pymongo>=4.9"]
|
|
|
|
# --- postgres ---
|
|
postgres = ["asyncpg>=0.30.0"]
|
|
|
|
# --- redis ---
|
|
redis = ["redis[hiredis]>=5.0"]
|
|
|
|
# --- mail ---
|
|
email = ["aioimaplib>=2.0.1", "aiosmtplib>=5.1.0"]
|
|
|
|
# --- data ---
|
|
|
|
# --- observability ---
|
|
langfuse = ["langfuse>=4.2.0"]
|
|
|
|
# --- chroma ---
|
|
# thin HTTP-only client; the accessor uses AsyncHttpClient exclusively
|
|
chroma = ["chromadb-client>=1.0.0"]
|
|
|
|
# --- qdrant ---
|
|
qdrant = ["qdrant-client[fastembed]>=1.18.0"]
|
|
|
|
# --- anthropic ---
|
|
anthropic = ["anthropic>=0.88"]
|
|
|
|
# --- openai ---
|
|
openai = ["openai>=2.46.0", "openai-agents>=0.18.3"]
|
|
|
|
# --- pydantic-ai ---
|
|
pydantic-ai = [
|
|
"pydantic-ai-slim[anthropic,openai]>=2.13.0",
|
|
"pydantic-ai-backend>=0.2.16",
|
|
]
|
|
|
|
# --- deepagents ---
|
|
deepagents = [
|
|
"deepagents>=0.7.6",
|
|
]
|
|
|
|
# --- openhands ---
|
|
openhands = [
|
|
"openhands-sdk>=1.36.1 ; python_full_version >= '3.12'",
|
|
"openhands-tools>=1.36.1 ; python_full_version >= '3.12'",
|
|
]
|
|
|
|
# --- agno ---
|
|
agno = [
|
|
"agno>=2.7.4",
|
|
]
|
|
|
|
# --- claude-agent-sdk ---
|
|
claude-agent-sdk = [
|
|
"claude-agent-sdk>=0.2.123",
|
|
]
|
|
|
|
# --- camel ---
|
|
camel = [
|
|
"camel-ai>=0.2.90,<0.3",
|
|
"markitdown>=0.1.5",
|
|
]
|
|
|
|
# --- sandboxes ---
|
|
daytona = [
|
|
"daytona>=0.176.0",
|
|
]
|
|
|
|
# --- meta: install everything ---
|
|
all = [
|
|
"mirage-ai[s3]",
|
|
"mirage-ai[r2]",
|
|
"mirage-ai[gcs]",
|
|
"mirage-ai[oci]",
|
|
"mirage-ai[databricks]",
|
|
"mirage-ai[ssh]",
|
|
"mirage-ai[nextcloud]",
|
|
"mirage-ai[hf]",
|
|
"mirage-ai[fuse]",
|
|
"mirage-ai[mongodb]",
|
|
"mirage-ai[gridfs]",
|
|
"mirage-ai[postgres]",
|
|
"mirage-ai[redis]",
|
|
"mirage-ai[email]",
|
|
"mirage-ai[langfuse]",
|
|
"mirage-ai[mem0]",
|
|
"mirage-ai[chroma]",
|
|
"mirage-ai[qdrant]",
|
|
"mirage-ai[anthropic]",
|
|
"mirage-ai[openai]",
|
|
"mirage-ai[pydantic-ai]",
|
|
"mirage-ai[deepagents]",
|
|
"mirage-ai[openhands]",
|
|
"mirage-ai[agno]",
|
|
"mirage-ai[claude-agent-sdk]",
|
|
"mirage-ai[daytona]",
|
|
"mirage-ai[e2b]",
|
|
]
|
|
sandbox = [
|
|
"mirage-ai[s3]",
|
|
"mirage-ai[r2]",
|
|
"mirage-ai[gcs]",
|
|
"mirage-ai[oci]",
|
|
"mirage-ai[databricks]",
|
|
"mirage-ai[ssh]",
|
|
"mirage-ai[nextcloud]",
|
|
"mirage-ai[hf]",
|
|
"mirage-ai[fuse]",
|
|
"mirage-ai[mongodb]",
|
|
"mirage-ai[gridfs]",
|
|
"mirage-ai[postgres]",
|
|
"mirage-ai[redis]",
|
|
"mirage-ai[email]",
|
|
"mirage-ai[langfuse]",
|
|
"mirage-ai[chroma]",
|
|
"mirage-ai[qdrant]",
|
|
]
|
|
lancedb = [
|
|
"lancedb>=0.33.0",
|
|
]
|
|
mem0 = [
|
|
"mem0ai>=2.0.6",
|
|
]
|
|
e2b = [
|
|
"e2b>=2.0.0",
|
|
]
|
|
|
|
[tool.uv]
|
|
conflicts = [
|
|
[
|
|
{ extra = "camel" },
|
|
{ extra = "openai" },
|
|
],
|
|
[
|
|
{ extra = "camel" },
|
|
{ extra = "openhands" },
|
|
],
|
|
[
|
|
{ extra = "camel" },
|
|
{ extra = "pydantic-ai" },
|
|
],
|
|
[
|
|
{ extra = "camel" },
|
|
{ extra = "all" },
|
|
],
|
|
]
|
|
|
|
[dependency-groups]
|
|
dev = [
|
|
"aioresponses>=0.7.6",
|
|
"python-dotenv>=1.2.2",
|
|
"grpcio>=1.78.0",
|
|
"grpcio-tools>=1.78.0",
|
|
"moto[s3,server]>=5.1.22",
|
|
"pre-commit",
|
|
"pytest",
|
|
"pytest-asyncio>=0.24.0",
|
|
"pytest-cov>=7.0.0",
|
|
"pytest-httpx>=0.36.0",
|
|
"mypy>=2.3.0",
|
|
"lz4>=4.4.5",
|
|
]
|
|
|
|
[tool.flake8]
|
|
exclude = ["mirage/commands/remote/grpc/proto/command_pb2.py", "mirage/commands/remote/grpc/proto/command_pb2_grpc.py"]
|
|
per-file-ignores = [
|
|
"python/mirage/resource/*/prompt.py:E501",
|
|
]
|
|
|
|
[tool.pytest.ini_options]
|
|
testpaths = ["tests"]
|
|
addopts = "--cov=mirage --cov-report=term-missing -q --import-mode=importlib"
|
|
markers = [
|
|
"network: tests that require network access",
|
|
"no_host_override: skip the tests/server/conftest autouse MIRAGE_ALLOWED_HOSTS=* override",
|
|
"no_auth_override: skip the tests/server/conftest autouse MIRAGE_AUTH_MODE=local-with-no-token override",
|
|
]
|
|
|
|
[tool.mypy]
|
|
python_version = "3.12"
|
|
packages = ["mirage"]
|
|
ignore_missing_imports = true
|
|
warn_unused_ignores = true
|
|
warn_redundant_casts = true
|
|
check_untyped_defs = true
|
|
no_implicit_optional = true
|
|
disallow_any_generics = true
|
|
# Every module, rather than an allowlist of 54 against 1826. The
|
|
# allowlist could only ever name what someone remembered to add, so the
|
|
# handles CLAUDE.md prescribes types for (`accessor: Accessor`,
|
|
# `index: IndexCacheStore | None`) went unannotated everywhere it did
|
|
# not reach. TypeScript gets the same guarantee from `strict` in
|
|
# tsconfig.base.json, inherited by every package.
|
|
disallow_untyped_defs = true
|
|
warn_return_any = true
|
|
|
|
# The inversion's remainder, and it only shrinks. Before this, an
|
|
# allowlist of 54 modules opted *in* to annotation checking, so the
|
|
# default for 1826 modules was unchecked and every new file joined the
|
|
# unchecked side. The default is now strict and this list is what has
|
|
# not been annotated yet -- delete entries as directories are cleared,
|
|
# never add one. A new module is checked the day it lands.
|
|
[[tool.mypy.overrides]]
|
|
module = [
|
|
"mirage.accessor._hf",
|
|
"mirage.accessor.gdocs",
|
|
"mirage.accessor.gdrive",
|
|
"mirage.accessor.gmail",
|
|
"mirage.accessor.gsheets",
|
|
"mirage.accessor.gslides",
|
|
"mirage.accessor.history",
|
|
"mirage.accessor.nextcloud",
|
|
"mirage.agents.agno.toolkit",
|
|
"mirage.agents.camel.file",
|
|
"mirage.agents.openai_agents.runner",
|
|
"mirage.agents.openai_agents.shell",
|
|
"mirage.agents.openhands.workspace",
|
|
"mirage.bridge.thread",
|
|
"mirage.cache",
|
|
"mirage.cache.file.ram",
|
|
"mirage.cache.file.redis",
|
|
"mirage.cache.lock",
|
|
"mirage.cli.client",
|
|
"mirage.cli.output",
|
|
"mirage.cli.workspace",
|
|
"mirage.commands.builtin.dify.cat",
|
|
"mirage.commands.builtin.generic.crossmount.detect",
|
|
"mirage.commands.builtin.generic.rm_cmd",
|
|
"mirage.commands.builtin.generic_bind.archive_io",
|
|
"mirage.commands.builtin.generic_bind.builders.du",
|
|
"mirage.commands.builtin.generic_bind.builders.sed",
|
|
"mirage.commands.builtin.generic_bind.factory",
|
|
"mirage.commands.builtin.generic_bind.provision",
|
|
"mirage.commands.builtin.github.du",
|
|
"mirage.commands.builtin.github.grep",
|
|
"mirage.commands.builtin.gmail.grep",
|
|
"mirage.commands.builtin.grep_helper",
|
|
"mirage.commands.builtin.utils.limit",
|
|
"mirage.commands.cli.builtin.git.format",
|
|
"mirage.commands.cli.builtin.git.objects",
|
|
"mirage.commands.cli.builtin.linear.util",
|
|
"mirage.commands.config",
|
|
"mirage.config",
|
|
"mirage.core.box.resolve",
|
|
"mirage.core.chroma.stat",
|
|
"mirage.core.databricks_volume.copy",
|
|
"mirage.core.databricks_volume.read",
|
|
"mirage.core.databricks_volume.stat",
|
|
"mirage.core.databricks_volume.stream",
|
|
"mirage.core.discord.members",
|
|
"mirage.core.discord.read",
|
|
"mirage.core.discord.readdir",
|
|
"mirage.core.disk.exists",
|
|
"mirage.core.disk.read",
|
|
"mirage.core.email.client",
|
|
"mirage.core.email._parse",
|
|
"mirage.core.github.readdir",
|
|
"mirage.core.github.repo",
|
|
"mirage.core.gmail.labels",
|
|
"mirage.core.gmail.messages",
|
|
"mirage.core.hf_buckets.read",
|
|
"mirage.core.hf_buckets.readdir",
|
|
"mirage.core.jq.stream",
|
|
"mirage.core.lancedb.query",
|
|
"mirage.core.lancedb.read",
|
|
"mirage.core.lancedb.readdir",
|
|
"mirage.core.langfuse.client",
|
|
"mirage.core.mem0.client",
|
|
"mirage.core.mongodb.client",
|
|
"mirage.core.mongodb._sampler",
|
|
"mirage.core.mongodb.search",
|
|
"mirage.core.mongodb.stream",
|
|
"mirage.core.nextcloud.read",
|
|
"mirage.core.nextcloud.readdir",
|
|
"mirage.core.nextcloud.search.query",
|
|
"mirage.core.notion.read",
|
|
"mirage.core.postgres.client",
|
|
"mirage.core.postgres.search",
|
|
"mirage.core.qdrant.read",
|
|
"mirage.core.qdrant.readdir",
|
|
"mirage.core.s3.read",
|
|
"mirage.core.slack.readdir",
|
|
"mirage.core.slack.users",
|
|
"mirage.core.ssh.rm",
|
|
"mirage.core.ssh.stream",
|
|
"mirage.core.trello.stat",
|
|
"mirage.fuse.core",
|
|
"mirage.fuse.darwin",
|
|
"mirage.fuse.fs",
|
|
"mirage.fuse.mount",
|
|
"mirage.observe.context",
|
|
"mirage.ops.chroma.grep",
|
|
"mirage.ops.chroma.search",
|
|
"mirage.ops.dify.grep",
|
|
"mirage.ops.dify.search",
|
|
"mirage.ops.gcal.read",
|
|
"mirage.ops.gdocs.read",
|
|
"mirage.ops.generic.factory",
|
|
"mirage.ops.gsheets.read",
|
|
"mirage.ops.gslides.read",
|
|
"mirage.ops.ops",
|
|
"mirage.ops.registry",
|
|
"mirage.resource",
|
|
"mirage.resource.box.box",
|
|
"mirage.resource.chroma",
|
|
"mirage.resource.chroma.chroma",
|
|
"mirage.resource.databricks_volume",
|
|
"mirage.resource.databricks_volume.databricks_volume",
|
|
"mirage.resource.dev.dev",
|
|
"mirage.resource.dify",
|
|
"mirage.resource.dify.dify",
|
|
"mirage.resource.discord",
|
|
"mirage.resource.discord.discord",
|
|
"mirage.resource.disk.disk",
|
|
"mirage.resource.dropbox",
|
|
"mirage.resource.dropbox.dropbox",
|
|
"mirage.resource.email",
|
|
"mirage.resource.email.email",
|
|
"mirage.resource.gcal",
|
|
"mirage.resource.gcal.gcal",
|
|
"mirage.resource.gdocs",
|
|
"mirage.resource.gdocs.gdocs",
|
|
"mirage.resource.gdrive",
|
|
"mirage.resource.gdrive.gdrive",
|
|
"mirage.resource.github.github",
|
|
"mirage.resource.gmail",
|
|
"mirage.resource.gmail.gmail",
|
|
"mirage.resource.gridfs.gridfs",
|
|
"mirage.resource.gsheets",
|
|
"mirage.resource.gsheets.gsheets",
|
|
"mirage.resource.gslides",
|
|
"mirage.resource.gslides.gslides",
|
|
"mirage.resource.hf_buckets.hf_buckets",
|
|
"mirage.resource.hf_datasets.hf_datasets",
|
|
"mirage.resource.hf_models.hf_models",
|
|
"mirage.resource.hf_spaces.hf_spaces",
|
|
"mirage.resource.history.history",
|
|
"mirage.resource.jaeger",
|
|
"mirage.resource.jaeger.jaeger",
|
|
"mirage.resource.lancedb",
|
|
"mirage.resource.lancedb.lancedb",
|
|
"mirage.resource.langfuse",
|
|
"mirage.resource.langfuse.langfuse",
|
|
"mirage.resource.linear",
|
|
"mirage.resource.linear.linear",
|
|
"mirage.resource.loader",
|
|
"mirage.resource.mem0",
|
|
"mirage.resource.mongodb",
|
|
"mirage.resource.mongodb.mongodb",
|
|
"mirage.resource.nextcloud.nextcloud",
|
|
"mirage.resource.notion",
|
|
"mirage.resource.notion.notion",
|
|
"mirage.resource.onedrive.onedrive",
|
|
"mirage.resource.postgres",
|
|
"mirage.resource.postgres.postgres",
|
|
"mirage.resource.qdrant",
|
|
"mirage.resource.qdrant.qdrant",
|
|
"mirage.resource.ram",
|
|
"mirage.resource.ram.ram",
|
|
"mirage.resource.redis",
|
|
"mirage.resource.redis.redis",
|
|
"mirage.resource.registry",
|
|
"mirage.resource.s3.s3",
|
|
"mirage.resource.sharepoint.sharepoint",
|
|
"mirage.resource.slack",
|
|
"mirage.resource.slack.slack",
|
|
"mirage.resource.ssh.ssh",
|
|
"mirage.resource.trello",
|
|
"mirage.resource.trello.trello",
|
|
"mirage.runtime.python.monty.osaccess",
|
|
"mirage.runtime.vfs",
|
|
"mirage.runtime.wasm.host",
|
|
"mirage.server.app",
|
|
"mirage.server.routers.execute",
|
|
"mirage.server.routers.jobs",
|
|
"mirage.server.routers.sessions",
|
|
"mirage.server.summary",
|
|
"mirage.server.version.api",
|
|
"mirage.server.version.restore",
|
|
"mirage.server.version.state_diff",
|
|
"mirage.server.version.state_tree",
|
|
"mirage.shell.arith",
|
|
"mirage.shell.parse",
|
|
"mirage.workspace.dispatcher.dispatcher",
|
|
"mirage.workspace.executor.builtins.scope",
|
|
"mirage.workspace.executor.control",
|
|
"mirage.workspace.executor.jobs",
|
|
"mirage.workspace.executor.pipes",
|
|
"mirage.workspace.executor.redirect",
|
|
"mirage.workspace.expand.node",
|
|
"mirage.workspace.expand.variable",
|
|
"mirage.workspace.mount.mount",
|
|
"mirage.workspace.mount.namespace",
|
|
"mirage.workspace.mount.storage",
|
|
"mirage.workspace.node.command_dispatch",
|
|
"mirage.workspace.node.execute_node",
|
|
"mirage.workspace.node.program",
|
|
"mirage.workspace.node.provision_node",
|
|
"mirage.workspace.node.test_expr",
|
|
"mirage.workspace.provision.command",
|
|
"mirage.workspace.provision.control",
|
|
"mirage.workspace.provision.pipes",
|
|
"mirage.workspace.provision.redirect",
|
|
"mirage.workspace.session",
|
|
"mirage.workspace.snapshot.api",
|
|
"mirage.workspace.snapshot.manifest",
|
|
"mirage.workspace.snapshot.state",
|
|
"mirage.workspace.snapshot.tar_io",
|
|
"mirage.workspace.workspace.cache",
|
|
"mirage.workspace.workspace.execute",
|
|
"mirage.workspace.workspace.workspace",
|
|
]
|
|
disallow_untyped_defs = false
|
|
warn_return_any = false
|