@juicesharp/rpiv-web-tools 1.8.0 → 1.8.1

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.
Files changed (2) hide show
  1. package/package.json +56 -53
  2. package/web-tools.ts +20 -41
package/package.json CHANGED
@@ -1,55 +1,58 @@
1
1
  {
2
- "name": "@juicesharp/rpiv-web-tools",
3
- "version": "1.8.0",
4
- "description": "Pi extension. Web search and fetch for the model with pluggable providers (Brave, Tavily, Serper, Exa, Jina, Firecrawl).",
5
- "keywords": [
6
- "pi-package",
7
- "pi-extension",
8
- "rpiv",
9
- "web-search",
10
- "search",
11
- "fetch",
12
- "scrape",
13
- "brave",
14
- "tavily",
15
- "serper",
16
- "exa",
17
- "jina",
18
- "firecrawl"
19
- ],
20
- "type": "module",
21
- "license": "MIT",
22
- "author": "juicesharp",
23
- "repository": {
24
- "type": "git",
25
- "url": "git+https://github.com/juicesharp/rpiv-mono.git",
26
- "directory": "packages/rpiv-web-tools"
27
- },
28
- "homepage": "https://github.com/juicesharp/rpiv-mono/tree/main/packages/rpiv-web-tools#readme",
29
- "bugs": {
30
- "url": "https://github.com/juicesharp/rpiv-mono/issues"
31
- },
32
- "publishConfig": {
33
- "access": "public"
34
- },
35
- "scripts": {
36
- "test": "vitest run"
37
- },
38
- "files": [
39
- "index.ts",
40
- "web-tools.ts",
41
- "providers/",
42
- "README.md",
43
- "LICENSE"
44
- ],
45
- "pi": {
46
- "extensions": [
47
- "./index.ts"
48
- ]
49
- },
50
- "peerDependencies": {
51
- "@earendil-works/pi-coding-agent": "*",
52
- "@earendil-works/pi-tui": "*",
53
- "typebox": "*"
54
- }
2
+ "name": "@juicesharp/rpiv-web-tools",
3
+ "version": "1.8.1",
4
+ "description": "Pi extension. Web search and fetch for the model with pluggable providers (Brave, Tavily, Serper, Exa, Jina, Firecrawl).",
5
+ "keywords": [
6
+ "pi-package",
7
+ "pi-extension",
8
+ "rpiv",
9
+ "web-search",
10
+ "search",
11
+ "fetch",
12
+ "scrape",
13
+ "brave",
14
+ "tavily",
15
+ "serper",
16
+ "exa",
17
+ "jina",
18
+ "firecrawl"
19
+ ],
20
+ "type": "module",
21
+ "license": "MIT",
22
+ "author": "juicesharp",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/juicesharp/rpiv-mono.git",
26
+ "directory": "packages/rpiv-web-tools"
27
+ },
28
+ "homepage": "https://github.com/juicesharp/rpiv-mono/tree/main/packages/rpiv-web-tools#readme",
29
+ "bugs": {
30
+ "url": "https://github.com/juicesharp/rpiv-mono/issues"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public"
34
+ },
35
+ "scripts": {
36
+ "test": "vitest run"
37
+ },
38
+ "files": [
39
+ "index.ts",
40
+ "web-tools.ts",
41
+ "providers/",
42
+ "README.md",
43
+ "LICENSE"
44
+ ],
45
+ "pi": {
46
+ "extensions": [
47
+ "./index.ts"
48
+ ]
49
+ },
50
+ "dependencies": {
51
+ "@juicesharp/rpiv-config": "^1.8.1"
52
+ },
53
+ "peerDependencies": {
54
+ "@earendil-works/pi-coding-agent": "*",
55
+ "@earendil-works/pi-tui": "*",
56
+ "typebox": "*"
57
+ }
55
58
  }
package/web-tools.ts CHANGED
@@ -11,10 +11,9 @@
11
11
  * 3. (Brave only, legacy) apiKey field in config.json
12
12
  */
13
13
 
14
- import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
15
14
  import { mkdtemp, writeFile } from "node:fs/promises";
16
- import { homedir, tmpdir } from "node:os";
17
- import { dirname, join } from "node:path";
15
+ import { tmpdir } from "node:os";
16
+ import { join } from "node:path";
18
17
  import type { ExtensionAPI, Theme } from "@earendil-works/pi-coding-agent";
19
18
  import {
20
19
  DEFAULT_MAX_BYTES,
@@ -24,6 +23,8 @@ import {
24
23
  truncateHead,
25
24
  } from "@earendil-works/pi-coding-agent";
26
25
  import { Text } from "@earendil-works/pi-tui";
26
+ import type { GuidanceFields } from "@juicesharp/rpiv-config";
27
+ import { configPath, loadJsonConfig, saveJsonConfig, validateGuidanceFields } from "@juicesharp/rpiv-config";
27
28
  import { Type } from "typebox";
28
29
  import { createSearchProvider } from "./providers/factory.js";
29
30
  import { PROVIDERS } from "./providers/index.js";
@@ -44,9 +45,7 @@ const API_KEY_MASK_VISIBLE_CHARS = 4;
44
45
  const FETCH_TEMP_DIR_PREFIX = "rpiv-fetch-";
45
46
  const FETCH_TEMP_FILE_NAME = "content.txt";
46
47
 
47
- const CONFIG_DIR = join(homedir(), ".config", "rpiv-web-tools");
48
- const CONFIG_PATH = join(CONFIG_DIR, "config.json");
49
- const CONFIG_FILE_MODE = 0o600;
48
+ const CONFIG_PATH = configPath("rpiv-web-tools");
50
49
 
51
50
  const SUPPORTED_HTTP_PROTOCOLS = new Set(["http:", "https:"]);
52
51
 
@@ -60,10 +59,7 @@ const DEFAULT_PROVIDER_NAME = "brave";
60
59
  // Config file persistence
61
60
  // ---------------------------------------------------------------------------
62
61
 
63
- interface GuidanceFields {
64
- promptSnippet?: string;
65
- promptGuidelines?: string[];
66
- }
62
+ // GuidanceFields is now imported from @juicesharp/rpiv-config
67
63
 
68
64
  interface WebToolsGuidance {
69
65
  web_search?: GuidanceFields;
@@ -78,44 +74,18 @@ interface WebToolsConfig {
78
74
  }
79
75
 
80
76
  function loadConfig(): WebToolsConfig {
81
- if (!existsSync(CONFIG_PATH)) return {};
82
- try {
83
- return JSON.parse(readFileSync(CONFIG_PATH, "utf-8")) as WebToolsConfig;
84
- } catch {
85
- return {};
86
- }
77
+ return loadJsonConfig<WebToolsConfig>(CONFIG_PATH);
87
78
  }
88
79
 
89
- function saveConfig(config: WebToolsConfig): void {
90
- mkdirSync(dirname(CONFIG_PATH), { recursive: true });
91
- writeFileSync(CONFIG_PATH, `${JSON.stringify(config, null, 2)}\n`, "utf-8");
92
- try {
93
- chmodSync(CONFIG_PATH, CONFIG_FILE_MODE);
94
- } catch {
95
- // chmod may fail on some filesystems — best effort only
96
- }
80
+ function saveConfig(config: WebToolsConfig): boolean {
81
+ return saveJsonConfig(CONFIG_PATH, config);
97
82
  }
98
83
 
99
84
  // ---------------------------------------------------------------------------
100
85
  // Executor guidance — overrides + defaults
101
86
  // ---------------------------------------------------------------------------
102
87
 
103
- function validateGuidanceFields(fields: unknown): GuidanceFields {
104
- if (!fields || typeof fields !== "object") return {};
105
- const g = fields as Record<string, unknown>;
106
- const result: GuidanceFields = {};
107
- if (typeof g.promptSnippet === "string" && g.promptSnippet.length > 0) {
108
- result.promptSnippet = g.promptSnippet;
109
- }
110
- if (
111
- Array.isArray(g.promptGuidelines) &&
112
- g.promptGuidelines.length > 0 &&
113
- g.promptGuidelines.every((s) => typeof s === "string" && s.length > 0)
114
- ) {
115
- result.promptGuidelines = g.promptGuidelines;
116
- }
117
- return result;
118
- }
88
+ // validateGuidanceFields is now imported from @juicesharp/rpiv-config
119
89
 
120
90
  export const DEFAULT_WEB_SEARCH_SNIPPET = "Search the web for up-to-date information";
121
91
  export const DEFAULT_WEB_SEARCH_GUIDELINES: string[] = [
@@ -545,7 +515,16 @@ export function registerWebSearchConfigCommand(pi: ExtensionAPI): void {
545
515
  apiKeys: { ...current.apiKeys, [selectedProvider]: keyToWrite },
546
516
  };
547
517
  delete (toSave as { apiKey?: string }).apiKey;
548
- saveConfig(toSave);
518
+ if (!saveConfig(toSave)) {
519
+ // Don't lie about persistence — a "Saved …" message followed by an
520
+ // auth error on the next web_search would point the user at the
521
+ // wrong surface (vendor) instead of the actual cause (disk write).
522
+ ctx.ui.notify(
523
+ `Failed to save ${selectedMeta.label} API key to ${CONFIG_PATH} — disk write failed`,
524
+ "error",
525
+ );
526
+ return;
527
+ }
549
528
  ctx.ui.notify(
550
529
  trimmed
551
530
  ? `Saved ${selectedMeta.label} API key to ${CONFIG_PATH}`