Add ntro timing utility and integrate into agent loop
This commit is contained in:
parent
d4ec96ff62
commit
7bda512be6
12
scripts/ntro.py
Normal file
12
scripts/ntro.py
Normal file
@ -0,0 +1,12 @@
|
||||
import time
|
||||
|
||||
def start():
|
||||
return {"_start": time.perf_counter_ns()}
|
||||
|
||||
def end(stamp):
|
||||
elapsed_ns = time.perf_counter_ns() - stamp["_start"]
|
||||
elapsed_ms = elapsed_ns / 1_000_000
|
||||
print(f"[ntropy] {elapsed_ms:.2f}ms")
|
||||
stamp["_start"] = time.perf_counter_ns()
|
||||
return elapsed_ms
|
||||
|
||||
129
tui/agent.py
Normal file
129
tui/agent.py
Normal file
@ -0,0 +1,129 @@
|
||||
# agent.py — Agent loop dan tool execution.
|
||||
# submit() adalah entry point: membaca input buffer, mengirim ke LLM,
|
||||
# memproses tool calls, dan menampilkan hasil di log.
|
||||
|
||||
import json
|
||||
from datetime import datetime
|
||||
from .render import draw
|
||||
from scripts import ntro
|
||||
|
||||
|
||||
def log(app, role, text):
|
||||
# Simpan item ke app.log untuk di-render oleh render.py
|
||||
app.log.append({
|
||||
"role": role,
|
||||
"text": text,
|
||||
"time": datetime.now().strftime("%H:%M"),
|
||||
})
|
||||
|
||||
|
||||
def submit(app, stdscr):
|
||||
# Kirim query dari input buffer ke LLM.
|
||||
# Loop sampai LLM mengembalikan final answer (tanpa tool_calls)
|
||||
# atau mencapai max_iterations.
|
||||
|
||||
query = "\n".join(app.input_buffer).strip()
|
||||
if not query:
|
||||
return
|
||||
|
||||
log(app, "user", query)
|
||||
# Reset input buffer
|
||||
app.input_buffer = [""]
|
||||
app.input_line = 0
|
||||
app.input_col = 0
|
||||
app.scroll = 999999 # scroll ke paling bawah
|
||||
app.processing = True
|
||||
draw(app, stdscr)
|
||||
stdscr.refresh()
|
||||
|
||||
app.messages.append({"role": "user", "content": query})
|
||||
|
||||
stamp = ntro.start()
|
||||
|
||||
for step in range(app.agent_max_iterations):
|
||||
stamp_step = ntro.start()
|
||||
log(app, "system", f" step {step + 1} \u2014 LLM...")
|
||||
app.scroll = 999999
|
||||
draw(app, stdscr)
|
||||
stdscr.refresh()
|
||||
|
||||
response = app.llm.chat(app.messages, tools=app.TOOLS)
|
||||
|
||||
# Hapus "step N — LLM..." log, ganti dengan hasil aktual
|
||||
app.log.pop()
|
||||
|
||||
if response.tool_calls:
|
||||
# LLM meminta menjalankan tool(s)
|
||||
amsg = {
|
||||
"role": "assistant",
|
||||
"content": response.content,
|
||||
"tool_calls": response.tool_calls,
|
||||
}
|
||||
app.messages.append(amsg)
|
||||
if response.content and response.content.strip():
|
||||
log(app, "ai", response.content)
|
||||
app.scroll = 999999
|
||||
draw(app, stdscr)
|
||||
stdscr.refresh()
|
||||
for tc in response.tool_calls:
|
||||
tname = tc["function"]["name"]
|
||||
log(app, "system", f" \u2192 {tname}")
|
||||
app.scroll = 999999
|
||||
draw(app, stdscr)
|
||||
stdscr.refresh()
|
||||
execute_tool(app, tc)
|
||||
else:
|
||||
# Final answer — tidak ada tool_calls
|
||||
if response.content:
|
||||
app.messages.append({
|
||||
"role": "assistant",
|
||||
"content": response.content,
|
||||
})
|
||||
log(app, "ai", response.content)
|
||||
log(app, "sep", "")
|
||||
app.processing = False
|
||||
app.scroll = 999999
|
||||
draw(app, stdscr)
|
||||
stdscr.refresh()
|
||||
ntro.end(stamp)
|
||||
return
|
||||
ntro.end(stamp_step)
|
||||
|
||||
# Timeout — max iterations tercapai tanpa final answer
|
||||
log(app, "error", "Max iterations reached without final answer.")
|
||||
app.messages.append({"role": "assistant",
|
||||
"content": "Max iterations reached without final answer."})
|
||||
app.processing = False
|
||||
ntro.end(stamp)
|
||||
|
||||
|
||||
def execute_tool(app, tool_call):
|
||||
# Dispatch tool_call ke handler yang terdaftar di TOOL_HANDLERS.
|
||||
# search_code dan git_operation butuh penanganan argumen khusus.
|
||||
tname = tool_call["function"]["name"]
|
||||
targs = json.loads(tool_call["function"]["arguments"])
|
||||
handler = app.TOOL_HANDLERS.get(tname)
|
||||
|
||||
if not handler:
|
||||
result = f"Tool {tname} not found"
|
||||
else:
|
||||
try:
|
||||
if tname == "search_code":
|
||||
result = handler(
|
||||
pattern=targs["pattern"],
|
||||
search_type=targs["search_type"],
|
||||
path=targs.get("path", "."),
|
||||
)
|
||||
elif tname == "git_operation":
|
||||
result = handler(args=targs["args"])
|
||||
else:
|
||||
result = handler(**targs)
|
||||
except Exception as e:
|
||||
result = f"Error executing tool: {str(e)}"
|
||||
|
||||
# Hasil tool disimpan ke messages agar bisa dikirim balik ke LLM
|
||||
app.messages.append({
|
||||
"role": "tool",
|
||||
"tool_call_id": tool_call["id"],
|
||||
"content": str(result),
|
||||
})
|
||||
Loading…
Reference in New Issue
Block a user