harn-stdlib 0.10.126

Embedded Harn standard library source catalog
Documentation
import { agent_emit_event } from "std/agent/state"

/**
 * Purpose labels: a plain-language heading the agent writes for the run of
 * tool calls it is about to make, so a reader sees "Searching for GitHub
 * issues" instead of eleven unexplained tool rows.
 *
 * The label is declared by the model in the same turn that proposes the
 * calls, so it costs no extra model call. This module owns the declaration
 * grammar, the normalization rules, and the typed event; it never decides
 * whether a call runs. Extraction is pure string work on text the loop is
 * already holding, and the emit is fire-and-forget, so a label can never
 * gate, reorder, or delay dispatch.
 */
/**
 * Where the declaration instruction is delivered. A per-turn declaration is a
 * per-turn instruction, and the seam it is delivered at decides whether the
 * model acts on it at all.
 *
 * - `system`: once, in the system prompt. Cheapest, and empirically the
 *   weakest — a strong model reads it and narrates in prose anyway.
 * - `nudge`: injected into every turn, so it sits next to the work.
 * - `prefill`: the assistant turn is started at `<purpose>`, so the model is
 *   continuing a heading rather than choosing to write one.
 */
pub type PurposeLabelDelivery = "system" | "nudge" | "prefill"

/** Caller-facing options for declared purpose labels. */
pub type PurposeLabelOptions = {enabled?: bool, max_chars?: int, delivery?: PurposeLabelDelivery}

/** Normalized purpose-label policy. */
pub type PurposeLabelConfig = {enabled: bool, max_chars: int, delivery: PurposeLabelDelivery}

/** The literal an assistant turn is started at under `prefill` delivery. */
pub const PURPOSE_LABEL_PREFILL: string = "<purpose>"

/** One turn's declaration, with the declaration removed from the prose. */
pub type PurposeLabelExtraction = {label: string, text: string, declared: bool}

/**
 * The declaration grammar. A tag rather than a structured field because the
 * native tool-call channel carries calls out of band: under native tool
 * calling the assistant text is still prose, so a tag is the one spelling
 * that survives every tool format.
 */
pub const PURPOSE_LABEL_PATTERN: string = "<purpose>(.*?)</purpose>"

/**
 * The same declaration with its opening tag already spent. Anchored to the
 * start so it can only claim a heading the harness itself opened, never a
 * stray `</purpose>` later in prose.
 */
pub const PURPOSE_LABEL_ORPHAN_PATTERN: string = "^\\s*([^<]*?)</purpose>"

const PURPOSE_LABEL_FLAGS: string = "is"

const PURPOSE_LABEL_DEFAULT_MAX_CHARS: int = 64

/**
 * Normalize the `purpose_labels` agent-loop option. Default off, and a bool
 * is shorthand for `{enabled: bool}`.
 *
 * @effects: []
 * @errors: [agent_loop]
 * @api_stability: experimental
 */
pub fn agent_purpose_label_config(value: any = nil) -> PurposeLabelConfig {
  const defaults: PurposeLabelConfig = {
    enabled: false,
    max_chars: PURPOSE_LABEL_DEFAULT_MAX_CHARS,
    delivery: "system",
  }
  if value == nil {
    return defaults
  }
  if type_of(value) == "bool" {
    return defaults + {enabled: value}
  }
  if type_of(value) != "dict" {
    throw "agent_loop: purpose_labels must be a bool, dict, or nil; got " + type_of(value)
  }
  const enabled = value?.enabled
  if enabled != nil && type_of(enabled) != "bool" {
    throw "agent_loop: purpose_labels.enabled must be a bool; got " + type_of(enabled)
  }
  const max_chars = value?.max_chars
  if max_chars != nil && (type_of(max_chars) != "int" || max_chars < 8) {
    throw "agent_loop: purpose_labels.max_chars must be an int >= 8; got " + type_of(max_chars)
  }
  const delivery = value?.delivery
  if delivery != nil && !contains(["system", "nudge", "prefill"], delivery) {
    throw "agent_loop: purpose_labels.delivery must be system, nudge, or prefill; got "
      + to_string(delivery)
  }
  return {
    enabled: enabled ?? true,
    max_chars: max_chars ?? defaults.max_chars,
    delivery: delivery ?? defaults.delivery,
  }
}

/**
 * The instruction as a per-turn nudge, or "" when this delivery does not use
 * one. Same sentence as the system fragment; only the seam differs, so the two
 * rungs stay comparable.
 *
 * @effects: []
 * @errors: []
 * @api_stability: experimental
 */
pub fn agent_purpose_label_turn_nudge(config: PurposeLabelConfig) -> string {
  if !config.enabled || config.delivery != "nudge" {
    return ""
  }
  return __purpose_label_instruction(config)
}

/**
 * The literal to start the assistant turn at, or "" when this delivery does
 * not prefill.
 *
 * @effects: []
 * @errors: []
 * @api_stability: experimental
 */
pub fn agent_purpose_label_prefill(config: PurposeLabelConfig) -> string {
  if !config.enabled || config.delivery != "prefill" {
    return ""
  }
  return PURPOSE_LABEL_PREFILL
}

/**
 * The instruction appended to the system prompt when labels are on. Kept
 * here so the declaration grammar and the sentence that teaches it cannot
 * drift apart.
 *
 * `prefill` carries it too. A prefilled `<purpose>` opener is a seam, not a
 * teaching: measured without the instruction, the model fired on 5 of 8 turns
 * but simply continued its ordinary narration past the tag ("I'll help you
 * understand what the stdlib module does and check..."), so the rung looked
 * compliant while producing no heading. Prefill positions the declaration;
 * only the instruction says what belongs there.
 *
 * @effects: []
 * @errors: []
 * @api_stability: experimental
 */
pub fn agent_purpose_label_prompt_fragment(config: PurposeLabelConfig) -> string {
  if !config.enabled || !contains(["system", "prefill"], config.delivery) {
    return ""
  }
  return __purpose_label_instruction(config)
}

/**
 * The one wording, shared by every delivery so the seams stay comparable.
 *
 * Phrased as a requirement with the tag first. An earlier wording that led
 * with prose and hedged ("write it only when the purpose changes") was
 * reliably ignored: the model narrated its intent in plain prose and never
 * reached for the tag.
 *
 * @effects: []
 * @errors: []
 */
fn __purpose_label_instruction(config: PurposeLabelConfig) -> string {
  return "PURPOSE HEADINGS. Every message in which you call tools MUST begin "
    + "with a purpose heading on its own first line, in exactly this form:\n"
    + "<purpose>Searching for GitHub issues</purpose>\n"
    + "Write it before anything else in the message, every time you call a "
    + "tool. Say the purpose of the batch in plain language a reader who does "
    + "not know this codebase would understand, under "
    + to_string(config.max_chars)
    + " characters, and name the goal rather than the tools. When the purpose "
    + "is unchanged from your last one, repeat it verbatim. It is a heading "
    + "for the reader and never changes what you do."
}

/**
 * Clamp one declared label to a renderable single line.
 *
 * @effects: []
 * @errors: []
 * @api_stability: experimental
 */
pub fn agent_purpose_label_normalize(raw: any, max_chars: int) -> string {
  if type_of(raw) != "string" {
    return ""
  }
  const collapsed = trim(regex_replace("\\s+", " ", raw))
  if collapsed == "" {
    return ""
  }
  if collapsed.count <= max_chars {
    return collapsed
  }
  // Clip on a word boundary so the heading stays readable, falling back to a
  // hard cut when the first word is already longer than the budget.
  let kept = ""
  for word in split(collapsed, " ") {
    const candidate = if kept == "" {
      word
    } else {
      kept + " " + word
    }
    if candidate.count > max_chars {
      break
    }
    kept = candidate
  }
  if kept == "" {
    kept = collapsed[0:max_chars]
  }
  return trim(kept) + "..."
}

/**
 * Pull the declaration out of one turn's raw text and return the prose with
 * every declaration removed. A turn with no declaration is the normal case
 * and returns `declared: false` with the text untouched.
 *
 * @effects: []
 * @errors: []
 * @api_stability: experimental
 */
pub fn agent_purpose_label_extract(
  config: PurposeLabelConfig,
  raw_text: any,
) -> PurposeLabelExtraction {
  const text = if type_of(raw_text) == "string" {
    raw_text
  } else {
    ""
  }
  if !config.enabled || text == "" {
    return {label: "", text: text, declared: false}
  }
  // `regex_captures` returns a LIST of capture records and an EMPTY list on no
  // match — never nil. A nil check here would make extraction silently inert.
  let captures = regex_captures(PURPOSE_LABEL_PATTERN, text, PURPOSE_LABEL_FLAGS)
  let pattern = PURPOSE_LABEL_PATTERN
  if type_of(captures) == "list" && captures.count == 0 && config.delivery == "prefill" {
    // The harness wrote the opening tag itself, so the provider returns only
    // the continuation: a heading and a closing tag with no opener. Reading
    // that as "no declaration" would make the whole prefill rung measure zero
    // while looking like model non-compliance. Gated on the delivery that
    // actually prefills, because the anchored pattern would otherwise promote
    // any leading prose before a stray `</purpose>` into a heading.
    pattern = PURPOSE_LABEL_ORPHAN_PATTERN
    captures = regex_captures(pattern, text, PURPOSE_LABEL_FLAGS)
  }
  if type_of(captures) != "list" || captures.count == 0 {
    return {label: "", text: text, declared: false}
  }
  const groups = captures[0]?.groups ?? []
  const first = if type_of(groups) == "list" && groups.count > 0 {
    groups[0]
  } else {
    ""
  }
  const label = agent_purpose_label_normalize(first, config.max_chars)
  // Strip every declaration, not just the captured one: a turn that wrote two
  // must not leave markup in the rendered prose.
  const stripped = trim(regex_replace(pattern, "", text, PURPOSE_LABEL_FLAGS))
  return {label: label, text: stripped, declared: label != ""}
}

/**
 * Emit one purpose label. Best-effort by construction: a label is
 * presentation metadata, so a failure to publish one must never surface as a
 * turn failure.
 *
 * @effects: [agent]
 * @errors: []
 * @api_stability: experimental
 */
pub fn agent_purpose_label_emit(
  agent: HarnessAgent,
  session_id: any,
  label: string,
  iteration: any = nil,
  tool_call_count: any = nil,
) -> nil {
  if trim(label) == "" {
    return nil
  }
  let _ = try {
    agent_emit_event(
      agent,
      session_id,
      "purpose_label",
      {
        label: label,
        source: "declared",
        iteration: iteration,
        tool_call_ids: [],
        tool_call_count: tool_call_count,
      },
    )
  }
  return nil
}