@nexart/ui-renderer 0.8.7 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,6 @@
1
1
  /**
2
2
  * @nexart/ui-renderer - Preview Runtime Types
3
+ * Version: 0.9.0
3
4
  *
4
5
  * ╔══════════════════════════════════════════════════════════════════════════╗
5
6
  * ║ PREVIEW RUNTIME — NON-AUTHORITATIVE ║
@@ -35,12 +36,42 @@ export declare const CANVAS_LIMITS: {
35
36
  /** Minimum dimension */
36
37
  readonly MIN_DIMENSION: 100;
37
38
  };
39
+ /**
40
+ * Preview budget limits (v0.9.0)
41
+ * Enforced optionally to prevent runaway previews.
42
+ */
43
+ export declare const PREVIEW_BUDGET: {
44
+ /** Maximum frames before budget exceeded (default: 1800) */
45
+ readonly MAX_FRAMES: 1800;
46
+ /** Maximum execution time in ms (default: 5 minutes) */
47
+ readonly MAX_TOTAL_TIME_MS: 300000;
48
+ /** Default stride when degrading (skip every N frames) */
49
+ readonly DEGRADE_STRIDE: 2;
50
+ };
38
51
  /**
39
52
  * Preview mode options
40
53
  */
41
54
  export type PreviewMode = 'static' | 'loop';
42
55
  /**
43
- * Preview engine configuration
56
+ * Budget exceed reason
57
+ */
58
+ export type BudgetExceedReason = 'frame_limit' | 'time_limit';
59
+ /**
60
+ * Budget exceeded info (passed to callbacks)
61
+ */
62
+ export interface BudgetExceededInfo {
63
+ reason: BudgetExceedReason;
64
+ framesRendered: number;
65
+ totalTimeMs: number;
66
+ stride: number;
67
+ scale: number;
68
+ }
69
+ /**
70
+ * Budget behavior options
71
+ */
72
+ export type BudgetBehavior = 'degrade' | 'stop';
73
+ /**
74
+ * Preview engine configuration (v0.9.0)
44
75
  */
45
76
  export interface PreviewEngineConfig {
46
77
  /** Canvas element to render to */
@@ -59,6 +90,34 @@ export interface PreviewEngineConfig {
59
90
  vars?: number[];
60
91
  /** Total frames for loop mode (for t calculation) */
61
92
  totalFrames?: number;
93
+ /** Callback when budget is exceeded */
94
+ onBudgetExceeded?: (info: BudgetExceededInfo) => void;
95
+ /** Behavior when budget exceeded: 'degrade' (skip frames) or 'stop' (halt + overlay) */
96
+ budgetBehavior?: BudgetBehavior;
97
+ /** Show overlay when budget exceeded (default: true for 'stop' behavior) */
98
+ showOverlay?: boolean;
99
+ /** Maximum frames before budget exceeded (default: 1800) */
100
+ maxFrames?: number;
101
+ /** Maximum execution time in ms (default: 300000) */
102
+ maxTimeMs?: number;
103
+ }
104
+ /**
105
+ * Preview stats (v0.9.0)
106
+ * Exposes runtime state for observability.
107
+ */
108
+ export interface PreviewStats {
109
+ mode: 'preview';
110
+ scale: number;
111
+ semanticWidth: number;
112
+ semanticHeight: number;
113
+ bufferWidth: number;
114
+ bufferHeight: number;
115
+ frames: number;
116
+ stride: number;
117
+ totalTimeMs: number;
118
+ budgetExceeded?: {
119
+ reason: BudgetExceedReason;
120
+ };
62
121
  }
63
122
  /**
64
123
  * Preview render result
@@ -78,7 +137,7 @@ export interface PreviewRenderResult {
78
137
  errorMessage?: string;
79
138
  }
80
139
  /**
81
- * Preview renderer interface
140
+ * Preview renderer interface (v0.9.0)
82
141
  */
83
142
  export interface PreviewRenderer {
84
143
  /** Render a single frame (static mode) */
@@ -91,6 +150,10 @@ export interface PreviewRenderer {
91
150
  destroy: () => void;
92
151
  /** Check if currently rendering */
93
152
  isRendering: () => boolean;
153
+ /** Get current preview stats (v0.9.0) */
154
+ getPreviewStats: () => PreviewStats;
155
+ /** Current scale factor (v0.9.0) */
156
+ readonly previewScale: number;
94
157
  /** This renderer is NOT canonical */
95
158
  readonly isCanonical: false;
96
159
  /** This renderer is NOT archival */
@@ -103,4 +166,20 @@ export interface FpsThrottleState {
103
166
  /** Timestamp of last rendered frame */
104
167
  lastFrameTimeMs: number;
105
168
  }
169
+ /**
170
+ * Canonical request for handoff to @nexart/codemode-sdk (v0.9.0)
171
+ */
172
+ export interface CanonicalRequest {
173
+ seed: number;
174
+ vars: number[];
175
+ code: string;
176
+ settings?: {
177
+ width: number;
178
+ height: number;
179
+ mode: PreviewMode;
180
+ totalFrames?: number;
181
+ };
182
+ renderer: 'preview';
183
+ uiRendererVersion: string;
184
+ }
106
185
  //# sourceMappingURL=preview-types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"preview-types.d.ts","sourceRoot":"","sources":["../../src/preview/preview-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,SAAS,CAAC;AAEvC;;;GAGG;AACH,eAAO,MAAM,WAAW;IACtB,kEAAkE;;IAElE,0CAA0C;;CAElC,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,aAAa;IACxB,2CAA2C;;IAE3C,wBAAwB;;CAEhB,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE5C;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,kCAAkC;IAClC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB;IACnB,IAAI,EAAE,WAAW,CAAC;IAClB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,+CAA+C;IAC/C,OAAO,EAAE,OAAO,CAAC;IACjB,sBAAsB;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,iCAAiC;IACjC,eAAe,EAAE,MAAM,CAAC;IACxB,2DAA2D;IAC3D,eAAe,EAAE,OAAO,CAAC;IACzB,uCAAuC;IACvC,iBAAiB,CAAC,EAAE,aAAa,GAAG,YAAY,GAAG,WAAW,GAAG,OAAO,CAAC;IACzE,0CAA0C;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,0CAA0C;IAC1C,YAAY,EAAE,MAAM,mBAAmB,CAAC;IACxC,2BAA2B;IAC3B,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,oCAAoC;IACpC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,mCAAmC;IACnC,WAAW,EAAE,MAAM,OAAO,CAAC;IAC3B,qCAAqC;IACrC,QAAQ,CAAC,WAAW,EAAE,KAAK,CAAC;IAC5B,oCAAoC;IACpC,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,uCAAuC;IACvC,eAAe,EAAE,MAAM,CAAC;CACzB"}
1
+ {"version":3,"file":"preview-types.d.ts","sourceRoot":"","sources":["../../src/preview/preview-types.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  /**
2
2
  * @nexart/ui-renderer - Preview Runtime Types
3
+ * Version: 0.9.0
3
4
  *
4
5
  * ╔══════════════════════════════════════════════════════════════════════════╗
5
6
  * ║ PREVIEW RUNTIME — NON-AUTHORITATIVE ║
@@ -30,3 +31,15 @@ export const CANVAS_LIMITS = {
30
31
  /** Minimum dimension */
31
32
  MIN_DIMENSION: 100,
32
33
  };
34
+ /**
35
+ * Preview budget limits (v0.9.0)
36
+ * Enforced optionally to prevent runaway previews.
37
+ */
38
+ export const PREVIEW_BUDGET = {
39
+ /** Maximum frames before budget exceeded (default: 1800) */
40
+ MAX_FRAMES: 1800, // ~30 seconds at 60 FPS
41
+ /** Maximum execution time in ms (default: 5 minutes) */
42
+ MAX_TOTAL_TIME_MS: 300000, // 5 minutes
43
+ /** Default stride when degrading (skip every N frames) */
44
+ DEGRADE_STRIDE: 2,
45
+ };
@@ -0,0 +1,92 @@
1
+ /**
2
+ * @nexart/ui-renderer - Basic Preview Example
3
+ *
4
+ * Demonstrates basic usage of createPreviewRuntime with stats logging.
5
+ *
6
+ * Run with: npm run example:basic
7
+ *
8
+ * Note: This example is designed for browser environments.
9
+ * In Node.js, it will print the expected usage pattern.
10
+ */
11
+
12
+ console.log(`
13
+ ╔══════════════════════════════════════════════════════════════════════════╗
14
+ ║ @nexart/ui-renderer - Basic Preview Example ║
15
+ ╚══════════════════════════════════════════════════════════════════════════╝
16
+
17
+ This example shows how to use createPreviewRuntime in a browser environment.
18
+
19
+ BROWSER CODE:
20
+ ─────────────────────────────────────────────────────────────────────────────
21
+
22
+ import { createPreviewRuntime } from '@nexart/ui-renderer';
23
+
24
+ // Create a canvas element
25
+ const canvas = document.getElementById('preview-canvas');
26
+
27
+ // Create the preview runtime
28
+ const runtime = createPreviewRuntime({
29
+ canvas,
30
+ source: \`
31
+ function setup() {
32
+ noFill();
33
+ stroke(0);
34
+ }
35
+ function draw() {
36
+ background(246, 245, 242);
37
+ var count = int(map(VAR[0], 0, 100, 5, 30));
38
+ for (var i = 0; i < count; i++) {
39
+ var x = width / 2 + cos(t * TWO_PI + i * 0.5) * 300;
40
+ var y = height / 2 + sin(t * TWO_PI + i * 0.3) * 200;
41
+ ellipse(x, y, 50);
42
+ }
43
+ }
44
+ \`,
45
+ mode: 'loop',
46
+ width: 1950,
47
+ height: 2400,
48
+ seed: 12345,
49
+ vars: [50, 75, 25],
50
+ totalFrames: 120,
51
+ });
52
+
53
+ // Start the animation
54
+ runtime.startLoop();
55
+
56
+ // Log stats every second
57
+ setInterval(() => {
58
+ const stats = runtime.getPreviewStats();
59
+ console.log('Preview Stats:', {
60
+ mode: stats.mode,
61
+ scale: stats.scale.toFixed(2),
62
+ frames: stats.frames,
63
+ stride: stats.stride,
64
+ totalTimeMs: Math.round(stats.totalTimeMs),
65
+ budgetExceeded: stats.budgetExceeded ?? 'no',
66
+ });
67
+ }, 1000);
68
+
69
+ // Stop after 10 seconds
70
+ setTimeout(() => {
71
+ runtime.stopLoop();
72
+ console.log('Preview stopped');
73
+ }, 10000);
74
+
75
+ ─────────────────────────────────────────────────────────────────────────────
76
+
77
+ KEY POINTS:
78
+ - Use createPreviewRuntime (recommended) or createPreviewEngine
79
+ - mode: 'loop' for animations, 'static' for single frame
80
+ - Check getPreviewStats() to monitor budget and performance
81
+ - Preview is NOT canonical — use @nexart/codemode-sdk for minting
82
+ `);
83
+
84
+ // Demonstrate API shape (Node.js compatible)
85
+ import { SDK_VERSION, PREVIEW_BUDGET, CANVAS_LIMITS } from '../src/index';
86
+
87
+ console.log('SDK Configuration:');
88
+ console.log(' Version:', SDK_VERSION);
89
+ console.log(' FPS: Native RAF (~60 FPS)');
90
+ console.log(' Max Dimension:', CANVAS_LIMITS.MAX_DIMENSION + 'px');
91
+ console.log(' Max Frames:', PREVIEW_BUDGET.MAX_FRAMES);
92
+ console.log(' Max Time:', PREVIEW_BUDGET.MAX_TOTAL_TIME_MS / 1000 + 's');
@@ -0,0 +1,161 @@
1
+ /**
2
+ * @nexart/ui-renderer - Budget Demo Example
3
+ *
4
+ * Demonstrates budget exceed handling with callbacks and overlay.
5
+ *
6
+ * Run with: npm run example:budget
7
+ *
8
+ * Note: This example is designed for browser environments.
9
+ * In Node.js, it will print the expected usage pattern.
10
+ */
11
+
12
+ console.log(`
13
+ ╔══════════════════════════════════════════════════════════════════════════╗
14
+ ║ @nexart/ui-renderer - Budget Demo Example ║
15
+ ╚══════════════════════════════════════════════════════════════════════════╝
16
+
17
+ This example shows how to handle budget exceeded events.
18
+
19
+ BROWSER CODE (with 'stop' behavior):
20
+ ─────────────────────────────────────────────────────────────────────────────
21
+
22
+ import { createPreviewRuntime } from '@nexart/ui-renderer';
23
+
24
+ const canvas = document.getElementById('preview-canvas');
25
+
26
+ // Heavy sketch that will exceed budget quickly
27
+ const heavySketch = \`
28
+ function draw() {
29
+ background(30);
30
+ for (var i = 0; i < 10000; i++) {
31
+ var x = random(width);
32
+ var y = random(height);
33
+ stroke(random(255), random(255), random(255), 50);
34
+ point(x, y);
35
+ }
36
+ }
37
+ \`;
38
+
39
+ const runtime = createPreviewRuntime({
40
+ canvas,
41
+ source: heavySketch,
42
+ mode: 'loop',
43
+ width: 1950,
44
+ height: 2400,
45
+
46
+ // Budget configuration
47
+ maxFrames: 100, // Low frame limit for demo
48
+ maxTimeMs: 10000, // 10 second time limit
49
+ budgetBehavior: 'stop', // 'stop' or 'degrade'
50
+ showOverlay: true, // Show overlay when stopped
51
+
52
+ // Callback when budget is exceeded
53
+ onBudgetExceeded: (info) => {
54
+ console.log('⚠️ Budget exceeded!');
55
+ console.log(' Reason:', info.reason);
56
+ console.log(' Frames rendered:', info.framesRendered);
57
+ console.log(' Total time:', Math.round(info.totalTimeMs) + 'ms');
58
+ console.log(' Scale:', info.scale.toFixed(2));
59
+ console.log(' Stride:', info.stride);
60
+ },
61
+ });
62
+
63
+ runtime.startLoop();
64
+
65
+ ─────────────────────────────────────────────────────────────────────────────
66
+
67
+ BROWSER CODE (with 'degrade' behavior):
68
+ ─────────────────────────────────────────────────────────────────────────────
69
+
70
+ const runtime = createPreviewRuntime({
71
+ canvas,
72
+ source: heavySketch,
73
+ mode: 'loop',
74
+ width: 1950,
75
+ height: 2400,
76
+
77
+ budgetBehavior: 'degrade', // Continue running but skip frames
78
+ maxFrames: 100,
79
+
80
+ onBudgetExceeded: (info) => {
81
+ console.log('Budget exceeded, now skipping every 2nd frame');
82
+ // Preview continues but at reduced frame rate
83
+ },
84
+ });
85
+
86
+ ─────────────────────────────────────────────────────────────────────────────
87
+
88
+ CHECKING STATS:
89
+ ─────────────────────────────────────────────────────────────────────────────
90
+
91
+ const stats = runtime.getPreviewStats();
92
+
93
+ if (stats.budgetExceeded) {
94
+ console.log('Preview was stopped due to:', stats.budgetExceeded.reason);
95
+
96
+ // Options:
97
+ // 1. Reduce sketch complexity
98
+ // 2. Increase budget limits
99
+ // 3. Use @nexart/codemode-sdk for canonical execution
100
+ }
101
+
102
+ ─────────────────────────────────────────────────────────────────────────────
103
+
104
+ HANDOFF TO CANONICAL:
105
+ ─────────────────────────────────────────────────────────────────────────────
106
+
107
+ import { toCanonicalRequest } from '@nexart/ui-renderer';
108
+
109
+ const config = {
110
+ canvas,
111
+ source: sketchCode,
112
+ mode: 'loop',
113
+ width: 1950,
114
+ height: 2400,
115
+ seed: 12345,
116
+ vars: [50, 75, 25],
117
+ };
118
+
119
+ // Get canonical request for @nexart/codemode-sdk
120
+ const canonicalReq = toCanonicalRequest(config);
121
+ console.log('Canonical request:', canonicalReq);
122
+ // {
123
+ // seed: 12345,
124
+ // vars: [50, 75, 25],
125
+ // code: "...",
126
+ // settings: { width: 1950, height: 2400, mode: 'loop' },
127
+ // renderer: 'preview',
128
+ // uiRendererVersion: '0.9.0'
129
+ // }
130
+
131
+ // Pass to backend or use @nexart/codemode-sdk directly:
132
+ // import { createRuntime } from '@nexart/codemode-sdk';
133
+ // const runtime = createRuntime({ seed, vars, mode });
134
+
135
+ ─────────────────────────────────────────────────────────────────────────────
136
+ `);
137
+
138
+ // Demonstrate API shape (Node.js compatible)
139
+ import { SDK_VERSION, PREVIEW_BUDGET, toCanonicalRequest, type PreviewEngineConfig } from '../src/index';
140
+
141
+ console.log('Budget Configuration:');
142
+ console.log(' Max Frames:', PREVIEW_BUDGET.MAX_FRAMES);
143
+ console.log(' Max Time:', PREVIEW_BUDGET.MAX_TOTAL_TIME_MS / 1000 + 's');
144
+ console.log(' Degrade Stride:', PREVIEW_BUDGET.DEGRADE_STRIDE);
145
+
146
+ console.log('');
147
+ console.log('toCanonicalRequest example output:');
148
+
149
+ const mockConfig = {
150
+ canvas: null as any,
151
+ source: 'function draw() { circle(100, 100, 50); }',
152
+ mode: 'loop' as const,
153
+ width: 1950,
154
+ height: 2400,
155
+ seed: 12345,
156
+ vars: [50, 75, 25],
157
+ totalFrames: 120,
158
+ };
159
+
160
+ const canonical = toCanonicalRequest(mockConfig);
161
+ console.log(JSON.stringify(canonical, null, 2));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nexart/ui-renderer",
3
- "version": "0.8.7",
4
- "description": "Lightweight Preview Runtime for NexArt Protocol. Non-canonical, FPS-capped continuous animation (8 FPS, max 900px canvas).",
3
+ "version": "0.9.0",
4
+ "description": "Lightweight Preview Runtime for NexArt Protocol. Non-canonical, browser-first, with budget callbacks and observability for AI coding agents.",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "main": "./dist/index.js",
@@ -14,14 +14,20 @@
14
14
  }
15
15
  },
16
16
  "files": [
17
- "dist"
17
+ "dist",
18
+ "examples",
19
+ "README.md",
20
+ "CHANGELOG.md"
18
21
  ],
19
22
  "scripts": {
20
23
  "build": "tsc",
21
- "prepublishOnly": "npm run build"
24
+ "prepublishOnly": "npm run build",
25
+ "example:basic": "npx tsx examples/basic-preview.ts",
26
+ "example:budget": "npx tsx examples/budget-demo.ts",
27
+ "test": "npm run build && node --test dist/*.test.js 2>/dev/null || echo 'No tests yet'"
22
28
  },
23
29
  "dependencies": {
24
- "@nexart/codemode-sdk": "^1.4.0"
30
+ "@nexart/codemode-sdk": "^1.8.0"
25
31
  },
26
32
  "devDependencies": {
27
33
  "typescript": "^5.0.0"
@@ -34,7 +40,9 @@
34
40
  "declarative",
35
41
  "protocol",
36
42
  "authoring",
37
- "preview"
43
+ "preview",
44
+ "ai-agent",
45
+ "deterministic"
38
46
  ],
39
47
  "repository": {
40
48
  "type": "git",