@ddwang/magnitude-core 0.3.1-ddwang.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/dist/actions/desktopActions.d.ts +58 -0
  2. package/dist/actions/desktopActions.js +154 -0
  3. package/dist/actions/index.d.ts +26 -0
  4. package/dist/actions/index.js +11 -0
  5. package/dist/actions/taskActions.d.ts +8 -0
  6. package/dist/actions/taskActions.js +27 -0
  7. package/dist/actions/types.d.ts +31 -0
  8. package/dist/actions/types.js +5 -0
  9. package/dist/actions/util.d.ts +20 -0
  10. package/dist/actions/util.js +297 -0
  11. package/dist/actions/webActions.d.ts +79 -0
  12. package/dist/actions/webActions.js +190 -0
  13. package/dist/agent/browserAgent.d.ts +29 -0
  14. package/dist/agent/browserAgent.js +122 -0
  15. package/dist/agent/errors.d.ts +8 -0
  16. package/dist/agent/errors.js +68 -0
  17. package/dist/agent/index.d.ts +53 -0
  18. package/dist/agent/index.js +377 -0
  19. package/dist/agent/narrator.d.ts +4 -0
  20. package/dist/agent/narrator.js +63 -0
  21. package/dist/agent/pause.test.d.ts +1 -0
  22. package/dist/agent/pause.test.js +194 -0
  23. package/dist/ai/baml_client/async_client.d.ts +73 -0
  24. package/dist/ai/baml_client/async_client.js +152 -0
  25. package/dist/ai/baml_client/async_request.d.ts +35 -0
  26. package/dist/ai/baml_client/async_request.js +98 -0
  27. package/dist/ai/baml_client/config.d.ts +11 -0
  28. package/dist/ai/baml_client/config.js +20 -0
  29. package/dist/ai/baml_client/globals.d.ts +16 -0
  30. package/dist/ai/baml_client/globals.js +37 -0
  31. package/dist/ai/baml_client/index.d.ts +16 -0
  32. package/dist/ai/baml_client/index.js +41 -0
  33. package/dist/ai/baml_client/inlinedbaml.d.ts +19 -0
  34. package/dist/ai/baml_client/inlinedbaml.js +31 -0
  35. package/dist/ai/baml_client/parser.d.ts +53 -0
  36. package/dist/ai/baml_client/parser.js +86 -0
  37. package/dist/ai/baml_client/partial_types.d.ts +61 -0
  38. package/dist/ai/baml_client/partial_types.js +10 -0
  39. package/dist/ai/baml_client/sync_client.d.ts +50 -0
  40. package/dist/ai/baml_client/sync_client.js +100 -0
  41. package/dist/ai/baml_client/sync_request.d.ts +35 -0
  42. package/dist/ai/baml_client/sync_request.js +98 -0
  43. package/dist/ai/baml_client/tracing.d.ts +16 -0
  44. package/dist/ai/baml_client/tracing.js +18 -0
  45. package/dist/ai/baml_client/type_builder.d.ts +38 -0
  46. package/dist/ai/baml_client/type_builder.js +96 -0
  47. package/dist/ai/baml_client/types.d.ts +69 -0
  48. package/dist/ai/baml_client/types.js +15 -0
  49. package/dist/ai/claudeCode.d.ts +1 -0
  50. package/dist/ai/claudeCode.js +186 -0
  51. package/dist/ai/modelHarness.d.ts +39 -0
  52. package/dist/ai/modelHarness.js +189 -0
  53. package/dist/ai/multiModelHarness.d.ts +27 -0
  54. package/dist/ai/multiModelHarness.js +52 -0
  55. package/dist/ai/types.d.ts +90 -0
  56. package/dist/ai/types.js +5 -0
  57. package/dist/ai/util.d.ts +13 -0
  58. package/dist/ai/util.js +165 -0
  59. package/dist/cli.d.ts +0 -0
  60. package/dist/cli.js +3 -0
  61. package/dist/common/actions.d.ts +0 -0
  62. package/dist/common/actions.js +14 -0
  63. package/dist/common/events.d.ts +15 -0
  64. package/dist/common/events.js +3 -0
  65. package/dist/common/failure.d.ts +68 -0
  66. package/dist/common/failure.js +1 -0
  67. package/dist/common/index.d.ts +3 -0
  68. package/dist/common/index.js +3 -0
  69. package/dist/common/retry.d.ts +16 -0
  70. package/dist/common/retry.js +30 -0
  71. package/dist/common/util.d.ts +23 -0
  72. package/dist/common/util.js +132 -0
  73. package/dist/connectors/browserConnector.d.ts +40 -0
  74. package/dist/connectors/browserConnector.js +127 -0
  75. package/dist/connectors/desktopConnector.d.ts +58 -0
  76. package/dist/connectors/desktopConnector.js +68 -0
  77. package/dist/connectors/index.d.ts +10 -0
  78. package/dist/connectors/index.js +2 -0
  79. package/dist/index.cjs +6143 -0
  80. package/dist/index.d.cts +825 -0
  81. package/dist/index.d.ts +20 -0
  82. package/dist/index.js +26 -0
  83. package/dist/index.mjs +6097 -0
  84. package/dist/logger.d.ts +3 -0
  85. package/dist/logger.js +15 -0
  86. package/dist/memory/agentMemory.d.ts +37 -0
  87. package/dist/memory/agentMemory.js +121 -0
  88. package/dist/memory/image.d.ts +26 -0
  89. package/dist/memory/image.js +106 -0
  90. package/dist/memory/index.d.ts +3 -0
  91. package/dist/memory/index.js +3 -0
  92. package/dist/memory/masking.d.ts +7 -0
  93. package/dist/memory/masking.js +141 -0
  94. package/dist/memory/masking.test.d.ts +1 -0
  95. package/dist/memory/masking.test.js +117 -0
  96. package/dist/memory/observation.d.ts +38 -0
  97. package/dist/memory/observation.js +79 -0
  98. package/dist/memory/rendering/index.d.ts +10 -0
  99. package/dist/memory/rendering/index.js +13 -0
  100. package/dist/memory/rendering/renderJsonParts.d.ts +3 -0
  101. package/dist/memory/rendering/renderJsonParts.js +115 -0
  102. package/dist/memory/rendering/renderJsonParts.test.d.ts +1 -0
  103. package/dist/memory/rendering/renderJsonParts.test.js +217 -0
  104. package/dist/memory/rendering/renderXmlParts.d.ts +7 -0
  105. package/dist/memory/rendering/renderXmlParts.js +127 -0
  106. package/dist/memory/serde.d.ts +20 -0
  107. package/dist/memory/serde.js +81 -0
  108. package/dist/memory/util.d.ts +2 -0
  109. package/dist/memory/util.js +17 -0
  110. package/dist/telemetry/events.d.ts +9 -0
  111. package/dist/telemetry/events.js +80 -0
  112. package/dist/telemetry/index.d.ts +6 -0
  113. package/dist/telemetry/index.js +91 -0
  114. package/dist/types.d.ts +30 -0
  115. package/dist/types.js +1 -0
  116. package/dist/util.d.ts +1 -0
  117. package/dist/util.js +12 -0
  118. package/dist/version.d.ts +1 -0
  119. package/dist/version.js +3 -0
  120. package/dist/web/browserProvider.d.ts +23 -0
  121. package/dist/web/browserProvider.js +153 -0
  122. package/dist/web/harness.d.ts +102 -0
  123. package/dist/web/harness.js +340 -0
  124. package/dist/web/stability.d.ts +57 -0
  125. package/dist/web/stability.js +316 -0
  126. package/dist/web/tabs.d.ts +58 -0
  127. package/dist/web/tabs.js +293 -0
  128. package/dist/web/transformer.d.ts +7 -0
  129. package/dist/web/transformer.js +41 -0
  130. package/dist/web/types.d.ts +32 -0
  131. package/dist/web/types.js +2 -0
  132. package/dist/web/util.d.ts +3 -0
  133. package/dist/web/util.js +81 -0
  134. package/dist/web/visualizer/cursor.d.ts +16 -0
  135. package/dist/web/visualizer/cursor.js +152 -0
  136. package/dist/web/visualizer/index.d.ts +22 -0
  137. package/dist/web/visualizer/index.js +47 -0
  138. package/dist/web/visualizer/mouseEffects.d.ts +18 -0
  139. package/dist/web/visualizer/mouseEffects.js +287 -0
  140. package/dist/web/visualizer/typeEffects.d.ts +10 -0
  141. package/dist/web/visualizer/typeEffects.js +190 -0
  142. package/package.json +71 -0
@@ -0,0 +1,287 @@
1
+ import { retryOnErrorIsSuccess } from "@/common";
2
+ export class MouseEffectVisual {
3
+ baseOpacity;
4
+ showHoverCircle;
5
+ showClickRipple;
6
+ showDragLine;
7
+ page;
8
+ constructor(options = {}) {
9
+ this.baseOpacity = options.baseOpacity ?? 0.5;
10
+ this.showHoverCircle = options.showHoverCircle ?? true;
11
+ this.showClickRipple = options.showClickRipple ?? true;
12
+ this.showDragLine = options.showDragLine ?? true;
13
+ }
14
+ async setActivePage(page) {
15
+ this.page = page;
16
+ page.on('load', async () => {
17
+ // Clear the initialized flag on navigation to ensure re-initialization
18
+ await page.evaluate(() => {
19
+ window.__mouseEffectsInitialized = false;
20
+ }).catch(() => { }); // Ignore errors
21
+ await retryOnErrorIsSuccess(this.setupOnPage.bind(this), { mode: 'retry_all', delayMs: 200, retryLimit: 10 });
22
+ });
23
+ await retryOnErrorIsSuccess(this.setupOnPage.bind(this), { mode: 'retry_all', delayMs: 200, retryLimit: 10 });
24
+ }
25
+ async setupOnPage() {
26
+ await this.page.evaluate((options) => {
27
+ if (window.__mouseEffectsInitialized) {
28
+ return;
29
+ }
30
+ window.__mouseEffectsInitialized = true;
31
+ // Create custom cursor element only if enabled
32
+ let cursor = null;
33
+ if (options.showHoverCircle) {
34
+ cursor = document.createElement('div');
35
+ cursor.id = 'custom-cursor';
36
+ cursor.style.cssText = `
37
+ position: fixed;
38
+ width: 20px;
39
+ height: 20px;
40
+ border: 2px solid rgba(0, 150, 255, ${options.opacity});
41
+ border-radius: 50%;
42
+ background: rgba(0, 150, 255, ${options.opacity * 0.5});
43
+ pointer-events: none;
44
+ z-index: 1000000050;
45
+ transition: transform 0.1s ease-out;
46
+ `;
47
+ document.body.appendChild(cursor);
48
+ }
49
+ // Create drag line element only if enabled
50
+ let dragLine = null;
51
+ let line = null;
52
+ if (options.showDragLine) {
53
+ dragLine = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
54
+ dragLine.id = 'drag-line';
55
+ dragLine.style.cssText = `
56
+ position: fixed;
57
+ top: 0;
58
+ left: 0;
59
+ width: 100vw;
60
+ height: 100vh;
61
+ pointer-events: none;
62
+ z-index: 1000000030;
63
+ overflow: visible;
64
+ `;
65
+ line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
66
+ line.setAttribute('stroke', '#0096ff');
67
+ line.setAttribute('stroke-width', '2');
68
+ line.setAttribute('stroke-dasharray', '5,5');
69
+ line.setAttribute('opacity', '0.8');
70
+ line.style.display = 'none';
71
+ dragLine.appendChild(line);
72
+ document.body.appendChild(dragLine);
73
+ }
74
+ let isMouseDown = false;
75
+ let dragStartX = 0;
76
+ let dragStartY = 0;
77
+ const activeRipples = new Set();
78
+ // Track mouse movement
79
+ document.addEventListener('mousemove', (e) => {
80
+ // Update cursor position - always center on mouse
81
+ if (cursor) {
82
+ cursor.style.left = e.clientX - 10 + 'px';
83
+ cursor.style.top = e.clientY - 10 + 'px';
84
+ }
85
+ // Update drag line if dragging
86
+ if (isMouseDown && line) {
87
+ line.setAttribute('x1', dragStartX.toString());
88
+ line.setAttribute('y1', dragStartY.toString());
89
+ line.setAttribute('x2', e.clientX.toString());
90
+ line.setAttribute('y2', e.clientY.toString());
91
+ line.style.display = 'block';
92
+ }
93
+ });
94
+ // Mouse down - start drag and shrink cursor
95
+ document.addEventListener('mousedown', (e) => {
96
+ isMouseDown = true;
97
+ dragStartX = e.clientX;
98
+ dragStartY = e.clientY;
99
+ // Use transform scale instead of changing width/height
100
+ if (cursor) {
101
+ cursor.style.transform = 'scale(0.5)';
102
+ cursor.style.background = `rgba(0, 150, 255, ${options.opacity * 1.5})`;
103
+ cursor.style.border = `2px solid rgba(0, 150, 255, ${options.opacity * 2})`;
104
+ }
105
+ });
106
+ // Mouse up - end drag and restore cursor
107
+ document.addEventListener('mouseup', (e) => {
108
+ isMouseDown = false;
109
+ // Hide drag line
110
+ if (line) {
111
+ line.style.display = 'none';
112
+ }
113
+ // Restore cursor
114
+ if (cursor) {
115
+ cursor.style.transform = 'scale(1)';
116
+ cursor.style.background = `rgba(0, 150, 255, ${options.opacity * 0.5})`;
117
+ cursor.style.border = `2px solid rgba(0, 150, 255, ${options.opacity})`;
118
+ }
119
+ });
120
+ // Visualize clicks
121
+ document.addEventListener('click', (e) => {
122
+ if (options.showClickRipple) {
123
+ // Add ripple animation styles once
124
+ if (!document.querySelector('style[data-cursor-effects]')) {
125
+ const style = document.createElement('style');
126
+ style.setAttribute('data-cursor-effects', 'true');
127
+ style.textContent = `
128
+ @keyframes ripple {
129
+ 0% {
130
+ transform: scale(0);
131
+ opacity: 1;
132
+ }
133
+ 100% {
134
+ transform: scale(2);
135
+ opacity: 0;
136
+ }
137
+ }
138
+ .click-ripple {
139
+ position: fixed;
140
+ width: 60px;
141
+ height: 60px;
142
+ border: 3px solid #0096ff;
143
+ border-radius: 50%;
144
+ pointer-events: none;
145
+ z-index: 1000000040;
146
+ transform: scale(0);
147
+ opacity: 0;
148
+ }
149
+ .click-ripple.active {
150
+ animation: ripple 0.6s ease-out forwards;
151
+ }
152
+ `;
153
+ document.head.appendChild(style);
154
+ }
155
+ // Create ripple effect
156
+ const ripple = document.createElement('div');
157
+ ripple.className = 'click-ripple';
158
+ ripple.style.left = `${e.clientX - 30}px`;
159
+ ripple.style.top = `${e.clientY - 30}px`;
160
+ document.body.appendChild(ripple);
161
+ activeRipples.add(ripple);
162
+ // Trigger animation on next frame to ensure proper initialization
163
+ requestAnimationFrame(() => {
164
+ ripple.classList.add('active');
165
+ });
166
+ // Remove ripple after animation
167
+ setTimeout(() => {
168
+ ripple.remove();
169
+ activeRipples.delete(ripple);
170
+ }, 600);
171
+ }
172
+ // Flash the cursor only if not already scaled down
173
+ if (cursor) {
174
+ const currentTransform = cursor.style.transform;
175
+ if (currentTransform !== 'scale(0.5)') {
176
+ cursor.style.background = `rgba(0, 150, 255, ${options.opacity * 1.5})`;
177
+ cursor.style.border = `2px solid rgba(0, 150, 255, 1)`;
178
+ cursor.style.transform = 'scale(1.5)';
179
+ setTimeout(() => {
180
+ cursor.style.background = `rgba(0, 150, 255, ${options.opacity * 0.5})`;
181
+ cursor.style.border = `2px solid rgba(0, 150, 255, ${options.opacity})`;
182
+ cursor.style.transform = 'scale(1)';
183
+ }, 200);
184
+ }
185
+ }
186
+ });
187
+ // Also track right clicks
188
+ document.addEventListener('contextmenu', (e) => {
189
+ // Don't prevent default - let context menu show
190
+ if (options.showClickRipple) {
191
+ // Create ripple for right click (reuse same styles)
192
+ const ripple = document.createElement('div');
193
+ ripple.className = 'click-ripple';
194
+ ripple.style.left = `${e.clientX - 30}px`;
195
+ ripple.style.top = `${e.clientY - 30}px`;
196
+ document.body.appendChild(ripple);
197
+ activeRipples.add(ripple);
198
+ // Trigger animation on next frame
199
+ requestAnimationFrame(() => {
200
+ ripple.classList.add('active');
201
+ });
202
+ setTimeout(() => {
203
+ ripple.remove();
204
+ activeRipples.delete(ripple);
205
+ }, 600);
206
+ }
207
+ });
208
+ // Scroll visualization
209
+ let scrollTimeout;
210
+ let scrollArrow = null;
211
+ // Create the single scroll arrow
212
+ scrollArrow = document.createElement('div');
213
+ scrollArrow.style.cssText = `
214
+ position: fixed;
215
+ width: 40px;
216
+ height: 40px;
217
+ font-size: 24px;
218
+ color: #0096ff;
219
+ text-align: center;
220
+ line-height: 40px;
221
+ pointer-events: none;
222
+ z-index: 1000000045;
223
+ display: none;
224
+ transition: transform 0.1s ease-out, opacity 0.2s ease-out;
225
+ `;
226
+ document.body.appendChild(scrollArrow);
227
+ // Handle both wheel and scroll events
228
+ const handleScroll = (e) => {
229
+ if (!scrollArrow)
230
+ return;
231
+ // Skip if no vertical scroll
232
+ if (Math.abs(e.deltaY) < 0.5)
233
+ return;
234
+ // Clear existing timeout
235
+ if (scrollTimeout) {
236
+ clearTimeout(scrollTimeout);
237
+ }
238
+ // Update arrow
239
+ const scrollDirection = e.deltaY > 0 ? 'down' : 'up';
240
+ scrollArrow.textContent = scrollDirection === 'down' ? '▼' : '▲';
241
+ // Position above/below cursor based on direction
242
+ // Arrow is 40px tall, cursor is ~20px, add 10px spacing
243
+ const offset = scrollDirection === 'down' ? 30 : -30;
244
+ scrollArrow.style.left = `${e.clientX - 20}px`;
245
+ scrollArrow.style.top = `${e.clientY + offset - 20}px`; // -20 to account for arrow center
246
+ // Scale based on deltaY magnitude
247
+ const scale = 0.8 + Math.min(Math.abs(e.deltaY) / 10, 0.4);
248
+ scrollArrow.style.transform = `scale(${scale})`;
249
+ scrollArrow.style.opacity = '0.4';
250
+ scrollArrow.style.display = 'block';
251
+ // Hide after scroll stops
252
+ scrollTimeout = setTimeout(() => {
253
+ if (scrollArrow) {
254
+ scrollArrow.style.opacity = '0';
255
+ setTimeout(() => {
256
+ if (scrollArrow)
257
+ scrollArrow.style.display = 'none';
258
+ }, 200);
259
+ }
260
+ }, 150);
261
+ };
262
+ // Add event listeners for both wheel and scroll events
263
+ document.addEventListener('wheel', handleScroll, { passive: true });
264
+ // Also listen to scroll events on window and document.body for better compatibility
265
+ window.addEventListener('wheel', handleScroll, { passive: true });
266
+ document.body.addEventListener('wheel', handleScroll, { passive: true });
267
+ // Hide cursor when it leaves the viewport
268
+ document.addEventListener('mouseleave', () => {
269
+ if (cursor) {
270
+ cursor.style.display = 'none';
271
+ }
272
+ // Clean up any active ripples
273
+ activeRipples.forEach(ripple => ripple.remove());
274
+ activeRipples.clear();
275
+ // Hide scroll arrow
276
+ if (scrollArrow) {
277
+ scrollArrow.style.display = 'none';
278
+ }
279
+ });
280
+ document.addEventListener('mouseenter', () => {
281
+ if (cursor) {
282
+ cursor.style.display = 'block';
283
+ }
284
+ });
285
+ }, { opacity: this.baseOpacity, showHoverCircle: this.showHoverCircle, showClickRipple: this.showClickRipple, showDragLine: this.showDragLine });
286
+ }
287
+ }
@@ -0,0 +1,10 @@
1
+ import { Page } from "playwright";
2
+ export declare class TypeEffectVisual {
3
+ private baseOpacity;
4
+ private displayDuration;
5
+ private maxKeys;
6
+ private page;
7
+ constructor(baseOpacity?: number, displayDuration?: number, maxKeys?: number);
8
+ setActivePage(page: Page): Promise<void>;
9
+ setupOnPage(): Promise<void>;
10
+ }
@@ -0,0 +1,190 @@
1
+ import { retryOnErrorIsSuccess } from "@/common";
2
+ export class TypeEffectVisual {
3
+ baseOpacity;
4
+ displayDuration;
5
+ maxKeys;
6
+ page;
7
+ constructor(baseOpacity = 0.6, displayDuration = 2000, maxKeys = 5) {
8
+ this.baseOpacity = baseOpacity;
9
+ this.displayDuration = displayDuration;
10
+ this.maxKeys = maxKeys;
11
+ }
12
+ async setActivePage(page) {
13
+ this.page = page;
14
+ page.on('load', async () => {
15
+ await retryOnErrorIsSuccess(this.setupOnPage.bind(this), { mode: 'retry_all', delayMs: 200, retryLimit: 10 });
16
+ });
17
+ await retryOnErrorIsSuccess(this.setupOnPage.bind(this), { mode: 'retry_all', delayMs: 200, retryLimit: 5 });
18
+ }
19
+ async setupOnPage() {
20
+ await this.page.evaluate((options) => {
21
+ if (window.__typeEffectsInitialized) {
22
+ return;
23
+ }
24
+ window.__typeEffectsInitialized = true;
25
+ // Create container for key badges
26
+ const container = document.createElement('div');
27
+ container.id = 'type-effects-container';
28
+ container.style.cssText = `
29
+ position: fixed;
30
+ bottom: 40px;
31
+ left: 50%;
32
+ transform: translateX(-50%);
33
+ display: flex;
34
+ gap: 8px;
35
+ align-items: center;
36
+ pointer-events: none;
37
+ z-index: 1000000060;
38
+ `;
39
+ document.body.appendChild(container);
40
+ // Add styles for key badges
41
+ const style = document.createElement('style');
42
+ style.setAttribute('data-type-effects', 'true');
43
+ style.textContent = `
44
+ @keyframes keyIn {
45
+ 0% {
46
+ opacity: 0;
47
+ transform: scale(0.5) translateY(20px);
48
+ }
49
+ 100% {
50
+ opacity: 1;
51
+ transform: scale(1) translateY(0);
52
+ }
53
+ }
54
+ @keyframes keyOut {
55
+ 0% {
56
+ opacity: 1;
57
+ transform: scale(1) translateY(0);
58
+ }
59
+ 100% {
60
+ opacity: 0;
61
+ transform: scale(0.8) translateY(10px);
62
+ }
63
+ }
64
+ .key-badge {
65
+ display: inline-flex;
66
+ align-items: center;
67
+ justify-content: center;
68
+ min-width: 40px;
69
+ height: 40px;
70
+ padding: 0 12px;
71
+ background: rgba(0, 100, 200, ${options.opacity * 0.9});
72
+ border: none;
73
+ border-radius: 6px;
74
+ font-family: monospace;
75
+ font-size: 16px;
76
+ font-weight: bold;
77
+ color: white;
78
+ animation: keyIn 0.2s ease-out forwards;
79
+ white-space: nowrap;
80
+ user-select: none;
81
+ -webkit-user-select: none;
82
+ -moz-user-select: none;
83
+ -ms-user-select: none;
84
+ }
85
+ .key-badge.fading {
86
+ animation: keyOut 0.3s ease-out forwards;
87
+ }
88
+ `;
89
+ document.head.appendChild(style);
90
+ // Define special keys to track (excluding modifiers on their own)
91
+ const specialKeys = {
92
+ 'Enter': '↵ Enter',
93
+ 'Tab': '⇥ Tab',
94
+ 'Delete': '⌦ Del',
95
+ 'Escape': '⎋ Esc',
96
+ 'ArrowUp': '↑',
97
+ 'ArrowDown': '↓',
98
+ 'ArrowLeft': '←',
99
+ 'ArrowRight': '→',
100
+ 'Home': '⇱ Home',
101
+ 'End': '⇲ End',
102
+ 'PageUp': '⇞ PgUp',
103
+ 'PageDown': '⇟ PgDn',
104
+ 'Insert': 'Ins',
105
+ };
106
+ // Active badges
107
+ const activeBadges = [];
108
+ // Handle keydown events
109
+ document.addEventListener('keydown', (e) => {
110
+ const key = e.key;
111
+ // Check if we have meaningful modifiers (Ctrl or Cmd)
112
+ const hasMeaningfulModifiers = e.ctrlKey || e.metaKey;
113
+ // For modifier combos, we want to show them with ANY key (including letters/numbers)
114
+ if (hasMeaningfulModifiers) {
115
+ // Skip if it's just a modifier key by itself
116
+ if (['Control', 'Alt', 'Shift', 'Meta'].includes(key)) {
117
+ return;
118
+ }
119
+ // Build the combo display
120
+ let modifiers = [];
121
+ if (e.ctrlKey)
122
+ modifiers.push('Ctrl');
123
+ if (e.metaKey)
124
+ modifiers.push('⌘');
125
+ // Include Shift/Alt only if Ctrl or Cmd is also pressed
126
+ if ((e.ctrlKey || e.metaKey) && e.shiftKey)
127
+ modifiers.push('Shift');
128
+ if ((e.ctrlKey || e.metaKey) && e.altKey)
129
+ modifiers.push('Alt');
130
+ // Get the key display
131
+ let keyDisplay = specialKeys[key] || key.toUpperCase();
132
+ if (key.length === 1) {
133
+ keyDisplay = key.toUpperCase();
134
+ }
135
+ const displayText = modifiers.join('+') + '+' + keyDisplay;
136
+ // Create badge
137
+ createBadge(displayText);
138
+ }
139
+ else {
140
+ // No modifiers - only show if it's a special key
141
+ const keyDisplay = specialKeys[key];
142
+ if (keyDisplay) {
143
+ createBadge(keyDisplay);
144
+ }
145
+ }
146
+ });
147
+ function createBadge(displayText) {
148
+ // Create badge element
149
+ const badge = document.createElement('div');
150
+ badge.className = 'key-badge';
151
+ badge.textContent = displayText;
152
+ // Add to container
153
+ container.appendChild(badge);
154
+ // Set up removal timeout
155
+ const timeout = setTimeout(() => {
156
+ badge.classList.add('fading');
157
+ setTimeout(() => {
158
+ badge.remove();
159
+ // Remove from active badges
160
+ const index = activeBadges.findIndex(b => b.element === badge);
161
+ if (index !== -1) {
162
+ activeBadges.splice(index, 1);
163
+ }
164
+ }, 300);
165
+ }, options.displayDuration);
166
+ // Track active badge
167
+ activeBadges.push({ element: badge, timeout });
168
+ // Remove oldest badges if we exceed max
169
+ while (activeBadges.length > options.maxKeys) {
170
+ const oldest = activeBadges.shift();
171
+ if (oldest) {
172
+ clearTimeout(oldest.timeout);
173
+ oldest.element.classList.add('fading');
174
+ setTimeout(() => oldest.element.remove(), 300);
175
+ }
176
+ }
177
+ }
178
+ // Clean up on page hide
179
+ document.addEventListener('visibilitychange', () => {
180
+ if (document.hidden) {
181
+ activeBadges.forEach(({ element, timeout }) => {
182
+ clearTimeout(timeout);
183
+ element.remove();
184
+ });
185
+ activeBadges.length = 0;
186
+ }
187
+ });
188
+ }, { opacity: this.baseOpacity, displayDuration: this.displayDuration, maxKeys: this.maxKeys });
189
+ }
190
+ }
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "@ddwang/magnitude-core",
3
+ "version": "0.3.1-ddwang.1",
4
+ "description": "Magnitude e2e testing agent",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "main": "./dist/index.cjs",
9
+ "module": "./dist/index.mjs",
10
+ "types": "./dist/index.d.cts",
11
+ "bin": {
12
+ "magnus": "dist/cli.js"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/magnitudedev/magnitude.git"
17
+ },
18
+ "homepage": "https://github.com/magnitudedev/magnitude#readme",
19
+ "bugs": {
20
+ "url": "https://github.com/magnitudedev/magnitude/issues"
21
+ },
22
+ "files": [
23
+ "dist"
24
+ ],
25
+ "keywords": [
26
+ "ai",
27
+ "agent",
28
+ "testing",
29
+ "ui-testing",
30
+ "automation",
31
+ "magnitude",
32
+ "typescript"
33
+ ],
34
+ "scripts": {
35
+ "build": "baml-cli generate && tsc && pkgroll",
36
+ "check": "tsc --noEmit",
37
+ "cli": "bun ./src/cli.ts",
38
+ "pubdev": "bun run build && yalc publish --force --push"
39
+ },
40
+ "author": {
41
+ "name": "Magnitude",
42
+ "email": "founders@magnitude.run",
43
+ "url": "https://magnitude.run"
44
+ },
45
+ "contributors": [
46
+ "Anders Lie <anders@magnitude.run>"
47
+ ],
48
+ "license": "Apache-2.0",
49
+ "devDependencies": {
50
+ "@types/node": "^22.13.4",
51
+ "@types/object-hash": "^3.0.6",
52
+ "pkgroll": "^2.10.0",
53
+ "typescript": "~5.7.2"
54
+ },
55
+ "dependencies": {
56
+ "@boundaryml/baml": "^0.202.0",
57
+ "@paralleldrive/cuid2": "^2.2.2",
58
+ "ansis": "^4.1.0",
59
+ "commander": "^13.1.0",
60
+ "eventemitter3": "^5.0.1",
61
+ "magnitude-extract": "0.0.2",
62
+ "object-hash": "^3.0.0",
63
+ "pino": "^9.6.0",
64
+ "pino-pretty": "^13.0.0",
65
+ "playwright": "npm:patchright@^1.52.0",
66
+ "posthog-node": "^5.1.1",
67
+ "sharp": "^0.33.5",
68
+ "zod": "^3.24.4",
69
+ "zod-to-json-schema": "^3.24.5"
70
+ }
71
+ }