cc-transcript 14.0.0__tar.gz → 14.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.
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/PKG-INFO +1 -1
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/_native.pyi +6 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/pyproject.toml +1 -1
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/src/command.rs +115 -2
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/src/parse.rs +2 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/src/types.rs +2 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/data/command_prefix_pins.tsv +1 -1
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/views/print.rs +15 -1
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/views/store.rs +7 -2
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/Cargo.lock +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/Cargo.toml +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/LICENSE +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/README.md +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/__init__.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/activity.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/activity_probe.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/builders.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/command.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/context.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/corrections.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/cost.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/decisions.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/discovery.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/disktruth.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/evidence.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/extract/__init__.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/extract/correct.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/facts.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/filterspec.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/heartbeats.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/ids.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/judge/__init__.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/judge/llm.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/judge/similar.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/judge/verdicts.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/ledger.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/literals.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/mining/__init__.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/mining/candidates.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/mining/confidence.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/mining/engine.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/mining/filterspec.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/mining/formats.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/mining/sampling.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/mining/signals.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/mining/sourcekind.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/mining/spec.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/mining/store.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/models.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/nlp.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/notifications.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/parser.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/py.typed +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/query.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/render.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/sentiment/__init__.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/sentiment/buckets.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/sentiment/data/afinn-en-165.tsv +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/sentiment/data/domain_overrides.tsv +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/sentiment/data/en-ewt.udpipe +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/sentiment/engine.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/sentiment/lexicon.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/sentiment/scorespec.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/store.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/tools.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/watch.py +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/cli/Cargo.toml +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/cli/src/commands/corrections.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/cli/src/commands/digest.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/cli/src/commands/facts.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/cli/src/commands/grep.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/cli/src/commands/list.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/cli/src/commands/mod.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/cli/src/commands/scratchpad.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/cli/src/commands/show.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/cli/src/commands/slice.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/cli/src/commands/stats.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/cli/src/commands/watch.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/cli/src/lib.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/cli/src/main.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/cli/src/output.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/cli/src/target.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/Cargo.toml +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/benches/parse.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/benches/render.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/benches/toolcall.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/src/activity.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/src/buckets.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/src/context.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/src/corrections.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/src/cost.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/src/discovery.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/src/facts.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/src/filter.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/src/ids.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/src/lib.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/src/literals/command.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/src/literals/corrections.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/src/literals/mining.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/src/literals/mod.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/src/literals/protocol.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/src/notifications.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/src/protocol.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/src/pystr.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/src/query.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/src/render.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/src/toolcall.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/src/value.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/core/src/watch.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/Cargo.toml +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/build.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/bin/stub_gen.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/command.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/context.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/corrections.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/discovery.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/lexicon.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/lib.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/mining.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/nlp.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/python.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/render.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/score.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/toolcall.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/views/attachment.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/views/blocks.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/views/command.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/views/convert.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/views/dunder.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/views/events.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/views/meta.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/views/mod.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/views/system.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/views/toolcall.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/views/toolresult.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/views/transcript.rs +0 -0
- {cc_transcript-14.0.0 → cc_transcript-14.1.0}/rust/crates/py/src/watch.rs +0 -0
|
@@ -1259,6 +1259,8 @@ class PrintMessage:
|
|
|
1259
1259
|
blocks: The structured content blocks of the message.
|
|
1260
1260
|
uuid: The message's event uuid, when present.
|
|
1261
1261
|
session_id: The session the message belongs to.
|
|
1262
|
+
id: The API message id, when present (assistant messages carry one).
|
|
1263
|
+
usage: The message's token usage, when present (assistant messages carry one).
|
|
1262
1264
|
"""
|
|
1263
1265
|
__match_args__: typing.ClassVar[tuple[str, ...]]
|
|
1264
1266
|
@property
|
|
@@ -1273,6 +1275,10 @@ class PrintMessage:
|
|
|
1273
1275
|
def uuid(self) -> ids.EventUuid | None: ...
|
|
1274
1276
|
@property
|
|
1275
1277
|
def session_id(self) -> ids.SessionId: ...
|
|
1278
|
+
@property
|
|
1279
|
+
def id(self) -> typing.Optional[builtins.str]: ...
|
|
1280
|
+
@property
|
|
1281
|
+
def usage(self) -> typing.Optional[Usage]: ...
|
|
1276
1282
|
|
|
1277
1283
|
@typing.final
|
|
1278
1284
|
class PrintResult:
|
|
@@ -183,10 +183,23 @@ pub struct CommandLine {
|
|
|
183
183
|
impl CommandLine {
|
|
184
184
|
// Parity: command.py CommandLine.parse — blank/comment-only input yields empty parts.
|
|
185
185
|
pub fn parse(raw: &str) -> CommandLine {
|
|
186
|
-
let parts = BASH_PARSER.with(|parser| match parser.borrow_mut().parse(raw, None) {
|
|
186
|
+
let mut parts = BASH_PARSER.with(|parser| match parser.borrow_mut().parse(raw, None) {
|
|
187
187
|
Some(tree) => walk_node(tree.root_node(), raw.as_bytes()),
|
|
188
188
|
None => Vec::new(),
|
|
189
189
|
});
|
|
190
|
+
// Nested inside an enumerated host's span: visible but span-less, like an absorbed word.
|
|
191
|
+
let spans: Vec<Option<(usize, usize)>> = parts.iter().map(|(cmd, _)| cmd.span).collect();
|
|
192
|
+
for (i, (cmd, _)) in parts.iter_mut().enumerate() {
|
|
193
|
+
let Some((start, end)) = cmd.span else {
|
|
194
|
+
continue;
|
|
195
|
+
};
|
|
196
|
+
let enclosed = spans.iter().enumerate().any(|(j, other)| {
|
|
197
|
+
j != i && matches!(other, Some((os, oe)) if *os <= start && end <= *oe && (*os, *oe) != (start, end))
|
|
198
|
+
});
|
|
199
|
+
if enclosed {
|
|
200
|
+
cmd.span = None;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
190
203
|
CommandLine {
|
|
191
204
|
raw: raw.to_string(),
|
|
192
205
|
parts,
|
|
@@ -568,7 +581,11 @@ fn walk_node(node: Node, src: &[u8]) -> Vec<(Command, Option<String>)> {
|
|
|
568
581
|
"program" => walk_program(node, src),
|
|
569
582
|
"list" => collect_parts(node, src, COMPOUND_OPS),
|
|
570
583
|
"pipeline" => collect_parts(node, src, &["|"]),
|
|
571
|
-
"command" =>
|
|
584
|
+
"command" => {
|
|
585
|
+
let mut parts = vec![(extract_command(node, src), None)];
|
|
586
|
+
parts.extend(substitution_parts(node, src));
|
|
587
|
+
parts
|
|
588
|
+
}
|
|
572
589
|
"redirected_statement" => walk_redirected(node, src),
|
|
573
590
|
_ => {
|
|
574
591
|
let mut parts = Vec::new();
|
|
@@ -581,6 +598,21 @@ fn walk_node(node: Node, src: &[u8]) -> Vec<(Command, Option<String>)> {
|
|
|
581
598
|
}
|
|
582
599
|
}
|
|
583
600
|
|
|
601
|
+
// Word/argument-position `$(…)`/backtick substitutions under a command node, enumerated as parts
|
|
602
|
+
// mirroring assignment position: document order (host first), redirect targets excluded.
|
|
603
|
+
fn substitution_parts(node: Node, src: &[u8]) -> Vec<(Command, Option<String>)> {
|
|
604
|
+
let mut parts = Vec::new();
|
|
605
|
+
let mut cursor = node.walk();
|
|
606
|
+
for child in node.children(&mut cursor) {
|
|
607
|
+
match child.kind() {
|
|
608
|
+
"command_substitution" => parts.extend(walk_node(child, src)),
|
|
609
|
+
"file_redirect" => {}
|
|
610
|
+
_ => parts.extend(substitution_parts(child, src)),
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
parts
|
|
614
|
+
}
|
|
615
|
+
|
|
584
616
|
// Parity: command.py CommandLine.walk_program — collect_parts over `;`, dropping the heredoc body
|
|
585
617
|
// and delimiter lines that tree-sitter's multi-heredoc ERROR recovery re-parses as sibling commands.
|
|
586
618
|
fn walk_program(node: Node, src: &[u8]) -> Vec<(Command, Option<String>)> {
|
|
@@ -1017,6 +1049,87 @@ mod tests {
|
|
|
1017
1049
|
assert_eq!(line.parts[0].0.redirects[0].fd, None);
|
|
1018
1050
|
}
|
|
1019
1051
|
|
|
1052
|
+
fn execs(line: &CommandLine) -> Vec<&str> {
|
|
1053
|
+
line.parts
|
|
1054
|
+
.iter()
|
|
1055
|
+
.map(|(cmd, _)| cmd.executable.as_str())
|
|
1056
|
+
.collect()
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
// Both substitution positions get one treatment: the nested command is a first-class part.
|
|
1060
|
+
#[test]
|
|
1061
|
+
fn substitutions_enumerate_in_word_position_like_assignment_position() {
|
|
1062
|
+
assert_eq!(
|
|
1063
|
+
execs(&CommandLine::parse("x=$(ccx repo overview)")),
|
|
1064
|
+
["ccx"]
|
|
1065
|
+
);
|
|
1066
|
+
let word = CommandLine::parse("echo $(ccx repo overview)");
|
|
1067
|
+
assert_eq!(execs(&word), ["echo", "ccx"]);
|
|
1068
|
+
assert_eq!(word.parts[1].0.args, ["repo", "overview"]);
|
|
1069
|
+
assert_eq!(
|
|
1070
|
+
execs(&CommandLine::parse("echo `ccx repo overview`")),
|
|
1071
|
+
["echo", "ccx"]
|
|
1072
|
+
);
|
|
1073
|
+
// command_name, quoted, concatenated, and env-prefix-value positions all enumerate.
|
|
1074
|
+
assert_eq!(
|
|
1075
|
+
execs(&CommandLine::parse("$(which python) --version")),
|
|
1076
|
+
["$(which python)", "which"]
|
|
1077
|
+
);
|
|
1078
|
+
assert_eq!(execs(&CommandLine::parse("echo \"$(a)\"")), ["echo", "a"]);
|
|
1079
|
+
assert_eq!(
|
|
1080
|
+
execs(&CommandLine::parse("tag=v$(git rev-parse HEAD) make")),
|
|
1081
|
+
["make", "git"]
|
|
1082
|
+
);
|
|
1083
|
+
// Redirect targets stay out, matching statement-level redirects.
|
|
1084
|
+
assert_eq!(execs(&CommandLine::parse("echo hi > $(target)")), ["echo"]);
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
// Document order: the host command first, then each outermost substitution left to right,
|
|
1088
|
+
// recursing so nested substitutions follow their host.
|
|
1089
|
+
#[test]
|
|
1090
|
+
fn substitutions_enumerate_nested_in_document_order() {
|
|
1091
|
+
assert_eq!(
|
|
1092
|
+
execs(&CommandLine::parse("diff $(sort a) $(b $(c))")),
|
|
1093
|
+
["diff", "sort", "b", "c"]
|
|
1094
|
+
);
|
|
1095
|
+
assert_eq!(
|
|
1096
|
+
execs(&CommandLine::parse("echo $(a | b; c)")),
|
|
1097
|
+
["echo", "a", "b", "c"]
|
|
1098
|
+
);
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
// Operator attachment mirrors assignment position: the op hangs off the last enumerated part.
|
|
1102
|
+
#[test]
|
|
1103
|
+
fn substitution_parts_carry_operators_and_spans_like_assignment_position() {
|
|
1104
|
+
let assign = CommandLine::parse("x=$(a) && foo");
|
|
1105
|
+
assert_eq!(execs(&assign), ["a", "foo"]);
|
|
1106
|
+
assert_eq!(assign.parts[0].1.as_deref(), Some("&&"));
|
|
1107
|
+
let word = CommandLine::parse("echo $(a) && foo");
|
|
1108
|
+
assert_eq!(execs(&word), ["echo", "a", "foo"]);
|
|
1109
|
+
assert_eq!(word.parts[0].1, None);
|
|
1110
|
+
assert_eq!(word.parts[1].1.as_deref(), Some("&&"));
|
|
1111
|
+
assert_eq!(word.next_op(1), Some("&&"));
|
|
1112
|
+
assert_eq!(word.prev_op(2), Some("&&"));
|
|
1113
|
+
assert!(!word.piped(0) && !word.piped(1));
|
|
1114
|
+
// Nested inside the host's span: visible but span-less (splice's non-overlap invariant);
|
|
1115
|
+
// assignment position has no host, so its span survives and splices in place.
|
|
1116
|
+
let line = CommandLine::parse("echo $(ccx repo overview)");
|
|
1117
|
+
assert_eq!(line.parts[0].0.span, Some((0, 25)));
|
|
1118
|
+
assert_eq!(line.parts[1].0.span, None);
|
|
1119
|
+
assert!(matches!(
|
|
1120
|
+
line.splice(&BTreeMap::from([(1, "ls".to_string())])),
|
|
1121
|
+
Err(SpliceError::NoSpan { index: 1 })
|
|
1122
|
+
));
|
|
1123
|
+
let assign_only = CommandLine::parse("x=$(ccx repo overview)");
|
|
1124
|
+
assert_eq!(assign_only.parts[0].0.span, Some((4, 21)));
|
|
1125
|
+
assert_eq!(
|
|
1126
|
+
assign_only
|
|
1127
|
+
.splice(&BTreeMap::from([(0, "ls".to_string())]))
|
|
1128
|
+
.unwrap(),
|
|
1129
|
+
"x=$(ls)"
|
|
1130
|
+
);
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1020
1133
|
#[test]
|
|
1021
1134
|
fn rewrite_occurrences_maps_or_none() {
|
|
1022
1135
|
let line = CommandLine::parse("git push; ls; git pull");
|
|
@@ -699,6 +699,8 @@ fn parse_print_message(element: &Value) -> Result<PrintMessage, ParseError> {
|
|
|
699
699
|
};
|
|
700
700
|
Ok(PrintMessage {
|
|
701
701
|
body,
|
|
702
|
+
id: field_str(message, "id").map(str::to_string),
|
|
703
|
+
usage: parse_usage(message)?,
|
|
702
704
|
uuid: field_str(element, "uuid").map(str::to_string),
|
|
703
705
|
session_id: require_str(element, "session_id")?.to_string(),
|
|
704
706
|
})
|
|
@@ -34,7 +34,7 @@ process-substitution diff <(sort a.txt) <(sort b.txt) diff
|
|
|
34
34
|
process-substitution-in-pipeline cat <(git log) | head -3 cat|head
|
|
35
35
|
arithmetic-expansion echo $((1 + 2)) echo
|
|
36
36
|
arithmetic-assignment-prefix x=$((COUNT + 1)) make build make
|
|
37
|
-
backtick-substitution echo `git rev-parse HEAD` echo
|
|
37
|
+
backtick-substitution echo `git rev-parse HEAD` echo|git rev-parse
|
|
38
38
|
function-definition-body-and-call foo() { git status; }; foo git status|foo
|
|
39
39
|
multiline-quoted-string git commit -m "line1\nline2" git commit
|
|
40
40
|
newline-separated-commands git add .\ngit commit -m x git add|git commit
|
|
@@ -264,6 +264,8 @@ view_dunders!(
|
|
|
264
264
|
/// blocks: The structured content blocks of the message.
|
|
265
265
|
/// uuid: The message's event uuid, when present.
|
|
266
266
|
/// session_id: The session the message belongs to.
|
|
267
|
+
/// id: The API message id, when present (assistant messages carry one).
|
|
268
|
+
/// usage: The message's token usage, when present (assistant messages carry one).
|
|
267
269
|
#[pyo3_stub_gen::derive::gen_stub_pyclass]
|
|
268
270
|
#[pyclass(name = "PrintMessage", module = "cc_transcript.models", frozen)]
|
|
269
271
|
pub(crate) struct PrintMessageView {
|
|
@@ -326,12 +328,24 @@ impl PrintMessageView {
|
|
|
326
328
|
fn session_id(&self, _py: Python<'_>) -> PyResult<String> {
|
|
327
329
|
Ok(self.message().session_id.clone())
|
|
328
330
|
}
|
|
331
|
+
|
|
332
|
+
#[getter]
|
|
333
|
+
fn id(&self, _py: Python<'_>) -> PyResult<Option<String>> {
|
|
334
|
+
Ok(self.message().id.clone())
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
#[getter]
|
|
338
|
+
fn usage(&self, _py: Python<'_>) -> PyResult<Option<UsageView>> {
|
|
339
|
+
Ok(self.message().usage.as_ref().map(|_| UsageView {
|
|
340
|
+
host: UsageHost::PrintMessage(Arc::clone(&self.p.0), self.msg),
|
|
341
|
+
}))
|
|
342
|
+
}
|
|
329
343
|
}
|
|
330
344
|
|
|
331
345
|
view_dunders!(
|
|
332
346
|
PrintMessageView,
|
|
333
347
|
"PrintMessage",
|
|
334
|
-
fields = [role, model, text, blocks, uuid, session_id]
|
|
348
|
+
fields = [role, model, text, blocks, uuid, session_id, id, usage]
|
|
335
349
|
);
|
|
336
350
|
|
|
337
351
|
/// A parsed 'claude -p --output-format json' result.
|
|
@@ -100,12 +100,13 @@ impl BlockRef {
|
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
/// Where a Usage lives: an assistant entry's optional usage,
|
|
104
|
-
/// usage of a ``--print`` result.
|
|
103
|
+
/// Where a Usage lives: an assistant entry's optional usage, the aggregate
|
|
104
|
+
/// usage of a ``--print`` result, or one ``--print`` message's usage.
|
|
105
105
|
#[derive(Clone)]
|
|
106
106
|
pub(crate) enum UsageHost {
|
|
107
107
|
Entry(EventRef),
|
|
108
108
|
Print(Arc<PrintResult>),
|
|
109
|
+
PrintMessage(Arc<PrintResult>, usize),
|
|
109
110
|
}
|
|
110
111
|
|
|
111
112
|
impl UsageHost {
|
|
@@ -117,6 +118,10 @@ impl UsageHost {
|
|
|
117
118
|
.as_ref()
|
|
118
119
|
.expect("usage view over an assistant entry with usage"),
|
|
119
120
|
UsageHost::Print(pr) => &pr.usage,
|
|
121
|
+
UsageHost::PrintMessage(pr, msg) => pr.messages[*msg]
|
|
122
|
+
.usage
|
|
123
|
+
.as_ref()
|
|
124
|
+
.expect("usage view over a print message with usage"),
|
|
120
125
|
}
|
|
121
126
|
}
|
|
122
127
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cc_transcript-14.0.0 → cc_transcript-14.1.0}/cc_transcript/sentiment/data/domain_overrides.tsv
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|