Metadata-Version: 2.4
Name: mirage-ai
Version: 0.0.1
Summary: 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.
Author-email: Zecheng Zhang <zecheng@strukto.ai>
License-Expression: Apache-2.0
Project-URL: Homepage, https://www.strukto.ai/
Project-URL: Repository, https://github.com/strukto-ai/mirage
Project-URL: Documentation, https://docs.mirage.strukto.ai
Project-URL: Issues, https://github.com/strukto-ai/mirage/issues
Keywords: ai-agents,filesystem,vfs,fuse,s3,google-drive,slack,agent-tools,shell,rag
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Filesystems
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: aiofiles>=24.1.0
Requires-Dist: aiohttp>=3.13.3
Requires-Dist: fastapi>=0.135.1
Requires-Dist: httpx>=0.28.1
Requires-Dist: python-multipart>=0.0.20
Requires-Dist: numpy>=2.4.3
Requires-Dist: orjson>=3.11
Requires-Dist: pyyaml>=6.0.3
Requires-Dist: python-dotenv>=1.2.2
Requires-Dist: tree-sitter>=0.25.2
Requires-Dist: tree-sitter-bash>=0.25.1
Requires-Dist: typer>=0.12.0
Requires-Dist: uvicorn[standard]>=0.41.0
Requires-Dist: pypdfium2>=5.7.0
Requires-Dist: pillow>=12.2.0
Requires-Dist: jq>=1.11.0
Requires-Dist: mfusepy>=1.0.0
Provides-Extra: s3
Requires-Dist: aioboto3>=13.0; extra == "s3"
Provides-Extra: r2
Requires-Dist: aioboto3>=13.0; extra == "r2"
Provides-Extra: gcs
Requires-Dist: aioboto3>=13.0; extra == "gcs"
Provides-Extra: oci
Requires-Dist: aioboto3>=13.0; extra == "oci"
Provides-Extra: ssh
Requires-Dist: asyncssh>=2.22.0; extra == "ssh"
Requires-Dist: paramiko>=4.0.0; extra == "ssh"
Provides-Extra: fuse
Requires-Dist: mfusepy>=1.0.0; extra == "fuse"
Provides-Extra: mongodb
Requires-Dist: motor>=3.7.1; extra == "mongodb"
Provides-Extra: postgres
Requires-Dist: asyncpg>=0.30.0; extra == "postgres"
Provides-Extra: redis
Requires-Dist: redis[hiredis]>=5.0; extra == "redis"
Provides-Extra: email
Requires-Dist: aioimaplib>=2.0.1; extra == "email"
Requires-Dist: aiosmtplib>=5.1.0; extra == "email"
Provides-Extra: parquet
Requires-Dist: pandas>=3.0.1; extra == "parquet"
Requires-Dist: pyarrow>=15.0; extra == "parquet"
Provides-Extra: hdf5
Requires-Dist: h5py>=3.16.0; extra == "hdf5"
Requires-Dist: tables>=3.11.1; extra == "hdf5"
Provides-Extra: pdf
Requires-Dist: pypdfium2>=5.6.0; extra == "pdf"
Requires-Dist: pillow>=12.2.0; extra == "pdf"
Provides-Extra: audio
Requires-Dist: av>=17.0.0; extra == "audio"
Requires-Dist: sherpa-onnx>=1.12.34; extra == "audio"
Requires-Dist: tinytag>=2.2.1; extra == "audio"
Provides-Extra: langfuse
Requires-Dist: langfuse>=4.2.0; extra == "langfuse"
Provides-Extra: anthropic
Requires-Dist: anthropic>=0.88; extra == "anthropic"
Provides-Extra: openai
Requires-Dist: openai>=2.30.0; extra == "openai"
Requires-Dist: openai-agents>=0.14.7; extra == "openai"
Provides-Extra: pydantic-ai
Requires-Dist: pydantic-ai>=1.35; extra == "pydantic-ai"
Requires-Dist: pydantic-ai-backend>=0.1.0; extra == "pydantic-ai"
Requires-Dist: mirage-ai[pdf]; extra == "pydantic-ai"
Provides-Extra: deepagents
Requires-Dist: deepagents>=0.4.12; extra == "deepagents"
Requires-Dist: mirage-ai[pdf]; extra == "deepagents"
Provides-Extra: openhands
Requires-Dist: openhands-sdk>=1.18.0; extra == "openhands"
Requires-Dist: openhands-tools>=1.18.0; extra == "openhands"
Provides-Extra: camel
Requires-Dist: camel-ai<0.3,>=0.2.40; extra == "camel"
Requires-Dist: markitdown>=0.1.5; extra == "camel"
Provides-Extra: all
Requires-Dist: mirage-ai[s3]; extra == "all"
Requires-Dist: mirage-ai[r2]; extra == "all"
Requires-Dist: mirage-ai[gcs]; extra == "all"
Requires-Dist: mirage-ai[oci]; extra == "all"
Requires-Dist: mirage-ai[ssh]; extra == "all"
Requires-Dist: mirage-ai[fuse]; extra == "all"
Requires-Dist: mirage-ai[mongodb]; extra == "all"
Requires-Dist: mirage-ai[postgres]; extra == "all"
Requires-Dist: mirage-ai[redis]; extra == "all"
Requires-Dist: mirage-ai[email]; extra == "all"
Requires-Dist: mirage-ai[parquet]; extra == "all"
Requires-Dist: mirage-ai[hdf5]; extra == "all"
Requires-Dist: mirage-ai[pdf]; extra == "all"
Requires-Dist: mirage-ai[audio]; extra == "all"
Requires-Dist: mirage-ai[langfuse]; extra == "all"
Requires-Dist: mirage-ai[anthropic]; extra == "all"
Requires-Dist: mirage-ai[openai]; extra == "all"
Requires-Dist: mirage-ai[pydantic-ai]; extra == "all"
Requires-Dist: mirage-ai[deepagents]; extra == "all"
Requires-Dist: mirage-ai[openhands]; extra == "all"
Dynamic: license-file

<p align="center">
  <img src="https://raw.githubusercontent.com/strukto-ai/mirage/main/assets/mirage-og-light@2x.png" alt="Mirage: A Unified Virtual File System for AI Agents" width="900">
</p>

<p align="center">
    <a href="https://docs.mirage.strukto.ai" alt="Documentation">
        <img src="https://img.shields.io/badge/mirage-docs-0C0C0C?labelColor=FAFAFA" /></a>
    <a href="https://www.strukto.ai" alt="Website">
        <img src="https://img.shields.io/badge/made by-strukto.ai-0C0C0C?labelColor=FAFAFA" /></a>
    <a href="https://github.com/strukto-ai/mirage/blob/main/LICENSE" alt="License">
        <img src="https://img.shields.io/github/license/strukto-ai/mirage?color=0C0C0C&labelColor=FAFAFA" /></a>
    <a href="https://discord.gg/u8BPQ65KsS" alt="Discord">
        <img src="https://img.shields.io/badge/discord-join-0C0C0C?labelColor=FAFAFA&logo=discord&logoColor=0C0C0C" /></a>
    <br/>
    <a href="https://docs.mirage.strukto.ai/python/quickstart" alt="Python docs">
        <img src="https://img.shields.io/badge/python-docs-0C0C0C?labelColor=FAFAFA&logo=python&logoColor=0C0C0C" alt="Python docs"></a>
    <a href="https://pypi.org/project/mirage-ai/" alt="PyPI Version">
        <img src="https://img.shields.io/pypi/v/mirage-ai.svg?color=0C0C0C&labelColor=FAFAFA"/></a>
    <br/>
    <a href="https://docs.mirage.strukto.ai/typescript/quickstart" alt="TypeScript docs">
        <img src="https://img.shields.io/badge/typescript-docs-0C0C0C?labelColor=FAFAFA&logo=typescript&logoColor=0C0C0C" alt="TypeScript docs"></a>
    <a href="https://www.npmjs.com/package/@struktoai/mirage-node" alt="NPM Version">
        <img src="https://img.shields.io/npm/v/@struktoai/mirage-node.svg?color=0C0C0C&labelColor=FAFAFA"/></a>
</p>

Mirage is **a Unified Virtual File System for AI Agents**: a single tree that mounts services and data sources like S3, Google Drive, Slack, Gmail, and Redis side-by-side as one filesystem.

AI agents reach every backend with the same handful of Unix-like tools, and pipelines compose across services as naturally as on a local disk. It's a simulated environment, agents see one filesystem underneath. Any LLM that already knows bash can use Mirage out of the box, with zero new vocabulary.

```ts
const ws = new Workspace({
  '/data':   new RAMResource(),
  '/s3':     new S3Resource({ bucket: 'logs' }),
  '/slack':  new SlackResource({}),
  '/github': new GitHubResource({}),
})

await ws.execute('grep alert /slack/general/*.json | wc -l')
await ws.execute('cat /github/mirage/README.md')
await ws.execute('cp /s3/report.csv /data/local.csv')
```

## About

- **One filesystem, every backend.** Every service speaks the same filesystem semantics, so agents reason about one abstraction instead of N SDKs and M MCPs, leaning on the filesystem and bash vocabulary LLMs are most fluent in.
- **Multiple resources, one filesystem:** RAM, Disk, Redis, S3 / R2 / OCI / Supabase / GCS, Gmail / GDrive / GDocs / GSheets / GSlides, GitHub / Linear / Notion / Trello, Slack / Discord / Telegram / Email, MongoDB, SSH, and more, mounted side-by-side under a single root.
- **Familiar bash tools across every mount.** Agents reuse the same handful of Unix-like tools instead of learning a new API per service, and pipelines compose across services as naturally as on a local disk, the exact corpus modern LLMs are most heavily trained on.
- **Portable workspaces:** clone, snapshot, and version your environment. Move agent runs between machines without restarting or reconfiguring the system.
- **Embed in your apps and services:** Python and TypeScript SDKs let you give your AI agents a virtual filesystem directly inside FastAPI, Express, browser apps, or any async runtime, no separate process required. Clone, snapshot, and version the workspace from inside your code.
- **Works with major agent application frameworks:** OpenAI Agents SDK, Vercel AI SDK (TypeScript), LangChain, Pydantic AI, CAMEL, and OpenHands.
- **Lightweight CLI + daemon:** plugs into coding agents like Claude Code and Codex so they reach every mounted resource through familiar bash, getting more useful work done per turn.

## Architecture

<p align="center">
  <picture>
    <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/strukto-ai/mirage/main/assets/mirage-arch-dark.svg">
    <img src="https://raw.githubusercontent.com/strukto-ai/mirage/main/assets/mirage-arch-light.svg" alt="Mirage architecture: AI Agent and Application → Mirage Bash and VFS → Dispatcher &amp; Cache → Infrastructure and Remote" width="900">
  </picture>
</p>

## Installation

### Prerequisites

- **Python** ≥ 3.12 for the `mirage-ai` package and the `mirage` CLI
- **Node.js** ≥ 20 for the TypeScript SDK
- **macOS** or **Linux** (FUSE-based mounts require platform support)

### Python

```bash
uv add mirage-ai
```

This installs both the `mirage` library and the `mirage` CLI binary.

### TypeScript

Pick the package that matches your runtime:

```bash
npm install @struktoai/mirage-node      # Node.js servers and CLIs
npm install @struktoai/mirage-browser   # browser / edge runtimes
npm install @struktoai/mirage-core      # runtime-agnostic primitives
```

`@struktoai/mirage-node` and `@struktoai/mirage-browser` both pull in `@struktoai/mirage-core` automatically.

### CLI

```bash
curl -fsSL https://strukto.ai/install.sh | sh
```

Or via your package manager of choice:

```bash
brew install mirage
```

```bash
uvx mirage-ai
```

```bash
npx @struktoai/mirage-cli
```

## Quickstart (Python)

```python
from mirage import Workspace
from mirage.resource.gdocs import GDocsConfig, GDocsResource
from mirage.resource.ram import RAMResource
from mirage.resource.s3 import S3Config, S3Resource
from mirage.resource.slack import SlackConfig, SlackResource

ws = Workspace({
    "/data":  RAMResource(),
    "/s3":    S3Resource(S3Config(bucket="my-bucket")),
    "/slack": SlackResource(SlackConfig()),
    "/docs":  GDocsResource(GDocsConfig()),
})

await ws.execute("cp /s3/report.csv /data/report.csv")
await ws.execute("grep alert /s3/data/log.jsonl | wc -l")

ws.snapshot("demo.tar")
```

## Quickstart (TypeScript)

```ts
import {
  Workspace,
  RAMResource,
  S3Resource,
  SlackResource,
  GDocsResource,
} from '@struktoai/mirage-browser'

const ws = new Workspace({
  '/data':  new RAMResource(),
  '/s3':    new S3Resource({ bucket: 'my-bucket' }),
  '/slack': new SlackResource({}),
  '/docs':  new GDocsResource({}),
})

await ws.execute('cp /s3/report.csv /data/report.csv')
await ws.execute('grep alert /s3/data/log.jsonl | wc -l')
```

## Quickstart (CLI)

```bash
mirage workspace create ws.yaml --id demo
mirage execute   --workspace_id demo --command "cp /s3/report.csv /data/report.csv"
mirage provision --workspace_id demo --command "cat /s3/data/large.jsonl"
mirage workspace snapshot demo demo.tar
mirage workspace load demo.tar --id demo-restored
```

## Agent Frameworks

Mirage drops into the major agent application frameworks as a sandbox or tool layer. Your agent runs against the same mount tree it would in bash, so swapping the model or runtime never changes the surface.

### OpenAI Agents SDK (Python)

The `MirageSandboxClient` plugs a `Workspace` into the OpenAI Agents SDK as a sandbox: bash commands the agent runs execute against your mounts.

```python
from agents import Runner
from agents.run import RunConfig
from agents.sandbox import SandboxAgent, SandboxRunConfig

from mirage.agents.openai_agents import MirageSandboxClient

client = MirageSandboxClient(ws)
agent = SandboxAgent(
    name="Mirage Sandbox Agent",
    model="gpt-5.4-nano",
    instructions=ws.file_prompt,
)

result = await Runner.run(
    agent,
    "Summarize /s3/data/report.parquet into /report.txt.",
    run_config=RunConfig(sandbox=SandboxRunConfig(client=client)),
)
```

### Vercel AI SDK (TypeScript)

`mirageTools(ws)` exposes the workspace as a typed AI SDK tool set, so any model wired into the AI SDK can read and write across mounts, in Node or the browser.

```ts
import { generateText } from 'ai'
import { openai } from '@ai-sdk/openai'
import { mirageTools } from '@struktoai/mirage-agents/vercel'
import { buildSystemPrompt } from '@struktoai/mirage-agents/openai'

const { text } = await generateText({
  model: openai('gpt-5.4-nano'),
  system: buildSystemPrompt({ mountInfo: { '/': 'In-memory filesystem' } }),
  prompt: "Use readFile to read /docs/paper.pdf, then describe what's in it.",
  tools: mirageTools(ws),
})
```

LangChain, Pydantic AI, CAMEL, OpenHands, and Mastra adapters live alongside these.

## Cache

Every `Workspace` ships with a **two-layer cache** so repeated work against remote backends (S3, GDrive, Slack, …) hits local state instead of the network:

- **Index cache.** Listings and metadata. The first directory walk hits the API; subsequent ones serve from the index until TTL expires.
- **File cache.** Object bytes. The first read streams from origin; later pipelines read from cache.
- **Pluggable backends.** Each layer is a store with two built-ins:
  - **RAM** (default): in-process, zero setup, 512 MB file cache and 10-minute index TTL. Best for single-process apps and notebooks.
  - **Redis**: shared across workers, processes, and machines. Best for serverless, multi-replica services, or when you want cache state to survive restarts.

```ts
import { RedisFileCacheStore, RedisIndexCacheStore, Workspace } from 'mirage/node'

const ws = new Workspace(
  { '/s3': new S3Resource({ bucket: 'my-bucket' }) },
  {
    cache: new RedisFileCacheStore({ url: 'redis://localhost:6379/0', limit: '8GB' }),
    index: new RedisIndexCacheStore({ url: 'redis://localhost:6379/0', ttl: 600 }),
  },
)
```

```ts
import { S3Resource, Workspace } from 'mirage/node'

const ws = new Workspace({ '/s3': new S3Resource({ bucket: 'my-bucket' }) })

// 1. Index miss → S3 LIST. Listing stored in index cache.
await ws.execute('ls /s3/data/')

// 2. Index hit → 0 network calls.
await ws.execute('find /s3/data/ -name "*.jsonl"')

// 3. File miss → S3 GET. Bytes stored in file cache.
await ws.execute('cat /s3/data/log.jsonl | wc -l')

// 4. File hit → 0 network calls.
await ws.execute('grep alert /s3/data/log.jsonl')
```
