hypha-debugger 0.1.4 → 0.1.6
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/debugger.d.ts +13 -0
- package/dist/hypha-debugger.js +347 -16
- package/dist/hypha-debugger.js.map +1 -1
- package/dist/hypha-debugger.min.js +4 -4
- package/dist/hypha-debugger.min.js.map +1 -1
- package/dist/hypha-debugger.mjs +346 -17
- package/dist/hypha-debugger.mjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/services/navigate.d.ts +25 -1
- package/package.json +1 -1
package/dist/hypha-debugger.mjs
CHANGED
|
@@ -2127,20 +2127,248 @@ executeScript.__schema__ = {
|
|
|
2127
2127
|
};
|
|
2128
2128
|
|
|
2129
2129
|
/**
|
|
2130
|
-
* Navigation service.
|
|
2130
|
+
* Navigation service with auto-reconnect support.
|
|
2131
|
+
*
|
|
2132
|
+
* For agent-triggered reload() and same-origin navigate(), we use a "soft"
|
|
2133
|
+
* approach: fetch the target HTML, inject the debugger <script> tag, then
|
|
2134
|
+
* replace the document via document.write(). The injected script auto-starts
|
|
2135
|
+
* from sessionStorage config, so the debugger reconnects with the same
|
|
2136
|
+
* workspace and service ID. The agent's URL stays stable.
|
|
2137
|
+
*
|
|
2138
|
+
* For cross-origin navigate(), goBack(), and goForward(), we fall back to
|
|
2139
|
+
* normal navigation. The debugger config is saved to sessionStorage so
|
|
2140
|
+
* re-clicking the bookmarklet reconnects seamlessly.
|
|
2141
|
+
*/
|
|
2142
|
+
const STORAGE_KEY$1 = "__hypha_debugger_config__";
|
|
2143
|
+
/** Read the saved script URL from sessionStorage, or fall back to CDN. */
|
|
2144
|
+
function getScriptUrl() {
|
|
2145
|
+
try {
|
|
2146
|
+
const raw = sessionStorage.getItem(STORAGE_KEY$1);
|
|
2147
|
+
if (raw) {
|
|
2148
|
+
const config = JSON.parse(raw);
|
|
2149
|
+
if (config.script_url)
|
|
2150
|
+
return config.script_url;
|
|
2151
|
+
}
|
|
2152
|
+
}
|
|
2153
|
+
catch {
|
|
2154
|
+
// ignore
|
|
2155
|
+
}
|
|
2156
|
+
return "https://cdn.jsdelivr.net/npm/hypha-debugger/dist/hypha-debugger.min.js";
|
|
2157
|
+
}
|
|
2158
|
+
/**
|
|
2159
|
+
* Inject the debugger loader script into HTML before </body> (or append).
|
|
2160
|
+
*/
|
|
2161
|
+
function injectLoader(html, scriptUrl) {
|
|
2162
|
+
const loader = `<script src="${scriptUrl}"><\/script>`;
|
|
2163
|
+
if (html.includes("</body>")) {
|
|
2164
|
+
return html.replace("</body>", loader + "\n</body>");
|
|
2165
|
+
}
|
|
2166
|
+
if (html.includes("</html>")) {
|
|
2167
|
+
return html.replace("</html>", loader + "\n</html>");
|
|
2168
|
+
}
|
|
2169
|
+
return html + "\n" + loader;
|
|
2170
|
+
}
|
|
2171
|
+
/**
|
|
2172
|
+
* Perform a soft page replacement: fetch HTML, inject debugger script,
|
|
2173
|
+
* replace the document via document.write(). If the fetch or write fails,
|
|
2174
|
+
* falls back to hard navigation.
|
|
2175
|
+
*/
|
|
2176
|
+
function softReplace(url, pushState) {
|
|
2177
|
+
const scriptUrl = getScriptUrl();
|
|
2178
|
+
fetch(url, { credentials: "same-origin", cache: "reload" })
|
|
2179
|
+
.then((response) => {
|
|
2180
|
+
if (!response.ok)
|
|
2181
|
+
throw new Error(`HTTP ${response.status}`);
|
|
2182
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
2183
|
+
if (!contentType.includes("text/html")) {
|
|
2184
|
+
throw new Error("Not HTML");
|
|
2185
|
+
}
|
|
2186
|
+
return response.text();
|
|
2187
|
+
})
|
|
2188
|
+
.then((html) => {
|
|
2189
|
+
const modified = injectLoader(html, scriptUrl);
|
|
2190
|
+
document.open();
|
|
2191
|
+
document.write(modified);
|
|
2192
|
+
document.close();
|
|
2193
|
+
if (pushState) {
|
|
2194
|
+
try {
|
|
2195
|
+
history.pushState({}, "", pushState);
|
|
2196
|
+
}
|
|
2197
|
+
catch {
|
|
2198
|
+
// ignore — URL might already match
|
|
2199
|
+
}
|
|
2200
|
+
}
|
|
2201
|
+
})
|
|
2202
|
+
.catch(() => {
|
|
2203
|
+
// Soft replace failed — fall back to hard navigation
|
|
2204
|
+
if (pushState) {
|
|
2205
|
+
window.location.href = pushState;
|
|
2206
|
+
}
|
|
2207
|
+
else {
|
|
2208
|
+
window.location.reload();
|
|
2209
|
+
}
|
|
2210
|
+
});
|
|
2211
|
+
}
|
|
2212
|
+
/** Check if a URL is same-origin as the current page. */
|
|
2213
|
+
function isSameOrigin(url) {
|
|
2214
|
+
try {
|
|
2215
|
+
const target = new URL(url, location.href);
|
|
2216
|
+
return target.origin === location.origin;
|
|
2217
|
+
}
|
|
2218
|
+
catch {
|
|
2219
|
+
return false;
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
2222
|
+
// ── Global navigation interception ────────────────────────────────────
|
|
2223
|
+
let _interceptInstalled = false;
|
|
2224
|
+
/**
|
|
2225
|
+
* Install global listeners that intercept same-origin link clicks and
|
|
2226
|
+
* form submissions, routing them through soft navigation so the debugger
|
|
2227
|
+
* stays connected.
|
|
2228
|
+
*
|
|
2229
|
+
* Called once from HyphaDebugger.start().
|
|
2131
2230
|
*/
|
|
2231
|
+
function installNavigationInterceptor() {
|
|
2232
|
+
if (_interceptInstalled)
|
|
2233
|
+
return () => { };
|
|
2234
|
+
_interceptInstalled = true;
|
|
2235
|
+
/**
|
|
2236
|
+
* Click handler: intercept <a> clicks that would navigate to a
|
|
2237
|
+
* same-origin HTML page.
|
|
2238
|
+
*/
|
|
2239
|
+
const onClick = (e) => {
|
|
2240
|
+
// Skip if modifier keys (new tab, etc.) or not left-click
|
|
2241
|
+
if (e.defaultPrevented || e.button !== 0)
|
|
2242
|
+
return;
|
|
2243
|
+
if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey)
|
|
2244
|
+
return;
|
|
2245
|
+
// Walk up from target to find the nearest <a>
|
|
2246
|
+
let anchor = null;
|
|
2247
|
+
let el = e.target;
|
|
2248
|
+
while (el) {
|
|
2249
|
+
if (el.tagName === "A") {
|
|
2250
|
+
anchor = el;
|
|
2251
|
+
break;
|
|
2252
|
+
}
|
|
2253
|
+
el = el.parentElement;
|
|
2254
|
+
}
|
|
2255
|
+
if (!anchor)
|
|
2256
|
+
return;
|
|
2257
|
+
const href = anchor.href;
|
|
2258
|
+
if (!href)
|
|
2259
|
+
return;
|
|
2260
|
+
// Skip non-http(s), download links, target=_blank, javascript:, #hash-only
|
|
2261
|
+
if (anchor.target && anchor.target !== "_self")
|
|
2262
|
+
return;
|
|
2263
|
+
if (anchor.hasAttribute("download"))
|
|
2264
|
+
return;
|
|
2265
|
+
if (href.startsWith("javascript:") || href.startsWith("mailto:") || href.startsWith("tel:"))
|
|
2266
|
+
return;
|
|
2267
|
+
// Skip hash-only links (same page anchor)
|
|
2268
|
+
try {
|
|
2269
|
+
const target = new URL(href, location.href);
|
|
2270
|
+
if (target.origin === location.origin &&
|
|
2271
|
+
target.pathname === location.pathname &&
|
|
2272
|
+
target.search === location.search &&
|
|
2273
|
+
target.hash !== location.hash) {
|
|
2274
|
+
return; // Just a hash change, let browser handle it
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2277
|
+
catch {
|
|
2278
|
+
return;
|
|
2279
|
+
}
|
|
2280
|
+
// Skip cross-origin
|
|
2281
|
+
if (!isSameOrigin(href))
|
|
2282
|
+
return;
|
|
2283
|
+
// Intercept: prevent default navigation and do soft replace
|
|
2284
|
+
e.preventDefault();
|
|
2285
|
+
const targetUrl = new URL(href, location.href).href;
|
|
2286
|
+
softReplace(targetUrl, targetUrl);
|
|
2287
|
+
};
|
|
2288
|
+
/**
|
|
2289
|
+
* Submit handler: intercept form submissions to same-origin action URLs.
|
|
2290
|
+
* Only handles GET forms (POST forms need the request body which is harder
|
|
2291
|
+
* to replicate via fetch).
|
|
2292
|
+
*/
|
|
2293
|
+
const onSubmit = (e) => {
|
|
2294
|
+
if (e.defaultPrevented)
|
|
2295
|
+
return;
|
|
2296
|
+
const form = e.target;
|
|
2297
|
+
const method = (form.method || "GET").toUpperCase();
|
|
2298
|
+
// Only intercept GET forms — POST forms are too complex to replicate
|
|
2299
|
+
if (method !== "GET")
|
|
2300
|
+
return;
|
|
2301
|
+
const action = form.action || location.href;
|
|
2302
|
+
if (!isSameOrigin(action))
|
|
2303
|
+
return;
|
|
2304
|
+
// Build the URL with form data as query params
|
|
2305
|
+
const formData = new FormData(form);
|
|
2306
|
+
const url = new URL(action, location.href);
|
|
2307
|
+
for (const [key, value] of formData.entries()) {
|
|
2308
|
+
if (typeof value === "string") {
|
|
2309
|
+
url.searchParams.set(key, value);
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
// Skip if target is _blank or similar
|
|
2313
|
+
if (form.target && form.target !== "_self")
|
|
2314
|
+
return;
|
|
2315
|
+
e.preventDefault();
|
|
2316
|
+
softReplace(url.href, url.href);
|
|
2317
|
+
};
|
|
2318
|
+
/**
|
|
2319
|
+
* Popstate handler: intercept browser back/forward (bfcache miss).
|
|
2320
|
+
* When the browser navigates via back/forward and there's no bfcache,
|
|
2321
|
+
* we can catch it via popstate and do a soft load of the target URL.
|
|
2322
|
+
*/
|
|
2323
|
+
const onPopState = () => {
|
|
2324
|
+
// The URL has already changed when popstate fires.
|
|
2325
|
+
// Do a soft load of the current URL (which is the target of back/forward).
|
|
2326
|
+
softReplace(location.href);
|
|
2327
|
+
};
|
|
2328
|
+
document.addEventListener("click", onClick, true); // capture phase
|
|
2329
|
+
document.addEventListener("submit", onSubmit, true);
|
|
2330
|
+
window.addEventListener("popstate", onPopState);
|
|
2331
|
+
// Return cleanup function
|
|
2332
|
+
return () => {
|
|
2333
|
+
document.removeEventListener("click", onClick, true);
|
|
2334
|
+
document.removeEventListener("submit", onSubmit, true);
|
|
2335
|
+
window.removeEventListener("popstate", onPopState);
|
|
2336
|
+
_interceptInstalled = false;
|
|
2337
|
+
};
|
|
2338
|
+
}
|
|
2339
|
+
// ── navigate ──────────────────────────────────────────────────────────
|
|
2132
2340
|
function navigate(url) {
|
|
2133
2341
|
try {
|
|
2134
|
-
|
|
2135
|
-
|
|
2342
|
+
const targetUrl = new URL(url, location.href);
|
|
2343
|
+
const sameOrigin = targetUrl.origin === location.origin;
|
|
2344
|
+
if (sameOrigin) {
|
|
2345
|
+
// Soft navigate: fetch + inject + document.write, then pushState
|
|
2346
|
+
// Schedule after RPC response is sent
|
|
2347
|
+
setTimeout(() => softReplace(targetUrl.href, targetUrl.href), 150);
|
|
2348
|
+
return {
|
|
2349
|
+
success: true,
|
|
2350
|
+
message: `Navigating to ${url} (debugger will auto-reconnect)`,
|
|
2351
|
+
};
|
|
2352
|
+
}
|
|
2353
|
+
else {
|
|
2354
|
+
// Cross-origin: can't soft navigate, fall back to hard
|
|
2355
|
+
window.location.href = url;
|
|
2356
|
+
return {
|
|
2357
|
+
success: true,
|
|
2358
|
+
message: `Navigating to ${url} (cross-origin, debugger will disconnect)`,
|
|
2359
|
+
};
|
|
2360
|
+
}
|
|
2136
2361
|
}
|
|
2137
2362
|
catch (err) {
|
|
2138
|
-
return {
|
|
2363
|
+
return {
|
|
2364
|
+
success: false,
|
|
2365
|
+
message: `Navigation failed: ${err.message ?? err}`,
|
|
2366
|
+
};
|
|
2139
2367
|
}
|
|
2140
2368
|
}
|
|
2141
2369
|
navigate.__schema__ = {
|
|
2142
2370
|
name: "navigate",
|
|
2143
|
-
description: "Navigate the browser to a new URL.",
|
|
2371
|
+
description: "Navigate the browser to a new URL. For same-origin URLs, the debugger auto-reconnects. Cross-origin navigation will disconnect the debugger.",
|
|
2144
2372
|
parameters: {
|
|
2145
2373
|
type: "object",
|
|
2146
2374
|
properties: {
|
|
@@ -2152,18 +2380,25 @@ navigate.__schema__ = {
|
|
|
2152
2380
|
required: ["url"],
|
|
2153
2381
|
},
|
|
2154
2382
|
};
|
|
2383
|
+
// ── goBack / goForward ───────────────────────────────────────────────
|
|
2155
2384
|
function goBack() {
|
|
2156
2385
|
try {
|
|
2157
2386
|
window.history.back();
|
|
2158
|
-
return {
|
|
2387
|
+
return {
|
|
2388
|
+
success: true,
|
|
2389
|
+
message: "Navigated back (debugger will auto-reconnect via popstate)",
|
|
2390
|
+
};
|
|
2159
2391
|
}
|
|
2160
2392
|
catch (err) {
|
|
2161
|
-
return {
|
|
2393
|
+
return {
|
|
2394
|
+
success: false,
|
|
2395
|
+
message: `Back navigation failed: ${err.message ?? err}`,
|
|
2396
|
+
};
|
|
2162
2397
|
}
|
|
2163
2398
|
}
|
|
2164
2399
|
goBack.__schema__ = {
|
|
2165
2400
|
name: "goBack",
|
|
2166
|
-
description: "Navigate back in browser history.",
|
|
2401
|
+
description: "Navigate back in browser history. The debugger auto-reconnects for same-origin pages.",
|
|
2167
2402
|
parameters: {
|
|
2168
2403
|
type: "object",
|
|
2169
2404
|
properties: {},
|
|
@@ -2172,7 +2407,10 @@ goBack.__schema__ = {
|
|
|
2172
2407
|
function goForward() {
|
|
2173
2408
|
try {
|
|
2174
2409
|
window.history.forward();
|
|
2175
|
-
return {
|
|
2410
|
+
return {
|
|
2411
|
+
success: true,
|
|
2412
|
+
message: "Navigated forward (debugger will auto-reconnect via popstate)",
|
|
2413
|
+
};
|
|
2176
2414
|
}
|
|
2177
2415
|
catch (err) {
|
|
2178
2416
|
return {
|
|
@@ -2183,16 +2421,21 @@ function goForward() {
|
|
|
2183
2421
|
}
|
|
2184
2422
|
goForward.__schema__ = {
|
|
2185
2423
|
name: "goForward",
|
|
2186
|
-
description: "Navigate forward in browser history.",
|
|
2424
|
+
description: "Navigate forward in browser history. The debugger auto-reconnects for same-origin pages.",
|
|
2187
2425
|
parameters: {
|
|
2188
2426
|
type: "object",
|
|
2189
2427
|
properties: {},
|
|
2190
2428
|
},
|
|
2191
2429
|
};
|
|
2430
|
+
// ── reload ───────────────────────────────────────────────────────────
|
|
2192
2431
|
function reload() {
|
|
2193
2432
|
try {
|
|
2194
|
-
|
|
2195
|
-
|
|
2433
|
+
// Schedule soft reload after RPC response is sent
|
|
2434
|
+
setTimeout(() => softReplace(location.href), 150);
|
|
2435
|
+
return {
|
|
2436
|
+
success: true,
|
|
2437
|
+
message: "Reloading page (debugger will auto-reconnect)",
|
|
2438
|
+
};
|
|
2196
2439
|
}
|
|
2197
2440
|
catch (err) {
|
|
2198
2441
|
return { success: false, message: `Reload failed: ${err.message ?? err}` };
|
|
@@ -2200,7 +2443,7 @@ function reload() {
|
|
|
2200
2443
|
}
|
|
2201
2444
|
reload.__schema__ = {
|
|
2202
2445
|
name: "reload",
|
|
2203
|
-
description: "Reload the current page.",
|
|
2446
|
+
description: "Reload the current page. The debugger auto-reconnects after reload using soft page replacement.",
|
|
2204
2447
|
parameters: {
|
|
2205
2448
|
type: "object",
|
|
2206
2449
|
properties: {},
|
|
@@ -5311,12 +5554,16 @@ function randomHex(bytes = 8) {
|
|
|
5311
5554
|
crypto.getRandomValues(arr);
|
|
5312
5555
|
return Array.from(arr, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
5313
5556
|
}
|
|
5557
|
+
/** sessionStorage key for persisting debugger config across reloads. */
|
|
5558
|
+
const STORAGE_KEY = "__hypha_debugger_config__";
|
|
5314
5559
|
class HyphaDebugger {
|
|
5315
5560
|
constructor(config) {
|
|
5316
5561
|
this.overlay = null;
|
|
5317
5562
|
this.cursor = null;
|
|
5318
5563
|
this.server = null;
|
|
5319
5564
|
this.serviceInfo = null;
|
|
5565
|
+
this.boundBeforeUnload = null;
|
|
5566
|
+
this.cleanupInterceptor = null;
|
|
5320
5567
|
const requireToken = config.require_token ?? false;
|
|
5321
5568
|
// Always append random suffix unless user provided a custom id.
|
|
5322
5569
|
let serviceId = config.service_id ?? "web-debugger";
|
|
@@ -5376,6 +5623,13 @@ class HyphaDebugger {
|
|
|
5376
5623
|
// Store globally
|
|
5377
5624
|
w.__HYPHA_DEBUGGER__ = w.__HYPHA_DEBUGGER__ ?? {};
|
|
5378
5625
|
w.__HYPHA_DEBUGGER__.instance = this;
|
|
5626
|
+
// Persist config to sessionStorage for auto-reconnect after reload
|
|
5627
|
+
this.saveConfigToStorage();
|
|
5628
|
+
this.boundBeforeUnload = () => this.saveConfigToStorage();
|
|
5629
|
+
window.addEventListener("beforeunload", this.boundBeforeUnload);
|
|
5630
|
+
// Intercept same-origin link clicks, form submits, and popstate
|
|
5631
|
+
// so the debugger survives user-initiated navigation
|
|
5632
|
+
this.cleanupInterceptor = installNavigationInterceptor();
|
|
5379
5633
|
return session;
|
|
5380
5634
|
}
|
|
5381
5635
|
catch (err) {
|
|
@@ -5391,6 +5645,15 @@ class HyphaDebugger {
|
|
|
5391
5645
|
}
|
|
5392
5646
|
}
|
|
5393
5647
|
async destroy() {
|
|
5648
|
+
// Remove event listeners
|
|
5649
|
+
if (this.boundBeforeUnload) {
|
|
5650
|
+
window.removeEventListener("beforeunload", this.boundBeforeUnload);
|
|
5651
|
+
this.boundBeforeUnload = null;
|
|
5652
|
+
}
|
|
5653
|
+
if (this.cleanupInterceptor) {
|
|
5654
|
+
this.cleanupInterceptor();
|
|
5655
|
+
this.cleanupInterceptor = null;
|
|
5656
|
+
}
|
|
5394
5657
|
try {
|
|
5395
5658
|
if (this.serviceInfo && this.server) {
|
|
5396
5659
|
await this.server.unregisterService(this.serviceInfo.id);
|
|
@@ -5399,6 +5662,13 @@ class HyphaDebugger {
|
|
|
5399
5662
|
catch {
|
|
5400
5663
|
// Ignore unregister errors on cleanup
|
|
5401
5664
|
}
|
|
5665
|
+
// Clear sessionStorage config (explicit destroy = user wants to stop)
|
|
5666
|
+
try {
|
|
5667
|
+
sessionStorage.removeItem(STORAGE_KEY);
|
|
5668
|
+
}
|
|
5669
|
+
catch {
|
|
5670
|
+
// ignore
|
|
5671
|
+
}
|
|
5402
5672
|
disposeController();
|
|
5403
5673
|
this.cursor?.destroy();
|
|
5404
5674
|
this.cursor = null;
|
|
@@ -5410,6 +5680,48 @@ class HyphaDebugger {
|
|
|
5410
5680
|
delete w.__HYPHA_DEBUGGER__.session;
|
|
5411
5681
|
}
|
|
5412
5682
|
}
|
|
5683
|
+
/**
|
|
5684
|
+
* Persist debugger config to sessionStorage so the debugger can
|
|
5685
|
+
* auto-reconnect after a page reload (soft reload injects the script,
|
|
5686
|
+
* autoStart() reads this config).
|
|
5687
|
+
*/
|
|
5688
|
+
saveConfigToStorage() {
|
|
5689
|
+
try {
|
|
5690
|
+
const data = {
|
|
5691
|
+
server_url: this.config.server_url,
|
|
5692
|
+
workspace: this.server?.config?.workspace ?? this.config.workspace,
|
|
5693
|
+
token: this.config.token,
|
|
5694
|
+
service_id: this.config.service_id,
|
|
5695
|
+
service_name: this.config.service_name,
|
|
5696
|
+
show_ui: this.config.show_ui,
|
|
5697
|
+
visibility: this.config.visibility,
|
|
5698
|
+
require_token: this.config.require_token,
|
|
5699
|
+
script_url: this.detectScriptUrl(),
|
|
5700
|
+
};
|
|
5701
|
+
sessionStorage.setItem(STORAGE_KEY, JSON.stringify(data));
|
|
5702
|
+
}
|
|
5703
|
+
catch {
|
|
5704
|
+
// sessionStorage might be unavailable (private browsing, full quota)
|
|
5705
|
+
}
|
|
5706
|
+
}
|
|
5707
|
+
/**
|
|
5708
|
+
* Detect the URL of the currently loaded hypha-debugger script.
|
|
5709
|
+
* Used by navigate.ts to inject the correct script after soft reload.
|
|
5710
|
+
*/
|
|
5711
|
+
detectScriptUrl() {
|
|
5712
|
+
try {
|
|
5713
|
+
const scripts = document.querySelectorAll("script[src]");
|
|
5714
|
+
for (const s of Array.from(scripts)) {
|
|
5715
|
+
if (s.src && s.src.includes("hypha-debugger")) {
|
|
5716
|
+
return s.src;
|
|
5717
|
+
}
|
|
5718
|
+
}
|
|
5719
|
+
}
|
|
5720
|
+
catch {
|
|
5721
|
+
// ignore
|
|
5722
|
+
}
|
|
5723
|
+
return "https://cdn.jsdelivr.net/npm/hypha-debugger/dist/hypha-debugger.min.js";
|
|
5724
|
+
}
|
|
5413
5725
|
/**
|
|
5414
5726
|
* Generate token, build service URL, update overlay instructions, and
|
|
5415
5727
|
* return a DebugSession.
|
|
@@ -5665,6 +5977,26 @@ async function startDebugger(config) {
|
|
|
5665
5977
|
function autoStart() {
|
|
5666
5978
|
if (typeof window === "undefined" || typeof document === "undefined")
|
|
5667
5979
|
return;
|
|
5980
|
+
// Skip if already started
|
|
5981
|
+
if (window.__HYPHA_DEBUGGER__?.instance)
|
|
5982
|
+
return;
|
|
5983
|
+
// Check sessionStorage for saved config (auto-reconnect after soft reload)
|
|
5984
|
+
try {
|
|
5985
|
+
const saved = sessionStorage.getItem("__hypha_debugger_config__");
|
|
5986
|
+
if (saved) {
|
|
5987
|
+
const savedConfig = JSON.parse(saved);
|
|
5988
|
+
if (savedConfig.server_url) {
|
|
5989
|
+
console.log("[hypha-debugger] Reconnecting from saved session...");
|
|
5990
|
+
startDebugger(savedConfig).catch((err) => {
|
|
5991
|
+
console.error("[hypha-debugger] Auto-reconnect failed:", err);
|
|
5992
|
+
});
|
|
5993
|
+
return;
|
|
5994
|
+
}
|
|
5995
|
+
}
|
|
5996
|
+
}
|
|
5997
|
+
catch {
|
|
5998
|
+
// sessionStorage not available or parse error — continue to script tag detection
|
|
5999
|
+
}
|
|
5668
6000
|
// Find our own script tag
|
|
5669
6001
|
const scripts = document.querySelectorAll("script[src]");
|
|
5670
6002
|
let scriptEl = null;
|
|
@@ -5677,9 +6009,6 @@ function autoStart() {
|
|
|
5677
6009
|
// Skip if data-manual is set
|
|
5678
6010
|
if (scriptEl?.hasAttribute("data-manual"))
|
|
5679
6011
|
return;
|
|
5680
|
-
// Skip if already started
|
|
5681
|
-
if (window.__HYPHA_DEBUGGER__?.instance)
|
|
5682
|
-
return;
|
|
5683
6012
|
const serverUrl = scriptEl?.getAttribute("data-server-url") ?? "https://hypha.aicell.io";
|
|
5684
6013
|
const config = {
|
|
5685
6014
|
server_url: serverUrl,
|
|
@@ -5713,5 +6042,5 @@ if (typeof window !== "undefined") {
|
|
|
5713
6042
|
}
|
|
5714
6043
|
}
|
|
5715
6044
|
|
|
5716
|
-
export { AICursor, HyphaDebugger, PageController, clickElement$1 as clickElement, clickElementByIndex, disposeController, executeScript, fillInput, generateSkillMd, getBrowserState, getComputedStyles, getConsoleLogs, getElementBounds, getHtml, getPageInfo, getReactTree, goBack, goForward, inputText, installConsoleCapture, navigate, queryDom, reload, removeHighlights, scroll, scrollTo, selectOption, startDebugger, takeScreenshot, wrapFn };
|
|
6045
|
+
export { AICursor, HyphaDebugger, PageController, clickElement$1 as clickElement, clickElementByIndex, disposeController, executeScript, fillInput, generateSkillMd, getBrowserState, getComputedStyles, getConsoleLogs, getElementBounds, getHtml, getPageInfo, getReactTree, goBack, goForward, inputText, installConsoleCapture, installNavigationInterceptor, navigate, queryDom, reload, removeHighlights, scroll, scrollTo, selectOption, softReplace, startDebugger, takeScreenshot, wrapFn };
|
|
5717
6046
|
//# sourceMappingURL=hypha-debugger.mjs.map
|