webfox 0.0.0-test.0 → 4.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.
Files changed (118) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +256 -3
  3. package/assets/webfox-lockup-dark.png +0 -0
  4. package/assets/webfox-lockup.png +0 -0
  5. package/dist/adapter-2YBFCBCZ.js +161 -0
  6. package/dist/adapter-67TIISDW.js +753 -0
  7. package/dist/adapter-AB7LKV7N.js +324 -0
  8. package/dist/adapter-AUYLTDPM.js +73 -0
  9. package/dist/adapter-HITGYUXN.js +494 -0
  10. package/dist/adapter-HPTMLH75.js +334 -0
  11. package/dist/adapter-I6OUKBZQ.js +492 -0
  12. package/dist/adapter-ISZQTZDP.js +166 -0
  13. package/dist/adapter-MAG7X663.js +230 -0
  14. package/dist/adapter-NEXSOHGT.js +232 -0
  15. package/dist/adapter-PADXKW43.js +162 -0
  16. package/dist/adapter-SDQX2533.js +123 -0
  17. package/dist/adapter-UAZNLDSS.js +237 -0
  18. package/dist/adapter-XBAQSK7I.js +282 -0
  19. package/dist/application-types.d.ts +34 -0
  20. package/dist/application.d.ts +2 -0
  21. package/dist/chunk-EF4VMDZL.js +85 -0
  22. package/dist/chunk-G2YAQEET.js +38 -0
  23. package/dist/chunk-I2UIACY3.js +12 -0
  24. package/dist/chunk-L425U55P.js +3051 -0
  25. package/dist/chunk-QRHDXM2L.js +31 -0
  26. package/dist/chunk-SMF5ALX7.js +762 -0
  27. package/dist/chunk-U4BLULLV.js +52 -0
  28. package/dist/chunk-WCTOYZVB.js +85 -0
  29. package/dist/chunk-X6ZBIHZC.js +21 -0
  30. package/dist/chunk-YZXM4U2C.js +21 -0
  31. package/dist/chunk-ZVTVERW5.js +20 -0
  32. package/dist/cli.js +641 -0
  33. package/dist/config.schema.json +4270 -0
  34. package/dist/configuration/defaults.d.ts +3 -0
  35. package/dist/configuration/file.d.ts +17 -0
  36. package/dist/configuration/options-schema.d.ts +2 -0
  37. package/dist/configuration/planning.d.ts +10 -0
  38. package/dist/configuration/schema.d.ts +9 -0
  39. package/dist/configuration/types.d.ts +37 -0
  40. package/dist/contents.d.ts +19 -0
  41. package/dist/domain.d.ts +89 -0
  42. package/dist/errors.d.ts +17 -0
  43. package/dist/index.d.ts +8 -0
  44. package/dist/index.js +38 -0
  45. package/dist/package-metadata.d.ts +3 -0
  46. package/dist/pi-keybindings.d.ts +1 -0
  47. package/dist/pi-params.d.ts +3 -0
  48. package/dist/pi-render.d.ts +50 -0
  49. package/dist/pi-search-render.d.ts +4 -0
  50. package/dist/pi-text.d.ts +4 -0
  51. package/dist/pi-validation.d.ts +4 -0
  52. package/dist/pi.d.ts +2 -0
  53. package/dist/pi.js +563 -0
  54. package/dist/providers/brave/adapter.d.ts +7 -0
  55. package/dist/providers/brave/definition.d.ts +1 -0
  56. package/dist/providers/brave/types.d.ts +4 -0
  57. package/dist/providers/cli-json.d.ts +9 -0
  58. package/dist/providers/cloudflare/adapter.d.ts +5 -0
  59. package/dist/providers/cloudflare/definition.d.ts +1 -0
  60. package/dist/providers/cloudflare/types.d.ts +4 -0
  61. package/dist/providers/contract.d.ts +88 -0
  62. package/dist/providers/custom/adapter.d.ts +9 -0
  63. package/dist/providers/custom/definition.d.ts +1 -0
  64. package/dist/providers/custom/types.d.ts +9 -0
  65. package/dist/providers/definition.d.ts +32 -0
  66. package/dist/providers/exa/adapter.d.ts +8 -0
  67. package/dist/providers/exa/definition.d.ts +1 -0
  68. package/dist/providers/exa/types.d.ts +4 -0
  69. package/dist/providers/firecrawl/adapter.d.ts +7 -0
  70. package/dist/providers/firecrawl/definition.d.ts +1 -0
  71. package/dist/providers/firecrawl/types.d.ts +4 -0
  72. package/dist/providers/gemini/adapter.d.ts +14 -0
  73. package/dist/providers/gemini/definition.d.ts +1 -0
  74. package/dist/providers/gemini/types.d.ts +3 -0
  75. package/dist/providers/linkup/adapter.d.ts +7 -0
  76. package/dist/providers/linkup/definition.d.ts +1 -0
  77. package/dist/providers/linkup/types.d.ts +4 -0
  78. package/dist/providers/metadata.d.ts +15 -0
  79. package/dist/providers/ollama/adapter.d.ts +6 -0
  80. package/dist/providers/ollama/definition.d.ts +1 -0
  81. package/dist/providers/ollama/types.d.ts +4 -0
  82. package/dist/providers/openai/adapter.d.ts +7 -0
  83. package/dist/providers/openai/definition.d.ts +1 -0
  84. package/dist/providers/openai/types.d.ts +28 -0
  85. package/dist/providers/parallel/adapter.d.ts +6 -0
  86. package/dist/providers/parallel/definition.d.ts +1 -0
  87. package/dist/providers/parallel/types.d.ts +4 -0
  88. package/dist/providers/perplexity/adapter.d.ts +7 -0
  89. package/dist/providers/perplexity/definition.d.ts +1 -0
  90. package/dist/providers/perplexity/types.d.ts +4 -0
  91. package/dist/providers/registry.d.ts +16 -0
  92. package/dist/providers/serper/adapter.d.ts +5 -0
  93. package/dist/providers/serper/definition.d.ts +1 -0
  94. package/dist/providers/serper/types.d.ts +21 -0
  95. package/dist/providers/shared.d.ts +4 -0
  96. package/dist/providers/tavily/adapter.d.ts +6 -0
  97. package/dist/providers/tavily/definition.d.ts +1 -0
  98. package/dist/providers/tavily/types.d.ts +4 -0
  99. package/dist/providers/valyu/adapter.d.ts +8 -0
  100. package/dist/providers/valyu/definition.d.ts +1 -0
  101. package/dist/providers/valyu/types.d.ts +4 -0
  102. package/dist/render.d.ts +5 -0
  103. package/dist/runtime/credentials.d.ts +15 -0
  104. package/dist/runtime/duration.d.ts +2 -0
  105. package/dist/runtime/execute.d.ts +20 -0
  106. package/dist/runtime/lifecycle.d.ts +8 -0
  107. package/dist/runtime/outward.d.ts +11 -0
  108. package/dist/runtime/polling.d.ts +13 -0
  109. package/dist/runtime/process.d.ts +4 -0
  110. package/docs/cli-experience.md +177 -0
  111. package/docs/provider.md +177 -0
  112. package/docs/reference.md +181 -0
  113. package/example-config.yaml +36 -0
  114. package/examples/custom/README.md +57 -0
  115. package/examples/custom/provider.mjs +54 -0
  116. package/examples/custom/webfox.json +18 -0
  117. package/package.json +122 -8
  118. package/index.js +0 -2
@@ -0,0 +1,177 @@
1
+ # CLI reference
2
+
3
+ Install the `webfox` package to use the `web` executable. Start with the
4
+ [README](../README.md) for setup and everyday examples.
5
+
6
+ ## Commands and help
7
+
8
+ ```sh
9
+ web --help
10
+ web search --help
11
+ web search --provider openai --help
12
+ web providers
13
+ web providers openai
14
+ web config default search brave
15
+ web config path
16
+ web config show
17
+ web config validate
18
+ ```
19
+
20
+ Ordinary help shows all command controls. Explicit provider help adds that
21
+ provider's exact supported flags. For example, OpenAI exposes `--model`,
22
+ `--search-context-size`, and `--user-location-country`. Arrays use repeatable
23
+ flags; booleans provide `--foo` and `--no-foo`.
24
+
25
+ Root and capability help end with copyable examples. Help highlights headings,
26
+ commands, flags, and arguments on a terminal. Piped help stays plain;
27
+ `NO_COLOR` or `--no-color` disables styling.
28
+
29
+ ## Inputs
30
+
31
+ Search and answer accept up to ten independent queries or questions. Quote each
32
+ input; results keep input order. Research accepts exactly one brief. Contents
33
+ accepts one or more URLs.
34
+
35
+ ```sh
36
+ web search "Node.js cancellation" "Bun cancellation"
37
+ web answer "What is MCP?" "What is A2A?" --provider openai
38
+ web contents https://example.com/a https://example.com/b --provider tavily
39
+ web research "Compare databases" --provider gemini --timeout 20m
40
+ ```
41
+
42
+ Omit positional input to read piped or redirected stdin:
43
+
44
+ ```sh
45
+ # Read from files
46
+ web search < query.txt
47
+ web answer --provider openai < question.txt
48
+ web research --provider gemini < brief.md
49
+ web contents --provider tavily < urls.txt
50
+
51
+ # Pipe input
52
+ echo "What is MCP?" | web answer --provider openai
53
+ echo "https://example.com" | web contents --provider tavily
54
+ ```
55
+
56
+ Search, answer, and research read one complete input, including newlines.
57
+ Contents reads newline-separated URLs. Positional arguments take precedence over
58
+ stdin. Without arguments, a terminal reports missing input instead of waiting;
59
+ piped or redirected stdin is read through EOF. Empty or whitespace-only stdin is
60
+ an input error. An explicit `-` still reads stdin, including from a terminal, but
61
+ cannot be mixed with positional input. Help never reads stdin.
62
+
63
+ None of these commands accepts repeated `--query`, `--output`, or `--raw` flags.
64
+
65
+ ## Common controls
66
+
67
+ | Flag | Meaning |
68
+ | --- | --- |
69
+ | `--provider <id>` | Override the saved provider for this request. |
70
+ | `--max-results <n>` | Limit results per query; search only. |
71
+ | `--format text\|json` | Select the result format; text is the default, even when piped. |
72
+ | `--timeout <duration>` | Set the overall deadline, including credential commands and retries. |
73
+ | `--quiet` | Suppress progress and success notices on stderr, not errors. |
74
+ | `--no-color` | Disable terminal colors. |
75
+ | `--config <path>` | Select a configuration file. |
76
+ | `--cwd <path>` | Set the working directory for custom providers and option files. |
77
+ | `--options-json <json\|@file>` | Supply complex provider options; provider-specific flags take precedence. |
78
+
79
+ Durations require a unit: `500ms`, `30s`, `20m`, or `1h`. Ctrl-C cancels waiting
80
+ for stdin, credential commands, subprocesses, and provider operations.
81
+ Cancellation stops the caller waiting even if an SDK cannot cancel its underlying
82
+ request. Cancelling a remote research request does not necessarily cancel its
83
+ billable job.
84
+
85
+ Complex objects and options whose names collide with common flags remain
86
+ available through `--options-json`. Retry tuning belongs in configuration, not
87
+ CLI flags. See the [configuration reference](./reference.md#configuration) for
88
+ option precedence, deadlines, and retries.
89
+
90
+ ## Provider inspection
91
+
92
+ `web providers` shows providers as rows and capabilities as columns:
93
+
94
+ - `☆` marks an unconfigured provider; `★` marks one with at least one configured
95
+ capability. Providers with separate credentials may still need configuration
96
+ for other capabilities.
97
+ - `✔︎` means supported, `✘︎` means unsupported, and `◉` means selected as the
98
+ default for that capability. Selection is independent of configuration, so an
99
+ unconfigured provider can still show `◉`.
100
+
101
+ The `custom` row appears only when a command is configured or a capability selects
102
+ it as its default. Its support checkmarks reflect configured commands. Use
103
+ `web providers custom` for inspection and setup guidance even before configuring
104
+ commands.
105
+
106
+ Configured means local settings or credential sources exist—not that credentials,
107
+ executables, or connectivity have been verified. Inspection and help never run
108
+ credential commands or initialize provider SDKs.
109
+
110
+ ## Output and progress
111
+
112
+ Text remains the default when piped. Stdout contains results, not success banners
113
+ or execution diagnostics. Status messages go to stderr:
114
+
115
+ - `▶︎` for progress.
116
+ - `✔︎` for success.
117
+ - `✘︎` for errors.
118
+ - `■` for cancellation.
119
+
120
+ Errors include a stable error code and, for per-input failures, the affected input.
121
+ Use `--quiet` to suppress progress and success notices. Status colors follow
122
+ terminal detection, `NO_COLOR`, and `--no-color`; JSON never acquires terminal
123
+ styling. The CLI and library do not truncate results.
124
+
125
+ For remote research jobs, progress confirms submission and acceptance, then
126
+ reports provider status changes or elapsed time roughly every 30 seconds while
127
+ polling. Transient status-check failures show the retry delay and count; they do
128
+ not start a new research job. Opaque job IDs and duplicate completion messages
129
+ are omitted. One success line gives the total elapsed time; the report itself
130
+ goes to stdout. These updates describe provider status, not estimated completion
131
+ percentages or inferred research stages.
132
+
133
+ In text mode, failed-input diagnostics go only to stderr. JSON retains structured
134
+ errors in the result document as well.
135
+
136
+ ## JSON results
137
+
138
+ Pipe JSON output into tools such as `jq`. For example, extract URLs from
139
+ successful search results:
140
+
141
+ ```sh
142
+ web search "TypeBox" --format json | jq -r '.results[] | select(.ok) | .value.results[].url'
143
+ ```
144
+
145
+ JSON is one versioned document with results in input order. Status is `ok` when
146
+ all inputs succeed and `partial` otherwise:
147
+
148
+ ```json
149
+ {
150
+ "schemaVersion": 1,
151
+ "capability": "search",
152
+ "provider": "brave",
153
+ "status": "partial",
154
+ "results": [
155
+ { "input": "first query", "ok": true, "value": { "results": [] } },
156
+ {
157
+ "input": "second query",
158
+ "ok": false,
159
+ "error": { "code": "TIMEOUT", "message": "Operation exceeded its deadline." }
160
+ }
161
+ ]
162
+ }
163
+ ```
164
+
165
+ A result has either `ok: true` and `value`, or `ok: false` and a structured
166
+ `error`. Partial batches retain completed successes, including when another input
167
+ times out or is cancelled. A contents result's `input` is the requested URL;
168
+ `value.url` is the final URL when the provider reports it.
169
+
170
+ ## Exit codes
171
+
172
+ | Code | Meaning |
173
+ | --- | --- |
174
+ | `0` | Success or help. |
175
+ | `1` | Provider failure, partial result, or timeout. |
176
+ | `2` | Invalid input or configuration. |
177
+ | `130` | Cancellation. |
@@ -0,0 +1,177 @@
1
+ # Provider guide
2
+
3
+ Choose a provider for each capability, then supply its credentials. Save your
4
+ choices with `web config default`, or select a provider for one request with
5
+ `--provider`.
6
+
7
+ ```sh
8
+ web providers
9
+ web providers brave
10
+ web search --provider brave --help
11
+ web config default search brave
12
+ ```
13
+
14
+ `web providers <id>` shows setup guidance and supported capabilities. Configured
15
+ means local settings or credential sources exist—not that credentials or
16
+ connectivity have been verified. Inspection and help don't run credential commands
17
+ or make provider requests.
18
+
19
+ Use `web <capability> --provider <id> --help` for the full list of supported
20
+ options. To save options or read credentials from a password manager, see the
21
+ [configuration reference](./reference.md#configuration).
22
+
23
+ ## Brave
24
+
25
+ Supports search, answers, and research. Set `BRAVE_SEARCH_API_KEY` for search and
26
+ `BRAVE_ANSWERS_API_KEY` for answers and research. The keys are separate; configuring
27
+ one doesn't configure the other capabilities.
28
+
29
+ ```sh
30
+ web search "Node.js release notes" --provider brave
31
+ ```
32
+
33
+ ## Cloudflare
34
+
35
+ Supports page extraction through Cloudflare Browser Rendering. Set both
36
+ `CLOUDFLARE_API_TOKEN` and `CLOUDFLARE_ACCOUNT_ID`.
37
+
38
+ ```sh
39
+ web contents https://example.com --provider cloudflare
40
+ ```
41
+
42
+ ## Custom
43
+
44
+ Connect your own command for any of the four capabilities. Configure
45
+ `providers.custom.commands.<capability>.argv`, optionally with `cwd` and
46
+ credential-source `env` entries. Only configured commands are available.
47
+
48
+ The process receives one JSON request:
49
+
50
+ ```json
51
+ {
52
+ "schemaVersion": 1,
53
+ "capability": "search",
54
+ "input": { "query": "example", "maxResults": 5 },
55
+ "options": {},
56
+ "cwd": "/working/directory"
57
+ }
58
+ ```
59
+
60
+ Write one normalized result object to stdout and newline-delimited progress to
61
+ stderr. A nonzero exit signals failure. Contents answers must include a zero-based
62
+ `inputIndex` relative to the process request; `url` separately represents the final
63
+ URL. Errors are structured `{ "code": "PROVIDER_FAILURE", "message": "..." }`
64
+ objects. See the [custom-provider example](../examples/custom/README.md) for a
65
+ working command and the complete request/response contract.
66
+
67
+ ## Exa
68
+
69
+ Supports search, page extraction, answers, and research. Set `EXA_API_KEY`.
70
+ Research returns a synthesized report with source links.
71
+
72
+ ```sh
73
+ web search "Node.js release notes" --provider exa
74
+ web research "Compare databases for an analytics service" --provider exa --timeout 20m
75
+ ```
76
+
77
+ ## Firecrawl
78
+
79
+ Supports search, page extraction, and page-scoped answers. Set `FIRECRAWL_API_KEY`
80
+ for the hosted service. A self-hosted `providers.firecrawl.baseUrl` can work
81
+ without an API key.
82
+
83
+ Answers require a page URL, supplied through provider defaults or `--url`:
84
+
85
+ ```sh
86
+ web contents https://example.com --provider firecrawl
87
+ web answer "What does this page explain?" --provider firecrawl --url https://example.com
88
+ ```
89
+
90
+ ## Gemini
91
+
92
+ Supports grounded answers and research, not standalone search. Set
93
+ `GOOGLE_API_KEY`. Google's Search tool runs inside a model interaction; Webfox
94
+ does not discard the generated answer and present its sources as ordinary search
95
+ results.
96
+
97
+ Answers default to `gemini-3.8-flash`. Override the model with
98
+ `providers.gemini.options.answer.model` or the answer command's `--model` flag.
99
+ Research uses `deep-research-preview-04-2026`, Google's standard
100
+ [Deep Research agent](https://ai.google.dev/gemini-api/docs/deep-research).
101
+ The research agent is fixed; answer model settings don't affect it.
102
+
103
+ If you previously selected Gemini for search, choose a search-capable provider
104
+ and remove `providers.gemini.options.search` from your configuration.
105
+
106
+ ## Linkup
107
+
108
+ Supports search, page extraction, and research. Set `LINKUP_API_KEY`.
109
+
110
+ ```sh
111
+ web search "Node.js release notes" --provider linkup
112
+ ```
113
+
114
+ ## Ollama
115
+
116
+ Supports search and page extraction through **hosted web APIs** at
117
+ `https://ollama.com`, not through the local Ollama model server. Set
118
+ `OLLAMA_API_KEY` from your Ollama account; no model download or local daemon is
119
+ required.
120
+
121
+ ```sh
122
+ web search "Node.js streams documentation" --provider ollama --max-results 5
123
+ web contents https://example.com --provider ollama
124
+ ```
125
+
126
+ Search supports up to 10 results. The `contents` capability uses Ollama's web
127
+ fetch endpoint. `providers.ollama.baseUrl` can point to a compatible proxy; it
128
+ does not turn the local inference API into a web search service.
129
+
130
+ ## OpenAI
131
+
132
+ Supports search, grounded answers, and research. Set `OPENAI_API_KEY`.
133
+
134
+ ```sh
135
+ web answer "What is MCP?" --provider openai --model gpt-6-astra
136
+ web search --provider openai --help
137
+ ```
138
+
139
+ ## Parallel
140
+
141
+ Supports search and page extraction. Set `PARALLEL_API_KEY`.
142
+
143
+ ```sh
144
+ web search "Node.js release notes" --provider parallel
145
+ ```
146
+
147
+ ## Perplexity
148
+
149
+ Supports search, grounded answers, and research. Set `PERPLEXITY_API_KEY`.
150
+
151
+ ```sh
152
+ web answer "What is MCP?" --provider perplexity
153
+ ```
154
+
155
+ ## Serper
156
+
157
+ Supports search. Set `SERPER_API_KEY`.
158
+
159
+ ```sh
160
+ web search "Node.js release notes" --provider serper
161
+ ```
162
+
163
+ ## Tavily
164
+
165
+ Supports search and page extraction. Set `TAVILY_API_KEY`.
166
+
167
+ ```sh
168
+ web contents https://example.com --provider tavily
169
+ ```
170
+
171
+ ## Valyu
172
+
173
+ Supports search, page extraction, answers, and research. Set `VALYU_API_KEY`.
174
+
175
+ ```sh
176
+ web search "Node.js release notes" --provider valyu
177
+ ```
@@ -0,0 +1,181 @@
1
+ # Webfox reference
2
+
3
+ This reference covers advanced configuration and the TypeScript API. For everyday
4
+ commands, start with the [README](../README.md). See the
5
+ [provider guide](./provider.md) for setup and provider-specific behavior, or the
6
+ [CLI reference](./cli-experience.md) for scripting and output contracts.
7
+
8
+ ## Configuration
9
+
10
+ ### File selection and validation
11
+
12
+ Configuration paths resolve in this order:
13
+
14
+ 1. `--config` or the library's `configPath`.
15
+ 2. `WEBFOX_CONFIG`.
16
+ 3. `%APPDATA%\webfox\config.yaml` on Windows, when `APPDATA` is set.
17
+ 4. `$XDG_CONFIG_HOME/webfox/config.yaml`.
18
+ 5. `~/.config/webfox/config.yaml`.
19
+
20
+ A missing default file means no saved settings. An explicitly selected missing
21
+ file is an error; `web config default` can create it. The setter preserves
22
+ unrelated settings and comments and atomically replaces the file with owner-only
23
+ permissions. `web config show` emits redacted YAML, hiding literal credentials
24
+ and credential commands. `web config validate` checks configuration and provider
25
+ option schemas without resolving credentials or making requests.
26
+
27
+ Use YAML 1.2 with string mapping keys and finite numbers. Duplicate keys,
28
+ multiple documents, aliases, explicit tags, and unknown configuration fields are
29
+ rejected. Empty files are valid and mean no saved settings. The published JSON
30
+ Schema supports validation and editor completion and is available as
31
+ `webfox/config.schema.json`.
32
+
33
+ JSON syntax is also valid YAML. To use a JSON configuration file, select it
34
+ explicitly with `WEBFOX_CONFIG` or `--config`.
35
+
36
+ See the [example configuration](../example-config.yaml).
37
+
38
+ ### Defaults and provider options
39
+
40
+ Capability defaults contain only provider selection and portable settings
41
+ (currently search's `maxResults`). Provider-specific options belong exclusively
42
+ under that provider:
43
+
44
+ ```yaml
45
+ defaults:
46
+ search:
47
+ provider: brave
48
+ maxResults: 5
49
+ answer:
50
+ provider: openai
51
+ execution:
52
+ timeoutMs: 30000
53
+ researchTimeoutMs: 1800000
54
+ retries: 1
55
+ retryDelayMs: 2000
56
+ concurrency: 4
57
+ providers:
58
+ brave:
59
+ options:
60
+ search:
61
+ mode: news
62
+ openai:
63
+ credentials:
64
+ api:
65
+ command: [op, read, "op://vault/openai/api-key"]
66
+ options:
67
+ answer:
68
+ model: gpt-6-astra
69
+ ```
70
+
71
+ Options have one precedence order, from lowest to highest:
72
+
73
+ 1. Provider defaults.
74
+ 2. `providers.<id>.options.<capability>`.
75
+ 3. Request options, or CLI `--options-json`.
76
+ 4. Provider-specific CLI flags.
77
+
78
+ Switching providers never carries the previous provider's options into a request.
79
+ Defaults and overrides can be incomplete; required fields are checked after
80
+ merging. For example, Firecrawl answers need a `url` supplied in defaults or
81
+ with `--url`.
82
+
83
+ ### Credentials
84
+
85
+ Each credential source has exactly one form:
86
+
87
+ ```yaml
88
+ { env: OPENAI_API_KEY }
89
+ { command: [program, argument] }
90
+ { value: "literal-secret" }
91
+ ```
92
+
93
+ Standard environment references work without a provider section. `web providers
94
+ <id>` lists credential names. See the [provider guide](./provider.md) for each
95
+ provider's keys and setup requirements.
96
+
97
+ Credential commands run asynchronously as argument arrays, never through a shell.
98
+ They inherit the client's environment and working directory and obey its request
99
+ signal. Successful outputs are cached per client, not globally. Overriding one
100
+ credential preserves the provider's other standard references.
101
+
102
+ Resolved credentials are redacted from results, progress, and public errors
103
+ before they reach callers. Secret-bearing metadata fields are also redacted.
104
+ This policy is not a sandbox for untrusted adapters or commands.
105
+
106
+ ### Timeouts, retries, and cancellation
107
+
108
+ Defaults are 30 seconds for ordinary operations, 30 minutes for research, four
109
+ concurrent inputs, and no retries. Retry backoff starts at two seconds and grows
110
+ up to 30 seconds within the same overall deadline. The deadline includes
111
+ credential commands, provider operations, and retries.
112
+
113
+ Only transient failures on operations the adapter marks retry-safe are retried.
114
+ Research job creation is never blindly retried; polling applies the configured
115
+ retry count and backoff without creating another job. URL operations are
116
+ scheduled separately so completed pages survive another page's failure or
117
+ timeout.
118
+
119
+ Cancellation stops the caller waiting even if an SDK cannot cancel its underlying
120
+ request. Cancelling a remote research request does not necessarily cancel its
121
+ billable job.
122
+
123
+ ## TypeScript library
124
+
125
+ ```ts
126
+ import { createWebfox } from "webfox";
127
+
128
+ const web = createWebfox();
129
+ const document = await web.search({
130
+ provider: "openai",
131
+ queries: ["TypeBox validation", "Node.js AbortSignal"],
132
+ maxResults: 5,
133
+ options: { searchContextSize: "high" },
134
+ timeoutMs: 30_000,
135
+ onProgress: ({ message }) => console.error(message),
136
+ });
137
+
138
+ for (const result of document.results) {
139
+ if (result.ok) console.log(result.value.results);
140
+ else console.error(result.error.code, result.error.message);
141
+ }
142
+ ```
143
+
144
+ `createWebfox({ config?, configPath?, cwd?, env? })` snapshots configuration and
145
+ environment for one client. It exposes:
146
+
147
+ - `search({ queries, maxResults?, ...controls })`.
148
+ - `contents({ urls, ...controls })`.
149
+ - `answer({ queries, ...controls })`.
150
+ - `research({ input, ...controls })`.
151
+ - `inspectCapability(capability, provider?)`: selection, configuration status,
152
+ provider option-override schema, and effective non-secret defaults.
153
+ - `listProviders()` and `getProvider(id)`: supported/configured capabilities and
154
+ saved selections.
155
+
156
+ Request controls are `provider`, `options`, `timeoutMs`, `signal`, and
157
+ `onProgress`. Planning errors throw `WebfoxError`; per-input execution failures
158
+ remain in the document. Results use the same
159
+ [document contract as CLI JSON](./cli-experience.md#json-results), without
160
+ truncation. Provider registration is deliberately not public; use a
161
+ [custom provider command](./provider.md#custom) to connect another backend.
162
+
163
+ For all capabilities, `onProgress` includes per-input lifecycle events with
164
+ `inputIndex`, `input`, and `state` (`queued`, `running`, `done`, `failed`, or
165
+ `cancelled`). Indexes refer to the original input order, including duplicate
166
+ inputs. Provider progress messages may omit these fields.
167
+
168
+ ## pi extension behavior
169
+
170
+ Webfox exposes `web_search`, `web_contents`, `web_answer`, and `web_research`
171
+ for capabilities with an explicitly configured default provider. Each tool's
172
+ parameter schema is built dynamically from that provider: the model sees its
173
+ supported options rather than parameters for every backend. Unsupported
174
+ parameters are rejected with their exact paths and, when unambiguous, a suggested
175
+ valid location.
176
+
177
+ Restart pi after changing configuration to refresh the tool schemas. The
178
+ extension forwards cancellation and progress, marks partial results as errors,
179
+ and truncates tool output at 2,000 lines or 50 KiB, with full results saved to a
180
+ temporary file. It needs no globally installed `web` command and starts no
181
+ background research jobs.
@@ -0,0 +1,36 @@
1
+ $schema: https://unpkg.com/webfox@3.5.1/dist/config.schema.json
2
+ defaults:
3
+ search:
4
+ provider: brave
5
+ maxResults: 5
6
+ contents:
7
+ provider: tavily
8
+ answer:
9
+ provider: openai
10
+ research:
11
+ provider: gemini
12
+ execution:
13
+ timeoutMs: 30000
14
+ retries: 1
15
+ retryDelayMs: 2000
16
+ researchTimeoutMs: 1800000
17
+ providers:
18
+ brave:
19
+ credentials:
20
+ search:
21
+ env: BRAVE_SEARCH_API_KEY
22
+ tavily:
23
+ credentials:
24
+ api:
25
+ env: TAVILY_API_KEY
26
+ openai:
27
+ credentials:
28
+ api:
29
+ env: OPENAI_API_KEY
30
+ options:
31
+ answer:
32
+ model: gpt-6-astra
33
+ gemini:
34
+ credentials:
35
+ api:
36
+ env: GOOGLE_API_KEY
@@ -0,0 +1,57 @@
1
+ # Custom provider example
2
+
3
+ `provider.mjs` implements all four capabilities without network access. Run the
4
+ example from the repository root using the included `webfox.json`:
5
+
6
+ ```sh
7
+ web search "example query" --config examples/custom/webfox.json
8
+ web contents https://example.com --config examples/custom/webfox.json --format json
9
+ ```
10
+
11
+ The configuration defines explicit custom commands and saved defaults. In your
12
+ own setup, use absolute command paths or set the command’s `cwd`.
13
+
14
+ ## Process contract
15
+
16
+ Each invocation receives one JSON request on stdin, writes one JSON object to
17
+ stdout, and sends newline-delimited progress to stderr. A nonzero exit signals
18
+ failure. The runtime bounds process output and terminates the process group on
19
+ cancellation or timeout (the direct child on Windows).
20
+
21
+ ```json
22
+ {
23
+ "schemaVersion": 1,
24
+ "capability": "search",
25
+ "input": { "query": "example", "maxResults": 5 },
26
+ "options": {},
27
+ "cwd": "/working/directory"
28
+ }
29
+ ```
30
+
31
+ Payloads and responses:
32
+
33
+ | Capability | Input | Response |
34
+ | --- | --- | --- |
35
+ | Search | `{ "query": "...", "maxResults": 5 }` | `{ "results": [{ "title": "...", "url": "https://...", "snippet": "..." }] }` |
36
+ | Contents | `{ "urls": ["https://..."] }` | `{ "answers": [{ "inputIndex": 0, "url": "https://...", "content": "..." }] }` |
37
+ | Answer | `{ "query": "..." }` | `{ "text": "..." }` |
38
+ | Research | `{ "input": "..." }` | `{ "text": "..." }` |
39
+
40
+ Contents answers must cover every request index exactly once. `inputIndex`
41
+ associates a response with the requested URL; `url` can hold a redirected URL.
42
+ A failed page uses a structured error instead of content:
43
+
44
+ ```json
45
+ {
46
+ "inputIndex": 0,
47
+ "url": "https://example.com",
48
+ "error": { "code": "PROVIDER_FAILURE", "message": "Extraction failed." }
49
+ }
50
+ ```
51
+
52
+ The runtime currently schedules one URL per invocation. Treat indices as local
53
+ to the supplied request, not the entire user batch.
54
+
55
+ Replace the deterministic branches with your own integrations. Credentials for
56
+ child processes go in the command’s `env` map as `{ "env": "NAME" }`,
57
+ `{ "command": ["program", "arg"] }`, or `{ "value": "..." }` sources.
@@ -0,0 +1,54 @@
1
+ let body = "";
2
+ for await (const chunk of process.stdin) body += chunk;
3
+
4
+ const request = JSON.parse(body);
5
+ if (request.schemaVersion !== 1) {
6
+ process.stderr.write("unsupported schemaVersion\n");
7
+ process.exit(2);
8
+ }
9
+
10
+ process.stderr.write(`running custom ${request.capability}\n`);
11
+
12
+ switch (request.capability) {
13
+ case "search":
14
+ process.stdout.write(
15
+ JSON.stringify({
16
+ results: [
17
+ {
18
+ title: `Example result for ${request.input.query}`,
19
+ url: "https://example.com/",
20
+ snippet: "Replace this branch with your search integration.",
21
+ },
22
+ ],
23
+ }),
24
+ );
25
+ break;
26
+ case "contents":
27
+ process.stdout.write(
28
+ JSON.stringify({
29
+ answers: request.input.urls.map((url, inputIndex) => ({
30
+ inputIndex,
31
+ url,
32
+ content: `Example contents for ${url}`,
33
+ })),
34
+ }),
35
+ );
36
+ break;
37
+ case "answer":
38
+ process.stdout.write(
39
+ JSON.stringify({
40
+ text: `Example answer for ${request.input.query}`,
41
+ }),
42
+ );
43
+ break;
44
+ case "research":
45
+ process.stdout.write(
46
+ JSON.stringify({
47
+ text: `Example research report for ${request.input.input}`,
48
+ }),
49
+ );
50
+ break;
51
+ default:
52
+ process.stderr.write("unsupported capability\n");
53
+ process.exit(2);
54
+ }