@opentiny/next-sdk 0.4.2 → 0.4.3

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 (88) hide show
  1. package/dist/{SimulatorMask-BHVXyogh-CARX3Rff.js → SimulatorMask-BHVXyogh-CKmEDsYG.js} +1 -1
  2. package/dist/{index-R_HIbfUX.js → index-CHMa2zG4.js} +1065 -1042
  3. package/dist/index.js +1 -1
  4. package/dist/page-tools/a11y/config.d.ts +6 -3
  5. package/dist/page-tools/a11y/constants.d.ts +20 -0
  6. package/dist/page-tools/a11y/utils.d.ts +14 -0
  7. package/dist/page-tools/constants.d.ts +4 -2
  8. package/dist/page-tools/context.d.ts +2 -0
  9. package/dist/page-tools/handlers/hover.d.ts +9 -0
  10. package/dist/page-tools/schema.d.ts +3 -3
  11. package/dist/page-tools/utils/dom.d.ts +8 -2
  12. package/dist/runtime.js +19 -172
  13. package/package.json +6 -1
  14. package/WebMcpClient.ts +0 -505
  15. package/WebMcpServer.ts +0 -447
  16. package/agent/AgentModelProvider.ts +0 -932
  17. package/agent/type.ts +0 -91
  18. package/agent/utils/generateReActPrompt.ts +0 -71
  19. package/agent/utils/getAISDKTools.ts +0 -34
  20. package/agent/utils/getBuiltinMcpTools.ts +0 -86
  21. package/agent/utils/parseReActAction.ts +0 -34
  22. package/core.ts +0 -26
  23. package/index.ts +0 -91
  24. package/page-tools/a11y/build.ts +0 -74
  25. package/page-tools/a11y/config.ts +0 -465
  26. package/page-tools/a11y/constants.ts +0 -131
  27. package/page-tools/a11y/search.ts +0 -127
  28. package/page-tools/a11y/types.ts +0 -105
  29. package/page-tools/a11y/utils.ts +0 -239
  30. package/page-tools/a11y/vnode.ts +0 -439
  31. package/page-tools/a11y-tree.ts +0 -14
  32. package/page-tools/bridge.ts +0 -722
  33. package/page-tools/configs/console-cloud.ts +0 -172
  34. package/page-tools/constants.ts +0 -12
  35. package/page-tools/context.ts +0 -50
  36. package/page-tools/effects.ts +0 -345
  37. package/page-tools/handlers/browserState.ts +0 -12
  38. package/page-tools/handlers/click.ts +0 -30
  39. package/page-tools/handlers/executeJavascript.ts +0 -22
  40. package/page-tools/handlers/fill.ts +0 -65
  41. package/page-tools/handlers/scroll.ts +0 -66
  42. package/page-tools/handlers/searchTree.ts +0 -27
  43. package/page-tools/handlers/select.ts +0 -39
  44. package/page-tools/initialize-builtin-WebMCP.ts +0 -20
  45. package/page-tools/page-agent-highlight/index.ts +0 -245
  46. package/page-tools/page-agent-mask/SimulatorMask.module.css +0 -14
  47. package/page-tools/page-agent-mask/SimulatorMask.ts +0 -299
  48. package/page-tools/page-agent-mask/checkDarkMode.ts +0 -181
  49. package/page-tools/page-agent-mask/cursor-border.svg +0 -3
  50. package/page-tools/page-agent-mask/cursor-fill.svg +0 -5
  51. package/page-tools/page-agent-mask/cursor.module.css +0 -70
  52. package/page-tools/page-agent-mask/hauwei.svg +0 -25
  53. package/page-tools/page-agent-prompt.md +0 -139
  54. package/page-tools/page-agent-tool-event.ts +0 -113
  55. package/page-tools/page-agent-tool.ts +0 -207
  56. package/page-tools/page-state-cache.ts +0 -78
  57. package/page-tools/schema.ts +0 -52
  58. package/page-tools/tool-config.ts +0 -100
  59. package/page-tools/utils/dom.ts +0 -158
  60. package/page-tools/utils/scroll.ts +0 -58
  61. package/remoter/QrCode.ts +0 -54
  62. package/remoter/createRemoter.ts +0 -957
  63. package/remoter/svgs/chat.svg +0 -43
  64. package/remoter/svgs/icon-copy.svg +0 -25
  65. package/remoter/svgs/link.svg +0 -28
  66. package/remoter/svgs/logo.svg +0 -45
  67. package/remoter/svgs/qrcode.svg +0 -35
  68. package/remoter/svgs/scan.svg +0 -21
  69. package/remoter/tooltips.ts +0 -260
  70. package/runtime.html +0 -39
  71. package/runtime.ts +0 -44
  72. package/script/utils.ts +0 -26
  73. package/skills/index.ts +0 -287
  74. package/test/page-tools/a11y/build.test.ts +0 -638
  75. package/test/page-tools/a11y/config.test.ts +0 -370
  76. package/test/page-tools/configs/console-cloud.test.ts +0 -168
  77. package/test/page-tools/page-agent-highlight.test.ts +0 -110
  78. package/test/page-tools/page-agent-tool-dispatch.test.ts +0 -208
  79. package/test/page-tools/page-agent-tool.test.ts +0 -102
  80. package/test/page-tools/tool-config.test.ts +0 -112
  81. package/test/page-tools/utils/dom.test.ts +0 -122
  82. package/tsconfig.json +0 -16
  83. package/utils/builtinProxy.ts +0 -144
  84. package/utils/env.ts +0 -13
  85. package/utils/uuid.ts +0 -10
  86. package/vite.config.runtime.ts +0 -22
  87. package/vite.config.ts +0 -63
  88. package/vitest.config.ts +0 -10
@@ -1,299 +0,0 @@
1
- import { Motion } from 'ai-motion'
2
-
3
- import { isPageDark } from './checkDarkMode'
4
-
5
- const injectStyles = `
6
- .webmcp-page-agent-cursor {
7
- position: absolute;
8
- width: var(--cursor-size, 75px);
9
- height: var(--cursor-size, 75px);
10
- pointer-events: none;
11
- z-index: 10000;
12
- }
13
-
14
- .webmcp-page-agent-cursorFilling {
15
- position: absolute;
16
- width: 100%;
17
- height: 100%;
18
- background: url("data:image/svg+xml,%3Csvg%20viewBox%3D%270%200%2079.0834%2079.4553%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20%20width%3D%2779.083374%27%20height%3D%2779.455322%27%20fill%3D%27none%27%20%3E--%3Cdefs%3E%3Cfilter%20id%3D%27filter_0%27%20width%3D%2779.083374%27%20height%3D%2779.455322%27%20x%3D%270.000000%27%20y%3D%270.000000%27%20filterUnits%3D%27userSpaceOnUse%27%20%20color-interpolation-filters%3D%27sRGB%27%3E%3CfeFlood%20flood-opacity%3D%270%27%20result%3D%27BackgroundImageFix%27%20%2F%3E%3CfeOffset%20dx%3D%276.000000%27%20dy%3D%276.000000%27%20in%3D%27SourceAlpha%27%20%2F%3E%3CfeGaussianBlur%20stdDeviation%3D%276.66666651%27%20%2F%3E%3CfeColorMatrix%20type%3D%27matrix%27%20values%3D%270%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200.18%200%20%27%20%2F%3E%3CfeBlend%20result%3D%27effect_dropShadow_1%27%20in2%3D%27BackgroundImageFix%27%20mode%3D%27normal%27%20%2F%3E%3CfeBlend%20result%3D%27shape%27%20in%3D%27SourceGraphic%27%20in2%3D%27effect_dropShadow_1%27%20mode%3D%27normal%27%20%2F%3E%3C%2Ffilter%3E%3ClinearGradient%20id%3D%27paint_linear_0%27%20x1%3D%2718.4743214%27%20x2%3D%2718.4213886%27%20y1%3D%27-1.86264515e-09%27%20y2%3D%2734.9221306%27%20gradientUnits%3D%27userSpaceOnUse%27%3E%3Cstop%20stop-color%3D%27rgb%28255%2C181%2C96%29%27%20offset%3D%270%27%20stop-opacity%3D%271%27%20%2F%3E%3Cstop%20stop-color%3D%27rgb%28255%2C120%2C114%29%27%20offset%3D%270.5%27%20stop-opacity%3D%271%27%20%2F%3E%3Cstop%20stop-color%3D%27rgb%28241%2C109%2C237%29%27%20offset%3D%271%27%20stop-opacity%3D%271%27%20%2F%3E%3C%2FlinearGradient%3E%3C%2Fdefs%3E%3Cg%20filter%3D%27url%28%23filter_0%29%27%3E%3Cpath%20d%3D%27M20.2632%203.57771L34.6257%2032.3027C35.4444%2033.9402%2033.8152%2035.7258%2032.1097%2035.0603L19.2014%2030.0229C18.7339%2029.8404%2018.2148%2029.8404%2017.7472%2030.0229L4.83891%2035.0603C3.13343%2035.7258%201.50423%2033.9402%202.32297%2032.3027L16.6855%203.57771C17.4225%202.10361%2019.5261%202.10361%2020.2632%203.57771Z%27%20fill%3D%27url%28%23paint_linear_0%29%27%20fill-rule%3D%27evenodd%27%20transform%3D%27matrix%280.719908%2C-0.69407%2C0.69407%2C0.719908%2C2.00256%2C28.0095%29%27%20%2F%3E%3Cpath%20d%3D%27M37.2169%2032.6848C37.1578%2032.189%2037.0096%2031.7039%2036.7723%2031.2294L22.4098%202.5044C22.1973%202.07946%2021.9328%201.70554%2021.6163%201.38261C21.3524%201.11342%2021.0524%200.879671%2020.7162%200.681366C20.3925%200.490407%2020.0558%200.34434%2019.7061%200.243163C19.312%200.129145%2018.9014%200.0721366%2018.4743%200.0721366C18.0472%200.0721366%2017.6367%200.129145%2017.2426%200.243163C16.8929%200.34434%2016.5562%200.490407%2016.2324%200.681366C15.8962%200.879671%2015.5962%201.11342%2015.3323%201.38261C15.0158%201.70553%2014.7513%202.07946%2014.5388%202.5044L0.176342%2031.2294C-0.0609121%2031.7039%20-0.209128%2032.189%20-0.268305%2032.6848C-0.316251%2033.0865%20-0.305747%2033.4951%20-0.236792%2033.9108C-0.171059%2034.307%20-0.0570567%2034.6809%200.105216%2035.0326C0.292784%2035.4391%200.544845%2035.8158%200.861397%2036.1627C1.17794%2036.5097%201.53001%2036.7951%201.91761%2037.0191C2.25297%2037.2128%202.61492%2037.3606%203.00348%2037.4623C3.41106%2037.5689%203.81704%2037.6168%204.22142%2037.6058C4.72053%2037.5922%205.21719%2037.4889%205.71141%2037.2961L18.4743%2032.3154L31.2372%2037.2961C31.7315%2037.4889%2032.2281%2037.5922%2032.7272%2037.6058C33.1316%2037.6168%2033.5376%2037.5689%2033.9452%2037.4623C34.3337%2037.3606%2034.6957%2037.2128%2035.0311%2037.0191C35.4187%2036.7951%2035.7707%2036.5097%2036.0873%2036.1627C36.4038%2035.8158%2036.6558%2035.4391%2036.8434%2035.0327C37.0057%2034.681%2037.1197%2034.307%2037.1854%2033.9108C37.2544%2033.4951%2037.2649%2033.0865%2037.2169%2032.6848ZM34.6257%2032.3027L20.2632%203.57771C19.5261%202.10361%2017.4225%202.10361%2016.6855%203.57771L2.32297%2032.3027C1.50423%2033.9402%203.13343%2035.7258%204.83891%2035.0603L17.7472%2030.0229C18.2148%2029.8404%2018.7339%2029.8404%2019.2014%2030.0229L32.1097%2035.0603C33.8152%2035.7258%2035.4444%2033.9402%2034.6257%2032.3027Z%27%20fill%3D%27rgb%28255%2C255%2C255%29%27%20fill-rule%3D%27evenodd%27%20transform%3D%27matrix%280.719908%2C-0.69407%2C0.69407%2C0.719908%2C2.00256%2C28.0095%29%27%20%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");
19
- background-size: 100% 100%;
20
- background-repeat: no-repeat;
21
-
22
- transform-origin: center;
23
- margin-left: -10px;
24
- margin-top: -18px;
25
- }
26
-
27
- .webmcp-page-agent-cursorRipple {
28
- position: absolute;
29
- width: 100%;
30
- height: 100%;
31
- pointer-events: none;
32
- margin-left: -50%;
33
- margin-top: -50%;
34
-
35
- &::after {
36
- content: '';
37
- opacity: 0;
38
- position: absolute;
39
- inset: 0;
40
- border: 4px solid rgba(57, 182, 255, 1);
41
- border-radius: 50%;
42
- }
43
- }
44
-
45
- .webmcp-page-agent-cursor.clicking .webmcp-page-agent-cursorRipple::after {
46
- animation: webmcp-page-agent-cursor-ripple 300ms ease-out forwards;
47
- }
48
-
49
- @keyframes webmcp-page-agent-cursor-ripple {
50
- 0% {
51
- transform: scale(0);
52
- opacity: 1;
53
- }
54
-
55
- 100% {
56
- transform: scale(2);
57
- opacity: 0;
58
- }
59
- }
60
-
61
- .webmcp-page-agent-wrapper {
62
- position: fixed;
63
- inset: 0;
64
- z-index: 2147483641;
65
- /* 确保在所有元素之上,除了 panel */
66
- cursor: wait;
67
- overflow: hidden;
68
-
69
- display: none;
70
- }
71
-
72
- .webmcp-page-agent-wrapper.visible {
73
- display: block;
74
- }
75
- `
76
-
77
- export class SimulatorMask extends EventTarget {
78
- shown: boolean = false
79
- wrapper = document.createElement('div')
80
- motion: Motion | null = null
81
-
82
- #disposed = false
83
-
84
- #cursor = document.createElement('div')
85
-
86
- #currentCursorX = 0
87
- #currentCursorY = 0
88
-
89
- #targetCursorX = 0
90
- #targetCursorY = 0
91
-
92
- constructor() {
93
- super()
94
- // 注入样式,防止打包失败
95
- document.head.appendChild(document.createElement('style')).textContent = injectStyles
96
- this.wrapper.id = 'page-agent-runtime_simulator-mask'
97
- this.wrapper.className = 'webmcp-page-agent-wrapper'
98
- this.wrapper.setAttribute('data-browser-use-ignore', 'true')
99
- this.wrapper.setAttribute('data-page-agent-ignore', 'true')
100
-
101
- try {
102
- const motion = new Motion({
103
- mode: isPageDark() ? 'dark' : 'light',
104
- styles: { position: 'absolute', inset: '0' },
105
- glowWidth: 80,
106
- borderWidth: 8,
107
- colors: ['rgb(121, 216, 247)', 'rgb(171, 219, 110)', 'rgb(252, 188, 114)', 'rgb(235, 117, 231)']
108
- })
109
- this.motion = motion
110
- this.wrapper.appendChild(motion.element)
111
- motion.autoResize(this.wrapper)
112
- } catch (e) {
113
- console.warn('[SimulatorMask] Motion overlay unavailable:', e)
114
- }
115
-
116
- const stopEvent = (e: Event) => {
117
- e.stopPropagation()
118
- e.preventDefault()
119
- }
120
- ;['click', 'mousedown', 'mouseup', 'mousemove', 'wheel', 'keydown', 'keyup'].forEach((eventName) =>
121
- this.wrapper.addEventListener(eventName, stopEvent)
122
- )
123
- // Create AI cursor
124
- this.#createCursor()
125
- // this.show()
126
-
127
- document.body.appendChild(this.wrapper)
128
-
129
- this.#moveCursorToTarget()
130
-
131
- // global events
132
- // @note Mask should be isolated from the rest of the code.
133
- // Global events are easier to manage and cleanup.
134
-
135
- const movePointerToListener = (event: Event) => {
136
- const { x, y } = (event as CustomEvent).detail
137
- this.setCursorPosition(x, y)
138
- }
139
- const clickPointerListener = () => {
140
- this.triggerClickAnimation()
141
- }
142
- const enablePassThroughListener = () => {
143
- this.wrapper.style.pointerEvents = 'none'
144
- }
145
- const disablePassThroughListener = () => {
146
- this.wrapper.style.pointerEvents = 'auto'
147
- }
148
-
149
- window.addEventListener('PageAgent::MovePointerTo', movePointerToListener)
150
- window.addEventListener('PageAgent::ClickPointer', clickPointerListener)
151
- window.addEventListener('PageAgent::EnablePassThrough', enablePassThroughListener)
152
- window.addEventListener('PageAgent::DisablePassThrough', disablePassThroughListener)
153
-
154
- this.addEventListener('dispose', () => {
155
- window.removeEventListener('PageAgent::MovePointerTo', movePointerToListener)
156
- window.removeEventListener('PageAgent::ClickPointer', clickPointerListener)
157
- window.removeEventListener('PageAgent::EnablePassThrough', enablePassThroughListener)
158
- window.removeEventListener('PageAgent::DisablePassThrough', disablePassThroughListener)
159
- })
160
- }
161
-
162
- #createCursor() {
163
- this.#cursor.className = 'webmcp-page-agent-cursor'
164
-
165
- // Create ripple effect container
166
- const rippleContainer = document.createElement('div')
167
- rippleContainer.className = 'webmcp-page-agent-cursorRipple'
168
- this.#cursor.appendChild(rippleContainer)
169
-
170
- // Create filling layer
171
- const fillingLayer = document.createElement('div')
172
- fillingLayer.className = 'webmcp-page-agent-cursorFilling'
173
- this.#cursor.appendChild(fillingLayer)
174
-
175
- // Create border layer
176
- // const borderLayer = document.createElement('div')
177
- // borderLayer.className = 'webmcp-page-agent-cursorBorder'
178
- // this.#cursor.appendChild(borderLayer)
179
-
180
- this.wrapper.appendChild(this.#cursor)
181
- }
182
-
183
- #moveCursorToTarget() {
184
- if (this.#disposed) return
185
-
186
- const newX = this.#currentCursorX + (this.#targetCursorX - this.#currentCursorX) * 0.2
187
- const newY = this.#currentCursorY + (this.#targetCursorY - this.#currentCursorY) * 0.2
188
-
189
- const xDistance = Math.abs(newX - this.#targetCursorX)
190
- if (xDistance > 0) {
191
- if (xDistance < 2) {
192
- this.#currentCursorX = this.#targetCursorX
193
- } else {
194
- this.#currentCursorX = newX
195
- }
196
- this.#cursor.style.left = `${this.#currentCursorX}px`
197
- }
198
-
199
- const yDistance = Math.abs(newY - this.#targetCursorY)
200
- if (yDistance > 0) {
201
- if (yDistance < 2) {
202
- this.#currentCursorY = this.#targetCursorY
203
- } else {
204
- this.#currentCursorY = newY
205
- }
206
- this.#cursor.style.top = `${this.#currentCursorY}px`
207
- }
208
-
209
- requestAnimationFrame(() => this.#moveCursorToTarget())
210
- }
211
-
212
- setCursorPosition(x: number, y: number) {
213
- if (this.#disposed) return
214
-
215
- this.#targetCursorX = x
216
- this.#targetCursorY = y
217
- }
218
-
219
- triggerClickAnimation() {
220
- if (this.#disposed) return
221
-
222
- this.#cursor.classList.remove('clicking')
223
- // Force reflow to restart animation
224
- void this.#cursor.offsetHeight
225
- this.#cursor.classList.add('clicking')
226
- }
227
-
228
- show() {
229
- if (this.shown || this.#disposed) return
230
-
231
- this.shown = true
232
- this.motion?.start()
233
- this.motion?.fadeIn()
234
-
235
- this.wrapper.classList.add('visible')
236
-
237
- // Initialize cursor position
238
- this.#currentCursorX = window.innerWidth / 2
239
- this.#currentCursorY = window.innerHeight / 2
240
- this.#targetCursorX = this.#currentCursorX
241
- this.#targetCursorY = this.#currentCursorY
242
- this.#cursor.style.left = `${this.#currentCursorX}px`
243
- this.#cursor.style.top = `${this.#currentCursorY}px`
244
- }
245
-
246
- hide() {
247
- if (!this.shown || this.#disposed) return
248
-
249
- this.shown = false
250
- this.motion?.fadeOut()
251
- this.motion?.pause()
252
-
253
- this.#cursor.classList.remove('clicking')
254
-
255
- setTimeout(() => {
256
- this.wrapper.classList.remove('visible')
257
- }, 800) // Match the animation duration
258
- }
259
-
260
- dispose() {
261
- this.#disposed = true
262
- this.motion?.dispose()
263
- this.wrapper.remove()
264
- this.dispatchEvent(new Event('dispose'))
265
- }
266
- // 根据目标元素大小,在 wrapper 添加绝对定位边框:2px 宽、与目标间距 2px,对角渐变 (0,0 → 1,1)
267
- borderElement(targetElement: HTMLElement) {
268
- if (!targetElement) return
269
-
270
- this.wrapper.querySelector('.webmcp-page-agent-border')?.remove()
271
-
272
- const rect = targetElement.getBoundingClientRect()
273
- const gap = 2
274
- const borderWidth = 2
275
- const offset = gap + borderWidth
276
-
277
- const el = document.createElement('div')
278
- el.className = 'webmcp-page-agent-border'
279
- el.style.position = 'absolute'
280
- el.style.left = `${rect.left - offset}px`
281
- el.style.top = `${rect.top - offset}px`
282
- el.style.width = `${rect.width + offset * 2}px`
283
- el.style.height = `${rect.height + offset * 2}px`
284
- el.style.boxSizing = 'border-box'
285
- el.style.pointerEvents = 'none'
286
- el.style.zIndex = '10000'
287
- el.style.border = `${borderWidth}px solid transparent`
288
- // 对角渐变:左上 (0,0) → 右下 (1,1)
289
- el.style.borderImageSource = 'linear-gradient(to bottom right, #79D8F7, #ABDB6E, #FCBC72, #FA8682, #EB75E7)'
290
- el.style.borderImageSlice = '1'
291
- el.style.borderImageWidth = `${borderWidth}px`
292
-
293
- this.wrapper.appendChild(el)
294
- }
295
-
296
- removeBorderElement() {
297
- this.wrapper.querySelector('.webmcp-page-agent-border')?.remove()
298
- }
299
- }
@@ -1,181 +0,0 @@
1
- /**
2
- * A comprehensive function to determine if the page is currently in a dark theme.
3
- * Heuristic check. Only work for common patterns. Return false by default.
4
- */
5
- export function isPageDark() {
6
- try {
7
- if (hasDarkModeClass()) return true
8
- if (hasDarkModeDataAttribute()) return true
9
- if (isColorSchemeDark()) return true
10
- if (isBackgroundDark()) return true
11
- if (isMainContentBackgroundDark()) return true
12
- if (isTextColorLight()) return true
13
-
14
- return false
15
- } catch (error) {
16
- console.warn('Error determining if page is dark:', error)
17
- return false
18
- }
19
- }
20
-
21
- /**
22
- * Checks for common dark mode CSS classes on the html or body elements.
23
- */
24
- function hasDarkModeClass() {
25
- const DEFAULT_DARK_MODE_CLASSES = ['dark', 'dark-mode', 'theme-dark', 'night', 'night-mode']
26
-
27
- const htmlElement = document.documentElement
28
- const bodyElement = document.body || document.documentElement // can be null in some cases
29
-
30
- // Check class names on <html> and <body>
31
- for (const className of DEFAULT_DARK_MODE_CLASSES) {
32
- if (htmlElement.classList.contains(className) || bodyElement?.classList.contains(className)) {
33
- return true
34
- }
35
- }
36
-
37
- return false
38
- }
39
-
40
- /**
41
- * Some UI frameworks use data attributes to indicate theme
42
- */
43
- function hasDarkModeDataAttribute() {
44
- const htmlElement = document.documentElement
45
- const bodyElement = document.body || document.documentElement // can be null in some cases
46
-
47
- const dataAttrs = ['data-theme', 'data-color-mode', 'data-bs-theme', 'data-mui-color-scheme']
48
- for (const attr of dataAttrs) {
49
- const bodyValue = bodyElement?.getAttribute(attr)
50
- const htmlValue = htmlElement.getAttribute(attr)
51
-
52
- if (bodyValue?.toLowerCase() === 'dark' || htmlValue?.toLowerCase() === 'dark') {
53
- return true
54
- }
55
- }
56
-
57
- return false
58
- }
59
-
60
- /**
61
- * Checks the CSS `color-scheme` property and `<meta name="color-scheme">` tag.
62
- * Only "dark"/"only dark" counts as dark; "light dark" is ambiguous and ignored.
63
- */
64
- function isColorSchemeDark() {
65
- // Check <meta name="color-scheme" content="dark">
66
- const meta = document.querySelector<HTMLMetaElement>('meta[name="color-scheme"]')
67
- const metaContent = meta?.content.toLowerCase()
68
- if (metaContent === 'dark' || metaContent === 'only dark') return true
69
-
70
- // Check the computed color-scheme CSS property on :root
71
- const rootStyle = window.getComputedStyle(document.documentElement)
72
- const colorScheme = rootStyle.getPropertyValue('color-scheme').trim().toLowerCase()
73
- return colorScheme === 'dark' || colorScheme === 'only dark'
74
- }
75
-
76
- /**
77
- * Checks the background color of the body element to determine if the page is dark.
78
- */
79
- function isBackgroundDark() {
80
- // We check both <html> and <body> because some pages set the color on <html>
81
- const htmlStyle = window.getComputedStyle(document.documentElement)
82
- const bodyStyle = window.getComputedStyle(document.body || document.documentElement)
83
-
84
- // Get background colors
85
- const htmlBgColor = htmlStyle.backgroundColor
86
- const bodyBgColor = bodyStyle.backgroundColor
87
-
88
- // The body's background might be transparent, in which case we should
89
- // fall back to the html element's background.
90
- if (isColorDark(bodyBgColor)) {
91
- return true
92
- } else if (bodyBgColor === 'transparent' || bodyBgColor.startsWith('rgba(0, 0, 0, 0)')) {
93
- return isColorDark(htmlBgColor)
94
- }
95
-
96
- return false
97
- }
98
-
99
- /**
100
- * Checks if the text color on the body is light, which implies a dark background.
101
- */
102
- function isTextColorLight() {
103
- /** Luminance (0-255) above which body text is considered light */
104
- const LIGHT_TEXT_LUMINANCE = 200
105
-
106
- const bodyStyle = window.getComputedStyle(document.body || document.documentElement)
107
- const luminance = getLuminance(bodyStyle.color)
108
-
109
- // Light text has high luminance (e.g. white text on dark bg)
110
- return luminance !== null && luminance > LIGHT_TEXT_LUMINANCE
111
- }
112
-
113
- /**
114
- * Checks the background color of major layout elements (#app, #root, etc.).
115
- * Many SPAs render into a container that may have its own dark background while
116
- * <body> remains transparent.
117
- */
118
- function isMainContentBackgroundDark() {
119
- const { innerWidth: vw, innerHeight: vh } = window
120
- const minArea = vw * vh * 0.5
121
-
122
- const selectors = ['#app', '#root', '#__next']
123
- for (const selector of selectors) {
124
- const el = document.querySelector(selector)
125
- if (!el) continue
126
-
127
- const rect = el.getBoundingClientRect()
128
- if (rect.width * rect.height < minArea) continue
129
-
130
- if (isColorDark(window.getComputedStyle(el).backgroundColor)) return true
131
- }
132
- return false
133
- }
134
-
135
- // --- utils ---
136
-
137
- /**
138
- * Parses an RGB or RGBA color string and returns an object with r, g, b properties.
139
- * @param {string} colorString - e.g., "rgb(34, 34, 34)" or "rgba(0, 0, 0, 0.5)"
140
- * @returns {{r: number, g: number, b: number}|null}
141
- */
142
- function parseRgbColor(colorString: string) {
143
- const rgbMatch = /rgba?\((\d+),\s*(\d+),\s*(\d+)/.exec(colorString)
144
- if (!rgbMatch) {
145
- return null // Not a valid rgb/rgba string
146
- }
147
- return {
148
- r: parseInt(rgbMatch[1]),
149
- g: parseInt(rgbMatch[2]),
150
- b: parseInt(rgbMatch[3]),
151
- }
152
- }
153
-
154
- /**
155
- * Calculates the perceived luminance (0-255) of a CSS color string.
156
- * @param {string} colorString - e.g., "rgb(50, 50, 50)" or "rgba(0, 0, 0, 0.5)"
157
- * @returns {number|null} - The luminance, or null if the color is transparent or unparseable.
158
- */
159
- function getLuminance(colorString: string): number | null {
160
- if (!colorString || colorString === 'transparent' || colorString.startsWith('rgba(0, 0, 0, 0)')) {
161
- return null // Transparent has no meaningful luminance
162
- }
163
-
164
- const rgb = parseRgbColor(colorString)
165
- if (!rgb) {
166
- return null // Could not parse color
167
- }
168
-
169
- // Standard perceived luminance formula
170
- return 0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b
171
- }
172
-
173
- /**
174
- * Determines if a color is "dark" based on its calculated luminance.
175
- * @param {string} colorString - The CSS color string (e.g., "rgb(50, 50, 50)").
176
- * @param {number} threshold - A value between 0 and 255. Colors with luminance below this will be considered dark. Default is 128.
177
- */
178
- function isColorDark(colorString: string, threshold = 128) {
179
- const luminance = getLuminance(colorString)
180
- return luminance !== null && luminance < threshold
181
- }
@@ -1,3 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" fill="none">
2
- <g><path d="M 15 42 L 15 36.99 Q 15 31.99 23.7 31.99 L 28.05 31.99 Q 32.41 31.99 32.41 21.99 L 32.41 17 Q 32.41 12 41.09 16.95 L 76.31 37.05 Q 85 42 76.31 46.95 L 41.09 67.05 Q 32.41 72 32.41 62.01 L 32.41 57.01 Q 32.41 52.01 23.7 52.01 L 19.35 52.01 Q 15 52.01 15 47.01 Z" fill="none" stroke="#000000" stroke-width="6" stroke-miterlimit="10" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g>
3
- </svg>
@@ -1,5 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
2
- <defs>
3
- </defs>
4
- <g xmlns="http://www.w3.org/2000/svg" style="filter: drop-shadow(light-dark(rgba(0, 0, 0, 0.4), rgba(237, 237, 237, 0.4)) 3px 4px 4px);"><path d="M 15 42 L 15 36.99 Q 15 31.99 23.7 31.99 L 28.05 31.99 Q 32.41 31.99 32.41 21.99 L 32.41 17 Q 32.41 12 41.09 16.95 L 76.31 37.05 Q 85 42 76.31 46.95 L 41.09 67.05 Q 32.41 72 32.41 62.01 L 32.41 57.01 Q 32.41 52.01 23.7 52.01 L 19.35 52.01 Q 15 52.01 15 47.01 Z" fill="#ffffff" stroke="none" style="fill: #ffffff;"/></g>
5
- </svg>
@@ -1,70 +0,0 @@
1
- .webmcp-page-agent-cursor {
2
- position: absolute;
3
- width: var(--cursor-size, 75px);
4
- height: var(--cursor-size, 75px);
5
- pointer-events: none;
6
- z-index: 10000;
7
- }
8
-
9
- .webmcp-page-agent-cursorBorder {
10
- position: absolute;
11
- width: 100%;
12
- height: 100%;
13
- background: linear-gradient(45deg, rgb(57, 182, 255), rgb(189, 69, 251));
14
- mask-image: url("data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20100%20100'%20fill='none'%3e%3cg%3e%3cpath%20d='M%2015%2042%20L%2015%2036.99%20Q%2015%2031.99%2023.7%2031.99%20L%2028.05%2031.99%20Q%2032.41%2031.99%2032.41%2021.99%20L%2032.41%2017%20Q%2032.41%2012%2041.09%2016.95%20L%2076.31%2037.05%20Q%2085%2042%2076.31%2046.95%20L%2041.09%2067.05%20Q%2032.41%2072%2032.41%2062.01%20L%2032.41%2057.01%20Q%2032.41%2052.01%2023.7%2052.01%20L%2019.35%2052.01%20Q%2015%2052.01%2015%2047.01%20Z'%20fill='none'%20stroke='%23000000'%20stroke-width='6'%20stroke-miterlimit='10'%20style='stroke:%20light-dark(rgb(0,%200,%200),%20rgb(255,%20255,%20255));'/%3e%3c/g%3e%3c/svg%3e");
15
- mask-size: 100% 100%;
16
- mask-repeat: no-repeat;
17
-
18
- transform-origin: center;
19
- transform: rotate(-90deg) scale(0.8);
20
- margin-left: -10px;
21
- margin-top: -18px;
22
- }
23
-
24
- .webmcp-page-agent-cursorFilling {
25
- position: absolute;
26
- width: 100%;
27
- height: 100%;
28
- background: url("data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20100%20100'%3e%3cdefs%3e%3c/defs%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20style='filter:%20drop-shadow(light-dark(rgba(0,%200,%200,%200.4),%20rgba(237,%20237,%20237,%200.4))%203px%204px%204px);'%3e%3cpath%20d='M%2015%2042%20L%2015%2036.99%20Q%2015%2031.99%2023.7%2031.99%20L%2028.05%2031.99%20Q%2032.41%2031.99%2032.41%2021.99%20L%2032.41%2017%20Q%2032.41%2012%2041.09%2016.95%20L%2076.31%2037.05%20Q%2085%2042%2076.31%2046.95%20L%2041.09%2067.05%20Q%2032.41%2072%2032.41%2062.01%20L%2032.41%2057.01%20Q%2032.41%2052.01%2023.7%2052.01%20L%2019.35%2052.01%20Q%2015%2052.01%2015%2047.01%20Z'%20fill='%23ffffff'%20stroke='none'%20style='fill:%20%23ffffff;'/%3e%3c/g%3e%3c/svg%3e");
29
- background-size: 100% 100%;
30
- background-repeat: no-repeat;
31
-
32
- transform-origin: center;
33
- transform: rotate(-90deg) scale(0.8);
34
- margin-left: -10px;
35
- margin-top: -18px;
36
- }
37
-
38
- .webmcp-page-agent-cursorRipple {
39
- position: absolute;
40
- width: 100%;
41
- height: 100%;
42
- pointer-events: none;
43
- margin-left: -50%;
44
- margin-top: -50%;
45
-
46
- &::after {
47
- content: '';
48
- opacity: 0;
49
- position: absolute;
50
- inset: 0;
51
- border: 4px solid rgba(57, 182, 255, 1);
52
- border-radius: 50%;
53
- }
54
- }
55
-
56
- .webmcp-page-agent-cursor.clicking .webmcp-page-agent-cursorRipple::after {
57
- animation: webmcp-page-agent-cursor-ripple 300ms ease-out forwards;
58
- }
59
-
60
- @keyframes webmcp-page-agent-cursor-ripple {
61
- 0% {
62
- transform: scale(0);
63
- opacity: 1;
64
- }
65
-
66
- 100% {
67
- transform: scale(2);
68
- opacity: 0;
69
- }
70
- }
@@ -1,25 +0,0 @@
1
- <svg viewBox="0 0 79.0834 79.4553" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="79.083374" height="79.455322" fill="none" customFrame="#000000">
2
- --
3
- <defs>
4
- <g id="pixso_custom_effect_0">
5
- <effect x="6.000000" y="6.000000" visibility="visible" fill="rgb(0,0,0)" fill-opacity="0.180000007" effectType="dropShadow" stdDeviation="20" radius="0" />
6
- </g>
7
- <filter id="filter_0" width="79.083374" height="79.455322" x="0.000000" y="0.000000" filterUnits="userSpaceOnUse" customEffect="url(#pixso_custom_effect_0)" color-interpolation-filters="sRGB">
8
- <feFlood flood-opacity="0" result="BackgroundImageFix" />
9
- <feOffset dx="6.000000" dy="6.000000" in="SourceAlpha" />
10
- <feGaussianBlur stdDeviation="6.66666651" />
11
- <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.18 0 " />
12
- <feBlend result="effect_dropShadow_1" in2="BackgroundImageFix" mode="normal" />
13
- <feBlend result="shape" in="SourceGraphic" in2="effect_dropShadow_1" mode="normal" />
14
- </filter>
15
- <linearGradient id="paint_linear_0" x1="18.4743214" x2="18.4213886" y1="-1.86264515e-09" y2="34.9221306" gradientUnits="userSpaceOnUse">
16
- <stop stop-color="rgb(255,181,96)" offset="0" stop-opacity="1" />
17
- <stop stop-color="rgb(255,120,114)" offset="0.5" stop-opacity="1" />
18
- <stop stop-color="rgb(241,109,237)" offset="1" stop-opacity="1" />
19
- </linearGradient>
20
- </defs>
21
- <g filter="url(#filter_0)">
22
- <path id="多边形 11" d="M20.2632 3.57771L34.6257 32.3027C35.4444 33.9402 33.8152 35.7258 32.1097 35.0603L19.2014 30.0229C18.7339 29.8404 18.2148 29.8404 17.7472 30.0229L4.83891 35.0603C3.13343 35.7258 1.50423 33.9402 2.32297 32.3027L16.6855 3.57771C17.4225 2.10361 19.5261 2.10361 20.2632 3.57771Z" fill="url(#paint_linear_0)" fill-rule="evenodd" transform="matrix(0.719908,-0.69407,0.69407,0.719908,2.00256,28.0095)" />
23
- <path id="多边形 11" d="M37.2169 32.6848C37.1578 32.189 37.0096 31.7039 36.7723 31.2294L22.4098 2.5044C22.1973 2.07946 21.9328 1.70554 21.6163 1.38261C21.3524 1.11342 21.0524 0.879671 20.7162 0.681366C20.3925 0.490407 20.0558 0.34434 19.7061 0.243163C19.312 0.129145 18.9014 0.0721366 18.4743 0.0721366C18.0472 0.0721366 17.6367 0.129145 17.2426 0.243163C16.8929 0.34434 16.5562 0.490407 16.2324 0.681366C15.8962 0.879671 15.5962 1.11342 15.3323 1.38261C15.0158 1.70553 14.7513 2.07946 14.5388 2.5044L0.176342 31.2294C-0.0609121 31.7039 -0.209128 32.189 -0.268305 32.6848C-0.316251 33.0865 -0.305747 33.4951 -0.236792 33.9108C-0.171059 34.307 -0.0570567 34.6809 0.105216 35.0326C0.292784 35.4391 0.544845 35.8158 0.861397 36.1627C1.17794 36.5097 1.53001 36.7951 1.91761 37.0191C2.25297 37.2128 2.61492 37.3606 3.00348 37.4623C3.41106 37.5689 3.81704 37.6168 4.22142 37.6058C4.72053 37.5922 5.21719 37.4889 5.71141 37.2961L18.4743 32.3154L31.2372 37.2961C31.7315 37.4889 32.2281 37.5922 32.7272 37.6058C33.1316 37.6168 33.5376 37.5689 33.9452 37.4623C34.3337 37.3606 34.6957 37.2128 35.0311 37.0191C35.4187 36.7951 35.7707 36.5097 36.0873 36.1627C36.4038 35.8158 36.6558 35.4391 36.8434 35.0327C37.0057 34.681 37.1197 34.307 37.1854 33.9108C37.2544 33.4951 37.2649 33.0865 37.2169 32.6848ZM34.6257 32.3027L20.2632 3.57771C19.5261 2.10361 17.4225 2.10361 16.6855 3.57771L2.32297 32.3027C1.50423 33.9402 3.13343 35.7258 4.83891 35.0603L17.7472 30.0229C18.2148 29.8404 18.7339 29.8404 19.2014 30.0229L32.1097 35.0603C33.8152 35.7258 35.4444 33.9402 34.6257 32.3027Z" fill="rgb(255,255,255)" fill-rule="evenodd" transform="matrix(0.719908,-0.69407,0.69407,0.719908,2.00256,28.0095)" />
24
- </g>
25
- </svg>