@ai-matrx/agents 0.59.270 → 0.59.272

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -641,6 +641,8 @@ interface RecordsQuery extends PromiseLike<PgResult> {
641
641
  nullsFirst?: boolean;
642
642
  }): RecordsQuery;
643
643
  maybeSingle(): PromiseLike<PgResult>;
644
+ /** Only the catalog stamp (`readModelCatalogStamp`) uses it. */
645
+ limit?(count: number): RecordsQuery;
644
646
  }
645
647
  interface ModelRecordsClient {
646
648
  schema(name: string): {
@@ -791,6 +793,12 @@ declare function readPublicModel(client: PublicModelClient, key: string): Promis
791
793
  } | null;
792
794
  error: string | null;
793
795
  }>;
796
+ /**
797
+ * THE catalog stamp: the newest `ai.model_definition.updated_at` (one row, one column) — the cheap read a
798
+ * tab makes to learn whether the catalog changed while it was not listening (catalog/changes.ts
799
+ * `followModelCatalogVisibility`). Null when the catalog is empty. Throws the database's error.
800
+ */
801
+ declare function readModelCatalogStamp(client: ModelRecordsClient): Promise<string | null>;
794
802
 
795
803
  /**
796
804
  * `@ai-matrx/agents/models` — `createModelCatalog`: the headless model catalog store.
@@ -1101,7 +1109,7 @@ interface LocalModel {
1101
1109
  /** Matrx 2's 1.48 id for a model seeded from its old list (metadata.desktop_id). */
1102
1110
  desktop_id?: string | null;
1103
1111
  maker_logo_file_id?: string | null;
1104
- /** The admin Catalogs kind (`catalogKindOf`): llm_model, whisper_model, tts_model_file, image_gen_model, video_gen_model, ner_model, wake_word_model, lora. */
1112
+ /** The admin Catalogs kind (`catalogKindOf`): llm_model, whisper_model, tts_model_file, image_gen_model, video_gen_model, ner_model, wake_word_model, lora, embedding_model, or unknown (no rule places it; `catalogKindVerdict` says why). */
1105
1113
  kind?: string;
1106
1114
  /** At least one variant is offered (Matrx 2 lists it). */
1107
1115
  offered?: boolean;
@@ -1837,8 +1845,12 @@ interface ReadModelCatalogOptions {
1837
1845
  appInstanceIds?: readonly string[];
1838
1846
  };
1839
1847
  }
1848
+ /** The kind of a model the catalog cannot place by its capabilities: shown loudly, never offered to a chat. */
1849
+ declare const UNKNOWN_MODEL_KIND: "unknown";
1840
1850
  /** The catalog kinds whose rows live in the unified catalog (ai.*): the admin Catalogs page's model kinds. */
1841
1851
  declare const MODEL_CATALOG_KINDS: ReadonlySet<string>;
1852
+ /** The interactions a text-in, text-out model answers a person in: only these make an llm_model. */
1853
+ declare const LLM_INTERACTIONS: ReadonlySet<string>;
1842
1854
  /** What `catalogKindOf` reads from a model (a CuratedModel or a LocalModel from `readModelCatalog` both fit). */
1843
1855
  interface CatalogKindInput {
1844
1856
  readonly variants: ReadonlyArray<{
@@ -1853,11 +1865,20 @@ interface CatalogKindInput {
1853
1865
  readonly shelf?: string | null;
1854
1866
  } | null;
1855
1867
  }
1868
+ /** A model's admin kind and, when it is `unknown`, why (one line, said on the admin page and in reader warnings). */
1869
+ interface CatalogKindVerdict {
1870
+ kind: string;
1871
+ reason: string | null;
1872
+ }
1856
1873
  /**
1857
- * THE admin Catalogs kind of a unified model: the kind of the old public.catalog_entries rows its variants
1858
- * carry (the list migration stamps them), when that is a model kind; else placed by what it does.
1859
- * `kindOfEntry` maps catalog_entries.id → kind.
1874
+ * THE admin Catalogs kind of a unified model, with the reason when it cannot be placed: the kind of the
1875
+ * old public.catalog_entries rows its variants carry (the list migration stamps them), when that is a
1876
+ * model kind; else placed by what it does (capabilities, never a name list). There is NO default: a model
1877
+ * is an llm_model only when it takes text, gives text and answers in a chat-like interaction
1878
+ * (LLM_INTERACTIONS); anything the rules cannot place is `unknown`, with the reason.
1860
1879
  */
1880
+ declare function catalogKindVerdict(m: CatalogKindInput, kindOfEntry: ReadonlyMap<string, string>): CatalogKindVerdict;
1881
+ /** THE admin Catalogs kind of a unified model (`catalogKindVerdict(...).kind`); `unknown` when it cannot be placed. */
1861
1882
  declare function catalogKindOf(m: CatalogKindInput, kindOfEntry: ReadonlyMap<string, string>): string;
1862
1883
  /** sha256 (hex) of the catalog's canonical JSON, its own `catalog_fingerprint` left out. Isomorphic (pure JS). */
1863
1884
  declare function catalogFingerprint(catalog: LocalModelCatalog): string;
@@ -2032,7 +2053,12 @@ declare function modelDisplayLabel(row: ModelLabelSource | null | undefined): st
2032
2053
  * `@ai-matrx/agents/models/react`). No surface keeps a model cache that misses the event.
2033
2054
  *
2034
2055
  * The hub lives on `globalThis` so two bundled copies of this module share one set of listeners.
2056
+ *
2057
+ * A tab that is not listening (the bus room not joined yet, or asleep) catches up when it comes to the
2058
+ * front: `followModelCatalogVisibility({ client })` reads the catalog stamp when the tab hides and again
2059
+ * when it shows or takes focus (throttled), and announces a change when the stamp moved.
2035
2060
  */
2061
+
2036
2062
  /** A `catalog_changed` payload: `{ catalog?: "models" | ..., change?, model_id? }`. */
2037
2063
  type ModelCatalogChangePayload = Record<string, unknown>;
2038
2064
  /** The bus client's subscribe call: `(action, handler) => unsubscribe` (the web's `registerDirectiveHandler`). */
@@ -2047,6 +2073,32 @@ declare function modelCatalogRevision(): number;
2047
2073
  declare function announceModelCatalogChanged(payload?: ModelCatalogChangePayload): void;
2048
2074
  /** Bind the host's bus client: every `catalog_changed` it delivers reaches every model reader. Returns the unbind. */
2049
2075
  declare function followModelCatalogChanges(subscribe: ModelCatalogDirectiveSubscribe): () => void;
2076
+ interface ModelCatalogVisibilityOptions {
2077
+ /** The client the stamp is read with (supabase-js fits as is). */
2078
+ client: ModelRecordsClient;
2079
+ /** At most one stamp read per this many ms when the tab shows / takes focus. Default 20 s. */
2080
+ minIntervalMs?: number;
2081
+ /** The page (tests pass a double); defaults to the global `document` / `window`. */
2082
+ page?: {
2083
+ document: Pick<Document, "visibilityState" | "addEventListener" | "removeEventListener">;
2084
+ window: Pick<Window, "addEventListener" | "removeEventListener">;
2085
+ };
2086
+ /** Where a failed stamp read is said. Default: console.error, tagged. */
2087
+ errorSink?: (event: {
2088
+ code: string;
2089
+ message: string;
2090
+ }) => void;
2091
+ now?: () => number;
2092
+ }
2093
+ /**
2094
+ * When the tab shows or takes focus, read the catalog stamp (one row) and, when it moved since the tab
2095
+ * last knew it, announce a model catalog change through the SAME door as the bus (every catalog re-reads
2096
+ * what it read; every reader following `onModelCatalogChanged` re-reads). The baseline is taken when the
2097
+ * tab hides (or at bind when it starts hidden), and refreshed by every announced change. Reads already in
2098
+ * flight are joined; shows/focuses within `minIntervalMs` share the last read. Returns the unbind. No-op
2099
+ * where there is no document (a server render, a worker).
2100
+ */
2101
+ declare function followModelCatalogVisibility(options: ModelCatalogVisibilityOptions): () => void;
2050
2102
 
2051
- export { CHAT_DEFAULT_MODEL_KNOB, CONTENT_TYPES, DEFAULT_CAPABILITIES, DEVICE_FILE_USABLE_STATES, DEVICE_OWN_FILE_USABLE_STATES, DEVICE_RULE_TWIN_FIXTURE, DEVICE_SERVED_SETTINGS_KEY, DEVICE_SERVED_VIA, DeviceModelUnavailableError, EMPTY_MODEL_RECORDS, EXCLUDED_REVIEW_STATES, FEATURE_BUCKETS, FEATURE_BUCKET_ORDER, FEATURE_KEYS, FILE_TYPE_QUANT, GgufError, INPUT_MODALITIES, INTERACTION_MODES, MAX_SUCCESSION_HOPS, MODEL_CATALOG_KINDS, MODEL_FAVORITE_ENTITY_TYPE, NEW_AGENT_DEFAULT_MODEL_KNOB, OUTPUT_MODALITIES, SERVICE_LABEL, SERVICE_LABEL_PLURAL, TOP_TIER_COST_RATING, TOP_TIER_LOCKED_TITLE, acceptsTextInstructions, announceModelCatalogChanged, availableOnDevices, blendedPrice, buildModelClassIndex, buildSuccessionIndex, catalogFingerprint, catalogForApp, catalogKeyColumn, catalogKindOf, cheapestAdequateModel, classConfigKey, collapseTiersByClass, costRatingTier, costRatingWord, createModelCatalog, createModelFavorites, createModelRecords, curatedList, displayOrderOf, favoriteIdsEqual, fetchCuratedModels, findNonCanonicalCapabilityValues, fitsMemory, fitsNeed, fitsThisComputer, followModelCatalogChanges, formatMemoryBytes, fromDiscovery, ggufEngine, ggufFacts, groupFeatures, hardwareClassesOf, hasCompatibleDecisionInteraction, isChatModelCapability, isContentType, isConversationalModelCapability, isDecisionModelCapability, isFeatureKey, isHelperGguf, isInteractionMode, isListedVariant, isLocalModelCatalog, isManagedAgentModelCapability, isModelCatalogChange, isProjectorName, isSupersedable, isTopTierRating, judgeHeaderFacts, mergeAuditRecordIntoCapabilities, missingShards, modelCatalogRevision, modelClassKnobFor, modelClassName, modelClassPinOf, modelDisplayLabel, modelsForSelectionPurpose, normalizeArch, normalizeModel, normalizeModels, normalizeOs, normalizePromptSettings, onModelCatalogChanged, orderCatalogGroups, orderCatalogModels, outputFormatControlKey, parseCapabilities, pickProjector, priceTierRating, quantFromName, rankVariants, readCuratedRows, readDeviceModelFiles, readGgufHeader, readModelCatalog, readModelIdentities, readPublicModel, reconcileModelFavoriteIds, reportModelDiagnostic, requireCanonicalCapabilities, requiredArtifactIds, requiredArtifacts, resetSuccessionLogForTests, resolveDeviceModel, resolveLiveModelId, resolveModelMapKnob, resolveNewAgentModelId, resolvePreferredModelChoice, resolveSuccessor, runtimesOnEngine, seesImages, selectActiveModels, selectActiveModelsReady, selectAllModelOptions, selectAllModels, selectAllModelsReady, selectDeprecatedModels, selectDeprecatedModelsReady, selectModelById, selectModelClassConfig, selectModelClassName, selectModelControls, selectModelDetailError, selectModelFetchType, selectModelFullyLoaded, selectModelIdentityById, selectModelIdentityLookupStatus, selectModelLabelById, selectModelLabelWithClass, selectModelNameById, selectModelOptions, selectVariant, serviceCountLabel, setModelDiagnosticsSink, shapeCuratedModels, shardFileName, shardName, speedRatingLabel, speedRatingWord, splitSetProblems, takesInput, toAuditRecord, toDeviceModelFile, validateModelSet, variantVerdict, withModelClass };
2052
- export type { AdminOffering, AdminPricingBand, ArtifactUse, AuditCapabilitiesRecord, AvailabilityVariant, CapabilitiesParseContext, CatalogKeyColumn, CatalogKindInput, CatalogModel, CatalogTier, CheapestAdequateOptions, CompatStatus, ContentType, CuratedCatalogClient, CuratedModel, CuratedPresentation, CuratedRows, CuratedVariant, DecidedBy, DeviceAvailability, DeviceGraphics, DeviceHardware, DeviceModelFile, DeviceModelResolution, DeviceServedSettings, DiscoveryAmbiguity, DiscoveryArtifact, DiscoveryMedia, DiscoveryResult, DiscoveryRuntime, DiscoverySource, DiscoveryVariant, FeatureBucket, FeatureBucketMeta, FeatureKey, FitCapabilities, GgufHeader, GgufRead, GgufTensor, GroupedFeatures, HardwareClass, HardwareClasses, HeaderFlag, HeaderJudgement, HeaderRefusal, Interaction, InteractionMode, LocalArtifact, LocalCatalogClient, LocalCatalogQuery, LocalCompatRow, LocalModel, LocalModelCatalog, LocalPresentation, LocalRuntime, LocalRuntimeBuild, LocalVariant, Modality, ModelCapabilities, ModelCatalog, ModelCatalogChangePayload, ModelCatalogClient, ModelCatalogConfig, ModelCatalogDirectiveSubscribe, ModelCatalogErrorSink, ModelCatalogPgError, ModelCatalogPgResult, ModelCatalogQuery, ModelCatalogState, ModelCatalogVariant, ModelCatalogVariantState, ModelClassConfig, ModelClassEntry, ModelClassIndex, ModelDiagnosticEntry, ModelDiagnosticsSink, ModelFavorites, ModelFavoritesCache, ModelFavoritesClient, ModelFavoritesConfig, ModelFavoritesErrorSink, ModelFavoritesState, ModelFetchScope, ModelFileHandle, ModelFit, ModelIdentityRow, ModelJson, ModelLabelSource, ModelNeed, ModelOfferingRow, ModelOption, ModelOptionWithLifecycle, ModelRecord, ModelRecordFetchType, ModelRecords, ModelRecordsClient, ModelRecordsConfig, ModelRecordsState, ModelSelectionPurpose, ModelSetEnv, ModelSetFacts, ModelSetValidation, NewAgentModel, NoSelection, OrderedLike, PreferredModelChoice, PreferredModelChoicePorts, PriceTier, PricedCatalogModel, PublicModelClient, RankOptions, RankedVariant, ReadModelCatalogOptions, SelectDevice, Selection, ShardName, SuccessionClient, SuccessionIndex, SuccessionNode, VariantDiscovery, VariantVerdict, Want };
2103
+ export { CHAT_DEFAULT_MODEL_KNOB, CONTENT_TYPES, DEFAULT_CAPABILITIES, DEVICE_FILE_USABLE_STATES, DEVICE_OWN_FILE_USABLE_STATES, DEVICE_RULE_TWIN_FIXTURE, DEVICE_SERVED_SETTINGS_KEY, DEVICE_SERVED_VIA, DeviceModelUnavailableError, EMPTY_MODEL_RECORDS, EXCLUDED_REVIEW_STATES, FEATURE_BUCKETS, FEATURE_BUCKET_ORDER, FEATURE_KEYS, FILE_TYPE_QUANT, GgufError, INPUT_MODALITIES, INTERACTION_MODES, LLM_INTERACTIONS, MAX_SUCCESSION_HOPS, MODEL_CATALOG_KINDS, MODEL_FAVORITE_ENTITY_TYPE, NEW_AGENT_DEFAULT_MODEL_KNOB, OUTPUT_MODALITIES, SERVICE_LABEL, SERVICE_LABEL_PLURAL, TOP_TIER_COST_RATING, TOP_TIER_LOCKED_TITLE, UNKNOWN_MODEL_KIND, acceptsTextInstructions, announceModelCatalogChanged, availableOnDevices, blendedPrice, buildModelClassIndex, buildSuccessionIndex, catalogFingerprint, catalogForApp, catalogKeyColumn, catalogKindOf, catalogKindVerdict, cheapestAdequateModel, classConfigKey, collapseTiersByClass, costRatingTier, costRatingWord, createModelCatalog, createModelFavorites, createModelRecords, curatedList, displayOrderOf, favoriteIdsEqual, fetchCuratedModels, findNonCanonicalCapabilityValues, fitsMemory, fitsNeed, fitsThisComputer, followModelCatalogChanges, followModelCatalogVisibility, formatMemoryBytes, fromDiscovery, ggufEngine, ggufFacts, groupFeatures, hardwareClassesOf, hasCompatibleDecisionInteraction, isChatModelCapability, isContentType, isConversationalModelCapability, isDecisionModelCapability, isFeatureKey, isHelperGguf, isInteractionMode, isListedVariant, isLocalModelCatalog, isManagedAgentModelCapability, isModelCatalogChange, isProjectorName, isSupersedable, isTopTierRating, judgeHeaderFacts, mergeAuditRecordIntoCapabilities, missingShards, modelCatalogRevision, modelClassKnobFor, modelClassName, modelClassPinOf, modelDisplayLabel, modelsForSelectionPurpose, normalizeArch, normalizeModel, normalizeModels, normalizeOs, normalizePromptSettings, onModelCatalogChanged, orderCatalogGroups, orderCatalogModels, outputFormatControlKey, parseCapabilities, pickProjector, priceTierRating, quantFromName, rankVariants, readCuratedRows, readDeviceModelFiles, readGgufHeader, readModelCatalog, readModelCatalogStamp, readModelIdentities, readPublicModel, reconcileModelFavoriteIds, reportModelDiagnostic, requireCanonicalCapabilities, requiredArtifactIds, requiredArtifacts, resetSuccessionLogForTests, resolveDeviceModel, resolveLiveModelId, resolveModelMapKnob, resolveNewAgentModelId, resolvePreferredModelChoice, resolveSuccessor, runtimesOnEngine, seesImages, selectActiveModels, selectActiveModelsReady, selectAllModelOptions, selectAllModels, selectAllModelsReady, selectDeprecatedModels, selectDeprecatedModelsReady, selectModelById, selectModelClassConfig, selectModelClassName, selectModelControls, selectModelDetailError, selectModelFetchType, selectModelFullyLoaded, selectModelIdentityById, selectModelIdentityLookupStatus, selectModelLabelById, selectModelLabelWithClass, selectModelNameById, selectModelOptions, selectVariant, serviceCountLabel, setModelDiagnosticsSink, shapeCuratedModels, shardFileName, shardName, speedRatingLabel, speedRatingWord, splitSetProblems, takesInput, toAuditRecord, toDeviceModelFile, validateModelSet, variantVerdict, withModelClass };
2104
+ export type { AdminOffering, AdminPricingBand, ArtifactUse, AuditCapabilitiesRecord, AvailabilityVariant, CapabilitiesParseContext, CatalogKeyColumn, CatalogKindInput, CatalogKindVerdict, CatalogModel, CatalogTier, CheapestAdequateOptions, CompatStatus, ContentType, CuratedCatalogClient, CuratedModel, CuratedPresentation, CuratedRows, CuratedVariant, DecidedBy, DeviceAvailability, DeviceGraphics, DeviceHardware, DeviceModelFile, DeviceModelResolution, DeviceServedSettings, DiscoveryAmbiguity, DiscoveryArtifact, DiscoveryMedia, DiscoveryResult, DiscoveryRuntime, DiscoverySource, DiscoveryVariant, FeatureBucket, FeatureBucketMeta, FeatureKey, FitCapabilities, GgufHeader, GgufRead, GgufTensor, GroupedFeatures, HardwareClass, HardwareClasses, HeaderFlag, HeaderJudgement, HeaderRefusal, Interaction, InteractionMode, LocalArtifact, LocalCatalogClient, LocalCatalogQuery, LocalCompatRow, LocalModel, LocalModelCatalog, LocalPresentation, LocalRuntime, LocalRuntimeBuild, LocalVariant, Modality, ModelCapabilities, ModelCatalog, ModelCatalogChangePayload, ModelCatalogClient, ModelCatalogConfig, ModelCatalogDirectiveSubscribe, ModelCatalogErrorSink, ModelCatalogPgError, ModelCatalogPgResult, ModelCatalogQuery, ModelCatalogState, ModelCatalogVariant, ModelCatalogVariantState, ModelCatalogVisibilityOptions, ModelClassConfig, ModelClassEntry, ModelClassIndex, ModelDiagnosticEntry, ModelDiagnosticsSink, ModelFavorites, ModelFavoritesCache, ModelFavoritesClient, ModelFavoritesConfig, ModelFavoritesErrorSink, ModelFavoritesState, ModelFetchScope, ModelFileHandle, ModelFit, ModelIdentityRow, ModelJson, ModelLabelSource, ModelNeed, ModelOfferingRow, ModelOption, ModelOptionWithLifecycle, ModelRecord, ModelRecordFetchType, ModelRecords, ModelRecordsClient, ModelRecordsConfig, ModelRecordsState, ModelSelectionPurpose, ModelSetEnv, ModelSetFacts, ModelSetValidation, NewAgentModel, NoSelection, OrderedLike, PreferredModelChoice, PreferredModelChoicePorts, PriceTier, PricedCatalogModel, PublicModelClient, RankOptions, RankedVariant, ReadModelCatalogOptions, SelectDevice, Selection, ShardName, SuccessionClient, SuccessionIndex, SuccessionNode, VariantDiscovery, VariantVerdict, Want };
@@ -641,6 +641,8 @@ interface RecordsQuery extends PromiseLike<PgResult> {
641
641
  nullsFirst?: boolean;
642
642
  }): RecordsQuery;
643
643
  maybeSingle(): PromiseLike<PgResult>;
644
+ /** Only the catalog stamp (`readModelCatalogStamp`) uses it. */
645
+ limit?(count: number): RecordsQuery;
644
646
  }
645
647
  interface ModelRecordsClient {
646
648
  schema(name: string): {
@@ -791,6 +793,12 @@ declare function readPublicModel(client: PublicModelClient, key: string): Promis
791
793
  } | null;
792
794
  error: string | null;
793
795
  }>;
796
+ /**
797
+ * THE catalog stamp: the newest `ai.model_definition.updated_at` (one row, one column) — the cheap read a
798
+ * tab makes to learn whether the catalog changed while it was not listening (catalog/changes.ts
799
+ * `followModelCatalogVisibility`). Null when the catalog is empty. Throws the database's error.
800
+ */
801
+ declare function readModelCatalogStamp(client: ModelRecordsClient): Promise<string | null>;
794
802
 
795
803
  /**
796
804
  * `@ai-matrx/agents/models` — `createModelCatalog`: the headless model catalog store.
@@ -1101,7 +1109,7 @@ interface LocalModel {
1101
1109
  /** Matrx 2's 1.48 id for a model seeded from its old list (metadata.desktop_id). */
1102
1110
  desktop_id?: string | null;
1103
1111
  maker_logo_file_id?: string | null;
1104
- /** The admin Catalogs kind (`catalogKindOf`): llm_model, whisper_model, tts_model_file, image_gen_model, video_gen_model, ner_model, wake_word_model, lora. */
1112
+ /** The admin Catalogs kind (`catalogKindOf`): llm_model, whisper_model, tts_model_file, image_gen_model, video_gen_model, ner_model, wake_word_model, lora, embedding_model, or unknown (no rule places it; `catalogKindVerdict` says why). */
1105
1113
  kind?: string;
1106
1114
  /** At least one variant is offered (Matrx 2 lists it). */
1107
1115
  offered?: boolean;
@@ -1837,8 +1845,12 @@ interface ReadModelCatalogOptions {
1837
1845
  appInstanceIds?: readonly string[];
1838
1846
  };
1839
1847
  }
1848
+ /** The kind of a model the catalog cannot place by its capabilities: shown loudly, never offered to a chat. */
1849
+ declare const UNKNOWN_MODEL_KIND: "unknown";
1840
1850
  /** The catalog kinds whose rows live in the unified catalog (ai.*): the admin Catalogs page's model kinds. */
1841
1851
  declare const MODEL_CATALOG_KINDS: ReadonlySet<string>;
1852
+ /** The interactions a text-in, text-out model answers a person in: only these make an llm_model. */
1853
+ declare const LLM_INTERACTIONS: ReadonlySet<string>;
1842
1854
  /** What `catalogKindOf` reads from a model (a CuratedModel or a LocalModel from `readModelCatalog` both fit). */
1843
1855
  interface CatalogKindInput {
1844
1856
  readonly variants: ReadonlyArray<{
@@ -1853,11 +1865,20 @@ interface CatalogKindInput {
1853
1865
  readonly shelf?: string | null;
1854
1866
  } | null;
1855
1867
  }
1868
+ /** A model's admin kind and, when it is `unknown`, why (one line, said on the admin page and in reader warnings). */
1869
+ interface CatalogKindVerdict {
1870
+ kind: string;
1871
+ reason: string | null;
1872
+ }
1856
1873
  /**
1857
- * THE admin Catalogs kind of a unified model: the kind of the old public.catalog_entries rows its variants
1858
- * carry (the list migration stamps them), when that is a model kind; else placed by what it does.
1859
- * `kindOfEntry` maps catalog_entries.id → kind.
1874
+ * THE admin Catalogs kind of a unified model, with the reason when it cannot be placed: the kind of the
1875
+ * old public.catalog_entries rows its variants carry (the list migration stamps them), when that is a
1876
+ * model kind; else placed by what it does (capabilities, never a name list). There is NO default: a model
1877
+ * is an llm_model only when it takes text, gives text and answers in a chat-like interaction
1878
+ * (LLM_INTERACTIONS); anything the rules cannot place is `unknown`, with the reason.
1860
1879
  */
1880
+ declare function catalogKindVerdict(m: CatalogKindInput, kindOfEntry: ReadonlyMap<string, string>): CatalogKindVerdict;
1881
+ /** THE admin Catalogs kind of a unified model (`catalogKindVerdict(...).kind`); `unknown` when it cannot be placed. */
1861
1882
  declare function catalogKindOf(m: CatalogKindInput, kindOfEntry: ReadonlyMap<string, string>): string;
1862
1883
  /** sha256 (hex) of the catalog's canonical JSON, its own `catalog_fingerprint` left out. Isomorphic (pure JS). */
1863
1884
  declare function catalogFingerprint(catalog: LocalModelCatalog): string;
@@ -2032,7 +2053,12 @@ declare function modelDisplayLabel(row: ModelLabelSource | null | undefined): st
2032
2053
  * `@ai-matrx/agents/models/react`). No surface keeps a model cache that misses the event.
2033
2054
  *
2034
2055
  * The hub lives on `globalThis` so two bundled copies of this module share one set of listeners.
2056
+ *
2057
+ * A tab that is not listening (the bus room not joined yet, or asleep) catches up when it comes to the
2058
+ * front: `followModelCatalogVisibility({ client })` reads the catalog stamp when the tab hides and again
2059
+ * when it shows or takes focus (throttled), and announces a change when the stamp moved.
2035
2060
  */
2061
+
2036
2062
  /** A `catalog_changed` payload: `{ catalog?: "models" | ..., change?, model_id? }`. */
2037
2063
  type ModelCatalogChangePayload = Record<string, unknown>;
2038
2064
  /** The bus client's subscribe call: `(action, handler) => unsubscribe` (the web's `registerDirectiveHandler`). */
@@ -2047,6 +2073,32 @@ declare function modelCatalogRevision(): number;
2047
2073
  declare function announceModelCatalogChanged(payload?: ModelCatalogChangePayload): void;
2048
2074
  /** Bind the host's bus client: every `catalog_changed` it delivers reaches every model reader. Returns the unbind. */
2049
2075
  declare function followModelCatalogChanges(subscribe: ModelCatalogDirectiveSubscribe): () => void;
2076
+ interface ModelCatalogVisibilityOptions {
2077
+ /** The client the stamp is read with (supabase-js fits as is). */
2078
+ client: ModelRecordsClient;
2079
+ /** At most one stamp read per this many ms when the tab shows / takes focus. Default 20 s. */
2080
+ minIntervalMs?: number;
2081
+ /** The page (tests pass a double); defaults to the global `document` / `window`. */
2082
+ page?: {
2083
+ document: Pick<Document, "visibilityState" | "addEventListener" | "removeEventListener">;
2084
+ window: Pick<Window, "addEventListener" | "removeEventListener">;
2085
+ };
2086
+ /** Where a failed stamp read is said. Default: console.error, tagged. */
2087
+ errorSink?: (event: {
2088
+ code: string;
2089
+ message: string;
2090
+ }) => void;
2091
+ now?: () => number;
2092
+ }
2093
+ /**
2094
+ * When the tab shows or takes focus, read the catalog stamp (one row) and, when it moved since the tab
2095
+ * last knew it, announce a model catalog change through the SAME door as the bus (every catalog re-reads
2096
+ * what it read; every reader following `onModelCatalogChanged` re-reads). The baseline is taken when the
2097
+ * tab hides (or at bind when it starts hidden), and refreshed by every announced change. Reads already in
2098
+ * flight are joined; shows/focuses within `minIntervalMs` share the last read. Returns the unbind. No-op
2099
+ * where there is no document (a server render, a worker).
2100
+ */
2101
+ declare function followModelCatalogVisibility(options: ModelCatalogVisibilityOptions): () => void;
2050
2102
 
2051
- export { CHAT_DEFAULT_MODEL_KNOB, CONTENT_TYPES, DEFAULT_CAPABILITIES, DEVICE_FILE_USABLE_STATES, DEVICE_OWN_FILE_USABLE_STATES, DEVICE_RULE_TWIN_FIXTURE, DEVICE_SERVED_SETTINGS_KEY, DEVICE_SERVED_VIA, DeviceModelUnavailableError, EMPTY_MODEL_RECORDS, EXCLUDED_REVIEW_STATES, FEATURE_BUCKETS, FEATURE_BUCKET_ORDER, FEATURE_KEYS, FILE_TYPE_QUANT, GgufError, INPUT_MODALITIES, INTERACTION_MODES, MAX_SUCCESSION_HOPS, MODEL_CATALOG_KINDS, MODEL_FAVORITE_ENTITY_TYPE, NEW_AGENT_DEFAULT_MODEL_KNOB, OUTPUT_MODALITIES, SERVICE_LABEL, SERVICE_LABEL_PLURAL, TOP_TIER_COST_RATING, TOP_TIER_LOCKED_TITLE, acceptsTextInstructions, announceModelCatalogChanged, availableOnDevices, blendedPrice, buildModelClassIndex, buildSuccessionIndex, catalogFingerprint, catalogForApp, catalogKeyColumn, catalogKindOf, cheapestAdequateModel, classConfigKey, collapseTiersByClass, costRatingTier, costRatingWord, createModelCatalog, createModelFavorites, createModelRecords, curatedList, displayOrderOf, favoriteIdsEqual, fetchCuratedModels, findNonCanonicalCapabilityValues, fitsMemory, fitsNeed, fitsThisComputer, followModelCatalogChanges, formatMemoryBytes, fromDiscovery, ggufEngine, ggufFacts, groupFeatures, hardwareClassesOf, hasCompatibleDecisionInteraction, isChatModelCapability, isContentType, isConversationalModelCapability, isDecisionModelCapability, isFeatureKey, isHelperGguf, isInteractionMode, isListedVariant, isLocalModelCatalog, isManagedAgentModelCapability, isModelCatalogChange, isProjectorName, isSupersedable, isTopTierRating, judgeHeaderFacts, mergeAuditRecordIntoCapabilities, missingShards, modelCatalogRevision, modelClassKnobFor, modelClassName, modelClassPinOf, modelDisplayLabel, modelsForSelectionPurpose, normalizeArch, normalizeModel, normalizeModels, normalizeOs, normalizePromptSettings, onModelCatalogChanged, orderCatalogGroups, orderCatalogModels, outputFormatControlKey, parseCapabilities, pickProjector, priceTierRating, quantFromName, rankVariants, readCuratedRows, readDeviceModelFiles, readGgufHeader, readModelCatalog, readModelIdentities, readPublicModel, reconcileModelFavoriteIds, reportModelDiagnostic, requireCanonicalCapabilities, requiredArtifactIds, requiredArtifacts, resetSuccessionLogForTests, resolveDeviceModel, resolveLiveModelId, resolveModelMapKnob, resolveNewAgentModelId, resolvePreferredModelChoice, resolveSuccessor, runtimesOnEngine, seesImages, selectActiveModels, selectActiveModelsReady, selectAllModelOptions, selectAllModels, selectAllModelsReady, selectDeprecatedModels, selectDeprecatedModelsReady, selectModelById, selectModelClassConfig, selectModelClassName, selectModelControls, selectModelDetailError, selectModelFetchType, selectModelFullyLoaded, selectModelIdentityById, selectModelIdentityLookupStatus, selectModelLabelById, selectModelLabelWithClass, selectModelNameById, selectModelOptions, selectVariant, serviceCountLabel, setModelDiagnosticsSink, shapeCuratedModels, shardFileName, shardName, speedRatingLabel, speedRatingWord, splitSetProblems, takesInput, toAuditRecord, toDeviceModelFile, validateModelSet, variantVerdict, withModelClass };
2052
- export type { AdminOffering, AdminPricingBand, ArtifactUse, AuditCapabilitiesRecord, AvailabilityVariant, CapabilitiesParseContext, CatalogKeyColumn, CatalogKindInput, CatalogModel, CatalogTier, CheapestAdequateOptions, CompatStatus, ContentType, CuratedCatalogClient, CuratedModel, CuratedPresentation, CuratedRows, CuratedVariant, DecidedBy, DeviceAvailability, DeviceGraphics, DeviceHardware, DeviceModelFile, DeviceModelResolution, DeviceServedSettings, DiscoveryAmbiguity, DiscoveryArtifact, DiscoveryMedia, DiscoveryResult, DiscoveryRuntime, DiscoverySource, DiscoveryVariant, FeatureBucket, FeatureBucketMeta, FeatureKey, FitCapabilities, GgufHeader, GgufRead, GgufTensor, GroupedFeatures, HardwareClass, HardwareClasses, HeaderFlag, HeaderJudgement, HeaderRefusal, Interaction, InteractionMode, LocalArtifact, LocalCatalogClient, LocalCatalogQuery, LocalCompatRow, LocalModel, LocalModelCatalog, LocalPresentation, LocalRuntime, LocalRuntimeBuild, LocalVariant, Modality, ModelCapabilities, ModelCatalog, ModelCatalogChangePayload, ModelCatalogClient, ModelCatalogConfig, ModelCatalogDirectiveSubscribe, ModelCatalogErrorSink, ModelCatalogPgError, ModelCatalogPgResult, ModelCatalogQuery, ModelCatalogState, ModelCatalogVariant, ModelCatalogVariantState, ModelClassConfig, ModelClassEntry, ModelClassIndex, ModelDiagnosticEntry, ModelDiagnosticsSink, ModelFavorites, ModelFavoritesCache, ModelFavoritesClient, ModelFavoritesConfig, ModelFavoritesErrorSink, ModelFavoritesState, ModelFetchScope, ModelFileHandle, ModelFit, ModelIdentityRow, ModelJson, ModelLabelSource, ModelNeed, ModelOfferingRow, ModelOption, ModelOptionWithLifecycle, ModelRecord, ModelRecordFetchType, ModelRecords, ModelRecordsClient, ModelRecordsConfig, ModelRecordsState, ModelSelectionPurpose, ModelSetEnv, ModelSetFacts, ModelSetValidation, NewAgentModel, NoSelection, OrderedLike, PreferredModelChoice, PreferredModelChoicePorts, PriceTier, PricedCatalogModel, PublicModelClient, RankOptions, RankedVariant, ReadModelCatalogOptions, SelectDevice, Selection, ShardName, SuccessionClient, SuccessionIndex, SuccessionNode, VariantDiscovery, VariantVerdict, Want };
2103
+ export { CHAT_DEFAULT_MODEL_KNOB, CONTENT_TYPES, DEFAULT_CAPABILITIES, DEVICE_FILE_USABLE_STATES, DEVICE_OWN_FILE_USABLE_STATES, DEVICE_RULE_TWIN_FIXTURE, DEVICE_SERVED_SETTINGS_KEY, DEVICE_SERVED_VIA, DeviceModelUnavailableError, EMPTY_MODEL_RECORDS, EXCLUDED_REVIEW_STATES, FEATURE_BUCKETS, FEATURE_BUCKET_ORDER, FEATURE_KEYS, FILE_TYPE_QUANT, GgufError, INPUT_MODALITIES, INTERACTION_MODES, LLM_INTERACTIONS, MAX_SUCCESSION_HOPS, MODEL_CATALOG_KINDS, MODEL_FAVORITE_ENTITY_TYPE, NEW_AGENT_DEFAULT_MODEL_KNOB, OUTPUT_MODALITIES, SERVICE_LABEL, SERVICE_LABEL_PLURAL, TOP_TIER_COST_RATING, TOP_TIER_LOCKED_TITLE, UNKNOWN_MODEL_KIND, acceptsTextInstructions, announceModelCatalogChanged, availableOnDevices, blendedPrice, buildModelClassIndex, buildSuccessionIndex, catalogFingerprint, catalogForApp, catalogKeyColumn, catalogKindOf, catalogKindVerdict, cheapestAdequateModel, classConfigKey, collapseTiersByClass, costRatingTier, costRatingWord, createModelCatalog, createModelFavorites, createModelRecords, curatedList, displayOrderOf, favoriteIdsEqual, fetchCuratedModels, findNonCanonicalCapabilityValues, fitsMemory, fitsNeed, fitsThisComputer, followModelCatalogChanges, followModelCatalogVisibility, formatMemoryBytes, fromDiscovery, ggufEngine, ggufFacts, groupFeatures, hardwareClassesOf, hasCompatibleDecisionInteraction, isChatModelCapability, isContentType, isConversationalModelCapability, isDecisionModelCapability, isFeatureKey, isHelperGguf, isInteractionMode, isListedVariant, isLocalModelCatalog, isManagedAgentModelCapability, isModelCatalogChange, isProjectorName, isSupersedable, isTopTierRating, judgeHeaderFacts, mergeAuditRecordIntoCapabilities, missingShards, modelCatalogRevision, modelClassKnobFor, modelClassName, modelClassPinOf, modelDisplayLabel, modelsForSelectionPurpose, normalizeArch, normalizeModel, normalizeModels, normalizeOs, normalizePromptSettings, onModelCatalogChanged, orderCatalogGroups, orderCatalogModels, outputFormatControlKey, parseCapabilities, pickProjector, priceTierRating, quantFromName, rankVariants, readCuratedRows, readDeviceModelFiles, readGgufHeader, readModelCatalog, readModelCatalogStamp, readModelIdentities, readPublicModel, reconcileModelFavoriteIds, reportModelDiagnostic, requireCanonicalCapabilities, requiredArtifactIds, requiredArtifacts, resetSuccessionLogForTests, resolveDeviceModel, resolveLiveModelId, resolveModelMapKnob, resolveNewAgentModelId, resolvePreferredModelChoice, resolveSuccessor, runtimesOnEngine, seesImages, selectActiveModels, selectActiveModelsReady, selectAllModelOptions, selectAllModels, selectAllModelsReady, selectDeprecatedModels, selectDeprecatedModelsReady, selectModelById, selectModelClassConfig, selectModelClassName, selectModelControls, selectModelDetailError, selectModelFetchType, selectModelFullyLoaded, selectModelIdentityById, selectModelIdentityLookupStatus, selectModelLabelById, selectModelLabelWithClass, selectModelNameById, selectModelOptions, selectVariant, serviceCountLabel, setModelDiagnosticsSink, shapeCuratedModels, shardFileName, shardName, speedRatingLabel, speedRatingWord, splitSetProblems, takesInput, toAuditRecord, toDeviceModelFile, validateModelSet, variantVerdict, withModelClass };
2104
+ export type { AdminOffering, AdminPricingBand, ArtifactUse, AuditCapabilitiesRecord, AvailabilityVariant, CapabilitiesParseContext, CatalogKeyColumn, CatalogKindInput, CatalogKindVerdict, CatalogModel, CatalogTier, CheapestAdequateOptions, CompatStatus, ContentType, CuratedCatalogClient, CuratedModel, CuratedPresentation, CuratedRows, CuratedVariant, DecidedBy, DeviceAvailability, DeviceGraphics, DeviceHardware, DeviceModelFile, DeviceModelResolution, DeviceServedSettings, DiscoveryAmbiguity, DiscoveryArtifact, DiscoveryMedia, DiscoveryResult, DiscoveryRuntime, DiscoverySource, DiscoveryVariant, FeatureBucket, FeatureBucketMeta, FeatureKey, FitCapabilities, GgufHeader, GgufRead, GgufTensor, GroupedFeatures, HardwareClass, HardwareClasses, HeaderFlag, HeaderJudgement, HeaderRefusal, Interaction, InteractionMode, LocalArtifact, LocalCatalogClient, LocalCatalogQuery, LocalCompatRow, LocalModel, LocalModelCatalog, LocalPresentation, LocalRuntime, LocalRuntimeBuild, LocalVariant, Modality, ModelCapabilities, ModelCatalog, ModelCatalogChangePayload, ModelCatalogClient, ModelCatalogConfig, ModelCatalogDirectiveSubscribe, ModelCatalogErrorSink, ModelCatalogPgError, ModelCatalogPgResult, ModelCatalogQuery, ModelCatalogState, ModelCatalogVariant, ModelCatalogVariantState, ModelCatalogVisibilityOptions, ModelClassConfig, ModelClassEntry, ModelClassIndex, ModelDiagnosticEntry, ModelDiagnosticsSink, ModelFavorites, ModelFavoritesCache, ModelFavoritesClient, ModelFavoritesConfig, ModelFavoritesErrorSink, ModelFavoritesState, ModelFetchScope, ModelFileHandle, ModelFit, ModelIdentityRow, ModelJson, ModelLabelSource, ModelNeed, ModelOfferingRow, ModelOption, ModelOptionWithLifecycle, ModelRecord, ModelRecordFetchType, ModelRecords, ModelRecordsClient, ModelRecordsConfig, ModelRecordsState, ModelSelectionPurpose, ModelSetEnv, ModelSetFacts, ModelSetValidation, NewAgentModel, NoSelection, OrderedLike, PreferredModelChoice, PreferredModelChoicePorts, PriceTier, PricedCatalogModel, PublicModelClient, RankOptions, RankedVariant, ReadModelCatalogOptions, SelectDevice, Selection, ShardName, SuccessionClient, SuccessionIndex, SuccessionNode, VariantDiscovery, VariantVerdict, Want };
@@ -759,42 +759,6 @@ var OUTPUT_MODALITIES = [
759
759
  "decision"
760
760
  ];
761
761
 
762
- // models/catalog/changes.ts
763
- var KEY2 = /* @__PURE__ */ Symbol.for("ai-matrx.agents.model-catalog-changes");
764
- function hub() {
765
- const g = globalThis;
766
- return g[KEY2] ??= { listeners: /* @__PURE__ */ new Set(), revision: 0 };
767
- }
768
- function isModelCatalogChange(payload) {
769
- const catalog = payload?.["catalog"];
770
- return catalog === void 0 || catalog === null || catalog === "models";
771
- }
772
- function onModelCatalogChanged(listener) {
773
- const h = hub();
774
- h.listeners.add(listener);
775
- return () => {
776
- h.listeners.delete(listener);
777
- };
778
- }
779
- function modelCatalogRevision() {
780
- return hub().revision;
781
- }
782
- function announceModelCatalogChanged(payload = {}) {
783
- if (!isModelCatalogChange(payload)) return;
784
- const h = hub();
785
- h.revision += 1;
786
- for (const l of [...h.listeners]) {
787
- try {
788
- l(payload);
789
- } catch (err) {
790
- console.error("[@ai-matrx/agents/models] a catalog_changed listener threw", err);
791
- }
792
- }
793
- }
794
- function followModelCatalogChanges(subscribe) {
795
- return subscribe("catalog_changed", (payload) => announceModelCatalogChanged(payload ?? {}));
796
- }
797
-
798
762
  // models/label.ts
799
763
  function modelDisplayLabel(row) {
800
764
  if (!row) return void 0;
@@ -1386,6 +1350,102 @@ async function readPublicModel(client, key) {
1386
1350
  if (error) return { row: null, error: error.message };
1387
1351
  return { row: data ?? null, error: null };
1388
1352
  }
1353
+ async function readModelCatalogStamp(client) {
1354
+ const q = client.schema("ai").from("model_definition").select("updated_at").order("updated_at", { ascending: false, nullsFirst: false });
1355
+ if (!q.limit) throw new Error("readModelCatalogStamp: the client has no .limit() (a supabase-js client does)");
1356
+ const { data, error } = await q.limit(1).maybeSingle();
1357
+ if (error) throw new Error(error.message);
1358
+ const stamp = data?.updated_at;
1359
+ return typeof stamp === "string" ? stamp : null;
1360
+ }
1361
+
1362
+ // models/catalog/changes.ts
1363
+ var KEY2 = /* @__PURE__ */ Symbol.for("ai-matrx.agents.model-catalog-changes");
1364
+ function hub() {
1365
+ const g = globalThis;
1366
+ return g[KEY2] ??= { listeners: /* @__PURE__ */ new Set(), revision: 0 };
1367
+ }
1368
+ function isModelCatalogChange(payload) {
1369
+ const catalog = payload?.["catalog"];
1370
+ return catalog === void 0 || catalog === null || catalog === "models";
1371
+ }
1372
+ function onModelCatalogChanged(listener) {
1373
+ const h = hub();
1374
+ h.listeners.add(listener);
1375
+ return () => {
1376
+ h.listeners.delete(listener);
1377
+ };
1378
+ }
1379
+ function modelCatalogRevision() {
1380
+ return hub().revision;
1381
+ }
1382
+ function announceModelCatalogChanged(payload = {}) {
1383
+ if (!isModelCatalogChange(payload)) return;
1384
+ const h = hub();
1385
+ h.revision += 1;
1386
+ for (const l of [...h.listeners]) {
1387
+ try {
1388
+ l(payload);
1389
+ } catch (err) {
1390
+ console.error("[@ai-matrx/agents/models] a catalog_changed listener threw", err);
1391
+ }
1392
+ }
1393
+ }
1394
+ function followModelCatalogChanges(subscribe) {
1395
+ return subscribe("catalog_changed", (payload) => announceModelCatalogChanged(payload ?? {}));
1396
+ }
1397
+ function followModelCatalogVisibility(options) {
1398
+ const page = options.page ?? (typeof document !== "undefined" && typeof window !== "undefined" ? { document, window } : null);
1399
+ if (!page) return () => {
1400
+ };
1401
+ const minIntervalMs = options.minIntervalMs ?? 2e4;
1402
+ const now = options.now ?? (() => Date.now());
1403
+ const sink = options.errorSink ?? ((e) => {
1404
+ console.error(`[@ai-matrx/agents/models] ${e.code}: ${e.message}`);
1405
+ });
1406
+ let baseline;
1407
+ let inFlight = null;
1408
+ let lastShownRead = -Infinity;
1409
+ const stamp = () => inFlight ??= readModelCatalogStamp(options.client).finally(() => {
1410
+ inFlight = null;
1411
+ });
1412
+ const fail = (err) => sink({ code: "model-catalog-stamp-failed", message: err instanceof Error ? err.message : String(err) });
1413
+ const learnBaseline = () => {
1414
+ if (baseline !== void 0) return;
1415
+ void stamp().then((s4) => {
1416
+ if (baseline === void 0) baseline = s4;
1417
+ }, fail);
1418
+ };
1419
+ const onHidden = () => {
1420
+ if (page.document.visibilityState === "hidden") learnBaseline();
1421
+ };
1422
+ const onShown = () => {
1423
+ if (page.document.visibilityState === "hidden") return;
1424
+ const t = now();
1425
+ if (t - lastShownRead < minIntervalMs) return;
1426
+ lastShownRead = t;
1427
+ const known = baseline;
1428
+ if (known === void 0) return learnBaseline();
1429
+ void stamp().then((s4) => {
1430
+ if (s4 === known) return;
1431
+ baseline = s4;
1432
+ announceModelCatalogChanged({ catalog: "models", change: "catch_up_visible" });
1433
+ }, fail);
1434
+ };
1435
+ const offChanges = onModelCatalogChanged(() => {
1436
+ baseline = void 0;
1437
+ if (page.document.visibilityState === "hidden") learnBaseline();
1438
+ });
1439
+ const onVisibility = () => page.document.visibilityState === "hidden" ? onHidden() : onShown();
1440
+ page.document.addEventListener("visibilitychange", onVisibility);
1441
+ page.window.addEventListener("focus", onShown);
1442
+ if (page.document.visibilityState === "hidden") learnBaseline();
1443
+ return () => {
1444
+ offChanges();
1445
+ page.document.removeEventListener("visibilitychange", onVisibility);
1446
+ page.window.removeEventListener("focus", onShown);
1447
+ };
1448
+ }
1389
1449
 
1390
1450
  // models/catalog/store.ts
1391
1451
  var IDLE = { status: "idle", models: [], error: null, loadedAt: null };
@@ -2641,6 +2701,7 @@ var DeviceModelUnavailableError = class extends Error {
2641
2701
  };
2642
2702
 
2643
2703
  // models/catalog-reader.ts
2704
+ var UNKNOWN_MODEL_KIND = "unknown";
2644
2705
  var MODEL_CATALOG_KINDS = /* @__PURE__ */ new Set([
2645
2706
  "llm_model",
2646
2707
  "whisper_model",
@@ -2649,23 +2710,35 @@ var MODEL_CATALOG_KINDS = /* @__PURE__ */ new Set([
2649
2710
  "video_gen_model",
2650
2711
  "ner_model",
2651
2712
  "wake_word_model",
2652
- "lora"
2713
+ "lora",
2714
+ "embedding_model",
2715
+ UNKNOWN_MODEL_KIND
2653
2716
  ]);
2654
- function catalogKindOf(m, kindOfEntry) {
2717
+ var LLM_INTERACTIONS = /* @__PURE__ */ new Set(["turn", "single", "agent"]);
2718
+ function catalogKindVerdict(m, kindOfEntry) {
2655
2719
  for (const v of m.variants)
2656
2720
  for (const id of v.catalog_entry_ids ?? []) {
2657
2721
  const k = kindOfEntry.get(id);
2658
- if (k && MODEL_CATALOG_KINDS.has(k)) return k;
2722
+ if (k && k !== UNKNOWN_MODEL_KIND && MODEL_CATALOG_KINDS.has(k)) return { kind: k, reason: null };
2659
2723
  }
2660
2724
  const out = m.capabilities.output ?? [];
2661
2725
  const inp = m.capabilities.input ?? [];
2662
- if (m.presentation?.shelf === "loras") return "lora";
2663
- if (out.includes("video")) return "video_gen_model";
2664
- if (out.includes("image")) return "image_gen_model";
2665
- if (out.includes("audio")) return "tts_model_file";
2666
- if (inp.includes("audio")) return "whisper_model";
2667
- if (m.capabilities.interaction === "extraction") return "ner_model";
2668
- return "llm_model";
2726
+ const interaction = m.capabilities.interaction ?? "";
2727
+ const placed = (kind) => ({ kind, reason: null });
2728
+ if (m.presentation?.shelf === "loras" || interaction === "adapter") return placed("lora");
2729
+ if (out.includes("video")) return placed("video_gen_model");
2730
+ if (out.includes("image")) return placed("image_gen_model");
2731
+ if (out.includes("embedding")) return placed("embedding_model");
2732
+ if (out.includes("audio")) return placed("tts_model_file");
2733
+ if (inp.includes("audio") && (out.includes("decision") || interaction === "detection")) return placed("wake_word_model");
2734
+ if (inp.includes("audio") && out.includes("text")) return placed("whisper_model");
2735
+ if (interaction === "extraction") return placed("ner_model");
2736
+ if (inp.includes("text") && out.includes("text") && LLM_INTERACTIONS.has(interaction)) return placed("llm_model");
2737
+ const shape = `input [${inp.join(", ")}], output [${out.join(", ")}], interaction ${interaction || "(none)"}`;
2738
+ return { kind: UNKNOWN_MODEL_KIND, reason: `no kind rule places ${shape}` };
2739
+ }
2740
+ function catalogKindOf(m, kindOfEntry) {
2741
+ return catalogKindVerdict(m, kindOfEntry).kind;
2669
2742
  }
2670
2743
  function canonicalJson(value) {
2671
2744
  if (value === void 0) return "null";
@@ -2744,6 +2817,8 @@ async function readCatalogWith(client, opts, preread) {
2744
2817
  const p = presentationOf.get(c.id);
2745
2818
  stamp(p);
2746
2819
  const maker = providerById.get(s3(m.provider_id));
2820
+ const verdict = catalogKindVerdict(c, kindOfEntry);
2821
+ if (verdict.reason) warnings.push(`${s3(m.name)}: kind unknown: ${verdict.reason}`);
2747
2822
  return [
2748
2823
  {
2749
2824
  id: s3(m.id),
@@ -2754,7 +2829,7 @@ async function readCatalogWith(client, opts, preread) {
2754
2829
  maker_logo_file_id: sn3(maker?.logo_file_id),
2755
2830
  description: sn3(m.description),
2756
2831
  capabilities: m.capabilities ?? {},
2757
- kind: catalogKindOf(c, kindOfEntry),
2832
+ kind: verdict.kind,
2758
2833
  offered: c.offered,
2759
2834
  updated_at: c.updated_at,
2760
2835
  presentation: p ? {
@@ -2995,6 +3070,7 @@ export {
2995
3070
  GgufError,
2996
3071
  INPUT_MODALITIES,
2997
3072
  INTERACTION_MODES,
3073
+ LLM_INTERACTIONS,
2998
3074
  MAX_SUCCESSION_HOPS,
2999
3075
  MODEL_CATALOG_KINDS,
3000
3076
  MODEL_FAVORITE_ENTITY_TYPE,
@@ -3004,6 +3080,7 @@ export {
3004
3080
  SERVICE_LABEL_PLURAL,
3005
3081
  TOP_TIER_COST_RATING,
3006
3082
  TOP_TIER_LOCKED_TITLE,
3083
+ UNKNOWN_MODEL_KIND,
3007
3084
  acceptsTextInstructions,
3008
3085
  announceModelCatalogChanged,
3009
3086
  availableOnDevices,
@@ -3014,6 +3091,7 @@ export {
3014
3091
  catalogForApp,
3015
3092
  catalogKeyColumn,
3016
3093
  catalogKindOf,
3094
+ catalogKindVerdict,
3017
3095
  cheapestAdequateModel,
3018
3096
  classConfigKey,
3019
3097
  collapseTiersByClass,
@@ -3031,6 +3109,7 @@ export {
3031
3109
  fitsNeed,
3032
3110
  fitsThisComputer,
3033
3111
  followModelCatalogChanges,
3112
+ followModelCatalogVisibility,
3034
3113
  formatMemoryBytes,
3035
3114
  fromDiscovery,
3036
3115
  ggufEngine,
@@ -3079,6 +3158,7 @@ export {
3079
3158
  readDeviceModelFiles,
3080
3159
  readGgufHeader,
3081
3160
  readModelCatalog,
3161
+ readModelCatalogStamp,
3082
3162
  readModelIdentities,
3083
3163
  readPublicModel,
3084
3164
  reconcileModelFavoriteIds,
@@ -675,7 +675,12 @@ declare function ModelListDropdown({ value: savedValue, localModels: localModels
675
675
  * `@ai-matrx/agents/models/react`). No surface keeps a model cache that misses the event.
676
676
  *
677
677
  * The hub lives on `globalThis` so two bundled copies of this module share one set of listeners.
678
+ *
679
+ * A tab that is not listening (the bus room not joined yet, or asleep) catches up when it comes to the
680
+ * front: `followModelCatalogVisibility({ client })` reads the catalog stamp when the tab hides and again
681
+ * when it shows or takes focus (throttled), and announces a change when the stamp moved.
678
682
  */
683
+
679
684
  /** A `catalog_changed` payload: `{ catalog?: "models" | ..., change?, model_id? }`. */
680
685
  type ModelCatalogChangePayload = Record<string, unknown>;
681
686
 
@@ -799,7 +804,7 @@ interface LocalModel {
799
804
  /** Matrx 2's 1.48 id for a model seeded from its old list (metadata.desktop_id). */
800
805
  desktop_id?: string | null;
801
806
  maker_logo_file_id?: string | null;
802
- /** The admin Catalogs kind (`catalogKindOf`): llm_model, whisper_model, tts_model_file, image_gen_model, video_gen_model, ner_model, wake_word_model, lora. */
807
+ /** The admin Catalogs kind (`catalogKindOf`): llm_model, whisper_model, tts_model_file, image_gen_model, video_gen_model, ner_model, wake_word_model, lora, embedding_model, or unknown (no rule places it; `catalogKindVerdict` says why). */
803
808
  kind?: string;
804
809
  /** At least one variant is offered (Matrx 2 lists it). */
805
810
  offered?: boolean;
@@ -675,7 +675,12 @@ declare function ModelListDropdown({ value: savedValue, localModels: localModels
675
675
  * `@ai-matrx/agents/models/react`). No surface keeps a model cache that misses the event.
676
676
  *
677
677
  * The hub lives on `globalThis` so two bundled copies of this module share one set of listeners.
678
+ *
679
+ * A tab that is not listening (the bus room not joined yet, or asleep) catches up when it comes to the
680
+ * front: `followModelCatalogVisibility({ client })` reads the catalog stamp when the tab hides and again
681
+ * when it shows or takes focus (throttled), and announces a change when the stamp moved.
678
682
  */
683
+
679
684
  /** A `catalog_changed` payload: `{ catalog?: "models" | ..., change?, model_id? }`. */
680
685
  type ModelCatalogChangePayload = Record<string, unknown>;
681
686
 
@@ -799,7 +804,7 @@ interface LocalModel {
799
804
  /** Matrx 2's 1.48 id for a model seeded from its old list (metadata.desktop_id). */
800
805
  desktop_id?: string | null;
801
806
  maker_logo_file_id?: string | null;
802
- /** The admin Catalogs kind (`catalogKindOf`): llm_model, whisper_model, tts_model_file, image_gen_model, video_gen_model, ner_model, wake_word_model, lora. */
807
+ /** The admin Catalogs kind (`catalogKindOf`): llm_model, whisper_model, tts_model_file, image_gen_model, video_gen_model, ner_model, wake_word_model, lora, embedding_model, or unknown (no rule places it; `catalogKindVerdict` says why). */
803
808
  kind?: string;
804
809
  /** At least one variant is offered (Matrx 2 lists it). */
805
810
  offered?: boolean;
@@ -25,6 +25,7 @@ __export(settings_exports, {
25
25
  CATALOGUE_KEYS: () => CATALOGUE_KEYS,
26
26
  EMPTY_UI_GATES: () => EMPTY_UI_GATES,
27
27
  ENUM_OFF_VALUE: () => ENUM_OFF_VALUE,
28
+ NEVER_IMPLICIT_AUTO_KEYS: () => NEVER_IMPLICIT_AUTO_KEYS,
28
29
  PARAM_ALIASES: () => PARAM_ALIASES,
29
30
  SETTINGS_CATALOGUE: () => SETTINGS_CATALOGUE,
30
31
  UI_GATE_EDITABLE_KEYS: () => UI_GATE_EDITABLE_KEYS,
@@ -39,6 +40,7 @@ __export(settings_exports, {
39
40
  extractModelDefaults: () => extractModelDefaults,
40
41
  gateEnabled: () => gateEnabled,
41
42
  getActionForMode: () => getActionForMode,
43
+ isNeverImplicitChoice: () => isNeverImplicitChoice,
42
44
  isOffValue: () => isOffValue,
43
45
  isUiGateKey: () => isUiGateKey,
44
46
  isUnsetChoice: () => isUnsetChoice,
@@ -1032,13 +1034,19 @@ function withSettingState(settings, key, state, control, value) {
1032
1034
  // settings/auto-means-unset.ts
1033
1035
  var AUTO_VALUE = "auto";
1034
1036
  var AUTO_MEANS_UNSET_KEYS = /* @__PURE__ */ new Set([
1035
- "reasoning_effort",
1036
1037
  "visualization"
1037
1038
  ]);
1039
+ var NEVER_IMPLICIT_AUTO_KEYS = /* @__PURE__ */ new Set([
1040
+ "reasoning_effort"
1041
+ ]);
1038
1042
  function isUnsetChoice(key, value) {
1039
1043
  if (value === void 0 || value === null) return true;
1040
1044
  return value === AUTO_VALUE && AUTO_MEANS_UNSET_KEYS.has(key);
1041
1045
  }
1046
+ function isNeverImplicitChoice(key, value) {
1047
+ if (isUnsetChoice(key, value)) return true;
1048
+ return value === AUTO_VALUE && NEVER_IMPLICIT_AUTO_KEYS.has(key);
1049
+ }
1042
1050
 
1043
1051
  // settings/starting-value.ts
1044
1052
  function startingValueFor(key, control) {
@@ -1056,8 +1064,8 @@ function startingValueFor(key, control) {
1056
1064
  value = [];
1057
1065
  }
1058
1066
  }
1059
- if (isUnsetChoice(key, value) && control.type === "enum" && control.enum?.length) {
1060
- value = control.enum.find((choice) => !isUnsetChoice(key, choice));
1067
+ if (isNeverImplicitChoice(key, value) && control.type === "enum" && control.enum?.length) {
1068
+ value = control.enum.find((choice) => !isNeverImplicitChoice(key, choice));
1061
1069
  }
1062
1070
  if (key === "response_format" && typeof value === "string") {
1063
1071
  value = value === "" ? void 0 : { type: value };