cc-transcript 6.0.0__tar.gz → 7.0.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.
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/PKG-INFO +2 -2
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/extract/correct.py +4 -3
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/judge/__init__.py +1 -1
- cc_transcript-7.0.0/cc_transcript/judge/llm.py +62 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/pyproject.toml +2 -2
- cc_transcript-6.0.0/cc_transcript/judge/llm.py +0 -99
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/Cargo.lock +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/Cargo.toml +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/LICENSE +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/README.md +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/__init__.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/__main__.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/_parser_rs.pyi +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/activity.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/backend.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/builders.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/cli.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/context.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/corrections.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/corrections_cli.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/cost.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/decisions.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/discovery.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/disktruth.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/evidence.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/extract/__init__.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/filterspec.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/ids.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/judge/verdicts.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/messages.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/mining/__init__.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/mining/candidates.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/mining/confidence.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/mining/engine.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/mining/filterspec.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/mining/formats.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/mining/signals.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/mining/sourcekind.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/mining/spec.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/mining/store.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/models.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/parser.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/py.typed +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/query.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/render.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/rust.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/sentiment/__init__.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/sentiment/buckets.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/sentiment/engine.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/sentiment/lexicon.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/sentiment/scorespec.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/store.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/cc_transcript/tools.py +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/rust/Cargo.toml +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/rust/data/afinn-en-165.tsv +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/rust/data/domain_overrides.tsv +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/rust/src/event.rs +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/rust/src/filter.rs +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/rust/src/lexicon.rs +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/rust/src/lib.rs +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/rust/src/mining.rs +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/rust/src/model.rs +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/rust/src/score.rs +0 -0
- {cc_transcript-6.0.0 → cc_transcript-7.0.0}/rust/src/value.rs +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cc-transcript
|
|
3
|
-
Version:
|
|
3
|
+
Version: 7.0.0
|
|
4
4
|
Classifier: Development Status :: 3 - Alpha
|
|
5
5
|
Classifier: Environment :: Console
|
|
6
6
|
Classifier: Intended Audience :: Developers
|
|
@@ -16,7 +16,7 @@ Requires-Dist: orjson>=3.10
|
|
|
16
16
|
Requires-Dist: pytest>=8.0 ; extra == 'dev'
|
|
17
17
|
Requires-Dist: ty>=0.0.44 ; extra == 'dev'
|
|
18
18
|
Requires-Dist: ruff>=0.8 ; extra == 'dev'
|
|
19
|
-
Requires-Dist: spawnllm>=0.
|
|
19
|
+
Requires-Dist: spawnllm>=0.5.0 ; extra == 'llm'
|
|
20
20
|
Requires-Dist: spacy>=3.8 ; extra == 'sentiment'
|
|
21
21
|
Requires-Dist: afinn>=0.1 ; extra == 'sentiment'
|
|
22
22
|
Provides-Extra: dev
|
|
@@ -25,7 +25,6 @@ import anyio.to_thread
|
|
|
25
25
|
from pydantic import BaseModel
|
|
26
26
|
|
|
27
27
|
from cc_transcript.evidence import GitFix, harvest_pairs, lower_pair
|
|
28
|
-
from cc_transcript.judge.llm import run_structured_on
|
|
29
28
|
from cc_transcript.render import Budget, hunk_lines
|
|
30
29
|
|
|
31
30
|
if TYPE_CHECKING:
|
|
@@ -138,10 +137,12 @@ def usable_backend() -> LlmBackend | None:
|
|
|
138
137
|
async def choose_pair(
|
|
139
138
|
pairs: Sequence[CandidatePair], *, feedback: str, anchor_turn: int, tier: TModel, backend: LlmBackend | None
|
|
140
139
|
) -> CandidatePair | None:
|
|
140
|
+
from spawnllm import extract
|
|
141
|
+
|
|
141
142
|
if backend is None:
|
|
142
143
|
return max(pairs, key=lambda pair: pair.overlap)
|
|
143
|
-
pick = await
|
|
144
|
-
|
|
144
|
+
pick = await extract(
|
|
145
|
+
build_pick_prompt(feedback, pairs, anchor_turn=anchor_turn), CorrectionPick, backend=backend, model=tier
|
|
145
146
|
)
|
|
146
147
|
return pairs[pick.candidate - 1] if pick.candidate is not None and 1 <= pick.candidate <= len(pairs) else None
|
|
147
148
|
|
|
@@ -12,7 +12,7 @@ prompts, the verdict model, and any SQL views over the verdict table.
|
|
|
12
12
|
|
|
13
13
|
from __future__ import annotations
|
|
14
14
|
|
|
15
|
-
from cc_transcript.judge.llm import
|
|
15
|
+
from cc_transcript.judge.llm import default_backend, resolved_model, structured_judge
|
|
16
16
|
from cc_transcript.judge.verdicts import (
|
|
17
17
|
AuditEstimate,
|
|
18
18
|
AuditSample,
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""Headless structured completions via spawnllm's first ready CLI backend.
|
|
2
|
+
|
|
3
|
+
The structured call comes from the shared ``spawnllm`` library;
|
|
4
|
+
:func:`spawnllm.extract` resolves a backend, runs the spawn, and validates the
|
|
5
|
+
response into the model. The backend is whichever of spawnllm's CLIs is
|
|
6
|
+
installed and authenticated (:func:`spawnllm.select_backend`), using the
|
|
7
|
+
caller's existing CLI auth — no API key, no pinned provider. ``spawnllm`` and
|
|
8
|
+
``pydantic`` load lazily inside each function, so importing the judge package
|
|
9
|
+
needs no extra installed.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from functools import cache
|
|
15
|
+
from typing import TYPE_CHECKING
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from collections.abc import Awaitable, Callable
|
|
19
|
+
|
|
20
|
+
from pydantic import BaseModel
|
|
21
|
+
from spawnllm import LlmBackend, TModel
|
|
22
|
+
|
|
23
|
+
LLM_TIMEOUT = 180
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@cache
|
|
27
|
+
def default_backend() -> LlmBackend:
|
|
28
|
+
"""The first installed, authenticated spawnllm backend, cached per process.
|
|
29
|
+
|
|
30
|
+
Raises:
|
|
31
|
+
spawnllm.BackendUnavailable: When no backend is installed and authenticated.
|
|
32
|
+
"""
|
|
33
|
+
from spawnllm import select_backend
|
|
34
|
+
|
|
35
|
+
return select_backend()
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def resolved_model(tier: TModel) -> str:
|
|
39
|
+
"""The concrete model name the active backend runs for an abstract tier.
|
|
40
|
+
|
|
41
|
+
The verdict store keys on this string; it reflects whichever backend
|
|
42
|
+
:func:`spawnllm.select_backend` resolves, so a judged corpus stays coherent
|
|
43
|
+
within one backend environment.
|
|
44
|
+
"""
|
|
45
|
+
return default_backend().models[tier]
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def structured_judge[M: BaseModel](
|
|
49
|
+
response_model: type[M], *, tier: TModel, timeout: int = LLM_TIMEOUT
|
|
50
|
+
) -> Callable[[str], Awaitable[M]]:
|
|
51
|
+
"""Returns a prompt-to-verdict callable that plugs into :func:`run_verdicts`.
|
|
52
|
+
|
|
53
|
+
Each call runs one structured completion on the cached default backend via
|
|
54
|
+
:func:`spawnllm.extract`, which validates the response into ``response_model``.
|
|
55
|
+
|
|
56
|
+
Example:
|
|
57
|
+
>>> judge = structured_judge(Verdict, tier="medium")
|
|
58
|
+
>>> await run_verdicts(rows, prompt_for, judge, persist, concurrency=8)
|
|
59
|
+
"""
|
|
60
|
+
from spawnllm import extract
|
|
61
|
+
|
|
62
|
+
return lambda prompt: extract(prompt, response_model, backend=default_backend(), model=tier, timeout=timeout)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "cc-transcript"
|
|
3
|
-
version = "
|
|
3
|
+
version = "7.0.0"
|
|
4
4
|
description = "The Claude Code session-activity platform: a superset JSONL parser (Rust fast path, Python reference), typed tool calls with a cross-language content digest, turns/edits/evidence over one spine, context windows with labeled fidelity, unified decision and correction ledgers, LLM judging, and a transcript-investigation CLI."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "PolyForm-Noncommercial-1.0.0"
|
|
@@ -46,7 +46,7 @@ sentiment = [
|
|
|
46
46
|
"spacy>=3.8",
|
|
47
47
|
"afinn>=0.1",
|
|
48
48
|
]
|
|
49
|
-
llm = ["spawnllm>=0.
|
|
49
|
+
llm = ["spawnllm>=0.5.0"]
|
|
50
50
|
|
|
51
51
|
[project.scripts]
|
|
52
52
|
cc-transcript = "cc_transcript.cli:cli"
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
"""Headless structured completions via spawnllm's first ready CLI backend.
|
|
2
|
-
|
|
3
|
-
Run dispatch and envelope parsing come from the shared ``spawnllm`` library;
|
|
4
|
-
:func:`spawnllm.run` drives the spawn and built-in transient retry. The backend
|
|
5
|
-
is whichever of spawnllm's CLIs is installed and authenticated
|
|
6
|
-
(:func:`spawnllm.select_backend`), using the caller's existing CLI auth — no API
|
|
7
|
-
key, no pinned provider. ``spawnllm`` and ``pydantic`` load lazily inside each
|
|
8
|
-
function, so importing the judge package needs no extra installed.
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
from __future__ import annotations
|
|
12
|
-
|
|
13
|
-
from functools import cache
|
|
14
|
-
from typing import TYPE_CHECKING, cast
|
|
15
|
-
|
|
16
|
-
if TYPE_CHECKING:
|
|
17
|
-
from collections.abc import Awaitable, Callable
|
|
18
|
-
|
|
19
|
-
from pydantic import BaseModel
|
|
20
|
-
from spawnllm import LlmBackend, TModel
|
|
21
|
-
|
|
22
|
-
LLM_TIMEOUT = 180
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
@cache
|
|
26
|
-
def default_backend() -> LlmBackend:
|
|
27
|
-
"""The first installed, authenticated spawnllm backend, cached per process.
|
|
28
|
-
|
|
29
|
-
Raises:
|
|
30
|
-
spawnllm.BackendUnavailable: When no backend is installed and authenticated.
|
|
31
|
-
"""
|
|
32
|
-
from spawnllm import select_backend
|
|
33
|
-
|
|
34
|
-
return select_backend()
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def resolved_model(tier: TModel) -> str:
|
|
38
|
-
"""The concrete model name the active backend runs for an abstract tier.
|
|
39
|
-
|
|
40
|
-
The verdict store keys on this string; it reflects whichever backend
|
|
41
|
-
:func:`spawnllm.select_backend` resolves, so a judged corpus stays coherent
|
|
42
|
-
within one backend environment.
|
|
43
|
-
"""
|
|
44
|
-
return default_backend().models[tier]
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
async def run_structured_on[M: BaseModel](
|
|
48
|
-
backend: LlmBackend, prompt: str, *, response_model: type[M], tier: TModel, timeout: int = LLM_TIMEOUT
|
|
49
|
-
) -> M:
|
|
50
|
-
"""Runs one structured completion on an explicit ``backend``.
|
|
51
|
-
|
|
52
|
-
A caller that resolves a backend once per pass passes it here, so a large pass
|
|
53
|
-
probes auth once; :func:`run_structured` is the select-and-run convenience.
|
|
54
|
-
:func:`spawnllm.run` retries transient failures with backoff before returning.
|
|
55
|
-
|
|
56
|
-
Raises:
|
|
57
|
-
subprocess.TimeoutExpired: If the backend CLI outlives ``timeout``.
|
|
58
|
-
pydantic.ValidationError: If the response does not match the schema.
|
|
59
|
-
"""
|
|
60
|
-
from spawnllm import RunSpec, run
|
|
61
|
-
|
|
62
|
-
rr = await run(
|
|
63
|
-
RunSpec(
|
|
64
|
-
prompt=prompt,
|
|
65
|
-
model=backend.models[tier],
|
|
66
|
-
schema=backend.schema_for(response_model),
|
|
67
|
-
timeout=timeout,
|
|
68
|
-
),
|
|
69
|
-
backend=backend,
|
|
70
|
-
)
|
|
71
|
-
return cast(M, backend.parse_response(rr.stdout, response_model))
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
async def run_structured[M: BaseModel](
|
|
75
|
-
prompt: str, *, response_model: type[M], tier: TModel, timeout: int = LLM_TIMEOUT
|
|
76
|
-
) -> M:
|
|
77
|
-
"""Runs one structured completion on the first ready backend.
|
|
78
|
-
|
|
79
|
-
The prompt is delivered to the CLI and the response forced into
|
|
80
|
-
``response_model``'s JSON schema. Backend selection is cached per process.
|
|
81
|
-
|
|
82
|
-
Raises:
|
|
83
|
-
spawnllm.BackendUnavailable: If no backend is installed and authenticated.
|
|
84
|
-
subprocess.TimeoutExpired: If the backend CLI outlives ``timeout``.
|
|
85
|
-
pydantic.ValidationError: If the response does not match the schema.
|
|
86
|
-
"""
|
|
87
|
-
return await run_structured_on(default_backend(), prompt, response_model=response_model, tier=tier, timeout=timeout)
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
def structured_judge[M: BaseModel](
|
|
91
|
-
response_model: type[M], *, tier: TModel, timeout: int = LLM_TIMEOUT
|
|
92
|
-
) -> Callable[[str], Awaitable[M]]:
|
|
93
|
-
"""Returns a prompt-to-verdict callable that plugs into :func:`run_verdicts`.
|
|
94
|
-
|
|
95
|
-
Example:
|
|
96
|
-
>>> judge = structured_judge(Verdict, tier="medium")
|
|
97
|
-
>>> await run_verdicts(rows, prompt_for, judge, persist, concurrency=8)
|
|
98
|
-
"""
|
|
99
|
-
return lambda prompt: run_structured(prompt, response_model=response_model, tier=tier, timeout=timeout)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|