55} from "@t3tools/contracts" ;
66import * as Clock from "effect/Clock" ;
77import * as Context from "effect/Context" ;
8+ import * as DateTime from "effect/DateTime" ;
89import * as Effect from "effect/Effect" ;
910import * as FileSystem from "effect/FileSystem" ;
1011import * as Layer from "effect/Layer" ;
@@ -30,6 +31,7 @@ const MANIFEST_TTL_MS = 60 * 60 * 1000;
3031const MANIFEST_RETRY_MS = 5 * 60 * 1000 ;
3132
3233const FETCH_TIMEOUT_MS = 10_000 ;
34+ const MODEL_NEW_BADGE_DURATION_MS = 7 * 24 * 60 * 60 * 1000 ;
3335
3436const ManifestModelStatus = Schema . Literals ( [ "current" , "legacy" ] ) ;
3537
@@ -45,7 +47,8 @@ const ManifestProviderModel = Schema.Struct({
4547 subProvider : Schema . optional ( TrimmedNonEmptyString ) ,
4648 aliases : Schema . optional ( Schema . Array ( TrimmedNonEmptyString ) ) ,
4749 status : ManifestModelStatus ,
48- badge : Schema . optional ( Schema . Literal ( "new" ) ) ,
50+ /** ISO date or timestamp of the model's public release, as published by its provider. */
51+ releasedAt : Schema . optional ( Schema . String ) ,
4952 profile : Schema . optional ( TrimmedNonEmptyString ) ,
5053 adapter : Schema . optional ( Schema . Unknown ) ,
5154} ) ;
@@ -110,6 +113,7 @@ function manifestUpdatedAtMs(manifest: ModelManifestData): number {
110113export function resolveProviderCatalog (
111114 manifest : ModelManifestData ,
112115 driverKind : ProviderDriverKind ,
116+ nowMs = DateTime . toEpochMillis ( DateTime . nowUnsafe ( ) ) ,
113117) : ModelCatalog . ProviderCatalog | null {
114118 const catalog = manifest . providers ?. [ driverKind ] ;
115119 if ( ! catalog ) return null ;
@@ -123,13 +127,19 @@ export function resolveProviderCatalog(
123127 const profile = entry . profile ? catalog . profiles [ entry . profile ] : undefined ;
124128 if ( entry . profile && ! profile ) return null ;
125129
130+ const releasedAtMs = entry . releasedAt === undefined ? NaN : Date . parse ( entry . releasedAt ) ;
131+ const showNewBadge =
132+ entry . status === "current" &&
133+ nowMs >= releasedAtMs &&
134+ nowMs - releasedAtMs < MODEL_NEW_BADGE_DURATION_MS ;
135+
126136 models . push ( {
127137 slug : entry . slug ,
128138 name : entry . name ,
129139 ...( entry . shortName ? { shortName : entry . shortName } : { } ) ,
130140 ...( entry . subProvider ? { subProvider : entry . subProvider } : { } ) ,
131141 ...( entry . aliases ? { aliases : entry . aliases } : { } ) ,
132- ...( entry . badge ? { badge : entry . badge } : { } ) ,
142+ ...( showNewBadge ? { badge : "new" as const } : { } ) ,
133143 status : entry . status ,
134144 capabilities : profile ?. capabilities ?? null ,
135145 adapter : entry . adapter ,
@@ -267,10 +277,10 @@ export const layerModelCatalog = Layer.effect(
267277 Effect . gen ( function * ( ) {
268278 const manifest = yield * ModelManifest ;
269279 return ModelCatalog . ModelCatalog . of ( {
270- current : Effect . fn ( "ModelCatalog.current" ) ( function ( driverKind ) {
271- return manifest . current . pipe (
272- Effect . map ( ( data ) => resolveProviderCatalog ( data , driverKind ) ?? undefined ) ,
273- ) ;
280+ current : Effect . fn ( "ModelCatalog.current" ) ( function * ( driverKind : ProviderDriverKind ) {
281+ const data = yield * manifest . current ;
282+ const nowMs = yield * Clock . currentTimeMillis ;
283+ return resolveProviderCatalog ( data , driverKind , nowMs ) ?? undefined ;
274284 } ) ,
275285 bundled : ( driverKind ) =>
276286 resolveProviderCatalog ( BUNDLED_MODEL_MANIFEST , driverKind ) ?? undefined ,
0 commit comments