cc-transcript 14.16.1__tar.gz → 14.22.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.
Potentially problematic release.
This version of cc-transcript might be problematic. Click here for more details.
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/PKG-INFO +1 -1
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/__init__.py +2 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/__init__.pyi +4 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/_native.pyi +9 -1
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/activity.py +176 -60
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/query.py +518 -78
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/render.py +25 -6
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/pyproject.toml +1 -1
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/benches/parse.rs +10 -1
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/activity.rs +90 -7
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/context.rs +14 -5
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/parse.rs +1 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/render.rs +135 -18
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/types.rs +1 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/python.rs +68 -22
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/render.rs +2 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/views/attachment.rs +9 -1
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/Cargo.lock +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/Cargo.toml +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/LICENSE +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/README.md +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/activity_probe.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/builders.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/codex.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/command.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/context.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/corrections.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/cost.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/decision_store.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/decisions.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/discovery.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/disktruth.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/evidence.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/extract/__init__.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/extract/correct.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/facts.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/filterspec.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/heartbeats.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/ids.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/judge/__init__.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/judge/llm.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/judge/similar.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/judge/verdicts.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/ledger.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/literals.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/mining/__init__.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/mining/candidates.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/mining/confidence.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/mining/engine.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/mining/formats.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/mining/sampling.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/mining/signals.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/mining/sourcekind.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/mining/spec.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/mining/store.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/models.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/nlp.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/notifications.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/parser.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/py.typed +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/sentiment/__init__.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/sentiment/buckets.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/sentiment/data/afinn-en-165.tsv +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/sentiment/data/domain_overrides.tsv +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/sentiment/data/en-ewt.udpipe +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/sentiment/engine.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/sentiment/lexicon.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/sentiment/scorespec.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/synthetic.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/tools.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/cc_transcript/watch.py +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/cli/Cargo.toml +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/cli/src/commands/blame.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/cli/src/commands/corrections.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/cli/src/commands/digest.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/cli/src/commands/facts.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/cli/src/commands/grep.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/cli/src/commands/list.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/cli/src/commands/mod.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/cli/src/commands/scratchpad.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/cli/src/commands/show.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/cli/src/commands/slice.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/cli/src/commands/stats.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/cli/src/commands/watch.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/cli/src/lib.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/cli/src/main.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/cli/src/output.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/cli/src/target.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/cli/src/timearg.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/Cargo.toml +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/benches/render.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/benches/toolcall.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/actor.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/blame.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/buckets.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/codex/discovery.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/codex/lower.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/codex/mod.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/codex/parse.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/codex/probe.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/codex/protocol.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/codex/types.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/command.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/corrections.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/cost.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/discovery.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/facts.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/feedback.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/filter.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/gateway.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/ids.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/judge.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/lib.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/literals/command.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/literals/corrections.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/literals/feedback.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/literals/mining.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/literals/mod.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/literals/protocol.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/notifications.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/protocol.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/pystr.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/query.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/rng.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/schema.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/sqlite.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/toolcall.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/value.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/core/src/watch.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/Cargo.toml +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/build.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/data/command_prefix_pins.tsv +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/actor_bridge.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/bin/stub_gen.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/codex.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/command.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/context.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/corrections.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/discovery.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/feedback.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/judge.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/lexicon.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/lib.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/mining.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/nlp.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/score.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/sqlite.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/toolcall.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/views/blocks.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/views/command.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/views/convert.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/views/dunder.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/views/events.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/views/meta.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/views/mod.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/views/print.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/views/store.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/views/system.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/views/toolcall.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/views/toolresult.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/views/transcript.rs +0 -0
- {cc_transcript-14.16.1 → cc_transcript-14.22.0}/rust/crates/py/src/watch.rs +0 -0
|
@@ -197,6 +197,7 @@ EXPORTS: dict[str, str] = {
|
|
|
197
197
|
"Lifecycle",
|
|
198
198
|
),
|
|
199
199
|
"cc_transcript.activity": (
|
|
200
|
+
"ActivityLift",
|
|
200
201
|
"Edit",
|
|
201
202
|
"SessionActivity",
|
|
202
203
|
"ToolUse",
|
|
@@ -240,6 +241,7 @@ EXPORTS: dict[str, str] = {
|
|
|
240
241
|
"DeepSession",
|
|
241
242
|
"DeepView",
|
|
242
243
|
"FileRef",
|
|
244
|
+
"PredicateInputs",
|
|
243
245
|
"Session",
|
|
244
246
|
"SubagentIndex",
|
|
245
247
|
"SubagentSession",
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
# isort: off
|
|
3
3
|
|
|
4
4
|
from cc_transcript.activity import (
|
|
5
|
+
ActivityLift as ActivityLift,
|
|
5
6
|
Edit as Edit,
|
|
6
7
|
SessionActivity as SessionActivity,
|
|
7
8
|
ToolUse as ToolUse,
|
|
@@ -207,6 +208,7 @@ from cc_transcript.query import (
|
|
|
207
208
|
DeepSession as DeepSession,
|
|
208
209
|
DeepView as DeepView,
|
|
209
210
|
FileRef as FileRef,
|
|
211
|
+
PredicateInputs as PredicateInputs,
|
|
210
212
|
Session as Session,
|
|
211
213
|
SubagentIndex as SubagentIndex,
|
|
212
214
|
SubagentSession as SubagentSession,
|
|
@@ -304,6 +306,7 @@ EXPORTS: dict[str, str]
|
|
|
304
306
|
__all__ = [
|
|
305
307
|
"ASSISTANTS",
|
|
306
308
|
"Action",
|
|
309
|
+
"ActivityLift",
|
|
307
310
|
"ApiError",
|
|
308
311
|
"ApplyPatchCall",
|
|
309
312
|
"AskUserQuestionResult",
|
|
@@ -390,6 +393,7 @@ __all__ = [
|
|
|
390
393
|
"PRICING",
|
|
391
394
|
"PatchEdit",
|
|
392
395
|
"Plugin",
|
|
396
|
+
"PredicateInputs",
|
|
393
397
|
"PreservedMessages",
|
|
394
398
|
"PreservedSegment",
|
|
395
399
|
"PrintMessage",
|
|
@@ -108,6 +108,7 @@ __all__ = [
|
|
|
108
108
|
"activity_hunk_overlap",
|
|
109
109
|
"activity_lift",
|
|
110
110
|
"activity_lift_from_events",
|
|
111
|
+
"activity_lift_tail",
|
|
111
112
|
"activity_overlap_between",
|
|
112
113
|
"activity_parse_show_hunks",
|
|
113
114
|
"bucket_events_from_events",
|
|
@@ -1497,12 +1498,17 @@ class QueuedCommand:
|
|
|
1497
1498
|
plain-string prompt (e.g. an image-paste payload).
|
|
1498
1499
|
command_mode: How the command was queued, e.g. ``prompt`` or
|
|
1499
1500
|
``task-notification``, or None.
|
|
1501
|
+
origin: Who sent a ``prompt``-mode command: ``human`` for the user,
|
|
1502
|
+
``peer`` for another agent or session, ``channel`` for an MCP
|
|
1503
|
+
channel event; None when the transcript does not record it.
|
|
1500
1504
|
"""
|
|
1501
1505
|
__match_args__: typing.ClassVar[tuple[str, ...]]
|
|
1502
1506
|
@property
|
|
1503
1507
|
def prompt(self) -> typing.Optional[builtins.str]: ...
|
|
1504
1508
|
@property
|
|
1505
1509
|
def command_mode(self) -> typing.Optional[builtins.str]: ...
|
|
1510
|
+
@property
|
|
1511
|
+
def origin(self) -> typing.Optional[builtins.str]: ...
|
|
1506
1512
|
|
|
1507
1513
|
@typing.final
|
|
1508
1514
|
class ReadCall(ToolCallBase):
|
|
@@ -2295,6 +2301,8 @@ def activity_lift(path: builtins.str, max_events: builtins.int) -> dict[str, typ
|
|
|
2295
2301
|
|
|
2296
2302
|
def activity_lift_from_events(events: list[models.TranscriptEvent], opener_flags: typing.Optional[typing.Sequence[builtins.bool]] = None) -> list[dict[str, typing.Any]]: ...
|
|
2297
2303
|
|
|
2304
|
+
def activity_lift_tail(events: list[models.TranscriptEvent], opener_flags: typing.Optional[typing.Sequence[builtins.bool]] = None, open_turn: builtins.bool = False) -> dict[str, typing.Any]: ...
|
|
2305
|
+
|
|
2298
2306
|
def activity_overlap_between(incorrect: typing.Sequence[tuple[builtins.str, builtins.str]], correction: typing.Sequence[tuple[builtins.str, builtins.str]]) -> builtins.float: ...
|
|
2299
2307
|
|
|
2300
2308
|
def activity_parse_show_hunks(diff: builtins.str) -> builtins.list[tuple[builtins.str, builtins.str]]: ...
|
|
@@ -2492,7 +2500,7 @@ def render_tool_call(name: builtins.str, input_json: builtins.str, turn_chars: b
|
|
|
2492
2500
|
|
|
2493
2501
|
def render_tool_call_view(call: tools.ToolCall, turn_chars: builtins.int, tool_chars: builtins.int) -> builtins.str: ...
|
|
2494
2502
|
|
|
2495
|
-
def render_turn_from_events(prompt: builtins.str, events: list[models.TranscriptEvent], turn_chars: builtins.int, tool_chars: builtins.int) -> builtins.str: ...
|
|
2503
|
+
def render_turn_from_events(prompt: builtins.str, events: list[models.TranscriptEvent], turn_chars: builtins.int, tool_chars: builtins.int, tool_results: builtins.bool) -> builtins.str: ...
|
|
2496
2504
|
|
|
2497
2505
|
def score_post_process(spec_json: builtins.str, buckets: typing.Sequence[typing.Sequence[builtins.str]], raw: typing.Sequence[builtins.int]) -> builtins.list[builtins.int]: ...
|
|
2498
2506
|
|
|
@@ -13,8 +13,8 @@ products.
|
|
|
13
13
|
from __future__ import annotations
|
|
14
14
|
|
|
15
15
|
from collections.abc import Callable
|
|
16
|
-
from dataclasses import dataclass
|
|
17
|
-
from typing import TYPE_CHECKING
|
|
16
|
+
from dataclasses import dataclass, replace
|
|
17
|
+
from typing import TYPE_CHECKING, Any
|
|
18
18
|
|
|
19
19
|
from cc_transcript import _native
|
|
20
20
|
from cc_transcript.discovery import TranscriptExpiredError, resolve
|
|
@@ -25,7 +25,7 @@ from cc_transcript.parser import parse
|
|
|
25
25
|
from cc_transcript.tools import edits_of, parse_tool_call, parse_tool_result
|
|
26
26
|
|
|
27
27
|
if TYPE_CHECKING:
|
|
28
|
-
from collections.abc import Sequence
|
|
28
|
+
from collections.abc import Mapping, Sequence
|
|
29
29
|
from datetime import datetime
|
|
30
30
|
from pathlib import Path
|
|
31
31
|
|
|
@@ -181,64 +181,10 @@ class SessionActivity:
|
|
|
181
181
|
turn; everything else folds into the current one. Events before the
|
|
182
182
|
first qualifying prompt form turn 0 with prompt ``""``.
|
|
183
183
|
"""
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
if user_classifier is native_user_classifier
|
|
188
|
-
else [bool(user_classifier(event)) if isinstance(event, UserEvent) else False for event in evs]
|
|
184
|
+
return cls(
|
|
185
|
+
session_id=session_id,
|
|
186
|
+
turns=ActivityLift(session_id, user_classifier=user_classifier).extend(events).turns,
|
|
189
187
|
)
|
|
190
|
-
tool_blocks = {
|
|
191
|
-
event_idx: tuple(block for block in event.blocks if isinstance(block, ToolUseBlock))
|
|
192
|
-
for event_idx, event in enumerate(evs)
|
|
193
|
-
if isinstance(event, AssistantEvent)
|
|
194
|
-
}
|
|
195
|
-
tool_block_positions: dict[int, int] = {}
|
|
196
|
-
turns: list[Turn] = []
|
|
197
|
-
for index, skeleton in enumerate(_native.activity_lift_from_events(evs, opener_flags)):
|
|
198
|
-
tool_uses: list[ToolUse] = []
|
|
199
|
-
for use in skeleton["tool_uses"]:
|
|
200
|
-
event_idx = use["event_idx"]
|
|
201
|
-
event = evs[event_idx]
|
|
202
|
-
block_position = tool_block_positions.get(event_idx, 0)
|
|
203
|
-
block = tool_blocks[event_idx][block_position]
|
|
204
|
-
tool_block_positions[event_idx] = block_position + 1
|
|
205
|
-
result_event_idx = use["result_event_idx"]
|
|
206
|
-
if result_event_idx is None:
|
|
207
|
-
result = None
|
|
208
|
-
result_ts = None
|
|
209
|
-
else:
|
|
210
|
-
result_event = evs[result_event_idx]
|
|
211
|
-
result = next(
|
|
212
|
-
candidate
|
|
213
|
-
for candidate in reversed(result_event.blocks)
|
|
214
|
-
if isinstance(candidate, ToolResultBlock) and candidate.tool_use_id == use["tool_use_id"]
|
|
215
|
-
)
|
|
216
|
-
result_ts = result_event.meta.timestamp
|
|
217
|
-
call = parse_tool_call(block.name, block.input, on_error="other")
|
|
218
|
-
tool_uses.append(
|
|
219
|
-
ToolUse(
|
|
220
|
-
ref=EventRef(session_id, event.meta.uuid, block.id),
|
|
221
|
-
call=call,
|
|
222
|
-
result=result,
|
|
223
|
-
result_ts=result_ts,
|
|
224
|
-
edits=edits_of(call),
|
|
225
|
-
turn_index=index,
|
|
226
|
-
ts=event.meta.timestamp,
|
|
227
|
-
)
|
|
228
|
-
)
|
|
229
|
-
started_idx = skeleton["started_idx"]
|
|
230
|
-
ended_idx = skeleton["ended_idx"]
|
|
231
|
-
turns.append(
|
|
232
|
-
Turn(
|
|
233
|
-
index=index,
|
|
234
|
-
prompt=skeleton["prompt"],
|
|
235
|
-
started_at=None if started_idx is None else evs[started_idx].meta.timestamp,
|
|
236
|
-
ended_at=None if ended_idx is None else evs[ended_idx].meta.timestamp,
|
|
237
|
-
events=tuple(evs[skeleton["start"] : skeleton["end"]]),
|
|
238
|
-
tool_uses=tuple(tool_uses),
|
|
239
|
-
)
|
|
240
|
-
)
|
|
241
|
-
return cls(session_id=session_id, turns=tuple(turns))
|
|
242
188
|
|
|
243
189
|
@classmethod
|
|
244
190
|
def from_session(
|
|
@@ -326,6 +272,176 @@ class SessionActivity:
|
|
|
326
272
|
return tuple(same_turn + later)
|
|
327
273
|
|
|
328
274
|
|
|
275
|
+
class ActivityLift:
|
|
276
|
+
"""A session's lift that grows with its transcript.
|
|
277
|
+
|
|
278
|
+
Each :meth:`extend` folds the events appended since the previous call into
|
|
279
|
+
the activity lifted so far: closed turns are kept, the open turn grows by
|
|
280
|
+
the appended events alone, and a tool use whose result arrives in the tail
|
|
281
|
+
is re-paired wherever it sits. The result always equals
|
|
282
|
+
:meth:`SessionActivity.from_events` over every event fed so far. A step
|
|
283
|
+
costs the appended events, the tool uses they re-pair, and copies of the
|
|
284
|
+
turn tuple and of the open turn's event and tool-use tuples; it never
|
|
285
|
+
re-derives the session.
|
|
286
|
+
|
|
287
|
+
Feed only the events appended since the previous call: nothing checks
|
|
288
|
+
provenance, so events fed twice lift twice. The contract is append-only:
|
|
289
|
+
a cursor's transcript is assumed never rewritten behind the events it has
|
|
290
|
+
been fed, and a transcript rewritten in place, rather than appended to,
|
|
291
|
+
needs a new cursor. Claude Code and Codex transcripts satisfy it.
|
|
292
|
+
|
|
293
|
+
The classifier is read once, at construction, and must be deterministic
|
|
294
|
+
and event-only: its answer for an event has to stay the same as later
|
|
295
|
+
events are appended, since turns lifted under it are never revisited.
|
|
296
|
+
|
|
297
|
+
Example:
|
|
298
|
+
>>> lift = ActivityLift(session_id)
|
|
299
|
+
>>> activity = lift.extend(events)
|
|
300
|
+
>>> lift.extend(appended) == SessionActivity.from_events(session_id, [*events, *appended])
|
|
301
|
+
True
|
|
302
|
+
"""
|
|
303
|
+
|
|
304
|
+
__slots__ = ("_activity", "_results", "_session_id", "_user_classifier", "_uses")
|
|
305
|
+
|
|
306
|
+
def __init__(self, session_id: SessionId, *, user_classifier: UserClassifier = native_user_classifier) -> None:
|
|
307
|
+
self._session_id = session_id
|
|
308
|
+
self._user_classifier = user_classifier
|
|
309
|
+
self._activity = SessionActivity(session_id=session_id, turns=())
|
|
310
|
+
self._uses: dict[ToolUseId, tuple[tuple[int, int], ...]] = {}
|
|
311
|
+
self._results: dict[ToolUseId, UserEvent] = {}
|
|
312
|
+
|
|
313
|
+
@property
|
|
314
|
+
def session_id(self) -> SessionId:
|
|
315
|
+
"""The session being lifted."""
|
|
316
|
+
return self._session_id
|
|
317
|
+
|
|
318
|
+
@property
|
|
319
|
+
def user_classifier(self) -> UserClassifier:
|
|
320
|
+
"""Decides which user events open turns."""
|
|
321
|
+
return self._user_classifier
|
|
322
|
+
|
|
323
|
+
@property
|
|
324
|
+
def activity(self) -> SessionActivity:
|
|
325
|
+
"""Everything lifted so far."""
|
|
326
|
+
return self._activity
|
|
327
|
+
|
|
328
|
+
def extend(self, events: Sequence[TranscriptEvent]) -> SessionActivity:
|
|
329
|
+
"""Lifts ``events``, appended after everything fed so far, into :attr:`activity`."""
|
|
330
|
+
tail = list(events)
|
|
331
|
+
if not tail:
|
|
332
|
+
return self._activity
|
|
333
|
+
opener_flags = (
|
|
334
|
+
None
|
|
335
|
+
if self._user_classifier is native_user_classifier
|
|
336
|
+
else [bool(self._user_classifier(event)) if isinstance(event, UserEvent) else False for event in tail]
|
|
337
|
+
)
|
|
338
|
+
turns = list(self._activity.turns)
|
|
339
|
+
lifted = _native.activity_lift_tail(tail, opener_flags, open_turn=bool(turns))
|
|
340
|
+
first = len(turns) - 1 if lifted["continued"] else len(turns)
|
|
341
|
+
grown = [
|
|
342
|
+
lift_turn(self._session_id, first + offset, skeleton, tail, self._results)
|
|
343
|
+
for offset, skeleton in enumerate(lifted["turns"])
|
|
344
|
+
]
|
|
345
|
+
if lifted["continued"]:
|
|
346
|
+
turns[-1] = continued(turns[-1], grown[0])
|
|
347
|
+
turns.extend(grown[1:])
|
|
348
|
+
else:
|
|
349
|
+
turns.extend(grown)
|
|
350
|
+
repairs: dict[int, dict[int, UserEvent]] = {}
|
|
351
|
+
for tool_use_id, result_idx in lifted["results"]:
|
|
352
|
+
for turn_index, position in self._uses.get(tool_use_id, ()):
|
|
353
|
+
repairs.setdefault(turn_index, {})[position] = tail[result_idx]
|
|
354
|
+
self._results[tool_use_id] = tail[result_idx]
|
|
355
|
+
for turn_index, at in repairs.items():
|
|
356
|
+
turns[turn_index] = repaired(turns[turn_index], at)
|
|
357
|
+
for turn in grown:
|
|
358
|
+
base = len(turns[turn.index].tool_uses) - len(turn.tool_uses)
|
|
359
|
+
for position, use in enumerate(turn.tool_uses, base):
|
|
360
|
+
self._uses[use.ref.tool_use_id] = (*self._uses.get(use.ref.tool_use_id, ()), (turn.index, position))
|
|
361
|
+
self._activity = SessionActivity(session_id=self._session_id, turns=tuple(turns))
|
|
362
|
+
return self._activity
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
def lift_turn(
|
|
366
|
+
session_id: SessionId,
|
|
367
|
+
index: int,
|
|
368
|
+
skeleton: dict[str, Any],
|
|
369
|
+
evs: Sequence[TranscriptEvent],
|
|
370
|
+
prior_results: Mapping[ToolUseId, UserEvent],
|
|
371
|
+
) -> Turn:
|
|
372
|
+
events = tuple(evs[skeleton["start"] : skeleton["end"]])
|
|
373
|
+
calls = [
|
|
374
|
+
(event, block)
|
|
375
|
+
for event in events
|
|
376
|
+
if isinstance(event, AssistantEvent)
|
|
377
|
+
for block in event.blocks
|
|
378
|
+
if isinstance(block, ToolUseBlock)
|
|
379
|
+
]
|
|
380
|
+
started_idx = skeleton["started_idx"]
|
|
381
|
+
ended_idx = skeleton["ended_idx"]
|
|
382
|
+
return Turn(
|
|
383
|
+
index=index,
|
|
384
|
+
prompt=skeleton["prompt"],
|
|
385
|
+
started_at=None if started_idx is None else evs[started_idx].meta.timestamp,
|
|
386
|
+
ended_at=None if ended_idx is None else evs[ended_idx].meta.timestamp,
|
|
387
|
+
events=events,
|
|
388
|
+
tool_uses=tuple(
|
|
389
|
+
lift_tool_use(
|
|
390
|
+
session_id,
|
|
391
|
+
index,
|
|
392
|
+
event,
|
|
393
|
+
block,
|
|
394
|
+
prior_results.get(block.id) if (result_idx := use["result_event_idx"]) is None else evs[result_idx],
|
|
395
|
+
)
|
|
396
|
+
for (event, block), use in zip(calls, skeleton["tool_uses"], strict=True)
|
|
397
|
+
),
|
|
398
|
+
)
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
def lift_tool_use(
|
|
402
|
+
session_id: SessionId, turn_index: int, event: AssistantEvent, block: ToolUseBlock, result_event: UserEvent | None
|
|
403
|
+
) -> ToolUse:
|
|
404
|
+
call = parse_tool_call(block.name, block.input, on_error="other")
|
|
405
|
+
return ToolUse(
|
|
406
|
+
ref=EventRef(session_id, event.meta.uuid, block.id),
|
|
407
|
+
call=call,
|
|
408
|
+
result=None if result_event is None else result_block(result_event, block.id),
|
|
409
|
+
result_ts=None if result_event is None else result_event.meta.timestamp,
|
|
410
|
+
edits=edits_of(call),
|
|
411
|
+
turn_index=turn_index,
|
|
412
|
+
ts=event.meta.timestamp,
|
|
413
|
+
)
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
def result_block(event: UserEvent, tool_use_id: ToolUseId) -> ToolResultBlock:
|
|
417
|
+
return next(
|
|
418
|
+
candidate
|
|
419
|
+
for candidate in reversed(event.blocks)
|
|
420
|
+
if isinstance(candidate, ToolResultBlock) and candidate.tool_use_id == tool_use_id
|
|
421
|
+
)
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
def continued(turn: Turn, tail: Turn) -> Turn:
|
|
425
|
+
return replace(
|
|
426
|
+
turn,
|
|
427
|
+
started_at=tail.started_at if turn.started_at is None else turn.started_at,
|
|
428
|
+
ended_at=turn.ended_at if tail.ended_at is None else tail.ended_at,
|
|
429
|
+
events=turn.events + tail.events,
|
|
430
|
+
tool_uses=turn.tool_uses + tail.tool_uses,
|
|
431
|
+
)
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
def repaired(turn: Turn, at: Mapping[int, UserEvent]) -> Turn:
|
|
435
|
+
uses = list(turn.tool_uses)
|
|
436
|
+
for position, event in at.items():
|
|
437
|
+
uses[position] = replace(
|
|
438
|
+
uses[position],
|
|
439
|
+
result=result_block(event, uses[position].ref.tool_use_id),
|
|
440
|
+
result_ts=event.meta.timestamp,
|
|
441
|
+
)
|
|
442
|
+
return replace(turn, tool_uses=tuple(uses))
|
|
443
|
+
|
|
444
|
+
|
|
329
445
|
def hunk_overlap(a: Hunk, b: Hunk) -> float:
|
|
330
446
|
"""The fraction of ``a.new``'s non-empty lines present in ``b.old``.
|
|
331
447
|
|