@detiq/crawler 0.1.6 → 0.1.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@detiq/crawler",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "private": false,
5
5
  "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org/" },
6
6
  "type": "module",
package/src/ai-login.ts CHANGED
@@ -141,7 +141,20 @@ export async function loginWithStagehand(
141
141
  await logStep('fill_password', async () => {
142
142
  const observations = await stagehand.observe('Find the password input field');
143
143
  const selector = observations[0]?.selector || 'input[type="password"]';
144
- await pg.locator(selector).fill(creds.password);
144
+ try {
145
+ await pg.locator(selector).fill(creds.password);
146
+ } catch {
147
+ // Stagehand locator failed (e.g. form re-rendered, proxy can't locate element).
148
+ // Fall back to direct DOM fill via evaluate so the password never touches the LLM.
149
+ await pg.evaluate((pwd: string) => {
150
+ const input = document.querySelector('input[type="password"]') as HTMLInputElement | null;
151
+ if (!input) throw new Error('No password field found on page');
152
+ const setter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value')?.set;
153
+ setter?.call(input, pwd);
154
+ input.dispatchEvent(new Event('input', { bubbles: true }));
155
+ input.dispatchEvent(new Event('change', { bubbles: true }));
156
+ }, creds.password);
157
+ }
145
158
  });
146
159
  await logStep('click_submit', () => actWithMouseSim(stagehand, 'Click the sign in, log in, login, or continue button to submit credentials'));
147
160
  await pg.waitForLoadState('networkidle').catch(() => pg.waitForTimeout(2000));
package/src/crawler.ts CHANGED
@@ -1059,9 +1059,13 @@ export async function crawlProject(opts: {
1059
1059
  }, state.origins);
1060
1060
  }
1061
1061
 
1062
- // Reload to apply cookies + trigger localStorage restore initScript
1062
+ // Navigate to appUrl with cookies now set.
1063
+ // We MUST navigate to appUrl (not reload current page) because the initial
1064
+ // goto ran without cookies and was redirected to /login. Reloading /login stays
1065
+ // at /login even with a valid cookie (public path, no auth redirect). Navigating
1066
+ // to appUrl lets server middleware see the cookie and route to the authenticated app.
1063
1067
  await onProgress?.(12, 'Restoring session');
1064
- await rawPage.reload({ waitUntil: 'domcontentloaded' });
1068
+ await rawPage.goto(opts.appUrl, { waitUntil: 'domcontentloaded' }).catch(() => { });
1065
1069
  await waitForStableDOM(page);
1066
1070
  // SPA root pages redirect client-side (useEffect → router.replace). Wait for it.
1067
1071
  if (page.url() === opts.appUrl || page.url() === opts.appUrl.replace(/\/$/, '')) {
package/src/skyvern.ts CHANGED
@@ -67,9 +67,6 @@ export async function skyvernNavigate(
67
67
  return { screenshotUrls: [], visitedUrls: [], status: 'failed' };
68
68
  }
69
69
 
70
- const { assertResolvesToPublicAddress } = await import('@detiq/core');
71
- await assertResolvesToPublicAddress(apiUrl);
72
-
73
70
  const visitedUrls: string[] = [];
74
71
  const screenshotUrls: string[] = [];
75
72
  const skyvernSteps: SkyvernStep[] = [];
@@ -164,9 +161,6 @@ export async function skyvernFallback(task: SkyvernTask, tenantConfig?: SkyvernC
164
161
  return 'failed';
165
162
  }
166
163
 
167
- const { assertResolvesToPublicAddress } = await import('@detiq/core');
168
- await assertResolvesToPublicAddress(apiUrl);
169
-
170
164
  try {
171
165
  const res = await fetch(`${apiUrl}/api/v1/tasks`, {
172
166
  method: 'POST',