// Typed reporting for model-facing stdlib caps. Pure text helpers stay pure;
// the owner that puts bounded content into an agent prompt calls this module.
import { agent_emit_event } from "std/agent/state"
import { truncate_text } from "std/text"
/**
* Emit exact source-loss metadata for a model-facing stdlib cap.
*
* @effects: [host]
* @errors: []
* @api_stability: experimental
*/
pub fn agent_report_truncation(
agent: HarnessAgent,
original: any,
retained: any,
detail: string,
) -> nil {
const source = to_string(original ?? "")
const kept = to_string(retained ?? "")
const dropped_bytes = bytes_len(bytes_from_string(source)) - bytes_len(bytes_from_string(kept))
if dropped_bytes <= 0 {
return nil
}
const session_id = agent.current_id()
// Pure projection helpers can be evaluated before a session exists. The
// model-facing owners run inside a session and therefore have an event sink.
if type_of(session_id) != "string" || session_id == "" {
return nil
}
let _ = agent_emit_event(
agent,
session_id,
"boundary_failure",
{
boundary: "agent_prompt_content",
kind: "truncated",
detail: detail,
dropped_count: 1,
dropped_bytes: dropped_bytes,
},
)
return nil
}
/**
* Truncate text and emit a typed boundary event when source content is lost.
*
* @effects: [host]
* @errors: []
* @api_stability: experimental
*/
pub fn agent_truncate_prompt_text(
agent: HarnessAgent,
text: any,
limit: int,
detail: string,
) -> string {
const value = to_string(text ?? "")
const truncated = truncate_text(value, limit)
if len(value) > limit {
let _ = agent_report_truncation(agent, value, substring(value, 0, limit), detail)
}
return truncated
}
/**
* Bound one command-output category before it enters an agent prompt.
*
* @effects: [host]
* @errors: []
* @api_stability: experimental
*/
pub fn prompt_cap(agent: HarnessAgent, text: any, limit: int, kind: string) -> string {
return agent_truncate_prompt_text(agent, text, limit, "command " + kind + " truncated")
}