///|
const ONE_M_CONTEXT_MARKER = "[1M]"
///|
priv struct ModelMapping {
haiku_model : String?
sonnet_model : String?
opus_model : String?
default_model : String?
}
///|
fn ModelMapping::new(
haiku_model? : String? = None,
sonnet_model? : String? = None,
opus_model? : String? = None,
default_model? : String? = None,
) -> ModelMapping {
{
haiku_model: clean_model_mapping_value(haiku_model),
sonnet_model: clean_model_mapping_value(sonnet_model),
opus_model: clean_model_mapping_value(opus_model),
default_model: clean_model_mapping_value(default_model),
}
}
///|
fn ModelMapping::has_mapping(self : ModelMapping) -> Bool {
self.haiku_model is Some(_) ||
self.sonnet_model is Some(_) ||
self.opus_model is Some(_) ||
self.default_model is Some(_)
}
///|
fn ModelMapping::map_model(
self : ModelMapping,
original_model : String,
) -> String {
let model_lower = original_model.to_lower()
if model_lower.contains("haiku") {
if self.haiku_model is Some(model) {
return model
}
}
if model_lower.contains("opus") {
if self.opus_model is Some(model) {
return model
}
}
if model_lower.contains("sonnet") {
if self.sonnet_model is Some(model) {
return model
}
}
match self.default_model {
Some(model) => model
None => original_model
}
}
///|
fn ModelMapping::to_json(self : ModelMapping) -> Json {
{
"haikuModel": optional_model_mapping_string_json(self.haiku_model),
"sonnetModel": optional_model_mapping_string_json(self.sonnet_model),
"opusModel": optional_model_mapping_string_json(self.opus_model),
"defaultModel": optional_model_mapping_string_json(self.default_model),
}.to_json()
}
///|
fn ProviderRouteTarget::map_model_for_upstream(
self : ProviderRouteTarget,
original_model : String,
) -> String {
let mapped = match self.model_mapping {
Some(mapping) if mapping.has_mapping() => mapping.map_model(original_model)
_ => original_model
}
if self.is_github_copilot_upstream() {
match copilot_normalize_to_upstream_id(mapped) {
Some(normalized) => normalized
None => mapped
}
} else {
strip_one_m_suffix_for_upstream(mapped)
}
}
///|
fn strip_one_m_suffix_for_upstream(model : String) -> String {
let trimmed = model.trim_end().to_owned()
if trimmed.length() < ONE_M_CONTEXT_MARKER.length() {
return model
}
let start = trimmed.length() - ONE_M_CONTEXT_MARKER.length()
let suffix = trimmed[start:].to_owned()
if suffix.to_lower() == ONE_M_CONTEXT_MARKER.to_lower() {
trimmed[:start].to_owned().trim_end().to_owned()
} else {
model
}
}
///|
fn clean_model_mapping_value(value : String?) -> String? {
match value {
Some(value) => {
let trimmed = value.trim().to_owned()
if trimmed.is_empty() {
None
} else {
Some(trimmed)
}
}
None => None
}
}
///|
fn optional_model_mapping_string_json(value : String?) -> Json {
match value {
Some(value) => Json::string(value)
None => Json::null()
}
}
///|
fn ProviderRouteTarget::is_github_copilot_upstream(
self : ProviderRouteTarget,
) -> Bool {
if self.provider_type == Some("github_copilot") {
return true
}
match self.base_url {
Some(base_url) => base_url.to_lower().contains("githubcopilot.com")
None => false
}
}
///|
pub fn copilot_normalize_to_upstream_id(client_id : String) -> String? {
let trimmed = client_id.trim().to_owned()
let lower = trimmed.to_lower()
if trimmed.length() < 8 || !lower.has_prefix("claude-") {
return None
}
let has_one_m_bracket = lower.has_suffix("[1m]")
if trimmed.contains(".") && !has_one_m_bracket {
return None
}
let (base, has_one_m_suffix) = copilot_split_one_m_suffix(trimmed)
let stripped = copilot_strip_trailing_date(base)
let mut candidate = match copilot_dashes_to_dot_in_last_version(stripped) {
Some(dotted) => dotted
None => {
if !has_one_m_suffix {
return None
}
stripped
}
}
if has_one_m_suffix {
candidate = "\{candidate}-1m"
}
if candidate == client_id {
None
} else {
Some(candidate)
}
}
///|
pub fn copilot_resolve_against_model_ids(
client_id : String,
model_ids : Array[String],
) -> String? {
let normalized = copilot_normalize_to_upstream_id(client_id)
let target = match normalized {
Some(value) => value
None => client_id
}
let target_lower = target.to_lower()
if model_ids.any(fn(model_id) { model_id.to_lower() == target_lower }) {
return match normalized {
Some(value) if value != client_id => Some(value)
_ => None
}
}
match copilot_family_fallback(target, model_ids) {
Some(fallback) if fallback.to_lower() != client_id.to_lower() =>
Some(fallback)
_ => None
}
}
///|
pub fn copilot_resolve_against_models_json(
client_id : String,
models_json : Json,
) -> String? {
copilot_resolve_against_model_ids(
client_id,
copilot_model_ids_from_models_json(models_json),
)
}
///|
pub fn copilot_model_ids_from_models_json(models_json : Json) -> Array[String] {
let items = match models_json {
Array(items) => items
Object(obj) =>
match obj.get("data") {
Some(Array(items)) => items
_ => []
}
_ => []
}
let ids : Array[String] = []
for item in items {
guard item is Object(model_obj) else { continue }
if !copilot_model_picker_enabled(model_obj) {
continue
}
match copilot_json_string_value(model_obj, "id") {
Some(id) if !id.trim().is_empty() => ids.push(id)
_ => ()
}
}
ids
}
///|
fn copilot_model_picker_enabled(model_obj : Map[String, Json]) -> Bool {
match model_obj.get("model_picker_enabled") {
Some(False) => false
Some(True) => true
_ => true
}
}
///|
fn copilot_json_string_value(obj : Map[String, Json], key : String) -> String? {
match obj.get(key) {
Some(String(value)) => Some(value)
_ => None
}
}
///|
fn copilot_model_vendor_from_models_json(
model_id : String,
models_json : Json,
) -> String? {
let target = model_id.to_lower()
match models_json {
Array(models) => {
for entry in models {
match copilot_model_vendor_from_entry(target, None, entry) {
Some(vendor) => return Some(vendor)
None => ()
}
}
None
}
Object(obj) => {
match obj.get("data") {
Some(Array(models)) =>
for entry in models {
match copilot_model_vendor_from_entry(target, None, entry) {
Some(vendor) => return Some(vendor)
None => ()
}
}
_ => ()
}
match obj.get("models") {
Some(models) =>
match copilot_model_vendor_from_models_json(model_id, models) {
Some(vendor) => return Some(vendor)
None => ()
}
None => ()
}
for key, entry in obj {
match copilot_model_vendor_from_entry(target, Some(key), entry) {
Some(vendor) => return Some(vendor)
None => ()
}
}
None
}
_ => None
}
}
///|
fn copilot_model_vendor_from_entry(
target : String,
fallback_id : String?,
entry : Json,
) -> String? {
guard entry is Object(obj) else { return None }
let id = match copilot_json_string_value(obj, "id") {
Some(value) => value
None =>
match copilot_json_string_value(obj, "model") {
Some(value) => value
None => fallback_id.unwrap_or("")
}
}
if id.to_lower() != target {
return None
}
for key in ["vendor", "provider", "owned_by", "ownedBy", "category", "owner"] {
match copilot_json_string_value(obj, key) {
Some(value) if !value.trim().is_empty() => return Some(value)
_ => ()
}
}
None
}
///|
fn copilot_split_one_m_suffix(id : String) -> (String, Bool) {
let lower = id.to_lower()
if lower.has_suffix("[1m]") {
(id[:id.length() - 4].to_owned(), true)
} else if lower.has_suffix("-1m") {
(id[:id.length() - 3].to_owned(), true)
} else {
(id, false)
}
}
///|
fn copilot_strip_trailing_date(id : String) -> String {
let parts = id.split("-").collect()
if parts.length() < 2 {
return id
}
let last = parts[parts.length() - 1].to_owned()
if last.length() != 8 || !copilot_ascii_digits(last) {
return id
}
let kept : Array[String] = []
for index in 0..<(parts.length() - 1) {
kept.push(parts[index].to_owned())
}
kept.join("-")
}
///|
fn copilot_dashes_to_dot_in_last_version(id : String) -> String? {
let parts = id.split("-").collect()
if parts.length() < 3 {
return None
}
let last = parts[parts.length() - 1].to_owned()
let previous = parts[parts.length() - 2].to_owned()
if !copilot_ascii_digits(last) || !copilot_ascii_digits(previous) {
return None
}
let head : Array[String] = []
for index in 0..<(parts.length() - 1) {
head.push(parts[index].to_owned())
}
Some("\{head.join("-")}.\{last}")
}
///|
fn copilot_ascii_digits(value : String) -> Bool {
if value.is_empty() {
return false
}
for ch in value {
let code = ch.to_int()
if code < '0'.to_int() || code > '9'.to_int() {
return false
}
}
true
}
///|
fn copilot_family_fallback(
target : String,
model_ids : Array[String],
) -> String? {
guard copilot_detect_family(target) is Some(family) else { return None }
let want_one_m = target.to_lower().has_suffix("-1m")
if want_one_m {
match
copilot_pick_best_family_model(family, model_ids, require_one_m=true) {
Some(model) => return Some(model)
None => ()
}
}
copilot_pick_best_family_model(family, model_ids, require_one_m=false)
}
///|
fn copilot_pick_best_family_model(
family : String,
model_ids : Array[String],
require_one_m~ : Bool,
) -> String? {
let mut best : String? = None
let mut best_major = -1
let mut best_minor = -1
for model_id in model_ids {
let lower = model_id.to_lower()
if !lower.contains(family) || lower.has_suffix("-1m") != require_one_m {
continue
}
match copilot_extract_major_minor(model_id) {
Some((major, minor)) =>
if major > best_major || (major == best_major && minor > best_minor) {
best = Some(model_id)
best_major = major
best_minor = minor
}
None => ()
}
}
best
}
///|
fn copilot_detect_family(id : String) -> String? {
let lower = id.to_lower()
if lower.contains("haiku") {
Some("haiku")
} else if lower.contains("sonnet") {
Some("sonnet")
} else if lower.contains("opus") {
Some("opus")
} else {
None
}
}
///|
fn copilot_extract_major_minor(id : String) -> (Int, Int)? {
let lower = id.to_lower()
guard copilot_detect_family(lower) is Some(family) else { return None }
guard lower.find(family) is Some(index) else { return None }
let after_family = lower[index + family.length():].to_owned()
if !after_family.has_prefix("-") {
return None
}
let after_dash = after_family[1:].to_owned()
let segment = copilot_model_version_segment(after_dash)
let parts = segment.split(".").collect()
if parts.length() == 0 {
return None
}
let major = @string.parse_int(parts[0].to_owned(), base=10) catch {
_ => return None
}
let minor = if parts.length() > 1 {
@string.parse_int(parts[1].to_owned(), base=10) catch {
_ => return None
}
} else {
0
}
Some((major, minor))
}
///|
fn copilot_model_version_segment(value : String) -> String {
let mut end = value.length()
for separator in ["-", "[", " "] {
match value.find(separator) {
Some(index) if index < end => end = index
_ => ()
}
}
value[:end].to_owned()
}