@mrclrchtr/supi-web 1.3.0 → 1.4.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 +53 -66
- package/node_modules/@mrclrchtr/supi-core/README.md +52 -41
- package/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-core/src/api.ts +13 -13
- package/node_modules/@mrclrchtr/supi-core/src/{config-settings.ts → config/config-settings.ts} +2 -2
- package/node_modules/@mrclrchtr/supi-core/src/{context-provider-registry.ts → context/context-provider-registry.ts} +1 -1
- package/node_modules/@mrclrchtr/supi-core/src/extension.ts +1 -1
- package/node_modules/@mrclrchtr/supi-core/src/index.ts +13 -13
- package/node_modules/@mrclrchtr/supi-core/src/{settings-registry.ts → settings/settings-registry.ts} +1 -1
- package/package.json +4 -3
- package/src/docs.ts +16 -30
- package/src/tool/web-docs-fetch-guidance.ts +14 -0
- package/src/tool/web-docs-search-guidance.ts +12 -0
- package/src/tool/web-fetch-md-guidance.ts +44 -0
- package/src/web.ts +7 -41
- /package/node_modules/@mrclrchtr/supi-core/src/{config.ts → config/config.ts} +0 -0
- /package/node_modules/@mrclrchtr/supi-core/src/{context-messages.ts → context/context-messages.ts} +0 -0
- /package/node_modules/@mrclrchtr/supi-core/src/{context-tag.ts → context/context-tag.ts} +0 -0
- /package/node_modules/@mrclrchtr/supi-core/src/{settings-command.ts → settings/settings-command.ts} +0 -0
- /package/node_modules/@mrclrchtr/supi-core/src/{settings-ui.ts → settings/settings-ui.ts} +0 -0
package/README.md
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
# @mrclrchtr/supi-web
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Adds web-page fetching and library-documentation lookup tools to the [pi coding agent](https://github.com/earendil-works/pi).
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
|
-
Included in `@mrclrchtr/supi`, or install standalone:
|
|
8
|
-
|
|
9
7
|
```bash
|
|
10
8
|
pi install npm:@mrclrchtr/supi-web
|
|
11
9
|
```
|
|
@@ -16,90 +14,79 @@ For local development:
|
|
|
16
14
|
pi install ./packages/supi-web
|
|
17
15
|
```
|
|
18
16
|
|
|
19
|
-
After editing the source, run `/reload
|
|
20
|
-
|
|
21
|
-
## Package surfaces
|
|
22
|
-
|
|
23
|
-
- `@mrclrchtr/supi-web/api` — programmatic exports (conversion helpers, fetch utilities, tool factories)
|
|
24
|
-
- `@mrclrchtr/supi-web/extension` — aggregated pi extension entrypoint that registers all three tools
|
|
25
|
-
|
|
26
|
-
`pi.extensions` still points at the real file path `./src/extension.ts` inside the package. The `/api` and `/extension` paths are consumer-facing package exports, not manifest aliases.
|
|
17
|
+
After editing the source, run `/reload`.
|
|
27
18
|
|
|
28
|
-
## What
|
|
19
|
+
## What you get
|
|
29
20
|
|
|
30
|
-
|
|
21
|
+
After install, pi gets three tools:
|
|
31
22
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
| `web_docs_search` | Search Context7 for libraries by name |
|
|
36
|
-
| `web_docs_fetch` | Retrieve up-to-date documentation for a specific library via Context7 |
|
|
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
|
|
37
26
|
|
|
38
|
-
##
|
|
27
|
+
## Choose the right tool
|
|
39
28
|
|
|
40
|
-
###
|
|
29
|
+
### `web_fetch_md`
|
|
41
30
|
|
|
42
|
-
|
|
43
|
-
|-----------|------|---------|-------------|
|
|
44
|
-
| `url` | `string` | **required** | `http://` or `https://` URL to fetch |
|
|
45
|
-
| `output_mode` | `"auto" \| "inline" \| "file"` | `"auto"` | `auto` returns inline if ≤15,000 chars, else writes to temp file |
|
|
46
|
-
| `abs_links` | `boolean` | `true` | Absolutize relative links and image sources |
|
|
47
|
-
| `timeout_ms` | `number` | `30000` | Fetch timeout in milliseconds |
|
|
31
|
+
Use this for general web pages.
|
|
48
32
|
|
|
49
|
-
|
|
33
|
+
Important behavior:
|
|
50
34
|
|
|
51
|
-
|
|
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
|
|
52
41
|
|
|
53
|
-
|
|
54
|
-
2. **Sniffing** — range GET of first 8KB to detect Markdown/plain text vs HTML
|
|
55
|
-
3. **Sibling probing** — tries `.md` / `.markdown` variants (e.g. `page.md` for `page.html`)
|
|
56
|
-
4. **HTML conversion** — full GET → JSDOM + Readability + Turndown → clean Markdown
|
|
42
|
+
The fetch pipeline tries several strategies in order:
|
|
57
43
|
|
|
58
|
-
|
|
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
|
|
59
48
|
|
|
60
|
-
|
|
49
|
+
### `web_docs_search`
|
|
61
50
|
|
|
62
|
-
|
|
51
|
+
Use this when you need a Context7 library ID first.
|
|
63
52
|
|
|
64
|
-
|
|
65
|
-
|-----------|------|---------|-------------|
|
|
66
|
-
| `library_name` | `string` | **required** | Library name to search for (e.g. `"react"`, `"next.js"`, `"fastapi"`) |
|
|
67
|
-
| `query` | `string` | **required** | What the agent is trying to do — used for relevance ranking |
|
|
53
|
+
It returns a Markdown table of matching libraries with fields such as:
|
|
68
54
|
|
|
69
|
-
|
|
55
|
+
- ID
|
|
56
|
+
- name
|
|
57
|
+
- description
|
|
58
|
+
- trust score
|
|
59
|
+
- benchmark score
|
|
60
|
+
- snippet count
|
|
61
|
+
- versions
|
|
70
62
|
|
|
71
|
-
|
|
63
|
+
### `web_docs_fetch`
|
|
72
64
|
|
|
73
|
-
|
|
65
|
+
Use this when you already know the Context7 library ID and want current docs or snippets for a specific question.
|
|
74
66
|
|
|
75
|
-
|
|
67
|
+
- `library_id` is required
|
|
68
|
+
- `query` is required
|
|
69
|
+
- `raw: true` returns JSON-serialized snippet objects instead of plain text Markdown
|
|
76
70
|
|
|
77
|
-
|
|
71
|
+
## Context7 notes
|
|
78
72
|
|
|
79
|
-
|
|
80
|
-
|-----------|------|---------|-------------|
|
|
81
|
-
| `library_id` | `string` | **required** | Context7 library ID (e.g. `/facebook/react`, `/vercel/next.js/v15.1.8`) |
|
|
82
|
-
| `query` | `string` | **required** | Specific question about the library |
|
|
83
|
-
| `raw` | `boolean` | `false` | When `true`, returns JSON-serialized snippet objects instead of plain text Markdown |
|
|
73
|
+
`web_docs_search` and `web_docs_fetch` use Context7 through `@upstash/context7-sdk`.
|
|
84
74
|
|
|
85
|
-
|
|
75
|
+
If `CONTEXT7_API_KEY` is set, the SDK will use it automatically.
|
|
86
76
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
### Source files
|
|
77
|
+
## Package surfaces
|
|
90
78
|
|
|
91
|
-
-
|
|
92
|
-
-
|
|
93
|
-
- `src/web.ts` — `web_fetch_md` tool registration
|
|
94
|
-
- `src/docs.ts` — `web_docs_search` + `web_docs_fetch` tool registration
|
|
95
|
-
- `src/context7-client.ts` — thin wrapper around `@upstash/context7-sdk`
|
|
96
|
-
- `src/fetch.ts` — HTTP fetch logic
|
|
97
|
-
- `src/convert.ts` — HTML to Markdown conversion
|
|
79
|
+
- `@mrclrchtr/supi-web/api` — conversion helpers, fetch helpers, and extension exports
|
|
80
|
+
- `@mrclrchtr/supi-web/extension` — extension entrypoint that registers all three tools
|
|
98
81
|
|
|
99
|
-
##
|
|
82
|
+
## Source
|
|
100
83
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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`
|
|
@@ -1,65 +1,78 @@
|
|
|
1
1
|
# @mrclrchtr/supi-core
|
|
2
2
|
|
|
3
|
-
Shared infrastructure for SuPi
|
|
3
|
+
Shared infrastructure for SuPi extensions.
|
|
4
|
+
|
|
5
|
+
This package is mainly for extension authors. It gives you a common config system, settings plumbing, context helpers, registries, and a small extension surface that registers `/supi-settings`.
|
|
4
6
|
|
|
5
7
|
## Install
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
### As a dependency for another extension
|
|
8
10
|
|
|
9
11
|
```bash
|
|
10
12
|
pnpm add @mrclrchtr/supi-core
|
|
11
13
|
```
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
`@mrclrchtr/supi-core` now has two explicit surfaces:
|
|
15
|
+
### As a pi package
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
`pi.extensions` still points at the real file path `./src/extension.ts` inside the package. The `/api` and `/extension` paths are consumer-facing package exports, not manifest aliases.
|
|
17
|
+
```bash
|
|
18
|
+
pi install npm:@mrclrchtr/supi-core
|
|
19
|
+
```
|
|
21
20
|
|
|
22
|
-
|
|
21
|
+
Installing it as a pi package adds the minimal `/supi-settings` extension surface.
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
## Package surfaces
|
|
25
24
|
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
- the shared settings registry, overlay UI, and `registerSettingsCommand()` helper
|
|
29
|
-
- XML `<extension-context>` wrapping plus context-message utilities
|
|
30
|
-
- context-provider and debug-event registries reused across SuPi packages
|
|
31
|
-
- project root and path helpers reused by packages such as `supi-lsp`
|
|
25
|
+
- `@mrclrchtr/supi-core/api` — reusable helpers for other packages and extensions
|
|
26
|
+
- `@mrclrchtr/supi-core/extension` — minimal pi extension that registers `/supi-settings`
|
|
32
27
|
|
|
33
|
-
##
|
|
28
|
+
## What you get from the API
|
|
34
29
|
|
|
35
|
-
Config
|
|
30
|
+
### Config helpers
|
|
36
31
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
32
|
+
- `loadSupiConfig()` — merged config with resolution order `defaults <- global <- project`
|
|
33
|
+
- `loadSupiConfigForScope()` — load one scope at a time for settings UIs
|
|
34
|
+
- `writeSupiConfig()` — persist values
|
|
35
|
+
- `removeSupiConfigKey()` — remove a key or override
|
|
40
36
|
|
|
41
37
|
Config file locations:
|
|
42
38
|
|
|
43
39
|
- global: `~/.pi/agent/supi/config.json`
|
|
44
40
|
- project: `.pi/supi/config.json`
|
|
45
41
|
|
|
46
|
-
|
|
42
|
+
### Settings helpers
|
|
43
|
+
|
|
44
|
+
- `registerSettings()` — register an arbitrary settings section
|
|
45
|
+
- `registerConfigSettings()` — register a config-backed settings section with scoped persistence helpers
|
|
46
|
+
- `registerSettingsCommand()` — register `/supi-settings`
|
|
47
|
+
- `openSettingsOverlay()` — open the shared settings UI directly
|
|
48
|
+
- `createInputSubmenu()` — helper for simple text-entry submenus
|
|
49
|
+
|
|
50
|
+
The built-in settings UI supports:
|
|
47
51
|
|
|
48
|
-
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
- `removeSupiConfigKey()`
|
|
52
|
-
- `registerConfigSettings()`
|
|
52
|
+
- project/global scope toggle
|
|
53
|
+
- grouped extension sections
|
|
54
|
+
- searchable setting lists
|
|
53
55
|
|
|
54
|
-
|
|
56
|
+
### Context helpers
|
|
55
57
|
|
|
56
|
-
- `wrapExtensionContext()`
|
|
58
|
+
- `wrapExtensionContext()` — wrap injected text in SuPi's `<extension-context>` tag
|
|
57
59
|
- `findLastUserMessageIndex()`
|
|
58
60
|
- `getContextToken()`
|
|
61
|
+
- `getPromptContent()`
|
|
59
62
|
- `pruneAndReorderContextMessages()`
|
|
60
|
-
- `
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
- `restorePromptContent()`
|
|
64
|
+
|
|
65
|
+
### Shared registries
|
|
66
|
+
|
|
67
|
+
- context-provider registry for `/supi-context`
|
|
68
|
+
- debug-event registry for producers that want shared debug capture
|
|
69
|
+
- settings registry used by `/supi-settings`
|
|
70
|
+
|
|
71
|
+
### Project and session helpers
|
|
72
|
+
|
|
73
|
+
- project-root detection and directory walking helpers such as `findProjectRoot()` and `walkProject()`
|
|
74
|
+
- active-branch session helper: `getActiveBranchEntries()`
|
|
75
|
+
- terminal helpers such as `formatTitle()`, `signalWaiting()`, and `signalDone()`
|
|
63
76
|
|
|
64
77
|
## Example
|
|
65
78
|
|
|
@@ -80,17 +93,15 @@ registerConfigSettings({
|
|
|
80
93
|
});
|
|
81
94
|
|
|
82
95
|
const message = wrapExtensionContext("my-extension", "hello", {
|
|
83
|
-
turn: 1,
|
|
84
96
|
file: "CLAUDE.md",
|
|
97
|
+
turn: 1,
|
|
85
98
|
});
|
|
86
99
|
```
|
|
87
100
|
|
|
88
|
-
## Requirements
|
|
89
|
-
|
|
90
|
-
- `@earendil-works/pi-coding-agent`
|
|
91
|
-
- `@earendil-works/pi-tui`
|
|
92
|
-
|
|
93
101
|
## Source
|
|
94
102
|
|
|
95
|
-
-
|
|
96
|
-
-
|
|
103
|
+
- `src/api.ts` — exported library surface
|
|
104
|
+
- `src/extension.ts` — minimal `/supi-settings` entrypoint
|
|
105
|
+
- `src/config.ts` — shared config loading and writing
|
|
106
|
+
- `src/config-settings.ts` — config-backed settings registration helper
|
|
107
|
+
- `src/settings-ui.ts` — shared settings overlay
|
|
@@ -2,30 +2,30 @@
|
|
|
2
2
|
// Provides XML context tag wrapping, unified config system, context-message utilities,
|
|
3
3
|
// and settings registry for supi-wide TUI settings.
|
|
4
4
|
|
|
5
|
-
export type { SupiConfigLocation, SupiConfigOptions } from "./config.ts";
|
|
5
|
+
export type { SupiConfigLocation, SupiConfigOptions } from "./config/config.ts";
|
|
6
6
|
export {
|
|
7
7
|
loadSupiConfig,
|
|
8
8
|
loadSupiConfigForScope,
|
|
9
9
|
removeSupiConfigKey,
|
|
10
10
|
writeSupiConfig,
|
|
11
|
-
} from "./config.ts";
|
|
12
|
-
export type { ConfigSettingsHelpers, ConfigSettingsOptions } from "./config-settings.ts";
|
|
13
|
-
export { registerConfigSettings } from "./config-settings.ts";
|
|
14
|
-
export type { ContextMessageLike } from "./context-messages.ts";
|
|
11
|
+
} from "./config/config.ts";
|
|
12
|
+
export type { ConfigSettingsHelpers, ConfigSettingsOptions } from "./config/config-settings.ts";
|
|
13
|
+
export { registerConfigSettings } from "./config/config-settings.ts";
|
|
14
|
+
export type { ContextMessageLike } from "./context/context-messages.ts";
|
|
15
15
|
export {
|
|
16
16
|
findLastUserMessageIndex,
|
|
17
17
|
getContextToken,
|
|
18
18
|
getPromptContent,
|
|
19
19
|
pruneAndReorderContextMessages,
|
|
20
20
|
restorePromptContent,
|
|
21
|
-
} from "./context-messages.ts";
|
|
22
|
-
export type { ContextProvider } from "./context-provider-registry.ts";
|
|
21
|
+
} from "./context/context-messages.ts";
|
|
22
|
+
export type { ContextProvider } from "./context/context-provider-registry.ts";
|
|
23
23
|
export {
|
|
24
24
|
clearRegisteredContextProviders,
|
|
25
25
|
getRegisteredContextProviders,
|
|
26
26
|
registerContextProvider,
|
|
27
|
-
} from "./context-provider-registry.ts";
|
|
28
|
-
export { wrapExtensionContext } from "./context-tag.ts";
|
|
27
|
+
} from "./context/context-provider-registry.ts";
|
|
28
|
+
export { wrapExtensionContext } from "./context/context-tag.ts";
|
|
29
29
|
export type {
|
|
30
30
|
DebugAgentAccess,
|
|
31
31
|
DebugEvent,
|
|
@@ -64,14 +64,14 @@ export {
|
|
|
64
64
|
walkProject,
|
|
65
65
|
} from "./project-roots.ts";
|
|
66
66
|
export { getActiveBranchEntries } from "./session-utils.ts";
|
|
67
|
-
export { registerSettingsCommand } from "./settings-command.ts";
|
|
68
|
-
export type { SettingsScope, SettingsSection } from "./settings-registry.ts";
|
|
67
|
+
export { registerSettingsCommand } from "./settings/settings-command.ts";
|
|
68
|
+
export type { SettingsScope, SettingsSection } from "./settings/settings-registry.ts";
|
|
69
69
|
export {
|
|
70
70
|
clearRegisteredSettings,
|
|
71
71
|
getRegisteredSettings,
|
|
72
72
|
registerSettings,
|
|
73
|
-
} from "./settings-registry.ts";
|
|
74
|
-
export { createInputSubmenu, openSettingsOverlay } from "./settings-ui.ts";
|
|
73
|
+
} from "./settings/settings-registry.ts";
|
|
74
|
+
export { createInputSubmenu, openSettingsOverlay } from "./settings/settings-ui.ts";
|
|
75
75
|
export type { TitleTarget } from "./terminal.ts";
|
|
76
76
|
export {
|
|
77
77
|
DONE_SYMBOL,
|
package/node_modules/@mrclrchtr/supi-core/src/{config-settings.ts → config/config-settings.ts}
RENAMED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
// Wraps registerSettings() and centralizes selected-scope loading + scoped persistence.
|
|
3
3
|
|
|
4
4
|
import type { SettingItem } from "@earendil-works/pi-tui";
|
|
5
|
+
import type { SettingsScope } from "../settings/settings-registry.ts";
|
|
6
|
+
import { registerSettings } from "../settings/settings-registry.ts";
|
|
5
7
|
import { loadSupiConfigForScope, removeSupiConfigKey, writeSupiConfig } from "./config.ts";
|
|
6
|
-
import type { SettingsScope } from "./settings-registry.ts";
|
|
7
|
-
import { registerSettings } from "./settings-registry.ts";
|
|
8
8
|
|
|
9
9
|
export interface ConfigSettingsHelpers {
|
|
10
10
|
/** Write a key to the selected scope's config section. */
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Extensions declare context data providers via `registerContextProvider()` during their
|
|
4
4
|
// factory function. The `/supi-context` command reads them via `getRegisteredContextProviders()`.
|
|
5
5
|
|
|
6
|
-
import { createRegistry } from "
|
|
6
|
+
import { createRegistry } from "../registry-utils.ts";
|
|
7
7
|
|
|
8
8
|
export interface ContextProvider {
|
|
9
9
|
/** Unique identifier — e.g. "rtk" */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { registerSettingsCommand as default } from "./settings-command.ts";
|
|
1
|
+
export { registerSettingsCommand as default } from "./settings/settings-command.ts";
|
|
@@ -2,30 +2,30 @@
|
|
|
2
2
|
// Provides XML context tag wrapping, unified config system, context-message utilities,
|
|
3
3
|
// and settings registry for supi-wide TUI settings.
|
|
4
4
|
|
|
5
|
-
export type { SupiConfigLocation, SupiConfigOptions } from "./config.ts";
|
|
5
|
+
export type { SupiConfigLocation, SupiConfigOptions } from "./config/config.ts";
|
|
6
6
|
export {
|
|
7
7
|
loadSupiConfig,
|
|
8
8
|
loadSupiConfigForScope,
|
|
9
9
|
removeSupiConfigKey,
|
|
10
10
|
writeSupiConfig,
|
|
11
|
-
} from "./config.ts";
|
|
12
|
-
export type { ConfigSettingsHelpers, ConfigSettingsOptions } from "./config-settings.ts";
|
|
13
|
-
export { registerConfigSettings } from "./config-settings.ts";
|
|
14
|
-
export type { ContextMessageLike } from "./context-messages.ts";
|
|
11
|
+
} from "./config/config.ts";
|
|
12
|
+
export type { ConfigSettingsHelpers, ConfigSettingsOptions } from "./config/config-settings.ts";
|
|
13
|
+
export { registerConfigSettings } from "./config/config-settings.ts";
|
|
14
|
+
export type { ContextMessageLike } from "./context/context-messages.ts";
|
|
15
15
|
export {
|
|
16
16
|
findLastUserMessageIndex,
|
|
17
17
|
getContextToken,
|
|
18
18
|
getPromptContent,
|
|
19
19
|
pruneAndReorderContextMessages,
|
|
20
20
|
restorePromptContent,
|
|
21
|
-
} from "./context-messages.ts";
|
|
22
|
-
export type { ContextProvider } from "./context-provider-registry.ts";
|
|
21
|
+
} from "./context/context-messages.ts";
|
|
22
|
+
export type { ContextProvider } from "./context/context-provider-registry.ts";
|
|
23
23
|
export {
|
|
24
24
|
clearRegisteredContextProviders,
|
|
25
25
|
getRegisteredContextProviders,
|
|
26
26
|
registerContextProvider,
|
|
27
|
-
} from "./context-provider-registry.ts";
|
|
28
|
-
export { wrapExtensionContext } from "./context-tag.ts";
|
|
27
|
+
} from "./context/context-provider-registry.ts";
|
|
28
|
+
export { wrapExtensionContext } from "./context/context-tag.ts";
|
|
29
29
|
export type {
|
|
30
30
|
DebugAgentAccess,
|
|
31
31
|
DebugEvent,
|
|
@@ -64,14 +64,14 @@ export {
|
|
|
64
64
|
walkProject,
|
|
65
65
|
} from "./project-roots.ts";
|
|
66
66
|
export { getActiveBranchEntries } from "./session-utils.ts";
|
|
67
|
-
export { registerSettingsCommand } from "./settings-command.ts";
|
|
68
|
-
export type { SettingsScope, SettingsSection } from "./settings-registry.ts";
|
|
67
|
+
export { registerSettingsCommand } from "./settings/settings-command.ts";
|
|
68
|
+
export type { SettingsScope, SettingsSection } from "./settings/settings-registry.ts";
|
|
69
69
|
export {
|
|
70
70
|
clearRegisteredSettings,
|
|
71
71
|
getRegisteredSettings,
|
|
72
72
|
registerSettings,
|
|
73
|
-
} from "./settings-registry.ts";
|
|
74
|
-
export { createInputSubmenu, openSettingsOverlay } from "./settings-ui.ts";
|
|
73
|
+
} from "./settings/settings-registry.ts";
|
|
74
|
+
export { createInputSubmenu, openSettingsOverlay } from "./settings/settings-ui.ts";
|
|
75
75
|
export type { TitleTarget } from "./terminal.ts";
|
|
76
76
|
export {
|
|
77
77
|
DONE_SYMBOL,
|
package/node_modules/@mrclrchtr/supi-core/src/{settings-registry.ts → settings/settings-registry.ts}
RENAMED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// factory function. The generic settings UI reads them via `getRegisteredSettings()`.
|
|
5
5
|
|
|
6
6
|
import type { SettingItem } from "@earendil-works/pi-tui";
|
|
7
|
-
import { createRegistry } from "
|
|
7
|
+
import { createRegistry } from "../registry-utils.ts";
|
|
8
8
|
|
|
9
9
|
export type SettingsScope = "project" | "global";
|
|
10
10
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrclrchtr/supi-web",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.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.4.0"
|
|
29
29
|
},
|
|
30
30
|
"bundledDependencies": [
|
|
31
31
|
"@mrclrchtr/supi-core"
|
|
@@ -44,7 +44,8 @@
|
|
|
44
44
|
},
|
|
45
45
|
"pi": {
|
|
46
46
|
"extensions": [
|
|
47
|
-
"./src/extension.ts"
|
|
47
|
+
"./src/extension.ts",
|
|
48
|
+
"node_modules/@mrclrchtr/supi-core/src/extension.ts"
|
|
48
49
|
]
|
|
49
50
|
},
|
|
50
51
|
"main": "src/api.ts",
|
package/src/docs.ts
CHANGED
|
@@ -8,43 +8,29 @@
|
|
|
8
8
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
9
9
|
import { Type } from "typebox";
|
|
10
10
|
import { Context7Error, getContext, searchLibrary } from "./context7-client.ts";
|
|
11
|
+
import {
|
|
12
|
+
promptGuidelines as fetchPromptGuidelines,
|
|
13
|
+
promptSnippet as fetchPromptSnippet,
|
|
14
|
+
toolDescription as fetchToolDescription,
|
|
15
|
+
} from "./tool/web-docs-fetch-guidance.ts";
|
|
16
|
+
import {
|
|
17
|
+
promptGuidelines as searchPromptGuidelines,
|
|
18
|
+
promptSnippet as searchPromptSnippet,
|
|
19
|
+
toolDescription as searchToolDescription,
|
|
20
|
+
} from "./tool/web-docs-search-guidance.ts";
|
|
11
21
|
|
|
12
22
|
const SEARCH_TOOL_NAME = "web_docs_search";
|
|
13
23
|
const SEARCH_TOOL_LABEL = "Web Docs Search";
|
|
14
24
|
const FETCH_TOOL_NAME = "web_docs_fetch";
|
|
15
25
|
const FETCH_TOOL_LABEL = "Web Docs Fetch";
|
|
16
26
|
|
|
17
|
-
const SEARCH_TOOL_DESCRIPTION = `Search for libraries via Context7. Returns a Markdown table of matching libraries with metadata (ID, name, description, trust score, benchmark score, snippet count, versions). Use the library ID from results with web_docs_fetch to retrieve documentation.`;
|
|
18
|
-
|
|
19
|
-
const FETCH_TOOL_DESCRIPTION = `Retrieve documentation context for a specific library via Context7. Returns up-to-date code snippets and documentation prose as Markdown, tailored to the query. Use web_docs_search first to find the library ID. Set raw=true to get JSON-serialized snippet objects instead of plain text. Requires a Context7 library ID (e.g. /facebook/react, /vercel/next.js).`;
|
|
20
|
-
|
|
21
|
-
const SEARCH_PROMPT_SNIPPET =
|
|
22
|
-
"web_docs_search — search Context7 for libraries matching a name, returns library IDs for use with web_docs_fetch";
|
|
23
|
-
|
|
24
|
-
const FETCH_PROMPT_SNIPPET =
|
|
25
|
-
"web_docs_fetch — retrieve up-to-date documentation context from Context7 for a specific library";
|
|
26
|
-
|
|
27
|
-
const SEARCH_PROMPT_GUIDELINES = [
|
|
28
|
-
"Use web_docs_search to find Context7 library IDs by name before calling web_docs_fetch.",
|
|
29
|
-
"Pass a descriptive query along with the library name for better relevance ranking.",
|
|
30
|
-
"Review the search results carefully — pick the library ID that best matches the user's need.",
|
|
31
|
-
];
|
|
32
|
-
|
|
33
|
-
const FETCH_PROMPT_GUIDELINES = [
|
|
34
|
-
"Use web_docs_fetch to get up-to-date, version-specific documentation for any library.",
|
|
35
|
-
"The library_id must be a Context7 library ID like /facebook/react or /vercel/next.js.",
|
|
36
|
-
"Set raw=true only when you need structured JSON snippets instead of plain text Markdown.",
|
|
37
|
-
"If the library ID is unknown, call web_docs_search first to find it.",
|
|
38
|
-
"Prefer descriptive, specific queries over vague ones for better results.",
|
|
39
|
-
];
|
|
40
|
-
|
|
41
27
|
export default function docsExtension(pi: ExtensionAPI): void {
|
|
42
28
|
pi.registerTool({
|
|
43
29
|
name: SEARCH_TOOL_NAME,
|
|
44
30
|
label: SEARCH_TOOL_LABEL,
|
|
45
|
-
description:
|
|
46
|
-
promptSnippet:
|
|
47
|
-
promptGuidelines:
|
|
31
|
+
description: searchToolDescription,
|
|
32
|
+
promptSnippet: searchPromptSnippet,
|
|
33
|
+
promptGuidelines: searchPromptGuidelines,
|
|
48
34
|
parameters: Type.Object({
|
|
49
35
|
library_name: Type.String({
|
|
50
36
|
description: "Library name to search for (e.g. react, next.js, fastapi)",
|
|
@@ -59,9 +45,9 @@ export default function docsExtension(pi: ExtensionAPI): void {
|
|
|
59
45
|
pi.registerTool({
|
|
60
46
|
name: FETCH_TOOL_NAME,
|
|
61
47
|
label: FETCH_TOOL_LABEL,
|
|
62
|
-
description:
|
|
63
|
-
promptSnippet:
|
|
64
|
-
promptGuidelines:
|
|
48
|
+
description: fetchToolDescription,
|
|
49
|
+
promptSnippet: fetchPromptSnippet,
|
|
50
|
+
promptGuidelines: fetchPromptGuidelines,
|
|
65
51
|
parameters: Type.Object({
|
|
66
52
|
library_id: Type.String({
|
|
67
53
|
description:
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Prompt guidance and tool description for the web_docs_fetch tool.
|
|
2
|
+
|
|
3
|
+
export const toolDescription = `Retrieve up-to-date documentation context for a specific library via Context7. Returns Markdown documentation and code snippets tailored to the query, or JSON-serialized snippet objects when \`raw: true\`. Use web_docs_fetch after web_docs_search or whenever the exact Context7 library ID is already known. Requires a Context7 library ID (e.g. /facebook/react, /vercel/next.js).`;
|
|
4
|
+
|
|
5
|
+
export const promptSnippet =
|
|
6
|
+
"web_docs_fetch — retrieve focused, up-to-date Context7 docs for a known library ID";
|
|
7
|
+
|
|
8
|
+
export const promptGuidelines = [
|
|
9
|
+
"Use web_docs_fetch after web_docs_search, or use web_docs_fetch directly when the exact Context7 `library_id` is already known.",
|
|
10
|
+
"Use web_docs_fetch only with Context7 library IDs such as `/facebook/react` or `/vercel/next.js`.",
|
|
11
|
+
"Use web_docs_fetch with a specific, task-oriented `query` to retrieve focused version-aware documentation instead of a vague broad dump.",
|
|
12
|
+
"Use web_docs_fetch with `raw: true` only when you need structured JSON snippet objects instead of Markdown documentation.",
|
|
13
|
+
"Call web_docs_search before web_docs_fetch when the correct `library_id` is unknown or ambiguous.",
|
|
14
|
+
];
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Prompt guidance and tool description for the web_docs_search tool.
|
|
2
|
+
|
|
3
|
+
export const toolDescription = `Search Context7 for library IDs and metadata before fetching docs. Returns a Markdown table of matching libraries (ID, name, description, trust score, benchmark score, snippet count, versions). Use web_docs_search when you know the library name but not the exact Context7 library ID.`;
|
|
4
|
+
|
|
5
|
+
export const promptSnippet =
|
|
6
|
+
"web_docs_search — find Context7 library IDs and candidate versions before calling web_docs_fetch";
|
|
7
|
+
|
|
8
|
+
export const promptGuidelines = [
|
|
9
|
+
"Use web_docs_search before web_docs_fetch when you do not already know the exact Context7 `library_id`.",
|
|
10
|
+
"Use web_docs_search with both `library_name` and a descriptive `query` so Context7 can rank results for the user's actual task.",
|
|
11
|
+
"Review web_docs_search results carefully and choose the `library_id` that best matches the user's framework, package scope, and version needs.",
|
|
12
|
+
];
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
|
|
3
|
+
// Prompt guidance and tool description for the web_fetch_md tool.
|
|
4
|
+
|
|
5
|
+
const INLINE_MAX_CHARS = 15_000;
|
|
6
|
+
|
|
7
|
+
export const toolDescription = `Fetch a web page and convert it to clean Markdown for LLM ingestion.
|
|
8
|
+
|
|
9
|
+
Use web_fetch_md when the user provides a public URL or asks you to inspect public web content. Only accepts real \`http://\` or \`https://\` URLs. If the page is access-controlled (login, paywall, private content), stop and ask the user for an allowed source or exported content.
|
|
10
|
+
|
|
11
|
+
Output modes:
|
|
12
|
+
- \`auto\` (default): returns Markdown inline if ≤${INLINE_MAX_CHARS.toLocaleString()} characters; otherwise writes to a temporary file and returns the path.
|
|
13
|
+
- \`inline\`: always returns Markdown inline.
|
|
14
|
+
- \`file\`: always writes to a temporary file and returns the path.
|
|
15
|
+
|
|
16
|
+
Links and images are absolutized by default. Use \`abs_links: false\` to keep them as-is.`;
|
|
17
|
+
|
|
18
|
+
export const promptSnippet =
|
|
19
|
+
"web_fetch_md — fetch a public URL and convert the response to clean Markdown for LLM ingestion";
|
|
20
|
+
|
|
21
|
+
function isGhAvailable(): boolean {
|
|
22
|
+
try {
|
|
23
|
+
const result = spawnSync("gh", ["--version"], { stdio: "ignore" });
|
|
24
|
+
return result.status === 0;
|
|
25
|
+
} catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function buildPromptGuidelines(): string[] {
|
|
31
|
+
const guidelines = [
|
|
32
|
+
"Use web_fetch_md to fetch a public web page and convert it to clean Markdown for the model.",
|
|
33
|
+
"Use web_fetch_md only with real `http://` or `https://` URLs; if a page is access-controlled, stop and ask the user for an allowed source or exported content.",
|
|
34
|
+
"Use web_fetch_md with `output_mode: auto` unless you have a specific reason to force inline output or a temp file path.",
|
|
35
|
+
"Use web_fetch_md with `output_mode: inline` only when you need the Markdown directly in context, and use web_fetch_md with `output_mode: file` when you explicitly want a saved temp file path.",
|
|
36
|
+
"Use web_fetch_md with `abs_links: false` only when relative links or images are intentionally desired.",
|
|
37
|
+
];
|
|
38
|
+
if (isGhAvailable()) {
|
|
39
|
+
guidelines.push(
|
|
40
|
+
"Use bash with the `gh` CLI instead of web_fetch_md for GitHub URLs when `gh` is available.",
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
return guidelines;
|
|
44
|
+
}
|
package/src/web.ts
CHANGED
|
@@ -2,55 +2,21 @@
|
|
|
2
2
|
* SuPi Web extension entry point — registers the `web_fetch_md` tool with pi.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { spawnSync } from "node:child_process";
|
|
6
5
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
7
6
|
import { Type } from "typebox";
|
|
8
7
|
import { htmlToMarkdown, wrapAsCodeBlock } from "./convert.ts";
|
|
9
8
|
import { FetchError, fetchWithNegotiation, isValidHttpUrl } from "./fetch.ts";
|
|
10
9
|
import { writeTempFile } from "./temp-file.ts";
|
|
10
|
+
import {
|
|
11
|
+
buildPromptGuidelines,
|
|
12
|
+
promptSnippet,
|
|
13
|
+
toolDescription,
|
|
14
|
+
} from "./tool/web-fetch-md-guidance.ts";
|
|
11
15
|
|
|
12
16
|
const TOOL_NAME = "web_fetch_md";
|
|
13
17
|
const TOOL_LABEL = "Web Fetch";
|
|
14
18
|
const INLINE_MAX_CHARS = 15_000;
|
|
15
19
|
|
|
16
|
-
const TOOL_DESCRIPTION = `Fetch a web page and convert it to clean Markdown for LLM ingestion.
|
|
17
|
-
|
|
18
|
-
Only accepts real \`http://\` or \`https://\` URLs. If the page is access-controlled (login, paywall, private content), stop and ask the user for an allowed source or exported content.
|
|
19
|
-
|
|
20
|
-
Output modes:
|
|
21
|
-
- \`auto\` (default): returns Markdown inline if ≤${INLINE_MAX_CHARS.toLocaleString()} characters; otherwise writes to a temporary file and returns the path.
|
|
22
|
-
- \`inline\`: always returns Markdown inline.
|
|
23
|
-
- \`file\`: always writes to a temporary file and returns the path.
|
|
24
|
-
|
|
25
|
-
Links and images are absolutized by default. Use \`abs_links: false\` to keep them as-is.`;
|
|
26
|
-
|
|
27
|
-
const PROMPT_SNIPPET =
|
|
28
|
-
"web_fetch_md — fetch a URL and convert it to clean Markdown suitable for LLM ingestion.";
|
|
29
|
-
|
|
30
|
-
function isGhAvailable(): boolean {
|
|
31
|
-
try {
|
|
32
|
-
const result = spawnSync("gh", ["--version"], { stdio: "ignore" });
|
|
33
|
-
return result.status === 0;
|
|
34
|
-
} catch {
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function buildPromptGuidelines(): string[] {
|
|
40
|
-
const guidelines = [
|
|
41
|
-
"Use web_fetch_md to fetch web pages and convert them to clean Markdown for LLM ingestion.",
|
|
42
|
-
"Only accept real `http://` or `https://` URLs; stop and ask the user for an allowed source if the page is access-controlled.",
|
|
43
|
-
"Prefer `output_mode: auto` (default) so large pages are written to temp files instead of flooding the context window.",
|
|
44
|
-
"Set `abs_links: false` only when relative links are intentional (e.g., local documentation).",
|
|
45
|
-
];
|
|
46
|
-
if (isGhAvailable()) {
|
|
47
|
-
guidelines.push(
|
|
48
|
-
"For GitHub URLs (e.g., repos, issues, PRs, releases), prefer the `gh` CLI via `bash` over this tool.",
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
return guidelines;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
20
|
const OutputModeEnum = Type.Union(
|
|
55
21
|
[Type.Literal("auto"), Type.Literal("inline"), Type.Literal("file")],
|
|
56
22
|
{ default: "auto", description: "Output mode: auto, inline, or file" },
|
|
@@ -60,8 +26,8 @@ export default function webExtension(pi: ExtensionAPI): void {
|
|
|
60
26
|
pi.registerTool({
|
|
61
27
|
name: TOOL_NAME,
|
|
62
28
|
label: TOOL_LABEL,
|
|
63
|
-
description:
|
|
64
|
-
promptSnippet
|
|
29
|
+
description: toolDescription,
|
|
30
|
+
promptSnippet,
|
|
65
31
|
promptGuidelines: buildPromptGuidelines(),
|
|
66
32
|
parameters: Type.Object({
|
|
67
33
|
url: Type.String({ description: "http(s) URL to fetch" }),
|
|
File without changes
|
/package/node_modules/@mrclrchtr/supi-core/src/{context-messages.ts → context/context-messages.ts}
RENAMED
|
File without changes
|
|
File without changes
|
/package/node_modules/@mrclrchtr/supi-core/src/{settings-command.ts → settings/settings-command.ts}
RENAMED
|
File without changes
|
|
File without changes
|