@modelrelay/sdk 1.28.0 → 1.29.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/chunk-CV3DTA6P.js +1196 -0
- package/dist/index.cjs +1 -584
- package/dist/index.d.cts +1 -200
- package/dist/index.d.ts +1 -200
- package/dist/index.js +1 -579
- package/dist/node.cjs +590 -1
- package/dist/node.d.cts +200 -1
- package/dist/node.d.ts +200 -1
- package/dist/node.js +581 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -70,7 +70,7 @@ import {
|
|
|
70
70
|
toolResultMessage,
|
|
71
71
|
tryParseToolArgs,
|
|
72
72
|
zodToJsonSchema
|
|
73
|
-
} from "./chunk-
|
|
73
|
+
} from "./chunk-CV3DTA6P.js";
|
|
74
74
|
|
|
75
75
|
// src/api_keys.ts
|
|
76
76
|
var PUBLISHABLE_PREFIX = "mr_pk_";
|
|
@@ -7692,579 +7692,6 @@ function createMockFetchQueue(responses) {
|
|
|
7692
7692
|
return { fetch: fetchImpl, calls };
|
|
7693
7693
|
}
|
|
7694
7694
|
|
|
7695
|
-
// src/tools_browser.ts
|
|
7696
|
-
var BrowserToolNames = {
|
|
7697
|
-
/** Navigate to a URL and return accessibility tree */
|
|
7698
|
-
NAVIGATE: "browser.navigate",
|
|
7699
|
-
/** Click an element by accessible name/role */
|
|
7700
|
-
CLICK: "browser.click",
|
|
7701
|
-
/** Type text into an input field */
|
|
7702
|
-
TYPE: "browser.type",
|
|
7703
|
-
/** Get current accessibility tree */
|
|
7704
|
-
SNAPSHOT: "browser.snapshot",
|
|
7705
|
-
/** Scroll the page */
|
|
7706
|
-
SCROLL: "browser.scroll",
|
|
7707
|
-
/** Capture a screenshot */
|
|
7708
|
-
SCREENSHOT: "browser.screenshot",
|
|
7709
|
-
/** Extract data using CSS selectors */
|
|
7710
|
-
EXTRACT: "browser.extract"
|
|
7711
|
-
};
|
|
7712
|
-
var BrowserDefaults = {
|
|
7713
|
-
/** Navigation timeout in milliseconds */
|
|
7714
|
-
NAVIGATION_TIMEOUT_MS: 3e4,
|
|
7715
|
-
/** Action timeout in milliseconds */
|
|
7716
|
-
ACTION_TIMEOUT_MS: 5e3,
|
|
7717
|
-
/** Maximum nodes to include in accessibility tree output */
|
|
7718
|
-
MAX_SNAPSHOT_NODES: 500,
|
|
7719
|
-
/** Maximum screenshot size in bytes */
|
|
7720
|
-
MAX_SCREENSHOT_BYTES: 5e6
|
|
7721
|
-
};
|
|
7722
|
-
var BrowserToolPack = class {
|
|
7723
|
-
constructor(options = {}) {
|
|
7724
|
-
this.browser = null;
|
|
7725
|
-
this.context = null;
|
|
7726
|
-
this.page = null;
|
|
7727
|
-
this.cdpSession = null;
|
|
7728
|
-
this.ownsBrowser = false;
|
|
7729
|
-
this.ownsContext = false;
|
|
7730
|
-
this.cfg = {
|
|
7731
|
-
allowedDomains: options.allowedDomains ?? [],
|
|
7732
|
-
blockedDomains: options.blockedDomains ?? [],
|
|
7733
|
-
navigationTimeoutMs: options.navigationTimeoutMs ?? BrowserDefaults.NAVIGATION_TIMEOUT_MS,
|
|
7734
|
-
actionTimeoutMs: options.actionTimeoutMs ?? BrowserDefaults.ACTION_TIMEOUT_MS,
|
|
7735
|
-
maxSnapshotNodes: options.maxSnapshotNodes ?? BrowserDefaults.MAX_SNAPSHOT_NODES,
|
|
7736
|
-
headless: options.headless ?? true
|
|
7737
|
-
};
|
|
7738
|
-
if (options.browser) {
|
|
7739
|
-
this.browser = options.browser;
|
|
7740
|
-
this.ownsBrowser = false;
|
|
7741
|
-
}
|
|
7742
|
-
if (options.context) {
|
|
7743
|
-
this.context = options.context;
|
|
7744
|
-
this.ownsContext = false;
|
|
7745
|
-
}
|
|
7746
|
-
}
|
|
7747
|
-
/**
|
|
7748
|
-
* Initialize the browser. Must be called before using any tools.
|
|
7749
|
-
*/
|
|
7750
|
-
async initialize() {
|
|
7751
|
-
if (this.page) {
|
|
7752
|
-
return;
|
|
7753
|
-
}
|
|
7754
|
-
const { chromium } = await import("playwright");
|
|
7755
|
-
if (!this.browser) {
|
|
7756
|
-
this.browser = await chromium.launch({
|
|
7757
|
-
headless: this.cfg.headless
|
|
7758
|
-
});
|
|
7759
|
-
this.ownsBrowser = true;
|
|
7760
|
-
}
|
|
7761
|
-
if (!this.context) {
|
|
7762
|
-
this.context = await this.browser.newContext();
|
|
7763
|
-
this.ownsContext = true;
|
|
7764
|
-
}
|
|
7765
|
-
this.page = await this.context.newPage();
|
|
7766
|
-
}
|
|
7767
|
-
/**
|
|
7768
|
-
* Close the browser and clean up resources.
|
|
7769
|
-
*/
|
|
7770
|
-
async close() {
|
|
7771
|
-
if (this.cdpSession) {
|
|
7772
|
-
await this.cdpSession.detach().catch(() => {
|
|
7773
|
-
});
|
|
7774
|
-
this.cdpSession = null;
|
|
7775
|
-
}
|
|
7776
|
-
if (this.page) {
|
|
7777
|
-
await this.page.close().catch(() => {
|
|
7778
|
-
});
|
|
7779
|
-
this.page = null;
|
|
7780
|
-
}
|
|
7781
|
-
if (this.ownsContext && this.context) {
|
|
7782
|
-
await this.context.close().catch(() => {
|
|
7783
|
-
});
|
|
7784
|
-
this.context = null;
|
|
7785
|
-
}
|
|
7786
|
-
if (this.ownsBrowser && this.browser) {
|
|
7787
|
-
await this.browser.close().catch(() => {
|
|
7788
|
-
});
|
|
7789
|
-
this.browser = null;
|
|
7790
|
-
}
|
|
7791
|
-
}
|
|
7792
|
-
/**
|
|
7793
|
-
* Get tool definitions for use with LLM APIs.
|
|
7794
|
-
*/
|
|
7795
|
-
getToolDefinitions() {
|
|
7796
|
-
return [
|
|
7797
|
-
{
|
|
7798
|
-
type: ToolTypes.Function,
|
|
7799
|
-
function: {
|
|
7800
|
-
name: BrowserToolNames.NAVIGATE,
|
|
7801
|
-
description: "Navigate to a URL and return the page's accessibility tree. The tree shows interactive elements (buttons, links, inputs) with their accessible names.",
|
|
7802
|
-
parameters: {
|
|
7803
|
-
type: "object",
|
|
7804
|
-
properties: {
|
|
7805
|
-
url: {
|
|
7806
|
-
type: "string",
|
|
7807
|
-
description: "The URL to navigate to (must be http/https)"
|
|
7808
|
-
},
|
|
7809
|
-
waitUntil: {
|
|
7810
|
-
type: "string",
|
|
7811
|
-
enum: ["load", "domcontentloaded", "networkidle"],
|
|
7812
|
-
description: "When to consider navigation complete. Default: domcontentloaded"
|
|
7813
|
-
}
|
|
7814
|
-
},
|
|
7815
|
-
required: ["url"]
|
|
7816
|
-
}
|
|
7817
|
-
}
|
|
7818
|
-
},
|
|
7819
|
-
{
|
|
7820
|
-
type: ToolTypes.Function,
|
|
7821
|
-
function: {
|
|
7822
|
-
name: BrowserToolNames.CLICK,
|
|
7823
|
-
description: "Click an element by its accessible name. Returns updated accessibility tree.",
|
|
7824
|
-
parameters: {
|
|
7825
|
-
type: "object",
|
|
7826
|
-
properties: {
|
|
7827
|
-
name: {
|
|
7828
|
-
type: "string",
|
|
7829
|
-
description: "The accessible name of the element (from button text, aria-label, etc.)"
|
|
7830
|
-
},
|
|
7831
|
-
role: {
|
|
7832
|
-
type: "string",
|
|
7833
|
-
enum: [
|
|
7834
|
-
"button",
|
|
7835
|
-
"link",
|
|
7836
|
-
"menuitem",
|
|
7837
|
-
"checkbox",
|
|
7838
|
-
"radio",
|
|
7839
|
-
"tab"
|
|
7840
|
-
],
|
|
7841
|
-
description: "ARIA role to match. If omitted, searches buttons, links, and menuitems."
|
|
7842
|
-
}
|
|
7843
|
-
},
|
|
7844
|
-
required: ["name"]
|
|
7845
|
-
}
|
|
7846
|
-
}
|
|
7847
|
-
},
|
|
7848
|
-
{
|
|
7849
|
-
type: ToolTypes.Function,
|
|
7850
|
-
function: {
|
|
7851
|
-
name: BrowserToolNames.TYPE,
|
|
7852
|
-
description: "Type text into an input field identified by accessible name.",
|
|
7853
|
-
parameters: {
|
|
7854
|
-
type: "object",
|
|
7855
|
-
properties: {
|
|
7856
|
-
name: {
|
|
7857
|
-
type: "string",
|
|
7858
|
-
description: "The accessible name of the input (from label, aria-label, placeholder)"
|
|
7859
|
-
},
|
|
7860
|
-
text: {
|
|
7861
|
-
type: "string",
|
|
7862
|
-
description: "The text to type"
|
|
7863
|
-
},
|
|
7864
|
-
role: {
|
|
7865
|
-
type: "string",
|
|
7866
|
-
enum: ["textbox", "searchbox", "combobox"],
|
|
7867
|
-
description: "ARIA role. Default: textbox"
|
|
7868
|
-
}
|
|
7869
|
-
},
|
|
7870
|
-
required: ["name", "text"]
|
|
7871
|
-
}
|
|
7872
|
-
}
|
|
7873
|
-
},
|
|
7874
|
-
{
|
|
7875
|
-
type: ToolTypes.Function,
|
|
7876
|
-
function: {
|
|
7877
|
-
name: BrowserToolNames.SNAPSHOT,
|
|
7878
|
-
description: "Get the current page's accessibility tree without navigating.",
|
|
7879
|
-
parameters: {
|
|
7880
|
-
type: "object",
|
|
7881
|
-
properties: {}
|
|
7882
|
-
}
|
|
7883
|
-
}
|
|
7884
|
-
},
|
|
7885
|
-
{
|
|
7886
|
-
type: ToolTypes.Function,
|
|
7887
|
-
function: {
|
|
7888
|
-
name: BrowserToolNames.SCROLL,
|
|
7889
|
-
description: "Scroll the page in a given direction.",
|
|
7890
|
-
parameters: {
|
|
7891
|
-
type: "object",
|
|
7892
|
-
properties: {
|
|
7893
|
-
direction: {
|
|
7894
|
-
type: "string",
|
|
7895
|
-
enum: ["up", "down"],
|
|
7896
|
-
description: "Scroll direction"
|
|
7897
|
-
},
|
|
7898
|
-
amount: {
|
|
7899
|
-
type: "string",
|
|
7900
|
-
enum: ["page", "half", "toTop", "toBottom"],
|
|
7901
|
-
description: "How much to scroll. Default: page"
|
|
7902
|
-
}
|
|
7903
|
-
},
|
|
7904
|
-
required: ["direction"]
|
|
7905
|
-
}
|
|
7906
|
-
}
|
|
7907
|
-
},
|
|
7908
|
-
{
|
|
7909
|
-
type: ToolTypes.Function,
|
|
7910
|
-
function: {
|
|
7911
|
-
name: BrowserToolNames.SCREENSHOT,
|
|
7912
|
-
description: "Capture a PNG screenshot of the current page. Use sparingly - prefer accessibility tree for decisions.",
|
|
7913
|
-
parameters: {
|
|
7914
|
-
type: "object",
|
|
7915
|
-
properties: {
|
|
7916
|
-
fullPage: {
|
|
7917
|
-
type: "boolean",
|
|
7918
|
-
description: "Capture full scrollable page. Default: false (viewport only)"
|
|
7919
|
-
}
|
|
7920
|
-
}
|
|
7921
|
-
}
|
|
7922
|
-
}
|
|
7923
|
-
},
|
|
7924
|
-
{
|
|
7925
|
-
type: ToolTypes.Function,
|
|
7926
|
-
function: {
|
|
7927
|
-
name: BrowserToolNames.EXTRACT,
|
|
7928
|
-
description: "Extract structured data from the page using CSS selectors.",
|
|
7929
|
-
parameters: {
|
|
7930
|
-
type: "object",
|
|
7931
|
-
properties: {
|
|
7932
|
-
selector: {
|
|
7933
|
-
type: "string",
|
|
7934
|
-
description: "CSS selector for elements to extract"
|
|
7935
|
-
},
|
|
7936
|
-
attribute: {
|
|
7937
|
-
type: "string",
|
|
7938
|
-
description: "Attribute to extract (textContent, href, src, etc.). Default: textContent"
|
|
7939
|
-
},
|
|
7940
|
-
multiple: {
|
|
7941
|
-
type: "boolean",
|
|
7942
|
-
description: "Return all matches as JSON array. Default: false (first match only)"
|
|
7943
|
-
}
|
|
7944
|
-
},
|
|
7945
|
-
required: ["selector"]
|
|
7946
|
-
}
|
|
7947
|
-
}
|
|
7948
|
-
}
|
|
7949
|
-
];
|
|
7950
|
-
}
|
|
7951
|
-
/**
|
|
7952
|
-
* Register tool handlers into an existing registry.
|
|
7953
|
-
*/
|
|
7954
|
-
registerInto(registry) {
|
|
7955
|
-
registry.register(BrowserToolNames.NAVIGATE, this.navigate.bind(this));
|
|
7956
|
-
registry.register(BrowserToolNames.CLICK, this.click.bind(this));
|
|
7957
|
-
registry.register(BrowserToolNames.TYPE, this.type.bind(this));
|
|
7958
|
-
registry.register(BrowserToolNames.SNAPSHOT, this.snapshot.bind(this));
|
|
7959
|
-
registry.register(BrowserToolNames.SCROLL, this.scroll.bind(this));
|
|
7960
|
-
registry.register(BrowserToolNames.SCREENSHOT, this.screenshot.bind(this));
|
|
7961
|
-
registry.register(BrowserToolNames.EXTRACT, this.extract.bind(this));
|
|
7962
|
-
return registry;
|
|
7963
|
-
}
|
|
7964
|
-
/**
|
|
7965
|
-
* Create a new registry with just this pack's tools.
|
|
7966
|
-
*/
|
|
7967
|
-
toRegistry() {
|
|
7968
|
-
return this.registerInto(new ToolRegistry());
|
|
7969
|
-
}
|
|
7970
|
-
// ========================================================================
|
|
7971
|
-
// Private: Helpers
|
|
7972
|
-
// ========================================================================
|
|
7973
|
-
ensureInitialized() {
|
|
7974
|
-
if (!this.page) {
|
|
7975
|
-
throw new Error(
|
|
7976
|
-
"BrowserToolPack not initialized. Call initialize() first."
|
|
7977
|
-
);
|
|
7978
|
-
}
|
|
7979
|
-
}
|
|
7980
|
-
parseArgs(call, required) {
|
|
7981
|
-
const func = call.function;
|
|
7982
|
-
if (!func) {
|
|
7983
|
-
throw new ToolArgumentError({
|
|
7984
|
-
message: "tool call missing function",
|
|
7985
|
-
toolCallId: call.id,
|
|
7986
|
-
toolName: "",
|
|
7987
|
-
rawArguments: ""
|
|
7988
|
-
});
|
|
7989
|
-
}
|
|
7990
|
-
const rawArgs = func.arguments || "{}";
|
|
7991
|
-
let parsed;
|
|
7992
|
-
try {
|
|
7993
|
-
parsed = JSON.parse(rawArgs);
|
|
7994
|
-
} catch (err) {
|
|
7995
|
-
throw new ToolArgumentError({
|
|
7996
|
-
message: `invalid JSON arguments: ${err.message}`,
|
|
7997
|
-
toolCallId: call.id,
|
|
7998
|
-
toolName: func.name,
|
|
7999
|
-
rawArguments: rawArgs
|
|
8000
|
-
});
|
|
8001
|
-
}
|
|
8002
|
-
if (typeof parsed !== "object" || parsed === null) {
|
|
8003
|
-
throw new ToolArgumentError({
|
|
8004
|
-
message: "arguments must be an object",
|
|
8005
|
-
toolCallId: call.id,
|
|
8006
|
-
toolName: func.name,
|
|
8007
|
-
rawArguments: rawArgs
|
|
8008
|
-
});
|
|
8009
|
-
}
|
|
8010
|
-
const args = parsed;
|
|
8011
|
-
for (const key of required) {
|
|
8012
|
-
const value = args[key];
|
|
8013
|
-
if (value === void 0 || value === null || value === "") {
|
|
8014
|
-
throw new ToolArgumentError({
|
|
8015
|
-
message: `${key} is required`,
|
|
8016
|
-
toolCallId: call.id,
|
|
8017
|
-
toolName: func.name,
|
|
8018
|
-
rawArguments: rawArgs
|
|
8019
|
-
});
|
|
8020
|
-
}
|
|
8021
|
-
}
|
|
8022
|
-
return args;
|
|
8023
|
-
}
|
|
8024
|
-
validateUrl(url, call) {
|
|
8025
|
-
let parsed;
|
|
8026
|
-
try {
|
|
8027
|
-
parsed = new URL(url);
|
|
8028
|
-
} catch {
|
|
8029
|
-
throw new ToolArgumentError({
|
|
8030
|
-
message: `Invalid URL: ${url}`,
|
|
8031
|
-
toolCallId: call.id,
|
|
8032
|
-
toolName: call.function?.name ?? "",
|
|
8033
|
-
rawArguments: call.function?.arguments ?? ""
|
|
8034
|
-
});
|
|
8035
|
-
}
|
|
8036
|
-
if (!["http:", "https:"].includes(parsed.protocol)) {
|
|
8037
|
-
throw new ToolArgumentError({
|
|
8038
|
-
message: `Invalid protocol: ${parsed.protocol}. Only http/https allowed.`,
|
|
8039
|
-
toolCallId: call.id,
|
|
8040
|
-
toolName: call.function?.name ?? "",
|
|
8041
|
-
rawArguments: call.function?.arguments ?? ""
|
|
8042
|
-
});
|
|
8043
|
-
}
|
|
8044
|
-
const domain = parsed.hostname;
|
|
8045
|
-
if (this.cfg.blockedDomains.some((d) => domain.endsWith(d))) {
|
|
8046
|
-
throw new ToolArgumentError({
|
|
8047
|
-
message: `Domain blocked: ${domain}`,
|
|
8048
|
-
toolCallId: call.id,
|
|
8049
|
-
toolName: call.function?.name ?? "",
|
|
8050
|
-
rawArguments: call.function?.arguments ?? ""
|
|
8051
|
-
});
|
|
8052
|
-
}
|
|
8053
|
-
if (this.cfg.allowedDomains.length > 0) {
|
|
8054
|
-
if (!this.cfg.allowedDomains.some((d) => domain.endsWith(d))) {
|
|
8055
|
-
throw new ToolArgumentError({
|
|
8056
|
-
message: `Domain not in allowlist: ${domain}`,
|
|
8057
|
-
toolCallId: call.id,
|
|
8058
|
-
toolName: call.function?.name ?? "",
|
|
8059
|
-
rawArguments: call.function?.arguments ?? ""
|
|
8060
|
-
});
|
|
8061
|
-
}
|
|
8062
|
-
}
|
|
8063
|
-
}
|
|
8064
|
-
/**
|
|
8065
|
-
* Validates the current page URL against allowlist/blocklist.
|
|
8066
|
-
* Called after navigation and before any action to catch redirects
|
|
8067
|
-
* and in-session navigation to blocked domains.
|
|
8068
|
-
*/
|
|
8069
|
-
ensureCurrentUrlAllowed() {
|
|
8070
|
-
if (!this.page) return;
|
|
8071
|
-
const currentUrl = this.page.url();
|
|
8072
|
-
if (currentUrl === "about:blank") return;
|
|
8073
|
-
let parsed;
|
|
8074
|
-
try {
|
|
8075
|
-
parsed = new URL(currentUrl);
|
|
8076
|
-
} catch {
|
|
8077
|
-
throw new Error(`Current page has invalid URL: ${currentUrl}`);
|
|
8078
|
-
}
|
|
8079
|
-
if (!["http:", "https:"].includes(parsed.protocol)) {
|
|
8080
|
-
throw new Error(
|
|
8081
|
-
`Current page protocol not allowed: ${parsed.protocol}. Only http/https allowed.`
|
|
8082
|
-
);
|
|
8083
|
-
}
|
|
8084
|
-
const domain = parsed.hostname;
|
|
8085
|
-
if (this.cfg.blockedDomains.some((d) => domain.endsWith(d))) {
|
|
8086
|
-
throw new Error(`Current page domain is blocked: ${domain}`);
|
|
8087
|
-
}
|
|
8088
|
-
if (this.cfg.allowedDomains.length > 0) {
|
|
8089
|
-
if (!this.cfg.allowedDomains.some((d) => domain.endsWith(d))) {
|
|
8090
|
-
throw new Error(`Current page domain not in allowlist: ${domain}`);
|
|
8091
|
-
}
|
|
8092
|
-
}
|
|
8093
|
-
}
|
|
8094
|
-
async getAccessibilityTree() {
|
|
8095
|
-
this.ensureInitialized();
|
|
8096
|
-
if (!this.cdpSession) {
|
|
8097
|
-
this.cdpSession = await this.page.context().newCDPSession(this.page);
|
|
8098
|
-
await this.cdpSession.send("Accessibility.enable");
|
|
8099
|
-
}
|
|
8100
|
-
const response = await this.cdpSession.send(
|
|
8101
|
-
"Accessibility.getFullAXTree"
|
|
8102
|
-
);
|
|
8103
|
-
return response.nodes;
|
|
8104
|
-
}
|
|
8105
|
-
formatAXTree(nodes) {
|
|
8106
|
-
const lines = [];
|
|
8107
|
-
let count = 0;
|
|
8108
|
-
for (const node of nodes) {
|
|
8109
|
-
if (count >= this.cfg.maxSnapshotNodes) {
|
|
8110
|
-
lines.push(`[truncated at ${this.cfg.maxSnapshotNodes} nodes]`);
|
|
8111
|
-
break;
|
|
8112
|
-
}
|
|
8113
|
-
if (node.ignored) {
|
|
8114
|
-
continue;
|
|
8115
|
-
}
|
|
8116
|
-
const role = node.role?.value || "unknown";
|
|
8117
|
-
const name = node.name?.value || "";
|
|
8118
|
-
if (!name && ["generic", "none", "text"].includes(role)) {
|
|
8119
|
-
continue;
|
|
8120
|
-
}
|
|
8121
|
-
const states = [];
|
|
8122
|
-
if (node.properties) {
|
|
8123
|
-
for (const prop of node.properties) {
|
|
8124
|
-
if (prop.value?.value === true) {
|
|
8125
|
-
const stateName = prop.name;
|
|
8126
|
-
if (["focused", "checked", "disabled", "expanded", "selected"].includes(
|
|
8127
|
-
stateName
|
|
8128
|
-
)) {
|
|
8129
|
-
states.push(stateName);
|
|
8130
|
-
}
|
|
8131
|
-
}
|
|
8132
|
-
}
|
|
8133
|
-
}
|
|
8134
|
-
const stateStr = states.length ? " " + states.join(" ") : "";
|
|
8135
|
-
const nameStr = name ? ` "${name}"` : "";
|
|
8136
|
-
lines.push(`[${role}${nameStr}${stateStr}]`);
|
|
8137
|
-
count++;
|
|
8138
|
-
}
|
|
8139
|
-
return lines.join("\n");
|
|
8140
|
-
}
|
|
8141
|
-
// ========================================================================
|
|
8142
|
-
// Private: Tool Handlers
|
|
8143
|
-
// ========================================================================
|
|
8144
|
-
async navigate(_args, call) {
|
|
8145
|
-
const args = this.parseArgs(call, ["url"]);
|
|
8146
|
-
this.validateUrl(args.url, call);
|
|
8147
|
-
this.ensureInitialized();
|
|
8148
|
-
const waitUntil = args.waitUntil ?? "domcontentloaded";
|
|
8149
|
-
await this.page.goto(args.url, {
|
|
8150
|
-
timeout: this.cfg.navigationTimeoutMs,
|
|
8151
|
-
waitUntil
|
|
8152
|
-
});
|
|
8153
|
-
this.ensureCurrentUrlAllowed();
|
|
8154
|
-
const tree = await this.getAccessibilityTree();
|
|
8155
|
-
return this.formatAXTree(tree);
|
|
8156
|
-
}
|
|
8157
|
-
async click(_args, call) {
|
|
8158
|
-
const args = this.parseArgs(call, ["name"]);
|
|
8159
|
-
this.ensureInitialized();
|
|
8160
|
-
this.ensureCurrentUrlAllowed();
|
|
8161
|
-
let locator;
|
|
8162
|
-
if (args.role) {
|
|
8163
|
-
locator = this.page.getByRole(args.role, {
|
|
8164
|
-
name: args.name
|
|
8165
|
-
});
|
|
8166
|
-
} else {
|
|
8167
|
-
locator = this.page.getByRole("button", { name: args.name }).or(this.page.getByRole("link", { name: args.name })).or(this.page.getByRole("menuitem", { name: args.name }));
|
|
8168
|
-
}
|
|
8169
|
-
await locator.click({ timeout: this.cfg.actionTimeoutMs });
|
|
8170
|
-
const tree = await this.getAccessibilityTree();
|
|
8171
|
-
return this.formatAXTree(tree);
|
|
8172
|
-
}
|
|
8173
|
-
async type(_args, call) {
|
|
8174
|
-
const args = this.parseArgs(call, ["name", "text"]);
|
|
8175
|
-
this.ensureInitialized();
|
|
8176
|
-
this.ensureCurrentUrlAllowed();
|
|
8177
|
-
const role = args.role ?? "textbox";
|
|
8178
|
-
const locator = this.page.getByRole(role, { name: args.name });
|
|
8179
|
-
await locator.fill(args.text, { timeout: this.cfg.actionTimeoutMs });
|
|
8180
|
-
return `Typed "${args.text}" into ${role} "${args.name}"`;
|
|
8181
|
-
}
|
|
8182
|
-
async snapshot(_args, _call) {
|
|
8183
|
-
this.ensureInitialized();
|
|
8184
|
-
this.ensureCurrentUrlAllowed();
|
|
8185
|
-
const tree = await this.getAccessibilityTree();
|
|
8186
|
-
return this.formatAXTree(tree);
|
|
8187
|
-
}
|
|
8188
|
-
async scroll(_args, call) {
|
|
8189
|
-
const args = this.parseArgs(call, ["direction"]);
|
|
8190
|
-
this.ensureInitialized();
|
|
8191
|
-
this.ensureCurrentUrlAllowed();
|
|
8192
|
-
const amount = args.amount ?? "page";
|
|
8193
|
-
if (amount === "toTop") {
|
|
8194
|
-
await this.page.evaluate(() => window.scrollTo(0, 0));
|
|
8195
|
-
} else if (amount === "toBottom") {
|
|
8196
|
-
await this.page.evaluate(
|
|
8197
|
-
() => window.scrollTo(0, document.body.scrollHeight)
|
|
8198
|
-
);
|
|
8199
|
-
} else {
|
|
8200
|
-
const viewport = this.page.viewportSize();
|
|
8201
|
-
const height = viewport?.height ?? 800;
|
|
8202
|
-
const scrollAmount = amount === "half" ? height / 2 : height;
|
|
8203
|
-
const delta = args.direction === "down" ? scrollAmount : -scrollAmount;
|
|
8204
|
-
await this.page.evaluate((d) => window.scrollBy(0, d), delta);
|
|
8205
|
-
}
|
|
8206
|
-
const tree = await this.getAccessibilityTree();
|
|
8207
|
-
return this.formatAXTree(tree);
|
|
8208
|
-
}
|
|
8209
|
-
async screenshot(_args, call) {
|
|
8210
|
-
const args = this.parseArgs(call, []);
|
|
8211
|
-
this.ensureInitialized();
|
|
8212
|
-
this.ensureCurrentUrlAllowed();
|
|
8213
|
-
const buffer = await this.page.screenshot({
|
|
8214
|
-
fullPage: args.fullPage ?? false,
|
|
8215
|
-
type: "png"
|
|
8216
|
-
});
|
|
8217
|
-
if (buffer.length > BrowserDefaults.MAX_SCREENSHOT_BYTES) {
|
|
8218
|
-
throw new Error(
|
|
8219
|
-
`Screenshot size (${buffer.length} bytes) exceeds maximum allowed (${BrowserDefaults.MAX_SCREENSHOT_BYTES} bytes). Try capturing viewport only.`
|
|
8220
|
-
);
|
|
8221
|
-
}
|
|
8222
|
-
const base64 = buffer.toString("base64");
|
|
8223
|
-
return `data:image/png;base64,${base64}`;
|
|
8224
|
-
}
|
|
8225
|
-
async extract(_args, call) {
|
|
8226
|
-
const args = this.parseArgs(call, ["selector"]);
|
|
8227
|
-
this.ensureInitialized();
|
|
8228
|
-
this.ensureCurrentUrlAllowed();
|
|
8229
|
-
const attribute = args.attribute ?? "textContent";
|
|
8230
|
-
const multiple = args.multiple ?? false;
|
|
8231
|
-
if (multiple) {
|
|
8232
|
-
const elements = this.page.locator(args.selector);
|
|
8233
|
-
const count = await elements.count();
|
|
8234
|
-
const results = [];
|
|
8235
|
-
for (let i = 0; i < count; i++) {
|
|
8236
|
-
const el = elements.nth(i);
|
|
8237
|
-
let value;
|
|
8238
|
-
if (attribute === "textContent") {
|
|
8239
|
-
value = await el.textContent();
|
|
8240
|
-
} else {
|
|
8241
|
-
value = await el.getAttribute(attribute);
|
|
8242
|
-
}
|
|
8243
|
-
if (value !== null) {
|
|
8244
|
-
results.push(value.trim());
|
|
8245
|
-
}
|
|
8246
|
-
}
|
|
8247
|
-
return JSON.stringify(results);
|
|
8248
|
-
} else {
|
|
8249
|
-
const el = this.page.locator(args.selector).first();
|
|
8250
|
-
let value;
|
|
8251
|
-
if (attribute === "textContent") {
|
|
8252
|
-
value = await el.textContent();
|
|
8253
|
-
} else {
|
|
8254
|
-
value = await el.getAttribute(attribute);
|
|
8255
|
-
}
|
|
8256
|
-
return value?.trim() ?? "";
|
|
8257
|
-
}
|
|
8258
|
-
}
|
|
8259
|
-
};
|
|
8260
|
-
function createBrowserToolPack(options = {}) {
|
|
8261
|
-
return new BrowserToolPack(options);
|
|
8262
|
-
}
|
|
8263
|
-
function createBrowserTools(options = {}) {
|
|
8264
|
-
const pack = new BrowserToolPack(options);
|
|
8265
|
-
return { pack, registry: pack.toRegistry() };
|
|
8266
|
-
}
|
|
8267
|
-
|
|
8268
7695
|
// src/tools_runner.ts
|
|
8269
7696
|
var ToolRunner = class {
|
|
8270
7697
|
constructor(options) {
|
|
@@ -8750,9 +8177,6 @@ export {
|
|
|
8750
8177
|
AuthClient,
|
|
8751
8178
|
BillingProviders,
|
|
8752
8179
|
BindingTargetError,
|
|
8753
|
-
BrowserDefaults,
|
|
8754
|
-
BrowserToolNames,
|
|
8755
|
-
BrowserToolPack,
|
|
8756
8180
|
Chain,
|
|
8757
8181
|
ChainBuilder,
|
|
8758
8182
|
ConfigError,
|
|
@@ -8845,8 +8269,6 @@ export {
|
|
|
8845
8269
|
createAccessTokenAuth,
|
|
8846
8270
|
createApiKeyAuth,
|
|
8847
8271
|
createAssistantMessage,
|
|
8848
|
-
createBrowserToolPack,
|
|
8849
|
-
createBrowserTools,
|
|
8850
8272
|
createFunctionCall,
|
|
8851
8273
|
createFunctionTool,
|
|
8852
8274
|
createFunctionToolFromSchema,
|