cc-transcript 3.0.1__tar.gz → 3.1.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.
Files changed (56) hide show
  1. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/PKG-INFO +1 -1
  2. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/cli.py +37 -14
  3. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/pyproject.toml +1 -1
  4. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/Cargo.lock +0 -0
  5. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/Cargo.toml +0 -0
  6. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/LICENSE +0 -0
  7. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/README.md +0 -0
  8. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/__init__.py +0 -0
  9. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/__main__.py +0 -0
  10. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/_parser_rs.pyi +0 -0
  11. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/activity.py +0 -0
  12. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/backend.py +0 -0
  13. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/builders.py +0 -0
  14. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/context.py +0 -0
  15. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/corrections.py +0 -0
  16. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/decisions.py +0 -0
  17. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/discovery.py +0 -0
  18. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/disktruth.py +0 -0
  19. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/evidence.py +0 -0
  20. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/filterspec.py +0 -0
  21. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/ids.py +0 -0
  22. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/judge/__init__.py +0 -0
  23. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/judge/llm.py +0 -0
  24. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/judge/verdicts.py +0 -0
  25. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/messages.py +0 -0
  26. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/mining/__init__.py +0 -0
  27. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/mining/candidates.py +0 -0
  28. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/mining/confidence.py +0 -0
  29. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/mining/filterspec.py +0 -0
  30. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/mining/formats.py +0 -0
  31. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/mining/signals.py +0 -0
  32. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/mining/sourcekind.py +0 -0
  33. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/mining/store.py +0 -0
  34. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/models.py +0 -0
  35. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/parser.py +0 -0
  36. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/py.typed +0 -0
  37. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/query.py +0 -0
  38. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/render.py +0 -0
  39. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/rust.py +0 -0
  40. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/sentiment/__init__.py +0 -0
  41. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/sentiment/buckets.py +0 -0
  42. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/sentiment/engine.py +0 -0
  43. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/sentiment/lexicon.py +0 -0
  44. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/sentiment/scorespec.py +0 -0
  45. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/store.py +0 -0
  46. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/cc_transcript/tools.py +0 -0
  47. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/rust/Cargo.toml +0 -0
  48. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/rust/data/afinn-en-165.tsv +0 -0
  49. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/rust/data/domain_overrides.tsv +0 -0
  50. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/rust/src/event.rs +0 -0
  51. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/rust/src/filter.rs +0 -0
  52. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/rust/src/lexicon.rs +0 -0
  53. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/rust/src/lib.rs +0 -0
  54. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/rust/src/model.rs +0 -0
  55. {cc_transcript-3.0.1 → cc_transcript-3.1.0}/rust/src/score.rs +0 -0
  56. {cc_transcript-3.0.1 → cc_transcript-3.1.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.0.1
3
+ Version: 3.1.0
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: Environment :: Console
6
6
  Classifier: Intended Audience :: Developers
@@ -9,7 +9,7 @@ from datetime import datetime
9
9
  from functools import partial, reduce
10
10
  from itertools import chain, islice
11
11
  from pathlib import Path
12
- from typing import TYPE_CHECKING, get_args
12
+ from typing import TYPE_CHECKING, NamedTuple, get_args
13
13
 
14
14
  import anyio
15
15
  import click
@@ -44,7 +44,7 @@ from cc_transcript.render import (
44
44
  tool_names,
45
45
  transcript_header,
46
46
  )
47
- from cc_transcript.tools import file_path_of, parse_tool_call
47
+ from cc_transcript.tools import file_path_of, parse_tool_call, tool_name_matches
48
48
 
49
49
  if TYPE_CHECKING:
50
50
  from collections.abc import Iterable, Mapping, Sequence
@@ -128,13 +128,26 @@ def project_matches(path: Path, root: Path, project: str | None) -> bool:
128
128
  return project is None or any(project in part for part in path.relative_to(root).parts[:-1])
129
129
 
130
130
 
131
+ class Targets(NamedTuple):
132
+ paths: list[tuple[Path, float]]
133
+ total: int
134
+
135
+
131
136
  def resolve_targets(
132
137
  paths: Sequence[Path], *, root: Path, project: str | None, contains: str | None, limit: int | None
133
- ) -> list[tuple[Path, float]]:
138
+ ) -> Targets:
134
139
  if paths:
135
- return [(path, path.stat().st_mtime) for path in paths]
140
+ return Targets([(path, path.stat().st_mtime) for path in paths], len(paths))
136
141
  matched = discover(root, project=project, contains=contains)
137
- return matched if limit is None else matched[:limit]
142
+ return Targets(matched if limit is None else matched[:limit], len(matched))
143
+
144
+
145
+ def scope_note(targets: Targets) -> str:
146
+ return (
147
+ f"searched {len(targets.paths)} of {targets.total} transcripts — use --all"
148
+ if len(targets.paths) < targets.total
149
+ else ""
150
+ )
138
151
 
139
152
 
140
153
  def filter_rows(rows: list[Row], *, kinds: frozenset[str], spec: FilterSpec | None) -> list[Row]:
@@ -178,9 +191,14 @@ def slice_rows(
178
191
  def uses_tool(event: TranscriptEvent, tool: str, names: Mapping[ToolUseId, str]) -> bool:
179
192
  match event:
180
193
  case AssistantEvent(blocks=blocks):
181
- return any(isinstance(block, ToolUseBlock) and block.name == tool for block in blocks)
194
+ return any(isinstance(block, ToolUseBlock) and tool_name_matches(block.name, tool) for block in blocks)
182
195
  case UserEvent(blocks=blocks):
183
- return any(isinstance(block, ToolResultBlock) and names.get(block.tool_use_id) == tool for block in blocks)
196
+ return any(
197
+ isinstance(block, ToolResultBlock)
198
+ and (name := names.get(block.tool_use_id)) is not None
199
+ and tool_name_matches(name, tool)
200
+ for block in blocks
201
+ )
184
202
  case _:
185
203
  return False
186
204
 
@@ -364,7 +382,7 @@ def grep(
364
382
  out: list[str | bytes] = []
365
383
  files_matched = matched = 0
366
384
  budget = max_matches
367
- for parsed in parse_transcripts(targets):
385
+ for parsed in parse_transcripts(targets.paths):
368
386
  if budget == 0:
369
387
  break
370
388
  names = tool_names(parsed.events)
@@ -406,7 +424,7 @@ def grep(
406
424
  for i in range(lo, hi)
407
425
  )
408
426
  if not as_json:
409
- out.append(f"{files_matched} files, {matched} matches")
427
+ out.append(f"{files_matched} files, {matched} matches" + (f" · {note}" if (note := scope_note(targets)) else ""))
410
428
  emit(out)
411
429
  if matched == 0:
412
430
  raise SystemExit(1)
@@ -429,21 +447,26 @@ def stats(
429
447
  ) -> None:
430
448
  """Summarize event, model, and tool statistics."""
431
449
  targets = resolve_targets(paths, root=root, project=project, contains=contains, limit=None if all_ else limit)
432
- transcripts = parse_transcripts(targets)
450
+ transcripts = parse_transcripts(targets.paths)
433
451
  if per_file and as_json:
434
452
  emit(
435
453
  orjson.dumps({"path": str(parsed.path)} | stats_dict(collect_stats([parsed]))) for parsed in transcripts
436
454
  )
437
455
  elif per_file:
438
456
  emit(
439
- block
440
- for parsed in transcripts
441
- for block in (transcript_header(parsed.path), render_stats(collect_stats([parsed])), "")
457
+ chain(
458
+ (
459
+ block
460
+ for parsed in transcripts
461
+ for block in (transcript_header(parsed.path), render_stats(collect_stats([parsed])), "")
462
+ ),
463
+ (note,) if (note := scope_note(targets)) else (),
464
+ )
442
465
  )
443
466
  elif as_json:
444
467
  emit((orjson.dumps(stats_dict(collect_stats(transcripts))),))
445
468
  else:
446
- emit((render_stats(collect_stats(transcripts)),))
469
+ emit((render_stats(collect_stats(transcripts)), *((note,) if (note := scope_note(targets)) else ())))
447
470
 
448
471
 
449
472
  @cli.command("slice")
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "cc-transcript"
3
- version = "3.0.1"
3
+ version = "3.1.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"
File without changes
File without changes
File without changes
File without changes