harn-stdlib 0.7.58

Embedded Harn standard library source catalog
Documentation
import {
  agent_session_active_skills,
  agent_session_messages,
  agent_session_record_skill_event,
  agent_session_set_active_skills,
} from "std/agent/state"

fn __skills_registry(opts) {
  let registry = opts?.skill_registry ?? opts?.skills
  if type_of(registry) == "list" {
    return {_type: "skill_registry", skills: registry}
  }
  return registry
}

fn __skills_entries(registry) {
  if registry == nil {
    return []
  }
  return registry?.skills ?? []
}

fn __skill_id(entry) {
  return entry?.id ?? entry?.name ?? ""
}

fn __skill_find(registry, id) {
  for entry in __skills_entries(registry) {
    if __skill_id(entry) == id {
      return entry
    }
  }
  return nil
}

fn __skill_ids(entries) {
  var ids = []
  for entry in entries {
    let id = __skill_id(entry)
    if id != "" {
      ids = ids.push(id)
    }
  }
  return ids
}

fn __tool_registry_has(registry, name) {
  if type_of(registry) != "dict" {
    return false
  }
  for tool_entry in registry?.tools ?? [] {
    if __tool_name(tool_entry) == name {
      return true
    }
  }
  return false
}

fn __with_load_skill_tool(session, opts) {
  let existing = opts?.tools
  let registry = if type_of(existing) == "dict" {
    existing
  } else {
    tool_registry()
  }
  if __tool_registry_has(registry, "load_skill") {
    return opts + {tools: registry}
  }
  let next_registry = tool_define(
    registry,
    "load_skill",
    "Load the full instructions for a skill from the active skill catalog",
    {
      parameters: {
        name: {type: "string", description: "Skill id from the catalog"},
        require_signature: {
          type: "boolean",
          description: "Reject the skill unless provenance shows a trusted signature",
          required: false,
        },
      },
      handler: { args -> load_skill(args + {session_id: session.session_id}) },
    },
  )
  return opts + {tools: next_registry}
}

fn __skills_same_ids(prev, next) {
  let prev_ids = __skill_ids(prev)
  let next_ids = __skill_ids(next)
  if len(prev_ids) != len(next_ids) {
    return false
  }
  for (index, id) in iter(next_ids).enumerate() {
    if prev_ids[index] != id {
      return false
    }
  }
  return true
}

fn __active_from_ids(registry, ids) {
  var active = []
  for item in ids {
    let id = item?.id ?? item?.name ?? item
    let entry = __skill_find(registry, id)
    if entry != nil {
      active = active.push(entry + {id: id})
    }
  }
  return active
}

fn __latest_user_text(session) {
  var latest = session?.task ?? ""
  for message in agent_session_messages(session.session_id) {
    if message?.role == "user" {
      latest = message?.content ?? latest
    }
  }
  return latest
}

fn __match_config(opts) {
  return opts?.skill_match ?? {}
}

fn __match_strategy(opts) {
  return __match_config(opts)?.strategy ?? "metadata"
}

fn __match_top_n(opts) {
  let value = __match_config(opts)?.top_n
  if type_of(value) == "int" && value > 0 {
    return value
  }
  return 1
}

fn __match_sticky(opts) {
  let value = __match_config(opts)?.sticky
  if type_of(value) == "bool" {
    return value
  }
  return true
}

fn __score_candidates(session, registry, opts, iteration) {
  return __host_skill_score(
    {task: __latest_user_text(session), working_files: opts?.working_files ?? [], iteration: iteration},
    registry,
    __match_config(opts),
  )?.scored
    ?? []
}

fn __top_active_from_scores(registry, scored, opts) {
  var active = []
  let top_n = __match_top_n(opts)
  let strategy = __match_strategy(opts)
  for candidate in scored {
    if len(active) >= top_n {
      break
    }
    let score = candidate?.score ?? 0.0
    if score <= 0.0 && strategy == "metadata" {
      continue
    }
    let id = candidate?.id ?? candidate?.name ?? ""
    let entry = __skill_find(registry, id)
    if entry != nil {
      active = active.push(entry + {id: id, score: score, trigger: candidate?.trigger ?? candidate?.reason ?? ""})
    }
  }
  return active
}

fn __record_matched(session, opts, iteration, scored) {
  agent_session_record_skill_event(
    session.session_id,
    "skill_matched",
    {
      strategy: __match_strategy(opts),
      iteration: iteration,
      reassess: iteration > 0,
      candidates: scored,
      working_files: opts?.working_files ?? [],
    },
  )
}

fn __record_deactivations(session, prev, next, iteration) {
  let next_ids = __skill_ids(next)
  for entry in prev {
    let id = __skill_id(entry)
    if id != "" && !contains(next_ids, id) {
      agent_session_record_skill_event(
        session.session_id,
        "skill_deactivated",
        {name: id, id: id, iteration: iteration},
      )
    }
  }
}

fn __record_activations(session, prev, next, iteration) {
  let prev_ids = __skill_ids(prev)
  for entry in next {
    let id = __skill_id(entry)
    if id == "" || contains(prev_ids, id) {
      continue
    }
    agent_session_record_skill_event(
      session.session_id,
      "skill_activated",
      {
        name: id,
        id: id,
        description: entry?.description ?? "",
        iteration: iteration,
        score: entry?.score ?? 0.0,
        trigger: entry?.trigger ?? "",
        allowed_tools: entry?.allowed_tools ?? [],
      },
    )
    if len(entry?.allowed_tools ?? []) > 0 {
      agent_session_record_skill_event(
        session.session_id,
        "skill_scope_tools",
        {name: id, id: id, allowed_tools: entry.allowed_tools},
      )
    }
  }
}

fn __allowed_union(active) {
  var allowed = []
  for active_entry in active {
    for allowed_entry in active_entry?.allowed_tools ?? [] {
      if !contains(allowed, allowed_entry) {
        allowed = allowed.push(allowed_entry)
      }
    }
  }
  return allowed
}

fn __tool_name(tool_entry) {
  return tool_entry?.name ?? tool_entry?.function?.name ?? ""
}

fn __tool_namespace(tool_entry) {
  return tool_entry?.namespace ?? tool_entry?.function?.namespace ?? ""
}

fn __allowed_matches_tool(entry, tool_entry) {
  if entry == "*" {
    return true
  }
  let name = __tool_name(tool_entry)
  if entry == name {
    return true
  }
  if starts_with(entry, "namespace:") {
    return substring(entry, len("namespace:")) == __tool_namespace(tool_entry)
  }
  return false
}

fn __skill_scoped_tools(opts, active) {
  let allowed = __allowed_union(active)
  if len(allowed) == 0 || contains(allowed, "*") {
    return opts?.tools
  }
  let registry = opts?.tools
  if type_of(registry) != "dict" {
    return registry
  }
  var kept = []
  for tool_entry in registry?.tools ?? [] {
    if __tool_name(tool_entry) == "load_skill" {
      kept = kept.push(tool_entry)
      continue
    }
    var keep = false
    for entry in allowed {
      if __allowed_matches_tool(entry, tool_entry) {
        keep = true
        break
      }
    }
    if keep {
      kept = kept.push(tool_entry)
    }
  }
  return registry + {tools: kept}
}

fn __opts_with_active_skills(opts, active) {
  let scoped_tools = __skill_scoped_tools(opts, active)
  var next = opts + {active_skills: active}
  if scoped_tools != nil {
    next = next + {tools: scoped_tools}
  }
  return next
}

/** agent_skills_match. */
pub fn agent_skills_match(session, opts, iteration) {
  let registry = __skills_registry(opts)
  if registry == nil || len(__skills_entries(registry)) == 0 {
    return opts
  }
  let tool_opts = __with_load_skill_tool(session, opts)
  let prev = __active_from_ids(registry, agent_session_active_skills(session.session_id) ?? [])
  if __match_sticky(opts) && len(prev) > 0 {
    return __opts_with_active_skills(tool_opts, prev)
  }
  let scored = __score_candidates(session, registry, tool_opts, iteration)
  __record_matched(session, tool_opts, iteration, scored)
  let active = __top_active_from_scores(registry, scored, tool_opts)
  if !__skills_same_ids(prev, active) {
    __record_deactivations(session, prev, active, iteration)
    __record_activations(session, prev, active, iteration)
    agent_session_set_active_skills(session.session_id, active)
  }
  return __opts_with_active_skills(tool_opts, active)
}