@anvaka/vue-llm 0.1.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/README.md ADDED
@@ -0,0 +1,166 @@
1
+ # @anvaka/vue-llm (WIP)
2
+
3
+ Browser-only LLM client + Vue 3 plugin, provider adapters, and lightweight components.
4
+
5
+ ## Features
6
+ - Provider factory with 8 built-in providers (OpenAI, Anthropic, Grok, Gemini, Ollama, Llama Server, OpenRouter, Custom) – extend with `registerProvider()`
7
+ - LocalStorage-based config store (custom storage adapter supported)
8
+ - Streaming + promise requests via `llmClient.stream()`
9
+ - Vue plugin for dependency injection
10
+ - `useLLM()` composable with reactive streaming state
11
+ - Ready-to-use components: `ProviderSelector`, `LLMConfigModal`, `StoredKeysManager`
12
+ - CSS variable theming (`--llm-*` tokens)
13
+
14
+ ## Quick Start
15
+ ```js
16
+ import { createApp } from 'vue'
17
+ import App from './App.vue'
18
+ import { LLMPlugin } from '@anvaka/vue-llm'
19
+ import '@anvaka/vue-llm/styles/variables.css'
20
+
21
+ createApp(App)
22
+ .use(LLMPlugin, { autoInit: false, namespace: 'myllm' })
23
+ .mount('#app')
24
+ ```
25
+
26
+ ## Components
27
+
28
+ ### ProviderSelector
29
+ Dropdown to switch between configured providers.
30
+ ```vue
31
+ <script setup>
32
+ import { ProviderSelector } from '@anvaka/vue-llm'
33
+ </script>
34
+ <template>
35
+ <ProviderSelector @changed="onProviderChanged" @open-config="showModal = true" />
36
+ </template>
37
+ ```
38
+
39
+ ### LLMConfigModal
40
+ Full configuration modal for managing providers (add, edit, test, delete).
41
+ ```vue
42
+ <script setup>
43
+ import { ref } from 'vue'
44
+ import { LLMConfigModal } from '@anvaka/vue-llm'
45
+ const showConfig = ref(false)
46
+ </script>
47
+ <template>
48
+ <LLMConfigModal
49
+ :is-visible="showConfig"
50
+ @close="showConfig = false"
51
+ @config-changed="onConfigChanged"
52
+ />
53
+ </template>
54
+ ```
55
+
56
+ Props:
57
+ - `isVisible` (Boolean) – controls modal visibility
58
+ - `editTarget` (Object) – optional config to edit directly
59
+ - `showJudge` (Boolean) – enable judge mode UI
60
+ - `showAllMode` (Boolean) – show all providers including disabled
61
+
62
+ Events:
63
+ - `close` – emitted when modal closes
64
+ - `configChanged` – emitted when a provider config is saved/deleted
65
+
66
+ ### StoredKeysManager
67
+ Manage stored API keys separately from provider configs.
68
+ ```vue
69
+ <script setup>
70
+ import { StoredKeysManager } from '@anvaka/vue-llm'
71
+ </script>
72
+ <template>
73
+ <StoredKeysManager @close="closeManager" @keysUpdated="refreshUI" />
74
+ </template>
75
+ ```
76
+
77
+ ## useLLM Composable
78
+ Access the LLM client, config store, and key store with reactive helpers.
79
+ ```js
80
+ import { useLLM } from '@anvaka/vue-llm'
81
+
82
+ const {
83
+ // Core objects
84
+ client, // LLMClient instance
85
+ configStore, // ConfigStore instance
86
+ keyStore, // KeyStore instance
87
+
88
+ // Streaming with reactive state
89
+ stream, // (messages, options) => Promise - stream with reactive updates
90
+ isStreaming, // ref<boolean>
91
+ streamContent, // ref<string> - accumulated response
92
+ streamThinking, // ref<string> - accumulated thinking content
93
+
94
+ // Config management
95
+ getEnabledConfigs, // () => config[] - enabled providers only
96
+ getAllConfigs, // () => config[] - all providers including disabled
97
+ getActiveConfig, // () => config | null
98
+ getActiveProviderId, // () => string | null
99
+ setActiveProviderId, // (id) => boolean
100
+ saveConfig, // (id, config) => boolean
101
+ deleteConfig, // (id) => boolean
102
+ enableProvider, // (id) => boolean
103
+ disableProvider, // (id) => boolean
104
+ getAvailableModels, // (providerType, config) => Promise<string[]>
105
+ testConnection, // (config) => Promise<string>
106
+ refresh, // () => Promise<void>
107
+
108
+ // Key management
109
+ getStoredKey, // (id) => string | null
110
+ storeKey, // (id, apiKey, options) => boolean
111
+ deleteStoredKey, // (id) => boolean
112
+ hasStoredKey, // (providerType) => boolean
113
+ getAllStoredKeys, // () => Record<string, KeyData>
114
+ getStoredKeyMeta // (id) => KeyMeta | null
115
+ } = useLLM()
116
+ ```
117
+
118
+ ## Non-Vue Usage
119
+ For scripts outside Vue components, use the singleton exports:
120
+ ```js
121
+ import { llmClient, configStore, keyStore } from '@anvaka/vue-llm'
122
+
123
+ // Stream directly
124
+ await llmClient.stream({ messages: [...] }, chunk => console.log(chunk.fullContent))
125
+
126
+ // Manage configs
127
+ configStore.saveConfig('my-provider', { ... })
128
+ configStore.setActiveProviderId('my-provider')
129
+ ```
130
+
131
+ ## Theming
132
+ Override any `--llm-*` CSS variable globally or per container.
133
+ ```css
134
+ :root { --llm-accent: #ff7e41; }
135
+ html[data-theme='light'] { --llm-bg: #fff; }
136
+ ```
137
+
138
+ ## Extending Providers
139
+ ```js
140
+ import { BaseProvider, registerProvider } from '@anvaka/vue-llm/providers'
141
+
142
+ class MyProvider extends BaseProvider {
143
+ /* implement abstract methods */
144
+ }
145
+ registerProvider('my-provider', MyProvider)
146
+ ```
147
+
148
+ ### Available Exports
149
+ ```js
150
+ // From '@anvaka/vue-llm/providers'
151
+ import {
152
+ BaseProvider,
153
+ PROVIDERS, // { OPENAI, ANTHROPIC, GROK, GEMINI, OLLAMA, LLAMA_SERVER, OPENROUTER, CUSTOM }
154
+ DEFAULT_CONFIGS, // Default configs for each provider type
155
+ createProvider, // (type, config) => Provider
156
+ registerProvider, // (type, ProviderClass) => void
157
+ createProviderFlexible // (type, config) => Provider (includes custom-registered)
158
+ } from '@anvaka/vue-llm/providers'
159
+
160
+ // Helper for creating config objects
161
+ import { createDefaultConfig } from '@anvaka/vue-llm'
162
+ const config = createDefaultConfig('openai') // Returns template config object
163
+ ```
164
+
165
+ ## License
166
+ MIT
@@ -0,0 +1,9 @@
1
+ const s = (t, e) => {
2
+ const o = t.__vccOpts || t;
3
+ for (const [r, c] of e)
4
+ o[r] = c;
5
+ return o;
6
+ };
7
+ export {
8
+ s as default
9
+ };
@@ -0,0 +1,248 @@
1
+ import { createProviderFlexible as I } from "../providers/factory.js";
2
+ class A {
3
+ constructor({ configStore: t, logger: s } = {}) {
4
+ this.configStore = t, this.logger = s || console, this.config = null, this.provider = null, this.usageTracker = null;
5
+ }
6
+ async initialize(t = null) {
7
+ if (this.config = t || this.configStore.getActiveConfig(), !this.config)
8
+ throw new Error("LLM not configured");
9
+ this.provider = I(this.config.provider, this.config), await this.provider.initialize(), this.usageTracker = this._createUsageTracker();
10
+ }
11
+ async ensureInitialized() {
12
+ this.provider || await this.initialize();
13
+ }
14
+ async refresh() {
15
+ this.config = null, this.provider = null, await this.initialize();
16
+ }
17
+ async testConnection(t) {
18
+ var r;
19
+ const s = this.config, i = this.provider;
20
+ try {
21
+ await this.initialize(t);
22
+ const e = [
23
+ { role: "system", content: 'Respond with exactly "pong"' },
24
+ { role: "user", content: "ping" }
25
+ ], n = this.validateCapabilities({
26
+ model: this.config.model,
27
+ enableThinking: !1,
28
+ temperature: 0.1,
29
+ maxTokens: 10,
30
+ stream: !1
31
+ }), o = this.provider.prepareRequest(e, n), a = await this.provider.makeRequest(o);
32
+ return (r = this.provider.processResponse(a).content) == null ? void 0 : r.trim();
33
+ } finally {
34
+ this.config = s, this.provider = i;
35
+ }
36
+ }
37
+ _createUsageTracker() {
38
+ return {
39
+ totalTokens: 0,
40
+ totalCost: 0,
41
+ recordUsage: (t, s) => {
42
+ var i;
43
+ (i = s.usage) != null && i.tokens && (this.totalTokens += s.usage.tokens);
44
+ },
45
+ recordPartialUsage: (t) => {
46
+ t != null && t.tokens && (this.totalTokens += t.tokens);
47
+ }
48
+ };
49
+ }
50
+ validateCapabilities(t) {
51
+ var i;
52
+ if (!this.provider) return t;
53
+ const s = t.enableThinking !== void 0 ? t.enableThinking : ((i = this.config) == null ? void 0 : i.enableThinking) || !1;
54
+ return {
55
+ ...t,
56
+ enableThinking: s && this.provider.hasCapability("thinking"),
57
+ images: t.images && this.provider.hasCapability("vision") ? t.images : null,
58
+ tools: t.tools && this.provider.hasCapability("tools") ? t.tools : null
59
+ };
60
+ }
61
+ async ping() {
62
+ var n;
63
+ await this.ensureInitialized();
64
+ const t = [
65
+ { role: "system", content: 'Respond with exactly "pong"' },
66
+ { role: "user", content: "ping" }
67
+ ], s = this.validateCapabilities({
68
+ model: this.config.model,
69
+ temperature: 0.1,
70
+ maxTokens: 10,
71
+ stream: !1
72
+ }), i = this.provider.prepareRequest(t, s), r = await this.provider.makeRequest(i);
73
+ return (n = this.provider.processResponse(r).content) == null ? void 0 : n.trim();
74
+ }
75
+ async stream(t, s) {
76
+ await this.ensureInitialized();
77
+ const i = this.validateCapabilities({ ...t, stream: !0, model: t.model || this.config.model, requestId: this.generateRequestId() }), r = t.messages;
78
+ let e = "";
79
+ return await this.provider.streamRequest(r, i, (n) => {
80
+ e = n.fullContent, s && s(n);
81
+ }), e;
82
+ }
83
+ generateRequestId() {
84
+ return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
85
+ }
86
+ getCapabilities() {
87
+ return this.provider ? Array.from(this.provider.capabilities) : [];
88
+ }
89
+ getUsageStats() {
90
+ var t, s;
91
+ return {
92
+ totalTokens: ((t = this.usageTracker) == null ? void 0 : t.totalTokens) || 0,
93
+ totalCost: ((s = this.usageTracker) == null ? void 0 : s.totalCost) || 0
94
+ };
95
+ }
96
+ async discoverModels() {
97
+ return await this.ensureInitialized(), this.provider.discoverModels();
98
+ }
99
+ getConfigByName(t) {
100
+ var r;
101
+ if (!t || !((r = this.configStore) != null && r.getEnabledConfigs)) return null;
102
+ const s = t.trim(), i = this.configStore.getEnabledConfigs().filter((e) => this._matchesDisplayName(e, s));
103
+ if (i.length === 0) return null;
104
+ if (i.length > 1) {
105
+ const e = i.map((n) => n.id).join(", ");
106
+ throw new Error(`Multiple provider presets share the name '${t}'. Conflicting ids: ${e}`);
107
+ }
108
+ return i[0];
109
+ }
110
+ _matchesDisplayName(t, s) {
111
+ return !t || !s ? !1 : t.name === s || this._formatDisplayName(t) === s;
112
+ }
113
+ _formatDisplayName(t) {
114
+ const s = (t == null ? void 0 : t.provider) || "provider", i = (t == null ? void 0 : t.baseUrl) || "n/a";
115
+ return (t == null ? void 0 : t.name) || `${s} (${i})`;
116
+ }
117
+ // Compatibility wrapper replicating old createLLMWrapper() dual streaming/promise API.
118
+ // Provides llm(prompt, opts).into(target, attrs?) and .withOperation(name) chain.
119
+ createLLMWrapper(t, s = null, i = null) {
120
+ const r = this;
121
+ function e(n, o = {}) {
122
+ return new S(r, t, n, o, s, i);
123
+ }
124
+ return e;
125
+ }
126
+ }
127
+ class S {
128
+ constructor(t, s, i, r, e, n) {
129
+ this.client = t, this.contextNode = s, this.prompt = i, this.options = r || {}, this.originatingCode = e, this.defaultPresetName = n, this.targetNode = null, this.targetAttributes = {}, this.operationName = null, this._executed = !1, this._promise = null;
130
+ }
131
+ withOperation(t) {
132
+ return this.operationName = t, this;
133
+ }
134
+ into(t, s = {}) {
135
+ return this.targetNode = t, this.targetAttributes = s, this._ensureExecution(), this;
136
+ }
137
+ then(t, s) {
138
+ return this._ensureExecution(), this._promise.then(t, s);
139
+ }
140
+ catch(t) {
141
+ return this._ensureExecution(), this._promise.catch(t);
142
+ }
143
+ finally(t) {
144
+ return this._ensureExecution(), this._promise.finally(t);
145
+ }
146
+ _ensureExecution() {
147
+ this._executed || (this._executed = !0, this._promise = this._run());
148
+ }
149
+ async _run() {
150
+ var o;
151
+ const t = await this._createExecutionContext(), { provider: s, config: i } = t;
152
+ if (!s || !i) throw new Error("LLM not configured");
153
+ const r = this.client.validateCapabilities.bind({ provider: s, config: i }), e = [];
154
+ this.options.system && e.push({ role: "system", content: this.options.system }), e.push({ role: "user", content: this.prompt });
155
+ const n = {
156
+ model: this.options.model || i.model,
157
+ temperature: this.options.temperature ?? i.temperature,
158
+ maxTokens: this.options.maxTokens ?? i.maxTokens,
159
+ enableThinking: this.options.enableThinking,
160
+ requestId: this.client.generateRequestId(),
161
+ ...this.options.images ? { images: this.options.images } : {},
162
+ ...this.options.tools ? { tools: this.options.tools } : {}
163
+ };
164
+ try {
165
+ if (this.targetNode) {
166
+ const h = r({ ...n, stream: !0 });
167
+ return await this._streamIntoTarget(e, h, s, i);
168
+ }
169
+ const a = r({ ...n, stream: !1 });
170
+ return await this._promiseResponse(e, a, s, i);
171
+ } finally {
172
+ (o = t.cleanup) == null || o.call(t);
173
+ }
174
+ }
175
+ async _createExecutionContext() {
176
+ var r, e, n, o;
177
+ const t = this._resolvePresetName();
178
+ if (!t)
179
+ return await this.client.ensureInitialized(), { provider: this.client.provider, config: this.client.config, cleanup: () => {
180
+ } };
181
+ if (!this.client.configStore)
182
+ throw new Error("Provider presets require a configured ConfigStore instance");
183
+ const s = (e = (r = this.client).getConfigByName) == null ? void 0 : e.call(r, t);
184
+ if (!s) {
185
+ const a = (((o = (n = this.client.configStore).getEnabledConfigs) == null ? void 0 : o.call(n)) || []).map((u) => u.name || `${u.provider} (${u.baseUrl})`).filter(Boolean), h = a.length ? ` Available presets: ${a.join(", ")}` : " No configured providers found.";
186
+ throw new Error(`Provider preset '${t}' not found.${h}`);
187
+ }
188
+ const i = I(s.provider, s);
189
+ return await i.initialize(), { provider: i, config: s, cleanup: () => {
190
+ var a;
191
+ return (a = i.cancelAllRequests) == null ? void 0 : a.call(i);
192
+ } };
193
+ }
194
+ _resolvePresetName() {
195
+ const t = typeof this.options.preset == "string" ? this.options.preset : null, s = typeof this.defaultPresetName == "string" ? this.defaultPresetName : null, i = t || s;
196
+ return i ? i.trim() : null;
197
+ }
198
+ _applyAttributes(t) {
199
+ var s, i;
200
+ for (const [r, e] of Object.entries(this.targetAttributes || {}))
201
+ try {
202
+ t.setAttribute(r, e);
203
+ } catch (n) {
204
+ (i = (s = this.client.logger) == null ? void 0 : s.warn) == null || i.call(s, "Failed to set attribute on target node", { key: r, value: e, error: n });
205
+ }
206
+ }
207
+ async _streamIntoTarget(t, s, i, r) {
208
+ var c, m, p, f, g, d, v, b, _, w, y, k, T, q;
209
+ let e, n;
210
+ typeof this.targetNode == "string" ? (n = this.targetNode, e = this.contextNode.createChild(n), (c = e.setSelected) == null || c.call(e)) : (e = this.targetNode, n = ((m = e.getText) == null ? void 0 : m.call(e)) || ""), this._applyAttributes(e);
211
+ const o = r == null ? void 0 : r.name;
212
+ o && e.addTag && e.addTag("provider", o), (p = e.addLLMLog) == null || p.call(e, this.operationName || "streaming-request", {
213
+ provider: r == null ? void 0 : r.provider,
214
+ model: r == null ? void 0 : r.model,
215
+ messages: t,
216
+ options: s
217
+ }), (f = e.setStreamingState) == null || f.call(e, !0), e._activeRequestId = s.requestId;
218
+ let a = "", h = null, u = 0;
219
+ try {
220
+ return await i.streamRequest(t, s, (l) => {
221
+ var C, x, R;
222
+ l.content && (a = l.fullContent, (C = e.setText) == null || C.call(e, a)), (x = l.usage) != null && x.tokens && (u += l.usage.tokens), l.finishReason && (h = l.finishReason), l.done && ((R = e.setStreamingState) == null || R.call(e, !1), e._activeRequestId = null);
223
+ }), (g = e.addLLMLog) == null || g.call(e, (this.operationName || "streaming-request") + "-response", { requestId: s.requestId }, { content: a, usage: { tokens: u } }), h === "length" ? ((d = e.setAttribute) == null || d.call(e, "_truncated", !0), (v = e.addLog) == null || v.call(e, "Response truncated. Increase Max Tokens.", "warn", { finish_reason: "length" })) : (b = e.setAttribute) == null || b.call(e, "_truncated", !1), await ((_ = e.persistNow) == null ? void 0 : _.call(e)), e;
224
+ } catch (l) {
225
+ throw (w = e.addLLMLog) == null || w.call(e, (this.operationName || "streaming-request") + "-error", { requestId: s.requestId }, null, l), (y = e.setStreamingState) == null || y.call(e, !1), e._activeRequestId = null, (k = e.setText) == null || k.call(e, `Error: ${l.message}`), (T = e.setAttribute) == null || T.call(e, "_truncated", !1), await ((q = e.persistNow) == null ? void 0 : q.call(e)), l;
226
+ }
227
+ }
228
+ async _promiseResponse(t, s, i, r) {
229
+ var h, u, c, m, p, f, g;
230
+ const e = i.prepareRequest(t, s), n = await i.makeRequest(e), o = i.processResponse(n);
231
+ if ((o.finishReason || ((u = (h = n == null ? void 0 : n.choices) == null ? void 0 : h[0]) == null ? void 0 : u.finish_reason) || null) === "length")
232
+ try {
233
+ this.contextNode.setAttribute("_truncated", !0);
234
+ } catch (d) {
235
+ (m = (c = this.client.logger) == null ? void 0 : c.warn) == null || m.call(c, "Unable to mark node as truncated", { error: d });
236
+ }
237
+ else
238
+ try {
239
+ this.contextNode.setAttribute("_truncated", !1);
240
+ } catch (d) {
241
+ (f = (p = this.client.logger) == null ? void 0 : p.warn) == null || f.call(p, "Unable to clear truncated marker on node", { error: d });
242
+ }
243
+ return ((g = o.content) == null ? void 0 : g.trim()) || "";
244
+ }
245
+ }
246
+ export {
247
+ A as LLMClient
248
+ };
@@ -0,0 +1,52 @@
1
+ import { LocalStorageAdapter as r } from "./storageAdapter.js";
2
+ class n {
3
+ constructor({ storageAdapter: t = null } = {}) {
4
+ this.storage = t || new r("llm"), this.CONFIGS_KEY = "configs", this.ACTIVE_KEY = "active-provider";
5
+ }
6
+ _readConfigs() {
7
+ const t = this.storage.get(this.CONFIGS_KEY);
8
+ if (!t) return {};
9
+ try {
10
+ return JSON.parse(t);
11
+ } catch {
12
+ return {};
13
+ }
14
+ }
15
+ _writeConfigs(t) {
16
+ try {
17
+ this.storage.set(this.CONFIGS_KEY, JSON.stringify(t));
18
+ } catch {
19
+ }
20
+ }
21
+ listConfigs() {
22
+ return this._readConfigs();
23
+ }
24
+ getConfig(t) {
25
+ return this._readConfigs()[t] || null;
26
+ }
27
+ saveConfig(t, i) {
28
+ const e = this._readConfigs();
29
+ return e[t] = { ...i, configuredAt: (/* @__PURE__ */ new Date()).toISOString() }, this._writeConfigs(e), !0;
30
+ }
31
+ deleteConfig(t) {
32
+ const i = this._readConfigs();
33
+ return delete i[t], this._writeConfigs(i), this.getActiveProviderId() === t && this.setActiveProviderId(null), !0;
34
+ }
35
+ getActiveProviderId() {
36
+ return this.storage.get(this.ACTIVE_KEY);
37
+ }
38
+ setActiveProviderId(t) {
39
+ t ? this.storage.set(this.ACTIVE_KEY, t) : this.storage.remove(this.ACTIVE_KEY);
40
+ }
41
+ getActiveConfig() {
42
+ const t = this.getActiveProviderId();
43
+ return t ? this.getConfig(t) : null;
44
+ }
45
+ getEnabledConfigs() {
46
+ const t = this._readConfigs();
47
+ return Object.entries(t).filter(([i, e]) => e && e.enabled !== !1 && e.provider && e.baseUrl).map(([i, e]) => ({ id: i, ...e }));
48
+ }
49
+ }
50
+ export {
51
+ n as ConfigStore
52
+ };
@@ -0,0 +1,58 @@
1
+ const d = "stored-keys";
2
+ class u {
3
+ constructor(e, t = d) {
4
+ this.storage = e, this.key = t;
5
+ }
6
+ _read() {
7
+ const e = this.storage.get(this.key);
8
+ if (!e) return {};
9
+ try {
10
+ return JSON.parse(e);
11
+ } catch {
12
+ return {};
13
+ }
14
+ }
15
+ _write(e) {
16
+ try {
17
+ this.storage.set(this.key, JSON.stringify(e));
18
+ } catch {
19
+ }
20
+ }
21
+ getAll() {
22
+ return this._read();
23
+ }
24
+ get(e) {
25
+ var r;
26
+ return ((r = this._read()[e]) == null ? void 0 : r.apiKey) || null;
27
+ }
28
+ set(e, t, r = {}) {
29
+ const s = this._read(), { providerType: n, serviceEndpoint: o, providerName: a } = r;
30
+ return s[e] = { apiKey: t, storedAt: (/* @__PURE__ */ new Date()).toISOString(), ...n && { providerType: n }, ...o && { serviceEndpoint: o }, ...a && { providerName: a } }, this._write(s), !0;
31
+ }
32
+ delete(e) {
33
+ const t = this._read();
34
+ return delete t[e], this._write(t), !0;
35
+ }
36
+ has(e) {
37
+ var r;
38
+ const t = this._read();
39
+ return e === "custom" ? Object.values(t).some((s) => s.providerType === "custom") : !!((r = t[e]) != null && r.apiKey);
40
+ }
41
+ getForType(e) {
42
+ const t = this._read(), r = {};
43
+ for (const [s, n] of Object.entries(t))
44
+ (n.providerType === e || s === e) && (r[s] = n);
45
+ return r;
46
+ }
47
+ meta(e) {
48
+ const t = this._read()[e];
49
+ return t ? { hasKey: !!t.apiKey, storedAt: t.storedAt, maskedKey: t.apiKey ? l(t.apiKey) : null, providerType: t.providerType, serviceEndpoint: t.serviceEndpoint, providerName: t.providerName } : null;
50
+ }
51
+ }
52
+ function l(i) {
53
+ return !i || i.length < 12 ? "••••••••" : `${i.substring(0, 8)}••••${i.substring(i.length - 4)}`;
54
+ }
55
+ export {
56
+ u as KeyStore,
57
+ l as maskApiKey
58
+ };
@@ -0,0 +1,67 @@
1
+ class i {
2
+ constructor(t = "llm") {
3
+ this.ns = t;
4
+ }
5
+ _k(t) {
6
+ return `${this.ns}:${t}`;
7
+ }
8
+ get(t) {
9
+ try {
10
+ return localStorage.getItem(this._k(t));
11
+ } catch {
12
+ return null;
13
+ }
14
+ }
15
+ set(t, s) {
16
+ try {
17
+ localStorage.setItem(this._k(t), s);
18
+ } catch {
19
+ }
20
+ }
21
+ remove(t) {
22
+ try {
23
+ localStorage.removeItem(this._k(t));
24
+ } catch {
25
+ }
26
+ }
27
+ // List all keys for this namespace (returns object of raw string values)
28
+ list(t = "") {
29
+ const s = {};
30
+ try {
31
+ const l = this._k(t);
32
+ for (let r = 0; r < localStorage.length; r++) {
33
+ const e = localStorage.key(r);
34
+ e && e.startsWith(this.ns + ":") && e.startsWith(l) && (s[e.slice(this.ns.length + 1)] = localStorage.getItem(e));
35
+ }
36
+ } catch {
37
+ }
38
+ return s;
39
+ }
40
+ }
41
+ class h {
42
+ constructor(t = "llm") {
43
+ this.ns = t, this.store = /* @__PURE__ */ new Map();
44
+ }
45
+ _k(t) {
46
+ return `${this.ns}:${t}`;
47
+ }
48
+ get(t) {
49
+ return this.store.get(this._k(t)) || null;
50
+ }
51
+ set(t, s) {
52
+ this.store.set(this._k(t), s);
53
+ }
54
+ remove(t) {
55
+ this.store.delete(this._k(t));
56
+ }
57
+ list(t = "") {
58
+ const s = {}, l = this._k(t);
59
+ for (const [r, e] of this.store.entries())
60
+ r.startsWith(l) && (s[r.slice(this.ns.length + 1)] = e);
61
+ return s;
62
+ }
63
+ }
64
+ export {
65
+ i as LocalStorageAdapter,
66
+ h as MemoryStorageAdapter
67
+ };
package/dist/index.js ADDED
@@ -0,0 +1,38 @@
1
+ import { LLMClient as l } from "./core/LLMClient.js";
2
+ import { ConfigStore as S } from "./core/configStore.js";
3
+ import { KeyStore as p, maskApiKey as M } from "./core/keyStore.js";
4
+ import { LocalStorageAdapter as s, MemoryStorageAdapter as x } from "./core/storageAdapter.js";
5
+ import { DEFAULT_CONFIGS as g, PROVIDERS as _, createProvider as C, createProviderFlexible as O, registerProvider as u } from "./providers/factory.js";
6
+ import { createLLM as r } from "./vue/plugin.js";
7
+ import { LLMPlugin as P, LLM_CLIENT_SYMBOL as E, LLM_CONFIG_SYMBOL as v, LLM_KEYSTORE_SYMBOL as A } from "./vue/plugin.js";
8
+ import { createDefaultConfig as I, useLLM as K } from "./vue/useLLM.js";
9
+ import { default as k } from "./vue/components/ProviderSelector.vue.js";
10
+ import { default as D } from "./vue/components/LLMConfigModal.vue.js";
11
+ import { default as R } from "./vue/components/StoredKeysManager.vue.js";
12
+ const e = r({}), t = e.client, L = e.configStore, a = e.keyStore;
13
+ export {
14
+ S as ConfigStore,
15
+ g as DEFAULT_CONFIGS,
16
+ p as KeyStore,
17
+ l as LLMClient,
18
+ D as LLMConfigModal,
19
+ P as LLMPlugin,
20
+ E as LLM_CLIENT_SYMBOL,
21
+ v as LLM_CONFIG_SYMBOL,
22
+ A as LLM_KEYSTORE_SYMBOL,
23
+ s as LocalStorageAdapter,
24
+ x as MemoryStorageAdapter,
25
+ _ as PROVIDERS,
26
+ k as ProviderSelector,
27
+ R as StoredKeysManager,
28
+ L as configStore,
29
+ I as createDefaultConfig,
30
+ r as createLLM,
31
+ C as createProvider,
32
+ O as createProviderFlexible,
33
+ a as keyStore,
34
+ t as llmClient,
35
+ M as maskApiKey,
36
+ u as registerProvider,
37
+ K as useLLM
38
+ };