@nexart/codemode-sdk 1.7.0 → 1.8.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 +60 -0
- package/README.md +132 -6
- package/dist/core-index.d.ts +1 -1
- package/dist/core-index.js +1 -1
- package/dist/entry/browser.d.ts +8 -2
- package/dist/entry/browser.d.ts.map +1 -1
- package/dist/entry/browser.js +10 -2
- package/dist/entry/node.d.ts +3 -1
- package/dist/entry/node.d.ts.map +1 -1
- package/dist/entry/node.js +3 -1
- package/dist/runtime.d.ts +52 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +219 -0
- package/examples/basic.ts +61 -0
- package/examples/preflight-test.ts +275 -0
- package/examples/verify.ts +151 -0
- package/package.json +19 -3
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,66 @@ All notable changes to @nexart/codemode-sdk will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## [1.8.0] — 2026-01-24
|
|
8
|
+
|
|
9
|
+
### Added — Agent-First Runtime Authority Layer
|
|
10
|
+
|
|
11
|
+
**Additive, Non-Breaking Release**
|
|
12
|
+
|
|
13
|
+
This release introduces `createRuntime()` — an agent-first API designed for AI coding assistants (Replit, Lovable, Claude Code) to reliably execute deterministic code without rolling their own PRNG/noise implementations.
|
|
14
|
+
|
|
15
|
+
#### New Runtime API (`createRuntime`)
|
|
16
|
+
- **`createRuntime(options)`** — Create a deterministic runtime instance
|
|
17
|
+
- `seed: string | number` — Seed for deterministic randomness
|
|
18
|
+
- `vars?: number[]` — VAR array (0-100 inputs), defaults to zeros
|
|
19
|
+
- `strict?: boolean` — Enable strict mode (default: false)
|
|
20
|
+
- `mode?: 'static' | 'loop'` — Execution mode (default: 'static')
|
|
21
|
+
- `metadata?: Record<string, any>` — Optional user metadata for digest
|
|
22
|
+
|
|
23
|
+
#### Runtime Methods
|
|
24
|
+
- **`random(): number`** — Deterministic random [0, 1) using Mulberry32
|
|
25
|
+
- **`randomInt(min, max): number`** — Deterministic integer in range
|
|
26
|
+
- **`randomRange(min, max): number`** — Deterministic float in range
|
|
27
|
+
- **`noise(x, y?, z?): number`** — Deterministic Perlin noise
|
|
28
|
+
- **`run(fn): T`** — Execute code with optional strict enforcement
|
|
29
|
+
- **`digest(): string`** — Stable hash for verification (FNV-1a)
|
|
30
|
+
- **`getState(): RuntimeState`** — Canonical state snapshot for replay
|
|
31
|
+
|
|
32
|
+
#### Strict Mode Enforcement
|
|
33
|
+
When `strict: true`, the runtime intercepts non-deterministic APIs during `run()`:
|
|
34
|
+
- `Math.random` → Throws with actionable error message
|
|
35
|
+
- `Date.now` → Throws with actionable error message
|
|
36
|
+
- `performance.now` → Throws with actionable error message
|
|
37
|
+
|
|
38
|
+
Error format: `NEXART_STRICT: Non-deterministic API used: {api}. {guidance}`
|
|
39
|
+
|
|
40
|
+
#### Documentation Updates
|
|
41
|
+
- Added "For AI Coding Agents" section at top of README
|
|
42
|
+
- Added "Determinism Contract" with ✅/❌ checklist
|
|
43
|
+
- Added "Why Not Just Use a PRNG?" comparison table
|
|
44
|
+
- Added "Environment Imports" matrix
|
|
45
|
+
- Simplified license section for clarity
|
|
46
|
+
|
|
47
|
+
#### Examples
|
|
48
|
+
- `examples/basic.ts` — Basic usage demonstration
|
|
49
|
+
- `examples/verify.ts` — Determinism verification tests
|
|
50
|
+
- `npm run example:basic` — Run basic example
|
|
51
|
+
- `npm run example:verify` — Run verification tests
|
|
52
|
+
|
|
53
|
+
#### Package Updates
|
|
54
|
+
- Added keywords: deterministic, reproducible, verifiable, replay, canonical, simulation, procedural, seed, prng, ai-agent, strict-mode
|
|
55
|
+
- Updated description for agent discoverability
|
|
56
|
+
|
|
57
|
+
### Unchanged
|
|
58
|
+
|
|
59
|
+
- No changes to protocol behavior or determinism
|
|
60
|
+
- No changes to protocol version (remains v1.2.0)
|
|
61
|
+
- No changes to existing APIs (executeCodeMode, createEngine, etc.)
|
|
62
|
+
- Default import remains browser-safe
|
|
63
|
+
- Full backward compatibility with v1.7.x
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
7
67
|
## [1.7.0] — 2026-01-21
|
|
8
68
|
|
|
9
69
|
### Added — Browser-Safe Entrypoint + Conditional Exports
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# NexArt Code Mode Runtime SDK
|
|
2
2
|
|
|
3
|
-
**Version: 1.
|
|
3
|
+
**Version: 1.8.0 (Protocol v1.2.0)**
|
|
4
4
|
|
|
5
5
|
╔══════════════════════════════════════════════════════════════════════════════╗
|
|
6
6
|
║ @nexart/codemode-sdk — Canonical Execution Surface ║
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
║ ║
|
|
10
10
|
║ Protocol: nexart ║
|
|
11
11
|
║ Engine: codemode ║
|
|
12
|
-
║ SDK Version: 1.
|
|
12
|
+
║ SDK Version: 1.8.0 ║
|
|
13
13
|
║ Protocol Version: 1.2.0 ║
|
|
14
14
|
║ Phase: 3 ║
|
|
15
15
|
║ Enforcement: HARD ║
|
|
@@ -17,12 +17,90 @@
|
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
20
|
-
##
|
|
20
|
+
## For AI Coding Agents (Replit / Lovable / Claude Code)
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
> **Enforcement is not active yet.**
|
|
22
|
+
**ALWAYS use `createRuntime({ seed, strict: true })` for deterministic execution.**
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
```typescript
|
|
25
|
+
import { createRuntime } from "@nexart/codemode-sdk";
|
|
26
|
+
|
|
27
|
+
const runtime = createRuntime({
|
|
28
|
+
seed: "my-artwork-42",
|
|
29
|
+
vars: [50, 75, 25],
|
|
30
|
+
strict: true, // IMPORTANT: Throws on Math.random, Date.now, etc.
|
|
31
|
+
mode: "static"
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Use runtime.random() instead of Math.random()
|
|
35
|
+
const value = runtime.random(); // Deterministic [0, 1)
|
|
36
|
+
const intVal = runtime.randomInt(0, 10); // Deterministic integer
|
|
37
|
+
const n = runtime.noise(x, y); // Deterministic Perlin noise
|
|
38
|
+
|
|
39
|
+
// Verify determinism
|
|
40
|
+
console.log(runtime.digest()); // Stable hash for verification
|
|
41
|
+
console.log(runtime.getState()); // Canonical state snapshot
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Strict mode throws actionable errors:**
|
|
45
|
+
- `NEXART_STRICT: Non-deterministic API used: Math.random. Use runtime.random() instead.`
|
|
46
|
+
- `NEXART_STRICT: Non-deterministic API used: Date.now. Pass time as an input or use deterministic counters.`
|
|
47
|
+
- `NEXART_STRICT: Non-deterministic API used: performance.now.`
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Determinism Contract
|
|
52
|
+
|
|
53
|
+
✅ **Guaranteed:**
|
|
54
|
+
- Same `sdkVersion` + `seed` + `vars` → identical output
|
|
55
|
+
- Cross-environment stable digest (browser, Node.js, CI)
|
|
56
|
+
- Seeded PRNG via `runtime.random()` (Mulberry32)
|
|
57
|
+
- Seeded noise via `runtime.noise()` (Perlin)
|
|
58
|
+
|
|
59
|
+
❌ **Forbidden (blocked in strict mode):**
|
|
60
|
+
- `Math.random()` — use `runtime.random()` instead
|
|
61
|
+
- `Date.now()` — pass time as input or use frame counters
|
|
62
|
+
- `performance.now()` — use deterministic timing
|
|
63
|
+
- External IO during deterministic runs (not supported)
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Why Not Just Use a PRNG?
|
|
68
|
+
|
|
69
|
+
| Feature | Plain PRNG | NexArt Runtime |
|
|
70
|
+
|---------|-----------|----------------|
|
|
71
|
+
| Seeded random | ✅ | ✅ |
|
|
72
|
+
| Seeded noise | ❌ (separate lib) | ✅ built-in |
|
|
73
|
+
| Strict mode (blocks entropy) | ❌ | ✅ |
|
|
74
|
+
| Canonical state snapshot | ❌ | ✅ `getState()` |
|
|
75
|
+
| Cross-env stable digest | ❌ | ✅ `digest()` |
|
|
76
|
+
| VAR protocol (0-100 inputs) | ❌ | ✅ |
|
|
77
|
+
| Replay/verification | Manual | Built-in |
|
|
78
|
+
| Error messages for agents | ❌ | ✅ actionable |
|
|
79
|
+
|
|
80
|
+
**The runtime provides a complete determinism layer, not just random numbers.**
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Environment Imports
|
|
85
|
+
|
|
86
|
+
| Environment | Import Path |
|
|
87
|
+
|-------------|-------------|
|
|
88
|
+
| Browser / Vite / Next.js / React | `import { createRuntime } from "@nexart/codemode-sdk"` |
|
|
89
|
+
| Node.js (general use) | `import { createRuntime } from "@nexart/codemode-sdk"` |
|
|
90
|
+
| Node.js server rendering (canvas) | `import { executeCodeMode } from "@nexart/codemode-sdk/node"` |
|
|
91
|
+
|
|
92
|
+
**The default import is always browser-safe.** Node-only features (`executeCodeMode`, `runStaticMode`) require explicit `/node` import.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## License
|
|
97
|
+
|
|
98
|
+
**Free for:**
|
|
99
|
+
- Experiments and prototypes
|
|
100
|
+
- Personal projects
|
|
101
|
+
- Open-source projects
|
|
102
|
+
|
|
103
|
+
**Commercial production deployments require a license.** See [LICENSING.md](./LICENSING.md) for details.
|
|
26
104
|
|
|
27
105
|
---
|
|
28
106
|
|
|
@@ -62,6 +140,54 @@ The answer is: "Whatever @nexart/codemode-sdk does — that is the protocol."
|
|
|
62
140
|
|
|
63
141
|
---
|
|
64
142
|
|
|
143
|
+
## What's New in v1.8.0
|
|
144
|
+
|
|
145
|
+
**Agent-First Runtime Authority Layer**
|
|
146
|
+
|
|
147
|
+
This release introduces `createRuntime()` — an agent-first API designed for AI coding assistants to reliably execute deterministic code.
|
|
148
|
+
|
|
149
|
+
### New Runtime API
|
|
150
|
+
```typescript
|
|
151
|
+
import { createRuntime } from "@nexart/codemode-sdk";
|
|
152
|
+
|
|
153
|
+
const runtime = createRuntime({
|
|
154
|
+
seed: "my-seed",
|
|
155
|
+
vars: [50, 75],
|
|
156
|
+
strict: true,
|
|
157
|
+
mode: "static",
|
|
158
|
+
metadata: { artist: "demo" }
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
runtime.random(); // Deterministic PRNG
|
|
162
|
+
runtime.randomInt(0, 100); // Deterministic integer
|
|
163
|
+
runtime.noise(x, y, z); // Deterministic Perlin noise
|
|
164
|
+
runtime.digest(); // Stable hash for verification
|
|
165
|
+
runtime.getState(); // Canonical state snapshot
|
|
166
|
+
runtime.run(() => { ... }); // Execute with strict enforcement
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### 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
|
+
|
|
65
191
|
## What's New in v1.7.0
|
|
66
192
|
|
|
67
193
|
**Browser-Safe Entrypoint + Conditional Exports**
|
package/dist/core-index.d.ts
CHANGED
|
@@ -16,6 +16,6 @@ export { createEngine, } from './engine';
|
|
|
16
16
|
/**
|
|
17
17
|
* SDK Identity
|
|
18
18
|
*/
|
|
19
|
-
export declare const SDK_VERSION = "1.
|
|
19
|
+
export declare const SDK_VERSION = "1.8.0";
|
|
20
20
|
export declare const SDK_NAME = "@nexart/codemode-sdk";
|
|
21
21
|
//# sourceMappingURL=core-index.d.ts.map
|
package/dist/core-index.js
CHANGED
package/dist/entry/browser.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @nexart/codemode-sdk/browser — Browser-Safe Entry Point
|
|
3
3
|
*
|
|
4
4
|
* ╔══════════════════════════════════════════════════════════════════════════╗
|
|
5
|
-
* ║ BROWSER-SAFE SDK ENTRY POINT (v1.
|
|
5
|
+
* ║ BROWSER-SAFE SDK ENTRY POINT (v1.8.0) ║
|
|
6
6
|
* ║ ║
|
|
7
7
|
* ║ This entrypoint exports ONLY browser-safe modules. ║
|
|
8
8
|
* ║ It does NOT include static-engine or any Node.js dependencies. ║
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
* ║ Use this for Vite, React, Next.js, or any browser environment. ║
|
|
11
11
|
* ║ ║
|
|
12
12
|
* ║ For Node.js/server: import from '@nexart/codemode-sdk/node' ║
|
|
13
|
+
* ║ ║
|
|
14
|
+
* ║ AI AGENTS: Start with createRuntime({ seed, strict: true }) ║
|
|
13
15
|
* ╚══════════════════════════════════════════════════════════════════════════╝
|
|
14
16
|
*/
|
|
15
17
|
export type { RenderMode, RuntimeCanvas, EngineConfig, RenderResult, RunOptions, ProgressInfo, Engine, TimeVariables, ProtocolVariables, ProtocolMetadata, ExecuteCodeModeInput, ExecuteCodeModeResult, NexArtBuilderManifest, } from '../types';
|
|
@@ -21,7 +23,9 @@ export { runLoopMode, cancelLoopMode, } from '../loop-engine';
|
|
|
21
23
|
export { validateCodeModeSource, } from '../execute';
|
|
22
24
|
export { createEngine, } from '../engine';
|
|
23
25
|
export { registerBuilderManifest, } from '../builder-manifest';
|
|
24
|
-
export
|
|
26
|
+
export { createRuntime, NexArtRuntime, RUNTIME_VERSION, } from '../runtime';
|
|
27
|
+
export type { RuntimeOptions, RuntimeState, NexArtRuntime as NexArtRuntimeType, } from '../runtime';
|
|
28
|
+
export declare const SDK_VERSION = "1.8.0";
|
|
25
29
|
export declare const SDK_NAME = "@nexart/codemode-sdk";
|
|
26
30
|
export declare const SDK_ENTRY = "browser";
|
|
27
31
|
/**
|
|
@@ -33,5 +37,7 @@ export declare const SDK_ENTRY = "browser";
|
|
|
33
37
|
* - Use runLoopMode() directly for animations
|
|
34
38
|
* - For static rendering, use the server-side endpoint
|
|
35
39
|
* - Or import from '@nexart/codemode-sdk/node' in SSR contexts
|
|
40
|
+
*
|
|
41
|
+
* AI AGENTS: Use createRuntime({ seed, strict: true }) for deterministic execution.
|
|
36
42
|
*/
|
|
37
43
|
//# sourceMappingURL=browser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../entry/browser.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../entry/browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,YAAY,EACV,UAAU,EACV,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,MAAM,EACN,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,cAAc,GACf,MAAM,UAAU,CAAC;AAKlB,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,uBAAuB,EACvB,gBAAgB,GACjB,MAAM,sBAAsB,CAAC;AAK9B,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,uBAAuB,EACvB,iBAAiB,EACjB,SAAS,EACT,OAAO,EACP,OAAO,EACP,0BAA0B,EAC1B,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,eAAe,CAAC;AAEvB,YAAY,EACV,SAAS,EACT,eAAe,GAChB,MAAM,eAAe,CAAC;AAKvB,OAAO,EACL,WAAW,EACX,cAAc,GACf,MAAM,gBAAgB,CAAC;AAKxB,OAAO,EACL,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAKpB,OAAO,EACL,YAAY,GACb,MAAM,WAAW,CAAC;AAKnB,OAAO,EACL,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAK7B,OAAO,EACL,aAAa,EACb,aAAa,EACb,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,YAAY,EACV,cAAc,EACd,YAAY,EACZ,aAAa,IAAI,iBAAiB,GACnC,MAAM,YAAY,CAAC;AAKpB,eAAO,MAAM,WAAW,UAAU,CAAC;AACnC,eAAO,MAAM,QAAQ,yBAAyB,CAAC;AAC/C,eAAO,MAAM,SAAS,YAAY,CAAC;AAEnC;;;;;;;;;;;GAWG"}
|
package/dist/entry/browser.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @nexart/codemode-sdk/browser — Browser-Safe Entry Point
|
|
3
3
|
*
|
|
4
4
|
* ╔══════════════════════════════════════════════════════════════════════════╗
|
|
5
|
-
* ║ BROWSER-SAFE SDK ENTRY POINT (v1.
|
|
5
|
+
* ║ BROWSER-SAFE SDK ENTRY POINT (v1.8.0) ║
|
|
6
6
|
* ║ ║
|
|
7
7
|
* ║ This entrypoint exports ONLY browser-safe modules. ║
|
|
8
8
|
* ║ It does NOT include static-engine or any Node.js dependencies. ║
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
* ║ Use this for Vite, React, Next.js, or any browser environment. ║
|
|
11
11
|
* ║ ║
|
|
12
12
|
* ║ For Node.js/server: import from '@nexart/codemode-sdk/node' ║
|
|
13
|
+
* ║ ║
|
|
14
|
+
* ║ AI AGENTS: Start with createRuntime({ seed, strict: true }) ║
|
|
13
15
|
* ╚══════════════════════════════════════════════════════════════════════════╝
|
|
14
16
|
*/
|
|
15
17
|
export { PROTOCOL_IDENTITY, DEFAULT_VARS, DEFAULT_CONFIG, } from '../types';
|
|
@@ -38,9 +40,13 @@ export { createEngine, } from '../engine';
|
|
|
38
40
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
39
41
|
export { registerBuilderManifest, } from '../builder-manifest';
|
|
40
42
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
43
|
+
// AGENT-FIRST RUNTIME — v1.8.0 (Browser-safe, no Node dependencies)
|
|
44
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
45
|
+
export { createRuntime, NexArtRuntime, RUNTIME_VERSION, } from '../runtime';
|
|
46
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
41
47
|
// SDK IDENTITY
|
|
42
48
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
43
|
-
export const SDK_VERSION = '1.
|
|
49
|
+
export const SDK_VERSION = '1.8.0';
|
|
44
50
|
export const SDK_NAME = '@nexart/codemode-sdk';
|
|
45
51
|
export const SDK_ENTRY = 'browser';
|
|
46
52
|
/**
|
|
@@ -52,4 +58,6 @@ export const SDK_ENTRY = 'browser';
|
|
|
52
58
|
* - Use runLoopMode() directly for animations
|
|
53
59
|
* - For static rendering, use the server-side endpoint
|
|
54
60
|
* - Or import from '@nexart/codemode-sdk/node' in SSR contexts
|
|
61
|
+
*
|
|
62
|
+
* AI AGENTS: Use createRuntime({ seed, strict: true }) for deterministic execution.
|
|
55
63
|
*/
|
package/dist/entry/node.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @nexart/codemode-sdk/node — Node.js Entry Point
|
|
3
3
|
*
|
|
4
4
|
* ╔══════════════════════════════════════════════════════════════════════════╗
|
|
5
|
-
* ║ NODE.JS SDK ENTRY POINT (v1.
|
|
5
|
+
* ║ NODE.JS SDK ENTRY POINT (v1.8.0) ║
|
|
6
6
|
* ║ ║
|
|
7
7
|
* ║ This entrypoint exports Node.js-specific modules that require: ║
|
|
8
8
|
* ║ - canvas package (node-canvas) ║
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
* ║ Use this for server-side rendering, oracles, or CLI tools. ║
|
|
12
12
|
* ║ ║
|
|
13
13
|
* ║ For browser/Vite: import from '@nexart/codemode-sdk/browser' ║
|
|
14
|
+
* ║ ║
|
|
15
|
+
* ║ AI AGENTS: Start with createRuntime({ seed, strict: true }) ║
|
|
14
16
|
* ╚══════════════════════════════════════════════════════════════════════════╝
|
|
15
17
|
*/
|
|
16
18
|
export * from './browser';
|
package/dist/entry/node.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../entry/node.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../entry/node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,cAAc,WAAW,CAAC;AAK1B,OAAO,EACL,aAAa,GACd,MAAM,kBAAkB,CAAC;AAK1B,OAAO,EACL,eAAe,GAChB,MAAM,YAAY,CAAC;AAKpB,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAClD,eAAO,MAAM,SAAS,SAAS,CAAC"}
|
package/dist/entry/node.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @nexart/codemode-sdk/node — Node.js Entry Point
|
|
3
3
|
*
|
|
4
4
|
* ╔══════════════════════════════════════════════════════════════════════════╗
|
|
5
|
-
* ║ NODE.JS SDK ENTRY POINT (v1.
|
|
5
|
+
* ║ NODE.JS SDK ENTRY POINT (v1.8.0) ║
|
|
6
6
|
* ║ ║
|
|
7
7
|
* ║ This entrypoint exports Node.js-specific modules that require: ║
|
|
8
8
|
* ║ - canvas package (node-canvas) ║
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
* ║ Use this for server-side rendering, oracles, or CLI tools. ║
|
|
12
12
|
* ║ ║
|
|
13
13
|
* ║ For browser/Vite: import from '@nexart/codemode-sdk/browser' ║
|
|
14
|
+
* ║ ║
|
|
15
|
+
* ║ AI AGENTS: Start with createRuntime({ seed, strict: true }) ║
|
|
14
16
|
* ╚══════════════════════════════════════════════════════════════════════════╝
|
|
15
17
|
*/
|
|
16
18
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NexArt Code Mode SDK - Agent-First Runtime Authority Layer
|
|
3
|
+
* Version: 1.8.0 (Protocol v1.2.0)
|
|
4
|
+
*
|
|
5
|
+
* ╔══════════════════════════════════════════════════════════════════════════╗
|
|
6
|
+
* ║ AGENT-FIRST RUNTIME — DETERMINISTIC EXECUTION AUTHORITY ║
|
|
7
|
+
* ║ ║
|
|
8
|
+
* ║ This module provides a high-level runtime API designed for AI agents ║
|
|
9
|
+
* ║ (Replit, Lovable, Claude Code) to reliably execute deterministic code. ║
|
|
10
|
+
* ║ ║
|
|
11
|
+
* ║ Key Features: ║
|
|
12
|
+
* ║ - Deterministic PRNG: runtime.random() (seeded Mulberry32) ║
|
|
13
|
+
* ║ - Deterministic noise: runtime.noise(x, y?, z?) (seeded Perlin) ║
|
|
14
|
+
* ║ - Strict mode: Throws on Math.random, Date.now, performance.now ║
|
|
15
|
+
* ║ - Digest: Stable hash for verification and replay ║
|
|
16
|
+
* ║ - State snapshot: Canonical state for bundles ║
|
|
17
|
+
* ║ ║
|
|
18
|
+
* ║ BROWSER-SAFE: No Node.js dependencies. Works in Vite/Next/React. ║
|
|
19
|
+
* ╚══════════════════════════════════════════════════════════════════════════╝
|
|
20
|
+
*/
|
|
21
|
+
export declare const RUNTIME_VERSION = "1.8.0";
|
|
22
|
+
export interface RuntimeOptions {
|
|
23
|
+
seed: string | number;
|
|
24
|
+
vars?: number[];
|
|
25
|
+
strict?: boolean;
|
|
26
|
+
mode?: 'static' | 'loop';
|
|
27
|
+
metadata?: Record<string, unknown>;
|
|
28
|
+
}
|
|
29
|
+
export interface RuntimeState {
|
|
30
|
+
sdkVersion: string;
|
|
31
|
+
seed: number;
|
|
32
|
+
vars: number[];
|
|
33
|
+
mode: 'static' | 'loop';
|
|
34
|
+
metadata?: Record<string, unknown>;
|
|
35
|
+
}
|
|
36
|
+
export interface NexArtRuntime {
|
|
37
|
+
random(): number;
|
|
38
|
+
randomInt(min: number, max: number): number;
|
|
39
|
+
randomRange(min: number, max: number): number;
|
|
40
|
+
noise(x: number, y?: number, z?: number): number;
|
|
41
|
+
run<T>(fn: () => T): T;
|
|
42
|
+
digest(): string;
|
|
43
|
+
getState(): RuntimeState;
|
|
44
|
+
getSeed(): number;
|
|
45
|
+
readonly strict: boolean;
|
|
46
|
+
}
|
|
47
|
+
export declare function createRuntime(options: RuntimeOptions): NexArtRuntime;
|
|
48
|
+
export declare const NexArtRuntime: {
|
|
49
|
+
create: typeof createRuntime;
|
|
50
|
+
VERSION: string;
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,eAAO,MAAM,eAAe,UAAU,CAAC;AAEvC,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,IAAI,MAAM,CAAC;IACjB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5C,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9C,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACjD,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IACvB,MAAM,IAAI,MAAM,CAAC;IACjB,QAAQ,IAAI,YAAY,CAAC;IACzB,OAAO,IAAI,MAAM,CAAC;IAClB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAqGD,wBAAgB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,aAAa,CAuHpE;AAED,eAAO,MAAM,aAAa;;;CAGzB,CAAC"}
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NexArt Code Mode SDK - Agent-First Runtime Authority Layer
|
|
3
|
+
* Version: 1.8.0 (Protocol v1.2.0)
|
|
4
|
+
*
|
|
5
|
+
* ╔══════════════════════════════════════════════════════════════════════════╗
|
|
6
|
+
* ║ AGENT-FIRST RUNTIME — DETERMINISTIC EXECUTION AUTHORITY ║
|
|
7
|
+
* ║ ║
|
|
8
|
+
* ║ This module provides a high-level runtime API designed for AI agents ║
|
|
9
|
+
* ║ (Replit, Lovable, Claude Code) to reliably execute deterministic code. ║
|
|
10
|
+
* ║ ║
|
|
11
|
+
* ║ Key Features: ║
|
|
12
|
+
* ║ - Deterministic PRNG: runtime.random() (seeded Mulberry32) ║
|
|
13
|
+
* ║ - Deterministic noise: runtime.noise(x, y?, z?) (seeded Perlin) ║
|
|
14
|
+
* ║ - Strict mode: Throws on Math.random, Date.now, performance.now ║
|
|
15
|
+
* ║ - Digest: Stable hash for verification and replay ║
|
|
16
|
+
* ║ - State snapshot: Canonical state for bundles ║
|
|
17
|
+
* ║ ║
|
|
18
|
+
* ║ BROWSER-SAFE: No Node.js dependencies. Works in Vite/Next/React. ║
|
|
19
|
+
* ╚══════════════════════════════════════════════════════════════════════════╝
|
|
20
|
+
*/
|
|
21
|
+
export const RUNTIME_VERSION = '1.8.0';
|
|
22
|
+
function hashSeed(seed) {
|
|
23
|
+
if (typeof seed === 'number') {
|
|
24
|
+
return Math.floor(seed) >>> 0;
|
|
25
|
+
}
|
|
26
|
+
let hash = 0;
|
|
27
|
+
for (let i = 0; i < seed.length; i++) {
|
|
28
|
+
const char = seed.charCodeAt(i);
|
|
29
|
+
hash = ((hash << 5) - hash) + char;
|
|
30
|
+
hash = hash >>> 0;
|
|
31
|
+
}
|
|
32
|
+
return hash || 1;
|
|
33
|
+
}
|
|
34
|
+
function createSeededRNG(seed) {
|
|
35
|
+
let a = seed >>> 0;
|
|
36
|
+
return () => {
|
|
37
|
+
a += 0x6D2B79F5;
|
|
38
|
+
let t = Math.imul(a ^ (a >>> 15), a | 1);
|
|
39
|
+
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
|
|
40
|
+
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function createSeededNoise(seed) {
|
|
44
|
+
const permutation = [];
|
|
45
|
+
const rng = createSeededRNG(seed);
|
|
46
|
+
for (let i = 0; i < 256; i++) {
|
|
47
|
+
permutation[i] = i;
|
|
48
|
+
}
|
|
49
|
+
for (let i = 255; i > 0; i--) {
|
|
50
|
+
const j = Math.floor(rng() * (i + 1));
|
|
51
|
+
[permutation[i], permutation[j]] = [permutation[j], permutation[i]];
|
|
52
|
+
}
|
|
53
|
+
for (let i = 0; i < 256; i++) {
|
|
54
|
+
permutation[256 + i] = permutation[i];
|
|
55
|
+
}
|
|
56
|
+
const fade = (t) => t * t * t * (t * (t * 6 - 15) + 10);
|
|
57
|
+
const lerp = (a, b, t) => a + t * (b - a);
|
|
58
|
+
const grad = (hash, x, y, z) => {
|
|
59
|
+
const h = hash & 15;
|
|
60
|
+
const u = h < 8 ? x : y;
|
|
61
|
+
const v = h < 4 ? y : h === 12 || h === 14 ? x : z;
|
|
62
|
+
return ((h & 1) === 0 ? u : -u) + ((h & 2) === 0 ? v : -v);
|
|
63
|
+
};
|
|
64
|
+
return (x, y = 0, z = 0) => {
|
|
65
|
+
const X = Math.floor(x) & 255;
|
|
66
|
+
const Y = Math.floor(y) & 255;
|
|
67
|
+
const Z = Math.floor(z) & 255;
|
|
68
|
+
x -= Math.floor(x);
|
|
69
|
+
y -= Math.floor(y);
|
|
70
|
+
z -= Math.floor(z);
|
|
71
|
+
const u = fade(x);
|
|
72
|
+
const v = fade(y);
|
|
73
|
+
const w = fade(z);
|
|
74
|
+
const A = permutation[X] + Y;
|
|
75
|
+
const AA = permutation[A] + Z;
|
|
76
|
+
const AB = permutation[A + 1] + Z;
|
|
77
|
+
const B = permutation[X + 1] + Y;
|
|
78
|
+
const BA = permutation[B] + Z;
|
|
79
|
+
const BB = permutation[B + 1] + Z;
|
|
80
|
+
return (lerp(lerp(lerp(grad(permutation[AA], x, y, z), grad(permutation[BA], x - 1, y, z), u), lerp(grad(permutation[AB], x, y - 1, z), grad(permutation[BB], x - 1, y - 1, z), u), v), lerp(lerp(grad(permutation[AA + 1], x, y, z - 1), grad(permutation[BA + 1], x - 1, y, z - 1), u), lerp(grad(permutation[AB + 1], x, y - 1, z - 1), grad(permutation[BB + 1], x - 1, y - 1, z - 1), u), v), w) + 1) / 2;
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function stableStringify(obj) {
|
|
84
|
+
if (obj === null)
|
|
85
|
+
return 'null';
|
|
86
|
+
if (obj === undefined)
|
|
87
|
+
return 'undefined';
|
|
88
|
+
if (typeof obj !== 'object')
|
|
89
|
+
return JSON.stringify(obj);
|
|
90
|
+
if (Array.isArray(obj)) {
|
|
91
|
+
return '[' + obj.map(stableStringify).join(',') + ']';
|
|
92
|
+
}
|
|
93
|
+
const keys = Object.keys(obj).sort();
|
|
94
|
+
const pairs = keys.map(k => `${JSON.stringify(k)}:${stableStringify(obj[k])}`);
|
|
95
|
+
return '{' + pairs.join(',') + '}';
|
|
96
|
+
}
|
|
97
|
+
function fnv1aHash(str) {
|
|
98
|
+
let hash = 0x811c9dc5;
|
|
99
|
+
for (let i = 0; i < str.length; i++) {
|
|
100
|
+
hash ^= str.charCodeAt(i);
|
|
101
|
+
hash = Math.imul(hash, 0x01000193);
|
|
102
|
+
}
|
|
103
|
+
const h1 = (hash >>> 0).toString(16).padStart(8, '0');
|
|
104
|
+
let hash2 = 0x811c9dc5;
|
|
105
|
+
for (let i = str.length - 1; i >= 0; i--) {
|
|
106
|
+
hash2 ^= str.charCodeAt(i);
|
|
107
|
+
hash2 = Math.imul(hash2, 0x01000193);
|
|
108
|
+
}
|
|
109
|
+
const h2 = (hash2 >>> 0).toString(16).padStart(8, '0');
|
|
110
|
+
return h1 + h2;
|
|
111
|
+
}
|
|
112
|
+
export function createRuntime(options) {
|
|
113
|
+
const numericSeed = hashSeed(options.seed);
|
|
114
|
+
const vars = options.vars ?? [];
|
|
115
|
+
const mode = options.mode ?? 'static';
|
|
116
|
+
const strict = options.strict ?? false;
|
|
117
|
+
const metadata = options.metadata;
|
|
118
|
+
if (vars.length > 10) {
|
|
119
|
+
throw new Error(`[NexArt Runtime] vars array must have 0-10 elements, got ${vars.length}`);
|
|
120
|
+
}
|
|
121
|
+
for (let i = 0; i < vars.length; i++) {
|
|
122
|
+
if (typeof vars[i] !== 'number' || !Number.isFinite(vars[i])) {
|
|
123
|
+
throw new Error(`[NexArt Runtime] vars[${i}] must be a finite number`);
|
|
124
|
+
}
|
|
125
|
+
if (vars[i] < 0 || vars[i] > 100) {
|
|
126
|
+
throw new Error(`[NexArt Runtime] vars[${i}] must be in range 0-100, got ${vars[i]}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const paddedVars = [...vars];
|
|
130
|
+
while (paddedVars.length < 10) {
|
|
131
|
+
paddedVars.push(0);
|
|
132
|
+
}
|
|
133
|
+
const rng = createSeededRNG(numericSeed);
|
|
134
|
+
const noiseFunc = createSeededNoise(numericSeed);
|
|
135
|
+
const state = {
|
|
136
|
+
sdkVersion: RUNTIME_VERSION,
|
|
137
|
+
seed: numericSeed,
|
|
138
|
+
vars: paddedVars,
|
|
139
|
+
mode,
|
|
140
|
+
...(metadata !== undefined && { metadata }),
|
|
141
|
+
};
|
|
142
|
+
function random() {
|
|
143
|
+
return rng();
|
|
144
|
+
}
|
|
145
|
+
function randomInt(min, max) {
|
|
146
|
+
const range = max - min + 1;
|
|
147
|
+
return Math.floor(rng() * range) + min;
|
|
148
|
+
}
|
|
149
|
+
function randomRange(min, max) {
|
|
150
|
+
return rng() * (max - min) + min;
|
|
151
|
+
}
|
|
152
|
+
function noise(x, y, z) {
|
|
153
|
+
return noiseFunc(x, y ?? 0, z ?? 0);
|
|
154
|
+
}
|
|
155
|
+
function run(fn) {
|
|
156
|
+
if (!strict) {
|
|
157
|
+
return fn();
|
|
158
|
+
}
|
|
159
|
+
const originalMathRandom = Math.random;
|
|
160
|
+
const originalDateNow = Date.now;
|
|
161
|
+
const hasPerformance = typeof performance !== 'undefined' && performance !== null;
|
|
162
|
+
const originalPerformanceNow = hasPerformance ? performance.now : undefined;
|
|
163
|
+
const throwMathRandom = () => {
|
|
164
|
+
throw new Error('NEXART_STRICT: Non-deterministic API used: Math.random. Use runtime.random() instead.');
|
|
165
|
+
};
|
|
166
|
+
const throwDateNow = () => {
|
|
167
|
+
throw new Error('NEXART_STRICT: Non-deterministic API used: Date.now. Pass time as an input or use deterministic counters.');
|
|
168
|
+
};
|
|
169
|
+
const throwPerformanceNow = () => {
|
|
170
|
+
throw new Error('NEXART_STRICT: Non-deterministic API used: performance.now.');
|
|
171
|
+
};
|
|
172
|
+
try {
|
|
173
|
+
Math.random = throwMathRandom;
|
|
174
|
+
Date.now = throwDateNow;
|
|
175
|
+
if (hasPerformance && originalPerformanceNow) {
|
|
176
|
+
performance.now = throwPerformanceNow;
|
|
177
|
+
}
|
|
178
|
+
return fn();
|
|
179
|
+
}
|
|
180
|
+
finally {
|
|
181
|
+
Math.random = originalMathRandom;
|
|
182
|
+
Date.now = originalDateNow;
|
|
183
|
+
if (hasPerformance && originalPerformanceNow) {
|
|
184
|
+
performance.now = originalPerformanceNow;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function digest() {
|
|
189
|
+
const input = stableStringify({
|
|
190
|
+
sdkVersion: RUNTIME_VERSION,
|
|
191
|
+
seed: numericSeed,
|
|
192
|
+
vars: paddedVars,
|
|
193
|
+
mode,
|
|
194
|
+
...(metadata !== undefined && { metadata }),
|
|
195
|
+
});
|
|
196
|
+
return fnv1aHash(input);
|
|
197
|
+
}
|
|
198
|
+
function getState() {
|
|
199
|
+
return { ...state, vars: [...state.vars] };
|
|
200
|
+
}
|
|
201
|
+
function getSeed() {
|
|
202
|
+
return numericSeed;
|
|
203
|
+
}
|
|
204
|
+
return Object.freeze({
|
|
205
|
+
random,
|
|
206
|
+
randomInt,
|
|
207
|
+
randomRange,
|
|
208
|
+
noise,
|
|
209
|
+
run,
|
|
210
|
+
digest,
|
|
211
|
+
getState,
|
|
212
|
+
getSeed,
|
|
213
|
+
strict,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
export const NexArtRuntime = {
|
|
217
|
+
create: createRuntime,
|
|
218
|
+
VERSION: RUNTIME_VERSION,
|
|
219
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @nexart/codemode-sdk — Basic Example
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates the agent-first runtime API for deterministic execution.
|
|
5
|
+
*
|
|
6
|
+
* Run: npm run example:basic
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { createRuntime } from '../runtime';
|
|
10
|
+
|
|
11
|
+
console.log('╔══════════════════════════════════════════════════════════════╗');
|
|
12
|
+
console.log('║ NexArt Code Mode SDK — Basic Example ║');
|
|
13
|
+
console.log('╚══════════════════════════════════════════════════════════════╝');
|
|
14
|
+
console.log();
|
|
15
|
+
|
|
16
|
+
const runtime = createRuntime({
|
|
17
|
+
seed: 'demo-seed-42',
|
|
18
|
+
vars: [50, 75, 25],
|
|
19
|
+
strict: true,
|
|
20
|
+
mode: 'static',
|
|
21
|
+
metadata: { artist: 'demo', project: 'example' }
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
console.log('Runtime State:');
|
|
25
|
+
console.log(JSON.stringify(runtime.getState(), null, 2));
|
|
26
|
+
console.log();
|
|
27
|
+
|
|
28
|
+
console.log('Digest:', runtime.digest());
|
|
29
|
+
console.log('Seed (numeric):', runtime.getSeed());
|
|
30
|
+
console.log('Strict mode:', runtime.strict);
|
|
31
|
+
console.log();
|
|
32
|
+
|
|
33
|
+
console.log('Deterministic random values:');
|
|
34
|
+
const randoms: number[] = [];
|
|
35
|
+
for (let i = 0; i < 5; i++) {
|
|
36
|
+
const val = runtime.random();
|
|
37
|
+
randoms.push(val);
|
|
38
|
+
console.log(` random() #${i + 1}: ${val.toFixed(8)}`);
|
|
39
|
+
}
|
|
40
|
+
console.log();
|
|
41
|
+
|
|
42
|
+
console.log('Deterministic noise values:');
|
|
43
|
+
for (let i = 0; i < 5; i++) {
|
|
44
|
+
const x = i * 0.5;
|
|
45
|
+
const val = runtime.noise(x, 0.5);
|
|
46
|
+
console.log(` noise(${x}, 0.5): ${val.toFixed(8)}`);
|
|
47
|
+
}
|
|
48
|
+
console.log();
|
|
49
|
+
|
|
50
|
+
console.log('Running code in strict mode...');
|
|
51
|
+
const result = runtime.run(() => {
|
|
52
|
+
let sum = 0;
|
|
53
|
+
for (let i = 0; i < 10; i++) {
|
|
54
|
+
sum += runtime.random();
|
|
55
|
+
}
|
|
56
|
+
return sum;
|
|
57
|
+
});
|
|
58
|
+
console.log(` Sum of 10 random values: ${result.toFixed(8)}`);
|
|
59
|
+
console.log();
|
|
60
|
+
|
|
61
|
+
console.log('✅ Basic example completed successfully!');
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @nexart/codemode-sdk — Preflight Release Tests
|
|
3
|
+
*
|
|
4
|
+
* Extended verification tests for v1.8.0 release validation.
|
|
5
|
+
* Tests strict mode restoration, error messages, and cross-env digest parity.
|
|
6
|
+
*
|
|
7
|
+
* Run: npx tsx examples/preflight-test.ts
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { createRuntime, RUNTIME_VERSION } from '../runtime';
|
|
11
|
+
|
|
12
|
+
console.log('╔══════════════════════════════════════════════════════════════╗');
|
|
13
|
+
console.log('║ NexArt Code Mode SDK — Preflight Release Tests ║');
|
|
14
|
+
console.log(`║ Version: ${RUNTIME_VERSION.padEnd(52)}║`);
|
|
15
|
+
console.log('╚══════════════════════════════════════════════════════════════╝');
|
|
16
|
+
console.log();
|
|
17
|
+
|
|
18
|
+
let passCount = 0;
|
|
19
|
+
let failCount = 0;
|
|
20
|
+
|
|
21
|
+
function test(name: string, fn: () => boolean): void {
|
|
22
|
+
try {
|
|
23
|
+
const result = fn();
|
|
24
|
+
if (result) {
|
|
25
|
+
console.log(`✅ PASS: ${name}`);
|
|
26
|
+
passCount++;
|
|
27
|
+
} else {
|
|
28
|
+
console.log(`❌ FAIL: ${name}`);
|
|
29
|
+
failCount++;
|
|
30
|
+
}
|
|
31
|
+
} catch (error: any) {
|
|
32
|
+
console.log(`❌ FAIL: ${name} — ${error.message}`);
|
|
33
|
+
failCount++;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
console.log('TEST GROUP 1: Strict Mode Restoration on Throw');
|
|
38
|
+
console.log('─'.repeat(60));
|
|
39
|
+
|
|
40
|
+
test('Strict mode restores Math.random after user code throws', () => {
|
|
41
|
+
const runtime = createRuntime({ seed: 12345, strict: true });
|
|
42
|
+
const originalMathRandom = Math.random;
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
runtime.run(() => {
|
|
46
|
+
throw new Error('User code explosion');
|
|
47
|
+
});
|
|
48
|
+
} catch {
|
|
49
|
+
// Expected
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const restored = Math.random === originalMathRandom;
|
|
53
|
+
if (!restored) {
|
|
54
|
+
console.log(' ⚠️ Math.random was NOT restored after throw');
|
|
55
|
+
}
|
|
56
|
+
return restored;
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test('Strict mode restores Date.now after user code throws', () => {
|
|
60
|
+
const runtime = createRuntime({ seed: 12345, strict: true });
|
|
61
|
+
const originalDateNow = Date.now;
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
runtime.run(() => {
|
|
65
|
+
throw new Error('User code explosion');
|
|
66
|
+
});
|
|
67
|
+
} catch {
|
|
68
|
+
// Expected
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const restored = Date.now === originalDateNow;
|
|
72
|
+
if (!restored) {
|
|
73
|
+
console.log(' ⚠️ Date.now was NOT restored after throw');
|
|
74
|
+
}
|
|
75
|
+
return restored;
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test('Strict mode restores performance.now after user code throws', () => {
|
|
79
|
+
const runtime = createRuntime({ seed: 12345, strict: true });
|
|
80
|
+
const hasPerformance = typeof performance !== 'undefined' && performance !== null;
|
|
81
|
+
|
|
82
|
+
if (!hasPerformance) {
|
|
83
|
+
console.log(' ℹ️ performance object not available, skipping');
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const originalPerformanceNow = performance.now;
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
runtime.run(() => {
|
|
91
|
+
throw new Error('User code explosion');
|
|
92
|
+
});
|
|
93
|
+
} catch {
|
|
94
|
+
// Expected
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const restored = performance.now === originalPerformanceNow;
|
|
98
|
+
if (!restored) {
|
|
99
|
+
console.log(' ⚠️ performance.now was NOT restored after throw');
|
|
100
|
+
}
|
|
101
|
+
return restored;
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
console.log();
|
|
105
|
+
console.log('TEST GROUP 2: Strict Mode Error Messages');
|
|
106
|
+
console.log('─'.repeat(60));
|
|
107
|
+
|
|
108
|
+
test('Math.random error message is actionable', () => {
|
|
109
|
+
const runtime = createRuntime({ seed: 12345, strict: true });
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
runtime.run(() => Math.random());
|
|
113
|
+
return false;
|
|
114
|
+
} catch (error: any) {
|
|
115
|
+
const expected = 'NEXART_STRICT: Non-deterministic API used: Math.random. Use runtime.random() instead.';
|
|
116
|
+
const match = error.message === expected;
|
|
117
|
+
if (!match) {
|
|
118
|
+
console.log(` Expected: "${expected}"`);
|
|
119
|
+
console.log(` Got: "${error.message}"`);
|
|
120
|
+
}
|
|
121
|
+
return match;
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test('Date.now error message is actionable', () => {
|
|
126
|
+
const runtime = createRuntime({ seed: 12345, strict: true });
|
|
127
|
+
|
|
128
|
+
try {
|
|
129
|
+
runtime.run(() => Date.now());
|
|
130
|
+
return false;
|
|
131
|
+
} catch (error: any) {
|
|
132
|
+
const expected = 'NEXART_STRICT: Non-deterministic API used: Date.now. Pass time as an input or use deterministic counters.';
|
|
133
|
+
const match = error.message === expected;
|
|
134
|
+
if (!match) {
|
|
135
|
+
console.log(` Expected: "${expected}"`);
|
|
136
|
+
console.log(` Got: "${error.message}"`);
|
|
137
|
+
}
|
|
138
|
+
return match;
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test('performance.now error message is actionable', () => {
|
|
143
|
+
const runtime = createRuntime({ seed: 12345, strict: true });
|
|
144
|
+
const hasPerformance = typeof performance !== 'undefined' && performance !== null;
|
|
145
|
+
|
|
146
|
+
if (!hasPerformance) {
|
|
147
|
+
console.log(' ℹ️ performance object not available, skipping');
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
try {
|
|
152
|
+
runtime.run(() => performance.now());
|
|
153
|
+
return false;
|
|
154
|
+
} catch (error: any) {
|
|
155
|
+
const expected = 'NEXART_STRICT: Non-deterministic API used: performance.now.';
|
|
156
|
+
const match = error.message === expected;
|
|
157
|
+
if (!match) {
|
|
158
|
+
console.log(` Expected: "${expected}"`);
|
|
159
|
+
console.log(` Got: "${error.message}"`);
|
|
160
|
+
}
|
|
161
|
+
return match;
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
console.log();
|
|
166
|
+
console.log('TEST GROUP 3: Digest Determinism');
|
|
167
|
+
console.log('─'.repeat(60));
|
|
168
|
+
|
|
169
|
+
test('Digest is stable across multiple calls', () => {
|
|
170
|
+
const config = { seed: 'stable-digest-test', vars: [10, 20, 30], mode: 'static' as const };
|
|
171
|
+
const runtime1 = createRuntime(config);
|
|
172
|
+
const runtime2 = createRuntime(config);
|
|
173
|
+
|
|
174
|
+
const digest1 = runtime1.digest();
|
|
175
|
+
const digest2 = runtime2.digest();
|
|
176
|
+
|
|
177
|
+
if (digest1 !== digest2) {
|
|
178
|
+
console.log(` Digest 1: ${digest1}`);
|
|
179
|
+
console.log(` Digest 2: ${digest2}`);
|
|
180
|
+
}
|
|
181
|
+
return digest1 === digest2;
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
test('Digest changes when seed changes', () => {
|
|
185
|
+
const runtime1 = createRuntime({ seed: 'seed-a', vars: [10, 20, 30] });
|
|
186
|
+
const runtime2 = createRuntime({ seed: 'seed-b', vars: [10, 20, 30] });
|
|
187
|
+
|
|
188
|
+
return runtime1.digest() !== runtime2.digest();
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
test('Digest changes when vars change', () => {
|
|
192
|
+
const runtime1 = createRuntime({ seed: 'same-seed', vars: [10, 20, 30] });
|
|
193
|
+
const runtime2 = createRuntime({ seed: 'same-seed', vars: [10, 20, 31] });
|
|
194
|
+
|
|
195
|
+
return runtime1.digest() !== runtime2.digest();
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
test('Digest changes when mode changes', () => {
|
|
199
|
+
const runtime1 = createRuntime({ seed: 'same-seed', vars: [10, 20, 30], mode: 'static' });
|
|
200
|
+
const runtime2 = createRuntime({ seed: 'same-seed', vars: [10, 20, 30], mode: 'loop' });
|
|
201
|
+
|
|
202
|
+
return runtime1.digest() !== runtime2.digest();
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
test('Digest is 16-char hex string', () => {
|
|
206
|
+
const runtime = createRuntime({ seed: 'format-test' });
|
|
207
|
+
const digest = runtime.digest();
|
|
208
|
+
const isValidFormat = /^[0-9a-f]{16}$/.test(digest);
|
|
209
|
+
if (!isValidFormat) {
|
|
210
|
+
console.log(` Digest format invalid: "${digest}"`);
|
|
211
|
+
}
|
|
212
|
+
return isValidFormat;
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
console.log();
|
|
216
|
+
console.log('TEST GROUP 4: PRNG Determinism');
|
|
217
|
+
console.log('─'.repeat(60));
|
|
218
|
+
|
|
219
|
+
test('Same seed produces identical random sequence', () => {
|
|
220
|
+
const seq1: number[] = [];
|
|
221
|
+
const seq2: number[] = [];
|
|
222
|
+
|
|
223
|
+
const runtime1 = createRuntime({ seed: 'prng-test' });
|
|
224
|
+
const runtime2 = createRuntime({ seed: 'prng-test' });
|
|
225
|
+
|
|
226
|
+
for (let i = 0; i < 10; i++) {
|
|
227
|
+
seq1.push(runtime1.random());
|
|
228
|
+
seq2.push(runtime2.random());
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return seq1.every((v, i) => v === seq2[i]);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
test('Different seeds produce different sequences', () => {
|
|
235
|
+
const runtime1 = createRuntime({ seed: 'seed-x' });
|
|
236
|
+
const runtime2 = createRuntime({ seed: 'seed-y' });
|
|
237
|
+
|
|
238
|
+
return runtime1.random() !== runtime2.random();
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
test('Noise is deterministic for same inputs', () => {
|
|
242
|
+
const runtime1 = createRuntime({ seed: 'noise-test' });
|
|
243
|
+
const runtime2 = createRuntime({ seed: 'noise-test' });
|
|
244
|
+
|
|
245
|
+
const n1 = runtime1.noise(1.5, 2.5, 3.5);
|
|
246
|
+
const n2 = runtime2.noise(1.5, 2.5, 3.5);
|
|
247
|
+
|
|
248
|
+
return n1 === n2;
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
console.log();
|
|
252
|
+
console.log('TEST GROUP 5: Known Digest Values');
|
|
253
|
+
console.log('─'.repeat(60));
|
|
254
|
+
|
|
255
|
+
const knownConfig = { seed: 'known-digest-oracle', vars: [50, 50, 50, 50, 50, 50, 50, 50, 50, 50], mode: 'static' as const };
|
|
256
|
+
const knownRuntime = createRuntime(knownConfig);
|
|
257
|
+
const oracleDigest = knownRuntime.digest();
|
|
258
|
+
console.log(`Oracle digest for cross-env verification: ${oracleDigest}`);
|
|
259
|
+
|
|
260
|
+
test('Oracle digest format valid', () => {
|
|
261
|
+
return /^[0-9a-f]{16}$/.test(oracleDigest);
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
console.log();
|
|
265
|
+
console.log('═'.repeat(60));
|
|
266
|
+
console.log(`RESULTS: ${passCount} passed, ${failCount} failed`);
|
|
267
|
+
console.log('═'.repeat(60));
|
|
268
|
+
|
|
269
|
+
if (failCount > 0) {
|
|
270
|
+
console.log('❌ PREFLIGHT FAILED - DO NOT SHIP');
|
|
271
|
+
process.exit(1);
|
|
272
|
+
} else {
|
|
273
|
+
console.log('✅ PREFLIGHT PASSED - READY TO SHIP');
|
|
274
|
+
process.exit(0);
|
|
275
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @nexart/codemode-sdk — Verification Example
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates determinism verification and strict mode error handling.
|
|
5
|
+
*
|
|
6
|
+
* Run: npm run example:verify
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { createRuntime } from '../runtime';
|
|
10
|
+
|
|
11
|
+
console.log('╔══════════════════════════════════════════════════════════════╗');
|
|
12
|
+
console.log('║ NexArt Code Mode SDK — Verification Example ║');
|
|
13
|
+
console.log('╚══════════════════════════════════════════════════════════════╝');
|
|
14
|
+
console.log();
|
|
15
|
+
|
|
16
|
+
function generateRandomSequence(seed: string | number, vars: number[], count: number): number[] {
|
|
17
|
+
const runtime = createRuntime({ seed, vars, strict: true });
|
|
18
|
+
const values: number[] = [];
|
|
19
|
+
for (let i = 0; i < count; i++) {
|
|
20
|
+
values.push(runtime.random());
|
|
21
|
+
}
|
|
22
|
+
return values;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
console.log('TEST 1: Same seed + vars = same output');
|
|
26
|
+
console.log('─'.repeat(50));
|
|
27
|
+
|
|
28
|
+
const seq1 = generateRandomSequence('test-seed', [50, 25], 5);
|
|
29
|
+
const seq2 = generateRandomSequence('test-seed', [50, 25], 5);
|
|
30
|
+
|
|
31
|
+
console.log('Run 1:', seq1.map(v => v.toFixed(6)).join(', '));
|
|
32
|
+
console.log('Run 2:', seq2.map(v => v.toFixed(6)).join(', '));
|
|
33
|
+
|
|
34
|
+
const identical = seq1.every((v, i) => v === seq2[i]);
|
|
35
|
+
console.log(`Result: ${identical ? '✅ PASS' : '❌ FAIL'} — sequences are ${identical ? 'identical' : 'different'}`);
|
|
36
|
+
console.log();
|
|
37
|
+
|
|
38
|
+
console.log('TEST 2: Same seed + vars = same digest');
|
|
39
|
+
console.log('─'.repeat(50));
|
|
40
|
+
|
|
41
|
+
const runtime1 = createRuntime({ seed: 'digest-test', vars: [10, 20, 30] });
|
|
42
|
+
const runtime2 = createRuntime({ seed: 'digest-test', vars: [10, 20, 30] });
|
|
43
|
+
|
|
44
|
+
const digest1 = runtime1.digest();
|
|
45
|
+
const digest2 = runtime2.digest();
|
|
46
|
+
|
|
47
|
+
console.log('Digest 1:', digest1);
|
|
48
|
+
console.log('Digest 2:', digest2);
|
|
49
|
+
|
|
50
|
+
const digestsMatch = digest1 === digest2;
|
|
51
|
+
console.log(`Result: ${digestsMatch ? '✅ PASS' : '❌ FAIL'} — digests are ${digestsMatch ? 'identical' : 'different'}`);
|
|
52
|
+
console.log();
|
|
53
|
+
|
|
54
|
+
console.log('TEST 3: Different vars = different digest');
|
|
55
|
+
console.log('─'.repeat(50));
|
|
56
|
+
|
|
57
|
+
const runtime3 = createRuntime({ seed: 'digest-test', vars: [10, 20, 30] });
|
|
58
|
+
const runtime4 = createRuntime({ seed: 'digest-test', vars: [10, 20, 31] });
|
|
59
|
+
|
|
60
|
+
const digest3 = runtime3.digest();
|
|
61
|
+
const digest4 = runtime4.digest();
|
|
62
|
+
|
|
63
|
+
console.log('Digest (vars [10,20,30]):', digest3);
|
|
64
|
+
console.log('Digest (vars [10,20,31]):', digest4);
|
|
65
|
+
|
|
66
|
+
const digestsDiffer = digest3 !== digest4;
|
|
67
|
+
console.log(`Result: ${digestsDiffer ? '✅ PASS' : '❌ FAIL'} — digests are ${digestsDiffer ? 'different' : 'identical'}`);
|
|
68
|
+
console.log();
|
|
69
|
+
|
|
70
|
+
console.log('TEST 4: Strict mode blocks Math.random');
|
|
71
|
+
console.log('─'.repeat(50));
|
|
72
|
+
|
|
73
|
+
const strictRuntime = createRuntime({ seed: 12345, strict: true });
|
|
74
|
+
|
|
75
|
+
let strictErrorCaught = false;
|
|
76
|
+
let errorMessage = '';
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
strictRuntime.run(() => {
|
|
80
|
+
return Math.random();
|
|
81
|
+
});
|
|
82
|
+
} catch (error: any) {
|
|
83
|
+
strictErrorCaught = true;
|
|
84
|
+
errorMessage = error.message;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
console.log('Called Math.random() in strict run...');
|
|
88
|
+
console.log(`Error caught: ${strictErrorCaught}`);
|
|
89
|
+
if (strictErrorCaught) {
|
|
90
|
+
console.log(`Error message: "${errorMessage}"`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const expectedMessage = 'NEXART_STRICT: Non-deterministic API used: Math.random. Use runtime.random() instead.';
|
|
94
|
+
const correctError = errorMessage === expectedMessage;
|
|
95
|
+
console.log(`Result: ${strictErrorCaught && correctError ? '✅ PASS' : '❌ FAIL'} — strict mode ${strictErrorCaught ? 'blocked' : 'did not block'} Math.random`);
|
|
96
|
+
console.log();
|
|
97
|
+
|
|
98
|
+
console.log('TEST 5: Strict mode blocks Date.now');
|
|
99
|
+
console.log('─'.repeat(50));
|
|
100
|
+
|
|
101
|
+
let dateErrorCaught = false;
|
|
102
|
+
let dateErrorMessage = '';
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
strictRuntime.run(() => {
|
|
106
|
+
return Date.now();
|
|
107
|
+
});
|
|
108
|
+
} catch (error: any) {
|
|
109
|
+
dateErrorCaught = true;
|
|
110
|
+
dateErrorMessage = error.message;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
console.log('Called Date.now() in strict run...');
|
|
114
|
+
console.log(`Error caught: ${dateErrorCaught}`);
|
|
115
|
+
if (dateErrorCaught) {
|
|
116
|
+
console.log(`Error message: "${dateErrorMessage}"`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const expectedDateMessage = 'NEXART_STRICT: Non-deterministic API used: Date.now. Pass time as an input or use deterministic counters.';
|
|
120
|
+
const correctDateError = dateErrorMessage === expectedDateMessage;
|
|
121
|
+
console.log(`Result: ${dateErrorCaught && correctDateError ? '✅ PASS' : '❌ FAIL'} — strict mode ${dateErrorCaught ? 'blocked' : 'did not block'} Date.now`);
|
|
122
|
+
console.log();
|
|
123
|
+
|
|
124
|
+
console.log('TEST 6: Non-strict mode allows Math.random');
|
|
125
|
+
console.log('─'.repeat(50));
|
|
126
|
+
|
|
127
|
+
const nonStrictRuntime = createRuntime({ seed: 12345, strict: false });
|
|
128
|
+
|
|
129
|
+
let nonStrictResult: number | null = null;
|
|
130
|
+
let nonStrictError = false;
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
nonStrictResult = nonStrictRuntime.run(() => {
|
|
134
|
+
return Math.random();
|
|
135
|
+
});
|
|
136
|
+
} catch {
|
|
137
|
+
nonStrictError = true;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
console.log('Called Math.random() in non-strict run...');
|
|
141
|
+
console.log(`Error thrown: ${nonStrictError}`);
|
|
142
|
+
console.log(`Result value: ${nonStrictResult}`);
|
|
143
|
+
console.log(`Result: ${!nonStrictError && nonStrictResult !== null ? '✅ PASS' : '❌ FAIL'} — non-strict mode ${!nonStrictError ? 'allowed' : 'blocked'} Math.random`);
|
|
144
|
+
console.log();
|
|
145
|
+
|
|
146
|
+
const allPassed = identical && digestsMatch && digestsDiffer && strictErrorCaught && correctError && dateErrorCaught && correctDateError && !nonStrictError;
|
|
147
|
+
console.log('═'.repeat(50));
|
|
148
|
+
console.log(allPassed ? '✅ All verification tests passed!' : '❌ Some tests failed');
|
|
149
|
+
console.log('═'.repeat(50));
|
|
150
|
+
|
|
151
|
+
process.exit(allPassed ? 0 : 1);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nexart/codemode-sdk",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "NexArt Code Mode SDK -
|
|
3
|
+
"version": "1.8.0",
|
|
4
|
+
"description": "NexArt Code Mode SDK - Deterministic, reproducible, verifiable generative art runtime. Agent-first design for AI coding assistants.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/entry/browser.js",
|
|
7
7
|
"types": "./dist/entry/browser.d.ts",
|
|
@@ -35,15 +35,19 @@
|
|
|
35
35
|
},
|
|
36
36
|
"files": [
|
|
37
37
|
"dist",
|
|
38
|
+
"examples",
|
|
38
39
|
"README.md",
|
|
39
40
|
"CHANGELOG.md",
|
|
40
41
|
"CODE_MODE_PROTOCOL.md",
|
|
41
42
|
"LICENSE.md",
|
|
43
|
+
"LICENSING.md",
|
|
42
44
|
"builder.manifest.schema.json"
|
|
43
45
|
],
|
|
44
46
|
"scripts": {
|
|
45
47
|
"build": "tsc",
|
|
46
48
|
"test": "npx tsx smoke-test.ts",
|
|
49
|
+
"example:basic": "npx tsx examples/basic.ts",
|
|
50
|
+
"example:verify": "npx tsx examples/verify.ts",
|
|
47
51
|
"prepublishOnly": "npm run build && npm run test"
|
|
48
52
|
},
|
|
49
53
|
"keywords": [
|
|
@@ -52,9 +56,21 @@
|
|
|
52
56
|
"nft",
|
|
53
57
|
"p5js",
|
|
54
58
|
"deterministic",
|
|
59
|
+
"reproducible",
|
|
60
|
+
"verifiable",
|
|
61
|
+
"replay",
|
|
62
|
+
"canonical",
|
|
63
|
+
"simulation",
|
|
64
|
+
"procedural",
|
|
65
|
+
"generative",
|
|
66
|
+
"seed",
|
|
67
|
+
"prng",
|
|
68
|
+
"noise",
|
|
55
69
|
"codemode",
|
|
56
70
|
"browser",
|
|
57
|
-
"node"
|
|
71
|
+
"node",
|
|
72
|
+
"ai-agent",
|
|
73
|
+
"strict-mode"
|
|
58
74
|
],
|
|
59
75
|
"author": "NexArt",
|
|
60
76
|
"license": "MIT",
|