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.
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/PKG-INFO +1 -1
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/__init__.py +1 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/__init__.pyi +2 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/_native.pyi +56 -1
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/command.py +4 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/literals.py +7 -1
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/pyproject.toml +1 -1
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/target.rs +2 -2
- cc_transcript-14.6.0/rust/crates/core/src/codex/discovery.rs +192 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/codex/mod.rs +4 -0
- cc_transcript-14.6.0/rust/crates/core/src/codex/probe.rs +546 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/command.rs +772 -39
- cc_transcript-14.6.0/rust/crates/core/src/gateway.rs +207 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/lib.rs +1 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/literals/command.rs +5 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/context.rs +2 -2
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/python.rs +26 -16
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/render.rs +4 -4
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/command.rs +126 -2
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/mod.rs +1 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/Cargo.lock +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/Cargo.toml +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/LICENSE +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/README.md +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/activity.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/activity_probe.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/builders.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/context.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/corrections.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/cost.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/decisions.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/discovery.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/disktruth.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/evidence.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/extract/__init__.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/extract/correct.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/facts.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/filterspec.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/heartbeats.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/ids.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/judge/__init__.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/judge/llm.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/judge/similar.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/judge/verdicts.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/ledger.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/mining/__init__.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/mining/candidates.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/mining/confidence.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/mining/engine.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/mining/formats.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/mining/sampling.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/mining/signals.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/mining/sourcekind.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/mining/spec.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/mining/store.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/models.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/nlp.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/notifications.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/parser.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/py.typed +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/query.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/render.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/sentiment/__init__.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/sentiment/buckets.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/sentiment/data/afinn-en-165.tsv +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/sentiment/data/domain_overrides.tsv +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/sentiment/data/en-ewt.udpipe +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/sentiment/engine.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/sentiment/lexicon.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/sentiment/scorespec.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/synthetic.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/tools.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/cc_transcript/watch.py +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/Cargo.toml +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/commands/corrections.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/commands/digest.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/commands/facts.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/commands/grep.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/commands/list.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/commands/mod.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/commands/scratchpad.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/commands/show.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/commands/slice.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/commands/stats.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/commands/watch.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/lib.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/main.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/cli/src/output.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/Cargo.toml +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/benches/parse.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/benches/render.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/benches/toolcall.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/activity.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/actor.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/buckets.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/codex/lower.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/codex/parse.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/codex/protocol.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/codex/types.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/context.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/corrections.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/cost.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/discovery.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/facts.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/feedback.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/filter.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/ids.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/literals/corrections.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/literals/feedback.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/literals/mining.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/literals/mod.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/literals/protocol.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/notifications.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/parse.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/protocol.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/pystr.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/query.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/render.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/sqlite.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/toolcall.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/types.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/value.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/core/src/watch.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/Cargo.toml +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/build.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/data/command_prefix_pins.tsv +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/actor_bridge.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/bin/stub_gen.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/command.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/corrections.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/discovery.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/feedback.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/lexicon.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/lib.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/mining.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/nlp.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/score.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/sqlite.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/toolcall.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/attachment.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/blocks.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/convert.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/dunder.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/events.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/meta.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/print.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/store.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/system.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/toolcall.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/toolresult.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/views/transcript.rs +0 -0
- {cc_transcript-14.5.0 → cc_transcript-14.6.0}/rust/crates/py/src/watch.rs +0 -0
|
@@ -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.
|
|
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::
|
|
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 =
|
|
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,
|