@wenathlan/saddle 1.8.16 → 1.8.18

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 (223) hide show
  1. package/README.md +38 -13
  2. package/dist/apps/registry.d.ts +1 -1
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +1 -0
  6. package/dist/index.js.map +1 -1
  7. package/dist/isolation/contracts.d.ts +118 -0
  8. package/dist/isolation/contracts.d.ts.map +1 -0
  9. package/dist/isolation/contracts.js +84 -0
  10. package/dist/isolation/contracts.js.map +1 -0
  11. package/dist/mcp/server.d.ts +2 -2
  12. package/dist/scrape/robots.js +1 -1
  13. package/docs/artifactavailability.md +18 -2
  14. package/docs/containerplatforms-1.8.17.md +29 -0
  15. package/docs/releasenotes-1.8.16.md +6 -2
  16. package/docs/releasenotes-1.8.17.md +43 -0
  17. package/docs/releasenotes-1.8.18.md +32 -0
  18. package/docs/research-1.8.18-isolation.md +43 -0
  19. package/docs/saddle.archive.1.8.17.tar.gz.gpg +0 -0
  20. package/docs/todo-1.8.16.md +92 -8
  21. package/docs/todo-1.8.18.md +152 -0
  22. package/docs/workflowoperations.md +32 -0
  23. package/extension/manifest.json +1 -1
  24. package/package.json +3 -2
  25. package/docs/logs/.gitkeep +0 -0
  26. package/docs/plans/00.index.md +0 -50
  27. package/docs/plans/01.architecture.md +0 -86
  28. package/docs/plans/02.research.computer.use.md +0 -58
  29. package/docs/plans/03.research.captcha.bypass.md +0 -68
  30. package/docs/plans/04.research.sandbox.ai.md +0 -52
  31. package/docs/plans/05.capture.platform.md +0 -57
  32. package/docs/plans/06.dependencies.md +0 -97
  33. package/docs/plans/07.captcha.test.page.md +0 -41
  34. package/docs/plans/08.production.infra.md +0 -70
  35. package/docs/plans/09.database.schema.md +0 -121
  36. package/docs/plans/10.cloudinary.storage.md +0 -57
  37. package/docs/plans/11.movement.logs.json.md +0 -72
  38. package/docs/plans/12.research.atlas.agent.browser.md +0 -79
  39. package/docs/plans/13.research.anti.detection.md +0 -898
  40. package/docs/plans/14.research.proxy.md +0 -1495
  41. package/docs/plans/15.research.retry.rate.limit.md +0 -1958
  42. package/docs/plans/16.research.crawling.md +0 -1417
  43. package/docs/plans/17.research.caching.md +0 -1610
  44. package/docs/plans/18.research.content.extraction.md +0 -1952
  45. package/docs/plans/19.research.errors.events.md +0 -1523
  46. package/docs/plans/20.research.zod.validation.md +0 -1350
  47. package/docs/plans/21.research.batch.concurrency.md +0 -1888
  48. package/docs/plans/22.research.universal.runtime.md +0 -944
  49. package/docs/plans/23.research.ai.integration.md +0 -1465
  50. package/docs/plans/24.research.memory.persistence.md +0 -1979
  51. package/docs/plans/25.research.server.api.md +0 -342
  52. package/docs/plans/26.research.compilation.md +0 -249
  53. package/docs/plans/27.research.html.parsing.md +0 -251
  54. package/docs/plans/28.action.plan.md +0 -50
  55. package/docs/plans/29.api.reference.md +0 -174
  56. package/docs/plans/30.architecture.plan.md +0 -94
  57. package/docs/plans/31.auditoria.dados.md +0 -163
  58. package/docs/plans/32.bots.automacao.computacional.md +0 -214
  59. package/docs/plans/33.bots.codigo.revisao.md +0 -220
  60. package/docs/plans/34.bots.seguranca.cicd.md +0 -366
  61. package/docs/plans/35.comparativo.concorrencia.md +0 -464
  62. package/docs/plans/36.computational.memory.md +0 -340
  63. package/docs/plans/37.deploystrategy.md +0 -394
  64. package/docs/plans/38.flow.md +0 -155
  65. package/docs/plans/39.multi.platform.bot.md +0 -252
  66. package/docs/plans/40.npm.publish.md +0 -250
  67. package/docs/plans/41.o.que.falta.md +0 -407
  68. package/docs/plans/42.pesquisa.concorrencia.md +0 -721
  69. package/docs/plans/43.plan.universal.architecture.md +0 -496
  70. package/docs/plans/44.reference.md +0 -100
  71. package/docs/plans/45.robotarchitecture.md +0 -237
  72. package/docs/plans/46.scdnintegration.md +0 -284
  73. package/docs/plans/47.multiforge.readme.md +0 -129
  74. package/docs/plans/48.theory.v4.repo.os.md +0 -152
  75. package/docs/plans/49.third.party.infra.md +0 -12
  76. package/docs/plans/50.file.as.compute.md +0 -39
  77. package/docs/plans/51.architecture.virtual.processor.md +0 -80
  78. package/docs/plans/52.manifesto.v8.md +0 -11
  79. package/docs/plans/58.cdn.list.md +0 -23
  80. package/docs/plans/59.sql.frameworks.md +0 -33
  81. package/docs/plans/60.sql.thirdparty.md +0 -26
  82. package/docs/plans/61.objective.multiforge.md +0 -63
  83. package/docs/plans/62.huggingface.upload.md +0 -26
  84. package/docs/plans/63.kaggle.upload.md +0 -24
  85. package/docs/plans/64.npm.storage.md +0 -30
  86. package/docs/plans/65.rclone.terabox.md +0 -32
  87. package/docs/plans/66.buckets.and.models.todo.md +0 -14
  88. package/docs/plans/67.database.todo.md +0 -13
  89. package/docs/plans/68.deploy.packages.todo.md +0 -12
  90. package/docs/plans/69.report.human.operator.md +0 -133
  91. package/docs/plans/70.report.brain2qwerty.ems.md +0 -135
  92. package/docs/plans/71.report.hd.infinito.vram.md +0 -155
  93. package/docs/plans/72.plan.hd.infinito.node.md +0 -146
  94. package/docs/plans/73.plan.scifi.repos.md +0 -125
  95. package/docs/plans/74.000.manifesto.v8.flat.2..md +0 -11
  96. package/docs/plans/README.md +0 -489
  97. package/docs/plans/aggregate_platforms.mjs +0 -146
  98. package/docs/plans/examplesession.json +0 -36
  99. package/docs/plans/missing-facts.md +0 -192
  100. package/docs/plans/models.md +0 -64
  101. package/docs/plans/organize.cjs +0 -270
  102. package/docs/plans/platforms.md +0 -2887
  103. package/docs/plans/sites.md +0 -31322
  104. package/docs/sources/farm.py +0 -117
  105. package/docs/sources/html/saddle1.html +0 -132
  106. package/docs/sources/html/saddle2.html +0 -157
  107. package/docs/sources/html/saddle3.html +0 -119
  108. package/docs/sources/html/saddle4.html +0 -144
  109. package/docs/sources/html/saddle5.html +0 -72
  110. package/docs/sources/html/saddle6.html +0 -171
  111. package/docs/sources/html/saddle7.html +0 -236
  112. package/docs/sources/saddle.ts +0 -74
  113. package/docs/sources/schema.prisma +0 -88
  114. package/docs/sources/script.sh +0 -64
  115. package/docs/sources/workflows.yml +0 -458
  116. package/docs/talks1/_body.txt +0 -14
  117. package/docs/talks1/_index.md +0 -15
  118. package/docs/talks1/_screenshot.png +0 -0
  119. package/docs/talks1/assistant-01.md +0 -5
  120. package/docs/talks1/assistant-02.md +0 -5
  121. package/docs/talks1/assistant-03.md +0 -531
  122. package/docs/talks1/assistant-04.md +0 -26
  123. package/docs/talks1/assistant-05.md +0 -774
  124. package/docs/talks1/assistant-06.md +0 -1718
  125. package/docs/talks1/scrape-share.cjs +0 -185
  126. package/docs/talks1/scrape-share.ts +0 -183
  127. package/docs/talks1/user-01.md +0 -3
  128. package/docs/talks1/user-02.md +0 -3
  129. package/docs/talks1/user-03.md +0 -88
  130. package/docs/talks1/user-04.md +0 -3
  131. package/docs/talks1/user-05.md +0 -3
  132. package/docs/talks1/user-06.md +0 -88
  133. package/docs/talks1/user-07.md +0 -88
  134. package/docs/talks2/_body.txt +0 -14
  135. package/docs/talks2/_index.md +0 -16
  136. package/docs/talks2/_screenshot.png +0 -0
  137. package/docs/talks2/assistant-01.md +0 -5
  138. package/docs/talks2/assistant-02.md +0 -5
  139. package/docs/talks2/assistant-03.md +0 -424
  140. package/docs/talks2/assistant-04.md +0 -598
  141. package/docs/talks2/assistant-05.md +0 -1280
  142. package/docs/talks2/assistant-06.md +0 -1227
  143. package/docs/talks2/assistant-07.md +0 -1252
  144. package/docs/talks2/user-01.md +0 -3
  145. package/docs/talks2/user-02.md +0 -3
  146. package/docs/talks2/user-03.md +0 -88
  147. package/docs/talks2/user-04.md +0 -88
  148. package/docs/talks2/user-05.md +0 -88
  149. package/docs/talks2/user-06.md +0 -88
  150. package/docs/talks2/user-07.md +0 -3
  151. package/docs/talks3/_body.txt +0 -467
  152. package/docs/talks3/_index.md +0 -10
  153. package/docs/talks3/_screenshot.png +0 -0
  154. package/docs/talks3/assistant-01.md +0 -417
  155. package/docs/talks3/assistant-02.md +0 -417
  156. package/docs/talks3/assistant-03.md +0 -29
  157. package/docs/talks3/assistant-04.md +0 -727
  158. package/docs/talks3/user-01.md +0 -88
  159. package/docs/talks3/user-02.md +0 -88
  160. package/docs/talks3/user-03.md +0 -3
  161. package/docs/talks3/user-04.md +0 -3
  162. package/docs/talks4/_body.txt +0 -14
  163. package/docs/talks4/_index.md +0 -12
  164. package/docs/talks4/_screenshot.png +0 -0
  165. package/docs/talks4/assistant-01.md +0 -5
  166. package/docs/talks4/assistant-02.md +0 -5
  167. package/docs/talks4/assistant-03.md +0 -35
  168. package/docs/talks4/assistant-04.md +0 -512
  169. package/docs/talks4/assistant-05.md +0 -599
  170. package/docs/talks4/user-01.md +0 -3
  171. package/docs/talks4/user-02.md +0 -3
  172. package/docs/talks4/user-03.md +0 -88
  173. package/docs/talks4/user-04.md +0 -88
  174. package/docs/talks4/user-05.md +0 -7
  175. package/docs/talks5/_body.txt +0 -14
  176. package/docs/talks5/_index.md +0 -13
  177. package/docs/talks5/_screenshot.png +0 -0
  178. package/docs/talks5/assistant-01.md +0 -5
  179. package/docs/talks5/assistant-02.md +0 -5
  180. package/docs/talks5/assistant-03.md +0 -690
  181. package/docs/talks5/assistant-04.md +0 -758
  182. package/docs/talks5/assistant-05.md +0 -974
  183. package/docs/talks5/user-01.md +0 -3
  184. package/docs/talks5/user-02.md +0 -3
  185. package/docs/talks5/user-03.md +0 -105
  186. package/docs/talks5/user-04.md +0 -105
  187. package/docs/talks5/user-05.md +0 -63
  188. package/docs/talks5/user-06.md +0 -105
  189. package/docs/talks6/_body.txt +0 -14
  190. package/docs/talks6/_index.md +0 -9
  191. package/docs/talks6/_screenshot.png +0 -0
  192. package/docs/talks6/assistant-01.md +0 -5
  193. package/docs/talks6/assistant-02.md +0 -5
  194. package/docs/talks6/assistant-03.md +0 -1499
  195. package/docs/talks6/user-01.md +0 -3
  196. package/docs/talks6/user-02.md +0 -3
  197. package/docs/talks6/user-03.md +0 -88
  198. package/docs/talks6/user-04.md +0 -88
  199. package/docs/talks7/_body.txt +0 -14
  200. package/docs/talks7/_index.md +0 -10
  201. package/docs/talks7/_screenshot.png +0 -0
  202. package/docs/talks7/assistant-01.md +0 -5
  203. package/docs/talks7/assistant-02.md +0 -5
  204. package/docs/talks7/assistant-03.md +0 -523
  205. package/docs/talks7/assistant-04.md +0 -617
  206. package/docs/talks7/user-01.md +0 -3
  207. package/docs/talks7/user-02.md +0 -3
  208. package/docs/talks7/user-03.md +0 -105
  209. package/docs/talks7/user-04.md +0 -67
  210. package/docs/talks8/conversa1.txt +0 -1322
  211. package/docs/talks8/conversa2.txt +0 -237
  212. package/docs/talks9/Beyond the Obvious_ 50 Plataformas Auto-Hospedadas de Forja de C/303/263digo para Al/303/251m de Gitea e GitLab.md" +0 -174
  213. package/docs/talks9/De NPM a Multi-Linguagem_ Uma Arquitetura T/303/251cnica para a Execu/303/247/303/243o Integrada de C/303/263digo no Ecossistema Node.js.md" +0 -59
  214. package/docs/talks9/De NPM a VMs Virtuais_ Uma An/303/241lise Arquitet/303/264nica para a Realiza/303/247/303/243o do Ciclo de Vida do Projeto SADDLE.md" +0 -91
  215. package/docs/talks9/Mapeamento da Engrenagem Computacional_ Uma Arquitetura para Execu/303/247/303/243o Isolada e Persist/303/252ncia em Ambientes Distribu/303/255dos.md" +0 -116
  216. package/docs/talks9/O Cen/303/241rio Pr/303/241tico do SADDLE_ Uma An/303/241lise de Viabilidade e Modelo de Ciclo de Vida Integrado.md" +0 -128
  217. package/docs/talks9/README (2).md +0 -489
  218. package/docs/talks9/README.md +0 -198
  219. package/docs/talks9/Viabilidade do Saddle_ Uma An/303/241lise T/303/251cnica da Transforma/303/247/303/243o de Armazenamento Remoto em Mem/303/263ria Computacional.md" +0 -80
  220. package/docs/talks9/conversa.txt +0 -544
  221. package/docs/talks9/other (2).md +0 -39
  222. package/docs/talks9/other.md +0 -57
  223. package/docs/talks9/outro.txt +0 -24
@@ -1,1227 +0,0 @@
1
- # assistant
2
-
3
- [Thinking] The user is asking me to continue researching and provide a comprehensive step-by-step implementation plan for their sandbox platform. They want to use:
4
-
5
- Free infrastructure from repositories (GitHub, GitLab, Forgejo, Gitea, Codeberg)
6
- Free GPU platforms (HuggingFace, Kaggle, ModelScope)
7
- Memory conversion (storage → RAM) using zram, tmpfs, etc.
8
- ORMs and databases (Prisma, Drizzle, MySQL2, SQLite)
9
- Open source projects and libraries
10
- Publish as npm package and open source repo
11
- Use CDN (jsdelivr/esm) for execution
12
-
13
- They specifically mention:
14
-
15
- Using the storage from these repos/buckets to convert to RAM
16
- Using their infrastructure for storage
17
- npm packages with CDN availability
18
- Two fronts: own library + third-party libraries
19
-
20
- I'm in plan mode, so I can only read, search, and plan - no edits. Let me search for more specific information about:
21
-
22
- jsdelivr/esm CDN for npm packages
23
- More specific implementation details
24
- How to use repo storage as memory
25
-
26
- [Thinking] Now I have comprehensive information about:
27
-
28
- jsdelivr/esm CDN for npm packages
29
- GitHub as filesystem storage (git-fs, github-filesystem)
30
- Cloudflare R2 for storage
31
- Virtual filesystems (memfs, @platformatic/vfs)
32
-
33
- Let me now create a comprehensive plan that covers all the user's requirements. The user wants:
34
-
35
- A sandbox platform using free infrastructure
36
- Memory conversion (storage → RAM)
37
- Using repo storage as memory
38
- npm package with CDN availability
39
- Two fronts: own library + third-party
40
-
41
- Let me create the final comprehensive plan.
42
-
43
- [Thinking] Now let me create the comprehensive final plan.
44
-
45
- [Thinking] I've provided a comprehensive plan. Let me now ask the user if they want me to implement any specific part.
46
-
47
- PLANO FINAL COMPLETO: Plataforma Sandbox + Memória Virtual Contínua
48
-
49
- VISÃO GERAL: O QUE VOCÊ QUER FAZER
50
- ┌─────────────────────────────────────────────────────────────────────────────┐
51
- │ SANDBOX PLATFORM - VISÃO GERAL │
52
- │ │
53
- │ USUÁRIO cria sandbox → SISTEMA cria repositório → PIPELINE roda → │
54
- │ RUNNER executa Linux/Docker → MEMÓRIA converte storage→RAM → │
55
- │ SNAPSHOT persiste estado → CDN disponibiliza pacotes │
56
- │ │
57
- │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
58
- │ │ Repositórios │ │ Pipelines │ │ Memória │ │ CDN/Edge │ │
59
- │ │ (GitHub, │ │ (GitHub │ │ Virtual │ │ (jsdelivr, │ │
60
- │ │ GitLab, │ │ Actions, │ │ (zram, │ │ esm.sh, │ │
61
- │ │ Forgejo) │ │ GitLab CI) │ │ tmpfs, │ │ Cloudflare) │ │
62
- │ └──────────────┘ └──────────────┘ │ overlay) │ └──────────────┘ │
63
- │ └──────────────┘ │
64
- └─────────────────────────────────────────────────────────────────────────────┘
65
-
66
- PARTE 1: MAPA COMPLETO DE INFRAESTRUTURA GRATUITA
67
- 1.1 Repositórios + CI/CD
68
-
69
-
70
-
71
- Plataforma
72
- RAM
73
- CPU
74
- Storage
75
- GPU
76
- Minutos
77
- URL
78
-
79
-
80
-
81
- GitHub (público)
82
- 16 GB
83
- 4 vCPU
84
- 14 GB
85
- Não
86
- Ilimitado
87
- github.com
88
-
89
-
90
- GitHub (privado)
91
- 16 GB
92
- 4 vCPU
93
- 14 GB
94
- Não
95
- 2.000/mês
96
- github.com
97
-
98
-
99
- GitLab Free
100
- 8 GB
101
- 2 vCPU
102
- 30 GB
103
- Não
104
- 400/mês
105
- gitlab.com
106
-
107
-
108
- Codeberg (Forgejo)
109
- 8 GB
110
- 4 vCPU
111
- -
112
- Não
113
- -
114
- codeberg.org
115
-
116
-
117
- Forgejo self-hosted
118
- Ilimitado
119
- Ilimitado
120
- Ilimitado
121
- Não
122
- Ilimitado
123
- Auto-hospedado
124
-
125
-
126
- 1.2 Plataformas GPU Gratuita
127
-
128
-
129
-
130
- Plataforma
131
- RAM
132
- GPU
133
- VRAM
134
- Limite
135
- Preço
136
-
137
-
138
-
139
- HuggingFace (free)
140
- 16 GB
141
- Não
142
- -
143
- 2 dias inativo
144
- $0
145
-
146
-
147
- HuggingFace (T4)
148
- 15 GB
149
- T4
150
- 16 GB
151
- Ilimitado
152
- $0.40/h
153
-
154
-
155
- Kaggle
156
- 29 GB
157
- T4 x2
158
- 16 GB
159
- 30h/semana
160
- $0
161
-
162
-
163
- ModelScope
164
- Variável
165
- Variável
166
- Variável
167
- Free tier
168
- $0
169
-
170
-
171
- 1.3 Storage Gratuito
172
-
173
-
174
-
175
- Plataforma
176
- Storage
177
- Bandwidth
178
- Uso
179
-
180
-
181
-
182
- GitHub LFS
183
- 1 GB
184
- 1 GB/mês
185
- Repositórios
186
-
187
-
188
- Cloudflare R2
189
- 10 GB
190
- Ilimitado
191
- Buckets
192
-
193
-
194
- Cloudflare Workers
195
- 100K req/dia
196
- Ilimitado
197
- API
198
-
199
-
200
- jsdelivr CDN
201
- Ilimitado
202
- Ilimitado
203
- Pacotes npm
204
-
205
-
206
- HuggingFace Hub
207
- Ilimitado
208
- Ilimitado
209
- Modelos/Dados
210
-
211
-
212
-
213
- PARTE 2: BIBLIOTECAS DE MEMÓRIA VIRTUAL
214
- 2.1 Conversão Storage → RAM
215
-
216
-
217
-
218
- Biblioteca
219
- npm/pip
220
- O que faz
221
- RAM
222
-
223
-
224
-
225
- memfs
226
- npm i memfs
227
- Filesystem em RAM com API fs
228
- Voluntário
229
-
230
-
231
- @platformatic/vfs
232
- npm i @platformatic/vfs
233
- VFS com SQLite provider
234
- Voluntário
235
-
236
-
237
- chuk-virtual-fs
238
- pip install chuk-virtual-fs
239
- Virtual FS multi-backend
240
- Voluntário
241
-
242
-
243
- mirage
244
- pip install mirage-ai
245
- 50+ backends (RAM, Redis, S3)
246
- Voluntário
247
-
248
-
249
- ems
250
- npm i ems
251
- Memória compartilhada cross-process
252
- Voluntário
253
-
254
-
255
- node-shared-mem
256
- npm i node-shared-mem
257
- Shared memory via N-API
258
- Voluntário
259
-
260
-
261
- 2.2 GitHub como Storage (converte repo → RAM)
262
-
263
-
264
-
265
- Biblioteca
266
- npm
267
- O que faz
268
-
269
-
270
-
271
- github-filesystem
272
- npm i github-filesystem
273
- GitHub como filesystem (commit/instant mode)
274
-
275
-
276
- git-fs
277
- npm i git-fs
278
- Virtual FS hidratado da GitHub API
279
-
280
-
281
- github-storage
282
- npm i github-storage
283
- GitHub como file database
284
-
285
-
286
- @platformatic/vfs
287
- npm i @platformatic/vfs
288
- VFS com mount de GitHub
289
-
290
-
291
- 2.3 Bancos em Memória
292
-
293
-
294
-
295
- Biblioteca
296
- npm/pip
297
- Backend
298
- Uso
299
-
300
-
301
-
302
- Drizzle ORM
303
- npm i drizzle-orm
304
- SQLite/MySQL/PostgreSQL
305
- ORM TypeScript
306
-
307
-
308
- Prisma
309
- npm i prisma
310
- SQLite/MySQL/PostgreSQL
311
- ORM TypeScript
312
-
313
-
314
- better-sqlite3
315
- npm i better-sqlite3
316
- SQLite
317
- Driver nativo
318
-
319
-
320
- mysql2
321
- npm i mysql2
322
- MySQL
323
- Driver MySQL
324
-
325
-
326
- SQLite in-memory
327
- Nativo
328
- :memory:
329
- Banco efêmero
330
-
331
-
332
- 2.4 Bridges Node.js ↔ Python
333
-
334
-
335
-
336
- Biblioteca
337
- npm
338
- O que faz
339
-
340
-
341
-
342
- pythonia
343
- npm i pythonia
344
- Chama Python de Node.js
345
-
346
-
347
- pymport
348
- npm i pymport
349
- Bibliotecas Python nativas
350
-
351
-
352
- nodepyx
353
- npm i nodepyx
354
- CPython embutido
355
-
356
-
357
-
358
- PARTE 3: ARQUITETURA DA PLATAFORMA
359
- ┌─────────────────────────────────────────────────────────────────────────────┐
360
- │ PLATAFORMA SANDBOX.IO │
361
- │ │
362
- │ ┌─────────────────────────────────────────────────────────────────────┐ │
363
- │ │ CDN LAYER (jsdelivr + esm.sh) │ │
364
- │ │ import { Sandbox } from 'https://esm.run/@sandbox-platform/core' │ │
365
- │ └─────────────────────────────────────────────────────────────────────┘ │
366
- │ │ │
367
- │ ┌─────────────────────────────────┴─────────────────────────────────┐ │
368
- │ │ API LAYER (Cloudflare Workers) │ │
369
- │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
370
- │ │ │ POST │ │ GET │ │ WS │ │ Cron │ │ │
371
- │ │ │ /sandbox │ │ /status │ │ /exec │ │ /cleanup │ │ │
372
- │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │
373
- │ └───────────────────────────────────────────────────────────────────┘ │
374
- │ │ │
375
- │ ┌─────────────────────────────────┴─────────────────────────────────┐ │
376
- │ │ ORQUESTRADOR (Node.js + Drizzle) │ │
377
- │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
378
- │ │ │ GitHub │ │ GitLab │ │ Forgejo │ │ Hugging │ │ │
379
- │ │ │ Actions │ │ CI │ │ Actions │ │ Face │ │ │
380
- │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │
381
- │ └───────────────────────────────────────────────────────────────────┘ │
382
- │ │ │
383
- │ ┌─────────────────────────────────┴─────────────────────────────────┐ │
384
- │ │ MEMÓRIA VIRTUAL CONTÍNUA │ │
385
- │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
386
- │ │ │ zram │ │ tmpfs │ │ overlay │ │ SQLite │ │ │
387
- │ │ │ (swap │ │ (/tmp │ │ (CoW │ │ in- │ │ │
388
- │ │ │ compr.) │ │ em RAM) │ │ RAM) │ │ memory │ │ │
389
- │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │
390
- │ └───────────────────────────────────────────────────────────────────┘ │
391
- │ │ │
392
- │ ┌─────────────────────────────────┴─────────────────────────────────┐ │
393
- │ │ SANDBOX RUNNERS │ │
394
- │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
395
- │ │ │ Docker │ │ kern │ │ QEMU │ │ Fire- │ │ │
396
- │ │ │ Engine │ │ rootless │ │ microVM │ │ cracker │ │ │
397
- │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │
398
- │ └───────────────────────────────────────────────────────────────────┘ │
399
- └─────────────────────────────────────────────────────────────────────────────┘
400
-
401
- PARTE 4: SCRIPTS DE IMPLEMENTAÇÃO
402
- 4.1 Estrutura do Projeto
403
- sandbox-platform/
404
- ├── package.json
405
- ├── tsconfig.json
406
- ├── wrangler.toml # Cloudflare Workers config
407
- ├── src/
408
- │ ├── index.ts # Entry point (Worker)
409
- │ ├── api/
410
- │ │ ├── sandbox.ts # CRUD de sandboxes
411
- │ │ ├── memory.ts # Gerenciamento de memória
412
- │ │ └── webhook.ts # Webhooks de pipeline
413
- │ ├── orchestrator/
414
- │ │ ├── index.ts # Orquestrador principal
415
- │ │ ├── github.ts # GitHub Actions
416
- │ │ ├── gitlab.ts # GitLab CI
417
- │ │ ├── forgejo.ts # Forgejo/Gitea
418
- │ │ └── huggingface.ts # HuggingFace Spaces
419
- │ ├── memory/
420
- │ │ ├── virtual-memory.ts # Memória virtual (memfs)
421
- │ │ ├── memory-bridge.ts # Bridge storage→RAM
422
- │ │ ├── zram-manager.ts # zram setup
423
- │ │ └── github-fs.ts # GitHub como filesystem
424
- │ ├── db/
425
- │ │ ├── schema.ts # Drizzle schema
426
- │ │ └── index.ts # Database (SQLite :memory:)
427
- │ └── utils/
428
- │ ├── crypto.ts
429
- │ └── logger.ts
430
- ├── workflows/ # Templates de workflow
431
- │ ├── github-sandbox.yml
432
- │ ├── gitlab-sandbox.yml
433
- │ ├── forgejo-sandbox.yml
434
- │ └── huggingface-dockerfile
435
- ├── packages/
436
- │ └── core/ # Pacote npm principal
437
- │ ├── package.json
438
- │ └── src/
439
- │ └── index.ts
440
- └── README.md
441
- 4.2 package.json
442
- {
443
- "name": "@sandbox-platform/core",
444
- "version": "1.0.0",
445
- "description": "Plataforma de sandbox com memória virtual contínua",
446
- "type": "module",
447
- "main": "dist/index.js",
448
- "types": "dist/index.d.ts",
449
- "exports": {
450
- ".": {
451
- "import": "./dist/index.js",
452
- "types": "./dist/index.d.ts"
453
- },
454
- "./memory": {
455
- "import": "./dist/memory/index.js",
456
- "types": "./dist/memory/index.d.ts"
457
- },
458
- "./orchestrator": {
459
- "import": "./dist/orchestrator/index.js",
460
- "types": "./dist/orchestrator/index.d.ts"
461
- }
462
- },
463
- "scripts": {
464
- "build": "tsc",
465
- "dev": "tsx watch src/index.ts",
466
- "test": "vitest",
467
- "deploy": "wrangler deploy",
468
- "prepublishOnly": "npm run build"
469
- },
470
- "dependencies": {
471
- "drizzle-orm": "^0.30.0",
472
- "better-sqlite3": "^11.0.0",
473
- "memfs": "^4.6.0",
474
- "hono": "^4.0.0",
475
- "@hono/node-server": "^1.0.0",
476
- "zod": "^3.23.0"
477
- },
478
- "peerDependencies": {
479
- "typescript": "^5.0.0"
480
- },
481
- "keywords": [
482
- "sandbox",
483
- "virtual-memory",
484
- "github-actions",
485
- "gitlab-ci",
486
- "forgejo",
487
- "huggingface",
488
- "zram",
489
- "tmpfs",
490
- "memfs"
491
- ],
492
- "license": "MIT",
493
- "repository": {
494
- "type": "git",
495
- "url": "https://github.com/your-org/sandbox-platform"
496
- },
497
- "files": [
498
- "dist",
499
- "README.md"
500
- ]
501
- }
502
- 4.3 Drizzle Schema (banco em memória)
503
- // src/db/schema.ts
504
- import { sqliteTable, text, integer, blob } from 'drizzle-orm/sqlite-core';
505
-
506
- export const sandboxes = sqliteTable('sandboxes', {
507
- id: text('id').primaryKey(),
508
- userId: text('user_id').notNull(),
509
- platform: text('platform').notNull(), // github|gitlab|forgejo|huggingface
510
- status: text('status').notNull(), // creating|running|stopped|destroyed
511
- ramLimit: integer('ram_limit').notNull(), // MB
512
- cpuLimit: integer('cpu_limit').notNull(),
513
- gpuEnabled: integer('gpu_enabled', { mode: 'boolean' }).default(false),
514
- repoUrl: text('repo_url'),
515
- workflowId: text('workflow_id'),
516
- memorySnapshot: blob('memory_snapshot'), // Snapshot da memória
517
- createdAt: text('created_at').notNull(),
518
- expiresAt: text('expires_at'),
519
- });
520
-
521
- export const memoryRegions = sqliteTable('memory_regions', {
522
- id: text('id').primaryKey(),
523
- sandboxId: text('sandbox_id').references(() => sandboxes.id),
524
- type: text('type').notNull(), // zram|tmpfs|overlay|sqlite|github
525
- mountPoint: text('mount_point').notNull(),
526
- sizeBytes: integer('size_bytes').notNull(),
527
- usedBytes: integer('used_bytes').default(0),
528
- compressedSize: integer('compressed_size'),
529
- data: blob('data'), // Dados em RAM
530
- storagePath: text('storage_path'), // Path no storage externo
531
- createdAt: text('created_at').notNull(),
532
- });
533
-
534
- export const packages = sqliteTable('packages', {
535
- id: text('id').primaryKey(),
536
- name: text('name').notNull(),
537
- version: text('version').notNull(),
538
- registry: text('registry').notNull(), // npm|pypi|crates
539
- cdnUrl: text('cdn_url'), // jsdelivr/esm.sh URL
540
- storageUrl: text('storage_url'), // GitHub/R2 URL
541
- sizeBytes: integer('size_bytes').notNull(),
542
- cachedInRam: integer('cached_in_ram', { mode: 'boolean' }).default(false),
543
- });
544
- 4.4 Database Index (SQLite in-memory)
545
- // src/db/index.ts
546
- import { drizzle } from 'drizzle-orm/better-sqlite3';
547
- import Database from 'better-sqlite3';
548
- import * as schema from './schema';
549
-
550
- // SQLite EM MEMÓRIA - zero I/O disco
551
- const sqlite = new Database(':memory:');
552
-
553
- // Criar tabelas
554
- sqlite.exec(`
555
- CREATE TABLE IF NOT EXISTS sandboxes (
556
- id TEXT PRIMARY KEY,
557
- user_id TEXT NOT NULL,
558
- platform TEXT NOT NULL,
559
- status TEXT NOT NULL,
560
- ram_limit INTEGER NOT NULL,
561
- cpu_limit INTEGER NOT NULL,
562
- gpu_enabled INTEGER DEFAULT 0,
563
- repo_url TEXT,
564
- workflow_id TEXT,
565
- memory_snapshot BLOB,
566
- created_at TEXT NOT NULL,
567
- expires_at TEXT
568
- );
569
-
570
- CREATE TABLE IF NOT EXISTS memory_regions (
571
- id TEXT PRIMARY KEY,
572
- sandbox_id TEXT REFERENCES sandboxes(id),
573
- type TEXT NOT NULL,
574
- mount_point TEXT NOT NULL,
575
- size_bytes INTEGER NOT NULL,
576
- used_bytes INTEGER DEFAULT 0,
577
- compressed_size INTEGER,
578
- data BLOB,
579
- storage_path TEXT,
580
- created_at TEXT NOT NULL
581
- );
582
-
583
- CREATE TABLE IF NOT EXISTS packages (
584
- id TEXT PRIMARY KEY,
585
- name TEXT NOT NULL,
586
- version TEXT NOT NULL,
587
- registry TEXT NOT NULL,
588
- cdn_url TEXT,
589
- storage_url TEXT,
590
- size_bytes INTEGER NOT NULL,
591
- cached_in_ram INTEGER DEFAULT 0
592
- );
593
- `);
594
-
595
- export const db = drizzle(sqlite, { schema });
596
- 4.5 Orquestrador Principal
597
- // src/orchestrator/index.ts
598
- import { db } from '../db';
599
- import { sandboxes, memoryRegions } from '../db/schema';
600
-
601
- interface SandboxConfig {
602
- userId: string;
603
- ramLimit: number; // MB
604
- cpuLimit: number;
605
- gpuEnabled?: boolean;
606
- packages?: string[];
607
- platform?: 'github' | 'gitlab' | 'forgejo' | 'huggingface';
608
- autoSnapshot?: boolean;
609
- ttl?: number; // horas
610
- }
611
-
612
- export class SandboxOrchestrator {
613
-
614
- async createSandbox(config: SandboxConfig): Promise<string> {
615
- const sandboxId = `sbx-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
616
-
617
- // Auto-escolher plataforma
618
- const platform = config.platform || this.selectPlatform(config);
619
-
620
- // Criar registro no banco (em memória)
621
- await db.insert(sandboxes).values({
622
- id: sandboxId,
623
- userId: config.userId,
624
- platform,
625
- status: 'creating',
626
- ramLimit: config.ramLimit,
627
- cpuLimit: config.cpuLimit,
628
- gpuEnabled: config.gpuEnabled || false,
629
- createdAt: new Date().toISOString(),
630
- expiresAt: config.ttl
631
- ? new Date(Date.now() + config.ttl * 3600000).toISOString()
632
- : null,
633
- });
634
-
635
- // Criar regiões de memória
636
- await this.createMemoryRegions(sandboxId, config);
637
-
638
- // Disparar workflow na plataforma
639
- await this.triggerWorkflow(sandboxId, platform, config);
640
-
641
- return sandboxId;
642
- }
643
-
644
- private selectPlatform(config: SandboxConfig): string {
645
- if (config.gpuEnabled) return 'huggingface';
646
- if (config.ramLimit > 16384) return 'gitlab';
647
- return 'github'; // Padrão: ilimitado para públicos
648
- }
649
-
650
- private async createMemoryRegions(sandboxId: string, config: SandboxConfig) {
651
- const regions = [
652
- { type: 'zram', mountPoint: '/swap', sizeBytes: config.ramLimit * 1024 * 1024 },
653
- { type: 'tmpfs', mountPoint: '/tmp', sizeBytes: 4 * 1024 * 1024 * 1024 },
654
- { type: 'tmpfs', mountPoint: '/workspace', sizeBytes: 4 * 1024 * 1024 * 1024 },
655
- { type: 'overlay', mountPoint: '/overlay', sizeBytes: 2 * 1024 * 1024 * 1024 },
656
- { type: 'sqlite', mountPoint: ':memory:', sizeBytes: 512 * 1024 * 1024 },
657
- ];
658
-
659
- for (const region of regions) {
660
- await db.insert(memoryRegions).values({
661
- id: `${sandboxId}-${region.type}`,
662
- sandboxId,
663
- type: region.type,
664
- mountPoint: region.mountPoint,
665
- sizeBytes: region.sizeBytes,
666
- createdAt: new Date().toISOString(),
667
- });
668
- }
669
- }
670
-
671
- private async triggerWorkflow(sandboxId: string, platform: string, config: SandboxConfig) {
672
- switch (platform) {
673
- case 'github':
674
- await this.triggerGitHubWorkflow(sandboxId, config);
675
- break;
676
- case 'gitlab':
677
- await this.triggerGitLabPipeline(sandboxId, config);
678
- break;
679
- case 'forgejo':
680
- await this.triggerForgejoWorkflow(sandboxId, config);
681
- break;
682
- case 'huggingface':
683
- await this.triggerHuggingFaceSpace(sandboxId, config);
684
- break;
685
- }
686
- }
687
-
688
- private async triggerGitHubWorkflow(sandboxId: string, config: SandboxConfig) {
689
- const workflow = this.generateGitHubWorkflow(sandboxId, config);
690
-
691
- // Criar repositório
692
- await fetch(`https://api.github.com/orgs/${process.env.GITHUB_ORG}/repos`, {
693
- method: 'POST',
694
- headers: {
695
- 'Authorization': `token ${process.env.GITHUB_TOKEN}`,
696
- 'Content-Type': 'application/json',
697
- },
698
- body: JSON.stringify({
699
- name: `sandbox-${sandboxId}`,
700
- private: true,
701
- auto_init: true,
702
- }),
703
- });
704
-
705
- // Criar workflow
706
- await fetch(
707
- `https://api.github.com/repos/${process.env.GITHUB_ORG}/sandbox-${sandboxId}/contents/.github/workflows/sandbox.yml`,
708
- {
709
- method: 'PUT',
710
- headers: {
711
- 'Authorization': `token ${process.env.GITHUB_TOKEN}`,
712
- 'Content-Type': 'application/json',
713
- },
714
- body: JSON.stringify({
715
- message: 'Create sandbox workflow',
716
- content: Buffer.from(workflow).toString('base64'),
717
- }),
718
- }
719
- );
720
-
721
- // Disparar workflow
722
- await fetch(
723
- `https://api.github.com/repos/${process.env.GITHUB_ORG}/sandbox-${sandboxId}/actions/workflows/sandbox.yml/dispatches`,
724
- {
725
- method: 'POST',
726
- headers: {
727
- 'Authorization': `token ${process.env.GITHUB_TOKEN}`,
728
- 'Content-Type': 'application/json',
729
- },
730
- body: JSON.stringify({
731
- ref: 'main',
732
- inputs: {
733
- ram_limit: `${config.ramLimit}M`,
734
- cpu_limit: config.cpuLimit.toString(),
735
- packages: config.packages?.join(' ') || '',
736
- },
737
- }),
738
- }
739
- );
740
- }
741
-
742
- private generateGitHubWorkflow(sandboxId: string, config: SandboxConfig): string {
743
- return `
744
- name: Sandbox ${sandboxId}
745
-
746
- on:
747
- workflow_dispatch:
748
- inputs:
749
- ram_limit:
750
- default: '${config.ramLimit}M'
751
- cpu_limit:
752
- default: '${config.cpuLimit}'
753
- packages:
754
- default: '${config.packages?.join(' ') || ''}'
755
-
756
- jobs:
757
- sandbox:
758
- runs-on: ubuntu-latest
759
-
760
- container:
761
- image: ubuntu:22.04
762
- options: >-
763
- --memory \${{ github.event.inputs.ram_limit }}
764
- --cpus \${{ github.event.inputs.cpu_limit }}
765
- --tmpfs /tmp:size=4G
766
- --tmpfs /run:size=2G
767
- --tmpfs /workspace:size=4G
768
-
769
- steps:
770
- - name: Setup zram (storage → RAM comprimida)
771
- run: |
772
- modprobe zram
773
- echo lz4 > /sys/block/zram0/comp_algorithm
774
- echo 8G > /sys/block/zram0/disksize
775
- mkswap /dev/zram0
776
- swapon /dev/zram0
777
- echo "=== zram configurado ==="
778
- zramctl
779
-
780
- - name: Setup tmpfs (storage → RAM puro)
781
- run: |
782
- mount -t tmpfs -o size=4G tmpfs /workspace
783
- mount -t tmpfs -o size=2G tmpfs /tmp
784
- echo "=== tmpfs configurado ==="
785
- df -h /workspace /tmp
786
-
787
- - name: Setup overlay (CoW em RAM)
788
- run: |
789
- mkdir -p /overlay-upper /overlay-work /merged
790
- mount -t overlay overlay \\
791
- -o lowerdir=/lower,upperdir=/overlay-upper,workdir=/overlay-work \\
792
- /merged
793
- echo "=== overlay configurado ==="
794
-
795
- - name: Install packages
796
- run: |
797
- apt-get update
798
- apt-get install -y \${{ github.event.inputs.packages }}
799
-
800
- - name: Setup SQLite in-memory
801
- run: |
802
- echo "=== SQLite in-memory configurado ==="
803
- echo "Banco de dados em RAM, zero I/O disco"
804
-
805
- - name: Verify resources
806
- run: |
807
- echo "=== RAM ==="
808
- free -h
809
- echo "=== zram ==="
810
- zramctl
811
- echo "=== tmpfs ==="
812
- df -h /workspace /tmp
813
- echo "=== Disk ==="
814
- df -h /
815
- echo "=== CPU ==="
816
- nproc
817
-
818
- - name: Run sandbox
819
- working-directory: /workspace
820
- run: |
821
- echo "Sandbox ${sandboxId} is running!"
822
- echo "RAM total: \$(free -h | grep Mem | awk '{print \$2}')"
823
- echo "RAM comprimida (zram): \$(zramctl | tail -1 | awk '{print \$4}')"
824
- echo "tmpfs /workspace: \$(df -h /workspace | tail -1 | awk '{print \$2}')"
825
-
826
- # Manter sandbox vivo
827
- sleep 3600
828
- `;
829
- }
830
- }
831
- 4.6 Memória Virtual (memfs + Bridge)
832
- // src/memory/virtual-memory.ts
833
- import { fs, Volume } from 'memfs';
834
-
835
- export class VirtualMemory {
836
- private volumes: Map<string, ReturnType<typeof Volume.create>> = new Map();
837
-
838
- constructor() {
839
- // Criar volumes em RAM
840
- this.createVolume('system', 8 * 1024 * 1024 * 1024); // 8 GB
841
- this.createVolume('workspace', 4 * 1024 * 1024 * 1024); // 4 GB
842
- this.createVolume('packages', 2 * 1024 * 1024 * 1024); // 2 GB
843
- }
844
-
845
- private createVolume(name: string, sizeBytes: number) {
846
- const vol = Volume.create({ size: sizeBytes });
847
- this.volumes.set(name, vol);
848
- fs.mountVol(`/${name}`, vol);
849
- }
850
-
851
- // Ler arquivo da memória virtual
852
- async read(path: string): Promise<Buffer> {
853
- return new Promise((resolve, reject) => {
854
- fs.readFile(path, (err, data) => {
855
- if (err) reject(err);
856
- else resolve(data as Buffer);
857
- });
858
- });
859
- }
860
-
861
- // Escrever arquivo na memória virtual
862
- async write(path: string, data: Buffer): Promise<void> {
863
- return new Promise((resolve, reject) => {
864
- fs.writeFile(path, data, (err) => {
865
- if (err) reject(err);
866
- else resolve();
867
- });
868
- });
869
- }
870
-
871
- // Cache de pacotes npm em RAM
872
- async cachePackage(name: string, version: string, data: Buffer): Promise<string> {
873
- const path = `/packages/${name}@${version}.js`;
874
- await this.write(path, data);
875
- return path;
876
- }
877
-
878
- // Ler pacote do cache
879
- async getCachedPackage(name: string, version: string): Promise<Buffer | null> {
880
- const path = `/packages/${name}@${version}.js`;
881
- try {
882
- return await this.read(path);
883
- } catch {
884
- return null;
885
- }
886
- }
887
- }
888
- 4.7 GitHub como Storage (converte repo → RAM)
889
- // src/memory/github-fs.ts
890
- export class GitHubFileSystem {
891
- private token: string;
892
- private cache: Map<string, Buffer> = new Map();
893
-
894
- constructor(token: string) {
895
- this.token = token;
896
- }
897
-
898
- // Ler arquivo do GitHub e cachear em RAM
899
- async readFile(owner: string, repo: string, path: string): Promise<Buffer> {
900
- const cacheKey = `${owner}/${repo}/${path}`;
901
-
902
- // Verificar cache
903
- if (this.cache.has(cacheKey)) {
904
- return this.cache.get(cacheKey)!;
905
- }
906
-
907
- // Buscar do GitHub
908
- const response = await fetch(
909
- `https://api.github.com/repos/${owner}/${repo}/contents/${path}`,
910
- {
911
- headers: {
912
- 'Authorization': `token ${this.token}`,
913
- 'Accept': 'application/vnd.github.v3.raw',
914
- },
915
- }
916
- );
917
-
918
- const data = Buffer.from(await response.arrayBuffer());
919
-
920
- // Cachear em RAM
921
- this.cache.set(cacheKey, data);
922
-
923
- return data;
924
- }
925
-
926
- // Listar arquivos do repositório
927
- async listFiles(owner: string, repo: string, path: string = ''): Promise<string[]> {
928
- const response = await fetch(
929
- `https://api.github.com/repos/${owner}/${repo}/contents/${path}`,
930
- {
931
- headers: {
932
- 'Authorization': `token ${this.token}`,
933
- },
934
- }
935
- );
936
-
937
- const files = await response.json();
938
- return files.map((f: any) => f.path);
939
- }
940
-
941
- // Hidratar filesystem inteiro em RAM
942
- async hydrateRepo(owner: string, repo: string): Promise<Map<string, Buffer>> {
943
- const files = await this.listFiles(owner, repo);
944
-
945
- for (const file of files) {
946
- await this.readFile(owner, repo, file);
947
- }
948
-
949
- return this.cache;
950
- }
951
-
952
- // Obter estatísticas do cache
953
- getStats(): { files: number; totalSize: number } {
954
- let totalSize = 0;
955
- for (const buffer of this.cache.values()) {
956
- totalSize += buffer.length;
957
- }
958
- return {
959
- files: this.cache.size,
960
- totalSize,
961
- };
962
- }
963
- }
964
- 4.8 API Principal (Cloudflare Workers)
965
- // src/index.ts
966
- import { Hono } from 'hono';
967
- import { SandboxOrchestrator } from './orchestrator';
968
- import { VirtualMemory } from './memory/virtual-memory';
969
- import { GitHubFileSystem } from './memory/github-fs';
970
-
971
- const app = new Hono();
972
- const orchestrator = new SandboxOrchestrator();
973
- const memory = new VirtualMemory();
974
-
975
- // Criar sandbox
976
- app.post('/api/sandbox', async (c) => {
977
- const body = await c.req.json();
978
-
979
- const sandboxId = await orchestrator.createSandbox({
980
- userId: body.userId,
981
- ramLimit: body.ramLimit || 8192,
982
- cpuLimit: body.cpuLimit || 4,
983
- gpuEnabled: body.gpuEnabled || false,
984
- packages: body.packages || [],
985
- platform: body.platform,
986
- ttl: body.ttl || 24,
987
- });
988
-
989
- return c.json({ sandboxId, status: 'creating' });
990
- });
991
-
992
- // Status da sandbox
993
- app.get('/api/sandbox/:id', async (c) => {
994
- const id = c.req.param('id');
995
- // Buscar do banco em memória
996
- return c.json({ id, status: 'running' });
997
- });
998
-
999
- // Memória virtual
1000
- app.get('/api/memory/stats', async (c) => {
1001
- return c.json({
1002
- zram: '8GB comprimida',
1003
- tmpfs: '4GB /workspace + 2GB /tmp',
1004
- overlay: '2GB CoW',
1005
- sqlite: '512MB in-memory',
1006
- github: 'Cache de repositórios',
1007
- });
1008
- });
1009
-
1010
- // GitHub como storage
1011
- app.post('/api/github/hydrate', async (c) => {
1012
- const { owner, repo } = await c.req.json();
1013
-
1014
- const githubFs = new GitHubFileSystem(process.env.GITHUB_TOKEN!);
1015
- const files = await githubFs.hydrateRepo(owner, repo);
1016
-
1017
- return c.json({
1018
- files: files.size,
1019
- status: 'hydrated in RAM',
1020
- });
1021
- });
1022
-
1023
- // CDN endpoint
1024
- app.get('/cdn/:package/:version', async (c) => {
1025
- const { package: pkg, version } = c.req.param();
1026
-
1027
- // Buscar do cache em RAM
1028
- const cached = await memory.getCachedPackage(pkg, version);
1029
- if (cached) {
1030
- return new Response(cached, {
1031
- headers: { 'Content-Type': 'application/javascript' },
1032
- });
1033
- }
1034
-
1035
- // Buscar do jsdelivr
1036
- const response = await fetch(
1037
- `https://cdn.jsdelivr.net/npm/${pkg}@${version}/+esm`
1038
- );
1039
-
1040
- const data = Buffer.from(await response.arrayBuffer());
1041
- await memory.cachePackage(pkg, version, data);
1042
-
1043
- return new Response(data, {
1044
- headers: { 'Content-Type': 'application/javascript' },
1045
- });
1046
- });
1047
-
1048
- export default app;
1049
- 4.9 Wrangler Config (Cloudflare Workers)
1050
- # wrangler.toml
1051
- name = "sandbox-platform"
1052
- main = "src/index.ts"
1053
- compatibility_date = "2024-01-01"
1054
-
1055
- [vars]
1056
- GITHUB_ORG = "your-org"
1057
- GITLAB_TOKEN = ""
1058
- FORGEJO_TOKEN = ""
1059
- HF_TOKEN = ""
1060
-
1061
- # R2 Bucket para storage persistente
1062
- [[r2_buckets]]
1063
- binding = "STORAGE"
1064
- bucket_name = "sandbox-storage"
1065
-
1066
- # Durable Objects para estado
1067
- [[durable_objects.bindings]]
1068
- name = "SANDBOX_STATE"
1069
- class_name = "SandboxState"
1070
-
1071
- PARTE 5: CDN + EXECUÇÃO GLOBAL
1072
- 5.1 Uso via CDN (jsdelivr/esm.sh)
1073
- // Qualquer pessoa pode usar em qualquer lugar:
1074
- import { SandboxOrchestrator } from 'https://esm.run/@sandbox-platform/core';
1075
-
1076
- const orchestrator = new SandboxOrchestrator();
1077
-
1078
- // Criar sandbox
1079
- const sandbox = await orchestrator.createSandbox({
1080
- userId: 'user123',
1081
- ramLimit: 8192,
1082
- packages: ['nodejs', 'python3'],
1083
- });
1084
-
1085
- // Usar GitHub como storage
1086
- import { GitHubFileSystem } from 'https://esm.run/@sandbox-platform/core/memory';
1087
-
1088
- const githubFs = new GitHubFileSystem(token);
1089
- const files = await githubFs.hydrateRepo('owner', 'repo');
1090
-
1091
- // Usar memória virtual
1092
- import { VirtualMemory } from 'https://esm.run/@sandbox-platform/core/memory';
1093
-
1094
- const memory = new VirtualMemory();
1095
- await memory.write('/workspace/code.js', Buffer.from('console.log("hello")'));
1096
- 5.2 Uso via npm
1097
- npm install @sandbox-platform/core
1098
- import { SandboxOrchestrator } from '@sandbox-platform/core';
1099
- import { VirtualMemory, GitHubFileSystem } from '@sandbox-platform/core/memory';
1100
-
1101
- PARTE 6: RESUMO DOS RECURSOS
1102
- Infraestrutura Gratuita Disponível:
1103
-
1104
-
1105
-
1106
- Componente
1107
- Fonte Gratuita
1108
- RAM/CPU
1109
-
1110
-
1111
-
1112
- CI/CD
1113
- GitHub Actions (público)
1114
- 16 GB RAM, 4 vCPU
1115
-
1116
-
1117
- GPU
1118
- Kaggle Notebooks
1119
- 29 GB RAM, T4 x2
1120
-
1121
-
1122
- Storage
1123
- Cloudflare R2
1124
- 10 GB grátis
1125
-
1126
-
1127
- CDN
1128
- jsdelivr/esm.sh
1129
- Ilimitado
1130
-
1131
-
1132
- Database
1133
- SQLite in-memory
1134
- Voluntário
1135
-
1136
-
1137
- Orquestrador
1138
- Cloudflare Workers
1139
- 100K req/dia
1140
-
1141
-
1142
- Filesystem
1143
- memfs (RAM)
1144
- Voluntário
1145
-
1146
-
1147
- GitHub como DB
1148
- github-storage
1149
- 5000 req/hora
1150
-
1151
-
1152
- Conversão Storage → RAM:
1153
-
1154
-
1155
-
1156
- Método
1157
- Comando
1158
- Resultado
1159
-
1160
-
1161
-
1162
- zram
1163
- modprobe zram && echo lz4 > /sys/block/zram0/comp_algorithm
1164
- 4 GB storage → ~12 GB RAM comprimida
1165
-
1166
-
1167
- tmpfs
1168
- mount -t tmpfs -o size=4G tmpfs /workspace
1169
- 4 GB storage → 4 GB RAM
1170
-
1171
-
1172
- overlay
1173
- mount -t overlay overlay -o lowerdir=/lower,upperdir=/upper
1174
- CoW em RAM
1175
-
1176
-
1177
- SQLite
1178
- new Database(':memory:')
1179
- Banco relacional em RAM
1180
-
1181
-
1182
- memfs
1183
- Volume.create({ size: 8*1024*1024*1024 })
1184
- Filesystem em RAM
1185
-
1186
-
1187
- GitHub cache
1188
- githubFs.readFile() → cache.set()
1189
- Repo inteiro em RAM
1190
-
1191
- PLANO COMPLETO FINAL
1192
- O que você pode fazer AGORA:
1193
- Opção 1: Criar o projeto completo
1194
-
1195
- Criar a estrutura de pastas
1196
- Configurar package.json com todas as dependências
1197
- Implementar Drizzle ORM com SQLite em memória
1198
- Implementar memória virtual (memfs)
1199
- Implementar GitHub como storage
1200
- Configurar Cloudflare Workers
1201
- Criar workflows de CI/CD
1202
-
1203
- Opção 2: Focar em uma parte específica
1204
-
1205
- Apenas a memória virtual (zram + tmpfs + memfs)
1206
- Apenas o orquestrador (GitHub + GitLab + Forgejo)
1207
- Apenas o CDN (jsdelivr + esm.sh)
1208
- Apenas o banco em memória (Drizzle + SQLite)
1209
-
1210
- Opção 3: Criar o pacote npm primeiro
1211
-
1212
- Criar @sandbox-platform/core
1213
- Publicar no npm
1214
- Disponibilizar via CDN
1215
- Criar documentação
1216
-
1217
- Recursos 100% Gratuitos:
1218
-
1219
- ✅ GitHub Actions (público): 16 GB RAM, ilimitado
1220
- ✅ Kaggle: 29 GB RAM, GPU T4 x2
1221
- ✅ Cloudflare Workers: 100K req/dia
1222
- ✅ Cloudflare R2: 10 GB storage
1223
- ✅ jsdelivr CDN: ilimitado
1224
- ✅ SQLite in-memory: zero custo
1225
- ✅ memfs: filesystem em RAM
1226
-
1227
- O que você quer implementar primeiro?