@mcpmake/core 0.2.0
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/analyzer/auth-detector.d.ts +13 -0
- package/dist/analyzer/auth-detector.d.ts.map +1 -0
- package/dist/analyzer/auth-detector.js +143 -0
- package/dist/analyzer/auth-detector.js.map +1 -0
- package/dist/analyzer/dom-parser.d.ts +11 -0
- package/dist/analyzer/dom-parser.d.ts.map +1 -0
- package/dist/analyzer/dom-parser.js +260 -0
- package/dist/analyzer/dom-parser.js.map +1 -0
- package/dist/analyzer/goal-crawler.d.ts +26 -0
- package/dist/analyzer/goal-crawler.d.ts.map +1 -0
- package/dist/analyzer/goal-crawler.js +178 -0
- package/dist/analyzer/goal-crawler.js.map +1 -0
- package/dist/analyzer/hybrid-detector.d.ts +29 -0
- package/dist/analyzer/hybrid-detector.d.ts.map +1 -0
- package/dist/analyzer/hybrid-detector.js +97 -0
- package/dist/analyzer/hybrid-detector.js.map +1 -0
- package/dist/analyzer/index.d.ts +13 -0
- package/dist/analyzer/index.d.ts.map +1 -0
- package/dist/analyzer/index.js +9 -0
- package/dist/analyzer/index.js.map +1 -0
- package/dist/analyzer/screenshot-capture.d.ts +30 -0
- package/dist/analyzer/screenshot-capture.d.ts.map +1 -0
- package/dist/analyzer/screenshot-capture.js +43 -0
- package/dist/analyzer/screenshot-capture.js.map +1 -0
- package/dist/analyzer/selector-builder.d.ts +20 -0
- package/dist/analyzer/selector-builder.d.ts.map +1 -0
- package/dist/analyzer/selector-builder.js +200 -0
- package/dist/analyzer/selector-builder.js.map +1 -0
- package/dist/analyzer/semantic-analyzer.d.ts +14 -0
- package/dist/analyzer/semantic-analyzer.d.ts.map +1 -0
- package/dist/analyzer/semantic-analyzer.js +146 -0
- package/dist/analyzer/semantic-analyzer.js.map +1 -0
- package/dist/analyzer/site-crawler.d.ts +39 -0
- package/dist/analyzer/site-crawler.d.ts.map +1 -0
- package/dist/analyzer/site-crawler.js +236 -0
- package/dist/analyzer/site-crawler.js.map +1 -0
- package/dist/config/configurable-command.d.ts +14 -0
- package/dist/config/configurable-command.d.ts.map +1 -0
- package/dist/config/configurable-command.js +71 -0
- package/dist/config/configurable-command.js.map +1 -0
- package/dist/config/mcpmake-config.d.ts +69 -0
- package/dist/config/mcpmake-config.d.ts.map +1 -0
- package/dist/config/mcpmake-config.js +209 -0
- package/dist/config/mcpmake-config.js.map +1 -0
- package/dist/emitter/code-writer.d.ts +9 -0
- package/dist/emitter/code-writer.d.ts.map +1 -0
- package/dist/emitter/code-writer.js +26 -0
- package/dist/emitter/code-writer.js.map +1 -0
- package/dist/emitter/index.d.ts +33 -0
- package/dist/emitter/index.d.ts.map +1 -0
- package/dist/emitter/index.js +297 -0
- package/dist/emitter/index.js.map +1 -0
- package/dist/emitter/mcpb-bundler.d.ts +32 -0
- package/dist/emitter/mcpb-bundler.d.ts.map +1 -0
- package/dist/emitter/mcpb-bundler.js +173 -0
- package/dist/emitter/mcpb-bundler.js.map +1 -0
- package/dist/emitter/project-scaffolder.d.ts +5 -0
- package/dist/emitter/project-scaffolder.d.ts.map +1 -0
- package/dist/emitter/project-scaffolder.js +101 -0
- package/dist/emitter/project-scaffolder.js.map +1 -0
- package/dist/emitter/python-template-loader.d.ts +5 -0
- package/dist/emitter/python-template-loader.d.ts.map +1 -0
- package/dist/emitter/python-template-loader.js +31 -0
- package/dist/emitter/python-template-loader.js.map +1 -0
- package/dist/emitter/python-templates/dockerfile.hbs +14 -0
- package/dist/emitter/python-templates/env.example.hbs +12 -0
- package/dist/emitter/python-templates/requirements.txt.hbs +4 -0
- package/dist/emitter/python-templates/server.py.hbs +93 -0
- package/dist/emitter/site-scaffolder.d.ts +14 -0
- package/dist/emitter/site-scaffolder.d.ts.map +1 -0
- package/dist/emitter/site-scaffolder.js +71 -0
- package/dist/emitter/site-scaffolder.js.map +1 -0
- package/dist/emitter/site-template-loader.d.ts +6 -0
- package/dist/emitter/site-template-loader.d.ts.map +1 -0
- package/dist/emitter/site-template-loader.js +48 -0
- package/dist/emitter/site-template-loader.js.map +1 -0
- package/dist/emitter/site-templates/browser-manager.ts.hbs +233 -0
- package/dist/emitter/site-templates/config.ts.hbs +28 -0
- package/dist/emitter/site-templates/dockerfile.hbs +31 -0
- package/dist/emitter/site-templates/env.example.hbs +19 -0
- package/dist/emitter/site-templates/package.json.hbs +26 -0
- package/dist/emitter/site-templates/server-main-http.ts.hbs +108 -0
- package/dist/emitter/site-templates/server-main.ts.hbs +23 -0
- package/dist/emitter/site-templates/tool-handler-action.ts.hbs +86 -0
- package/dist/emitter/site-templates/tool-handler-form.ts.hbs +116 -0
- package/dist/emitter/site-templates/tool-handler-lifecycle.ts.hbs +146 -0
- package/dist/emitter/site-templates/tool-index.ts.hbs +11 -0
- package/dist/emitter/template-loader.d.ts +2 -0
- package/dist/emitter/template-loader.d.ts.map +1 -0
- package/dist/emitter/template-loader.js +28 -0
- package/dist/emitter/template-loader.js.map +1 -0
- package/dist/emitter/templates/auth-provider.ts.hbs +57 -0
- package/dist/emitter/templates/config.ts.hbs +110 -0
- package/dist/emitter/templates/discovery.ts.hbs +320 -0
- package/dist/emitter/templates/dockerfile.hbs +34 -0
- package/dist/emitter/templates/env.example.hbs +52 -0
- package/dist/emitter/templates/gitignore.hbs +5 -0
- package/dist/emitter/templates/http-executor.ts.hbs +159 -0
- package/dist/emitter/templates/oauth.ts.hbs +188 -0
- package/dist/emitter/templates/package.json.hbs +25 -0
- package/dist/emitter/templates/prompts.ts.hbs +22 -0
- package/dist/emitter/templates/readme.md.hbs +156 -0
- package/dist/emitter/templates/resources.ts.hbs +63 -0
- package/dist/emitter/templates/response-filter.ts.hbs +128 -0
- package/dist/emitter/templates/server-main-http.ts.hbs +442 -0
- package/dist/emitter/templates/server-main.ts.hbs +40 -0
- package/dist/emitter/templates/task-handlers.ts.hbs +189 -0
- package/dist/emitter/templates/task-manager.ts.hbs +139 -0
- package/dist/emitter/templates/task-sse.ts.hbs +105 -0
- package/dist/emitter/templates/tool-handler.ts.hbs +142 -0
- package/dist/emitter/templates/tool-index.ts.hbs +42 -0
- package/dist/emitter/templates/tool-test.ts.hbs +57 -0
- package/dist/emitter/templates/trace.ts.hbs +79 -0
- package/dist/emitter/templates/tsconfig.json.hbs +16 -0
- package/dist/emitter/templates/types.ts.hbs +5 -0
- package/dist/emitter/worker-template-loader.d.ts +6 -0
- package/dist/emitter/worker-template-loader.d.ts.map +1 -0
- package/dist/emitter/worker-template-loader.js +34 -0
- package/dist/emitter/worker-template-loader.js.map +1 -0
- package/dist/emitter/worker-templates/config.ts.hbs +93 -0
- package/dist/emitter/worker-templates/dev-vars.example.hbs +27 -0
- package/dist/emitter/worker-templates/gitignore.hbs +6 -0
- package/dist/emitter/worker-templates/package.json.hbs +24 -0
- package/dist/emitter/worker-templates/readme.md.hbs +73 -0
- package/dist/emitter/worker-templates/server.test.ts.hbs +20 -0
- package/dist/emitter/worker-templates/tool-handler.ts.hbs +103 -0
- package/dist/emitter/worker-templates/tool-index.ts.hbs +28 -0
- package/dist/emitter/worker-templates/tsconfig.json.hbs +17 -0
- package/dist/emitter/worker-templates/worker.ts.hbs +286 -0
- package/dist/emitter/worker-templates/wrangler.toml.hbs +19 -0
- package/dist/generator/spec-generator.d.ts +7 -0
- package/dist/generator/spec-generator.d.ts.map +1 -0
- package/dist/generator/spec-generator.js +51 -0
- package/dist/generator/spec-generator.js.map +1 -0
- package/dist/index.d.ts +75 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +101 -0
- package/dist/index.js.map +1 -0
- package/dist/parser/har-filter.d.ts +9 -0
- package/dist/parser/har-filter.d.ts.map +1 -0
- package/dist/parser/har-filter.js +72 -0
- package/dist/parser/har-filter.js.map +1 -0
- package/dist/parser/har-loader.d.ts +3 -0
- package/dist/parser/har-loader.d.ts.map +1 -0
- package/dist/parser/har-loader.js +15 -0
- package/dist/parser/har-loader.js.map +1 -0
- package/dist/parser/har-normalizer.d.ts +21 -0
- package/dist/parser/har-normalizer.d.ts.map +1 -0
- package/dist/parser/har-normalizer.js +79 -0
- package/dist/parser/har-normalizer.js.map +1 -0
- package/dist/parser/index.d.ts +11 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +7 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/openapi-loader.d.ts +7 -0
- package/dist/parser/openapi-loader.d.ts.map +1 -0
- package/dist/parser/openapi-loader.js +309 -0
- package/dist/parser/openapi-loader.js.map +1 -0
- package/dist/parser/operation-extractor.d.ts +14 -0
- package/dist/parser/operation-extractor.d.ts.map +1 -0
- package/dist/parser/operation-extractor.js +156 -0
- package/dist/parser/operation-extractor.js.map +1 -0
- package/dist/parser/overlay-loader.d.ts +11 -0
- package/dist/parser/overlay-loader.d.ts.map +1 -0
- package/dist/parser/overlay-loader.js +185 -0
- package/dist/parser/overlay-loader.js.map +1 -0
- package/dist/parser/postman-loader.d.ts +10 -0
- package/dist/parser/postman-loader.d.ts.map +1 -0
- package/dist/parser/postman-loader.js +107 -0
- package/dist/parser/postman-loader.js.map +1 -0
- package/dist/parser/schema-converter.d.ts +13 -0
- package/dist/parser/schema-converter.d.ts.map +1 -0
- package/dist/parser/schema-converter.js +118 -0
- package/dist/parser/schema-converter.js.map +1 -0
- package/dist/plugins/adapter.d.ts +41 -0
- package/dist/plugins/adapter.d.ts.map +1 -0
- package/dist/plugins/adapter.js +16 -0
- package/dist/plugins/adapter.js.map +1 -0
- package/dist/plugins/loader.d.ts +26 -0
- package/dist/plugins/loader.d.ts.map +1 -0
- package/dist/plugins/loader.js +59 -0
- package/dist/plugins/loader.js.map +1 -0
- package/dist/pricing.d.ts +56 -0
- package/dist/pricing.d.ts.map +1 -0
- package/dist/pricing.js +134 -0
- package/dist/pricing.js.map +1 -0
- package/dist/providers/index.d.ts +16 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +57 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/recorder/browser-recorder.d.ts +23 -0
- package/dist/recorder/browser-recorder.d.ts.map +1 -0
- package/dist/recorder/browser-recorder.js +206 -0
- package/dist/recorder/browser-recorder.js.map +1 -0
- package/dist/rescan/diff-engine.d.ts +6 -0
- package/dist/rescan/diff-engine.d.ts.map +1 -0
- package/dist/rescan/diff-engine.js +313 -0
- package/dist/rescan/diff-engine.js.map +1 -0
- package/dist/rescan/index.d.ts +4 -0
- package/dist/rescan/index.d.ts.map +1 -0
- package/dist/rescan/index.js +3 -0
- package/dist/rescan/index.js.map +1 -0
- package/dist/rescan/rescan-runner.d.ts +43 -0
- package/dist/rescan/rescan-runner.d.ts.map +1 -0
- package/dist/rescan/rescan-runner.js +70 -0
- package/dist/rescan/rescan-runner.js.map +1 -0
- package/dist/rescan/rescan-scheduler.d.ts +42 -0
- package/dist/rescan/rescan-scheduler.d.ts.map +1 -0
- package/dist/rescan/rescan-scheduler.js +180 -0
- package/dist/rescan/rescan-scheduler.js.map +1 -0
- package/dist/site-transformer/browser-tools.d.ts +11 -0
- package/dist/site-transformer/browser-tools.d.ts.map +1 -0
- package/dist/site-transformer/browser-tools.js +60 -0
- package/dist/site-transformer/browser-tools.js.map +1 -0
- package/dist/site-transformer/index.d.ts +3 -0
- package/dist/site-transformer/index.d.ts.map +1 -0
- package/dist/site-transformer/index.js +3 -0
- package/dist/site-transformer/index.js.map +1 -0
- package/dist/site-transformer/selector-healer.d.ts +9 -0
- package/dist/site-transformer/selector-healer.d.ts.map +1 -0
- package/dist/site-transformer/selector-healer.js +107 -0
- package/dist/site-transformer/selector-healer.js.map +1 -0
- package/dist/site-transformer/tool-generator.d.ts +14 -0
- package/dist/site-transformer/tool-generator.d.ts.map +1 -0
- package/dist/site-transformer/tool-generator.js +246 -0
- package/dist/site-transformer/tool-generator.js.map +1 -0
- package/dist/transformer/auth-detector.d.ts +29 -0
- package/dist/transformer/auth-detector.d.ts.map +1 -0
- package/dist/transformer/auth-detector.js +104 -0
- package/dist/transformer/auth-detector.js.map +1 -0
- package/dist/transformer/catalog-builder.d.ts +19 -0
- package/dist/transformer/catalog-builder.d.ts.map +1 -0
- package/dist/transformer/catalog-builder.js +57 -0
- package/dist/transformer/catalog-builder.js.map +1 -0
- package/dist/transformer/client-compat.d.ts +7 -0
- package/dist/transformer/client-compat.d.ts.map +1 -0
- package/dist/transformer/client-compat.js +45 -0
- package/dist/transformer/client-compat.js.map +1 -0
- package/dist/transformer/har-clusterer.d.ts +10 -0
- package/dist/transformer/har-clusterer.d.ts.map +1 -0
- package/dist/transformer/har-clusterer.js +28 -0
- package/dist/transformer/har-clusterer.js.map +1 -0
- package/dist/transformer/har-dedup.d.ts +11 -0
- package/dist/transformer/har-dedup.d.ts.map +1 -0
- package/dist/transformer/har-dedup.js +82 -0
- package/dist/transformer/har-dedup.js.map +1 -0
- package/dist/transformer/har-schema-inferrer.d.ts +16 -0
- package/dist/transformer/har-schema-inferrer.d.ts.map +1 -0
- package/dist/transformer/har-schema-inferrer.js +91 -0
- package/dist/transformer/har-schema-inferrer.js.map +1 -0
- package/dist/transformer/har-to-operations.d.ts +14 -0
- package/dist/transformer/har-to-operations.d.ts.map +1 -0
- package/dist/transformer/har-to-operations.js +193 -0
- package/dist/transformer/har-to-operations.js.map +1 -0
- package/dist/transformer/index.d.ts +9 -0
- package/dist/transformer/index.d.ts.map +1 -0
- package/dist/transformer/index.js +7 -0
- package/dist/transformer/index.js.map +1 -0
- package/dist/transformer/llm-namer.d.ts +7 -0
- package/dist/transformer/llm-namer.d.ts.map +1 -0
- package/dist/transformer/llm-namer.js +60 -0
- package/dist/transformer/llm-namer.js.map +1 -0
- package/dist/transformer/naming.d.ts +5 -0
- package/dist/transformer/naming.d.ts.map +1 -0
- package/dist/transformer/naming.js +31 -0
- package/dist/transformer/naming.js.map +1 -0
- package/dist/transformer/operation-filter.d.ts +14 -0
- package/dist/transformer/operation-filter.d.ts.map +1 -0
- package/dist/transformer/operation-filter.js +53 -0
- package/dist/transformer/operation-filter.js.map +1 -0
- package/dist/transformer/resource-builder.d.ts +13 -0
- package/dist/transformer/resource-builder.d.ts.map +1 -0
- package/dist/transformer/resource-builder.js +87 -0
- package/dist/transformer/resource-builder.js.map +1 -0
- package/dist/transformer/schema-merger.d.ts +15 -0
- package/dist/transformer/schema-merger.d.ts.map +1 -0
- package/dist/transformer/schema-merger.js +66 -0
- package/dist/transformer/schema-merger.js.map +1 -0
- package/dist/transformer/stainless-config.d.ts +75 -0
- package/dist/transformer/stainless-config.d.ts.map +1 -0
- package/dist/transformer/stainless-config.js +59 -0
- package/dist/transformer/stainless-config.js.map +1 -0
- package/dist/transformer/stainless-translator.d.ts +61 -0
- package/dist/transformer/stainless-translator.d.ts.map +1 -0
- package/dist/transformer/stainless-translator.js +375 -0
- package/dist/transformer/stainless-translator.js.map +1 -0
- package/dist/transformer/tool-builder.d.ts +4 -0
- package/dist/transformer/tool-builder.d.ts.map +1 -0
- package/dist/transformer/tool-builder.js +119 -0
- package/dist/transformer/tool-builder.js.map +1 -0
- package/dist/types/index.d.ts +140 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/site.d.ts +285 -0
- package/dist/types/site.d.ts.map +1 -0
- package/dist/types/site.js +9 -0
- package/dist/types/site.js.map +1 -0
- package/dist/utils/fail.d.ts +49 -0
- package/dist/utils/fail.d.ts.map +1 -0
- package/dist/utils/fail.js +223 -0
- package/dist/utils/fail.js.map +1 -0
- package/dist/utils/fs.d.ts +6 -0
- package/dist/utils/fs.d.ts.map +1 -0
- package/dist/utils/fs.js +29 -0
- package/dist/utils/fs.js.map +1 -0
- package/dist/utils/interactive.d.ts +7 -0
- package/dist/utils/interactive.d.ts.map +1 -0
- package/dist/utils/interactive.js +31 -0
- package/dist/utils/interactive.js.map +1 -0
- package/dist/utils/logger.d.ts +2 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +3 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/sanitize.d.ts +29 -0
- package/dist/utils/sanitize.d.ts.map +1 -0
- package/dist/utils/sanitize.js +45 -0
- package/dist/utils/sanitize.js.map +1 -0
- package/dist/utils/watcher.d.ts +12 -0
- package/dist/utils/watcher.d.ts.map +1 -0
- package/dist/utils/watcher.js +37 -0
- package/dist/utils/watcher.js.map +1 -0
- package/package.json +45 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detects authentication flows from analyzed page descriptors.
|
|
3
|
+
*
|
|
4
|
+
* Scans forms, buttons, and links for patterns indicating login forms,
|
|
5
|
+
* OAuth redirects, and active session indicators.
|
|
6
|
+
*/
|
|
7
|
+
import type { PageDescriptor, AuthFlowDescriptor } from '../types/site.js';
|
|
8
|
+
/**
|
|
9
|
+
* Detect the authentication flow from a set of analyzed pages.
|
|
10
|
+
* Returns undefined if no auth flow is detected.
|
|
11
|
+
*/
|
|
12
|
+
export declare function detectAuthFlow(pages: PageDescriptor[]): AuthFlowDescriptor | undefined;
|
|
13
|
+
//# sourceMappingURL=auth-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-detector.d.ts","sourceRoot":"","sources":["../../src/analyzer/auth-detector.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,cAAc,EAEd,kBAAkB,EAGnB,MAAM,kBAAkB,CAAC;AAgB1B;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,kBAAkB,GAAG,SAAS,CAwBtF"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detects authentication flows from analyzed page descriptors.
|
|
3
|
+
*
|
|
4
|
+
* Scans forms, buttons, and links for patterns indicating login forms,
|
|
5
|
+
* OAuth redirects, and active session indicators.
|
|
6
|
+
*/
|
|
7
|
+
import { logger } from '../utils/logger.js';
|
|
8
|
+
/** Patterns for detecting username/email fields. */
|
|
9
|
+
const USERNAME_PATTERNS = /user|email|login|account|e-mail/i;
|
|
10
|
+
/** Patterns for detecting password fields. */
|
|
11
|
+
const PASSWORD_PATTERNS = /pass|pwd|secret/i;
|
|
12
|
+
/** Patterns for detecting OAuth redirect buttons/links. */
|
|
13
|
+
const OAUTH_PATTERNS = /google|github|facebook|twitter|apple|microsoft|oauth|sso|sign.in.with|log.in.with/i;
|
|
14
|
+
/** Patterns for detecting session indicators (logged-in state). */
|
|
15
|
+
const SESSION_INDICATOR_PATTERNS = /log\s*out|sign\s*out|my\s*account|profile|avatar|dashboard/i;
|
|
16
|
+
/**
|
|
17
|
+
* Detect the authentication flow from a set of analyzed pages.
|
|
18
|
+
* Returns undefined if no auth flow is detected.
|
|
19
|
+
*/
|
|
20
|
+
export function detectAuthFlow(pages) {
|
|
21
|
+
// Try form-login detection first (most specific)
|
|
22
|
+
const formLogin = detectFormLogin(pages);
|
|
23
|
+
if (formLogin) {
|
|
24
|
+
logger.info(`Detected auth flow: form-login on ${formLogin.loginPage?.url ?? 'unknown page'}`);
|
|
25
|
+
return formLogin;
|
|
26
|
+
}
|
|
27
|
+
// Try OAuth redirect detection
|
|
28
|
+
const oauthRedirect = detectOAuthRedirect(pages);
|
|
29
|
+
if (oauthRedirect) {
|
|
30
|
+
logger.info('Detected auth flow: oauth-redirect');
|
|
31
|
+
return oauthRedirect;
|
|
32
|
+
}
|
|
33
|
+
// Check for session indicators without a visible login form
|
|
34
|
+
const sessionOnly = detectSessionIndicators(pages);
|
|
35
|
+
if (sessionOnly) {
|
|
36
|
+
logger.info('Detected auth flow: cookie-session (session indicators found, no login form)');
|
|
37
|
+
return sessionOnly;
|
|
38
|
+
}
|
|
39
|
+
logger.info('No authentication flow detected');
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
// ─── Form Login Detection ─────────────────────────────────────────
|
|
43
|
+
function detectFormLogin(pages) {
|
|
44
|
+
for (const page of pages) {
|
|
45
|
+
for (const form of page.forms) {
|
|
46
|
+
const usernameField = findUsernameField(form);
|
|
47
|
+
const passwordField = findPasswordField(form);
|
|
48
|
+
if (usernameField && passwordField) {
|
|
49
|
+
return {
|
|
50
|
+
type: 'form-login',
|
|
51
|
+
loginPage: page,
|
|
52
|
+
loginForm: form,
|
|
53
|
+
usernameField: usernameField,
|
|
54
|
+
passwordField: passwordField,
|
|
55
|
+
submitButton: form.submitButton,
|
|
56
|
+
sessionIndicator: findSessionIndicator(pages),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
function findUsernameField(form) {
|
|
64
|
+
for (const field of form.fields) {
|
|
65
|
+
if (field.fieldType === 'email')
|
|
66
|
+
return field.selector;
|
|
67
|
+
if (USERNAME_PATTERNS.test(field.name))
|
|
68
|
+
return field.selector;
|
|
69
|
+
if (field.label && USERNAME_PATTERNS.test(field.label))
|
|
70
|
+
return field.selector;
|
|
71
|
+
if (field.placeholder && USERNAME_PATTERNS.test(field.placeholder))
|
|
72
|
+
return field.selector;
|
|
73
|
+
}
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
function findPasswordField(form) {
|
|
77
|
+
for (const field of form.fields) {
|
|
78
|
+
if (field.fieldType === 'password')
|
|
79
|
+
return field.selector;
|
|
80
|
+
if (PASSWORD_PATTERNS.test(field.name))
|
|
81
|
+
return field.selector;
|
|
82
|
+
}
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
// ─── OAuth Detection ──────────────────────────────────────────────
|
|
86
|
+
function detectOAuthRedirect(pages) {
|
|
87
|
+
for (const page of pages) {
|
|
88
|
+
// Check buttons for OAuth patterns
|
|
89
|
+
for (const btn of page.buttons) {
|
|
90
|
+
const text = btn.text ?? btn.ariaLabel ?? '';
|
|
91
|
+
const href = btn.href ?? '';
|
|
92
|
+
if (OAUTH_PATTERNS.test(text) || OAUTH_PATTERNS.test(href)) {
|
|
93
|
+
return {
|
|
94
|
+
type: 'oauth-redirect',
|
|
95
|
+
loginPage: page,
|
|
96
|
+
sessionIndicator: findSessionIndicator(pages),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// Check links for OAuth patterns
|
|
101
|
+
for (const link of page.links) {
|
|
102
|
+
const text = link.text ?? '';
|
|
103
|
+
if (OAUTH_PATTERNS.test(text) || OAUTH_PATTERNS.test(link.href)) {
|
|
104
|
+
return {
|
|
105
|
+
type: 'oauth-redirect',
|
|
106
|
+
loginPage: page,
|
|
107
|
+
sessionIndicator: findSessionIndicator(pages),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
// ─── Session Indicator Detection ──────────────────────────────────
|
|
115
|
+
function findSessionIndicator(pages) {
|
|
116
|
+
for (const page of pages) {
|
|
117
|
+
// Check buttons for logout/profile patterns
|
|
118
|
+
for (const btn of page.buttons) {
|
|
119
|
+
const text = btn.text ?? btn.ariaLabel ?? '';
|
|
120
|
+
if (SESSION_INDICATOR_PATTERNS.test(text)) {
|
|
121
|
+
return { selector: btn.selector };
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Check links for logout/profile patterns
|
|
125
|
+
for (const link of page.links) {
|
|
126
|
+
const text = link.text ?? '';
|
|
127
|
+
if (SESSION_INDICATOR_PATTERNS.test(text) || SESSION_INDICATOR_PATTERNS.test(link.href)) {
|
|
128
|
+
return { selector: link.selector };
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
function detectSessionIndicators(pages) {
|
|
135
|
+
const indicator = findSessionIndicator(pages);
|
|
136
|
+
if (!indicator)
|
|
137
|
+
return undefined;
|
|
138
|
+
return {
|
|
139
|
+
type: 'cookie-session',
|
|
140
|
+
sessionIndicator: indicator,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=auth-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-detector.js","sourceRoot":"","sources":["../../src/analyzer/auth-detector.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,oDAAoD;AACpD,MAAM,iBAAiB,GAAG,kCAAkC,CAAC;AAE7D,8CAA8C;AAC9C,MAAM,iBAAiB,GAAG,kBAAkB,CAAC;AAE7C,2DAA2D;AAC3D,MAAM,cAAc,GAClB,oFAAoF,CAAC;AAEvF,mEAAmE;AACnE,MAAM,0BAA0B,GAAG,6DAA6D,CAAC;AAEjG;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,KAAuB;IACpD,iDAAiD;IACjD,MAAM,SAAS,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IACzC,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,CAAC,IAAI,CAAC,qCAAqC,SAAS,CAAC,SAAS,EAAE,GAAG,IAAI,cAAc,EAAE,CAAC,CAAC;QAC/F,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,+BAA+B;IAC/B,MAAM,aAAa,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;IACjD,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;QAClD,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,4DAA4D;IAC5D,MAAM,WAAW,GAAG,uBAAuB,CAAC,KAAK,CAAC,CAAC;IACnD,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,CAAC,IAAI,CAAC,8EAA8E,CAAC,CAAC;QAC5F,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;IAC/C,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,qEAAqE;AAErE,SAAS,eAAe,CAAC,KAAuB;IAC9C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,MAAM,aAAa,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAC9C,MAAM,aAAa,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAE9C,IAAI,aAAa,IAAI,aAAa,EAAE,CAAC;gBACnC,OAAO;oBACL,IAAI,EAAE,YAA4B;oBAClC,SAAS,EAAE,IAAI;oBACf,SAAS,EAAE,IAAI;oBACf,aAAa,EAAE,aAAa;oBAC5B,aAAa,EAAE,aAAa;oBAC5B,YAAY,EAAE,IAAI,CAAC,YAAY;oBAC/B,gBAAgB,EAAE,oBAAoB,CAAC,KAAK,CAAC;iBAC9C,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAoB;IAC7C,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChC,IAAI,KAAK,CAAC,SAAS,KAAK,OAAO;YAAE,OAAO,KAAK,CAAC,QAAQ,CAAC;QACvD,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC,QAAQ,CAAC;QAC9D,IAAI,KAAK,CAAC,KAAK,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC,QAAQ,CAAC;QAC9E,IAAI,KAAK,CAAC,WAAW,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC;YAAE,OAAO,KAAK,CAAC,QAAQ,CAAC;IAC5F,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAoB;IAC7C,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChC,IAAI,KAAK,CAAC,SAAS,KAAK,UAAU;YAAE,OAAO,KAAK,CAAC,QAAQ,CAAC;QAC1D,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC,QAAQ,CAAC;IAChE,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,qEAAqE;AAErE,SAAS,mBAAmB,CAAC,KAAuB;IAClD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,mCAAmC;QACnC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC/B,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC;YAC7C,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;YAC5B,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC3D,OAAO;oBACL,IAAI,EAAE,gBAAgC;oBACtC,SAAS,EAAE,IAAI;oBACf,gBAAgB,EAAE,oBAAoB,CAAC,KAAK,CAAC;iBAC9C,CAAC;YACJ,CAAC;QACH,CAAC;QAED,iCAAiC;QACjC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;YAC7B,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChE,OAAO;oBACL,IAAI,EAAE,gBAAgC;oBACtC,SAAS,EAAE,IAAI;oBACf,gBAAgB,EAAE,oBAAoB,CAAC,KAAK,CAAC;iBAC9C,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,qEAAqE;AAErE,SAAS,oBAAoB,CAC3B,KAAuB;IAEvB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,4CAA4C;QAC5C,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC/B,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC;YAC7C,IAAI,0BAA0B,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC1C,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC;YACpC,CAAC;QACH,CAAC;QAED,0CAA0C;QAC1C,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;YAC7B,IAAI,0BAA0B,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,0BAA0B,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxF,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;YACrC,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,uBAAuB,CAAC,KAAuB;IACtD,MAAM,SAAS,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAC9C,IAAI,CAAC,SAAS;QAAE,OAAO,SAAS,CAAC;IAEjC,OAAO;QACL,IAAI,EAAE,gBAAgC;QACtC,gBAAgB,EAAE,SAAS;KAC5B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses a Playwright page's DOM to extract interactive elements:
|
|
3
|
+
* forms (with fields), standalone buttons, and navigation links.
|
|
4
|
+
*/
|
|
5
|
+
import type { Page } from 'playwright';
|
|
6
|
+
import type { PageDescriptor } from '../types/site.js';
|
|
7
|
+
/**
|
|
8
|
+
* Parse a single page and extract all interactive elements.
|
|
9
|
+
*/
|
|
10
|
+
export declare function parsePage(page: Page): Promise<PageDescriptor>;
|
|
11
|
+
//# sourceMappingURL=dom-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom-parser.d.ts","sourceRoot":"","sources":["../../src/analyzer/dom-parser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EACV,cAAc,EAMf,MAAM,kBAAkB,CAAC;AAU1B;;GAEG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,cAAc,CAAC,CAmBnE"}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses a Playwright page's DOM to extract interactive elements:
|
|
3
|
+
* forms (with fields), standalone buttons, and navigation links.
|
|
4
|
+
*/
|
|
5
|
+
import { buildSelectorSet } from './selector-builder.js';
|
|
6
|
+
import { logger } from '../utils/logger.js';
|
|
7
|
+
import crypto from 'node:crypto';
|
|
8
|
+
/** Maximum elements to extract per category to avoid huge outputs. */
|
|
9
|
+
const MAX_FORMS = 20;
|
|
10
|
+
const MAX_BUTTONS = 50;
|
|
11
|
+
const MAX_LINKS = 100;
|
|
12
|
+
/**
|
|
13
|
+
* Parse a single page and extract all interactive elements.
|
|
14
|
+
*/
|
|
15
|
+
export async function parsePage(page) {
|
|
16
|
+
const url = page.url();
|
|
17
|
+
const title = await page.title().catch(() => undefined);
|
|
18
|
+
const forms = await extractForms(page);
|
|
19
|
+
const buttons = await extractStandaloneButtons(page);
|
|
20
|
+
const links = await extractLinks(page);
|
|
21
|
+
const pageId = generateStableId('page', url);
|
|
22
|
+
return {
|
|
23
|
+
pageId,
|
|
24
|
+
url,
|
|
25
|
+
title,
|
|
26
|
+
forms,
|
|
27
|
+
buttons,
|
|
28
|
+
links,
|
|
29
|
+
analyzedAt: new Date().toISOString(),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
// ─── Form Extraction ────────────────────────────────────────────────
|
|
33
|
+
async function extractForms(page) {
|
|
34
|
+
const formElements = await page.$$('form');
|
|
35
|
+
const forms = [];
|
|
36
|
+
for (const formEl of formElements.slice(0, MAX_FORMS)) {
|
|
37
|
+
try {
|
|
38
|
+
const form = await extractSingleForm(page, formEl);
|
|
39
|
+
if (form.fields.length > 0) {
|
|
40
|
+
forms.push(form);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
logger.debug(`Skipping form: ${err}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return forms;
|
|
48
|
+
}
|
|
49
|
+
async function extractSingleForm(page, formEl) {
|
|
50
|
+
if (!formEl)
|
|
51
|
+
throw new Error('Form element is null');
|
|
52
|
+
const formAttrs = await formEl.evaluate((el) => ({
|
|
53
|
+
action: el.action || '',
|
|
54
|
+
method: (el.method || 'get').toLowerCase(),
|
|
55
|
+
id: el.id || '',
|
|
56
|
+
name: el.getAttribute('name') || '',
|
|
57
|
+
}));
|
|
58
|
+
const selector = await buildSelectorSet(page, formEl);
|
|
59
|
+
const fields = await extractFormFields(page, formEl);
|
|
60
|
+
// Find submit button
|
|
61
|
+
let submitButton;
|
|
62
|
+
const submitEl = (await formEl.$('button[type="submit"]')) ??
|
|
63
|
+
(await formEl.$('input[type="submit"]')) ??
|
|
64
|
+
(await formEl.$('button:not([type])'));
|
|
65
|
+
if (submitEl) {
|
|
66
|
+
submitButton = await buildSelectorSet(page, submitEl);
|
|
67
|
+
}
|
|
68
|
+
const formId = generateStableId('form', formAttrs.action || formAttrs.id || formAttrs.name || selector.primary);
|
|
69
|
+
return {
|
|
70
|
+
formId,
|
|
71
|
+
action: formAttrs.action || undefined,
|
|
72
|
+
method: formAttrs.method === 'post' ? 'post' : 'get',
|
|
73
|
+
selector,
|
|
74
|
+
fields,
|
|
75
|
+
submitButton,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
async function extractFormFields(page, formEl) {
|
|
79
|
+
if (!formEl)
|
|
80
|
+
return [];
|
|
81
|
+
const fieldElements = await formEl.$$('input:not([type="hidden"]):not([type="submit"]):not([type="reset"]):not([type="button"]), ' +
|
|
82
|
+
'textarea, select');
|
|
83
|
+
const fields = [];
|
|
84
|
+
for (const fieldEl of fieldElements) {
|
|
85
|
+
try {
|
|
86
|
+
const attrs = await fieldEl.evaluate((el) => {
|
|
87
|
+
const input = el;
|
|
88
|
+
return {
|
|
89
|
+
tagName: el.tagName.toLowerCase(),
|
|
90
|
+
name: input.name || '',
|
|
91
|
+
type: input.type || 'text',
|
|
92
|
+
placeholder: input.placeholder || '',
|
|
93
|
+
required: input.required || false,
|
|
94
|
+
value: input.value || '',
|
|
95
|
+
ariaLabel: el.getAttribute('aria-label') || '',
|
|
96
|
+
// Get associated label
|
|
97
|
+
label: input.labels?.[0]?.textContent?.trim() || '',
|
|
98
|
+
// Get select options
|
|
99
|
+
options: el.tagName === 'SELECT'
|
|
100
|
+
? Array.from(el.options).map((o) => o.text || o.value)
|
|
101
|
+
: undefined,
|
|
102
|
+
};
|
|
103
|
+
});
|
|
104
|
+
const fieldType = mapFieldType(attrs.tagName, attrs.type);
|
|
105
|
+
const selector = await buildSelectorSet(page, fieldEl);
|
|
106
|
+
const label = attrs.label || attrs.ariaLabel || attrs.placeholder || attrs.name;
|
|
107
|
+
// Skip fields with no name and no useful label
|
|
108
|
+
if (!attrs.name && !label)
|
|
109
|
+
continue;
|
|
110
|
+
fields.push({
|
|
111
|
+
name: attrs.name || label.replace(/\s+/g, '_').toLowerCase(),
|
|
112
|
+
fieldType,
|
|
113
|
+
selector,
|
|
114
|
+
label: label || undefined,
|
|
115
|
+
placeholder: attrs.placeholder || undefined,
|
|
116
|
+
required: attrs.required,
|
|
117
|
+
options: attrs.options,
|
|
118
|
+
defaultValue: attrs.value || undefined,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
logger.debug(`Skipping form field: ${err}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return fields;
|
|
126
|
+
}
|
|
127
|
+
// ─── Button Extraction ──────────────────────────────────────────────
|
|
128
|
+
async function extractStandaloneButtons(page) {
|
|
129
|
+
// Find buttons that are NOT inside a form (form buttons are handled by extractForms)
|
|
130
|
+
const buttonElements = await page.$$('button:not(form button):not(form input), ' + '[role="button"]:not(form [role="button"])');
|
|
131
|
+
const buttons = [];
|
|
132
|
+
for (const btnEl of buttonElements.slice(0, MAX_BUTTONS)) {
|
|
133
|
+
try {
|
|
134
|
+
const attrs = await btnEl.evaluate((el) => ({
|
|
135
|
+
tagName: el.tagName.toLowerCase(),
|
|
136
|
+
type: el.getAttribute('type') || 'button',
|
|
137
|
+
text: el.textContent?.trim().slice(0, 80) || '',
|
|
138
|
+
ariaLabel: el.getAttribute('aria-label') || '',
|
|
139
|
+
href: el.getAttribute('href') || '',
|
|
140
|
+
isHidden: el.offsetParent === null ||
|
|
141
|
+
getComputedStyle(el).display === 'none' ||
|
|
142
|
+
getComputedStyle(el).visibility === 'hidden',
|
|
143
|
+
}));
|
|
144
|
+
// Skip hidden or empty buttons
|
|
145
|
+
if (attrs.isHidden)
|
|
146
|
+
continue;
|
|
147
|
+
if (!attrs.text && !attrs.ariaLabel)
|
|
148
|
+
continue;
|
|
149
|
+
const selector = await buildSelectorSet(page, btnEl);
|
|
150
|
+
const buttonId = generateStableId('btn', attrs.text || attrs.ariaLabel || selector.primary);
|
|
151
|
+
const buttonType = attrs.href
|
|
152
|
+
? 'link'
|
|
153
|
+
: attrs.type === 'submit'
|
|
154
|
+
? 'submit'
|
|
155
|
+
: 'button';
|
|
156
|
+
buttons.push({
|
|
157
|
+
buttonId,
|
|
158
|
+
selector,
|
|
159
|
+
text: attrs.text || undefined,
|
|
160
|
+
ariaLabel: attrs.ariaLabel || undefined,
|
|
161
|
+
type: buttonType,
|
|
162
|
+
href: attrs.href || undefined,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
logger.debug(`Skipping button: ${err}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return buttons;
|
|
170
|
+
}
|
|
171
|
+
// ─── Link Extraction ────────────────────────────────────────────────
|
|
172
|
+
async function extractLinks(page) {
|
|
173
|
+
const linkElements = await page.$$('a[href]');
|
|
174
|
+
const links = [];
|
|
175
|
+
const seenHrefs = new Set();
|
|
176
|
+
const pageOrigin = new URL(page.url()).origin;
|
|
177
|
+
for (const linkEl of linkElements.slice(0, MAX_LINKS * 2)) {
|
|
178
|
+
// Over-fetch then filter
|
|
179
|
+
try {
|
|
180
|
+
const attrs = await linkEl.evaluate((el) => ({
|
|
181
|
+
href: el.href,
|
|
182
|
+
text: el.textContent?.trim().slice(0, 80) || '',
|
|
183
|
+
ariaLabel: el.getAttribute('aria-label') || '',
|
|
184
|
+
isHidden: el.offsetParent === null ||
|
|
185
|
+
getComputedStyle(el).display === 'none' ||
|
|
186
|
+
getComputedStyle(el).visibility === 'hidden',
|
|
187
|
+
target: el.getAttribute('target') || '',
|
|
188
|
+
}));
|
|
189
|
+
if (attrs.isHidden)
|
|
190
|
+
continue;
|
|
191
|
+
if (!attrs.text && !attrs.ariaLabel)
|
|
192
|
+
continue;
|
|
193
|
+
// Deduplicate by href
|
|
194
|
+
const normalizedHref = normalizeHref(attrs.href);
|
|
195
|
+
if (seenHrefs.has(normalizedHref))
|
|
196
|
+
continue;
|
|
197
|
+
seenHrefs.add(normalizedHref);
|
|
198
|
+
// Skip non-http links (javascript:, mailto:, tel:, #)
|
|
199
|
+
if (!attrs.href.startsWith('http'))
|
|
200
|
+
continue;
|
|
201
|
+
const isNavigation = attrs.href.startsWith(pageOrigin) && !attrs.href.includes('#');
|
|
202
|
+
const selector = await buildSelectorSet(page, linkEl);
|
|
203
|
+
const linkId = generateStableId('link', normalizedHref);
|
|
204
|
+
links.push({
|
|
205
|
+
linkId,
|
|
206
|
+
selector,
|
|
207
|
+
text: attrs.text || undefined,
|
|
208
|
+
href: attrs.href,
|
|
209
|
+
isNavigation,
|
|
210
|
+
});
|
|
211
|
+
if (links.length >= MAX_LINKS)
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
catch (err) {
|
|
215
|
+
logger.debug(`Skipping link: ${err}`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return links;
|
|
219
|
+
}
|
|
220
|
+
// ─── Helpers ────────────────────────────────────────────────────────
|
|
221
|
+
function mapFieldType(tagName, type) {
|
|
222
|
+
if (tagName === 'textarea')
|
|
223
|
+
return 'textarea';
|
|
224
|
+
if (tagName === 'select')
|
|
225
|
+
return 'select';
|
|
226
|
+
const typeMap = {
|
|
227
|
+
text: 'text',
|
|
228
|
+
email: 'email',
|
|
229
|
+
password: 'password',
|
|
230
|
+
number: 'number',
|
|
231
|
+
tel: 'tel',
|
|
232
|
+
url: 'url',
|
|
233
|
+
search: 'search',
|
|
234
|
+
checkbox: 'checkbox',
|
|
235
|
+
radio: 'radio',
|
|
236
|
+
file: 'file',
|
|
237
|
+
date: 'date',
|
|
238
|
+
'datetime-local': 'datetime-local',
|
|
239
|
+
color: 'color',
|
|
240
|
+
range: 'range',
|
|
241
|
+
hidden: 'hidden',
|
|
242
|
+
};
|
|
243
|
+
return typeMap[type] || 'other';
|
|
244
|
+
}
|
|
245
|
+
function normalizeHref(href) {
|
|
246
|
+
try {
|
|
247
|
+
const url = new URL(href);
|
|
248
|
+
// Remove trailing slash and fragment
|
|
249
|
+
return `${url.origin}${url.pathname.replace(/\/$/, '')}${url.search}`;
|
|
250
|
+
}
|
|
251
|
+
catch {
|
|
252
|
+
return href;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/** Generate a deterministic, stable ID from a category and key. */
|
|
256
|
+
function generateStableId(category, key) {
|
|
257
|
+
const hash = crypto.createHash('sha256').update(key).digest('hex').slice(0, 8);
|
|
258
|
+
return `${category}_${hash}`;
|
|
259
|
+
}
|
|
260
|
+
//# sourceMappingURL=dom-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom-parser.js","sourceRoot":"","sources":["../../src/analyzer/dom-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Goal-directed crawl: instead of BFS crawling, uses an LLM to decide
|
|
3
|
+
* which links to follow based on a user-specified goal (e.g. "book a flight").
|
|
4
|
+
*
|
|
5
|
+
* At each page, we extract the page title and available link texts,
|
|
6
|
+
* ask Claude (Haiku) which link to click next, and navigate accordingly.
|
|
7
|
+
* Stops when the LLM says GOAL_REACHED or we hit maxSteps.
|
|
8
|
+
*/
|
|
9
|
+
import type { CrawlResult } from './site-crawler.js';
|
|
10
|
+
export interface GoalCrawlOptions {
|
|
11
|
+
url: string;
|
|
12
|
+
goal: string;
|
|
13
|
+
maxSteps?: number;
|
|
14
|
+
headless?: boolean;
|
|
15
|
+
viewport?: {
|
|
16
|
+
width: number;
|
|
17
|
+
height: number;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Crawl a website in a goal-directed manner using an LLM to pick links.
|
|
22
|
+
*
|
|
23
|
+
* Requires ANTHROPIC_API_KEY to be set.
|
|
24
|
+
*/
|
|
25
|
+
export declare function goalDirectedCrawl(options: GoalCrawlOptions): Promise<CrawlResult>;
|
|
26
|
+
//# sourceMappingURL=goal-crawler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"goal-crawler.d.ts","sourceRoot":"","sources":["../../src/analyzer/goal-crawler.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAWrD,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9C;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC,CA0KvF"}
|