cc-transcript 14.5.0__tar.gz → 14.6.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 (152) hide show
  1. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/PKG-INFO +1 -1
  2. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/__init__.py +1 -0
  3. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/__init__.pyi +2 -0
  4. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/_native.pyi +56 -1
  5. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/command.py +4 -0
  6. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/literals.py +7 -1
  7. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/pyproject.toml +1 -1
  8. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/target.rs +2 -2
  9. cc_transcript-14.6.0/rust/crates/core/src/codex/discovery.rs +192 -0
  10. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/codex/mod.rs +4 -0
  11. cc_transcript-14.6.0/rust/crates/core/src/codex/probe.rs +546 -0
  12. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/command.rs +772 -39
  13. cc_transcript-14.6.0/rust/crates/core/src/gateway.rs +207 -0
  14. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/lib.rs +1 -0
  15. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/literals/command.rs +5 -0
  16. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/context.rs +2 -2
  17. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/python.rs +26 -16
  18. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/render.rs +4 -4
  19. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/command.rs +126 -2
  20. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/mod.rs +1 -0
  21. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/Cargo.lock +0 -0
  22. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/Cargo.toml +0 -0
  23. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/LICENSE +0 -0
  24. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/README.md +0 -0
  25. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/activity.py +0 -0
  26. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/activity_probe.py +0 -0
  27. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/builders.py +0 -0
  28. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/context.py +0 -0
  29. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/corrections.py +0 -0
  30. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/cost.py +0 -0
  31. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/decisions.py +0 -0
  32. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/discovery.py +0 -0
  33. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/disktruth.py +0 -0
  34. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/evidence.py +0 -0
  35. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/extract/__init__.py +0 -0
  36. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/extract/correct.py +0 -0
  37. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/facts.py +0 -0
  38. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/filterspec.py +0 -0
  39. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/heartbeats.py +0 -0
  40. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/ids.py +0 -0
  41. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/judge/__init__.py +0 -0
  42. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/judge/llm.py +0 -0
  43. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/judge/similar.py +0 -0
  44. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/judge/verdicts.py +0 -0
  45. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/ledger.py +0 -0
  46. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/mining/__init__.py +0 -0
  47. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/mining/candidates.py +0 -0
  48. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/mining/confidence.py +0 -0
  49. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/mining/engine.py +0 -0
  50. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/mining/formats.py +0 -0
  51. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/mining/sampling.py +0 -0
  52. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/mining/signals.py +0 -0
  53. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/mining/sourcekind.py +0 -0
  54. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/mining/spec.py +0 -0
  55. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/mining/store.py +0 -0
  56. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/models.py +0 -0
  57. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/nlp.py +0 -0
  58. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/notifications.py +0 -0
  59. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/parser.py +0 -0
  60. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/py.typed +0 -0
  61. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/query.py +0 -0
  62. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/render.py +0 -0
  63. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/sentiment/__init__.py +0 -0
  64. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/sentiment/buckets.py +0 -0
  65. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/sentiment/data/afinn-en-165.tsv +0 -0
  66. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/sentiment/data/domain_overrides.tsv +0 -0
  67. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/sentiment/data/en-ewt.udpipe +0 -0
  68. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/sentiment/engine.py +0 -0
  69. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/sentiment/lexicon.py +0 -0
  70. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/sentiment/scorespec.py +0 -0
  71. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/synthetic.py +0 -0
  72. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/tools.py +0 -0
  73. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/watch.py +0 -0
  74. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/Cargo.toml +0 -0
  75. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/commands/corrections.rs +0 -0
  76. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/commands/digest.rs +0 -0
  77. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/commands/facts.rs +0 -0
  78. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/commands/grep.rs +0 -0
  79. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/commands/list.rs +0 -0
  80. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/commands/mod.rs +0 -0
  81. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/commands/scratchpad.rs +0 -0
  82. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/commands/show.rs +0 -0
  83. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/commands/slice.rs +0 -0
  84. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/commands/stats.rs +0 -0
  85. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/commands/watch.rs +0 -0
  86. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/lib.rs +0 -0
  87. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/main.rs +0 -0
  88. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/output.rs +0 -0
  89. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/Cargo.toml +0 -0
  90. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/benches/parse.rs +0 -0
  91. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/benches/render.rs +0 -0
  92. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/benches/toolcall.rs +0 -0
  93. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/activity.rs +0 -0
  94. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/actor.rs +0 -0
  95. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/buckets.rs +0 -0
  96. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/codex/lower.rs +0 -0
  97. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/codex/parse.rs +0 -0
  98. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/codex/protocol.rs +0 -0
  99. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/codex/types.rs +0 -0
  100. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/context.rs +0 -0
  101. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/corrections.rs +0 -0
  102. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/cost.rs +0 -0
  103. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/discovery.rs +0 -0
  104. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/facts.rs +0 -0
  105. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/feedback.rs +0 -0
  106. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/filter.rs +0 -0
  107. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/ids.rs +0 -0
  108. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/literals/corrections.rs +0 -0
  109. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/literals/feedback.rs +0 -0
  110. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/literals/mining.rs +0 -0
  111. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/literals/mod.rs +0 -0
  112. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/literals/protocol.rs +0 -0
  113. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/notifications.rs +0 -0
  114. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/parse.rs +0 -0
  115. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/protocol.rs +0 -0
  116. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/pystr.rs +0 -0
  117. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/query.rs +0 -0
  118. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/render.rs +0 -0
  119. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/sqlite.rs +0 -0
  120. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/toolcall.rs +0 -0
  121. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/types.rs +0 -0
  122. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/value.rs +0 -0
  123. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/watch.rs +0 -0
  124. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/Cargo.toml +0 -0
  125. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/build.rs +0 -0
  126. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/data/command_prefix_pins.tsv +0 -0
  127. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/actor_bridge.rs +0 -0
  128. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/bin/stub_gen.rs +0 -0
  129. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/command.rs +0 -0
  130. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/corrections.rs +0 -0
  131. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/discovery.rs +0 -0
  132. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/feedback.rs +0 -0
  133. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/lexicon.rs +0 -0
  134. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/lib.rs +0 -0
  135. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/mining.rs +0 -0
  136. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/nlp.rs +0 -0
  137. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/score.rs +0 -0
  138. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/sqlite.rs +0 -0
  139. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/toolcall.rs +0 -0
  140. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/attachment.rs +0 -0
  141. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/blocks.rs +0 -0
  142. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/convert.rs +0 -0
  143. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/dunder.rs +0 -0
  144. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/events.rs +0 -0
  145. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/meta.rs +0 -0
  146. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/print.rs +0 -0
  147. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/store.rs +0 -0
  148. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/system.rs +0 -0
  149. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/toolcall.rs +0 -0
  150. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/toolresult.rs +0 -0
  151. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/transcript.rs +0 -0
  152. {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/watch.rs +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cc-transcript
3
- Version: 14.5.0
3
+ Version: 14.6.0
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: Environment :: Console
6
6
  Classifier: Intended Audience :: Developers
@@ -87,6 +87,7 @@ EXPORTS: dict[str, str] = {
87
87
  "CommandLineQuery",
88
88
  "Occurrence",
89
89
  "Redirect",
90
+ "Word",
90
91
  "command_prefixes",
91
92
  "parse_command_line",
92
93
  ),
@@ -33,6 +33,7 @@ from cc_transcript.command import (
33
33
  CommandLineQuery as CommandLineQuery,
34
34
  Occurrence as Occurrence,
35
35
  Redirect as Redirect,
36
+ Word as Word,
36
37
  command_prefixes as command_prefixes,
37
38
  parse_command_line as parse_command_line,
38
39
  )
@@ -421,6 +422,7 @@ __all__ = [
421
422
  "UserEvent",
422
423
  "WatchEvent",
423
424
  "Watcher",
425
+ "Word",
424
426
  "WorkflowCall",
425
427
  "WriteCall",
426
428
  "WriteResult",
@@ -95,6 +95,7 @@ __all__ = [
95
95
  "Usage",
96
96
  "UserEvent",
97
97
  "WatchTailer",
98
+ "Word",
98
99
  "WorkflowCall",
99
100
  "WriteCall",
100
101
  "WriteResult",
@@ -411,6 +412,11 @@ class Command:
411
412
  @property
412
413
  def span(self) -> typing.Optional[tuple[builtins.int, builtins.int]]: ...
413
414
  @property
415
+ def words(self) -> tuple[Word, ...]:
416
+ r"""
417
+ The structural words: ``words[0]`` is the executable, ``words[1:]`` parallel ``args``.
418
+ """
419
+ @property
414
420
  def argv(self) -> tuple[str, ...]: ...
415
421
  @property
416
422
  def program(self) -> builtins.str: ...
@@ -470,6 +476,11 @@ class CommandLine:
470
476
  def parse(cls, raw: builtins.str) -> CommandLine: ...
471
477
  @staticmethod
472
478
  def dequote(text: builtins.str) -> builtins.str: ...
479
+ @staticmethod
480
+ def quote(text: builtins.str) -> builtins.str:
481
+ r"""
482
+ Quote ``text`` as one POSIX-sh word, with Python ``shlex.quote`` semantics.
483
+ """
473
484
  def splice(self, replacements: typing.Mapping[builtins.int, builtins.str]) -> builtins.str: ...
474
485
  def rewrite_occurrences(self, to: collections.abc.Callable[[Occurrence], str | None]) -> typing.Optional[builtins.str]: ...
475
486
  def __iter__(self) -> collections.abc.Iterator[Command]: ...
@@ -1087,7 +1098,30 @@ class Occurrence:
1087
1098
  def next_op(self) -> typing.Optional[builtins.str]: ...
1088
1099
  @property
1089
1100
  def piped(self) -> builtins.bool: ...
1101
+ @property
1102
+ def nesting(self) -> builtins.int:
1103
+ r"""
1104
+ Substitution/payload hops below top level; 0 for a top-level command.
1105
+ """
1106
+ @property
1107
+ def host(self) -> Occurrence | None:
1108
+ r"""
1109
+ The occurrence hosting this nested part, or None at top level.
1110
+ """
1111
+ @property
1112
+ def quote_contexts(self) -> tuple[str, ...]:
1113
+ r"""
1114
+ Enclosing payload quote layers outermost-first: ``"'"``, ``'"'``, or ``""`` (bare).
1115
+ """
1090
1116
  def __new__(cls, line: CommandLine, index: builtins.int) -> Occurrence: ...
1117
+ def embeddable(self, text: builtins.str) -> builtins.bool:
1118
+ r"""
1119
+ Whether splicing ``text`` at this occurrence survives every enclosing quote layer.
1120
+ """
1121
+ def quote_for(self, text: builtins.str) -> typing.Optional[builtins.str]:
1122
+ r"""
1123
+ One shell-word spelling of ``text`` that survives every enclosing layer, or None.
1124
+ """
1091
1125
 
1092
1126
  @typing.final
1093
1127
  class OtherAttachment:
@@ -2063,6 +2097,27 @@ class WatchTailer:
2063
2097
  size, mtime, session_id, seen}}}`, the Python `TailState` projection.
2064
2098
  """
2065
2099
 
2100
+ @typing.final
2101
+ class Word:
2102
+ r"""
2103
+ One structural word of a parsed command (``Command.words``).
2104
+ Attributes:
2105
+ raw: verbatim source text.
2106
+ value: literal with quotes/escapes removed; None when an expansion taints it.
2107
+ span: byte span in the owning ``CommandLine.raw``; None without verbatim source.
2108
+ expandable: bash would glob/brace/tilde-expand despite the literal value.
2109
+ """
2110
+ __match_args__: typing.ClassVar[tuple[str, ...]]
2111
+ @property
2112
+ def raw(self) -> builtins.str: ...
2113
+ @property
2114
+ def value(self) -> typing.Optional[builtins.str]: ...
2115
+ @property
2116
+ def span(self) -> typing.Optional[tuple[builtins.int, builtins.int]]: ...
2117
+ @property
2118
+ def expandable(self) -> builtins.bool: ...
2119
+ def __new__(cls, raw: builtins.str, value: typing.Optional[builtins.str] = None, span: typing.Optional[tuple[builtins.int, builtins.int]] = None, expandable: builtins.bool = False) -> Word: ...
2120
+
2066
2121
  @typing.final
2067
2122
  class WorkflowCall(ToolCallBase):
2068
2123
  r"""
@@ -2162,7 +2217,7 @@ def discovery_subagent_paths(path: builtins.str | os.PathLike | pathlib.Path) ->
2162
2217
 
2163
2218
  def discovery_subagent_transcripts(path: builtins.str | os.PathLike | pathlib.Path) -> dict[str, pathlib.Path]: ...
2164
2219
 
2165
- def embedded_literals() -> dict[str, str | float | list[str]]: ...
2220
+ def embedded_literals() -> dict[str, str | float | int | list[str]]: ...
2166
2221
 
2167
2222
  def expand_tool_names(spec: builtins.str) -> frozenset[str]:
2168
2223
  r"""
@@ -18,6 +18,10 @@ from cc_transcript._native import CommandLine as CommandLine
18
18
  from cc_transcript._native import CommandLineQuery as CommandLineQuery
19
19
  from cc_transcript._native import Occurrence as Occurrence
20
20
  from cc_transcript._native import Redirect as Redirect
21
+ from cc_transcript._native import Word as Word
22
+ from cc_transcript.literals import literal_int
23
+
24
+ PAYLOAD_DEPTH_LIMIT: int = literal_int("command.PAYLOAD_DEPTH_LIMIT")
21
25
 
22
26
  parse_command_line = lru_cache(maxsize=4096)(CommandLine.parse)
23
27
 
@@ -12,7 +12,7 @@ from __future__ import annotations
12
12
 
13
13
  from cc_transcript import _native
14
14
 
15
- LITERALS: dict[str, str | float | list[str]] = _native.embedded_literals()
15
+ LITERALS: dict[str, str | float | int | list[str]] = _native.embedded_literals()
16
16
 
17
17
 
18
18
  def literal_str(key: str) -> str:
@@ -25,3 +25,9 @@ def literal_float(key: str) -> float:
25
25
  value = LITERALS[key]
26
26
  assert isinstance(value, float), key
27
27
  return value
28
+
29
+
30
+ def literal_int(key: str) -> int:
31
+ value = LITERALS[key]
32
+ assert isinstance(value, int), key
33
+ return value
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "cc-transcript"
3
- version = "14.5.0" # informational — releases stamp the version from the git tag
3
+ version = "14.6.0" # informational — releases stamp the version from the git tag
4
4
  description = "Grep every Claude Code session you've ever run."
5
5
  readme = "README.md"
6
6
  license = "PolyForm-Noncommercial-1.0.0"
@@ -4,7 +4,7 @@
4
4
  use std::path::{Path, PathBuf};
5
5
 
6
6
  use cc_transcript_core::discovery::{find_in, mtime_secs};
7
- use cc_transcript_core::parse::parse_bytes;
7
+ use cc_transcript_core::gateway::parse_transcript_bytes;
8
8
  use cc_transcript_core::render::display_path;
9
9
  use cc_transcript_core::types::Entry;
10
10
  use rayon::prelude::*;
@@ -108,7 +108,7 @@ pub fn parse_transcripts(targets: &[(PathBuf, f64)]) -> Vec<Parsed> {
108
108
  .par_iter()
109
109
  .map(|(path, _)| {
110
110
  let bytes = std::fs::read(path).ok()?;
111
- let entries = parse_bytes(&bytes, |_| true).ok()?;
111
+ let entries = parse_transcript_bytes(&bytes).ok()?.entries;
112
112
  Some(Parsed {
113
113
  path: path.clone(),
114
114
  session_id: session_id_of(&entries),
@@ -0,0 +1,192 @@
1
+ use std::fs;
2
+ use std::path::{Path, PathBuf};
3
+
4
+ use chrono::NaiveDateTime;
5
+
6
+ #[derive(Debug, Clone, PartialEq, Eq)]
7
+ pub struct RolloutFile {
8
+ pub path: PathBuf,
9
+ pub session_id: String,
10
+ pub compressed: bool,
11
+ }
12
+
13
+ pub fn sessions_root(root: Option<&Path>) -> PathBuf {
14
+ root.map(Path::to_path_buf).unwrap_or_else(|| {
15
+ std::env::home_dir()
16
+ .expect("a home directory resolves via HOME or the pwd database")
17
+ .join(".codex")
18
+ .join("sessions")
19
+ })
20
+ }
21
+
22
+ pub fn discover(root: &Path) -> Vec<RolloutFile> {
23
+ if !root.exists() {
24
+ return Vec::new();
25
+ }
26
+ let mut found = Vec::new();
27
+ walk(root, &mut |path| {
28
+ let Some((stamp, session_id, compressed)) = parse_file_name(path) else {
29
+ return;
30
+ };
31
+ found.push((
32
+ stamp,
33
+ RolloutFile {
34
+ path: path.to_path_buf(),
35
+ session_id,
36
+ compressed,
37
+ },
38
+ ));
39
+ });
40
+ found.sort_by(|a, b| b.0.cmp(&a.0).then_with(|| a.1.path.cmp(&b.1.path)));
41
+ found.into_iter().map(|(_, rollout)| rollout).collect()
42
+ }
43
+
44
+ pub fn resolve(session_id: &str, root: &Path) -> Option<PathBuf> {
45
+ let found = discover(root);
46
+ found
47
+ .iter()
48
+ .find(|rollout| rollout.session_id == session_id && !rollout.compressed)
49
+ .or_else(|| {
50
+ found
51
+ .iter()
52
+ .find(|rollout| rollout.session_id == session_id)
53
+ })
54
+ .map(|rollout| rollout.path.clone())
55
+ }
56
+
57
+ fn walk(dir: &Path, visit: &mut impl FnMut(&Path)) {
58
+ let Ok(entries) = fs::read_dir(dir) else {
59
+ return;
60
+ };
61
+ for entry in entries.flatten() {
62
+ let Ok(file_type) = entry.file_type() else {
63
+ continue;
64
+ };
65
+ let path = entry.path();
66
+ if file_type.is_dir() {
67
+ walk(&path, visit);
68
+ } else {
69
+ visit(&path);
70
+ }
71
+ }
72
+ }
73
+
74
+ fn parse_file_name(path: &Path) -> Option<(String, String, bool)> {
75
+ let name = path.file_name()?.to_str()?;
76
+ let (stem, compressed) = match name.strip_suffix(".jsonl.zst") {
77
+ Some(stem) => (stem, true),
78
+ None => (name.strip_suffix(".jsonl")?, false),
79
+ };
80
+ let body = stem.strip_prefix("rollout-")?;
81
+ let split = body.len().checked_sub(37)?;
82
+ if body.as_bytes().get(split) != Some(&b'-') {
83
+ return None;
84
+ }
85
+ let stamp = body.get(..split)?;
86
+ let session_id = body.get(split + 1..)?;
87
+ NaiveDateTime::parse_from_str(stamp, "%Y-%m-%dT%H-%M-%S").ok()?;
88
+ if !is_uuid_v7(session_id) {
89
+ return None;
90
+ }
91
+ Some((stamp.to_string(), session_id.to_string(), compressed))
92
+ }
93
+
94
+ fn is_uuid_v7(value: &str) -> bool {
95
+ if value.len() != 36 {
96
+ return false;
97
+ }
98
+ value.bytes().enumerate().all(|(index, byte)| match index {
99
+ 8 | 13 | 18 | 23 => byte == b'-',
100
+ 14 => byte == b'7',
101
+ 19 => matches!(byte, b'8' | b'9' | b'a' | b'b' | b'A' | b'B'),
102
+ _ => byte.is_ascii_hexdigit(),
103
+ })
104
+ }
105
+
106
+ #[cfg(test)]
107
+ mod tests {
108
+ use super::*;
109
+ use std::fs::File;
110
+
111
+ fn touch(root: &Path, rel: &str) -> PathBuf {
112
+ let path = root.join(rel);
113
+ fs::create_dir_all(path.parent().unwrap()).unwrap();
114
+ File::create(&path).unwrap();
115
+ path
116
+ }
117
+
118
+ #[test]
119
+ fn discovers_and_resolves_rollouts() {
120
+ let root = std::env::temp_dir().join(format!(
121
+ "codex-discovery-{}-{:?}",
122
+ std::process::id(),
123
+ std::thread::current().id()
124
+ ));
125
+ fs::remove_dir_all(&root).ok();
126
+ let oldest = touch(
127
+ &root,
128
+ "2025/12/31/rollout-2025-12-31T23-59-59-019b7000-0000-7000-8000-000000000001.jsonl",
129
+ );
130
+ let twin = touch(
131
+ &root,
132
+ "2026/01/01/rollout-2026-01-01T00-00-01-019b7000-0000-7000-8000-000000000002.jsonl",
133
+ );
134
+ let twin_zst = touch(
135
+ &root,
136
+ "2026/01/03/rollout-2026-01-03T09-00-00-019b7000-0000-7000-8000-000000000002.jsonl.zst",
137
+ );
138
+ let newest = touch(
139
+ &root,
140
+ "2026/01/02/rollout-2026-01-02T03-04-05-019b7000-0000-7000-8000-000000000003.jsonl",
141
+ );
142
+ touch(&root, "2026/01/02/notes.jsonl");
143
+ touch(
144
+ &root,
145
+ "2026/01/02/rollout-2026-01-02T03-04-06-not-a-uuid.jsonl",
146
+ );
147
+
148
+ let found = discover(&sessions_root(Some(&root)));
149
+ assert_eq!(
150
+ found,
151
+ [
152
+ RolloutFile {
153
+ path: twin_zst.clone(),
154
+ session_id: "019b7000-0000-7000-8000-000000000002".into(),
155
+ compressed: true,
156
+ },
157
+ RolloutFile {
158
+ path: newest,
159
+ session_id: "019b7000-0000-7000-8000-000000000003".into(),
160
+ compressed: false,
161
+ },
162
+ RolloutFile {
163
+ path: twin.clone(),
164
+ session_id: "019b7000-0000-7000-8000-000000000002".into(),
165
+ compressed: false,
166
+ },
167
+ RolloutFile {
168
+ path: oldest.clone(),
169
+ session_id: "019b7000-0000-7000-8000-000000000001".into(),
170
+ compressed: false,
171
+ },
172
+ ]
173
+ );
174
+ assert_eq!(
175
+ resolve("019b7000-0000-7000-8000-000000000002", &root),
176
+ Some(twin.clone())
177
+ );
178
+ fs::remove_file(twin).unwrap();
179
+ assert_eq!(
180
+ resolve("019b7000-0000-7000-8000-000000000002", &root),
181
+ Some(twin_zst)
182
+ );
183
+ assert_eq!(
184
+ resolve("019b7000-0000-7000-8000-000000000001", &root),
185
+ Some(oldest)
186
+ );
187
+ assert_eq!(resolve("019b7000-0000-7000-8000-000000000099", &root), None);
188
+ assert_eq!(sessions_root(Some(&root)), root);
189
+ assert!(sessions_root(None).ends_with(".codex/sessions"));
190
+ fs::remove_dir_all(&root).ok();
191
+ }
192
+ }
@@ -1,10 +1,14 @@
1
+ pub mod discovery;
1
2
  pub mod lower;
2
3
  pub mod parse;
4
+ pub mod probe;
3
5
  pub mod protocol;
4
6
  pub mod types;
5
7
 
8
+ pub use discovery::{discover, resolve, sessions_root, RolloutFile};
6
9
  pub use lower::{lower, CodexLowering, CodexUsageAggregate};
7
10
  pub use parse::parse_codex_bytes;
11
+ pub use probe::{codex_session_activity, session_probe, CodexProbe, Lifecycle};
8
12
  pub use protocol::{injection_wrapper, mcp_tool_name, output_exit_code, INJECTION_WRAPPERS};
9
13
  pub use types::{
10
14
  CodexEntry, CodexItem, CodexOther, CodexSession, Compacted, EventMsg, ResponseItem,