Skip to content

Add Tavily web search integration and Telegram typing indicator#3

Merged
initializ-mk merged 10 commits intodevelopfrom
tavily_skills
Feb 23, 2026
Merged

Add Tavily web search integration and Telegram typing indicator#3
initializ-mk merged 10 commits intodevelopfrom
tavily_skills

Conversation

@initializ-mk
Copy link
Contributor

Summary

  • Web search provider abstraction: Refactored the monolithic web_search tool into a provider pattern with pluggable backends (Tavily and Perplexity). Auto-detects from env vars (TAVILY_API_KEY > PERPLEXITY_API_KEY), with explicit override via WEB_SEARCH_PROVIDER.
  • Tavily as external skill: Added tavily-search to the skill registry with an embedded shell script (scripts/tavily-search.sh), skill markdown, and forge skills add CLI command for vendoring skills into projects.
  • Init wizard update: When web_search is selected, the wizard now presents a provider choice (Tavily recommended / Perplexity) before prompting for the API key.
  • Telegram typing indicator: Sends sendChatAction("typing") immediately when a message is received and repeats every 4s while the LLM processes, for both polling and webhook modes.

New files

File Purpose
forge-core/tools/builtins/web_search_provider.go Provider interface + webSearchOpts
forge-core/tools/builtins/web_search_tavily.go Tavily provider implementation
forge-core/tools/builtins/web_search_perplexity.go Perplexity provider (extracted from web_search.go)
forge-core/registry/skills/tavily-search.md Tavily skill markdown with frontmatter
forge-core/registry/scripts/tavily-search.sh Standalone search script (curl + jq)

Test plan

  • go test ./forge-core/tools/builtins/ — 16/16 pass (incl. Tavily provider, Perplexity provider, override, auto-detect, no-key)
  • go test ./forge-core/registry/ — 7/7 pass (incl. tavily-search index, script loading)
  • go test ./forge-core/security/ — 22/22 pass
  • go test ./forge-plugins/channels/telegram/ — 13/13 pass (incl. sendChatAction, typing indicator)
  • go build ./forge-core/... and go build ./forge-cli/... compile cleanly

- Add web_search provider abstraction with Tavily (default) and Perplexity backends
- Auto-detect provider from env vars (TAVILY_API_KEY > PERPLEXITY_API_KEY),
  with explicit override via WEB_SEARCH_PROVIDER
- Add tavily-search as external skill with embedded script and registry entry
- Add `forge skills add` command for vendoring registry skills into projects
- Update init wizard with provider selection phase when web_search is chosen
- Send Telegram "typing" chat action while LLM processes requests
- Add CLAUDE.md with pre-commit gofmt and golangci-lint instructions
- Wire validateTavilyKey into the init wizard tools step
- Fix gofmt formatting in skills.go and tools_step.go
- Rename ValidatePerplexityFunc to ValidateWebSearchKeyFunc for both providers
…alidation

- Egress step now only shows the selected web_search provider domain
  (Tavily or Perplexity) instead of both
- Skills step prompts for required_env, one_of_env, and optional_env
  when skills are selected, blocking if required/one_of is not provided
- Web search tool step validates Tavily/Perplexity API keys with async
  validation (same pattern as provider step)
- DeriveEgressFunc now receives envVars to filter provider-specific domains
- Updated tests to match new provider-specific behavior
Tools line now displays "web_search [tavily]" or "web_search [perplexity]"
to indicate which provider was selected.
The review step reads from WizardContext directly, not the tools step
Summary(). Updated Prepare() to annotate web_search with the provider
from ctx.EnvVars.
Init() was not resetting phase, currentPrompt, envPrompts, or envValues.
When the user navigated back from a later step, the stale skillsEnvPhase
with an exhausted currentPrompt caused an index out of range panic.
Skills step now checks env vars collected by earlier wizard steps
(via Prepare/knownEnvVars) so it won't re-prompt for keys like
OPENAI_API_KEY already provided as the model provider. buildEnvVars()
uses a written map to skip duplicate keys when writing the .env file.
Provider step Apply() now stores the API key in ctx.EnvVars
(e.g. OPENAI_API_KEY) so the skills step's Prepare() can detect
it via knownEnvVars and skip the one_of group entirely.
MultiSelect and SingleSelect Init() methods were no-ops that didn't
reset the done flag. After navigating back, done remained true causing
Update() to short-circuit and treat all keys (including space) as
no-ops while the step immediately re-completed.
Three issues fixed:
- Wizard now handles esc globally as quit (matching kbd hints)
- Removed redundant esc→back mapping from review step that caused
  the review↔egress loop
- EgressDisplay.Init() now resets done flag so back-navigation
  doesn't immediately re-advance
@initializ-mk initializ-mk merged commit f7fe4c2 into develop Feb 23, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant