@ssk_dev/pi-web-access-lean 0.22.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 +21 -0
- package/README.md +80 -0
- package/README.zh-CN.md +80 -0
- package/index.ts +133 -0
- package/package.json +61 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 kunkun9527
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# @ssk_dev/pi-web-access-lean
|
|
2
|
+
|
|
3
|
+
> **Lean Pi web access plugin, same functionality — 141 initialization tokens, 94% fewer than the original.**
|
|
4
|
+
> [See my full setup for Pi](https://github.com/kunkun9527/my-lean-pi-setup)
|
|
5
|
+
|
|
6
|
+
[简体中文](README.zh-CN.md)
|
|
7
|
+
|
|
8
|
+
A token-lean Pi facade over [`pi-web-access`](https://github.com/nicobailon/pi-web-access). It keeps the complete upstream web runtime while presenting one compact model-facing schema.
|
|
9
|
+
|
|
10
|
+
## What it keeps
|
|
11
|
+
|
|
12
|
+
- Web search and result continuation.
|
|
13
|
+
- Source and claim checking.
|
|
14
|
+
- URL fetching and upstream provider behavior.
|
|
15
|
+
- Complete advanced operation schemas, disclosed locally through `help` only when needed.
|
|
16
|
+
|
|
17
|
+
## Why it is lean
|
|
18
|
+
|
|
19
|
+
Instead of exposing four detailed provider-facing tools on every request, the wrapper routes them through one `web_access` tool. Simple calls use a short string; advanced parameters remain available as JSON without keeping every operation schema in the prompt.
|
|
20
|
+
|
|
21
|
+
## Install
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pi install npm:@ssk_dev/pi-web-access-lean
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Do not load another `pi-web-access` wrapper at the same time, or web tools may be registered twice.
|
|
28
|
+
|
|
29
|
+
## Use
|
|
30
|
+
|
|
31
|
+
The model sees one tool:
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
web_access
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
| `op` | Purpose | `input` |
|
|
38
|
+
| --- | --- | --- |
|
|
39
|
+
| `search` | Search the web | Query string |
|
|
40
|
+
| `check` | Check a claim or source | Claim string |
|
|
41
|
+
| `fetch` | Fetch a URL | URL string |
|
|
42
|
+
| `get` | Continue a stored result | Response ID |
|
|
43
|
+
| `help` | Show full parameters | Operation name |
|
|
44
|
+
|
|
45
|
+
Simple example:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{ "op": "search", "input": "Pi coding agent extensions" }
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
For batch or advanced parameters, pass a JSON object encoded as the `input` string. Use `help` only when the complete upstream schema is required.
|
|
52
|
+
|
|
53
|
+
## Measured initialization footprint
|
|
54
|
+
|
|
55
|
+
With only this extension enabled, its recurring model-facing initialization contribution is:
|
|
56
|
+
|
|
57
|
+
| Model-facing tool | Lean | Upstream `pi-web-access@0.22.0` |
|
|
58
|
+
| --- | ---: | ---: |
|
|
59
|
+
| Facade / search | `web_access`: 141 | `web_search`: 994 |
|
|
60
|
+
| Source checking | Included in facade | `source_check`: 413 |
|
|
61
|
+
| Content fetching | Included in facade | `fetch_content`: 576 |
|
|
62
|
+
| Result continuation | Included in facade | `get_search_content`: 393 |
|
|
63
|
+
| **Total** | **141** | **2,376** |
|
|
64
|
+
|
|
65
|
+
That is **2,235 fewer tokens (94.1%)** than the pinned upstream extension. The measurement used Pi 0.84.4 and `pi-context-view@0.4.3` in a fresh isolated session, excluding Pi built-in tools, skills, context files, messages, and unrelated extensions. Context View estimates text as `ceil(characters / 4)`, so these are reproducible context-footprint estimates rather than exact GPT tokenizer counts. Runtime-only UI and slash commands are not included because they are not sent to the model.
|
|
66
|
+
|
|
67
|
+
## Versions
|
|
68
|
+
|
|
69
|
+
The upstream runtime is pinned to `pi-web-access@0.22.0`.
|
|
70
|
+
|
|
71
|
+
## Development
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
npm ci
|
|
75
|
+
npm run check
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## License and upstream
|
|
79
|
+
|
|
80
|
+
MIT. This project wraps the MIT-licensed [`pi-web-access`](https://github.com/nicobailon/pi-web-access).
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# @ssk_dev/pi-web-access-lean
|
|
2
|
+
|
|
3
|
+
> **Lean Pi web access 插件,功能相同:141 个初始化 tokens,较原插件减少 94%。**
|
|
4
|
+
> **整套配置:** [查看 Pi Lean Setup](https://github.com/kunkun9527/my-lean-pi-setup)
|
|
5
|
+
|
|
6
|
+
[English](README.md)
|
|
7
|
+
|
|
8
|
+
[`pi-web-access`](https://github.com/nicobailon/pi-web-access) 的 token 精简版 Pi facade。它保留完整的上游联网运行时,同时只向模型提供一个紧凑 schema。
|
|
9
|
+
|
|
10
|
+
## 保留的能力
|
|
11
|
+
|
|
12
|
+
- 网页搜索和结果续取。
|
|
13
|
+
- 来源与事实声明核验。
|
|
14
|
+
- URL 抓取和上游供应商行为。
|
|
15
|
+
- 完整高级操作 schema,仅在需要时通过 `help` 在本地披露。
|
|
16
|
+
|
|
17
|
+
## 为什么更精简
|
|
18
|
+
|
|
19
|
+
包装层不再让每次请求都携带四个详细的模型可见工具,而是通过一个 `web_access` 工具路由这些能力。简单调用只使用短字符串;高级参数仍可通过 JSON 使用,无需长期把每个操作 schema 放入提示词。
|
|
20
|
+
|
|
21
|
+
## 安装
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pi install npm:@ssk_dev/pi-web-access-lean
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
不要同时加载另一个 `pi-web-access` 包装层,否则联网工具可能被重复注册。
|
|
28
|
+
|
|
29
|
+
## 使用
|
|
30
|
+
|
|
31
|
+
模型只看到一个工具:
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
web_access
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
| `op` | 作用 | `input` |
|
|
38
|
+
| --- | --- | --- |
|
|
39
|
+
| `search` | 搜索网页 | 查询字符串 |
|
|
40
|
+
| `check` | 核验声明或来源 | 声明字符串 |
|
|
41
|
+
| `fetch` | 抓取 URL | URL 字符串 |
|
|
42
|
+
| `get` | 续取已保存结果 | Response ID |
|
|
43
|
+
| `help` | 显示完整参数 | 操作名称 |
|
|
44
|
+
|
|
45
|
+
简单示例:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{ "op": "search", "input": "Pi coding agent extensions" }
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
批量或高级参数应把 JSON 对象编码为 `input` 字符串。仅在需要完整上游 schema 时使用 `help`。
|
|
52
|
+
|
|
53
|
+
## 实测初始化上下文占用
|
|
54
|
+
|
|
55
|
+
仅启用本扩展时,它持续贡献给模型的初始化上下文为:
|
|
56
|
+
|
|
57
|
+
| 模型可见工具 | Lean | 上游 `pi-web-access@0.22.0` |
|
|
58
|
+
| --- | ---: | ---: |
|
|
59
|
+
| Facade / 搜索 | `web_access`:141 | `web_search`:994 |
|
|
60
|
+
| 来源核验 | 已包含在 facade 中 | `source_check`:413 |
|
|
61
|
+
| 内容抓取 | 已包含在 facade 中 | `fetch_content`:576 |
|
|
62
|
+
| 结果续取 | 已包含在 facade 中 | `get_search_content`:393 |
|
|
63
|
+
| **合计** | **141** | **2,376** |
|
|
64
|
+
|
|
65
|
+
相比固定版本的上游扩展,减少 **2,235 tokens(94.1%)**。测量使用 Pi 0.84.4 和 `pi-context-view@0.4.3`,在全新隔离会话中只启用目标扩展,并排除 Pi 内置工具、skills、context files、消息及无关扩展。Context View 按 `ceil(字符数 / 4)` 估算,因此这些是可复现的上下文占用估值,不是 GPT tokenizer 的精确计数。未计入不会发送给模型的纯运行时 UI 和 slash commands。
|
|
66
|
+
|
|
67
|
+
## 版本
|
|
68
|
+
|
|
69
|
+
上游运行时固定为 `pi-web-access@0.22.0`。
|
|
70
|
+
|
|
71
|
+
## 开发
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
npm ci
|
|
75
|
+
npm run check
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## 许可证与上游
|
|
79
|
+
|
|
80
|
+
MIT。本项目包装了采用 MIT 许可证的 [`pi-web-access`](https://github.com/nicobailon/pi-web-access)。
|
package/index.ts
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// pi-web-access-lean: one provider-facing facade over the full pi-web-access runtime.
|
|
2
|
+
// Detailed operation schemas stay local and are disclosed only through `help`.
|
|
3
|
+
import type {
|
|
4
|
+
ExtensionAPI,
|
|
5
|
+
ToolDefinition,
|
|
6
|
+
} from "@earendil-works/pi-coding-agent";
|
|
7
|
+
import webAccess from "pi-web-access/index.ts";
|
|
8
|
+
import { Type } from "typebox";
|
|
9
|
+
|
|
10
|
+
type CapturedTool = ToolDefinition<any, any, any>;
|
|
11
|
+
type UpstreamExtension = (pi: ExtensionAPI) => void;
|
|
12
|
+
|
|
13
|
+
const ROUTES = {
|
|
14
|
+
search: { toolName: "web_search", inputName: "query" },
|
|
15
|
+
check: { toolName: "source_check", inputName: "claim" },
|
|
16
|
+
fetch: { toolName: "fetch_content", inputName: "url" },
|
|
17
|
+
get: { toolName: "get_search_content", inputName: "responseId" },
|
|
18
|
+
} as const;
|
|
19
|
+
|
|
20
|
+
type Operation = keyof typeof ROUTES;
|
|
21
|
+
type FacadeOperation = Operation | "help";
|
|
22
|
+
|
|
23
|
+
const FACADE_PARAMETERS = Type.Object({
|
|
24
|
+
op: Type.Unsafe<FacadeOperation>({
|
|
25
|
+
type: "string",
|
|
26
|
+
enum: ["search", "check", "fetch", "get", "help"],
|
|
27
|
+
}),
|
|
28
|
+
input: Type.Optional(Type.String({
|
|
29
|
+
description: "Main query, claim, URL, or responseId; use a JSON object string for advanced parameters",
|
|
30
|
+
})),
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
function capturePi(
|
|
34
|
+
pi: ExtensionAPI,
|
|
35
|
+
tools: Map<string, CapturedTool>,
|
|
36
|
+
): ExtensionAPI {
|
|
37
|
+
return new Proxy(pi, {
|
|
38
|
+
get(target, property, receiver) {
|
|
39
|
+
if (property === "registerTool") {
|
|
40
|
+
return (tool: CapturedTool) => tools.set(tool.name, tool);
|
|
41
|
+
}
|
|
42
|
+
const value = Reflect.get(target, property, receiver);
|
|
43
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function parseInput(input: string, inputName: string): Record<string, unknown> {
|
|
49
|
+
if (!input.trimStart().startsWith("{")) return { [inputName]: input };
|
|
50
|
+
|
|
51
|
+
let parsed: unknown;
|
|
52
|
+
try {
|
|
53
|
+
parsed = JSON.parse(input);
|
|
54
|
+
} catch (error) {
|
|
55
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
56
|
+
throw new Error(`web_access input is invalid JSON: ${reason}`);
|
|
57
|
+
}
|
|
58
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
59
|
+
throw new Error("web_access advanced input must be a JSON object");
|
|
60
|
+
}
|
|
61
|
+
return parsed as Record<string, unknown>;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function helpResult(
|
|
65
|
+
operation: string,
|
|
66
|
+
tools: Map<string, CapturedTool>,
|
|
67
|
+
) {
|
|
68
|
+
const route = ROUTES[operation as Operation];
|
|
69
|
+
if (!route) {
|
|
70
|
+
return {
|
|
71
|
+
content: [{
|
|
72
|
+
type: "text" as const,
|
|
73
|
+
text: "Operations: search(query), check(claim), fetch(URL), get(responseId). For advanced parameters, call help with input set to one operation name.",
|
|
74
|
+
}],
|
|
75
|
+
details: { operation: "help" },
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const tool = tools.get(route.toolName);
|
|
80
|
+
if (!tool) throw new Error(`web_access could not find upstream tool: ${route.toolName}`);
|
|
81
|
+
const text = [
|
|
82
|
+
`${operation} routes to ${route.toolName}`,
|
|
83
|
+
tool.description,
|
|
84
|
+
"Advanced input must be a JSON object string matching this schema:",
|
|
85
|
+
JSON.stringify(tool.parameters, null, 2),
|
|
86
|
+
].filter(Boolean).join("\n\n");
|
|
87
|
+
return {
|
|
88
|
+
content: [{ type: "text" as const, text }],
|
|
89
|
+
details: { operation, toolName: route.toolName },
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function createWebAccessFacade(
|
|
94
|
+
upstream: UpstreamExtension = webAccess,
|
|
95
|
+
): (pi: ExtensionAPI) => void {
|
|
96
|
+
return (pi: ExtensionAPI): void => {
|
|
97
|
+
const tools = new Map<string, CapturedTool>();
|
|
98
|
+
upstream(capturePi(pi, tools));
|
|
99
|
+
const facadeTool: ToolDefinition<typeof FACADE_PARAMETERS, unknown, unknown> = {
|
|
100
|
+
name: "web_access",
|
|
101
|
+
label: "Web Access",
|
|
102
|
+
description: "Search, verify, fetch, or continue web content through one local router. Use help for advanced parameters.",
|
|
103
|
+
promptGuidelines: [
|
|
104
|
+
"web_access input is the query, claim, URL, or responseId for search, check, fetch, or get. Pass a JSON object string for batch or advanced parameters; use help only when fields are unclear.",
|
|
105
|
+
],
|
|
106
|
+
parameters: FACADE_PARAMETERS,
|
|
107
|
+
async execute(callId, params, signal, onUpdate, ctx) {
|
|
108
|
+
if (params.op === "help") {
|
|
109
|
+
return helpResult((params.input ?? "").trim(), tools);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const route = ROUTES[params.op];
|
|
113
|
+
if (!route) {
|
|
114
|
+
throw new Error(`web_access operation is not implemented: ${params.op}`);
|
|
115
|
+
}
|
|
116
|
+
const tool = tools.get(route.toolName);
|
|
117
|
+
if (!tool) {
|
|
118
|
+
throw new Error(`web_access could not find upstream tool: ${route.toolName}`);
|
|
119
|
+
}
|
|
120
|
+
return tool.execute(
|
|
121
|
+
callId,
|
|
122
|
+
parseInput(params.input ?? "", route.inputName),
|
|
123
|
+
signal,
|
|
124
|
+
onUpdate,
|
|
125
|
+
ctx,
|
|
126
|
+
);
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
pi.registerTool(facadeTool);
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export default createWebAccessFacade();
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ssk_dev/pi-web-access-lean",
|
|
3
|
+
"version": "0.22.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Lean Pi web access plugin, same functionality — 141 initialization tokens, 94% fewer than the original.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public"
|
|
9
|
+
},
|
|
10
|
+
"author": "kunkun9527",
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/kunkun9527/pi-web-access-lean.git"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://github.com/kunkun9527/pi-web-access-lean#readme",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/kunkun9527/pi-web-access-lean/issues"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"pi-package",
|
|
21
|
+
"pi-extension",
|
|
22
|
+
"web-search",
|
|
23
|
+
"web-access",
|
|
24
|
+
"token-efficient"
|
|
25
|
+
],
|
|
26
|
+
"files": [
|
|
27
|
+
"index.ts",
|
|
28
|
+
"README.md",
|
|
29
|
+
"README.zh-CN.md",
|
|
30
|
+
"LICENSE"
|
|
31
|
+
],
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=22.19.0"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"test": "node --test tests/*.test.mjs",
|
|
37
|
+
"typecheck": "tsc -p tsconfig.json",
|
|
38
|
+
"check": "npm run typecheck && npm test"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"pi-web-access": "0.22.0",
|
|
42
|
+
"typebox": "1.3.7"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"@earendil-works/pi-ai": ">=0.84.1 <1.0.0",
|
|
46
|
+
"@earendil-works/pi-coding-agent": ">=0.84.1 <1.0.0",
|
|
47
|
+
"@earendil-works/pi-tui": ">=0.84.1 <1.0.0"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@earendil-works/pi-ai": "0.84.3",
|
|
51
|
+
"@earendil-works/pi-coding-agent": "0.84.3",
|
|
52
|
+
"@earendil-works/pi-tui": "0.84.3",
|
|
53
|
+
"jiti": "2.7.0",
|
|
54
|
+
"typescript": "5.9.3"
|
|
55
|
+
},
|
|
56
|
+
"pi": {
|
|
57
|
+
"extensions": [
|
|
58
|
+
"./index.ts"
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
}
|