harn-stdlib 0.8.39

Embedded Harn standard library source catalog
Documentation
// Thin Harn wrappers over host session-state primitives. These are CRUD only;
// no decision logic lives here. The agent loop holds the session dict locally
// and passes session_id into the host for any mutation.
/**
 * agent_session_init.
 *
 * @effects: [host]
 * @allocation: heap
 * @errors: []
 * @api_stability: experimental
 * @example: agent_session_init(message, system_prompt, opts)
 */
pub fn agent_session_init(message, system_prompt, opts) {
  return __host_agent_session_init(message, system_prompt, opts)
}

/**
 * agent_session_finalize.
 *
 * @effects: [host]
 * @allocation: heap
 * @errors: []
 * @api_stability: experimental
 * @example: agent_session_finalize(session_id, status)
 */
pub fn agent_session_finalize(session_id, status) {
  return __host_agent_session_finalize(session_id, status)
}

/**
 * agent_session_messages.
 *
 * @effects: [host]
 * @allocation: heap
 * @errors: []
 * @api_stability: experimental
 * @example: agent_session_messages(session_id)
 */
pub fn agent_session_messages(session_id) {
  return __host_agent_session_messages(session_id)
}

/**
 * agent_session_record_assistant.
 *
 * @effects: [host]
 * @allocation: heap
 * @errors: []
 * @api_stability: experimental
 * @example: agent_session_record_assistant(session_id, llm_result)
 */
pub fn agent_session_record_assistant(session_id, llm_result) {
  return __host_agent_session_record_assistant(session_id, llm_result)
}

/**
 * agent_session_record_tool_results.
 *
 * @effects: [host]
 * @allocation: heap
 * @errors: []
 * @api_stability: experimental
 * @example: agent_session_record_tool_results(session_id, dispatch)
 */
pub fn agent_session_record_tool_results(session_id, dispatch) {
  return __host_agent_session_record_tool_results(session_id, dispatch)
}

fn __agent_usage_int(value) {
  if type_of(value) == "int" {
    return value
  }
  if type_of(value) == "float" {
    return to_int(value)
  }
  return 0
}

/**
 * agent_reminder_providers_fire.
 *
 * @effects: [host]
 * @allocation: heap
 * @errors: []
 * @api_stability: experimental
 * @example: agent_reminder_providers_fire(session_id, "post_compact", payload, opts)
 */
pub fn agent_reminder_providers_fire(session_id, event, payload = nil, opts = nil) {
  return __host_agent_reminder_providers_fire(session_id, event, payload ?? {}, opts ?? {})
}

/**
 * agent_session_record_usage.
 *
 * @effects: [host]
 * @allocation: heap
 * @errors: []
 * @api_stability: experimental
 * @example: agent_session_record_usage(session_id, llm_result, opts, iteration)
 */
pub fn agent_session_record_usage(session_id, llm_result, opts = nil, iteration = 0) {
  let totals = __host_agent_session_record_usage(session_id, llm_result)
  let llm = llm_result?.llm ?? {}
  let input_tokens = __agent_usage_int(llm?.input_tokens ?? llm_result?.input_tokens)
  let output_tokens = __agent_usage_int(llm?.output_tokens ?? llm_result?.output_tokens)
  agent_reminder_providers_fire(
    session_id,
    "on_budget_threshold",
    {
      session: {id: session_id},
      iteration: iteration,
      input_tokens: input_tokens,
      output_tokens: output_tokens,
      tokens_used: totals?.tokens_used ?? 0,
      cost_usd: totals?.cost_usd ?? 0.0,
      provider: llm_result?.provider ?? opts?.provider ?? "",
      model: llm_result?.model ?? opts?.model ?? "",
    },
    opts ?? {},
  )
  return totals
}

/**
 * agent_session_drain_feedback.
 *
 * @effects: [host]
 * @allocation: heap
 * @errors: []
 * @api_stability: experimental
 * @example: agent_session_drain_feedback(session_id)
 */
pub fn agent_session_drain_feedback(session_id) {
  return __host_agent_session_drain_feedback(session_id)
}

/**
 * agent_session_drain_bridge_injections.
 *
 * @effects: [host]
 * @allocation: heap
 * @errors: []
 * @api_stability: experimental
 * @example: agent_session_drain_bridge_injections(session_id, "finish_step")
 */
pub fn agent_session_drain_bridge_injections(session_id, checkpoint) {
  return __host_agent_session_drain_bridge_injections(session_id, checkpoint)
}

/**
 * agent_session_push_bridge_injection.
 *
 * Push a system-reminder onto the session's host bridge queue. The
 * reminder is held until the agent loop's next eligible checkpoint
 * drains it (gated by `options.mode`). Returns the reminder id.
 *
 * `options` mirrors the ACP `session/remind` JSON-RPC params:
 * `{body, mode?, tags?, dedupe_key?, ttl_turns?, role_hint?,
 * propagate?, preserve_on_compact?}`.
 *
 * `mode` defaults to `"audit_only"`:
 *
 *   - `"interrupt_immediate"` — skip the next pending tool batch at the
 *     `pre_tool_dispatch` checkpoint.
 *   - `"finish_step"` — drained at every iteration boundary; the
 *     reminder renders into the model's next prompt.
 *   - `"audit_only"` — drained only at `loop_exit`. The reminder lands
 *     in the transcript audit but is NEVER rendered into a model
 *     prompt (no further LLM call runs after `loop_exit`). Use this
 *     for record-keeping; use `finish_step` if the model must see it
 *     before the loop terminates (harn#2212).
 *
 * @effects: [host]
 * @allocation: heap
 * @errors: [HARN-RMD-002]
 * @api_stability: experimental
 * @example: agent_session_push_bridge_injection(session_id, {body: "stop", mode: "interrupt_immediate"})
 */
pub fn agent_session_push_bridge_injection(session_id, options) {
  return __host_agent_session_push_bridge_injection(session_id, options)
}

/**
 * agent_session_totals.
 *
 * @effects: [host]
 * @allocation: heap
 * @errors: []
 * @api_stability: experimental
 * @example: agent_session_totals(session_id)
 */
pub fn agent_session_totals(session_id) {
  return __host_agent_session_totals(session_id)
}

/**
 * agent_session_inject_feedback.
 *
 * @effects: [host]
 * @allocation: heap
 * @errors: []
 * @api_stability: experimental
 * @example: agent_session_inject_feedback(session_id, kind, content)
 */
pub fn agent_session_inject_feedback(session_id, kind, content) {
  return __host_agent_session_inject_feedback(session_id, kind, content)
}

/**
 * agent_session_pop_last_assistant. Discard the trailing assistant
 * turn from a session transcript. Used by `agent_step_judge` in
 * `replace` (pop-and-regen) mode to remove a vetoed assistant
 * response before the next iteration regenerates. Returns true if a
 * turn was popped, false if the transcript was empty. Errors if the
 * trailing message is not an assistant turn — signals a call-site
 * discipline bug, not a runtime condition.
 *
 * @effects: [host]
 * @allocation: heap
 * @errors: [runtime]
 * @api_stability: experimental
 * @example: agent_session_pop_last_assistant(session_id)
 */
pub fn agent_session_pop_last_assistant(session_id) {
  return __host_agent_session_pop_last_assistant(session_id)
}

/**
 * agent_session_post_event. Post an event into a running session's
 * inbox from outside the loop (triggers, connectors, host
 * integrations). The next turn boundary — including the post-
 * compaction drain — surfaces the entry as feedback.
 *
 * @effects: [host]
 * @allocation: heap
 * @errors: []
 * @api_stability: experimental
 * @example: agent_session_post_event(session_id, kind, content, source)
 */
pub fn agent_session_post_event(session_id, kind, content, source = nil) {
  return __host_agent_session_post_event(session_id, kind, content, source)
}

/**
 * agent_session_apply_reminder_post_turn.
 *
 * @effects: [host]
 * @allocation: heap
 * @errors: []
 * @api_stability: experimental
 * @example: agent_session_apply_reminder_post_turn(session_id, turn)
 */
pub fn agent_session_apply_reminder_post_turn(session_id, turn = 0) {
  return __host_agent_session_apply_reminder_post_turn(session_id, turn)
}

/**
 * agent_session_set_active_skills.
 *
 * @effects: [host]
 * @allocation: heap
 * @errors: []
 * @api_stability: experimental
 * @example: agent_session_set_active_skills(session_id, skills)
 */
pub fn agent_session_set_active_skills(session_id, skills) {
  return __host_agent_session_set_active_skills(session_id, skills)
}

/**
 * agent_session_active_skills.
 *
 * @effects: [host]
 * @allocation: heap
 * @errors: []
 * @api_stability: experimental
 * @example: agent_session_active_skills(session_id)
 */
pub fn agent_session_active_skills(session_id) {
  return __host_agent_session_active_skills(session_id)
}

/**
 * agent_session_record_skill_event.
 *
 * @effects: [host]
 * @allocation: heap
 * @errors: []
 * @api_stability: experimental
 * @example: agent_session_record_skill_event(session_id, kind, metadata)
 */
pub fn agent_session_record_skill_event(session_id, kind, metadata) {
  return __host_agent_session_record_skill_event(session_id, kind, metadata)
}

/**
 * agent_session_claim_tool_format_internal.
 *
 * @effects: [host]
 * @allocation: heap
 * @errors: []
 * @api_stability: experimental
 * @example: agent_session_claim_tool_format_internal(session_id, tool_format)
 */
pub fn agent_session_claim_tool_format_internal(session_id, tool_format) {
  return __host_agent_session_claim_tool_format(session_id, tool_format)
}

/**
 * agent_emit_event.
 *
 * @effects: [host]
 * @allocation: heap
 * @errors: []
 * @api_stability: experimental
 * @example: agent_emit_event(session_id, event_type, payload)
 */
pub fn agent_emit_event(session_id, event_type, payload) {
  return __host_agent_emit_event(session_id, event_type, payload)
}

/**
 * agent_record_native_tool_fallback.
 *
 * @effects: [host]
 * @allocation: heap
 * @errors: []
 * @api_stability: experimental
 * @example: agent_record_native_tool_fallback(session_id, payload)
 */
pub fn agent_record_native_tool_fallback(session_id, payload) {
  return __host_agent_record_native_tool_fallback(session_id, payload)
}

/**
 * agent_record_compaction.
 *
 * @effects: [host]
 * @allocation: heap
 * @errors: []
 * @api_stability: experimental
 * @example: agent_record_compaction(session_id, payload)
 */
pub fn agent_record_compaction(session_id, payload) {
  return __host_agent_record_compaction(session_id, payload)
}

/**
 * agent_session_project_turn projects the session transcript through a
 * policy, appends a `transcript.projection` event into the raw
 * transcript, emits a typed `TranscriptProjected` agent event, and
 * returns the projected messages with metadata.
 *
 * The persisted message list is never mutated — projection only
 * controls what the next provider request will see. Supported policies:
 * "raw", "clean_tool_repair", "squash_failed_calls", "summary_prefix",
 * and "custom" (with a `projector` closure).
 *
 * @effects: [host]
 * @allocation: heap
 * @errors: []
 * @api_stability: experimental
 * @example: agent_session_project_turn(session_id, {policy: "clean_tool_repair"})
 */
pub fn agent_session_project_turn(session_id, options = nil) {
  return __host_agent_session_project_turn(session_id, options ?? {})
}