@czap/core 0.1.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/LICENSE +21 -0
- package/README.md +19 -0
- package/dist/addressed-digest.d.ts +15 -0
- package/dist/addressed-digest.d.ts.map +1 -0
- package/dist/addressed-digest.js +35 -0
- package/dist/addressed-digest.js.map +1 -0
- package/dist/animation.d.ts +46 -0
- package/dist/animation.d.ts.map +1 -0
- package/dist/animation.js +70 -0
- package/dist/animation.js.map +1 -0
- package/dist/assembly.d.ts +25 -0
- package/dist/assembly.d.ts.map +1 -0
- package/dist/assembly.js +58 -0
- package/dist/assembly.js.map +1 -0
- package/dist/av-bridge.d.ts +74 -0
- package/dist/av-bridge.d.ts.map +1 -0
- package/dist/av-bridge.js +107 -0
- package/dist/av-bridge.js.map +1 -0
- package/dist/av-renderer.d.ts +56 -0
- package/dist/av-renderer.d.ts.map +1 -0
- package/dist/av-renderer.js +65 -0
- package/dist/av-renderer.js.map +1 -0
- package/dist/blend.d.ts +61 -0
- package/dist/blend.d.ts.map +1 -0
- package/dist/blend.js +100 -0
- package/dist/blend.js.map +1 -0
- package/dist/boundary.d.ts +154 -0
- package/dist/boundary.d.ts.map +1 -0
- package/dist/boundary.js +269 -0
- package/dist/boundary.js.map +1 -0
- package/dist/brands.d.ts +63 -0
- package/dist/brands.d.ts.map +1 -0
- package/dist/brands.js +31 -0
- package/dist/brands.js.map +1 -0
- package/dist/caps.d.ts +49 -0
- package/dist/caps.d.ts.map +1 -0
- package/dist/caps.js +73 -0
- package/dist/caps.js.map +1 -0
- package/dist/capsule.d.ts +77 -0
- package/dist/capsule.d.ts.map +1 -0
- package/dist/capsule.js +18 -0
- package/dist/capsule.js.map +1 -0
- package/dist/capsules/boundary-evaluate.d.ts +28 -0
- package/dist/capsules/boundary-evaluate.d.ts.map +1 -0
- package/dist/capsules/boundary-evaluate.js +117 -0
- package/dist/capsules/boundary-evaluate.js.map +1 -0
- package/dist/capsules/canonical-cbor.d.ts +13 -0
- package/dist/capsules/canonical-cbor.d.ts.map +1 -0
- package/dist/capsules/canonical-cbor.js +60 -0
- package/dist/capsules/canonical-cbor.js.map +1 -0
- package/dist/capsules/token-buffer.d.ts +24 -0
- package/dist/capsules/token-buffer.d.ts.map +1 -0
- package/dist/capsules/token-buffer.js +53 -0
- package/dist/capsules/token-buffer.js.map +1 -0
- package/dist/capture.d.ts +40 -0
- package/dist/capture.d.ts.map +1 -0
- package/dist/capture.js +10 -0
- package/dist/capture.js.map +1 -0
- package/dist/cbor.d.ts +33 -0
- package/dist/cbor.d.ts.map +1 -0
- package/dist/cbor.js +179 -0
- package/dist/cbor.js.map +1 -0
- package/dist/cell.d.ts +53 -0
- package/dist/cell.d.ts.map +1 -0
- package/dist/cell.js +83 -0
- package/dist/cell.js.map +1 -0
- package/dist/codec.d.ts +30 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +25 -0
- package/dist/codec.js.map +1 -0
- package/dist/component.d.ts +52 -0
- package/dist/component.d.ts.map +1 -0
- package/dist/component.js +44 -0
- package/dist/component.js.map +1 -0
- package/dist/composable.d.ts +76 -0
- package/dist/composable.d.ts.map +1 -0
- package/dist/composable.js +221 -0
- package/dist/composable.js.map +1 -0
- package/dist/compositor-pool.d.ts +74 -0
- package/dist/compositor-pool.d.ts.map +1 -0
- package/dist/compositor-pool.js +119 -0
- package/dist/compositor-pool.js.map +1 -0
- package/dist/compositor.d.ts +90 -0
- package/dist/compositor.d.ts.map +1 -0
- package/dist/compositor.js +278 -0
- package/dist/compositor.js.map +1 -0
- package/dist/config.d.ts +72 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +97 -0
- package/dist/config.js.map +1 -0
- package/dist/dag.d.ts +251 -0
- package/dist/dag.d.ts.map +1 -0
- package/dist/dag.js +450 -0
- package/dist/dag.js.map +1 -0
- package/dist/defaults.d.ts +45 -0
- package/dist/defaults.d.ts.map +1 -0
- package/dist/defaults.js +45 -0
- package/dist/defaults.js.map +1 -0
- package/dist/derived.d.ts +34 -0
- package/dist/derived.d.ts.map +1 -0
- package/dist/derived.js +101 -0
- package/dist/derived.js.map +1 -0
- package/dist/diagnostics.d.ts +77 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +122 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/dirty.d.ts +55 -0
- package/dist/dirty.d.ts.map +1 -0
- package/dist/dirty.js +80 -0
- package/dist/dirty.js.map +1 -0
- package/dist/easing.d.ts +55 -0
- package/dist/easing.d.ts.map +1 -0
- package/dist/easing.js +291 -0
- package/dist/easing.js.map +1 -0
- package/dist/ecs.d.ts +105 -0
- package/dist/ecs.d.ts.map +1 -0
- package/dist/ecs.js +245 -0
- package/dist/ecs.js.map +1 -0
- package/dist/fnv.d.ts +14 -0
- package/dist/fnv.d.ts.map +1 -0
- package/dist/fnv.js +28 -0
- package/dist/fnv.js.map +1 -0
- package/dist/frame-budget.d.ts +73 -0
- package/dist/frame-budget.d.ts.map +1 -0
- package/dist/frame-budget.js +114 -0
- package/dist/frame-budget.js.map +1 -0
- package/dist/gen-frame.d.ts +102 -0
- package/dist/gen-frame.d.ts.map +1 -0
- package/dist/gen-frame.js +121 -0
- package/dist/gen-frame.js.map +1 -0
- package/dist/harness/arbitrary-from-schema.d.ts +28 -0
- package/dist/harness/arbitrary-from-schema.d.ts.map +1 -0
- package/dist/harness/arbitrary-from-schema.js +262 -0
- package/dist/harness/arbitrary-from-schema.js.map +1 -0
- package/dist/harness/cached-projection.d.ts +19 -0
- package/dist/harness/cached-projection.d.ts.map +1 -0
- package/dist/harness/cached-projection.js +39 -0
- package/dist/harness/cached-projection.js.map +1 -0
- package/dist/harness/index.d.ts +16 -0
- package/dist/harness/index.d.ts.map +1 -0
- package/dist/harness/index.js +15 -0
- package/dist/harness/index.js.map +1 -0
- package/dist/harness/policy-gate.d.ts +18 -0
- package/dist/harness/policy-gate.d.ts.map +1 -0
- package/dist/harness/policy-gate.js +46 -0
- package/dist/harness/policy-gate.js.map +1 -0
- package/dist/harness/pure-transform.d.ts +42 -0
- package/dist/harness/pure-transform.d.ts.map +1 -0
- package/dist/harness/pure-transform.js +76 -0
- package/dist/harness/pure-transform.js.map +1 -0
- package/dist/harness/receipted-mutation.d.ts +23 -0
- package/dist/harness/receipted-mutation.d.ts.map +1 -0
- package/dist/harness/receipted-mutation.js +52 -0
- package/dist/harness/receipted-mutation.js.map +1 -0
- package/dist/harness/scene-composition.d.ts +19 -0
- package/dist/harness/scene-composition.d.ts.map +1 -0
- package/dist/harness/scene-composition.js +47 -0
- package/dist/harness/scene-composition.js.map +1 -0
- package/dist/harness/site-adapter.d.ts +18 -0
- package/dist/harness/site-adapter.d.ts.map +1 -0
- package/dist/harness/site-adapter.js +38 -0
- package/dist/harness/site-adapter.js.map +1 -0
- package/dist/harness/state-machine.d.ts +19 -0
- package/dist/harness/state-machine.d.ts.map +1 -0
- package/dist/harness/state-machine.js +44 -0
- package/dist/harness/state-machine.js.map +1 -0
- package/dist/hlc.d.ts +99 -0
- package/dist/hlc.d.ts.map +1 -0
- package/dist/hlc.js +219 -0
- package/dist/hlc.js.map +1 -0
- package/dist/index.d.ts +104 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +137 -0
- package/dist/index.js.map +1 -0
- package/dist/interpolate.d.ts +14 -0
- package/dist/interpolate.d.ts.map +1 -0
- package/dist/interpolate.js +31 -0
- package/dist/interpolate.js.map +1 -0
- package/dist/live-cell.d.ts +46 -0
- package/dist/live-cell.d.ts.map +1 -0
- package/dist/live-cell.js +154 -0
- package/dist/live-cell.js.map +1 -0
- package/dist/op.d.ts +58 -0
- package/dist/op.d.ts.map +1 -0
- package/dist/op.js +171 -0
- package/dist/op.js.map +1 -0
- package/dist/plan.d.ts +195 -0
- package/dist/plan.d.ts.map +1 -0
- package/dist/plan.js +211 -0
- package/dist/plan.js.map +1 -0
- package/dist/protocol.d.ts +33 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +10 -0
- package/dist/protocol.js.map +1 -0
- package/dist/quantizer-types.d.ts +28 -0
- package/dist/quantizer-types.d.ts.map +1 -0
- package/dist/quantizer-types.js +9 -0
- package/dist/quantizer-types.js.map +1 -0
- package/dist/receipt.d.ts +294 -0
- package/dist/receipt.d.ts.map +1 -0
- package/dist/receipt.js +352 -0
- package/dist/receipt.js.map +1 -0
- package/dist/runtime-coordinator.d.ts +75 -0
- package/dist/runtime-coordinator.d.ts.map +1 -0
- package/dist/runtime-coordinator.js +149 -0
- package/dist/runtime-coordinator.js.map +1 -0
- package/dist/scheduler.d.ts +58 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +109 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/ship-capsule.d.ts +54 -0
- package/dist/ship-capsule.d.ts.map +1 -0
- package/dist/ship-capsule.js +142 -0
- package/dist/ship-capsule.js.map +1 -0
- package/dist/ship-manifest.d.ts +45 -0
- package/dist/ship-manifest.d.ts.map +1 -0
- package/dist/ship-manifest.js +175 -0
- package/dist/ship-manifest.js.map +1 -0
- package/dist/signal.d.ts +149 -0
- package/dist/signal.d.ts.map +1 -0
- package/dist/signal.js +277 -0
- package/dist/signal.js.map +1 -0
- package/dist/speculative.d.ts +67 -0
- package/dist/speculative.d.ts.map +1 -0
- package/dist/speculative.js +139 -0
- package/dist/speculative.js.map +1 -0
- package/dist/store.d.ts +39 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +42 -0
- package/dist/store.js.map +1 -0
- package/dist/style.d.ts +119 -0
- package/dist/style.d.ts.map +1 -0
- package/dist/style.js +168 -0
- package/dist/style.js.map +1 -0
- package/dist/testing.d.ts +14 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +14 -0
- package/dist/testing.js.map +1 -0
- package/dist/theme.d.ts +78 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +109 -0
- package/dist/theme.js.map +1 -0
- package/dist/timeline.d.ts +45 -0
- package/dist/timeline.d.ts.map +1 -0
- package/dist/timeline.js +101 -0
- package/dist/timeline.js.map +1 -0
- package/dist/token-buffer.d.ts +43 -0
- package/dist/token-buffer.d.ts.map +1 -0
- package/dist/token-buffer.js +112 -0
- package/dist/token-buffer.js.map +1 -0
- package/dist/token.d.ts +107 -0
- package/dist/token.d.ts.map +1 -0
- package/dist/token.js +143 -0
- package/dist/token.js.map +1 -0
- package/dist/tuple.d.ts +16 -0
- package/dist/tuple.d.ts.map +1 -0
- package/dist/tuple.js +16 -0
- package/dist/tuple.js.map +1 -0
- package/dist/type-utils.d.ts +41 -0
- package/dist/type-utils.d.ts.map +1 -0
- package/dist/type-utils.js +10 -0
- package/dist/type-utils.js.map +1 -0
- package/dist/typed-ref.d.ts +50 -0
- package/dist/typed-ref.d.ts.map +1 -0
- package/dist/typed-ref.js +59 -0
- package/dist/typed-ref.js.map +1 -0
- package/dist/ui-quality.d.ts +50 -0
- package/dist/ui-quality.d.ts.map +1 -0
- package/dist/ui-quality.js +64 -0
- package/dist/ui-quality.js.map +1 -0
- package/dist/validation-error.d.ts +25 -0
- package/dist/validation-error.d.ts.map +1 -0
- package/dist/validation-error.js +32 -0
- package/dist/validation-error.js.map +1 -0
- package/dist/vector-clock.d.ts +46 -0
- package/dist/vector-clock.d.ts.map +1 -0
- package/dist/vector-clock.js +91 -0
- package/dist/vector-clock.js.map +1 -0
- package/dist/video.d.ts +62 -0
- package/dist/video.d.ts.map +1 -0
- package/dist/video.js +59 -0
- package/dist/video.js.map +1 -0
- package/dist/wasm-dispatch.d.ts +52 -0
- package/dist/wasm-dispatch.d.ts.map +1 -0
- package/dist/wasm-dispatch.js +204 -0
- package/dist/wasm-dispatch.js.map +1 -0
- package/dist/wasm-fallback.d.ts +19 -0
- package/dist/wasm-fallback.d.ts.map +1 -0
- package/dist/wasm-fallback.js +93 -0
- package/dist/wasm-fallback.js.map +1 -0
- package/dist/wire.d.ts +49 -0
- package/dist/wire.d.ts.map +1 -0
- package/dist/wire.js +201 -0
- package/dist/wire.js.map +1 -0
- package/dist/zap.d.ts +42 -0
- package/dist/zap.d.ts.map +1 -0
- package/dist/zap.js +172 -0
- package/dist/zap.js.map +1 -0
- package/package.json +71 -0
- package/src/addressed-digest.ts +48 -0
- package/src/animation.ts +103 -0
- package/src/assembly.ts +76 -0
- package/src/av-bridge.ts +161 -0
- package/src/av-renderer.ts +118 -0
- package/src/blend.ts +135 -0
- package/src/boundary.ts +363 -0
- package/src/brands.ts +86 -0
- package/src/caps.ts +100 -0
- package/src/capsule.ts +95 -0
- package/src/capsules/boundary-evaluate.ts +128 -0
- package/src/capsules/canonical-cbor.ts +60 -0
- package/src/capsules/token-buffer.ts +57 -0
- package/src/capture.ts +48 -0
- package/src/cbor.ts +199 -0
- package/src/cell.ts +130 -0
- package/src/codec.ts +39 -0
- package/src/component.ts +102 -0
- package/src/composable.ts +328 -0
- package/src/compositor-pool.ts +162 -0
- package/src/compositor.ts +387 -0
- package/src/config.ts +157 -0
- package/src/dag.ts +527 -0
- package/src/defaults.ts +60 -0
- package/src/derived.ts +164 -0
- package/src/diagnostics.ts +186 -0
- package/src/dirty.ts +101 -0
- package/src/easing.ts +334 -0
- package/src/ecs.ts +382 -0
- package/src/fnv.ts +31 -0
- package/src/frame-budget.ts +149 -0
- package/src/gen-frame.ts +229 -0
- package/src/harness/arbitrary-from-schema.ts +270 -0
- package/src/harness/cached-projection.ts +46 -0
- package/src/harness/index.ts +16 -0
- package/src/harness/policy-gate.ts +51 -0
- package/src/harness/pure-transform.ts +121 -0
- package/src/harness/receipted-mutation.ts +59 -0
- package/src/harness/scene-composition.ts +54 -0
- package/src/harness/site-adapter.ts +43 -0
- package/src/harness/state-machine.ts +49 -0
- package/src/hlc.ts +238 -0
- package/src/index.ts +274 -0
- package/src/interpolate.ts +37 -0
- package/src/live-cell.ts +199 -0
- package/src/op.ts +233 -0
- package/src/plan.ts +317 -0
- package/src/protocol.ts +49 -0
- package/src/quantizer-types.ts +29 -0
- package/src/receipt.ts +444 -0
- package/src/runtime-coordinator.ts +230 -0
- package/src/scheduler.ts +161 -0
- package/src/ship-capsule.ts +191 -0
- package/src/signal.ts +345 -0
- package/src/speculative.ts +186 -0
- package/src/store.ts +77 -0
- package/src/style.ts +249 -0
- package/src/testing.ts +14 -0
- package/src/theme.ts +153 -0
- package/src/timeline.ts +146 -0
- package/src/token-buffer.ts +151 -0
- package/src/token.ts +197 -0
- package/src/tuple.ts +19 -0
- package/src/type-utils.ts +48 -0
- package/src/typed-ref.ts +79 -0
- package/src/ui-quality.ts +105 -0
- package/src/validation-error.ts +34 -0
- package/src/vector-clock.ts +111 -0
- package/src/video.ts +106 -0
- package/src/wasm-dispatch.ts +300 -0
- package/src/wasm-fallback.ts +102 -0
- package/src/wire.ts +274 -0
- package/src/zap.ts +241 -0
package/dist/ecs.js
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ECS -- Entity, Part, System, World.
|
|
3
|
+
*
|
|
4
|
+
* Composition over inheritance. Entities are bags of parts,
|
|
5
|
+
* systems operate on entities matching part queries.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import { Effect, Ref } from 'effect';
|
|
10
|
+
/** Brand an arbitrary string as an `EntityId`. Sanctioned single-site cast. */
|
|
11
|
+
export const EntityId = (value) => value;
|
|
12
|
+
import { fnv1a } from './fnv.js';
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// Dense Component Storage -- Float64Array-backed, zero-allocation iteration
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
const DENSE_SENTINEL = -Infinity;
|
|
17
|
+
function _makeDenseStore(name, capacity) {
|
|
18
|
+
const entityToIndex = new Map();
|
|
19
|
+
const indexToEntity = [];
|
|
20
|
+
const data = new Float64Array(capacity);
|
|
21
|
+
data.fill(DENSE_SENTINEL);
|
|
22
|
+
const store = {
|
|
23
|
+
name,
|
|
24
|
+
capacity,
|
|
25
|
+
_dense: true,
|
|
26
|
+
entityToIndex,
|
|
27
|
+
indexToEntity,
|
|
28
|
+
data,
|
|
29
|
+
count: 0,
|
|
30
|
+
get(entityId) {
|
|
31
|
+
const idx = entityToIndex.get(entityId);
|
|
32
|
+
if (idx === undefined)
|
|
33
|
+
return undefined;
|
|
34
|
+
return data[idx];
|
|
35
|
+
},
|
|
36
|
+
set(entityId, value) {
|
|
37
|
+
let idx = entityToIndex.get(entityId);
|
|
38
|
+
if (idx !== undefined) {
|
|
39
|
+
data[idx] = value;
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (store.count >= capacity) {
|
|
43
|
+
throw new RangeError(`Dense store "${name}" at capacity (${capacity}). Cannot add entity ${entityId}.`);
|
|
44
|
+
}
|
|
45
|
+
idx = store.count;
|
|
46
|
+
entityToIndex.set(entityId, idx);
|
|
47
|
+
indexToEntity[idx] = entityId;
|
|
48
|
+
data[idx] = value;
|
|
49
|
+
store.count++;
|
|
50
|
+
},
|
|
51
|
+
has(entityId) {
|
|
52
|
+
return entityToIndex.has(entityId);
|
|
53
|
+
},
|
|
54
|
+
delete(entityId) {
|
|
55
|
+
const idx = entityToIndex.get(entityId);
|
|
56
|
+
if (idx === undefined)
|
|
57
|
+
return false;
|
|
58
|
+
const lastIdx = store.count - 1;
|
|
59
|
+
if (idx !== lastIdx) {
|
|
60
|
+
// Swap-remove: move last element into the vacated slot
|
|
61
|
+
const lastEntity = indexToEntity[lastIdx];
|
|
62
|
+
data[idx] = data[lastIdx];
|
|
63
|
+
indexToEntity[idx] = lastEntity;
|
|
64
|
+
entityToIndex.set(lastEntity, idx);
|
|
65
|
+
}
|
|
66
|
+
data[lastIdx] = DENSE_SENTINEL;
|
|
67
|
+
indexToEntity.length = lastIdx;
|
|
68
|
+
entityToIndex.delete(entityId);
|
|
69
|
+
store.count--;
|
|
70
|
+
return true;
|
|
71
|
+
},
|
|
72
|
+
reset() {
|
|
73
|
+
entityToIndex.clear();
|
|
74
|
+
indexToEntity.length = 0;
|
|
75
|
+
data.fill(DENSE_SENTINEL);
|
|
76
|
+
store.count = 0;
|
|
77
|
+
},
|
|
78
|
+
view() {
|
|
79
|
+
return data.subarray(0, store.count);
|
|
80
|
+
},
|
|
81
|
+
entities() {
|
|
82
|
+
return indexToEntity;
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
return store;
|
|
86
|
+
}
|
|
87
|
+
function _makeWorld() {
|
|
88
|
+
return Effect.gen(function* () {
|
|
89
|
+
const entitiesRef = yield* Ref.make(new Map());
|
|
90
|
+
const systemsRef = yield* Ref.make([]);
|
|
91
|
+
const denseStoresRef = yield* Ref.make(new Map());
|
|
92
|
+
let nextEntitySeq = 0;
|
|
93
|
+
const world = {
|
|
94
|
+
spawn(components) {
|
|
95
|
+
return Effect.gen(function* () {
|
|
96
|
+
const seq = nextEntitySeq++;
|
|
97
|
+
const id = EntityId(`entity-${seq}:${fnv1a(JSON.stringify(components ?? {}))}`);
|
|
98
|
+
const componentMap = new Map();
|
|
99
|
+
if (components) {
|
|
100
|
+
for (const [name, value] of Object.entries(components)) {
|
|
101
|
+
componentMap.set(name, value);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
yield* Ref.update(entitiesRef, (m) => {
|
|
105
|
+
const next = new Map(m);
|
|
106
|
+
next.set(id, componentMap);
|
|
107
|
+
return next;
|
|
108
|
+
});
|
|
109
|
+
return id;
|
|
110
|
+
});
|
|
111
|
+
},
|
|
112
|
+
despawn(id) {
|
|
113
|
+
return Effect.gen(function* () {
|
|
114
|
+
// Remove from entity map
|
|
115
|
+
yield* Ref.update(entitiesRef, (m) => {
|
|
116
|
+
const next = new Map(m);
|
|
117
|
+
next.delete(id);
|
|
118
|
+
return next;
|
|
119
|
+
});
|
|
120
|
+
// Remove from all dense stores
|
|
121
|
+
const denseStores = yield* Ref.get(denseStoresRef);
|
|
122
|
+
for (const store of denseStores.values()) {
|
|
123
|
+
store.delete(id);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
},
|
|
127
|
+
addComponent(id, component, value) {
|
|
128
|
+
return Ref.update(entitiesRef, (m) => {
|
|
129
|
+
const next = new Map(m);
|
|
130
|
+
const entity = next.get(id);
|
|
131
|
+
if (entity) {
|
|
132
|
+
const updated = new Map(entity);
|
|
133
|
+
updated.set(component.name, value);
|
|
134
|
+
next.set(id, updated);
|
|
135
|
+
}
|
|
136
|
+
return next;
|
|
137
|
+
});
|
|
138
|
+
},
|
|
139
|
+
setComponent(id, name, value) {
|
|
140
|
+
return Ref.update(entitiesRef, (m) => {
|
|
141
|
+
const next = new Map(m);
|
|
142
|
+
const entity = next.get(id);
|
|
143
|
+
if (entity) {
|
|
144
|
+
const updated = new Map(entity);
|
|
145
|
+
updated.set(name, value);
|
|
146
|
+
next.set(id, updated);
|
|
147
|
+
}
|
|
148
|
+
return next;
|
|
149
|
+
});
|
|
150
|
+
},
|
|
151
|
+
removeComponent(id, name) {
|
|
152
|
+
return Ref.update(entitiesRef, (m) => {
|
|
153
|
+
const next = new Map(m);
|
|
154
|
+
const entity = next.get(id);
|
|
155
|
+
if (entity) {
|
|
156
|
+
const updated = new Map(entity);
|
|
157
|
+
updated.delete(name);
|
|
158
|
+
next.set(id, updated);
|
|
159
|
+
}
|
|
160
|
+
return next;
|
|
161
|
+
});
|
|
162
|
+
},
|
|
163
|
+
query(...componentNames) {
|
|
164
|
+
return Effect.gen(function* () {
|
|
165
|
+
const entities = yield* Ref.get(entitiesRef);
|
|
166
|
+
const results = [];
|
|
167
|
+
for (const [id, components] of entities) {
|
|
168
|
+
const hasAll = componentNames.every((name) => components.has(name));
|
|
169
|
+
if (hasAll) {
|
|
170
|
+
const componentsCopy = new Map(components);
|
|
171
|
+
// Spread component values as direct properties so systems can access
|
|
172
|
+
// computed output fields (e.g. `_opacity`, `_phase`, `_blend`) directly.
|
|
173
|
+
const entity = Object.assign({ id, components: componentsCopy }, Object.fromEntries(componentsCopy));
|
|
174
|
+
results.push(entity);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return results;
|
|
178
|
+
});
|
|
179
|
+
},
|
|
180
|
+
addSystem(system) {
|
|
181
|
+
return Ref.update(systemsRef, (systems) => [...systems, system]);
|
|
182
|
+
},
|
|
183
|
+
addDenseStore(store) {
|
|
184
|
+
return Ref.update(denseStoresRef, (m) => {
|
|
185
|
+
const next = new Map(m);
|
|
186
|
+
next.set(store.name, store);
|
|
187
|
+
return next;
|
|
188
|
+
});
|
|
189
|
+
},
|
|
190
|
+
tick() {
|
|
191
|
+
return Effect.gen(function* () {
|
|
192
|
+
const systems = yield* Ref.get(systemsRef);
|
|
193
|
+
const denseStores = yield* Ref.get(denseStoresRef);
|
|
194
|
+
for (const system of systems) {
|
|
195
|
+
if (isDenseSystem(system)) {
|
|
196
|
+
// Dense path: collect the stores this system queries
|
|
197
|
+
const queriedStores = new Map();
|
|
198
|
+
for (const name of system.query) {
|
|
199
|
+
const store = denseStores.get(name);
|
|
200
|
+
if (store)
|
|
201
|
+
queriedStores.set(name, store);
|
|
202
|
+
}
|
|
203
|
+
// Only execute if all queried stores exist
|
|
204
|
+
if (queriedStores.size === system.query.length) {
|
|
205
|
+
yield* system.execute(queriedStores);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
// Regular path: entity-component query
|
|
210
|
+
const matched = yield* world.query(...system.query);
|
|
211
|
+
yield* system.execute(matched, world);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
return world;
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
function isDenseSystem(system) {
|
|
221
|
+
return '_denseSystem' in system && system._denseSystem === true;
|
|
222
|
+
}
|
|
223
|
+
// ---------------------------------------------------------------------------
|
|
224
|
+
// Part namespace -- factories and types
|
|
225
|
+
// ---------------------------------------------------------------------------
|
|
226
|
+
function _makeDensePart(name, capacity) {
|
|
227
|
+
return _makeDenseStore(name, capacity);
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Part namespace — factories for ECS component stores.
|
|
231
|
+
*
|
|
232
|
+
* Currently exposes the dense `Float64Array`-backed store used for hot-path
|
|
233
|
+
* numeric state; sparse/object-valued parts are registered ad-hoc via
|
|
234
|
+
* {@link World}.`addComponent`.
|
|
235
|
+
*/
|
|
236
|
+
export const Part = {
|
|
237
|
+
/** Allocate a dense component store with fixed capacity. */
|
|
238
|
+
dense: _makeDensePart,
|
|
239
|
+
};
|
|
240
|
+
/** World namespace — construct the ECS world that ticks systems over entities. */
|
|
241
|
+
export const World = {
|
|
242
|
+
/** Scoped Effect that produces a fresh ECS {@link World.Shape}. */
|
|
243
|
+
make: _makeWorld,
|
|
244
|
+
};
|
|
245
|
+
//# sourceMappingURL=ecs.js.map
|
package/dist/ecs.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ecs.js","sourceRoot":"","sources":["../src/ecs.ts"],"names":[],"mappings":"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"}
|
package/dist/fnv.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FNV-1a hash utility for content addressing.
|
|
3
|
+
*
|
|
4
|
+
* Shared implementation used by Boundary, Token, Style, Theme, Component,
|
|
5
|
+
* and GenFrame modules. Produces `fnv1a:XXXXXXXX` ContentAddress values.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import type { ContentAddress } from './brands.js';
|
|
10
|
+
/** FNV-1a hash of a string, returned as a ContentAddress. */
|
|
11
|
+
export declare function fnv1a(str: string): ContentAddress;
|
|
12
|
+
/** FNV-1a hash of raw bytes, returned as a ContentAddress. */
|
|
13
|
+
export declare function fnv1aBytes(bytes: Uint8Array): ContentAddress;
|
|
14
|
+
//# sourceMappingURL=fnv.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fnv.d.ts","sourceRoot":"","sources":["../src/fnv.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlD,6DAA6D;AAC7D,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CAOjD;AAED,8DAA8D;AAC9D,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,cAAc,CAO5D"}
|
package/dist/fnv.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FNV-1a hash utility for content addressing.
|
|
3
|
+
*
|
|
4
|
+
* Shared implementation used by Boundary, Token, Style, Theme, Component,
|
|
5
|
+
* and GenFrame modules. Produces `fnv1a:XXXXXXXX` ContentAddress values.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import { ContentAddress as mkContentAddress } from './brands.js';
|
|
10
|
+
/** FNV-1a hash of a string, returned as a ContentAddress. */
|
|
11
|
+
export function fnv1a(str) {
|
|
12
|
+
let h = 0x811c9dc5;
|
|
13
|
+
for (let i = 0; i < str.length; i++) {
|
|
14
|
+
h ^= str.charCodeAt(i);
|
|
15
|
+
h = Math.imul(h, 0x01000193);
|
|
16
|
+
}
|
|
17
|
+
return mkContentAddress(`fnv1a:${(h >>> 0).toString(16).padStart(8, '0')}`);
|
|
18
|
+
}
|
|
19
|
+
/** FNV-1a hash of raw bytes, returned as a ContentAddress. */
|
|
20
|
+
export function fnv1aBytes(bytes) {
|
|
21
|
+
let h = 0x811c9dc5;
|
|
22
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
23
|
+
h ^= bytes[i];
|
|
24
|
+
h = Math.imul(h, 0x01000193);
|
|
25
|
+
}
|
|
26
|
+
return mkContentAddress(`fnv1a:${(h >>> 0).toString(16).padStart(8, '0')}`);
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=fnv.js.map
|
package/dist/fnv.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fnv.js","sourceRoot":"","sources":["../src/fnv.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,cAAc,IAAI,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEjE,6DAA6D;AAC7D,MAAM,UAAU,KAAK,CAAC,GAAW;IAC/B,IAAI,CAAC,GAAG,UAAU,CAAC;IACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACvB,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,gBAAgB,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;AAC9E,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,UAAU,CAAC,KAAiB;IAC1C,IAAI,CAAC,GAAG,UAAU,CAAC;IACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAE,CAAC;QACf,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,gBAAgB,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;AAC9E,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FrameBudget -- rAF priority lanes for frame budget management.
|
|
3
|
+
*
|
|
4
|
+
* Tracks remaining frame budget per animation frame and
|
|
5
|
+
* schedules work by priority: `critical > high > low > idle`.
|
|
6
|
+
*
|
|
7
|
+
* Hot path methods (remaining, canRun, scheduleSync) are plain JS.
|
|
8
|
+
* Effect is used only for resource lifecycle (rAF cleanup) and
|
|
9
|
+
* backwards-compatible schedule() wrapper.
|
|
10
|
+
*
|
|
11
|
+
* @module
|
|
12
|
+
*/
|
|
13
|
+
import type { Scope } from 'effect';
|
|
14
|
+
import { Effect } from 'effect';
|
|
15
|
+
/**
|
|
16
|
+
* Frame-budget priority lane in descending urgency. `critical` always runs;
|
|
17
|
+
* `high` / `low` / `idle` gate based on the milliseconds remaining in the
|
|
18
|
+
* current frame.
|
|
19
|
+
*/
|
|
20
|
+
export type Priority = 'critical' | 'high' | 'low' | 'idle';
|
|
21
|
+
interface FrameBudgetShape {
|
|
22
|
+
remaining(): number;
|
|
23
|
+
canRun(priority: Priority): boolean;
|
|
24
|
+
/** Synchronous scheduler for hot paths — no Effect overhead. */
|
|
25
|
+
scheduleSync<A>(priority: Priority, task: () => A): A | null;
|
|
26
|
+
schedule<A>(priority: Priority, task: Effect.Effect<A>): Effect.Effect<A | null>;
|
|
27
|
+
readonly fps: Effect.Effect<number>;
|
|
28
|
+
/** Synchronous FPS accessor for hot paths. */
|
|
29
|
+
readonly fpsSync: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Creates a FrameBudget tracker tied to rAF, with priority-based scheduling.
|
|
33
|
+
* Critical tasks always run; lower priorities are deferred if budget is exhausted.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* const program = Effect.scoped(Effect.gen(function* () {
|
|
38
|
+
* const budget = yield* FrameBudget.make({ targetFps: 60 });
|
|
39
|
+
* const remaining = budget.remaining(); // ms left in this frame
|
|
40
|
+
* const canAnimate = budget.canRun('high'); // true if enough budget
|
|
41
|
+
* const result = yield* budget.schedule('low', Effect.succeed('done'));
|
|
42
|
+
* // result is 'done' if budget permits, null otherwise
|
|
43
|
+
* }));
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
declare function _make(config?: {
|
|
47
|
+
targetFps?: number;
|
|
48
|
+
}): Effect.Effect<FrameBudgetShape, never, Scope.Scope>;
|
|
49
|
+
/**
|
|
50
|
+
* FrameBudget -- rAF-based frame budget manager with priority lanes.
|
|
51
|
+
* Tracks remaining time per animation frame and gates work by priority:
|
|
52
|
+
* `critical` (always runs) `> high > low > idle`.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* const program = Effect.scoped(Effect.gen(function* () {
|
|
57
|
+
* const budget = yield* FrameBudget.make({ targetFps: 60 });
|
|
58
|
+
* if (budget.canRun('high')) {
|
|
59
|
+
* yield* budget.schedule('high', Effect.succeed('rendered'));
|
|
60
|
+
* }
|
|
61
|
+
* const fps = yield* budget.fps; // current measured FPS
|
|
62
|
+
* }));
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export declare const FrameBudget: {
|
|
66
|
+
make: typeof _make;
|
|
67
|
+
};
|
|
68
|
+
export declare namespace FrameBudget {
|
|
69
|
+
/** Structural shape of a {@link FrameBudget} instance — `canRun`, `schedule`, `remaining`, `fps`. */
|
|
70
|
+
type Shape = FrameBudgetShape;
|
|
71
|
+
}
|
|
72
|
+
export {};
|
|
73
|
+
//# sourceMappingURL=frame-budget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame-budget.d.ts","sourceRoot":"","sources":["../src/frame-budget.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGhC;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;AAU5D,UAAU,gBAAgB;IACxB,SAAS,IAAI,MAAM,CAAC;IACpB,MAAM,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC;IACpC,gEAAgE;IAChE,YAAY,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IAC7D,QAAQ,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACjF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACpC,8CAA8C;IAC9C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;;;;;;GAcG;AACH,iBAAS,KAAK,CAAC,MAAM,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAmEnG;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,WAAW;;CAAkB,CAAC;AAE3C,MAAM,CAAC,OAAO,WAAW,WAAW,CAAC;IACnC,qGAAqG;IACrG,KAAY,KAAK,GAAG,gBAAgB,CAAC;CACtC"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FrameBudget -- rAF priority lanes for frame budget management.
|
|
3
|
+
*
|
|
4
|
+
* Tracks remaining frame budget per animation frame and
|
|
5
|
+
* schedules work by priority: `critical > high > low > idle`.
|
|
6
|
+
*
|
|
7
|
+
* Hot path methods (remaining, canRun, scheduleSync) are plain JS.
|
|
8
|
+
* Effect is used only for resource lifecycle (rAF cleanup) and
|
|
9
|
+
* backwards-compatible schedule() wrapper.
|
|
10
|
+
*
|
|
11
|
+
* @module
|
|
12
|
+
*/
|
|
13
|
+
import { Effect } from 'effect';
|
|
14
|
+
import { DEFAULT_TARGET_FPS, MS_PER_SEC } from './defaults.js';
|
|
15
|
+
// ms budget per priority lane within a 16ms frame (critical=0 runs first, high=2ms, low=6ms, idle=12ms)
|
|
16
|
+
const PRIORITY_THRESHOLDS = {
|
|
17
|
+
critical: 0,
|
|
18
|
+
high: 2,
|
|
19
|
+
low: 6,
|
|
20
|
+
idle: 12,
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Creates a FrameBudget tracker tied to rAF, with priority-based scheduling.
|
|
24
|
+
* Critical tasks always run; lower priorities are deferred if budget is exhausted.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* const program = Effect.scoped(Effect.gen(function* () {
|
|
29
|
+
* const budget = yield* FrameBudget.make({ targetFps: 60 });
|
|
30
|
+
* const remaining = budget.remaining(); // ms left in this frame
|
|
31
|
+
* const canAnimate = budget.canRun('high'); // true if enough budget
|
|
32
|
+
* const result = yield* budget.schedule('low', Effect.succeed('done'));
|
|
33
|
+
* // result is 'done' if budget permits, null otherwise
|
|
34
|
+
* }));
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
function _make(config) {
|
|
38
|
+
const targetFps = config?.targetFps ?? DEFAULT_TARGET_FPS;
|
|
39
|
+
if (targetFps <= 0 || !Number.isFinite(targetFps)) {
|
|
40
|
+
throw new RangeError(`FrameBudget.make: targetFps must be a positive finite number, got ${targetFps}`);
|
|
41
|
+
}
|
|
42
|
+
const frameBudgetMs = MS_PER_SEC / targetFps;
|
|
43
|
+
return Effect.gen(function* () {
|
|
44
|
+
let frameStart = typeof performance !== 'undefined' ? performance.now() : 0;
|
|
45
|
+
let currentFps = targetFps;
|
|
46
|
+
let lastFrameTime = typeof performance !== 'undefined' ? performance.now() : 0;
|
|
47
|
+
let frameCount = 0;
|
|
48
|
+
let fpsAccum = 0;
|
|
49
|
+
if (typeof requestAnimationFrame !== 'undefined') {
|
|
50
|
+
const tick = (now) => {
|
|
51
|
+
frameStart = now;
|
|
52
|
+
frameCount++;
|
|
53
|
+
fpsAccum += now - lastFrameTime;
|
|
54
|
+
lastFrameTime = now;
|
|
55
|
+
if (fpsAccum >= MS_PER_SEC) {
|
|
56
|
+
currentFps = Math.round((frameCount * MS_PER_SEC) / fpsAccum);
|
|
57
|
+
frameCount = 0;
|
|
58
|
+
fpsAccum %= MS_PER_SEC;
|
|
59
|
+
}
|
|
60
|
+
rafId = requestAnimationFrame(tick);
|
|
61
|
+
};
|
|
62
|
+
let rafId = requestAnimationFrame(tick);
|
|
63
|
+
yield* Effect.addFinalizer(() => Effect.sync(() => cancelAnimationFrame(rafId)));
|
|
64
|
+
}
|
|
65
|
+
const budget = {
|
|
66
|
+
remaining() {
|
|
67
|
+
if (typeof performance === 'undefined')
|
|
68
|
+
return frameBudgetMs;
|
|
69
|
+
return Math.max(0, frameBudgetMs - (performance.now() - frameStart));
|
|
70
|
+
},
|
|
71
|
+
canRun(priority) {
|
|
72
|
+
const rem = budget.remaining();
|
|
73
|
+
return rem >= PRIORITY_THRESHOLDS[priority];
|
|
74
|
+
},
|
|
75
|
+
scheduleSync(priority, task) {
|
|
76
|
+
if (budget.canRun(priority) || priority === 'critical') {
|
|
77
|
+
return task();
|
|
78
|
+
}
|
|
79
|
+
return null;
|
|
80
|
+
},
|
|
81
|
+
schedule(priority, task) {
|
|
82
|
+
return Effect.gen(function* () {
|
|
83
|
+
if (priority === 'critical' || budget.canRun(priority)) {
|
|
84
|
+
return yield* task;
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
87
|
+
});
|
|
88
|
+
},
|
|
89
|
+
fps: Effect.sync(() => currentFps),
|
|
90
|
+
get fpsSync() {
|
|
91
|
+
return currentFps;
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
return budget;
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* FrameBudget -- rAF-based frame budget manager with priority lanes.
|
|
99
|
+
* Tracks remaining time per animation frame and gates work by priority:
|
|
100
|
+
* `critical` (always runs) `> high > low > idle`.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* const program = Effect.scoped(Effect.gen(function* () {
|
|
105
|
+
* const budget = yield* FrameBudget.make({ targetFps: 60 });
|
|
106
|
+
* if (budget.canRun('high')) {
|
|
107
|
+
* yield* budget.schedule('high', Effect.succeed('rendered'));
|
|
108
|
+
* }
|
|
109
|
+
* const fps = yield* budget.fps; // current measured FPS
|
|
110
|
+
* }));
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
export const FrameBudget = { make: _make };
|
|
114
|
+
//# sourceMappingURL=frame-budget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame-budget.js","sourceRoot":"","sources":["../src/frame-budget.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAS/D,wGAAwG;AACxG,MAAM,mBAAmB,GAA6B;IACpD,QAAQ,EAAE,CAAC;IACX,IAAI,EAAE,CAAC;IACP,GAAG,EAAE,CAAC;IACN,IAAI,EAAE,EAAE;CACT,CAAC;AAaF;;;;;;;;;;;;;;GAcG;AACH,SAAS,KAAK,CAAC,MAA+B;IAC5C,MAAM,SAAS,GAAG,MAAM,EAAE,SAAS,IAAI,kBAAkB,CAAC;IAC1D,IAAI,SAAS,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,UAAU,CAAC,qEAAqE,SAAS,EAAE,CAAC,CAAC;IACzG,CAAC;IACD,MAAM,aAAa,GAAG,UAAU,GAAG,SAAS,CAAC;IAE7C,OAAO,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QACzB,IAAI,UAAU,GAAG,OAAO,WAAW,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5E,IAAI,UAAU,GAAG,SAAS,CAAC;QAC3B,IAAI,aAAa,GAAG,OAAO,WAAW,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/E,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,IAAI,QAAQ,GAAG,CAAC,CAAC;QAEjB,IAAI,OAAO,qBAAqB,KAAK,WAAW,EAAE,CAAC;YACjD,MAAM,IAAI,GAAG,CAAC,GAAW,EAAE,EAAE;gBAC3B,UAAU,GAAG,GAAG,CAAC;gBACjB,UAAU,EAAE,CAAC;gBACb,QAAQ,IAAI,GAAG,GAAG,aAAa,CAAC;gBAChC,aAAa,GAAG,GAAG,CAAC;gBACpB,IAAI,QAAQ,IAAI,UAAU,EAAE,CAAC;oBAC3B,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,UAAU,GAAG,UAAU,CAAC,GAAG,QAAQ,CAAC,CAAC;oBAC9D,UAAU,GAAG,CAAC,CAAC;oBACf,QAAQ,IAAI,UAAU,CAAC;gBACzB,CAAC;gBACD,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;YACtC,CAAC,CAAC;YACF,IAAI,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;YACxC,KAAK,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACnF,CAAC;QAED,MAAM,MAAM,GAAqB;YAC/B,SAAS;gBACP,IAAI,OAAO,WAAW,KAAK,WAAW;oBAAE,OAAO,aAAa,CAAC;gBAC7D,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,aAAa,GAAG,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC;YACvE,CAAC;YAED,MAAM,CAAC,QAAkB;gBACvB,MAAM,GAAG,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;gBAC/B,OAAO,GAAG,IAAI,mBAAmB,CAAC,QAAQ,CAAE,CAAC;YAC/C,CAAC;YAED,YAAY,CAAI,QAAkB,EAAE,IAAa;gBAC/C,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;oBACvD,OAAO,IAAI,EAAE,CAAC;gBAChB,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;YAED,QAAQ,CAAI,QAAkB,EAAE,IAAsB;gBACpD,OAAO,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;oBACzB,IAAI,QAAQ,KAAK,UAAU,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;wBACvD,OAAO,KAAK,CAAC,CAAC,IAAI,CAAC;oBACrB,CAAC;oBACD,OAAO,IAAI,CAAC;gBACd,CAAC,CAAC,CAAC;YACL,CAAC;YAED,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC;YAElC,IAAI,OAAO;gBACT,OAAO,UAAU,CAAC;YACpB,CAAC;SACF,CAAC;QAEF,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GenFrame -- generative UI frame scheduler.
|
|
3
|
+
*
|
|
4
|
+
* Fixed-step scheduler producing "UI frames" at configurable fps
|
|
5
|
+
* from token buffer. Each frame classified as keyframe (I-frame),
|
|
6
|
+
* delta (P-frame), or interpolated (B-frame).
|
|
7
|
+
*
|
|
8
|
+
* Integrates with FrameBudget for priority scheduling and receipt
|
|
9
|
+
* chain for disconnect-resilient generative UI state.
|
|
10
|
+
*
|
|
11
|
+
* @module
|
|
12
|
+
*/
|
|
13
|
+
import type { ContentAddress } from './brands.js';
|
|
14
|
+
import type { TokenBuffer } from './token-buffer.js';
|
|
15
|
+
import type { UIQualityTier } from './ui-quality.js';
|
|
16
|
+
/**
|
|
17
|
+
* Classification of a {@link UIFrame} in the generative-UI pipeline, analogous to
|
|
18
|
+
* I/P/B frames in video: `keyframe` replaces, `delta` patches, `interpolated`
|
|
19
|
+
* keeps the DOM still and animates via CSS only.
|
|
20
|
+
*/
|
|
21
|
+
export type FrameType = 'keyframe' | 'delta' | 'interpolated';
|
|
22
|
+
/** How a {@link UIFrame} is applied to the DOM: full replace, patch, or CSS-only motion. */
|
|
23
|
+
export type MorphStrategy = 'replace' | 'patch' | 'css-only';
|
|
24
|
+
/**
|
|
25
|
+
* A single frame emitted by the {@link GenFrame} scheduler — the unit of work
|
|
26
|
+
* the DOM runtime consumes. Carries the drained tokens, its classification,
|
|
27
|
+
* the quality tier that produced it, and a content-addressed receipt for
|
|
28
|
+
* disconnect-resilient replay.
|
|
29
|
+
*/
|
|
30
|
+
export interface UIFrame {
|
|
31
|
+
readonly type: FrameType;
|
|
32
|
+
readonly tokens: readonly string[];
|
|
33
|
+
readonly qualityTier: UIQualityTier;
|
|
34
|
+
readonly morphStrategy: MorphStrategy;
|
|
35
|
+
readonly timestamp: number;
|
|
36
|
+
readonly receiptId: ContentAddress;
|
|
37
|
+
readonly bufferPosition: number;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Recovery plan returned by {@link GenFrame.resolveGap} when a stream disconnects:
|
|
41
|
+
* resume from a buffer position, replay cached frames, request a full restart,
|
|
42
|
+
* or do nothing.
|
|
43
|
+
*/
|
|
44
|
+
export type GapStrategy = {
|
|
45
|
+
readonly type: 'resume';
|
|
46
|
+
readonly bufferPosition: number;
|
|
47
|
+
} | {
|
|
48
|
+
readonly type: 'replay';
|
|
49
|
+
readonly frames: readonly UIFrame[];
|
|
50
|
+
} | {
|
|
51
|
+
readonly type: 're-request';
|
|
52
|
+
readonly fromScratch: true;
|
|
53
|
+
} | {
|
|
54
|
+
readonly type: 'noop';
|
|
55
|
+
};
|
|
56
|
+
/** Transport-layer snapshot indicating whether the stream can resume from its last event. */
|
|
57
|
+
export interface ResumptionInfo {
|
|
58
|
+
readonly canResume: boolean;
|
|
59
|
+
readonly lastEventId?: string;
|
|
60
|
+
}
|
|
61
|
+
/** Accessor bundle that exposes the receipt chain to {@link GenFrame.resolveGap}. */
|
|
62
|
+
export interface ReceiptChainInfo {
|
|
63
|
+
readonly hasFramesAfter: (receiptId: ContentAddress | null) => boolean;
|
|
64
|
+
readonly getFramesAfter: (receiptId: ContentAddress | null) => readonly UIFrame[];
|
|
65
|
+
}
|
|
66
|
+
declare function resolveGap(lastAckReceiptId: ContentAddress | null, currentStreamPosition: number, receiptChain: ReceiptChainInfo, resumptionState: ResumptionInfo): GapStrategy;
|
|
67
|
+
interface GenFrameConfig {
|
|
68
|
+
readonly fps?: number;
|
|
69
|
+
readonly tokenBuffer: TokenBuffer.Shape<string>;
|
|
70
|
+
readonly getQualityTier: () => UIQualityTier;
|
|
71
|
+
}
|
|
72
|
+
interface GenFrameSchedulerShape {
|
|
73
|
+
tick(): UIFrame | null;
|
|
74
|
+
readonly frameCount: number;
|
|
75
|
+
readonly lastFrame: UIFrame | null;
|
|
76
|
+
markKeyframe(): void;
|
|
77
|
+
reset(): void;
|
|
78
|
+
}
|
|
79
|
+
declare function _make(config: GenFrameConfig): GenFrameSchedulerShape;
|
|
80
|
+
/**
|
|
81
|
+
* Generative-UI frame scheduler namespace.
|
|
82
|
+
*
|
|
83
|
+
* Turns a bursty LLM token stream into evenly-paced frames the DOM runtime
|
|
84
|
+
* can apply without stalling, and resolves disconnect gaps using the receipt
|
|
85
|
+
* chain or transport resumption.
|
|
86
|
+
*/
|
|
87
|
+
export declare const GenFrame: {
|
|
88
|
+
/** Create a new fixed-step scheduler bound to a {@link TokenBuffer} and quality-tier probe. */
|
|
89
|
+
make: typeof _make;
|
|
90
|
+
/** Pick a recovery {@link GapStrategy} after a stream disconnect. */
|
|
91
|
+
resolveGap: typeof resolveGap;
|
|
92
|
+
};
|
|
93
|
+
export declare namespace GenFrame {
|
|
94
|
+
/** Structural shape of a scheduler instance returned by {@link GenFrame.make}. */
|
|
95
|
+
type Shape = GenFrameSchedulerShape;
|
|
96
|
+
/** Configuration accepted by {@link GenFrame.make}. */
|
|
97
|
+
type Config = GenFrameConfig;
|
|
98
|
+
/** Alias for {@link UIFrame}. */
|
|
99
|
+
type Frame = UIFrame;
|
|
100
|
+
}
|
|
101
|
+
export {};
|
|
102
|
+
//# sourceMappingURL=gen-frame.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gen-frame.d.ts","sourceRoot":"","sources":["../src/gen-frame.ts"],"names":[],"mappings":"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"}
|