@mrclrchtr/supi-web 1.5.0 → 1.7.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/README.md +51 -49
- package/node_modules/@mrclrchtr/supi-core/package.json +6 -2
- package/node_modules/@mrclrchtr/supi-core/src/api.ts +12 -1
- package/node_modules/@mrclrchtr/supi-core/src/config/config.ts +1 -1
- package/node_modules/@mrclrchtr/supi-core/src/index.ts +12 -1
- package/node_modules/@mrclrchtr/supi-core/src/tool-framework.ts +116 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -20,73 +20,75 @@ After editing the source, run `/reload`.
|
|
|
20
20
|
|
|
21
21
|
After install, pi gets three tools:
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
| Tool | Purpose |
|
|
24
|
+
|------|---------|
|
|
25
|
+
| `web_fetch_md` | Fetch a web page and convert it to clean Markdown for LLM ingestion |
|
|
26
|
+
| `web_docs_search` | Search Context7 for library IDs and metadata before fetching docs |
|
|
27
|
+
| `web_docs_fetch` | Fetch up-to-date documentation for a known Context7 library |
|
|
26
28
|
|
|
27
|
-
##
|
|
29
|
+
## `web_fetch_md`
|
|
28
30
|
|
|
29
|
-
|
|
31
|
+
Fetches a public URL and returns clean Markdown.
|
|
30
32
|
|
|
31
|
-
|
|
33
|
+
### Parameters
|
|
32
34
|
|
|
33
|
-
|
|
35
|
+
| Parameter | Type | Required | Default | Description |
|
|
36
|
+
|-----------|------|----------|---------|-------------|
|
|
37
|
+
| `url` | string | ✓ | — | `http://` or `https://` URL to fetch |
|
|
38
|
+
| `output_mode` | `"auto"` \| `"inline"` \| `"file"` | — | `"auto"` | How to return the result |
|
|
39
|
+
| `abs_links` | boolean | — | `true` | Absolutize relative links and images |
|
|
40
|
+
| `timeout_ms` | number | — | `30000` | Fetch timeout in milliseconds |
|
|
34
41
|
|
|
35
|
-
|
|
36
|
-
- defaults to `output_mode: auto`
|
|
37
|
-
- returns Markdown inline when the result is at most **15,000 characters**
|
|
38
|
-
- otherwise writes the Markdown to a temporary `.md` file and returns the file path
|
|
39
|
-
- absolutizes links and image URLs by default
|
|
40
|
-
- wraps plain-text responses as fenced code blocks instead of pretending they are prose
|
|
42
|
+
### Output modes
|
|
41
43
|
|
|
42
|
-
|
|
44
|
+
- **`auto`** — returns Markdown inline if ≤15,000 characters; otherwise writes to a temporary file and returns the path
|
|
45
|
+
- **`inline`** — always returns Markdown inline
|
|
46
|
+
- **`file`** — always writes to a temporary file and returns the path
|
|
43
47
|
|
|
44
|
-
|
|
45
|
-
2. content sniffing
|
|
46
|
-
3. sibling `.md` / `.markdown` probing
|
|
47
|
-
4. HTML fetch followed by Readability + Turndown conversion
|
|
48
|
+
### Behavior
|
|
48
49
|
|
|
49
|
-
|
|
50
|
+
- Only accepts real `http://` or `https://` URLs
|
|
51
|
+
- Access-controlled pages (login, paywall) should be skipped — ask the user for an allowed source instead
|
|
52
|
+
- Plain-text responses are wrapped in fenced code blocks
|
|
53
|
+
- Links and images are absolutized by default; set `abs_links: false` to keep them relative
|
|
50
54
|
|
|
51
|
-
|
|
55
|
+
## `web_docs_search`
|
|
52
56
|
|
|
53
|
-
|
|
57
|
+
Searches Context7 for library IDs before fetching documentation.
|
|
54
58
|
|
|
55
|
-
|
|
56
|
-
- name
|
|
57
|
-
- description
|
|
58
|
-
- trust score
|
|
59
|
-
- benchmark score
|
|
60
|
-
- snippet count
|
|
61
|
-
- versions
|
|
59
|
+
### Parameters
|
|
62
60
|
|
|
63
|
-
|
|
61
|
+
| Parameter | Type | Required | Description |
|
|
62
|
+
|-----------|------|----------|-------------|
|
|
63
|
+
| `library_name` | string | ✓ | Library name to search for (e.g. `"react"`, `"next.js"`) |
|
|
64
|
+
| `query` | string | ✓ | What you're trying to do — used for relevance ranking |
|
|
64
65
|
|
|
65
|
-
|
|
66
|
+
Results return as a Markdown table with library ID, name, description, trust score, benchmark score, snippet count, and available versions.
|
|
66
67
|
|
|
67
|
-
|
|
68
|
-
- `query` is required
|
|
69
|
-
- `raw: true` returns JSON-serialized snippet objects instead of plain text Markdown
|
|
68
|
+
## `web_docs_fetch`
|
|
70
69
|
|
|
71
|
-
|
|
70
|
+
Retrieves documentation context for a known Context7 library.
|
|
72
71
|
|
|
73
|
-
|
|
72
|
+
### Parameters
|
|
74
73
|
|
|
75
|
-
|
|
74
|
+
| Parameter | Type | Required | Default | Description |
|
|
75
|
+
|-----------|------|----------|---------|-------------|
|
|
76
|
+
| `library_id` | string | ✓ | — | Context7 library ID (e.g. `/facebook/react`, `/vercel/next.js`) |
|
|
77
|
+
| `query` | string | ✓ | — | Specific question about the library |
|
|
78
|
+
| `raw` | boolean | — | `false` | When `true`, returns JSON-serialized snippet objects instead of Markdown |
|
|
76
79
|
|
|
77
|
-
|
|
80
|
+
Default mode returns pre-formatted Markdown. Set `raw: true` when you need structured JSON for programmatic use.
|
|
78
81
|
|
|
79
|
-
|
|
80
|
-
- `@mrclrchtr/supi-web/extension` — extension entrypoint that registers all three tools
|
|
82
|
+
## Typical workflow
|
|
81
83
|
|
|
82
|
-
|
|
84
|
+
1. **`web_docs_search`** — find the right library ID
|
|
85
|
+
2. **Pick a `library_id`** from the results
|
|
86
|
+
3. **`web_docs_fetch`** — retrieve focused, version-aware docs
|
|
83
87
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
- `src/tool/web-docs-search-guidance.ts` — model-facing prompt surfaces for `web_docs_search`
|
|
92
|
-
- `src/tool/web-docs-fetch-guidance.ts` — model-facing prompt surfaces for `web_docs_fetch`
|
|
88
|
+
Skip step 1 if you already know the exact Context7 `library_id`.
|
|
89
|
+
|
|
90
|
+
## Context7 API key
|
|
91
|
+
|
|
92
|
+
`web_docs_search` and `web_docs_fetch` use [Context7](https://context7.com/) through `@upstash/context7-sdk`.
|
|
93
|
+
|
|
94
|
+
If `CONTEXT7_API_KEY` is set in your environment, the SDK uses it automatically for higher rate limits. Without a key, the tools still work with lower defaults.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrclrchtr/supi-core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "SuPi core — shared infrastructure for SuPi extensions (XML context tags, config system)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
],
|
|
21
21
|
"peerDependencies": {
|
|
22
22
|
"@earendil-works/pi-coding-agent": "*",
|
|
23
|
-
"@earendil-works/pi-tui": "*"
|
|
23
|
+
"@earendil-works/pi-tui": "*",
|
|
24
|
+
"typebox": "*"
|
|
24
25
|
},
|
|
25
26
|
"peerDependenciesMeta": {
|
|
26
27
|
"@earendil-works/pi-coding-agent": {
|
|
@@ -28,6 +29,9 @@
|
|
|
28
29
|
},
|
|
29
30
|
"@earendil-works/pi-tui": {
|
|
30
31
|
"optional": true
|
|
32
|
+
},
|
|
33
|
+
"typebox": {
|
|
34
|
+
"optional": true
|
|
31
35
|
}
|
|
32
36
|
},
|
|
33
37
|
"main": "src/api.ts",
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
// supi-core — shared infrastructure for SuPi extensions.
|
|
2
2
|
// Provides XML context tag wrapping, unified config system, context-message utilities,
|
|
3
|
-
//
|
|
3
|
+
// settings registry for supi-wide TUI settings, and a shared tool-spec/registration framework.
|
|
4
4
|
|
|
5
5
|
export type { SupiConfigLocation, SupiConfigOptions } from "./config/config.ts";
|
|
6
6
|
export {
|
|
7
7
|
loadSupiConfig,
|
|
8
8
|
loadSupiConfigForScope,
|
|
9
|
+
readJsonFile,
|
|
9
10
|
removeSupiConfigKey,
|
|
10
11
|
writeSupiConfig,
|
|
11
12
|
} from "./config/config.ts";
|
|
@@ -83,3 +84,13 @@ export {
|
|
|
83
84
|
signalWaiting,
|
|
84
85
|
WAITING_SYMBOL,
|
|
85
86
|
} from "./terminal.ts";
|
|
87
|
+
export type { SuiPiToolPromptSurface, SuiPiToolSpec, ToolExecuteFn } from "./tool-framework.ts";
|
|
88
|
+
export {
|
|
89
|
+
CharacterParam,
|
|
90
|
+
derivePromptSurface,
|
|
91
|
+
FileParam,
|
|
92
|
+
LineParam,
|
|
93
|
+
MaxResultsParam,
|
|
94
|
+
registerSuiPiTools,
|
|
95
|
+
SymbolParam,
|
|
96
|
+
} from "./tool-framework.ts";
|
|
@@ -20,7 +20,7 @@ function getProjectConfigPath(cwd: string): string {
|
|
|
20
20
|
return path.join(cwd, PROJECT_CONFIG_DIR, CONFIG_FILE);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
function readJsonFile(filePath: string): Record<string, unknown> | null {
|
|
23
|
+
export function readJsonFile(filePath: string): Record<string, unknown> | null {
|
|
24
24
|
let content: string;
|
|
25
25
|
try {
|
|
26
26
|
content = fs.readFileSync(filePath, "utf-8");
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
// supi-core — shared infrastructure for SuPi extensions.
|
|
2
2
|
// Provides XML context tag wrapping, unified config system, context-message utilities,
|
|
3
|
-
//
|
|
3
|
+
// settings registry for supi-wide TUI settings, and a shared tool-spec/registration framework.
|
|
4
4
|
|
|
5
5
|
export type { SupiConfigLocation, SupiConfigOptions } from "./config/config.ts";
|
|
6
6
|
export {
|
|
7
7
|
loadSupiConfig,
|
|
8
8
|
loadSupiConfigForScope,
|
|
9
|
+
readJsonFile,
|
|
9
10
|
removeSupiConfigKey,
|
|
10
11
|
writeSupiConfig,
|
|
11
12
|
} from "./config/config.ts";
|
|
@@ -83,3 +84,13 @@ export {
|
|
|
83
84
|
signalWaiting,
|
|
84
85
|
WAITING_SYMBOL,
|
|
85
86
|
} from "./terminal.ts";
|
|
87
|
+
export type { SuiPiToolPromptSurface, SuiPiToolSpec, ToolExecuteFn } from "./tool-framework.ts";
|
|
88
|
+
export {
|
|
89
|
+
CharacterParam,
|
|
90
|
+
derivePromptSurface,
|
|
91
|
+
FileParam,
|
|
92
|
+
LineParam,
|
|
93
|
+
MaxResultsParam,
|
|
94
|
+
registerSuiPiTools,
|
|
95
|
+
SymbolParam,
|
|
96
|
+
} from "./tool-framework.ts";
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// Shared tool framework for SuPi extensions.
|
|
2
|
+
//
|
|
3
|
+
// Provides a standard ToolSpec→PromptSurface→registerTool pipeline so
|
|
4
|
+
// individual packages do not duplicate spec interfaces, guidance derivation,
|
|
5
|
+
// registration loops, or common TypeBox parameter schemas.
|
|
6
|
+
|
|
7
|
+
import type {
|
|
8
|
+
AgentToolResult,
|
|
9
|
+
AgentToolUpdateCallback,
|
|
10
|
+
ExtensionAPI,
|
|
11
|
+
ExtensionContext,
|
|
12
|
+
} from "@earendil-works/pi-coding-agent";
|
|
13
|
+
import { type TSchema, Type } from "typebox";
|
|
14
|
+
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// Types
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
|
|
19
|
+
/** Minimum contract for a SuPi tool definition. */
|
|
20
|
+
export interface SuiPiToolSpec {
|
|
21
|
+
name: string;
|
|
22
|
+
label: string;
|
|
23
|
+
description: string;
|
|
24
|
+
promptSnippet: string;
|
|
25
|
+
promptGuidelines: string[];
|
|
26
|
+
parameters: TSchema;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Derived prompt surface — what pi flattens into the system prompt. */
|
|
30
|
+
export interface SuiPiToolPromptSurface {
|
|
31
|
+
description: string;
|
|
32
|
+
promptSnippet: string;
|
|
33
|
+
promptGuidelines: string[];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
// Guidance derivation
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Static derivation: copies spec fields into a prompt surface.
|
|
42
|
+
*
|
|
43
|
+
* Packages that need dynamic guidance (e.g. server-coverage injection) should
|
|
44
|
+
* build their own surfaces, optionally starting from the output of this helper.
|
|
45
|
+
*/
|
|
46
|
+
export function derivePromptSurface(spec: SuiPiToolSpec): SuiPiToolPromptSurface {
|
|
47
|
+
return {
|
|
48
|
+
description: spec.description,
|
|
49
|
+
promptSnippet: spec.promptSnippet,
|
|
50
|
+
promptGuidelines: [...spec.promptGuidelines],
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
// Registration
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
|
|
58
|
+
// biome-ignore lint/complexity/useMaxParams: matches pi ToolDefinition.execute signature
|
|
59
|
+
export type ToolExecuteFn = (
|
|
60
|
+
toolCallId: string,
|
|
61
|
+
params: unknown,
|
|
62
|
+
signal: AbortSignal | undefined,
|
|
63
|
+
onUpdate: AgentToolUpdateCallback<Record<string, unknown>> | undefined,
|
|
64
|
+
ctx: ExtensionContext,
|
|
65
|
+
) => Promise<AgentToolResult<Record<string, unknown>>>;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Register a set of tools from specs + pre-derived surfaces.
|
|
69
|
+
*
|
|
70
|
+
* `createExecute` receives the spec and returns a pi-compatible execute
|
|
71
|
+
* function. This keeps execute-logic package-local while the framework owns
|
|
72
|
+
* the declarative surface and registration boilerplate.
|
|
73
|
+
*/
|
|
74
|
+
export function registerSuiPiTools(
|
|
75
|
+
pi: ExtensionAPI,
|
|
76
|
+
specs: readonly SuiPiToolSpec[],
|
|
77
|
+
surfaces: Record<string, SuiPiToolPromptSurface>,
|
|
78
|
+
createExecute: (spec: SuiPiToolSpec) => ToolExecuteFn,
|
|
79
|
+
): void {
|
|
80
|
+
for (const spec of specs) {
|
|
81
|
+
const surface = surfaces[spec.name];
|
|
82
|
+
pi.registerTool({
|
|
83
|
+
name: spec.name,
|
|
84
|
+
label: spec.label,
|
|
85
|
+
description: surface?.description ?? spec.description,
|
|
86
|
+
promptSnippet: surface?.promptSnippet ?? spec.promptSnippet,
|
|
87
|
+
promptGuidelines: surface?.promptGuidelines ?? [...spec.promptGuidelines],
|
|
88
|
+
parameters: spec.parameters,
|
|
89
|
+
execute: createExecute(spec),
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
// Shared parameter builders
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
|
|
98
|
+
/** File path (relative or absolute). */
|
|
99
|
+
export const FileParam = Type.String({ description: "File path (relative or absolute)" });
|
|
100
|
+
|
|
101
|
+
/** 1-based line number. */
|
|
102
|
+
export const LineParam = Type.Number({ description: "1-based line number", minimum: 1 });
|
|
103
|
+
|
|
104
|
+
/** 1-based character column (UTF-16). */
|
|
105
|
+
export const CharacterParam = Type.Number({
|
|
106
|
+
description: "1-based column number (UTF-16)",
|
|
107
|
+
minimum: 1,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
/** Symbol name for discovery-based resolution. */
|
|
111
|
+
export const SymbolParam = Type.String({
|
|
112
|
+
description: "Symbol name for discovery-based resolution",
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
/** Maximum results to return. */
|
|
116
|
+
export const MaxResultsParam = Type.Number({ description: "Maximum results to return" });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrclrchtr/supi-web",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "SuPi Web extension — fetch web pages as clean Markdown (web_fetch_md) and library docs via Context7 (web_docs_search, web_docs_fetch)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"@mozilla/readability": "^0.6.0",
|
|
26
26
|
"turndown": "^7.2.0",
|
|
27
27
|
"turndown-plugin-gfm": "^1.0.2",
|
|
28
|
-
"@mrclrchtr/supi-core": "1.
|
|
28
|
+
"@mrclrchtr/supi-core": "1.7.0"
|
|
29
29
|
},
|
|
30
30
|
"bundledDependencies": [
|
|
31
31
|
"@mrclrchtr/supi-core"
|