@rotifer/playground 0.8.5 → 0.9.0
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 +96 -0
- package/README.md +39 -23
- package/README.zh.md +38 -22
- package/dist/cloud/auth.d.ts +14 -4
- package/dist/cloud/auth.d.ts.map +1 -1
- package/dist/cloud/auth.js +19 -7
- package/dist/cloud/auth.js.map +1 -1
- package/dist/cloud/badge.d.ts +42 -0
- package/dist/cloud/badge.d.ts.map +1 -0
- package/dist/cloud/badge.js +67 -0
- package/dist/cloud/badge.js.map +1 -0
- package/dist/cloud/client.d.ts +14 -0
- package/dist/cloud/client.d.ts.map +1 -1
- package/dist/cloud/client.js +54 -13
- package/dist/cloud/client.js.map +1 -1
- package/dist/cloud/gene-ref.d.ts +41 -0
- package/dist/cloud/gene-ref.d.ts.map +1 -0
- package/dist/cloud/gene-ref.js +45 -0
- package/dist/cloud/gene-ref.js.map +1 -0
- package/dist/cloud/index.d.ts +1 -0
- package/dist/cloud/index.d.ts.map +1 -1
- package/dist/cloud/index.js +1 -0
- package/dist/cloud/index.js.map +1 -1
- package/dist/cloud/types.d.ts +2 -0
- package/dist/cloud/types.d.ts.map +1 -1
- package/dist/cloud/types.js +2 -1
- package/dist/cloud/types.js.map +1 -1
- package/dist/commands/agent-list.d.ts.map +1 -1
- package/dist/commands/agent-list.js +8 -1
- package/dist/commands/agent-list.js.map +1 -1
- package/dist/commands/agent-run.d.ts.map +1 -1
- package/dist/commands/agent-run.js +12 -8
- package/dist/commands/agent-run.js.map +1 -1
- package/dist/commands/arena-submit.d.ts.map +1 -1
- package/dist/commands/arena-submit.js +2 -8
- package/dist/commands/arena-submit.js.map +1 -1
- package/dist/commands/compile.d.ts.map +1 -1
- package/dist/commands/compile.js +35 -20
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/doctor.d.ts +3 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +58 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/hello.d.ts.map +1 -1
- package/dist/commands/hello.js +45 -6
- package/dist/commands/hello.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +11 -9
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/list.js +3 -3
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/network.d.ts.map +1 -1
- package/dist/commands/network.js +172 -64
- package/dist/commands/network.js.map +1 -1
- package/dist/commands/publish.d.ts.map +1 -1
- package/dist/commands/publish.js +72 -0
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/reputation.d.ts.map +1 -1
- package/dist/commands/reputation.js +51 -10
- package/dist/commands/reputation.js.map +1 -1
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +13 -4
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/test.d.ts.map +1 -1
- package/dist/commands/test.js +9 -4
- package/dist/commands/test.js.map +1 -1
- package/dist/commands/user-config.js +2 -2
- package/dist/commands/user-config.js.map +1 -1
- package/dist/commands/versions.d.ts.map +1 -1
- package/dist/commands/versions.js +34 -3
- package/dist/commands/versions.js.map +1 -1
- package/dist/commands/vg.d.ts.map +1 -1
- package/dist/commands/vg.js +7 -25
- package/dist/commands/vg.js.map +1 -1
- package/dist/commands/whoami.d.ts.map +1 -1
- package/dist/commands/whoami.js +7 -1
- package/dist/commands/whoami.js.map +1 -1
- package/dist/commands/wrap.d.ts.map +1 -1
- package/dist/commands/wrap.js +25 -2
- package/dist/commands/wrap.js.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/types/phenotype.d.ts +181 -0
- package/dist/types/phenotype.d.ts.map +1 -0
- package/dist/types/phenotype.js +87 -0
- package/dist/types/phenotype.js.map +1 -0
- package/dist/utils/binding.d.ts +28 -3
- package/dist/utils/binding.d.ts.map +1 -1
- package/dist/utils/binding.js +61 -18
- package/dist/utils/binding.js.map +1 -1
- package/dist/utils/config.js +1 -1
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/detect-source-language.d.ts +20 -0
- package/dist/utils/detect-source-language.d.ts.map +1 -0
- package/dist/utils/detect-source-language.js +83 -0
- package/dist/utils/detect-source-language.js.map +1 -0
- package/dist/utils/javy-compiler.d.ts +32 -1
- package/dist/utils/javy-compiler.d.ts.map +1 -1
- package/dist/utils/javy-compiler.js +137 -12
- package/dist/utils/javy-compiler.js.map +1 -1
- package/dist/utils/p2p-daemon.d.ts +30 -0
- package/dist/utils/p2p-daemon.d.ts.map +1 -0
- package/dist/utils/p2p-daemon.js +199 -0
- package/dist/utils/p2p-daemon.js.map +1 -0
- package/dist/utils/phenotype-validator.d.ts.map +1 -1
- package/dist/utils/phenotype-validator.js +197 -2
- package/dist/utils/phenotype-validator.js.map +1 -1
- package/dist/utils/project-root.js +1 -1
- package/dist/utils/project-root.js.map +1 -1
- package/dist/utils/sandbox-defaults.d.ts +9 -0
- package/dist/utils/sandbox-defaults.d.ts.map +1 -0
- package/dist/utils/sandbox-defaults.js +12 -0
- package/dist/utils/sandbox-defaults.js.map +1 -0
- package/dist/utils/user-config.d.ts +2 -0
- package/dist/utils/user-config.d.ts.map +1 -1
- package/dist/utils/user-config.js +12 -2
- package/dist/utils/user-config.js.map +1 -1
- package/package.json +15 -6
- package/scripts/postinstall.js +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,102 @@ 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.9.0](https://github.com/rotifer-protocol/rotifer-playground/compare/v0.8.6...v0.9.0) (2026-06-22)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* **cli:** add `rotifer doctor` toolchain health command (R5) ([049df01](https://github.com/rotifer-protocol/rotifer-playground/commit/049df012365e990cacd7bde1b909ca73485fc771))
|
|
14
|
+
* **migrations:** Sprint C Phase 4 — content_hash server-side validation ([b14740e](https://github.com/rotifer-protocol/rotifer-playground/commit/b14740e7c5c68dbae2297ec251d251ad063b8c11))
|
|
15
|
+
* **migrations:** Sprint C Phase 5 — protocol consistency v09 baseline ([6d40b06](https://github.com/rotifer-protocol/rotifer-playground/commit/6d40b0686fd31ed69de1e8545f318937670e5a24))
|
|
16
|
+
* **migrations:** Sprint C Phase 6a — downloads RLS hardening ([901263a](https://github.com/rotifer-protocol/rotifer-playground/commit/901263a9d737cb66db5900f241f237b50d4fc655))
|
|
17
|
+
* **network:** run a real libp2p node from the CLI (phase 1) ([#80](https://github.com/rotifer-protocol/rotifer-playground/issues/80)) ([1fe6f29](https://github.com/rotifer-protocol/rotifer-playground/commit/1fe6f29035f7be13c96ab5b1b416d72d7636483d))
|
|
18
|
+
* **network:** run the P2P node as a background daemon with a local control channel (phase 2) ([#81](https://github.com/rotifer-protocol/rotifer-playground/issues/81)) ([710a4b4](https://github.com/rotifer-protocol/rotifer-playground/commit/710a4b4cc85c510ba28aa385e90ccd372832ba94))
|
|
19
|
+
* **p2p:** implement application-layer security primitives (flood/replay/eclipse/sybil) ([#82](https://github.com/rotifer-protocol/rotifer-playground/issues/82)) ([a0f8a7e](https://github.com/rotifer-protocol/rotifer-playground/commit/a0f8a7e5641cabd011b76ff9f58604b32df1b0ac))
|
|
20
|
+
* **p2p:** LAN demo plumbing — configurable listen host (--host) + announcement propagation (`network received`) ([#87](https://github.com/rotifer-protocol/rotifer-playground/issues/87)) ([d94f540](https://github.com/rotifer-protocol/rotifer-playground/commit/d94f54015c1d660ba5f404cc99f03f13d4fd7842))
|
|
21
|
+
* **p2p:** real libp2p networking — identity, swarm, Kademlia DHT, GossipSub ([#74](https://github.com/rotifer-protocol/rotifer-playground/issues/74)) ([59573f3](https://github.com/rotifer-protocol/rotifer-playground/commit/59573f38d13e47d854109b4bfaab626b03b9e9ca))
|
|
22
|
+
* **p2p:** verify message signatures + authenticate gossip publishers (§3.2 iteration 2) ([#83](https://github.com/rotifer-protocol/rotifer-playground/issues/83)) ([44a5c66](https://github.com/rotifer-protocol/rotifer-playground/commit/44a5c662905b502d73f5a99b3c6d27a7240e0851))
|
|
23
|
+
* **p2p:** wire the per-peer rate limiter into the live gossip receive path (§3.2 iteration 3) ([#84](https://github.com/rotifer-protocol/rotifer-playground/issues/84)) ([027e322](https://github.com/rotifer-protocol/rotifer-playground/commit/027e3227e0188c489314feeb1fd9154a516b5d09))
|
|
24
|
+
* **phenotype:** add Hybrid Fidelity types — externalDependencies / simulationSpec / degradationSpec + FIDELITY_DISCOUNT (v0.9 §3.11) ([9403f5b](https://github.com/rotifer-protocol/rotifer-playground/commit/9403f5b1a8b6820f006fb6283bcf431530197171))
|
|
25
|
+
* **phenotype:** align gene transparency field to spec §4.2 (F8, §3.3) ([#86](https://github.com/rotifer-protocol/rotifer-playground/issues/86)) ([c725c2f](https://github.com/rotifer-protocol/rotifer-playground/commit/c725c2f95eee5efc5d2f596755d6039d2f0a0a08))
|
|
26
|
+
* **phenotype:** validator + shared types + publish/agent-list updates ([22f2ca8](https://github.com/rotifer-protocol/rotifer-playground/commit/22f2ca8a33ef1f385ea5f4917fc2a42b5bb36623))
|
|
27
|
+
* **publish:** auto V(g) badge upload + --skip-vg flag (Phase 1) ([4c47cce](https://github.com/rotifer-protocol/rotifer-playground/commit/4c47ccebc49f1c342c9b915b2cd4ded8c494b29e))
|
|
28
|
+
* **supabase:** close v0.9 stage-2 B-R6 — pgTAP all-green + TS E2E live + CI blocking ([242e413](https://github.com/rotifer-protocol/rotifer-playground/commit/242e4138a5b862ce2f282896f9c7d6f88577bd50))
|
|
29
|
+
* **supabase:** impl compute_path_diversity (v0.9 stage 2 B-R5, Ramanujan R1) ([c93950f](https://github.com/rotifer-protocol/rotifer-playground/commit/c93950f5f43661aa51867a3a3e640a2ba390eca1))
|
|
30
|
+
* **supabase:** impl get_display_fitness + get_display_weight (v0.9 stage 2 B-R3+R4) ([5e4b0e1](https://github.com/rotifer-protocol/rotifer-playground/commit/5e4b0e125b79e7e5dc4fca01be5ec41a695e84dc))
|
|
31
|
+
* **supabase:** impl reset_season() RPC + activate pg_cron (v0.9 stage 2) ([2616878](https://github.com/rotifer-protocol/rotifer-playground/commit/261687814c02f370beb792a39551169f79d0ae7a))
|
|
32
|
+
* **v0.8.8 §3.4 §3.7:** default-publish config + V(g) gate coverage ([c7983de](https://github.com/rotifer-protocol/rotifer-playground/commit/c7983de4a0f2f0ce973344d5eb6130f1e81dd4bd))
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
### Bug Fixes
|
|
36
|
+
|
|
37
|
+
* align degradationBehavior + failureSemantics with Rust IR PascalCase 5 enum ([099540c](https://github.com/rotifer-protocol/rotifer-playground/commit/099540c49969f86894297a00c1e6bfa42c7d0a94))
|
|
38
|
+
* **auth:** bind the CLI login callback to the allow-listed localhost:9876 ([#77](https://github.com/rotifer-protocol/rotifer-playground/issues/77)) ([b6179b4](https://github.com/rotifer-protocol/rotifer-playground/commit/b6179b4d046ff96a204fdb42e2225a7844027d1d))
|
|
39
|
+
* **cli/versions:** accept @owner/name single-arg form for ref-syntax parity ([95298b8](https://github.com/rotifer-protocol/rotifer-playground/commit/95298b86819d3a6d7d6fb073d8cdf2161c3c6b6d))
|
|
40
|
+
* **cli:** parse @owner/name in gene refs + route reputation + refresh whoami ([460225e](https://github.com/rotifer-protocol/rotifer-playground/commit/460225ec40ca6b4691e3f891adfd74c9a210bf00))
|
|
41
|
+
* **cloud/badge:** align uploadSafetyBadge URL with worker /safety route ([848c571](https://github.com/rotifer-protocol/rotifer-playground/commit/848c5714394b4a49f091cac00fe7e61c204b2bba))
|
|
42
|
+
* **compile:** async-express guard at compile time + offline toolchain preflight ([#57](https://github.com/rotifer-protocol/rotifer-playground/issues/57), [#58](https://github.com/rotifer-protocol/rotifer-playground/issues/58)) ([c690a9a](https://github.com/rotifer-protocol/rotifer-playground/commit/c690a9a7643024b5eff736f91042c63f4cc9ca02))
|
|
43
|
+
* **db:** make search_path pin migration replay-safe ([bc1828e](https://github.com/rotifer-protocol/rotifer-playground/commit/bc1828e25880f74d2fa6bdf729f4fd6daf8f74de))
|
|
44
|
+
* **db:** unfreeze reputation cron silent failure ([b0c7fc3](https://github.com/rotifer-protocol/rotifer-playground/commit/b0c7fc3b94519deea2125ed9a5ad2aabd03a60d9))
|
|
45
|
+
* **deps:** align @napi-rs/cli constraint to ^3.7.0 to match lockfile ([#54](https://github.com/rotifer-protocol/rotifer-playground/issues/54)) ([dada9f7](https://github.com/rotifer-protocol/rotifer-playground/commit/dada9f73aac97d914404862c377d4812026f71b7)), closes [#52](https://github.com/rotifer-protocol/rotifer-playground/issues/52)
|
|
46
|
+
* **deps:** upgrade wasmtime 42.0.2 -> 43.0.2 (RUSTSEC-2026-0114) ([20bb434](https://github.com/rotifer-protocol/rotifer-playground/commit/20bb4343821ef760a3754a7e010f83bdd818adb2))
|
|
47
|
+
* **genes:** polymarket-scanner transparency "Open" → "OPEN" (v0.3.1, F8) ([#105](https://github.com/rotifer-protocol/rotifer-playground/issues/105)) ([894db2d](https://github.com/rotifer-protocol/rotifer-playground/commit/894db2d29112e25719197c4618494a76c5bc00bf))
|
|
48
|
+
* **hello:** block incompatible fallback genome for web3 template ([6e24098](https://github.com/rotifer-protocol/rotifer-playground/commit/6e24098267fed0e8d9d7c887e7f63bc21effc300))
|
|
49
|
+
* **phenotype:** widen readonly enum arrays for .includes() type compat ([a762070](https://github.com/rotifer-protocol/rotifer-playground/commit/a762070487ecf45780877fe841e2bc2be7058b62))
|
|
50
|
+
* **release:** cover the 3 stale version surfaces in release-please ([#108](https://github.com/rotifer-protocol/rotifer-playground/issues/108)) ([5a5d75b](https://github.com/rotifer-protocol/rotifer-playground/commit/5a5d75b4788c2e772db04c1ad255821e85424062))
|
|
51
|
+
* **sandbox:** surface guest stderr on WASM trap (R4) ([95a529b](https://github.com/rotifer-protocol/rotifer-playground/commit/95a529bba601021285ff83455cb848502ea72a56))
|
|
52
|
+
* **supabase:** unblock publish — qualify digest() + degrade hash mismatch to warning ([98d1fd5](https://github.com/rotifer-protocol/rotifer-playground/commit/98d1fd5c4a2796139e5664663345ad1927702fe9))
|
|
53
|
+
* **vscode:** use vortex logo for plugin icons ([e95731e](https://github.com/rotifer-protocol/rotifer-playground/commit/e95731ea1a763463001399993614b58b5fb249c1))
|
|
54
|
+
* **wrap:** route validation errors through structured formatter, no stack-trace leak ([#55](https://github.com/rotifer-protocol/rotifer-playground/issues/55)) ([e705323](https://github.com/rotifer-protocol/rotifer-playground/commit/e70532362c5d1a4591a429ef75cb1e1afed1ec0c)), closes [#51](https://github.com/rotifer-protocol/rotifer-playground/issues/51)
|
|
55
|
+
|
|
56
|
+
## [Unreleased]
|
|
57
|
+
|
|
58
|
+
### Added
|
|
59
|
+
|
|
60
|
+
- **`rotifer doctor`** — checks the TS→WASM toolchain (esbuild / javy) offline and reports
|
|
61
|
+
per-tool status, the active `npx` path, and the Node prefix running rotifer; exits non-zero
|
|
62
|
+
when the toolchain is incomplete. Surfaces the preflight from #58 as a standalone command.
|
|
63
|
+
|
|
64
|
+
### Fixed
|
|
65
|
+
|
|
66
|
+
- **WASM runtime errors surface the guest's stderr** — when a Native gene traps, the
|
|
67
|
+
sandbox now appends anything the guest wrote to fd 2 (e.g. the Javy/QuickJS error
|
|
68
|
+
message) to the failure, instead of returning only an opaque WASM backtrace (R4)
|
|
69
|
+
- **Starter template traps in Native WASM** — `rotifer init` now scaffolds a synchronous
|
|
70
|
+
`express()`; the previous `async express()` starter compiled fine but trapped in the
|
|
71
|
+
Javy/QuickJS sandbox with an opaque backtrace (#57)
|
|
72
|
+
- **Async `express()` now rejected at compile time** — `rotifer compile` statically detects
|
|
73
|
+
`async function express` / Promise-returning signatures and fails with `E0025` and an
|
|
74
|
+
actionable message, instead of deferring to a runtime trap whose error text was swallowed
|
|
75
|
+
by the WASM host (#57)
|
|
76
|
+
- **Toolchain failures get a diagnosis instead of `spawnSync npx ETIMEDOUT`** — the TS→WASM
|
|
77
|
+
pipeline preflights esbuild/javy offline (`npx --no-install`, falling back to the `javy`
|
|
78
|
+
binary that `javy-cli@3` actually installs) and reports per-tool status, the active `npx`
|
|
79
|
+
path, and exact install commands; npx no longer hits the npm registry implicitly (#58)
|
|
80
|
+
- **Stale WASM warning on `rotifer run`** — when `index.ts` is newer than `gene.ir.wasm`,
|
|
81
|
+
run now warns that it is executing stale WASM and suggests recompiling (#58)
|
|
82
|
+
|
|
83
|
+
## [0.8.6] - 2026-04-16
|
|
84
|
+
|
|
85
|
+
### Fixed
|
|
86
|
+
|
|
87
|
+
- **Javy async Gene WASM trap** — `express()` returning a Promise now produces a clear error message instead of an opaque "Pending jobs in the event queue" WASM trap ([#29](https://github.com/rotifer-protocol/rotifer-playground/pull/29))
|
|
88
|
+
- **Compile cache ignoring source changes** — `rotifer compile` now prefers TypeScript/JavaScript source files over a stale `gene.wasm`; previously, the existing WASM was reused even after source edits ([#29](https://github.com/rotifer-protocol/rotifer-playground/pull/29))
|
|
89
|
+
- **irHash serialization mismatch** — phenotype `irHash` field is now stripped before passing to the native Rust binding, preventing serde deserialization failures on the native execution path ([#29](https://github.com/rotifer-protocol/rotifer-playground/pull/29))
|
|
90
|
+
- **WASM sandbox fuel exhaustion** — default `max_fuel` increased from 1M to 500M; default memory raised to 256 MiB; timeout extended to 60s — Javy/QuickJS Genes no longer hit "fuel exhausted" on trivial workloads ([#29](https://github.com/rotifer-protocol/rotifer-playground/pull/29))
|
|
91
|
+
|
|
92
|
+
### Added
|
|
93
|
+
|
|
94
|
+
- **Native addon distribution** — prebuilt native bindings are now shipped via platform-specific npm packages (`@rotifer/playground-darwin-arm64`, `-darwin-x64`, `-linux-x64-gnu`, `-win32-x64-msvc`); `npm install` automatically pulls the correct binary for the user's platform ([#28](https://github.com/rotifer-protocol/rotifer-playground/issues/28))
|
|
95
|
+
- **`napi-build.yml` reusable workflow** — 4-platform matrix build for native addons (macOS ARM/x64, Linux x64, Windows x64)
|
|
96
|
+
- **`sync:native-versions` script** — one-command version sync across all platform packages
|
|
97
|
+
- **Version alignment checks** — `verify:versions` now validates platform package versions and `optionalDependencies` consistency
|
|
98
|
+
|
|
99
|
+
### Changed
|
|
100
|
+
|
|
101
|
+
- Release pipeline now builds and publishes native addons before the main package (`native-build → publish-native → publish`)
|
|
102
|
+
- CI `rust-check` job now verifies napi compilation with `@napi-rs/cli` instead of `cargo build`
|
|
103
|
+
|
|
8
104
|
## [0.8.5] - 2026-04-08
|
|
9
105
|
|
|
10
106
|
### Changed
|
package/README.md
CHANGED
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
[](https://github.com/rotifer-protocol/rotifer-spec)
|
|
8
8
|
[](https://rotifer.dev/discord)
|
|
9
9
|
|
|
10
|
-
Development environment for the **Rotifer Protocol** — build genes, compete in Arenas, share via Cloud, and simulate agent evolution.
|
|
10
|
+
Development environment for the **Rotifer Protocol** — **WASM-Native, Polyglot by Design**: build genes in TypeScript / Rust / AssemblyScript / Go / C, compete in Arenas, share via Cloud, and simulate agent evolution.
|
|
11
11
|
|
|
12
|
-
> **Status:** v0.8.
|
|
12
|
+
> **Status:** v0.8.6 — CLI runtime bugfix release: fixes Javy shim async traps, compile cache staleness, irHash serde incompatibility, fuel exhaustion, and native addon distribution. All four platforms now ship prebuilt `.node` binaries via optional dependencies. See [CHANGELOG.md](CHANGELOG.md) for full release history. P2P implementation and L4 Collective Immunity are still planned — see [Implementation Status](#implementation-status) below.
|
|
13
13
|
|
|
14
14
|
---
|
|
15
15
|
|
|
@@ -22,21 +22,32 @@ npm install -g @rotifer/playground
|
|
|
22
22
|
Or use directly via npx:
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
|
-
npx @rotifer/playground init my-
|
|
25
|
+
npx -y @rotifer/playground@latest init my-agent
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
**Requirements:** Node.js >= 20.0.0
|
|
29
29
|
|
|
30
30
|
---
|
|
31
31
|
|
|
32
|
+
## First Agent in Seconds
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
rotifer init my-agent && cd my-agent
|
|
36
|
+
rotifer hello --template quality-advisor
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`rotifer init` bootstraps the local Arena and Genesis genes. `rotifer hello --template quality-advisor` is the recommended preset-agent entrypoint for a first run.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
32
43
|
## 30-Second Demo
|
|
33
44
|
|
|
34
45
|
```bash
|
|
35
|
-
$ rotifer init my-
|
|
46
|
+
$ rotifer init my-agent
|
|
36
47
|
|
|
37
|
-
Rotifer Protocol -
|
|
48
|
+
Rotifer Protocol - Agent Workspace Initialization
|
|
38
49
|
───────────────────────────────────────────
|
|
39
|
-
✓
|
|
50
|
+
✓ Agent workspace scaffolding created
|
|
40
51
|
ℹ Installing Genesis genes...
|
|
41
52
|
✓ 5 Genesis genes installed
|
|
42
53
|
|
|
@@ -52,10 +63,10 @@ $ rotifer init my-project
|
|
|
52
63
|
6 hello-world general 0.57 Wrapped
|
|
53
64
|
|
|
54
65
|
ℹ 6 genes across 5 domain(s) — Arena is alive!
|
|
55
|
-
✓
|
|
66
|
+
✓ Agent workspace ready: my-agent
|
|
56
67
|
```
|
|
57
68
|
|
|
58
|
-
One command.
|
|
69
|
+
One command boots the Arena. `rotifer hello --template quality-advisor` turns those bundled genes into your first preset agent.
|
|
59
70
|
|
|
60
71
|
---
|
|
61
72
|
|
|
@@ -64,7 +75,7 @@ One command. Five Genesis genes. A living Arena.
|
|
|
64
75
|
### Act 1 — Wow (30 seconds)
|
|
65
76
|
|
|
66
77
|
```bash
|
|
67
|
-
rotifer init my-
|
|
78
|
+
rotifer init my-agent && cd my-agent
|
|
68
79
|
```
|
|
69
80
|
|
|
70
81
|
You see an Arena with 6 genes ranked by fitness. No configuration needed.
|
|
@@ -72,21 +83,25 @@ You see an Arena with 6 genes ranked by fitness. No configuration needed.
|
|
|
72
83
|
### Act 2 — Aha (5 minutes)
|
|
73
84
|
|
|
74
85
|
```bash
|
|
75
|
-
rotifer
|
|
76
|
-
rotifer
|
|
77
|
-
rotifer test hello-world # Run sandbox tests (WASM sandbox for compiled genes)
|
|
78
|
-
rotifer test hello-world --compliance # Run structural compliance checks
|
|
79
|
-
rotifer arena submit hello-world # Submit to Arena (admission gate)
|
|
80
|
-
rotifer arena list # See your gene's ranking
|
|
86
|
+
rotifer hello --template quality-advisor # Run the recommended preset Agent
|
|
87
|
+
rotifer agent list # Inspect the generated hello-* agent
|
|
81
88
|
```
|
|
82
89
|
|
|
83
|
-
|
|
90
|
+
Bundled genes become a working preset agent in seconds.
|
|
84
91
|
|
|
85
92
|
### Act 3 — Hooked (30 minutes)
|
|
86
93
|
|
|
87
|
-
|
|
94
|
+
Turn your own code into a gene, then build a custom agent:
|
|
88
95
|
|
|
89
96
|
```bash
|
|
97
|
+
# Wrap existing code as a gene
|
|
98
|
+
rotifer scan genes/ # Discover candidate functions
|
|
99
|
+
rotifer wrap hello-world # Wrap as a gene (generates Phenotype)
|
|
100
|
+
rotifer test hello-world # Run sandbox tests (WASM sandbox for compiled genes)
|
|
101
|
+
rotifer test hello-world --compliance # Run structural compliance checks
|
|
102
|
+
rotifer arena submit hello-world # Submit to Arena (admission gate)
|
|
103
|
+
rotifer arena list # See your gene's ranking
|
|
104
|
+
|
|
90
105
|
# Write a gene in TypeScript — same language, zero learning curve
|
|
91
106
|
mkdir genes/my-search && cat > genes/my-search/index.ts << 'EOF'
|
|
92
107
|
export function express(input: { query: string }) {
|
|
@@ -95,8 +110,8 @@ export function express(input: { query: string }) {
|
|
|
95
110
|
EOF
|
|
96
111
|
|
|
97
112
|
rotifer wrap my-search --domain search
|
|
98
|
-
rotifer compile my-search
|
|
99
|
-
rotifer arena submit my-search
|
|
113
|
+
rotifer compile my-search # TS → JS → WASM → Rotifer IR
|
|
114
|
+
rotifer arena submit my-search # Watch it climb the rankings
|
|
100
115
|
rotifer arena list --domain search # Compare against Genesis genes
|
|
101
116
|
|
|
102
117
|
# Create an Agent with a gene genome (supports Seq, Par, Cond, Try)
|
|
@@ -142,17 +157,18 @@ playground/
|
|
|
142
157
|
|
|
143
158
|
## CLI Commands
|
|
144
159
|
|
|
145
|
-
Run `rotifer --help` for the grouped command list. The
|
|
160
|
+
Run `rotifer --help` for the grouped command list. The commands below cover the main local, cloud, arena, and agent workflows.
|
|
146
161
|
|
|
147
162
|
| Command | Description |
|
|
148
163
|
|---------|-------------|
|
|
149
|
-
| `rotifer init [
|
|
164
|
+
| `rotifer init [workspace-name]` | Initialize a new Agent workspace with Genesis genes |
|
|
165
|
+
| `rotifer hello [--template <id>]` | Create and run a preset agent from curated templates inside a Rotifer Agent workspace |
|
|
150
166
|
| `rotifer scan [path]` | Scan for candidate genes and local skills |
|
|
151
167
|
| `rotifer wrap <gene-name>` | Wrap a function or SKILL.md as a gene |
|
|
152
168
|
| `rotifer test [gene-name]` | Test a gene (WASM sandbox preferred, `--compliance` for structural checks) |
|
|
153
169
|
| `rotifer compile [gene-name]` | Compile gene to Rotifer IR (auto TS→WASM) |
|
|
154
170
|
| `rotifer run <gene-name>` | Execute a single local gene directly |
|
|
155
|
-
| `rotifer list` | List local genes in the current
|
|
171
|
+
| `rotifer list` | List local genes in the current Agent workspace |
|
|
156
172
|
| `rotifer login` | Log in to Rotifer Cloud (OAuth) |
|
|
157
173
|
| `rotifer logout` | Log out from Rotifer Cloud |
|
|
158
174
|
| `rotifer publish [gene-name]` | Publish gene(s) to Rotifer Cloud |
|
|
@@ -179,7 +195,7 @@ Run `rotifer --help` for the grouped command list. The CLI has **18** primary to
|
|
|
179
195
|
|
|
180
196
|
## Genesis Genes
|
|
181
197
|
|
|
182
|
-
Five pre-installed genes ship with every
|
|
198
|
+
Five pre-installed genes ship with every Agent workspace:
|
|
183
199
|
|
|
184
200
|
| Gene | Domain | Fidelity | Description |
|
|
185
201
|
|------|--------|----------|-------------|
|
package/README.zh.md
CHANGED
|
@@ -22,21 +22,32 @@ npm install -g @rotifer/playground
|
|
|
22
22
|
或通过 npx 直接使用:
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
|
-
npx @rotifer/playground init my-
|
|
25
|
+
npx -y @rotifer/playground@latest init my-agent
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
**环境要求:** Node.js >= 20.0.0
|
|
29
29
|
|
|
30
30
|
---
|
|
31
31
|
|
|
32
|
+
## 几秒钟跑通第一个 Agent
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
rotifer init my-agent && cd my-agent
|
|
36
|
+
rotifer hello --template quality-advisor
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`rotifer init` 先把本地 Arena 和 Genesis genes 建起来;`rotifer hello --template quality-advisor` 则是推荐的首次预设 Agent 入口。
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
32
43
|
## 30 秒演示
|
|
33
44
|
|
|
34
45
|
```bash
|
|
35
|
-
$ rotifer init my-
|
|
46
|
+
$ rotifer init my-agent
|
|
36
47
|
|
|
37
|
-
Rotifer Protocol -
|
|
48
|
+
Rotifer Protocol - Agent Workspace Initialization
|
|
38
49
|
───────────────────────────────────────────
|
|
39
|
-
✓
|
|
50
|
+
✓ Agent workspace scaffolding created
|
|
40
51
|
ℹ Installing Genesis genes...
|
|
41
52
|
✓ 5 Genesis genes installed
|
|
42
53
|
|
|
@@ -52,10 +63,10 @@ $ rotifer init my-project
|
|
|
52
63
|
6 hello-world general 0.57 Wrapped
|
|
53
64
|
|
|
54
65
|
ℹ 6 genes across 5 domain(s) — Arena is alive!
|
|
55
|
-
✓
|
|
66
|
+
✓ Agent workspace ready: my-agent
|
|
56
67
|
```
|
|
57
68
|
|
|
58
|
-
|
|
69
|
+
一条命令先把 Arena 跑起来;`rotifer hello --template quality-advisor` 再把这些内置基因收口成你的第一个预设 Agent。
|
|
59
70
|
|
|
60
71
|
---
|
|
61
72
|
|
|
@@ -64,7 +75,7 @@ $ rotifer init my-project
|
|
|
64
75
|
### 第一幕——Wow(30 秒)
|
|
65
76
|
|
|
66
77
|
```bash
|
|
67
|
-
rotifer init my-
|
|
78
|
+
rotifer init my-agent && cd my-agent
|
|
68
79
|
```
|
|
69
80
|
|
|
70
81
|
你将看到一个包含 6 个基因的 Arena,按适应度排名。无需任何配置。
|
|
@@ -72,22 +83,26 @@ rotifer init my-project && cd my-project
|
|
|
72
83
|
### 第二幕——Aha(5 分钟)
|
|
73
84
|
|
|
74
85
|
```bash
|
|
75
|
-
rotifer
|
|
76
|
-
rotifer
|
|
77
|
-
rotifer test hello-world # 在 L2 沙箱中运行测试(已编译基因走 WASM 沙箱)
|
|
78
|
-
rotifer test hello-world --compliance # 运行结构性合规检查
|
|
79
|
-
rotifer arena submit hello-world # 提交到 Arena(准入评估)
|
|
80
|
-
rotifer arena list # 查看你的基因排名
|
|
86
|
+
rotifer hello --template quality-advisor # 运行推荐的预设 Agent
|
|
87
|
+
rotifer agent list # 查看生成的 hello-* agent
|
|
81
88
|
```
|
|
82
89
|
|
|
83
|
-
|
|
90
|
+
内置基因在几秒内就能组合成一个可运行的预设 agent。
|
|
84
91
|
|
|
85
92
|
### 第三幕——Hooked(30 分钟)
|
|
86
93
|
|
|
87
|
-
|
|
94
|
+
把自己的代码变成基因,再组合成自定义 Agent:
|
|
88
95
|
|
|
89
96
|
```bash
|
|
90
|
-
#
|
|
97
|
+
# 先把现有代码包装成基因
|
|
98
|
+
rotifer scan genes/ # 发现候选基因函数
|
|
99
|
+
rotifer wrap hello-world # 包装为基因(生成 Phenotype)
|
|
100
|
+
rotifer test hello-world # 在 L2 沙箱中运行测试(已编译基因走 WASM 沙箱)
|
|
101
|
+
rotifer test hello-world --compliance # 运行结构性合规检查
|
|
102
|
+
rotifer arena submit hello-world # 提交到 Arena(准入评估)
|
|
103
|
+
rotifer arena list # 查看你的基因排名
|
|
104
|
+
|
|
105
|
+
# 再用 TypeScript 写一个新基因——同一语言,零学习成本
|
|
91
106
|
mkdir genes/my-search && cat > genes/my-search/index.ts << 'EOF'
|
|
92
107
|
export function express(input: { query: string }) {
|
|
93
108
|
return { results: [`Found: ${input.query}`], total: 1 };
|
|
@@ -95,8 +110,8 @@ export function express(input: { query: string }) {
|
|
|
95
110
|
EOF
|
|
96
111
|
|
|
97
112
|
rotifer wrap my-search --domain search
|
|
98
|
-
rotifer compile my-search
|
|
99
|
-
rotifer arena submit my-search
|
|
113
|
+
rotifer compile my-search # TS → JS → WASM (Javy) → Rotifer IR
|
|
114
|
+
rotifer arena submit my-search # 观察它攀升排名
|
|
100
115
|
rotifer arena list --domain search # 与 Genesis 基因对比
|
|
101
116
|
|
|
102
117
|
# 创建一个拥有基因组的 Agent(支持 Seq, Par, Cond, Try)
|
|
@@ -142,17 +157,18 @@ playground/
|
|
|
142
157
|
|
|
143
158
|
## CLI 命令
|
|
144
159
|
|
|
145
|
-
运行 `rotifer --help`
|
|
160
|
+
运行 `rotifer --help` 查看按模块分组的命令列表。下面列出最常用的本地、Cloud、Arena 与 Agent 工作流命令:
|
|
146
161
|
|
|
147
162
|
| 命令 | 说明 |
|
|
148
163
|
|------|------|
|
|
149
|
-
| `rotifer init [
|
|
164
|
+
| `rotifer init [workspace-name]` | 初始化新的 Rotifer Agent 工作区 |
|
|
165
|
+
| `rotifer hello [--template <id>]` | 在 Rotifer Agent 工作区内从精选模板创建并运行一个预设 agent |
|
|
150
166
|
| `rotifer scan [path]` | 扫描候选基因和本地技能 |
|
|
151
167
|
| `rotifer wrap <gene-name>` | 将函数或 `SKILL.md` 包装为基因 |
|
|
152
168
|
| `rotifer test [gene-name]` | 在沙箱中测试基因 |
|
|
153
169
|
| `rotifer compile [gene-name]` | 将基因编译为 Rotifer IR(WASM) |
|
|
154
170
|
| `rotifer run <gene-name>` | 直接执行单个本地基因 |
|
|
155
|
-
| `rotifer list` |
|
|
171
|
+
| `rotifer list` | 列出当前 Agent 工作区中的本地基因 |
|
|
156
172
|
| `rotifer login` | 登录 Rotifer Cloud |
|
|
157
173
|
| `rotifer logout` | 从 Rotifer Cloud 登出 |
|
|
158
174
|
| `rotifer publish [gene-name]` | 将基因发布到 Rotifer Cloud |
|
|
@@ -179,7 +195,7 @@ playground/
|
|
|
179
195
|
|
|
180
196
|
## Genesis 基因
|
|
181
197
|
|
|
182
|
-
|
|
198
|
+
每个新 Agent 工作区预装五个基因:
|
|
183
199
|
|
|
184
200
|
| 基因 | 领域 | 保真度 | 说明 |
|
|
185
201
|
|------|------|--------|------|
|
package/dist/cloud/auth.d.ts
CHANGED
|
@@ -12,14 +12,24 @@ export declare function isLoggedIn(): boolean;
|
|
|
12
12
|
export declare function requireAuth(): Promise<CloudCredentials>;
|
|
13
13
|
export declare function generateCodeVerifier(): string;
|
|
14
14
|
export declare function generateCodeChallenge(verifier: string): string;
|
|
15
|
+
/** Loopback interface the callback server binds to (IPv4, avoids localhost→::1). */
|
|
15
16
|
export declare const OAUTH_CALLBACK_HOST = "127.0.0.1";
|
|
17
|
+
/**
|
|
18
|
+
* Fixed loopback port for the OAuth callback. Must exactly match a Supabase Auth
|
|
19
|
+
* "Redirect URLs" allow-list entry (`http://localhost:9876/callback`); Supabase
|
|
20
|
+
* does not match a port wildcard, so a random port falls back to the Site URL
|
|
21
|
+
* (the website) and the local listener never receives the token.
|
|
22
|
+
*/
|
|
23
|
+
export declare const OAUTH_CALLBACK_PORT = 9876;
|
|
16
24
|
export declare function buildOAuthCallbackUrl(port: number, path?: string): string;
|
|
17
25
|
/**
|
|
18
|
-
* Start
|
|
19
|
-
*
|
|
20
|
-
*
|
|
26
|
+
* Start the local OAuth callback server. Defaults to the fixed, allow-listed
|
|
27
|
+
* port 9876 so the OAuth `redirect_to` matches Supabase's allow-list; pass `0`
|
|
28
|
+
* (e.g. in tests) for a random ephemeral port to avoid cross-test port
|
|
29
|
+
* contention. Returns the bound port plus a promise that resolves when the
|
|
30
|
+
* callback arrives.
|
|
21
31
|
*/
|
|
22
|
-
export declare function startOAuthCallbackServer(): Promise<{
|
|
32
|
+
export declare function startOAuthCallbackServer(port?: number): Promise<{
|
|
23
33
|
port: number;
|
|
24
34
|
waitForCallback: Promise<string>;
|
|
25
35
|
}>;
|
package/dist/cloud/auth.d.ts.map
CHANGED
|
@@ -1 +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;AAoChE,wBAAgB,eAAe,IAAI,gBAAgB,GAAG,IAAI,CAazD;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CA4C1D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAM7D;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAMvC;AAED,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAS7D;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,eAAO,MAAM,mBAAmB,cAAc,CAAC;AAE/C,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAoB,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/cloud/auth.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAe,MAAM,YAAY,CAAC;AAoChE,wBAAgB,eAAe,IAAI,gBAAgB,GAAG,IAAI,CAazD;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CA4C1D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAM7D;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAMvC;AAED,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAS7D;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,oFAAoF;AACpF,eAAO,MAAM,mBAAmB,cAAc,CAAC;AAE/C;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,OAAO,CAAC;AAExC,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAoB,GAAG,MAAM,CAItF;AAED;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAC5C,IAAI,GAAE,MAA4B,GACjC,OAAO,CAAC;IACT,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;CAClC,CAAC,CAwED"}
|
package/dist/cloud/auth.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.OAUTH_CALLBACK_HOST = void 0;
|
|
3
|
+
exports.OAUTH_CALLBACK_PORT = exports.OAUTH_CALLBACK_HOST = void 0;
|
|
4
4
|
exports.loadCredentials = loadCredentials;
|
|
5
5
|
exports.refreshTokenIfNeeded = refreshTokenIfNeeded;
|
|
6
6
|
exports.saveCredentials = saveCredentials;
|
|
@@ -132,16 +132,28 @@ function generateCodeVerifier() {
|
|
|
132
132
|
function generateCodeChallenge(verifier) {
|
|
133
133
|
return (0, node_crypto_1.createHash)("sha256").update(verifier).digest("base64url");
|
|
134
134
|
}
|
|
135
|
+
/** Loopback interface the callback server binds to (IPv4, avoids localhost→::1). */
|
|
135
136
|
exports.OAUTH_CALLBACK_HOST = "127.0.0.1";
|
|
137
|
+
/**
|
|
138
|
+
* Fixed loopback port for the OAuth callback. Must exactly match a Supabase Auth
|
|
139
|
+
* "Redirect URLs" allow-list entry (`http://localhost:9876/callback`); Supabase
|
|
140
|
+
* does not match a port wildcard, so a random port falls back to the Site URL
|
|
141
|
+
* (the website) and the local listener never receives the token.
|
|
142
|
+
*/
|
|
143
|
+
exports.OAUTH_CALLBACK_PORT = 9876;
|
|
136
144
|
function buildOAuthCallbackUrl(port, path = "/callback") {
|
|
137
|
-
|
|
145
|
+
// Host is `localhost` to match the Supabase redirect allow-list; the server
|
|
146
|
+
// binds the IPv4 loopback (OAUTH_CALLBACK_HOST), which localhost resolves to.
|
|
147
|
+
return `http://localhost:${port}${path}`;
|
|
138
148
|
}
|
|
139
149
|
/**
|
|
140
|
-
* Start
|
|
141
|
-
*
|
|
142
|
-
*
|
|
150
|
+
* Start the local OAuth callback server. Defaults to the fixed, allow-listed
|
|
151
|
+
* port 9876 so the OAuth `redirect_to` matches Supabase's allow-list; pass `0`
|
|
152
|
+
* (e.g. in tests) for a random ephemeral port to avoid cross-test port
|
|
153
|
+
* contention. Returns the bound port plus a promise that resolves when the
|
|
154
|
+
* callback arrives.
|
|
143
155
|
*/
|
|
144
|
-
async function startOAuthCallbackServer() {
|
|
156
|
+
async function startOAuthCallbackServer(port = exports.OAUTH_CALLBACK_PORT) {
|
|
145
157
|
return new Promise((resolve, reject) => {
|
|
146
158
|
let callbackResolve;
|
|
147
159
|
let callbackReject;
|
|
@@ -192,7 +204,7 @@ if (window.location.hash) {
|
|
|
192
204
|
</script><noscript>Enable JavaScript to complete login.</noscript></body></html>`);
|
|
193
205
|
}
|
|
194
206
|
});
|
|
195
|
-
server.listen(
|
|
207
|
+
server.listen(port, exports.OAUTH_CALLBACK_HOST, () => {
|
|
196
208
|
const addr = server.address();
|
|
197
209
|
resolve({ port: addr.port, waitForCallback });
|
|
198
210
|
});
|
package/dist/cloud/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/cloud/auth.ts"],"names":[],"mappings":";;;AAwCA,0CAaC;AAOD,oDA4CC;AAED,0CAMC;AAED,4CAMC;AAED,gCAEC;AAED,kCASC;AAED,oDAEC;AAED,sDAEC;
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/cloud/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { ScanResult } from "../scanner/types.js";
|
|
2
|
+
export declare const BADGE_WORKER_URL = "https://badge.rotifer.dev";
|
|
3
|
+
export type SafetyMode = "self-reported" | "skipped";
|
|
4
|
+
export interface SafetyUploadResult {
|
|
5
|
+
ok: boolean;
|
|
6
|
+
status?: number;
|
|
7
|
+
error?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface BadgeActionContext {
|
|
10
|
+
skipVg?: boolean;
|
|
11
|
+
skipSecurity?: boolean;
|
|
12
|
+
hasScanResult: boolean;
|
|
13
|
+
}
|
|
14
|
+
export type BadgeAction = {
|
|
15
|
+
kind: "upload";
|
|
16
|
+
mode: SafetyMode;
|
|
17
|
+
} | {
|
|
18
|
+
kind: "skip";
|
|
19
|
+
reason: string;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Decide whether to upload a V(g) Safety Badge after publish, and in which mode.
|
|
23
|
+
*
|
|
24
|
+
* Pure function — no I/O, no logging. Tested independently of fetch.
|
|
25
|
+
*
|
|
26
|
+
* Decision matrix (v0.9 §3.8 Phase 1):
|
|
27
|
+
* skipVg=false, hasScanResult=true → upload self-reported
|
|
28
|
+
* skipVg=true → upload skipped (intent: explicit)
|
|
29
|
+
* skipVg=false, hasScanResult=false → no upload (intent unclear; e.g. --skip-security used alone)
|
|
30
|
+
*/
|
|
31
|
+
export declare function decideBadgeAction(ctx: BadgeActionContext): BadgeAction;
|
|
32
|
+
/**
|
|
33
|
+
* Upload V(g) safety badge to the Badge Worker.
|
|
34
|
+
*
|
|
35
|
+
* - mode="self-reported": requires scanResult; uploads grade + findings_count
|
|
36
|
+
* - mode="skipped": scanResult ignored; uploads sentinel record (badge will display "skipped")
|
|
37
|
+
*
|
|
38
|
+
* Returns `{ ok }` instead of throwing — callers (e.g. `rotifer publish`) MUST
|
|
39
|
+
* NOT block on badge upload failures (badge is observability, not protocol).
|
|
40
|
+
*/
|
|
41
|
+
export declare function uploadSafetyBadge(geneId: string, scanResult: ScanResult | null, scannerVersion: string, mode: SafetyMode, token: string, workerUrl?: string): Promise<SafetyUploadResult>;
|
|
42
|
+
//# sourceMappingURL=badge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"badge.d.ts","sourceRoot":"","sources":["../../src/cloud/badge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD,eAAO,MAAM,gBAAgB,8BAA8B,CAAC;AAE5D,MAAM,MAAM,UAAU,GAAG,eAAe,GAAG,SAAS,CAAC;AAErD,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAErC;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,kBAAkB,GAAG,WAAW,CAQtE;AAED;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,UAAU,GAAG,IAAI,EAC7B,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,MAAM,EACb,SAAS,GAAE,MAAyB,GACnC,OAAO,CAAC,kBAAkB,CAAC,CAiC7B"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BADGE_WORKER_URL = void 0;
|
|
4
|
+
exports.decideBadgeAction = decideBadgeAction;
|
|
5
|
+
exports.uploadSafetyBadge = uploadSafetyBadge;
|
|
6
|
+
exports.BADGE_WORKER_URL = "https://badge.rotifer.dev";
|
|
7
|
+
/**
|
|
8
|
+
* Decide whether to upload a V(g) Safety Badge after publish, and in which mode.
|
|
9
|
+
*
|
|
10
|
+
* Pure function — no I/O, no logging. Tested independently of fetch.
|
|
11
|
+
*
|
|
12
|
+
* Decision matrix (v0.9 §3.8 Phase 1):
|
|
13
|
+
* skipVg=false, hasScanResult=true → upload self-reported
|
|
14
|
+
* skipVg=true → upload skipped (intent: explicit)
|
|
15
|
+
* skipVg=false, hasScanResult=false → no upload (intent unclear; e.g. --skip-security used alone)
|
|
16
|
+
*/
|
|
17
|
+
function decideBadgeAction(ctx) {
|
|
18
|
+
if (ctx.skipVg) {
|
|
19
|
+
return { kind: "upload", mode: "skipped" };
|
|
20
|
+
}
|
|
21
|
+
if (ctx.hasScanResult) {
|
|
22
|
+
return { kind: "upload", mode: "self-reported" };
|
|
23
|
+
}
|
|
24
|
+
return { kind: "skip", reason: "no scan result; pass --skip-vg to upload skipped placeholder" };
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Upload V(g) safety badge to the Badge Worker.
|
|
28
|
+
*
|
|
29
|
+
* - mode="self-reported": requires scanResult; uploads grade + findings_count
|
|
30
|
+
* - mode="skipped": scanResult ignored; uploads sentinel record (badge will display "skipped")
|
|
31
|
+
*
|
|
32
|
+
* Returns `{ ok }` instead of throwing — callers (e.g. `rotifer publish`) MUST
|
|
33
|
+
* NOT block on badge upload failures (badge is observability, not protocol).
|
|
34
|
+
*/
|
|
35
|
+
async function uploadSafetyBadge(geneId, scanResult, scannerVersion, mode, token, workerUrl = exports.BADGE_WORKER_URL) {
|
|
36
|
+
const body = {
|
|
37
|
+
gene_id: geneId,
|
|
38
|
+
scanner_version: scannerVersion,
|
|
39
|
+
mode,
|
|
40
|
+
};
|
|
41
|
+
if (mode === "self-reported") {
|
|
42
|
+
if (!scanResult) {
|
|
43
|
+
return { ok: false, error: "self-reported mode requires scanResult" };
|
|
44
|
+
}
|
|
45
|
+
body.grade = scanResult.grade;
|
|
46
|
+
body.findings_count = scanResult.findings.length;
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
const res = await fetch(`${workerUrl}/safety`, {
|
|
50
|
+
method: "POST",
|
|
51
|
+
headers: {
|
|
52
|
+
"Content-Type": "application/json",
|
|
53
|
+
Authorization: `Bearer ${token}`,
|
|
54
|
+
},
|
|
55
|
+
body: JSON.stringify(body),
|
|
56
|
+
});
|
|
57
|
+
if (res.ok) {
|
|
58
|
+
return { ok: true, status: res.status };
|
|
59
|
+
}
|
|
60
|
+
const errText = await res.text().catch(() => "");
|
|
61
|
+
return { ok: false, status: res.status, error: errText };
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
return { ok: false, error: e.message };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=badge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"badge.js","sourceRoot":"","sources":["../../src/cloud/badge.ts"],"names":[],"mappings":";;;AAgCA,8CAQC;AAWD,8CAwCC;AAzFY,QAAA,gBAAgB,GAAG,2BAA2B,CAAC;AAoB5D;;;;;;;;;GASG;AACH,SAAgB,iBAAiB,CAAC,GAAuB;IACvD,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;QACf,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IAC7C,CAAC;IACD,IAAI,GAAG,CAAC,aAAa,EAAE,CAAC;QACtB,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;IACnD,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,8DAA8D,EAAE,CAAC;AAClG,CAAC;AAED;;;;;;;;GAQG;AACI,KAAK,UAAU,iBAAiB,CACrC,MAAc,EACd,UAA6B,EAC7B,cAAsB,EACtB,IAAgB,EAChB,KAAa,EACb,YAAoB,wBAAgB;IAEpC,MAAM,IAAI,GAA4B;QACpC,OAAO,EAAE,MAAM;QACf,eAAe,EAAE,cAAc;QAC/B,IAAI;KACL,CAAC;IAEF,IAAI,IAAI,KAAK,eAAe,EAAE,CAAC;QAC7B,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,wCAAwC,EAAE,CAAC;QACxE,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC;QAC9B,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC;IACnD,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,SAAS,SAAS,EAAE;YAC7C,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,KAAK,EAAE;aACjC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAC;QAEH,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;YACX,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC;QAC1C,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QACjD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;IAC3D,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAG,CAAW,CAAC,OAAO,EAAE,CAAC;IACpD,CAAC;AACH,CAAC"}
|