smart-web-mcp 0.44.0 → 1.0.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/CHANGELOG.md +352 -1
- package/README.md +33 -566
- package/dist/assessment.d.ts +10 -3
- package/dist/assessment.js +21 -6
- package/dist/assessment.js.map +1 -1
- package/dist/body-export.d.ts +10 -0
- package/dist/body-export.js +28 -0
- package/dist/body-export.js.map +1 -0
- package/dist/browser-session.d.ts +32 -1
- package/dist/browser-session.js +373 -3
- package/dist/browser-session.js.map +1 -1
- package/dist/cli-fetch-options.d.ts +7 -0
- package/dist/cli-fetch-options.js +41 -0
- package/dist/cli-fetch-options.js.map +1 -0
- package/dist/cli.js +31 -12
- package/dist/cli.js.map +1 -1
- package/dist/comment-export.d.ts +10 -0
- package/dist/comment-export.js +39 -0
- package/dist/comment-export.js.map +1 -0
- package/dist/composition.d.ts +1 -22
- package/dist/composition.js +0 -16
- package/dist/composition.js.map +1 -1
- package/dist/extraction/budget.d.ts +3 -0
- package/dist/extraction/budget.js +88 -7
- package/dist/extraction/budget.js.map +1 -1
- package/dist/extraction/document.js +134 -9
- package/dist/extraction/document.js.map +1 -1
- package/dist/korea/coupang-filters.d.ts +5 -0
- package/dist/korea/coupang-filters.js +87 -0
- package/dist/korea/coupang-filters.js.map +1 -0
- package/dist/korea/coupang.d.ts +27 -6
- package/dist/korea/coupang.js +202 -82
- package/dist/korea/coupang.js.map +1 -1
- package/dist/korea/proxy-client.d.ts +1 -0
- package/dist/korea/proxy-client.js +6 -2
- package/dist/korea/proxy-client.js.map +1 -1
- package/dist/korea/smartvertical.d.ts +1 -0
- package/dist/korea/smartvertical.js +39 -25
- package/dist/korea/smartvertical.js.map +1 -1
- package/dist/lib.d.ts +4 -2
- package/dist/lib.js +2 -1
- package/dist/lib.js.map +1 -1
- package/dist/mcp-server.js +39 -15
- package/dist/mcp-server.js.map +1 -1
- package/dist/operator-browser-fixture.d.ts +7 -0
- package/dist/operator-browser-fixture.js +19 -0
- package/dist/operator-browser-fixture.js.map +1 -0
- package/dist/operator-canary-cli.d.ts +6 -0
- package/dist/operator-canary-cli.js +190 -0
- package/dist/operator-canary-cli.js.map +1 -0
- package/dist/operator-canary.d.ts +74 -0
- package/dist/operator-canary.js +135 -0
- package/dist/operator-canary.js.map +1 -0
- package/dist/operator-cdp.d.ts +15 -0
- package/dist/operator-cdp.js +195 -0
- package/dist/operator-cdp.js.map +1 -0
- package/dist/operator-frame.d.ts +3 -0
- package/dist/operator-frame.js +55 -0
- package/dist/operator-frame.js.map +1 -0
- package/dist/settings.d.ts +3 -0
- package/dist/settings.js +1 -0
- package/dist/settings.js.map +1 -1
- package/dist/shared.d.ts +47 -10
- package/dist/shared.js +15 -9
- package/dist/shared.js.map +1 -1
- package/dist/smartbrowser.d.ts +169 -0
- package/dist/smartbrowser.js +288 -0
- package/dist/smartbrowser.js.map +1 -0
- package/dist/smartcrawl.js +16 -21
- package/dist/smartcrawl.js.map +1 -1
- package/dist/smartfetch/academic-fallback.js +3 -5
- package/dist/smartfetch/academic-fallback.js.map +1 -1
- package/dist/smartfetch/archive-fallback.js +2 -5
- package/dist/smartfetch/archive-fallback.js.map +1 -1
- package/dist/smartfetch/assets.d.ts +1 -1
- package/dist/smartfetch/assets.js +28 -1
- package/dist/smartfetch/assets.js.map +1 -1
- package/dist/smartfetch/jina-reader.d.ts +1 -0
- package/dist/smartfetch/jina-reader.js +17 -3
- package/dist/smartfetch/jina-reader.js.map +1 -1
- package/dist/smartfetch/pipeline.js +15 -25
- package/dist/smartfetch/pipeline.js.map +1 -1
- package/dist/smartfetch/provider-policy.d.ts +3 -0
- package/dist/smartfetch/provider-policy.js +45 -2
- package/dist/smartfetch/provider-policy.js.map +1 -1
- package/dist/smartfetch/provider-types.d.ts +8 -0
- package/dist/smartfetch/providers/article.js +76 -10
- package/dist/smartfetch/providers/article.js.map +1 -1
- package/dist/smartfetch/providers/blind-post.d.ts +2 -0
- package/dist/smartfetch/providers/blind-post.js +167 -0
- package/dist/smartfetch/providers/blind-post.js.map +1 -0
- package/dist/smartfetch/providers/clien.d.ts +2 -0
- package/dist/smartfetch/providers/clien.js +157 -0
- package/dist/smartfetch/providers/clien.js.map +1 -0
- package/dist/smartfetch/providers/commerce.d.ts +15 -0
- package/dist/smartfetch/providers/commerce.js +123 -7
- package/dist/smartfetch/providers/commerce.js.map +1 -1
- package/dist/smartfetch/providers/dcinside.js +313 -20
- package/dist/smartfetch/providers/dcinside.js.map +1 -1
- package/dist/smartfetch/providers/hackernews-html.d.ts +21 -0
- package/dist/smartfetch/providers/hackernews-html.js +148 -0
- package/dist/smartfetch/providers/hackernews-html.js.map +1 -0
- package/dist/smartfetch/providers/hackernews.js +76 -14
- package/dist/smartfetch/providers/hackernews.js.map +1 -1
- package/dist/smartfetch/providers/index.js +7 -1
- package/dist/smartfetch/providers/index.js.map +1 -1
- package/dist/smartfetch/providers/linkedin.js +2 -1
- package/dist/smartfetch/providers/linkedin.js.map +1 -1
- package/dist/smartfetch/providers/naver-blog.d.ts +2 -0
- package/dist/smartfetch/providers/naver-blog.js +87 -45
- package/dist/smartfetch/providers/naver-blog.js.map +1 -1
- package/dist/smartfetch/providers/naver-cafe-native.d.ts +7 -0
- package/dist/smartfetch/providers/naver-cafe-native.js +188 -0
- package/dist/smartfetch/providers/naver-cafe-native.js.map +1 -0
- package/dist/smartfetch/providers/naver-cafe.js +165 -4
- package/dist/smartfetch/providers/naver-cafe.js.map +1 -1
- package/dist/smartfetch/providers/naver-map-search.js +1 -1
- package/dist/smartfetch/providers/naver-map-search.js.map +1 -1
- package/dist/smartfetch/providers/ppomppu.d.ts +2 -0
- package/dist/smartfetch/providers/ppomppu.js +289 -0
- package/dist/smartfetch/providers/ppomppu.js.map +1 -0
- package/dist/smartfetch/providers/reddit.js +24 -3
- package/dist/smartfetch/providers/reddit.js.map +1 -1
- package/dist/smartfetch/providers/threads.js +1 -1
- package/dist/smartfetch/providers/threads.js.map +1 -1
- package/dist/smartfetch/providers/wikipedia.js +138 -0
- package/dist/smartfetch/providers/wikipedia.js.map +1 -1
- package/dist/smartfetch.d.ts +11 -2
- package/dist/smartfetch.js +369 -78
- package/dist/smartfetch.js.map +1 -1
- package/dist/smartsearch-brave.d.ts +2 -0
- package/dist/smartsearch-brave.js +43 -0
- package/dist/smartsearch-brave.js.map +1 -0
- package/dist/smartsearch-browser.d.ts +5 -0
- package/dist/smartsearch-browser.js +116 -0
- package/dist/smartsearch-browser.js.map +1 -0
- package/dist/smartsearch-ddg.d.ts +2 -0
- package/dist/smartsearch-ddg.js +46 -0
- package/dist/smartsearch-ddg.js.map +1 -0
- package/dist/smartsearch-node.d.ts +6 -0
- package/dist/smartsearch-node.js +21 -0
- package/dist/smartsearch-node.js.map +1 -0
- package/dist/smartsearch-postgresql.d.ts +7 -0
- package/dist/smartsearch-postgresql.js +44 -0
- package/dist/smartsearch-postgresql.js.map +1 -0
- package/dist/smartsearch-python.d.ts +8 -0
- package/dist/smartsearch-python.js +87 -0
- package/dist/smartsearch-python.js.map +1 -0
- package/dist/smartsearch-quality.d.ts +6 -0
- package/dist/smartsearch-quality.js +47 -0
- package/dist/smartsearch-quality.js.map +1 -0
- package/dist/smartsearch-youtube.d.ts +7 -0
- package/dist/smartsearch-youtube.js +76 -0
- package/dist/smartsearch-youtube.js.map +1 -0
- package/dist/smartsearch.d.ts +3 -0
- package/dist/smartsearch.js +617 -132
- package/dist/smartsearch.js.map +1 -1
- package/package.json +8 -5
- package/python/requirements-undetected-chromedriver.txt +2 -2
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { chromium } from "playwright";
|
|
2
|
+
const browserTransports = new WeakMap();
|
|
3
|
+
export function ownedBrowserCleanupIncomplete(browser) {
|
|
4
|
+
return browser !== undefined && browserTransports.get(browser)?.cleanupIncomplete === true;
|
|
5
|
+
}
|
|
6
|
+
export function createOwnedCdpTransport(wire) {
|
|
7
|
+
const owned = new Set();
|
|
8
|
+
const creations = new Set();
|
|
9
|
+
const closures = new Map();
|
|
10
|
+
const pending = new Map();
|
|
11
|
+
let sequence = -1;
|
|
12
|
+
let closing = false;
|
|
13
|
+
let disconnected = false;
|
|
14
|
+
let cleanupTimer;
|
|
15
|
+
let cleanupCount = 0;
|
|
16
|
+
const request = (method, params) => new Promise((resolve, reject) => {
|
|
17
|
+
const id = sequence--;
|
|
18
|
+
pending.set(id, { resolve, reject: () => reject(new Error("Owned CDP transport disconnected")) });
|
|
19
|
+
wire.send({ id, method, params });
|
|
20
|
+
});
|
|
21
|
+
const finishCleanup = () => {
|
|
22
|
+
if (closing && !disconnected && creations.size === 0 && cleanupCount === 0) {
|
|
23
|
+
clearTimeout(cleanupTimer);
|
|
24
|
+
wire.close();
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
const closeTarget = (targetId) => {
|
|
28
|
+
cleanupCount++;
|
|
29
|
+
void request("Target.closeTarget", { targetId }).then(message => {
|
|
30
|
+
if (!message.error && message.result?.success === true)
|
|
31
|
+
owned.delete(targetId);
|
|
32
|
+
}).catch(() => { }).finally(() => {
|
|
33
|
+
cleanupCount--;
|
|
34
|
+
finishCleanup();
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
const transport = {
|
|
38
|
+
get cleanupIncomplete() { return disconnected && (creations.size > 0 || owned.size > 0); },
|
|
39
|
+
send(value) {
|
|
40
|
+
if (closing)
|
|
41
|
+
return;
|
|
42
|
+
const message = value;
|
|
43
|
+
if (!message.sessionId && message.method === "Target.setAutoAttach") {
|
|
44
|
+
// No existing or concurrently-created foreign tabs may be attached.
|
|
45
|
+
wire.send({ ...message, params: { autoAttach: false, waitForDebuggerOnStart: false, flatten: true } });
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
if (!message.sessionId && message.method === "Target.createTarget" && message.id !== undefined)
|
|
49
|
+
creations.add(message.id);
|
|
50
|
+
if (!message.sessionId && message.method === "Target.closeTarget" && message.id !== undefined && typeof message.params?.targetId === "string") {
|
|
51
|
+
closures.set(message.id, message.params.targetId);
|
|
52
|
+
}
|
|
53
|
+
wire.send(message);
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
close() {
|
|
57
|
+
if (closing)
|
|
58
|
+
return;
|
|
59
|
+
closing = true;
|
|
60
|
+
// Also handle a create response arriving while close is in progress.
|
|
61
|
+
// Keep the socket alive for bounded cleanup, never close the browser.
|
|
62
|
+
cleanupTimer = setTimeout(() => wire.close(), 750);
|
|
63
|
+
for (const target of owned)
|
|
64
|
+
closeTarget(target);
|
|
65
|
+
finishCleanup();
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
wire.onmessage = value => {
|
|
69
|
+
const message = value;
|
|
70
|
+
if (message.id !== undefined && closures.has(message.id)) {
|
|
71
|
+
if (!message.error && message.result?.success === true)
|
|
72
|
+
owned.delete(closures.get(message.id));
|
|
73
|
+
closures.delete(message.id);
|
|
74
|
+
}
|
|
75
|
+
if (message.id !== undefined && pending.has(message.id)) {
|
|
76
|
+
const callback = pending.get(message.id);
|
|
77
|
+
pending.delete(message.id);
|
|
78
|
+
callback.resolve(message);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (message.id !== undefined && creations.delete(message.id)) {
|
|
82
|
+
const targetId = message.result?.targetId;
|
|
83
|
+
if (typeof targetId !== "string" || message.error) {
|
|
84
|
+
if (!closing)
|
|
85
|
+
transport.onmessage?.(message);
|
|
86
|
+
finishCleanup();
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
owned.add(targetId);
|
|
90
|
+
if (closing) {
|
|
91
|
+
closeTarget(targetId);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
// Forward create only after the real attachedToTarget event has given
|
|
95
|
+
// Playwright its new page. Root auto-attach remains disabled throughout.
|
|
96
|
+
void request("Target.attachToTarget", { targetId, flatten: true }).then(attached => {
|
|
97
|
+
if (attached.error) {
|
|
98
|
+
transport.close();
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (!closing)
|
|
102
|
+
transport.onmessage?.(message);
|
|
103
|
+
}).catch(() => transport.close());
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
// Extra sessions requested by Playwright for the owned page, and child
|
|
107
|
+
// frame/worker attachment within that page, retain their native behavior.
|
|
108
|
+
transport.onmessage?.(message);
|
|
109
|
+
};
|
|
110
|
+
wire.onclose = () => {
|
|
111
|
+
closing = true;
|
|
112
|
+
disconnected = true;
|
|
113
|
+
clearTimeout(cleanupTimer);
|
|
114
|
+
for (const callback of pending.values())
|
|
115
|
+
callback.reject();
|
|
116
|
+
pending.clear();
|
|
117
|
+
transport.onclose?.("Owned CDP transport disconnected");
|
|
118
|
+
};
|
|
119
|
+
return transport;
|
|
120
|
+
}
|
|
121
|
+
export async function connectOwnedCdpTransport(transport, options) {
|
|
122
|
+
try {
|
|
123
|
+
const browser = await chromium.connectOverCDP(transport, options);
|
|
124
|
+
browserTransports.set(browser, transport);
|
|
125
|
+
return browser;
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
transport.close();
|
|
129
|
+
throw error;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
export async function connectOwnedBrowser(endpoint, options) {
|
|
133
|
+
const start = Date.now();
|
|
134
|
+
const controller = new AbortController();
|
|
135
|
+
const timer = setTimeout(() => controller.abort(), options.timeout);
|
|
136
|
+
let transport;
|
|
137
|
+
try {
|
|
138
|
+
const origin = new URL(endpoint);
|
|
139
|
+
if (origin.protocol !== "http:" || !["127.0.0.1", "[::1]"].includes(origin.hostname)
|
|
140
|
+
|| origin.username || origin.password || origin.pathname !== "/" || origin.search || origin.hash) {
|
|
141
|
+
throw new Error("Invalid local CDP endpoint");
|
|
142
|
+
}
|
|
143
|
+
const response = await fetch(new URL("/json/version", origin), { signal: controller.signal, redirect: "error" });
|
|
144
|
+
if (!response.ok)
|
|
145
|
+
throw new Error("Local CDP discovery failed");
|
|
146
|
+
const value = await response.json();
|
|
147
|
+
const address = typeof value === "object" && value !== null && "webSocketDebuggerUrl" in value ? value.webSocketDebuggerUrl : undefined;
|
|
148
|
+
if (typeof address !== "string")
|
|
149
|
+
throw new Error("Local CDP discovery has no browser socket");
|
|
150
|
+
const ws = new URL(address);
|
|
151
|
+
if (ws.protocol !== "ws:" || ws.hostname !== origin.hostname || ws.port !== origin.port
|
|
152
|
+
|| ws.username || ws.password || !/^\/devtools\/browser\/[^/]+$/.test(ws.pathname) || ws.search || ws.hash) {
|
|
153
|
+
throw new Error("Local CDP discovery returned an invalid browser socket");
|
|
154
|
+
}
|
|
155
|
+
if (controller.signal.aborted)
|
|
156
|
+
throw new Error("Owned CDP connection timeout");
|
|
157
|
+
const socket = new WebSocket(ws);
|
|
158
|
+
const wire = {
|
|
159
|
+
send: message => socket.send(JSON.stringify(message)),
|
|
160
|
+
close: () => socket.close(),
|
|
161
|
+
};
|
|
162
|
+
transport = createOwnedCdpTransport(wire);
|
|
163
|
+
socket.addEventListener("message", event => {
|
|
164
|
+
try {
|
|
165
|
+
wire.onmessage?.(JSON.parse(String(event.data)));
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
socket.close();
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
socket.addEventListener("close", () => wire.onclose?.());
|
|
172
|
+
const abort = () => socket.close();
|
|
173
|
+
controller.signal.addEventListener("abort", abort, { once: true });
|
|
174
|
+
socket.addEventListener("close", () => controller.signal.removeEventListener("abort", abort), { once: true });
|
|
175
|
+
await new Promise((resolve, reject) => {
|
|
176
|
+
socket.addEventListener("open", () => resolve(), { once: true });
|
|
177
|
+
socket.addEventListener("error", () => reject(new Error("Local CDP socket failed")), { once: true });
|
|
178
|
+
socket.addEventListener("close", () => reject(new Error("Local CDP socket closed")), { once: true });
|
|
179
|
+
});
|
|
180
|
+
const remaining = options.timeout - (Date.now() - start);
|
|
181
|
+
if (remaining <= 0 || controller.signal.aborted)
|
|
182
|
+
throw new Error("Owned CDP connection timeout");
|
|
183
|
+
return await connectOwnedCdpTransport(transport, { ...options, timeout: remaining });
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
transport?.close();
|
|
187
|
+
if (controller.signal.aborted)
|
|
188
|
+
throw new Error("Owned CDP connection timeout");
|
|
189
|
+
throw error;
|
|
190
|
+
}
|
|
191
|
+
finally {
|
|
192
|
+
clearTimeout(timer);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=operator-cdp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operator-cdp.js","sourceRoot":"","sources":["../src/operator-cdp.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
const engineName = "smartweb_identity";
|
|
3
|
+
const engine = () => ({
|
|
4
|
+
queryAll(root, key) {
|
|
5
|
+
const bridge = globalThis;
|
|
6
|
+
bridge[key] = true;
|
|
7
|
+
return [root.nodeType === 9 ? root.documentElement : root];
|
|
8
|
+
},
|
|
9
|
+
});
|
|
10
|
+
export async function prepareFrameIdentity(context) {
|
|
11
|
+
// Playwright 1.63's CDP default context does not inherit selectors.register
|
|
12
|
+
// entries. Isolate its existing channel registration seam here; unlike global
|
|
13
|
+
// per-call engine names this neither grows a registry nor touches other tabs.
|
|
14
|
+
// Registration changes only this client's selector registry, not browser state.
|
|
15
|
+
const channel = context._channel;
|
|
16
|
+
if (!channel?.registerSelectorEngine)
|
|
17
|
+
throw new Error("Native frame identity adapter is unavailable");
|
|
18
|
+
await channel.registerSelectorEngine({ selectorEngine: { name: engineName, source: `(${engine.toString()})()`, contentScript: true } }, { timeout: 0 });
|
|
19
|
+
}
|
|
20
|
+
export async function nativeFrameId(scope, session) {
|
|
21
|
+
const key = `__smartWebFrame_${randomUUID().replaceAll("-", "")}`;
|
|
22
|
+
const contexts = [];
|
|
23
|
+
const collect = ({ context }) => { contexts.push(context); };
|
|
24
|
+
let found;
|
|
25
|
+
session.on("Runtime.executionContextCreated", collect);
|
|
26
|
+
try {
|
|
27
|
+
// A standalone content-script selector executes in the selected Frame's
|
|
28
|
+
// isolated world. No page globals, mutable DOM attributes, URL/name matching,
|
|
29
|
+
// or private Playwright frame IDs carry identity across the protocol boundary.
|
|
30
|
+
const marker = await scope.$(`${engineName}=${key}`);
|
|
31
|
+
await marker?.dispose();
|
|
32
|
+
await session.send("Runtime.enable");
|
|
33
|
+
const isolated = contexts.filter(context => context.auxData?.isDefault === false);
|
|
34
|
+
if (isolated.length > 40)
|
|
35
|
+
throw new Error("Selected frame identity exceeds the isolated context bound");
|
|
36
|
+
for (const context of isolated) {
|
|
37
|
+
const remote = await session.send("Runtime.evaluate", { uniqueContextId: context.uniqueId, expression: `globalThis[${JSON.stringify(key)}] === true`, returnByValue: true });
|
|
38
|
+
if (!remote.exceptionDetails && remote.result.value === true) {
|
|
39
|
+
if (found)
|
|
40
|
+
throw new Error("Selected frame identity is ambiguous");
|
|
41
|
+
found = context;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (!found?.auxData?.frameId || scope.isDetached())
|
|
45
|
+
throw new Error("Selected frame identity could not be resolved in an isolated world");
|
|
46
|
+
return found.auxData.frameId;
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
if (found)
|
|
50
|
+
await session.send("Runtime.evaluate", { uniqueContextId: found.uniqueId, expression: `delete globalThis[${JSON.stringify(key)}]` }).catch(() => { });
|
|
51
|
+
session.off("Runtime.executionContextCreated", collect);
|
|
52
|
+
await session.send("Runtime.disable").catch(() => { });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=operator-frame.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operator-frame.js","sourceRoot":"","sources":["../src/operator-frame.ts"],"names":[],"mappings":"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"}
|
package/dist/settings.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export type SmartWebSettings = {
|
|
|
9
9
|
enableSearxng?: boolean;
|
|
10
10
|
enableDuckDuckGo?: boolean;
|
|
11
11
|
enableBraveHtml?: boolean;
|
|
12
|
+
enableBrowserFallback?: boolean;
|
|
12
13
|
};
|
|
13
14
|
fetch?: {
|
|
14
15
|
chromeChannel?: string;
|
|
@@ -58,6 +59,8 @@ export type SmartWebSettings = {
|
|
|
58
59
|
* and runs headed with anti-bot hardening.
|
|
59
60
|
*/
|
|
60
61
|
browserProfile?: string;
|
|
62
|
+
/** Approved loopback CDP endpoint, used only for explicit smartfetch reads. */
|
|
63
|
+
browserCdpUrl?: string;
|
|
61
64
|
};
|
|
62
65
|
network?: {
|
|
63
66
|
allowPrivateHosts?: boolean;
|
package/dist/settings.js
CHANGED
package/dist/settings.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAC/G,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"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"}
|
package/dist/shared.d.ts
CHANGED
|
@@ -22,6 +22,8 @@ export type PrimaryContent = {
|
|
|
22
22
|
export type AdapterResult = {
|
|
23
23
|
ok: boolean;
|
|
24
24
|
method: string;
|
|
25
|
+
http_status?: number;
|
|
26
|
+
retry_after?: string;
|
|
25
27
|
content: string;
|
|
26
28
|
links: string[];
|
|
27
29
|
final_url?: string;
|
|
@@ -59,18 +61,24 @@ export type SearchHandoff = {
|
|
|
59
61
|
pages_loaded: number;
|
|
60
62
|
errors: string[];
|
|
61
63
|
};
|
|
64
|
+
export type SmartsearchProviderAttempt = {
|
|
65
|
+
provider: string;
|
|
66
|
+
status: "succeeded" | "failed";
|
|
67
|
+
result_count: number;
|
|
68
|
+
error?: string;
|
|
69
|
+
};
|
|
70
|
+
export type SmartsearchExecution = {
|
|
71
|
+
status: "succeeded" | "failed";
|
|
72
|
+
attempts: SmartsearchProviderAttempt[];
|
|
73
|
+
};
|
|
62
74
|
export type RetrievalConfidence = "low" | "medium" | "high";
|
|
63
75
|
export type CaptchaType = "turnstile" | "recaptcha" | "hcaptcha";
|
|
64
76
|
export type RetrievalHandoffSuggestion = {
|
|
65
|
-
tool: "smartcrawl"
|
|
77
|
+
tool: "smartcrawl";
|
|
66
78
|
reason: string;
|
|
67
79
|
mode: "read" | "act";
|
|
68
80
|
url: string;
|
|
69
81
|
goal: string;
|
|
70
|
-
/** When the page contains a known CAPTCHA widget, this field tells the
|
|
71
|
-
* receiving runtime what type of CAPTCHA to expect so it can prepare
|
|
72
|
-
* the appropriate solving strategy (checkbox click, external solver, etc.). */
|
|
73
|
-
captcha_type?: CaptchaType;
|
|
74
82
|
};
|
|
75
83
|
export type RetrievalAssessment = {
|
|
76
84
|
confidence: RetrievalConfidence;
|
|
@@ -79,6 +87,13 @@ export type RetrievalAssessment = {
|
|
|
79
87
|
interactive_flow_likely: boolean;
|
|
80
88
|
signals: string[];
|
|
81
89
|
recommended_handoff: RetrievalHandoffSuggestion | null;
|
|
90
|
+
/** Remaining task state, not an executable plan or successful recovery. */
|
|
91
|
+
continuation?: {
|
|
92
|
+
status: "user_required" | "action_required" | "unavailable";
|
|
93
|
+
url: string;
|
|
94
|
+
reason: string;
|
|
95
|
+
captcha_type?: CaptchaType;
|
|
96
|
+
} | null;
|
|
82
97
|
};
|
|
83
98
|
export type SmartfetchPolicyMetadata = {
|
|
84
99
|
provider_id: string;
|
|
@@ -100,6 +115,8 @@ export type SmartfetchBudgetFieldMetadata = {
|
|
|
100
115
|
truncated: boolean;
|
|
101
116
|
original_chars?: number;
|
|
102
117
|
returned_chars?: number;
|
|
118
|
+
/** Source UTF-16 units omitted, excluding inserted marker text. */
|
|
119
|
+
omitted_chars?: number;
|
|
103
120
|
original_items?: number;
|
|
104
121
|
returned_items?: number;
|
|
105
122
|
omitted_items?: number;
|
|
@@ -114,7 +131,7 @@ export type SmartfetchBudgetMetadata = {
|
|
|
114
131
|
text_content: number;
|
|
115
132
|
};
|
|
116
133
|
/** Which budget control selected this projection, when resolved at the host/MCP layer. */
|
|
117
|
-
source?: "output_budget" | "preferred_budget_chars" | "headroom_tokens" | "context_mode" | "default";
|
|
134
|
+
source?: "output_budget" | "preferred_budget_chars" | "headroom_tokens" | "context_mode" | "settings" | "default";
|
|
118
135
|
/** Human-readable selection rationale for host/debug visibility. */
|
|
119
136
|
reason?: string;
|
|
120
137
|
};
|
|
@@ -163,6 +180,8 @@ export type SearchResponse = {
|
|
|
163
180
|
results: SearchResult[];
|
|
164
181
|
fallbacks_tried: string[];
|
|
165
182
|
notes: string[];
|
|
183
|
+
/** Structured provider execution outcome. Optional for backward compatibility with custom runtimes. */
|
|
184
|
+
execution?: SmartsearchExecution;
|
|
166
185
|
budget?: SmartfetchBudgetMetadata;
|
|
167
186
|
assessment?: RetrievalAssessment;
|
|
168
187
|
handoff?: SearchHandoff;
|
|
@@ -178,6 +197,22 @@ export type SmartfetchOutput = {
|
|
|
178
197
|
post: Record<string, unknown> | null;
|
|
179
198
|
thread: Record<string, unknown>[];
|
|
180
199
|
comments: Record<string, unknown>[];
|
|
200
|
+
comment_export?: {
|
|
201
|
+
path: string;
|
|
202
|
+
format: "json";
|
|
203
|
+
bytes: number;
|
|
204
|
+
sha256: string;
|
|
205
|
+
comments_count: number;
|
|
206
|
+
complete: boolean;
|
|
207
|
+
};
|
|
208
|
+
body_export?: {
|
|
209
|
+
path: string;
|
|
210
|
+
format: "text";
|
|
211
|
+
bytes: number;
|
|
212
|
+
sha256: string;
|
|
213
|
+
chars: number;
|
|
214
|
+
complete: boolean;
|
|
215
|
+
};
|
|
181
216
|
download: SmartfetchAsset | null;
|
|
182
217
|
assets: SmartfetchAsset[];
|
|
183
218
|
outbound_links: string[];
|
|
@@ -194,7 +229,7 @@ export type SmartfetchOutput = {
|
|
|
194
229
|
/** Final MCP/output projection budget preset selected for this response. */
|
|
195
230
|
selected_output_budget?: "compact" | "balanced" | "full";
|
|
196
231
|
/** Which budget control won precedence for the selected output budget. */
|
|
197
|
-
selected_output_budget_source?: "output_budget" | "preferred_budget_chars" | "headroom_tokens" | "context_mode" | "default";
|
|
232
|
+
selected_output_budget_source?: "output_budget" | "preferred_budget_chars" | "headroom_tokens" | "context_mode" | "settings" | "default";
|
|
198
233
|
/** Human-readable explanation of how the selected output budget was resolved. */
|
|
199
234
|
selected_output_budget_reason?: string;
|
|
200
235
|
};
|
|
@@ -278,6 +313,7 @@ export declare function resolveValidatedUrl(url: string, options?: {
|
|
|
278
313
|
timeoutMs?: number;
|
|
279
314
|
maxRedirects?: number;
|
|
280
315
|
headers?: HeadersInit;
|
|
316
|
+
signal?: AbortSignal;
|
|
281
317
|
}): Promise<{
|
|
282
318
|
ok: false;
|
|
283
319
|
reason: string;
|
|
@@ -285,6 +321,8 @@ export declare function resolveValidatedUrl(url: string, options?: {
|
|
|
285
321
|
} | {
|
|
286
322
|
ok: true;
|
|
287
323
|
url: string;
|
|
324
|
+
http_status: number;
|
|
325
|
+
retry_after: string;
|
|
288
326
|
}>;
|
|
289
327
|
export declare function isXUrl(url: string): boolean;
|
|
290
328
|
export declare function isRedditUrl(url: string): boolean;
|
|
@@ -302,9 +340,8 @@ export declare function needsDynamicCrawl(result: AdapterResult): boolean;
|
|
|
302
340
|
* a response body that is suspiciously small for its HTML size.
|
|
303
341
|
*
|
|
304
342
|
* This is intentionally narrower than `needsDynamicCrawl`: gokuProps or
|
|
305
|
-
* interactive-JS-app shells
|
|
306
|
-
*
|
|
307
|
-
* `web_task` handoff instead.
|
|
343
|
+
* interactive-JS-app shells are handled separately from challenge detection;
|
|
344
|
+
* a challenge match never authorizes CAPTCHA solving or consent actions.
|
|
308
345
|
*/
|
|
309
346
|
export declare function needsBotChallengeBrowserUpgrade(result: AdapterResult): boolean;
|
|
310
347
|
/**
|
package/dist/shared.js
CHANGED
|
@@ -479,6 +479,8 @@ function isRedirectStatus(status) {
|
|
|
479
479
|
}
|
|
480
480
|
export async function resolveValidatedUrl(url, options) {
|
|
481
481
|
const validationOptions = options?.allowPrivateHosts === undefined ? undefined : { allowPrivateHosts: options.allowPrivateHosts };
|
|
482
|
+
if (options?.signal?.aborted)
|
|
483
|
+
return { ok: false, reason: "redirect_resolution_failed", message: "Request cancelled before URL validation" };
|
|
482
484
|
const initial = await validateOutboundUrl(url, validationOptions);
|
|
483
485
|
if (!initial.ok)
|
|
484
486
|
return initial;
|
|
@@ -487,11 +489,13 @@ export async function resolveValidatedUrl(url, options) {
|
|
|
487
489
|
const controller = new AbortController();
|
|
488
490
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
489
491
|
let currentUrl = url;
|
|
492
|
+
const signal = options?.signal ? AbortSignal.any([options.signal, controller.signal]) : controller.signal;
|
|
490
493
|
try {
|
|
491
494
|
for (let hop = 0; hop <= maxRedirects; hop++) {
|
|
495
|
+
signal.throwIfAborted();
|
|
492
496
|
const requestInit = {
|
|
493
497
|
method: "GET",
|
|
494
|
-
signal
|
|
498
|
+
signal,
|
|
495
499
|
redirect: "manual",
|
|
496
500
|
};
|
|
497
501
|
if (options?.headers !== undefined)
|
|
@@ -499,16 +503,16 @@ export async function resolveValidatedUrl(url, options) {
|
|
|
499
503
|
const response = await fetch(currentUrl, requestInit);
|
|
500
504
|
if (!isRedirectStatus(response.status)) {
|
|
501
505
|
try {
|
|
502
|
-
|
|
506
|
+
void response.body?.cancel().catch(() => { });
|
|
503
507
|
}
|
|
504
508
|
catch {
|
|
505
509
|
// Ignore best-effort stream cleanup failures.
|
|
506
510
|
}
|
|
507
|
-
return { ok: true, url: currentUrl };
|
|
511
|
+
return { ok: true, url: currentUrl, http_status: response.status, retry_after: response.headers.get("retry-after") || "" };
|
|
508
512
|
}
|
|
509
513
|
if (hop === maxRedirects) {
|
|
510
514
|
try {
|
|
511
|
-
|
|
515
|
+
void response.body?.cancel().catch(() => { });
|
|
512
516
|
}
|
|
513
517
|
catch {
|
|
514
518
|
// Ignore best-effort stream cleanup failures.
|
|
@@ -517,7 +521,7 @@ export async function resolveValidatedUrl(url, options) {
|
|
|
517
521
|
}
|
|
518
522
|
const location = response.headers.get("location");
|
|
519
523
|
try {
|
|
520
|
-
|
|
524
|
+
void response.body?.cancel().catch(() => { });
|
|
521
525
|
}
|
|
522
526
|
catch {
|
|
523
527
|
// Ignore best-effort stream cleanup failures.
|
|
@@ -526,6 +530,7 @@ export async function resolveValidatedUrl(url, options) {
|
|
|
526
530
|
return { ok: false, reason: "redirect_missing_location", message: "Redirect response did not include a Location header" };
|
|
527
531
|
}
|
|
528
532
|
const nextUrl = new URL(location, currentUrl).toString();
|
|
533
|
+
signal.throwIfAborted();
|
|
529
534
|
const validation = await validateOutboundUrl(nextUrl, validationOptions);
|
|
530
535
|
if (!validation.ok)
|
|
531
536
|
return validation;
|
|
@@ -645,9 +650,8 @@ export function needsDynamicCrawl(result) {
|
|
|
645
650
|
* a response body that is suspiciously small for its HTML size.
|
|
646
651
|
*
|
|
647
652
|
* This is intentionally narrower than `needsDynamicCrawl`: gokuProps or
|
|
648
|
-
* interactive-JS-app shells
|
|
649
|
-
*
|
|
650
|
-
* `web_task` handoff instead.
|
|
653
|
+
* interactive-JS-app shells are handled separately from challenge detection;
|
|
654
|
+
* a challenge match never authorizes CAPTCHA solving or consent actions.
|
|
651
655
|
*/
|
|
652
656
|
export function needsBotChallengeBrowserUpgrade(result) {
|
|
653
657
|
if (!result.ok)
|
|
@@ -733,7 +737,9 @@ export async function fetchText(url, timeoutMs, init) {
|
|
|
733
737
|
const controller = new AbortController();
|
|
734
738
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
735
739
|
try {
|
|
736
|
-
const
|
|
740
|
+
const signal = init?.signal ? AbortSignal.any([init.signal, controller.signal]) : controller.signal;
|
|
741
|
+
signal.throwIfAborted();
|
|
742
|
+
const response = await fetch(url, { ...init, signal });
|
|
737
743
|
const text = await response.text();
|
|
738
744
|
return { ok: response.ok, status: response.status, text };
|
|
739
745
|
}
|