-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy path03_streaming_review.py
More file actions
139 lines (116 loc) · 4.25 KB
/
Copy path03_streaming_review.py
File metadata and controls
139 lines (116 loc) · 4.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/usr/bin/env python3
"""Streaming Code Review using GitHub Copilot SDK.
See the tutorial for learning goals, prerequisites, and usage:
docs/copilot_sdk_tutorial/tutorials/03_streaming.md (English)
docs/copilot_sdk_tutorial/tutorials/03_streaming.ja.md (日本語)
"""
import argparse
import asyncio
import sys
from pathlib import Path
from _telemetry import add_telemetry_arguments, apply_telemetry_arguments, make_client
from copilot.generated.rpc import PermissionDecisionApproveOnce
from copilot.generated.session_events import (
SessionEventType,
PermissionRequest,
)
from copilot.session import (
PermissionRequestResult,
SystemMessageReplaceConfig,
)
# ---------------------------------------------------------------------------
# Sample diff (embedded so the script runs without external files)
# ---------------------------------------------------------------------------
SAMPLE_DIFF = """\
diff --git a/src/auth.py b/src/auth.py
index 1a2b3c4..5d6e7f8 100644
--- a/src/auth.py
+++ b/src/auth.py
@@ -12,7 +12,7 @@ import hashlib
def hash_password(password: str) -> str:
- return hashlib.md5(password.encode()).hexdigest()
+ return hashlib.sha256(password.encode()).hexdigest()
@@ -28,6 +28,12 @@ def verify_token(token: str) -> bool:
if not token:
return False
+ # TODO: add expiry check
return token in _valid_tokens
+def delete_user(user_id: int) -> None:
+ # WARNING: no authorization check
+ db.execute("DELETE FROM users WHERE id = %s" % user_id)
"""
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(
description="Streaming Code Review using the GitHub Copilot SDK",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=__doc__,
)
parser.add_argument(
"--diff",
"-d",
default=None,
help="Path to a unified diff file (uses built-in sample if not provided)",
)
parser.add_argument(
"--cli-url",
"-c",
default=None,
help=(
"Optional Copilot CLI server URL (e.g. localhost:3000). "
"When omitted, the SDK launches the copilot CLI over stdio."
),
)
add_telemetry_arguments(parser)
return parser.parse_args()
async def run(cli_url: str | None, diff_text: str) -> None:
def approve_all(
request: PermissionRequest,
context: dict,
) -> PermissionRequestResult:
return PermissionDecisionApproveOnce()
client = make_client(cli_url)
await client.start()
session = await client.create_session(
on_permission_request=approve_all,
tools=[],
streaming=True, # ← streaming enabled
system_message=SystemMessageReplaceConfig(
mode="replace",
content=(
"You are a senior software engineer conducting a thorough code review. "
"For each change in the diff: identify bugs, security issues, and style problems. "
"Be concise but precise. Use Markdown formatting."
),
),
)
# Stream tokens to stdout as they arrive
print("=== Streaming Code Review ===\n")
def on_event(event) -> None: # noqa: ANN001
if event.type == SessionEventType.ASSISTANT_MESSAGE_DELTA:
print(event.data.delta_content, end="", flush=True)
elif event.type == SessionEventType.SESSION_ERROR:
print(f"\n[Error] {event.data.message}", file=sys.stderr)
session.on(on_event)
prompt = f"Please review the following diff and provide feedback:\n\n```diff\n{diff_text}\n```"
await session.send_and_wait(prompt, timeout=300)
print("\n\n=== Review Complete ===")
def main() -> None:
args = parse_args()
apply_telemetry_arguments(args)
if args.diff:
diff_path = Path(args.diff)
if not diff_path.exists():
print(f"Error: diff file not found: {args.diff}", file=sys.stderr)
sys.exit(1)
diff_text = diff_path.read_text()
else:
diff_text = SAMPLE_DIFF
print(
"[Info] Using built-in sample diff. Pass --diff <path> to use your own.\n"
)
try:
asyncio.run(run(args.cli_url, diff_text))
except KeyboardInterrupt:
print("\nBye!")
if __name__ == "__main__":
main()