@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 +166 -0
- package/dist/_virtual/_plugin-vue_export-helper.js +9 -0
- package/dist/core/LLMClient.js +248 -0
- package/dist/core/configStore.js +52 -0
- package/dist/core/keyStore.js +58 -0
- package/dist/core/storageAdapter.js +67 -0
- package/dist/index.js +38 -0
- package/dist/providers/AnthropicProvider.js +88 -0
- package/dist/providers/BaseProvider.js +155 -0
- package/dist/providers/CustomProvider.js +53 -0
- package/dist/providers/GeminiProvider.js +163 -0
- package/dist/providers/GrokProvider.js +70 -0
- package/dist/providers/LlamaServerProvider.js +56 -0
- package/dist/providers/OllamaProvider.js +77 -0
- package/dist/providers/OpenAIProvider.js +98 -0
- package/dist/providers/OpenRouterProvider.js +81 -0
- package/dist/providers/factory.js +69 -0
- package/dist/providers/index.js +12 -0
- package/dist/vue/components/LLMConfigModal.vue.js +498 -0
- package/dist/vue/components/ProviderSelector.vue.js +53 -0
- package/dist/vue/components/StoredKeysManager.vue.js +223 -0
- package/dist/vue/index.js +17 -0
- package/dist/vue/plugin.js +26 -0
- package/dist/vue/useLLM.js +137 -0
- package/dist/vue-llm.css +1 -0
- package/package.json +41 -0
- package/src/styles/components.css +15 -0
- package/src/styles/variables.css +70 -0
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,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
|
+
};
|