semantic-code-review 0.24.2__py3-none-any.whl
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.
- semantic_code_review/__init__.py +5 -0
- semantic_code_review/augment/__init__.py +3 -0
- semantic_code_review/augment/agents.py +95 -0
- semantic_code_review/augment/console.py +440 -0
- semantic_code_review/augment/extra_review.py +237 -0
- semantic_code_review/augment/fold_summary.py +447 -0
- semantic_code_review/augment/hunks.py +264 -0
- semantic_code_review/augment/mcp_server.py +156 -0
- semantic_code_review/augment/overview.py +233 -0
- semantic_code_review/augment/pass_.py +171 -0
- semantic_code_review/augment/pipeline.py +571 -0
- semantic_code_review/augment/progress.py +223 -0
- semantic_code_review/augment/prompts.py +93 -0
- semantic_code_review/augment/schemas.py +408 -0
- semantic_code_review/augment/tools.py +475 -0
- semantic_code_review/augment/trace_adapter.py +369 -0
- semantic_code_review/backends/__init__.py +95 -0
- semantic_code_review/backends/_cli_driver.py +571 -0
- semantic_code_review/backends/anthropic_sdk.py +56 -0
- semantic_code_review/backends/base.py +104 -0
- semantic_code_review/backends/claude_cli.py +421 -0
- semantic_code_review/backends/google_sdk.py +73 -0
- semantic_code_review/backends/openai_compat.py +42 -0
- semantic_code_review/cache/__init__.py +3 -0
- semantic_code_review/cache/store.py +87 -0
- semantic_code_review/cli/__init__.py +70 -0
- semantic_code_review/cli/_shared.py +157 -0
- semantic_code_review/cli/augment.py +74 -0
- semantic_code_review/cli/config_cmd.py +266 -0
- semantic_code_review/cli/fetch.py +33 -0
- semantic_code_review/cli/lint.py +27 -0
- semantic_code_review/cli/pr.py +98 -0
- semantic_code_review/cli/review.py +104 -0
- semantic_code_review/cli/runs_cmd.py +17 -0
- semantic_code_review/cli/show.py +19 -0
- semantic_code_review/cli/strip.py +20 -0
- semantic_code_review/config.py +563 -0
- semantic_code_review/config_template.py +154 -0
- semantic_code_review/fetch/__init__.py +61 -0
- semantic_code_review/fetch/anchor.py +244 -0
- semantic_code_review/fetch/github.py +229 -0
- semantic_code_review/fetch/github_comments.py +404 -0
- semantic_code_review/fetch/local.py +443 -0
- semantic_code_review/fetch/run_source.py +70 -0
- semantic_code_review/format/__init__.py +3 -0
- semantic_code_review/format/emit.py +163 -0
- semantic_code_review/format/lint.py +74 -0
- semantic_code_review/format/parse.py +574 -0
- semantic_code_review/format/sidecar.py +19 -0
- semantic_code_review/format/strip.py +20 -0
- semantic_code_review/git_ops.py +252 -0
- semantic_code_review/paths.py +61 -0
- semantic_code_review/review/__init__.py +3 -0
- semantic_code_review/review/comments.py +176 -0
- semantic_code_review/review/github.py +284 -0
- semantic_code_review/review/github_graphql.py +433 -0
- semantic_code_review/review/pr_flow.py +299 -0
- semantic_code_review/review/runner.py +407 -0
- semantic_code_review/review/server.py +1043 -0
- semantic_code_review/structural/__init__.py +41 -0
- semantic_code_review/structural/diff.py +102 -0
- semantic_code_review/structural/parse.py +330 -0
- semantic_code_review/structural/symbols.py +43 -0
- semantic_code_review/viewer/__init__.py +3 -0
- semantic_code_review/viewer/assets/annotations.ts +547 -0
- semantic_code_review/viewer/assets/boot.ts +273 -0
- semantic_code_review/viewer/assets/comment_store.ts +121 -0
- semantic_code_review/viewer/assets/comments.ts +624 -0
- semantic_code_review/viewer/assets/console.ts +426 -0
- semantic_code_review/viewer/assets/console_render.ts +213 -0
- semantic_code_review/viewer/assets/console_selection.ts +102 -0
- semantic_code_review/viewer/assets/data_store.ts +156 -0
- semantic_code_review/viewer/assets/file_rows.ts +49 -0
- semantic_code_review/viewer/assets/folds.ts +560 -0
- semantic_code_review/viewer/assets/index.html +62 -0
- semantic_code_review/viewer/assets/post_modal.ts +383 -0
- semantic_code_review/viewer/assets/progress.ts +138 -0
- semantic_code_review/viewer/assets/render.ts +937 -0
- semantic_code_review/viewer/assets/sidebar.ts +429 -0
- semantic_code_review/viewer/assets/sse.ts +78 -0
- semantic_code_review/viewer/assets/text_highlight.ts +215 -0
- semantic_code_review/viewer/assets/types.d.ts +388 -0
- semantic_code_review/viewer/assets/vendor/LICENSE +29 -0
- semantic_code_review/viewer/assets/vendor/VENDOR.md +55 -0
- semantic_code_review/viewer/assets/vendor/github-dark.min.css +10 -0
- semantic_code_review/viewer/assets/vendor/github.min.css +10 -0
- semantic_code_review/viewer/assets/vendor/highlight.min.js +1244 -0
- semantic_code_review/viewer/assets/vendor/mermaid.LICENSE +21 -0
- semantic_code_review/viewer/assets/vendor/mermaid.min.js +3587 -0
- semantic_code_review/viewer/assets/vendor/refresh.sh +65 -0
- semantic_code_review/viewer/assets/viewer.css +1202 -0
- semantic_code_review/viewer/assets/viewer.js +10588 -0
- semantic_code_review/viewer/build_json.py +546 -0
- semantic_code_review/viewer/hunk_layout.py +471 -0
- semantic_code_review-0.24.2.dist-info/METADATA +348 -0
- semantic_code_review-0.24.2.dist-info/RECORD +100 -0
- semantic_code_review-0.24.2.dist-info/WHEEL +5 -0
- semantic_code_review-0.24.2.dist-info/entry_points.txt +2 -0
- semantic_code_review-0.24.2.dist-info/licenses/LICENSE +21 -0
- semantic_code_review-0.24.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"""Shared recipe for a single LLM pass.
|
|
2
|
+
|
|
3
|
+
The four passes (`overview`, `hunk`, `fold-summary`, `extra-review-pr`)
|
|
4
|
+
all wrap the same five-step recipe around a per-pass prompt and apply
|
|
5
|
+
step: cache lookup → ``agent.iter()`` driver → trace write → usage
|
|
6
|
+
accounting → cache put. This module owns the recipe; each pass file
|
|
7
|
+
owns only the prompt assembly, agent construction, and the apply step
|
|
8
|
+
that folds the returned payload into an ``AnnotatedDiff``.
|
|
9
|
+
|
|
10
|
+
Driving via ``agent.iter()`` rather than ``agent.run()`` keeps the
|
|
11
|
+
partial message history accessible on the failure path — without it,
|
|
12
|
+
a mid-run ``UsageLimitExceeded`` leaves no trace, which is exactly the
|
|
13
|
+
case that most needs one.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import json
|
|
19
|
+
import logging
|
|
20
|
+
from dataclasses import dataclass
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
from typing import Any
|
|
23
|
+
|
|
24
|
+
from pydantic_ai import Agent
|
|
25
|
+
|
|
26
|
+
from ..cache.store import CacheStore
|
|
27
|
+
from .agents import Client
|
|
28
|
+
from .trace_adapter import (
|
|
29
|
+
submit_args_from_result,
|
|
30
|
+
write_partial_trace,
|
|
31
|
+
write_pydantic_ai_trace,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
log = logging.getLogger(__name__)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass(frozen=True)
|
|
38
|
+
class PassMeta:
|
|
39
|
+
"""Static identity of a pass.
|
|
40
|
+
|
|
41
|
+
``name`` is the cache-key prefix and the ``pass`` field in cache-hit
|
|
42
|
+
trace markers. ``submit_tool`` and ``tool_names`` are recorded in
|
|
43
|
+
the trace envelope so a trace reader can see what tools were in
|
|
44
|
+
play. ``swallow_errors`` switches the failure policy: when true,
|
|
45
|
+
:func:`run_pass` logs and returns ``None`` instead of re-raising —
|
|
46
|
+
used by the extra-review pass, which is best-effort and must not
|
|
47
|
+
poison the main-pass output.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
name: str
|
|
51
|
+
submit_tool: str
|
|
52
|
+
tool_names: tuple[str, ...] = ()
|
|
53
|
+
swallow_errors: bool = False
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
async def run_pass(
|
|
57
|
+
meta: PassMeta,
|
|
58
|
+
*,
|
|
59
|
+
client: Client,
|
|
60
|
+
agent: Agent[Any, Any],
|
|
61
|
+
user_content: Any,
|
|
62
|
+
system: str,
|
|
63
|
+
model: str,
|
|
64
|
+
cache_inputs: tuple[Any, ...],
|
|
65
|
+
deps: Any = None,
|
|
66
|
+
model_settings: Any = None,
|
|
67
|
+
cache: CacheStore | None = None,
|
|
68
|
+
trace_path: Path | None = None,
|
|
69
|
+
cache_request: dict[str, Any] | None = None,
|
|
70
|
+
) -> dict[str, Any] | None:
|
|
71
|
+
"""Run one LLM pass through the shared recipe.
|
|
72
|
+
|
|
73
|
+
Returns the response payload as a JSON-shaped dict (the same shape
|
|
74
|
+
persisted in the cache), or ``None`` when ``meta.swallow_errors`` is
|
|
75
|
+
set and the agent run raised. Callers convert the dict into
|
|
76
|
+
domain shapes themselves and fold the result into the diff.
|
|
77
|
+
|
|
78
|
+
The cache key is ``(meta.name, model, system, *cache_inputs)`` —
|
|
79
|
+
``model`` is the user-facing model string so the key stays stable
|
|
80
|
+
across the SDK/CLI driver split for the same logical model. The
|
|
81
|
+
trace envelope records ``str(client.model)`` instead so the
|
|
82
|
+
diagnostic surface carries the precise model identifier.
|
|
83
|
+
"""
|
|
84
|
+
key = None
|
|
85
|
+
if cache is not None:
|
|
86
|
+
key = cache.key(meta.name, model, system, *cache_inputs)
|
|
87
|
+
entry = cache.get(key)
|
|
88
|
+
if entry is not None:
|
|
89
|
+
if trace_path is not None:
|
|
90
|
+
_write_cache_hit_marker(trace_path, meta.name, entry)
|
|
91
|
+
return entry["response"]
|
|
92
|
+
|
|
93
|
+
async with agent.iter(
|
|
94
|
+
user_content,
|
|
95
|
+
deps=deps,
|
|
96
|
+
model_settings=model_settings,
|
|
97
|
+
) as agent_run:
|
|
98
|
+
try:
|
|
99
|
+
async for _ in agent_run:
|
|
100
|
+
pass
|
|
101
|
+
except BaseException as exc:
|
|
102
|
+
if trace_path is not None:
|
|
103
|
+
write_partial_trace(
|
|
104
|
+
list(agent_run.all_messages()),
|
|
105
|
+
trace_path=trace_path,
|
|
106
|
+
model=str(client.model),
|
|
107
|
+
system=system,
|
|
108
|
+
tool_names=list(meta.tool_names),
|
|
109
|
+
submit_tool=meta.submit_tool,
|
|
110
|
+
error=exc,
|
|
111
|
+
)
|
|
112
|
+
if meta.swallow_errors:
|
|
113
|
+
log.warning(
|
|
114
|
+
"%s pass failed: %s: %s",
|
|
115
|
+
meta.name,
|
|
116
|
+
type(exc).__name__,
|
|
117
|
+
exc,
|
|
118
|
+
)
|
|
119
|
+
return None
|
|
120
|
+
raise
|
|
121
|
+
run_result = agent_run.result
|
|
122
|
+
|
|
123
|
+
assert run_result is not None # the agent run completed without an early return
|
|
124
|
+
|
|
125
|
+
if trace_path is not None:
|
|
126
|
+
write_pydantic_ai_trace(
|
|
127
|
+
run_result,
|
|
128
|
+
trace_path=trace_path,
|
|
129
|
+
model=str(client.model),
|
|
130
|
+
system=system,
|
|
131
|
+
tool_names=list(meta.tool_names),
|
|
132
|
+
submit_tool=meta.submit_tool,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
payload = submit_args_from_result(run_result)
|
|
136
|
+
|
|
137
|
+
if cache is not None and key is not None:
|
|
138
|
+
usage = run_result.usage()
|
|
139
|
+
cache.put(
|
|
140
|
+
key,
|
|
141
|
+
request=cache_request or {},
|
|
142
|
+
response=payload,
|
|
143
|
+
tokens_in=usage.input_tokens or 0,
|
|
144
|
+
tokens_out=usage.output_tokens or 0,
|
|
145
|
+
)
|
|
146
|
+
return payload
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def _write_cache_hit_marker(
|
|
150
|
+
path: Path,
|
|
151
|
+
pass_name: str,
|
|
152
|
+
entry: dict[str, Any],
|
|
153
|
+
) -> None:
|
|
154
|
+
"""Write the cache-hit envelope at ``path``.
|
|
155
|
+
|
|
156
|
+
Mirrors the live-run trace shape just enough that a trace reader
|
|
157
|
+
can identify the pass and see the cached response — the full
|
|
158
|
+
iteration history isn't reconstructible from a cache entry.
|
|
159
|
+
"""
|
|
160
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
161
|
+
path.write_text(
|
|
162
|
+
json.dumps(
|
|
163
|
+
{"cache_hit": True, "pass": pass_name, "response": entry.get("response")},
|
|
164
|
+
indent=2,
|
|
165
|
+
ensure_ascii=False,
|
|
166
|
+
),
|
|
167
|
+
encoding="utf-8",
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
__all__ = ["PassMeta", "run_pass"]
|