@harmonia-core/ui 1.2.9 → 1.2.12
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/dist/capacity/index.js +517 -12
- package/dist/capacity/index.js.map +1 -1
- package/dist/capacity/index.mjs +509 -4
- package/dist/capacity/index.mjs.map +1 -1
- package/dist/capacity/provider.d.ts +1 -1
- package/dist/capacity/provider.d.ts.map +1 -1
- package/dist/components/ambient-field-monitor.d.ts +1 -1
- package/dist/components/ambient-field-monitor.d.ts.map +1 -1
- package/dist/components/capacity-controls.d.ts +1 -1
- package/dist/components/capacity-controls.d.ts.map +1 -1
- package/dist/components/capacity-demo-card.d.ts +1 -1
- package/dist/components/capacity-demo-card.d.ts.map +1 -1
- package/dist/components/ui/badge.d.ts +1 -1
- package/dist/components/ui/badge.d.ts.map +1 -1
- package/dist/components/ui/button.d.ts +1 -1
- package/dist/components/ui/button.d.ts.map +1 -1
- package/dist/components/ui/card.d.ts +7 -7
- package/dist/components/ui/card.d.ts.map +1 -1
- package/dist/components/ui/select.d.ts +1 -1
- package/dist/components/ui/select.d.ts.map +1 -1
- package/dist/components/ui/slider.d.ts +1 -1
- package/dist/components/ui/slider.d.ts.map +1 -1
- package/package.json +4 -4
- package/dist/aggregator-M6X5XUQY.js +0 -475
- package/dist/aggregator-M6X5XUQY.js.map +0 -1
- package/dist/aggregator-TH7FATMR.mjs +0 -473
- package/dist/aggregator-TH7FATMR.mjs.map +0 -1
- package/dist/chunk-E3LOUS7X.mjs +0 -43
- package/dist/chunk-E3LOUS7X.mjs.map +0 -1
- package/dist/chunk-JPRRZPBL.js +0 -47
- package/dist/chunk-JPRRZPBL.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../lib/capacity/signals/detectors/time-detector.ts","../lib/capacity/signals/detectors/session-detector.ts","../lib/capacity/signals/detectors/scroll-detector.ts","../lib/capacity/signals/detectors/interaction-detector.ts","../lib/capacity/signals/detectors/input-detector.ts","../lib/capacity/signals/detectors/environment-detector.ts","../lib/capacity/signals/aggregator.ts"],"names":["__async"],"mappings":"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","file":"aggregator-M6X5XUQY.js","sourcesContent":["/**\n * @file Implements a signal detector for time-based capacity.\n * Emits two readings per detect() call: cognitive (hour-of-day diurnal pattern)\n * and temporal (weekday vs. weekend).\n */\n\nimport { SignalDetector, SignalReading } from './types';\n\n/**\n * The TimeDetector class implements the SignalDetector interface\n * to provide signal readings based on the current time and day.\n */\nexport class TimeDetector implements SignalDetector {\n readonly name = 'TimeDetector';\n readonly weight = 0.6; // Medium weight — time is significant but a broad generalisation\n\n /**\n * Detects and returns SignalReadings based on the current time and day.\n * Returns two readings: cognitive (hour-of-day) and temporal (weekday/weekend).\n */\n detect(): SignalReading[] {\n const now = new Date();\n const hour = now.getHours();\n const dayOfWeek = now.getDay(); // 0 = Sunday, 6 = Saturday\n const ts = now.getTime();\n\n // ── Cognitive capacity: typical diurnal patterns ────────────────────────\n let cognitiveValue: number;\n if (hour >= 9 && hour < 12) {\n cognitiveValue = 0.8; // Morning peak\n } else if (hour >= 14 && hour < 17) {\n cognitiveValue = 0.6; // Afternoon dip\n } else if (hour >= 17 && hour < 20) {\n cognitiveValue = 0.5; // Evening, winding down\n } else if (hour >= 20 || hour < 6) {\n cognitiveValue = 0.3; // Late night / early morning\n } else {\n cognitiveValue = 0.7; // Early morning ramp-up (6–9am)\n }\n\n // ── Temporal capacity: weekday vs. weekend ──────────────────────────────\n const temporalValue = (dayOfWeek >= 1 && dayOfWeek <= 5) ? 0.7 : 0.9;\n // Weekends tend to feel less time-pressured → higher temporal capacity\n\n return [\n {\n dimension: 'cognitive',\n value: cognitiveValue,\n confidence: 0.7, // Medium — population average, not personalised\n timestamp: ts,\n detectorName: this.name,\n },\n {\n dimension: 'temporal',\n value: temporalValue,\n confidence: 0.6, // Slightly lower — weekday/weekend is a coarser signal\n timestamp: ts,\n detectorName: this.name,\n },\n ];\n }\n}\n","/**\n * @file Implements a signal detector for session duration.\n * This detector assesses temporal capacity based on how long the user has been active in the current session.\n */\n\nimport { SignalDetector, SignalReading } from './types';\n\n/**\n * The SessionDetector class implements the SignalDetector interface\n * to provide signal readings based on the current session duration.\n */\nexport class SessionDetector implements SignalDetector {\n readonly name = 'SessionDetector';\n readonly weight = 0.7; // Medium-high weight, as session duration can significantly impact capacity\n private sessionStartTime: number;\n\n constructor() {\n this.sessionStartTime = Date.now();\n }\n\n /**\n * Detects and returns a SignalReading based on the current session duration.\n * It provides insights into the temporal dimension.\n *\n * @returns {SignalReading} A reading indicating the inferred capacity.\n */\n detect(): SignalReading[] {\n const now = Date.now();\n const sessionDurationMinutes = (now - this.sessionStartTime) / (1000 * 60);\n\n let temporalValue: number;\n let confidence: number;\n\n // Temporal capacity inference based on session duration\n if (sessionDurationMinutes < 15) {\n temporalValue = 0.9; // High capacity, just started\n confidence = 0.8;\n } else if (sessionDurationMinutes < 60) {\n temporalValue = 0.7; // Moderate capacity, sustained engagement\n confidence = 0.7;\n } else if (sessionDurationMinutes < 180) {\n temporalValue = 0.5; // Lower capacity, potential fatigue\n confidence = 0.6;\n } else {\n temporalValue = 0.3; // Significantly lower capacity, extended use\n confidence = 0.7;\n }\n\n return [{\n dimension: 'temporal',\n value: temporalValue,\n confidence: confidence,\n timestamp: now,\n detectorName: this.name,\n }];\n }\n}\n","/**\n * @file Implements a signal detector for scroll velocity.\n * This detector assesses cognitive capacity based on the user's scrolling behavior.\n */\n\nimport { SignalDetector, SignalReading } from './types';\n\nconst DEBOUNCE_TIME_MS = 100; // Milliseconds to debounce scroll events\n\n/**\n * The ScrollDetector class implements the SignalDetector interface\n * to provide signal readings based on scroll velocity.\n */\nexport class ScrollDetector implements SignalDetector {\n readonly name = 'ScrollDetector';\n readonly weight = 0.5; // Moderate weight, as scroll velocity can indicate engagement or frustration\n\n private lastScrollY = 0;\n private lastScrollTime = 0;\n private scrollVelocity = 0;\n private timeoutId: NodeJS.Timeout | null = null;\n\n constructor() {\n if (typeof window !== 'undefined') {\n window.addEventListener('scroll', this.handleScroll, { passive: true });\n }\n }\n\n /**\n * Handles the scroll event, debouncing it and calculating scroll velocity.\n * @private\n */\n private handleScroll = () => {\n if (this.timeoutId) {\n clearTimeout(this.timeoutId);\n }\n\n this.timeoutId = setTimeout(() => {\n const now = Date.now();\n const scrollY = window.scrollY;\n\n const distance = Math.abs(scrollY - this.lastScrollY);\n const timeElapsed = now - this.lastScrollTime;\n\n if (timeElapsed > 0) {\n // Pixels per second\n this.scrollVelocity = (distance / timeElapsed) * 1000;\n } else {\n this.scrollVelocity = 0;\n }\n\n this.lastScrollY = scrollY;\n this.lastScrollTime = now;\n }, DEBOUNCE_TIME_MS);\n };\n\n /**\n * Detects and returns a SignalReading based on the current scroll velocity.\n * It provides insights into the cognitive dimension.\n *\n * @returns {SignalReading} A reading indicating the inferred capacity.\n */\n detect(): SignalReading[] {\n const now = Date.now();\n let cognitiveValue: number;\n let confidence: number;\n\n // Interpret scroll velocity: very fast/slow could indicate issues, moderate is normal\n if (this.scrollVelocity > 1500) {\n cognitiveValue = 0.4; // Very fast scroll, possibly disengaged or frantically searching\n confidence = 0.6;\n } else if (this.scrollVelocity > 500) {\n cognitiveValue = 0.7; // Moderate scroll, engaged browsing\n confidence = 0.8;\n } else if (this.scrollVelocity > 50) {\n cognitiveValue = 0.6; // Slow scroll, careful reading or struggling\n confidence = 0.7;\n } else {\n cognitiveValue = 0.5; // Very slow or no scroll, idle or deeply focused\n confidence = 0.5;\n }\n\n return [{\n dimension: 'cognitive',\n value: cognitiveValue,\n confidence: confidence,\n timestamp: now,\n detectorName: this.name,\n }];\n }\n\n /**\n * Cleans up the scroll event listener when the detector is no longer needed.\n */\n destroy() {\n if (typeof window !== 'undefined') {\n window.removeEventListener('scroll', this.handleScroll);\n if (this.timeoutId) {\n clearTimeout(this.timeoutId);\n }\n }\n }\n}\n","/**\n * @file Implements a signal detector for user interaction patterns.\n * Assesses cognitive capacity from click rate and precision using a rolling window.\n *\n * Bug fixes vs. original:\n * - clickCount / totalClickDistance accumulated forever → replaced with a 60-second\n * rolling window so recent behaviour dominates over historical averages.\n * - IDLE_THRESHOLD_MS was 3 s (too aggressive for focused reading) → raised to 15 s.\n */\n\nimport { SignalDetector, SignalReading } from './types';\n\nconst DEBOUNCE_MOVE_TIME_MS = 50;\nconst IDLE_THRESHOLD_MS = 15_000; // 15 s — focused readers pause longer than 3 s\nconst CLICK_WINDOW_MS = 60_000; // 60 s rolling window for click history\n\ninterface ClickEntry {\n time: number;\n distance: number; // px distance from previous click position\n}\n\nexport class InteractionDetector implements SignalDetector {\n readonly name = 'InteractionDetector';\n readonly weight = 0.7;\n\n private lastMouseMoveTime = 0;\n private lastClickTime = 0;\n private lastClickPosition: { x: number; y: number } | null = null;\n private clickHistory: ClickEntry[] = []; // rolling 60-second window\n private idleTimer: ReturnType<typeof setTimeout> | null = null;\n private isIdle = false;\n\n constructor() {\n if (typeof window !== 'undefined') {\n window.addEventListener('mousemove', this.handleMouseMove, { passive: true });\n window.addEventListener('click', this.handleClick, { passive: true });\n }\n this.resetIdleTimer();\n }\n\n private resetIdleTimer = () => {\n if (this.idleTimer) clearTimeout(this.idleTimer);\n this.isIdle = false;\n this.idleTimer = setTimeout(() => { this.isIdle = true; }, IDLE_THRESHOLD_MS);\n };\n\n private handleMouseMove = () => {\n this.lastMouseMoveTime = Date.now();\n this.resetIdleTimer();\n };\n\n private handleClick = (event: MouseEvent) => {\n this.resetIdleTimer();\n const now = Date.now();\n this.lastClickTime = now;\n\n let distance = 0;\n if (this.lastClickPosition) {\n const dx = event.clientX - this.lastClickPosition.x;\n const dy = event.clientY - this.lastClickPosition.y;\n distance = Math.sqrt(dx * dx + dy * dy);\n }\n this.lastClickPosition = { x: event.clientX, y: event.clientY };\n this.clickHistory.push({ time: now, distance });\n };\n\n detect(): SignalReading[] {\n const now = Date.now();\n\n // Prune entries outside the rolling window\n const cutoff = now - CLICK_WINDOW_MS;\n this.clickHistory = this.clickHistory.filter(c => c.time >= cutoff);\n\n const clickCount = this.clickHistory.length;\n const avgClickDistance =\n clickCount > 0\n ? this.clickHistory.reduce((sum, c) => sum + c.distance, 0) / clickCount\n : 0;\n\n const timeSinceLastClick = now - this.lastClickTime;\n\n let cognitiveValue: number;\n let confidence: number;\n\n if (this.isIdle) {\n cognitiveValue = 0.4; // Idle: disengaged or deeply thinking\n confidence = 0.6;\n } else if (timeSinceLastClick < 500 && clickCount > 5 && avgClickDistance < 20) {\n cognitiveValue = 0.9; // Highly engaged: frequent, precise clicks\n confidence = 0.9;\n } else if (timeSinceLastClick < 1500 && clickCount > 1 && avgClickDistance < 50) {\n cognitiveValue = 0.7; // Moderately engaged\n confidence = 0.7;\n } else if (avgClickDistance > 100) {\n cognitiveValue = 0.3; // Low precision: possibly frustrated or impaired\n confidence = 0.6;\n } else {\n cognitiveValue = 0.5; // Ambiguous / default\n confidence = 0.5;\n }\n\n return [{\n dimension: 'cognitive',\n value: cognitiveValue,\n confidence,\n timestamp: now,\n detectorName: this.name,\n }];\n }\n\n destroy() {\n if (typeof window !== 'undefined') {\n window.removeEventListener('mousemove', this.handleMouseMove);\n window.removeEventListener('click', this.handleClick);\n }\n if (this.idleTimer) clearTimeout(this.idleTimer);\n }\n}\n","/**\n * @file Implements a signal detector for user input patterns (typing speed + error rate).\n * Assesses cognitive capacity based on typing behaviour.\n *\n * Bug fix vs. original:\n * - errorCount / lastErrorTime tracked errors since an arbitrary past reset; old\n * errors counted the same as current ones → replaced with an errorTimes[] sliding\n * window so only errors within ERROR_CHECK_WINDOW (5 s) are counted.\n * - Inference now uses recentErrorCount (integer) instead of a boolean, letting the\n * code distinguish a single correction from repeated fumbling.\n */\n\nimport { SignalDetector, SignalReading } from './types';\n\nconst TYPING_SPEED_SAMPLE_SIZE = 10; // Key presses to average for CPM calculation\nconst ERROR_CHECK_WINDOW = 5_000; // ms: only count errors in this sliding window\n\nexport class InputDetector implements SignalDetector {\n readonly name = 'InputDetector';\n readonly weight = 0.6;\n\n private keyPressTimes: number[] = [];\n private errorTimes: number[] = []; // timestamps of recent Backspace/Delete presses\n\n constructor() {\n if (typeof window !== 'undefined') {\n window.addEventListener('keydown', this.handleKeyDown, { passive: true });\n }\n }\n\n private handleKeyDown = (event: KeyboardEvent) => {\n const now = Date.now();\n\n this.keyPressTimes.push(now);\n if (this.keyPressTimes.length > TYPING_SPEED_SAMPLE_SIZE) {\n this.keyPressTimes.shift();\n }\n\n if (event.key === 'Backspace' || event.key === 'Delete') {\n this.errorTimes.push(now);\n }\n };\n\n detect(): SignalReading[] {\n const now = Date.now();\n\n // ── Typing speed (characters per minute) ───────────────────────────────\n let typingSpeedCPM = 0;\n if (this.keyPressTimes.length > 1) {\n const elapsed = this.keyPressTimes[this.keyPressTimes.length - 1] - this.keyPressTimes[0];\n if (elapsed > 0) {\n typingSpeedCPM = (this.keyPressTimes.length / elapsed) * 60_000;\n }\n }\n\n // ── Recent error count (sliding window) ────────────────────────────────\n const cutoff = now - ERROR_CHECK_WINDOW;\n this.errorTimes = this.errorTimes.filter(t => t >= cutoff);\n const recentErrorCount = this.errorTimes.length;\n\n // ── Cognitive inference ─────────────────────────────────────────────────\n let cognitiveValue: number;\n let confidence: number;\n\n if (typingSpeedCPM > 100 && recentErrorCount === 0) {\n cognitiveValue = 0.9; // Fast + accurate → high cognitive capacity\n confidence = 0.8;\n } else if (typingSpeedCPM > 40 && recentErrorCount <= 1) {\n cognitiveValue = 0.7; // Moderate speed, minimal errors\n confidence = 0.7;\n } else if (recentErrorCount > 2 || typingSpeedCPM < 20) {\n cognitiveValue = 0.4; // Repeated errors or very slow → lower capacity\n confidence = 0.6;\n } else {\n cognitiveValue = 0.6; // Ambiguous / default\n confidence = 0.5;\n }\n\n return [{\n dimension: 'cognitive',\n value: cognitiveValue,\n confidence,\n timestamp: now,\n detectorName: this.name,\n }];\n }\n\n destroy() {\n if (typeof window !== 'undefined') {\n window.removeEventListener('keydown', this.handleKeyDown);\n }\n }\n}\n","/**\n * @file Implements signal detectors for environmental preferences.\n * Reads prefers-reduced-motion (→ temporal) and prefers-color-scheme (→ emotional).\n *\n * Bug fixes vs. original:\n * - Memory leak: stored MediaQueryList refs so removeEventListener unregisters the\n * exact same handler that was registered (arrow-function class properties create a\n * new reference on each access, so calling this.detect would never unregister).\n * - Discarded temporal dimension: now returns both temporal and emotional readings.\n */\n\nimport { SignalDetector, SignalReading } from './types';\n\nexport class EnvironmentDetector implements SignalDetector {\n readonly name = 'EnvironmentDetector';\n readonly weight = 0.8; // High weight — these are explicit user preferences\n\n private mqlReducedMotion: MediaQueryList | null = null;\n private mqlDarkMode: MediaQueryList | null = null;\n // A single stable handler reference that both addEventListener and\n // removeEventListener receive. detect() is stateless so the handler is a\n // no-op: the aggregator polls detect() on its own 2-second schedule.\n private readonly handleChange: () => void;\n\n constructor() {\n this.handleChange = () => {};\n if (typeof window !== 'undefined') {\n this.mqlReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)');\n this.mqlDarkMode = window.matchMedia('(prefers-color-scheme: dark)');\n this.mqlReducedMotion.addEventListener('change', this.handleChange);\n this.mqlDarkMode.addEventListener('change', this.handleChange);\n }\n }\n\n /**\n * Returns two readings:\n * - temporal: based on prefers-reduced-motion (low → less time pressure on animations)\n * - emotional: based on prefers-color-scheme (dark → slightly lower emotional load)\n */\n detect(): SignalReading[] {\n const now = Date.now();\n\n // Use stored refs for efficiency; fall back to fresh queries on SSR or if\n // the constructor ran without a window (e.g. jest with no matchMedia stub).\n const prefersReducedMotion =\n this.mqlReducedMotion != null\n ? this.mqlReducedMotion.matches\n : typeof window !== 'undefined' &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n\n const prefersDarkMode =\n this.mqlDarkMode != null\n ? this.mqlDarkMode.matches\n : typeof window !== 'undefined' &&\n window.matchMedia('(prefers-color-scheme: dark)').matches;\n\n return [\n {\n dimension: 'temporal',\n // prefers-reduced-motion → user may have lower tolerance for demanding UIs\n value: prefersReducedMotion ? 0.3 : 0.8,\n confidence: 0.9,\n timestamp: now,\n detectorName: this.name,\n },\n {\n dimension: 'emotional',\n // Dark mode preference → slightly lower emotional capacity or reduced-stimulation preference\n value: prefersDarkMode ? 0.6 : 0.7,\n confidence: 0.9,\n timestamp: now,\n detectorName: this.name,\n },\n ];\n }\n\n /**\n * Removes the event listeners registered in the constructor.\n * Uses the stored refs so the same function reference is unregistered.\n */\n destroy() {\n this.mqlReducedMotion?.removeEventListener('change', this.handleChange);\n this.mqlDarkMode?.removeEventListener('change', this.handleChange);\n this.mqlReducedMotion = null;\n this.mqlDarkMode = null;\n }\n}\n","/**\n * @file Aggregates signals from all detectors into a suggested CapacityField.\n *\n * Bug fixes vs. original:\n * - detect() now returns SignalReading[] so readings.push(...) spreads the array.\n * - getDetectorWeight() now uses a per-detector/dimension lookup table instead of\n * ignoring the dimension parameter.\n * - destroy() uses the optional-chaining destroy?() instead of (detector as any).destroy().\n */\n\nimport { SignalDetector, SignalReading } from './detectors/types';\nimport { CapacityField } from '../types';\nimport { TimeDetector } from './detectors/time-detector';\nimport { SessionDetector } from './detectors/session-detector';\nimport { ScrollDetector } from './detectors/scroll-detector';\nimport { InteractionDetector } from './detectors/interaction-detector';\nimport { InputDetector } from './detectors/input-detector';\nimport { EnvironmentDetector } from './detectors/environment-detector';\n\nexport class SignalAggregator {\n private detectors: SignalDetector[];\n\n /**\n * Per-detector, per-dimension weight overrides.\n * Falls back to detector.weight for any unlisted combination.\n *\n * Rationale for asymmetries:\n * - TimeDetector: cognitive signal is stronger (diurnal pattern) than temporal\n * (weekday/weekend is coarser)\n * - EnvironmentDetector: emotional signal (color scheme) is a stronger explicit\n * preference than temporal (reduced-motion)\n */\n private static readonly DIMENSION_WEIGHTS: Partial<\n Record<string, Partial<Record<SignalReading['dimension'], number>>>\n > = {\n TimeDetector: { cognitive: 0.6, temporal: 0.5 },\n EnvironmentDetector: { emotional: 0.8, temporal: 0.7 },\n InteractionDetector: { cognitive: 0.7 },\n InputDetector: { cognitive: 0.6 },\n SessionDetector: { temporal: 0.7 },\n ScrollDetector: { cognitive: 0.5 },\n };\n\n constructor() {\n this.detectors = [\n new TimeDetector(),\n new SessionDetector(),\n new ScrollDetector(),\n new InteractionDetector(),\n new InputDetector(),\n new EnvironmentDetector(),\n ];\n }\n\n /**\n * Collects signal readings from all detectors and aggregates them into a\n * confidence-weighted CapacityField.\n */\n async aggregateSignals(): Promise<CapacityField> {\n const readings: SignalReading[] = [];\n\n for (const detector of this.detectors) {\n const detectorReadings = await detector.detect();\n readings.push(...detectorReadings);\n }\n\n const weightedSums: Record<SignalReading['dimension'], number> = {\n cognitive: 0, temporal: 0, emotional: 0, valence: 0,\n };\n const totalWeights: Record<SignalReading['dimension'], number> = {\n cognitive: 0, temporal: 0, emotional: 0, valence: 0,\n };\n\n for (const reading of readings) {\n const effectiveWeight =\n reading.confidence * this.getDetectorWeight(reading.dimension, reading.detectorName);\n weightedSums[reading.dimension] += reading.value * effectiveWeight;\n totalWeights[reading.dimension] += effectiveWeight;\n }\n\n return {\n cognitive: totalWeights.cognitive > 0 ? weightedSums.cognitive / totalWeights.cognitive : 0.5,\n temporal: totalWeights.temporal > 0 ? weightedSums.temporal / totalWeights.temporal : 0.5,\n emotional: totalWeights.emotional > 0 ? weightedSums.emotional / totalWeights.emotional : 0.5,\n valence: totalWeights.valence > 0 ? weightedSums.valence / totalWeights.valence : 0,\n };\n }\n\n /**\n * Returns the effective weight for a detector/dimension pair.\n * Checks DIMENSION_WEIGHTS first; falls back to detector.weight.\n */\n private getDetectorWeight(\n dimension: SignalReading['dimension'],\n detectorName: string,\n ): number {\n const override = SignalAggregator.DIMENSION_WEIGHTS[detectorName]?.[dimension];\n if (override !== undefined) return override;\n return this.detectors.find(d => d.name === detectorName)?.weight ?? 0;\n }\n\n /** Cleans up all detector resources (event listeners, timers). */\n destroy() {\n for (const detector of this.detectors) {\n detector.destroy?.();\n }\n }\n}\n"]}
|
|
@@ -1,473 +0,0 @@
|
|
|
1
|
-
import { __async } from './chunk-E3LOUS7X.mjs';
|
|
2
|
-
|
|
3
|
-
// lib/capacity/signals/detectors/time-detector.ts
|
|
4
|
-
var TimeDetector = class {
|
|
5
|
-
constructor() {
|
|
6
|
-
this.name = "TimeDetector";
|
|
7
|
-
this.weight = 0.6;
|
|
8
|
-
}
|
|
9
|
-
// Medium weight — time is significant but a broad generalisation
|
|
10
|
-
/**
|
|
11
|
-
* Detects and returns SignalReadings based on the current time and day.
|
|
12
|
-
* Returns two readings: cognitive (hour-of-day) and temporal (weekday/weekend).
|
|
13
|
-
*/
|
|
14
|
-
detect() {
|
|
15
|
-
const now = /* @__PURE__ */ new Date();
|
|
16
|
-
const hour = now.getHours();
|
|
17
|
-
const dayOfWeek = now.getDay();
|
|
18
|
-
const ts = now.getTime();
|
|
19
|
-
let cognitiveValue;
|
|
20
|
-
if (hour >= 9 && hour < 12) {
|
|
21
|
-
cognitiveValue = 0.8;
|
|
22
|
-
} else if (hour >= 14 && hour < 17) {
|
|
23
|
-
cognitiveValue = 0.6;
|
|
24
|
-
} else if (hour >= 17 && hour < 20) {
|
|
25
|
-
cognitiveValue = 0.5;
|
|
26
|
-
} else if (hour >= 20 || hour < 6) {
|
|
27
|
-
cognitiveValue = 0.3;
|
|
28
|
-
} else {
|
|
29
|
-
cognitiveValue = 0.7;
|
|
30
|
-
}
|
|
31
|
-
const temporalValue = dayOfWeek >= 1 && dayOfWeek <= 5 ? 0.7 : 0.9;
|
|
32
|
-
return [
|
|
33
|
-
{
|
|
34
|
-
dimension: "cognitive",
|
|
35
|
-
value: cognitiveValue,
|
|
36
|
-
confidence: 0.7,
|
|
37
|
-
// Medium — population average, not personalised
|
|
38
|
-
timestamp: ts,
|
|
39
|
-
detectorName: this.name
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
dimension: "temporal",
|
|
43
|
-
value: temporalValue,
|
|
44
|
-
confidence: 0.6,
|
|
45
|
-
// Slightly lower — weekday/weekend is a coarser signal
|
|
46
|
-
timestamp: ts,
|
|
47
|
-
detectorName: this.name
|
|
48
|
-
}
|
|
49
|
-
];
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
// lib/capacity/signals/detectors/session-detector.ts
|
|
54
|
-
var SessionDetector = class {
|
|
55
|
-
constructor() {
|
|
56
|
-
this.name = "SessionDetector";
|
|
57
|
-
this.weight = 0.7;
|
|
58
|
-
this.sessionStartTime = Date.now();
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Detects and returns a SignalReading based on the current session duration.
|
|
62
|
-
* It provides insights into the temporal dimension.
|
|
63
|
-
*
|
|
64
|
-
* @returns {SignalReading} A reading indicating the inferred capacity.
|
|
65
|
-
*/
|
|
66
|
-
detect() {
|
|
67
|
-
const now = Date.now();
|
|
68
|
-
const sessionDurationMinutes = (now - this.sessionStartTime) / (1e3 * 60);
|
|
69
|
-
let temporalValue;
|
|
70
|
-
let confidence;
|
|
71
|
-
if (sessionDurationMinutes < 15) {
|
|
72
|
-
temporalValue = 0.9;
|
|
73
|
-
confidence = 0.8;
|
|
74
|
-
} else if (sessionDurationMinutes < 60) {
|
|
75
|
-
temporalValue = 0.7;
|
|
76
|
-
confidence = 0.7;
|
|
77
|
-
} else if (sessionDurationMinutes < 180) {
|
|
78
|
-
temporalValue = 0.5;
|
|
79
|
-
confidence = 0.6;
|
|
80
|
-
} else {
|
|
81
|
-
temporalValue = 0.3;
|
|
82
|
-
confidence = 0.7;
|
|
83
|
-
}
|
|
84
|
-
return [{
|
|
85
|
-
dimension: "temporal",
|
|
86
|
-
value: temporalValue,
|
|
87
|
-
confidence,
|
|
88
|
-
timestamp: now,
|
|
89
|
-
detectorName: this.name
|
|
90
|
-
}];
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
// lib/capacity/signals/detectors/scroll-detector.ts
|
|
95
|
-
var DEBOUNCE_TIME_MS = 100;
|
|
96
|
-
var ScrollDetector = class {
|
|
97
|
-
constructor() {
|
|
98
|
-
this.name = "ScrollDetector";
|
|
99
|
-
this.weight = 0.5;
|
|
100
|
-
// Moderate weight, as scroll velocity can indicate engagement or frustration
|
|
101
|
-
this.lastScrollY = 0;
|
|
102
|
-
this.lastScrollTime = 0;
|
|
103
|
-
this.scrollVelocity = 0;
|
|
104
|
-
this.timeoutId = null;
|
|
105
|
-
/**
|
|
106
|
-
* Handles the scroll event, debouncing it and calculating scroll velocity.
|
|
107
|
-
* @private
|
|
108
|
-
*/
|
|
109
|
-
this.handleScroll = () => {
|
|
110
|
-
if (this.timeoutId) {
|
|
111
|
-
clearTimeout(this.timeoutId);
|
|
112
|
-
}
|
|
113
|
-
this.timeoutId = setTimeout(() => {
|
|
114
|
-
const now = Date.now();
|
|
115
|
-
const scrollY = window.scrollY;
|
|
116
|
-
const distance = Math.abs(scrollY - this.lastScrollY);
|
|
117
|
-
const timeElapsed = now - this.lastScrollTime;
|
|
118
|
-
if (timeElapsed > 0) {
|
|
119
|
-
this.scrollVelocity = distance / timeElapsed * 1e3;
|
|
120
|
-
} else {
|
|
121
|
-
this.scrollVelocity = 0;
|
|
122
|
-
}
|
|
123
|
-
this.lastScrollY = scrollY;
|
|
124
|
-
this.lastScrollTime = now;
|
|
125
|
-
}, DEBOUNCE_TIME_MS);
|
|
126
|
-
};
|
|
127
|
-
if (typeof window !== "undefined") {
|
|
128
|
-
window.addEventListener("scroll", this.handleScroll, { passive: true });
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Detects and returns a SignalReading based on the current scroll velocity.
|
|
133
|
-
* It provides insights into the cognitive dimension.
|
|
134
|
-
*
|
|
135
|
-
* @returns {SignalReading} A reading indicating the inferred capacity.
|
|
136
|
-
*/
|
|
137
|
-
detect() {
|
|
138
|
-
const now = Date.now();
|
|
139
|
-
let cognitiveValue;
|
|
140
|
-
let confidence;
|
|
141
|
-
if (this.scrollVelocity > 1500) {
|
|
142
|
-
cognitiveValue = 0.4;
|
|
143
|
-
confidence = 0.6;
|
|
144
|
-
} else if (this.scrollVelocity > 500) {
|
|
145
|
-
cognitiveValue = 0.7;
|
|
146
|
-
confidence = 0.8;
|
|
147
|
-
} else if (this.scrollVelocity > 50) {
|
|
148
|
-
cognitiveValue = 0.6;
|
|
149
|
-
confidence = 0.7;
|
|
150
|
-
} else {
|
|
151
|
-
cognitiveValue = 0.5;
|
|
152
|
-
confidence = 0.5;
|
|
153
|
-
}
|
|
154
|
-
return [{
|
|
155
|
-
dimension: "cognitive",
|
|
156
|
-
value: cognitiveValue,
|
|
157
|
-
confidence,
|
|
158
|
-
timestamp: now,
|
|
159
|
-
detectorName: this.name
|
|
160
|
-
}];
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
|
-
* Cleans up the scroll event listener when the detector is no longer needed.
|
|
164
|
-
*/
|
|
165
|
-
destroy() {
|
|
166
|
-
if (typeof window !== "undefined") {
|
|
167
|
-
window.removeEventListener("scroll", this.handleScroll);
|
|
168
|
-
if (this.timeoutId) {
|
|
169
|
-
clearTimeout(this.timeoutId);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
// lib/capacity/signals/detectors/interaction-detector.ts
|
|
176
|
-
var IDLE_THRESHOLD_MS = 15e3;
|
|
177
|
-
var CLICK_WINDOW_MS = 6e4;
|
|
178
|
-
var InteractionDetector = class {
|
|
179
|
-
constructor() {
|
|
180
|
-
this.name = "InteractionDetector";
|
|
181
|
-
this.weight = 0.7;
|
|
182
|
-
this.lastMouseMoveTime = 0;
|
|
183
|
-
this.lastClickTime = 0;
|
|
184
|
-
this.lastClickPosition = null;
|
|
185
|
-
this.clickHistory = [];
|
|
186
|
-
// rolling 60-second window
|
|
187
|
-
this.idleTimer = null;
|
|
188
|
-
this.isIdle = false;
|
|
189
|
-
this.resetIdleTimer = () => {
|
|
190
|
-
if (this.idleTimer) clearTimeout(this.idleTimer);
|
|
191
|
-
this.isIdle = false;
|
|
192
|
-
this.idleTimer = setTimeout(() => {
|
|
193
|
-
this.isIdle = true;
|
|
194
|
-
}, IDLE_THRESHOLD_MS);
|
|
195
|
-
};
|
|
196
|
-
this.handleMouseMove = () => {
|
|
197
|
-
this.lastMouseMoveTime = Date.now();
|
|
198
|
-
this.resetIdleTimer();
|
|
199
|
-
};
|
|
200
|
-
this.handleClick = (event) => {
|
|
201
|
-
this.resetIdleTimer();
|
|
202
|
-
const now = Date.now();
|
|
203
|
-
this.lastClickTime = now;
|
|
204
|
-
let distance = 0;
|
|
205
|
-
if (this.lastClickPosition) {
|
|
206
|
-
const dx = event.clientX - this.lastClickPosition.x;
|
|
207
|
-
const dy = event.clientY - this.lastClickPosition.y;
|
|
208
|
-
distance = Math.sqrt(dx * dx + dy * dy);
|
|
209
|
-
}
|
|
210
|
-
this.lastClickPosition = { x: event.clientX, y: event.clientY };
|
|
211
|
-
this.clickHistory.push({ time: now, distance });
|
|
212
|
-
};
|
|
213
|
-
if (typeof window !== "undefined") {
|
|
214
|
-
window.addEventListener("mousemove", this.handleMouseMove, { passive: true });
|
|
215
|
-
window.addEventListener("click", this.handleClick, { passive: true });
|
|
216
|
-
}
|
|
217
|
-
this.resetIdleTimer();
|
|
218
|
-
}
|
|
219
|
-
detect() {
|
|
220
|
-
const now = Date.now();
|
|
221
|
-
const cutoff = now - CLICK_WINDOW_MS;
|
|
222
|
-
this.clickHistory = this.clickHistory.filter((c) => c.time >= cutoff);
|
|
223
|
-
const clickCount = this.clickHistory.length;
|
|
224
|
-
const avgClickDistance = clickCount > 0 ? this.clickHistory.reduce((sum, c) => sum + c.distance, 0) / clickCount : 0;
|
|
225
|
-
const timeSinceLastClick = now - this.lastClickTime;
|
|
226
|
-
let cognitiveValue;
|
|
227
|
-
let confidence;
|
|
228
|
-
if (this.isIdle) {
|
|
229
|
-
cognitiveValue = 0.4;
|
|
230
|
-
confidence = 0.6;
|
|
231
|
-
} else if (timeSinceLastClick < 500 && clickCount > 5 && avgClickDistance < 20) {
|
|
232
|
-
cognitiveValue = 0.9;
|
|
233
|
-
confidence = 0.9;
|
|
234
|
-
} else if (timeSinceLastClick < 1500 && clickCount > 1 && avgClickDistance < 50) {
|
|
235
|
-
cognitiveValue = 0.7;
|
|
236
|
-
confidence = 0.7;
|
|
237
|
-
} else if (avgClickDistance > 100) {
|
|
238
|
-
cognitiveValue = 0.3;
|
|
239
|
-
confidence = 0.6;
|
|
240
|
-
} else {
|
|
241
|
-
cognitiveValue = 0.5;
|
|
242
|
-
confidence = 0.5;
|
|
243
|
-
}
|
|
244
|
-
return [{
|
|
245
|
-
dimension: "cognitive",
|
|
246
|
-
value: cognitiveValue,
|
|
247
|
-
confidence,
|
|
248
|
-
timestamp: now,
|
|
249
|
-
detectorName: this.name
|
|
250
|
-
}];
|
|
251
|
-
}
|
|
252
|
-
destroy() {
|
|
253
|
-
if (typeof window !== "undefined") {
|
|
254
|
-
window.removeEventListener("mousemove", this.handleMouseMove);
|
|
255
|
-
window.removeEventListener("click", this.handleClick);
|
|
256
|
-
}
|
|
257
|
-
if (this.idleTimer) clearTimeout(this.idleTimer);
|
|
258
|
-
}
|
|
259
|
-
};
|
|
260
|
-
|
|
261
|
-
// lib/capacity/signals/detectors/input-detector.ts
|
|
262
|
-
var TYPING_SPEED_SAMPLE_SIZE = 10;
|
|
263
|
-
var ERROR_CHECK_WINDOW = 5e3;
|
|
264
|
-
var InputDetector = class {
|
|
265
|
-
// timestamps of recent Backspace/Delete presses
|
|
266
|
-
constructor() {
|
|
267
|
-
this.name = "InputDetector";
|
|
268
|
-
this.weight = 0.6;
|
|
269
|
-
this.keyPressTimes = [];
|
|
270
|
-
this.errorTimes = [];
|
|
271
|
-
this.handleKeyDown = (event) => {
|
|
272
|
-
const now = Date.now();
|
|
273
|
-
this.keyPressTimes.push(now);
|
|
274
|
-
if (this.keyPressTimes.length > TYPING_SPEED_SAMPLE_SIZE) {
|
|
275
|
-
this.keyPressTimes.shift();
|
|
276
|
-
}
|
|
277
|
-
if (event.key === "Backspace" || event.key === "Delete") {
|
|
278
|
-
this.errorTimes.push(now);
|
|
279
|
-
}
|
|
280
|
-
};
|
|
281
|
-
if (typeof window !== "undefined") {
|
|
282
|
-
window.addEventListener("keydown", this.handleKeyDown, { passive: true });
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
detect() {
|
|
286
|
-
const now = Date.now();
|
|
287
|
-
let typingSpeedCPM = 0;
|
|
288
|
-
if (this.keyPressTimes.length > 1) {
|
|
289
|
-
const elapsed = this.keyPressTimes[this.keyPressTimes.length - 1] - this.keyPressTimes[0];
|
|
290
|
-
if (elapsed > 0) {
|
|
291
|
-
typingSpeedCPM = this.keyPressTimes.length / elapsed * 6e4;
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
const cutoff = now - ERROR_CHECK_WINDOW;
|
|
295
|
-
this.errorTimes = this.errorTimes.filter((t) => t >= cutoff);
|
|
296
|
-
const recentErrorCount = this.errorTimes.length;
|
|
297
|
-
let cognitiveValue;
|
|
298
|
-
let confidence;
|
|
299
|
-
if (typingSpeedCPM > 100 && recentErrorCount === 0) {
|
|
300
|
-
cognitiveValue = 0.9;
|
|
301
|
-
confidence = 0.8;
|
|
302
|
-
} else if (typingSpeedCPM > 40 && recentErrorCount <= 1) {
|
|
303
|
-
cognitiveValue = 0.7;
|
|
304
|
-
confidence = 0.7;
|
|
305
|
-
} else if (recentErrorCount > 2 || typingSpeedCPM < 20) {
|
|
306
|
-
cognitiveValue = 0.4;
|
|
307
|
-
confidence = 0.6;
|
|
308
|
-
} else {
|
|
309
|
-
cognitiveValue = 0.6;
|
|
310
|
-
confidence = 0.5;
|
|
311
|
-
}
|
|
312
|
-
return [{
|
|
313
|
-
dimension: "cognitive",
|
|
314
|
-
value: cognitiveValue,
|
|
315
|
-
confidence,
|
|
316
|
-
timestamp: now,
|
|
317
|
-
detectorName: this.name
|
|
318
|
-
}];
|
|
319
|
-
}
|
|
320
|
-
destroy() {
|
|
321
|
-
if (typeof window !== "undefined") {
|
|
322
|
-
window.removeEventListener("keydown", this.handleKeyDown);
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
};
|
|
326
|
-
|
|
327
|
-
// lib/capacity/signals/detectors/environment-detector.ts
|
|
328
|
-
var EnvironmentDetector = class {
|
|
329
|
-
constructor() {
|
|
330
|
-
this.name = "EnvironmentDetector";
|
|
331
|
-
this.weight = 0.8;
|
|
332
|
-
// High weight — these are explicit user preferences
|
|
333
|
-
this.mqlReducedMotion = null;
|
|
334
|
-
this.mqlDarkMode = null;
|
|
335
|
-
this.handleChange = () => {
|
|
336
|
-
};
|
|
337
|
-
if (typeof window !== "undefined") {
|
|
338
|
-
this.mqlReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
339
|
-
this.mqlDarkMode = window.matchMedia("(prefers-color-scheme: dark)");
|
|
340
|
-
this.mqlReducedMotion.addEventListener("change", this.handleChange);
|
|
341
|
-
this.mqlDarkMode.addEventListener("change", this.handleChange);
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
/**
|
|
345
|
-
* Returns two readings:
|
|
346
|
-
* - temporal: based on prefers-reduced-motion (low → less time pressure on animations)
|
|
347
|
-
* - emotional: based on prefers-color-scheme (dark → slightly lower emotional load)
|
|
348
|
-
*/
|
|
349
|
-
detect() {
|
|
350
|
-
const now = Date.now();
|
|
351
|
-
const prefersReducedMotion = this.mqlReducedMotion != null ? this.mqlReducedMotion.matches : typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
352
|
-
const prefersDarkMode = this.mqlDarkMode != null ? this.mqlDarkMode.matches : typeof window !== "undefined" && window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
353
|
-
return [
|
|
354
|
-
{
|
|
355
|
-
dimension: "temporal",
|
|
356
|
-
// prefers-reduced-motion → user may have lower tolerance for demanding UIs
|
|
357
|
-
value: prefersReducedMotion ? 0.3 : 0.8,
|
|
358
|
-
confidence: 0.9,
|
|
359
|
-
timestamp: now,
|
|
360
|
-
detectorName: this.name
|
|
361
|
-
},
|
|
362
|
-
{
|
|
363
|
-
dimension: "emotional",
|
|
364
|
-
// Dark mode preference → slightly lower emotional capacity or reduced-stimulation preference
|
|
365
|
-
value: prefersDarkMode ? 0.6 : 0.7,
|
|
366
|
-
confidence: 0.9,
|
|
367
|
-
timestamp: now,
|
|
368
|
-
detectorName: this.name
|
|
369
|
-
}
|
|
370
|
-
];
|
|
371
|
-
}
|
|
372
|
-
/**
|
|
373
|
-
* Removes the event listeners registered in the constructor.
|
|
374
|
-
* Uses the stored refs so the same function reference is unregistered.
|
|
375
|
-
*/
|
|
376
|
-
destroy() {
|
|
377
|
-
var _a, _b;
|
|
378
|
-
(_a = this.mqlReducedMotion) == null ? void 0 : _a.removeEventListener("change", this.handleChange);
|
|
379
|
-
(_b = this.mqlDarkMode) == null ? void 0 : _b.removeEventListener("change", this.handleChange);
|
|
380
|
-
this.mqlReducedMotion = null;
|
|
381
|
-
this.mqlDarkMode = null;
|
|
382
|
-
}
|
|
383
|
-
};
|
|
384
|
-
|
|
385
|
-
// lib/capacity/signals/aggregator.ts
|
|
386
|
-
var _SignalAggregator = class _SignalAggregator {
|
|
387
|
-
constructor() {
|
|
388
|
-
this.detectors = [
|
|
389
|
-
new TimeDetector(),
|
|
390
|
-
new SessionDetector(),
|
|
391
|
-
new ScrollDetector(),
|
|
392
|
-
new InteractionDetector(),
|
|
393
|
-
new InputDetector(),
|
|
394
|
-
new EnvironmentDetector()
|
|
395
|
-
];
|
|
396
|
-
}
|
|
397
|
-
/**
|
|
398
|
-
* Collects signal readings from all detectors and aggregates them into a
|
|
399
|
-
* confidence-weighted CapacityField.
|
|
400
|
-
*/
|
|
401
|
-
aggregateSignals() {
|
|
402
|
-
return __async(this, null, function* () {
|
|
403
|
-
const readings = [];
|
|
404
|
-
for (const detector of this.detectors) {
|
|
405
|
-
const detectorReadings = yield detector.detect();
|
|
406
|
-
readings.push(...detectorReadings);
|
|
407
|
-
}
|
|
408
|
-
const weightedSums = {
|
|
409
|
-
cognitive: 0,
|
|
410
|
-
temporal: 0,
|
|
411
|
-
emotional: 0,
|
|
412
|
-
valence: 0
|
|
413
|
-
};
|
|
414
|
-
const totalWeights = {
|
|
415
|
-
cognitive: 0,
|
|
416
|
-
temporal: 0,
|
|
417
|
-
emotional: 0,
|
|
418
|
-
valence: 0
|
|
419
|
-
};
|
|
420
|
-
for (const reading of readings) {
|
|
421
|
-
const effectiveWeight = reading.confidence * this.getDetectorWeight(reading.dimension, reading.detectorName);
|
|
422
|
-
weightedSums[reading.dimension] += reading.value * effectiveWeight;
|
|
423
|
-
totalWeights[reading.dimension] += effectiveWeight;
|
|
424
|
-
}
|
|
425
|
-
return {
|
|
426
|
-
cognitive: totalWeights.cognitive > 0 ? weightedSums.cognitive / totalWeights.cognitive : 0.5,
|
|
427
|
-
temporal: totalWeights.temporal > 0 ? weightedSums.temporal / totalWeights.temporal : 0.5,
|
|
428
|
-
emotional: totalWeights.emotional > 0 ? weightedSums.emotional / totalWeights.emotional : 0.5,
|
|
429
|
-
valence: totalWeights.valence > 0 ? weightedSums.valence / totalWeights.valence : 0
|
|
430
|
-
};
|
|
431
|
-
});
|
|
432
|
-
}
|
|
433
|
-
/**
|
|
434
|
-
* Returns the effective weight for a detector/dimension pair.
|
|
435
|
-
* Checks DIMENSION_WEIGHTS first; falls back to detector.weight.
|
|
436
|
-
*/
|
|
437
|
-
getDetectorWeight(dimension, detectorName) {
|
|
438
|
-
var _a, _b, _c;
|
|
439
|
-
const override = (_a = _SignalAggregator.DIMENSION_WEIGHTS[detectorName]) == null ? void 0 : _a[dimension];
|
|
440
|
-
if (override !== void 0) return override;
|
|
441
|
-
return (_c = (_b = this.detectors.find((d) => d.name === detectorName)) == null ? void 0 : _b.weight) != null ? _c : 0;
|
|
442
|
-
}
|
|
443
|
-
/** Cleans up all detector resources (event listeners, timers). */
|
|
444
|
-
destroy() {
|
|
445
|
-
var _a;
|
|
446
|
-
for (const detector of this.detectors) {
|
|
447
|
-
(_a = detector.destroy) == null ? void 0 : _a.call(detector);
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
};
|
|
451
|
-
/**
|
|
452
|
-
* Per-detector, per-dimension weight overrides.
|
|
453
|
-
* Falls back to detector.weight for any unlisted combination.
|
|
454
|
-
*
|
|
455
|
-
* Rationale for asymmetries:
|
|
456
|
-
* - TimeDetector: cognitive signal is stronger (diurnal pattern) than temporal
|
|
457
|
-
* (weekday/weekend is coarser)
|
|
458
|
-
* - EnvironmentDetector: emotional signal (color scheme) is a stronger explicit
|
|
459
|
-
* preference than temporal (reduced-motion)
|
|
460
|
-
*/
|
|
461
|
-
_SignalAggregator.DIMENSION_WEIGHTS = {
|
|
462
|
-
TimeDetector: { cognitive: 0.6, temporal: 0.5 },
|
|
463
|
-
EnvironmentDetector: { emotional: 0.8, temporal: 0.7 },
|
|
464
|
-
InteractionDetector: { cognitive: 0.7 },
|
|
465
|
-
InputDetector: { cognitive: 0.6 },
|
|
466
|
-
SessionDetector: { temporal: 0.7 },
|
|
467
|
-
ScrollDetector: { cognitive: 0.5 }
|
|
468
|
-
};
|
|
469
|
-
var SignalAggregator = _SignalAggregator;
|
|
470
|
-
|
|
471
|
-
export { SignalAggregator };
|
|
472
|
-
//# sourceMappingURL=aggregator-TH7FATMR.mjs.map
|
|
473
|
-
//# sourceMappingURL=aggregator-TH7FATMR.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../lib/capacity/signals/detectors/time-detector.ts","../lib/capacity/signals/detectors/session-detector.ts","../lib/capacity/signals/detectors/scroll-detector.ts","../lib/capacity/signals/detectors/interaction-detector.ts","../lib/capacity/signals/detectors/input-detector.ts","../lib/capacity/signals/detectors/environment-detector.ts","../lib/capacity/signals/aggregator.ts"],"names":[],"mappings":"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","file":"aggregator-TH7FATMR.mjs","sourcesContent":["/**\n * @file Implements a signal detector for time-based capacity.\n * Emits two readings per detect() call: cognitive (hour-of-day diurnal pattern)\n * and temporal (weekday vs. weekend).\n */\n\nimport { SignalDetector, SignalReading } from './types';\n\n/**\n * The TimeDetector class implements the SignalDetector interface\n * to provide signal readings based on the current time and day.\n */\nexport class TimeDetector implements SignalDetector {\n readonly name = 'TimeDetector';\n readonly weight = 0.6; // Medium weight — time is significant but a broad generalisation\n\n /**\n * Detects and returns SignalReadings based on the current time and day.\n * Returns two readings: cognitive (hour-of-day) and temporal (weekday/weekend).\n */\n detect(): SignalReading[] {\n const now = new Date();\n const hour = now.getHours();\n const dayOfWeek = now.getDay(); // 0 = Sunday, 6 = Saturday\n const ts = now.getTime();\n\n // ── Cognitive capacity: typical diurnal patterns ────────────────────────\n let cognitiveValue: number;\n if (hour >= 9 && hour < 12) {\n cognitiveValue = 0.8; // Morning peak\n } else if (hour >= 14 && hour < 17) {\n cognitiveValue = 0.6; // Afternoon dip\n } else if (hour >= 17 && hour < 20) {\n cognitiveValue = 0.5; // Evening, winding down\n } else if (hour >= 20 || hour < 6) {\n cognitiveValue = 0.3; // Late night / early morning\n } else {\n cognitiveValue = 0.7; // Early morning ramp-up (6–9am)\n }\n\n // ── Temporal capacity: weekday vs. weekend ──────────────────────────────\n const temporalValue = (dayOfWeek >= 1 && dayOfWeek <= 5) ? 0.7 : 0.9;\n // Weekends tend to feel less time-pressured → higher temporal capacity\n\n return [\n {\n dimension: 'cognitive',\n value: cognitiveValue,\n confidence: 0.7, // Medium — population average, not personalised\n timestamp: ts,\n detectorName: this.name,\n },\n {\n dimension: 'temporal',\n value: temporalValue,\n confidence: 0.6, // Slightly lower — weekday/weekend is a coarser signal\n timestamp: ts,\n detectorName: this.name,\n },\n ];\n }\n}\n","/**\n * @file Implements a signal detector for session duration.\n * This detector assesses temporal capacity based on how long the user has been active in the current session.\n */\n\nimport { SignalDetector, SignalReading } from './types';\n\n/**\n * The SessionDetector class implements the SignalDetector interface\n * to provide signal readings based on the current session duration.\n */\nexport class SessionDetector implements SignalDetector {\n readonly name = 'SessionDetector';\n readonly weight = 0.7; // Medium-high weight, as session duration can significantly impact capacity\n private sessionStartTime: number;\n\n constructor() {\n this.sessionStartTime = Date.now();\n }\n\n /**\n * Detects and returns a SignalReading based on the current session duration.\n * It provides insights into the temporal dimension.\n *\n * @returns {SignalReading} A reading indicating the inferred capacity.\n */\n detect(): SignalReading[] {\n const now = Date.now();\n const sessionDurationMinutes = (now - this.sessionStartTime) / (1000 * 60);\n\n let temporalValue: number;\n let confidence: number;\n\n // Temporal capacity inference based on session duration\n if (sessionDurationMinutes < 15) {\n temporalValue = 0.9; // High capacity, just started\n confidence = 0.8;\n } else if (sessionDurationMinutes < 60) {\n temporalValue = 0.7; // Moderate capacity, sustained engagement\n confidence = 0.7;\n } else if (sessionDurationMinutes < 180) {\n temporalValue = 0.5; // Lower capacity, potential fatigue\n confidence = 0.6;\n } else {\n temporalValue = 0.3; // Significantly lower capacity, extended use\n confidence = 0.7;\n }\n\n return [{\n dimension: 'temporal',\n value: temporalValue,\n confidence: confidence,\n timestamp: now,\n detectorName: this.name,\n }];\n }\n}\n","/**\n * @file Implements a signal detector for scroll velocity.\n * This detector assesses cognitive capacity based on the user's scrolling behavior.\n */\n\nimport { SignalDetector, SignalReading } from './types';\n\nconst DEBOUNCE_TIME_MS = 100; // Milliseconds to debounce scroll events\n\n/**\n * The ScrollDetector class implements the SignalDetector interface\n * to provide signal readings based on scroll velocity.\n */\nexport class ScrollDetector implements SignalDetector {\n readonly name = 'ScrollDetector';\n readonly weight = 0.5; // Moderate weight, as scroll velocity can indicate engagement or frustration\n\n private lastScrollY = 0;\n private lastScrollTime = 0;\n private scrollVelocity = 0;\n private timeoutId: NodeJS.Timeout | null = null;\n\n constructor() {\n if (typeof window !== 'undefined') {\n window.addEventListener('scroll', this.handleScroll, { passive: true });\n }\n }\n\n /**\n * Handles the scroll event, debouncing it and calculating scroll velocity.\n * @private\n */\n private handleScroll = () => {\n if (this.timeoutId) {\n clearTimeout(this.timeoutId);\n }\n\n this.timeoutId = setTimeout(() => {\n const now = Date.now();\n const scrollY = window.scrollY;\n\n const distance = Math.abs(scrollY - this.lastScrollY);\n const timeElapsed = now - this.lastScrollTime;\n\n if (timeElapsed > 0) {\n // Pixels per second\n this.scrollVelocity = (distance / timeElapsed) * 1000;\n } else {\n this.scrollVelocity = 0;\n }\n\n this.lastScrollY = scrollY;\n this.lastScrollTime = now;\n }, DEBOUNCE_TIME_MS);\n };\n\n /**\n * Detects and returns a SignalReading based on the current scroll velocity.\n * It provides insights into the cognitive dimension.\n *\n * @returns {SignalReading} A reading indicating the inferred capacity.\n */\n detect(): SignalReading[] {\n const now = Date.now();\n let cognitiveValue: number;\n let confidence: number;\n\n // Interpret scroll velocity: very fast/slow could indicate issues, moderate is normal\n if (this.scrollVelocity > 1500) {\n cognitiveValue = 0.4; // Very fast scroll, possibly disengaged or frantically searching\n confidence = 0.6;\n } else if (this.scrollVelocity > 500) {\n cognitiveValue = 0.7; // Moderate scroll, engaged browsing\n confidence = 0.8;\n } else if (this.scrollVelocity > 50) {\n cognitiveValue = 0.6; // Slow scroll, careful reading or struggling\n confidence = 0.7;\n } else {\n cognitiveValue = 0.5; // Very slow or no scroll, idle or deeply focused\n confidence = 0.5;\n }\n\n return [{\n dimension: 'cognitive',\n value: cognitiveValue,\n confidence: confidence,\n timestamp: now,\n detectorName: this.name,\n }];\n }\n\n /**\n * Cleans up the scroll event listener when the detector is no longer needed.\n */\n destroy() {\n if (typeof window !== 'undefined') {\n window.removeEventListener('scroll', this.handleScroll);\n if (this.timeoutId) {\n clearTimeout(this.timeoutId);\n }\n }\n }\n}\n","/**\n * @file Implements a signal detector for user interaction patterns.\n * Assesses cognitive capacity from click rate and precision using a rolling window.\n *\n * Bug fixes vs. original:\n * - clickCount / totalClickDistance accumulated forever → replaced with a 60-second\n * rolling window so recent behaviour dominates over historical averages.\n * - IDLE_THRESHOLD_MS was 3 s (too aggressive for focused reading) → raised to 15 s.\n */\n\nimport { SignalDetector, SignalReading } from './types';\n\nconst DEBOUNCE_MOVE_TIME_MS = 50;\nconst IDLE_THRESHOLD_MS = 15_000; // 15 s — focused readers pause longer than 3 s\nconst CLICK_WINDOW_MS = 60_000; // 60 s rolling window for click history\n\ninterface ClickEntry {\n time: number;\n distance: number; // px distance from previous click position\n}\n\nexport class InteractionDetector implements SignalDetector {\n readonly name = 'InteractionDetector';\n readonly weight = 0.7;\n\n private lastMouseMoveTime = 0;\n private lastClickTime = 0;\n private lastClickPosition: { x: number; y: number } | null = null;\n private clickHistory: ClickEntry[] = []; // rolling 60-second window\n private idleTimer: ReturnType<typeof setTimeout> | null = null;\n private isIdle = false;\n\n constructor() {\n if (typeof window !== 'undefined') {\n window.addEventListener('mousemove', this.handleMouseMove, { passive: true });\n window.addEventListener('click', this.handleClick, { passive: true });\n }\n this.resetIdleTimer();\n }\n\n private resetIdleTimer = () => {\n if (this.idleTimer) clearTimeout(this.idleTimer);\n this.isIdle = false;\n this.idleTimer = setTimeout(() => { this.isIdle = true; }, IDLE_THRESHOLD_MS);\n };\n\n private handleMouseMove = () => {\n this.lastMouseMoveTime = Date.now();\n this.resetIdleTimer();\n };\n\n private handleClick = (event: MouseEvent) => {\n this.resetIdleTimer();\n const now = Date.now();\n this.lastClickTime = now;\n\n let distance = 0;\n if (this.lastClickPosition) {\n const dx = event.clientX - this.lastClickPosition.x;\n const dy = event.clientY - this.lastClickPosition.y;\n distance = Math.sqrt(dx * dx + dy * dy);\n }\n this.lastClickPosition = { x: event.clientX, y: event.clientY };\n this.clickHistory.push({ time: now, distance });\n };\n\n detect(): SignalReading[] {\n const now = Date.now();\n\n // Prune entries outside the rolling window\n const cutoff = now - CLICK_WINDOW_MS;\n this.clickHistory = this.clickHistory.filter(c => c.time >= cutoff);\n\n const clickCount = this.clickHistory.length;\n const avgClickDistance =\n clickCount > 0\n ? this.clickHistory.reduce((sum, c) => sum + c.distance, 0) / clickCount\n : 0;\n\n const timeSinceLastClick = now - this.lastClickTime;\n\n let cognitiveValue: number;\n let confidence: number;\n\n if (this.isIdle) {\n cognitiveValue = 0.4; // Idle: disengaged or deeply thinking\n confidence = 0.6;\n } else if (timeSinceLastClick < 500 && clickCount > 5 && avgClickDistance < 20) {\n cognitiveValue = 0.9; // Highly engaged: frequent, precise clicks\n confidence = 0.9;\n } else if (timeSinceLastClick < 1500 && clickCount > 1 && avgClickDistance < 50) {\n cognitiveValue = 0.7; // Moderately engaged\n confidence = 0.7;\n } else if (avgClickDistance > 100) {\n cognitiveValue = 0.3; // Low precision: possibly frustrated or impaired\n confidence = 0.6;\n } else {\n cognitiveValue = 0.5; // Ambiguous / default\n confidence = 0.5;\n }\n\n return [{\n dimension: 'cognitive',\n value: cognitiveValue,\n confidence,\n timestamp: now,\n detectorName: this.name,\n }];\n }\n\n destroy() {\n if (typeof window !== 'undefined') {\n window.removeEventListener('mousemove', this.handleMouseMove);\n window.removeEventListener('click', this.handleClick);\n }\n if (this.idleTimer) clearTimeout(this.idleTimer);\n }\n}\n","/**\n * @file Implements a signal detector for user input patterns (typing speed + error rate).\n * Assesses cognitive capacity based on typing behaviour.\n *\n * Bug fix vs. original:\n * - errorCount / lastErrorTime tracked errors since an arbitrary past reset; old\n * errors counted the same as current ones → replaced with an errorTimes[] sliding\n * window so only errors within ERROR_CHECK_WINDOW (5 s) are counted.\n * - Inference now uses recentErrorCount (integer) instead of a boolean, letting the\n * code distinguish a single correction from repeated fumbling.\n */\n\nimport { SignalDetector, SignalReading } from './types';\n\nconst TYPING_SPEED_SAMPLE_SIZE = 10; // Key presses to average for CPM calculation\nconst ERROR_CHECK_WINDOW = 5_000; // ms: only count errors in this sliding window\n\nexport class InputDetector implements SignalDetector {\n readonly name = 'InputDetector';\n readonly weight = 0.6;\n\n private keyPressTimes: number[] = [];\n private errorTimes: number[] = []; // timestamps of recent Backspace/Delete presses\n\n constructor() {\n if (typeof window !== 'undefined') {\n window.addEventListener('keydown', this.handleKeyDown, { passive: true });\n }\n }\n\n private handleKeyDown = (event: KeyboardEvent) => {\n const now = Date.now();\n\n this.keyPressTimes.push(now);\n if (this.keyPressTimes.length > TYPING_SPEED_SAMPLE_SIZE) {\n this.keyPressTimes.shift();\n }\n\n if (event.key === 'Backspace' || event.key === 'Delete') {\n this.errorTimes.push(now);\n }\n };\n\n detect(): SignalReading[] {\n const now = Date.now();\n\n // ── Typing speed (characters per minute) ───────────────────────────────\n let typingSpeedCPM = 0;\n if (this.keyPressTimes.length > 1) {\n const elapsed = this.keyPressTimes[this.keyPressTimes.length - 1] - this.keyPressTimes[0];\n if (elapsed > 0) {\n typingSpeedCPM = (this.keyPressTimes.length / elapsed) * 60_000;\n }\n }\n\n // ── Recent error count (sliding window) ────────────────────────────────\n const cutoff = now - ERROR_CHECK_WINDOW;\n this.errorTimes = this.errorTimes.filter(t => t >= cutoff);\n const recentErrorCount = this.errorTimes.length;\n\n // ── Cognitive inference ─────────────────────────────────────────────────\n let cognitiveValue: number;\n let confidence: number;\n\n if (typingSpeedCPM > 100 && recentErrorCount === 0) {\n cognitiveValue = 0.9; // Fast + accurate → high cognitive capacity\n confidence = 0.8;\n } else if (typingSpeedCPM > 40 && recentErrorCount <= 1) {\n cognitiveValue = 0.7; // Moderate speed, minimal errors\n confidence = 0.7;\n } else if (recentErrorCount > 2 || typingSpeedCPM < 20) {\n cognitiveValue = 0.4; // Repeated errors or very slow → lower capacity\n confidence = 0.6;\n } else {\n cognitiveValue = 0.6; // Ambiguous / default\n confidence = 0.5;\n }\n\n return [{\n dimension: 'cognitive',\n value: cognitiveValue,\n confidence,\n timestamp: now,\n detectorName: this.name,\n }];\n }\n\n destroy() {\n if (typeof window !== 'undefined') {\n window.removeEventListener('keydown', this.handleKeyDown);\n }\n }\n}\n","/**\n * @file Implements signal detectors for environmental preferences.\n * Reads prefers-reduced-motion (→ temporal) and prefers-color-scheme (→ emotional).\n *\n * Bug fixes vs. original:\n * - Memory leak: stored MediaQueryList refs so removeEventListener unregisters the\n * exact same handler that was registered (arrow-function class properties create a\n * new reference on each access, so calling this.detect would never unregister).\n * - Discarded temporal dimension: now returns both temporal and emotional readings.\n */\n\nimport { SignalDetector, SignalReading } from './types';\n\nexport class EnvironmentDetector implements SignalDetector {\n readonly name = 'EnvironmentDetector';\n readonly weight = 0.8; // High weight — these are explicit user preferences\n\n private mqlReducedMotion: MediaQueryList | null = null;\n private mqlDarkMode: MediaQueryList | null = null;\n // A single stable handler reference that both addEventListener and\n // removeEventListener receive. detect() is stateless so the handler is a\n // no-op: the aggregator polls detect() on its own 2-second schedule.\n private readonly handleChange: () => void;\n\n constructor() {\n this.handleChange = () => {};\n if (typeof window !== 'undefined') {\n this.mqlReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)');\n this.mqlDarkMode = window.matchMedia('(prefers-color-scheme: dark)');\n this.mqlReducedMotion.addEventListener('change', this.handleChange);\n this.mqlDarkMode.addEventListener('change', this.handleChange);\n }\n }\n\n /**\n * Returns two readings:\n * - temporal: based on prefers-reduced-motion (low → less time pressure on animations)\n * - emotional: based on prefers-color-scheme (dark → slightly lower emotional load)\n */\n detect(): SignalReading[] {\n const now = Date.now();\n\n // Use stored refs for efficiency; fall back to fresh queries on SSR or if\n // the constructor ran without a window (e.g. jest with no matchMedia stub).\n const prefersReducedMotion =\n this.mqlReducedMotion != null\n ? this.mqlReducedMotion.matches\n : typeof window !== 'undefined' &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n\n const prefersDarkMode =\n this.mqlDarkMode != null\n ? this.mqlDarkMode.matches\n : typeof window !== 'undefined' &&\n window.matchMedia('(prefers-color-scheme: dark)').matches;\n\n return [\n {\n dimension: 'temporal',\n // prefers-reduced-motion → user may have lower tolerance for demanding UIs\n value: prefersReducedMotion ? 0.3 : 0.8,\n confidence: 0.9,\n timestamp: now,\n detectorName: this.name,\n },\n {\n dimension: 'emotional',\n // Dark mode preference → slightly lower emotional capacity or reduced-stimulation preference\n value: prefersDarkMode ? 0.6 : 0.7,\n confidence: 0.9,\n timestamp: now,\n detectorName: this.name,\n },\n ];\n }\n\n /**\n * Removes the event listeners registered in the constructor.\n * Uses the stored refs so the same function reference is unregistered.\n */\n destroy() {\n this.mqlReducedMotion?.removeEventListener('change', this.handleChange);\n this.mqlDarkMode?.removeEventListener('change', this.handleChange);\n this.mqlReducedMotion = null;\n this.mqlDarkMode = null;\n }\n}\n","/**\n * @file Aggregates signals from all detectors into a suggested CapacityField.\n *\n * Bug fixes vs. original:\n * - detect() now returns SignalReading[] so readings.push(...) spreads the array.\n * - getDetectorWeight() now uses a per-detector/dimension lookup table instead of\n * ignoring the dimension parameter.\n * - destroy() uses the optional-chaining destroy?() instead of (detector as any).destroy().\n */\n\nimport { SignalDetector, SignalReading } from './detectors/types';\nimport { CapacityField } from '../types';\nimport { TimeDetector } from './detectors/time-detector';\nimport { SessionDetector } from './detectors/session-detector';\nimport { ScrollDetector } from './detectors/scroll-detector';\nimport { InteractionDetector } from './detectors/interaction-detector';\nimport { InputDetector } from './detectors/input-detector';\nimport { EnvironmentDetector } from './detectors/environment-detector';\n\nexport class SignalAggregator {\n private detectors: SignalDetector[];\n\n /**\n * Per-detector, per-dimension weight overrides.\n * Falls back to detector.weight for any unlisted combination.\n *\n * Rationale for asymmetries:\n * - TimeDetector: cognitive signal is stronger (diurnal pattern) than temporal\n * (weekday/weekend is coarser)\n * - EnvironmentDetector: emotional signal (color scheme) is a stronger explicit\n * preference than temporal (reduced-motion)\n */\n private static readonly DIMENSION_WEIGHTS: Partial<\n Record<string, Partial<Record<SignalReading['dimension'], number>>>\n > = {\n TimeDetector: { cognitive: 0.6, temporal: 0.5 },\n EnvironmentDetector: { emotional: 0.8, temporal: 0.7 },\n InteractionDetector: { cognitive: 0.7 },\n InputDetector: { cognitive: 0.6 },\n SessionDetector: { temporal: 0.7 },\n ScrollDetector: { cognitive: 0.5 },\n };\n\n constructor() {\n this.detectors = [\n new TimeDetector(),\n new SessionDetector(),\n new ScrollDetector(),\n new InteractionDetector(),\n new InputDetector(),\n new EnvironmentDetector(),\n ];\n }\n\n /**\n * Collects signal readings from all detectors and aggregates them into a\n * confidence-weighted CapacityField.\n */\n async aggregateSignals(): Promise<CapacityField> {\n const readings: SignalReading[] = [];\n\n for (const detector of this.detectors) {\n const detectorReadings = await detector.detect();\n readings.push(...detectorReadings);\n }\n\n const weightedSums: Record<SignalReading['dimension'], number> = {\n cognitive: 0, temporal: 0, emotional: 0, valence: 0,\n };\n const totalWeights: Record<SignalReading['dimension'], number> = {\n cognitive: 0, temporal: 0, emotional: 0, valence: 0,\n };\n\n for (const reading of readings) {\n const effectiveWeight =\n reading.confidence * this.getDetectorWeight(reading.dimension, reading.detectorName);\n weightedSums[reading.dimension] += reading.value * effectiveWeight;\n totalWeights[reading.dimension] += effectiveWeight;\n }\n\n return {\n cognitive: totalWeights.cognitive > 0 ? weightedSums.cognitive / totalWeights.cognitive : 0.5,\n temporal: totalWeights.temporal > 0 ? weightedSums.temporal / totalWeights.temporal : 0.5,\n emotional: totalWeights.emotional > 0 ? weightedSums.emotional / totalWeights.emotional : 0.5,\n valence: totalWeights.valence > 0 ? weightedSums.valence / totalWeights.valence : 0,\n };\n }\n\n /**\n * Returns the effective weight for a detector/dimension pair.\n * Checks DIMENSION_WEIGHTS first; falls back to detector.weight.\n */\n private getDetectorWeight(\n dimension: SignalReading['dimension'],\n detectorName: string,\n ): number {\n const override = SignalAggregator.DIMENSION_WEIGHTS[detectorName]?.[dimension];\n if (override !== undefined) return override;\n return this.detectors.find(d => d.name === detectorName)?.weight ?? 0;\n }\n\n /** Cleans up all detector resources (event listeners, timers). */\n destroy() {\n for (const detector of this.detectors) {\n detector.destroy?.();\n }\n }\n}\n"]}
|