@struktoai/mirage-browser 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.
Files changed (129) hide show
  1. package/README.md +230 -0
  2. package/dist/box-Y2SJWAAO.js +8 -0
  3. package/dist/box-Y2SJWAAO.js.map +1 -0
  4. package/dist/chunk-27UVUTJH.js +126 -0
  5. package/dist/chunk-27UVUTJH.js.map +1 -0
  6. package/dist/chunk-33SBWNB4.js +103 -0
  7. package/dist/chunk-33SBWNB4.js.map +1 -0
  8. package/dist/chunk-3PWPFOPS.js +88 -0
  9. package/dist/chunk-3PWPFOPS.js.map +1 -0
  10. package/dist/chunk-5Q5GJUAF.js +88 -0
  11. package/dist/chunk-5Q5GJUAF.js.map +1 -0
  12. package/dist/chunk-7GZXXXAS.js +24 -0
  13. package/dist/chunk-7GZXXXAS.js.map +1 -0
  14. package/dist/chunk-B4SYG2FD.js +24 -0
  15. package/dist/chunk-B4SYG2FD.js.map +1 -0
  16. package/dist/chunk-BIZONEJC.js +24 -0
  17. package/dist/chunk-BIZONEJC.js.map +1 -0
  18. package/dist/chunk-CQJTW45B.js +92 -0
  19. package/dist/chunk-CQJTW45B.js.map +1 -0
  20. package/dist/chunk-CZOTICOC.js +93 -0
  21. package/dist/chunk-CZOTICOC.js.map +1 -0
  22. package/dist/chunk-DDM2Z7YA.js +94 -0
  23. package/dist/chunk-DDM2Z7YA.js.map +1 -0
  24. package/dist/chunk-DPC7QRYO.js +99 -0
  25. package/dist/chunk-DPC7QRYO.js.map +1 -0
  26. package/dist/chunk-FL7YLP7D.js +107 -0
  27. package/dist/chunk-FL7YLP7D.js.map +1 -0
  28. package/dist/chunk-GFWWDQUZ.js +24 -0
  29. package/dist/chunk-GFWWDQUZ.js.map +1 -0
  30. package/dist/chunk-LG6GVNOL.js +94 -0
  31. package/dist/chunk-LG6GVNOL.js.map +1 -0
  32. package/dist/chunk-LSSB3AEW.js +94 -0
  33. package/dist/chunk-LSSB3AEW.js.map +1 -0
  34. package/dist/chunk-LUDXUYIA.js +89 -0
  35. package/dist/chunk-LUDXUYIA.js.map +1 -0
  36. package/dist/chunk-LZRPA2P7.js +99 -0
  37. package/dist/chunk-LZRPA2P7.js.map +1 -0
  38. package/dist/chunk-ML57VOCK.js +7590 -0
  39. package/dist/chunk-ML57VOCK.js.map +1 -0
  40. package/dist/chunk-MSNVGH6T.js +92 -0
  41. package/dist/chunk-MSNVGH6T.js.map +1 -0
  42. package/dist/chunk-NBWTZXH2.js +27 -0
  43. package/dist/chunk-NBWTZXH2.js.map +1 -0
  44. package/dist/chunk-ONQ5JGPR.js +96 -0
  45. package/dist/chunk-ONQ5JGPR.js.map +1 -0
  46. package/dist/chunk-OPROOV6J.js +24 -0
  47. package/dist/chunk-OPROOV6J.js.map +1 -0
  48. package/dist/chunk-QARIHW3I.js +23 -0
  49. package/dist/chunk-QARIHW3I.js.map +1 -0
  50. package/dist/chunk-QYFCHCGX.js +144 -0
  51. package/dist/chunk-QYFCHCGX.js.map +1 -0
  52. package/dist/chunk-SQQI4A6Y.js +94 -0
  53. package/dist/chunk-SQQI4A6Y.js.map +1 -0
  54. package/dist/chunk-UFXEZ56G.js +79 -0
  55. package/dist/chunk-UFXEZ56G.js.map +1 -0
  56. package/dist/chunk-UW3D2AF6.js +94 -0
  57. package/dist/chunk-UW3D2AF6.js.map +1 -0
  58. package/dist/chunk-UZWJ462U.js +93 -0
  59. package/dist/chunk-UZWJ462U.js.map +1 -0
  60. package/dist/chunk-VLFE4FGD.js +178 -0
  61. package/dist/chunk-VLFE4FGD.js.map +1 -0
  62. package/dist/chunk-XIURBEVZ.js +24 -0
  63. package/dist/chunk-XIURBEVZ.js.map +1 -0
  64. package/dist/chunk-ZJ6ROCTP.js +114 -0
  65. package/dist/chunk-ZJ6ROCTP.js.map +1 -0
  66. package/dist/config-4FABMWVK.js +9 -0
  67. package/dist/config-4FABMWVK.js.map +1 -0
  68. package/dist/config-DGIUMGBB.js +9 -0
  69. package/dist/config-DGIUMGBB.js.map +1 -0
  70. package/dist/config-G3TTNXLY.js +9 -0
  71. package/dist/config-G3TTNXLY.js.map +1 -0
  72. package/dist/config-GPCEEKCB.js +9 -0
  73. package/dist/config-GPCEEKCB.js.map +1 -0
  74. package/dist/config-KQ5VR2KZ.js +9 -0
  75. package/dist/config-KQ5VR2KZ.js.map +1 -0
  76. package/dist/config-LPMMVXLS.js +9 -0
  77. package/dist/config-LPMMVXLS.js.map +1 -0
  78. package/dist/config-U4UI4OKA.js +9 -0
  79. package/dist/config-U4UI4OKA.js.map +1 -0
  80. package/dist/config-VZGK63Z5.js +9 -0
  81. package/dist/config-VZGK63Z5.js.map +1 -0
  82. package/dist/discord-RG6URXXS.js +7 -0
  83. package/dist/discord-RG6URXXS.js.map +1 -0
  84. package/dist/dropbox-P7SOL7GN.js +8 -0
  85. package/dist/dropbox-P7SOL7GN.js.map +1 -0
  86. package/dist/gcs-2QHB4CBT.js +8 -0
  87. package/dist/gcs-2QHB4CBT.js.map +1 -0
  88. package/dist/gdocs-JNZTOZ33.js +8 -0
  89. package/dist/gdocs-JNZTOZ33.js.map +1 -0
  90. package/dist/gdrive-6MEIVN2F.js +8 -0
  91. package/dist/gdrive-6MEIVN2F.js.map +1 -0
  92. package/dist/github-M7WODJR2.js +7 -0
  93. package/dist/github-M7WODJR2.js.map +1 -0
  94. package/dist/github_ci-4XELEFSZ.js +8 -0
  95. package/dist/github_ci-4XELEFSZ.js.map +1 -0
  96. package/dist/gmail-AO6A3URH.js +8 -0
  97. package/dist/gmail-AO6A3URH.js.map +1 -0
  98. package/dist/gsheets-RFOKXMOJ.js +8 -0
  99. package/dist/gsheets-RFOKXMOJ.js.map +1 -0
  100. package/dist/gslides-GTVZPLLB.js +8 -0
  101. package/dist/gslides-GTVZPLLB.js.map +1 -0
  102. package/dist/index.d.ts +1127 -0
  103. package/dist/index.js +743 -0
  104. package/dist/index.js.map +1 -0
  105. package/dist/langfuse-CDOLELMB.js +7 -0
  106. package/dist/langfuse-CDOLELMB.js.map +1 -0
  107. package/dist/linear-SXOQGG6B.js +7 -0
  108. package/dist/linear-SXOQGG6B.js.map +1 -0
  109. package/dist/mongodb-HA7FAKDJ.js +7 -0
  110. package/dist/mongodb-HA7FAKDJ.js.map +1 -0
  111. package/dist/notion-ANZNMM3L.js +7 -0
  112. package/dist/notion-ANZNMM3L.js.map +1 -0
  113. package/dist/oci-ML5ZRVZ2.js +8 -0
  114. package/dist/oci-ML5ZRVZ2.js.map +1 -0
  115. package/dist/opfs-57XFMWWE.js +7 -0
  116. package/dist/opfs-57XFMWWE.js.map +1 -0
  117. package/dist/postgres-CK4HWZSL.js +7 -0
  118. package/dist/postgres-CK4HWZSL.js.map +1 -0
  119. package/dist/r2-56O4Q2J4.js +8 -0
  120. package/dist/r2-56O4Q2J4.js.map +1 -0
  121. package/dist/s3-A4XFE6QV.js +9 -0
  122. package/dist/s3-A4XFE6QV.js.map +1 -0
  123. package/dist/slack-QA7H7WLM.js +7 -0
  124. package/dist/slack-QA7H7WLM.js.map +1 -0
  125. package/dist/supabase-NNK2RWG3.js +8 -0
  126. package/dist/supabase-NNK2RWG3.js.map +1 -0
  127. package/dist/trello-H6PZT2IT.js +7 -0
  128. package/dist/trello-H6PZT2IT.js.map +1 -0
  129. package/package.json +74 -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 &amp; 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,8 @@
1
+ import {
2
+ BoxResource
3
+ } from "./chunk-DDM2Z7YA.js";
4
+ import "./chunk-NBWTZXH2.js";
5
+ export {
6
+ BoxResource
7
+ };
8
+ //# sourceMappingURL=box-Y2SJWAAO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,126 @@
1
+ // src/resource/mongodb/mongodb.ts
2
+ import {
3
+ MONGODB_COMMANDS,
4
+ MONGODB_OPS,
5
+ MONGODB_PROMPT,
6
+ MongoDBAccessor,
7
+ mongoRead,
8
+ mongoReaddir,
9
+ mongoStat,
10
+ PathSpec,
11
+ RAMIndexCacheStore,
12
+ resolveMongoDBConfig,
13
+ resolveMongoGlob,
14
+ ResourceName
15
+ } from "@struktoai/mirage-core";
16
+
17
+ // src/resource/mongodb/http_driver.ts
18
+ var HttpMongoDriver = class {
19
+ endpoint;
20
+ fetchImpl;
21
+ headers;
22
+ constructor(options) {
23
+ this.endpoint = options.endpoint;
24
+ this.fetchImpl = options.fetchImpl ?? fetch.bind(globalThis);
25
+ this.headers = options.headers ?? {};
26
+ }
27
+ async post(req) {
28
+ const r = await this.fetchImpl(this.endpoint, {
29
+ method: "POST",
30
+ headers: { "Content-Type": "application/json", ...this.headers },
31
+ body: JSON.stringify(req)
32
+ });
33
+ if (!r.ok) {
34
+ const body = await r.text().catch(() => "");
35
+ throw new Error(`mongo proxy ${req.op} \u2192 ${String(r.status)} ${body}`);
36
+ }
37
+ return await r.json();
38
+ }
39
+ listDatabases() {
40
+ return this.post({ op: "listDatabases" });
41
+ }
42
+ listCollections(database) {
43
+ return this.post({ op: "listCollections", database });
44
+ }
45
+ async findDocuments(database, collection, filter = {}, options = {}) {
46
+ return this.post({
47
+ op: "findDocuments",
48
+ database,
49
+ collection,
50
+ filter,
51
+ options
52
+ });
53
+ }
54
+ countDocuments(database, collection, filter = {}) {
55
+ return this.post({ op: "countDocuments", database, collection, filter });
56
+ }
57
+ listIndexes(database, collection) {
58
+ return this.post({
59
+ op: "listIndexes",
60
+ database,
61
+ collection
62
+ });
63
+ }
64
+ close() {
65
+ return Promise.resolve();
66
+ }
67
+ };
68
+
69
+ // src/resource/mongodb/mongodb.ts
70
+ var MongoDBResource = class {
71
+ kind = ResourceName.MONGODB;
72
+ isRemote = true;
73
+ indexTtl = 0;
74
+ prompt;
75
+ config;
76
+ driver;
77
+ accessor;
78
+ index;
79
+ constructor(options) {
80
+ const { config, prefix, driver, endpoint } = "config" in options ? options : { config: options, prefix: void 0, driver: void 0, endpoint: void 0 };
81
+ this.config = resolveMongoDBConfig(config);
82
+ this.driver = driver ?? new HttpMongoDriver({ endpoint: endpoint ?? this.config.uri });
83
+ this.accessor = new MongoDBAccessor(this.driver, this.config);
84
+ this.index = new RAMIndexCacheStore({ ttl: this.indexTtl });
85
+ this.prompt = MONGODB_PROMPT.replace("{prefix}", prefix ?? "");
86
+ }
87
+ open() {
88
+ return Promise.resolve();
89
+ }
90
+ async close() {
91
+ await this.driver.close();
92
+ }
93
+ ops() {
94
+ return MONGODB_OPS;
95
+ }
96
+ commands() {
97
+ return MONGODB_COMMANDS;
98
+ }
99
+ readFile(p) {
100
+ return mongoRead(this.accessor, p, this.index);
101
+ }
102
+ readdir(p) {
103
+ return mongoReaddir(this.accessor, p, this.index);
104
+ }
105
+ stat(p) {
106
+ return mongoStat(this.accessor, p, this.index);
107
+ }
108
+ glob(paths, prefix = "") {
109
+ const effective = prefix !== "" ? paths.map(
110
+ (p) => p.prefix !== "" ? p : new PathSpec({
111
+ original: p.original,
112
+ directory: p.directory,
113
+ ...p.pattern !== null ? { pattern: p.pattern } : {},
114
+ resolved: p.resolved,
115
+ prefix
116
+ })
117
+ ) : paths;
118
+ return resolveMongoGlob(this.accessor, effective, this.index);
119
+ }
120
+ };
121
+
122
+ export {
123
+ HttpMongoDriver,
124
+ MongoDBResource
125
+ };
126
+ //# sourceMappingURL=chunk-27UVUTJH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/resource/mongodb/mongodb.ts","../src/resource/mongodb/http_driver.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 type IndexCacheStore,\n MONGODB_COMMANDS,\n MONGODB_OPS,\n MONGODB_PROMPT,\n MongoDBAccessor,\n type MongoDBConfig,\n type MongoDBConfigResolved,\n type MongoDriver,\n mongoRead,\n mongoReaddir,\n mongoStat,\n PathSpec,\n RAMIndexCacheStore,\n type RegisteredCommand,\n type RegisteredOp,\n type Resource,\n resolveMongoDBConfig,\n resolveMongoGlob,\n ResourceName,\n} from '@struktoai/mirage-core'\nimport { HttpMongoDriver } from './http_driver.ts'\n\nexport interface MongoDBResourceOptions {\n config: MongoDBConfig\n prefix?: string\n driver?: MongoDriver\n endpoint?: string\n}\n\nexport class MongoDBResource implements Resource {\n readonly kind: string = ResourceName.MONGODB\n readonly isRemote: boolean = true\n readonly indexTtl: number = 0\n readonly prompt: string\n readonly config: MongoDBConfigResolved\n readonly driver: MongoDriver\n readonly accessor: MongoDBAccessor\n readonly index: IndexCacheStore\n\n constructor(options: MongoDBResourceOptions | MongoDBConfig) {\n const { config, prefix, driver, endpoint } =\n 'config' in options\n ? options\n : { config: options, prefix: undefined, driver: undefined, endpoint: undefined }\n this.config = resolveMongoDBConfig(config)\n this.driver = driver ?? new HttpMongoDriver({ endpoint: endpoint ?? this.config.uri })\n this.accessor = new MongoDBAccessor(this.driver, this.config)\n this.index = new RAMIndexCacheStore({ ttl: this.indexTtl })\n this.prompt = MONGODB_PROMPT.replace('{prefix}', prefix ?? '')\n }\n\n open(): Promise<void> {\n return Promise.resolve()\n }\n\n async close(): Promise<void> {\n await this.driver.close()\n }\n\n ops(): readonly RegisteredOp[] {\n return MONGODB_OPS\n }\n\n commands(): readonly RegisteredCommand[] {\n return MONGODB_COMMANDS\n }\n\n readFile(p: PathSpec): Promise<Uint8Array> {\n return mongoRead(this.accessor, p, this.index)\n }\n\n readdir(p: PathSpec): Promise<string[]> {\n return mongoReaddir(this.accessor, p, this.index)\n }\n\n stat(p: PathSpec): Promise<FileStat> {\n return mongoStat(this.accessor, p, this.index)\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 resolveMongoGlob(this.accessor, effective, this.index)\n }\n}\n","// ========= 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 type { MongoDriver, MongoFindOptions } from '@struktoai/mirage-core'\n\nexport interface HttpMongoDriverOptions {\n endpoint: string\n fetchImpl?: typeof fetch\n headers?: Record<string, string>\n}\n\ninterface MongoProxyRequest {\n op: 'listDatabases' | 'listCollections' | 'findDocuments' | 'countDocuments' | 'listIndexes'\n database?: string\n collection?: string\n filter?: Record<string, unknown>\n options?: MongoFindOptions\n}\n\nexport class HttpMongoDriver implements MongoDriver {\n readonly endpoint: string\n private readonly fetchImpl: typeof fetch\n private readonly headers: Record<string, string>\n\n constructor(options: HttpMongoDriverOptions) {\n this.endpoint = options.endpoint\n this.fetchImpl = options.fetchImpl ?? fetch.bind(globalThis)\n this.headers = options.headers ?? {}\n }\n\n private async post<T>(req: MongoProxyRequest): Promise<T> {\n const r = await this.fetchImpl(this.endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...this.headers },\n body: JSON.stringify(req),\n })\n if (!r.ok) {\n const body = await r.text().catch(() => '')\n throw new Error(`mongo proxy ${req.op} → ${String(r.status)} ${body}`)\n }\n return (await r.json()) as T\n }\n\n listDatabases(): Promise<string[]> {\n return this.post<string[]>({ op: 'listDatabases' })\n }\n\n listCollections(database: string): Promise<string[]> {\n return this.post<string[]>({ op: 'listCollections', database })\n }\n\n async findDocuments<T = Record<string, unknown>>(\n database: string,\n collection: string,\n filter: Record<string, unknown> = {},\n options: MongoFindOptions = {},\n ): Promise<T[]> {\n return this.post<T[]>({\n op: 'findDocuments',\n database,\n collection,\n filter,\n options,\n })\n }\n\n countDocuments(\n database: string,\n collection: string,\n filter: Record<string, unknown> = {},\n ): Promise<number> {\n return this.post<number>({ op: 'countDocuments', database, collection, filter })\n }\n\n listIndexes(database: string, collection: string): Promise<Record<string, unknown>[]> {\n return this.post<Record<string, unknown>[]>({\n op: 'listIndexes',\n database,\n collection,\n })\n }\n\n close(): Promise<void> {\n return Promise.resolve()\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,103 @@
1
+ // src/resource/linear/linear.ts
2
+ import {
3
+ HttpLinearTransport,
4
+ LINEAR_COMMANDS,
5
+ LINEAR_PROMPT,
6
+ LINEAR_VFS_OPS,
7
+ LINEAR_WRITE_PROMPT,
8
+ LinearAccessor,
9
+ linearRead,
10
+ linearReaddir,
11
+ linearStat,
12
+ PathSpec,
13
+ RAMIndexCacheStore,
14
+ ResourceName,
15
+ resolveLinearGlob
16
+ } from "@struktoai/mirage-core";
17
+
18
+ // src/resource/linear/config.ts
19
+ function redactLinearConfig(config) {
20
+ const out = { apiKey: "<REDACTED>" };
21
+ if (config.workspace !== void 0) out.workspace = config.workspace;
22
+ if (config.teamIds !== void 0) out.teamIds = config.teamIds;
23
+ if (config.baseUrl !== void 0) out.baseUrl = config.baseUrl;
24
+ return out;
25
+ }
26
+
27
+ // src/resource/linear/linear.ts
28
+ var LinearResource = class {
29
+ kind = ResourceName.LINEAR;
30
+ isRemote = true;
31
+ indexTtl = 600;
32
+ prompt = LINEAR_PROMPT;
33
+ writePrompt = LINEAR_WRITE_PROMPT;
34
+ config;
35
+ accessor;
36
+ index;
37
+ constructor(config) {
38
+ this.config = config;
39
+ const transportOpts = { apiKey: config.apiKey };
40
+ if (config.baseUrl !== void 0) transportOpts.baseUrl = config.baseUrl;
41
+ this.accessor = new LinearAccessor(new HttpLinearTransport(transportOpts));
42
+ this.index = new RAMIndexCacheStore({ ttl: this.indexTtl });
43
+ }
44
+ open() {
45
+ return Promise.resolve();
46
+ }
47
+ close() {
48
+ return Promise.resolve();
49
+ }
50
+ commands() {
51
+ return LINEAR_COMMANDS;
52
+ }
53
+ ops() {
54
+ return LINEAR_VFS_OPS;
55
+ }
56
+ filter() {
57
+ const out = {};
58
+ if (this.config.teamIds !== void 0) out.teamIds = this.config.teamIds;
59
+ return out;
60
+ }
61
+ readFile(p) {
62
+ return linearRead(this.accessor, p, this.index, this.filter());
63
+ }
64
+ readdir(p) {
65
+ return linearReaddir(this.accessor, p, this.index, this.filter());
66
+ }
67
+ stat(p) {
68
+ return linearStat(this.accessor, p, this.index);
69
+ }
70
+ async fingerprint(p) {
71
+ const lookup = await this.index.get(p.original);
72
+ return lookup.entry?.remoteTime ?? null;
73
+ }
74
+ glob(paths, prefix = "") {
75
+ const effective = prefix !== "" ? paths.map(
76
+ (p) => p.prefix !== "" ? p : new PathSpec({
77
+ original: p.original,
78
+ directory: p.directory,
79
+ ...p.pattern !== null ? { pattern: p.pattern } : {},
80
+ resolved: p.resolved,
81
+ prefix
82
+ })
83
+ ) : paths;
84
+ return resolveLinearGlob(this.accessor, effective, this.index, this.filter());
85
+ }
86
+ getState() {
87
+ return Promise.resolve({
88
+ type: this.kind,
89
+ needsOverride: true,
90
+ redactedFields: ["apiKey"],
91
+ config: redactLinearConfig(this.config)
92
+ });
93
+ }
94
+ loadState(_state) {
95
+ return Promise.resolve();
96
+ }
97
+ };
98
+
99
+ export {
100
+ redactLinearConfig,
101
+ LinearResource
102
+ };
103
+ //# sourceMappingURL=chunk-33SBWNB4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/resource/linear/linear.ts","../src/resource/linear/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 {\n type FileStat,\n HttpLinearTransport,\n type IndexCacheStore,\n LINEAR_COMMANDS,\n LINEAR_PROMPT,\n LINEAR_VFS_OPS,\n LINEAR_WRITE_PROMPT,\n LinearAccessor,\n type LinearReaddirFilter,\n linearRead,\n linearReaddir,\n linearStat,\n PathSpec,\n RAMIndexCacheStore,\n type RegisteredCommand,\n type RegisteredOp,\n type Resource,\n ResourceName,\n resolveLinearGlob,\n} from '@struktoai/mirage-core'\nimport { redactLinearConfig, type LinearConfig, type LinearConfigRedacted } from './config.ts'\n\nexport interface LinearResourceState {\n type: string\n needsOverride: boolean\n redactedFields: readonly string[]\n config: LinearConfigRedacted\n}\n\nexport class LinearResource implements Resource {\n readonly kind: string = ResourceName.LINEAR\n readonly isRemote: boolean = true\n readonly indexTtl: number = 600\n readonly prompt: string = LINEAR_PROMPT\n readonly writePrompt: string = LINEAR_WRITE_PROMPT\n readonly config: LinearConfig\n readonly accessor: LinearAccessor\n readonly index: IndexCacheStore\n\n constructor(config: LinearConfig) {\n this.config = config\n const transportOpts: { apiKey: string; baseUrl?: string } = { apiKey: config.apiKey }\n if (config.baseUrl !== undefined) transportOpts.baseUrl = config.baseUrl\n this.accessor = new LinearAccessor(new HttpLinearTransport(transportOpts))\n this.index = new RAMIndexCacheStore({ ttl: this.indexTtl })\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 LINEAR_COMMANDS\n }\n\n ops(): readonly RegisteredOp[] {\n return LINEAR_VFS_OPS\n }\n\n private filter(): LinearReaddirFilter {\n const out: LinearReaddirFilter = {}\n if (this.config.teamIds !== undefined) out.teamIds = this.config.teamIds\n return out\n }\n\n readFile(p: PathSpec): Promise<Uint8Array> {\n return linearRead(this.accessor, p, this.index, this.filter())\n }\n\n readdir(p: PathSpec): Promise<string[]> {\n return linearReaddir(this.accessor, p, this.index, this.filter())\n }\n\n stat(p: PathSpec): Promise<FileStat> {\n return linearStat(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 resolveLinearGlob(this.accessor, effective, this.index, this.filter())\n }\n\n getState(): Promise<LinearResourceState> {\n return Promise.resolve({\n type: this.kind,\n needsOverride: true,\n redactedFields: ['apiKey'],\n config: redactLinearConfig(this.config),\n })\n }\n\n loadState(_state: LinearResourceState): Promise<void> {\n return Promise.resolve()\n }\n}\n","// ========= 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\nexport interface LinearConfig {\n apiKey: string\n workspace?: string\n teamIds?: readonly string[]\n baseUrl?: string\n}\n\nexport interface LinearConfigRedacted {\n apiKey: '<REDACTED>'\n workspace?: string\n teamIds?: readonly string[]\n baseUrl?: string\n}\n\nexport function redactLinearConfig(config: LinearConfig): LinearConfigRedacted {\n const out: LinearConfigRedacted = { apiKey: '<REDACTED>' }\n if (config.workspace !== undefined) out.workspace = config.workspace\n if (config.teamIds !== undefined) out.teamIds = config.teamIds\n if (config.baseUrl !== undefined) out.baseUrl = config.baseUrl\n return out\n}\n"],"mappings":";AAcA;AAAA,EAEE;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAIA;AAAA,EACA;AAAA,OACK;;;ACNA,SAAS,mBAAmB,QAA4C;AAC7E,QAAM,MAA4B,EAAE,QAAQ,aAAa;AACzD,MAAI,OAAO,cAAc,OAAW,KAAI,YAAY,OAAO;AAC3D,MAAI,OAAO,YAAY,OAAW,KAAI,UAAU,OAAO;AACvD,MAAI,OAAO,YAAY,OAAW,KAAI,UAAU,OAAO;AACvD,SAAO;AACT;;;ADUO,IAAM,iBAAN,MAAyC;AAAA,EACrC,OAAe,aAAa;AAAA,EAC5B,WAAoB;AAAA,EACpB,WAAmB;AAAA,EACnB,SAAiB;AAAA,EACjB,cAAsB;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,QAAsB;AAChC,SAAK,SAAS;AACd,UAAM,gBAAsD,EAAE,QAAQ,OAAO,OAAO;AACpF,QAAI,OAAO,YAAY,OAAW,eAAc,UAAU,OAAO;AACjE,SAAK,WAAW,IAAI,eAAe,IAAI,oBAAoB,aAAa,CAAC;AACzE,SAAK,QAAQ,IAAI,mBAAmB,EAAE,KAAK,KAAK,SAAS,CAAC;AAAA,EAC5D;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,EAEQ,SAA8B;AACpC,UAAM,MAA2B,CAAC;AAClC,QAAI,KAAK,OAAO,YAAY,OAAW,KAAI,UAAU,KAAK,OAAO;AACjE,WAAO;AAAA,EACT;AAAA,EAEA,SAAS,GAAkC;AACzC,WAAO,WAAW,KAAK,UAAU,GAAG,KAAK,OAAO,KAAK,OAAO,CAAC;AAAA,EAC/D;AAAA,EAEA,QAAQ,GAAgC;AACtC,WAAO,cAAc,KAAK,UAAU,GAAG,KAAK,OAAO,KAAK,OAAO,CAAC;AAAA,EAClE;AAAA,EAEA,KAAK,GAAgC;AACnC,WAAO,WAAW,KAAK,UAAU,GAAG,KAAK,KAAK;AAAA,EAChD;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,kBAAkB,KAAK,UAAU,WAAW,KAAK,OAAO,KAAK,OAAO,CAAC;AAAA,EAC9E;AAAA,EAEA,WAAyC;AACvC,WAAO,QAAQ,QAAQ;AAAA,MACrB,MAAM,KAAK;AAAA,MACX,eAAe;AAAA,MACf,gBAAgB,CAAC,QAAQ;AAAA,MACzB,QAAQ,mBAAmB,KAAK,MAAM;AAAA,IACxC,CAAC;AAAA,EACH;AAAA,EAEA,UAAU,QAA4C;AACpD,WAAO,QAAQ,QAAQ;AAAA,EACzB;AACF;","names":[]}
@@ -0,0 +1,88 @@
1
+ import {
2
+ S3Resource
3
+ } from "./chunk-VLFE4FGD.js";
4
+
5
+ // src/resource/r2/r2.ts
6
+ import { ResourceName } from "@struktoai/mirage-core";
7
+
8
+ // src/resource/r2/config.ts
9
+ function resolvedR2Endpoint(config) {
10
+ if (config.endpoint !== void 0 && config.endpoint !== "") return config.endpoint;
11
+ if (config.accountId !== void 0 && config.accountId !== "") {
12
+ return `https://${config.accountId}.r2.cloudflarestorage.com`;
13
+ }
14
+ return void 0;
15
+ }
16
+ function r2ToS3Config(config) {
17
+ const endpoint = resolvedR2Endpoint(config);
18
+ return {
19
+ bucket: config.bucket,
20
+ presignedUrlProvider: config.presignedUrlProvider,
21
+ region: config.region ?? "auto",
22
+ ...endpoint !== void 0 ? { endpoint } : {},
23
+ ...config.defaultContentType !== void 0 ? { defaultContentType: config.defaultContentType } : {}
24
+ };
25
+ }
26
+ function redactR2Config(config) {
27
+ return { ...config, presignedUrlProvider: "<REDACTED>" };
28
+ }
29
+
30
+ // src/resource/r2/prompt.ts
31
+ var R2_BROWSER_PROMPT = `{prefix}
32
+ Remote Cloudflare R2 bucket accessed via presigned URLs (browser runtime).
33
+ Supports the full filesystem command set: ls/tree/cat/grep/find/du/cp/mv/rm/etc.
34
+ Listing operations require the presigner to sign LIST/COPY operations in
35
+ addition to GET/PUT/HEAD/DELETE \u2014 see S3BrowserPresignedUrlProvider docs.`;
36
+
37
+ // src/resource/r2/r2.ts
38
+ function remapOpsResource(ops, to) {
39
+ return ops.map((op) => op.resource === ResourceName.S3 ? { ...op, resource: to } : op);
40
+ }
41
+ function remapCommandsResource(commands, to) {
42
+ return commands.map((cmd) => {
43
+ if (cmd.resource !== ResourceName.S3) return cmd;
44
+ const proto = Object.getPrototypeOf(cmd);
45
+ const copy = Object.assign(Object.create(proto), cmd);
46
+ Object.assign(copy, { resource: to });
47
+ return copy;
48
+ });
49
+ }
50
+ var R2Resource = class extends S3Resource {
51
+ kind = ResourceName.R2;
52
+ prompt = R2_BROWSER_PROMPT;
53
+ r2Config;
54
+ r2Ops;
55
+ r2Commands;
56
+ constructor(config) {
57
+ super(r2ToS3Config(config));
58
+ this.r2Config = config;
59
+ this.r2Ops = remapOpsResource(super.ops(), ResourceName.R2);
60
+ this.r2Commands = remapCommandsResource(super.commands(), ResourceName.R2);
61
+ }
62
+ ops() {
63
+ return this.r2Ops;
64
+ }
65
+ commands() {
66
+ return this.r2Commands;
67
+ }
68
+ getState() {
69
+ return Promise.resolve({
70
+ type: this.kind,
71
+ needsOverride: true,
72
+ redactedFields: ["presignedUrlProvider"],
73
+ config: redactR2Config(this.r2Config)
74
+ });
75
+ }
76
+ loadState(_state) {
77
+ return Promise.resolve();
78
+ }
79
+ };
80
+
81
+ export {
82
+ resolvedR2Endpoint,
83
+ r2ToS3Config,
84
+ redactR2Config,
85
+ R2_BROWSER_PROMPT,
86
+ R2Resource
87
+ };
88
+ //# sourceMappingURL=chunk-3PWPFOPS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/resource/r2/r2.ts","../src/resource/r2/config.ts","../src/resource/r2/prompt.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 { ResourceName, type RegisteredCommand, type RegisteredOp } from '@struktoai/mirage-core'\nimport { S3Resource } from '../s3/s3.ts'\nimport { r2ToS3Config, redactR2Config, type R2Config, type R2ConfigRedacted } from './config.ts'\nimport { R2_BROWSER_PROMPT } from './prompt.ts'\n\nexport interface R2ResourceState {\n type: string\n needsOverride: boolean\n redactedFields: readonly string[]\n config: R2ConfigRedacted\n}\n\nfunction remapOpsResource(ops: readonly RegisteredOp[], to: string): RegisteredOp[] {\n return ops.map((op) => (op.resource === ResourceName.S3 ? { ...op, resource: to } : op))\n}\n\nfunction remapCommandsResource(\n commands: readonly RegisteredCommand[],\n to: string,\n): RegisteredCommand[] {\n return commands.map((cmd) => {\n if (cmd.resource !== ResourceName.S3) return cmd\n const proto = Object.getPrototypeOf(cmd) as object\n const copy = Object.assign(Object.create(proto) as RegisteredCommand, cmd)\n Object.assign(copy, { resource: to })\n return copy\n })\n}\n\nexport class R2Resource extends S3Resource {\n override readonly kind: string = ResourceName.R2\n override readonly prompt: string = R2_BROWSER_PROMPT\n readonly r2Config: R2Config\n private readonly r2Ops: readonly RegisteredOp[]\n private readonly r2Commands: readonly RegisteredCommand[]\n\n constructor(config: R2Config) {\n super(r2ToS3Config(config))\n this.r2Config = config\n this.r2Ops = remapOpsResource(super.ops(), ResourceName.R2)\n this.r2Commands = remapCommandsResource(super.commands(), ResourceName.R2)\n }\n\n override ops(): readonly RegisteredOp[] {\n return this.r2Ops\n }\n\n override commands(): readonly RegisteredCommand[] {\n return this.r2Commands\n }\n\n override getState(): Promise<R2ResourceState> {\n return Promise.resolve({\n type: this.kind,\n needsOverride: true,\n redactedFields: ['presignedUrlProvider'],\n config: redactR2Config(this.r2Config),\n })\n }\n\n override loadState(_state: R2ResourceState): Promise<void> {\n return Promise.resolve()\n }\n}\n","// ========= 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 type { S3BrowserPresignedUrlProvider, S3Config } from '../s3/config.ts'\n\nexport interface R2Config {\n bucket: string\n presignedUrlProvider: S3BrowserPresignedUrlProvider\n accountId?: string\n region?: string\n endpoint?: string\n defaultContentType?: string\n}\n\nexport interface R2ConfigRedacted extends Omit<R2Config, 'presignedUrlProvider'> {\n presignedUrlProvider: '<REDACTED>'\n}\n\nexport function resolvedR2Endpoint(config: R2Config): string | undefined {\n if (config.endpoint !== undefined && config.endpoint !== '') return config.endpoint\n if (config.accountId !== undefined && config.accountId !== '') {\n return `https://${config.accountId}.r2.cloudflarestorage.com`\n }\n return undefined\n}\n\nexport function r2ToS3Config(config: R2Config): S3Config {\n const endpoint = resolvedR2Endpoint(config)\n return {\n bucket: config.bucket,\n presignedUrlProvider: config.presignedUrlProvider,\n region: config.region ?? 'auto',\n ...(endpoint !== undefined ? { endpoint } : {}),\n ...(config.defaultContentType !== undefined\n ? { defaultContentType: config.defaultContentType }\n : {}),\n }\n}\n\nexport function redactR2Config(config: R2Config): R2ConfigRedacted {\n return { ...config, presignedUrlProvider: '<REDACTED>' }\n}\n","// ========= 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\nexport const R2_BROWSER_PROMPT = `{prefix}\n Remote Cloudflare R2 bucket accessed via presigned URLs (browser runtime).\n Supports the full filesystem command set: ls/tree/cat/grep/find/du/cp/mv/rm/etc.\n Listing operations require the presigner to sign LIST/COPY operations in\n addition to GET/PUT/HEAD/DELETE — see S3BrowserPresignedUrlProvider docs.`\n"],"mappings":";;;;;AAcA,SAAS,oBAA+D;;;ACejE,SAAS,mBAAmB,QAAsC;AACvE,MAAI,OAAO,aAAa,UAAa,OAAO,aAAa,GAAI,QAAO,OAAO;AAC3E,MAAI,OAAO,cAAc,UAAa,OAAO,cAAc,IAAI;AAC7D,WAAO,WAAW,OAAO,SAAS;AAAA,EACpC;AACA,SAAO;AACT;AAEO,SAAS,aAAa,QAA4B;AACvD,QAAM,WAAW,mBAAmB,MAAM;AAC1C,SAAO;AAAA,IACL,QAAQ,OAAO;AAAA,IACf,sBAAsB,OAAO;AAAA,IAC7B,QAAQ,OAAO,UAAU;AAAA,IACzB,GAAI,aAAa,SAAY,EAAE,SAAS,IAAI,CAAC;AAAA,IAC7C,GAAI,OAAO,uBAAuB,SAC9B,EAAE,oBAAoB,OAAO,mBAAmB,IAChD,CAAC;AAAA,EACP;AACF;AAEO,SAAS,eAAe,QAAoC;AACjE,SAAO,EAAE,GAAG,QAAQ,sBAAsB,aAAa;AACzD;;;ACtCO,IAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;;;AFYjC,SAAS,iBAAiB,KAA8B,IAA4B;AAClF,SAAO,IAAI,IAAI,CAAC,OAAQ,GAAG,aAAa,aAAa,KAAK,EAAE,GAAG,IAAI,UAAU,GAAG,IAAI,EAAG;AACzF;AAEA,SAAS,sBACP,UACA,IACqB;AACrB,SAAO,SAAS,IAAI,CAAC,QAAQ;AAC3B,QAAI,IAAI,aAAa,aAAa,GAAI,QAAO;AAC7C,UAAM,QAAQ,OAAO,eAAe,GAAG;AACvC,UAAM,OAAO,OAAO,OAAO,OAAO,OAAO,KAAK,GAAwB,GAAG;AACzE,WAAO,OAAO,MAAM,EAAE,UAAU,GAAG,CAAC;AACpC,WAAO;AAAA,EACT,CAAC;AACH;AAEO,IAAM,aAAN,cAAyB,WAAW;AAAA,EACvB,OAAe,aAAa;AAAA,EAC5B,SAAiB;AAAA,EAC1B;AAAA,EACQ;AAAA,EACA;AAAA,EAEjB,YAAY,QAAkB;AAC5B,UAAM,aAAa,MAAM,CAAC;AAC1B,SAAK,WAAW;AAChB,SAAK,QAAQ,iBAAiB,MAAM,IAAI,GAAG,aAAa,EAAE;AAC1D,SAAK,aAAa,sBAAsB,MAAM,SAAS,GAAG,aAAa,EAAE;AAAA,EAC3E;AAAA,EAES,MAA+B;AACtC,WAAO,KAAK;AAAA,EACd;AAAA,EAES,WAAyC;AAChD,WAAO,KAAK;AAAA,EACd;AAAA,EAES,WAAqC;AAC5C,WAAO,QAAQ,QAAQ;AAAA,MACrB,MAAM,KAAK;AAAA,MACX,eAAe;AAAA,MACf,gBAAgB,CAAC,sBAAsB;AAAA,MACvC,QAAQ,eAAe,KAAK,QAAQ;AAAA,IACtC,CAAC;AAAA,EACH;AAAA,EAES,UAAU,QAAwC;AACzD,WAAO,QAAQ,QAAQ;AAAA,EACzB;AACF;","names":[]}