provider-kit 1.2.0 → 1.2.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "provider-kit",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "42 LLM provider unified API — one interface for OpenAI, Anthropic, Ollama, OpenRouter, and 38 more. Built-in retry, timeout, and error handling.",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
package/src/index.js CHANGED
@@ -10,7 +10,7 @@
10
10
  * const reply = await provider.chat('gpt-4', [{ role: 'user', content: 'Hi' }]);
11
11
  */
12
12
 
13
- export { ProviderError, AbortError, withRetry, withTimeout, safeProviderCall, classifyError, createCancelSignal, createRouter } from './providers/provider-error-adapter.js';
13
+ export { ProviderError, AbortError, withRetry, withTimeout, safeProviderCall, classifyError, createCancelSignal, createRouter, createMonitor } from './providers/provider-error-adapter.js';
14
14
  export { ProviderManager, providerManager } from './providers/provider-manager.js';
15
15
  export { providerRegistry, createProvider, listPresetProviders, PRESET_PROVIDERS } from './providers/provider-registry.js';
16
16
  export { persistentConfig, createStore } from './core/persistent-config.js';
@@ -102,6 +102,59 @@ export function createCancelSignal() {
102
102
  };
103
103
  }
104
104
 
105
+ /**
106
+ * createMonitor — observability wrapper
107
+ *
108
+ * Wraps provider calls with latency tracking, error classification,
109
+ * and logging hooks. No external dependencies.
110
+ *
111
+ * Usage:
112
+ * const monitor = createMonitor({ onCall: (record) => console.table(record) });
113
+ * const provider = monitor.wrap(await createProvider('openai', key));
114
+ * await provider.chat('gpt-4', messages);
115
+ * // → onCall receives { provider, model, latency, ok, error, timestamp }
116
+ */
117
+ export function createMonitor(opts = {}) {
118
+ const onCall = opts.onCall || (() => {});
119
+
120
+ function wrap(provider) {
121
+ const origChat = provider.chat.bind(provider);
122
+ const origStream = provider.chatStream?.bind(provider);
123
+
124
+ provider.chat = async (model, messages, options) => {
125
+ const start = Date.now();
126
+ try {
127
+ const result = await origChat(model, messages, options);
128
+ onCall({ provider: provider.name || 'unknown', model, latency: Date.now() - start, ok: true, tokens: result.usage?.total_tokens || 0, timestamp: Date.now() });
129
+ return result;
130
+ } catch (e) {
131
+ const ce = classifyError(e, provider.name);
132
+ onCall({ provider: provider.name || 'unknown', model, latency: Date.now() - start, ok: false, error: ce.type, message: ce.message, timestamp: Date.now() });
133
+ throw e;
134
+ }
135
+ };
136
+
137
+ if (origStream) {
138
+ provider.chatStream = async function* (model, messages, options) {
139
+ const start = Date.now();
140
+ try {
141
+ const stream = origStream(model, messages, options);
142
+ for await (const chunk of stream) yield chunk;
143
+ onCall({ provider: provider.name || 'unknown', model, latency: Date.now() - start, ok: true, timestamp: Date.now() });
144
+ } catch (e) {
145
+ const ce = classifyError(e, provider.name);
146
+ onCall({ provider: provider.name || 'unknown', model, latency: Date.now() - start, ok: false, error: ce.type, timestamp: Date.now() });
147
+ throw e;
148
+ }
149
+ };
150
+ }
151
+
152
+ return provider;
153
+ }
154
+
155
+ return { wrap };
156
+ }
157
+
105
158
  /**
106
159
  * createRouter — model health probe + auto-routing
107
160
  *