@jami-studio/pinpoint 0.1.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.
Files changed (47) hide show
  1. package/.agents/skills/pinpoint/SKILL.md +77 -0
  2. package/README.md +412 -0
  3. package/dist/agent-context-HBCZ4MBN.js +13 -0
  4. package/dist/agent-context-HBCZ4MBN.js.map +1 -0
  5. package/dist/chunk-B7TY4FPP.js +569 -0
  6. package/dist/chunk-B7TY4FPP.js.map +1 -0
  7. package/dist/chunk-CGJZ7BOM.js +88 -0
  8. package/dist/chunk-CGJZ7BOM.js.map +1 -0
  9. package/dist/chunk-DGUM43GV.js +11 -0
  10. package/dist/chunk-DGUM43GV.js.map +1 -0
  11. package/dist/chunk-HAEYE6KB.js +25 -0
  12. package/dist/chunk-HAEYE6KB.js.map +1 -0
  13. package/dist/chunk-J5PXKVTM.js +53 -0
  14. package/dist/chunk-J5PXKVTM.js.map +1 -0
  15. package/dist/chunk-XBX2J7WU.js +94 -0
  16. package/dist/chunk-XBX2J7WU.js.map +1 -0
  17. package/dist/chunk-ZW7IO3EW.js +4927 -0
  18. package/dist/chunk-ZW7IO3EW.js.map +1 -0
  19. package/dist/cli.js +71 -0
  20. package/dist/cli.js.map +1 -0
  21. package/dist/formatter-CR4COA5Z.js +8 -0
  22. package/dist/formatter-CR4COA5Z.js.map +1 -0
  23. package/dist/index-NvFcZ4SO.d.ts +200 -0
  24. package/dist/index.browser.d.ts +377 -0
  25. package/dist/index.browser.js +620 -0
  26. package/dist/index.browser.js.map +1 -0
  27. package/dist/index.js +936 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/open-file-WR2JHI4P.js +8 -0
  30. package/dist/open-file-WR2JHI4P.js.map +1 -0
  31. package/dist/primitives/index.js +28 -0
  32. package/dist/primitives/index.js.map +1 -0
  33. package/dist/react.d.ts +23 -0
  34. package/dist/react.js +20 -0
  35. package/dist/react.js.map +1 -0
  36. package/dist/server/index.js +457 -0
  37. package/dist/server/index.js.map +1 -0
  38. package/dist/types/index.js +1 -0
  39. package/dist/types/index.js.map +1 -0
  40. package/package.json +88 -0
  41. package/src/scripts/create-pin.ts +43 -0
  42. package/src/scripts/delete-pin.ts +16 -0
  43. package/src/scripts/get-pins.ts +36 -0
  44. package/src/scripts/list-sessions.ts +33 -0
  45. package/src/scripts/resolve-pin.ts +27 -0
  46. package/src/scripts/run.ts +8 -0
  47. package/src/scripts/update-pin.ts +32 -0
@@ -0,0 +1,620 @@
1
+ "use client";
2
+ import {
3
+ DragSelect,
4
+ ElementInfoSchema,
5
+ ElementPicker,
6
+ FrameworkInfoSchema,
7
+ MemoryStore,
8
+ PinMarkerManager,
9
+ PinSchema,
10
+ RestClient,
11
+ TextSelect,
12
+ buildElementContext,
13
+ buildSelector,
14
+ detectFramework,
15
+ extractElementInfo,
16
+ getComponentInfo,
17
+ getSourceLocation,
18
+ mountPinpoint,
19
+ registerAdapter,
20
+ unmountPinpoint
21
+ } from "./chunk-ZW7IO3EW.js";
22
+ import {
23
+ formatPinsForAgent,
24
+ formatQueueForAgent,
25
+ formatRichPinContext
26
+ } from "./chunk-CGJZ7BOM.js";
27
+ import {
28
+ formatPins
29
+ } from "./chunk-XBX2J7WU.js";
30
+ import {
31
+ openFile
32
+ } from "./chunk-HAEYE6KB.js";
33
+
34
+ // src/frameworks/react-adapter.ts
35
+ var bippy = null;
36
+ var elementSource = null;
37
+ async function loadBippy() {
38
+ if (!bippy) {
39
+ try {
40
+ bippy = await import("bippy");
41
+ } catch {
42
+ bippy = null;
43
+ }
44
+ }
45
+ return bippy;
46
+ }
47
+ async function loadElementSource() {
48
+ if (!elementSource) {
49
+ try {
50
+ elementSource = await import("element-source");
51
+ } catch {
52
+ elementSource = null;
53
+ }
54
+ }
55
+ return elementSource;
56
+ }
57
+ var FRAMEWORK_INTERNALS = /* @__PURE__ */ new Set([
58
+ "Fragment",
59
+ "Suspense",
60
+ "StrictMode",
61
+ "Profiler",
62
+ "Provider",
63
+ "Consumer",
64
+ "ForwardRef",
65
+ "Memo",
66
+ // Next.js internals
67
+ "InnerLayoutRouter",
68
+ "OuterLayoutRouter",
69
+ "RenderFromTemplateContext",
70
+ "ScrollAndFocusHandler",
71
+ "RedirectBoundary",
72
+ "NotFoundBoundary",
73
+ "LoadingBoundary",
74
+ "ErrorBoundary",
75
+ "HotReload",
76
+ "Router",
77
+ "ServerRoot",
78
+ "AppRouter",
79
+ "ServerInsertedHTMLProvider",
80
+ // React Router internals
81
+ "Routes",
82
+ "RenderedRoute",
83
+ "Navigate",
84
+ "Outlet"
85
+ ]);
86
+ function getRDTHook() {
87
+ return typeof window !== "undefined" ? window.__REACT_DEVTOOLS_GLOBAL_HOOK__ : null;
88
+ }
89
+ var reactAdapter = {
90
+ name: "react",
91
+ detect() {
92
+ return !!getRDTHook();
93
+ },
94
+ getComponentInfo(element) {
95
+ const b = bippy;
96
+ if (!b) return null;
97
+ try {
98
+ const fiber = b.getFiberFromHostInstance(element);
99
+ if (!fiber) return null;
100
+ const components = [];
101
+ let current = fiber;
102
+ while (current) {
103
+ const name = b.getDisplayName(current);
104
+ if (name && !FRAMEWORK_INTERNALS.has(name)) {
105
+ components.unshift(name);
106
+ }
107
+ current = current.return ?? null;
108
+ if (components.length > 20) break;
109
+ }
110
+ let componentFiber = fiber;
111
+ while (componentFiber && typeof componentFiber.type === "string") {
112
+ componentFiber = componentFiber.return ?? null;
113
+ }
114
+ const displayName = componentFiber ? b.getDisplayName(componentFiber) : null;
115
+ const sourceInfo = getSourceFromFiber(componentFiber);
116
+ return {
117
+ name: displayName || components[components.length - 1] || "Unknown",
118
+ displayName: displayName || void 0,
119
+ filePath: sourceInfo?.file,
120
+ lineNumber: sourceInfo?.line
121
+ };
122
+ } catch {
123
+ return null;
124
+ }
125
+ },
126
+ getSourceLocation(element) {
127
+ const b = bippy;
128
+ if (!b) return null;
129
+ try {
130
+ const fiber = b.getFiberFromHostInstance(element);
131
+ if (!fiber) return null;
132
+ let componentFiber = fiber;
133
+ while (componentFiber && typeof componentFiber.type === "string") {
134
+ componentFiber = componentFiber.return ?? null;
135
+ }
136
+ return getSourceFromFiber(componentFiber);
137
+ } catch {
138
+ return null;
139
+ }
140
+ },
141
+ freeze() {
142
+ },
143
+ unfreeze() {
144
+ }
145
+ };
146
+ function getSourceFromFiber(fiber) {
147
+ if (!fiber) return null;
148
+ if (fiber._debugSource) {
149
+ return {
150
+ file: fiber._debugSource.fileName,
151
+ line: fiber._debugSource.lineNumber,
152
+ column: fiber._debugSource.columnNumber
153
+ };
154
+ }
155
+ return null;
156
+ }
157
+ if (typeof window !== "undefined") {
158
+ const init = () => {
159
+ loadBippy();
160
+ loadElementSource();
161
+ };
162
+ if (typeof requestIdleCallback !== "undefined") {
163
+ requestIdleCallback(init);
164
+ } else {
165
+ setTimeout(init, 100);
166
+ }
167
+ }
168
+
169
+ // src/frameworks/vue-adapter.ts
170
+ var vueAdapter = {
171
+ name: "vue",
172
+ detect() {
173
+ if (typeof window === "undefined") return false;
174
+ if (window.__VUE__) return true;
175
+ if (document.querySelector("[data-v-]")) return true;
176
+ return !!document.querySelector("[__vue_app__]");
177
+ },
178
+ getComponentInfo(element) {
179
+ const instance = getVueInstance(element);
180
+ if (!instance) return null;
181
+ const name = getComponentName(instance);
182
+ return {
183
+ name: name || "Unknown",
184
+ displayName: name || void 0,
185
+ filePath: instance.$options?.__file || instance.type?.__file,
186
+ lineNumber: void 0
187
+ // Vue doesn't expose line numbers like React
188
+ };
189
+ },
190
+ getSourceLocation(element) {
191
+ const instance = getVueInstance(element);
192
+ if (!instance) return null;
193
+ const file = instance.$options?.__file || instance.type?.__file || instance.type?.__name;
194
+ if (!file) return null;
195
+ return { file };
196
+ }
197
+ };
198
+ function getVueInstance(element) {
199
+ const el = element;
200
+ if (el.__vueParentComponent) {
201
+ return el.__vueParentComponent;
202
+ }
203
+ let current = element;
204
+ while (current) {
205
+ if (current.__vueParentComponent) {
206
+ return current.__vueParentComponent;
207
+ }
208
+ if (current.__vue__) {
209
+ return current.__vue__;
210
+ }
211
+ current = current.parentElement;
212
+ }
213
+ return null;
214
+ }
215
+ function getComponentName(instance) {
216
+ if (!instance) return null;
217
+ if (instance.type?.name) return instance.type.name;
218
+ if (instance.type?.__name) return instance.type.__name;
219
+ if (instance.$options?.name) return instance.$options.name;
220
+ const file = instance.type?.__file || instance.$options?.__file;
221
+ if (file) {
222
+ const match = file.match(/([^/\\]+)\.\w+$/);
223
+ if (match) return match[1];
224
+ }
225
+ return null;
226
+ }
227
+
228
+ // src/frameworks/generic-adapter.ts
229
+ var genericAdapter = {
230
+ name: "generic",
231
+ detect() {
232
+ return true;
233
+ },
234
+ getComponentInfo(_element) {
235
+ return null;
236
+ },
237
+ getSourceLocation(_element) {
238
+ return null;
239
+ }
240
+ };
241
+
242
+ // src/plugins/registry.ts
243
+ var plugins = /* @__PURE__ */ new Map();
244
+ var hookHandlers = /* @__PURE__ */ new Map();
245
+ function registerPlugin(plugin, api) {
246
+ if (plugins.has(plugin.name)) {
247
+ unregisterPlugin(plugin.name);
248
+ }
249
+ plugins.set(plugin.name, plugin);
250
+ if (plugin.hooks) {
251
+ for (const [hookName, handler] of Object.entries(plugin.hooks)) {
252
+ if (typeof handler === "function") {
253
+ const key = hookName;
254
+ if (!hookHandlers.has(key)) {
255
+ hookHandlers.set(key, /* @__PURE__ */ new Set());
256
+ }
257
+ hookHandlers.get(key).add(handler);
258
+ }
259
+ }
260
+ }
261
+ if (plugin.setup && api) {
262
+ const registry = {
263
+ register(hookName, handler) {
264
+ if (!hookHandlers.has(hookName)) {
265
+ hookHandlers.set(hookName, /* @__PURE__ */ new Set());
266
+ }
267
+ hookHandlers.get(hookName).add(handler);
268
+ },
269
+ unregister(hookName, handler) {
270
+ hookHandlers.get(hookName)?.delete(handler);
271
+ }
272
+ };
273
+ plugin.setup(api, registry);
274
+ }
275
+ }
276
+ function unregisterPlugin(name) {
277
+ const plugin = plugins.get(name);
278
+ if (!plugin) return;
279
+ if (plugin.hooks) {
280
+ for (const [hookName, handler] of Object.entries(plugin.hooks)) {
281
+ if (typeof handler === "function") {
282
+ hookHandlers.get(hookName)?.delete(handler);
283
+ }
284
+ }
285
+ }
286
+ plugins.delete(name);
287
+ }
288
+ function getPlugins() {
289
+ return Array.from(plugins.keys());
290
+ }
291
+ function dispatchHook(name, ...args) {
292
+ const handlers = hookHandlers.get(name);
293
+ if (!handlers) return;
294
+ for (const handler of handlers) {
295
+ try {
296
+ handler(...args);
297
+ } catch (err) {
298
+ console.warn(`[pinpoint] Plugin hook ${name} error:`, err);
299
+ }
300
+ }
301
+ }
302
+
303
+ // src/plugins/agent-native-plugin.ts
304
+ var agentNativePlugin = {
305
+ name: "agent-native"
306
+ };
307
+
308
+ // src/freeze/css-freeze.ts
309
+ var FREEZE_STYLE_ID = "__pinpoint-css-freeze";
310
+ function freezeCSS() {
311
+ if (document.getElementById(FREEZE_STYLE_ID)) {
312
+ return () => {
313
+ };
314
+ }
315
+ const style = document.createElement("style");
316
+ style.id = FREEZE_STYLE_ID;
317
+ style.textContent = `*, *::before, *::after {
318
+ animation-play-state: paused !important;
319
+ transition-property: none !important;
320
+ }`;
321
+ document.head.appendChild(style);
322
+ return () => {
323
+ style.remove();
324
+ };
325
+ }
326
+
327
+ // src/freeze/js-freeze.ts
328
+ var PINPOINT_SYMBOL = /* @__PURE__ */ Symbol.for("pinpoint-internal");
329
+ var MAX_QUEUE = 1e3;
330
+ var frozen = false;
331
+ var queue = [];
332
+ var originals = null;
333
+ function freezeJSTimers() {
334
+ if (frozen) return () => {
335
+ };
336
+ frozen = true;
337
+ queue = [];
338
+ originals = {
339
+ setTimeout: window.setTimeout.bind(window),
340
+ setInterval: window.setInterval.bind(window),
341
+ clearTimeout: window.clearTimeout.bind(window),
342
+ clearInterval: window.clearInterval.bind(window),
343
+ requestAnimationFrame: window.requestAnimationFrame.bind(window)
344
+ };
345
+ window.setTimeout = (callback, delay, ...args) => {
346
+ if (typeof callback !== "function") return 0;
347
+ if (callback[PINPOINT_SYMBOL]) {
348
+ return originals.setTimeout(callback, delay, ...args);
349
+ }
350
+ if (queue.length < MAX_QUEUE) {
351
+ queue.push({ type: "timeout", callback, delay, args });
352
+ }
353
+ return 0;
354
+ };
355
+ window.setInterval = (callback, delay, ...args) => {
356
+ if (typeof callback !== "function") return 0;
357
+ if (callback[PINPOINT_SYMBOL]) {
358
+ return originals.setInterval(callback, delay, ...args);
359
+ }
360
+ if (queue.length < MAX_QUEUE) {
361
+ queue.push({ type: "interval", callback, delay, args });
362
+ }
363
+ return 0;
364
+ };
365
+ window.requestAnimationFrame = (callback) => {
366
+ if (callback[PINPOINT_SYMBOL]) {
367
+ return originals.requestAnimationFrame(callback);
368
+ }
369
+ if (queue.length < MAX_QUEUE) {
370
+ queue.push({ type: "raf", callback });
371
+ }
372
+ return 0;
373
+ };
374
+ return () => {
375
+ if (!frozen || !originals) return;
376
+ frozen = false;
377
+ window.setTimeout = originals.setTimeout;
378
+ window.setInterval = originals.setInterval;
379
+ window.clearTimeout = originals.clearTimeout;
380
+ window.clearInterval = originals.clearInterval;
381
+ window.requestAnimationFrame = originals.requestAnimationFrame;
382
+ const replayBatch = () => {
383
+ const batch = queue.splice(0, 50);
384
+ for (const item of batch) {
385
+ try {
386
+ if (item.type === "raf") {
387
+ originals.requestAnimationFrame(
388
+ item.callback
389
+ );
390
+ } else {
391
+ originals.setTimeout(
392
+ item.callback,
393
+ 0,
394
+ ...item.args || []
395
+ );
396
+ }
397
+ } catch {
398
+ }
399
+ }
400
+ if (queue.length > 0) {
401
+ (window.requestIdleCallback || originals.setTimeout)(replayBatch);
402
+ }
403
+ };
404
+ if (queue.length > 0) {
405
+ (window.requestIdleCallback || originals.setTimeout)(replayBatch);
406
+ }
407
+ originals = null;
408
+ };
409
+ }
410
+
411
+ // src/freeze/media-freeze.ts
412
+ function freezeMedia() {
413
+ const mediaElements = document.querySelectorAll("video, audio");
414
+ const playing = [];
415
+ mediaElements.forEach((el) => {
416
+ const media = el;
417
+ if (!media.paused) {
418
+ media.pause();
419
+ playing.push(media);
420
+ }
421
+ });
422
+ const svgElements = document.querySelectorAll("svg");
423
+ const pausedSVGs = [];
424
+ svgElements.forEach((svg) => {
425
+ if (typeof svg.pauseAnimations === "function") {
426
+ try {
427
+ svg.pauseAnimations();
428
+ pausedSVGs.push(svg);
429
+ } catch {
430
+ }
431
+ }
432
+ });
433
+ return () => {
434
+ playing.forEach((media) => {
435
+ try {
436
+ media.play();
437
+ } catch {
438
+ }
439
+ });
440
+ pausedSVGs.forEach((svg) => {
441
+ try {
442
+ svg.unpauseAnimations();
443
+ } catch {
444
+ }
445
+ });
446
+ };
447
+ }
448
+
449
+ // src/freeze/react-freeze.ts
450
+ var frozen2 = false;
451
+ var originalDispatcher = null;
452
+ var queuedUpdates = [];
453
+ function getInternals() {
454
+ const hook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
455
+ if (!hook) return null;
456
+ const renderers = hook.renderers;
457
+ if (!renderers || renderers.size === 0) return null;
458
+ const renderer = renderers.values().next().value;
459
+ return renderer?.currentDispatcherRef || null;
460
+ }
461
+ function freezeReact() {
462
+ if (frozen2) return () => {
463
+ };
464
+ const internals = getInternals();
465
+ if (!internals) return () => {
466
+ };
467
+ frozen2 = true;
468
+ originalDispatcher = internals.current;
469
+ queuedUpdates = [];
470
+ const proxyDispatcher = new Proxy(originalDispatcher, {
471
+ get(target, prop) {
472
+ if (prop === "useState" || prop === "useReducer") {
473
+ return (...args) => {
474
+ const result = target[prop](...args);
475
+ if (Array.isArray(result) && typeof result[1] === "function") {
476
+ const originalSetter = result[1];
477
+ result[1] = (action) => {
478
+ queuedUpdates.push({
479
+ fiber: null,
480
+ queue: null,
481
+ update: { setter: originalSetter, action }
482
+ });
483
+ };
484
+ }
485
+ return result;
486
+ };
487
+ }
488
+ return target[prop];
489
+ }
490
+ });
491
+ internals.current = proxyDispatcher;
492
+ return () => {
493
+ if (!frozen2) return;
494
+ frozen2 = false;
495
+ if (internals && originalDispatcher) {
496
+ internals.current = originalDispatcher;
497
+ }
498
+ for (const { update } of queuedUpdates) {
499
+ try {
500
+ update.setter(update.action);
501
+ } catch {
502
+ }
503
+ }
504
+ queuedUpdates = [];
505
+ originalDispatcher = null;
506
+ };
507
+ }
508
+
509
+ // src/freeze/waapi-freeze.ts
510
+ function freezeWAAPI() {
511
+ const animations = document.getAnimations();
512
+ const playing = animations.filter((a) => a.playState === "running");
513
+ playing.forEach((a) => a.pause());
514
+ return () => {
515
+ playing.forEach((a) => {
516
+ try {
517
+ a.play();
518
+ } catch {
519
+ }
520
+ });
521
+ };
522
+ }
523
+
524
+ // src/freeze/controller.ts
525
+ var cleanups = [];
526
+ var active = false;
527
+ function freeze(_elements, options = {}) {
528
+ if (active) return;
529
+ active = true;
530
+ cleanups = [freezeCSS(), freezeWAAPI(), freezeReact(), freezeMedia()];
531
+ if (options.jsTimers) {
532
+ cleanups.push(freezeJSTimers());
533
+ }
534
+ }
535
+ function unfreeze() {
536
+ if (!active) return;
537
+ active = false;
538
+ for (const cleanup of cleanups) {
539
+ try {
540
+ cleanup();
541
+ } catch {
542
+ }
543
+ }
544
+ cleanups = [];
545
+ }
546
+ function isFreezeActive() {
547
+ return active;
548
+ }
549
+
550
+ // src/security/input-sanitization.ts
551
+ var HTML_ENTITIES = {
552
+ "&": "&amp;",
553
+ "<": "&lt;",
554
+ ">": "&gt;",
555
+ '"': "&quot;",
556
+ "'": "&#39;"
557
+ };
558
+ function escapeHtml(str) {
559
+ return str.replace(/[&<>"']/g, (char) => HTML_ENTITIES[char] || char);
560
+ }
561
+ function sanitizeString(str, maxLength = 1e3) {
562
+ const cleaned = str.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, "");
563
+ return cleaned.slice(0, maxLength);
564
+ }
565
+
566
+ // src/security/origin-validation.ts
567
+ function isAllowedOrigin(origin, allowedOrigins) {
568
+ if (origin === window.location.origin) return true;
569
+ if (origin.startsWith("http://localhost") || origin.startsWith("http://127.0.0.1") || origin.startsWith("https://localhost")) {
570
+ return true;
571
+ }
572
+ if (allowedOrigins && allowedOrigins.length > 0) {
573
+ return allowedOrigins.includes(origin);
574
+ }
575
+ return false;
576
+ }
577
+
578
+ // src/index.browser.ts
579
+ registerAdapter(reactAdapter);
580
+ registerAdapter(vueAdapter);
581
+ export {
582
+ DragSelect,
583
+ ElementInfoSchema,
584
+ ElementPicker,
585
+ FrameworkInfoSchema,
586
+ MemoryStore,
587
+ PinMarkerManager,
588
+ PinSchema,
589
+ RestClient,
590
+ TextSelect,
591
+ agentNativePlugin,
592
+ buildElementContext,
593
+ buildSelector,
594
+ detectFramework,
595
+ dispatchHook,
596
+ escapeHtml,
597
+ extractElementInfo,
598
+ formatPins,
599
+ formatPinsForAgent,
600
+ formatQueueForAgent,
601
+ formatRichPinContext,
602
+ freeze,
603
+ genericAdapter,
604
+ getComponentInfo,
605
+ getPlugins,
606
+ getSourceLocation,
607
+ isAllowedOrigin,
608
+ isFreezeActive,
609
+ mountPinpoint,
610
+ openFile,
611
+ reactAdapter,
612
+ registerAdapter,
613
+ registerPlugin,
614
+ sanitizeString,
615
+ unfreeze,
616
+ unmountPinpoint,
617
+ unregisterPlugin,
618
+ vueAdapter
619
+ };
620
+ //# sourceMappingURL=index.browser.js.map