Ready for first real test

This commit is contained in:
Aryan Singh committed 2026-07-02 00:46:34 -05:00
1 parent acddf9135f
commit b91c81ebdf
46 files changed
+34903 -26

No files matched your search

+31 -11
View File
@@ -41,11 +41,22 @@ RESEARCH_KICKOFF = (
"call get_option_chain(underlying, 'call' or 'put') and copy an exact contract_symbol."
)
DEEPEN_NUDGE = (
"You're not finished. Keep researching before finalizing: evaluate additional candidate "
"tickers you haven't examined yet, pull bars/news/fundamentals for them, verify with "
"web_search, and stress-test your leading ideas against the alternatives. Continue using tools."
)
# Rotating directive nudges — cycled so a long (~2hr) research session stays PRODUCTIVE
# (does new, varied work) instead of looping "am I done?". Keep using tools.
DEEPEN_NUDGES = [
"Not done yet. Screen 5-10 MORE candidate tickers in your style you haven't examined; pull "
"get_bars / get_news / get_fundamentals on them.",
"Build the BEAR case for your current top pick: what would make it wrong? Find data that "
"challenges your thesis (web_search + web_fetch recent coverage).",
"Use run_analysis to write a real script: fetch prices with yfinance, compute momentum / "
"moving averages / volatility / correlations, and save a chart to back your best idea.",
"Zoom out: check the macro + sector context (rates, the sector ETF, peers) via web_search and "
"get_bars. Does it support or undercut your picks?",
"Compare your leading picks head-to-head against 2-3 sector peers on valuation and momentum "
"(get_fundamentals + run_analysis). Are you picking the best expression of the thesis?",
"Re-examine catalysts and timing for each candidate (earnings dates, events via get_news / "
"web_search) and refine entry, stop, and take-profit levels with run_python.",
]
FINALIZE_PROMPT = (
"Research complete. Return a JSON object of the form {{\"picks\": [ ... ]}} containing about "
@@ -176,6 +187,7 @@ def run_agent(
deadline_ts: float,
step_budget: int,
min_steps: int = 0,
min_seconds: float = 0.0,
checkpointer=None,
model_name: str = "",
) -> AgentOutput:
@@ -195,6 +207,7 @@ def run_agent(
running_summary = ""
reasoning_trace: list[str] = []
steps_used = 0
nudge_count = 0
ended_reason = "natural"
def snapshot(status: AgentStatus, picks: list[Pick] | None = None, errors=None) -> AgentOutput:
@@ -229,11 +242,16 @@ def run_agent(
tool_calls = getattr(ai, "tool_calls", None)
if not tool_calls:
# Force depth: if the model wants to stop early, nudge it to keep researching
# until it has done at least min_steps (still bounded by the wall-clock deadline).
if steps_used < min_steps and time.time() < deadline_ts:
messages.append(HumanMessage(content=DEEPEN_NUDGE))
reasoning_trace.append(f"[nudge] deepen research ({steps_used}/{min_steps} steps)")
# Force depth: if the model tries to finalize before the TIME floor (or step floor),
# inject a rotating directive nudge so it keeps doing NEW research. Bounded by deadline.
elapsed = time.time() - start
if (elapsed < min_seconds or steps_used < min_steps) and time.time() < deadline_ts:
nudge = DEEPEN_NUDGES[nudge_count % len(DEEPEN_NUDGES)]
nudge_count += 1
messages.append(HumanMessage(content=nudge))
reasoning_trace.append(
f"[nudge #{nudge_count}] {elapsed/60:.0f}/{min_seconds/60:.0f}min elapsed, step {steps_used}"
)
continue
if ai.content:
reasoning_trace.append(f"[note] {str(ai.content)[:200]}")
@@ -241,7 +259,9 @@ def run_agent(
break
for tc in tool_calls:
name, args = tc["name"], tc.get("args", {}) or {}
# gpt-oss can leak harmony channel tokens into the tool name (e.g. "get_bars<|channel|>")
name = tc["name"].split("<|")[0].strip()
args = tc.get("args", {}) or {}
tool = tools_by_name.get(name)
try:
result = tool.invoke(args) if tool else f"ERROR: unknown tool {name}"