pi-unsloth-webtools 0.1.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/LICENSE +661 -0
- package/README.md +101 -0
- package/ROADMAP.md +77 -0
- package/engines.ts +855 -0
- package/entities.ts +2399 -0
- package/html-to-md.ts +1085 -0
- package/index.ts +86 -0
- package/package.json +64 -0
- package/pdf.ts +717 -0
- package/web-access.ts +375 -0
- package/web-fetch.ts +689 -0
- package/web-search.ts +112 -0
package/index.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { Type } from "typebox";
|
|
3
|
+
import { webSearch } from "./web-search.ts";
|
|
4
|
+
import { fetchPageText } from "./web-fetch.ts";
|
|
5
|
+
|
|
6
|
+
const FETCH_TIMEOUT_MS = 60_000;
|
|
7
|
+
|
|
8
|
+
const WebSearchParams = Type.Object({
|
|
9
|
+
query: Type.Optional(
|
|
10
|
+
Type.String({ description: "The search query" }),
|
|
11
|
+
),
|
|
12
|
+
url: Type.Optional(
|
|
13
|
+
Type.String({
|
|
14
|
+
description:
|
|
15
|
+
"A URL to fetch full page content from (instead of searching). Use this to read a page found in search results.",
|
|
16
|
+
}),
|
|
17
|
+
),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const WebFetchParams = Type.Object({
|
|
21
|
+
url: Type.String({ description: "URL of the page to fetch" }),
|
|
22
|
+
maxChars: Type.Optional(
|
|
23
|
+
Type.Number({
|
|
24
|
+
description: "Truncate the returned content to this many characters (default: no limit)",
|
|
25
|
+
}),
|
|
26
|
+
),
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export default function (pi: ExtensionAPI) {
|
|
30
|
+
pi.registerTool({
|
|
31
|
+
name: "web_search",
|
|
32
|
+
label: "Web Search",
|
|
33
|
+
description:
|
|
34
|
+
"Search the web and fetch page content. Returns snippets for all results. " +
|
|
35
|
+
"Use the url parameter to fetch full page text from a specific URL.",
|
|
36
|
+
promptSnippet: "Search the web and fetch page content",
|
|
37
|
+
promptGuidelines: [
|
|
38
|
+
"Use web_search with the url parameter (e.g. {\"url\": \"<URL>\"}) to read the full text of a page found in search results.",
|
|
39
|
+
],
|
|
40
|
+
parameters: WebSearchParams,
|
|
41
|
+
async execute(_toolCallId, params, signal, _onUpdate, _ctx) {
|
|
42
|
+
if (params.url?.trim()) {
|
|
43
|
+
return {
|
|
44
|
+
content: [
|
|
45
|
+
{
|
|
46
|
+
type: "text",
|
|
47
|
+
text: await fetchPageText(params.url.trim(), {
|
|
48
|
+
timeoutMs: FETCH_TIMEOUT_MS,
|
|
49
|
+
signal: signal ?? undefined,
|
|
50
|
+
}),
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
details: {},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const text = await webSearch(params.query, { signal: signal ?? undefined });
|
|
57
|
+
return { content: [{ type: "text", text }], details: {} };
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
pi.registerTool({
|
|
62
|
+
name: "web_fetch",
|
|
63
|
+
label: "Web Fetch",
|
|
64
|
+
description:
|
|
65
|
+
"Fetch a URL and return readable text content. HTML responses are converted to Markdown " +
|
|
66
|
+
"with a main-content heuristic (article/main scoping, hidden-element and boilerplate " +
|
|
67
|
+
"stripping); non-HTML text responses are returned as-is. GitHub repo root pages are " +
|
|
68
|
+
"rewritten to the README API so the model reads the README instead of the repo page's UI " +
|
|
69
|
+
"chrome. Blocks private/loopback/link-local targets (SSRF protection) and caps the " +
|
|
70
|
+
"download size.",
|
|
71
|
+
promptSnippet: "Fetch a web page and return readable text content",
|
|
72
|
+
parameters: WebFetchParams,
|
|
73
|
+
async execute(_toolCallId, params, signal, _onUpdate, _ctx) {
|
|
74
|
+
const maxChars =
|
|
75
|
+
typeof params.maxChars === "number" && params.maxChars > 0
|
|
76
|
+
? params.maxChars
|
|
77
|
+
: undefined;
|
|
78
|
+
const text = await fetchPageText(params.url, {
|
|
79
|
+
timeoutMs: FETCH_TIMEOUT_MS,
|
|
80
|
+
signal: signal ?? undefined,
|
|
81
|
+
maxChars,
|
|
82
|
+
});
|
|
83
|
+
return { content: [{ type: "text", text }], details: {} };
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "pi-unsloth-webtools",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Pi extension: web_search and web_fetch tools ported from the Unsloth Studio codebase (DuckDuckGo search, SSRF-safe direct fetching, HTML-to-Markdown extraction)",
|
|
6
|
+
"main": "index.ts",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/YuGiMob/pi-unsloth-webtools.git"
|
|
10
|
+
},
|
|
11
|
+
"author": "YuGiMob",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"pi-package",
|
|
14
|
+
"pi",
|
|
15
|
+
"coding-agent",
|
|
16
|
+
"extension",
|
|
17
|
+
"web-search",
|
|
18
|
+
"web-fetch",
|
|
19
|
+
"unsloth",
|
|
20
|
+
"duckduckgo",
|
|
21
|
+
"ssrf"
|
|
22
|
+
],
|
|
23
|
+
"license": "AGPL-3.0",
|
|
24
|
+
"files": [
|
|
25
|
+
"index.ts",
|
|
26
|
+
"web-search.ts",
|
|
27
|
+
"web-fetch.ts",
|
|
28
|
+
"web-access.ts",
|
|
29
|
+
"html-to-md.ts",
|
|
30
|
+
"engines.ts",
|
|
31
|
+
"entities.ts",
|
|
32
|
+
"pdf.ts",
|
|
33
|
+
"README.md",
|
|
34
|
+
"ROADMAP.md",
|
|
35
|
+
"LICENSE"
|
|
36
|
+
],
|
|
37
|
+
"pi": {
|
|
38
|
+
"extensions": [
|
|
39
|
+
"./index.ts"
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"@earendil-works/pi-coding-agent": "*",
|
|
44
|
+
"typebox": "*"
|
|
45
|
+
},
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=22.19.0"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"test": "vitest run",
|
|
51
|
+
"typecheck": "tsc --noEmit",
|
|
52
|
+
"prepublishOnly": "npm run typecheck"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@earendil-works/pi-coding-agent": "^0.84.0",
|
|
56
|
+
"@types/node": "^24.0.0",
|
|
57
|
+
"typebox": "^1.3.7",
|
|
58
|
+
"typescript": "~5.9.3",
|
|
59
|
+
"vitest": "^4.1.9"
|
|
60
|
+
},
|
|
61
|
+
"dependencies": {
|
|
62
|
+
"mupdf": "^1.28.0"
|
|
63
|
+
}
|
|
64
|
+
}
|