-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexample_usage.py
More file actions
199 lines (162 loc) · 8.26 KB
/
Copy pathexample_usage.py
File metadata and controls
199 lines (162 loc) · 8.26 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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
"""
Six end-to-end usage scenarios for the Agent Interaction Layer.
a. Fresh session — books.toscrape.com, find cheapest book in Mystery category
b. Session reuse — same conversation_id, different goal on the same site
c. Memory hit — third call where SiteMemory returns a hint from scenario (a)
d. Quotes site — quotes.toscrape.com, first quote tagged 'life'
e. Wikipedia — en.wikipedia.org/wiki/Tokyo, current population
f. Hacker News — news.ycombinator.com, highest-scored front page post
Run directly:
export ANTHROPIC_API_KEY=your_key
python example_usage.py
"""
import asyncio
import os
import sys
# Ensure local modules are importable when run directly
sys.path.insert(0, os.path.dirname(__file__))
from controller import AgentController, SessionManager
from logger import get_logger
log = get_logger("example")
# TEST URLs
TEST_URL = "https://books.toscrape.com" # purpose-built scraper test site
QUOTES_URL = "https://quotes.toscrape.com" # simple quotes listing site
WIKI_TOKYO_URL = "https://en.wikipedia.org/wiki/Tokyo" # static reference page
HN_URL = "https://news.ycombinator.com" # live front page with scores
async def main() -> None:
session_manager = SessionManager()
controller = AgentController(session_manager)
# ------------------------------------------------------------------
# Scenario (a): Fresh session
# A brand-new conversation_id → fresh isolated browser context.
# ------------------------------------------------------------------
print("\n" + "=" * 60)
print("Scenario (a): Fresh session — Mystery category cheapest book")
print("=" * 60)
conversation_id = "demo-conversation-001"
goal_a = "find the cheapest book in the Mystery category and return its title and price"
session_id_a = SessionManager.make_session_id(TEST_URL, goal_a, conversation_id)
print(f" conversation_id : {conversation_id}")
print(f" session_id : {session_id_a}")
print(f" goal : {goal_a}")
result_a = await controller.run(TEST_URL, goal_a, session_id_a)
print(f"\n RESULT:\n {result_a}\n")
# ------------------------------------------------------------------
# Scenario (b): Session reuse — same conversation_id, different goal
# SessionManager reuses the existing BrowserContext so the agent
# continues from the current page state rather than starting cold.
# ------------------------------------------------------------------
print("=" * 60)
print("Scenario (b): Session reuse — same conversation_id, different goal")
print("=" * 60)
goal_b = "find the most expensive book on the site and return its title and price"
# SAME conversation_id → same browser context is reused
session_id_b = SessionManager.make_session_id(TEST_URL, goal_b, conversation_id)
print(f" conversation_id : {conversation_id} (same as scenario a)")
print(f" session_id : {session_id_b}")
print(f" goal : {goal_b}")
result_b = await controller.run(TEST_URL, goal_b, session_id_b)
print(f"\n RESULT:\n {result_b}\n")
# ------------------------------------------------------------------
# Scenario (c): Memory hit
# Scenario (a) recorded a successful pattern in SiteMemory.
# A new conversation with the same goal triggers get_hint(), and the
# hint is prepended to the first decide() call.
# ------------------------------------------------------------------
print("=" * 60)
print("Scenario (c): Memory hit — new conversation, same site+goal")
print("=" * 60)
# Different conversation → fresh session, but memory from (a) survives
new_conversation_id = "demo-conversation-002"
goal_c = goal_a # same goal as (a) — will trigger keyword overlap match
# Manually check the hint before running so we can show it explicitly
hint = controller.memory.get_hint(TEST_URL, goal_c)
print(f" conversation_id : {new_conversation_id} (new)")
print(f" goal : {goal_c}")
print(f" memory hint : {hint or '(none — run scenario a first to build memory)'}")
session_id_c = SessionManager.make_session_id(TEST_URL, goal_c, new_conversation_id)
result_c = await controller.run(TEST_URL, goal_c, session_id_c)
print(f"\n RESULT:\n {result_c}\n")
# ------------------------------------------------------------------
# Scenario (d): quotes.toscrape.com — first 'life'-tagged quote
# Tests static-content extraction on a simple listing page.
# ------------------------------------------------------------------
print("=" * 60)
print("Scenario (d): Quotes — first quote tagged 'life'")
print("=" * 60)
try:
conversation_id_d = "demo-conversation-003"
goal_d = "find the first quote tagged with 'life' and return the quote text and its author"
session_id_d = SessionManager.make_session_id(QUOTES_URL, goal_d, conversation_id_d)
print(f" conversation_id : {conversation_id_d}")
print(f" session_id : {session_id_d}")
print(f" goal : {goal_d}")
result_d = await asyncio.wait_for(
controller.run(QUOTES_URL, goal_d, session_id_d),
timeout=180,
)
print(f"\n RESULT:\n {result_d}\n")
except asyncio.TimeoutError:
print("\n SCENARIO (d) WALL-CLOCK TIMEOUT after 180s\n")
except Exception as exc:
print(f"\n ERROR in scenario (d): {type(exc).__name__}: {exc}\n")
# ------------------------------------------------------------------
# Scenario (e): Wikipedia Tokyo — current population figure
# Tests numerical extraction from a dense reference article.
# ------------------------------------------------------------------
print("=" * 60)
print("Scenario (e): Wikipedia — Tokyo population")
print("=" * 60)
try:
conversation_id_e = "demo-conversation-004"
goal_e = (
"You are already on the Tokyo Wikipedia article. "
"Find and return the current population of Tokyo as stated on this page. "
"Do not navigate away or search — the answer is on this page."
)
session_id_e = SessionManager.make_session_id(WIKI_TOKYO_URL, goal_e, conversation_id_e)
print(f" conversation_id : {conversation_id_e}")
print(f" session_id : {session_id_e}")
print(f" goal : {goal_e}")
result_e = await asyncio.wait_for(
controller.run(WIKI_TOKYO_URL, goal_e, session_id_e),
timeout=180,
)
print(f"\n RESULT:\n {result_e}\n")
except asyncio.TimeoutError:
print("\n SCENARIO (e) WALL-CLOCK TIMEOUT after 180s\n")
except Exception as exc:
print(f"\n ERROR in scenario (e): {type(exc).__name__}: {exc}\n")
# ------------------------------------------------------------------
# Scenario (f): Hacker News — highest-scored front page post
# Tests live dynamic content with numeric score comparison.
# ------------------------------------------------------------------
print("=" * 60)
print("Scenario (f): Hacker News — highest-scored front page post")
print("=" * 60)
try:
conversation_id_f = "demo-conversation-005"
goal_f = "find the title and score of the highest-scored post on the front page"
session_id_f = SessionManager.make_session_id(HN_URL, goal_f, conversation_id_f)
print(f" conversation_id : {conversation_id_f}")
print(f" session_id : {session_id_f}")
print(f" goal : {goal_f}")
result_f = await asyncio.wait_for(
controller.run(HN_URL, goal_f, session_id_f),
timeout=180,
)
print(f"\n RESULT:\n {result_f}\n")
except asyncio.TimeoutError:
print("\n SCENARIO (f) WALL-CLOCK TIMEOUT after 180s\n")
except Exception as exc:
print(f"\n ERROR in scenario (f): {type(exc).__name__}: {exc}\n")
# Graceful teardown
for sid in list(session_manager._sessions.keys()):
await session_manager._destroy_session(sid)
if session_manager._playwright:
await session_manager._playwright.stop()
print("=" * 60)
print("All 6 scenarios complete.")
print("=" * 60)
if __name__ == "__main__":
asyncio.run(main())