Skip to content

Commit bf233fe

Browse files
authored
Merge pull request #1 from context-dot-dev/feat/context-dev-components
feat: add Context.dev Haystack integration
2 parents fc9a6f7 + 7b72a34 commit bf233fe

21 files changed

Lines changed: 1408 additions & 173 deletions

‎.github/workflows/release.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# SPDX-FileCopyrightText: 2026-present AUTHOR <your@email.com>
1+
# SPDX-FileCopyrightText: 2026-present Context.dev
22
#
33
# SPDX-License-Identifier: Apache-2.0
44

‎.github/workflows/test.yml‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# SPDX-FileCopyrightText: 2026-present AUTHOR <your@email.com>
1+
# SPDX-FileCopyrightText: 2026-present Context.dev
22
#
33
# SPDX-License-Identifier: Apache-2.0
44

@@ -44,5 +44,9 @@ jobs:
4444
if: matrix.python-version == '3.10' && runner.os == 'Linux'
4545
run: hatch run fmt-check
4646

47+
- name: Type check
48+
if: matrix.python-version == '3.10' && runner.os == 'Linux'
49+
run: hatch run test:types
50+
4751
- name: Run tests
4852
run: hatch run test:all

‎CONTRIBUTING.md‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Contributing
2+
3+
Thanks for contributing to the Context.dev Haystack integration.
4+
5+
## Setup
6+
7+
This project uses [Hatch](https://hatch.pypa.io/) for environments, formatting, tests, and builds.
8+
9+
```bash
10+
pip install hatch
11+
hatch --version
12+
```
13+
14+
## Checks
15+
16+
Run the same checks used by CI before opening a pull request:
17+
18+
```bash
19+
hatch run fmt-check
20+
hatch run test:types
21+
hatch run test:unit
22+
hatch run test:cov
23+
```
24+
25+
Integration tests call the live Context.dev API and consume credits. They are skipped unless `CONTEXT_API_KEY` is set:
26+
27+
```bash
28+
export CONTEXT_API_KEY="your-api-key"
29+
hatch run test:integration
30+
```
31+
32+
## Pull requests
33+
34+
Keep changes focused, add tests for behavior changes, and use Conventional Commit titles such as `feat: add a component option` or `fix: preserve response metadata`.
35+
36+
## Releases
37+
38+
Maintainers publish releases by pushing a semantic version tag such as `v0.1.0`. The release workflow builds the source distribution and wheel, then publishes both to PyPI.

‎README.md‎

Lines changed: 63 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,92 @@
1-
# Custom Component Template
1+
# Context.dev for Haystack
22

3-
A template repository for creating custom [Haystack](https://haystack.deepset.ai/) components and publishing them as standalone Python packages.
3+
[![PyPI](https://img.shields.io/pypi/v/context-dev-haystack)](https://pypi.org/project/context-dev-haystack/)
4+
[![Python](https://img.shields.io/pypi/pyversions/context-dev-haystack)](https://pypi.org/project/context-dev-haystack/)
5+
[![Test](https://github.com/context-dot-dev/context-haystack/actions/workflows/test.yml/badge.svg)](https://github.com/context-dot-dev/context-haystack/actions/workflows/test.yml)
6+
[![License](https://img.shields.io/github/license/context-dot-dev/context-haystack)](LICENSE)
47

5-
For more details, see the Haystack documentation on [creating custom components](https://docs.haystack.deepset.ai/docs/custom-components) and [creating custom document stores](https://docs.haystack.deepset.ai/docs/creating-custom-document-stores).
8+
Haystack components for live web search, webpage and YouTube transcript retrieval, and bounded website crawling with [Context.dev](https://context.dev).
69

7-
## How to use this template
10+
## Installation
811

9-
1. Click **[Use this template](https://github.com/deepset-ai/custom-component/generate)** to create a new repository.
12+
```bash
13+
pip install context-dev-haystack
14+
```
1015

11-
2. **Rename the package directory** from `src/haystack_integrations/components/example/` to match your integration. See [Namespace convention](#namespace-convention) below for the correct path.
16+
Create an API key in the [Context.dev dashboard](https://context.dev/dashboard/api-keys), then export it:
1217

13-
3. **Update `pyproject.toml`** — search for `TODO` comments and replace:
14-
- `name`: your package name, following the `<technology>-haystack` convention (e.g. `opensearch-haystack`)
15-
- `description`, `authors`, `keywords`, `project.urls`
16-
- `dependencies`: add your integration-specific dependencies
17-
- `tool.hatch.version.raw-options`: if you renamed directories, the version path is still derived from git tags so no change is needed here
18+
```bash
19+
export CONTEXT_API_KEY="your-api-key"
20+
```
1821

19-
4. **Add your component code** in the renamed directory and export your classes from `__init__.py`.
22+
## Components
2023

21-
5. **Add tests** in `tests/` — see the skeleton in `tests/test_example.py`.
24+
| Component | Purpose | Import |
25+
| --- | --- | --- |
26+
| `ContextWebSearch` | Search the live web and return ranked Haystack Documents and source links | `haystack_integrations.components.websearch.context` |
27+
| `ContextFetcher` | Fetch webpages or YouTube videos as clean Markdown Documents | `haystack_integrations.components.fetchers.context` |
28+
| `ContextCrawler` | Crawl websites into Documents with explicit page and depth limits | `haystack_integrations.components.fetchers.context` |
2229

23-
6. **Search for all `TODO` comments** across the project and address them.
30+
All components support both `run()` and `run_async()`, Haystack serialization, custom timeouts, and retry configuration.
2431

25-
Check out the [video walkthrough](https://www.youtube.com/watch?v=SWC0QecAMcI) for a step-by-step guide on how to use this template.
32+
## Search the live web
2633

27-
## Namespace convention
34+
```python
35+
from haystack_integrations.components.websearch.context import ContextWebSearch
2836

29-
Haystack integrations use the `haystack_integrations` namespace package. The directory structure under `src/` determines the import path for your component.
37+
search = ContextWebSearch(top_k=5, include_markdown=True)
38+
result = search.run(query="Recent advances in retrieval-augmented generation")
3039

31-
**Components** (converters, embedders, generators, rankers, etc.) use:
40+
documents = result["documents"]
41+
links = result["links"]
3242
```
33-
src/haystack_integrations/components/<type>/<name>/
34-
```
35-
Import path: `from haystack_integrations.components.<type>.<name> import MyComponent`
3643

37-
Common component types: `converters`, `embedders`, `generators`, `rankers`, `retrievers`, `connectors`, `tools`, `websearch`
44+
Use `include_domains`, `exclude_domains`, `freshness`, and `country` to constrain results. Extra Context.dev Search API fields can be supplied through `search_params`.
3845

39-
**Document stores** use a separate namespace:
40-
```
41-
src/haystack_integrations/document_stores/<name>/
46+
## Fetch webpages or YouTube transcripts
47+
48+
```python
49+
from haystack_integrations.components.fetchers.context import ContextFetcher
50+
51+
fetcher = ContextFetcher()
52+
result = fetcher.run(
53+
urls=[
54+
"https://haystack.deepset.ai",
55+
"https://www.youtube.com/watch?v=UF8uR6Z6KLc",
56+
]
57+
)
58+
59+
documents = result["documents"]
4260
```
43-
Import path: `from haystack_integrations.document_stores.<name> import MyDocumentStore`
4461

45-
## Development
62+
Each URL becomes a Haystack `Document`. Webpages contain clean Markdown and page metadata; supported YouTube URLs return timestamped transcript Markdown.
4663

47-
This project uses [Hatch](https://hatch.pypa.io/) for build and environment management.
64+
## Crawl a website
4865

49-
```bash
50-
# Install Hatch
51-
pip install hatch
52-
53-
# Format and lint
54-
hatch run fmt # auto-fix
55-
hatch run fmt-check # check only
56-
57-
# Run tests
58-
hatch run test:unit # unit tests only
59-
hatch run test:integration # integration tests only
60-
hatch run test:all # all tests
61-
hatch run test:cov # with coverage
66+
```python
67+
from haystack_integrations.components.fetchers.context import ContextCrawler
68+
69+
crawler = ContextCrawler(crawl_params={"maxPages": 25, "maxDepth": 2})
70+
result = crawler.run(urls=["https://docs.haystack.deepset.ai"])
71+
72+
documents = result["documents"]
6273
```
6374

64-
## Publishing to PyPI
75+
`ContextCrawler` defaults to one page to prevent accidental credit consumption. Set `maxPages` explicitly for larger crawls.
76+
77+
## Async usage
6578

66-
This template includes a GitHub Actions workflow that publishes your package to PyPI when you push a version tag.
79+
```python
80+
result = await search.run_async(query="Haystack agents")
81+
documents = result["documents"]
82+
```
6783

68-
1. **Add a `PYPI_API_TOKEN` secret** to your repository settings (Settings > Secrets and variables > Actions).
84+
The fetcher and crawler process multiple input URLs concurrently in their async methods.
6985

70-
2. **Create a version tag** and push it:
71-
```bash
72-
git tag v0.1.0
73-
git push origin v0.1.0
74-
```
86+
## Development
7587

76-
The release workflow will build and publish the package automatically.
88+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the Hatch-based development and release workflow.
7789

7890
## License
7991

80-
`Apache-2.0` - See [LICENSE](LICENSE) for details.
92+
Apache-2.0. See [LICENSE](LICENSE).

‎examples/context_pipeline.py‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# SPDX-FileCopyrightText: 2026-present Context.dev
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
from haystack import Pipeline
6+
7+
from haystack_integrations.components.websearch.context import ContextWebSearch
8+
9+
pipeline = Pipeline()
10+
pipeline.add_component("search", ContextWebSearch(top_k=5, include_markdown=True))
11+
12+
result = pipeline.run({"search": {"query": "What is Haystack by deepset?"}})
13+
for document in result["search"]["documents"]:
14+
print(document.meta["url"])

‎examples/example.py‎

Lines changed: 0 additions & 12 deletions
This file was deleted.

‎pyproject.toml‎

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# SPDX-FileCopyrightText: 2026-present AUTHOR <your@email.com>
1+
# SPDX-FileCopyrightText: 2026-present Context.dev
22
#
33
# SPDX-License-Identifier: Apache-2.0
44

@@ -7,19 +7,22 @@ requires = ["hatchling", "hatch-vcs"]
77
build-backend = "hatchling.build"
88

99
[project]
10-
name = "example-haystack" # TODO: Replace with your package name, e.g. "deepset-ai-haystack"
10+
name = "context-dev-haystack"
1111
dynamic = ["version"]
12-
description = "A custom Haystack component" # TODO: Replace with your description
12+
description = "Haystack components for Context.dev live web search, scraping, and crawling"
1313
readme = "README.md"
1414
requires-python = ">=3.10"
1515
license = "Apache-2.0"
1616
keywords = [
1717
"haystack",
18-
# TODO: Add relevant keywords for your integration
18+
"context-dev",
19+
"web-search",
20+
"web-scraping",
21+
"web-crawling",
22+
"rag",
1923
]
2024
authors = [
21-
# TODO: Replace with your name and email
22-
{ name = "AUTHOR", email = "your@email.com" },
25+
{ name = "Context.dev" },
2326
]
2427
classifiers = [
2528
"Development Status :: 4 - Beta",
@@ -35,15 +38,16 @@ classifiers = [
3538
"Programming Language :: Python :: Implementation :: PyPy",
3639
]
3740
dependencies = [
38-
"haystack-ai",
39-
# TODO: Add your integration-specific dependencies here
41+
"haystack-ai>=2.24.1",
42+
"httpx>=0.27.0",
43+
"requests>=2.32.0",
4044
]
4145

4246
[project.urls]
43-
# TODO: Replace with your repository URL
44-
Documentation = "https://github.com/your-org/example-haystack#readme"
45-
Issues = "https://github.com/your-org/example-haystack/issues"
46-
Source = "https://github.com/your-org/example-haystack"
47+
Homepage = "https://context.dev"
48+
Documentation = "https://github.com/context-dot-dev/context-haystack#readme"
49+
Issues = "https://github.com/context-dot-dev/context-haystack/issues"
50+
Source = "https://github.com/context-dot-dev/context-haystack"
4751

4852
[tool.hatch.version]
4953
source = "vcs"
@@ -65,15 +69,20 @@ fmt-check = "ruff check {args:.} && ruff format --check {args:.}"
6569

6670
[tool.hatch.envs.test]
6771
dependencies = [
72+
"mypy",
6873
"pytest",
74+
"pytest-asyncio",
6975
"pytest-cov",
76+
"pytest-mock",
77+
"types-requests",
7078
]
7179

7280
[tool.hatch.envs.test.scripts]
7381
unit = 'pytest -m "not integration" {args:tests}'
7482
integration = 'pytest -m "integration" {args:tests}'
7583
all = "pytest {args:tests}"
7684
cov = "pytest --cov=haystack_integrations {args:tests}"
85+
types = "mypy src tests"
7786

7887
[tool.ruff]
7988
line-length = 120
@@ -138,10 +147,10 @@ ban-relative-imports = "parents"
138147
"examples/**/*" = ["D", "T201", "ANN"]
139148

140149
[tool.mypy]
141-
install_types = true
142-
non_interactive = true
143150
check_untyped_defs = true
144151
disallow_incomplete_defs = true
152+
explicit_package_bases = true
153+
mypy_path = "src"
145154

146155
[[tool.mypy.overrides]]
147156
module = ["haystack.*"]

‎src/haystack_integrations/components/example/__init__.py‎

Lines changed: 0 additions & 8 deletions
This file was deleted.

‎src/haystack_integrations/components/example/example_component.py‎

Lines changed: 0 additions & 46 deletions
This file was deleted.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# SPDX-FileCopyrightText: 2026-present Context.dev
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
from haystack_integrations.components.fetchers.context.context_crawler import ContextCrawler
6+
from haystack_integrations.components.fetchers.context.context_fetcher import ContextFetcher
7+
from haystack_integrations.context import ContextError
8+
9+
__all__ = ["ContextCrawler", "ContextError", "ContextFetcher"]

0 commit comments

Comments
 (0)