npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@softspark/dsh-web-search-searxng

v1.0.0

Published

DeepSeek Harness web-search provider backed by a SearXNG instance: metasearch with no vendor API key and no account tying the queries together.

Readme

dsh-web-search-searxng

A web-search provider for the DeepSeek Harness, backed by a SearXNG instance. No API key, no vendor account, and nothing for this plugin to store.

npm CI License DSH community plugin

The harness ships one search provider and it is gated on DEEPSEEK_API_KEY. This registers a second one on the same seam and moves the selection onto it.

dsh plugin add @softspark/dsh-web-search-searxng

Then tell it where the instance is:

- id: web-search-searxng
  name: '@softspark/dsh-web-search-searxng'
  config:
    baseURL: http://searxng:8080

This is an independently maintained SoftSpark integration. It is unofficial and is not affiliated with or endorsed by DeepSeek or the SearXNG project.


What's new in 1.0.0

First public release.

  • One ctx.web search provider, id searxng, and the bundle patch that actually selects it — registering alone changes nothing, and nothing reports that as an error.
  • Results deduplicated by URL, because metasearch merges engines and the same page arrives more than once.
  • Optional fields omitted rather than invented; dsh-tool-web already renders title ?? hostname(url).
  • A named error for the JSON format SearXNG does not enable by default, so an instance answering HTML with HTTP 200 does not read as "no results".
  • No credential path at all, no redirects followed, and no error that carries the query.

Full history in CHANGELOG.md.


Why this exists

The harness ships one search provider, web-search-deepseek, and it is gated on DEEPSEEK_API_KEY. That is a sensible default and a poor fit for a workbench whose point is that no vendor account sits behind the agent's ordinary actions. The key is not just a payment detail: it is an identity, and it makes every query the agent runs attributable to one account held by one person.

Searching the web does not need that. A metasearch front end forwards the query to engines and returns what they say, and the account it does not have is the account nobody can correlate against.

What this does not claim. The engines still see the query, and so does whoever runs the instance. Pointing baseURL at a public SearXNG moves the trust from a vendor you have an account with to a stranger you do not — which is a different bargain, not a strictly better one. Run your own instance if the queries matter.


Configuration

| Key | Default | Meaning | |---|---|---| | baseURL | required | Absolute URL of the instance, without /search. No default: a guess would send queries somewhere you did not choose. | | timeoutMs | 15000 | Upper bound on one search. Between 1000 and 120000. | | language | unset | UI language passed through, e.g. pl or en-US. | | safeSearch | 0 | SearXNG safe-search level: 0 off, 1 moderate, 2 strict. | | categories | unset | Comma-separated categories, e.g. general,it. | | engines | unset | Comma-separated engine names, narrowing what the instance queries. |

Unset optional keys are omitted from the request rather than sent empty, so the instance's own defaults apply.

The instance must be allowed to answer in JSON

SearXNG does not enable the JSON output format by default. Without it, the instance answers the same URL with a rendered results page and HTTP 200 — which would read as "no results" if this provider did not check. Add it to the instance's settings.yml:

search:
  formats:
    - html
    - json

The provider names this fix in the error when it sees HTML, so the failure is one you can act on rather than one you have to guess at.


What the bundle does to the harness

Two rows, and both are needed:

- insert:
    - id: web-search-searxng
      name: '@softspark/dsh-web-search-searxng'

- patch:
    - id: web
      config:
        searchProvider: searxng

Registering the provider alone changes nothing. The web seam resolves searchProvider at call time, and a configured id that is registered always wins — so while web.searchProvider still names deepseek-official, this provider is registered and never selected. The patch: row is what moves the selection.

Leaving the DeepSeek row mounted is otherwise harmless: without a key it reports itself unavailable. Removing it is still worth doing where the point is that no key path exists at all.


Behaviour

Selection is not order-dependent. The seam resolves the configured id at execution time. An id that is registered but unavailable fails as WEB_PROVIDER_CONFIGURED_UNAVAILABLE rather than silently falling back to another provider — a fallback would make "which engine answered this" unanswerable.

available() makes no network call. It reports whether an absolute http(s) base URL is configured. Whether the instance is reachable is a question for the search itself, and answering it in a usability check would make every provider listing a round trip.

Results are deduplicated by URL. Metasearch merges engines and the same page arrives more than once; the first occurrence wins, so the engine ordering the instance chose is preserved.

Optional fields are omitted, not invented. A result with no title returns no title. dsh-tool-web renders title ?? hostname(url) and is built for this.

Redirects are refused. A search URL that redirects is a misconfiguration or an interception, not a route to follow.

Errors name what to do. An unreachable instance, a non-2xx answer, a timeout, and an HTML answer are four distinct messages. None of them contains the query — an error is a place a search term should never leak into.


Security

This plugin reads no credential and holds no key. It makes one outbound GET per search, to the baseURL you configured and nowhere else.

Report vulnerabilities per SECURITY.md.


Documentation

Licence

Apache-2.0. See LICENSE and NOTICE.