import { agent_session_inject_feedback } from "std/agent/state"
fn __default_done_sentinel(opts) {
return opts?.done_sentinel
}
fn __sentinel_hit(text, sentinel, parsed_done_marker) {
if sentinel == nil {
return false
}
if parsed_done_marker != nil && parsed_done_marker != "" {
return contains(parsed_done_marker, sentinel)
}
return contains(text, sentinel)
}
fn __dispatch_results_list(dispatch) {
if dispatch == nil {
return []
}
if type_of(dispatch) == "list" {
return dispatch
}
return dispatch?.results ?? []
}
fn __tool_result_ok(result) {
if result?.ok != nil {
return result.ok ? true : false
}
if result?.success != nil {
return result.success ? true : false
}
let status = result?.status ?? ""
return status == "ok" || status == "success"
}
fn __tool_result_name(result) {
return result?.tool_name ?? result?.name ?? ""
}
fn __tool_names_by_status(dispatch, want_ok) {
let results = __dispatch_results_list(dispatch)
var names = []
for result in results {
let name = __tool_result_name(result)
if name != "" && __tool_result_ok(result) == want_ok {
names = names.push(name)
}
}
return names
}
fn __post_turn_callback_verdict(opts, payload) {
let cb = opts?.post_turn_callback
if cb == nil {
return {kind: "none"}
}
let verdict = cb(payload)
return __interpret_verdict(verdict)
}
fn __interpret_verdict(verdict) {
if verdict == nil || verdict == "" {
return {kind: "none"}
}
if type_of(verdict) == "bool" {
return if verdict {
{kind: "stop"}
} else {
{kind: "none"}
}
}
if type_of(verdict) == "string" {
return {kind: "inject", message: verdict}
}
if type_of(verdict) == "dict" {
let stop = verdict?.stop ?? false
let base_llm_options = if type_of(verdict?.llm_options) == "dict" {
verdict.llm_options
} else {
{}
}
let llm_options = if verdict?.prefill != nil && verdict?.prefill != "" {
base_llm_options + {prefill: verdict?.prefill}
} else {
verdict?.llm_options
}
return {
kind: "rich",
stop: stop,
message: verdict?.message,
next_options: verdict?.next_options,
llm_options: llm_options,
}
}
return {kind: "none"}
}
fn __successful_tool_names(dispatch) {
return __tool_names_by_status(dispatch, true)
}
fn __rejected_tool_names(dispatch) {
return __tool_names_by_status(dispatch, false)
}
fn __stop_after_successful_tools(opts, dispatch) {
let names = opts?.stop_after_successful_tools
if names == nil || len(names) == 0 {
return false
}
let successful = __successful_tool_names(dispatch)
for required in names {
if contains(successful, required) {
return true
}
}
return false
}
fn __native_tool_text_completion(opts, has_tool_calls, text) {
if !(opts?.loop_until_done ?? false) || opts?.daemon {
return false
}
if opts?.tool_format != "native" || opts?.tools == nil {
return false
}
if __default_done_sentinel(opts) != nil {
return false
}
if has_tool_calls {
return false
}
return trim(text) != ""
}
fn __post_turn_verdict_result(session, opts, verdict) {
if verdict.kind == "stop" {
return {kind: "break", stop_reason: "post_turn_stop", needs_verify: opts?.verify_completion != nil}
}
if verdict.kind == "inject" {
agent_session_inject_feedback(session.session_id, "post_turn", verdict.message)
return {kind: "continue"}
}
if verdict.kind != "rich" {
return nil
}
if verdict.message != nil {
agent_session_inject_feedback(session.session_id, "post_turn", verdict.message)
}
if verdict.stop {
return {
kind: "break",
stop_reason: "post_turn_stop",
needs_verify: opts?.verify_completion != nil,
next_options: verdict?.next_options,
llm_options: verdict?.llm_options,
}
}
if verdict.message != nil || verdict?.next_options != nil || verdict?.llm_options != nil {
return {kind: "continue", next_options: verdict?.next_options, llm_options: verdict?.llm_options}
}
return nil
}
/** agent_extract_tool_calls. */
pub fn agent_extract_tool_calls(llm_result, opts) {
if len(llm_result?.tool_calls ?? []) > 0 {
return llm_result.tool_calls
}
if opts?.tools == nil {
return []
}
let parsed = agent_parse_tool_calls(llm_result?.text ?? "", opts.tools)
return parsed?.calls ?? []
}
/** agent_compute_post_turn. */
pub fn agent_compute_post_turn(session, llm_result, dispatch, opts, iteration) {
let sentinel = __default_done_sentinel(opts)
let text = llm_result?.text ?? ""
let sentinel_text = llm_result?.raw_text ?? text
let parsed_done_marker = llm_result?.parsed_done_marker
let dispatch_results = __dispatch_results_list(dispatch)
let successful_tool_names = __successful_tool_names(dispatch)
let rejected_tool_names = __rejected_tool_names(dispatch)
let has_tool_calls = len(llm_result?.tool_calls ?? []) > 0 || len(dispatch_results) > 0
if __sentinel_hit(sentinel_text, sentinel, parsed_done_marker) {
return {
kind: "break",
stop_reason: "sentinel",
needs_verify: opts?.done_judge != nil || opts?.verify_completion != nil
|| opts?.verify_completion_judge != nil,
}
}
if __stop_after_successful_tools(opts, dispatch) {
return {kind: "break", stop_reason: "natural", needs_verify: false}
}
let payload = {
session_id: session.session_id,
iteration: iteration,
has_tool_calls: has_tool_calls,
dispatch: dispatch,
tool_results: dispatch_results,
tool_count: len(dispatch_results),
successful_tool_names: successful_tool_names,
rejected_tool_names: rejected_tool_names,
session_successful_tools: opts?._session_successful_tools ?? successful_tool_names,
session_rejected_tools: opts?._session_rejected_tools ?? rejected_tool_names,
text: text,
visible_text: text,
}
let verdict = __post_turn_callback_verdict(opts, payload)
let verdict_result = __post_turn_verdict_result(session, opts, verdict)
if verdict_result != nil {
return verdict_result
}
if !has_tool_calls && trim(text) != "" && opts?.done_judge != nil {
return {kind: "break", stop_reason: "natural", needs_verify: true}
}
if __native_tool_text_completion(opts, has_tool_calls, text) {
return {
kind: "break",
stop_reason: "natural",
needs_verify: opts?.done_judge != nil || opts?.verify_completion != nil
|| opts?.verify_completion_judge != nil,
}
}
let loop_until_done = opts?.loop_until_done ?? false
let daemon = opts?.daemon ?? false
if !has_tool_calls && !loop_until_done && !daemon {
return {
kind: "break",
stop_reason: "natural",
needs_verify: opts?.done_judge != nil || opts?.verify_completion != nil,
}
}
return {kind: "continue"}
}