@kumbatio/energy-system 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 +247 -0
- package/dist/compat.d.ts +49 -0
- package/dist/compat.d.ts.map +1 -0
- package/dist/compat.js +109 -0
- package/dist/compat.js.map +1 -0
- package/dist/dom.d.ts +19 -0
- package/dist/dom.d.ts.map +1 -0
- package/dist/dom.js +72 -0
- package/dist/dom.js.map +1 -0
- package/dist/engine.d.ts +26 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +218 -0
- package/dist/engine.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/levels.d.ts +16 -0
- package/dist/levels.d.ts.map +1 -0
- package/dist/levels.js +114 -0
- package/dist/levels.js.map +1 -0
- package/dist/metrics.d.ts +6 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +47 -0
- package/dist/metrics.js.map +1 -0
- package/dist/persistence.d.ts +12 -0
- package/dist/persistence.d.ts.map +1 -0
- package/dist/persistence.js +93 -0
- package/dist/persistence.js.map +1 -0
- package/dist/react.d.ts +45 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +130 -0
- package/dist/react.js.map +1 -0
- package/dist/strategies.d.ts +36 -0
- package/dist/strategies.d.ts.map +1 -0
- package/dist/strategies.js +175 -0
- package/dist/strategies.js.map +1 -0
- package/dist/types.d.ts +88 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/package.json +73 -0
- package/src/energy.css +134 -0
package/dist/engine.js
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { createEnergyState, cycleEnergyLevel, isEnergyLevel, isEnergySource } from './levels.js';
|
|
2
|
+
function logEngineError(message, err) {
|
|
3
|
+
console.error(`[energy-system] ${message}`, err);
|
|
4
|
+
}
|
|
5
|
+
const PERSIST_RETRY_INITIAL_MS = 250;
|
|
6
|
+
const PERSIST_RETRY_MAX_MS = 30_000;
|
|
7
|
+
function resolveNow(clock) {
|
|
8
|
+
if (typeof clock === 'function')
|
|
9
|
+
return clock;
|
|
10
|
+
if (clock?.now)
|
|
11
|
+
return () => clock.now();
|
|
12
|
+
return () => Date.now();
|
|
13
|
+
}
|
|
14
|
+
function isSameState(a, b) {
|
|
15
|
+
return a.level === b.level && a.timestamp === b.timestamp && a.source === b.source;
|
|
16
|
+
}
|
|
17
|
+
function getSourcePriority(source) {
|
|
18
|
+
switch (source) {
|
|
19
|
+
case 'manual':
|
|
20
|
+
return 3;
|
|
21
|
+
case 'scheduled':
|
|
22
|
+
return 2;
|
|
23
|
+
case 'inferred':
|
|
24
|
+
return 1;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function isPreferredExternalState(candidate, current) {
|
|
28
|
+
if (candidate.timestamp !== current.timestamp) {
|
|
29
|
+
return candidate.timestamp > current.timestamp;
|
|
30
|
+
}
|
|
31
|
+
if (candidate.source !== current.source) {
|
|
32
|
+
return getSourcePriority(candidate.source) > getSourcePriority(current.source);
|
|
33
|
+
}
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
function normalizeState(candidate, now) {
|
|
37
|
+
if (!isEnergyLevel(candidate.level)) {
|
|
38
|
+
throw new Error(`Invalid energy level from persistence: ${String(candidate.level)}`);
|
|
39
|
+
}
|
|
40
|
+
const timestamp = Number.isFinite(candidate.timestamp) ? candidate.timestamp : now();
|
|
41
|
+
const source = isEnergySource(candidate.source) ? candidate.source : 'manual';
|
|
42
|
+
return createEnergyState(candidate.level, source, timestamp);
|
|
43
|
+
}
|
|
44
|
+
export function createEnergyEngine(options = {}) {
|
|
45
|
+
const { initialLevel = 100, persistence, onChange, clock } = options;
|
|
46
|
+
const now = resolveNow(clock);
|
|
47
|
+
const listeners = new Set();
|
|
48
|
+
let stateVersion = 0;
|
|
49
|
+
let disposed = false;
|
|
50
|
+
let state = createEnergyState(initialLevel, 'manual', now());
|
|
51
|
+
let persistedVersion = 0;
|
|
52
|
+
let requestedPersistVersion = 0;
|
|
53
|
+
let persistTask;
|
|
54
|
+
let persistRetryTimer;
|
|
55
|
+
let persistRetryDelayMs = PERSIST_RETRY_INITIAL_MS;
|
|
56
|
+
function queuePersist() {
|
|
57
|
+
if (!persistence || disposed)
|
|
58
|
+
return;
|
|
59
|
+
requestedPersistVersion = Math.max(requestedPersistVersion, stateVersion);
|
|
60
|
+
if (persistTask)
|
|
61
|
+
return;
|
|
62
|
+
persistTask = (async () => {
|
|
63
|
+
while (!disposed && persistedVersion < requestedPersistVersion) {
|
|
64
|
+
const snapshot = state;
|
|
65
|
+
const snapshotVersion = stateVersion;
|
|
66
|
+
try {
|
|
67
|
+
await persistence.save(snapshot);
|
|
68
|
+
persistedVersion = Math.max(persistedVersion, snapshotVersion);
|
|
69
|
+
persistRetryDelayMs = PERSIST_RETRY_INITIAL_MS;
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
logEngineError('Failed to persist energy state', err);
|
|
73
|
+
persistTask = undefined;
|
|
74
|
+
if (!disposed && !persistRetryTimer && persistedVersion < requestedPersistVersion) {
|
|
75
|
+
const retryDelayMs = persistRetryDelayMs;
|
|
76
|
+
// Exponential backoff so a persistently failing store (e.g. quota
|
|
77
|
+
// exceeded) is not hammered every 250ms forever.
|
|
78
|
+
persistRetryDelayMs = Math.min(persistRetryDelayMs * 2, PERSIST_RETRY_MAX_MS);
|
|
79
|
+
persistRetryTimer = setTimeout(() => {
|
|
80
|
+
persistRetryTimer = undefined;
|
|
81
|
+
queuePersist();
|
|
82
|
+
}, retryDelayMs);
|
|
83
|
+
}
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
persistTask = undefined;
|
|
88
|
+
if (!disposed && persistedVersion < requestedPersistVersion) {
|
|
89
|
+
queuePersist();
|
|
90
|
+
}
|
|
91
|
+
})();
|
|
92
|
+
}
|
|
93
|
+
function notify(prev) {
|
|
94
|
+
if (onChange) {
|
|
95
|
+
try {
|
|
96
|
+
onChange(state, prev);
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
logEngineError('onChange listener threw', err);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
for (const listener of listeners) {
|
|
103
|
+
try {
|
|
104
|
+
listener(state, prev);
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
logEngineError('Energy subscriber threw', err);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function applyState(next) {
|
|
112
|
+
// A disposed engine is inert: it must not mutate state, notify onChange,
|
|
113
|
+
// or schedule persistence after its resources were released.
|
|
114
|
+
if (disposed || isSameState(next, state))
|
|
115
|
+
return false;
|
|
116
|
+
const prev = state;
|
|
117
|
+
state = next;
|
|
118
|
+
stateVersion += 1;
|
|
119
|
+
notify(prev);
|
|
120
|
+
if (persistence) {
|
|
121
|
+
queuePersist();
|
|
122
|
+
}
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
let disposePersistenceObservation = () => { };
|
|
126
|
+
const engine = {
|
|
127
|
+
getState() {
|
|
128
|
+
return state;
|
|
129
|
+
},
|
|
130
|
+
setLevel(level, source = 'manual') {
|
|
131
|
+
applyState(createEnergyState(level, source, now()));
|
|
132
|
+
},
|
|
133
|
+
cycleLevel() {
|
|
134
|
+
engine.setLevel(cycleEnergyLevel(state.level), 'manual');
|
|
135
|
+
},
|
|
136
|
+
subscribe(listener) {
|
|
137
|
+
if (disposed) {
|
|
138
|
+
return () => { };
|
|
139
|
+
}
|
|
140
|
+
listeners.add(listener);
|
|
141
|
+
return () => {
|
|
142
|
+
listeners.delete(listener);
|
|
143
|
+
};
|
|
144
|
+
},
|
|
145
|
+
resolve(strategy) {
|
|
146
|
+
return strategy.resolve(state.level);
|
|
147
|
+
},
|
|
148
|
+
async hydrate() {
|
|
149
|
+
if (!persistence || disposed)
|
|
150
|
+
return;
|
|
151
|
+
const hydrateStartVersion = stateVersion;
|
|
152
|
+
let stored;
|
|
153
|
+
try {
|
|
154
|
+
stored = await persistence.load();
|
|
155
|
+
}
|
|
156
|
+
catch (err) {
|
|
157
|
+
logEngineError('Failed to load persisted energy state', err);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if (!stored || disposed)
|
|
161
|
+
return;
|
|
162
|
+
let normalized;
|
|
163
|
+
try {
|
|
164
|
+
normalized = normalizeState(stored, now);
|
|
165
|
+
}
|
|
166
|
+
catch (err) {
|
|
167
|
+
logEngineError('Ignoring invalid persisted energy state', err);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
if (isSameState(normalized, state))
|
|
171
|
+
return;
|
|
172
|
+
if (hydrateStartVersion === stateVersion || isPreferredExternalState(normalized, state)) {
|
|
173
|
+
applyState(normalized);
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
dispose() {
|
|
177
|
+
if (disposed)
|
|
178
|
+
return;
|
|
179
|
+
disposed = true;
|
|
180
|
+
disposePersistenceObservation();
|
|
181
|
+
if (persistRetryTimer) {
|
|
182
|
+
clearTimeout(persistRetryTimer);
|
|
183
|
+
persistRetryTimer = undefined;
|
|
184
|
+
}
|
|
185
|
+
listeners.clear();
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
// Auto-hydrate from persistence
|
|
189
|
+
if (persistence) {
|
|
190
|
+
void engine.hydrate().catch((err) => {
|
|
191
|
+
logEngineError('Unexpected hydrate failure', err);
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
if (persistence?.observe) {
|
|
195
|
+
try {
|
|
196
|
+
disposePersistenceObservation = persistence.observe((externalState) => {
|
|
197
|
+
if (disposed)
|
|
198
|
+
return;
|
|
199
|
+
let normalized;
|
|
200
|
+
try {
|
|
201
|
+
normalized = normalizeState(externalState, now);
|
|
202
|
+
}
|
|
203
|
+
catch (err) {
|
|
204
|
+
logEngineError('Ignoring invalid observed energy state', err);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (!isPreferredExternalState(normalized, state))
|
|
208
|
+
return;
|
|
209
|
+
applyState(normalized);
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
catch (err) {
|
|
213
|
+
logEngineError('Failed to subscribe to persistence observation', err);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return engine;
|
|
217
|
+
}
|
|
218
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAoChG,SAAS,cAAc,CAAC,OAAe,EAAE,GAAY;IACnD,OAAO,CAAC,KAAK,CAAC,mBAAmB,OAAO,EAAE,EAAE,GAAG,CAAC,CAAA;AAClD,CAAC;AAED,MAAM,wBAAwB,GAAG,GAAG,CAAA;AACpC,MAAM,oBAAoB,GAAG,MAAM,CAAA;AAEnC,SAAS,UAAU,CAAC,KAAoC;IACtD,IAAI,OAAO,KAAK,KAAK,UAAU;QAAE,OAAO,KAAK,CAAA;IAC7C,IAAI,KAAK,EAAE,GAAG;QAAE,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAA;IACxC,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAA;AACzB,CAAC;AAED,SAAS,WAAW,CAAC,CAAc,EAAE,CAAc;IACjD,OAAO,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,CAAA;AACpF,CAAC;AAED,SAAS,iBAAiB,CAAC,MAAoB;IAC7C,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,QAAQ;YACX,OAAO,CAAC,CAAA;QACV,KAAK,WAAW;YACd,OAAO,CAAC,CAAA;QACV,KAAK,UAAU;YACb,OAAO,CAAC,CAAA;IACZ,CAAC;AACH,CAAC;AAED,SAAS,wBAAwB,CAAC,SAAsB,EAAE,OAAoB;IAC5E,IAAI,SAAS,CAAC,SAAS,KAAK,OAAO,CAAC,SAAS,EAAE,CAAC;QAC9C,OAAO,SAAS,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAA;IAChD,CAAC;IAED,IAAI,SAAS,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;QACxC,OAAO,iBAAiB,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,iBAAiB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IAChF,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC;AAED,SAAS,cAAc,CAAC,SAAsB,EAAE,GAAiB;IAC/D,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,0CAA0C,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;IACtF,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,CAAA;IACpF,MAAM,MAAM,GAAiB,cAAc,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAA;IAE3F,OAAO,iBAAiB,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,CAAA;AAC9D,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,UAA+B,EAAE;IAClE,MAAM,EAAE,YAAY,GAAG,GAAG,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,OAAO,CAAA;IACpE,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,CAAA;IAC7B,MAAM,SAAS,GAAG,IAAI,GAAG,EAAwB,CAAA;IACjD,IAAI,YAAY,GAAG,CAAC,CAAA;IACpB,IAAI,QAAQ,GAAG,KAAK,CAAA;IAEpB,IAAI,KAAK,GAAgB,iBAAiB,CAAC,YAAY,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAA;IACzE,IAAI,gBAAgB,GAAG,CAAC,CAAA;IACxB,IAAI,uBAAuB,GAAG,CAAC,CAAA;IAC/B,IAAI,WAAsC,CAAA;IAC1C,IAAI,iBAA4D,CAAA;IAChE,IAAI,mBAAmB,GAAG,wBAAwB,CAAA;IAElD,SAAS,YAAY;QACnB,IAAI,CAAC,WAAW,IAAI,QAAQ;YAAE,OAAM;QAEpC,uBAAuB,GAAG,IAAI,CAAC,GAAG,CAAC,uBAAuB,EAAE,YAAY,CAAC,CAAA;QAEzE,IAAI,WAAW;YAAE,OAAM;QAEvB,WAAW,GAAG,CAAC,KAAK,IAAI,EAAE;YACxB,OAAO,CAAC,QAAQ,IAAI,gBAAgB,GAAG,uBAAuB,EAAE,CAAC;gBAC/D,MAAM,QAAQ,GAAG,KAAK,CAAA;gBACtB,MAAM,eAAe,GAAG,YAAY,CAAA;gBAEpC,IAAI,CAAC;oBACH,MAAM,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;oBAChC,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAA;oBAC9D,mBAAmB,GAAG,wBAAwB,CAAA;gBAChD,CAAC;gBAAC,OAAO,GAAY,EAAE,CAAC;oBACtB,cAAc,CAAC,gCAAgC,EAAE,GAAG,CAAC,CAAA;oBACrD,WAAW,GAAG,SAAS,CAAA;oBAEvB,IAAI,CAAC,QAAQ,IAAI,CAAC,iBAAiB,IAAI,gBAAgB,GAAG,uBAAuB,EAAE,CAAC;wBAClF,MAAM,YAAY,GAAG,mBAAmB,CAAA;wBACxC,kEAAkE;wBAClE,iDAAiD;wBACjD,mBAAmB,GAAG,IAAI,CAAC,GAAG,CAAC,mBAAmB,GAAG,CAAC,EAAE,oBAAoB,CAAC,CAAA;wBAC7E,iBAAiB,GAAG,UAAU,CAAC,GAAG,EAAE;4BAClC,iBAAiB,GAAG,SAAS,CAAA;4BAC7B,YAAY,EAAE,CAAA;wBAChB,CAAC,EAAE,YAAY,CAAC,CAAA;oBAClB,CAAC;oBAED,OAAM;gBACR,CAAC;YACH,CAAC;YAED,WAAW,GAAG,SAAS,CAAA;YAEvB,IAAI,CAAC,QAAQ,IAAI,gBAAgB,GAAG,uBAAuB,EAAE,CAAC;gBAC5D,YAAY,EAAE,CAAA;YAChB,CAAC;QACH,CAAC,CAAC,EAAE,CAAA;IACN,CAAC;IAED,SAAS,MAAM,CAAC,IAAiB;QAC/B,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,CAAC;gBACH,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;YACvB,CAAC;YAAC,OAAO,GAAY,EAAE,CAAC;gBACtB,cAAc,CAAC,yBAAyB,EAAE,GAAG,CAAC,CAAA;YAChD,CAAC;QACH,CAAC;QAED,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,IAAI,CAAC;gBACH,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;YACvB,CAAC;YAAC,OAAO,GAAY,EAAE,CAAC;gBACtB,cAAc,CAAC,yBAAyB,EAAE,GAAG,CAAC,CAAA;YAChD,CAAC;QACH,CAAC;IACH,CAAC;IAED,SAAS,UAAU,CAAC,IAAiB;QACnC,yEAAyE;QACzE,6DAA6D;QAC7D,IAAI,QAAQ,IAAI,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC;YAAE,OAAO,KAAK,CAAA;QAEtD,MAAM,IAAI,GAAG,KAAK,CAAA;QAClB,KAAK,GAAG,IAAI,CAAA;QACZ,YAAY,IAAI,CAAC,CAAA;QACjB,MAAM,CAAC,IAAI,CAAC,CAAA;QACZ,IAAI,WAAW,EAAE,CAAC;YAChB,YAAY,EAAE,CAAA;QAChB,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,IAAI,6BAA6B,GAAG,GAAG,EAAE,GAAE,CAAC,CAAA;IAE5C,MAAM,MAAM,GAAiB;QAC3B,QAAQ;YACN,OAAO,KAAK,CAAA;QACd,CAAC;QAED,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ;YAC/B,UAAU,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAA;QACrD,CAAC;QAED,UAAU;YACR,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,CAAA;QAC1D,CAAC;QAED,SAAS,CAAC,QAAQ;YAChB,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,GAAG,EAAE,GAAE,CAAC,CAAA;YACjB,CAAC;YAED,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;YACvB,OAAO,GAAG,EAAE;gBACV,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;YAC5B,CAAC,CAAA;QACH,CAAC;QAED,OAAO,CAAI,QAA+B;YACxC,OAAO,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;QACtC,CAAC;QAED,KAAK,CAAC,OAAO;YACX,IAAI,CAAC,WAAW,IAAI,QAAQ;gBAAE,OAAM;YAEpC,MAAM,mBAAmB,GAAG,YAAY,CAAA;YACxC,IAAI,MAA0B,CAAA;YAE9B,IAAI,CAAC;gBACH,MAAM,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,CAAA;YACnC,CAAC;YAAC,OAAO,GAAY,EAAE,CAAC;gBACtB,cAAc,CAAC,uCAAuC,EAAE,GAAG,CAAC,CAAA;gBAC5D,OAAM;YACR,CAAC;YAED,IAAI,CAAC,MAAM,IAAI,QAAQ;gBAAE,OAAM;YAE/B,IAAI,UAAuB,CAAA;YAE3B,IAAI,CAAC;gBACH,UAAU,GAAG,cAAc,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;YAC1C,CAAC;YAAC,OAAO,GAAY,EAAE,CAAC;gBACtB,cAAc,CAAC,yCAAyC,EAAE,GAAG,CAAC,CAAA;gBAC9D,OAAM;YACR,CAAC;YAED,IAAI,WAAW,CAAC,UAAU,EAAE,KAAK,CAAC;gBAAE,OAAM;YAE1C,IAAI,mBAAmB,KAAK,YAAY,IAAI,wBAAwB,CAAC,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC;gBACxF,UAAU,CAAC,UAAU,CAAC,CAAA;YACxB,CAAC;QACH,CAAC;QAED,OAAO;YACL,IAAI,QAAQ;gBAAE,OAAM;YAEpB,QAAQ,GAAG,IAAI,CAAA;YACf,6BAA6B,EAAE,CAAA;YAC/B,IAAI,iBAAiB,EAAE,CAAC;gBACtB,YAAY,CAAC,iBAAiB,CAAC,CAAA;gBAC/B,iBAAiB,GAAG,SAAS,CAAA;YAC/B,CAAC;YACD,SAAS,CAAC,KAAK,EAAE,CAAA;QACnB,CAAC;KACF,CAAA;IAED,gCAAgC;IAChC,IAAI,WAAW,EAAE,CAAC;QAChB,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;YAC3C,cAAc,CAAC,4BAA4B,EAAE,GAAG,CAAC,CAAA;QACnD,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,IAAI,WAAW,EAAE,OAAO,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,6BAA6B,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,EAAE;gBACpE,IAAI,QAAQ;oBAAE,OAAM;gBAEpB,IAAI,UAAuB,CAAA;gBAE3B,IAAI,CAAC;oBACH,UAAU,GAAG,cAAc,CAAC,aAAa,EAAE,GAAG,CAAC,CAAA;gBACjD,CAAC;gBAAC,OAAO,GAAY,EAAE,CAAC;oBACtB,cAAc,CAAC,wCAAwC,EAAE,GAAG,CAAC,CAAA;oBAC7D,OAAM;gBACR,CAAC;gBAED,IAAI,CAAC,wBAAwB,CAAC,UAAU,EAAE,KAAK,CAAC;oBAAE,OAAM;gBAExD,UAAU,CAAC,UAAU,CAAC,CAAA;YACxB,CAAC,CAAC,CAAA;QACJ,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,cAAc,CAAC,gDAAgD,EAAE,GAAG,CAAC,CAAA;QACvE,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type { AdaptationStrategy, CognitiveProfile, DecisionCapacity, EnergyClock, EnergyChangeListener, EnergyLevel, EnergyLevelDefinition, EnergyMetrics, EnergyPersistence, EnergySource, EnergyState, FocusDuration, InterruptionTolerance, TaskComplexity, } from './types.js';
|
|
2
|
+
export { ENERGY_LEVEL_VALUES, ENERGY_SOURCE_VALUES } from './types.js';
|
|
3
|
+
export { createEnergyState, cycleEnergyLevel, getEnergyLevel, getEnergyLevels, isEnergyLevel, isEnergySource, isHigherEnergy, } from './levels.js';
|
|
4
|
+
export type { ExternalLevelCompatibility, ExternalLevelCompatibilityOptions } from './compat.js';
|
|
5
|
+
export { createExternalLevelCompatibility, cycleDiscreteLevel, mapToNearestDiscreteLevel, mapToNearestEnergyLevel, } from './compat.js';
|
|
6
|
+
export { getEnergyMetrics } from './metrics.js';
|
|
7
|
+
export type { EnergyEngine, EnergyEngineOptions } from './engine.js';
|
|
8
|
+
export { createEnergyEngine } from './engine.js';
|
|
9
|
+
export type { NotificationConfig, TaskComplexityConfig, UIVisibilityConfig } from './strategies.js';
|
|
10
|
+
export { notificationStrategy, taskComplexityStrategy, uiVisibilityStrategy } from './strategies.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,oBAAoB,EACpB,WAAW,EACX,qBAAqB,EACrB,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,WAAW,EACX,aAAa,EACb,qBAAqB,EACrB,cAAc,GACf,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAGtE,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,aAAa,EACb,cAAc,EACd,cAAc,GACf,MAAM,aAAa,CAAA;AAEpB,YAAY,EAAE,0BAA0B,EAAE,iCAAiC,EAAE,MAAM,aAAa,CAAA;AAChG,OAAO,EACL,gCAAgC,EAChC,kBAAkB,EAClB,yBAAyB,EACzB,uBAAuB,GACxB,MAAM,aAAa,CAAA;AAGpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAG/C,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAGhD,YAAY,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AACnG,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { ENERGY_LEVEL_VALUES, ENERGY_SOURCE_VALUES } from './types.js';
|
|
2
|
+
// Level definitions and pure functions
|
|
3
|
+
export { createEnergyState, cycleEnergyLevel, getEnergyLevel, getEnergyLevels, isEnergyLevel, isEnergySource, isHigherEnergy, } from './levels.js';
|
|
4
|
+
export { createExternalLevelCompatibility, cycleDiscreteLevel, mapToNearestDiscreteLevel, mapToNearestEnergyLevel, } from './compat.js';
|
|
5
|
+
// Derived metrics
|
|
6
|
+
export { getEnergyMetrics } from './metrics.js';
|
|
7
|
+
export { createEnergyEngine } from './engine.js';
|
|
8
|
+
export { notificationStrategy, taskComplexityStrategy, uiVisibilityStrategy } from './strategies.js';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAEtE,uCAAuC;AACvC,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,aAAa,EACb,cAAc,EACd,cAAc,GACf,MAAM,aAAa,CAAA;AAGpB,OAAO,EACL,gCAAgC,EAChC,kBAAkB,EAClB,yBAAyB,EACzB,uBAAuB,GACxB,MAAM,aAAa,CAAA;AAEpB,kBAAkB;AAClB,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAI/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAIhD,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA"}
|
package/dist/levels.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { EnergyLevel, EnergyLevelDefinition, EnergySource, EnergyState } from './types.js';
|
|
2
|
+
/** Get all energy level definitions, ordered highest to lowest */
|
|
3
|
+
export declare function getEnergyLevels(): ReadonlyArray<Readonly<EnergyLevelDefinition>>;
|
|
4
|
+
/** Get definition for a specific energy level */
|
|
5
|
+
export declare function getEnergyLevel(level: EnergyLevel): Readonly<EnergyLevelDefinition>;
|
|
6
|
+
/** Cycle to the next energy level: 100 -> 75 -> 50 -> 25 -> 0 -> 100 */
|
|
7
|
+
export declare function cycleEnergyLevel(current: EnergyLevel): EnergyLevel;
|
|
8
|
+
/** Validate that an unknown value is a valid EnergyLevel */
|
|
9
|
+
export declare function isEnergyLevel(value: unknown): value is EnergyLevel;
|
|
10
|
+
/** Validate that an unknown value is a valid EnergySource */
|
|
11
|
+
export declare function isEnergySource(value: unknown): value is EnergySource;
|
|
12
|
+
/** Returns true if level `a` represents higher energy than level `b` */
|
|
13
|
+
export declare function isHigherEnergy(a: EnergyLevel, b: EnergyLevel): boolean;
|
|
14
|
+
/** Create an EnergyState for the current moment */
|
|
15
|
+
export declare function createEnergyState(level: EnergyLevel, source?: EnergySource, timestamp?: number): EnergyState;
|
|
16
|
+
//# sourceMappingURL=levels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"levels.d.ts","sourceRoot":"","sources":["../src/levels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAyE/F,kEAAkE;AAClE,wBAAgB,eAAe,IAAI,aAAa,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAC,CAEhF;AAED,iDAAiD;AACjD,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,QAAQ,CAAC,qBAAqB,CAAC,CAIlF;AAED,wEAAwE;AACxE,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,WAAW,CAKlE;AAED,4DAA4D;AAC5D,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAElE;AAED,6DAA6D;AAC7D,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY,CAEpE;AAED,wEAAwE;AACxE,wBAAgB,cAAc,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,WAAW,GAAG,OAAO,CAEtE;AAED,mDAAmD;AACnD,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,WAAW,EAClB,MAAM,GAAE,YAAuB,EAC/B,SAAS,SAAa,GACrB,WAAW,CAcb"}
|
package/dist/levels.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { ENERGY_LEVEL_VALUES, ENERGY_SOURCE_VALUES } from './types.js';
|
|
2
|
+
function freezeObject(value) {
|
|
3
|
+
return Object.freeze(value);
|
|
4
|
+
}
|
|
5
|
+
const LEVELS = Object.freeze([
|
|
6
|
+
freezeObject({
|
|
7
|
+
value: 100,
|
|
8
|
+
key: 'peak',
|
|
9
|
+
label: 'Peak',
|
|
10
|
+
description: 'High capacity. Planning, complex decisions, creative work.',
|
|
11
|
+
cognitiveProfile: freezeObject({
|
|
12
|
+
decisionCapacity: 'high',
|
|
13
|
+
focusDuration: 'extended',
|
|
14
|
+
taskComplexity: 'complex',
|
|
15
|
+
interruptionTolerance: 'high',
|
|
16
|
+
}),
|
|
17
|
+
}),
|
|
18
|
+
freezeObject({
|
|
19
|
+
value: 75,
|
|
20
|
+
key: 'active',
|
|
21
|
+
label: 'Active',
|
|
22
|
+
description: 'Good capacity. Focused execution, problem-solving.',
|
|
23
|
+
cognitiveProfile: freezeObject({
|
|
24
|
+
decisionCapacity: 'moderate',
|
|
25
|
+
focusDuration: 'moderate',
|
|
26
|
+
taskComplexity: 'moderate',
|
|
27
|
+
interruptionTolerance: 'moderate',
|
|
28
|
+
}),
|
|
29
|
+
}),
|
|
30
|
+
freezeObject({
|
|
31
|
+
value: 50,
|
|
32
|
+
key: 'steady',
|
|
33
|
+
label: 'Steady',
|
|
34
|
+
description: 'Moderate capacity. Routine tasks, familiar work.',
|
|
35
|
+
cognitiveProfile: freezeObject({
|
|
36
|
+
decisionCapacity: 'low',
|
|
37
|
+
focusDuration: 'short',
|
|
38
|
+
taskComplexity: 'routine',
|
|
39
|
+
interruptionTolerance: 'low',
|
|
40
|
+
}),
|
|
41
|
+
}),
|
|
42
|
+
freezeObject({
|
|
43
|
+
value: 25,
|
|
44
|
+
key: 'low',
|
|
45
|
+
label: 'Low',
|
|
46
|
+
description: 'Limited capacity. Simple tasks, review, light work.',
|
|
47
|
+
cognitiveProfile: freezeObject({
|
|
48
|
+
decisionCapacity: 'minimal',
|
|
49
|
+
focusDuration: 'minimal',
|
|
50
|
+
taskComplexity: 'simple',
|
|
51
|
+
interruptionTolerance: 'minimal',
|
|
52
|
+
}),
|
|
53
|
+
}),
|
|
54
|
+
freezeObject({
|
|
55
|
+
value: 0,
|
|
56
|
+
key: 'rest',
|
|
57
|
+
label: 'Rest',
|
|
58
|
+
description: 'Depleted. Consumption only \u2014 reading, reflecting.',
|
|
59
|
+
cognitiveProfile: freezeObject({
|
|
60
|
+
decisionCapacity: 'none',
|
|
61
|
+
focusDuration: 'none',
|
|
62
|
+
taskComplexity: 'consumption',
|
|
63
|
+
interruptionTolerance: 'none',
|
|
64
|
+
}),
|
|
65
|
+
}),
|
|
66
|
+
]);
|
|
67
|
+
/** Cycle order: 100 -> 75 -> 50 -> 25 -> 0 -> 100 */
|
|
68
|
+
const CYCLE_ORDER = [100, 75, 50, 25, 0];
|
|
69
|
+
/** Get all energy level definitions, ordered highest to lowest */
|
|
70
|
+
export function getEnergyLevels() {
|
|
71
|
+
return LEVELS;
|
|
72
|
+
}
|
|
73
|
+
/** Get definition for a specific energy level */
|
|
74
|
+
export function getEnergyLevel(level) {
|
|
75
|
+
const def = LEVELS.find((l) => l.value === level);
|
|
76
|
+
if (!def)
|
|
77
|
+
throw new Error(`Invalid energy level: ${level}`);
|
|
78
|
+
return def;
|
|
79
|
+
}
|
|
80
|
+
/** Cycle to the next energy level: 100 -> 75 -> 50 -> 25 -> 0 -> 100 */
|
|
81
|
+
export function cycleEnergyLevel(current) {
|
|
82
|
+
const fallback = 100;
|
|
83
|
+
const idx = CYCLE_ORDER.indexOf(current);
|
|
84
|
+
if (idx === -1)
|
|
85
|
+
return fallback;
|
|
86
|
+
return CYCLE_ORDER[(idx + 1) % CYCLE_ORDER.length] ?? fallback;
|
|
87
|
+
}
|
|
88
|
+
/** Validate that an unknown value is a valid EnergyLevel */
|
|
89
|
+
export function isEnergyLevel(value) {
|
|
90
|
+
return typeof value === 'number' && ENERGY_LEVEL_VALUES.has(value);
|
|
91
|
+
}
|
|
92
|
+
/** Validate that an unknown value is a valid EnergySource */
|
|
93
|
+
export function isEnergySource(value) {
|
|
94
|
+
return typeof value === 'string' && ENERGY_SOURCE_VALUES.has(value);
|
|
95
|
+
}
|
|
96
|
+
/** Returns true if level `a` represents higher energy than level `b` */
|
|
97
|
+
export function isHigherEnergy(a, b) {
|
|
98
|
+
return a > b;
|
|
99
|
+
}
|
|
100
|
+
/** Create an EnergyState for the current moment */
|
|
101
|
+
export function createEnergyState(level, source = 'manual', timestamp = Date.now()) {
|
|
102
|
+
if (!isEnergyLevel(level)) {
|
|
103
|
+
throw new Error(`Invalid energy level: ${String(level)}`);
|
|
104
|
+
}
|
|
105
|
+
if (!isEnergySource(source)) {
|
|
106
|
+
throw new Error(`Invalid energy source: ${String(source)}`);
|
|
107
|
+
}
|
|
108
|
+
return freezeObject({
|
|
109
|
+
level,
|
|
110
|
+
timestamp: Number.isFinite(timestamp) ? timestamp : Date.now(),
|
|
111
|
+
source,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=levels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"levels.js","sourceRoot":"","sources":["../src/levels.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAe,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AA4BzE;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,SAAa,GAAG,aAAa,CAqBpF"}
|
package/dist/metrics.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { getEnergyLevel } from './levels.js';
|
|
2
|
+
function freezeObject(value) {
|
|
3
|
+
return Object.freeze(value);
|
|
4
|
+
}
|
|
5
|
+
const PRODUCTIVITY_WINDOW_MINUTES = {
|
|
6
|
+
100: 120,
|
|
7
|
+
75: 90,
|
|
8
|
+
50: 45,
|
|
9
|
+
25: 25,
|
|
10
|
+
0: 0,
|
|
11
|
+
};
|
|
12
|
+
const BREAK_INTERVAL_MINUTES = {
|
|
13
|
+
100: 90,
|
|
14
|
+
75: 60,
|
|
15
|
+
50: 45,
|
|
16
|
+
25: 25,
|
|
17
|
+
0: 15,
|
|
18
|
+
};
|
|
19
|
+
const RECOVERY_HINT_MINUTES = {
|
|
20
|
+
50: 10,
|
|
21
|
+
25: 20,
|
|
22
|
+
0: 30,
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Derive app-agnostic energy metrics from the current state.
|
|
26
|
+
*/
|
|
27
|
+
export function getEnergyMetrics(state, now = Date.now()) {
|
|
28
|
+
const safeNow = Number.isFinite(now) ? now : Date.now();
|
|
29
|
+
const stateAgeMs = Math.max(0, safeNow - state.timestamp);
|
|
30
|
+
const definition = getEnergyLevel(state.level);
|
|
31
|
+
const recoveryHintMinutes = RECOVERY_HINT_MINUTES[state.level];
|
|
32
|
+
const base = {
|
|
33
|
+
stateAgeMs,
|
|
34
|
+
stateAgeMinutes: Math.round(stateAgeMs / 60_000),
|
|
35
|
+
expectedProductivityWindowMinutes: PRODUCTIVITY_WINDOW_MINUTES[state.level],
|
|
36
|
+
suggestedBreakIntervalMinutes: BREAK_INTERVAL_MINUTES[state.level],
|
|
37
|
+
recommendedTaskComplexity: definition.cognitiveProfile.taskComplexity,
|
|
38
|
+
sustainable: state.level > 0 && state.level < 100,
|
|
39
|
+
};
|
|
40
|
+
return recoveryHintMinutes === undefined
|
|
41
|
+
? freezeObject(base)
|
|
42
|
+
: freezeObject({
|
|
43
|
+
...base,
|
|
44
|
+
recoveryHintMinutes,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=metrics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAG5C,SAAS,YAAY,CAAmB,KAAQ;IAC9C,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAC7B,CAAC;AAED,MAAM,2BAA2B,GAAgC;IAC/D,GAAG,EAAE,GAAG;IACR,EAAE,EAAE,EAAE;IACN,EAAE,EAAE,EAAE;IACN,EAAE,EAAE,EAAE;IACN,CAAC,EAAE,CAAC;CACL,CAAA;AAED,MAAM,sBAAsB,GAAgC;IAC1D,GAAG,EAAE,EAAE;IACP,EAAE,EAAE,EAAE;IACN,EAAE,EAAE,EAAE;IACN,EAAE,EAAE,EAAE;IACN,CAAC,EAAE,EAAE;CACN,CAAA;AAED,MAAM,qBAAqB,GAAyC;IAClE,EAAE,EAAE,EAAE;IACN,EAAE,EAAE,EAAE;IACN,CAAC,EAAE,EAAE;CACN,CAAA;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAkB,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IACnE,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAA;IACvD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC,CAAA;IACzD,MAAM,UAAU,GAAG,cAAc,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IAC9C,MAAM,mBAAmB,GAAG,qBAAqB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IAE9D,MAAM,IAAI,GAAkB;QAC1B,UAAU;QACV,eAAe,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,MAAM,CAAC;QAChD,iCAAiC,EAAE,2BAA2B,CAAC,KAAK,CAAC,KAAK,CAAC;QAC3E,6BAA6B,EAAE,sBAAsB,CAAC,KAAK,CAAC,KAAK,CAAC;QAClE,yBAAyB,EAAE,UAAU,CAAC,gBAAgB,CAAC,cAAc;QACrE,WAAW,EAAE,KAAK,CAAC,KAAK,GAAG,CAAC,IAAI,KAAK,CAAC,KAAK,GAAG,GAAG;KAClD,CAAA;IAED,OAAO,mBAAmB,KAAK,SAAS;QACtC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC;QACpB,CAAC,CAAC,YAAY,CAAC;YACX,GAAG,IAAI;YACP,mBAAmB;SACpB,CAAC,CAAA;AACR,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { EnergyPersistence, EnergyState } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* localStorage-based persistence adapter.
|
|
4
|
+
* Stores the full EnergyState as JSON.
|
|
5
|
+
*/
|
|
6
|
+
export declare function localStoragePersistence(key?: string): EnergyPersistence;
|
|
7
|
+
/**
|
|
8
|
+
* In-memory persistence adapter.
|
|
9
|
+
* Useful for tests, SSR, or ephemeral sessions.
|
|
10
|
+
*/
|
|
11
|
+
export declare function memoryPersistence(initial?: EnergyState): EnergyPersistence;
|
|
12
|
+
//# sourceMappingURL=persistence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../src/persistence.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAe,iBAAiB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AA0B7E;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,SAAiB,GAAG,iBAAiB,CA4C/E;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG,iBAAiB,CAwB1E"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { createEnergyState, isEnergyLevel } from './levels.js';
|
|
2
|
+
function parsePersistedState(raw) {
|
|
3
|
+
if (!raw)
|
|
4
|
+
return null;
|
|
5
|
+
try {
|
|
6
|
+
const parsed = JSON.parse(raw);
|
|
7
|
+
if (typeof parsed === 'object' &&
|
|
8
|
+
parsed !== null &&
|
|
9
|
+
'level' in parsed &&
|
|
10
|
+
isEnergyLevel(parsed.level)) {
|
|
11
|
+
const obj = parsed;
|
|
12
|
+
return createEnergyState(obj.level, obj.source === 'scheduled' || obj.source === 'inferred' ? obj.source : 'manual', typeof obj.timestamp === 'number' ? obj.timestamp : Date.now());
|
|
13
|
+
}
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* localStorage-based persistence adapter.
|
|
22
|
+
* Stores the full EnergyState as JSON.
|
|
23
|
+
*/
|
|
24
|
+
export function localStoragePersistence(key = 'energy-state') {
|
|
25
|
+
return {
|
|
26
|
+
async load() {
|
|
27
|
+
if (typeof localStorage === 'undefined') {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
const raw = localStorage.getItem(key);
|
|
31
|
+
return parsePersistedState(raw);
|
|
32
|
+
},
|
|
33
|
+
async save(state) {
|
|
34
|
+
try {
|
|
35
|
+
localStorage.setItem(key, JSON.stringify(state));
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
// Rejecting (instead of swallowing) lets the engine's persistence
|
|
39
|
+
// queue observe the failure and retry with backoff. This also covers
|
|
40
|
+
// environments without localStorage (ReferenceError).
|
|
41
|
+
throw new Error(`Failed to save energy state to localStorage key '${key}'`, { cause: err });
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
observe(onState) {
|
|
45
|
+
if (typeof globalThis.addEventListener !== 'function' ||
|
|
46
|
+
typeof localStorage === 'undefined') {
|
|
47
|
+
return () => { };
|
|
48
|
+
}
|
|
49
|
+
const handleStorage = (event) => {
|
|
50
|
+
if (event.storageArea !== localStorage)
|
|
51
|
+
return;
|
|
52
|
+
if (event.key !== key)
|
|
53
|
+
return;
|
|
54
|
+
const parsed = parsePersistedState(event.newValue);
|
|
55
|
+
if (parsed) {
|
|
56
|
+
onState(parsed);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
globalThis.addEventListener('storage', handleStorage);
|
|
60
|
+
return () => {
|
|
61
|
+
globalThis.removeEventListener('storage', handleStorage);
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* In-memory persistence adapter.
|
|
68
|
+
* Useful for tests, SSR, or ephemeral sessions.
|
|
69
|
+
*/
|
|
70
|
+
export function memoryPersistence(initial) {
|
|
71
|
+
let stored = initial === undefined
|
|
72
|
+
? null
|
|
73
|
+
: createEnergyState(initial.level, initial.source, initial.timestamp);
|
|
74
|
+
const listeners = new Set();
|
|
75
|
+
return {
|
|
76
|
+
async load() {
|
|
77
|
+
return stored;
|
|
78
|
+
},
|
|
79
|
+
async save(state) {
|
|
80
|
+
stored = createEnergyState(state.level, state.source, state.timestamp);
|
|
81
|
+
for (const listener of listeners) {
|
|
82
|
+
listener(stored);
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
observe(onState) {
|
|
86
|
+
listeners.add(onState);
|
|
87
|
+
return () => {
|
|
88
|
+
listeners.delete(onState);
|
|
89
|
+
};
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=persistence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persistence.js","sourceRoot":"","sources":["../src/persistence.ts"],"names":[],"mappings":"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"}
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { EnergyEngine } from './engine.js';
|
|
2
|
+
import type { AdaptationStrategy, EnergyChangeListener, EnergyLevel, EnergyLevelDefinition, EnergyPersistence, EnergyState } from './types.js';
|
|
3
|
+
export interface EnergyProviderProps {
|
|
4
|
+
/** Pre-created engine. When provided, this engine is used directly. */
|
|
5
|
+
engine?: EnergyEngine;
|
|
6
|
+
/** Initial energy level when the provider creates its own engine. */
|
|
7
|
+
defaultLevel?: EnergyLevel;
|
|
8
|
+
/** Persistence adapter when the provider creates its own engine. */
|
|
9
|
+
persistence?: EnergyPersistence;
|
|
10
|
+
/** Called on every level change. */
|
|
11
|
+
onLevelChange?: EnergyChangeListener;
|
|
12
|
+
/** Whether to apply energy level to DOM via data attributes */
|
|
13
|
+
applyToDOM?: boolean;
|
|
14
|
+
children: React.ReactNode;
|
|
15
|
+
}
|
|
16
|
+
export declare function EnergyProvider({ engine: externalEngine, defaultLevel, persistence, onLevelChange, applyToDOM, children, }: EnergyProviderProps): import("react").FunctionComponentElement<import("react").ProviderProps<EnergyEngine | null>>;
|
|
17
|
+
/** Get the full energy state (level + timestamp + source) */
|
|
18
|
+
export declare function useEnergyState(): EnergyState;
|
|
19
|
+
/** Read the current energy level and setter */
|
|
20
|
+
export declare function useEnergyLevel(): [EnergyLevel, (level: EnergyLevel) => void];
|
|
21
|
+
/** @deprecated Use useEnergyState instead. */
|
|
22
|
+
export declare function useFullEnergyState(): EnergyState;
|
|
23
|
+
/** Returns a function that cycles to the next energy level */
|
|
24
|
+
export declare function useEnergyLevelCycler(): () => void;
|
|
25
|
+
/** Resolve a strategy against current energy level */
|
|
26
|
+
export declare function useStrategy<T>(strategy: AdaptationStrategy<T>): T;
|
|
27
|
+
/** Returns true if current energy level meets or exceeds the given minimum */
|
|
28
|
+
export declare function useEnergyGate(minLevel: EnergyLevel): boolean;
|
|
29
|
+
export interface EnergyIndicatorRenderProps {
|
|
30
|
+
level: EnergyLevel;
|
|
31
|
+
label: string;
|
|
32
|
+
description: string;
|
|
33
|
+
cognitiveProfile: EnergyLevelDefinition['cognitiveProfile'];
|
|
34
|
+
state: EnergyState;
|
|
35
|
+
definition: EnergyLevelDefinition;
|
|
36
|
+
levels: readonly EnergyLevelDefinition[];
|
|
37
|
+
cycle: () => void;
|
|
38
|
+
setLevel: (level: EnergyLevel) => void;
|
|
39
|
+
}
|
|
40
|
+
export interface EnergyIndicatorProps {
|
|
41
|
+
children: (props: EnergyIndicatorRenderProps) => React.ReactNode;
|
|
42
|
+
}
|
|
43
|
+
/** Headless energy indicator - bring your own UI */
|
|
44
|
+
export declare function EnergyIndicator({ children }: EnergyIndicatorProps): React.ReactNode;
|
|
45
|
+
//# sourceMappingURL=react.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAG/C,OAAO,KAAK,EACV,kBAAkB,EAClB,oBAAoB,EACpB,WAAW,EACX,qBAAqB,EACrB,iBAAiB,EACjB,WAAW,EACZ,MAAM,YAAY,CAAA;AAcnB,MAAM,WAAW,mBAAmB;IAClC,uEAAuE;IACvE,MAAM,CAAC,EAAE,YAAY,CAAA;IACrB,qEAAqE;IACrE,YAAY,CAAC,EAAE,WAAW,CAAA;IAC1B,oEAAoE;IACpE,WAAW,CAAC,EAAE,iBAAiB,CAAA;IAC/B,oCAAoC;IACpC,aAAa,CAAC,EAAE,oBAAoB,CAAA;IACpC,+DAA+D;IAC/D,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B;AAED,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EAAE,cAAc,EACtB,YAAkB,EAClB,WAAW,EACX,aAAa,EACb,UAAiB,EACjB,QAAQ,GACT,EAAE,mBAAmB,gGA8DrB;AAmBD,6DAA6D;AAC7D,wBAAgB,cAAc,IAAI,WAAW,CAE5C;AAED,+CAA+C;AAC/C,wBAAgB,cAAc,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC,CAU5E;AAED,8CAA8C;AAC9C,wBAAgB,kBAAkB,IAAI,WAAW,CAEhD;AAED,8DAA8D;AAC9D,wBAAgB,oBAAoB,IAAI,MAAM,IAAI,CAKjD;AAED,sDAAsD;AACtD,wBAAgB,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAAG,CAAC,CAGjE;AAED,8EAA8E;AAC9E,wBAAgB,aAAa,CAAC,QAAQ,EAAE,WAAW,GAAG,OAAO,CAG5D;AAID,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,WAAW,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,gBAAgB,EAAE,qBAAqB,CAAC,kBAAkB,CAAC,CAAA;IAC3D,KAAK,EAAE,WAAW,CAAA;IAClB,UAAU,EAAE,qBAAqB,CAAA;IACjC,MAAM,EAAE,SAAS,qBAAqB,EAAE,CAAA;IACxC,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAA;CACvC;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,CAAC,KAAK,EAAE,0BAA0B,KAAK,KAAK,CAAC,SAAS,CAAA;CACjE;AAED,oDAAoD;AACpD,wBAAgB,eAAe,CAAC,EAAE,QAAQ,EAAE,EAAE,oBAAoB,GAAG,KAAK,CAAC,SAAS,CAmBnF"}
|