agentic-pi 0.2.2 → 0.2.4
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 +140 -29
- package/dist/args.d.ts +27 -0
- package/dist/args.js +46 -0
- package/dist/args.js.map +1 -1
- package/dist/extensions/file-search/index.d.ts +66 -0
- package/dist/extensions/file-search/index.js +86 -0
- package/dist/extensions/file-search/index.js.map +1 -0
- package/dist/extensions/web-search/extract.d.ts +18 -0
- package/dist/extensions/web-search/extract.js +110 -0
- package/dist/extensions/web-search/extract.js.map +1 -0
- package/dist/extensions/web-search/index.d.ts +43 -0
- package/dist/extensions/web-search/index.js +86 -0
- package/dist/extensions/web-search/index.js.map +1 -0
- package/dist/extensions/web-search/providers/brave.d.ts +21 -0
- package/dist/extensions/web-search/providers/brave.js +73 -0
- package/dist/extensions/web-search/providers/brave.js.map +1 -0
- package/dist/extensions/web-search/providers/exa.d.ts +16 -0
- package/dist/extensions/web-search/providers/exa.js +85 -0
- package/dist/extensions/web-search/providers/exa.js.map +1 -0
- package/dist/extensions/web-search/providers/tavily.d.ts +18 -0
- package/dist/extensions/web-search/providers/tavily.js +85 -0
- package/dist/extensions/web-search/providers/tavily.js.map +1 -0
- package/dist/extensions/web-search/rate-limit.d.ts +14 -0
- package/dist/extensions/web-search/rate-limit.js +24 -0
- package/dist/extensions/web-search/rate-limit.js.map +1 -0
- package/dist/extensions/web-search/safe-fetch.d.ts +54 -0
- package/dist/extensions/web-search/safe-fetch.js +172 -0
- package/dist/extensions/web-search/safe-fetch.js.map +1 -0
- package/dist/extensions/web-search/selection.d.ts +42 -0
- package/dist/extensions/web-search/selection.js +64 -0
- package/dist/extensions/web-search/selection.js.map +1 -0
- package/dist/extensions/web-search/tools.d.ts +13 -0
- package/dist/extensions/web-search/tools.js +136 -0
- package/dist/extensions/web-search/tools.js.map +1 -0
- package/dist/extensions/web-search/types.d.ts +65 -0
- package/dist/extensions/web-search/types.js +10 -0
- package/dist/extensions/web-search/types.js.map +1 -0
- package/dist/run.d.ts +45 -0
- package/dist/run.js +24 -0
- package/dist/run.js.map +1 -1
- package/dist/runner.js +85 -2
- package/dist/runner.js.map +1 -1
- package/dist/sandbox/gondolin.d.ts +13 -4
- package/dist/sandbox/gondolin.js +10 -3
- package/dist/sandbox/gondolin.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -42,8 +42,8 @@ single line you parse.
|
|
|
42
42
|
|
|
43
43
|
Pi explicitly does not support MCP. agentic-pi ships a native Pi extension
|
|
44
44
|
exposing **31 GitHub tools** ported from lastlight's `mcp-github-app`:
|
|
45
|
-
clone/push, issues, PRs, reviews, labels, search.
|
|
46
|
-
|
|
45
|
+
clone/push, issues, PRs, reviews, labels, search. Tool names are prefixed
|
|
46
|
+
with `github_`.
|
|
47
47
|
|
|
48
48
|
Auth is opinionated: **GitHub App credentials preferred**, static
|
|
49
49
|
`GITHUB_TOKEN` only as a low-trust fallback. JWT-minted installation tokens
|
|
@@ -81,38 +81,29 @@ The `extension_status` JSONL event always reports `status`, `reason`,
|
|
|
81
81
|
`message`, `profile`, and `toolCount` so the orchestrator can log the
|
|
82
82
|
outcome programmatically without parsing stderr.
|
|
83
83
|
|
|
84
|
-
### 5.
|
|
84
|
+
### 5. Model selection
|
|
85
85
|
|
|
86
|
-
`--model provider/id`
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
`getModel()`.
|
|
86
|
+
`--model provider/id` (e.g. `anthropic/claude-opus-4-5`, `openai/gpt-4o`).
|
|
87
|
+
Credentials come from environment variables (`OPENAI_API_KEY`,
|
|
88
|
+
`ANTHROPIC_API_KEY`, `OPENROUTER_API_KEY`) or Pi's `~/.pi/agent/auth.json`
|
|
89
|
+
if you've logged in interactively. Provider/id mapping is delegated to
|
|
90
|
+
`@earendil-works/pi-ai`'s `getModel()`.
|
|
92
91
|
|
|
93
92
|
`--thinking <level>` maps directly to Pi's `thinkingLevel`
|
|
94
93
|
(`off`/`minimal`/`low`/`medium`/`high`/`xhigh`). Per-provider effort is
|
|
95
94
|
handled by Pi.
|
|
96
95
|
|
|
97
|
-
### 6.
|
|
98
|
-
|
|
99
|
-
- `--dangerously-skip-permissions` — Pi has no permission prompts to skip
|
|
100
|
-
("run in a container" is Pi's design stance). The flag is accepted so a
|
|
101
|
-
caller that previously spawned opencode does not need to strip it.
|
|
102
|
-
- `--variant <level>` — alias for `--thinking`.
|
|
103
|
-
|
|
104
|
-
### 7. Defaults that match a containerized sandbox
|
|
96
|
+
### 6. Defaults that match a containerized sandbox
|
|
105
97
|
|
|
106
98
|
- **`--no-session`** is intended to be the default in sandboxed runs (state
|
|
107
99
|
lives outside the container).
|
|
108
100
|
- **Built-in tools** (read, write, edit, bash, grep, find, ls) are enabled
|
|
109
101
|
by default. Add `--no-builtin-tools` if you want a GitHub-only agent.
|
|
110
102
|
- **`AGENTS.md`** in the working directory is auto-loaded as the agent's
|
|
111
|
-
system prompt — same convention Pi
|
|
112
|
-
|
|
113
|
-
up.
|
|
103
|
+
system prompt — same convention Pi uses. Drop your workflow's
|
|
104
|
+
`AGENTS.md` into the mounted workspace and the agent picks it up.
|
|
114
105
|
|
|
115
|
-
###
|
|
106
|
+
### 7. Optional micro-VM sandboxing via `--sandbox gondolin`
|
|
116
107
|
|
|
117
108
|
By default Pi's file and bash tools run on the host. Pass `--sandbox gondolin`
|
|
118
109
|
and they get routed through a per-run [Gondolin](https://github.com/earendil-works/gondolin)
|
|
@@ -195,14 +186,120 @@ The **App PEM is never copied into the VM** — only the resulting token,
|
|
|
195
186
|
which is short-lived. User-supplied `--sandbox-env GITHUB_TOKEN=…`
|
|
196
187
|
overrides the auto-injected value if you need to scope down further.
|
|
197
188
|
|
|
189
|
+
### 8. Safe web search via the `web-search` extension
|
|
190
|
+
|
|
191
|
+
agentic-pi can register two native Pi tools — `web_search` and `web_fetch` —
|
|
192
|
+
so the agent can do general-purpose research. Backed by a configurable
|
|
193
|
+
provider:
|
|
194
|
+
|
|
195
|
+
| Provider | API key env var | Native content extraction |
|
|
196
|
+
| --- | --- | --- |
|
|
197
|
+
| Tavily (default) | `TAVILY_API_KEY` | yes (search + extract) |
|
|
198
|
+
| Exa | `EXA_API_KEY` | yes (search + contents) |
|
|
199
|
+
| Brave Search | `BRAVE_SEARCH_API_KEY` | no — `web_fetch` falls back to a safe HTML→text extractor |
|
|
200
|
+
|
|
201
|
+
**Auto-enable.** When at least one API key env var is present, the
|
|
202
|
+
extension is configured automatically. With multiple keys set, priority is
|
|
203
|
+
**Tavily → Exa → Brave**; override with `--web-search-provider` or the
|
|
204
|
+
`WEB_SEARCH_PROVIDER` env var. Pass `--no-web-search` to suppress the
|
|
205
|
+
tools entirely.
|
|
206
|
+
|
|
207
|
+
**Host-process egress.** Both tools run in the agentic-pi process, **not**
|
|
208
|
+
inside the Gondolin guest. That means:
|
|
209
|
+
|
|
210
|
+
- The provider API host is **not** added to the Gondolin egress
|
|
211
|
+
allowlist, and the API key is **never** injected into the VM.
|
|
212
|
+
- Behavior is identical under `--sandbox=none`, `--sandbox=gondolin`, and
|
|
213
|
+
when agentic-pi itself is containerized. The host's own network policy
|
|
214
|
+
controls reachability to the provider + arbitrary http(s) URLs.
|
|
215
|
+
|
|
216
|
+
**Safety rails (built-in, non-configurable in v1).**
|
|
217
|
+
|
|
218
|
+
| Rail | Default |
|
|
219
|
+
| --- | --- |
|
|
220
|
+
| URL scheme allowlist | `http`, `https` only (`web_fetch`) |
|
|
221
|
+
| Request timeout | 15 s |
|
|
222
|
+
| Max response bytes | 1 MiB (streamed, aborted on overflow) |
|
|
223
|
+
| Max redirects | 3 (scheme re-checked at each hop) |
|
|
224
|
+
| Content-type gate (`web_fetch`) | `text/*`, `application/(xhtml+xml\|xml\|json)` |
|
|
225
|
+
| Max search results | 10 (regardless of `max_results` arg) |
|
|
226
|
+
| Extracted text cap | ~200 KiB |
|
|
227
|
+
| HTML cleaning | `<script>`, `<style>`, `<noscript>`, `<iframe>`, comments stripped before extraction |
|
|
228
|
+
| Per-run call budget | 30 combined `web_search` + `web_fetch` calls (override with `--web-search-max-calls`) |
|
|
229
|
+
|
|
230
|
+
When the call budget is hit, further invocations return a structured
|
|
231
|
+
rate-limit error result so the agent can recover; the run is **not**
|
|
232
|
+
aborted.
|
|
233
|
+
|
|
234
|
+
**No SSRF blocking.** Loopback / private IP ranges are **not** blocked by
|
|
235
|
+
default. Operators who care should run agentic-pi behind their own
|
|
236
|
+
egress firewall.
|
|
237
|
+
|
|
238
|
+
**Event stream.** A second `extension_status` event mirrors GitHub's:
|
|
239
|
+
|
|
240
|
+
```jsonl
|
|
241
|
+
{"type":"extension_status","extension":"web-search","status":"configured","provider":"tavily","toolCount":2,"maxCalls":30,"sessionId":"…","timestamp":"…"}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
When skipped (no keys / `--no-web-search`), `status: "skipped"` carries a
|
|
245
|
+
`reason` of `disabled-by-flag` or `no-credentials`. Misconfigurations
|
|
246
|
+
(explicit provider whose key is missing, or an unknown provider name)
|
|
247
|
+
surface as a warning before the run starts.
|
|
248
|
+
|
|
249
|
+
### 9. Default file search via FFF
|
|
250
|
+
|
|
251
|
+
agentic-pi bundles [`@ff-labs/pi-fff`](https://github.com/dmtrKovalenko/fff/tree/main/packages/pi-fff)
|
|
252
|
+
— a Rust-backed, git-aware, frecency-ranked, SIMD-accelerated fuzzy file/content
|
|
253
|
+
search — as the **default** file-search backend. It ships as a dependency and is
|
|
254
|
+
loaded for **every** run with no per-host `pi install` required.
|
|
255
|
+
|
|
256
|
+
**`override` mode by default.** FFF registers under Pi's built-in tool names
|
|
257
|
+
(`find`, `grep`, `multi_grep`), transparently replacing the built-ins. The agent
|
|
258
|
+
gets faster, git-aware search with zero prompt changes. Switch behaviour with
|
|
259
|
+
`--file-search-mode`:
|
|
260
|
+
|
|
261
|
+
| Mode | Tool names | Notes |
|
|
262
|
+
| --- | --- | --- |
|
|
263
|
+
| `override` (default) | `find`, `grep`, `multi_grep` | Transparent replacement of Pi's built-ins. |
|
|
264
|
+
| `tools-only` | `fffind`, `ffgrep`, `fff-multi-grep` | Added alongside Pi's built-ins; the agent chooses. |
|
|
265
|
+
| `tools-and-ui` | same as `tools-only` | Adds `@`-mention autocomplete — useless headless; not recommended. |
|
|
266
|
+
|
|
267
|
+
The CLI flag maps to FFF's `PI_FFF_MODE` env var. An explicit `PI_FFF_MODE` in the
|
|
268
|
+
environment wins over the flag. Pass `--no-file-search` to disable FFF entirely and
|
|
269
|
+
fall back to Pi's built-in `find`/`grep`.
|
|
270
|
+
|
|
271
|
+
**Host-process execution.** Like web search, FFF runs in the agentic-pi process,
|
|
272
|
+
**not** inside the Gondolin guest. Under `--sandbox gondolin`, `read`/`write`/`edit`/
|
|
273
|
+
`bash` route through the VM while `find`/`grep` (FFF) run host-side against the
|
|
274
|
+
bind-mounted workspace. Paths align (cwd is the mount), and FFF only touches the
|
|
275
|
+
local filesystem — no egress or secret exposure.
|
|
276
|
+
|
|
277
|
+
**Native binary.** FFF is a native Rust library (`@ff-labs/fff-node`) shipped as
|
|
278
|
+
prebuilt per-platform binaries (`fff-bin-linux-x64-gnu`/`-musl`, `darwin`, `win32`).
|
|
279
|
+
npm auto-selects the correct one at install time. In containers, run `npm install`
|
|
280
|
+
on the target platform — do **not** copy `node_modules` across glibc↔musl.
|
|
281
|
+
|
|
282
|
+
**Safe by default.** If pi-fff can't be resolved or its native binary fails to load
|
|
283
|
+
on the platform, the run is **not** aborted — file search skips with
|
|
284
|
+
`reason: "resolve-failed"` (surfaced as a warning) and the agent falls back to Pi's
|
|
285
|
+
built-in `find`/`grep`.
|
|
286
|
+
|
|
287
|
+
**Event stream.** A third `extension_status` event mirrors the others:
|
|
288
|
+
|
|
289
|
+
```jsonl
|
|
290
|
+
{"type":"extension_status","extension":"file-search","status":"configured","mode":"override","toolCount":3,"sessionId":"…","timestamp":"…"}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
When disabled or unavailable, `status: "skipped"` carries a `reason` of
|
|
294
|
+
`disabled-by-flag` or `resolve-failed`.
|
|
295
|
+
|
|
198
296
|
## When to use this
|
|
199
297
|
|
|
200
298
|
- You have an orchestrator that calls a coding agent once per workflow
|
|
201
299
|
phase, in a container, and parses a JSONL stream.
|
|
202
|
-
- You used to call `opencode run --format json` and want a less-opaque
|
|
203
|
-
replacement built on a more hackable substrate.
|
|
204
300
|
- You need GitHub repo operations available to the agent without standing
|
|
205
301
|
up an MCP server.
|
|
302
|
+
- You want safe, sandbox-mode-agnostic web search available to the agent.
|
|
206
303
|
|
|
207
304
|
## When **not** to use this
|
|
208
305
|
|
|
@@ -211,8 +308,9 @@ overrides the auto-injected value if you need to scope down further.
|
|
|
211
308
|
- You want generic MCP support. Pi has none by design and agentic-pi inherits
|
|
212
309
|
that decision; only the GitHub tool surface is built-in.
|
|
213
310
|
- You want a different tool surface (Linear, GitLab, internal APIs). Fork the
|
|
214
|
-
`extensions/github/` directory as a template
|
|
215
|
-
|
|
311
|
+
`extensions/github/` directory as a template. agentic-pi bundles specific Pi
|
|
312
|
+
extensions (GitHub, web search, FFF file search) but does not (yet) load
|
|
313
|
+
arbitrary operator-supplied extensions as a runtime plugin system.
|
|
216
314
|
|
|
217
315
|
## Usage
|
|
218
316
|
|
|
@@ -245,16 +343,21 @@ GITHUB_TOKEN=ghp_…
|
|
|
245
343
|
| --- | --- |
|
|
246
344
|
| `--model <provider/id>` | Required. e.g. `anthropic/claude-opus-4-5`, `openai/gpt-4o`. |
|
|
247
345
|
| `--thinking <level>` | `off` \| `minimal` \| `low` \| `medium` \| `high` \| `xhigh`. |
|
|
248
|
-
| `--variant <level>` | Alias for `--thinking`. |
|
|
249
346
|
| `--profile <name>` | `read` \| `issues-write` \| `review-write` \| `repo-write`. Omit to disable GitHub tools entirely. |
|
|
250
347
|
| `--cwd <path>` | Working directory for the agent. Default: `$PWD`. |
|
|
251
348
|
| `--no-session` | Ephemeral run — do not persist session jsonl. Recommended in sandboxed containers. |
|
|
252
349
|
| `--session-dir <path>` | Override session storage location. |
|
|
253
350
|
| `--no-builtin-tools` | Disable Pi's `read,write,edit,bash,grep,find,ls`. |
|
|
254
351
|
| `--tools <a,b,c>` | Explicit tool allowlist (combined with profile if set). |
|
|
255
|
-
| `--sandbox <none\|gondolin>` | Route `read`/`write`/`edit`/`bash` through a sandbox backend. Default `none`. `gondolin` boots a QEMU micro-VM mounting cwd at `/workspace`. Requires QEMU on the host; native-only (not Docker-in-Docker). See section
|
|
352
|
+
| `--sandbox <none\|gondolin>` | Route `read`/`write`/`edit`/`bash` through a sandbox backend. Default `none`. `gondolin` boots a QEMU micro-VM mounting cwd at `/workspace`. Requires QEMU on the host; native-only (not Docker-in-Docker). See section 7. |
|
|
256
353
|
| `--sandbox-env KEY=VAL` | Inject env var into the sandbox VM (repeatable). Ignored when `--sandbox=none`. Auto-injects a minted `GITHUB_TOKEN`/`GH_TOKEN` when `--profile` is also active. |
|
|
257
|
-
| `--
|
|
354
|
+
| `--allow-host <host>` | Add host to the sandbox HTTP egress allowlist (repeatable). Ignored when `--sandbox=none`. |
|
|
355
|
+
| `--no-network` | Disable sandbox HTTP egress entirely. Ignored when `--sandbox=none`. |
|
|
356
|
+
| `--web-search-provider <p>` | Force web-search provider: `tavily` \| `brave` \| `exa`. Default: auto-detect by env. See section 8. |
|
|
357
|
+
| `--no-web-search` | Disable the web-search extension (no `web_search`/`web_fetch` tools). |
|
|
358
|
+
| `--no-file-search` | Disable the bundled FFF file-search extension; fall back to Pi's built-in `find`/`grep`. |
|
|
359
|
+
| `--file-search-mode <m>` | FFF mode: `override` (default) \| `tools-only` \| `tools-and-ui`. Overridden by the `PI_FFF_MODE` env var. See section 9. |
|
|
360
|
+
| `--web-search-max-calls <n>` | Cap combined `web_search` + `web_fetch` calls per run. Default: 30. |
|
|
258
361
|
|
|
259
362
|
Reads the prompt from stdin. Emits JSONL on stdout. Exits 0 on `agent_end`,
|
|
260
363
|
1 on fatal error.
|
|
@@ -265,6 +368,8 @@ Reads the prompt from stdin. Emits JSONL on stdout. Exits 0 on `agent_end`,
|
|
|
265
368
|
{"type":"session","version":3,"id":"<uuid>","timestamp":"…","cwd":"…"}
|
|
266
369
|
{"type":"sandbox_status","backend":"none","status":{"backend":"none"},"sessionId":"<uuid>","timestamp":"…"}
|
|
267
370
|
{"type":"extension_status","extension":"github","status":"configured","profile":"read","toolCount":18,"sessionId":"<uuid>","timestamp":"…"}
|
|
371
|
+
{"type":"extension_status","extension":"web-search","status":"configured","provider":"tavily","toolCount":2,"maxCalls":30,"sessionId":"<uuid>","timestamp":"…"}
|
|
372
|
+
{"type":"extension_status","extension":"file-search","status":"configured","mode":"override","toolCount":3,"sessionId":"<uuid>","timestamp":"…"}
|
|
268
373
|
{"type":"agent_start","sessionId":"<uuid>","timestamp":"…"}
|
|
269
374
|
{"type":"turn_start","sessionId":"<uuid>","timestamp":"…"}
|
|
270
375
|
{"type":"message_start","message":{…},"sessionId":"<uuid>","timestamp":"…"}
|
|
@@ -343,7 +448,9 @@ console.log(result.records.length); // full event log
|
|
|
343
448
|
| `messages` | `unknown[]` | Full Pi message array from `agent_end`. |
|
|
344
449
|
| `stats` | `{userMessages, assistantMessages, toolCalls, toolResults, tokens: {input, output, cacheRead, cacheWrite, total}, cost}` \| `undefined` | Token + cost rollup. |
|
|
345
450
|
| `sandbox` | `{backend, status}` \| `undefined` | Mirror of the `sandbox_status` event. |
|
|
346
|
-
| `github` | `{status, reason, profile, toolCount}` \| `undefined` | Mirror of the `extension_status` event. |
|
|
451
|
+
| `github` | `{status, reason, profile, toolCount}` \| `undefined` | Mirror of the GitHub `extension_status` event. |
|
|
452
|
+
| `webSearch` | `{status, reason, provider, toolCount, maxCalls}` \| `undefined` | Mirror of the web-search `extension_status` event. |
|
|
453
|
+
| `fileSearch` | `{status, reason, mode, toolCount}` \| `undefined` | Mirror of the FFF file-search `extension_status` event. |
|
|
347
454
|
| `records` | `EmitterRecord[]` | Every JSONL record in order. Same shape that the CLI writes. |
|
|
348
455
|
| `warnings` | `string[]` | Warnings that would have gone to stderr in CLI mode. |
|
|
349
456
|
|
|
@@ -394,6 +501,8 @@ which walks `test/` for `*.test.ts`.
|
|
|
394
501
|
| `test/models.test.ts` | `provider/id` parsing including openrouter triple-slash | — |
|
|
395
502
|
| `test/extensions/github/profiles.test.ts` | Profile → tool allowlist (counts, superset structure, scope tiering) | — |
|
|
396
503
|
| `test/extensions/github/credentials.test.ts` | `assertSafeToken` and `credentialsFilePath` validation | — |
|
|
504
|
+
| `test/extensions/web-search/*.test.ts` | Provider selection, extension wiring, safe-fetch rails, HTML extraction, rate limiter, per-provider normalization (all with injected `fetchImpl`) | — |
|
|
505
|
+
| `test/extensions/file-search/index.test.ts` | FFF extension wiring: mode → tool names, package resolution, disabled-by-flag + resolve-failed skips | — |
|
|
397
506
|
| `test/sandbox/preflight.test.ts` | Preflight returns a structured ok\|error result | — |
|
|
398
507
|
| `test/run.integration.test.ts` | Programmatic `run()`: RunResult populated, onEvent fires for every record, **child-process check confirms zero stdout/stderr leak from library** | `OPENAI_API_KEY` not set |
|
|
399
508
|
| `test/run-sandbox.integration.test.ts` | `run({ sandbox: "gondolin" })` boots a VM, agent's `write` tool produces a host file via the mount | `OPENAI_API_KEY` not set OR QEMU/preflight unavailable |
|
|
@@ -465,6 +574,8 @@ src/
|
|
|
465
574
|
credentials.ts git credential-store file writer (mode 600)
|
|
466
575
|
profiles.ts 4 profiles → tool name allowlists
|
|
467
576
|
tools.ts 31 defineTool() registrations
|
|
577
|
+
extensions/file-search/
|
|
578
|
+
index.ts loadFileSearchExtension() — resolves bundled @ff-labs/pi-fff
|
|
468
579
|
sandbox/
|
|
469
580
|
index.ts buildSandbox(backend) dispatcher
|
|
470
581
|
preflight.ts QEMU + accelerator detection (refuses to start if hung)
|
package/dist/args.d.ts
CHANGED
|
@@ -60,6 +60,33 @@ export interface RunConfig {
|
|
|
60
60
|
* entirely. Ignored when `sandbox === "none"`.
|
|
61
61
|
*/
|
|
62
62
|
allowedHttpHosts?: string[] | null;
|
|
63
|
+
/**
|
|
64
|
+
* Web-search extension toggle. Default: true (auto-enables when a
|
|
65
|
+
* provider API key env var is present). Pass `--no-web-search` to
|
|
66
|
+
* force-disable.
|
|
67
|
+
*/
|
|
68
|
+
webSearch: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Explicit web-search provider. Overrides auto-detection by env var.
|
|
71
|
+
* Set via `--web-search-provider <tavily|brave|exa>`.
|
|
72
|
+
*/
|
|
73
|
+
webSearchProvider?: string;
|
|
74
|
+
/**
|
|
75
|
+
* Per-run cap on combined web_search + web_fetch calls. Default: 30.
|
|
76
|
+
* Set via `--web-search-max-calls <n>`.
|
|
77
|
+
*/
|
|
78
|
+
webSearchMaxCalls?: number;
|
|
79
|
+
/**
|
|
80
|
+
* File-search extension (FFF) toggle. Default: true — bundled and
|
|
81
|
+
* enabled for every run. Pass `--no-file-search` to fall back to Pi's
|
|
82
|
+
* built-in find/grep.
|
|
83
|
+
*/
|
|
84
|
+
fileSearch: boolean;
|
|
85
|
+
/**
|
|
86
|
+
* FFF mode. Default: "override" (FFF replaces built-in find/grep under
|
|
87
|
+
* the same names). Set via `--file-search-mode <override|tools-only|tools-and-ui>`.
|
|
88
|
+
*/
|
|
89
|
+
fileSearchMode?: "override" | "tools-only" | "tools-and-ui";
|
|
63
90
|
}
|
|
64
91
|
export declare function printHelp(): void;
|
|
65
92
|
export declare function parseArgs(argv: string[]): RunConfig;
|
package/dist/args.js
CHANGED
|
@@ -34,6 +34,20 @@ Flags:
|
|
|
34
34
|
Ignored when --sandbox=none.
|
|
35
35
|
--no-network Disable HTTP egress from the sandbox entirely.
|
|
36
36
|
Ignored when --sandbox=none.
|
|
37
|
+
--web-search-provider <p> Force a web-search provider: tavily | brave | exa.
|
|
38
|
+
Default: auto-detect from env (Tavily > Exa > Brave).
|
|
39
|
+
Provider's API key env var must be set:
|
|
40
|
+
TAVILY_API_KEY, EXA_API_KEY, or BRAVE_SEARCH_API_KEY.
|
|
41
|
+
--no-web-search Disable the web-search extension entirely
|
|
42
|
+
(web_search / web_fetch tools not registered).
|
|
43
|
+
--web-search-max-calls <n> Cap combined web_search + web_fetch calls per run.
|
|
44
|
+
Default: 30. When exceeded, further calls return a
|
|
45
|
+
structured error result.
|
|
46
|
+
--no-file-search Disable the bundled FFF file-search extension; fall
|
|
47
|
+
back to Pi's built-in find/grep.
|
|
48
|
+
--file-search-mode <m> FFF mode: override | tools-only | tools-and-ui.
|
|
49
|
+
Default: override (FFF replaces built-in find/grep
|
|
50
|
+
under the same names). Overridden by PI_FFF_MODE env.
|
|
37
51
|
--sandbox-image <name> Image to boot when --sandbox=gondolin. Values:
|
|
38
52
|
'default' (recommended) — bundled agentic-pi-dev image
|
|
39
53
|
with git/gh/node/python/rust baked in (auto-downloaded).
|
|
@@ -54,6 +68,8 @@ export function parseArgs(argv) {
|
|
|
54
68
|
noBuiltinTools: false,
|
|
55
69
|
dangerouslySkipPermissions: false,
|
|
56
70
|
sandbox: "none",
|
|
71
|
+
webSearch: true,
|
|
72
|
+
fileSearch: true,
|
|
57
73
|
};
|
|
58
74
|
for (let i = 0; i < argv.length; i++) {
|
|
59
75
|
const arg = argv[i];
|
|
@@ -147,6 +163,36 @@ export function parseArgs(argv) {
|
|
|
147
163
|
case "--no-network":
|
|
148
164
|
config.allowedHttpHosts = null;
|
|
149
165
|
break;
|
|
166
|
+
case "--no-web-search":
|
|
167
|
+
config.webSearch = false;
|
|
168
|
+
break;
|
|
169
|
+
case "--web-search-provider": {
|
|
170
|
+
const v = next().trim();
|
|
171
|
+
if (!v)
|
|
172
|
+
throw new Error("--web-search-provider requires a value");
|
|
173
|
+
config.webSearchProvider = v;
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
case "--web-search-max-calls": {
|
|
177
|
+
const v = next();
|
|
178
|
+
const n = Number(v);
|
|
179
|
+
if (!Number.isFinite(n) || Math.floor(n) !== n || n < 1) {
|
|
180
|
+
throw new Error(`--web-search-max-calls must be a positive integer (got '${v}')`);
|
|
181
|
+
}
|
|
182
|
+
config.webSearchMaxCalls = n;
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
case "--no-file-search":
|
|
186
|
+
config.fileSearch = false;
|
|
187
|
+
break;
|
|
188
|
+
case "--file-search-mode": {
|
|
189
|
+
const v = next();
|
|
190
|
+
if (v !== "override" && v !== "tools-only" && v !== "tools-and-ui") {
|
|
191
|
+
throw new Error(`invalid --file-search-mode '${v}'. Expected: override | tools-only | tools-and-ui`);
|
|
192
|
+
}
|
|
193
|
+
config.fileSearchMode = v;
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
150
196
|
case "-h":
|
|
151
197
|
case "--help":
|
|
152
198
|
printHelp();
|
package/dist/args.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAsFH,MAAM,UAAU,SAAS;IACvB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoDtB,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAc;IACtC,MAAM,MAAM,GAAc;QACxB,KAAK,EAAE,EAAE;QACT,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;QAClB,SAAS,EAAE,KAAK;QAChB,cAAc,EAAE,KAAK;QACrB,0BAA0B,EAAE,KAAK;QACjC,OAAO,EAAE,MAAM;QACf,SAAS,EAAE,IAAI;QACf,UAAU,EAAE,IAAI;KACjB,CAAC;IAEF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,MAAM,IAAI,GAAG,GAAW,EAAE;YACxB,MAAM,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YACpB,IAAI,CAAC,KAAK,SAAS;gBAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,GAAG,mBAAmB,CAAC,CAAC;YACrE,OAAO,CAAC,CAAC;QACX,CAAC,CAAC;QACF,QAAQ,GAAG,EAAE,CAAC;YACZ,KAAK,SAAS,CAAC;YACf,KAAK,IAAI;gBACP,MAAM,CAAC,KAAK,GAAG,IAAI,EAAE,CAAC;gBACtB,MAAM;YACR,KAAK,YAAY,CAAC;YAClB,KAAK,WAAW,CAAC,CAAC,CAAC;gBACjB,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;gBACjB,IAAI,CAAC,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;oBACtE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,EAAE,CAAC,CAAC;gBACpD,CAAC;gBACD,MAAM,CAAC,QAAQ,GAAG,CAA0B,CAAC;gBAC7C,MAAM;YACR,CAAC;YACD,KAAK,WAAW;gBACd,MAAM,CAAC,OAAO,GAAG,IAAI,EAAE,CAAC;gBACxB,MAAM;YACR,KAAK,OAAO;gBACV,MAAM,CAAC,GAAG,GAAG,IAAI,EAAE,CAAC;gBACpB,MAAM;YACR,KAAK,cAAc;gBACjB,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC;gBACxB,MAAM;YACR,KAAK,eAAe;gBAClB,MAAM,CAAC,UAAU,GAAG,IAAI,EAAE,CAAC;gBAC3B,MAAM;YACR,KAAK,oBAAoB;gBACvB,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC;gBAC7B,MAAM;YACR,KAAK,SAAS;gBACZ,MAAM,CAAC,KAAK,GAAG,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBACtE,MAAM;YACR,KAAK,gCAAgC;gBACnC,MAAM,CAAC,0BAA0B,GAAG,IAAI,CAAC;gBACzC,MAAM;YACR,KAAK,WAAW,CAAC,CAAC,CAAC;gBACjB,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;gBACjB,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,UAAU,EAAE,CAAC;oBACrC,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,8BAA8B,CAAC,CAAC;gBACzE,CAAC;gBACD,MAAM,CAAC,OAAO,GAAG,CAAC,CAAC;gBACnB,MAAM;YACR,CAAC;YACD,KAAK,iBAAiB,CAAC,CAAC,CAAC;gBACvB,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;gBACjB,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACnB,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;gBAChE,CAAC;gBACD,MAAM,CAAC,YAAY,GAAG,CAAC,CAAC;gBACxB,MAAM;YACR,CAAC;YACD,KAAK,eAAe,CAAC,CAAC,CAAC;gBACrB,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;gBACjB,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAC1B,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;oBACX,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,IAAI,CAAC,CAAC;gBAChE,CAAC;gBACD,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC3B,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;gBAC5B,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC1C,MAAM,IAAI,KAAK,CAAC,6DAA6D,GAAG,IAAI,CAAC,CAAC;gBACxF,CAAC;gBACD,MAAM,CAAC,UAAU,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC;gBACjE,MAAM;YACR,CAAC;YACD,KAAK,cAAc,CAAC,CAAC,CAAC;gBACpB,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;gBACxB,IAAI,CAAC,CAAC;oBAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;gBAClE,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;oBAClC,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,IAAI,CAAC,CAAC;gBACtE,CAAC;gBACD,gEAAgE;gBAChE,gEAAgE;gBAChE,+DAA+D;gBAC/D,gEAAgE;gBAChE,kEAAkE;gBAClE,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;gBAClF,MAAM,CAAC,gBAAgB,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC;gBACtC,MAAM;YACR,CAAC;YACD,KAAK,cAAc;gBACjB,MAAM,CAAC,gBAAgB,GAAG,IAAI,CAAC;gBAC/B,MAAM;YACR,KAAK,iBAAiB;gBACpB,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC;gBACzB,MAAM;YACR,KAAK,uBAAuB,CAAC,CAAC,CAAC;gBAC7B,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;gBACxB,IAAI,CAAC,CAAC;oBAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;gBAClE,MAAM,CAAC,iBAAiB,GAAG,CAAC,CAAC;gBAC7B,MAAM;YACR,CAAC;YACD,KAAK,wBAAwB,CAAC,CAAC,CAAC;gBAC9B,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;gBACjB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;gBACpB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;oBACxD,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,IAAI,CAAC,CAAC;gBACpF,CAAC;gBACD,MAAM,CAAC,iBAAiB,GAAG,CAAC,CAAC;gBAC7B,MAAM;YACR,CAAC;YACD,KAAK,kBAAkB;gBACrB,MAAM,CAAC,UAAU,GAAG,KAAK,CAAC;gBAC1B,MAAM;YACR,KAAK,oBAAoB,CAAC,CAAC,CAAC;gBAC1B,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;gBACjB,IAAI,CAAC,KAAK,UAAU,IAAI,CAAC,KAAK,YAAY,IAAI,CAAC,KAAK,cAAc,EAAE,CAAC;oBACnE,MAAM,IAAI,KAAK,CACb,+BAA+B,CAAC,mDAAmD,CACpF,CAAC;gBACJ,CAAC;gBACD,MAAM,CAAC,cAAc,GAAG,CAAC,CAAC;gBAC1B,MAAM;YACR,CAAC;YACD,KAAK,IAAI,CAAC;YACV,KAAK,QAAQ;gBACX,SAAS,EAAE,CAAC;gBACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB;gBACE,MAAM,IAAI,KAAK,CAAC,iBAAiB,GAAG,EAAE,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;IAC3E,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,uCAAuC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC;IAC1E,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File-search extension entry point.
|
|
3
|
+
*
|
|
4
|
+
* Bundles FFF (`@ff-labs/pi-fff`) — a Rust-backed, git-aware,
|
|
5
|
+
* frecency-ranked fuzzy file/content search — as agentic-pi's default
|
|
6
|
+
* file-search backend, so every run gets it without a per-host
|
|
7
|
+
* `pi install`.
|
|
8
|
+
*
|
|
9
|
+
* Unlike the `github` and `web-search` extensions, this one does NOT
|
|
10
|
+
* contribute a `customTools` array. pi-fff is a full Pi extension
|
|
11
|
+
* (registers tools + an `@`-mention enhancer via an ExtensionFactory), so
|
|
12
|
+
* it is loaded through Pi's resource loader, not the SDK's `customTools`
|
|
13
|
+
* channel. This module's job is to:
|
|
14
|
+
*
|
|
15
|
+
* 1. Resolve the installed pi-fff package directory (the value the
|
|
16
|
+
* runner hands to `DefaultResourceLoader.additionalExtensionPaths`).
|
|
17
|
+
* 2. Decide the FFF mode the runner publishes via the `PI_FFF_MODE` env.
|
|
18
|
+
*
|
|
19
|
+
* Mirrors the other extensions' "safe by default" contract: if the
|
|
20
|
+
* package can't be resolved (missing / incompatible native binary), we
|
|
21
|
+
* skip with a reason rather than aborting the run, and the agent falls
|
|
22
|
+
* back to Pi's built-in `find`/`grep`.
|
|
23
|
+
*/
|
|
24
|
+
/** FFF mode. `override` replaces Pi's built-in find/grep under the same names. */
|
|
25
|
+
export type FileSearchMode = "override" | "tools-only" | "tools-and-ui";
|
|
26
|
+
export declare const VALID_FILE_SEARCH_MODES: FileSearchMode[];
|
|
27
|
+
export declare const DEFAULT_FILE_SEARCH_MODE: FileSearchMode;
|
|
28
|
+
export type FileSearchSkipReason = "disabled-by-flag" | "resolve-failed";
|
|
29
|
+
export interface FileSearchExtensionConfig {
|
|
30
|
+
/** When false, the extension is force-skipped (disabled-by-flag). Default: true. */
|
|
31
|
+
fileSearch?: boolean;
|
|
32
|
+
/** FFF mode. Default: "override". */
|
|
33
|
+
fileSearchMode?: FileSearchMode;
|
|
34
|
+
/**
|
|
35
|
+
* Resolver override (injected by tests). Returns the absolute path to the
|
|
36
|
+
* installed `@ff-labs/pi-fff` package directory, or throws.
|
|
37
|
+
*/
|
|
38
|
+
resolvePackageDir?: () => string;
|
|
39
|
+
}
|
|
40
|
+
export interface FileSearchExtensionResult {
|
|
41
|
+
status: "configured" | "skipped";
|
|
42
|
+
reason?: FileSearchSkipReason;
|
|
43
|
+
message?: string;
|
|
44
|
+
/** The FFF mode in effect (echoed for observability). */
|
|
45
|
+
mode?: FileSearchMode;
|
|
46
|
+
/**
|
|
47
|
+
* Absolute path to the pi-fff package directory. The runner passes this
|
|
48
|
+
* to `DefaultResourceLoader.additionalExtensionPaths`. Undefined when
|
|
49
|
+
* skipped.
|
|
50
|
+
*/
|
|
51
|
+
packageDir?: string;
|
|
52
|
+
/**
|
|
53
|
+
* Tool names the agent will see, derived from `mode` (for the
|
|
54
|
+
* `extension_status` event only — the tools themselves are registered by
|
|
55
|
+
* pi-fff, not here).
|
|
56
|
+
*/
|
|
57
|
+
toolNames: string[];
|
|
58
|
+
}
|
|
59
|
+
export declare function loadFileSearchExtension(config?: FileSearchExtensionConfig): FileSearchExtensionResult;
|
|
60
|
+
/**
|
|
61
|
+
* True if the skip is something the user almost certainly wants surfaced
|
|
62
|
+
* as a warning. A resolve failure means file search was meant to work but
|
|
63
|
+
* the install/binary is broken; `disabled-by-flag` is an explicit choice
|
|
64
|
+
* and stays silent.
|
|
65
|
+
*/
|
|
66
|
+
export declare function isMisconfigurationSkip(result: FileSearchExtensionResult): boolean;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File-search extension entry point.
|
|
3
|
+
*
|
|
4
|
+
* Bundles FFF (`@ff-labs/pi-fff`) — a Rust-backed, git-aware,
|
|
5
|
+
* frecency-ranked fuzzy file/content search — as agentic-pi's default
|
|
6
|
+
* file-search backend, so every run gets it without a per-host
|
|
7
|
+
* `pi install`.
|
|
8
|
+
*
|
|
9
|
+
* Unlike the `github` and `web-search` extensions, this one does NOT
|
|
10
|
+
* contribute a `customTools` array. pi-fff is a full Pi extension
|
|
11
|
+
* (registers tools + an `@`-mention enhancer via an ExtensionFactory), so
|
|
12
|
+
* it is loaded through Pi's resource loader, not the SDK's `customTools`
|
|
13
|
+
* channel. This module's job is to:
|
|
14
|
+
*
|
|
15
|
+
* 1. Resolve the installed pi-fff package directory (the value the
|
|
16
|
+
* runner hands to `DefaultResourceLoader.additionalExtensionPaths`).
|
|
17
|
+
* 2. Decide the FFF mode the runner publishes via the `PI_FFF_MODE` env.
|
|
18
|
+
*
|
|
19
|
+
* Mirrors the other extensions' "safe by default" contract: if the
|
|
20
|
+
* package can't be resolved (missing / incompatible native binary), we
|
|
21
|
+
* skip with a reason rather than aborting the run, and the agent falls
|
|
22
|
+
* back to Pi's built-in `find`/`grep`.
|
|
23
|
+
*/
|
|
24
|
+
import { createRequire } from "node:module";
|
|
25
|
+
import { dirname } from "node:path";
|
|
26
|
+
export const VALID_FILE_SEARCH_MODES = [
|
|
27
|
+
"override",
|
|
28
|
+
"tools-only",
|
|
29
|
+
"tools-and-ui",
|
|
30
|
+
];
|
|
31
|
+
export const DEFAULT_FILE_SEARCH_MODE = "override";
|
|
32
|
+
/** Tool names FFF exposes per mode (see @ff-labs/pi-fff src/index.ts). */
|
|
33
|
+
function toolNamesForMode(mode) {
|
|
34
|
+
return mode === "override"
|
|
35
|
+
? ["find", "grep", "multi_grep"]
|
|
36
|
+
: ["fffind", "ffgrep", "fff-multi-grep"];
|
|
37
|
+
}
|
|
38
|
+
function defaultResolvePackageDir() {
|
|
39
|
+
// Resolve relative to this module so it works regardless of the
|
|
40
|
+
// consumer's cwd. `@ff-labs/pi-fff/package.json` is always present; its
|
|
41
|
+
// directory is what the loader's package resolver reads the `pi`
|
|
42
|
+
// manifest from.
|
|
43
|
+
const require = createRequire(import.meta.url);
|
|
44
|
+
return dirname(require.resolve("@ff-labs/pi-fff/package.json"));
|
|
45
|
+
}
|
|
46
|
+
export function loadFileSearchExtension(config = {}) {
|
|
47
|
+
if (config.fileSearch === false) {
|
|
48
|
+
return {
|
|
49
|
+
status: "skipped",
|
|
50
|
+
reason: "disabled-by-flag",
|
|
51
|
+
message: "file search disabled via --no-file-search",
|
|
52
|
+
toolNames: [],
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
const mode = config.fileSearchMode ?? DEFAULT_FILE_SEARCH_MODE;
|
|
56
|
+
const resolve = config.resolvePackageDir ?? defaultResolvePackageDir;
|
|
57
|
+
let packageDir;
|
|
58
|
+
try {
|
|
59
|
+
packageDir = resolve();
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
return {
|
|
63
|
+
status: "skipped",
|
|
64
|
+
reason: "resolve-failed",
|
|
65
|
+
message: `could not resolve @ff-labs/pi-fff: ${err.message}`,
|
|
66
|
+
mode,
|
|
67
|
+
toolNames: [],
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
status: "configured",
|
|
72
|
+
mode,
|
|
73
|
+
packageDir,
|
|
74
|
+
toolNames: toolNamesForMode(mode),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* True if the skip is something the user almost certainly wants surfaced
|
|
79
|
+
* as a warning. A resolve failure means file search was meant to work but
|
|
80
|
+
* the install/binary is broken; `disabled-by-flag` is an explicit choice
|
|
81
|
+
* and stays silent.
|
|
82
|
+
*/
|
|
83
|
+
export function isMisconfigurationSkip(result) {
|
|
84
|
+
return result.status === "skipped" && result.reason === "resolve-failed";
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/extensions/file-search/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,MAAM,CAAC,MAAM,uBAAuB,GAAqB;IACvD,UAAU;IACV,YAAY;IACZ,cAAc;CACf,CAAC;AAEF,MAAM,CAAC,MAAM,wBAAwB,GAAmB,UAAU,CAAC;AAoCnE,0EAA0E;AAC1E,SAAS,gBAAgB,CAAC,IAAoB;IAC5C,OAAO,IAAI,KAAK,UAAU;QACxB,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC;QAChC,CAAC,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,wBAAwB;IAC/B,gEAAgE;IAChE,wEAAwE;IACxE,iEAAiE;IACjE,iBAAiB;IACjB,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,OAAO,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,8BAA8B,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,SAAoC,EAAE;IAEtC,IAAI,MAAM,CAAC,UAAU,KAAK,KAAK,EAAE,CAAC;QAChC,OAAO;YACL,MAAM,EAAE,SAAS;YACjB,MAAM,EAAE,kBAAkB;YAC1B,OAAO,EAAE,2CAA2C;YACpD,SAAS,EAAE,EAAE;SACd,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,CAAC,cAAc,IAAI,wBAAwB,CAAC;IAC/D,MAAM,OAAO,GAAG,MAAM,CAAC,iBAAiB,IAAI,wBAAwB,CAAC;IAErE,IAAI,UAAkB,CAAC;IACvB,IAAI,CAAC;QACH,UAAU,GAAG,OAAO,EAAE,CAAC;IACzB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,MAAM,EAAE,SAAS;YACjB,MAAM,EAAE,gBAAgB;YACxB,OAAO,EAAE,sCAAuC,GAAa,CAAC,OAAO,EAAE;YACvE,IAAI;YACJ,SAAS,EAAE,EAAE;SACd,CAAC;IACJ,CAAC;IAED,OAAO;QACL,MAAM,EAAE,YAAY;QACpB,IAAI;QACJ,UAAU;QACV,SAAS,EAAE,gBAAgB,CAAC,IAAI,CAAC;KAClC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAiC;IACtE,OAAO,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,gBAAgB,CAAC;AAC3E,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal HTML → readable text extractor. No dependencies.
|
|
3
|
+
*
|
|
4
|
+
* Approach:
|
|
5
|
+
* 1. Strip <script>, <style>, <noscript>, <iframe>, and HTML comments
|
|
6
|
+
* so the agent never sees code or hidden trackers.
|
|
7
|
+
* 2. Replace block-level tags with newlines so paragraphs stay separated.
|
|
8
|
+
* 3. Drop all other tags.
|
|
9
|
+
* 4. Decode the common named entities and any &#NN; / &#xHH; numeric
|
|
10
|
+
* escapes.
|
|
11
|
+
* 5. Collapse runs of whitespace; cap output at MAX_BYTES.
|
|
12
|
+
*
|
|
13
|
+
* Not a Readability-style content-only extractor — for that, use Tavily or
|
|
14
|
+
* Exa's native extraction, which the provider clients invoke directly.
|
|
15
|
+
*/
|
|
16
|
+
export declare const EXTRACT_MAX_BYTES: number;
|
|
17
|
+
export declare function extractTitle(html: string): string | undefined;
|
|
18
|
+
export declare function htmlToText(html: string, maxBytes?: number): string;
|