citesight 0.12.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.
- citesight-0.12.0/.gitignore +56 -0
- citesight-0.12.0/PKG-INFO +47 -0
- citesight-0.12.0/README.md +36 -0
- citesight-0.12.0/cite_sight/__init__.py +153 -0
- citesight-0.12.0/pyproject.toml +20 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
node_modules/
|
|
3
|
+
npm-debug.log*
|
|
4
|
+
yarn-debug.log*
|
|
5
|
+
yarn-error.log*
|
|
6
|
+
|
|
7
|
+
# Production builds
|
|
8
|
+
dist/
|
|
9
|
+
build/
|
|
10
|
+
|
|
11
|
+
# Environment variables
|
|
12
|
+
.env
|
|
13
|
+
.env.local
|
|
14
|
+
.env.development.local
|
|
15
|
+
.env.test.local
|
|
16
|
+
.env.production.local
|
|
17
|
+
|
|
18
|
+
# IDE
|
|
19
|
+
.vscode/
|
|
20
|
+
.idea/
|
|
21
|
+
*.swp
|
|
22
|
+
*.swo
|
|
23
|
+
*~
|
|
24
|
+
|
|
25
|
+
# OS
|
|
26
|
+
.DS_Store
|
|
27
|
+
.DS_Store?
|
|
28
|
+
._*
|
|
29
|
+
.Spotlight-V100
|
|
30
|
+
.Trashes
|
|
31
|
+
ehthumbs.db
|
|
32
|
+
Thumbs.db
|
|
33
|
+
|
|
34
|
+
# Logs
|
|
35
|
+
logs/
|
|
36
|
+
*.log
|
|
37
|
+
|
|
38
|
+
# Coverage
|
|
39
|
+
coverage/
|
|
40
|
+
|
|
41
|
+
# ESLint
|
|
42
|
+
.eslintcache
|
|
43
|
+
|
|
44
|
+
# TypeScript
|
|
45
|
+
*.tsbuildinfo
|
|
46
|
+
|
|
47
|
+
# Temporary folders
|
|
48
|
+
tmp/
|
|
49
|
+
temp/
|
|
50
|
+
|
|
51
|
+
# Claude Code
|
|
52
|
+
.claude/
|
|
53
|
+
.superpowers/
|
|
54
|
+
packages/desktop/resources/runtime/
|
|
55
|
+
packages/desktop/resources/runtime-downloads/
|
|
56
|
+
packages/desktop/release/
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: citesight
|
|
3
|
+
Version: 0.12.0
|
|
4
|
+
Summary: Python wrapper for the CiteSight CLI (citation verification and local claim evidence review)
|
|
5
|
+
Project-URL: Homepage, https://github.com/michael-borck/cite-sight
|
|
6
|
+
Author: Michael Borck
|
|
7
|
+
License: MIT
|
|
8
|
+
Keywords: academic-integrity,citations,references
|
|
9
|
+
Requires-Python: >=3.9
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
# citesight
|
|
13
|
+
|
|
14
|
+
Python wrapper for the [CiteSight](https://github.com/michael-borck/cite-sight) CLI —
|
|
15
|
+
citation verification and (experimental) local claim-evidence review for student work.
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
1. Node.js 20+, then: `npm install -g cite-sight`
|
|
20
|
+
2. This package: `pip install citesight` (or from this folder: `pip install .`)
|
|
21
|
+
|
|
22
|
+
## Use
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
from cite_sight import check, library_plan, claim_overlap
|
|
26
|
+
|
|
27
|
+
result = check("essay.pdf", email="you@example.edu")
|
|
28
|
+
for v in result["references"]["verifications"]:
|
|
29
|
+
print(v["status"], "—", v["reference"]["title"])
|
|
30
|
+
|
|
31
|
+
# Coordinator pass: common vs unique sources across a cohort
|
|
32
|
+
plan = library_plan(["submissions/*.pdf"], output="unit-sources.json")
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Claim evidence review (experimental, local-only, requires
|
|
36
|
+
`cite-sight setup-claims runtime` + `model install`):
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
from cite_sight import claims
|
|
40
|
+
result = claims("essay.pdf", "sources.json", library="./unit-readings/")
|
|
41
|
+
for f in result["claims"]["findings"]:
|
|
42
|
+
print(f["status"], "—", f["claim"])
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
All functions shell out to the CLI and return parsed JSON — same verdicts as
|
|
46
|
+
the desktop app, no data leaves the machine beyond what the CLI itself sends
|
|
47
|
+
(reference metadata to open scholarly APIs; claim checking is fully offline).
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# citesight
|
|
2
|
+
|
|
3
|
+
Python wrapper for the [CiteSight](https://github.com/michael-borck/cite-sight) CLI —
|
|
4
|
+
citation verification and (experimental) local claim-evidence review for student work.
|
|
5
|
+
|
|
6
|
+
## Install
|
|
7
|
+
|
|
8
|
+
1. Node.js 20+, then: `npm install -g cite-sight`
|
|
9
|
+
2. This package: `pip install citesight` (or from this folder: `pip install .`)
|
|
10
|
+
|
|
11
|
+
## Use
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from cite_sight import check, library_plan, claim_overlap
|
|
15
|
+
|
|
16
|
+
result = check("essay.pdf", email="you@example.edu")
|
|
17
|
+
for v in result["references"]["verifications"]:
|
|
18
|
+
print(v["status"], "—", v["reference"]["title"])
|
|
19
|
+
|
|
20
|
+
# Coordinator pass: common vs unique sources across a cohort
|
|
21
|
+
plan = library_plan(["submissions/*.pdf"], output="unit-sources.json")
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Claim evidence review (experimental, local-only, requires
|
|
25
|
+
`cite-sight setup-claims runtime` + `model install`):
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from cite_sight import claims
|
|
29
|
+
result = claims("essay.pdf", "sources.json", library="./unit-readings/")
|
|
30
|
+
for f in result["claims"]["findings"]:
|
|
31
|
+
print(f["status"], "—", f["claim"])
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
All functions shell out to the CLI and return parsed JSON — same verdicts as
|
|
35
|
+
the desktop app, no data leaves the machine beyond what the CLI itself sends
|
|
36
|
+
(reference metadata to open scholarly APIs; claim checking is fully offline).
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"""Python wrapper for the CiteSight CLI.
|
|
2
|
+
|
|
3
|
+
Thin and honest: every function shells out to the `cite-sight` command
|
|
4
|
+
(Node.js, installed via `npm install -g cite-sight`) and returns the parsed
|
|
5
|
+
JSON. Requires Node.js 20+; nothing else. Set CITESIGHT_CLI to point at a
|
|
6
|
+
specific binary.
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
import os
|
|
12
|
+
import shutil
|
|
13
|
+
import subprocess
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Any, Iterable
|
|
16
|
+
|
|
17
|
+
__version__ = "0.12.0"
|
|
18
|
+
__all__ = ["CiteSightError", "is_cli_available", "check", "claims", "library_plan", "claim_overlap", "about"]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class CiteSightError(RuntimeError):
|
|
22
|
+
"""The cite-sight CLI is missing, or exited non-zero."""
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def is_cli_available() -> bool:
|
|
26
|
+
"""True when the cite-sight CLI can be found. Call this before showing
|
|
27
|
+
claim-checking UI in your own tool; all wrapper functions raise
|
|
28
|
+
CiteSightError with install instructions when it is missing."""
|
|
29
|
+
return bool(os.environ.get("CITESIGHT_CLI") or shutil.which("cite-sight"))
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _cli() -> str:
|
|
33
|
+
override = os.environ.get("CITESIGHT_CLI")
|
|
34
|
+
if override:
|
|
35
|
+
return override
|
|
36
|
+
found = shutil.which("cite-sight")
|
|
37
|
+
if not found:
|
|
38
|
+
raise CiteSightError(
|
|
39
|
+
"The 'cite-sight' CLI was not found on PATH. "
|
|
40
|
+
"Install Node.js 20+ and run: npm install -g cite-sight "
|
|
41
|
+
"(or set CITESIGHT_CLI to the binary path)."
|
|
42
|
+
)
|
|
43
|
+
return found
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _run(args: list[str], *, timeout: float | None) -> dict[str, Any]:
|
|
47
|
+
result = subprocess.run(
|
|
48
|
+
[_cli(), *args],
|
|
49
|
+
capture_output=True,
|
|
50
|
+
text=True,
|
|
51
|
+
timeout=timeout,
|
|
52
|
+
)
|
|
53
|
+
if result.returncode not in (0, 2): # 2 = findings met --fail-on, still valid JSON
|
|
54
|
+
raise CiteSightError(f"cite-sight exited {result.returncode}: {result.stderr.strip()[:2000]}")
|
|
55
|
+
try:
|
|
56
|
+
return json.loads(result.stdout)
|
|
57
|
+
except json.JSONDecodeError as exc:
|
|
58
|
+
raise CiteSightError(f"cite-sight returned non-JSON output: {exc}") from exc
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def check(
|
|
62
|
+
paths: Iterable[str | Path],
|
|
63
|
+
*,
|
|
64
|
+
style: str | None = None,
|
|
65
|
+
email: str | None = None,
|
|
66
|
+
offline: bool = False,
|
|
67
|
+
source_list: bool = False,
|
|
68
|
+
fail_on: str | None = None,
|
|
69
|
+
bibtex: str | None = None,
|
|
70
|
+
timeout: float | None = None,
|
|
71
|
+
) -> dict[str, Any]:
|
|
72
|
+
"""Verify references in one or more documents. Returns the analysis JSON.
|
|
73
|
+
|
|
74
|
+
The JSON shape matches the CLI: `references.verifications[]` with
|
|
75
|
+
`status`, `flags`, `matchedWork`, `publicationCheck`, plus
|
|
76
|
+
`crossReference` (orphan/near-match suggestions) and `detectedStyle`.
|
|
77
|
+
"""
|
|
78
|
+
args = ["check", *[str(p) for p in paths], "--json"]
|
|
79
|
+
if style:
|
|
80
|
+
args += ["--style", style]
|
|
81
|
+
if email:
|
|
82
|
+
args += ["--email", email]
|
|
83
|
+
if offline:
|
|
84
|
+
args.append("--offline")
|
|
85
|
+
if source_list:
|
|
86
|
+
args.append("--source-list")
|
|
87
|
+
if fail_on:
|
|
88
|
+
args += ["--fail-on", fail_on]
|
|
89
|
+
if bibtex:
|
|
90
|
+
args += ["--bibtex", bibtex]
|
|
91
|
+
return _run(args, timeout=timeout)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def claims(
|
|
95
|
+
document: str | Path,
|
|
96
|
+
sources_manifest: str | Path,
|
|
97
|
+
*,
|
|
98
|
+
model: str | None = None,
|
|
99
|
+
runner: str | None = None,
|
|
100
|
+
library: str | None = None,
|
|
101
|
+
max_claims: int = 50,
|
|
102
|
+
model_timeout: int = 180,
|
|
103
|
+
output: str | None = None,
|
|
104
|
+
timeout: float | None = None,
|
|
105
|
+
) -> dict[str, Any]:
|
|
106
|
+
"""Local claim-evidence review against mapped source files (experimental).
|
|
107
|
+
|
|
108
|
+
Uses the managed runtime/model installed via
|
|
109
|
+
`cite-sight setup-claims runtime` / `cite-sight setup-claims model <id>`
|
|
110
|
+
unless explicit `model`/`runner` paths are given. Findings are labelled
|
|
111
|
+
suggestions; quotations are verified against the source text.
|
|
112
|
+
"""
|
|
113
|
+
args = ["claims", str(document), "--sources", str(sources_manifest), "--max-claims", str(max_claims), "--model-timeout", str(model_timeout)]
|
|
114
|
+
if model:
|
|
115
|
+
args += ["--model", model]
|
|
116
|
+
if runner:
|
|
117
|
+
args += ["--runner", runner]
|
|
118
|
+
if library:
|
|
119
|
+
args += ["--library", str(library)]
|
|
120
|
+
if output:
|
|
121
|
+
args += ["--output", str(output)]
|
|
122
|
+
else:
|
|
123
|
+
args += ["--json"]
|
|
124
|
+
return _run(args, timeout=timeout)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def library_plan(
|
|
128
|
+
paths: Iterable[str | Path],
|
|
129
|
+
*,
|
|
130
|
+
output: str | None = None,
|
|
131
|
+
timeout: float | None = None,
|
|
132
|
+
) -> dict[str, Any]:
|
|
133
|
+
"""Common vs unique references across submissions — the coordinator's
|
|
134
|
+
shopping list of sources to collect once per unit."""
|
|
135
|
+
args = ["library", "plan", *[str(p) for p in paths]]
|
|
136
|
+
if output:
|
|
137
|
+
args += ["--output", str(output)]
|
|
138
|
+
return _run(args, timeout=timeout)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def claim_overlap(report: str | Path, *, threshold: float = 0.6) -> dict[str, Any]:
|
|
142
|
+
"""Similar claims on shared references across submissions (a signal, not proof)."""
|
|
143
|
+
result = subprocess.run(
|
|
144
|
+
[_cli(), "claim-overlap", str(report), "--threshold", str(threshold)],
|
|
145
|
+
capture_output=True, text=True,
|
|
146
|
+
)
|
|
147
|
+
return {"report": str(report), "output": result.stdout, "exit_code": result.returncode}
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def about(topic: str | None = None) -> str:
|
|
151
|
+
args = ["about"] + ([topic] if topic else [])
|
|
152
|
+
result = subprocess.run([_cli(), *args], capture_output=True, text=True)
|
|
153
|
+
return result.stdout
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "citesight"
|
|
7
|
+
version = "0.12.0"
|
|
8
|
+
description = "Python wrapper for the CiteSight CLI (citation verification and local claim evidence review)"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "Michael Borck" }]
|
|
13
|
+
keywords = ["citations", "academic-integrity", "references"]
|
|
14
|
+
dependencies = []
|
|
15
|
+
|
|
16
|
+
[project.urls]
|
|
17
|
+
Homepage = "https://github.com/michael-borck/cite-sight"
|
|
18
|
+
|
|
19
|
+
[tool.hatch.build.targets.wheel]
|
|
20
|
+
packages = ["cite_sight"]
|