@nexart/codemode-sdk 1.1.1 → 1.5.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.
Files changed (91) hide show
  1. package/README.md +131 -238
  2. package/dist/engine.d.ts +39 -17
  3. package/dist/engine.d.ts.map +1 -1
  4. package/dist/engine.js +253 -52
  5. package/dist/index.d.ts +17 -24
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +16 -30
  8. package/dist/loop-engine.d.ts +2 -1
  9. package/dist/loop-engine.d.ts.map +1 -1
  10. package/dist/loop-engine.js +16 -10
  11. package/dist/p5-runtime.d.ts +3 -3
  12. package/dist/p5-runtime.d.ts.map +1 -1
  13. package/dist/p5-runtime.js +398 -13
  14. package/dist/static-engine.d.ts +1 -1
  15. package/dist/static-engine.d.ts.map +1 -1
  16. package/dist/static-engine.js +3 -2
  17. package/dist/types.d.ts +6 -5
  18. package/dist/types.d.ts.map +1 -1
  19. package/dist/types.js +3 -3
  20. package/package.json +17 -23
  21. package/CHANGELOG.md +0 -109
  22. package/CODE_MODE_PROTOCOL.md +0 -312
  23. package/dist/core-index.d.ts +0 -21
  24. package/dist/core-index.d.ts.map +0 -1
  25. package/dist/core-index.js +0 -26
  26. package/dist/execute.d.ts +0 -46
  27. package/dist/execute.d.ts.map +0 -1
  28. package/dist/execute.js +0 -268
  29. package/dist/noise-bridge.d.ts +0 -44
  30. package/dist/noise-bridge.d.ts.map +0 -1
  31. package/dist/noise-bridge.js +0 -68
  32. package/dist/noise-engine.d.ts +0 -74
  33. package/dist/noise-engine.d.ts.map +0 -1
  34. package/dist/noise-engine.js +0 -132
  35. package/dist/noise-sketches/fractalNoise.d.ts +0 -11
  36. package/dist/noise-sketches/fractalNoise.d.ts.map +0 -1
  37. package/dist/noise-sketches/fractalNoise.js +0 -121
  38. package/dist/noise-sketches/index.d.ts +0 -21
  39. package/dist/noise-sketches/index.d.ts.map +0 -1
  40. package/dist/noise-sketches/index.js +0 -28
  41. package/dist/sound-bridge.d.ts +0 -89
  42. package/dist/sound-bridge.d.ts.map +0 -1
  43. package/dist/sound-bridge.js +0 -128
  44. package/dist/soundart-engine.d.ts +0 -87
  45. package/dist/soundart-engine.d.ts.map +0 -1
  46. package/dist/soundart-engine.js +0 -173
  47. package/dist/soundart-sketches/chladniBloom.d.ts +0 -3
  48. package/dist/soundart-sketches/chladniBloom.d.ts.map +0 -1
  49. package/dist/soundart-sketches/chladniBloom.js +0 -53
  50. package/dist/soundart-sketches/dualVortex.d.ts +0 -3
  51. package/dist/soundart-sketches/dualVortex.d.ts.map +0 -1
  52. package/dist/soundart-sketches/dualVortex.js +0 -67
  53. package/dist/soundart-sketches/geometryIllusion.d.ts +0 -3
  54. package/dist/soundart-sketches/geometryIllusion.d.ts.map +0 -1
  55. package/dist/soundart-sketches/geometryIllusion.js +0 -89
  56. package/dist/soundart-sketches/index.d.ts +0 -39
  57. package/dist/soundart-sketches/index.d.ts.map +0 -1
  58. package/dist/soundart-sketches/index.js +0 -72
  59. package/dist/soundart-sketches/isoflow.d.ts +0 -3
  60. package/dist/soundart-sketches/isoflow.d.ts.map +0 -1
  61. package/dist/soundart-sketches/isoflow.js +0 -60
  62. package/dist/soundart-sketches/loomWeave.d.ts +0 -3
  63. package/dist/soundart-sketches/loomWeave.d.ts.map +0 -1
  64. package/dist/soundart-sketches/loomWeave.js +0 -59
  65. package/dist/soundart-sketches/noiseTerraces.d.ts +0 -3
  66. package/dist/soundart-sketches/noiseTerraces.d.ts.map +0 -1
  67. package/dist/soundart-sketches/noiseTerraces.js +0 -53
  68. package/dist/soundart-sketches/orb.d.ts +0 -3
  69. package/dist/soundart-sketches/orb.d.ts.map +0 -1
  70. package/dist/soundart-sketches/orb.js +0 -50
  71. package/dist/soundart-sketches/pixelGlyphs.d.ts +0 -3
  72. package/dist/soundart-sketches/pixelGlyphs.d.ts.map +0 -1
  73. package/dist/soundart-sketches/pixelGlyphs.js +0 -72
  74. package/dist/soundart-sketches/prismFlowFields.d.ts +0 -3
  75. package/dist/soundart-sketches/prismFlowFields.d.ts.map +0 -1
  76. package/dist/soundart-sketches/prismFlowFields.js +0 -51
  77. package/dist/soundart-sketches/radialBurst.d.ts +0 -3
  78. package/dist/soundart-sketches/radialBurst.d.ts.map +0 -1
  79. package/dist/soundart-sketches/radialBurst.js +0 -60
  80. package/dist/soundart-sketches/resonantSoundBodies.d.ts +0 -3
  81. package/dist/soundart-sketches/resonantSoundBodies.d.ts.map +0 -1
  82. package/dist/soundart-sketches/resonantSoundBodies.js +0 -89
  83. package/dist/soundart-sketches/rings.d.ts +0 -11
  84. package/dist/soundart-sketches/rings.d.ts.map +0 -1
  85. package/dist/soundart-sketches/rings.js +0 -89
  86. package/dist/soundart-sketches/squares.d.ts +0 -3
  87. package/dist/soundart-sketches/squares.d.ts.map +0 -1
  88. package/dist/soundart-sketches/squares.js +0 -52
  89. package/dist/soundart-sketches/waveStripes.d.ts +0 -3
  90. package/dist/soundart-sketches/waveStripes.d.ts.map +0 -1
  91. package/dist/soundart-sketches/waveStripes.js +0 -44
package/dist/engine.js CHANGED
@@ -1,67 +1,268 @@
1
1
  /**
2
- * NexArt Code Mode Runtime SDK
3
- * Version: 0.1.0
2
+ * NexArt Code Mode Runtime SDK - Canonical Execution Entry Point
4
3
  *
5
- * Main entry point for the Code Mode runtime engine.
6
- *
7
- * Usage:
8
- * const engine = createEngine({ mode: 'static' });
9
- * engine.run({
10
- * code: 'function setup() { background(255); ellipse(width/2, height/2, 100); }',
11
- * onComplete: (result) => console.log(result.blob)
12
- * });
4
+ * ╔══════════════════════════════════════════════════════════════════════════╗
5
+ * ║ CODE MODE PROTOCOL v1.2.0 (Phase 3) — CANONICAL ENTRY POINT ║
6
+ * ║ ║
7
+ * ║ This is the ONLY official way to execute Code Mode. ║
8
+ * ║ All implementations (NexArt, ByX, external) MUST use this function.
9
+ * ║ ║
10
+ * ║ Authority: @nexart/codemode-sdk ║
11
+ * ╚══════════════════════════════════════════════════════════════════════════╝
13
12
  */
14
- import { DEFAULT_CONFIG } from './types';
15
13
  import { runStaticMode } from './static-engine';
16
- import { runLoopMode, cancelLoopMode } from './loop-engine';
14
+ import { runLoopMode } from './loop-engine';
15
+ import { PROTOCOL_IDENTITY, DEFAULT_CONFIG, } from './types';
17
16
  /**
18
- * Create a NexArt Code Mode rendering engine.
17
+ * Validate and normalize VAR array to 10 elements.
19
18
  *
20
- * @param config - Engine configuration
21
- * @returns Engine instance
19
+ * Rules (SDK v1.0.2, Protocol v1.0.0):
20
+ * - VAR is OPTIONAL: omit or pass [] for empty (defaults to all zeros)
21
+ * - VAR input length MUST be 0-10 elements (protocol error if > 10)
22
+ * - VAR values MUST be finite numbers (protocol error if not)
23
+ * - VAR values MUST be in range 0-100 (protocol error if out of range, NO clamping)
24
+ * - VAR is read-only inside sketches
25
+ * - Output is ALWAYS 10 elements (padded with zeros) for protocol consistency
22
26
  */
23
- export function createEngine(config) {
24
- const resolvedConfig = {
25
- mode: config.mode,
26
- width: config.width ?? DEFAULT_CONFIG.width,
27
- height: config.height ?? DEFAULT_CONFIG.height,
28
- duration: config.duration ?? DEFAULT_CONFIG.duration,
29
- fps: config.fps ?? DEFAULT_CONFIG.fps,
30
- };
31
- let isRunning = false;
32
- const run = async (options) => {
33
- if (isRunning) {
34
- throw new Error('Engine is already running. Call stop() first.');
27
+ function normalizeVars(vars) {
28
+ if (!vars || !Array.isArray(vars)) {
29
+ console.log('[CodeMode] No vars provided, using defaults [0,0,0,0,0,0,0,0,0,0]');
30
+ return [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
31
+ }
32
+ if (vars.length > 10) {
33
+ throw new Error(`[Code Mode Protocol Error] VAR array must have at most 10 elements, got ${vars.length}`);
34
+ }
35
+ const result = [];
36
+ for (let i = 0; i < vars.length; i++) {
37
+ const v = vars[i];
38
+ if (typeof v !== 'number' || !Number.isFinite(v)) {
39
+ throw new Error(`[Code Mode Protocol Error] VAR[${i}] must be a finite number, got ${typeof v === 'number' ? v : typeof v}`);
35
40
  }
36
- isRunning = true;
37
- try {
38
- if (resolvedConfig.mode === 'static') {
39
- await runStaticMode(resolvedConfig, options);
40
- }
41
- else if (resolvedConfig.mode === 'loop') {
42
- await runLoopMode(resolvedConfig, options);
43
- }
44
- else {
45
- throw new Error(`Unknown mode: ${resolvedConfig.mode}`);
46
- }
41
+ if (v < 0 || v > 100) {
42
+ throw new Error(`[Code Mode Protocol Error] VAR[${i}] = ${v} is out of range. Values must be 0-100.`);
43
+ }
44
+ result.push(v);
45
+ }
46
+ // Pad with zeros to always have 10 elements for protocol consistency
47
+ while (result.length < 10) {
48
+ result.push(0);
49
+ }
50
+ return result;
51
+ }
52
+ /**
53
+ * Validate execution input
54
+ */
55
+ function validateInput(input) {
56
+ if (!input.source || typeof input.source !== 'string') {
57
+ throw new Error('[Code Mode Protocol Error] source is required and must be a string');
58
+ }
59
+ if (typeof input.width !== 'number' || input.width <= 0) {
60
+ throw new Error('[Code Mode Protocol Error] width must be a positive number');
61
+ }
62
+ if (typeof input.height !== 'number' || input.height <= 0) {
63
+ throw new Error('[Code Mode Protocol Error] height must be a positive number');
64
+ }
65
+ if (typeof input.seed !== 'number') {
66
+ throw new Error('[Code Mode Protocol Error] seed is required and must be a number');
67
+ }
68
+ if (input.mode !== 'static' && input.mode !== 'loop') {
69
+ throw new Error('[Code Mode Protocol Error] mode must be "static" or "loop"');
70
+ }
71
+ if (input.mode === 'loop') {
72
+ if (typeof input.totalFrames !== 'number' || input.totalFrames <= 0) {
73
+ throw new Error('[Code Mode Protocol Error] totalFrames is required for loop mode and must be a positive number');
47
74
  }
48
- finally {
49
- isRunning = false;
75
+ }
76
+ // Validate forbidden patterns per CODE_MODE_PROTOCOL.md
77
+ const forbiddenPatterns = [
78
+ // Async timing (breaks determinism)
79
+ { pattern: /setTimeout\s*\(/, name: 'setTimeout' },
80
+ { pattern: /setInterval\s*\(/, name: 'setInterval' },
81
+ { pattern: /requestAnimationFrame\s*\(/, name: 'requestAnimationFrame' },
82
+ // Time-based entropy (breaks determinism)
83
+ { pattern: /Date\.now\s*\(/, name: 'Date.now() — use time variable instead' },
84
+ { pattern: /new\s+Date\s*\(/, name: 'new Date() — use time variable instead' },
85
+ // Unseeded random (use random() instead)
86
+ { pattern: /Math\.random\s*\(/, name: 'Math.random() — use random() instead (seeded)' },
87
+ // External IO (breaks determinism)
88
+ { pattern: /fetch\s*\(/, name: 'fetch() — external IO forbidden' },
89
+ { pattern: /XMLHttpRequest/, name: 'XMLHttpRequest — external IO forbidden' },
90
+ // Canvas is pre-initialized
91
+ { pattern: /createCanvas\s*\(/, name: 'createCanvas() — canvas is pre-initialized' },
92
+ // DOM manipulation forbidden
93
+ { pattern: /document\./, name: 'DOM access — document.* forbidden' },
94
+ { pattern: /window\./, name: 'DOM access — window.* forbidden' },
95
+ // External imports forbidden
96
+ { pattern: /\bimport\s+/, name: 'import — external imports forbidden' },
97
+ { pattern: /\brequire\s*\(/, name: 'require() — external imports forbidden' },
98
+ ];
99
+ for (const { pattern, name } of forbiddenPatterns) {
100
+ if (pattern.test(input.source)) {
101
+ throw new Error(`[Code Mode Protocol Error] Forbidden pattern: ${name}`);
50
102
  }
51
- };
52
- const stop = () => {
53
- if (resolvedConfig.mode === 'loop') {
54
- cancelLoopMode();
103
+ }
104
+ // Loop mode specific validation
105
+ if (input.mode === 'loop') {
106
+ if (!/function\s+draw\s*\(\s*\)/.test(input.source)) {
107
+ throw new Error('[Code Mode Protocol Error] Loop mode requires a draw() function');
55
108
  }
56
- isRunning = false;
57
- };
58
- const getConfig = () => {
59
- return { ...resolvedConfig };
109
+ if (/noLoop\s*\(\s*\)/.test(input.source)) {
110
+ throw new Error('[Code Mode Protocol Error] noLoop() is forbidden in Loop mode');
111
+ }
112
+ }
113
+ }
114
+ /**
115
+ * Create protocol metadata for the execution result
116
+ */
117
+ function createMetadata(input, vars) {
118
+ return {
119
+ ...PROTOCOL_IDENTITY,
120
+ seed: input.seed,
121
+ vars,
122
+ width: input.width,
123
+ height: input.height,
124
+ mode: input.mode,
125
+ ...(input.mode === 'loop' && input.totalFrames ? { totalFrames: input.totalFrames } : {}),
60
126
  };
127
+ }
128
+ /**
129
+ * Execute Code Mode in Static mode - delegates to static-engine.ts
130
+ */
131
+ async function executeStatic(input, vars) {
132
+ console.log('[CodeMode] Rendered via @nexart/codemode-sdk (Protocol v1.2.0)');
133
+ console.log('[CodeMode] Execution: Static mode — delegating to static-engine');
134
+ return new Promise((resolve, reject) => {
135
+ runStaticMode({
136
+ mode: 'static',
137
+ width: input.width,
138
+ height: input.height,
139
+ }, {
140
+ code: input.source,
141
+ seed: input.seed,
142
+ vars: vars,
143
+ onComplete: (result) => {
144
+ resolve({
145
+ image: result.blob,
146
+ metadata: createMetadata(input, vars),
147
+ });
148
+ },
149
+ onError: (error) => {
150
+ reject(error);
151
+ },
152
+ });
153
+ });
154
+ }
155
+ /**
156
+ * Execute Code Mode in Loop mode - delegates to loop-engine.ts
157
+ */
158
+ async function executeLoop(input, vars) {
159
+ console.log('[CodeMode] Rendered via @nexart/codemode-sdk (Protocol v1.2.0)');
160
+ console.log(`[CodeMode] Execution: Loop mode — delegating to loop-engine (${input.totalFrames} frames)`);
161
+ const fps = DEFAULT_CONFIG.fps;
162
+ const duration = (input.totalFrames || 60) / fps;
163
+ return new Promise((resolve, reject) => {
164
+ runLoopMode({
165
+ mode: 'loop',
166
+ width: input.width,
167
+ height: input.height,
168
+ duration: duration,
169
+ fps: fps,
170
+ }, {
171
+ code: input.source,
172
+ seed: input.seed,
173
+ vars: vars,
174
+ onComplete: (result) => {
175
+ resolve({
176
+ video: result.blob,
177
+ metadata: createMetadata(input, vars),
178
+ });
179
+ },
180
+ onError: (error) => {
181
+ reject(error);
182
+ },
183
+ });
184
+ });
185
+ }
186
+ /**
187
+ * executeCodeMode — Canonical Code Mode Execution Entry Point
188
+ *
189
+ * This is the ONLY official way to execute Code Mode.
190
+ * All implementations MUST use this function.
191
+ *
192
+ * @param input - Execution parameters
193
+ * @returns Promise<ExecuteCodeModeResult> - Execution result with protocol metadata
194
+ *
195
+ * @example
196
+ * ```typescript
197
+ * const result = await executeCodeMode({
198
+ * source: `function setup() { background(255); ellipse(width/2, height/2, 100); }`,
199
+ * width: 1950,
200
+ * height: 2400,
201
+ * seed: 12345,
202
+ * vars: [50, 75, 0, 0, 0, 0, 0, 0, 0, 0],
203
+ * mode: 'static'
204
+ * });
205
+ *
206
+ * console.log(result.metadata.protocolVersion); // '1.2.0'
207
+ * console.log(result.image); // PNG Blob
208
+ * ```
209
+ */
210
+ export async function executeCodeMode(input) {
211
+ // Validate input
212
+ validateInput(input);
213
+ // Normalize VAR values
214
+ const vars = normalizeVars(input.vars);
215
+ // Log protocol execution
216
+ console.log('[CodeMode] ════════════════════════════════════════════════');
217
+ console.log('[CodeMode] Protocol v1.2.0 — Phase 3 — HARD Enforcement');
218
+ console.log(`[CodeMode] Mode: ${input.mode}`);
219
+ console.log(`[CodeMode] Seed: ${input.seed}`);
220
+ console.log(`[CodeMode] VAR: [${vars.join(', ')}]`);
221
+ console.log('[CodeMode] ════════════════════════════════════════════════');
222
+ // Execute based on mode
223
+ if (input.mode === 'static') {
224
+ return executeStatic(input, vars);
225
+ }
226
+ else {
227
+ return executeLoop(input, vars);
228
+ }
229
+ }
230
+ /**
231
+ * Validate code without executing
232
+ */
233
+ export function validateCodeModeSource(source, mode) {
234
+ const errors = [];
235
+ // Same forbidden patterns as validateInput per CODE_MODE_PROTOCOL.md
236
+ const forbiddenPatterns = [
237
+ { pattern: /setTimeout\s*\(/, name: 'setTimeout' },
238
+ { pattern: /setInterval\s*\(/, name: 'setInterval' },
239
+ { pattern: /requestAnimationFrame\s*\(/, name: 'requestAnimationFrame' },
240
+ { pattern: /Date\.now\s*\(/, name: 'Date.now() — use time variable instead' },
241
+ { pattern: /new\s+Date\s*\(/, name: 'new Date() — use time variable instead' },
242
+ { pattern: /Math\.random\s*\(/, name: 'Math.random() — use random() instead (seeded)' },
243
+ { pattern: /fetch\s*\(/, name: 'fetch() — external IO forbidden' },
244
+ { pattern: /XMLHttpRequest/, name: 'XMLHttpRequest — external IO forbidden' },
245
+ { pattern: /createCanvas\s*\(/, name: 'createCanvas() — canvas is pre-initialized' },
246
+ { pattern: /document\./, name: 'DOM access — document.* forbidden' },
247
+ { pattern: /window\./, name: 'DOM access — window.* forbidden' },
248
+ { pattern: /\bimport\s+/, name: 'import — external imports forbidden' },
249
+ { pattern: /\brequire\s*\(/, name: 'require() — external imports forbidden' },
250
+ ];
251
+ for (const { pattern, name } of forbiddenPatterns) {
252
+ if (pattern.test(source)) {
253
+ errors.push(`Forbidden pattern: ${name}`);
254
+ }
255
+ }
256
+ if (mode === 'loop') {
257
+ if (!/function\s+draw\s*\(\s*\)/.test(source)) {
258
+ errors.push('Loop mode requires a draw() function');
259
+ }
260
+ if (/noLoop\s*\(\s*\)/.test(source)) {
261
+ errors.push('noLoop() is forbidden in Loop mode');
262
+ }
263
+ }
61
264
  return {
62
- run,
63
- stop,
64
- getConfig,
265
+ valid: errors.length === 0,
266
+ errors,
65
267
  };
66
268
  }
67
- export { DEFAULT_CONFIG } from './types';
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * NexArt Code Mode Runtime SDK
3
- * Version: 1.1.0 (Protocol v1.0.0)
3
+ * Version: 1.5.0 (Protocol v1.2.0)
4
4
  *
5
5
  * ╔══════════════════════════════════════════════════════════════════════════╗
6
6
  * ║ @nexart/codemode-sdk — Canonical Code Mode Authority ║
@@ -10,9 +10,9 @@
10
10
  * ║ ║
11
11
  * ║ Protocol: nexart ║
12
12
  * ║ Engine: codemode ║
13
- * ║ SDK Version: 1.1.0 ║
14
- * ║ Protocol Version: 1.0.0 ║
15
- * ║ Phase: 1
13
+ * ║ SDK Version: 1.5.0 ║
14
+ * ║ Protocol Version: 1.2.0 ║
15
+ * ║ Phase: 3
16
16
  * ║ Enforcement: HARD ║
17
17
  * ╚══════════════════════════════════════════════════════════════════════════╝
18
18
  *
@@ -21,30 +21,23 @@
21
21
  * import { executeCodeMode } from '@nexart/codemode-sdk';
22
22
  *
23
23
  * const result = await executeCodeMode({
24
- * source: `function setup() { background(255); ellipse(width/2, height/2, 100); }`,
24
+ * source: `
25
+ * function setup() {
26
+ * background(255);
27
+ * fill(0);
28
+ * ellipse(width/2, height/2, 100);
29
+ * }
30
+ * `,
31
+ * mode: 'static',
25
32
  * width: 1950,
26
33
  * height: 2400,
27
34
  * seed: 12345,
28
- * vars: [50, 0, 0, 0, 0, 0, 0, 0, 0, 0],
29
- * mode: 'static'
35
+ * vars: [50, 50, 50, 50, 50, 50, 50, 50, 50, 50]
30
36
  * });
31
- *
32
- * console.log(result.metadata.protocolVersion); // '1.0.0'
37
+ * console.log('Rendered:', result.blob.size, 'bytes');
33
38
  * ```
34
39
  */
35
- export { executeCodeMode, validateCodeModeSource } from './execute';
36
- export type { ExecuteCodeModeInput, ExecuteCodeModeResult, ProtocolMetadata, } from './types';
37
- export { PROTOCOL_IDENTITY } from './types';
38
- export { createEngine } from './engine';
39
- export type { Engine, EngineConfig, RunOptions, RenderResult, ProgressInfo, RenderMode, TimeVariables, } from './types';
40
- export { DEFAULT_CONFIG } from './types';
41
- export { renderSoundArtViaCodeMode, canRenderViaCodeMode, getCodeModeAvailableStyles, type SoundArtEngineConfig, type SoundArtRenderOptions, type SoundArtRenderResult, type SoundArtMetadata, } from './soundart-engine';
42
- export { type SoundSnapshot, type SoundFeatures, createSoundSnapshot, createEmptySoundSnapshot, freezeSoundSnapshot, } from '../../shared/soundSnapshot';
43
- export { injectSoundGlobals, createSoundGlobals, createEmptySoundGlobals, generateSoundPalette, inferGenreProfile, createSoundHelpers, type SoundGlobals, type GenreProfile, } from './sound-bridge';
44
- export { getSoundArtSketch, getAvailableSoundArtSketches, isSoundArtSketchAvailable, type SoundArtSketchName, } from './soundart-sketches';
45
- export { createP5Runtime, type P5Runtime, type P5RuntimeConfig } from './p5-runtime';
46
- export { renderNoiseViaCodeMode, compileNoiseSystem, canRenderNoiseViaCodeMode, type NoiseEngineConfig, type NoiseRenderOptions, type NoiseRenderResult, type NoiseMetadata, } from './noise-engine';
47
- export { type NoiseSnapshot, type NoiseParams, type NoiseBlendMode, createNoiseSnapshot, validateNoiseSnapshot, } from '../../shared/noiseSnapshot';
48
- export { createNoiseGlobals, injectNoiseGlobals, type NoiseGlobals, } from './noise-bridge';
49
- export { getNoiseSketch, getAvailableNoiseSketchNames, isValidNoiseSketch, type NoiseSketchName, } from './noise-sketches';
40
+ export { executeCodeMode, validateCodeModeSource } from './engine';
41
+ export type { ExecuteCodeModeInput, ExecuteCodeModeResult, ProtocolMetadata, RenderResult, TimeVariables, } from './types';
42
+ export { DEFAULT_CONFIG, PROTOCOL_IDENTITY } from './types';
50
43
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAKH,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AACpE,YAAY,EACV,oBAAoB,EACpB,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAK5C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,YAAY,EACV,MAAM,EACN,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAGzC,OAAO,EACL,yBAAyB,EACzB,oBAAoB,EACpB,0BAA0B,EAC1B,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,GACtB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,mBAAmB,EACnB,wBAAwB,EACxB,mBAAmB,GACpB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,uBAAuB,EACvB,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,YAAY,GAClB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,iBAAiB,EACjB,4BAA4B,EAC5B,yBAAyB,EACzB,KAAK,kBAAkB,GACxB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,eAAe,EAAE,KAAK,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAGrF,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,yBAAyB,EACzB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,aAAa,GACnB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,KAAK,YAAY,GAClB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,cAAc,EACd,4BAA4B,EAC5B,kBAAkB,EAClB,KAAK,eAAe,GACrB,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AACnE,YAAY,EACV,oBAAoB,EACpB,qBAAqB,EACrB,gBAAgB,EAChB,YAAY,EACZ,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * NexArt Code Mode Runtime SDK
3
- * Version: 1.1.0 (Protocol v1.0.0)
3
+ * Version: 1.5.0 (Protocol v1.2.0)
4
4
  *
5
5
  * ╔══════════════════════════════════════════════════════════════════════════╗
6
6
  * ║ @nexart/codemode-sdk — Canonical Code Mode Authority ║
@@ -10,9 +10,9 @@
10
10
  * ║ ║
11
11
  * ║ Protocol: nexart ║
12
12
  * ║ Engine: codemode ║
13
- * ║ SDK Version: 1.1.0 ║
14
- * ║ Protocol Version: 1.0.0 ║
15
- * ║ Phase: 1
13
+ * ║ SDK Version: 1.5.0 ║
14
+ * ║ Protocol Version: 1.2.0 ║
15
+ * ║ Phase: 3
16
16
  * ║ Enforcement: HARD ║
17
17
  * ╚══════════════════════════════════════════════════════════════════════════╝
18
18
  *
@@ -21,35 +21,21 @@
21
21
  * import { executeCodeMode } from '@nexart/codemode-sdk';
22
22
  *
23
23
  * const result = await executeCodeMode({
24
- * source: `function setup() { background(255); ellipse(width/2, height/2, 100); }`,
24
+ * source: `
25
+ * function setup() {
26
+ * background(255);
27
+ * fill(0);
28
+ * ellipse(width/2, height/2, 100);
29
+ * }
30
+ * `,
31
+ * mode: 'static',
25
32
  * width: 1950,
26
33
  * height: 2400,
27
34
  * seed: 12345,
28
- * vars: [50, 0, 0, 0, 0, 0, 0, 0, 0, 0],
29
- * mode: 'static'
35
+ * vars: [50, 50, 50, 50, 50, 50, 50, 50, 50, 50]
30
36
  * });
31
- *
32
- * console.log(result.metadata.protocolVersion); // '1.0.0'
37
+ * console.log('Rendered:', result.blob.size, 'bytes');
33
38
  * ```
34
39
  */
35
- // ═══════════════════════════════════════════════════════════════════════════
36
- // CANONICAL EXECUTION ENTRY POINT
37
- // ═══════════════════════════════════════════════════════════════════════════
38
- export { executeCodeMode, validateCodeModeSource } from './execute';
39
- export { PROTOCOL_IDENTITY } from './types';
40
- // ═══════════════════════════════════════════════════════════════════════════
41
- // LEGACY ENGINE API (use executeCodeMode for new implementations)
42
- // ═══════════════════════════════════════════════════════════════════════════
43
- export { createEngine } from './engine';
44
- export { DEFAULT_CONFIG } from './types';
45
- // SoundArt → Code Mode integration
46
- export { renderSoundArtViaCodeMode, canRenderViaCodeMode, getCodeModeAvailableStyles, } from './soundart-engine';
47
- export { createSoundSnapshot, createEmptySoundSnapshot, freezeSoundSnapshot, } from '../../shared/soundSnapshot';
48
- export { injectSoundGlobals, createSoundGlobals, createEmptySoundGlobals, generateSoundPalette, inferGenreProfile, createSoundHelpers, } from './sound-bridge';
49
- export { getSoundArtSketch, getAvailableSoundArtSketches, isSoundArtSketchAvailable, } from './soundart-sketches';
50
- export { createP5Runtime } from './p5-runtime';
51
- // Noise → Code Mode integration
52
- export { renderNoiseViaCodeMode, compileNoiseSystem, canRenderNoiseViaCodeMode, } from './noise-engine';
53
- export { createNoiseSnapshot, validateNoiseSnapshot, } from '../../shared/noiseSnapshot';
54
- export { createNoiseGlobals, injectNoiseGlobals, } from './noise-bridge';
55
- export { getNoiseSketch, getAvailableNoiseSketchNames, isValidNoiseSketch, } from './noise-sketches';
40
+ export { executeCodeMode, validateCodeModeSource } from './engine';
41
+ export { DEFAULT_CONFIG, PROTOCOL_IDENTITY } from './types';
@@ -1,11 +1,12 @@
1
1
  /**
2
2
  * NexArt Code Mode Runtime SDK - Loop Engine
3
- * Protocol: v1.0.0 (Phase 1) — HARD ENFORCEMENT
3
+ * Protocol: v1.2.0 (Phase 3) — HARD ENFORCEMENT
4
4
  *
5
5
  * Loop mode renderer: frame-authoritative, stateless execution.
6
6
  * - Executes setup() once
7
7
  * - Executes draw() once per frame
8
8
  * - Clears canvas before each frame (transparent)
9
+ * - Resets blend mode to NORMAL before each frame
9
10
  * - Injects normalized time variables
10
11
  * - No canvas persistence between frames
11
12
  *
@@ -1 +1 @@
1
- {"version":3,"file":"loop-engine.d.ts","sourceRoot":"","sources":["../loop-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAA+B,MAAM,SAAS,CAAC;AAMrF,wBAAgB,cAAc,IAAI,IAAI,CAErC;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,IAAI,CAAC,CA+Lf"}
1
+ {"version":3,"file":"loop-engine.d.ts","sourceRoot":"","sources":["../loop-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAA+B,MAAM,SAAS,CAAC;AAMrF,wBAAgB,cAAc,IAAI,IAAI,CAErC;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,IAAI,CAAC,CAuMf"}
@@ -1,11 +1,12 @@
1
1
  /**
2
2
  * NexArt Code Mode Runtime SDK - Loop Engine
3
- * Protocol: v1.0.0 (Phase 1) — HARD ENFORCEMENT
3
+ * Protocol: v1.2.0 (Phase 3) — HARD ENFORCEMENT
4
4
  *
5
5
  * Loop mode renderer: frame-authoritative, stateless execution.
6
6
  * - Executes setup() once
7
7
  * - Executes draw() once per frame
8
8
  * - Clears canvas before each frame (transparent)
9
+ * - Resets blend mode to NORMAL before each frame
9
10
  * - Injects normalized time variables
10
11
  * - No canvas persistence between frames
11
12
  *
@@ -69,16 +70,18 @@ export async function runLoopMode(config, options) {
69
70
  if (!drawCode) {
70
71
  throw new Error('Loop Mode requires a draw() function with content.');
71
72
  }
72
- // Create wrapped functions with p5 context, time variables, and VAR
73
- const wrappedSetup = new Function('p', 'frameCount', 't', 'time', 'tGlobal', 'VAR', `with(p) { ${setupCode} }`);
74
- const wrappedDraw = new Function('p', 'frameCount', 't', 'time', 'tGlobal', 'VAR', `with(p) { ${drawCode} }`);
73
+ // Inject totalFrames into runtime
74
+ p.totalFrames = totalFrames;
75
+ // Create wrapped functions with p5 context, time variables, VAR, and totalFrames
76
+ const wrappedSetup = new Function('p', 'frameCount', 't', 'time', 'tGlobal', 'VAR', 'totalFrames', `with(p) { ${setupCode} }`);
77
+ const wrappedDraw = new Function('p', 'frameCount', 't', 'time', 'tGlobal', 'VAR', 'totalFrames', `with(p) { ${drawCode} }`);
75
78
  onProgress?.({
76
79
  phase: 'setup',
77
80
  percent: 10,
78
81
  message: 'Executing setup()...',
79
82
  });
80
- // Execute setup() once with time = 0 and VAR
81
- wrappedSetup(p, 0, 0, 0, 0, p.VAR);
83
+ // Execute setup() once with time = 0, VAR, and totalFrames
84
+ wrappedSetup(p, 0, 0, 0, 0, p.VAR, totalFrames);
82
85
  // Capture frames
83
86
  const frames = [];
84
87
  onProgress?.({
@@ -98,12 +101,15 @@ export async function runLoopMode(config, options) {
98
101
  const time = t * duration;
99
102
  // Update p5 runtime frameCount
100
103
  p.frameCount = frame;
101
- // CRITICAL: Clear canvas before each draw() call
104
+ // CRITICAL: Reset canvas state before each draw() call
102
105
  // This enforces stateless, frame-authoritative rendering
103
- // Preserves artist-defined backgrounds (if they call background() in draw)
106
+ // 1. Clear canvas (transparent)
104
107
  p.clear();
105
- // Execute draw() with time variables and VAR
106
- wrappedDraw(p, frame, t, time, t, p.VAR);
108
+ // 2. Reset blend mode to NORMAL (Protocol v1.1 requirement)
109
+ // Prevents blend mode state from persisting across frames
110
+ p.blendMode('NORMAL');
111
+ // Execute draw() with time variables, VAR, and totalFrames
112
+ wrappedDraw(p, frame, t, time, t, p.VAR, totalFrames);
107
113
  // Capture frame as PNG blob
108
114
  const blob = await new Promise((resolve, reject) => {
109
115
  canvas.toBlob((b) => b ? resolve(b) : reject(new Error(`Failed to capture frame ${frame}`)), 'image/png');
@@ -2,7 +2,7 @@
2
2
  * NexArt Code Mode Runtime SDK - p5-like Runtime
3
3
  *
4
4
  * ╔══════════════════════════════════════════════════════════════════════════╗
5
- * ║ CODE MODE PROTOCOL v1.0.0 (Phase 1) — LOCKED
5
+ * ║ CODE MODE PROTOCOL v1.2.0 (Phase 3) — STABLE
6
6
  * ║ ║
7
7
  * ║ Status: HARD PROTOCOL ENFORCEMENT ║
8
8
  * ║ This is the stable, canonical execution surface. ║
@@ -33,8 +33,8 @@ import type { TimeVariables } from './types';
33
33
  * This constant defines the locked protocol version.
34
34
  * Changes to the execution surface require a version bump.
35
35
  */
36
- export declare const CODE_MODE_PROTOCOL_VERSION = "1.0.0";
37
- export declare const CODE_MODE_PROTOCOL_PHASE = 1;
36
+ export declare const CODE_MODE_PROTOCOL_VERSION = "1.2.0";
37
+ export declare const CODE_MODE_PROTOCOL_PHASE = 3;
38
38
  export declare const CODE_MODE_ENFORCEMENT: "HARD";
39
39
  export interface P5Runtime {
40
40
  [key: string]: any;
@@ -1 +1 @@
1
- {"version":3,"file":"p5-runtime.d.ts","sourceRoot":"","sources":["../p5-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,UAAU,CAAC;AAClD,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAC1C,eAAO,MAAM,qBAAqB,EAAG,MAAe,CAAC;AAErD,MAAM,WAAW,SAAS;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAmED,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,iBAAiB,EACzB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,eAAe,GACvB,SAAS,CA0hBX;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa,GAAG,IAAI,CAE3E;AAED;;;GAGG;AACH,eAAO,MAAM,SAAS,KAAK,CAAC;AAC5B,eAAO,MAAM,OAAO,IAAI,CAAC;AACzB,eAAO,MAAM,OAAO,MAAM,CAAC;AAE3B;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,MAAM,EAAE,CAmCpE;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAE3E"}
1
+ {"version":3,"file":"p5-runtime.d.ts","sourceRoot":"","sources":["../p5-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,UAAU,CAAC;AAClD,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAC1C,eAAO,MAAM,qBAAqB,EAAG,MAAe,CAAC;AAErD,MAAM,WAAW,SAAS;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAmED,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,iBAAiB,EACzB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,eAAe,GACvB,SAAS,CAq8BX;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa,GAAG,IAAI,CAM3E;AAED;;;GAGG;AACH,eAAO,MAAM,SAAS,KAAK,CAAC;AAC5B,eAAO,MAAM,OAAO,IAAI,CAAC;AACzB,eAAO,MAAM,OAAO,MAAM,CAAC;AAE3B;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,MAAM,EAAE,CAmCpE;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAE3E"}