pi-web-providers 1.0.0 → 2.0.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 +266 -91
- package/dist/index.js +18402 -4022
- package/example-config.json +5 -0
- package/examples/custom/README.md +224 -0
- package/examples/custom/wrappers/claude-answer.sh +42 -0
- package/examples/custom/wrappers/codex-search.sh +68 -0
- package/examples/custom/wrappers/gemini-contents.sh +49 -0
- package/examples/custom/wrappers/perplexity-research.sh +55 -0
- package/package.json +14 -4
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# Custom wrapper examples
|
|
2
|
+
|
|
3
|
+
These examples keep the wrapper logic small. They are bash scripts that use
|
|
4
|
+
`jq` for JSON handling. Each wrapper uses a different backend pattern:
|
|
5
|
+
|
|
6
|
+
- `wrappers/codex-search.sh` — `codex --search exec`
|
|
7
|
+
- `wrappers/gemini-contents.sh` — Gemini API via `curl`
|
|
8
|
+
- `wrappers/claude-answer.sh` — `claude -p`
|
|
9
|
+
- `wrappers/perplexity-research.sh` — Perplexity API via `curl`
|
|
10
|
+
|
|
11
|
+
Each wrapper:
|
|
12
|
+
|
|
13
|
+
- reads one JSON request from `stdin`
|
|
14
|
+
- writes one JSON response to `stdout`
|
|
15
|
+
- may write progress text to `stderr`
|
|
16
|
+
|
|
17
|
+
## Requirements
|
|
18
|
+
|
|
19
|
+
You need:
|
|
20
|
+
|
|
21
|
+
- `bash`
|
|
22
|
+
- `jq`
|
|
23
|
+
- `curl`
|
|
24
|
+
- `codex` on your `PATH` and authenticated locally
|
|
25
|
+
- `claude` on your `PATH` and authenticated locally
|
|
26
|
+
- `GOOGLE_API_KEY` for the Gemini example
|
|
27
|
+
- `PERPLEXITY_API_KEY` for the Perplexity example
|
|
28
|
+
|
|
29
|
+
## Copy the wrappers into your project
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
mkdir -p ./wrappers
|
|
33
|
+
cp examples/custom/wrappers/codex-search.sh ./wrappers/
|
|
34
|
+
cp examples/custom/wrappers/gemini-contents.sh ./wrappers/
|
|
35
|
+
cp examples/custom/wrappers/claude-answer.sh ./wrappers/
|
|
36
|
+
cp examples/custom/wrappers/perplexity-research.sh ./wrappers/
|
|
37
|
+
chmod +x ./wrappers/*.sh
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Then configure `custom` like this:
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"tools": {
|
|
45
|
+
"search": "custom",
|
|
46
|
+
"contents": "custom",
|
|
47
|
+
"answer": "custom",
|
|
48
|
+
"research": "custom"
|
|
49
|
+
},
|
|
50
|
+
"providers": {
|
|
51
|
+
"custom": {
|
|
52
|
+
"enabled": true,
|
|
53
|
+
"options": {
|
|
54
|
+
"search": {
|
|
55
|
+
"argv": ["bash", "./wrappers/codex-search.sh"]
|
|
56
|
+
},
|
|
57
|
+
"contents": {
|
|
58
|
+
"argv": ["bash", "./wrappers/gemini-contents.sh"]
|
|
59
|
+
},
|
|
60
|
+
"answer": {
|
|
61
|
+
"argv": ["bash", "./wrappers/claude-answer.sh"]
|
|
62
|
+
},
|
|
63
|
+
"research": {
|
|
64
|
+
"argv": ["bash", "./wrappers/perplexity-research.sh"]
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
`web_research` uses the same async workflow as every other research provider:
|
|
73
|
+
pi starts the wrapper in the background, tracks the job locally, and writes the
|
|
74
|
+
final report to a file when it finishes.
|
|
75
|
+
|
|
76
|
+
## Core command shapes
|
|
77
|
+
|
|
78
|
+
### Search with Codex
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
codex --search exec \
|
|
82
|
+
--skip-git-repo-check \
|
|
83
|
+
--sandbox read-only \
|
|
84
|
+
--output-schema ./schema.json \
|
|
85
|
+
"Search the public web and return JSON only"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Contents with Gemini and `curl`
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
curl -sS -X POST \
|
|
92
|
+
"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key=$GOOGLE_API_KEY" \
|
|
93
|
+
-H "Content-Type: application/json" \
|
|
94
|
+
-d '{
|
|
95
|
+
"contents": [{"parts": [{"text": "Extract the main content from https://example.com and return JSON only"}]}],
|
|
96
|
+
"tools": [{"urlContext": {}}],
|
|
97
|
+
"generationConfig": {"responseMimeType": "application/json"}
|
|
98
|
+
}'
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Answers with Claude
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
claude -p \
|
|
105
|
+
--output-format json \
|
|
106
|
+
--json-schema "$schema" \
|
|
107
|
+
--permission-mode dontAsk \
|
|
108
|
+
--allowedTools "WebSearch,WebFetch" \
|
|
109
|
+
"Answer this question using current public web information"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Research with Perplexity and `curl`
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
curl -sS https://api.perplexity.ai/chat/completions \
|
|
116
|
+
-H "Authorization: Bearer $PERPLEXITY_API_KEY" \
|
|
117
|
+
-H "Content-Type: application/json" \
|
|
118
|
+
-d '{
|
|
119
|
+
"model": "sonar-deep-research",
|
|
120
|
+
"stream": false,
|
|
121
|
+
"messages": [{"role": "user", "content": "Research this topic and return a long-form answer"}]
|
|
122
|
+
}'
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Try a wrapper directly
|
|
126
|
+
|
|
127
|
+
### Search
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
printf '%s' '{
|
|
131
|
+
"capability": "search",
|
|
132
|
+
"query": "latest Codex CLI release notes",
|
|
133
|
+
"maxResults": 5,
|
|
134
|
+
"options": {},
|
|
135
|
+
"cwd": "'"$PWD"'"
|
|
136
|
+
}' | bash examples/custom/wrappers/codex-search.sh
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Contents
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
printf '%s' '{
|
|
143
|
+
"capability": "contents",
|
|
144
|
+
"urls": ["https://example.com"],
|
|
145
|
+
"options": {},
|
|
146
|
+
"cwd": "'"$PWD"'"
|
|
147
|
+
}' | bash examples/custom/wrappers/gemini-contents.sh
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Answer
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
printf '%s' '{
|
|
154
|
+
"capability": "answer",
|
|
155
|
+
"query": "What changed in the latest Claude Code release?",
|
|
156
|
+
"options": {},
|
|
157
|
+
"cwd": "'"$PWD"'"
|
|
158
|
+
}' | bash examples/custom/wrappers/claude-answer.sh
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Research
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
printf '%s' '{
|
|
165
|
+
"capability": "research",
|
|
166
|
+
"input": "Compare current local agent CLIs for web-grounded tasks.",
|
|
167
|
+
"options": {},
|
|
168
|
+
"cwd": "'"$PWD"'"
|
|
169
|
+
}' | bash examples/custom/wrappers/perplexity-research.sh
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Request and response contract
|
|
173
|
+
|
|
174
|
+
### Search request
|
|
175
|
+
|
|
176
|
+
```json
|
|
177
|
+
{
|
|
178
|
+
"capability": "search",
|
|
179
|
+
"query": "latest Codex CLI release notes",
|
|
180
|
+
"maxResults": 5,
|
|
181
|
+
"options": {},
|
|
182
|
+
"cwd": "/path/to/project"
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Search response
|
|
187
|
+
|
|
188
|
+
```json
|
|
189
|
+
{
|
|
190
|
+
"results": [
|
|
191
|
+
{
|
|
192
|
+
"title": "Codex CLI docs",
|
|
193
|
+
"url": "https://github.com/openai/codex",
|
|
194
|
+
"snippet": "CLI docs, examples, and release information."
|
|
195
|
+
}
|
|
196
|
+
]
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Contents response
|
|
201
|
+
|
|
202
|
+
```json
|
|
203
|
+
{
|
|
204
|
+
"answers": [
|
|
205
|
+
{
|
|
206
|
+
"url": "https://example.com",
|
|
207
|
+
"content": "# Example\n\nMain page content",
|
|
208
|
+
"summary": "Optional short summary",
|
|
209
|
+
"metadata": {}
|
|
210
|
+
}
|
|
211
|
+
]
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Answer and research response
|
|
216
|
+
|
|
217
|
+
```json
|
|
218
|
+
{
|
|
219
|
+
"text": "Rendered tool output",
|
|
220
|
+
"summary": "Optional short summary",
|
|
221
|
+
"itemCount": 1,
|
|
222
|
+
"metadata": {}
|
|
223
|
+
}
|
|
224
|
+
```
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
request="$(cat)"
|
|
5
|
+
cwd="$(jq -r '.cwd // "."' <<<"$request")"
|
|
6
|
+
query="$(jq -r '.query' <<<"$request")"
|
|
7
|
+
model="$(jq -r '.options.model // empty' <<<"$request")"
|
|
8
|
+
|
|
9
|
+
schema='{"type":"object","properties":{"text":{"type":"string"},"summary":{"type":"string"},"itemCount":{"type":"integer"},"metadata":{"type":"object"}},"required":["text","summary","itemCount","metadata"],"additionalProperties":false}'
|
|
10
|
+
prompt="$(
|
|
11
|
+
cat <<EOF
|
|
12
|
+
Answer this question using current public web information:
|
|
13
|
+
$query
|
|
14
|
+
|
|
15
|
+
Return JSON only with these fields:
|
|
16
|
+
- text: the full grounded answer
|
|
17
|
+
- summary: a one-sentence summary
|
|
18
|
+
- itemCount: use 1
|
|
19
|
+
- metadata: include a short note such as the task type
|
|
20
|
+
|
|
21
|
+
Use WebSearch and WebFetch when needed.
|
|
22
|
+
EOF
|
|
23
|
+
)"
|
|
24
|
+
|
|
25
|
+
args=(
|
|
26
|
+
-p
|
|
27
|
+
--output-format json
|
|
28
|
+
--json-schema "$schema"
|
|
29
|
+
--permission-mode dontAsk
|
|
30
|
+
--allowedTools "WebSearch,WebFetch"
|
|
31
|
+
--no-session-persistence
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
if [[ -n "$model" ]]; then
|
|
35
|
+
args+=(--model "$model")
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
echo "Answering with Claude..." >&2
|
|
39
|
+
(
|
|
40
|
+
cd "$cwd"
|
|
41
|
+
claude "${args[@]}" "$prompt"
|
|
42
|
+
)
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
request="$(cat)"
|
|
5
|
+
cwd="$(jq -r '.cwd // "."' <<<"$request")"
|
|
6
|
+
query="$(jq -r '.query' <<<"$request")"
|
|
7
|
+
max_results="$(jq -r '.maxResults // 5' <<<"$request")"
|
|
8
|
+
model="$(jq -r '.options.model // empty' <<<"$request")"
|
|
9
|
+
|
|
10
|
+
schema_file="$(mktemp)"
|
|
11
|
+
output_file="$(mktemp)"
|
|
12
|
+
trap 'rm -f "$schema_file" "$output_file"' EXIT
|
|
13
|
+
|
|
14
|
+
cat >"$schema_file" <<'JSON'
|
|
15
|
+
{
|
|
16
|
+
"type": "object",
|
|
17
|
+
"properties": {
|
|
18
|
+
"results": {
|
|
19
|
+
"type": "array",
|
|
20
|
+
"items": {
|
|
21
|
+
"type": "object",
|
|
22
|
+
"properties": {
|
|
23
|
+
"title": { "type": "string" },
|
|
24
|
+
"url": { "type": "string" },
|
|
25
|
+
"snippet": { "type": "string" }
|
|
26
|
+
},
|
|
27
|
+
"required": ["title", "url", "snippet"],
|
|
28
|
+
"additionalProperties": false
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"required": ["results"],
|
|
33
|
+
"additionalProperties": false
|
|
34
|
+
}
|
|
35
|
+
JSON
|
|
36
|
+
|
|
37
|
+
prompt="$(
|
|
38
|
+
cat <<EOF
|
|
39
|
+
Search the public web for: $query
|
|
40
|
+
|
|
41
|
+
Return JSON only.
|
|
42
|
+
Return at most $max_results results.
|
|
43
|
+
Each result must include:
|
|
44
|
+
- title
|
|
45
|
+
- url
|
|
46
|
+
- snippet
|
|
47
|
+
|
|
48
|
+
Prefer primary or official sources when possible.
|
|
49
|
+
EOF
|
|
50
|
+
)"
|
|
51
|
+
|
|
52
|
+
args=(
|
|
53
|
+
--search exec
|
|
54
|
+
--skip-git-repo-check
|
|
55
|
+
--sandbox read-only
|
|
56
|
+
--color never
|
|
57
|
+
--cd "$cwd"
|
|
58
|
+
--output-schema "$schema_file"
|
|
59
|
+
--output-last-message "$output_file"
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
if [[ -n "$model" ]]; then
|
|
63
|
+
args+=(--model "$model")
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
echo "Searching with Codex..." >&2
|
|
67
|
+
codex "${args[@]}" "$prompt" >/dev/null
|
|
68
|
+
jq . "$output_file"
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
: "${GOOGLE_API_KEY:?GOOGLE_API_KEY is required}"
|
|
5
|
+
|
|
6
|
+
request="$(cat)"
|
|
7
|
+
model="$(jq -r '.options.model // "gemini-2.5-flash"' <<<"$request")"
|
|
8
|
+
url_count="$(jq '.urls | length' <<<"$request")"
|
|
9
|
+
urls="$(jq -r '.urls[]' <<<"$request")"
|
|
10
|
+
|
|
11
|
+
prompt="$(
|
|
12
|
+
cat <<EOF
|
|
13
|
+
Extract the main textual content from these URLs:
|
|
14
|
+
$urls
|
|
15
|
+
|
|
16
|
+
Return JSON only with this shape:
|
|
17
|
+
- answers: an array with exactly $url_count items
|
|
18
|
+
- each answer must include the input url, and either:
|
|
19
|
+
- content: the extracted text as a string
|
|
20
|
+
- or error: a short error string when extraction fails
|
|
21
|
+
- optionally include summary and metadata
|
|
22
|
+
EOF
|
|
23
|
+
)"
|
|
24
|
+
|
|
25
|
+
body="$(
|
|
26
|
+
jq -n \
|
|
27
|
+
--arg prompt "$prompt" \
|
|
28
|
+
'{
|
|
29
|
+
contents: [{parts: [{text: $prompt}]}],
|
|
30
|
+
tools: [{urlContext: {}}],
|
|
31
|
+
generationConfig: {responseMimeType: "application/json"}
|
|
32
|
+
}'
|
|
33
|
+
)"
|
|
34
|
+
|
|
35
|
+
echo "Fetching contents with Gemini..." >&2
|
|
36
|
+
response="$(curl -sS -X POST \
|
|
37
|
+
"https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${GOOGLE_API_KEY}" \
|
|
38
|
+
-H "Content-Type: application/json" \
|
|
39
|
+
-d "$body")"
|
|
40
|
+
|
|
41
|
+
error="$(jq -r '.error.message // empty' <<<"$response")"
|
|
42
|
+
if [[ -n "$error" ]]; then
|
|
43
|
+
echo "$error" >&2
|
|
44
|
+
exit 1
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
text="$(jq -r '[.candidates[]?.content.parts[]?.text // empty] | join("\n")' <<<"$response")"
|
|
48
|
+
json_text="$(printf '%s\n' "$text" | sed -e '1s/^```json[[:space:]]*//' -e '1s/^```[[:space:]]*//' -e '$s/```$//')"
|
|
49
|
+
jq . <<<"$json_text"
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
: "${PERPLEXITY_API_KEY:?PERPLEXITY_API_KEY is required}"
|
|
5
|
+
|
|
6
|
+
request="$(cat)"
|
|
7
|
+
input="$(jq -r '.input' <<<"$request")"
|
|
8
|
+
model="$(jq -r '.options.model // "sonar-deep-research"' <<<"$request")"
|
|
9
|
+
|
|
10
|
+
body="$(
|
|
11
|
+
jq -n \
|
|
12
|
+
--arg model "$model" \
|
|
13
|
+
--arg input "$input" \
|
|
14
|
+
'{
|
|
15
|
+
model: $model,
|
|
16
|
+
stream: false,
|
|
17
|
+
messages: [{role: "user", content: $input}]
|
|
18
|
+
}'
|
|
19
|
+
)"
|
|
20
|
+
|
|
21
|
+
echo "Researching with Perplexity..." >&2
|
|
22
|
+
response="$(curl -sS https://api.perplexity.ai/chat/completions \
|
|
23
|
+
-H "Authorization: Bearer ${PERPLEXITY_API_KEY}" \
|
|
24
|
+
-H "Content-Type: application/json" \
|
|
25
|
+
-d "$body")"
|
|
26
|
+
|
|
27
|
+
error="$(jq -r '.error.message // empty' <<<"$response")"
|
|
28
|
+
if [[ -n "$error" ]]; then
|
|
29
|
+
echo "$error" >&2
|
|
30
|
+
exit 1
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
citations="$(jq '.citations // []' <<<"$response")"
|
|
34
|
+
count="$(jq '(.citations // []) | length' <<<"$response")"
|
|
35
|
+
text="$(jq -r '
|
|
36
|
+
(.choices[0].message.content // "No research returned.") as $text
|
|
37
|
+
| (.citations // []) as $citations
|
|
38
|
+
| if ($citations | length) == 0 then
|
|
39
|
+
$text
|
|
40
|
+
else
|
|
41
|
+
$text + "\n\nSources:\n" + ($citations | to_entries | map("\(.key + 1). \(.value)") | join("\n"))
|
|
42
|
+
end
|
|
43
|
+
' <<<"$response")"
|
|
44
|
+
|
|
45
|
+
jq -n \
|
|
46
|
+
--arg text "$text" \
|
|
47
|
+
--arg summary "Research via Perplexity with $count source(s)" \
|
|
48
|
+
--argjson itemCount "$count" \
|
|
49
|
+
--argjson citations "$citations" \
|
|
50
|
+
'{
|
|
51
|
+
text: $text,
|
|
52
|
+
summary: $summary,
|
|
53
|
+
itemCount: $itemCount,
|
|
54
|
+
metadata: {citations: $citations}
|
|
55
|
+
}'
|
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-web-providers",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Configurable web access extension for pi with per-tool provider routing for search, contents, answers, and research
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Configurable web access extension for pi with per-tool provider routing for search, contents, answers, and research.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist",
|
|
8
8
|
"README.md",
|
|
9
|
-
"LICENSE"
|
|
9
|
+
"LICENSE",
|
|
10
|
+
"example-config.json",
|
|
11
|
+
"examples"
|
|
10
12
|
],
|
|
11
13
|
"keywords": [
|
|
12
14
|
"pi-package",
|
|
@@ -14,11 +16,15 @@
|
|
|
14
16
|
"coding-agent",
|
|
15
17
|
"web-search",
|
|
16
18
|
"claude",
|
|
19
|
+
"cloudflare",
|
|
17
20
|
"codex",
|
|
21
|
+
"custom",
|
|
18
22
|
"exa",
|
|
23
|
+
"firecrawl",
|
|
19
24
|
"gemini",
|
|
20
25
|
"perplexity",
|
|
21
26
|
"parallel",
|
|
27
|
+
"tavily",
|
|
22
28
|
"valyu"
|
|
23
29
|
],
|
|
24
30
|
"author": "mavam",
|
|
@@ -39,20 +45,24 @@
|
|
|
39
45
|
]
|
|
40
46
|
},
|
|
41
47
|
"scripts": {
|
|
42
|
-
"build": "rm -rf dist && esbuild src/index.ts --bundle --format=esm --platform=node --outfile=dist/index.js --external:@mariozechner/pi-coding-agent --external:@mariozechner/pi-ai --external:@mariozechner/pi-tui --external:@sinclair/typebox --external:@anthropic-ai/claude-agent-sdk --external:@google/genai --external:@openai/codex-sdk --external:@perplexity-ai/perplexity_ai --external:exa-js --external:parallel-web --external:valyu-js",
|
|
48
|
+
"build": "rm -rf dist && esbuild src/index.ts --bundle --format=esm --platform=node --outfile=dist/index.js --external:@mariozechner/pi-coding-agent --external:@mariozechner/pi-ai --external:@mariozechner/pi-tui --external:@sinclair/typebox --external:@anthropic-ai/claude-agent-sdk --external:@google/genai --external:@mendable/firecrawl-js --external:@openai/codex-sdk --external:@perplexity-ai/perplexity_ai --external:@tavily/core --external:cloudflare --external:exa-js --external:parallel-web --external:valyu-js",
|
|
43
49
|
"prepare": "npm run build",
|
|
44
50
|
"prepack": "npm run build",
|
|
45
51
|
"check": "tsc --noEmit",
|
|
46
52
|
"format": "biome format --write .",
|
|
47
53
|
"format:check": "biome format .",
|
|
54
|
+
"smoke:live": "npm run build && node scripts/live-smoke.mjs",
|
|
48
55
|
"test": "vitest run",
|
|
49
56
|
"test:watch": "vitest"
|
|
50
57
|
},
|
|
51
58
|
"dependencies": {
|
|
52
59
|
"@anthropic-ai/claude-agent-sdk": "^0.2.71",
|
|
53
60
|
"@google/genai": "^1.44.0",
|
|
61
|
+
"@mendable/firecrawl-js": "^4.18.1",
|
|
54
62
|
"@openai/codex-sdk": "^0.111.0",
|
|
55
63
|
"@perplexity-ai/perplexity_ai": "^0.26.1",
|
|
64
|
+
"@tavily/core": "^0.7.2",
|
|
65
|
+
"cloudflare": "^5.2.0",
|
|
56
66
|
"exa-js": "^2.7.0",
|
|
57
67
|
"parallel-web": "^0.3.1",
|
|
58
68
|
"valyu-js": "^2.5.9",
|