Clarify available source types in explorer and CLI
This commit is contained in:
parent
663fb1973a
commit
b26f662af9
|
|
@ -297,7 +297,7 @@ Expand from one or more seed entries:
|
||||||
.venv/bin/python -m citegeist --db library.sqlite3 expand langton1989artificial1
|
.venv/bin/python -m citegeist --db library.sqlite3 expand langton1989artificial1
|
||||||
```
|
```
|
||||||
|
|
||||||
Choose the source:
|
Choose the graph expansion source:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
.venv/bin/python -m citegeist --db library.sqlite3 expand langton1989artificial1 --source openalex
|
.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"
|
.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
|
```bash
|
||||||
.venv/bin/python -m citegeist --db library.sqlite3 expand-topic artificial-life --source openalex --relation cited_by
|
.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:
|
Control seed and discovery limits:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,11 @@ The adapter exposes JSON-serializable methods suitable for a local web bridge:
|
||||||
- `verify_bibtex(bibtex_text, context="", limit=5)`
|
- `verify_bibtex(bibtex_text, context="", limit=5)`
|
||||||
- `graph(seed_keys, relation_types=None, depth=1, review_status=None, missing_only=False)`
|
- `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
|
## Browser Contract
|
||||||
|
|
||||||
A demo app can expose a browser object like:
|
A demo app can expose a browser object like:
|
||||||
|
|
|
||||||
|
|
@ -561,7 +561,7 @@
|
||||||
</label>
|
</label>
|
||||||
<div class="row-3">
|
<div class="row-3">
|
||||||
<label>
|
<label>
|
||||||
Source
|
Expansion Source
|
||||||
<select id="expand-source">
|
<select id="expand-source">
|
||||||
<option value="openalex">openalex</option>
|
<option value="openalex">openalex</option>
|
||||||
<option value="crossref">crossref</option>
|
<option value="crossref">crossref</option>
|
||||||
|
|
@ -611,6 +611,7 @@
|
||||||
<div id="expand-summary" class="summary-box">
|
<div id="expand-summary" class="summary-box">
|
||||||
<strong>Expansion Policy</strong>
|
<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>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>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
@ -827,6 +828,7 @@
|
||||||
expandPreviewButton: document.getElementById("expand-preview-button"),
|
expandPreviewButton: document.getElementById("expand-preview-button"),
|
||||||
expandCommitButton: document.getElementById("expand-commit-button"),
|
expandCommitButton: document.getElementById("expand-commit-button"),
|
||||||
expandSummary: document.getElementById("expand-summary"),
|
expandSummary: document.getElementById("expand-summary"),
|
||||||
|
expandSourceNote: document.getElementById("expand-source-note"),
|
||||||
searchQuery: document.getElementById("search-query"),
|
searchQuery: document.getElementById("search-query"),
|
||||||
searchTopic: document.getElementById("search-topic"),
|
searchTopic: document.getElementById("search-topic"),
|
||||||
searchButton: document.getElementById("search-button"),
|
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() {
|
async function connect() {
|
||||||
setBusy(els.connectButton, true);
|
setBusy(els.connectButton, true);
|
||||||
try {
|
try {
|
||||||
|
|
@ -1092,6 +1131,7 @@
|
||||||
const client = createLiteratureExplorerClient(bridge);
|
const client = createLiteratureExplorerClient(bridge);
|
||||||
const capabilities = await client.capabilities();
|
const capabilities = await client.capabilities();
|
||||||
state.client = client;
|
state.client = client;
|
||||||
|
applyCapabilities(capabilities);
|
||||||
setStatus(`Connected to ${state.bridgeUrl}`, "ok");
|
setStatus(`Connected to ${state.bridgeUrl}`, "ok");
|
||||||
setLastOp("connect");
|
setLastOp("connect");
|
||||||
logActivity("capabilities", capabilities);
|
logActivity("capabilities", capabilities);
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,10 @@ from .extract import extract_references
|
||||||
from .storage import BibliographyStore
|
from .storage import BibliographyStore
|
||||||
from .verify import BibliographyVerifier
|
from .verify import BibliographyVerifier
|
||||||
|
|
||||||
|
METADATA_SOURCES = ["crossref", "datacite", "openalex", "pubmed"]
|
||||||
|
GRAPH_EXPANSION_SOURCES = ["crossref", "openalex"]
|
||||||
|
GRAPH_RELATION_TYPES = ["cites", "cited_by", "both"]
|
||||||
|
|
||||||
|
|
||||||
class LiteratureExplorerApi:
|
class LiteratureExplorerApi:
|
||||||
"""JSON-serializable adapter layer for browser or local UI bridges."""
|
"""JSON-serializable adapter layer for browser or local UI bridges."""
|
||||||
|
|
@ -41,6 +45,11 @@ class LiteratureExplorerApi:
|
||||||
"graph",
|
"graph",
|
||||||
],
|
],
|
||||||
"preview_operations": ["bootstrap", "expand_topic"],
|
"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]:
|
def search(self, query: str, *, limit: int = 20, topic_slug: str | None = None) -> dict[str, object]:
|
||||||
|
|
|
||||||
|
|
@ -198,7 +198,7 @@ def build_parser() -> argparse.ArgumentParser:
|
||||||
"--source",
|
"--source",
|
||||||
choices=["crossref", "openalex"],
|
choices=["crossref", "openalex"],
|
||||||
default="crossref",
|
default="crossref",
|
||||||
help="External source used for graph expansion",
|
help="Graph expansion source",
|
||||||
)
|
)
|
||||||
expand_parser.add_argument(
|
expand_parser.add_argument(
|
||||||
"--relation",
|
"--relation",
|
||||||
|
|
@ -221,7 +221,7 @@ def build_parser() -> argparse.ArgumentParser:
|
||||||
"--source",
|
"--source",
|
||||||
choices=["crossref", "openalex"],
|
choices=["crossref", "openalex"],
|
||||||
default="openalex",
|
default="openalex",
|
||||||
help="External source used for topic expansion",
|
help="Topic graph expansion source",
|
||||||
)
|
)
|
||||||
expand_topic_parser.add_argument(
|
expand_topic_parser.add_argument(
|
||||||
"--relation",
|
"--relation",
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,22 @@ def test_literature_explorer_api_search_and_show_entry():
|
||||||
store.close()
|
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():
|
def test_literature_explorer_api_bootstrap_returns_topic_payload():
|
||||||
store = BibliographyStore()
|
store = BibliographyStore()
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue