@nexart/codemode-sdk 1.8.0 → 1.8.2
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 +85 -0
- package/COMMERCIAL.md +41 -0
- package/LICENSE.md +5 -5
- package/README.md +250 -700
- package/dist/sdk/codemode/core-index.d.ts +6 -4
- package/dist/sdk/codemode/core-index.d.ts.map +1 -1
- package/dist/sdk/codemode/core-index.js +6 -4
- package/dist/{entry → sdk/codemode/entry}/browser.d.ts +5 -2
- package/dist/sdk/codemode/entry/browser.d.ts.map +1 -0
- package/dist/{entry → sdk/codemode/entry}/browser.js +10 -4
- package/dist/{entry → sdk/codemode/entry}/node.d.ts +2 -1
- package/dist/sdk/codemode/entry/node.d.ts.map +1 -0
- package/dist/{entry → sdk/codemode/entry}/node.js +2 -1
- package/dist/{runtime.d.ts → sdk/codemode/runtime.d.ts} +2 -2
- package/dist/sdk/codemode/runtime.d.ts.map +1 -0
- package/dist/{runtime.js → sdk/codemode/runtime.js} +3 -2
- package/dist/sdk/codemode/static-engine.d.ts.map +1 -1
- package/dist/sdk/codemode/static-engine.js +24 -11
- package/dist/sdk/codemode/version.d.ts +18 -0
- package/dist/sdk/codemode/version.d.ts.map +1 -0
- package/dist/sdk/codemode/version.js +17 -0
- package/examples/agent-quickstart.ts +159 -0
- package/examples/preflight-test.ts +1 -1
- package/package.json +4 -2
- package/dist/builder-manifest.d.ts +0 -79
- package/dist/builder-manifest.d.ts.map +0 -1
- package/dist/builder-manifest.js +0 -97
- package/dist/core-index.d.ts +0 -21
- package/dist/core-index.d.ts.map +0 -1
- package/dist/core-index.js +0 -26
- package/dist/engine.d.ts +0 -24
- package/dist/engine.d.ts.map +0 -1
- package/dist/engine.js +0 -67
- package/dist/entry/browser.d.ts.map +0 -1
- package/dist/entry/node.d.ts.map +0 -1
- package/dist/execute.d.ts +0 -46
- package/dist/execute.d.ts.map +0 -1
- package/dist/execute.js +0 -283
- package/dist/execution-sandbox.d.ts +0 -107
- package/dist/execution-sandbox.d.ts.map +0 -1
- package/dist/execution-sandbox.js +0 -207
- package/dist/index.d.ts +0 -31
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -63
- package/dist/loop-engine.d.ts +0 -22
- package/dist/loop-engine.d.ts.map +0 -1
- package/dist/loop-engine.js +0 -229
- package/dist/noise-bridge.d.ts +0 -44
- package/dist/noise-bridge.d.ts.map +0 -1
- package/dist/noise-bridge.js +0 -68
- package/dist/noise-engine.d.ts +0 -74
- package/dist/noise-engine.d.ts.map +0 -1
- package/dist/noise-engine.js +0 -132
- package/dist/noise-sketches/fractalNoise.d.ts +0 -11
- package/dist/noise-sketches/fractalNoise.d.ts.map +0 -1
- package/dist/noise-sketches/fractalNoise.js +0 -121
- package/dist/noise-sketches/index.d.ts +0 -21
- package/dist/noise-sketches/index.d.ts.map +0 -1
- package/dist/noise-sketches/index.js +0 -28
- package/dist/p5-runtime.d.ts +0 -75
- package/dist/p5-runtime.d.ts.map +0 -1
- package/dist/p5-runtime.js +0 -1031
- package/dist/runtime.d.ts.map +0 -1
- package/dist/sdk/codemode/index.d.ts +0 -31
- package/dist/sdk/codemode/index.d.ts.map +0 -1
- package/dist/sdk/codemode/index.js +0 -63
- package/dist/sdk/codemode/noise-bridge.d.ts +0 -44
- package/dist/sdk/codemode/noise-bridge.d.ts.map +0 -1
- package/dist/sdk/codemode/noise-bridge.js +0 -68
- package/dist/sdk/codemode/noise-engine.d.ts +0 -74
- package/dist/sdk/codemode/noise-engine.d.ts.map +0 -1
- package/dist/sdk/codemode/noise-engine.js +0 -132
- package/dist/sdk/codemode/noise-sketches/fractalNoise.d.ts +0 -11
- package/dist/sdk/codemode/noise-sketches/fractalNoise.d.ts.map +0 -1
- package/dist/sdk/codemode/noise-sketches/fractalNoise.js +0 -121
- package/dist/sdk/codemode/noise-sketches/index.d.ts +0 -21
- package/dist/sdk/codemode/noise-sketches/index.d.ts.map +0 -1
- package/dist/sdk/codemode/noise-sketches/index.js +0 -28
- package/dist/shared/noiseSnapshot.d.ts +0 -59
- package/dist/shared/noiseSnapshot.d.ts.map +0 -1
- package/dist/shared/noiseSnapshot.js +0 -72
- package/dist/sound-bridge.d.ts +0 -89
- package/dist/sound-bridge.d.ts.map +0 -1
- package/dist/sound-bridge.js +0 -128
- package/dist/soundart-engine.d.ts +0 -87
- package/dist/soundart-engine.d.ts.map +0 -1
- package/dist/soundart-engine.js +0 -173
- package/dist/soundart-sketches/chladniBloom.d.ts +0 -3
- package/dist/soundart-sketches/chladniBloom.d.ts.map +0 -1
- package/dist/soundart-sketches/chladniBloom.js +0 -53
- package/dist/soundart-sketches/dualVortex.d.ts +0 -3
- package/dist/soundart-sketches/dualVortex.d.ts.map +0 -1
- package/dist/soundart-sketches/dualVortex.js +0 -67
- package/dist/soundart-sketches/geometryIllusion.d.ts +0 -3
- package/dist/soundart-sketches/geometryIllusion.d.ts.map +0 -1
- package/dist/soundart-sketches/geometryIllusion.js +0 -89
- package/dist/soundart-sketches/index.d.ts +0 -39
- package/dist/soundart-sketches/index.d.ts.map +0 -1
- package/dist/soundart-sketches/index.js +0 -72
- package/dist/soundart-sketches/isoflow.d.ts +0 -3
- package/dist/soundart-sketches/isoflow.d.ts.map +0 -1
- package/dist/soundart-sketches/isoflow.js +0 -60
- package/dist/soundart-sketches/loomWeave.d.ts +0 -3
- package/dist/soundart-sketches/loomWeave.d.ts.map +0 -1
- package/dist/soundart-sketches/loomWeave.js +0 -59
- package/dist/soundart-sketches/noiseTerraces.d.ts +0 -3
- package/dist/soundart-sketches/noiseTerraces.d.ts.map +0 -1
- package/dist/soundart-sketches/noiseTerraces.js +0 -53
- package/dist/soundart-sketches/orb.d.ts +0 -3
- package/dist/soundart-sketches/orb.d.ts.map +0 -1
- package/dist/soundart-sketches/orb.js +0 -50
- package/dist/soundart-sketches/pixelGlyphs.d.ts +0 -3
- package/dist/soundart-sketches/pixelGlyphs.d.ts.map +0 -1
- package/dist/soundart-sketches/pixelGlyphs.js +0 -72
- package/dist/soundart-sketches/prismFlowFields.d.ts +0 -3
- package/dist/soundart-sketches/prismFlowFields.d.ts.map +0 -1
- package/dist/soundart-sketches/prismFlowFields.js +0 -51
- package/dist/soundart-sketches/radialBurst.d.ts +0 -3
- package/dist/soundart-sketches/radialBurst.d.ts.map +0 -1
- package/dist/soundart-sketches/radialBurst.js +0 -60
- package/dist/soundart-sketches/resonantSoundBodies.d.ts +0 -3
- package/dist/soundart-sketches/resonantSoundBodies.d.ts.map +0 -1
- package/dist/soundart-sketches/resonantSoundBodies.js +0 -89
- package/dist/soundart-sketches/rings.d.ts +0 -11
- package/dist/soundart-sketches/rings.d.ts.map +0 -1
- package/dist/soundart-sketches/rings.js +0 -89
- package/dist/soundart-sketches/squares.d.ts +0 -3
- package/dist/soundart-sketches/squares.d.ts.map +0 -1
- package/dist/soundart-sketches/squares.js +0 -52
- package/dist/soundart-sketches/waveStripes.d.ts +0 -3
- package/dist/soundart-sketches/waveStripes.d.ts.map +0 -1
- package/dist/soundart-sketches/waveStripes.js +0 -44
- package/dist/static-engine.d.ts +0 -20
- package/dist/static-engine.d.ts.map +0 -1
- package/dist/static-engine.js +0 -157
- package/dist/types.d.ts +0 -191
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -32
package/README.md
CHANGED
|
@@ -1,25 +1,84 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
**Version: 1.8.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
# @nexart/codemode-sdk
|
|
2
|
+
|
|
3
|
+
**Version: 1.8.2 (Protocol v1.2.0)**
|
|
4
|
+
|
|
5
|
+
A deterministic execution runtime for reproducible, verifiable computation.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Which API Should I Use?
|
|
10
|
+
|
|
11
|
+
**Decision table for choosing the right entrypoint:**
|
|
12
|
+
|
|
13
|
+
| Your Goal | Use This | Import Path |
|
|
14
|
+
|-----------|----------|-------------|
|
|
15
|
+
| Deterministic random/noise in any environment | **`createRuntime()`** ✅ DEFAULT | `@nexart/codemode-sdk` |
|
|
16
|
+
| AI agent integration | **`createRuntime()`** ✅ DEFAULT | `@nexart/codemode-sdk` |
|
|
17
|
+
| Browser/React/Vite app | **`createRuntime()`** ✅ DEFAULT | `@nexart/codemode-sdk` |
|
|
18
|
+
| Server-side image rendering | `executeCodeMode()` | `@nexart/codemode-sdk/node` |
|
|
19
|
+
| Full p5.js-style canvas execution | `executeCodeMode()` | `@nexart/codemode-sdk/node` |
|
|
20
|
+
|
|
21
|
+
**`createRuntime()`** is the **default and recommended** API:
|
|
22
|
+
- ✅ Works in browser and Node.js
|
|
23
|
+
- ✅ No canvas dependency
|
|
24
|
+
- ✅ Agent-first design
|
|
25
|
+
- ✅ Strict mode enforcement
|
|
26
|
+
- ✅ Lightweight
|
|
27
|
+
|
|
28
|
+
**`executeCodeMode()`** is the **legacy / Node-only** API:
|
|
29
|
+
- Requires Node.js with `canvas` package
|
|
30
|
+
- Full p5.js-style execution environment
|
|
31
|
+
- Returns rendered PNG/MP4
|
|
32
|
+
- Use only when you need actual image/video output
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## What This SDK Does
|
|
37
|
+
|
|
38
|
+
This SDK provides a **deterministic runtime layer** for executing code that must produce identical output given identical inputs — across environments, over time, and under verification.
|
|
39
|
+
|
|
40
|
+
**Core guarantees:**
|
|
41
|
+
- Same `seed` + `vars` + `code` → identical output (always)
|
|
42
|
+
- Cross-environment stability (browser, Node.js, CI pipelines)
|
|
43
|
+
- Strict mode blocks non-deterministic APIs (`Math.random`, `Date.now`, etc.)
|
|
44
|
+
- Canonical state snapshots for replay and verification
|
|
45
|
+
- Stable digest for integrity verification
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Who This Is For
|
|
50
|
+
|
|
51
|
+
**Use this SDK if determinism is non-negotiable:**
|
|
52
|
+
|
|
53
|
+
- **On-chain generative art** — NFTs, archival renders, mint verification
|
|
54
|
+
- **Procedural games** — Open-world generation, replay systems, save states
|
|
55
|
+
- **Simulations** — Physics, agent-based models, reproducible experiments
|
|
56
|
+
- **Finance research** — Backtesting, Monte Carlo, reproducible analysis
|
|
57
|
+
- **Education labs** — Repeatable demonstrations, grading consistency
|
|
58
|
+
|
|
59
|
+
**Skip this SDK if you're building:**
|
|
60
|
+
|
|
61
|
+
- CRUD apps
|
|
62
|
+
- Dashboards
|
|
63
|
+
- E-commerce
|
|
64
|
+
- Typical web applications without reproducibility requirements
|
|
65
|
+
|
|
66
|
+
For most applications, seeded randomness is unnecessary complexity.
|
|
17
67
|
|
|
18
68
|
---
|
|
19
69
|
|
|
20
70
|
## For AI Coding Agents (Replit / Lovable / Claude Code)
|
|
21
71
|
|
|
22
|
-
**
|
|
72
|
+
**Always start with `createRuntime()` — it is the default and recommended API.**
|
|
73
|
+
|
|
74
|
+
### Quick Rules for AI Agents
|
|
75
|
+
|
|
76
|
+
1. **Always use `createRuntime()`** — NOT `executeCodeMode()`
|
|
77
|
+
2. **Never use `Math.random()` or `Date.now()`** — use `runtime.random()` instead
|
|
78
|
+
3. **Always use `strict: true`** — unless you explicitly know why you aren't
|
|
79
|
+
4. **See `examples/agent-quickstart.ts`** — copy-paste ready reference
|
|
80
|
+
|
|
81
|
+
### Minimal Example
|
|
23
82
|
|
|
24
83
|
```typescript
|
|
25
84
|
import { createRuntime } from "@nexart/codemode-sdk";
|
|
@@ -27,24 +86,94 @@ import { createRuntime } from "@nexart/codemode-sdk";
|
|
|
27
86
|
const runtime = createRuntime({
|
|
28
87
|
seed: "my-artwork-42",
|
|
29
88
|
vars: [50, 75, 25],
|
|
30
|
-
strict: true, //
|
|
89
|
+
strict: true, // ALWAYS use strict: true — throws on non-deterministic APIs
|
|
31
90
|
mode: "static"
|
|
32
91
|
});
|
|
33
92
|
|
|
34
|
-
//
|
|
35
|
-
const value = runtime.random(); //
|
|
36
|
-
const intVal = runtime.randomInt(0, 10); //
|
|
37
|
-
const n = runtime.noise(
|
|
93
|
+
// Deterministic APIs (use these, not Math.random!)
|
|
94
|
+
const value = runtime.random(); // [0, 1)
|
|
95
|
+
const intVal = runtime.randomInt(0, 10); // integer in range
|
|
96
|
+
const n = runtime.noise(0.5, 0.5); // Perlin noise
|
|
38
97
|
|
|
39
|
-
//
|
|
40
|
-
|
|
41
|
-
|
|
98
|
+
// Execute with strict enforcement
|
|
99
|
+
const result = runtime.run(() => {
|
|
100
|
+
// Your deterministic code here
|
|
101
|
+
return runtime.random() * 100;
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// Verification
|
|
105
|
+
console.log(runtime.digest()); // Stable hash for verification
|
|
106
|
+
console.log(runtime.getState()); // Canonical state snapshot for replay
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Strict Mode Explained
|
|
110
|
+
|
|
111
|
+
Strict mode protects determinism by intercepting non-deterministic APIs during `runtime.run()`:
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
runtime.run(() => {
|
|
115
|
+
Math.random(); // Throws: NEXART_STRICT: Non-deterministic API used: Math.random. Use runtime.random() instead.
|
|
116
|
+
Date.now(); // Throws: NEXART_STRICT: Non-deterministic API used: Date.now. Pass time as an input or use deterministic counters.
|
|
117
|
+
});
|
|
42
118
|
```
|
|
43
119
|
|
|
44
|
-
**
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
-
|
|
120
|
+
**Why strict mode exists:**
|
|
121
|
+
- Determinism is the core guarantee — same inputs must always produce same outputs
|
|
122
|
+
- AI agents often default to `Math.random()` before reading documentation
|
|
123
|
+
- Strict mode catches these mistakes immediately with actionable error messages
|
|
124
|
+
- Interception is **scoped to `runtime.run()`** — it does NOT globally mutate your application
|
|
125
|
+
- Globals are restored after execution
|
|
126
|
+
|
|
127
|
+
**When to use `strict: false`:**
|
|
128
|
+
- Almost never. Only if you're intentionally mixing deterministic and non-deterministic code.
|
|
129
|
+
- If you're not sure, use `strict: true`.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Where This Fits
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
┌─────────────────────────────────────────────────────────┐
|
|
137
|
+
│ Your Application │
|
|
138
|
+
│ (React, Canvas, Three.js, game engine, simulation) │
|
|
139
|
+
└────────────────────────┬────────────────────────────────┘
|
|
140
|
+
│
|
|
141
|
+
▼
|
|
142
|
+
┌─────────────────────────────────────────────────────────┐
|
|
143
|
+
│ @nexart/codemode-sdk │
|
|
144
|
+
│ Deterministic runtime layer │
|
|
145
|
+
│ - Seeded PRNG (Mulberry32) │
|
|
146
|
+
│ - Seeded noise (Perlin) │
|
|
147
|
+
│ - Strict mode enforcement │
|
|
148
|
+
│ - State snapshots + digest │
|
|
149
|
+
└────────────────────────┬────────────────────────────────┘
|
|
150
|
+
│
|
|
151
|
+
▼
|
|
152
|
+
┌─────────────────────────────────────────────────────────┐
|
|
153
|
+
│ Output │
|
|
154
|
+
│ - Deterministic result │
|
|
155
|
+
│ - Verification digest │
|
|
156
|
+
│ - Replay state │
|
|
157
|
+
└─────────────────────────────────────────────────────────┘
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
The SDK sits between your UI/framework and your output. It does not render, does not manage state, does not touch the DOM. It provides deterministic primitives.
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Why Not Roll Your Own?
|
|
165
|
+
|
|
166
|
+
**What's easy:**
|
|
167
|
+
- Seeded PRNG (dozens of implementations exist)
|
|
168
|
+
- Noise libraries (simplex, Perlin, available everywhere)
|
|
169
|
+
|
|
170
|
+
**What's hard:**
|
|
171
|
+
- **Cross-environment stability** — Same seed producing same sequence across browser versions, Node.js versions, bundlers, and platforms
|
|
172
|
+
- **Strict enforcement** — Actually blocking `Math.random()` and `Date.now()` during execution, with actionable error messages
|
|
173
|
+
- **Replay and verification** — Canonical state snapshots that can reconstruct execution
|
|
174
|
+
- **Long-term drift resistance** — Guaranteeing identical output years later, not just today
|
|
175
|
+
|
|
176
|
+
If you need a quick seeded random, use any PRNG. If you need guaranteed reproducibility across time, environments, and verification systems — that's what this SDK provides.
|
|
48
177
|
|
|
49
178
|
---
|
|
50
179
|
|
|
@@ -60,14 +189,14 @@ console.log(runtime.getState()); // Canonical state snapshot
|
|
|
60
189
|
- `Math.random()` — use `runtime.random()` instead
|
|
61
190
|
- `Date.now()` — pass time as input or use frame counters
|
|
62
191
|
- `performance.now()` — use deterministic timing
|
|
63
|
-
- External IO during deterministic runs
|
|
192
|
+
- External IO during deterministic runs
|
|
64
193
|
|
|
65
194
|
---
|
|
66
195
|
|
|
67
|
-
##
|
|
196
|
+
## Feature Comparison
|
|
68
197
|
|
|
69
|
-
| Feature | Plain PRNG |
|
|
70
|
-
|
|
198
|
+
| Feature | Plain PRNG | This SDK |
|
|
199
|
+
|---------|-----------|----------|
|
|
71
200
|
| Seeded random | ✅ | ✅ |
|
|
72
201
|
| Seeded noise | ❌ (separate lib) | ✅ built-in |
|
|
73
202
|
| Strict mode (blocks entropy) | ❌ | ✅ |
|
|
@@ -77,8 +206,6 @@ console.log(runtime.getState()); // Canonical state snapshot
|
|
|
77
206
|
| Replay/verification | Manual | Built-in |
|
|
78
207
|
| Error messages for agents | ❌ | ✅ actionable |
|
|
79
208
|
|
|
80
|
-
**The runtime provides a complete determinism layer, not just random numbers.**
|
|
81
|
-
|
|
82
209
|
---
|
|
83
210
|
|
|
84
211
|
## Environment Imports
|
|
@@ -89,64 +216,64 @@ console.log(runtime.getState()); // Canonical state snapshot
|
|
|
89
216
|
| Node.js (general use) | `import { createRuntime } from "@nexart/codemode-sdk"` |
|
|
90
217
|
| Node.js server rendering (canvas) | `import { executeCodeMode } from "@nexart/codemode-sdk/node"` |
|
|
91
218
|
|
|
92
|
-
**The default import is
|
|
219
|
+
**The default import is browser-safe.** Node-only features require explicit `/node` import.
|
|
93
220
|
|
|
94
221
|
---
|
|
95
222
|
|
|
96
|
-
##
|
|
223
|
+
## Used By
|
|
97
224
|
|
|
98
|
-
**
|
|
99
|
-
-
|
|
100
|
-
-
|
|
101
|
-
- Open-source projects
|
|
225
|
+
- **NexArt** — Generative art platform
|
|
226
|
+
- **ByX** — Curated collections
|
|
227
|
+
- **Frontierra** — External builder integration
|
|
102
228
|
|
|
103
|
-
|
|
229
|
+
These are examples — the SDK is designed for any system requiring deterministic execution.
|
|
104
230
|
|
|
105
231
|
---
|
|
106
232
|
|
|
107
|
-
##
|
|
233
|
+
## Protocol Stability
|
|
108
234
|
|
|
109
235
|
| Property | Value |
|
|
110
236
|
|----------|-------|
|
|
111
|
-
| Protocol
|
|
112
|
-
| Version | v1.2.0 |
|
|
237
|
+
| Protocol Version | v1.2.0 |
|
|
113
238
|
| Status | **STABLE** |
|
|
114
|
-
|
|
|
115
|
-
| Lock Date | January 2026 |
|
|
116
|
-
|
|
117
|
-
**Core protocol surface is frozen. Any breaking change requires v2.0.0.**
|
|
239
|
+
| SDK Version | 1.8.2 |
|
|
118
240
|
|
|
119
|
-
|
|
241
|
+
**Core protocol surface is frozen. Breaking changes require v2.0.0.**
|
|
120
242
|
|
|
243
|
+
The following are locked in v1.x:
|
|
121
244
|
- Execution model (Static and Loop modes)
|
|
122
|
-
- VAR[0..9] specification
|
|
123
|
-
- Determinism guarantee
|
|
245
|
+
- VAR[0..9] specification
|
|
246
|
+
- Determinism guarantee
|
|
124
247
|
- Time semantics (t, frameCount, time, tGlobal, totalFrames)
|
|
125
|
-
- Random and noise behavior
|
|
126
|
-
- Forbidden patterns list
|
|
127
|
-
- Canvas pre-initialization (no createCanvas)
|
|
248
|
+
- Random and noise behavior
|
|
249
|
+
- Forbidden patterns list
|
|
128
250
|
|
|
129
251
|
---
|
|
130
252
|
|
|
131
|
-
|
|
253
|
+
## Licensing
|
|
132
254
|
|
|
133
|
-
|
|
255
|
+
Free for personal projects, experiments, research, and open-source.
|
|
134
256
|
|
|
135
|
-
|
|
257
|
+
Commercial production deployments require a license.
|
|
136
258
|
|
|
137
|
-
|
|
259
|
+
See [COMMERCIAL.md](./COMMERCIAL.md) for details.
|
|
138
260
|
|
|
139
|
-
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Installation
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
npm install @nexart/codemode-sdk
|
|
267
|
+
```
|
|
140
268
|
|
|
141
269
|
---
|
|
142
270
|
|
|
143
|
-
##
|
|
271
|
+
## Runtime API
|
|
144
272
|
|
|
145
|
-
|
|
273
|
+
### `createRuntime(options)`
|
|
146
274
|
|
|
147
|
-
|
|
275
|
+
Create a deterministic runtime instance.
|
|
148
276
|
|
|
149
|
-
### New Runtime API
|
|
150
277
|
```typescript
|
|
151
278
|
import { createRuntime } from "@nexart/codemode-sdk";
|
|
152
279
|
|
|
@@ -167,239 +294,52 @@ runtime.run(() => { ... }); // Execute with strict enforcement
|
|
|
167
294
|
```
|
|
168
295
|
|
|
169
296
|
### Strict Mode
|
|
170
|
-
- Throws actionable errors on `Math.random`, `Date.now`, `performance.now`
|
|
171
|
-
- Only applies during `runtime.run()` — non-invasive
|
|
172
|
-
- Error messages guide agents to correct usage
|
|
173
|
-
|
|
174
|
-
### Agent-First Documentation
|
|
175
|
-
- "For AI Coding Agents" section at top of README
|
|
176
|
-
- Determinism Contract with ✅/❌ checklist
|
|
177
|
-
- PRNG comparison table
|
|
178
|
-
- Environment import matrix
|
|
179
|
-
|
|
180
|
-
### Examples
|
|
181
|
-
- `npm run example:basic` — Basic usage demonstration
|
|
182
|
-
- `npm run example:verify` — Determinism verification tests
|
|
183
|
-
|
|
184
|
-
### No Breaking Changes
|
|
185
|
-
- All existing APIs work unchanged
|
|
186
|
-
- Default import remains browser-safe
|
|
187
|
-
- Protocol version unchanged (v1.2.0)
|
|
188
|
-
|
|
189
|
-
---
|
|
190
|
-
|
|
191
|
-
## What's New in v1.7.0
|
|
192
|
-
|
|
193
|
-
**Browser-Safe Entrypoint + Conditional Exports**
|
|
194
|
-
|
|
195
|
-
This release makes the SDK reliably usable in browser environments (Vite/React) without any Node.js dependency leakage.
|
|
196
|
-
|
|
197
|
-
### New Entry Points
|
|
198
|
-
- `@nexart/codemode-sdk/browser` — Browser-safe modules only (no Node.js dependencies)
|
|
199
|
-
- `@nexart/codemode-sdk/node` — Full SDK including static-engine (requires `canvas` package)
|
|
200
|
-
|
|
201
|
-
### Package.json Conditional Exports
|
|
202
|
-
- Default import (`.`) now uses conditional exports: browser gets browser entry, Node gets Node entry
|
|
203
|
-
- Explicit subpaths: `./browser` and `./node` for direct control
|
|
204
|
-
|
|
205
|
-
### Why This Matters
|
|
206
|
-
- AI agents and bundlers will no longer accidentally import Node.js modules in browser builds
|
|
207
|
-
- Vite/React apps can safely import the SDK without "createRequire is not defined" errors
|
|
208
|
-
- Server-side code gets full functionality including static image rendering
|
|
209
297
|
|
|
210
|
-
|
|
211
|
-
- Protocol behavior and determinism unchanged
|
|
212
|
-
- API surface unchanged
|
|
213
|
-
- Existing Node.js code continues to work
|
|
298
|
+
When `strict: true`, the runtime intercepts non-deterministic APIs during `run()`:
|
|
214
299
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
**Licensing & Builder Identity Scaffolding (Metadata Only)**
|
|
220
|
-
|
|
221
|
-
This is a non-breaking, metadata-only release. No changes to execution or determinism.
|
|
222
|
-
|
|
223
|
-
### Licensing (Informational Only)
|
|
224
|
-
- Added `LICENSE.md` with draft commercial licensing terms
|
|
225
|
-
- Enforcement is NOT active — all usage currently permitted under MIT
|
|
226
|
-
|
|
227
|
-
### Builder Manifest Schema
|
|
228
|
-
- Added `builder.manifest.schema.json` for optional builder attribution
|
|
229
|
-
- Fields: `builder_id`, `project_name`, `contact`, `website`, `intended_use`
|
|
230
|
-
- This file is **optional**, **not validated**, and **not loaded at runtime**
|
|
231
|
-
|
|
232
|
-
### Documentation
|
|
233
|
-
- SDK positioned as "canonical execution surface"
|
|
234
|
-
- Explicit determinism guarantees documented
|
|
235
|
-
- Real product references (ByX, Frontierra)
|
|
236
|
-
|
|
237
|
-
---
|
|
238
|
-
|
|
239
|
-
## Determinism Guarantees
|
|
240
|
-
|
|
241
|
-
**The NexArt Code Mode SDK guarantees deterministic output.**
|
|
242
|
-
|
|
243
|
-
Given identical inputs:
|
|
244
|
-
- Same `source` code
|
|
245
|
-
- Same `seed`
|
|
246
|
-
- Same `vars` array
|
|
247
|
-
- Same `width` and `height`
|
|
248
|
-
- Same `mode`
|
|
249
|
-
|
|
250
|
-
The SDK will produce **byte-for-byte identical output** across all executions.
|
|
251
|
-
|
|
252
|
-
### What Breaks Determinism
|
|
253
|
-
|
|
254
|
-
The following actions will break determinism and are **blocked** by the SDK:
|
|
255
|
-
|
|
256
|
-
| Pattern | Reason | Enforcement |
|
|
257
|
-
|---------|--------|-------------|
|
|
258
|
-
| `Math.random()` | Unseeded randomness | BLOCKED |
|
|
259
|
-
| `Date.now()` | Time-based entropy | BLOCKED |
|
|
260
|
-
| `new Date()` | Time-based entropy | BLOCKED |
|
|
261
|
-
| `performance.now()` | Timing entropy | BLOCKED |
|
|
262
|
-
| `crypto.getRandomValues()` | Crypto randomness | BLOCKED |
|
|
263
|
-
| `fetch()` | External IO | BLOCKED |
|
|
264
|
-
| External imports | Uncontrolled code | BLOCKED |
|
|
265
|
-
|
|
266
|
-
Use `random()` (seeded) and `noise()` (seeded) for all randomness needs.
|
|
267
|
-
|
|
268
|
-
### Oracle Verification
|
|
269
|
-
|
|
270
|
-
Before any release, run the determinism check:
|
|
271
|
-
|
|
272
|
-
```bash
|
|
273
|
-
npx tsx scripts/check-determinism.ts
|
|
300
|
+
```typescript
|
|
301
|
+
runtime.run(() => {
|
|
302
|
+
Math.random(); // Throws: NEXART_STRICT: Non-deterministic API used
|
|
303
|
+
});
|
|
274
304
|
```
|
|
275
305
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
## Products Using This SDK
|
|
281
|
-
|
|
282
|
-
- **NexArt**: Primary generative art platform
|
|
283
|
-
- **ByX**: Curated collection system
|
|
284
|
-
- **Frontierra**: External builder integration
|
|
285
|
-
|
|
286
|
-
---
|
|
287
|
-
|
|
288
|
-
## v1.5.1
|
|
289
|
-
|
|
290
|
-
**Builder Manifest — Passive Attribution (Write-Only)**
|
|
291
|
-
|
|
292
|
-
- `registerBuilderManifest(manifest?)` — Declare builder identity for future attribution
|
|
293
|
-
|
|
294
|
-
The Builder Manifest is a declaration of intent, not a capability. Write-only, optional, non-enforced.
|
|
295
|
-
|
|
296
|
-
---
|
|
297
|
-
|
|
298
|
-
## v1.4.0 (Protocol v1.2.0)
|
|
299
|
-
|
|
300
|
-
**Phase 3 — Pixel & Graphics**
|
|
301
|
-
|
|
302
|
-
- **Vertex Functions**: `curveVertex(x, y)`, `bezierVertex(cx1, cy1, cx2, cy2, x, y)` for smooth curves
|
|
303
|
-
- **Pixel System**: `loadPixels()`, `updatePixels()`, `pixels[]`, `get(x, y)`, `set(x, y, color)`
|
|
304
|
-
- **Graphics System**: `createGraphics(w, h)`, `image(pg, x, y, w, h)` for offscreen rendering
|
|
305
|
-
- **totalFrames**: Now injected into Loop Mode runtime
|
|
306
|
-
|
|
307
|
-
## v1.3.0 (Protocol v1.1.0)
|
|
308
|
-
|
|
309
|
-
**Phase 2 — Expressive Extensions**
|
|
310
|
-
|
|
311
|
-
- **Math Helpers**: `fract(n)`, `sign(n)`
|
|
312
|
-
- **Vector Helpers**: `vec`, `vecAdd`, `vecSub`, `vecMult`, `vecMag`, `vecNorm`, `vecDist`
|
|
313
|
-
- **Shape Helpers**: `polygon()`, `star()`
|
|
314
|
-
- **Blend Modes**: `blendMode(NORMAL|ADD|MULTIPLY|SCREEN)`
|
|
315
|
-
- **Noise Extensions**: `fbm()`, `ridgedNoise()`, `curlNoise()`
|
|
316
|
-
- **Easing Functions**: `easeIn`, `easeOut`, `easeInOut`, `easeCubic`, `easeExpo`
|
|
317
|
-
|
|
318
|
-
## v1.2.0
|
|
319
|
-
|
|
320
|
-
- Added `bezier()`, `curve()`, `strokeCap()`, `strokeJoin()`, `shearX()`, `shearY()`
|
|
321
|
-
- Added text system: `text()`, `textSize()`, `textFont()`, `textAlign()`, `textWidth()`
|
|
322
|
-
- Added `sq()`, `int()`, `TAU`, arc mode constants
|
|
323
|
-
|
|
324
|
-
## v1.1.1
|
|
325
|
-
|
|
326
|
-
- **Critical Fix**: `random()` now uses seeded Mulberry32 PRNG (was using Math.random)
|
|
327
|
-
- All randomness is now deterministic
|
|
328
|
-
|
|
329
|
-
## v1.0.x (Protocol Lock)
|
|
330
|
-
|
|
331
|
-
- **Protocol Lock**: Phase 1 execution surface is now LOCKED
|
|
332
|
-
- **Canonical Entry Point**: `executeCodeMode()` is the official execution API
|
|
333
|
-
- **VAR[0..9] Protocol Variables**: First-class protocol inputs (read-only, 0-100)
|
|
334
|
-
- **Determinism Guarantee**: Same code + seed + vars = identical output
|
|
335
|
-
|
|
336
|
-
---
|
|
337
|
-
|
|
338
|
-
## What This SDK Is
|
|
339
|
-
|
|
340
|
-
This SDK provides the **canonical runtime** for executing p5.js-style generative art:
|
|
341
|
-
|
|
342
|
-
- **Static Mode**: Executes `setup()` only, outputs PNG
|
|
343
|
-
- **Loop Mode**: Frame-authoritative rendering, outputs MP4
|
|
344
|
-
- **Deterministic**: Seed-controlled randomness, no external state
|
|
345
|
-
- **Protocol-Compliant**: All outputs include verification metadata
|
|
346
|
-
|
|
347
|
-
The SDK enforces the **NexArt Code Mode Protocol v1.2.0** for reproducible, mint-safe generative art.
|
|
348
|
-
|
|
349
|
-
---
|
|
350
|
-
|
|
351
|
-
## What This SDK Is NOT
|
|
352
|
-
|
|
353
|
-
- **Not a suggestion** — This SDK IS the protocol, not a reference implementation
|
|
354
|
-
- **Not a UI library** — No React components, no wallet integration
|
|
355
|
-
- **Not an IPFS client** — Does not handle storage or minting
|
|
356
|
-
- **Not p5.js** — Uses a minimal subset of p5.js-like functions
|
|
357
|
-
|
|
358
|
-
---
|
|
359
|
-
|
|
360
|
-
## Installation
|
|
361
|
-
|
|
362
|
-
```bash
|
|
363
|
-
# Copy the sdk/codemode folder to your project
|
|
364
|
-
cp -r sdk/codemode your-project/lib/codemode
|
|
365
|
-
```
|
|
306
|
+
Strict mode:
|
|
307
|
+
- Only applies during `runtime.run()` — non-invasive
|
|
308
|
+
- Does NOT globally mutate your application
|
|
309
|
+
- Provides actionable error messages
|
|
366
310
|
|
|
367
311
|
---
|
|
368
312
|
|
|
369
|
-
## Browser Usage
|
|
313
|
+
## Browser Usage
|
|
370
314
|
|
|
371
|
-
For Vite, React, Next.js, or any browser environment
|
|
315
|
+
For Vite, React, Next.js, or any browser environment:
|
|
372
316
|
|
|
373
317
|
```typescript
|
|
374
318
|
import {
|
|
319
|
+
createRuntime,
|
|
375
320
|
runLoopMode,
|
|
376
321
|
cancelLoopMode,
|
|
377
322
|
createP5Runtime,
|
|
378
323
|
validateCodeModeSource,
|
|
379
|
-
|
|
380
|
-
DEFAULT_CONFIG,
|
|
381
|
-
} from '@nexart/codemode-sdk/browser';
|
|
324
|
+
} from '@nexart/codemode-sdk';
|
|
382
325
|
```
|
|
383
326
|
|
|
384
|
-
**What's included
|
|
385
|
-
-
|
|
327
|
+
**What's included:**
|
|
328
|
+
- Runtime API (createRuntime)
|
|
386
329
|
- P5 runtime (createP5Runtime, injectTimeVariables, injectProtocolVariables)
|
|
387
330
|
- Loop engine (runLoopMode, cancelLoopMode)
|
|
388
331
|
- Execution sandbox (FORBIDDEN_APIS, createSafeMath)
|
|
389
332
|
- Validation (validateCodeModeSource)
|
|
390
|
-
- Builder manifest (registerBuilderManifest)
|
|
391
333
|
|
|
392
334
|
**What's NOT included (Node.js only):**
|
|
393
|
-
- `executeCodeMode` —
|
|
394
|
-
- `runStaticMode` — Requires Node.js canvas
|
|
395
|
-
|
|
396
|
-
For static rendering in browser apps, use your server-side API endpoint.
|
|
335
|
+
- `executeCodeMode` — Requires Node.js canvas
|
|
336
|
+
- `runStaticMode` — Requires Node.js canvas
|
|
397
337
|
|
|
398
338
|
---
|
|
399
339
|
|
|
400
|
-
## Node.js Usage
|
|
340
|
+
## Node.js Usage
|
|
401
341
|
|
|
402
|
-
For server-side rendering, oracles, or CLI tools
|
|
342
|
+
For server-side rendering, oracles, or CLI tools:
|
|
403
343
|
|
|
404
344
|
```typescript
|
|
405
345
|
import {
|
|
@@ -410,27 +350,20 @@ import {
|
|
|
410
350
|
} from '@nexart/codemode-sdk/node';
|
|
411
351
|
```
|
|
412
352
|
|
|
413
|
-
**What's included in `@nexart/codemode-sdk/node`:**
|
|
414
|
-
- Everything from the browser entry
|
|
415
|
-
- `executeCodeMode` — Canonical execution API
|
|
416
|
-
- `runStaticMode` — Node.js static rendering (requires `canvas` package)
|
|
417
|
-
|
|
418
353
|
**Requirements:**
|
|
419
354
|
- Node.js 18+
|
|
420
|
-
- `canvas` package
|
|
355
|
+
- `canvas` package for static mode
|
|
421
356
|
|
|
422
357
|
---
|
|
423
358
|
|
|
424
|
-
## Canonical API
|
|
359
|
+
## Canonical Execution API
|
|
425
360
|
|
|
426
|
-
### `executeCodeMode(input
|
|
361
|
+
### `executeCodeMode(input): Promise<Result>`
|
|
427
362
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
All implementations MUST use this function.
|
|
363
|
+
For systems requiring p5.js-style execution with full protocol metadata:
|
|
431
364
|
|
|
432
365
|
```typescript
|
|
433
|
-
import { executeCodeMode } from '@nexart/codemode-sdk';
|
|
366
|
+
import { executeCodeMode } from '@nexart/codemode-sdk/node';
|
|
434
367
|
|
|
435
368
|
const result = await executeCodeMode({
|
|
436
369
|
source: `
|
|
@@ -448,180 +381,24 @@ const result = await executeCodeMode({
|
|
|
448
381
|
mode: 'static'
|
|
449
382
|
});
|
|
450
383
|
|
|
451
|
-
//
|
|
452
|
-
console.log(result.
|
|
453
|
-
console.log(result.metadata.engine); // 'codemode'
|
|
454
|
-
console.log(result.metadata.protocolVersion); // '1.2.0'
|
|
455
|
-
console.log(result.metadata.deterministic); // true
|
|
456
|
-
console.log(result.image); // PNG Blob
|
|
457
|
-
```
|
|
458
|
-
|
|
459
|
-
### Input Parameters
|
|
460
|
-
|
|
461
|
-
| Parameter | Type | Required | Description |
|
|
462
|
-
|-----------|------|----------|-------------|
|
|
463
|
-
| `source` | `string` | ✅ | Code with setup() and optional draw() |
|
|
464
|
-
| `width` | `number` | ✅ | Canvas width in pixels |
|
|
465
|
-
| `height` | `number` | ✅ | Canvas height in pixels |
|
|
466
|
-
| `seed` | `number` | ✅ | Seed for deterministic randomness |
|
|
467
|
-
| `vars` | `number[]` | ❌ | VAR[0..9] values (0-100), defaults to all zeros |
|
|
468
|
-
| `mode` | `'static' \| 'loop'` | ✅ | Execution mode |
|
|
469
|
-
| `totalFrames` | `number` | ⚠️ | Required for loop mode |
|
|
470
|
-
|
|
471
|
-
### Result Structure
|
|
472
|
-
|
|
473
|
-
```typescript
|
|
474
|
-
interface ExecuteCodeModeResult {
|
|
475
|
-
image?: Blob; // Static mode: PNG
|
|
476
|
-
video?: Blob; // Loop mode: MP4
|
|
477
|
-
frames?: ImageData[]; // Optional: raw frame data
|
|
478
|
-
metadata: {
|
|
479
|
-
protocol: 'nexart';
|
|
480
|
-
engine: 'codemode';
|
|
481
|
-
protocolVersion: '1.0.0';
|
|
482
|
-
phase: 1;
|
|
483
|
-
deterministic: true;
|
|
484
|
-
seed: number;
|
|
485
|
-
vars: number[];
|
|
486
|
-
width: number;
|
|
487
|
-
height: number;
|
|
488
|
-
mode: 'static' | 'loop';
|
|
489
|
-
totalFrames?: number;
|
|
490
|
-
}
|
|
491
|
-
}
|
|
384
|
+
console.log(result.metadata.deterministic); // true
|
|
385
|
+
console.log(result.image); // PNG Blob
|
|
492
386
|
```
|
|
493
387
|
|
|
494
388
|
---
|
|
495
389
|
|
|
496
|
-
## Legacy API
|
|
497
|
-
|
|
498
|
-
> ⚠️ **Note**: The `createEngine()` API is still supported but new implementations should use `executeCodeMode()`.
|
|
499
|
-
|
|
500
|
-
### `createEngine(config: EngineConfig): Engine`
|
|
501
|
-
|
|
502
|
-
Create a rendering engine instance.
|
|
503
|
-
|
|
504
|
-
```typescript
|
|
505
|
-
import { createEngine } from './codemode';
|
|
506
|
-
|
|
507
|
-
const engine = createEngine({
|
|
508
|
-
mode: 'static', // 'static' | 'loop'
|
|
509
|
-
width: 1950, // Optional, default: 1950
|
|
510
|
-
height: 2400, // Optional, default: 2400
|
|
511
|
-
duration: 2, // Loop mode only, 1-4 seconds
|
|
512
|
-
fps: 30, // Loop mode only, default: 30
|
|
513
|
-
});
|
|
514
|
-
```
|
|
515
|
-
|
|
516
|
-
### `engine.run(options: RunOptions): Promise<void>`
|
|
517
|
-
|
|
518
|
-
Execute code and produce output.
|
|
519
|
-
|
|
520
|
-
```typescript
|
|
521
|
-
await engine.run({
|
|
522
|
-
code: `
|
|
523
|
-
function setup() {
|
|
524
|
-
background(255);
|
|
525
|
-
fill(0);
|
|
526
|
-
// Use VAR for external control
|
|
527
|
-
let size = map(VAR[0], 0, 100, 50, 200);
|
|
528
|
-
ellipse(width/2, height/2, size);
|
|
529
|
-
}
|
|
530
|
-
`,
|
|
531
|
-
seed: 12345, // Optional: seed for deterministic randomness
|
|
532
|
-
vars: [50, 75, 0, 0, 0, 0, 0, 0, 0, 0], // Optional: VAR[0..9] values (0-100)
|
|
533
|
-
onPreview: (canvas) => {
|
|
534
|
-
// Optional: called with canvas after first frame
|
|
535
|
-
},
|
|
536
|
-
onProgress: (info) => {
|
|
537
|
-
// Optional: progress updates
|
|
538
|
-
console.log(info.message, info.percent + '%');
|
|
539
|
-
},
|
|
540
|
-
onComplete: (result) => {
|
|
541
|
-
// Required: called with final result
|
|
542
|
-
console.log(result.type); // 'image' | 'video'
|
|
543
|
-
console.log(result.blob); // Blob
|
|
544
|
-
},
|
|
545
|
-
onError: (error) => {
|
|
546
|
-
// Optional: called on error
|
|
547
|
-
console.error(error);
|
|
548
|
-
},
|
|
549
|
-
});
|
|
550
|
-
```
|
|
551
|
-
|
|
552
|
-
### Protocol Variables (VAR[0..9]) — Protocol v1.0.0
|
|
553
|
-
|
|
554
|
-
Protocol variables are first-class inputs that control artwork parameters.
|
|
555
|
-
|
|
556
|
-
**VAR Specification (SDK v1.0.2):**
|
|
557
|
-
|
|
558
|
-
| Property | Value | Enforcement |
|
|
559
|
-
|----------|-------|-------------|
|
|
560
|
-
| Input count | 0-10 (VAR[0]..VAR[9]) | HARD — throws if > 10 |
|
|
561
|
-
| Runtime count | Always 10 | Padded with zeros |
|
|
562
|
-
| Type | finite number | HARD — throws if non-number |
|
|
563
|
-
| Range | 0-100 | HARD — throws if out of range |
|
|
564
|
-
| Mutability | Read-only | HARD — Proxy blocks writes |
|
|
565
|
-
| Injection | Before execution | Guaranteed |
|
|
566
|
-
| Lifecycle | Stable for entire render | Guaranteed |
|
|
567
|
-
| Default | All zeros | If not provided |
|
|
568
|
-
|
|
569
|
-
```typescript
|
|
570
|
-
// Pass values when running (0-10 elements)
|
|
571
|
-
await engine.run({
|
|
572
|
-
code: myCode,
|
|
573
|
-
vars: [80, 50, 25], // VAR[0]=80, VAR[1]=50, VAR[2]=25, VAR[3..9]=0
|
|
574
|
-
onComplete: (result) => { /* ... */ },
|
|
575
|
-
});
|
|
576
|
-
|
|
577
|
-
// Or omit entirely (all zeros)
|
|
578
|
-
await engine.run({
|
|
579
|
-
code: myCode,
|
|
580
|
-
onComplete: (result) => { /* ... */ },
|
|
581
|
-
});
|
|
582
|
-
|
|
583
|
-
// Access in sketch code
|
|
584
|
-
function setup() {
|
|
585
|
-
let density = map(VAR[0], 0, 100, 10, 200);
|
|
586
|
-
let speed = map(VAR[1], 0, 100, 0.5, 5);
|
|
587
|
-
// VAR[5] returns 0 if not provided
|
|
588
|
-
}
|
|
589
|
-
```
|
|
590
|
-
|
|
591
|
-
**Rules (Protocol Law):**
|
|
592
|
-
- Input accepts 0-10 elements; runtime VAR is always 10 elements
|
|
593
|
-
- VAR is injected BEFORE code execution (padded with zeros if needed)
|
|
594
|
-
- VAR values are READ-ONLY at runtime (Proxy-protected)
|
|
595
|
-
- Writing to VAR throws a protocol error
|
|
596
|
-
- Values MUST be in range 0-100 (throws if out of range)
|
|
597
|
-
- Same code + same seed + same VARs = identical output
|
|
598
|
-
|
|
599
|
-
### `engine.stop(): void`
|
|
600
|
-
|
|
601
|
-
Cancel a running render (Loop mode only).
|
|
602
|
-
|
|
603
|
-
### `engine.getConfig(): EngineConfig`
|
|
604
|
-
|
|
605
|
-
Get the resolved engine configuration.
|
|
606
|
-
|
|
607
|
-
---
|
|
608
|
-
|
|
609
390
|
## Execution Rules
|
|
610
391
|
|
|
611
392
|
### Static Mode
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
4. Time variables are all `0`
|
|
393
|
+
1. `setup()` executes once
|
|
394
|
+
2. `draw()` is NOT executed
|
|
395
|
+
3. Canvas captured as PNG
|
|
396
|
+
4. Time variables are 0
|
|
617
397
|
|
|
618
398
|
### Loop Mode
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
3. Canvas is **cleared** before each `draw()` call
|
|
623
|
-
4. If artist calls `background()` in draw, it paints over the clear
|
|
624
|
-
5. No canvas persistence between frames
|
|
399
|
+
1. `setup()` executes once
|
|
400
|
+
2. `draw()` executes per frame
|
|
401
|
+
3. Canvas cleared before each `draw()`
|
|
625
402
|
|
|
626
403
|
**Time Variables:**
|
|
627
404
|
|
|
@@ -631,277 +408,50 @@ Get the resolved engine configuration.
|
|
|
631
408
|
| `t` | float | Normalized time [0.0, 1.0) |
|
|
632
409
|
| `time` | float | Elapsed seconds |
|
|
633
410
|
| `tGlobal` | float | Alias for `t` |
|
|
411
|
+
| `totalFrames` | int | Total frames in loop |
|
|
634
412
|
|
|
635
413
|
---
|
|
636
414
|
|
|
637
|
-
## Forbidden Patterns
|
|
415
|
+
## Forbidden Patterns
|
|
638
416
|
|
|
639
|
-
The following
|
|
417
|
+
The following are rejected with `[Code Mode Protocol Error]`:
|
|
640
418
|
|
|
641
419
|
| Pattern | Reason |
|
|
642
420
|
|---------|--------|
|
|
643
|
-
| `
|
|
644
|
-
| `
|
|
645
|
-
| `
|
|
646
|
-
| `
|
|
647
|
-
| `
|
|
648
|
-
| `
|
|
649
|
-
| `
|
|
650
|
-
| `
|
|
651
|
-
| `
|
|
652
|
-
| `document.*` | DOM access
|
|
653
|
-
| `window.*` | DOM access
|
|
654
|
-
| `import` | External imports
|
|
655
|
-
| `require()` | External imports
|
|
656
|
-
|
|
657
|
-
Additionally in Loop Mode:
|
|
658
|
-
- `noLoop()` — Incompatible with frame capture
|
|
421
|
+
| `Math.random()` | Use seeded `random()` |
|
|
422
|
+
| `Date.now()` | Time-based entropy |
|
|
423
|
+
| `new Date()` | Time-based entropy |
|
|
424
|
+
| `performance.now()` | Timing entropy |
|
|
425
|
+
| `crypto.getRandomValues()` | Crypto randomness |
|
|
426
|
+
| `fetch()` | External IO |
|
|
427
|
+
| `setTimeout` | Async timing |
|
|
428
|
+
| `setInterval` | Async timing |
|
|
429
|
+
| `requestAnimationFrame` | Async timing |
|
|
430
|
+
| `document.*` | DOM access |
|
|
431
|
+
| `window.*` | DOM access |
|
|
432
|
+
| `import` | External imports |
|
|
433
|
+
| `require()` | External imports |
|
|
659
434
|
|
|
660
435
|
---
|
|
661
436
|
|
|
662
|
-
##
|
|
663
|
-
|
|
664
|
-
```typescript
|
|
665
|
-
import { createEngine } from './codemode';
|
|
666
|
-
|
|
667
|
-
const engine = createEngine({ mode: 'static' });
|
|
437
|
+
## Examples
|
|
668
438
|
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
noStroke();
|
|
674
|
-
for (let i = 0; i < 100; i++) {
|
|
675
|
-
fill(random(255), random(255), random(255));
|
|
676
|
-
ellipse(random(width), random(height), 50);
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
`,
|
|
680
|
-
onComplete: (result) => {
|
|
681
|
-
// result.type === 'image'
|
|
682
|
-
// result.blob is a PNG Blob
|
|
683
|
-
const url = URL.createObjectURL(result.blob);
|
|
684
|
-
document.body.innerHTML = `<img src="${url}" />`;
|
|
685
|
-
},
|
|
686
|
-
});
|
|
687
|
-
```
|
|
688
|
-
|
|
689
|
-
---
|
|
690
|
-
|
|
691
|
-
## Example: Loop Mode
|
|
692
|
-
|
|
693
|
-
```typescript
|
|
694
|
-
import { createEngine } from './codemode';
|
|
695
|
-
|
|
696
|
-
const engine = createEngine({
|
|
697
|
-
mode: 'loop',
|
|
698
|
-
duration: 2, // 2 second loop
|
|
699
|
-
});
|
|
700
|
-
|
|
701
|
-
await engine.run({
|
|
702
|
-
code: `
|
|
703
|
-
function setup() {
|
|
704
|
-
// Called once
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
function draw() {
|
|
708
|
-
background(30);
|
|
709
|
-
|
|
710
|
-
// t goes from 0 to 1 over the loop duration
|
|
711
|
-
let x = width/2 + cos(t * TWO_PI) * 200;
|
|
712
|
-
let y = height/2 + sin(t * TWO_PI) * 200;
|
|
713
|
-
|
|
714
|
-
fill(255);
|
|
715
|
-
ellipse(x, y, 80);
|
|
716
|
-
}
|
|
717
|
-
`,
|
|
718
|
-
onProgress: (info) => {
|
|
719
|
-
console.log(info.message);
|
|
720
|
-
},
|
|
721
|
-
onComplete: (result) => {
|
|
722
|
-
// result.type === 'video'
|
|
723
|
-
// result.blob is an MP4 Blob
|
|
724
|
-
const url = URL.createObjectURL(result.blob);
|
|
725
|
-
document.body.innerHTML = `<video src="${url}" autoplay loop />`;
|
|
726
|
-
},
|
|
727
|
-
});
|
|
728
|
-
```
|
|
729
|
-
|
|
730
|
-
---
|
|
731
|
-
|
|
732
|
-
## Supported Functions
|
|
733
|
-
|
|
734
|
-
The SDK includes a comprehensive p5.js-like runtime with 130+ functions:
|
|
735
|
-
|
|
736
|
-
**Drawing:**
|
|
737
|
-
`background`, `clear`, `fill`, `noFill`, `stroke`, `noStroke`, `strokeWeight`, `strokeCap`, `strokeJoin`
|
|
738
|
-
|
|
739
|
-
**Shapes:**
|
|
740
|
-
`ellipse`, `circle`, `rect`, `square`, `line`, `point`, `triangle`, `quad`, `arc`, `bezier`, `curve`
|
|
741
|
-
|
|
742
|
-
**Vertex (v1.4.0):**
|
|
743
|
-
`beginShape`, `vertex`, `curveVertex`, `bezierVertex`, `endShape`
|
|
744
|
-
|
|
745
|
-
**Shape Helpers (v1.3.0):**
|
|
746
|
-
`polygon`, `star`
|
|
747
|
-
|
|
748
|
-
**Transform:**
|
|
749
|
-
`push`, `pop`, `translate`, `rotate`, `scale`, `resetMatrix`, `shearX`, `shearY`
|
|
750
|
-
|
|
751
|
-
**Color:**
|
|
752
|
-
`colorMode`, `color`, `lerpColor`, `red`, `green`, `blue`, `alpha`, `hue`, `saturation`, `brightness`
|
|
753
|
-
|
|
754
|
-
**Text:**
|
|
755
|
-
`text`, `textSize`, `textFont`, `textAlign`, `textWidth`
|
|
756
|
-
|
|
757
|
-
**Blend Modes (v1.3.0):**
|
|
758
|
-
`blendMode(NORMAL|ADD|MULTIPLY|SCREEN)`
|
|
759
|
-
|
|
760
|
-
**Pixel System (v1.4.0):**
|
|
761
|
-
`loadPixels`, `updatePixels`, `pixels[]`, `get`, `set`
|
|
762
|
-
|
|
763
|
-
**Graphics (v1.4.0):**
|
|
764
|
-
`createGraphics`, `image`
|
|
765
|
-
|
|
766
|
-
**Color Formats:**
|
|
767
|
-
All of the following are accepted by `fill()`, `stroke()`, `background()`:
|
|
768
|
-
- Grayscale: `fill(128)`, `fill(128, 127)`
|
|
769
|
-
- RGB: `fill(255, 0, 0)`, `fill(255, 0, 0, 128)`
|
|
770
|
-
- Hex: `fill('#ff0000')`, `fill('#f00')`
|
|
771
|
-
- CSS: `fill('rgb(255,0,0)')`, `fill('rgba(255,0,0,0.5)')`, `fill('hsl(180,50%,50%)')`
|
|
772
|
-
|
|
773
|
-
**Protocol Variables:**
|
|
774
|
-
`VAR` — Array of 10 values (VAR[0] through VAR[9])
|
|
775
|
-
|
|
776
|
-
**Math:**
|
|
777
|
-
`random`, `noise`, `map`, `constrain`, `lerp`, `dist`, `mag`, `norm`, `sq`, `int`, `fract`, `sign`
|
|
778
|
-
|
|
779
|
-
**Vectors (v1.3.0):**
|
|
780
|
-
`vec`, `vecAdd`, `vecSub`, `vecMult`, `vecMag`, `vecNorm`, `vecDist`
|
|
781
|
-
|
|
782
|
-
**Noise Extensions (v1.3.0):**
|
|
783
|
-
`fbm`, `ridgedNoise`, `curlNoise`
|
|
784
|
-
|
|
785
|
-
**Easing (v1.3.0):**
|
|
786
|
-
`easeIn`, `easeOut`, `easeInOut`, `easeCubic`, `easeExpo`
|
|
787
|
-
|
|
788
|
-
**Trig:**
|
|
789
|
-
`sin`, `cos`, `tan`, `asin`, `acos`, `atan`, `atan2`, `radians`, `degrees`
|
|
790
|
-
|
|
791
|
-
**Constants:**
|
|
792
|
-
`PI`, `TWO_PI`, `TAU`, `HALF_PI`, `QUARTER_PI`, `width`, `height`, `frameCount`, `totalFrames`
|
|
793
|
-
|
|
794
|
-
---
|
|
795
|
-
|
|
796
|
-
## Video Encoding
|
|
797
|
-
|
|
798
|
-
Loop Mode requires server-side video encoding. The SDK calls:
|
|
799
|
-
|
|
800
|
-
```
|
|
801
|
-
POST /api/encode-loop
|
|
802
|
-
```
|
|
803
|
-
|
|
804
|
-
Ensure your server has this endpoint available (NexArt provides this).
|
|
805
|
-
|
|
806
|
-
---
|
|
807
|
-
|
|
808
|
-
## Files
|
|
809
|
-
|
|
810
|
-
```
|
|
811
|
-
sdk/codemode/
|
|
812
|
-
├── entry/
|
|
813
|
-
│ ├── browser.ts # Browser-safe entry point (v1.7.0)
|
|
814
|
-
│ └── node.ts # Node.js entry point (v1.7.0)
|
|
815
|
-
├── index.ts # Main export (app integration layer)
|
|
816
|
-
├── core-index.ts # Core runtime exports
|
|
817
|
-
├── execute.ts # executeCodeMode canonical entry point
|
|
818
|
-
├── engine.ts # createEngine entry point (legacy)
|
|
819
|
-
├── types.ts # TypeScript types
|
|
820
|
-
├── static-engine.ts # Static mode implementation (Node.js)
|
|
821
|
-
├── loop-engine.ts # Loop mode implementation (browser)
|
|
822
|
-
├── p5-runtime.ts # p5.js-like runtime
|
|
823
|
-
├── execution-sandbox.ts # Determinism enforcement
|
|
824
|
-
├── builder-manifest.ts # Builder manifest (write-only)
|
|
825
|
-
├── CHANGELOG.md # Version history
|
|
826
|
-
└── README.md # This file
|
|
439
|
+
```bash
|
|
440
|
+
npm run example:agent # Agent quickstart (RECOMMENDED for AI agents)
|
|
441
|
+
npm run example:basic # Basic usage
|
|
442
|
+
npm run example:verify # Determinism verification
|
|
827
443
|
```
|
|
828
444
|
|
|
829
445
|
---
|
|
830
446
|
|
|
831
|
-
##
|
|
832
|
-
|
|
833
|
-
MIT License
|
|
447
|
+
## Changelog
|
|
834
448
|
|
|
835
|
-
|
|
449
|
+
See [CHANGELOG.md](./CHANGELOG.md) for version history.
|
|
836
450
|
|
|
837
451
|
---
|
|
838
452
|
|
|
839
|
-
##
|
|
840
|
-
|
|
841
|
-
This SDK is designed for use by:
|
|
842
|
-
|
|
843
|
-
- **NexArt App**: The main generative art platform
|
|
844
|
-
- **ByX**: Curated collection system
|
|
845
|
-
- **External Builders**: Any platform consuming NexArt Code Mode
|
|
846
|
-
|
|
847
|
-
### Integration Example
|
|
848
|
-
|
|
849
|
-
```typescript
|
|
850
|
-
import { executeCodeMode } from '@nexart/codemode-sdk';
|
|
851
|
-
|
|
852
|
-
// Execute with explicit VAR values
|
|
853
|
-
const result = await executeCodeMode({
|
|
854
|
-
source: artistCode,
|
|
855
|
-
width: 1950,
|
|
856
|
-
height: 2400,
|
|
857
|
-
seed: 12345,
|
|
858
|
-
vars: [50, 75, 25, 0, 0, 0, 0, 0, 0, 0], // Exactly 10 values
|
|
859
|
-
mode: 'static'
|
|
860
|
-
});
|
|
861
|
-
|
|
862
|
-
// Result includes full protocol metadata for verification
|
|
863
|
-
const { image, metadata } = result;
|
|
864
|
-
console.log(metadata.protocolVersion); // '1.2.0'
|
|
865
|
-
console.log(metadata.deterministic); // true
|
|
866
|
-
```
|
|
867
|
-
|
|
868
|
-
### Error Handling
|
|
869
|
-
|
|
870
|
-
All protocol violations throw descriptive errors:
|
|
871
|
-
|
|
872
|
-
```typescript
|
|
873
|
-
try {
|
|
874
|
-
await executeCodeMode({ ... });
|
|
875
|
-
} catch (error) {
|
|
876
|
-
// "[Code Mode Protocol Error] VAR array must have exactly 10 elements, got 5"
|
|
877
|
-
// "[Code Mode Protocol Error] Forbidden pattern: Math.random()"
|
|
878
|
-
console.error(error.message);
|
|
879
|
-
}
|
|
880
|
-
```
|
|
881
|
-
|
|
882
|
-
---
|
|
883
|
-
|
|
884
|
-
## Frozen Execution Guarantees — v1.0.0
|
|
885
|
-
|
|
886
|
-
The following guarantees are LOCKED and will not change in v1.x:
|
|
887
|
-
|
|
888
|
-
| Guarantee | Description |
|
|
889
|
-
|-----------|-------------|
|
|
890
|
-
| Determinism | Same code + same seed + same VARs = identical output |
|
|
891
|
-
| Static Mode | `setup()` only, single PNG output |
|
|
892
|
-
| Loop Mode | Frame-authoritative, `draw()` per frame, MP4 output |
|
|
893
|
-
| Time Semantics | `t` ∈ [0,1), `frameCount` ∈ [0,totalFrames), `time` in seconds |
|
|
894
|
-
| Random | Seeded Mulberry32 PRNG via `random()` |
|
|
895
|
-
| Noise | Seeded Perlin noise via `noise()` |
|
|
896
|
-
| Canvas | Pre-initialized, no `createCanvas()` |
|
|
897
|
-
| VAR | Exactly 10 read-only protocol variables |
|
|
898
|
-
| Forbidden Patterns | 13 patterns rejected (see above) |
|
|
899
|
-
|
|
900
|
-
---
|
|
453
|
+
## About
|
|
901
454
|
|
|
902
|
-
|
|
455
|
+
This SDK is a reference implementation of a deterministic execution protocol designed for replay, verification, and long-term stability.
|
|
903
456
|
|
|
904
|
-
|
|
905
|
-
- WebGL/3D rendering support
|
|
906
|
-
- GIF output option
|
|
907
|
-
- GSL v1 SDK (protocol layer) — separate package
|
|
457
|
+
It prioritizes correctness and reproducibility over features.
|