@vymalo/opencode-models-info 0.11.0 → 0.14.0

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/mapping.js CHANGED
@@ -1,152 +1,166 @@
1
- const OPENCODE_MODALITIES = new Set(["text", "audio", "image", "video", "pdf"]);
1
+ const OPENCODE_MODALITIES = new Set([
2
+ "text",
3
+ "audio",
4
+ "image",
5
+ "video",
6
+ "pdf"
7
+ ]);
2
8
  /**
3
- * Pure transformation from an OpenRouter model entry to the subset of
4
- * OpenCode `ModelConfig` fields we know how to populate. Returns only the
5
- * fields we can derive; callers do the upstream-wins merge.
6
- */
9
+ * Pure transformation from an OpenRouter model entry to the subset of
10
+ * OpenCode `ModelConfig` fields we know how to populate. Returns only the
11
+ * fields we can derive; callers do the upstream-wins merge.
12
+ */
7
13
  export function mapOpenRouterEntry(entry, overwrite) {
8
- const out = {};
9
- if (entry.name) {
10
- out.name = entry.name;
11
- }
12
- const context = entry.top_provider?.context_length ?? entry.context_length;
13
- const output = entry.top_provider?.max_completion_tokens;
14
- if (typeof context === "number" && typeof output === "number") {
15
- out.limit = { context, output };
16
- }
17
- else if (typeof context === "number") {
18
- // OpenCode requires both fields when `limit` is set. Skip rather than fake.
19
- }
20
- const cost = mapPricing(entry.pricing);
21
- if (cost) {
22
- out.cost = cost;
23
- }
24
- const inputMods = filterModalities(entry.architecture?.input_modalities);
25
- const outputMods = filterModalities(entry.architecture?.output_modalities);
26
- if (inputMods.length > 0 && outputMods.length > 0) {
27
- out.modalities = { input: inputMods, output: outputMods };
28
- }
29
- const params = entry.supported_parameters ?? [];
30
- const paramSet = new Set(params.map((p) => p.toLowerCase()));
31
- // We can only *assert a capability false* when the source actually told us
32
- // about it. An absent `supported_parameters` / `input_modalities` means "we
33
- // don't know" never a misleading `false`.
34
- const knowsParams = Array.isArray(entry.supported_parameters);
35
- const knowsInputMods = Array.isArray(entry.architecture?.input_modalities);
36
- setCapability(out, "tool_call", paramSet.has("tools") || paramSet.has("tool_choice"), {
37
- known: knowsParams,
38
- overwrite
39
- });
40
- setCapability(out, "reasoning", paramSet.has("reasoning") || paramSet.has("reasoning_effort") || paramSet.has("thinking"), { known: knowsParams, overwrite });
41
- setCapability(out, "temperature", paramSet.has("temperature"), {
42
- known: knowsParams,
43
- overwrite
44
- });
45
- setCapability(out, "attachment", inputMods.some((m) => m !== "text"), {
46
- known: knowsInputMods,
47
- overwrite
48
- });
49
- return out;
14
+ const out = {};
15
+ if (entry.name) {
16
+ out.name = entry.name;
17
+ }
18
+ const context = entry.top_provider?.context_length ?? entry.context_length;
19
+ const output = entry.top_provider?.max_completion_tokens;
20
+ if (typeof context === "number" && typeof output === "number") {
21
+ out.limit = {
22
+ context,
23
+ output
24
+ };
25
+ } else if (typeof context === "number") {}
26
+ const cost = mapPricing(entry.pricing);
27
+ if (cost) {
28
+ out.cost = cost;
29
+ }
30
+ const inputMods = filterModalities(entry.architecture?.input_modalities);
31
+ const outputMods = filterModalities(entry.architecture?.output_modalities);
32
+ if (inputMods.length > 0 && outputMods.length > 0) {
33
+ out.modalities = {
34
+ input: inputMods,
35
+ output: outputMods
36
+ };
37
+ }
38
+ const params = entry.supported_parameters ?? [];
39
+ const paramSet = new Set(params.map((p) => p.toLowerCase()));
40
+ // We can only *assert a capability false* when the source actually told us
41
+ // about it. An absent `supported_parameters` / `input_modalities` means "we
42
+ // don't know" never a misleading `false`.
43
+ const knowsParams = Array.isArray(entry.supported_parameters);
44
+ const knowsInputMods = Array.isArray(entry.architecture?.input_modalities);
45
+ setCapability(out, "tool_call", paramSet.has("tools") || paramSet.has("tool_choice"), {
46
+ known: knowsParams,
47
+ overwrite
48
+ });
49
+ setCapability(out, "reasoning", paramSet.has("reasoning") || paramSet.has("reasoning_effort") || paramSet.has("thinking"), {
50
+ known: knowsParams,
51
+ overwrite
52
+ });
53
+ setCapability(out, "temperature", paramSet.has("temperature"), {
54
+ known: knowsParams,
55
+ overwrite
56
+ });
57
+ setCapability(out, "attachment", inputMods.some((m) => m !== "text"), {
58
+ known: knowsInputMods,
59
+ overwrite
60
+ });
61
+ return out;
50
62
  }
51
63
  /**
52
- * Emit a capability flag. By default these are *true-only*: an absent
53
- * capability stays `undefined`, which under upstream-wins correctly means
54
- * "leave whatever is there". But a field opted into `overwrite` wants the
55
- * endpoint's answer to win outright — so we must also emit an explicit `false`
56
- * to clear a stale `true` another plugin stamped. We only do that when the
57
- * source actually carried the relevant data (`known`); otherwise there is
58
- * nothing to assert and the field stays `undefined`.
59
- */
64
+ * Emit a capability flag. By default these are *true-only*: an absent
65
+ * capability stays `undefined`, which under upstream-wins correctly means
66
+ * "leave whatever is there". But a field opted into `overwrite` wants the
67
+ * endpoint's answer to win outright — so we must also emit an explicit `false`
68
+ * to clear a stale `true` another plugin stamped. We only do that when the
69
+ * source actually carried the relevant data (`known`); otherwise there is
70
+ * nothing to assert and the field stays `undefined`.
71
+ */
60
72
  function setCapability(out, field, present, opts) {
61
- if (present) {
62
- out[field] = true;
63
- }
64
- else if (opts.known && opts.overwrite?.has(field)) {
65
- out[field] = false;
66
- }
73
+ if (present) {
74
+ out[field] = true;
75
+ } else if (opts.known && opts.overwrite?.has(field)) {
76
+ out[field] = false;
77
+ }
67
78
  }
68
79
  function mapPricing(pricing) {
69
- if (!pricing) {
70
- return undefined;
71
- }
72
- const input = perMillion(pricing.prompt);
73
- const output = perMillion(pricing.completion);
74
- if (input === undefined || output === undefined) {
75
- return undefined;
76
- }
77
- const cost = { input, output };
78
- const cacheRead = perMillion(pricing.input_cache_read);
79
- if (cacheRead !== undefined) {
80
- cost.cache_read = cacheRead;
81
- }
82
- const cacheWrite = perMillion(pricing.input_cache_write);
83
- if (cacheWrite !== undefined) {
84
- cost.cache_write = cacheWrite;
85
- }
86
- return cost;
80
+ if (!pricing) {
81
+ return undefined;
82
+ }
83
+ const input = perMillion(pricing.prompt);
84
+ const output = perMillion(pricing.completion);
85
+ if (input === undefined || output === undefined) {
86
+ return undefined;
87
+ }
88
+ const cost = {
89
+ input,
90
+ output
91
+ };
92
+ const cacheRead = perMillion(pricing.input_cache_read);
93
+ if (cacheRead !== undefined) {
94
+ cost.cache_read = cacheRead;
95
+ }
96
+ const cacheWrite = perMillion(pricing.input_cache_write);
97
+ if (cacheWrite !== undefined) {
98
+ cost.cache_write = cacheWrite;
99
+ }
100
+ return cost;
87
101
  }
88
102
  /** OpenRouter pricing is a string per-token in USD; OpenCode stores per-1M-token. */
89
103
  function perMillion(raw) {
90
- if (raw === undefined || raw === null || raw === "") {
91
- return undefined;
92
- }
93
- const parsed = Number.parseFloat(raw);
94
- if (!Number.isFinite(parsed)) {
95
- return undefined;
96
- }
97
- return roundTo(parsed * 1_000_000, 6);
104
+ if (raw === undefined || raw === null || raw === "") {
105
+ return undefined;
106
+ }
107
+ const parsed = Number.parseFloat(raw);
108
+ if (!Number.isFinite(parsed)) {
109
+ return undefined;
110
+ }
111
+ return roundTo(parsed * 1e6, 6);
98
112
  }
99
113
  function roundTo(value, decimals) {
100
- const factor = 10 ** decimals;
101
- return Math.round(value * factor) / factor;
114
+ const factor = 10 ** decimals;
115
+ return Math.round(value * factor) / factor;
102
116
  }
103
117
  /**
104
- * A model is "text-only" when the source reported modalities and both input
105
- * and output are exactly `["text"]` — no vision/audio/video/pdf on either
106
- * side. Undefined `modalities` means the source never told us, so we can't
107
- * claim text-only (consistent with the true-only / "known" pattern above).
108
- */
118
+ * A model is "text-only" when the source reported modalities and both input
119
+ * and output are exactly `["text"]` — no vision/audio/video/pdf on either
120
+ * side. Undefined `modalities` means the source never told us, so we can't
121
+ * claim text-only (consistent with the true-only / "known" pattern above).
122
+ */
109
123
  export function isTextOnlyModality(modalities) {
110
- if (!modalities) {
111
- return false;
112
- }
113
- const isTextOnlyList = (mods) => mods.length === 1 && mods[0] === "text";
114
- return isTextOnlyList(modalities.input) && isTextOnlyList(modalities.output);
124
+ if (!modalities) {
125
+ return false;
126
+ }
127
+ const isTextOnlyList = (mods) => mods.length === 1 && mods[0] === "text";
128
+ return isTextOnlyList(modalities.input) && isTextOnlyList(modalities.output);
115
129
  }
116
130
  function filterModalities(values) {
117
- if (!values) {
118
- return [];
119
- }
120
- const out = [];
121
- for (const value of values) {
122
- if (OPENCODE_MODALITIES.has(value) &&
123
- !out.includes(value)) {
124
- out.push(value);
125
- }
126
- }
127
- return out;
131
+ if (!values) {
132
+ return [];
133
+ }
134
+ const out = [];
135
+ for (const value of values) {
136
+ if (OPENCODE_MODALITIES.has(value) && !out.includes(value)) {
137
+ out.push(value);
138
+ }
139
+ }
140
+ return out;
128
141
  }
129
142
  /**
130
- * Merge a derived metadata snapshot onto an existing OpenCode model entry.
131
- * Upstream wins by default: any field already present is left untouched.
132
- * Returns the same object reference (mutated) for ergonomic chaining.
133
- *
134
- * `overwrite` opts specific fields *out* of upstream-wins, letting the derived
135
- * (endpoint) value replace one that's already set. This exists because another
136
- * plugin (e.g. `@vymalo/opencode-oauth2`) may auto-stamp a field such as `name`
137
- * before this hook runs — to upstream-wins that looks like deliberate user
138
- * config, so without an opt-out the endpoint's value can never land. A field
139
- * named in `overwrite` only wins when the derived value is actually present.
140
- */
143
+ * Merge a derived metadata snapshot onto an existing OpenCode model entry.
144
+ * Upstream wins by default: any field already present is left untouched.
145
+ * Returns the same object reference (mutated) for ergonomic chaining.
146
+ *
147
+ * `overwrite` opts specific fields *out* of upstream-wins, letting the derived
148
+ * (endpoint) value replace one that's already set. This exists because another
149
+ * plugin (e.g. `@vymalo/opencode-oauth2`) may auto-stamp a field such as `name`
150
+ * before this hook runs — to upstream-wins that looks like deliberate user
151
+ * config, so without an opt-out the endpoint's value can never land. A field
152
+ * named in `overwrite` only wins when the derived value is actually present.
153
+ */
141
154
  export function mergeIntoModel(existing, derived, overwrite) {
142
- for (const [key, value] of Object.entries(derived)) {
143
- if (value === undefined) {
144
- continue;
145
- }
146
- if (existing[key] === undefined || overwrite?.has(key)) {
147
- existing[key] = value;
148
- }
149
- }
150
- return existing;
155
+ for (const [key, value] of Object.entries(derived)) {
156
+ if (value === undefined) {
157
+ continue;
158
+ }
159
+ if (existing[key] === undefined || overwrite?.has(key)) {
160
+ existing[key] = value;
161
+ }
162
+ }
163
+ return existing;
151
164
  }
165
+
152
166
  //# sourceMappingURL=mapping.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mapping.js","sourceRoot":"","sources":["../src/mapping.ts"],"names":[],"mappings":"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"}
1
+ {"mappings":"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","names":[],"sources":["../src/mapping.ts"],"version":3,"file":"mapping.js","sourceRoot":""}
@@ -2,10 +2,10 @@ import type { Plugin } from "@opencode-ai/plugin";
2
2
  import { type CacheStore } from "./cache.js";
3
3
  import { type Logger } from "./logging.js";
4
4
  export interface OpenCodePluginFactoryOptions {
5
- logger?: Logger;
6
- fetchImpl?: typeof fetch;
7
- cache?: CacheStore;
8
- cacheDir?: string;
5
+ logger?: Logger;
6
+ fetchImpl?: typeof fetch;
7
+ cache?: CacheStore;
8
+ cacheDir?: string;
9
9
  }
10
10
  export declare function createOpencodeModelsInfoPlugin(factoryOptions?: OpenCodePluginFactoryOptions): Plugin;
11
11
  export declare const OpencodeModelsInfoPlugin: Plugin;
package/dist/opencode.js CHANGED
@@ -3,79 +3,80 @@ import { createJsonConsoleLogger, DEFAULT_LOG_LEVEL, fromOpenCodeLogLevel, LOG_L
3
3
  import { enrichConfig, startCacheRefreshSchedulers } from "./plugin.js";
4
4
  const PLUGIN_SERVICE_NAME = "opencode-models-info-plugin";
5
5
  /**
6
- * Pipe plugin logs through OpenCode's `client.app.log` so they show up in the
7
- * host's structured log stream, with the JSON console as a reliable fallback.
8
- * Mirrors the pattern used by `@vymalo/opencode-oauth2`.
9
- */
6
+ * Pipe plugin logs through OpenCode's `client.app.log` so they show up in the
7
+ * host's structured log stream, with the JSON console as a reliable fallback.
8
+ * Mirrors the pattern used by `@vymalo/opencode-oauth2`.
9
+ */
10
10
  function createOpenCodeLogger(client, getMinLevel) {
11
- const fallback = createJsonConsoleLogger("debug");
12
- // OpenCode already captures plugin logs via client.app.log (and filters them
13
- // by its own log level). Mirroring every event to stdout on top of that just
14
- // floods the terminal, so only mirror warn/error to the JSON console by
15
- // default; set VYMALO_PLUGIN_CONSOLE_LOG=1 to restore full console output.
16
- const consoleAll = /^(1|true|yes|on)$/i.test(process.env.VYMALO_PLUGIN_CONSOLE_LOG ?? "");
17
- const write = (level, event, fields) => {
18
- if (LOG_LEVEL_PRIORITY[level] < LOG_LEVEL_PRIORITY[getMinLevel()]) {
19
- return;
20
- }
21
- if (consoleAll || level === "warn" || level === "error") {
22
- fallback[level](event, fields);
23
- }
24
- // OpenCode's log API has no `trace` tier — fold it into the host's most
25
- // verbose level (`debug`) for the wire payload; our own `getMinLevel()`
26
- // gate above is what actually unlocks trace events.
27
- const hostLevel = level === "trace" ? "debug" : level;
28
- void client.app
29
- .log({
30
- body: {
31
- service: PLUGIN_SERVICE_NAME,
32
- level: hostLevel,
33
- message: event,
34
- extra: fields
35
- }
36
- })
37
- .catch(() => {
38
- /* best-effort */
39
- });
40
- };
41
- return {
42
- trace: (event, fields) => write("trace", event, fields),
43
- debug: (event, fields) => write("debug", event, fields),
44
- info: (event, fields) => write("info", event, fields),
45
- warn: (event, fields) => write("warn", event, fields),
46
- error: (event, fields) => write("error", event, fields)
47
- };
11
+ const fallback = createJsonConsoleLogger("debug");
12
+ // OpenCode already captures plugin logs via client.app.log (and filters them
13
+ // by its own log level). Mirroring every event to stdout on top of that just
14
+ // floods the terminal, so only mirror warn/error to the JSON console by
15
+ // default; set VYMALO_PLUGIN_CONSOLE_LOG=1 to restore full console output.
16
+ const consoleAll = /^(1|true|yes|on)$/i.test(process.env.VYMALO_PLUGIN_CONSOLE_LOG ?? "");
17
+ const write = (level, event, fields) => {
18
+ if (LOG_LEVEL_PRIORITY[level] < LOG_LEVEL_PRIORITY[getMinLevel()]) {
19
+ return;
20
+ }
21
+ if (consoleAll || level === "warn" || level === "error") {
22
+ fallback[level](event, fields);
23
+ }
24
+ // OpenCode's log API has no `trace` tier — fold it into the host's most
25
+ // verbose level (`debug`) for the wire payload; our own `getMinLevel()`
26
+ // gate above is what actually unlocks trace events.
27
+ const hostLevel = level === "trace" ? "debug" : level;
28
+ void client.app.log({ body: {
29
+ service: PLUGIN_SERVICE_NAME,
30
+ level: hostLevel,
31
+ message: event,
32
+ extra: fields
33
+ } }).catch(() => {
34
+ /* best-effort */
35
+ });
36
+ };
37
+ return {
38
+ trace: (event, fields) => write("trace", event, fields),
39
+ debug: (event, fields) => write("debug", event, fields),
40
+ info: (event, fields) => write("info", event, fields),
41
+ warn: (event, fields) => write("warn", event, fields),
42
+ error: (event, fields) => write("error", event, fields)
43
+ };
48
44
  }
49
45
  export function createOpencodeModelsInfoPlugin(factoryOptions = {}) {
50
- return async ({ client }) => {
51
- let currentLogLevel = DEFAULT_LOG_LEVEL;
52
- const logger = factoryOptions.logger ?? createOpenCodeLogger(client, () => currentLogLevel);
53
- const cache = factoryOptions.cache ?? new FileCacheStore(factoryOptions.cacheDir);
54
- let schedulers = [];
55
- const stopSchedulers = () => {
56
- for (const handle of schedulers) {
57
- handle.stop();
58
- }
59
- schedulers = [];
60
- };
61
- return {
62
- config: async (config) => {
63
- currentLogLevel = fromOpenCodeLogLevel(config.logLevel) ?? DEFAULT_LOG_LEVEL;
64
- const deps = { cache, logger, fetchImpl: factoryOptions.fetchImpl };
65
- await enrichConfig(config, deps);
66
- // OpenCode re-runs `config` on certain config edits — stop the
67
- // schedulers from any prior run before starting fresh ones so a
68
- // rebuilt config never leaks a duplicate background timer per
69
- // provider.
70
- stopSchedulers();
71
- schedulers = startCacheRefreshSchedulers(config, deps);
72
- },
73
- dispose: async () => {
74
- stopSchedulers();
75
- }
76
- };
77
- };
46
+ return async ({ client }) => {
47
+ let currentLogLevel = DEFAULT_LOG_LEVEL;
48
+ const logger = factoryOptions.logger ?? createOpenCodeLogger(client, () => currentLogLevel);
49
+ const cache = factoryOptions.cache ?? new FileCacheStore(factoryOptions.cacheDir);
50
+ let schedulers = [];
51
+ const stopSchedulers = () => {
52
+ for (const handle of schedulers) {
53
+ handle.stop();
54
+ }
55
+ schedulers = [];
56
+ };
57
+ return {
58
+ config: async (config) => {
59
+ currentLogLevel = fromOpenCodeLogLevel(config.logLevel) ?? DEFAULT_LOG_LEVEL;
60
+ const deps = {
61
+ cache,
62
+ logger,
63
+ fetchImpl: factoryOptions.fetchImpl
64
+ };
65
+ await enrichConfig(config, deps);
66
+ // OpenCode re-runs `config` on certain config edits — stop the
67
+ // schedulers from any prior run before starting fresh ones so a
68
+ // rebuilt config never leaks a duplicate background timer per
69
+ // provider.
70
+ stopSchedulers();
71
+ schedulers = startCacheRefreshSchedulers(config, deps);
72
+ },
73
+ dispose: async () => {
74
+ stopSchedulers();
75
+ }
76
+ };
77
+ };
78
78
  }
79
79
  export const OpencodeModelsInfoPlugin = createOpencodeModelsInfoPlugin();
80
80
  export default OpencodeModelsInfoPlugin;
81
+
81
82
  //# sourceMappingURL=opencode.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"opencode.js","sourceRoot":"","sources":["../src/opencode.ts"],"names":[],"mappings":"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"}
1
+ {"mappings":"AAEA,SAA0B,sBAAsB;AAChD,SACE,yBACA,mBACA,sBAEA,0BAGK;AACP,SAAiC,cAAc,mCAAmC;AAGlF,MAAM,sBAAsB;;;;;;AAgB5B,SAAS,qBAAqB,QAA+B,aAAqC;CAChG,MAAM,WAAW,wBAAwB,OAAO;;;;;CAKhD,MAAM,aAAa,qBAAqB,KAAK,QAAQ,IAAI,6BAA6B,EAAE;CAExF,MAAM,SAAS,OAAiB,OAAe,WAAuB;EACpE,IAAI,mBAAmB,SAAS,mBAAmB,YAAY,IAAI;GACjE;EACF;EACA,IAAI,cAAc,UAAU,UAAU,UAAU,SAAS;GACvD,SAAS,MAAM,CAAC,OAAO,MAAM;EAC/B;;;;EAIA,MAAM,YAAY,UAAU,UAAU,UAAU;EAChD,KAAK,OAAO,IACT,IAAI,EACH,MAAM;GACJ,SAAS;GACT,OAAO;GACP,SAAS;GACT,OAAO;EACT,EACF,CAAC,CAAC,CACD,YAAY;;EAEb,CAAC;CACL;CAEA,OAAO;EACL,QAAQ,OAAO,WAAW,MAAM,SAAS,OAAO,MAAM;EACtD,QAAQ,OAAO,WAAW,MAAM,SAAS,OAAO,MAAM;EACtD,OAAO,OAAO,WAAW,MAAM,QAAQ,OAAO,MAAM;EACpD,OAAO,OAAO,WAAW,MAAM,QAAQ,OAAO,MAAM;EACpD,QAAQ,OAAO,WAAW,MAAM,SAAS,OAAO,MAAM;CACxD;AACF;AAEA,OAAO,SAAS,+BACd,iBAA+C,CAAC,GACxC;CACR,OAAO,OAAO,EAAE,aAAa;EAC3B,IAAI,kBAA4B;EAChC,MAAM,SAAS,eAAe,UAAU,qBAAqB,cAAc,eAAe;EAC1F,MAAM,QAAQ,eAAe,SAAS,IAAI,eAAe,eAAe,QAAQ;EAChF,IAAI,aAAgC,CAAC;EAErC,MAAM,uBAA6B;GACjC,KAAK,MAAM,UAAU,YAAY;IAC/B,OAAO,KAAK;GACd;GACA,aAAa,CAAC;EAChB;EAEA,OAAO;GACL,QAAQ,OAAO,WAA2B;IACxC,kBAAkB,qBAAqB,OAAO,QAAQ,KAAK;IAC3D,MAAM,OAAO;KAAE;KAAO;KAAQ,WAAW,eAAe;IAAU;IAClE,MAAM,aAAa,QAA6B,IAAI;;;;;IAMpD,eAAe;IACf,aAAa,4BAA4B,QAA6B,IAAI;GAC5E;GACA,SAAS,YAAY;IACnB,eAAe;GACjB;EACF;CACF;AACF;AAEA,OAAO,MAAM,2BAAmC,+BAA+B;AAE/E,eAAe","names":[],"sources":["../src/opencode.ts"],"version":3,"file":"opencode.js","sourceRoot":""}
package/dist/plugin.d.ts CHANGED
@@ -3,38 +3,38 @@ import type { Logger } from "./logging.js";
3
3
  import { type SchedulerHandle } from "./scheduler.js";
4
4
  export type ProviderOptions = Record<string, unknown> | undefined;
5
5
  export interface ProviderConfigLike {
6
- options?: Record<string, unknown>;
7
- models?: Record<string, Record<string, unknown>>;
6
+ options?: Record<string, unknown>;
7
+ models?: Record<string, Record<string, unknown>>;
8
8
  }
9
9
  export interface EnrichConfigInput {
10
- provider?: Record<string, ProviderConfigLike>;
10
+ provider?: Record<string, ProviderConfigLike>;
11
11
  }
12
12
  export interface EnrichDeps {
13
- cache: CacheStore;
14
- logger: Logger;
15
- fetchImpl?: typeof fetch;
16
- now?: () => number;
13
+ cache: CacheStore;
14
+ logger: Logger;
15
+ fetchImpl?: typeof fetch;
16
+ now?: () => number;
17
17
  }
18
18
  /**
19
- * Walk every provider in the assembled OpenCode config, fetch its
20
- * `meta.modelsInfoUrl` (if any) — honoring the cache — and merge derived
21
- * metadata onto each matching model entry. Runs providers in parallel; one
22
- * failure never blocks others.
23
- */
19
+ * Walk every provider in the assembled OpenCode config, fetch its
20
+ * `meta.modelsInfoUrl` (if any) — honoring the cache — and merge derived
21
+ * metadata onto each matching model entry. Runs providers in parallel; one
22
+ * failure never blocks others.
23
+ */
24
24
  export declare function enrichConfig(input: EnrichConfigInput, deps: EnrichDeps): Promise<void>;
25
25
  /**
26
- * Start one background refresh scheduler per opted-in provider, keeping the
27
- * on-disk cache warm at `meta.modelsInfoTtlSeconds` cadence (the same knob
28
- * that already governs cache freshness — no separate interval to configure).
29
- *
30
- * `config` only runs at plugin load and on rare config-signature changes
31
- * (see docs/models-info.md#periodic-refresh), so a long-lived OpenCode
32
- * process would otherwise keep serving whatever the catalog looked like at
33
- * boot until it happens to restart. This closes that gap for the *next*
34
- * `config` run — it cannot push a live update into an already-open session,
35
- * since a config hook has no way to hot-patch a running one. Callers own the
36
- * returned handles' lifecycle: stop them when the config that produced them
37
- * is superseded (a rebuilt `config` hook) or the plugin is disposed.
38
- */
26
+ * Start one background refresh scheduler per opted-in provider, keeping the
27
+ * on-disk cache warm at `meta.modelsInfoTtlSeconds` cadence (the same knob
28
+ * that already governs cache freshness — no separate interval to configure).
29
+ *
30
+ * `config` only runs at plugin load and on rare config-signature changes
31
+ * (see docs/models-info.md#periodic-refresh), so a long-lived OpenCode
32
+ * process would otherwise keep serving whatever the catalog looked like at
33
+ * boot until it happens to restart. This closes that gap for the *next*
34
+ * `config` run — it cannot push a live update into an already-open session,
35
+ * since a config hook has no way to hot-patch a running one. Callers own the
36
+ * returned handles' lifecycle: stop them when the config that produced them
37
+ * is superseded (a rebuilt `config` hook) or the plugin is disposed.
38
+ */
39
39
  export declare function startCacheRefreshSchedulers(input: EnrichConfigInput, deps: EnrichDeps): SchedulerHandle[];
40
40
  export { FileCacheStore };