Clarify available source types in explorer and CLI

This commit is contained in:
welsberr 2026-04-07 06:13:05 -04:00
parent 663fb1973a
commit b26f662af9
6 changed files with 77 additions and 5 deletions

View File

@ -297,7 +297,7 @@ Expand from one or more seed entries:
.venv/bin/python -m citegeist --db library.sqlite3 expand langton1989artificial1
```
Choose the source:
Choose the graph expansion source:
```bash
.venv/bin/python -m citegeist --db library.sqlite3 expand langton1989artificial1 --source openalex
@ -333,12 +333,14 @@ Override the topic phrase:
.venv/bin/python -m citegeist --db library.sqlite3 expand-topic artificial-life --topic-phrase "artificial life alife artificial organisms"
```
Choose source and relation:
Choose graph expansion source and relation:
```bash
.venv/bin/python -m citegeist --db library.sqlite3 expand-topic artificial-life --source openalex --relation cited_by
```
Note: graph expansion currently supports `openalex` and `crossref`. Metadata resolution, verification, and bootstrap topic seeding also use `datacite` and `pubmed`.
Control seed and discovery limits:
```bash

View File

@ -45,6 +45,11 @@ The adapter exposes JSON-serializable methods suitable for a local web bridge:
- `verify_bibtex(bibtex_text, context="", limit=5)`
- `graph(seed_keys, relation_types=None, depth=1, review_status=None, missing_only=False)`
The `capabilities()` payload also distinguishes between broader metadata/search sources and narrower graph-expansion sources:
- metadata and topic seeding currently use `crossref`, `datacite`, `openalex`, and `pubmed`
- topic graph expansion currently uses `crossref` and `openalex`
## Browser Contract
A demo app can expose a browser object like:

View File

@ -561,7 +561,7 @@
</label>
<div class="row-3">
<label>
Source
Expansion Source
<select id="expand-source">
<option value="openalex">openalex</option>
<option value="crossref">crossref</option>
@ -611,6 +611,7 @@
<div id="expand-summary" class="summary-box">
<strong>Expansion Policy</strong>
<p>Use <code>cites</code> to bias toward newer work, or <code>both</code> for broader graph growth. Recursive rounds stop once the recent-entry target is met.</p>
<p id="expand-source-note">Topic graph expansion currently supports openalex and crossref. Metadata search and bootstrap seeding also use datacite and pubmed.</p>
</div>
</section>
@ -827,6 +828,7 @@
expandPreviewButton: document.getElementById("expand-preview-button"),
expandCommitButton: document.getElementById("expand-commit-button"),
expandSummary: document.getElementById("expand-summary"),
expandSourceNote: document.getElementById("expand-source-note"),
searchQuery: document.getElementById("search-query"),
searchTopic: document.getElementById("search-topic"),
searchButton: document.getElementById("search-button"),
@ -1081,6 +1083,43 @@
`;
}
function populateSelectOptions(select, values, preferredValue) {
if (!select || !Array.isArray(values) || !values.length) return;
const previousValue = select.value;
select.innerHTML = "";
values.forEach((value) => {
const option = document.createElement("option");
option.value = value;
option.textContent = value;
select.appendChild(option);
});
if (values.includes(previousValue)) {
select.value = previousValue;
} else if (values.includes(preferredValue)) {
select.value = preferredValue;
} else {
select.value = values[0];
}
}
function applyCapabilities(capabilities) {
const topicExpansionSources = capabilities?.topic_expansion_sources || capabilities?.graph_expansion_sources || [];
const relationTypes = capabilities?.graph_relation_types || [];
const metadataSources = capabilities?.metadata_sources || [];
if (topicExpansionSources.length) {
populateSelectOptions(els.expandSource, topicExpansionSources, "openalex");
}
if (relationTypes.length) {
populateSelectOptions(els.expandRelation, relationTypes, "cites");
}
if (els.expandSourceNote) {
const expansionText = topicExpansionSources.length ? topicExpansionSources.join(", ") : "openalex, crossref";
const metadataText = metadataSources.length ? metadataSources.join(", ") : "crossref, datacite, openalex, pubmed";
els.expandSourceNote.textContent =
`Topic graph expansion currently supports ${expansionText}. Metadata search and bootstrap seeding also use ${metadataText}.`;
}
}
async function connect() {
setBusy(els.connectButton, true);
try {
@ -1092,6 +1131,7 @@
const client = createLiteratureExplorerClient(bridge);
const capabilities = await client.capabilities();
state.client = client;
applyCapabilities(capabilities);
setStatus(`Connected to ${state.bridgeUrl}`, "ok");
setLastOp("connect");
logActivity("capabilities", capabilities);

View File

@ -9,6 +9,10 @@ from .extract import extract_references
from .storage import BibliographyStore
from .verify import BibliographyVerifier
METADATA_SOURCES = ["crossref", "datacite", "openalex", "pubmed"]
GRAPH_EXPANSION_SOURCES = ["crossref", "openalex"]
GRAPH_RELATION_TYPES = ["cites", "cited_by", "both"]
class LiteratureExplorerApi:
"""JSON-serializable adapter layer for browser or local UI bridges."""
@ -41,6 +45,11 @@ class LiteratureExplorerApi:
"graph",
],
"preview_operations": ["bootstrap", "expand_topic"],
"metadata_sources": list(METADATA_SOURCES),
"topic_seed_sources": list(METADATA_SOURCES),
"graph_expansion_sources": list(GRAPH_EXPANSION_SOURCES),
"topic_expansion_sources": list(GRAPH_EXPANSION_SOURCES),
"graph_relation_types": list(GRAPH_RELATION_TYPES),
}
def search(self, query: str, *, limit: int = 20, topic_slug: str | None = None) -> dict[str, object]:

View File

@ -198,7 +198,7 @@ def build_parser() -> argparse.ArgumentParser:
"--source",
choices=["crossref", "openalex"],
default="crossref",
help="External source used for graph expansion",
help="Graph expansion source",
)
expand_parser.add_argument(
"--relation",
@ -221,7 +221,7 @@ def build_parser() -> argparse.ArgumentParser:
"--source",
choices=["crossref", "openalex"],
default="openalex",
help="External source used for topic expansion",
help="Topic graph expansion source",
)
expand_topic_parser.add_argument(
"--relation",

View File

@ -107,6 +107,22 @@ def test_literature_explorer_api_search_and_show_entry():
store.close()
def test_literature_explorer_api_capabilities_distinguish_metadata_and_expansion_sources():
store = BibliographyStore()
try:
api = LiteratureExplorerApi(store)
payload = api.capabilities()
assert payload["metadata_sources"] == ["crossref", "datacite", "openalex", "pubmed"]
assert payload["topic_seed_sources"] == ["crossref", "datacite", "openalex", "pubmed"]
assert payload["graph_expansion_sources"] == ["crossref", "openalex"]
assert payload["topic_expansion_sources"] == ["crossref", "openalex"]
assert payload["graph_relation_types"] == ["cites", "cited_by", "both"]
finally:
store.close()
def test_literature_explorer_api_bootstrap_returns_topic_payload():
store = BibliographyStore()
try: