@ashx-j/lunr 0.2.4 → 0.2.7
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.
- package/dist/builtin-extensions/ashxj-thinking.d.ts.map +1 -1
- package/dist/builtin-extensions/ashxj-thinking.js +12 -11
- package/dist/builtin-extensions/ashxj-thinking.js.map +1 -1
- package/dist/builtin-extensions/ashxj-tui.d.ts +4 -0
- package/dist/builtin-extensions/ashxj-tui.d.ts.map +1 -1
- package/dist/builtin-extensions/ashxj-tui.js +53 -15
- package/dist/builtin-extensions/ashxj-tui.js.map +1 -1
- package/dist/catalog/models.json +1 -1
- package/dist/catalog/providers/openrouter.json +1 -1
- package/dist/catalog/providers/xai.json +1 -1
- package/dist/catalog/publication.json +2 -2
- package/dist/core/agent-session.d.ts +4 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +28 -6
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/catalog-merge.d.ts +1 -1
- package/dist/core/catalog-merge.d.ts.map +1 -1
- package/dist/core/catalog-merge.js +2 -1
- package/dist/core/catalog-merge.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +1 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/moon.json +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/package.json +4 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Api, type Model } from "@ashx-j/lunr-ai";
|
|
2
2
|
import { type OfficialCatalogSource } from "./official-catalog.ts";
|
|
3
3
|
export type CatalogProviderRefreshStatus = "ok" | "timeout" | "error" | "skipped" | "static";
|
|
4
4
|
export declare function mergeCatalogLayers(args: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog-merge.d.ts","sourceRoot":"","sources":["../../src/core/catalog-merge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"catalog-merge.d.ts","sourceRoot":"","sources":["../../src/core/catalog-merge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,GAAG,EAAE,KAAK,KAAK,EAAyB,MAAM,uBAAuB,CAAC;AACpF,OAAO,EAAY,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE7E,MAAM,MAAM,4BAA4B,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE7F,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACxC,OAAO,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;IAC/B,IAAI,CAAC,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;IAC7B,IAAI,CAAC,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;IAC7B,QAAQ,CAAC,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;CACjC,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAuBf;AAED,qBAAa,oBAAoB;IAChC,OAAO,CAAC,QAAQ,CAAmC;IACnD,OAAO,CAAC,IAAI,CAAmC;IAC/C,OAAO,CAAC,IAAI,CAAmC;IAE/C,WAAW,CAAC,MAAM,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,CAE/C;IAED,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,CAE3C;IAED,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,CAE/D;IAED,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAE5C;IAED,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAExC;IAED,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAExC;CACD;AAYD,wBAAgB,kBAAkB,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,CAAA;CAAE,EAClG,QAAQ,EAAE,CAAC,EACX,OAAO,EAAE,oBAAoB,GAC3B,CAAC,CAYH;AAED,MAAM,WAAW,6BAA6B;IAC7C,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,4BAA4B,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,CAAC,EAAE;QAAE,MAAM,EAAE,qBAAqB,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1F,SAAS,EAAE,SAAS,6BAA6B,EAAE,CAAC;IACpD,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,yFAAyF;AACzF,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,0BAA0B,GAAG,MAAM,CA2CrF;AAcD,wBAAgB,cAAc,CAC7B,OAAO,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,EAC9B,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,EAC1B,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,GACpB,GAAG,CAAC,MAAM,CAAC,CAKb","sourcesContent":["import { type Api, type Model, withXaiEffortMetadata } from \"@ashx-j/lunr-ai\";\nimport { modelKey, type OfficialCatalogSource } from \"./official-catalog.ts\";\n\nexport type CatalogProviderRefreshStatus = \"ok\" | \"timeout\" | \"error\" | \"skipped\" | \"static\";\n\nexport function mergeCatalogLayers(args: {\n\tbakedIn: readonly Model<Api>[];\n\tlive?: readonly Model<Api>[];\n\tuser?: readonly Model<Api>[];\n\tofficial?: readonly Model<Api>[];\n}): Model<Api>[] {\n\tconst byId = new Map<string, Model<Api>>();\n\tfor (const model of args.bakedIn) byId.set(model.id, model);\n\tfor (const model of args.live ?? []) byId.set(model.id, model);\n\tfor (const model of args.user ?? []) byId.set(model.id, model);\n\tfor (const model of args.official ?? []) byId.set(model.id, model);\n\n\tconst seen = new Set<string>();\n\tconst result: Model<Api>[] = [];\n\tfor (const baked of args.bakedIn) {\n\t\tconst merged = byId.get(baked.id);\n\t\tif (!merged) continue;\n\t\tresult.push(merged);\n\t\tseen.add(baked.id);\n\t}\n\tfor (const model of [...(args.live ?? []), ...(args.user ?? []), ...(args.official ?? [])]) {\n\t\tif (seen.has(model.id)) continue;\n\t\tconst winner = byId.get(model.id);\n\t\tif (!winner) continue;\n\t\tresult.push(winner);\n\t\tseen.add(model.id);\n\t}\n\treturn result.map((model) => withXaiEffortMetadata(model));\n}\n\nexport class CatalogOverlaySource {\n\tprivate official = new Map<string, Model<Api>[]>();\n\tprivate user = new Map<string, Model<Api>[]>();\n\tprivate live = new Map<string, Model<Api>[]>();\n\n\tsetOfficial(models: readonly Model<Api>[]): void {\n\t\tthis.official = groupByProvider(models);\n\t}\n\n\tsetUser(models: readonly Model<Api>[]): void {\n\t\tthis.user = groupByProvider(models);\n\t}\n\n\tsetLive(providerId: string, models: readonly Model<Api>[]): void {\n\t\tthis.live.set(providerId, [...models]);\n\t}\n\n\tofficialFor(providerId: string): Model<Api>[] {\n\t\treturn this.official.get(providerId) ?? [];\n\t}\n\n\tuserFor(providerId: string): Model<Api>[] {\n\t\treturn this.user.get(providerId) ?? [];\n\t}\n\n\tliveFor(providerId: string): Model<Api>[] {\n\t\treturn this.live.get(providerId) ?? [];\n\t}\n}\n\nfunction groupByProvider(models: readonly Model<Api>[]): Map<string, Model<Api>[]> {\n\tconst byProvider = new Map<string, Model<Api>[]>();\n\tfor (const model of models) {\n\t\tconst list = byProvider.get(model.provider) ?? [];\n\t\tlist.push(model);\n\t\tbyProvider.set(model.provider, list);\n\t}\n\treturn byProvider;\n}\n\nexport function withCatalogOverlay<T extends { id: string; getModels: () => readonly Model<Api>[] }>(\n\tprovider: T,\n\toverlay: CatalogOverlaySource,\n): T {\n\tconst bakedIn = () => provider.getModels();\n\treturn {\n\t\t...provider,\n\t\tgetModels: () =>\n\t\t\tmergeCatalogLayers({\n\t\t\t\tbakedIn: bakedIn(),\n\t\t\t\tlive: overlay.liveFor(provider.id),\n\t\t\t\tuser: overlay.userFor(provider.id),\n\t\t\t\tofficial: overlay.officialFor(provider.id),\n\t\t\t}),\n\t};\n}\n\nexport interface CatalogRefreshProviderSummary {\n\tid: string;\n\tstatus: CatalogProviderRefreshStatus;\n\tadded?: number;\n\ttotal?: number;\n\terror?: string;\n}\n\nexport interface CatalogRefreshSummaryInput {\n\tofficial?: { source: OfficialCatalogSource; modelCount: number; evictedUserRows: number };\n\tproviders: readonly CatalogRefreshProviderSummary[];\n\tasked?: readonly string[];\n\textraDefaults?: number;\n\tollama?: string;\n}\n\n/** Build the /refresh toast. One hung provider must not become a global timeout line. */\nexport function formatCatalogRefreshSummary(input: CatalogRefreshSummaryInput): string {\n\tconst parts: string[] = [];\n\tif (input.official?.source === \"github\") {\n\t\tconst evicted =\n\t\t\tinput.official.evictedUserRows > 0 ? `; replaced ${input.official.evictedUserRows} user-filled row` : \"\";\n\t\tconst plural = input.official.evictedUserRows === 1 ? \"\" : input.official.evictedUserRows > 0 ? \"s\" : \"\";\n\t\tparts.push(`Official catalog updated (${input.official.modelCount} models)${evicted}${plural}.`);\n\t}\n\n\tconst refreshed: string[] = [];\n\tconst failed: string[] = [];\n\tfor (const provider of input.providers) {\n\t\tif (provider.status === \"ok\") {\n\t\t\tconst added = provider.added ?? 0;\n\t\t\tconst total = provider.total ?? 0;\n\t\t\trefreshed.push(added > 0 ? `${provider.id} (+${added})` : `${provider.id} (${total})`);\n\t\t} else if (provider.status === \"timeout\") {\n\t\t\tfailed.push(`${provider.id} timed out (cached)`);\n\t\t} else if (provider.status === \"error\") {\n\t\t\tfailed.push(formatLiveProviderError(provider));\n\t\t}\n\t}\n\n\tif (refreshed.length > 0) {\n\t\tparts.push(`Refreshed ${refreshed.join(\", \")}.`);\n\t} else if (input.providers.some((provider) => provider.status === \"ok\")) {\n\t\tparts.push(\"Refreshed model catalogs.\");\n\t}\n\n\tif (failed.length > 0) {\n\t\tparts.push(`${failed.join(\"; \")}.`);\n\t}\n\n\tif (input.asked && input.asked.length > 0) {\n\t\tparts.push(`Asked for missing metadata on ${input.asked.join(\", \")}.`);\n\t}\n\tif (input.extraDefaults && input.extraDefaults > 0) {\n\t\tparts.push(`+${input.extraDefaults} more using defaults.`);\n\t}\n\tif (input.ollama) parts.push(input.ollama);\n\n\tif (parts.length === 0) return \"Model catalogs refreshed.\";\n\treturn parts.join(\" \");\n}\n\nfunction formatLiveProviderError(provider: CatalogRefreshProviderSummary): string {\n\tif (\n\t\tprovider.id === \"xai\" &&\n\t\tprovider.error &&\n\t\t/invalid_grant|refresh token revoked/i.test(provider.error) &&\n\t\t!/timed out|aborted|cancelled|ECONN|ENOTFOUND|network/i.test(provider.error)\n\t) {\n\t\treturn \"xai login expired (run /login xai)\";\n\t}\n\treturn provider.error ? `${provider.id} failed (${provider.error})` : `${provider.id} failed`;\n}\n\nexport function knownModelKeys(\n\tbakedIn: readonly Model<Api>[],\n\tofficial: Iterable<string>,\n\tuser: Iterable<string>,\n): Set<string> {\n\tconst keys = new Set<string>(official);\n\tfor (const key of user) keys.add(key);\n\tfor (const model of bakedIn) keys.add(modelKey(model.provider, model.id));\n\treturn keys;\n}\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { withXaiEffortMetadata } from "@ashx-j/lunr-ai";
|
|
1
2
|
import { modelKey } from "./official-catalog.js";
|
|
2
3
|
export function mergeCatalogLayers(args) {
|
|
3
4
|
const byId = new Map();
|
|
@@ -27,7 +28,7 @@ export function mergeCatalogLayers(args) {
|
|
|
27
28
|
result.push(winner);
|
|
28
29
|
seen.add(model.id);
|
|
29
30
|
}
|
|
30
|
-
return result;
|
|
31
|
+
return result.map((model) => withXaiEffortMetadata(model));
|
|
31
32
|
}
|
|
32
33
|
export class CatalogOverlaySource {
|
|
33
34
|
official = new Map();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog-merge.js","sourceRoot":"","sources":["../../src/core/catalog-merge.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Api, Model } from \"@ashx-j/lunr-ai\";\nimport { modelKey, type OfficialCatalogSource } from \"./official-catalog.ts\";\n\nexport type CatalogProviderRefreshStatus = \"ok\" | \"timeout\" | \"error\" | \"skipped\" | \"static\";\n\nexport function mergeCatalogLayers(args: {\n\tbakedIn: readonly Model<Api>[];\n\tlive?: readonly Model<Api>[];\n\tuser?: readonly Model<Api>[];\n\tofficial?: readonly Model<Api>[];\n}): Model<Api>[] {\n\tconst byId = new Map<string, Model<Api>>();\n\tfor (const model of args.bakedIn) byId.set(model.id, model);\n\tfor (const model of args.live ?? []) byId.set(model.id, model);\n\tfor (const model of args.user ?? []) byId.set(model.id, model);\n\tfor (const model of args.official ?? []) byId.set(model.id, model);\n\n\tconst seen = new Set<string>();\n\tconst result: Model<Api>[] = [];\n\tfor (const baked of args.bakedIn) {\n\t\tconst merged = byId.get(baked.id);\n\t\tif (!merged) continue;\n\t\tresult.push(merged);\n\t\tseen.add(baked.id);\n\t}\n\tfor (const model of [...(args.live ?? []), ...(args.user ?? []), ...(args.official ?? [])]) {\n\t\tif (seen.has(model.id)) continue;\n\t\tconst winner = byId.get(model.id);\n\t\tif (!winner) continue;\n\t\tresult.push(winner);\n\t\tseen.add(model.id);\n\t}\n\treturn result;\n}\n\nexport class CatalogOverlaySource {\n\tprivate official = new Map<string, Model<Api>[]>();\n\tprivate user = new Map<string, Model<Api>[]>();\n\tprivate live = new Map<string, Model<Api>[]>();\n\n\tsetOfficial(models: readonly Model<Api>[]): void {\n\t\tthis.official = groupByProvider(models);\n\t}\n\n\tsetUser(models: readonly Model<Api>[]): void {\n\t\tthis.user = groupByProvider(models);\n\t}\n\n\tsetLive(providerId: string, models: readonly Model<Api>[]): void {\n\t\tthis.live.set(providerId, [...models]);\n\t}\n\n\tofficialFor(providerId: string): Model<Api>[] {\n\t\treturn this.official.get(providerId) ?? [];\n\t}\n\n\tuserFor(providerId: string): Model<Api>[] {\n\t\treturn this.user.get(providerId) ?? [];\n\t}\n\n\tliveFor(providerId: string): Model<Api>[] {\n\t\treturn this.live.get(providerId) ?? [];\n\t}\n}\n\nfunction groupByProvider(models: readonly Model<Api>[]): Map<string, Model<Api>[]> {\n\tconst byProvider = new Map<string, Model<Api>[]>();\n\tfor (const model of models) {\n\t\tconst list = byProvider.get(model.provider) ?? [];\n\t\tlist.push(model);\n\t\tbyProvider.set(model.provider, list);\n\t}\n\treturn byProvider;\n}\n\nexport function withCatalogOverlay<T extends { id: string; getModels: () => readonly Model<Api>[] }>(\n\tprovider: T,\n\toverlay: CatalogOverlaySource,\n): T {\n\tconst bakedIn = () => provider.getModels();\n\treturn {\n\t\t...provider,\n\t\tgetModels: () =>\n\t\t\tmergeCatalogLayers({\n\t\t\t\tbakedIn: bakedIn(),\n\t\t\t\tlive: overlay.liveFor(provider.id),\n\t\t\t\tuser: overlay.userFor(provider.id),\n\t\t\t\tofficial: overlay.officialFor(provider.id),\n\t\t\t}),\n\t};\n}\n\nexport interface CatalogRefreshProviderSummary {\n\tid: string;\n\tstatus: CatalogProviderRefreshStatus;\n\tadded?: number;\n\ttotal?: number;\n\terror?: string;\n}\n\nexport interface CatalogRefreshSummaryInput {\n\tofficial?: { source: OfficialCatalogSource; modelCount: number; evictedUserRows: number };\n\tproviders: readonly CatalogRefreshProviderSummary[];\n\tasked?: readonly string[];\n\textraDefaults?: number;\n\tollama?: string;\n}\n\n/** Build the /refresh toast. One hung provider must not become a global timeout line. */\nexport function formatCatalogRefreshSummary(input: CatalogRefreshSummaryInput): string {\n\tconst parts: string[] = [];\n\tif (input.official?.source === \"github\") {\n\t\tconst evicted =\n\t\t\tinput.official.evictedUserRows > 0 ? `; replaced ${input.official.evictedUserRows} user-filled row` : \"\";\n\t\tconst plural = input.official.evictedUserRows === 1 ? \"\" : input.official.evictedUserRows > 0 ? \"s\" : \"\";\n\t\tparts.push(`Official catalog updated (${input.official.modelCount} models)${evicted}${plural}.`);\n\t}\n\n\tconst refreshed: string[] = [];\n\tconst failed: string[] = [];\n\tfor (const provider of input.providers) {\n\t\tif (provider.status === \"ok\") {\n\t\t\tconst added = provider.added ?? 0;\n\t\t\tconst total = provider.total ?? 0;\n\t\t\trefreshed.push(added > 0 ? `${provider.id} (+${added})` : `${provider.id} (${total})`);\n\t\t} else if (provider.status === \"timeout\") {\n\t\t\tfailed.push(`${provider.id} timed out (cached)`);\n\t\t} else if (provider.status === \"error\") {\n\t\t\tfailed.push(formatLiveProviderError(provider));\n\t\t}\n\t}\n\n\tif (refreshed.length > 0) {\n\t\tparts.push(`Refreshed ${refreshed.join(\", \")}.`);\n\t} else if (input.providers.some((provider) => provider.status === \"ok\")) {\n\t\tparts.push(\"Refreshed model catalogs.\");\n\t}\n\n\tif (failed.length > 0) {\n\t\tparts.push(`${failed.join(\"; \")}.`);\n\t}\n\n\tif (input.asked && input.asked.length > 0) {\n\t\tparts.push(`Asked for missing metadata on ${input.asked.join(\", \")}.`);\n\t}\n\tif (input.extraDefaults && input.extraDefaults > 0) {\n\t\tparts.push(`+${input.extraDefaults} more using defaults.`);\n\t}\n\tif (input.ollama) parts.push(input.ollama);\n\n\tif (parts.length === 0) return \"Model catalogs refreshed.\";\n\treturn parts.join(\" \");\n}\n\nfunction formatLiveProviderError(provider: CatalogRefreshProviderSummary): string {\n\tif (\n\t\tprovider.id === \"xai\" &&\n\t\tprovider.error &&\n\t\t/invalid_grant|refresh token revoked/i.test(provider.error) &&\n\t\t!/timed out|aborted|cancelled|ECONN|ENOTFOUND|network/i.test(provider.error)\n\t) {\n\t\treturn \"xai login expired (run /login xai)\";\n\t}\n\treturn provider.error ? `${provider.id} failed (${provider.error})` : `${provider.id} failed`;\n}\n\nexport function knownModelKeys(\n\tbakedIn: readonly Model<Api>[],\n\tofficial: Iterable<string>,\n\tuser: Iterable<string>,\n): Set<string> {\n\tconst keys = new Set<string>(official);\n\tfor (const key of user) keys.add(key);\n\tfor (const model of bakedIn) keys.add(modelKey(model.provider, model.id));\n\treturn keys;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"catalog-merge.js","sourceRoot":"","sources":["../../src/core/catalog-merge.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Api, type Model, withXaiEffortMetadata } from \"@ashx-j/lunr-ai\";\nimport { modelKey, type OfficialCatalogSource } from \"./official-catalog.ts\";\n\nexport type CatalogProviderRefreshStatus = \"ok\" | \"timeout\" | \"error\" | \"skipped\" | \"static\";\n\nexport function mergeCatalogLayers(args: {\n\tbakedIn: readonly Model<Api>[];\n\tlive?: readonly Model<Api>[];\n\tuser?: readonly Model<Api>[];\n\tofficial?: readonly Model<Api>[];\n}): Model<Api>[] {\n\tconst byId = new Map<string, Model<Api>>();\n\tfor (const model of args.bakedIn) byId.set(model.id, model);\n\tfor (const model of args.live ?? []) byId.set(model.id, model);\n\tfor (const model of args.user ?? []) byId.set(model.id, model);\n\tfor (const model of args.official ?? []) byId.set(model.id, model);\n\n\tconst seen = new Set<string>();\n\tconst result: Model<Api>[] = [];\n\tfor (const baked of args.bakedIn) {\n\t\tconst merged = byId.get(baked.id);\n\t\tif (!merged) continue;\n\t\tresult.push(merged);\n\t\tseen.add(baked.id);\n\t}\n\tfor (const model of [...(args.live ?? []), ...(args.user ?? []), ...(args.official ?? [])]) {\n\t\tif (seen.has(model.id)) continue;\n\t\tconst winner = byId.get(model.id);\n\t\tif (!winner) continue;\n\t\tresult.push(winner);\n\t\tseen.add(model.id);\n\t}\n\treturn result.map((model) => withXaiEffortMetadata(model));\n}\n\nexport class CatalogOverlaySource {\n\tprivate official = new Map<string, Model<Api>[]>();\n\tprivate user = new Map<string, Model<Api>[]>();\n\tprivate live = new Map<string, Model<Api>[]>();\n\n\tsetOfficial(models: readonly Model<Api>[]): void {\n\t\tthis.official = groupByProvider(models);\n\t}\n\n\tsetUser(models: readonly Model<Api>[]): void {\n\t\tthis.user = groupByProvider(models);\n\t}\n\n\tsetLive(providerId: string, models: readonly Model<Api>[]): void {\n\t\tthis.live.set(providerId, [...models]);\n\t}\n\n\tofficialFor(providerId: string): Model<Api>[] {\n\t\treturn this.official.get(providerId) ?? [];\n\t}\n\n\tuserFor(providerId: string): Model<Api>[] {\n\t\treturn this.user.get(providerId) ?? [];\n\t}\n\n\tliveFor(providerId: string): Model<Api>[] {\n\t\treturn this.live.get(providerId) ?? [];\n\t}\n}\n\nfunction groupByProvider(models: readonly Model<Api>[]): Map<string, Model<Api>[]> {\n\tconst byProvider = new Map<string, Model<Api>[]>();\n\tfor (const model of models) {\n\t\tconst list = byProvider.get(model.provider) ?? [];\n\t\tlist.push(model);\n\t\tbyProvider.set(model.provider, list);\n\t}\n\treturn byProvider;\n}\n\nexport function withCatalogOverlay<T extends { id: string; getModels: () => readonly Model<Api>[] }>(\n\tprovider: T,\n\toverlay: CatalogOverlaySource,\n): T {\n\tconst bakedIn = () => provider.getModels();\n\treturn {\n\t\t...provider,\n\t\tgetModels: () =>\n\t\t\tmergeCatalogLayers({\n\t\t\t\tbakedIn: bakedIn(),\n\t\t\t\tlive: overlay.liveFor(provider.id),\n\t\t\t\tuser: overlay.userFor(provider.id),\n\t\t\t\tofficial: overlay.officialFor(provider.id),\n\t\t\t}),\n\t};\n}\n\nexport interface CatalogRefreshProviderSummary {\n\tid: string;\n\tstatus: CatalogProviderRefreshStatus;\n\tadded?: number;\n\ttotal?: number;\n\terror?: string;\n}\n\nexport interface CatalogRefreshSummaryInput {\n\tofficial?: { source: OfficialCatalogSource; modelCount: number; evictedUserRows: number };\n\tproviders: readonly CatalogRefreshProviderSummary[];\n\tasked?: readonly string[];\n\textraDefaults?: number;\n\tollama?: string;\n}\n\n/** Build the /refresh toast. One hung provider must not become a global timeout line. */\nexport function formatCatalogRefreshSummary(input: CatalogRefreshSummaryInput): string {\n\tconst parts: string[] = [];\n\tif (input.official?.source === \"github\") {\n\t\tconst evicted =\n\t\t\tinput.official.evictedUserRows > 0 ? `; replaced ${input.official.evictedUserRows} user-filled row` : \"\";\n\t\tconst plural = input.official.evictedUserRows === 1 ? \"\" : input.official.evictedUserRows > 0 ? \"s\" : \"\";\n\t\tparts.push(`Official catalog updated (${input.official.modelCount} models)${evicted}${plural}.`);\n\t}\n\n\tconst refreshed: string[] = [];\n\tconst failed: string[] = [];\n\tfor (const provider of input.providers) {\n\t\tif (provider.status === \"ok\") {\n\t\t\tconst added = provider.added ?? 0;\n\t\t\tconst total = provider.total ?? 0;\n\t\t\trefreshed.push(added > 0 ? `${provider.id} (+${added})` : `${provider.id} (${total})`);\n\t\t} else if (provider.status === \"timeout\") {\n\t\t\tfailed.push(`${provider.id} timed out (cached)`);\n\t\t} else if (provider.status === \"error\") {\n\t\t\tfailed.push(formatLiveProviderError(provider));\n\t\t}\n\t}\n\n\tif (refreshed.length > 0) {\n\t\tparts.push(`Refreshed ${refreshed.join(\", \")}.`);\n\t} else if (input.providers.some((provider) => provider.status === \"ok\")) {\n\t\tparts.push(\"Refreshed model catalogs.\");\n\t}\n\n\tif (failed.length > 0) {\n\t\tparts.push(`${failed.join(\"; \")}.`);\n\t}\n\n\tif (input.asked && input.asked.length > 0) {\n\t\tparts.push(`Asked for missing metadata on ${input.asked.join(\", \")}.`);\n\t}\n\tif (input.extraDefaults && input.extraDefaults > 0) {\n\t\tparts.push(`+${input.extraDefaults} more using defaults.`);\n\t}\n\tif (input.ollama) parts.push(input.ollama);\n\n\tif (parts.length === 0) return \"Model catalogs refreshed.\";\n\treturn parts.join(\" \");\n}\n\nfunction formatLiveProviderError(provider: CatalogRefreshProviderSummary): string {\n\tif (\n\t\tprovider.id === \"xai\" &&\n\t\tprovider.error &&\n\t\t/invalid_grant|refresh token revoked/i.test(provider.error) &&\n\t\t!/timed out|aborted|cancelled|ECONN|ENOTFOUND|network/i.test(provider.error)\n\t) {\n\t\treturn \"xai login expired (run /login xai)\";\n\t}\n\treturn provider.error ? `${provider.id} failed (${provider.error})` : `${provider.id} failed`;\n}\n\nexport function knownModelKeys(\n\tbakedIn: readonly Model<Api>[],\n\tofficial: Iterable<string>,\n\tuser: Iterable<string>,\n): Set<string> {\n\tconst keys = new Set<string>(official);\n\tfor (const key of user) keys.add(key);\n\tfor (const model of bakedIn) keys.add(modelKey(model.provider, model.id));\n\treturn keys;\n}\n"]}
|