package com.example.aiapp /** * What a session with no model of its own is called, in the button and in the list it opens. * * One constant rather than a literal in each place, because the two have to agree: a picker whose * options cannot say every state its button can display is one you can leave and not get back to. * It is also the Claude CLI's own word for "whatever is configured", so choosing it is a request * the session can act on rather than a name this app made up. */ const val DEFAULT_MODEL = "default" /** * A model's name as a person reads it. * * Providers answer with their own full identifier -- Claude Code resolves `haiku` to * `claude-haiku-4-5-20251001` and reports that, which is the honest answer to "what is this session * using" and far too long for a button in a row that also has to hold Stop and Send. * * So the two ends that identify nothing are dropped and nothing else is: the vendor prefix, which * is the same on every model this app can show, and the release date, which distinguishes builds of * one model rather than one model from another. What is left is the part somebody chose -- * `haiku-4-5` -- and anything that does not look like that is returned untouched, since a name this * does not recognise is a name it has no business editing. * * A display decision, not a correction: the full name is what the session reports and what a reader * is shown when there is room for it. */ fun modelLabel(model: String?): String { val name = model?.takeIf { it.isNotBlank() } ?: return DEFAULT_MODEL return name.removePrefix("claude-").replace(DATED_SUFFIX, "") } /** A trailing `-YYYYMMDD`, which is how these identifiers carry their release date. */ private val DATED_SUFFIX = Regex("""-\d{8}$""")