zcode-workbuddy-connect 0.0.0-stage → 1.0.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/src/catalog.js ADDED
@@ -0,0 +1,100 @@
1
+ /**
2
+ * WorkBuddy model catalog: a static fallback list captured from the live CN
3
+ * endpoint, replaced by the upstream's dynamic answer once it loads.
4
+ *
5
+ * The fallback exists so the provider registers a usable roster even while the
6
+ * first fetch is in flight or offline. It is deliberately *not* a promise about
7
+ * the upstream's current state.
8
+ *
9
+ * @module zcode-workbuddy-connect/catalog
10
+ */
11
+
12
+ import { modelWithCurrentPromotion } from './upstream.js'
13
+
14
+ /**
15
+ * Static CLI models observed on the CN endpoint. Reasoning metadata is taken
16
+ * verbatim from the live endpoint — each model's supported effort set and
17
+ * whether thinking can be disabled — and the `free` flag follows the upstream
18
+ * `x0.00` credits marker.
19
+ *
20
+ * Rows without `supportedEfforts` carry only a default effort.
21
+ */
22
+ export const FALLBACK_WORKBUDDY_MODELS = [
23
+ { id: 'auto', name: 'Auto', contextWindow: 256_000, maxTokens: 32_000, supportsImages: true, reasoning: { supports: false, onlyReasoning: false, defaultEffort: 'high', canDisableThinking: true }, billing: { free: false } },
24
+ { id: 'hy4-preview', name: 'Hy4 preview', contextWindow: 1_000_000, maxTokens: 64_000, supportsImages: true, reasoning: { supports: true, onlyReasoning: true, supportedEfforts: ['high'], defaultEffort: 'high', canDisableThinking: false }, billing: { free: false, rateUnknown: true } },
25
+ { id: 'hy3', name: 'Hy3', contextWindow: 192_000, maxTokens: 64_000, supportsImages: true, reasoning: { supports: false, onlyReasoning: false, defaultEffort: 'high', canDisableThinking: true }, billing: { credits: 'x0.00', free: true } },
26
+ { id: 'hy3-x', name: 'Hy3-X', contextWindow: 192_000, maxTokens: 64_000, supportsImages: true, reasoning: { supports: true, onlyReasoning: true, supportedEfforts: ['low', 'high'], defaultEffort: 'high', canDisableThinking: false }, billing: { credits: 'x0.05', free: false } },
27
+ { id: 'deepseek-v4.1-flash', name: 'Deepseek-V4.1-Flash', contextWindow: 1_000_000, maxTokens: 128_000, supportsImages: true, reasoning: { supports: false, onlyReasoning: false, defaultEffort: 'high', canDisableThinking: true }, billing: { credits: 'x0.03', free: false } },
28
+ { id: 'glm-5.3', name: 'GLM-5.3', contextWindow: 1_000_000, maxTokens: 64_000, supportsImages: true, reasoning: { supports: true, onlyReasoning: true, supportedEfforts: ['low', 'high', 'max'], defaultEffort: 'high', canDisableThinking: true }, billing: { credits: 'x0.79', free: false } },
29
+ { id: 'glm-5.3-flash', name: 'GLM-5.3-Flash', contextWindow: 1_000_000, maxTokens: 32_000, supportsImages: true, reasoning: { supports: true, onlyReasoning: true, supportedEfforts: ['low', 'high', 'max'], defaultEffort: 'high', canDisableThinking: true }, billing: { credits: 'x0.06', free: false } },
30
+ { id: 'glm-5.2', name: 'GLM-5.2', contextWindow: 1_000_000, maxTokens: 64_000, supportsImages: true, reasoning: { supports: false, onlyReasoning: false, defaultEffort: 'medium', canDisableThinking: true }, billing: { credits: 'x0.79', free: false } },
31
+ { id: 'glm-5.1', name: 'GLM-5.1', contextWindow: 200_000, maxTokens: 48_000, supportsImages: false, reasoning: { supports: false, onlyReasoning: false, defaultEffort: 'medium', canDisableThinking: true }, billing: { credits: 'x0.79', free: false } },
32
+ { id: 'glm-5v-turbo', name: 'GLM-5v-Turbo', contextWindow: 200_000, maxTokens: 64_000, supportsImages: true, reasoning: { supports: false, onlyReasoning: false, defaultEffort: 'medium', canDisableThinking: true }, billing: { credits: 'x0.71', free: false } },
33
+ { id: 'kimi-k3-1', name: 'Kimi-K3', contextWindow: 1_000_000, maxTokens: 32_000, supportsImages: true, reasoning: { supports: false, onlyReasoning: false, defaultEffort: 'medium', canDisableThinking: true }, billing: { credits: 'x1.62', free: false } },
34
+ { id: 'kimi-k2.8-preview', name: 'Kimi-K2.8-Preview', contextWindow: 1_000_000, maxTokens: 64_000, supportsImages: true, reasoning: { supports: true, onlyReasoning: true, supportedEfforts: ['low', 'high', 'max'], defaultEffort: 'high', canDisableThinking: true }, billing: { credits: 'x0.77', free: false } },
35
+ { id: 'kimi-k2.7', name: 'Kimi-K2.7-Code', contextWindow: 256_000, maxTokens: 32_000, supportsImages: true, reasoning: { supports: false, onlyReasoning: false, defaultEffort: 'medium', canDisableThinking: true }, billing: { credits: 'x0.57', free: false } },
36
+ { id: 'kimi-k2.6', name: 'Kimi-K2.6', contextWindow: 256_000, maxTokens: 32_000, supportsImages: true, reasoning: { supports: false, onlyReasoning: false, defaultEffort: 'medium', canDisableThinking: true }, billing: { credits: 'x0.52', free: false } },
37
+ { id: 'minimax-m3', name: 'MiniMax-M3', contextWindow: 512_000, maxTokens: 64_000, supportsImages: true, reasoning: { supports: false, onlyReasoning: false, defaultEffort: 'medium', canDisableThinking: true }, billing: { credits: 'x0.25', free: false } },
38
+ { id: 'deepseek-v4-pro', name: 'Deepseek-v4-Pro', contextWindow: 1_000_000, maxTokens: 128_000, supportsImages: true, reasoning: { supports: false, onlyReasoning: false, defaultEffort: 'high', canDisableThinking: true }, billing: { credits: 'x0.51', free: false } },
39
+ ]
40
+
41
+ /**
42
+ * Mutable catalog shared by the endpoint's `/v1/models` and the status CLI.
43
+ *
44
+ * Visibility is separate from content. A signed-out account must expose *no*
45
+ * models rather than a fallback roster: serving the fallback would advertise
46
+ * models that can only fail, which is worse than showing nothing.
47
+ */
48
+ export class WorkBuddyCatalog {
49
+ constructor(initial = FALLBACK_WORKBUDDY_MODELS) {
50
+ this.models = initial
51
+ this.visible = true
52
+ /** Provenance of the roster currently held. */
53
+ this.source = 'fallback'
54
+ this.fetchedAtMs = undefined
55
+ this.useMaximumContextWindow = false
56
+ }
57
+
58
+ /** Current entries; empty while the catalog has no usable credential. */
59
+ current() {
60
+ if (!this.visible) return []
61
+ return this.models.map(model => {
62
+ const current = modelWithCurrentPromotion(model)
63
+ const maximum = current.supportedContextWindows === undefined
64
+ ? undefined : Math.max(...current.supportedContextWindows)
65
+ return this.useMaximumContextWindow && maximum !== undefined && maximum > current.contextWindow
66
+ ? { ...current, defaultContextWindow: current.defaultContextWindow ?? current.contextWindow, contextWindow: maximum }
67
+ : current
68
+ })
69
+ }
70
+
71
+ /** Replace the list with a freshly fetched roster. */
72
+ set(models, { source, fetchedAtMs } = {}) {
73
+ this.models = [...models]
74
+ if (source !== undefined) this.source = source
75
+ this.fetchedAtMs = fetchedAtMs ?? Date.now()
76
+ }
77
+
78
+ isVisible() {
79
+ return this.visible
80
+ }
81
+
82
+ /** Show or hide the whole catalog. Returns whether the value changed. */
83
+ setVisible(visible) {
84
+ if (this.visible === visible) return false
85
+ this.visible = visible
86
+ return true
87
+ }
88
+
89
+ /** Select the largest declared window where the upstream offers a choice. */
90
+ setUseMaximumContextWindow(useMaximum) {
91
+ if (this.useMaximumContextWindow === useMaximum) return false
92
+ this.useMaximumContextWindow = useMaximum
93
+ return true
94
+ }
95
+
96
+ /** Models to fall back to when the upstream fetch fails; ignores visibility. */
97
+ fallback() {
98
+ return this.models
99
+ }
100
+ }