@cuylabs/agent-core 0.3.0 → 0.5.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.
Files changed (66) hide show
  1. package/README.md +216 -41
  2. package/dist/builder-RcTZuYnO.d.ts +34 -0
  3. package/dist/capabilities/index.d.ts +97 -0
  4. package/dist/capabilities/index.js +46 -0
  5. package/dist/chunk-6TDTQJ4P.js +116 -0
  6. package/dist/chunk-7MUFEN4K.js +559 -0
  7. package/dist/chunk-BDBZ3SLK.js +745 -0
  8. package/dist/chunk-DWYX7ASF.js +26 -0
  9. package/dist/chunk-FG4MD5MU.js +54 -0
  10. package/dist/chunk-IMGQOTU2.js +2019 -0
  11. package/dist/chunk-IVUJDISU.js +556 -0
  12. package/dist/chunk-LRHOS4ZN.js +584 -0
  13. package/dist/chunk-OTUGSCED.js +691 -0
  14. package/dist/chunk-P6YF7USR.js +182 -0
  15. package/dist/chunk-QAQADS4X.js +258 -0
  16. package/dist/chunk-QWFMX226.js +879 -0
  17. package/dist/{chunk-6VKLWNRE.js → chunk-SDSBEQXG.js} +1 -132
  18. package/dist/chunk-VBWWUHWI.js +724 -0
  19. package/dist/chunk-VEKUXUVF.js +41 -0
  20. package/dist/chunk-X635CM2F.js +305 -0
  21. package/dist/chunk-YUUJK53A.js +91 -0
  22. package/dist/chunk-ZXAKHMWH.js +283 -0
  23. package/dist/config-D2xeGEHK.d.ts +52 -0
  24. package/dist/context/index.d.ts +259 -0
  25. package/dist/context/index.js +26 -0
  26. package/dist/identifiers-BLUxFqV_.d.ts +12 -0
  27. package/dist/index-p0kOsVsE.d.ts +1067 -0
  28. package/dist/index-tmhaADz5.d.ts +198 -0
  29. package/dist/index.d.ts +185 -4316
  30. package/dist/index.js +1238 -5368
  31. package/dist/mcp/index.d.ts +26 -0
  32. package/dist/mcp/index.js +14 -0
  33. package/dist/messages-BYWGn8TY.d.ts +110 -0
  34. package/dist/middleware/index.d.ts +7 -0
  35. package/dist/middleware/index.js +12 -0
  36. package/dist/models/index.d.ts +33 -0
  37. package/dist/models/index.js +12 -0
  38. package/dist/network-D76DS5ot.d.ts +5 -0
  39. package/dist/prompt/index.d.ts +224 -0
  40. package/dist/prompt/index.js +45 -0
  41. package/dist/reasoning/index.d.ts +71 -0
  42. package/dist/reasoning/index.js +47 -0
  43. package/dist/registry-CuRWWtcT.d.ts +164 -0
  44. package/dist/resolver-DOfZ-xuk.d.ts +254 -0
  45. package/dist/runner-C7aMP_x3.d.ts +596 -0
  46. package/dist/runtime/index.d.ts +357 -0
  47. package/dist/runtime/index.js +64 -0
  48. package/dist/session-manager-Uawm2Le7.d.ts +274 -0
  49. package/dist/skill/index.d.ts +103 -0
  50. package/dist/skill/index.js +39 -0
  51. package/dist/storage/index.d.ts +167 -0
  52. package/dist/storage/index.js +50 -0
  53. package/dist/sub-agent/index.d.ts +14 -0
  54. package/dist/sub-agent/index.js +15 -0
  55. package/dist/tool/index.d.ts +173 -1
  56. package/dist/tool/index.js +12 -3
  57. package/dist/tool-DYp6-cC3.d.ts +239 -0
  58. package/dist/tool-pFAnJc5Y.d.ts +419 -0
  59. package/dist/tracker-DClqYqTj.d.ts +96 -0
  60. package/dist/tracking/index.d.ts +109 -0
  61. package/dist/tracking/index.js +20 -0
  62. package/dist/types-CQaXbRsS.d.ts +47 -0
  63. package/dist/types-MM1JoX5T.d.ts +810 -0
  64. package/dist/types-VQgymC1N.d.ts +156 -0
  65. package/package.json +89 -5
  66. package/dist/index-QR704uRr.d.ts +0 -472
@@ -0,0 +1,879 @@
1
+ import {
2
+ getModelId,
3
+ getProviderId
4
+ } from "./chunk-DWYX7ASF.js";
5
+
6
+ // src/capabilities/types.ts
7
+ var SourcePriority = /* @__PURE__ */ ((SourcePriority3) => {
8
+ SourcePriority3[SourcePriority3["UserConfig"] = 0] = "UserConfig";
9
+ SourcePriority3[SourcePriority3["LocalCache"] = 1] = "LocalCache";
10
+ SourcePriority3[SourcePriority3["BundledData"] = 2] = "BundledData";
11
+ SourcePriority3[SourcePriority3["PatternMatch"] = 3] = "PatternMatch";
12
+ SourcePriority3[SourcePriority3["RemoteAPI"] = 4] = "RemoteAPI";
13
+ return SourcePriority3;
14
+ })(SourcePriority || {});
15
+ var DEFAULT_RESOLVER_OPTIONS = {
16
+ enableRemoteFetch: false,
17
+ remoteApiUrl: "https://models.dev",
18
+ cachePath: ".agent-core/cache",
19
+ cacheTtlMs: 60 * 60 * 1e3,
20
+ // 1 hour
21
+ networkTimeoutMs: 10 * 1e3,
22
+ // 10 seconds
23
+ modelOverrides: {}
24
+ };
25
+
26
+ // src/capabilities/patterns.ts
27
+ var REASONING_PATTERNS = [
28
+ // OpenAI o-series
29
+ {
30
+ pattern: /^o[134]-?(mini|pro|preview)?$/i,
31
+ provider: "openai",
32
+ capabilities: { reasoning: true, toolCalling: true },
33
+ compatibility: { supportsReasoningEffort: true, thinkingFormat: "openai" },
34
+ confidence: 0.95
35
+ },
36
+ // OpenAI GPT-5.x
37
+ {
38
+ pattern: /gpt-?5(\.\d)?/i,
39
+ provider: "openai",
40
+ capabilities: { reasoning: true, toolCalling: true },
41
+ compatibility: { supportsReasoningEffort: true, thinkingFormat: "openai" },
42
+ confidence: 0.9
43
+ },
44
+ // DeepSeek R1 variants
45
+ {
46
+ pattern: /deepseek[_-]?r1|r1[_-]distill/i,
47
+ capabilities: { reasoning: true, toolCalling: false },
48
+ confidence: 0.95
49
+ },
50
+ // Anthropic Claude with thinking
51
+ {
52
+ pattern: /claude.*thinking|thinking.*claude/i,
53
+ provider: "anthropic",
54
+ capabilities: { reasoning: true, toolCalling: true },
55
+ compatibility: { thinkingFormat: "anthropic" },
56
+ confidence: 0.9
57
+ },
58
+ // Claude 4.x series (reasoning capable)
59
+ {
60
+ pattern: /claude[_-]?(opus|sonnet)[_-]?4/i,
61
+ provider: "anthropic",
62
+ capabilities: { reasoning: true, toolCalling: true },
63
+ compatibility: { thinkingFormat: "anthropic" },
64
+ confidence: 0.85
65
+ },
66
+ // Gemini thinking models
67
+ {
68
+ pattern: /gemini.*thinking|gemini[_-]?2\.5[_-]?pro/i,
69
+ provider: "google",
70
+ capabilities: { reasoning: true, toolCalling: true },
71
+ compatibility: { thinkingFormat: "google" },
72
+ confidence: 0.85
73
+ },
74
+ // Gemini 3.x (future-proofing)
75
+ {
76
+ pattern: /gemini[_-]?3/i,
77
+ provider: "google",
78
+ capabilities: { reasoning: true, toolCalling: true },
79
+ compatibility: { thinkingFormat: "google" },
80
+ confidence: 0.8
81
+ },
82
+ // Grok reasoning models
83
+ {
84
+ pattern: /grok[_-]?\d[_-]?(mini|reasoning)/i,
85
+ provider: "xai",
86
+ capabilities: { reasoning: true, toolCalling: true },
87
+ confidence: 0.85
88
+ },
89
+ // Qwen thinking models
90
+ {
91
+ pattern: /qwen.*thinking|qwen3/i,
92
+ capabilities: { reasoning: true, toolCalling: true },
93
+ confidence: 0.8
94
+ },
95
+ // Generic reasoning/thinking in name
96
+ {
97
+ pattern: /reasoning|thinking/i,
98
+ capabilities: { reasoning: true },
99
+ confidence: 0.7
100
+ }
101
+ ];
102
+ var PROVIDER_PATTERNS = [
103
+ { pattern: /^(gpt|o[134]|chatgpt|davinci)/i, provider: "openai" },
104
+ { pattern: /^claude/i, provider: "anthropic" },
105
+ { pattern: /^gemini|^palm/i, provider: "google" },
106
+ { pattern: /^grok/i, provider: "xai" },
107
+ { pattern: /^deepseek/i, provider: "deepseek" },
108
+ { pattern: /^mistral|^mixtral|codestral/i, provider: "mistral" },
109
+ { pattern: /^llama/i, provider: "meta" },
110
+ { pattern: /^qwen/i, provider: "alibaba" },
111
+ { pattern: /^command/i, provider: "cohere" }
112
+ ];
113
+ function inferProvider(modelId) {
114
+ const normalized = modelId.toLowerCase();
115
+ for (const { pattern, provider } of PROVIDER_PATTERNS) {
116
+ if (pattern.test(normalized)) {
117
+ return provider;
118
+ }
119
+ }
120
+ if (modelId.includes("/")) {
121
+ return modelId.split("/")[0];
122
+ }
123
+ return void 0;
124
+ }
125
+ function matchPatterns(modelId, providerHint) {
126
+ const normalized = modelId.toLowerCase();
127
+ for (const rule of REASONING_PATTERNS) {
128
+ if (rule.provider && providerHint && rule.provider !== providerHint) {
129
+ continue;
130
+ }
131
+ const matches = typeof rule.pattern === "string" ? normalized.includes(rule.pattern.toLowerCase()) : rule.pattern.test(normalized);
132
+ if (matches) {
133
+ return { rule, confidence: rule.confidence };
134
+ }
135
+ }
136
+ return void 0;
137
+ }
138
+ function createDefaultCapabilities() {
139
+ return {
140
+ reasoning: false,
141
+ toolCalling: true,
142
+ temperature: true,
143
+ attachments: false,
144
+ streaming: true,
145
+ inputModalities: ["text"],
146
+ outputModalities: ["text"]
147
+ };
148
+ }
149
+ var PatternCapabilitySource = class {
150
+ priority = 3 /* PatternMatch */;
151
+ name = "Pattern Matching";
152
+ async lookup(modelId, providerHint) {
153
+ const provider = providerHint || inferProvider(modelId);
154
+ const match = matchPatterns(modelId, provider);
155
+ const baseCapabilities = createDefaultCapabilities();
156
+ if (match) {
157
+ const entry = {
158
+ id: modelId,
159
+ name: modelId,
160
+ provider: match.rule.provider || provider || "unknown",
161
+ capabilities: {
162
+ ...baseCapabilities,
163
+ ...match.rule.capabilities
164
+ },
165
+ compatibility: match.rule.compatibility
166
+ };
167
+ return {
168
+ entry,
169
+ source: this.priority,
170
+ confident: match.confidence > 0.8
171
+ };
172
+ }
173
+ return {
174
+ entry: {
175
+ id: modelId,
176
+ name: modelId,
177
+ provider: provider || "unknown",
178
+ capabilities: baseCapabilities
179
+ },
180
+ source: this.priority,
181
+ confident: false
182
+ };
183
+ }
184
+ async isAvailable() {
185
+ return true;
186
+ }
187
+ };
188
+ function likelySupportsReasoning(modelId) {
189
+ const match = matchPatterns(modelId);
190
+ return match !== void 0 && match.rule.capabilities.reasoning === true;
191
+ }
192
+ function getProviderCompatibility(modelId, provider) {
193
+ const match = matchPatterns(modelId, provider);
194
+ return match?.rule.compatibility;
195
+ }
196
+
197
+ // src/capabilities/overrides.ts
198
+ function normalizeKey(value) {
199
+ const trimmed = value?.trim();
200
+ return trimmed && trimmed.length > 0 ? trimmed : void 0;
201
+ }
202
+ function findCapabilityOverride(overrides, modelId, provider) {
203
+ if (!overrides) return {};
204
+ const normalizedModel = normalizeKey(modelId);
205
+ const normalizedProvider = normalizeKey(provider);
206
+ if (!normalizedModel) return {};
207
+ if (normalizedProvider) {
208
+ const scopedKey = `${normalizedProvider}/${normalizedModel}`;
209
+ const scopedOverride = overrides[scopedKey];
210
+ if (scopedOverride) {
211
+ return { override: scopedOverride, matchedKey: scopedKey };
212
+ }
213
+ }
214
+ const modelOverride = overrides[normalizedModel];
215
+ if (modelOverride) {
216
+ return { override: modelOverride, matchedKey: normalizedModel };
217
+ }
218
+ return {};
219
+ }
220
+ function applyCapabilityOverride(entry, override) {
221
+ if (!override) return entry;
222
+ return {
223
+ ...entry,
224
+ capabilities: {
225
+ ...entry.capabilities,
226
+ ...override
227
+ }
228
+ };
229
+ }
230
+
231
+ // src/capabilities/cache/adapters.ts
232
+ function isNodeEnvironment() {
233
+ return typeof process !== "undefined" && process.versions != null && process.versions.node != null;
234
+ }
235
+ function hasLocalStorage() {
236
+ try {
237
+ return typeof localStorage !== "undefined" && localStorage !== null;
238
+ } catch {
239
+ return false;
240
+ }
241
+ }
242
+ var FileSystemAdapter = class {
243
+ cachePath;
244
+ fs;
245
+ path;
246
+ constructor(cachePath) {
247
+ this.cachePath = cachePath;
248
+ }
249
+ async ensureModules() {
250
+ if (!this.fs) {
251
+ this.fs = await import("fs/promises");
252
+ this.path = await import("path");
253
+ }
254
+ }
255
+ getFilePath() {
256
+ return this.path.join(this.cachePath, "model-capabilities.json");
257
+ }
258
+ async read() {
259
+ await this.ensureModules();
260
+ try {
261
+ const content = await this.fs.readFile(this.getFilePath(), "utf-8");
262
+ return JSON.parse(content);
263
+ } catch {
264
+ return void 0;
265
+ }
266
+ }
267
+ async write(data) {
268
+ await this.ensureModules();
269
+ const filePath = this.getFilePath();
270
+ await this.fs.mkdir(this.path.dirname(filePath), { recursive: true });
271
+ await this.fs.writeFile(filePath, JSON.stringify(data, null, 2));
272
+ }
273
+ async clear() {
274
+ await this.ensureModules();
275
+ try {
276
+ await this.fs.unlink(this.getFilePath());
277
+ } catch {
278
+ }
279
+ }
280
+ };
281
+ var LocalStorageAdapter = class {
282
+ key = "agent-core:model-capabilities";
283
+ async read() {
284
+ try {
285
+ const content = localStorage.getItem(this.key);
286
+ if (!content) return void 0;
287
+ return JSON.parse(content);
288
+ } catch {
289
+ return void 0;
290
+ }
291
+ }
292
+ async write(data) {
293
+ try {
294
+ localStorage.setItem(this.key, JSON.stringify(data));
295
+ } catch (error) {
296
+ console.warn("[agent-core] Failed to write to localStorage:", error);
297
+ }
298
+ }
299
+ async clear() {
300
+ try {
301
+ localStorage.removeItem(this.key);
302
+ } catch {
303
+ }
304
+ }
305
+ };
306
+ var MemoryAdapter = class {
307
+ data;
308
+ async read() {
309
+ return this.data;
310
+ }
311
+ async write(data) {
312
+ this.data = data;
313
+ }
314
+ async clear() {
315
+ this.data = void 0;
316
+ }
317
+ };
318
+ function createCapabilityCacheAdapter(cachePath) {
319
+ if (isNodeEnvironment()) {
320
+ return new FileSystemAdapter(cachePath);
321
+ }
322
+ if (hasLocalStorage()) {
323
+ return new LocalStorageAdapter();
324
+ }
325
+ return new MemoryAdapter();
326
+ }
327
+
328
+ // src/capabilities/cache/types.ts
329
+ var CACHE_VERSION = 1;
330
+ function cacheKey(modelId, provider) {
331
+ return provider ? `${provider}:${modelId}` : modelId;
332
+ }
333
+ function isExpired(data) {
334
+ return Date.now() > new Date(data.expiresAt).getTime();
335
+ }
336
+
337
+ // src/capabilities/cache/manager.ts
338
+ var CapabilityCache = class {
339
+ adapter;
340
+ memoryCache = /* @__PURE__ */ new Map();
341
+ ttlMs;
342
+ loaded = false;
343
+ constructor(options = {}) {
344
+ const opts = { ...DEFAULT_RESOLVER_OPTIONS, ...options };
345
+ this.ttlMs = opts.cacheTtlMs;
346
+ this.adapter = createCapabilityCacheAdapter(opts.cachePath);
347
+ }
348
+ async load() {
349
+ if (this.loaded) return;
350
+ try {
351
+ const data = await this.adapter.read();
352
+ if (data && data.version === CACHE_VERSION && !isExpired(data)) {
353
+ for (const [key, entry] of Object.entries(data.models)) {
354
+ this.memoryCache.set(key, entry);
355
+ }
356
+ }
357
+ } catch (error) {
358
+ console.warn("[agent-core] Failed to load capability cache:", error);
359
+ }
360
+ this.loaded = true;
361
+ }
362
+ async get(modelId, provider) {
363
+ await this.load();
364
+ return this.memoryCache.get(cacheKey(modelId, provider));
365
+ }
366
+ async set(entry) {
367
+ await this.load();
368
+ this.memoryCache.set(cacheKey(entry.id, entry.provider), entry);
369
+ }
370
+ async setMany(entries) {
371
+ await this.load();
372
+ for (const entry of entries) {
373
+ this.memoryCache.set(cacheKey(entry.id, entry.provider), entry);
374
+ }
375
+ }
376
+ async persist() {
377
+ const models = {};
378
+ for (const [key, entry] of this.memoryCache.entries()) {
379
+ models[key] = entry;
380
+ }
381
+ await this.adapter.write({
382
+ version: CACHE_VERSION,
383
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
384
+ expiresAt: new Date(Date.now() + this.ttlMs).toISOString(),
385
+ models
386
+ });
387
+ }
388
+ async clear() {
389
+ this.memoryCache.clear();
390
+ await this.adapter.clear();
391
+ this.loaded = false;
392
+ }
393
+ stats() {
394
+ return {
395
+ size: this.memoryCache.size,
396
+ loaded: this.loaded
397
+ };
398
+ }
399
+ async getAll() {
400
+ await this.load();
401
+ return Array.from(this.memoryCache.values());
402
+ }
403
+ async getAllByProvider() {
404
+ await this.load();
405
+ const byProvider = {};
406
+ for (const entry of this.memoryCache.values()) {
407
+ const provider = entry.provider ?? "unknown";
408
+ byProvider[provider] ??= [];
409
+ byProvider[provider].push(entry);
410
+ }
411
+ return byProvider;
412
+ }
413
+ };
414
+ var CacheCapabilitySource = class {
415
+ constructor(cache) {
416
+ this.cache = cache;
417
+ }
418
+ priority = 1 /* LocalCache */;
419
+ name = "Local Cache";
420
+ async lookup(modelId, provider) {
421
+ const entry = await this.cache.get(modelId, provider);
422
+ if (entry) {
423
+ return {
424
+ entry,
425
+ source: this.priority,
426
+ confident: true
427
+ };
428
+ }
429
+ return {
430
+ source: this.priority,
431
+ confident: false
432
+ };
433
+ }
434
+ async isAvailable() {
435
+ return this.cache.stats().size > 0;
436
+ }
437
+ };
438
+
439
+ // src/capabilities/remote/network.ts
440
+ function hasBrowserNetworkAPI() {
441
+ return typeof globalThis.navigator !== "undefined" && "onLine" in globalThis.navigator;
442
+ }
443
+ function isBrowserOnline() {
444
+ if (typeof globalThis.navigator !== "undefined" && "onLine" in globalThis.navigator) {
445
+ return globalThis.navigator.onLine;
446
+ }
447
+ return true;
448
+ }
449
+ var NetworkTracker = class {
450
+ status = {
451
+ online: true,
452
+ failureCount: 0
453
+ };
454
+ getStatus() {
455
+ if (hasBrowserNetworkAPI()) {
456
+ return {
457
+ ...this.status,
458
+ online: isBrowserOnline() && this.status.failureCount < 3
459
+ };
460
+ }
461
+ return {
462
+ ...this.status,
463
+ online: this.status.failureCount < 3
464
+ };
465
+ }
466
+ recordSuccess() {
467
+ this.status = {
468
+ online: true,
469
+ lastSuccess: Date.now(),
470
+ failureCount: 0
471
+ };
472
+ }
473
+ recordFailure(error) {
474
+ this.status = {
475
+ ...this.status,
476
+ online: this.status.failureCount < 2,
477
+ lastError: error,
478
+ failureCount: this.status.failureCount + 1
479
+ };
480
+ }
481
+ };
482
+ var networkTracker = new NetworkTracker();
483
+ function getNetworkStatus() {
484
+ return networkTracker.getStatus();
485
+ }
486
+ function recordNetworkSuccess() {
487
+ networkTracker.recordSuccess();
488
+ }
489
+ function recordNetworkFailure(error) {
490
+ networkTracker.recordFailure(error);
491
+ }
492
+ async function fetchWithTimeout(url, timeoutMs) {
493
+ const controller = new AbortController();
494
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
495
+ try {
496
+ const response = await fetch(url, {
497
+ signal: controller.signal,
498
+ headers: {
499
+ Accept: "application/json",
500
+ "User-Agent": "cuylabs-agent-core/1.0"
501
+ }
502
+ });
503
+ if (!response.ok) {
504
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
505
+ }
506
+ return response;
507
+ } finally {
508
+ clearTimeout(timeout);
509
+ }
510
+ }
511
+
512
+ // src/capabilities/remote/transform.ts
513
+ function transformModelsDevEntry(raw) {
514
+ const capabilities = {
515
+ reasoning: raw.reasoning ?? false,
516
+ toolCalling: raw.tool_call ?? false,
517
+ temperature: raw.temperature ?? true,
518
+ attachments: raw.attachment ?? false,
519
+ streaming: true,
520
+ inputModalities: raw.modalities?.input ?? ["text"],
521
+ outputModalities: raw.modalities?.output ?? ["text"],
522
+ contextWindow: raw.limit?.context,
523
+ maxOutput: raw.limit?.output
524
+ };
525
+ return {
526
+ id: raw.id,
527
+ name: raw.name,
528
+ provider: raw.provider ?? "unknown",
529
+ capabilities,
530
+ costInput: raw.cost?.input,
531
+ costOutput: raw.cost?.output,
532
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
533
+ };
534
+ }
535
+
536
+ // src/capabilities/remote/fetcher.ts
537
+ var RemoteCapabilityFetcher = class {
538
+ apiUrl;
539
+ timeoutMs;
540
+ cache;
541
+ lastFetchTime = 0;
542
+ minFetchInterval = 60 * 1e3;
543
+ constructor(cache, options = {}) {
544
+ const opts = { ...DEFAULT_RESOLVER_OPTIONS, ...options };
545
+ this.apiUrl = opts.remoteApiUrl;
546
+ this.timeoutMs = opts.networkTimeoutMs;
547
+ this.cache = cache;
548
+ }
549
+ async fetchAll() {
550
+ const now = Date.now();
551
+ if (now - this.lastFetchTime < this.minFetchInterval) {
552
+ throw new Error("Fetch rate limited - try again later");
553
+ }
554
+ if (!getNetworkStatus().online) {
555
+ throw new Error("Network appears offline");
556
+ }
557
+ try {
558
+ const response = await fetchWithTimeout(`${this.apiUrl}/api.json`, this.timeoutMs);
559
+ const data = await response.json();
560
+ const entries = [];
561
+ if (data && typeof data === "object") {
562
+ for (const [providerId, providerData] of Object.entries(data)) {
563
+ if (typeof providerData !== "object" || providerData === null) continue;
564
+ const models = providerData.models;
565
+ if (!Array.isArray(models)) continue;
566
+ for (const model of models) {
567
+ entries.push(transformModelsDevEntry({
568
+ ...model,
569
+ provider: providerId
570
+ }));
571
+ }
572
+ }
573
+ }
574
+ await this.cache.setMany(entries);
575
+ await this.cache.persist();
576
+ this.lastFetchTime = now;
577
+ recordNetworkSuccess();
578
+ return entries;
579
+ } catch (error) {
580
+ recordNetworkFailure(error instanceof Error ? error.message : String(error));
581
+ throw error;
582
+ }
583
+ }
584
+ async ping() {
585
+ try {
586
+ const response = await fetchWithTimeout(this.apiUrl, 5e3);
587
+ recordNetworkSuccess();
588
+ return response.ok;
589
+ } catch {
590
+ return false;
591
+ }
592
+ }
593
+ };
594
+
595
+ // src/capabilities/remote/source.ts
596
+ var RemoteCapabilitySource = class {
597
+ priority = 4 /* RemoteAPI */;
598
+ name = "Remote API (models.dev)";
599
+ fetcher;
600
+ cache;
601
+ fetchPromise;
602
+ enabled;
603
+ constructor(cache, options = {}) {
604
+ const opts = { ...DEFAULT_RESOLVER_OPTIONS, ...options };
605
+ this.cache = cache;
606
+ this.fetcher = new RemoteCapabilityFetcher(cache, opts);
607
+ this.enabled = opts.enableRemoteFetch;
608
+ }
609
+ async lookup(modelId, provider) {
610
+ if (!this.enabled) {
611
+ return {
612
+ source: this.priority,
613
+ confident: false,
614
+ error: "Remote fetch disabled"
615
+ };
616
+ }
617
+ const cached = await this.cache.get(modelId, provider);
618
+ if (cached) {
619
+ return {
620
+ entry: cached,
621
+ source: 1 /* LocalCache */,
622
+ confident: true
623
+ };
624
+ }
625
+ if (!this.fetchPromise) {
626
+ this.fetchPromise = this.fetcher.fetchAll().finally(() => {
627
+ this.fetchPromise = void 0;
628
+ });
629
+ }
630
+ try {
631
+ await this.fetchPromise;
632
+ const entry = await this.cache.get(modelId, provider);
633
+ if (entry) {
634
+ return {
635
+ entry,
636
+ source: this.priority,
637
+ confident: true
638
+ };
639
+ }
640
+ } catch (error) {
641
+ return {
642
+ source: this.priority,
643
+ confident: false,
644
+ error: error instanceof Error ? error.message : String(error)
645
+ };
646
+ }
647
+ return {
648
+ source: this.priority,
649
+ confident: false,
650
+ error: "Model not found in remote database"
651
+ };
652
+ }
653
+ async isAvailable() {
654
+ return this.enabled && getNetworkStatus().online;
655
+ }
656
+ async refresh() {
657
+ if (!this.enabled) return;
658
+ await this.fetcher.fetchAll();
659
+ }
660
+ };
661
+
662
+ // src/capabilities/resolver.ts
663
+ function extractModelId(model) {
664
+ return getModelId(model);
665
+ }
666
+ function extractProvider(model) {
667
+ const provider = getProviderId(model);
668
+ return provider ?? inferProvider(extractModelId(model));
669
+ }
670
+ var ModelCapabilityResolver = class {
671
+ options;
672
+ cache;
673
+ sources;
674
+ initialized = false;
675
+ initPromise;
676
+ constructor(options = {}) {
677
+ this.options = { ...DEFAULT_RESOLVER_OPTIONS, ...options };
678
+ this.cache = new CapabilityCache(this.options);
679
+ this.sources = [
680
+ new CacheCapabilitySource(this.cache),
681
+ new PatternCapabilitySource()
682
+ ];
683
+ if (this.options.enableRemoteFetch) {
684
+ this.sources.push(new RemoteCapabilitySource(this.cache, this.options));
685
+ }
686
+ this.sources.sort((a, b) => a.priority - b.priority);
687
+ }
688
+ /**
689
+ * Initialize the resolver (load cache, optionally fetch remote)
690
+ */
691
+ async initialize() {
692
+ if (this.initialized) return;
693
+ if (this.initPromise) return this.initPromise;
694
+ this.initPromise = (async () => {
695
+ if (this.options.enableRemoteFetch) {
696
+ const remoteSource = this.sources.find(
697
+ (s) => s instanceof RemoteCapabilitySource
698
+ );
699
+ if (remoteSource) {
700
+ remoteSource.refresh().catch((err) => {
701
+ console.warn("[agent-core] Background refresh failed:", err);
702
+ });
703
+ }
704
+ }
705
+ this.initialized = true;
706
+ })();
707
+ return this.initPromise;
708
+ }
709
+ /**
710
+ * Resolve capabilities for a model
711
+ */
712
+ async resolve(model) {
713
+ const start = Date.now();
714
+ await this.initialize();
715
+ const modelId = extractModelId(model);
716
+ const provider = extractProvider(model);
717
+ const overrideLookup = findCapabilityOverride(this.options.modelOverrides, modelId, provider);
718
+ let bestResult;
719
+ for (const source of this.sources) {
720
+ try {
721
+ const result = await source.lookup(modelId, provider);
722
+ if (result.entry) {
723
+ if (result.confident) {
724
+ bestResult = result;
725
+ break;
726
+ }
727
+ if (!bestResult) {
728
+ bestResult = result;
729
+ }
730
+ }
731
+ } catch (error) {
732
+ console.warn(`[agent-core] Source ${source.name} failed:`, error);
733
+ }
734
+ }
735
+ if (!bestResult?.entry) {
736
+ throw new Error(`Failed to resolve capabilities for model: ${modelId}`);
737
+ }
738
+ const entry = applyCapabilityOverride(bestResult.entry, overrideLookup.override);
739
+ return {
740
+ entry,
741
+ source: bestResult.source,
742
+ confident: bestResult.confident,
743
+ resolveTimeMs: Date.now() - start
744
+ };
745
+ }
746
+ /**
747
+ * Quick check if a model supports reasoning
748
+ * Uses cache/patterns only for speed
749
+ */
750
+ async supportsReasoning(model) {
751
+ const modelId = extractModelId(model);
752
+ const provider = extractProvider(model);
753
+ const cached = await this.cache.get(modelId, provider);
754
+ if (cached) {
755
+ return cached.capabilities.reasoning;
756
+ }
757
+ return likelySupportsReasoning(modelId);
758
+ }
759
+ /**
760
+ * Get capabilities for a model
761
+ */
762
+ async getCapabilities(model) {
763
+ const result = await this.resolve(model);
764
+ return result.entry.capabilities;
765
+ }
766
+ /**
767
+ * Get provider compatibility settings
768
+ */
769
+ async getCompatibility(model) {
770
+ const result = await this.resolve(model);
771
+ return result.entry.compatibility;
772
+ }
773
+ /**
774
+ * Force refresh from remote API
775
+ */
776
+ async refreshRemote() {
777
+ if (!this.options.enableRemoteFetch) {
778
+ throw new Error("Remote fetch is not enabled");
779
+ }
780
+ const remoteSource = this.sources.find(
781
+ (s) => s instanceof RemoteCapabilitySource
782
+ );
783
+ if (remoteSource) {
784
+ await remoteSource.refresh();
785
+ }
786
+ }
787
+ /**
788
+ * Get current network status
789
+ */
790
+ getNetworkStatus() {
791
+ return getNetworkStatus();
792
+ }
793
+ /**
794
+ * Get resolver statistics
795
+ */
796
+ getStats() {
797
+ const cacheStats = this.cache.stats();
798
+ const networkStatus = getNetworkStatus();
799
+ return {
800
+ cacheSize: cacheStats.size,
801
+ cacheLoaded: cacheStats.loaded,
802
+ remoteFetchEnabled: this.options.enableRemoteFetch,
803
+ networkOnline: networkStatus.online
804
+ };
805
+ }
806
+ /**
807
+ * Clear all cached data
808
+ */
809
+ async clearCache() {
810
+ await this.cache.clear();
811
+ }
812
+ /**
813
+ * List all available models
814
+ * Fetches from remote if cache is empty and remote is enabled
815
+ */
816
+ async listModels() {
817
+ await this.initialize();
818
+ const stats = this.cache.stats();
819
+ if (stats.size === 0 && this.options.enableRemoteFetch) {
820
+ const remoteSource = this.sources.find(
821
+ (s) => s instanceof RemoteCapabilitySource
822
+ );
823
+ if (remoteSource) {
824
+ await remoteSource.refresh();
825
+ }
826
+ }
827
+ return this.cache.getAll();
828
+ }
829
+ /**
830
+ * List all available models grouped by provider
831
+ */
832
+ async listModelsByProvider() {
833
+ await this.initialize();
834
+ const stats = this.cache.stats();
835
+ if (stats.size === 0 && this.options.enableRemoteFetch) {
836
+ const remoteSource = this.sources.find(
837
+ (s) => s instanceof RemoteCapabilitySource
838
+ );
839
+ if (remoteSource) {
840
+ await remoteSource.refresh();
841
+ }
842
+ }
843
+ return this.cache.getAllByProvider();
844
+ }
845
+ };
846
+ var defaultResolver;
847
+ function getDefaultResolver() {
848
+ if (!defaultResolver) {
849
+ defaultResolver = new ModelCapabilityResolver({
850
+ enableRemoteFetch: process.env.CODE_AGENT_ENABLE_REMOTE_FETCH === "true",
851
+ remoteApiUrl: process.env.CODE_AGENT_MODELS_API || "https://models.dev"
852
+ });
853
+ }
854
+ return defaultResolver;
855
+ }
856
+ function configureResolver(options) {
857
+ defaultResolver = new ModelCapabilityResolver(options);
858
+ }
859
+
860
+ export {
861
+ SourcePriority,
862
+ DEFAULT_RESOLVER_OPTIONS,
863
+ inferProvider,
864
+ PatternCapabilitySource,
865
+ likelySupportsReasoning,
866
+ getProviderCompatibility,
867
+ findCapabilityOverride,
868
+ applyCapabilityOverride,
869
+ CapabilityCache,
870
+ CacheCapabilitySource,
871
+ getNetworkStatus,
872
+ RemoteCapabilityFetcher,
873
+ RemoteCapabilitySource,
874
+ extractModelId,
875
+ extractProvider,
876
+ ModelCapabilityResolver,
877
+ getDefaultResolver,
878
+ configureResolver
879
+ };