@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 CHANGED
@@ -20,73 +20,75 @@ After editing the source, run `/reload`.
20
20
 
21
21
  After install, pi gets three tools:
22
22
 
23
- - `web_fetch_md` fetch a web page and convert it to Markdown
24
- - `web_docs_search` — search Context7 for a library ID
25
- - `web_docs_fetch` fetch up-to-date documentation for a specific Context7 library
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
- ## Choose the right tool
29
+ ## `web_fetch_md`
28
30
 
29
- ### `web_fetch_md`
31
+ Fetches a public URL and returns clean Markdown.
30
32
 
31
- Use this for general web pages.
33
+ ### Parameters
32
34
 
33
- Important behavior:
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
- - accepts only real `http://` or `https://` URLs
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
- The fetch pipeline tries several strategies in order:
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
- 1. Markdown-aware content negotiation
45
- 2. content sniffing
46
- 3. sibling `.md` / `.markdown` probing
47
- 4. HTML fetch followed by Readability + Turndown conversion
48
+ ### Behavior
48
49
 
49
- ### `web_docs_search`
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
- Use this when you need a Context7 library ID first.
55
+ ## `web_docs_search`
52
56
 
53
- It returns a Markdown table of matching libraries with fields such as:
57
+ Searches Context7 for library IDs before fetching documentation.
54
58
 
55
- - ID
56
- - name
57
- - description
58
- - trust score
59
- - benchmark score
60
- - snippet count
61
- - versions
59
+ ### Parameters
62
60
 
63
- ### `web_docs_fetch`
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
- Use this when you already know the Context7 library ID and want current docs or snippets for a specific question.
66
+ Results return as a Markdown table with library ID, name, description, trust score, benchmark score, snippet count, and available versions.
66
67
 
67
- - `library_id` is required
68
- - `query` is required
69
- - `raw: true` returns JSON-serialized snippet objects instead of plain text Markdown
68
+ ## `web_docs_fetch`
70
69
 
71
- ## Context7 notes
70
+ Retrieves documentation context for a known Context7 library.
72
71
 
73
- `web_docs_search` and `web_docs_fetch` use Context7 through `@upstash/context7-sdk`.
72
+ ### Parameters
74
73
 
75
- If `CONTEXT7_API_KEY` is set, the SDK will use it automatically.
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
- ## Package surfaces
80
+ Default mode returns pre-formatted Markdown. Set `raw: true` when you need structured JSON for programmatic use.
78
81
 
79
- - `@mrclrchtr/supi-web/api` — conversion helpers, fetch helpers, and extension exports
80
- - `@mrclrchtr/supi-web/extension` — extension entrypoint that registers all three tools
82
+ ## Typical workflow
81
83
 
82
- ## Source
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
- - `src/web.ts` `web_fetch_md`
85
- - `src/docs.ts` — `web_docs_search` and `web_docs_fetch`
86
- - `src/fetch.ts` HTTP fetching and negotiation
87
- - `src/convert.ts` — HTML-to-Markdown conversion
88
- - `src/context7-client.ts` Context7 client wrapper
89
- - `src/temp-file.ts` — temp-file output helper
90
- - `src/tool/web-fetch-md-guidance.ts` model-facing prompt surfaces for `web_fetch_md`
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.5.0",
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
- // and settings registry for supi-wide TUI settings.
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
- // and settings registry for supi-wide TUI settings.
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.5.0",
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.5.0"
28
+ "@mrclrchtr/supi-core": "1.7.0"
29
29
  },
30
30
  "bundledDependencies": [
31
31
  "@mrclrchtr/supi-core"