gossamer-web 0.9.0__tar.gz
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.
- gossamer_web-0.9.0/.coderadar.toml +37 -0
- gossamer_web-0.9.0/.github/workflows/ci.yml +120 -0
- gossamer_web-0.9.0/.github/workflows/release.yml +160 -0
- gossamer_web-0.9.0/.gitignore +54 -0
- gossamer_web-0.9.0/AGENTS.md +23 -0
- gossamer_web-0.9.0/CHANGELOG.md +1203 -0
- gossamer_web-0.9.0/CONTRIBUTING.md +64 -0
- gossamer_web-0.9.0/Cargo.lock +3196 -0
- gossamer_web-0.9.0/Cargo.toml +40 -0
- gossamer_web-0.9.0/LICENSE +194 -0
- gossamer_web-0.9.0/PKG-INFO +249 -0
- gossamer_web-0.9.0/README.md +204 -0
- gossamer_web-0.9.0/SECURITY.md +53 -0
- gossamer_web-0.9.0/benchmarks.py +399 -0
- gossamer_web-0.9.0/docs/ARCHITECTURE.md +356 -0
- gossamer_web-0.9.0/docs/QUICKREF.md +67 -0
- gossamer_web-0.9.0/gossamer/__init__.py +157 -0
- gossamer_web-0.9.0/gossamer/_core.pyi +860 -0
- gossamer_web-0.9.0/gossamer/agent_tools.py +1259 -0
- gossamer_web-0.9.0/gossamer/budget.py +138 -0
- gossamer_web-0.9.0/gossamer/cache.py +468 -0
- gossamer_web-0.9.0/gossamer/citations.py +336 -0
- gossamer_web-0.9.0/gossamer/cli.py +187 -0
- gossamer_web-0.9.0/gossamer/config.py +700 -0
- gossamer_web-0.9.0/gossamer/crawl.py +981 -0
- gossamer_web-0.9.0/gossamer/dedup.py +110 -0
- gossamer_web-0.9.0/gossamer/discovery.py +251 -0
- gossamer_web-0.9.0/gossamer/document.py +1158 -0
- gossamer_web-0.9.0/gossamer/env.py +86 -0
- gossamer_web-0.9.0/gossamer/fetch.py +1336 -0
- gossamer_web-0.9.0/gossamer/guard.py +561 -0
- gossamer_web-0.9.0/gossamer/keystore.py +138 -0
- gossamer_web-0.9.0/gossamer/liveness.py +153 -0
- gossamer_web-0.9.0/gossamer/mcp_server.py +311 -0
- gossamer_web-0.9.0/gossamer/meta_extractor.py +232 -0
- gossamer_web-0.9.0/gossamer/models.py +408 -0
- gossamer_web-0.9.0/gossamer/py.typed +0 -0
- gossamer_web-0.9.0/gossamer/research_categories.py +508 -0
- gossamer_web-0.9.0/gossamer/research_providers.py +3055 -0
- gossamer_web-0.9.0/gossamer/resource_store.py +330 -0
- gossamer_web-0.9.0/gossamer/robots.py +212 -0
- gossamer_web-0.9.0/gossamer/search.py +419 -0
- gossamer_web-0.9.0/gossamer/search_providers.py +830 -0
- gossamer_web-0.9.0/gossamer/sections.py +35 -0
- gossamer_web-0.9.0/gossamer/settings.py +255 -0
- gossamer_web-0.9.0/gossamer/ssrf.py +75 -0
- gossamer_web-0.9.0/gossamer/structured_parser.py +894 -0
- gossamer_web-0.9.0/gossamer/text_links.py +59 -0
- gossamer_web-0.9.0/gossamer/thesaurus.json +36 -0
- gossamer_web-0.9.0/gossamer/token_budget.py +276 -0
- gossamer_web-0.9.0/pyproject.toml +100 -0
- gossamer_web-0.9.0/requirements.txt +13 -0
- gossamer_web-0.9.0/scripts/audit_cargo.py +94 -0
- gossamer_web-0.9.0/skills/gossamer/SKILL.md +67 -0
- gossamer_web-0.9.0/src/adapters.rs +7548 -0
- gossamer_web-0.9.0/src/budget.rs +392 -0
- gossamer_web-0.9.0/src/cacheutils.rs +173 -0
- gossamer_web-0.9.0/src/categories.rs +149 -0
- gossamer_web-0.9.0/src/cite.rs +1037 -0
- gossamer_web-0.9.0/src/dedupe.rs +201 -0
- gossamer_web-0.9.0/src/guard.rs +325 -0
- gossamer_web-0.9.0/src/lib.rs +1643 -0
- gossamer_web-0.9.0/src/metaextract.rs +469 -0
- gossamer_web-0.9.0/src/miscutils.rs +310 -0
- gossamer_web-0.9.0/src/pycompat.rs +154 -0
- gossamer_web-0.9.0/src/robots.rs +313 -0
- gossamer_web-0.9.0/src/sections.rs +405 -0
- gossamer_web-0.9.0/src/ssrf.rs +380 -0
- gossamer_web-0.9.0/src/textlinks.rs +80 -0
- gossamer_web-0.9.0/src/tokens.rs +295 -0
- gossamer_web-0.9.0/src/urls.rs +581 -0
- gossamer_web-0.9.0/src/xmlatom.rs +236 -0
- gossamer_web-0.9.0/tests/conftest.py +198 -0
- gossamer_web-0.9.0/tests/fixtures/guard_corpus/README.md +20 -0
- gossamer_web-0.9.0/tests/fixtures/guard_corpus/benign/01_library_docs.md +25 -0
- gossamer_web-0.9.0/tests/fixtures/guard_corpus/benign/02_release_notes.md +24 -0
- gossamer_web-0.9.0/tests/fixtures/guard_corpus/benign/03_prompt_engineering_article.md +24 -0
- gossamer_web-0.9.0/tests/fixtures/guard_corpus/benign/04_forum_thread.md +23 -0
- gossamer_web-0.9.0/tests/fixtures/guard_corpus/benign/05_product_page.md +24 -0
- gossamer_web-0.9.0/tests/fixtures/guard_corpus/injected/01_hidden_comment.md +15 -0
- gossamer_web-0.9.0/tests/fixtures/guard_corpus/injected/02_fake_system_turn.md +17 -0
- gossamer_web-0.9.0/tests/fixtures/guard_corpus/injected/03_polite_request.md +15 -0
- gossamer_web-0.9.0/tests/fixtures/guard_corpus/injected/04_exfiltration.md +17 -0
- gossamer_web-0.9.0/tests/fixtures/guard_corpus/injected/05_tool_redirection.md +13 -0
- gossamer_web-0.9.0/tests/fixtures_mini.pdf +51 -0
- gossamer_web-0.9.0/tests/test_browser_integration.py +30 -0
- gossamer_web-0.9.0/tests/test_browser_provider.py +133 -0
- gossamer_web-0.9.0/tests/test_c1_follow_links.py +110 -0
- gossamer_web-0.9.0/tests/test_c2_metadata.py +152 -0
- gossamer_web-0.9.0/tests/test_c3_retry.py +170 -0
- gossamer_web-0.9.0/tests/test_c4_doc_cache_truncation.py +59 -0
- gossamer_web-0.9.0/tests/test_c5_structured_links.py +123 -0
- gossamer_web-0.9.0/tests/test_c6_batch_cache.py +168 -0
- gossamer_web-0.9.0/tests/test_cache.py +328 -0
- gossamer_web-0.9.0/tests/test_citations.py +373 -0
- gossamer_web-0.9.0/tests/test_cli.py +74 -0
- gossamer_web-0.9.0/tests/test_crawler.py +833 -0
- gossamer_web-0.9.0/tests/test_dedup_liveness.py +317 -0
- gossamer_web-0.9.0/tests/test_doc_images.py +150 -0
- gossamer_web-0.9.0/tests/test_doc_size_cap.py +94 -0
- gossamer_web-0.9.0/tests/test_exa_provider_features.py +240 -0
- gossamer_web-0.9.0/tests/test_extract_links.py +172 -0
- gossamer_web-0.9.0/tests/test_fix_bare_filename.py +73 -0
- gossamer_web-0.9.0/tests/test_fix_batch_metadata.py +123 -0
- gossamer_web-0.9.0/tests/test_fix_guard_bench.py +105 -0
- gossamer_web-0.9.0/tests/test_fix_json_integrity.py +145 -0
- gossamer_web-0.9.0/tests/test_fix_provider_fallback.py +90 -0
- gossamer_web-0.9.0/tests/test_fix_setext_sections.py +127 -0
- gossamer_web-0.9.0/tests/test_fix_url_error_contract.py +140 -0
- gossamer_web-0.9.0/tests/test_focused_discovery.py +456 -0
- gossamer_web-0.9.0/tests/test_focused_discovery_semantic.py +612 -0
- gossamer_web-0.9.0/tests/test_guard.py +699 -0
- gossamer_web-0.9.0/tests/test_html_store.py +101 -0
- gossamer_web-0.9.0/tests/test_input_shapes.py +254 -0
- gossamer_web-0.9.0/tests/test_live_smoke.py +407 -0
- gossamer_web-0.9.0/tests/test_m10_batch_error.py +134 -0
- gossamer_web-0.9.0/tests/test_m11_budget_loop.py +113 -0
- gossamer_web-0.9.0/tests/test_m12_markdown_links.py +136 -0
- gossamer_web-0.9.0/tests/test_m13_rate_limit_copy.py +53 -0
- gossamer_web-0.9.0/tests/test_m14_looks_like_text.py +47 -0
- gossamer_web-0.9.0/tests/test_m15_retry_after.py +133 -0
- gossamer_web-0.9.0/tests/test_m16_document_formats.py +109 -0
- gossamer_web-0.9.0/tests/test_m17_fetch_mode_dispatch.py +250 -0
- gossamer_web-0.9.0/tests/test_m1_local_paths.py +81 -0
- gossamer_web-0.9.0/tests/test_m2_provider_aliases.py +141 -0
- gossamer_web-0.9.0/tests/test_m3_retry.py +129 -0
- gossamer_web-0.9.0/tests/test_m4_truncate_fallback.py +69 -0
- gossamer_web-0.9.0/tests/test_m5_encoding.py +65 -0
- gossamer_web-0.9.0/tests/test_m6_asyncio.py +95 -0
- gossamer_web-0.9.0/tests/test_m7_bounded_state.py +107 -0
- gossamer_web-0.9.0/tests/test_m8_use_smart.py +185 -0
- gossamer_web-0.9.0/tests/test_m9_http_pool.py +118 -0
- gossamer_web-0.9.0/tests/test_mcp_server.py +178 -0
- gossamer_web-0.9.0/tests/test_meta_oxide.py +254 -0
- gossamer_web-0.9.0/tests/test_p2_doc_extra.py +73 -0
- gossamer_web-0.9.0/tests/test_p8_tool_registry.py +148 -0
- gossamer_web-0.9.0/tests/test_p9_doc_store.py +195 -0
- gossamer_web-0.9.0/tests/test_patent_adapters.py +171 -0
- gossamer_web-0.9.0/tests/test_phase3_adapters.py +457 -0
- gossamer_web-0.9.0/tests/test_phase3_wave2.py +415 -0
- gossamer_web-0.9.0/tests/test_plan_fixes.py +485 -0
- gossamer_web-0.9.0/tests/test_providers.py +278 -0
- gossamer_web-0.9.0/tests/test_research_categories.py +639 -0
- gossamer_web-0.9.0/tests/test_research_providers.py +732 -0
- gossamer_web-0.9.0/tests/test_resource_store.py +139 -0
- gossamer_web-0.9.0/tests/test_rust_parity_adapters.py +5560 -0
- gossamer_web-0.9.0/tests/test_rust_parity_budget.py +206 -0
- gossamer_web-0.9.0/tests/test_rust_parity_categories.py +94 -0
- gossamer_web-0.9.0/tests/test_rust_parity_citations.py +456 -0
- gossamer_web-0.9.0/tests/test_rust_parity_dedupe.py +198 -0
- gossamer_web-0.9.0/tests/test_rust_parity_guard.py +319 -0
- gossamer_web-0.9.0/tests/test_rust_parity_metaextract.py +242 -0
- gossamer_web-0.9.0/tests/test_rust_parity_robots.py +215 -0
- gossamer_web-0.9.0/tests/test_rust_parity_sections.py +275 -0
- gossamer_web-0.9.0/tests/test_rust_parity_ssrf.py +262 -0
- gossamer_web-0.9.0/tests/test_rust_parity_tokens.py +196 -0
- gossamer_web-0.9.0/tests/test_rust_parity_urls.py +262 -0
- gossamer_web-0.9.0/tests/test_s1_ssrf.py +232 -0
- gossamer_web-0.9.0/tests/test_s2_hidden.py +164 -0
- gossamer_web-0.9.0/tests/test_s3_size_cap.py +178 -0
- gossamer_web-0.9.0/tests/test_s4_robots.py +281 -0
- gossamer_web-0.9.0/tests/test_s5_concurrency.py +307 -0
- gossamer_web-0.9.0/tests/test_s6_scoped_clear.py +87 -0
- gossamer_web-0.9.0/tests/test_s7_disk_key.py +34 -0
- gossamer_web-0.9.0/tests/test_s7_fetch_politeness.py +129 -0
- gossamer_web-0.9.0/tests/test_search_provider_defaults.py +90 -0
- gossamer_web-0.9.0/tests/test_settings.py +188 -0
- gossamer_web-0.9.0/tests/test_t1_2_chunks.py +263 -0
- gossamer_web-0.9.0/tests/test_t1_2_pages.py +322 -0
- gossamer_web-0.9.0/tests/test_t1_3_provenance.py +373 -0
- gossamer_web-0.9.0/tests/test_t1_4_conditional.py +319 -0
- gossamer_web-0.9.0/tests/test_t1_sections.py +285 -0
- gossamer_web-0.9.0/tests/test_t2_6_observability.py +275 -0
- gossamer_web-0.9.0/tests/test_t2_7_transport.py +151 -0
- gossamer_web-0.9.0/tests/test_t2_8_search_cache.py +238 -0
- gossamer_web-0.9.0/tests/test_t2_9_async.py +102 -0
- gossamer_web-0.9.0/tests/test_t3_10_formats.py +312 -0
- gossamer_web-0.9.0/tests/test_t3_11_tables.py +334 -0
- gossamer_web-0.9.0/tests/test_t3_12_discovery.py +355 -0
- gossamer_web-0.9.0/tests/test_t3_13_research.py +324 -0
- gossamer_web-0.9.0/tests/test_wave3_adapters.py +268 -0
- gossamer_web-0.9.0/uv.lock +1613 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# CodeRadar project configuration
|
|
2
|
+
# Generated by `coderadar init` on 2026-08-24T23:23:19.765004
|
|
3
|
+
#
|
|
4
|
+
# `coderadar analyze` prints a line naming any key it could not use, so a
|
|
5
|
+
# stale or misspelled setting here will say so rather than sit silent.
|
|
6
|
+
|
|
7
|
+
[project]
|
|
8
|
+
# Narrow the walk to these subdirectories; omitted, the whole root is walked.
|
|
9
|
+
# roots = ["src/", "tests/"]
|
|
10
|
+
exclude = ["**/__pycache__/**", "**/.venv/**", "**/node_modules/**", "**/target/**", ".gossamer_cache/**"]
|
|
11
|
+
|
|
12
|
+
[database]
|
|
13
|
+
path = ".coderadar/store/coderadar.db"
|
|
14
|
+
|
|
15
|
+
[embedding]
|
|
16
|
+
# Index-time and query-time must name the same model: a dimension mismatch
|
|
17
|
+
# produces confident nonsense rather than an error.
|
|
18
|
+
model = "BAAI/bge-small-en-v1.5"
|
|
19
|
+
dimension = 384
|
|
20
|
+
batch_size = 32
|
|
21
|
+
|
|
22
|
+
[watch]
|
|
23
|
+
debounce_ms = 100
|
|
24
|
+
max_file_size_bytes = 1048576
|
|
25
|
+
|
|
26
|
+
[mutation]
|
|
27
|
+
enabled = true
|
|
28
|
+
default_dry_run = true
|
|
29
|
+
allow = ["src/", "lib/", "tests/", "scripts/", "gossamer/"]
|
|
30
|
+
deny = [".git/", ".coderadar/", "/migrations/", "/*.lock", "/generated/"]
|
|
31
|
+
|
|
32
|
+
[resolution]
|
|
33
|
+
min_confidence = 0.3
|
|
34
|
+
|
|
35
|
+
[resolution.import_graph]
|
|
36
|
+
max_import_depth = 3
|
|
37
|
+
include_same_package = true
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, master, dev]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main, master]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ${{ matrix.os }}
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: false
|
|
14
|
+
matrix:
|
|
15
|
+
os: [ubuntu-latest, windows-latest]
|
|
16
|
+
python-version: ['3.10', '3.11', '3.12', '3.13']
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
22
|
+
uses: actions/setup-python@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: ${{ matrix.python-version }}
|
|
25
|
+
|
|
26
|
+
- name: Install Rust
|
|
27
|
+
uses: dtolnay/rust-toolchain@stable
|
|
28
|
+
|
|
29
|
+
- name: Cache Rust dependencies
|
|
30
|
+
uses: actions/cache@v4
|
|
31
|
+
with:
|
|
32
|
+
path: |
|
|
33
|
+
~/.cargo/registry
|
|
34
|
+
~/.cargo/git
|
|
35
|
+
target
|
|
36
|
+
key: ${{ runner.os }}-rust-${{ hashFiles('**/Cargo.lock') }}
|
|
37
|
+
restore-keys: |
|
|
38
|
+
${{ runner.os }}-rust-
|
|
39
|
+
|
|
40
|
+
- name: Create virtual environment
|
|
41
|
+
run: python -m venv .venv
|
|
42
|
+
|
|
43
|
+
# The maturin build backend is pulled in by pip's build isolation,
|
|
44
|
+
# so no separate maturin install or `maturin develop` step is needed.
|
|
45
|
+
# Installing the package via its metadata is what validates the
|
|
46
|
+
# runtime dependency declarations (P1).
|
|
47
|
+
- name: Install package with dependencies (Linux/macOS)
|
|
48
|
+
if: runner.os != 'Windows'
|
|
49
|
+
run: |
|
|
50
|
+
./.venv/bin/pip install -e ".[mcp,documents]"
|
|
51
|
+
./.venv/bin/pip install -r requirements.txt
|
|
52
|
+
|
|
53
|
+
- name: Install package with dependencies (Windows)
|
|
54
|
+
if: runner.os == 'Windows'
|
|
55
|
+
run: |
|
|
56
|
+
.venv\Scripts\pip.exe install -e ".[mcp,documents]"
|
|
57
|
+
.venv\Scripts\pip.exe install -r requirements.txt
|
|
58
|
+
|
|
59
|
+
- name: Run tests (Linux/macOS)
|
|
60
|
+
if: runner.os != 'Windows'
|
|
61
|
+
run: ./.venv/bin/pytest tests/ -v --tb=short
|
|
62
|
+
|
|
63
|
+
- name: Run tests (Windows)
|
|
64
|
+
if: runner.os == 'Windows'
|
|
65
|
+
run: .venv\Scripts\pytest.exe tests/ -v --tb=short
|
|
66
|
+
|
|
67
|
+
supply-chain:
|
|
68
|
+
runs-on: ubuntu-latest
|
|
69
|
+
steps:
|
|
70
|
+
- uses: actions/checkout@v4
|
|
71
|
+
|
|
72
|
+
- name: Set up Python
|
|
73
|
+
uses: actions/setup-python@v5
|
|
74
|
+
with:
|
|
75
|
+
python-version: '3.12'
|
|
76
|
+
|
|
77
|
+
# Audit the installed runtime + extra dependencies against the OSV
|
|
78
|
+
# vulnerability database. Given PyPI-targeting worm campaigns of the
|
|
79
|
+
# past year, this is a hard gate, not a warning.
|
|
80
|
+
- name: pip-audit
|
|
81
|
+
run: |
|
|
82
|
+
python -m venv /tmp/auditenv
|
|
83
|
+
# The runner-bundled pip is often itself advisory-flagged —
|
|
84
|
+
# upgrade it inside the venv so the audit covers our dependencies,
|
|
85
|
+
# not the runner image.
|
|
86
|
+
/tmp/auditenv/bin/pip install --quiet --upgrade pip
|
|
87
|
+
/tmp/auditenv/bin/pip install --quiet pip-audit
|
|
88
|
+
/tmp/auditenv/bin/pip install --quiet -e ".[mcp,documents]"
|
|
89
|
+
/tmp/auditenv/bin/pip-audit
|
|
90
|
+
|
|
91
|
+
# Audit the Rust dependency tree (Cargo.lock) against OSV — the same
|
|
92
|
+
# database pip-audit uses, which mirrors RustSec. Stdlib-only script,
|
|
93
|
+
# no cargo toolchain step (cargo-audit's crates.io release is stale and
|
|
94
|
+
# its prebuilt binaries are a moving target).
|
|
95
|
+
- name: cargo audit (OSV)
|
|
96
|
+
run: python scripts/audit_cargo.py
|
|
97
|
+
|
|
98
|
+
lint:
|
|
99
|
+
runs-on: ubuntu-latest
|
|
100
|
+
steps:
|
|
101
|
+
- uses: actions/checkout@v4
|
|
102
|
+
|
|
103
|
+
- name: Set up Python
|
|
104
|
+
uses: actions/setup-python@v5
|
|
105
|
+
with:
|
|
106
|
+
python-version: '3.12'
|
|
107
|
+
|
|
108
|
+
- name: Install Rust
|
|
109
|
+
uses: dtolnay/rust-toolchain@stable
|
|
110
|
+
with:
|
|
111
|
+
components: clippy
|
|
112
|
+
|
|
113
|
+
- name: Rust clippy
|
|
114
|
+
run: cargo clippy --all-targets -- -D warnings
|
|
115
|
+
|
|
116
|
+
- name: Install Python linting tools
|
|
117
|
+
run: pip install "ruff==0.16.4"
|
|
118
|
+
|
|
119
|
+
- name: Run ruff
|
|
120
|
+
run: ruff check gossamer/
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Publishing happens on version tag push (e.g. `git tag v0.9.0 && git push
|
|
4
|
+
# origin v0.9.0`). The tag MUST match Cargo.toml/pyproject.toml — enforced
|
|
5
|
+
# by the check-tag job below.
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
tags:
|
|
10
|
+
- 'v*.*.*'
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
check-tag:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- name: Tag matches package version
|
|
19
|
+
run: |
|
|
20
|
+
TAG="${GITHUB_REF#refs/tags/v}"
|
|
21
|
+
CARGO=$(grep '^version' Cargo.toml | head -1 | cut -d'"' -f2)
|
|
22
|
+
PYPROJ=$(grep '^version' pyproject.toml | head -1 | cut -d'"' -f2)
|
|
23
|
+
echo "tag=$TAG cargo=$CARGO pyproject=$PYPROJ"
|
|
24
|
+
[ "$TAG" = "$CARGO" ] && [ "$TAG" = "$PYPROJ" ] || {
|
|
25
|
+
echo "::error::tag v$TAG != Cargo.toml ($CARGO) / pyproject.toml ($PYPROJ)"
|
|
26
|
+
exit 1
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
build-wheels:
|
|
30
|
+
needs: check-tag
|
|
31
|
+
runs-on: ${{ matrix.os }}
|
|
32
|
+
strategy:
|
|
33
|
+
fail-fast: false
|
|
34
|
+
matrix:
|
|
35
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
36
|
+
# Single interpreter per OS: pyo3 abi3-py38 makes one wheel per
|
|
37
|
+
# platform installable on every supported Python (>=3.10).
|
|
38
|
+
python-version: ['3.12']
|
|
39
|
+
|
|
40
|
+
steps:
|
|
41
|
+
- uses: actions/checkout@v4
|
|
42
|
+
|
|
43
|
+
- name: Set up Python
|
|
44
|
+
uses: actions/setup-python@v5
|
|
45
|
+
with:
|
|
46
|
+
python-version: ${{ matrix.python-version }}
|
|
47
|
+
|
|
48
|
+
# manylinux: auditwheel-repaired portable Linux wheels — plain
|
|
49
|
+
# `maturin build` emits linux_x86_64 wheels that PyPI REJECTS.
|
|
50
|
+
# (macOS/Windows need no equivalent; the flag is Linux-only.)
|
|
51
|
+
- name: Build wheel (Linux, manylinux)
|
|
52
|
+
if: runner.os == 'Linux'
|
|
53
|
+
uses: PyO3/maturin-action@v1
|
|
54
|
+
with:
|
|
55
|
+
command: build
|
|
56
|
+
args: --release --out dist
|
|
57
|
+
manylinux: auto
|
|
58
|
+
|
|
59
|
+
- name: Build wheel (macOS / Windows)
|
|
60
|
+
if: runner.os != 'Linux'
|
|
61
|
+
uses: PyO3/maturin-action@v1
|
|
62
|
+
with:
|
|
63
|
+
command: build
|
|
64
|
+
args: --release --out dist
|
|
65
|
+
|
|
66
|
+
- name: Upload wheel artifact
|
|
67
|
+
uses: actions/upload-artifact@v4
|
|
68
|
+
with:
|
|
69
|
+
name: wheels-${{ runner.os }}
|
|
70
|
+
path: dist/*.whl
|
|
71
|
+
|
|
72
|
+
build-sdist:
|
|
73
|
+
needs: check-tag
|
|
74
|
+
runs-on: ubuntu-latest
|
|
75
|
+
steps:
|
|
76
|
+
- uses: actions/checkout@v4
|
|
77
|
+
|
|
78
|
+
- name: Set up Python
|
|
79
|
+
uses: actions/setup-python@v5
|
|
80
|
+
with:
|
|
81
|
+
python-version: '3.12'
|
|
82
|
+
|
|
83
|
+
- name: Install Rust
|
|
84
|
+
uses: dtolnay/rust-toolchain@stable
|
|
85
|
+
|
|
86
|
+
- name: Install maturin
|
|
87
|
+
run: pip install "maturin>=1.0,<2.0"
|
|
88
|
+
|
|
89
|
+
# Needs network: resolves the meta_oxide git dependency. sdist
|
|
90
|
+
# consumers rebuild from source, so this is expected.
|
|
91
|
+
- name: Build sdist
|
|
92
|
+
run: maturin sdist --out dist
|
|
93
|
+
|
|
94
|
+
- name: Upload sdist artifact
|
|
95
|
+
uses: actions/upload-artifact@v4
|
|
96
|
+
with:
|
|
97
|
+
name: sdist
|
|
98
|
+
path: dist/*.tar.gz
|
|
99
|
+
|
|
100
|
+
publish:
|
|
101
|
+
needs: [build-wheels, build-sdist]
|
|
102
|
+
runs-on: ubuntu-latest
|
|
103
|
+
if: startsWith(github.ref, 'refs/tags/')
|
|
104
|
+
permissions:
|
|
105
|
+
contents: write # GitHub Release
|
|
106
|
+
id-token: write # PyPI Trusted Publishing (OIDC, no secret)
|
|
107
|
+
|
|
108
|
+
steps:
|
|
109
|
+
- name: Download artifacts
|
|
110
|
+
uses: actions/download-artifact@v4
|
|
111
|
+
with:
|
|
112
|
+
pattern: wheels-*
|
|
113
|
+
path: dist
|
|
114
|
+
merge-multiple: true
|
|
115
|
+
|
|
116
|
+
- name: Download sdist
|
|
117
|
+
uses: actions/download-artifact@v4
|
|
118
|
+
with:
|
|
119
|
+
name: sdist
|
|
120
|
+
path: dist
|
|
121
|
+
|
|
122
|
+
# A GitHub Release with the wheels is created for every tag, with or
|
|
123
|
+
# without PyPI credentials, so released versions are always
|
|
124
|
+
# downloadable and pinnable from GitHub.
|
|
125
|
+
- name: Create GitHub Release
|
|
126
|
+
uses: softprops/action-gh-release@v2
|
|
127
|
+
with:
|
|
128
|
+
files: dist/*
|
|
129
|
+
generate_release_notes: true
|
|
130
|
+
|
|
131
|
+
- name: Check PyPI token
|
|
132
|
+
id: token
|
|
133
|
+
env:
|
|
134
|
+
TOKEN: ${{ secrets.PYPI_API_TOKEN }}
|
|
135
|
+
run: |
|
|
136
|
+
if [ -n "$TOKEN" ]; then echo "has=true" >> "$GITHUB_OUTPUT"; fi
|
|
137
|
+
|
|
138
|
+
# Preferred: Trusted Publishing (configure once on PyPI: project
|
|
139
|
+
# settings → trusted publisher = this repo + release.yml workflow).
|
|
140
|
+
# Falls back to PYPI_API_TOKEN when OIDC is unavailable.
|
|
141
|
+
- name: Publish to PyPI (trusted publishing)
|
|
142
|
+
id: oidc
|
|
143
|
+
continue-on-error: true
|
|
144
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
145
|
+
|
|
146
|
+
- name: Publish to PyPI (API token)
|
|
147
|
+
if: steps.oidc.outcome == 'failure' && steps.token.outputs.has == 'true'
|
|
148
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
149
|
+
with:
|
|
150
|
+
password: ${{ secrets.PYPI_API_TOKEN }}
|
|
151
|
+
|
|
152
|
+
- name: Publish outcome
|
|
153
|
+
run: |
|
|
154
|
+
if [ "${{ steps.oidc.outcome }}" = "success" ]; then
|
|
155
|
+
echo "PyPI publish: trusted publishing OK"
|
|
156
|
+
elif [ "${{ steps.token.outputs.has }}" = "true" ]; then
|
|
157
|
+
echo "PyPI publish: API token path taken (check step above)"
|
|
158
|
+
else
|
|
159
|
+
echo "::notice::PyPI publish skipped — no trusted publisher and no PYPI_API_TOKEN secret. Wheels are on the GitHub Release."
|
|
160
|
+
fi
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# CodeRadar index
|
|
2
|
+
.coderadar/
|
|
3
|
+
|
|
4
|
+
# Rust build artifacts
|
|
5
|
+
/target/
|
|
6
|
+
**/*.rs.bk
|
|
7
|
+
|
|
8
|
+
# Python bytecode & caches
|
|
9
|
+
__pycache__/
|
|
10
|
+
*.py[cod]
|
|
11
|
+
*$py.class
|
|
12
|
+
.pytest_cache/
|
|
13
|
+
.mypy_cache/
|
|
14
|
+
.ruff_cache/
|
|
15
|
+
|
|
16
|
+
# Compiled extension (built via maturin; rebuild with `maturin develop`)
|
|
17
|
+
*.so
|
|
18
|
+
*.pyd
|
|
19
|
+
# Windows debug symbols from the built extension (churns on every rebuild).
|
|
20
|
+
*.pdb
|
|
21
|
+
|
|
22
|
+
# Packaging
|
|
23
|
+
build/
|
|
24
|
+
dist/
|
|
25
|
+
*.egg-info/
|
|
26
|
+
|
|
27
|
+
# Virtual environments
|
|
28
|
+
.venv/
|
|
29
|
+
venv/
|
|
30
|
+
env/
|
|
31
|
+
|
|
32
|
+
# Runtime caches
|
|
33
|
+
.gossamer_cache/
|
|
34
|
+
.web_research_cache/
|
|
35
|
+
stored_documents/
|
|
36
|
+
|
|
37
|
+
# Editors / OS
|
|
38
|
+
.vscode/
|
|
39
|
+
.idea/
|
|
40
|
+
.DS_Store
|
|
41
|
+
Thumbs.db
|
|
42
|
+
crash.log
|
|
43
|
+
|
|
44
|
+
# Scratch artifacts
|
|
45
|
+
step1_links.json
|
|
46
|
+
wiki_topics.json
|
|
47
|
+
|
|
48
|
+
# Windows device-name artifact (prevents accidental indexing)
|
|
49
|
+
nul
|
|
50
|
+
|
|
51
|
+
# Local planning spillover (audits, provider research, internal plans).
|
|
52
|
+
# Deliberately unsynced: working notes live here, the repo keeps only
|
|
53
|
+
# docs/QUICKREF.md + docs/ARCHITECTURE.md as its synced record.
|
|
54
|
+
/planning/
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# AGENTS.md — gossamer
|
|
2
|
+
|
|
3
|
+
Web research toolkit (Python + Rust). For any task needing **current external
|
|
4
|
+
information** (docs, APIs, papers, case law, market data, patents), use
|
|
5
|
+
gossamer instead of guessing or raw curl loops.
|
|
6
|
+
|
|
7
|
+
- **MCP** (if configured): 10 tools — `web_search`, `inspect_html_page`,
|
|
8
|
+
`batch_inspect_pages`, `extract_document`, `discover_resources`,
|
|
9
|
+
`crawl`, `manage_cache`, `research_by_category`,
|
|
10
|
+
`export_citations`, `check_sources`.
|
|
11
|
+
- **CLI** (always available, mirrors all 10 MCP tools 1:1):
|
|
12
|
+
`gossamer search|research|categories|inspect|batch|extract|check|discover|crawl|cache|cite`
|
|
13
|
+
(or `python -m gossamer.cli …` from the project venv).
|
|
14
|
+
- **Routing**: `gossamer categories` prints the live category → provider
|
|
15
|
+
table (`scholarly`/`legal`/`patent`/`financial`/`geo`). Patent providers
|
|
16
|
+
are key-gated — surface missing-key errors to the user, don't retry.
|
|
17
|
+
- **Budgets**: keep crawls ≤ 15 pages, set `max_tokens`, extract page ranges.
|
|
18
|
+
- **Keys**: `~/.gossamer/keys.json` (`python -m gossamer.keystore --init`);
|
|
19
|
+
never put secrets in configs or prompts.
|
|
20
|
+
|
|
21
|
+
Dev: `.venv/Scripts/python.exe -m pytest -q` (full suite),
|
|
22
|
+
`ruff check gossamer/`, `maturin develop --release` after touching `src/`.
|
|
23
|
+
Target branch for changes: `dev`.
|