@rotifer/playground 0.2.0-alpha.1 → 0.4.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +62 -0
- package/README.md +38 -17
- package/README.zh.md +26 -13
- package/dist/cloud/auth.d.ts +14 -0
- package/dist/cloud/auth.d.ts.map +1 -0
- package/dist/cloud/auth.js +129 -0
- package/dist/cloud/auth.js.map +1 -0
- package/dist/cloud/client.d.ts +30 -0
- package/dist/cloud/client.d.ts.map +1 -0
- package/dist/cloud/client.js +299 -0
- package/dist/cloud/client.js.map +1 -0
- package/dist/cloud/index.d.ts +4 -0
- package/dist/cloud/index.d.ts.map +1 -0
- package/dist/cloud/index.js +20 -0
- package/dist/cloud/index.js.map +1 -0
- package/dist/cloud/types.d.ts +73 -0
- package/dist/cloud/types.d.ts.map +1 -0
- package/dist/cloud/types.js +7 -0
- package/dist/cloud/types.js.map +1 -0
- package/dist/commands/arena-list.d.ts.map +1 -1
- package/dist/commands/arena-list.js +51 -1
- package/dist/commands/arena-list.js.map +1 -1
- package/dist/commands/arena-submit.d.ts.map +1 -1
- package/dist/commands/arena-submit.js +35 -1
- package/dist/commands/arena-submit.js.map +1 -1
- package/dist/commands/arena-watch.d.ts.map +1 -1
- package/dist/commands/arena-watch.js +96 -2
- package/dist/commands/arena-watch.js.map +1 -1
- package/dist/commands/compile.d.ts.map +1 -1
- package/dist/commands/compile.js +28 -7
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/install.d.ts +3 -0
- package/dist/commands/install.d.ts.map +1 -0
- package/dist/commands/install.js +94 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/login.d.ts +3 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +133 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +3 -0
- package/dist/commands/logout.d.ts.map +1 -0
- package/dist/commands/logout.js +53 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/publish.d.ts +3 -0
- package/dist/commands/publish.d.ts.map +1 -0
- package/dist/commands/publish.js +121 -0
- package/dist/commands/publish.js.map +1 -0
- package/dist/commands/search.d.ts +3 -0
- package/dist/commands/search.d.ts.map +1 -0
- package/dist/commands/search.js +106 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/javy-compiler.d.ts +22 -0
- package/dist/utils/javy-compiler.d.ts.map +1 -0
- package/dist/utils/javy-compiler.js +118 -0
- package/dist/utils/javy-compiler.js.map +1 -0
- package/genes/genesis-web-search/.cloud-manifest.json +6 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,68 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.4.0-alpha.1] - 2026-02-23
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Cloud Binding** — Cross-developer gene sharing via Supabase-backed REST API
|
|
13
|
+
- `rotifer login` — GitHub OAuth authentication via PKCE flow
|
|
14
|
+
- `rotifer logout` — Clear cloud credentials
|
|
15
|
+
- `rotifer publish <gene>` — Upload gene (phenotype + WASM) to cloud registry, saves `.cloud-manifest.json`
|
|
16
|
+
- `rotifer search [query]` — Search and browse cloud gene registry
|
|
17
|
+
- `rotifer install <gene-id>` — Download gene from cloud to local project
|
|
18
|
+
- Cloud Binding REST API specification (`docs/cloud-binding-api.md`)
|
|
19
|
+
- Supabase database schema with RLS policies (`supabase/migrations/001_initial.sql`)
|
|
20
|
+
- Auto-profile creation trigger (`supabase/migrations/002_auto_profile.sql`)
|
|
21
|
+
|
|
22
|
+
- **Cloud Arena** — Remote Arena competition across developers
|
|
23
|
+
- `rotifer arena submit --cloud` — Submit gene to cloud Arena
|
|
24
|
+
- `rotifer arena list --cloud` — View cloud Arena rankings
|
|
25
|
+
- `rotifer arena watch --cloud` — Real-time cloud ranking updates (polling)
|
|
26
|
+
- Server-side ranking via PostgreSQL `get_arena_rankings()` function
|
|
27
|
+
|
|
28
|
+
- **Endpoint-agnostic design** — CLI supports custom Cloud Binding endpoints via `--endpoint` flag or `~/.rotifer/cloud.json` config, enabling multiple deployments (global Supabase + rotifer.cloud China)
|
|
29
|
+
|
|
30
|
+
- **Supabase CLI integration** — Project linked via `supabase link`, migrations pushed via `supabase db push`
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
|
|
34
|
+
- OAuth login: switched from implicit flow to PKCE for secure token exchange
|
|
35
|
+
- Missing user profile on first login: added DB trigger `handle_new_user()` with backfill
|
|
36
|
+
- `rotifer publish` now saves `.cloud-manifest.json` in source gene dir for `arena submit --cloud` linkage
|
|
37
|
+
- `rotifer publish` graceful error when not logged in (was showing raw stack trace)
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
|
|
41
|
+
- CLI description updated from "local development environment" to "development environment" (reflects cloud capabilities)
|
|
42
|
+
- Test count: 91 → 114 (23 new cloud tests)
|
|
43
|
+
|
|
44
|
+
## [0.3.0-alpha.1] - 2026-02-17
|
|
45
|
+
|
|
46
|
+
### Added
|
|
47
|
+
|
|
48
|
+
- **TS→WASM Auto-Compilation** (Javy / QuickJS)
|
|
49
|
+
- `rotifer compile` auto-detects `index.ts`/`index.js` and compiles to Native WASM
|
|
50
|
+
- Pipeline: TypeScript → esbuild (bundle) → WASI shim → Javy (QuickJS→WASM) → Rotifer IR
|
|
51
|
+
- New `--lang <ts|wasm>` option to force compilation mode
|
|
52
|
+
- `javy-compiler.ts` utility with `compileTypeScriptToWasm()`, `isJavyAvailable()`, `findGeneSource()`
|
|
53
|
+
|
|
54
|
+
- **WASI Sandbox Support** (`rotifer-core::sandbox`)
|
|
55
|
+
- `WasmtimeSandbox` now supports both Direct (`express`) and WASI (`_start`) execution modes
|
|
56
|
+
- Minimal WASI shim: 9 host functions (`fd_read`, `fd_write`, `clock_time_get`, etc.)
|
|
57
|
+
- Auto-detection of WASI vs Direct modules at runtime
|
|
58
|
+
|
|
59
|
+
- **IR Verifier Updates**
|
|
60
|
+
- SIMD instructions downgraded from error to warning (common in Javy/QuickJS output)
|
|
61
|
+
- `_start` entry point accepted alongside `express` for WASI modules
|
|
62
|
+
|
|
63
|
+
### Changed
|
|
64
|
+
|
|
65
|
+
- Test coverage: 180 → 275 tests (91 TypeScript + 184 Rust)
|
|
66
|
+
- Documentation updated across README (EN/ZH), Getting Started (EN/ZH), and website
|
|
67
|
+
|
|
68
|
+
[0.3.0-alpha.1]: https://github.com/rotifer-protocol/rotifer-playground/releases/tag/v0.3.0-alpha.1
|
|
69
|
+
|
|
8
70
|
## [0.2.0-alpha.1] - 2026-02-22
|
|
9
71
|
|
|
10
72
|
### Added
|
package/README.md
CHANGED
|
@@ -5,10 +5,11 @@
|
|
|
5
5
|
[](LICENSE)
|
|
6
6
|
[](https://nodejs.org/)
|
|
7
7
|
[](https://github.com/rotifer-protocol/rotifer-spec)
|
|
8
|
+
[](https://discord.gg/6d4JrfMr)
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
Development environment for the **Rotifer Protocol** — build genes, compete in Arenas, share via Cloud, and simulate agent evolution.
|
|
10
11
|
|
|
11
|
-
> **Status:** Alpha (v0.
|
|
12
|
+
> **Status:** Alpha (v0.4.0-alpha.1). Core gene lifecycle, IR compiler pipeline, parallel algebra, **TS→WASM auto-compilation (Javy)**, **Cloud Binding (publish/search/install)**, and live Arena watching are functional.
|
|
12
13
|
|
|
13
14
|
---
|
|
14
15
|
|
|
@@ -82,13 +83,18 @@ Your existing code becomes a gene and competes in the Arena.
|
|
|
82
83
|
|
|
83
84
|
### Act 3 — Hooked (30 minutes)
|
|
84
85
|
|
|
85
|
-
Write a
|
|
86
|
+
Write a TypeScript gene and compile it to Native WASM automatically:
|
|
86
87
|
|
|
87
88
|
```bash
|
|
88
|
-
# Write a
|
|
89
|
-
mkdir genes/my-search &&
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
# Write a gene in TypeScript — same language, zero learning curve
|
|
90
|
+
mkdir genes/my-search && cat > genes/my-search/index.ts << 'EOF'
|
|
91
|
+
export function express(input: { query: string }) {
|
|
92
|
+
return { results: [`Found: ${input.query}`], total: 1 };
|
|
93
|
+
}
|
|
94
|
+
EOF
|
|
95
|
+
|
|
96
|
+
rotifer wrap my-search --domain search
|
|
97
|
+
rotifer compile my-search # TS → JS → WASM (Javy) → Rotifer IR
|
|
92
98
|
rotifer arena submit my-search # Watch it climb the rankings
|
|
93
99
|
rotifer arena list --domain search # Compare against Genesis genes
|
|
94
100
|
|
|
@@ -100,6 +106,8 @@ rotifer agent list
|
|
|
100
106
|
rotifer agent run search-bot --input '{"query":"rotifer protocol"}'
|
|
101
107
|
```
|
|
102
108
|
|
|
109
|
+
**v0.3 highlight:** `rotifer compile` auto-detects TypeScript genes and compiles them to Native WASM via [Javy](https://github.com/bytecodealliance/javy) (QuickJS→WASM). No separate toolchain required.
|
|
110
|
+
|
|
103
111
|
---
|
|
104
112
|
|
|
105
113
|
## Architecture
|
|
@@ -110,12 +118,14 @@ playground/
|
|
|
110
118
|
│ ├── rotifer-core/ Rust: types, sandbox, arena, algebra, fitness, storage
|
|
111
119
|
│ └── rotifer-napi/ napi-rs bridge: Rust ↔ Node.js FFI
|
|
112
120
|
├── src/ TypeScript CLI (commander.js)
|
|
113
|
-
│ ├── commands/
|
|
114
|
-
│ ├──
|
|
121
|
+
│ ├── commands/ 16 CLI commands
|
|
122
|
+
│ ├── cloud/ Cloud Binding client (auth, API, types)
|
|
123
|
+
│ ├── utils/ Config, display, NAPI binding, Javy compiler
|
|
115
124
|
│ └── errors/ Rust-style error formatting
|
|
116
125
|
├── genes/ 5 Genesis genes (bundled)
|
|
126
|
+
├── supabase/ Cloud Binding database migrations
|
|
117
127
|
├── templates/ Gene + composition scaffolds
|
|
118
|
-
└── tests/ Unit + E2E test suites (
|
|
128
|
+
└── tests/ Unit + E2E test suites (114 tests)
|
|
119
129
|
```
|
|
120
130
|
|
|
121
131
|
### Layers
|
|
@@ -124,7 +134,7 @@ playground/
|
|
|
124
134
|
|-------|-----------|----------------|
|
|
125
135
|
| **CLI** | TypeScript + commander.js | User interface, command routing, display |
|
|
126
136
|
| **Bridge** | napi-rs (cdylib) | Rust-to-Node.js FFI binding |
|
|
127
|
-
| **Core** | Rust + wasmtime | WASM sandbox, Arena engine, Algebra executor, Fitness computation, SQLite storage |
|
|
137
|
+
| **Core** | Rust + wasmtime | WASM sandbox (Direct + WASI), Arena engine, Algebra executor, Fitness computation, SQLite storage |
|
|
128
138
|
|
|
129
139
|
---
|
|
130
140
|
|
|
@@ -136,10 +146,15 @@ playground/
|
|
|
136
146
|
| `rotifer scan [path]` | Scan source files for candidate gene functions |
|
|
137
147
|
| `rotifer wrap <name>` | Wrap a function as a Rotifer gene |
|
|
138
148
|
| `rotifer test [name]` | Test a gene in L2 sandbox |
|
|
139
|
-
| `rotifer compile [name]` | Compile
|
|
140
|
-
| `rotifer arena submit <name>` | Submit a gene to the Arena |
|
|
141
|
-
| `rotifer arena list` | List Arena rankings |
|
|
142
|
-
| `rotifer arena watch <domain>` | Watch Arena rankings (
|
|
149
|
+
| `rotifer compile [name]` | Compile gene to Rotifer IR (auto TS→WASM via Javy) |
|
|
150
|
+
| `rotifer arena submit <name>` | Submit a gene to the Arena (`--cloud` for Cloud Arena) |
|
|
151
|
+
| `rotifer arena list` | List Arena rankings (`--cloud` for Cloud Arena) |
|
|
152
|
+
| `rotifer arena watch <domain>` | Watch Arena rankings live (`--cloud` for Cloud Arena) |
|
|
153
|
+
| `rotifer login` | Log in to Rotifer Cloud via GitHub OAuth |
|
|
154
|
+
| `rotifer logout` | Log out from Rotifer Cloud |
|
|
155
|
+
| `rotifer publish <name>` | Publish a gene to Rotifer Cloud |
|
|
156
|
+
| `rotifer search [query]` | Search genes on Rotifer Cloud |
|
|
157
|
+
| `rotifer install <gene-id>` | Install a gene from Rotifer Cloud |
|
|
143
158
|
| `rotifer agent create <name>` | Create an Agent with a genome |
|
|
144
159
|
| `rotifer agent list` | List all agents |
|
|
145
160
|
| `rotifer agent run <name>` | Execute an agent's genome pipeline |
|
|
@@ -185,7 +200,7 @@ cd playground
|
|
|
185
200
|
# TypeScript CLI
|
|
186
201
|
npm install
|
|
187
202
|
npm run build # Build to dist/
|
|
188
|
-
npm test # Run
|
|
203
|
+
npm test # Run 114 TypeScript tests
|
|
189
204
|
npm run lint # Type check only
|
|
190
205
|
|
|
191
206
|
# Rust Core (requires Rust toolchain)
|
|
@@ -216,11 +231,17 @@ Changes driven by implementation feedback are proposed through the ADR process.
|
|
|
216
231
|
|
|
217
232
|
- [x] **v0.1.0-alpha.1** — Core CLI + Genesis genes + Arena
|
|
218
233
|
- [x] **v0.2.0-alpha.1** — IR compiler pipeline, live Arena watching, NAPI bridge, end-to-end demo loop
|
|
219
|
-
- [
|
|
234
|
+
- [x] **v0.3.0-alpha.1** — Frontend SDK: TS→WASM auto-compilation via Javy, WASI sandbox support
|
|
235
|
+
- [x] **v0.4.0-alpha.1** — Cloud Binding: publish/search/install genes, Cloud Arena, GitHub OAuth
|
|
220
236
|
- [ ] **v1.0.0** — Full protocol compliance, multi-binding support, P2P HLT
|
|
221
237
|
|
|
222
238
|
---
|
|
223
239
|
|
|
240
|
+
## Community
|
|
241
|
+
|
|
242
|
+
- [Discord](https://discord.gg/6d4JrfMr) — Join the conversation
|
|
243
|
+
- [GitHub Discussions](https://github.com/rotifer-protocol/rotifer-playground/discussions) — Questions and proposals
|
|
244
|
+
|
|
224
245
|
## Contributing
|
|
225
246
|
|
|
226
247
|
See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and guidelines.
|
package/README.zh.md
CHANGED
|
@@ -5,10 +5,11 @@
|
|
|
5
5
|
[](LICENSE)
|
|
6
6
|
[](https://nodejs.org/)
|
|
7
7
|
[](https://github.com/rotifer-protocol/rotifer-spec)
|
|
8
|
+
[](https://discord.gg/6d4JrfMr)
|
|
8
9
|
|
|
9
|
-
**Rotifer Protocol**
|
|
10
|
+
**Rotifer Protocol** 的开发环境——构建基因、运行 Arena 竞争、通过 Cloud 共享、模拟代理进化。
|
|
10
11
|
|
|
11
|
-
> **状态:** Alpha (v0.
|
|
12
|
+
> **状态:** Alpha (v0.4.0-alpha.1)。核心基因生命周期、IR 编译器管线、并行代数、**TS→WASM 自动编译 (Javy)**、**Cloud Binding(发布/搜索/安装)**、实时 Arena 观察已可用。
|
|
12
13
|
|
|
13
14
|
---
|
|
14
15
|
|
|
@@ -82,13 +83,18 @@ rotifer arena list # 查看你的基因排名
|
|
|
82
83
|
|
|
83
84
|
### 第三幕——Hooked(30 分钟)
|
|
84
85
|
|
|
85
|
-
|
|
86
|
+
用 TypeScript 编写基因,自动编译为原生 WASM:
|
|
86
87
|
|
|
87
88
|
```bash
|
|
88
|
-
#
|
|
89
|
-
mkdir genes/my-search &&
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
# 用 TypeScript 写基因——同一语言,零学习成本
|
|
90
|
+
mkdir genes/my-search && cat > genes/my-search/index.ts << 'EOF'
|
|
91
|
+
export function express(input: { query: string }) {
|
|
92
|
+
return { results: [`Found: ${input.query}`], total: 1 };
|
|
93
|
+
}
|
|
94
|
+
EOF
|
|
95
|
+
|
|
96
|
+
rotifer wrap my-search --domain search
|
|
97
|
+
rotifer compile my-search # TS → JS → WASM (Javy) → Rotifer IR
|
|
92
98
|
rotifer arena submit my-search # 观察它攀升排名
|
|
93
99
|
rotifer arena list --domain search # 与 Genesis 基因对比
|
|
94
100
|
|
|
@@ -100,6 +106,8 @@ rotifer agent list
|
|
|
100
106
|
rotifer agent run search-bot --input '{"query":"rotifer protocol"}'
|
|
101
107
|
```
|
|
102
108
|
|
|
109
|
+
**v0.3 亮点:** `rotifer compile` 自动检测 TypeScript 基因,通过 [Javy](https://github.com/bytecodealliance/javy)(QuickJS→WASM)编译为原生 WASM,无需额外工具链。
|
|
110
|
+
|
|
103
111
|
---
|
|
104
112
|
|
|
105
113
|
## 架构
|
|
@@ -111,11 +119,11 @@ playground/
|
|
|
111
119
|
│ └── rotifer-napi/ napi-rs 桥接: Rust ↔ Node.js FFI
|
|
112
120
|
├── src/ TypeScript CLI (commander.js)
|
|
113
121
|
│ ├── commands/ 11 个 CLI 命令
|
|
114
|
-
│ ├── utils/ 配置、显示、NAPI
|
|
122
|
+
│ ├── utils/ 配置、显示、NAPI 绑定、Javy 编译器
|
|
115
123
|
│ └── errors/ Rust 风格的错误格式化
|
|
116
124
|
├── genes/ 5 个 Genesis 基因(内置)
|
|
117
125
|
├── templates/ 基因 + 组合脚手架模板
|
|
118
|
-
└── tests/ 单元测试 + E2E 测试(
|
|
126
|
+
└── tests/ 单元测试 + E2E 测试(91 个测试)
|
|
119
127
|
```
|
|
120
128
|
|
|
121
129
|
### 分层
|
|
@@ -124,7 +132,7 @@ playground/
|
|
|
124
132
|
|----|--------|------|
|
|
125
133
|
| **CLI** | TypeScript + commander.js | 用户界面、命令路由、显示 |
|
|
126
134
|
| **Bridge** | napi-rs (cdylib) | Rust 到 Node.js 的 FFI 绑定 |
|
|
127
|
-
| **Core** | Rust + wasmtime | WASM
|
|
135
|
+
| **Core** | Rust + wasmtime | WASM 沙箱(Direct + WASI)、Arena 引擎、Algebra 执行器、Fitness 计算、SQLite 存储 |
|
|
128
136
|
|
|
129
137
|
---
|
|
130
138
|
|
|
@@ -136,7 +144,7 @@ playground/
|
|
|
136
144
|
| `rotifer scan [path]` | 扫描源文件中的候选基因函数 |
|
|
137
145
|
| `rotifer wrap <name>` | 将函数包装为 Rotifer 基因 |
|
|
138
146
|
| `rotifer test [name]` | 在 L2 沙箱中测试基因 |
|
|
139
|
-
| `rotifer compile [name]` |
|
|
147
|
+
| `rotifer compile [name]` | 编译基因为 Rotifer IR(自动 TS→WASM via Javy) |
|
|
140
148
|
| `rotifer arena submit <name>` | 将基因提交到 Arena |
|
|
141
149
|
| `rotifer arena list` | 列出 Arena 排名 |
|
|
142
150
|
| `rotifer arena watch <domain>` | 观察 Arena 排名(MVP:占位符) |
|
|
@@ -185,7 +193,7 @@ cd playground
|
|
|
185
193
|
# TypeScript CLI
|
|
186
194
|
npm install
|
|
187
195
|
npm run build # 构建到 dist/
|
|
188
|
-
npm test # 运行
|
|
196
|
+
npm test # 运行 91 个 TypeScript 测试
|
|
189
197
|
npm run lint # 仅类型检查
|
|
190
198
|
|
|
191
199
|
# Rust Core(需要 Rust 工具链)
|
|
@@ -216,11 +224,16 @@ bash demo.sh
|
|
|
216
224
|
|
|
217
225
|
- [x] **v0.1.0-alpha.1** — 核心 CLI + Genesis 基因 + Arena
|
|
218
226
|
- [x] **v0.2.0-alpha.1** — IR 编译器管线、实时 Arena 观察、NAPI 桥接、端到端演示闭环
|
|
219
|
-
- [
|
|
227
|
+
- [x] **v0.3.0-alpha.1** — 前端 SDK:TS→WASM 自动编译 via Javy、WASI 沙箱支持
|
|
220
228
|
- [ ] **v1.0.0** — 完整协议合规、多绑定支持、P2P HLT
|
|
221
229
|
|
|
222
230
|
---
|
|
223
231
|
|
|
232
|
+
## 社区
|
|
233
|
+
|
|
234
|
+
- [Discord](https://discord.gg/6d4JrfMr) — 加入讨论
|
|
235
|
+
- [GitHub Discussions](https://github.com/rotifer-protocol/rotifer-playground/discussions) — 问题与提案
|
|
236
|
+
|
|
224
237
|
## 参与贡献
|
|
225
238
|
|
|
226
239
|
开发指南请参见 [CONTRIBUTING.md](CONTRIBUTING.md)。
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { CloudCredentials } from "./types.js";
|
|
2
|
+
export declare function loadCredentials(): CloudCredentials | null;
|
|
3
|
+
export declare function saveCredentials(creds: CloudCredentials): void;
|
|
4
|
+
export declare function clearCredentials(): void;
|
|
5
|
+
export declare function isLoggedIn(): boolean;
|
|
6
|
+
export declare function requireAuth(): CloudCredentials;
|
|
7
|
+
export declare function generateCodeVerifier(): string;
|
|
8
|
+
export declare function generateCodeChallenge(verifier: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Start a local HTTP server to receive the OAuth callback.
|
|
11
|
+
* Handles both PKCE flow (?code=...) and implicit flow (#access_token=...).
|
|
12
|
+
*/
|
|
13
|
+
export declare function waitForOAuthCallback(port?: number): Promise<string>;
|
|
14
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/cloud/auth.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAkBnD,wBAAgB,eAAe,IAAI,gBAAgB,GAAG,IAAI,CAazD;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAK7D;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAMvC;AAED,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAED,wBAAgB,WAAW,IAAI,gBAAgB,CAQ9C;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,GAAE,MAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CA+DzE"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loadCredentials = loadCredentials;
|
|
4
|
+
exports.saveCredentials = saveCredentials;
|
|
5
|
+
exports.clearCredentials = clearCredentials;
|
|
6
|
+
exports.isLoggedIn = isLoggedIn;
|
|
7
|
+
exports.requireAuth = requireAuth;
|
|
8
|
+
exports.generateCodeVerifier = generateCodeVerifier;
|
|
9
|
+
exports.generateCodeChallenge = generateCodeChallenge;
|
|
10
|
+
exports.waitForOAuthCallback = waitForOAuthCallback;
|
|
11
|
+
const node_fs_1 = require("node:fs");
|
|
12
|
+
const node_path_1 = require("node:path");
|
|
13
|
+
const node_http_1 = require("node:http");
|
|
14
|
+
const node_crypto_1 = require("node:crypto");
|
|
15
|
+
const types_js_1 = require("./types.js");
|
|
16
|
+
const ROTIFER_HOME = (0, node_path_1.join)(process.env.HOME || process.env.USERPROFILE || "/tmp", ".rotifer");
|
|
17
|
+
function ensureRotiferHome() {
|
|
18
|
+
if (!(0, node_fs_1.existsSync)(ROTIFER_HOME)) {
|
|
19
|
+
(0, node_fs_1.mkdirSync)(ROTIFER_HOME, { recursive: true });
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function credentialsPath() {
|
|
23
|
+
return (0, node_path_1.join)(ROTIFER_HOME, types_js_1.CREDENTIALS_FILE);
|
|
24
|
+
}
|
|
25
|
+
function loadCredentials() {
|
|
26
|
+
const path = credentialsPath();
|
|
27
|
+
if (!(0, node_fs_1.existsSync)(path))
|
|
28
|
+
return null;
|
|
29
|
+
try {
|
|
30
|
+
const data = JSON.parse((0, node_fs_1.readFileSync)(path, "utf-8"));
|
|
31
|
+
if (data.expires_at && Date.now() > data.expires_at) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
return data;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function saveCredentials(creds) {
|
|
41
|
+
ensureRotiferHome();
|
|
42
|
+
(0, node_fs_1.writeFileSync)(credentialsPath(), JSON.stringify(creds, null, 2) + "\n", {
|
|
43
|
+
mode: 0o600,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function clearCredentials() {
|
|
47
|
+
const path = credentialsPath();
|
|
48
|
+
if ((0, node_fs_1.existsSync)(path)) {
|
|
49
|
+
(0, node_fs_1.writeFileSync)(path, "", { mode: 0o600 });
|
|
50
|
+
require("node:fs").unlinkSync(path);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function isLoggedIn() {
|
|
54
|
+
return loadCredentials() !== null;
|
|
55
|
+
}
|
|
56
|
+
function requireAuth() {
|
|
57
|
+
const creds = loadCredentials();
|
|
58
|
+
if (!creds) {
|
|
59
|
+
throw new Error("Not logged in. Run 'rotifer login' first.");
|
|
60
|
+
}
|
|
61
|
+
return creds;
|
|
62
|
+
}
|
|
63
|
+
function generateCodeVerifier() {
|
|
64
|
+
return (0, node_crypto_1.randomBytes)(32).toString("base64url");
|
|
65
|
+
}
|
|
66
|
+
function generateCodeChallenge(verifier) {
|
|
67
|
+
return (0, node_crypto_1.createHash)("sha256").update(verifier).digest("base64url");
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Start a local HTTP server to receive the OAuth callback.
|
|
71
|
+
* Handles both PKCE flow (?code=...) and implicit flow (#access_token=...).
|
|
72
|
+
*/
|
|
73
|
+
function waitForOAuthCallback(port = 9876) {
|
|
74
|
+
return new Promise((resolve, reject) => {
|
|
75
|
+
const server = (0, node_http_1.createServer)((req, res) => {
|
|
76
|
+
const url = new URL(req.url || "/", `http://localhost:${port}`);
|
|
77
|
+
if (url.pathname === "/callback/token") {
|
|
78
|
+
const token = url.searchParams.get("access_token");
|
|
79
|
+
const refresh = url.searchParams.get("refresh_token");
|
|
80
|
+
if (token) {
|
|
81
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
82
|
+
res.end("<html><body><h2>Login successful!</h2>" +
|
|
83
|
+
"<p>You can close this window and return to the terminal.</p>" +
|
|
84
|
+
"</body></html>");
|
|
85
|
+
server.close();
|
|
86
|
+
resolve(`implicit:${token}:${refresh || ""}`);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const code = url.searchParams.get("code");
|
|
91
|
+
if (code) {
|
|
92
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
93
|
+
res.end("<html><body><h2>Login successful!</h2>" +
|
|
94
|
+
"<p>You can close this window and return to the terminal.</p>" +
|
|
95
|
+
"</body></html>");
|
|
96
|
+
server.close();
|
|
97
|
+
resolve(code);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
101
|
+
res.end(`<html><body><script>
|
|
102
|
+
if (window.location.hash) {
|
|
103
|
+
var params = new URLSearchParams(window.location.hash.substring(1));
|
|
104
|
+
var token = params.get('access_token');
|
|
105
|
+
var refresh = params.get('refresh_token');
|
|
106
|
+
if (token) {
|
|
107
|
+
window.location.href = '/callback/token?access_token=' + encodeURIComponent(token) + '&refresh_token=' + encodeURIComponent(refresh || '');
|
|
108
|
+
} else {
|
|
109
|
+
document.body.innerHTML = '<h2>Login failed</h2><p>No token received.</p>';
|
|
110
|
+
}
|
|
111
|
+
} else {
|
|
112
|
+
document.body.innerHTML = '<h2>Login failed</h2><p>Missing authorization data.</p>';
|
|
113
|
+
}
|
|
114
|
+
</script><noscript>Enable JavaScript to complete login.</noscript></body></html>`);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
server.listen(port, () => {
|
|
118
|
+
// Server ready
|
|
119
|
+
});
|
|
120
|
+
server.on("error", (err) => {
|
|
121
|
+
reject(new Error(`Failed to start callback server: ${err.message}`));
|
|
122
|
+
});
|
|
123
|
+
setTimeout(() => {
|
|
124
|
+
server.close();
|
|
125
|
+
reject(new Error("Login timed out after 120 seconds"));
|
|
126
|
+
}, 120_000);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/cloud/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { CloudConfig, CloudGene, CloudGeneListResponse, CloudArenaRankings, CloudArenaEntry, FitnessReport } from "./types.js";
|
|
2
|
+
export declare function loadCloudConfig(): CloudConfig;
|
|
3
|
+
export declare function listGenes(options: {
|
|
4
|
+
domain?: string;
|
|
5
|
+
query?: string;
|
|
6
|
+
owner?: string;
|
|
7
|
+
fidelity?: string;
|
|
8
|
+
sort?: string;
|
|
9
|
+
page?: number;
|
|
10
|
+
perPage?: number;
|
|
11
|
+
}): Promise<CloudGeneListResponse>;
|
|
12
|
+
export declare function getGene(id: string): Promise<CloudGene>;
|
|
13
|
+
export declare function publishGene(opts: {
|
|
14
|
+
name: string;
|
|
15
|
+
domain: string;
|
|
16
|
+
version: string;
|
|
17
|
+
fidelity: string;
|
|
18
|
+
description: string;
|
|
19
|
+
phenotype: Record<string, unknown>;
|
|
20
|
+
wasmBytes: Buffer | null;
|
|
21
|
+
}): Promise<CloudGene>;
|
|
22
|
+
export declare function unpublishGene(id: string): Promise<void>;
|
|
23
|
+
export declare function downloadGeneWasm(wasmUrl: string): Promise<Buffer>;
|
|
24
|
+
export declare function arenaSubmit(geneId: string, fitness: FitnessReport): Promise<CloudArenaEntry>;
|
|
25
|
+
export declare function arenaRankings(options: {
|
|
26
|
+
domain?: string;
|
|
27
|
+
page?: number;
|
|
28
|
+
perPage?: number;
|
|
29
|
+
}): Promise<CloudArenaRankings>;
|
|
30
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/cloud/client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,WAAW,EACX,SAAS,EACT,qBAAqB,EACrB,kBAAkB,EAClB,eAAe,EACf,aAAa,EACd,MAAM,YAAY,CAAC;AASpB,wBAAgB,eAAe,IAAI,WAAW,CAa7C;AAgDD,wBAAsB,SAAS,CAAC,OAAO,EAAE;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CA2CjC;AAED,wBAAsB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAiC5D;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,GAAG,OAAO,CAAC,SAAS,CAAC,CA0ErB;AAED,wBAAsB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAa7D;AAED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAKvE;AAID,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,eAAe,CAAC,CAsC1B;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA0C9B"}
|