@struktoai/mirage-node 0.0.1-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +230 -0
- package/dist/box-4P7DCJH7.js +8 -0
- package/dist/box-4P7DCJH7.js.map +1 -0
- package/dist/chunk-35PVZRWU.js +24 -0
- package/dist/chunk-35PVZRWU.js.map +1 -0
- package/dist/chunk-3PBSL7BS.js +93 -0
- package/dist/chunk-3PBSL7BS.js.map +1 -0
- package/dist/chunk-3Y625AUP.js +24 -0
- package/dist/chunk-3Y625AUP.js.map +1 -0
- package/dist/chunk-5E6BULAK.js +92 -0
- package/dist/chunk-5E6BULAK.js.map +1 -0
- package/dist/chunk-5ITBZN55.js +24 -0
- package/dist/chunk-5ITBZN55.js.map +1 -0
- package/dist/chunk-6M2NL363.js +94 -0
- package/dist/chunk-6M2NL363.js.map +1 -0
- package/dist/chunk-6M3QVVOH.js +32 -0
- package/dist/chunk-6M3QVVOH.js.map +1 -0
- package/dist/chunk-6VKNSO6U.js +56 -0
- package/dist/chunk-6VKNSO6U.js.map +1 -0
- package/dist/chunk-6Y6GWMFF.js +24 -0
- package/dist/chunk-6Y6GWMFF.js.map +1 -0
- package/dist/chunk-7QXJ4KWQ.js +132 -0
- package/dist/chunk-7QXJ4KWQ.js.map +1 -0
- package/dist/chunk-ALAMUIGJ.js +57 -0
- package/dist/chunk-ALAMUIGJ.js.map +1 -0
- package/dist/chunk-DCJQ2PIX.js +100 -0
- package/dist/chunk-DCJQ2PIX.js.map +1 -0
- package/dist/chunk-EKPH4MMD.js +27 -0
- package/dist/chunk-EKPH4MMD.js.map +1 -0
- package/dist/chunk-FZ2GJ4BJ.js +29 -0
- package/dist/chunk-FZ2GJ4BJ.js.map +1 -0
- package/dist/chunk-G7O6DAWU.js +178 -0
- package/dist/chunk-G7O6DAWU.js.map +1 -0
- package/dist/chunk-GCB4JUF7.js +94 -0
- package/dist/chunk-GCB4JUF7.js.map +1 -0
- package/dist/chunk-GKQNMLQU.js +7757 -0
- package/dist/chunk-GKQNMLQU.js.map +1 -0
- package/dist/chunk-GO67AOYK.js +24 -0
- package/dist/chunk-GO67AOYK.js.map +1 -0
- package/dist/chunk-GPF66TH2.js +24 -0
- package/dist/chunk-GPF66TH2.js.map +1 -0
- package/dist/chunk-H3JR7MN3.js +45 -0
- package/dist/chunk-H3JR7MN3.js.map +1 -0
- package/dist/chunk-H74QYTN7.js +50 -0
- package/dist/chunk-H74QYTN7.js.map +1 -0
- package/dist/chunk-HEQL3LPK.js +66 -0
- package/dist/chunk-HEQL3LPK.js.map +1 -0
- package/dist/chunk-HXWGG4K7.js +66 -0
- package/dist/chunk-HXWGG4K7.js.map +1 -0
- package/dist/chunk-I4RRGZGB.js +24 -0
- package/dist/chunk-I4RRGZGB.js.map +1 -0
- package/dist/chunk-ICSS5ETT.js +67 -0
- package/dist/chunk-ICSS5ETT.js.map +1 -0
- package/dist/chunk-KINMBZHC.js +18 -0
- package/dist/chunk-KINMBZHC.js.map +1 -0
- package/dist/chunk-LBBM3LKK.js +99 -0
- package/dist/chunk-LBBM3LKK.js.map +1 -0
- package/dist/chunk-LPMPTQYP.js +36 -0
- package/dist/chunk-LPMPTQYP.js.map +1 -0
- package/dist/chunk-M42JTWPR.js +2794 -0
- package/dist/chunk-M42JTWPR.js.map +1 -0
- package/dist/chunk-MVE5VVMQ.js +91 -0
- package/dist/chunk-MVE5VVMQ.js.map +1 -0
- package/dist/chunk-MY3NUJJD.js +67 -0
- package/dist/chunk-MY3NUJJD.js.map +1 -0
- package/dist/chunk-NOZZFJEB.js +93 -0
- package/dist/chunk-NOZZFJEB.js.map +1 -0
- package/dist/chunk-OYJXYJTE.js +2358 -0
- package/dist/chunk-OYJXYJTE.js.map +1 -0
- package/dist/chunk-PEZYBKZH.js +124 -0
- package/dist/chunk-PEZYBKZH.js.map +1 -0
- package/dist/chunk-QWWOBAYU.js +26 -0
- package/dist/chunk-QWWOBAYU.js.map +1 -0
- package/dist/chunk-RQYYYBQG.js +24 -0
- package/dist/chunk-RQYYYBQG.js.map +1 -0
- package/dist/chunk-T2WWAEKH.js +7591 -0
- package/dist/chunk-T2WWAEKH.js.map +1 -0
- package/dist/chunk-U6QSXTUS.js +7 -0
- package/dist/chunk-U6QSXTUS.js.map +1 -0
- package/dist/chunk-UWMOTOXA.js +93 -0
- package/dist/chunk-UWMOTOXA.js.map +1 -0
- package/dist/chunk-UZZD4MRJ.js +95 -0
- package/dist/chunk-UZZD4MRJ.js.map +1 -0
- package/dist/chunk-V5OLWE7F.js +88 -0
- package/dist/chunk-V5OLWE7F.js.map +1 -0
- package/dist/chunk-VCLMTMSO.js +23 -0
- package/dist/chunk-VCLMTMSO.js.map +1 -0
- package/dist/chunk-WSDQ2MRG.js +102 -0
- package/dist/chunk-WSDQ2MRG.js.map +1 -0
- package/dist/chunk-XDEEOTVK.js +93 -0
- package/dist/chunk-XDEEOTVK.js.map +1 -0
- package/dist/chunk-XQUQSNCA.js +117 -0
- package/dist/chunk-XQUQSNCA.js.map +1 -0
- package/dist/chunk-XVYZO2FG.js +14 -0
- package/dist/chunk-XVYZO2FG.js.map +1 -0
- package/dist/chunk-ZC4KNEOQ.js +50 -0
- package/dist/chunk-ZC4KNEOQ.js.map +1 -0
- package/dist/config-5ZPGISS6.js +13 -0
- package/dist/config-5ZPGISS6.js.map +1 -0
- package/dist/config-6HWSKHEU.js +9 -0
- package/dist/config-6HWSKHEU.js.map +1 -0
- package/dist/config-6TNFPYZF.js +9 -0
- package/dist/config-6TNFPYZF.js.map +1 -0
- package/dist/config-BHLXQ3OL.js +9 -0
- package/dist/config-BHLXQ3OL.js.map +1 -0
- package/dist/config-E7UOEWEP.js +9 -0
- package/dist/config-E7UOEWEP.js.map +1 -0
- package/dist/config-FNR6LJ5H.js +11 -0
- package/dist/config-FNR6LJ5H.js.map +1 -0
- package/dist/config-HIZHA5VD.js +13 -0
- package/dist/config-HIZHA5VD.js.map +1 -0
- package/dist/config-HNSDNQZH.js +9 -0
- package/dist/config-HNSDNQZH.js.map +1 -0
- package/dist/config-IXLFUSMQ.js +9 -0
- package/dist/config-IXLFUSMQ.js.map +1 -0
- package/dist/config-J3TM7NIS.js +9 -0
- package/dist/config-J3TM7NIS.js.map +1 -0
- package/dist/config-JXLZ4XEW.js +9 -0
- package/dist/config-JXLZ4XEW.js.map +1 -0
- package/dist/config-KQCEMLNZ.js +9 -0
- package/dist/config-KQCEMLNZ.js.map +1 -0
- package/dist/config-MOLWOSRG.js +9 -0
- package/dist/config-MOLWOSRG.js.map +1 -0
- package/dist/config-R3XJ5OW4.js +9 -0
- package/dist/config-R3XJ5OW4.js.map +1 -0
- package/dist/config-S47UDVRZ.js +13 -0
- package/dist/config-S47UDVRZ.js.map +1 -0
- package/dist/config-UKZ72IDO.js +13 -0
- package/dist/config-UKZ72IDO.js.map +1 -0
- package/dist/config-V7XI5UTG.js +9 -0
- package/dist/config-V7XI5UTG.js.map +1 -0
- package/dist/config-YLIX3ZBT.js +9 -0
- package/dist/config-YLIX3ZBT.js.map +1 -0
- package/dist/config-Z5JGDOKE.js +9 -0
- package/dist/config-Z5JGDOKE.js.map +1 -0
- package/dist/config-ZCZZAH5W.js +9 -0
- package/dist/config-ZCZZAH5W.js.map +1 -0
- package/dist/config-ZZGIWDUC.js +9 -0
- package/dist/config-ZZGIWDUC.js.map +1 -0
- package/dist/discord-2PWP2MGX.js +8 -0
- package/dist/discord-2PWP2MGX.js.map +1 -0
- package/dist/disk-C7TJNU2B.js +8 -0
- package/dist/disk-C7TJNU2B.js.map +1 -0
- package/dist/dropbox-L5DPYGKR.js +8 -0
- package/dist/dropbox-L5DPYGKR.js.map +1 -0
- package/dist/email-HASRFBKC.js +8 -0
- package/dist/email-HASRFBKC.js.map +1 -0
- package/dist/gcs-P5QMKTPR.js +10 -0
- package/dist/gcs-P5QMKTPR.js.map +1 -0
- package/dist/gdocs-IF2I35HZ.js +8 -0
- package/dist/gdocs-IF2I35HZ.js.map +1 -0
- package/dist/gdrive-TAETVCKP.js +8 -0
- package/dist/gdrive-TAETVCKP.js.map +1 -0
- package/dist/github-5E6GSCNZ.js +8 -0
- package/dist/github-5E6GSCNZ.js.map +1 -0
- package/dist/github_ci-2DSZI3Y7.js +8 -0
- package/dist/github_ci-2DSZI3Y7.js.map +1 -0
- package/dist/gmail-F5VYGKOT.js +8 -0
- package/dist/gmail-F5VYGKOT.js.map +1 -0
- package/dist/gsheets-BAO54CQ7.js +8 -0
- package/dist/gsheets-BAO54CQ7.js.map +1 -0
- package/dist/gslides-A62CEEMR.js +8 -0
- package/dist/gslides-A62CEEMR.js.map +1 -0
- package/dist/index.d.ts +1671 -0
- package/dist/index.js +3564 -0
- package/dist/index.js.map +1 -0
- package/dist/langfuse-YKBYRQLU.js +8 -0
- package/dist/langfuse-YKBYRQLU.js.map +1 -0
- package/dist/linear-WJDQ6JDE.js +8 -0
- package/dist/linear-WJDQ6JDE.js.map +1 -0
- package/dist/mongodb-MK4DVSIK.js +7 -0
- package/dist/mongodb-MK4DVSIK.js.map +1 -0
- package/dist/oci-KZ7XFZ2X.js +10 -0
- package/dist/oci-KZ7XFZ2X.js.map +1 -0
- package/dist/postgres-M2N2APFZ.js +7 -0
- package/dist/postgres-M2N2APFZ.js.map +1 -0
- package/dist/r2-X4DDNSAZ.js +10 -0
- package/dist/r2-X4DDNSAZ.js.map +1 -0
- package/dist/redis-NVCXUUIO.js +7 -0
- package/dist/redis-NVCXUUIO.js.map +1 -0
- package/dist/s3-HVAL7ZX3.js +8 -0
- package/dist/s3-HVAL7ZX3.js.map +1 -0
- package/dist/slack-GUQMDGLP.js +8 -0
- package/dist/slack-GUQMDGLP.js.map +1 -0
- package/dist/ssh-LY6WYVVD.js +9 -0
- package/dist/ssh-LY6WYVVD.js.map +1 -0
- package/dist/supabase-H3ZP4Y3W.js +10 -0
- package/dist/supabase-H3ZP4Y3W.js.map +1 -0
- package/dist/trello-WR6TEDYD.js +8 -0
- package/dist/trello-WR6TEDYD.js.map +1 -0
- package/package.json +118 -0
package/README.md
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<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">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
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.
|
|
6
|
+
|
|
7
|
+
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.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
const ws = new Workspace({
|
|
11
|
+
'/data': new RAMResource(),
|
|
12
|
+
'/s3': new S3Resource({ bucket: 'logs' }),
|
|
13
|
+
'/slack': new SlackResource({}),
|
|
14
|
+
'/github': new GitHubResource({}),
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
await ws.execute('grep alert /slack/general/*.json | wc -l')
|
|
18
|
+
await ws.execute('cat /github/mirage/README.md')
|
|
19
|
+
await ws.execute('cp /s3/report.csv /data/local.csv')
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## About
|
|
23
|
+
|
|
24
|
+
- **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.
|
|
25
|
+
- **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.
|
|
26
|
+
- **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.
|
|
27
|
+
- **Portable workspaces:** clone, snapshot, and version your environment. Move agent runs between machines without restarting or reconfiguring the system.
|
|
28
|
+
- **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.
|
|
29
|
+
- **Works with major agent application frameworks:** OpenAI Agents SDK, Vercel AI SDK (TypeScript), LangChain, Pydantic AI, CAMEL, and OpenHands.
|
|
30
|
+
- **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.
|
|
31
|
+
|
|
32
|
+
## Architecture
|
|
33
|
+
|
|
34
|
+
<p align="center">
|
|
35
|
+
<picture>
|
|
36
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/strukto-ai/mirage/main/assets/mirage-arch-dark.svg">
|
|
37
|
+
<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 & Cache → Infrastructure and Remote" width="900">
|
|
38
|
+
</picture>
|
|
39
|
+
</p>
|
|
40
|
+
|
|
41
|
+
## Installation
|
|
42
|
+
|
|
43
|
+
### Prerequisites
|
|
44
|
+
|
|
45
|
+
- **Python** ≥ 3.12 for the `mirage-ai` package and the `mirage` CLI
|
|
46
|
+
- **Node.js** ≥ 20 for the TypeScript SDK
|
|
47
|
+
- **macOS** or **Linux** (FUSE-based mounts require platform support)
|
|
48
|
+
|
|
49
|
+
### Python
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
uv add mirage-ai
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
This installs both the `mirage` library and the `mirage` CLI binary.
|
|
56
|
+
|
|
57
|
+
### TypeScript
|
|
58
|
+
|
|
59
|
+
Pick the package that matches your runtime:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npm install @struktoai/mirage-node # Node.js servers and CLIs
|
|
63
|
+
npm install @struktoai/mirage-browser # browser / edge runtimes
|
|
64
|
+
npm install @struktoai/mirage-core # runtime-agnostic primitives
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`@struktoai/mirage-node` and `@struktoai/mirage-browser` both pull in `@struktoai/mirage-core` automatically.
|
|
68
|
+
|
|
69
|
+
### CLI
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
curl -fsSL https://strukto.ai/install.sh | sh
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Or via your package manager of choice:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
brew install mirage
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
uvx mirage-ai
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npx @struktoai/mirage-cli
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Quickstart (Python)
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from mirage import Workspace
|
|
93
|
+
from mirage.resource.gdocs import GDocsConfig, GDocsResource
|
|
94
|
+
from mirage.resource.ram import RAMResource
|
|
95
|
+
from mirage.resource.s3 import S3Config, S3Resource
|
|
96
|
+
from mirage.resource.slack import SlackConfig, SlackResource
|
|
97
|
+
|
|
98
|
+
ws = Workspace({
|
|
99
|
+
"/data": RAMResource(),
|
|
100
|
+
"/s3": S3Resource(S3Config(bucket="my-bucket")),
|
|
101
|
+
"/slack": SlackResource(SlackConfig()),
|
|
102
|
+
"/docs": GDocsResource(GDocsConfig()),
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
await ws.execute("cp /s3/report.csv /data/report.csv")
|
|
106
|
+
await ws.execute("grep alert /s3/data/log.jsonl | wc -l")
|
|
107
|
+
|
|
108
|
+
ws.snapshot("demo.tar")
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Quickstart (TypeScript)
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
import {
|
|
115
|
+
Workspace,
|
|
116
|
+
RAMResource,
|
|
117
|
+
S3Resource,
|
|
118
|
+
SlackResource,
|
|
119
|
+
GDocsResource,
|
|
120
|
+
} from '@struktoai/mirage-browser'
|
|
121
|
+
|
|
122
|
+
const ws = new Workspace({
|
|
123
|
+
'/data': new RAMResource(),
|
|
124
|
+
'/s3': new S3Resource({ bucket: 'my-bucket' }),
|
|
125
|
+
'/slack': new SlackResource({}),
|
|
126
|
+
'/docs': new GDocsResource({}),
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
await ws.execute('cp /s3/report.csv /data/report.csv')
|
|
130
|
+
await ws.execute('grep alert /s3/data/log.jsonl | wc -l')
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Quickstart (CLI)
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
mirage workspace create ws.yaml --id demo
|
|
137
|
+
mirage execute --workspace_id demo --command "cp /s3/report.csv /data/report.csv"
|
|
138
|
+
mirage provision --workspace_id demo --command "cat /s3/data/large.jsonl"
|
|
139
|
+
mirage workspace snapshot demo demo.tar
|
|
140
|
+
mirage workspace load demo.tar --id demo-restored
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Agent Frameworks
|
|
144
|
+
|
|
145
|
+
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.
|
|
146
|
+
|
|
147
|
+
### OpenAI Agents SDK (Python)
|
|
148
|
+
|
|
149
|
+
The `MirageSandboxClient` plugs a `Workspace` into the OpenAI Agents SDK as a sandbox: bash commands the agent runs execute against your mounts.
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
from agents import Runner
|
|
153
|
+
from agents.run import RunConfig
|
|
154
|
+
from agents.sandbox import SandboxAgent, SandboxRunConfig
|
|
155
|
+
|
|
156
|
+
from mirage.agents.openai_agents import MirageSandboxClient
|
|
157
|
+
|
|
158
|
+
client = MirageSandboxClient(ws)
|
|
159
|
+
agent = SandboxAgent(
|
|
160
|
+
name="Mirage Sandbox Agent",
|
|
161
|
+
model="gpt-5.4-nano",
|
|
162
|
+
instructions=ws.file_prompt,
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
result = await Runner.run(
|
|
166
|
+
agent,
|
|
167
|
+
"Summarize /s3/data/report.parquet into /report.txt.",
|
|
168
|
+
run_config=RunConfig(sandbox=SandboxRunConfig(client=client)),
|
|
169
|
+
)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Vercel AI SDK (TypeScript)
|
|
173
|
+
|
|
174
|
+
`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.
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
import { generateText } from 'ai'
|
|
178
|
+
import { openai } from '@ai-sdk/openai'
|
|
179
|
+
import { mirageTools } from '@struktoai/mirage-agents/vercel'
|
|
180
|
+
import { buildSystemPrompt } from '@struktoai/mirage-agents/openai'
|
|
181
|
+
|
|
182
|
+
const { text } = await generateText({
|
|
183
|
+
model: openai('gpt-5.4-nano'),
|
|
184
|
+
system: buildSystemPrompt({ mountInfo: { '/': 'In-memory filesystem' } }),
|
|
185
|
+
prompt: "Use readFile to read /docs/paper.pdf, then describe what's in it.",
|
|
186
|
+
tools: mirageTools(ws),
|
|
187
|
+
})
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
LangChain, Pydantic AI, CAMEL, OpenHands, and Mastra adapters live alongside these.
|
|
191
|
+
|
|
192
|
+
## Cache
|
|
193
|
+
|
|
194
|
+
Every `Workspace` ships with a **two-layer cache** so repeated work against remote backends (S3, GDrive, Slack, …) hits local state instead of the network:
|
|
195
|
+
|
|
196
|
+
- **Index cache.** Listings and metadata. The first directory walk hits the API; subsequent ones serve from the index until TTL expires.
|
|
197
|
+
- **File cache.** Object bytes. The first read streams from origin; later pipelines read from cache.
|
|
198
|
+
- **Pluggable backends.** Each layer is a store with two built-ins:
|
|
199
|
+
- **RAM** (default): in-process, zero setup, 512 MB file cache and 10-minute index TTL. Best for single-process apps and notebooks.
|
|
200
|
+
- **Redis**: shared across workers, processes, and machines. Best for serverless, multi-replica services, or when you want cache state to survive restarts.
|
|
201
|
+
|
|
202
|
+
```ts
|
|
203
|
+
import { RedisFileCacheStore, RedisIndexCacheStore, Workspace } from 'mirage/node'
|
|
204
|
+
|
|
205
|
+
const ws = new Workspace(
|
|
206
|
+
{ '/s3': new S3Resource({ bucket: 'my-bucket' }) },
|
|
207
|
+
{
|
|
208
|
+
cache: new RedisFileCacheStore({ url: 'redis://localhost:6379/0', limit: '8GB' }),
|
|
209
|
+
index: new RedisIndexCacheStore({ url: 'redis://localhost:6379/0', ttl: 600 }),
|
|
210
|
+
},
|
|
211
|
+
)
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
```ts
|
|
215
|
+
import { S3Resource, Workspace } from 'mirage/node'
|
|
216
|
+
|
|
217
|
+
const ws = new Workspace({ '/s3': new S3Resource({ bucket: 'my-bucket' }) })
|
|
218
|
+
|
|
219
|
+
// 1. Index miss → S3 LIST. Listing stored in index cache.
|
|
220
|
+
await ws.execute('ls /s3/data/')
|
|
221
|
+
|
|
222
|
+
// 2. Index hit → 0 network calls.
|
|
223
|
+
await ws.execute('find /s3/data/ -name "*.jsonl"')
|
|
224
|
+
|
|
225
|
+
// 3. File miss → S3 GET. Bytes stored in file cache.
|
|
226
|
+
await ws.execute('cat /s3/data/log.jsonl | wc -l')
|
|
227
|
+
|
|
228
|
+
// 4. File hit → 0 network calls.
|
|
229
|
+
await ws.execute('grep alert /s3/data/log.jsonl')
|
|
230
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// src/resource/gdrive/config.ts
|
|
2
|
+
import { normalizeFields } from "@struktoai/mirage-core";
|
|
3
|
+
function redactGDriveConfig(config) {
|
|
4
|
+
return {
|
|
5
|
+
clientId: config.clientId,
|
|
6
|
+
clientSecret: "<REDACTED>",
|
|
7
|
+
refreshToken: "<REDACTED>"
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
function normalizeGDriveConfig(input) {
|
|
11
|
+
return normalizeFields(input, {
|
|
12
|
+
rename: {
|
|
13
|
+
client_id: "clientId",
|
|
14
|
+
client_secret: "clientSecret",
|
|
15
|
+
refresh_token: "refreshToken"
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export {
|
|
21
|
+
redactGDriveConfig,
|
|
22
|
+
normalizeGDriveConfig
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=chunk-35PVZRWU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/resource/gdrive/config.ts"],"sourcesContent":["// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========\n\nimport { normalizeFields } from '@struktoai/mirage-core'\n\nexport interface GDriveConfig {\n clientId: string\n clientSecret: string\n refreshToken: string\n refreshFn?: (refreshToken: string) => Promise<{ accessToken: string; expiresIn: number }>\n}\n\nexport interface GDriveConfigRedacted {\n clientId: string\n clientSecret: '<REDACTED>'\n refreshToken: '<REDACTED>'\n}\n\nexport function redactGDriveConfig(config: GDriveConfig): GDriveConfigRedacted {\n return {\n clientId: config.clientId,\n clientSecret: '<REDACTED>',\n refreshToken: '<REDACTED>',\n }\n}\n\nexport function normalizeGDriveConfig(input: Record<string, unknown>): GDriveConfig {\n return normalizeFields(input, {\n rename: {\n client_id: 'clientId',\n client_secret: 'clientSecret',\n refresh_token: 'refreshToken',\n },\n }) as unknown as GDriveConfig\n}\n"],"mappings":";AAcA,SAAS,uBAAuB;AAezB,SAAS,mBAAmB,QAA4C;AAC7E,SAAO;AAAA,IACL,UAAU,OAAO;AAAA,IACjB,cAAc;AAAA,IACd,cAAc;AAAA,EAChB;AACF;AAEO,SAAS,sBAAsB,OAA8C;AAClF,SAAO,gBAAgB,OAAO;AAAA,IAC5B,QAAQ;AAAA,MACN,WAAW;AAAA,MACX,eAAe;AAAA,MACf,eAAe;AAAA,IACjB;AAAA,EACF,CAAC;AACH;","names":[]}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import {
|
|
2
|
+
redactGSheetsConfig
|
|
3
|
+
} from "./chunk-I4RRGZGB.js";
|
|
4
|
+
|
|
5
|
+
// src/resource/gsheets/gsheets.ts
|
|
6
|
+
import {
|
|
7
|
+
GSHEETS_COMMANDS,
|
|
8
|
+
GSHEETS_PROMPT,
|
|
9
|
+
GSHEETS_VFS_OPS,
|
|
10
|
+
GSHEETS_WRITE_PROMPT,
|
|
11
|
+
GSheetsAccessor,
|
|
12
|
+
PathSpec,
|
|
13
|
+
RAMIndexCacheStore,
|
|
14
|
+
ResourceName,
|
|
15
|
+
TokenManager,
|
|
16
|
+
gsheetsRead,
|
|
17
|
+
gsheetsReaddir,
|
|
18
|
+
gsheetsResolveGlob,
|
|
19
|
+
gsheetsStat
|
|
20
|
+
} from "@struktoai/mirage-core";
|
|
21
|
+
var GSheetsResource = class {
|
|
22
|
+
kind = ResourceName.GSHEETS;
|
|
23
|
+
isRemote = true;
|
|
24
|
+
indexTtl = 86400;
|
|
25
|
+
prompt = GSHEETS_PROMPT;
|
|
26
|
+
writePrompt = GSHEETS_WRITE_PROMPT;
|
|
27
|
+
config;
|
|
28
|
+
accessor;
|
|
29
|
+
index;
|
|
30
|
+
constructor(config) {
|
|
31
|
+
this.config = config;
|
|
32
|
+
const tm = new TokenManager({
|
|
33
|
+
clientId: config.clientId,
|
|
34
|
+
clientSecret: config.clientSecret,
|
|
35
|
+
refreshToken: config.refreshToken
|
|
36
|
+
});
|
|
37
|
+
this.accessor = new GSheetsAccessor({ tokenManager: tm });
|
|
38
|
+
this.index = new RAMIndexCacheStore({ ttl: 86400 });
|
|
39
|
+
}
|
|
40
|
+
open() {
|
|
41
|
+
return Promise.resolve();
|
|
42
|
+
}
|
|
43
|
+
close() {
|
|
44
|
+
return Promise.resolve();
|
|
45
|
+
}
|
|
46
|
+
commands() {
|
|
47
|
+
return GSHEETS_COMMANDS;
|
|
48
|
+
}
|
|
49
|
+
ops() {
|
|
50
|
+
return GSHEETS_VFS_OPS;
|
|
51
|
+
}
|
|
52
|
+
readFile(p) {
|
|
53
|
+
return gsheetsRead(this.accessor, p, this.index);
|
|
54
|
+
}
|
|
55
|
+
readdir(p) {
|
|
56
|
+
return gsheetsReaddir(this.accessor, p, this.index);
|
|
57
|
+
}
|
|
58
|
+
stat(p) {
|
|
59
|
+
return gsheetsStat(this.accessor, p, this.index);
|
|
60
|
+
}
|
|
61
|
+
async fingerprint(p) {
|
|
62
|
+
const lookup = await this.index.get(p.original);
|
|
63
|
+
return lookup.entry?.remoteTime ?? null;
|
|
64
|
+
}
|
|
65
|
+
glob(paths, prefix = "") {
|
|
66
|
+
const effective = prefix !== "" ? paths.map(
|
|
67
|
+
(p) => p.prefix !== "" ? p : new PathSpec({
|
|
68
|
+
original: p.original,
|
|
69
|
+
directory: p.directory,
|
|
70
|
+
...p.pattern !== null ? { pattern: p.pattern } : {},
|
|
71
|
+
resolved: p.resolved,
|
|
72
|
+
prefix
|
|
73
|
+
})
|
|
74
|
+
) : paths;
|
|
75
|
+
return gsheetsResolveGlob(this.accessor, effective, this.index);
|
|
76
|
+
}
|
|
77
|
+
getState() {
|
|
78
|
+
return Promise.resolve({
|
|
79
|
+
type: this.kind,
|
|
80
|
+
needsOverride: true,
|
|
81
|
+
redactedFields: ["clientSecret", "refreshToken"],
|
|
82
|
+
config: redactGSheetsConfig(this.config)
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
loadState(_state) {
|
|
86
|
+
return Promise.resolve();
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export {
|
|
91
|
+
GSheetsResource
|
|
92
|
+
};
|
|
93
|
+
//# sourceMappingURL=chunk-3PBSL7BS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/resource/gsheets/gsheets.ts"],"sourcesContent":["// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========\n\nimport {\n type FileStat,\n GSHEETS_COMMANDS,\n GSHEETS_PROMPT,\n GSHEETS_VFS_OPS,\n GSHEETS_WRITE_PROMPT,\n GSheetsAccessor,\n type IndexCacheStore,\n PathSpec,\n RAMIndexCacheStore,\n type RegisteredCommand,\n type RegisteredOp,\n type Resource,\n ResourceName,\n TokenManager,\n gsheetsRead,\n gsheetsReaddir,\n gsheetsResolveGlob,\n gsheetsStat,\n} from '@struktoai/mirage-core'\nimport { redactGSheetsConfig, type GSheetsConfig, type GSheetsConfigRedacted } from './config.ts'\n\nexport interface GSheetsResourceState {\n type: string\n needsOverride: boolean\n redactedFields: readonly string[]\n config: GSheetsConfigRedacted\n}\n\nexport class GSheetsResource implements Resource {\n readonly kind: string = ResourceName.GSHEETS\n readonly isRemote: boolean = true\n readonly indexTtl: number = 86_400\n readonly prompt: string = GSHEETS_PROMPT\n readonly writePrompt: string = GSHEETS_WRITE_PROMPT\n readonly config: GSheetsConfig\n readonly accessor: GSheetsAccessor\n readonly index: IndexCacheStore\n\n constructor(config: GSheetsConfig) {\n this.config = config\n const tm = new TokenManager({\n clientId: config.clientId,\n clientSecret: config.clientSecret,\n refreshToken: config.refreshToken,\n })\n this.accessor = new GSheetsAccessor({ tokenManager: tm })\n this.index = new RAMIndexCacheStore({ ttl: 86_400 })\n }\n\n open(): Promise<void> {\n return Promise.resolve()\n }\n\n close(): Promise<void> {\n return Promise.resolve()\n }\n\n commands(): readonly RegisteredCommand[] {\n return GSHEETS_COMMANDS\n }\n\n ops(): readonly RegisteredOp[] {\n return GSHEETS_VFS_OPS\n }\n\n readFile(p: PathSpec): Promise<Uint8Array> {\n return gsheetsRead(this.accessor, p, this.index)\n }\n\n readdir(p: PathSpec): Promise<string[]> {\n return gsheetsReaddir(this.accessor, p, this.index)\n }\n\n stat(p: PathSpec): Promise<FileStat> {\n return gsheetsStat(this.accessor, p, this.index)\n }\n\n async fingerprint(p: PathSpec): Promise<string | null> {\n const lookup = await this.index.get(p.original)\n return lookup.entry?.remoteTime ?? null\n }\n\n glob(paths: readonly PathSpec[], prefix = ''): Promise<PathSpec[]> {\n const effective =\n prefix !== ''\n ? paths.map((p) =>\n p.prefix !== ''\n ? p\n : new PathSpec({\n original: p.original,\n directory: p.directory,\n ...(p.pattern !== null ? { pattern: p.pattern } : {}),\n resolved: p.resolved,\n prefix,\n }),\n )\n : paths\n return gsheetsResolveGlob(this.accessor, effective, this.index)\n }\n\n getState(): Promise<GSheetsResourceState> {\n return Promise.resolve({\n type: this.kind,\n needsOverride: true,\n redactedFields: ['clientSecret', 'refreshToken'],\n config: redactGSheetsConfig(this.config),\n })\n }\n\n loadState(_state: GSheetsResourceState): Promise<void> {\n return Promise.resolve()\n }\n}\n"],"mappings":";;;;;AAcA;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EAIA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAUA,IAAM,kBAAN,MAA0C;AAAA,EACtC,OAAe,aAAa;AAAA,EAC5B,WAAoB;AAAA,EACpB,WAAmB;AAAA,EACnB,SAAiB;AAAA,EACjB,cAAsB;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,QAAuB;AACjC,SAAK,SAAS;AACd,UAAM,KAAK,IAAI,aAAa;AAAA,MAC1B,UAAU,OAAO;AAAA,MACjB,cAAc,OAAO;AAAA,MACrB,cAAc,OAAO;AAAA,IACvB,CAAC;AACD,SAAK,WAAW,IAAI,gBAAgB,EAAE,cAAc,GAAG,CAAC;AACxD,SAAK,QAAQ,IAAI,mBAAmB,EAAE,KAAK,MAAO,CAAC;AAAA,EACrD;AAAA,EAEA,OAAsB;AACpB,WAAO,QAAQ,QAAQ;AAAA,EACzB;AAAA,EAEA,QAAuB;AACrB,WAAO,QAAQ,QAAQ;AAAA,EACzB;AAAA,EAEA,WAAyC;AACvC,WAAO;AAAA,EACT;AAAA,EAEA,MAA+B;AAC7B,WAAO;AAAA,EACT;AAAA,EAEA,SAAS,GAAkC;AACzC,WAAO,YAAY,KAAK,UAAU,GAAG,KAAK,KAAK;AAAA,EACjD;AAAA,EAEA,QAAQ,GAAgC;AACtC,WAAO,eAAe,KAAK,UAAU,GAAG,KAAK,KAAK;AAAA,EACpD;AAAA,EAEA,KAAK,GAAgC;AACnC,WAAO,YAAY,KAAK,UAAU,GAAG,KAAK,KAAK;AAAA,EACjD;AAAA,EAEA,MAAM,YAAY,GAAqC;AACrD,UAAM,SAAS,MAAM,KAAK,MAAM,IAAI,EAAE,QAAQ;AAC9C,WAAO,OAAO,OAAO,cAAc;AAAA,EACrC;AAAA,EAEA,KAAK,OAA4B,SAAS,IAAyB;AACjE,UAAM,YACJ,WAAW,KACP,MAAM;AAAA,MAAI,CAAC,MACT,EAAE,WAAW,KACT,IACA,IAAI,SAAS;AAAA,QACX,UAAU,EAAE;AAAA,QACZ,WAAW,EAAE;AAAA,QACb,GAAI,EAAE,YAAY,OAAO,EAAE,SAAS,EAAE,QAAQ,IAAI,CAAC;AAAA,QACnD,UAAU,EAAE;AAAA,QACZ;AAAA,MACF,CAAC;AAAA,IACP,IACA;AACN,WAAO,mBAAmB,KAAK,UAAU,WAAW,KAAK,KAAK;AAAA,EAChE;AAAA,EAEA,WAA0C;AACxC,WAAO,QAAQ,QAAQ;AAAA,MACrB,MAAM,KAAK;AAAA,MACX,eAAe;AAAA,MACf,gBAAgB,CAAC,gBAAgB,cAAc;AAAA,MAC/C,QAAQ,oBAAoB,KAAK,MAAM;AAAA,IACzC,CAAC;AAAA,EACH;AAAA,EAEA,UAAU,QAA6C;AACrD,WAAO,QAAQ,QAAQ;AAAA,EACzB;AACF;","names":[]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// src/resource/gdocs/config.ts
|
|
2
|
+
import { normalizeFields } from "@struktoai/mirage-core";
|
|
3
|
+
function redactGDocsConfig(config) {
|
|
4
|
+
return {
|
|
5
|
+
clientId: config.clientId,
|
|
6
|
+
clientSecret: "<REDACTED>",
|
|
7
|
+
refreshToken: "<REDACTED>"
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
function normalizeGDocsConfig(input) {
|
|
11
|
+
return normalizeFields(input, {
|
|
12
|
+
rename: {
|
|
13
|
+
client_id: "clientId",
|
|
14
|
+
client_secret: "clientSecret",
|
|
15
|
+
refresh_token: "refreshToken"
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export {
|
|
21
|
+
redactGDocsConfig,
|
|
22
|
+
normalizeGDocsConfig
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=chunk-3Y625AUP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/resource/gdocs/config.ts"],"sourcesContent":["// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========\n\nimport { normalizeFields } from '@struktoai/mirage-core'\n\nexport interface GDocsConfig {\n clientId: string\n clientSecret: string\n refreshToken: string\n refreshFn?: (refreshToken: string) => Promise<{ accessToken: string; expiresIn: number }>\n}\n\nexport interface GDocsConfigRedacted {\n clientId: string\n clientSecret: '<REDACTED>'\n refreshToken: '<REDACTED>'\n}\n\nexport function redactGDocsConfig(config: GDocsConfig): GDocsConfigRedacted {\n return {\n clientId: config.clientId,\n clientSecret: '<REDACTED>',\n refreshToken: '<REDACTED>',\n }\n}\n\nexport function normalizeGDocsConfig(input: Record<string, unknown>): GDocsConfig {\n return normalizeFields(input, {\n rename: {\n client_id: 'clientId',\n client_secret: 'clientSecret',\n refresh_token: 'refreshToken',\n },\n }) as unknown as GDocsConfig\n}\n"],"mappings":";AAcA,SAAS,uBAAuB;AAezB,SAAS,kBAAkB,QAA0C;AAC1E,SAAO;AAAA,IACL,UAAU,OAAO;AAAA,IACjB,cAAc;AAAA,IACd,cAAc;AAAA,EAChB;AACF;AAEO,SAAS,qBAAqB,OAA6C;AAChF,SAAO,gBAAgB,OAAO;AAAA,IAC5B,QAAQ;AAAA,MACN,WAAW;AAAA,MACX,eAAe;AAAA,MACf,eAAe;AAAA,IACjB;AAAA,EACF,CAAC;AACH;","names":[]}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import {
|
|
2
|
+
redactDropboxConfig
|
|
3
|
+
} from "./chunk-RQYYYBQG.js";
|
|
4
|
+
|
|
5
|
+
// src/resource/dropbox/dropbox.ts
|
|
6
|
+
import {
|
|
7
|
+
DROPBOX_COMMANDS,
|
|
8
|
+
DROPBOX_PROMPT,
|
|
9
|
+
DROPBOX_VFS_OPS,
|
|
10
|
+
DropboxAccessor,
|
|
11
|
+
DropboxTokenManager,
|
|
12
|
+
PathSpec,
|
|
13
|
+
RAMIndexCacheStore,
|
|
14
|
+
ResourceName,
|
|
15
|
+
dropboxRead,
|
|
16
|
+
dropboxReaddir,
|
|
17
|
+
dropboxResolveGlob,
|
|
18
|
+
dropboxStat
|
|
19
|
+
} from "@struktoai/mirage-core";
|
|
20
|
+
var DropboxResource = class {
|
|
21
|
+
kind = ResourceName.DROPBOX;
|
|
22
|
+
isRemote = true;
|
|
23
|
+
indexTtl = 86400;
|
|
24
|
+
prompt = DROPBOX_PROMPT;
|
|
25
|
+
config;
|
|
26
|
+
accessor;
|
|
27
|
+
index;
|
|
28
|
+
constructor(config) {
|
|
29
|
+
this.config = config;
|
|
30
|
+
const tm = new DropboxTokenManager({
|
|
31
|
+
clientId: config.clientId,
|
|
32
|
+
clientSecret: config.clientSecret,
|
|
33
|
+
refreshToken: config.refreshToken,
|
|
34
|
+
...config.refreshFn !== void 0 ? { refreshFn: config.refreshFn } : {}
|
|
35
|
+
});
|
|
36
|
+
this.accessor = new DropboxAccessor({ tokenManager: tm });
|
|
37
|
+
this.index = new RAMIndexCacheStore({ ttl: 86400 });
|
|
38
|
+
}
|
|
39
|
+
open() {
|
|
40
|
+
return Promise.resolve();
|
|
41
|
+
}
|
|
42
|
+
close() {
|
|
43
|
+
return Promise.resolve();
|
|
44
|
+
}
|
|
45
|
+
commands() {
|
|
46
|
+
return DROPBOX_COMMANDS;
|
|
47
|
+
}
|
|
48
|
+
ops() {
|
|
49
|
+
return DROPBOX_VFS_OPS;
|
|
50
|
+
}
|
|
51
|
+
readFile(p) {
|
|
52
|
+
return dropboxRead(this.accessor, p, this.index);
|
|
53
|
+
}
|
|
54
|
+
readdir(p) {
|
|
55
|
+
return dropboxReaddir(this.accessor, p, this.index);
|
|
56
|
+
}
|
|
57
|
+
stat(p) {
|
|
58
|
+
return dropboxStat(this.accessor, p, this.index);
|
|
59
|
+
}
|
|
60
|
+
async fingerprint(p) {
|
|
61
|
+
const lookup = await this.index.get(p.original);
|
|
62
|
+
return lookup.entry?.remoteTime ?? null;
|
|
63
|
+
}
|
|
64
|
+
glob(paths, prefix = "") {
|
|
65
|
+
const effective = prefix !== "" ? paths.map(
|
|
66
|
+
(p) => p.prefix !== "" ? p : new PathSpec({
|
|
67
|
+
original: p.original,
|
|
68
|
+
directory: p.directory,
|
|
69
|
+
...p.pattern !== null ? { pattern: p.pattern } : {},
|
|
70
|
+
resolved: p.resolved,
|
|
71
|
+
prefix
|
|
72
|
+
})
|
|
73
|
+
) : paths;
|
|
74
|
+
return dropboxResolveGlob(this.accessor, effective, this.index);
|
|
75
|
+
}
|
|
76
|
+
getState() {
|
|
77
|
+
return Promise.resolve({
|
|
78
|
+
type: this.kind,
|
|
79
|
+
needsOverride: true,
|
|
80
|
+
redactedFields: ["clientSecret", "refreshToken"],
|
|
81
|
+
config: redactDropboxConfig(this.config)
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
loadState(_state) {
|
|
85
|
+
return Promise.resolve();
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export {
|
|
90
|
+
DropboxResource
|
|
91
|
+
};
|
|
92
|
+
//# sourceMappingURL=chunk-5E6BULAK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/resource/dropbox/dropbox.ts"],"sourcesContent":["// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========\n\nimport {\n type FileStat,\n DROPBOX_COMMANDS,\n DROPBOX_PROMPT,\n DROPBOX_VFS_OPS,\n DropboxAccessor,\n DropboxTokenManager,\n type IndexCacheStore,\n PathSpec,\n RAMIndexCacheStore,\n type RegisteredCommand,\n type RegisteredOp,\n type Resource,\n ResourceName,\n dropboxRead,\n dropboxReaddir,\n dropboxResolveGlob,\n dropboxStat,\n} from '@struktoai/mirage-core'\nimport { redactDropboxConfig, type DropboxConfig, type DropboxConfigRedacted } from './config.ts'\n\nexport interface DropboxResourceState {\n type: string\n needsOverride: boolean\n redactedFields: readonly string[]\n config: DropboxConfigRedacted\n}\n\nexport class DropboxResource implements Resource {\n readonly kind: string = ResourceName.DROPBOX\n readonly isRemote: boolean = true\n readonly indexTtl: number = 86_400\n readonly prompt: string = DROPBOX_PROMPT\n readonly config: DropboxConfig\n readonly accessor: DropboxAccessor\n readonly index: IndexCacheStore\n\n constructor(config: DropboxConfig) {\n this.config = config\n const tm = new DropboxTokenManager({\n clientId: config.clientId,\n clientSecret: config.clientSecret,\n refreshToken: config.refreshToken,\n ...(config.refreshFn !== undefined ? { refreshFn: config.refreshFn } : {}),\n })\n this.accessor = new DropboxAccessor({ tokenManager: tm })\n this.index = new RAMIndexCacheStore({ ttl: 86_400 })\n }\n\n open(): Promise<void> {\n return Promise.resolve()\n }\n\n close(): Promise<void> {\n return Promise.resolve()\n }\n\n commands(): readonly RegisteredCommand[] {\n return DROPBOX_COMMANDS\n }\n\n ops(): readonly RegisteredOp[] {\n return DROPBOX_VFS_OPS\n }\n\n readFile(p: PathSpec): Promise<Uint8Array> {\n return dropboxRead(this.accessor, p, this.index)\n }\n\n readdir(p: PathSpec): Promise<string[]> {\n return dropboxReaddir(this.accessor, p, this.index)\n }\n\n stat(p: PathSpec): Promise<FileStat> {\n return dropboxStat(this.accessor, p, this.index)\n }\n\n async fingerprint(p: PathSpec): Promise<string | null> {\n const lookup = await this.index.get(p.original)\n return lookup.entry?.remoteTime ?? null\n }\n\n glob(paths: readonly PathSpec[], prefix = ''): Promise<PathSpec[]> {\n const effective =\n prefix !== ''\n ? paths.map((p) =>\n p.prefix !== ''\n ? p\n : new PathSpec({\n original: p.original,\n directory: p.directory,\n ...(p.pattern !== null ? { pattern: p.pattern } : {}),\n resolved: p.resolved,\n prefix,\n }),\n )\n : paths\n return dropboxResolveGlob(this.accessor, effective, this.index)\n }\n\n getState(): Promise<DropboxResourceState> {\n return Promise.resolve({\n type: this.kind,\n needsOverride: true,\n redactedFields: ['clientSecret', 'refreshToken'],\n config: redactDropboxConfig(this.config),\n })\n }\n\n loadState(_state: DropboxResourceState): Promise<void> {\n return Promise.resolve()\n }\n}\n"],"mappings":";;;;;AAcA;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EAIA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAUA,IAAM,kBAAN,MAA0C;AAAA,EACtC,OAAe,aAAa;AAAA,EAC5B,WAAoB;AAAA,EACpB,WAAmB;AAAA,EACnB,SAAiB;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,QAAuB;AACjC,SAAK,SAAS;AACd,UAAM,KAAK,IAAI,oBAAoB;AAAA,MACjC,UAAU,OAAO;AAAA,MACjB,cAAc,OAAO;AAAA,MACrB,cAAc,OAAO;AAAA,MACrB,GAAI,OAAO,cAAc,SAAY,EAAE,WAAW,OAAO,UAAU,IAAI,CAAC;AAAA,IAC1E,CAAC;AACD,SAAK,WAAW,IAAI,gBAAgB,EAAE,cAAc,GAAG,CAAC;AACxD,SAAK,QAAQ,IAAI,mBAAmB,EAAE,KAAK,MAAO,CAAC;AAAA,EACrD;AAAA,EAEA,OAAsB;AACpB,WAAO,QAAQ,QAAQ;AAAA,EACzB;AAAA,EAEA,QAAuB;AACrB,WAAO,QAAQ,QAAQ;AAAA,EACzB;AAAA,EAEA,WAAyC;AACvC,WAAO;AAAA,EACT;AAAA,EAEA,MAA+B;AAC7B,WAAO;AAAA,EACT;AAAA,EAEA,SAAS,GAAkC;AACzC,WAAO,YAAY,KAAK,UAAU,GAAG,KAAK,KAAK;AAAA,EACjD;AAAA,EAEA,QAAQ,GAAgC;AACtC,WAAO,eAAe,KAAK,UAAU,GAAG,KAAK,KAAK;AAAA,EACpD;AAAA,EAEA,KAAK,GAAgC;AACnC,WAAO,YAAY,KAAK,UAAU,GAAG,KAAK,KAAK;AAAA,EACjD;AAAA,EAEA,MAAM,YAAY,GAAqC;AACrD,UAAM,SAAS,MAAM,KAAK,MAAM,IAAI,EAAE,QAAQ;AAC9C,WAAO,OAAO,OAAO,cAAc;AAAA,EACrC;AAAA,EAEA,KAAK,OAA4B,SAAS,IAAyB;AACjE,UAAM,YACJ,WAAW,KACP,MAAM;AAAA,MAAI,CAAC,MACT,EAAE,WAAW,KACT,IACA,IAAI,SAAS;AAAA,QACX,UAAU,EAAE;AAAA,QACZ,WAAW,EAAE;AAAA,QACb,GAAI,EAAE,YAAY,OAAO,EAAE,SAAS,EAAE,QAAQ,IAAI,CAAC;AAAA,QACnD,UAAU,EAAE;AAAA,QACZ;AAAA,MACF,CAAC;AAAA,IACP,IACA;AACN,WAAO,mBAAmB,KAAK,UAAU,WAAW,KAAK,KAAK;AAAA,EAChE;AAAA,EAEA,WAA0C;AACxC,WAAO,QAAQ,QAAQ;AAAA,MACrB,MAAM,KAAK;AAAA,MACX,eAAe;AAAA,MACf,gBAAgB,CAAC,gBAAgB,cAAc;AAAA,MAC/C,QAAQ,oBAAoB,KAAK,MAAM;AAAA,IACzC,CAAC;AAAA,EACH;AAAA,EAEA,UAAU,QAA6C;AACrD,WAAO,QAAQ,QAAQ;AAAA,EACzB;AACF;","names":[]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// src/resource/gslides/config.ts
|
|
2
|
+
import { normalizeFields } from "@struktoai/mirage-core";
|
|
3
|
+
function redactGSlidesConfig(config) {
|
|
4
|
+
return {
|
|
5
|
+
clientId: config.clientId,
|
|
6
|
+
clientSecret: "<REDACTED>",
|
|
7
|
+
refreshToken: "<REDACTED>"
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
function normalizeGSlidesConfig(input) {
|
|
11
|
+
return normalizeFields(input, {
|
|
12
|
+
rename: {
|
|
13
|
+
client_id: "clientId",
|
|
14
|
+
client_secret: "clientSecret",
|
|
15
|
+
refresh_token: "refreshToken"
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export {
|
|
21
|
+
redactGSlidesConfig,
|
|
22
|
+
normalizeGSlidesConfig
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=chunk-5ITBZN55.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/resource/gslides/config.ts"],"sourcesContent":["// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========\n\nimport { normalizeFields } from '@struktoai/mirage-core'\n\nexport interface GSlidesConfig {\n clientId: string\n clientSecret: string\n refreshToken: string\n refreshFn?: (refreshToken: string) => Promise<{ accessToken: string; expiresIn: number }>\n}\n\nexport interface GSlidesConfigRedacted {\n clientId: string\n clientSecret: '<REDACTED>'\n refreshToken: '<REDACTED>'\n}\n\nexport function redactGSlidesConfig(config: GSlidesConfig): GSlidesConfigRedacted {\n return {\n clientId: config.clientId,\n clientSecret: '<REDACTED>',\n refreshToken: '<REDACTED>',\n }\n}\n\nexport function normalizeGSlidesConfig(input: Record<string, unknown>): GSlidesConfig {\n return normalizeFields(input, {\n rename: {\n client_id: 'clientId',\n client_secret: 'clientSecret',\n refresh_token: 'refreshToken',\n },\n }) as unknown as GSlidesConfig\n}\n"],"mappings":";AAcA,SAAS,uBAAuB;AAezB,SAAS,oBAAoB,QAA8C;AAChF,SAAO;AAAA,IACL,UAAU,OAAO;AAAA,IACjB,cAAc;AAAA,IACd,cAAc;AAAA,EAChB;AACF;AAEO,SAAS,uBAAuB,OAA+C;AACpF,SAAO,gBAAgB,OAAO;AAAA,IAC5B,QAAQ;AAAA,MACN,WAAW;AAAA,MACX,eAAe;AAAA,MACf,eAAe;AAAA,IACjB;AAAA,EACF,CAAC;AACH;","names":[]}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import {
|
|
2
|
+
redactBoxConfig
|
|
3
|
+
} from "./chunk-EKPH4MMD.js";
|
|
4
|
+
|
|
5
|
+
// src/resource/box/box.ts
|
|
6
|
+
import {
|
|
7
|
+
BOX_COMMANDS,
|
|
8
|
+
BOX_PROMPT,
|
|
9
|
+
BOX_VFS_OPS,
|
|
10
|
+
BoxAccessor,
|
|
11
|
+
BoxTokenManager,
|
|
12
|
+
PathSpec,
|
|
13
|
+
RAMIndexCacheStore,
|
|
14
|
+
ResourceName,
|
|
15
|
+
boxRead,
|
|
16
|
+
boxReaddir,
|
|
17
|
+
boxResolveGlob,
|
|
18
|
+
boxStat
|
|
19
|
+
} from "@struktoai/mirage-core";
|
|
20
|
+
var BoxResource = class {
|
|
21
|
+
kind = ResourceName.BOX;
|
|
22
|
+
isRemote = true;
|
|
23
|
+
indexTtl = 86400;
|
|
24
|
+
prompt = BOX_PROMPT;
|
|
25
|
+
config;
|
|
26
|
+
accessor;
|
|
27
|
+
index;
|
|
28
|
+
constructor(config) {
|
|
29
|
+
this.config = config;
|
|
30
|
+
const tm = new BoxTokenManager({
|
|
31
|
+
...config.clientId !== void 0 ? { clientId: config.clientId } : {},
|
|
32
|
+
...config.clientSecret !== void 0 ? { clientSecret: config.clientSecret } : {},
|
|
33
|
+
...config.refreshToken !== void 0 ? { refreshToken: config.refreshToken } : {},
|
|
34
|
+
...config.accessToken !== void 0 ? { accessToken: config.accessToken } : {},
|
|
35
|
+
...config.refreshFn !== void 0 ? { refreshFn: config.refreshFn } : {},
|
|
36
|
+
...config.onRefreshTokenRotated !== void 0 ? { onRefreshTokenRotated: config.onRefreshTokenRotated } : {}
|
|
37
|
+
});
|
|
38
|
+
this.accessor = new BoxAccessor({ tokenManager: tm });
|
|
39
|
+
this.index = new RAMIndexCacheStore({ ttl: 86400 });
|
|
40
|
+
}
|
|
41
|
+
open() {
|
|
42
|
+
return Promise.resolve();
|
|
43
|
+
}
|
|
44
|
+
close() {
|
|
45
|
+
return Promise.resolve();
|
|
46
|
+
}
|
|
47
|
+
commands() {
|
|
48
|
+
return BOX_COMMANDS;
|
|
49
|
+
}
|
|
50
|
+
ops() {
|
|
51
|
+
return BOX_VFS_OPS;
|
|
52
|
+
}
|
|
53
|
+
readFile(p) {
|
|
54
|
+
return boxRead(this.accessor, p, this.index);
|
|
55
|
+
}
|
|
56
|
+
readdir(p) {
|
|
57
|
+
return boxReaddir(this.accessor, p, this.index);
|
|
58
|
+
}
|
|
59
|
+
stat(p) {
|
|
60
|
+
return boxStat(this.accessor, p, this.index);
|
|
61
|
+
}
|
|
62
|
+
async fingerprint(p) {
|
|
63
|
+
const lookup = await this.index.get(p.original);
|
|
64
|
+
return lookup.entry?.remoteTime ?? null;
|
|
65
|
+
}
|
|
66
|
+
glob(paths, prefix = "") {
|
|
67
|
+
const effective = prefix !== "" ? paths.map(
|
|
68
|
+
(p) => p.prefix !== "" ? p : new PathSpec({
|
|
69
|
+
original: p.original,
|
|
70
|
+
directory: p.directory,
|
|
71
|
+
...p.pattern !== null ? { pattern: p.pattern } : {},
|
|
72
|
+
resolved: p.resolved,
|
|
73
|
+
prefix
|
|
74
|
+
})
|
|
75
|
+
) : paths;
|
|
76
|
+
return boxResolveGlob(this.accessor, effective, this.index);
|
|
77
|
+
}
|
|
78
|
+
getState() {
|
|
79
|
+
return Promise.resolve({
|
|
80
|
+
type: this.kind,
|
|
81
|
+
needsOverride: true,
|
|
82
|
+
redactedFields: ["clientSecret", "refreshToken", "accessToken"],
|
|
83
|
+
config: redactBoxConfig(this.config)
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
loadState(_state) {
|
|
87
|
+
return Promise.resolve();
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export {
|
|
92
|
+
BoxResource
|
|
93
|
+
};
|
|
94
|
+
//# sourceMappingURL=chunk-6M2NL363.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/resource/box/box.ts"],"sourcesContent":["// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========\n\nimport {\n BOX_COMMANDS,\n BOX_PROMPT,\n BOX_VFS_OPS,\n BoxAccessor,\n BoxTokenManager,\n type FileStat,\n type IndexCacheStore,\n PathSpec,\n RAMIndexCacheStore,\n type RegisteredCommand,\n type RegisteredOp,\n type Resource,\n ResourceName,\n boxRead,\n boxReaddir,\n boxResolveGlob,\n boxStat,\n} from '@struktoai/mirage-core'\nimport { redactBoxConfig, type BoxConfig, type BoxConfigRedacted } from './config.ts'\n\nexport interface BoxResourceState {\n type: string\n needsOverride: boolean\n redactedFields: readonly string[]\n config: BoxConfigRedacted\n}\n\nexport class BoxResource implements Resource {\n readonly kind: string = ResourceName.BOX\n readonly isRemote: boolean = true\n readonly indexTtl: number = 86_400\n readonly prompt: string = BOX_PROMPT\n readonly config: BoxConfig\n readonly accessor: BoxAccessor\n readonly index: IndexCacheStore\n\n constructor(config: BoxConfig) {\n this.config = config\n const tm = new BoxTokenManager({\n ...(config.clientId !== undefined ? { clientId: config.clientId } : {}),\n ...(config.clientSecret !== undefined ? { clientSecret: config.clientSecret } : {}),\n ...(config.refreshToken !== undefined ? { refreshToken: config.refreshToken } : {}),\n ...(config.accessToken !== undefined ? { accessToken: config.accessToken } : {}),\n ...(config.refreshFn !== undefined ? { refreshFn: config.refreshFn } : {}),\n ...(config.onRefreshTokenRotated !== undefined\n ? { onRefreshTokenRotated: config.onRefreshTokenRotated }\n : {}),\n })\n this.accessor = new BoxAccessor({ tokenManager: tm })\n this.index = new RAMIndexCacheStore({ ttl: 86_400 })\n }\n\n open(): Promise<void> {\n return Promise.resolve()\n }\n\n close(): Promise<void> {\n return Promise.resolve()\n }\n\n commands(): readonly RegisteredCommand[] {\n return BOX_COMMANDS\n }\n\n ops(): readonly RegisteredOp[] {\n return BOX_VFS_OPS\n }\n\n readFile(p: PathSpec): Promise<Uint8Array> {\n return boxRead(this.accessor, p, this.index)\n }\n\n readdir(p: PathSpec): Promise<string[]> {\n return boxReaddir(this.accessor, p, this.index)\n }\n\n stat(p: PathSpec): Promise<FileStat> {\n return boxStat(this.accessor, p, this.index)\n }\n\n async fingerprint(p: PathSpec): Promise<string | null> {\n const lookup = await this.index.get(p.original)\n return lookup.entry?.remoteTime ?? null\n }\n\n glob(paths: readonly PathSpec[], prefix = ''): Promise<PathSpec[]> {\n const effective =\n prefix !== ''\n ? paths.map((p) =>\n p.prefix !== ''\n ? p\n : new PathSpec({\n original: p.original,\n directory: p.directory,\n ...(p.pattern !== null ? { pattern: p.pattern } : {}),\n resolved: p.resolved,\n prefix,\n }),\n )\n : paths\n return boxResolveGlob(this.accessor, effective, this.index)\n }\n\n getState(): Promise<BoxResourceState> {\n return Promise.resolve({\n type: this.kind,\n needsOverride: true,\n redactedFields: ['clientSecret', 'refreshToken', 'accessToken'],\n config: redactBoxConfig(this.config),\n })\n }\n\n loadState(_state: BoxResourceState): Promise<void> {\n return Promise.resolve()\n }\n}\n"],"mappings":";;;;;AAcA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAGA;AAAA,EACA;AAAA,EAIA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAUA,IAAM,cAAN,MAAsC;AAAA,EAClC,OAAe,aAAa;AAAA,EAC5B,WAAoB;AAAA,EACpB,WAAmB;AAAA,EACnB,SAAiB;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,QAAmB;AAC7B,SAAK,SAAS;AACd,UAAM,KAAK,IAAI,gBAAgB;AAAA,MAC7B,GAAI,OAAO,aAAa,SAAY,EAAE,UAAU,OAAO,SAAS,IAAI,CAAC;AAAA,MACrE,GAAI,OAAO,iBAAiB,SAAY,EAAE,cAAc,OAAO,aAAa,IAAI,CAAC;AAAA,MACjF,GAAI,OAAO,iBAAiB,SAAY,EAAE,cAAc,OAAO,aAAa,IAAI,CAAC;AAAA,MACjF,GAAI,OAAO,gBAAgB,SAAY,EAAE,aAAa,OAAO,YAAY,IAAI,CAAC;AAAA,MAC9E,GAAI,OAAO,cAAc,SAAY,EAAE,WAAW,OAAO,UAAU,IAAI,CAAC;AAAA,MACxE,GAAI,OAAO,0BAA0B,SACjC,EAAE,uBAAuB,OAAO,sBAAsB,IACtD,CAAC;AAAA,IACP,CAAC;AACD,SAAK,WAAW,IAAI,YAAY,EAAE,cAAc,GAAG,CAAC;AACpD,SAAK,QAAQ,IAAI,mBAAmB,EAAE,KAAK,MAAO,CAAC;AAAA,EACrD;AAAA,EAEA,OAAsB;AACpB,WAAO,QAAQ,QAAQ;AAAA,EACzB;AAAA,EAEA,QAAuB;AACrB,WAAO,QAAQ,QAAQ;AAAA,EACzB;AAAA,EAEA,WAAyC;AACvC,WAAO;AAAA,EACT;AAAA,EAEA,MAA+B;AAC7B,WAAO;AAAA,EACT;AAAA,EAEA,SAAS,GAAkC;AACzC,WAAO,QAAQ,KAAK,UAAU,GAAG,KAAK,KAAK;AAAA,EAC7C;AAAA,EAEA,QAAQ,GAAgC;AACtC,WAAO,WAAW,KAAK,UAAU,GAAG,KAAK,KAAK;AAAA,EAChD;AAAA,EAEA,KAAK,GAAgC;AACnC,WAAO,QAAQ,KAAK,UAAU,GAAG,KAAK,KAAK;AAAA,EAC7C;AAAA,EAEA,MAAM,YAAY,GAAqC;AACrD,UAAM,SAAS,MAAM,KAAK,MAAM,IAAI,EAAE,QAAQ;AAC9C,WAAO,OAAO,OAAO,cAAc;AAAA,EACrC;AAAA,EAEA,KAAK,OAA4B,SAAS,IAAyB;AACjE,UAAM,YACJ,WAAW,KACP,MAAM;AAAA,MAAI,CAAC,MACT,EAAE,WAAW,KACT,IACA,IAAI,SAAS;AAAA,QACX,UAAU,EAAE;AAAA,QACZ,WAAW,EAAE;AAAA,QACb,GAAI,EAAE,YAAY,OAAO,EAAE,SAAS,EAAE,QAAQ,IAAI,CAAC;AAAA,QACnD,UAAU,EAAE;AAAA,QACZ;AAAA,MACF,CAAC;AAAA,IACP,IACA;AACN,WAAO,eAAe,KAAK,UAAU,WAAW,KAAK,KAAK;AAAA,EAC5D;AAAA,EAEA,WAAsC;AACpC,WAAO,QAAQ,QAAQ;AAAA,MACrB,MAAM,KAAK;AAAA,MACX,eAAe;AAAA,MACf,gBAAgB,CAAC,gBAAgB,gBAAgB,aAAa;AAAA,MAC9D,QAAQ,gBAAgB,KAAK,MAAM;AAAA,IACrC,CAAC;AAAA,EACH;AAAA,EAEA,UAAU,QAAyC;AACjD,WAAO,QAAQ,QAAQ;AAAA,EACzB;AACF;","names":[]}
|