@everworker/oneringai 0.2.2 → 0.3.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 CHANGED
@@ -16,6 +16,7 @@
16
16
  - [2. Dynamic Tool Management](#2-dynamic-tool-management-new)
17
17
  - [3. Tool Execution Plugins](#3-tool-execution-plugins-new)
18
18
  - [4. Session Persistence](#4-session-persistence)
19
+ - [Storage Registry](#storage-registry)
19
20
  - [5. Working Memory](#5-working-memory)
20
21
  - [6. Research with Search Tools](#6-research-with-search-tools)
21
22
  - [7. Context Management](#7-context-management)
@@ -27,8 +28,9 @@
27
28
  - [13. Streaming](#13-streaming)
28
29
  - [14. OAuth for External APIs](#14-oauth-for-external-apis)
29
30
  - [15. Developer Tools](#15-developer-tools)
30
- - [16. Document Reader](#16-document-reader-new) — PDF, DOCX, XLSX, PPTX, CSV, HTML, images
31
- - [17. External API Integration](#17-external-api-integration) — Scoped Registry, Vendor Templates, Tool Discovery
31
+ - [16. Custom Tool Generation](#16-custom-tool-generation-new) — Agents create, test, and persist their own tools
32
+ - [17. Document Reader](#17-document-reader) — PDF, DOCX, XLSX, PPTX, CSV, HTML, images
33
+ - [18. External API Integration](#18-external-api-integration) — Scoped Registry, Vendor Templates, Tool Discovery
32
34
  - [MCP Integration](#mcp-model-context-protocol-integration)
33
35
  - [Documentation](#documentation)
34
36
  - [Examples](#examples)
@@ -58,7 +60,7 @@
58
60
  ## HOSEA APP
59
61
  We realize that library alone in these times is not enough to get you excited, so we built a FREE FOREVER desktop app on top of this library to showcase its power! It's as easy to start using as cloning this library's repo, and then `cd apps/hosea` and then `npm install` and then `npm run dev`. Or watch the video first:
60
62
 
61
- ![Watch the demo](https://img.youtube.com/vi/_LzDiuOQD8Y/maxresdefault.jpg)](https://www.youtube.com/watch?v=_LzDiuOQD8Y)
63
+ [![Watch the demo](https://img.youtube.com/vi/_LzDiuOQD8Y/maxresdefault.jpg)](https://www.youtube.com/watch?v=_LzDiuOQD8Y)
62
64
 
63
65
  Or read the more detailed installation / setup instructions [here](https://github.com/Integrail/oneringai/blob/main/apps/hosea/README.md)
64
66
 
@@ -68,7 +70,7 @@ Better to see once and then dig in the code! :)
68
70
 
69
71
  - ✨ **Unified API** - One interface for 10+ AI providers (OpenAI, Anthropic, Google, Groq, DeepSeek, and more)
70
72
  - 🔑 **Connector-First Architecture** - Single auth system with support for multiple keys per vendor
71
- - 📊 **Model Registry** - Complete metadata for 23+ latest (2026) models with pricing and features
73
+ - 📊 **Model Registry** - Complete metadata for 35+ latest (2026) models with pricing and features
72
74
  - 🎤 **Audio Capabilities** - Text-to-Speech (TTS) and Speech-to-Text (STT) with OpenAI and Groq
73
75
  - 🖼️ **Image Generation** - DALL-E 3, gpt-image-1, Google Imagen 4 with editing and variations
74
76
  - 🎬 **Video Generation** - NEW: OpenAI Sora 2 and Google Veo 3 for AI video creation
@@ -87,12 +89,14 @@ Better to see once and then dig in the code! :)
87
89
  - 📝 **Persistent Instructions** - NEW: Agent-level custom instructions that persist across sessions on disk
88
90
  - 🛠️ **Agentic Workflows** - Built-in tool calling and multi-turn conversations
89
91
  - 🔧 **Developer Tools** - NEW: Filesystem and shell tools for coding assistants (read, write, edit, grep, glob, bash)
92
+ - 🧰 **Custom Tool Generation** - NEW: Let agents create, test, and persist their own reusable tools at runtime — complete meta-tool system with VM sandbox
90
93
  - 🖥️ **Desktop Automation** - NEW: OS-level computer use — screenshot, mouse, keyboard, and window control for vision-driven agent loops
91
94
  - 📄 **Document Reader** - NEW: Universal file-to-text converter — PDF, DOCX, XLSX, PPTX, CSV, HTML, images auto-converted to markdown
92
95
  - 🔌 **MCP Integration** - NEW: Model Context Protocol client for seamless tool discovery from local and remote servers
93
96
  - 👁️ **Vision Support** - Analyze images with AI across all providers
94
97
  - 📋 **Clipboard Integration** - Paste screenshots directly (like Claude Code!)
95
98
  - 🔐 **Scoped Connector Registry** - NEW: Pluggable access control for multi-tenant connector isolation
99
+ - 💾 **StorageRegistry** - Centralized storage configuration — swap all backends (sessions, media, custom tools, etc.) with one `configure()` call
96
100
  - 🔐 **OAuth 2.0** - Full OAuth support for external APIs with encrypted token storage
97
101
  - 📦 **Vendor Templates** - NEW: Pre-configured auth templates for 43+ services (GitHub, Slack, Stripe, etc.)
98
102
  - 🔄 **Streaming** - Real-time responses with event streams
@@ -320,7 +324,7 @@ const response = await agent.run([
320
324
  Connector-based web search with multiple providers:
321
325
 
322
326
  ```typescript
323
- import { Connector, SearchProvider, Services, webSearch, Agent } from '@everworker/oneringai';
327
+ import { Connector, SearchProvider, ConnectorTools, Services, Agent, tools } from '@everworker/oneringai';
324
328
 
325
329
  // Create search connector
326
330
  Connector.create({
@@ -338,11 +342,13 @@ const results = await search.search('latest AI developments 2026', {
338
342
  language: 'en',
339
343
  });
340
344
 
341
- // Option 2: Use with Agent
345
+ // Option 2: Use with Agent via ConnectorTools
346
+ const searchTools = ConnectorTools.for('serper-main');
347
+
342
348
  const agent = Agent.create({
343
349
  connector: 'openai',
344
350
  model: 'gpt-4',
345
- tools: [webSearch],
351
+ tools: [...searchTools, tools.webFetch],
346
352
  });
347
353
 
348
354
  await agent.run('Search for quantum computing news and summarize');
@@ -359,7 +365,7 @@ await agent.run('Search for quantum computing news and summarize');
359
365
  Enterprise web scraping with automatic fallback and bot protection bypass:
360
366
 
361
367
  ```typescript
362
- import { Connector, ScrapeProvider, Services, webScrape, Agent } from '@everworker/oneringai';
368
+ import { Connector, ScrapeProvider, ConnectorTools, Services, Agent, tools } from '@everworker/oneringai';
363
369
 
364
370
  // Create ZenRows connector for bot-protected sites
365
371
  Connector.create({
@@ -379,19 +385,24 @@ const result = await scraper.scrape('https://protected-site.com', {
379
385
  },
380
386
  });
381
387
 
382
- // Option 2: Use webScrape tool with Agent
388
+ // Option 2: Use web_scrape tool with Agent via ConnectorTools
389
+ const scrapeTools = ConnectorTools.for('zenrows');
390
+
383
391
  const agent = Agent.create({
384
392
  connector: 'openai',
385
393
  model: 'gpt-4',
386
- tools: [webScrape],
394
+ tools: [...scrapeTools, tools.webFetch],
387
395
  });
388
396
 
389
- // webScrape auto-falls back: native → JS → API
397
+ // web_scrape auto-falls back: native → API
390
398
  await agent.run('Scrape https://example.com and summarize');
391
399
  ```
392
400
 
393
401
  **Supported Scrape Providers:**
394
402
  - **ZenRows** - Enterprise scraping with JS rendering, residential proxies, anti-bot bypass
403
+ - **Jina Reader** - Clean content extraction with AI-powered readability
404
+ - **Firecrawl** - Web scraping with JavaScript rendering
405
+ - **ScrapingBee** - Headless browser scraping with proxy rotation
395
406
 
396
407
  ## Supported Providers
397
408
 
@@ -401,7 +412,7 @@ await agent.run('Scrape https://example.com and summarize');
401
412
  | **Anthropic (Claude)** | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | 200K |
402
413
  | **Google (Gemini)** | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | 1M |
403
414
  | **Google Vertex AI** | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | 1M |
404
- | **Grok (xAI)** | ✅ | ✅ | ❌ | ❌ | | | ✅ | 128K |
415
+ | **Grok (xAI)** | ✅ | ✅ | ❌ | ❌ | | | ✅ | 128K |
405
416
  | **Groq** | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ✅ | 128K |
406
417
  | **Together AI** | ✅ | Some | ❌ | ❌ | ❌ | ❌ | ✅ | 128K |
407
418
  | **DeepSeek** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | 64K |
@@ -612,6 +623,33 @@ if (loaded) {
612
623
 
613
624
  **Storage Location:** `~/.oneringai/agents/<agentId>/sessions/<sessionId>.json`
614
625
 
626
+ ### Storage Registry
627
+
628
+ Swap all storage backends (sessions, media, custom tools, OAuth tokens, etc.) with a single `configure()` call at init time. No breaking changes — all existing APIs continue to work.
629
+
630
+ ```typescript
631
+ import { StorageRegistry } from '@everworker/oneringai';
632
+
633
+ StorageRegistry.configure({
634
+ media: new S3MediaStorage(),
635
+ oauthTokens: new EncryptedFileTokenStorage(),
636
+ // Context-aware factories — optional StorageContext for multi-tenant partitioning
637
+ customTools: (ctx) => new MongoCustomToolStorage(ctx?.userId),
638
+ sessions: (agentId, ctx) => new RedisContextStorage(agentId, ctx?.tenantId),
639
+ persistentInstructions: (agentId, ctx) => new DBInstructionsStorage(agentId, ctx?.userId),
640
+ workingMemory: (ctx) => new RedisMemoryStorage(ctx?.tenantId),
641
+ });
642
+
643
+ // All agents and tools automatically use these backends
644
+ const agent = Agent.create({ connector: 'openai', model: 'gpt-4' });
645
+ ```
646
+
647
+ **Resolution order:** explicit constructor param > `StorageRegistry` > file-based default.
648
+
649
+ **Multi-tenant:** Factories receive an optional `StorageContext` (opaque, like `ConnectorAccessContext`). Set via `StorageRegistry.setContext({ userId, tenantId })` — auto-forwarded to all factory calls for per-user/per-tenant storage partitioning.
650
+
651
+ See the [User Guide](./USER_GUIDE.md#centralized-storage-registry) for full documentation.
652
+
615
653
  ### 5. Working Memory
616
654
 
617
655
  Use the `WorkingMemoryPluginNextGen` for agents that need to store and retrieve data:
@@ -643,7 +681,7 @@ await agent.run('Check weather for SF and remember the result');
643
681
  Use `Agent` with search tools and `WorkingMemoryPluginNextGen` for research workflows:
644
682
 
645
683
  ```typescript
646
- import { Agent, webSearch, SearchProvider, Connector, Services } from '@everworker/oneringai';
684
+ import { Agent, ConnectorTools, Connector, Services, tools } from '@everworker/oneringai';
647
685
 
648
686
  // Setup search connector
649
687
  Connector.create({
@@ -654,10 +692,12 @@ Connector.create({
654
692
  });
655
693
 
656
694
  // Create agent with search and memory
695
+ const searchTools = ConnectorTools.for('serper-main');
696
+
657
697
  const agent = Agent.create({
658
698
  connector: 'openai',
659
699
  model: 'gpt-4',
660
- tools: [webSearch],
700
+ tools: [...searchTools, tools.webFetch],
661
701
  context: {
662
702
  features: { workingMemory: true },
663
703
  },
@@ -933,25 +973,26 @@ Complete metadata for 23+ models:
933
973
  import { getModelInfo, calculateCost, LLM_MODELS, Vendor } from '@everworker/oneringai';
934
974
 
935
975
  // Get model information
936
- const model = getModelInfo('gpt-5.2-thinking');
976
+ const model = getModelInfo('gpt-5.2');
937
977
  console.log(model.features.input.tokens); // 400000
938
978
  console.log(model.features.input.cpm); // 1.75 (cost per million)
939
979
 
940
980
  // Calculate costs
941
- const cost = calculateCost('gpt-5.2-thinking', 50_000, 2_000);
981
+ const cost = calculateCost('gpt-5.2', 50_000, 2_000);
942
982
  console.log(`Cost: $${cost}`); // $0.1155
943
983
 
944
984
  // With caching
945
- const cachedCost = calculateCost('gpt-5.2-thinking', 50_000, 2_000, {
985
+ const cachedCost = calculateCost('gpt-5.2', 50_000, 2_000, {
946
986
  useCachedInput: true
947
987
  });
948
988
  console.log(`Cached: $${cachedCost}`); // $0.0293 (90% discount)
949
989
  ```
950
990
 
951
991
  **Available Models:**
952
- - **OpenAI (11)**: GPT-5.2 series, GPT-5 family, GPT-4.1, o3-mini
953
- - **Anthropic (5)**: Claude 4.5 series, Claude 4.x
992
+ - **OpenAI (12)**: GPT-5.2 series, GPT-5 family, GPT-4.1, GPT-4o, o3-mini, o1
993
+ - **Anthropic (7)**: Claude 4.5 series, Claude 4.x, Claude 3.7 Sonnet, Claude 3 Haiku
954
994
  - **Google (7)**: Gemini 3, Gemini 2.5
995
+ - **Grok (9)**: Grok 4.1, Grok 4, Grok Code, Grok 3, Grok 2 Vision
955
996
 
956
997
  ### 13. Streaming
957
998
 
@@ -1024,7 +1065,42 @@ await agent.run('Run npm test and report any failures');
1024
1065
  - Timeout protection (default 2 min)
1025
1066
  - Output truncation for large outputs
1026
1067
 
1027
- ### 16. Desktop Automation Tools (NEW)
1068
+ ### 16. Custom Tool Generation (NEW)
1069
+
1070
+ Let agents **create their own tools** at runtime — draft, test, iterate, save, and reuse. The agent writes JavaScript code, validates it, tests it in the VM sandbox, and persists it for future use. All 6 meta-tools are auto-registered and visible in Hosea.
1071
+
1072
+ ```typescript
1073
+ import { createCustomToolMetaTools, hydrateCustomTool } from '@everworker/oneringai';
1074
+
1075
+ // Give an agent the ability to create tools
1076
+ const agent = Agent.create({
1077
+ connector: 'openai',
1078
+ model: 'gpt-4',
1079
+ tools: [...createCustomToolMetaTools()],
1080
+ });
1081
+
1082
+ // The agent can now: draft → test → save tools autonomously
1083
+ await agent.run('Create a tool that fetches weather data from the OpenWeather API');
1084
+
1085
+ // Later: load and use a saved tool
1086
+ import { createFileCustomToolStorage } from '@everworker/oneringai';
1087
+ const storage = createFileCustomToolStorage();
1088
+ const definition = await storage.load('fetch_weather');
1089
+ const weatherTool = hydrateCustomTool(definition!);
1090
+
1091
+ // Register on any agent
1092
+ agent.tools.register(weatherTool, { source: 'custom', tags: ['weather', 'api'] });
1093
+ ```
1094
+
1095
+ **Meta-Tools:** `custom_tool_draft` (validate), `custom_tool_test` (execute in sandbox), `custom_tool_save` (persist), `custom_tool_list` (search), `custom_tool_load` (retrieve), `custom_tool_delete` (remove)
1096
+
1097
+ **Dynamic Descriptions:** Draft and test tools use `descriptionFactory` to show all available connectors and the full sandbox API — automatically updated when connectors are added or removed.
1098
+
1099
+ **Pluggable Storage:** Default `FileCustomToolStorage` saves to `~/.oneringai/custom-tools/`. Implement `ICustomToolStorage` for MongoDB, S3, or any backend.
1100
+
1101
+ > See the [User Guide](./USER_GUIDE.md#custom-tool-generation) for the complete workflow, sandbox API reference, and examples.
1102
+
1103
+ ### 17. Desktop Automation Tools (NEW)
1028
1104
 
1029
1105
  OS-level desktop automation for building "computer use" agents — screenshot the screen, send to a vision model, receive tool calls (click, type, etc.), execute them, repeat:
1030
1106
 
@@ -1060,7 +1136,7 @@ await agent.run('Open Safari and search for "weather forecast"');
1060
1136
  - Screenshots use the `__images` convention for automatic multimodal handling across all providers (Anthropic, OpenAI, Google)
1061
1137
  - Requires `@nut-tree-fork/nut-js` as an optional peer dependency: `npm install @nut-tree-fork/nut-js`
1062
1138
 
1063
- ### 17. Document Reader (NEW)
1139
+ ### 18. Document Reader
1064
1140
 
1065
1141
  Universal file-to-LLM-content converter. Reads arbitrary document formats and produces clean markdown text with optional image extraction:
1066
1142
 
@@ -1125,7 +1201,7 @@ await agent.run([
1125
1201
 
1126
1202
  See the [User Guide](./USER_GUIDE.md#document-reader) for complete API reference and configuration options.
1127
1203
 
1128
- ### 18. External API Integration
1204
+ ### 19. External API Integration
1129
1205
 
1130
1206
  Connect your AI agents to 35+ external services with enterprise-grade resilience:
1131
1207
 
@@ -1477,4 +1553,4 @@ MIT License - See [LICENSE](./LICENSE) file.
1477
1553
 
1478
1554
  ---
1479
1555
 
1480
- **Version:** 0.2.1 | **Last Updated:** 2026-02-11 | **[User Guide](./USER_GUIDE.md)** | **[API Reference](./API_REFERENCE.md)** | **[Changelog](./CHANGELOG.md)**
1556
+ **Version:** 0.2.1 | **Last Updated:** 2026-02-17 | **[User Guide](./USER_GUIDE.md)** | **[API Reference](./API_REFERENCE.md)** | **[Changelog](./CHANGELOG.md)**
@@ -295,7 +295,6 @@ interface ConnectorFetchOptions extends RequestInit {
295
295
  */
296
296
  declare class Connector {
297
297
  private static registry;
298
- private static defaultStorage;
299
298
  /**
300
299
  * Create and register a new connector
301
300
  * @param config - Must include `name` field
@@ -323,6 +322,11 @@ declare class Connector {
323
322
  * Clear all connectors (useful for testing)
324
323
  */
325
324
  static clear(): void;
325
+ /**
326
+ * Get the default token storage for OAuth connectors.
327
+ * Resolves from StorageRegistry, falling back to MemoryStorage.
328
+ */
329
+ private static get defaultStorage();
326
330
  /**
327
331
  * Set default token storage for OAuth connectors
328
332
  */
@@ -502,4 +506,4 @@ interface IProvider {
502
506
  validateConfig(): Promise<boolean>;
503
507
  }
504
508
 
505
- export { type APIKeyConnectorAuth as A, type ConnectorAccessContext as C, DEFAULT_CONNECTOR_TIMEOUT as D, type IConnectorRegistry as I, type JWTConnectorAuth as J, type OAuthConnectorAuth as O, type ProviderCapabilities as P, type StoredToken as S, type IConnectorAccessPolicy as a, Connector as b, type IProvider as c, type ConnectorFetchOptions as d, type ITokenStorage as e, type ConnectorConfig as f, type ConnectorAuth as g, type ConnectorConfigResult as h, DEFAULT_MAX_RETRIES as i, DEFAULT_RETRYABLE_STATUSES as j, DEFAULT_BASE_DELAY_MS as k, DEFAULT_MAX_DELAY_MS as l };
509
+ export { type APIKeyConnectorAuth as A, type ConnectorAccessContext as C, DEFAULT_BASE_DELAY_MS as D, type IConnectorRegistry as I, type JWTConnectorAuth as J, type OAuthConnectorAuth as O, type ProviderCapabilities as P, type StoredToken as S, type IConnectorAccessPolicy as a, Connector as b, type ConnectorConfig as c, type ITokenStorage as d, type IProvider as e, type ConnectorFetchOptions as f, type ConnectorAuth as g, type ConnectorConfigResult as h, DEFAULT_CONNECTOR_TIMEOUT as i, DEFAULT_MAX_DELAY_MS as j, DEFAULT_MAX_RETRIES as k, DEFAULT_RETRYABLE_STATUSES as l };
@@ -295,7 +295,6 @@ interface ConnectorFetchOptions extends RequestInit {
295
295
  */
296
296
  declare class Connector {
297
297
  private static registry;
298
- private static defaultStorage;
299
298
  /**
300
299
  * Create and register a new connector
301
300
  * @param config - Must include `name` field
@@ -323,6 +322,11 @@ declare class Connector {
323
322
  * Clear all connectors (useful for testing)
324
323
  */
325
324
  static clear(): void;
325
+ /**
326
+ * Get the default token storage for OAuth connectors.
327
+ * Resolves from StorageRegistry, falling back to MemoryStorage.
328
+ */
329
+ private static get defaultStorage();
326
330
  /**
327
331
  * Set default token storage for OAuth connectors
328
332
  */
@@ -502,4 +506,4 @@ interface IProvider {
502
506
  validateConfig(): Promise<boolean>;
503
507
  }
504
508
 
505
- export { type APIKeyConnectorAuth as A, type ConnectorAccessContext as C, DEFAULT_CONNECTOR_TIMEOUT as D, type IConnectorRegistry as I, type JWTConnectorAuth as J, type OAuthConnectorAuth as O, type ProviderCapabilities as P, type StoredToken as S, type IConnectorAccessPolicy as a, Connector as b, type IProvider as c, type ConnectorFetchOptions as d, type ITokenStorage as e, type ConnectorConfig as f, type ConnectorAuth as g, type ConnectorConfigResult as h, DEFAULT_MAX_RETRIES as i, DEFAULT_RETRYABLE_STATUSES as j, DEFAULT_BASE_DELAY_MS as k, DEFAULT_MAX_DELAY_MS as l };
509
+ export { type APIKeyConnectorAuth as A, type ConnectorAccessContext as C, DEFAULT_BASE_DELAY_MS as D, type IConnectorRegistry as I, type JWTConnectorAuth as J, type OAuthConnectorAuth as O, type ProviderCapabilities as P, type StoredToken as S, type IConnectorAccessPolicy as a, Connector as b, type ConnectorConfig as c, type ITokenStorage as d, type IProvider as e, type ConnectorFetchOptions as f, type ConnectorAuth as g, type ConnectorConfigResult as h, DEFAULT_CONNECTOR_TIMEOUT as i, DEFAULT_MAX_DELAY_MS as j, DEFAULT_MAX_RETRIES as k, DEFAULT_RETRYABLE_STATUSES as l };
@@ -1,4 +1,4 @@
1
- import { c as IProvider, b as Connector } from './IProvider-DcYJ3YE-.js';
1
+ import { e as IProvider, b as Connector } from './IProvider-BUbU5UwV.js';
2
2
  import { V as Vendor } from './Vendor-DYh_bzwo.js';
3
3
 
4
4
  /**
@@ -334,4 +334,4 @@ declare function getImageModelsWithFeature(feature: keyof IImageModelDescription
334
334
  */
335
335
  declare function calculateImageCost(modelName: string, imageCount: number, quality?: 'standard' | 'hd'): number | null;
336
336
 
337
- export { type AudioFormat as A, type IBaseModelDescription as I, type OutputFormat as O, type QualityLevel as Q, type SimpleGenerateOptions as S, type VendorOptionSchema as V, type IImageProvider as a, ImageGeneration as b, type ImageGenerationCreateOptions as c, type IImageModelDescription as d, type ImageModelCapabilities as e, type ImageModelPricing as f, IMAGE_MODELS as g, IMAGE_MODEL_REGISTRY as h, getImageModelInfo as i, getImageModelsByVendor as j, getActiveImageModels as k, getImageModelsWithFeature as l, calculateImageCost as m, type ImageGenerateOptions as n, type ImageEditOptions as o, type ImageVariationOptions as p, type ImageResponse as q, type AspectRatio$1 as r, type ISourceLinks as s };
337
+ export { type AudioFormat as A, type IBaseModelDescription as I, type OutputFormat as O, type QualityLevel as Q, type SimpleGenerateOptions as S, type VendorOptionSchema as V, type IImageProvider as a, type AspectRatio$1 as b, type IImageModelDescription as c, IMAGE_MODELS as d, IMAGE_MODEL_REGISTRY as e, type ISourceLinks as f, type ImageEditOptions as g, type ImageGenerateOptions as h, ImageGeneration as i, type ImageGenerationCreateOptions as j, type ImageModelCapabilities as k, type ImageModelPricing as l, type ImageResponse as m, type ImageVariationOptions as n, calculateImageCost as o, getActiveImageModels as p, getImageModelInfo as q, getImageModelsByVendor as r, getImageModelsWithFeature as s };
@@ -1,4 +1,4 @@
1
- import { c as IProvider, b as Connector } from './IProvider-c4QCbPjn.cjs';
1
+ import { e as IProvider, b as Connector } from './IProvider-Br817mKc.cjs';
2
2
  import { V as Vendor } from './Vendor-DYh_bzwo.cjs';
3
3
 
4
4
  /**
@@ -334,4 +334,4 @@ declare function getImageModelsWithFeature(feature: keyof IImageModelDescription
334
334
  */
335
335
  declare function calculateImageCost(modelName: string, imageCount: number, quality?: 'standard' | 'hd'): number | null;
336
336
 
337
- export { type AudioFormat as A, type IBaseModelDescription as I, type OutputFormat as O, type QualityLevel as Q, type SimpleGenerateOptions as S, type VendorOptionSchema as V, type IImageProvider as a, ImageGeneration as b, type ImageGenerationCreateOptions as c, type IImageModelDescription as d, type ImageModelCapabilities as e, type ImageModelPricing as f, IMAGE_MODELS as g, IMAGE_MODEL_REGISTRY as h, getImageModelInfo as i, getImageModelsByVendor as j, getActiveImageModels as k, getImageModelsWithFeature as l, calculateImageCost as m, type ImageGenerateOptions as n, type ImageEditOptions as o, type ImageVariationOptions as p, type ImageResponse as q, type AspectRatio$1 as r, type ISourceLinks as s };
337
+ export { type AudioFormat as A, type IBaseModelDescription as I, type OutputFormat as O, type QualityLevel as Q, type SimpleGenerateOptions as S, type VendorOptionSchema as V, type IImageProvider as a, type AspectRatio$1 as b, type IImageModelDescription as c, IMAGE_MODELS as d, IMAGE_MODEL_REGISTRY as e, type ISourceLinks as f, type ImageEditOptions as g, type ImageGenerateOptions as h, ImageGeneration as i, type ImageGenerationCreateOptions as j, type ImageModelCapabilities as k, type ImageModelPricing as l, type ImageResponse as m, type ImageVariationOptions as n, calculateImageCost as o, getActiveImageModels as p, getImageModelInfo as q, getImageModelsByVendor as r, getImageModelsWithFeature as s };
@@ -1,4 +1,4 @@
1
- export { aD as AfterToolContext, av as AgentEventName, A as AgentEvents, ay as AgenticLoopEventName, ax as AgenticLoopEvents, aG as ApprovalResult, aE as ApproveToolContext, m as AuditEntry, aC as BeforeToolContext, aI as ExecutionCompleteEvent, aw as ExecutionConfig, E as ExecutionContext, l as ExecutionMetrics, aH as ExecutionStartEvent, j as HistoryMode, aA as Hook, H as HookConfig, au as HookManager, az as HookName, aL as LLMRequestEvent, aM as LLMResponseEvent, aB as ModifyingHook, aK as ToolCompleteEvent, aF as ToolModification, aJ as ToolStartEvent } from '../../index-D62LXWdW.cjs';
2
- import '../../IProvider-c4QCbPjn.cjs';
1
+ export { x as AfterToolContext, y as AgentEventName, A as AgentEvents, z as AgenticLoopEventName, B as AgenticLoopEvents, D as ApprovalResult, G as ApproveToolContext, m as AuditEntry, J as BeforeToolContext, aH as ExecutionCompleteEvent, V as ExecutionConfig, E as ExecutionContext, l as ExecutionMetrics, aI as ExecutionStartEvent, j as HistoryMode, X as Hook, H as HookConfig, Y as HookManager, Z as HookName, aJ as LLMRequestEvent, aK as LLMResponseEvent, a6 as ModifyingHook, aL as ToolCompleteEvent, an as ToolModification, aM as ToolStartEvent } from '../../index-WlQwiNF8.cjs';
2
+ import '../../IProvider-Br817mKc.cjs';
3
3
  import '../../Vendor-DYh_bzwo.cjs';
4
4
  import 'eventemitter3';
@@ -1,4 +1,4 @@
1
- export { aD as AfterToolContext, av as AgentEventName, A as AgentEvents, ay as AgenticLoopEventName, ax as AgenticLoopEvents, aG as ApprovalResult, aE as ApproveToolContext, m as AuditEntry, aC as BeforeToolContext, aI as ExecutionCompleteEvent, aw as ExecutionConfig, E as ExecutionContext, l as ExecutionMetrics, aH as ExecutionStartEvent, j as HistoryMode, aA as Hook, H as HookConfig, au as HookManager, az as HookName, aL as LLMRequestEvent, aM as LLMResponseEvent, aB as ModifyingHook, aK as ToolCompleteEvent, aF as ToolModification, aJ as ToolStartEvent } from '../../index-DVb6vfA3.js';
2
- import '../../IProvider-DcYJ3YE-.js';
1
+ export { x as AfterToolContext, y as AgentEventName, A as AgentEvents, z as AgenticLoopEventName, B as AgenticLoopEvents, D as ApprovalResult, G as ApproveToolContext, m as AuditEntry, J as BeforeToolContext, aH as ExecutionCompleteEvent, V as ExecutionConfig, E as ExecutionContext, l as ExecutionMetrics, aI as ExecutionStartEvent, j as HistoryMode, X as Hook, H as HookConfig, Y as HookManager, Z as HookName, aJ as LLMRequestEvent, aK as LLMResponseEvent, a6 as ModifyingHook, aL as ToolCompleteEvent, an as ToolModification, aM as ToolStartEvent } from '../../index-BeZcWDiq.js';
2
+ import '../../IProvider-BUbU5UwV.js';
3
3
  import '../../Vendor-DYh_bzwo.js';
4
4
  import 'eventemitter3';
@@ -816,6 +816,109 @@ var OAuthManager = class {
816
816
  }
817
817
  }
818
818
  };
819
+
820
+ // src/core/StorageRegistry.ts
821
+ var StorageRegistry = class _StorageRegistry {
822
+ /** Internal storage map */
823
+ static entries = /* @__PURE__ */ new Map();
824
+ /** Default context passed to all factory calls (set via setContext) */
825
+ static _context;
826
+ /**
827
+ * Configure multiple storage backends at once.
828
+ *
829
+ * @example
830
+ * ```typescript
831
+ * // Single-tenant
832
+ * StorageRegistry.configure({
833
+ * customTools: new MongoCustomToolStorage(),
834
+ * sessions: (agentId) => new RedisContextStorage(agentId),
835
+ * });
836
+ *
837
+ * // Multi-tenant
838
+ * StorageRegistry.configure({
839
+ * sessions: (agentId, ctx) => new TenantContextStorage(agentId, ctx?.tenantId),
840
+ * persistentInstructions: (agentId, ctx) => new TenantInstructionsStorage(agentId, ctx?.userId),
841
+ * });
842
+ * ```
843
+ */
844
+ static configure(config) {
845
+ for (const [key, value] of Object.entries(config)) {
846
+ if (value !== void 0) {
847
+ _StorageRegistry.entries.set(key, value);
848
+ }
849
+ }
850
+ }
851
+ /**
852
+ * Set the default StorageContext.
853
+ *
854
+ * This context is automatically passed to all per-agent factory calls
855
+ * (sessions, persistentInstructions, workingMemory) when no explicit
856
+ * context is provided. Typically set once at app startup with global
857
+ * tenant/environment info, or per-request in multi-tenant servers.
858
+ *
859
+ * @example
860
+ * ```typescript
861
+ * // Single-tenant app — set once at init
862
+ * StorageRegistry.setContext({ tenantId: 'acme', environment: 'production' });
863
+ *
864
+ * // Multi-tenant server — set per-request
865
+ * app.use((req, res, next) => {
866
+ * StorageRegistry.setContext({ userId: req.user.id, tenantId: req.tenant.id });
867
+ * next();
868
+ * });
869
+ * ```
870
+ */
871
+ static setContext(context) {
872
+ _StorageRegistry._context = context;
873
+ }
874
+ /**
875
+ * Get the current default StorageContext.
876
+ */
877
+ static getContext() {
878
+ return _StorageRegistry._context;
879
+ }
880
+ /**
881
+ * Set a single storage backend.
882
+ */
883
+ static set(key, value) {
884
+ _StorageRegistry.entries.set(key, value);
885
+ }
886
+ /**
887
+ * Get a storage backend (or undefined if not configured).
888
+ */
889
+ static get(key) {
890
+ return _StorageRegistry.entries.get(key);
891
+ }
892
+ /**
893
+ * Resolve a storage backend, lazily creating and caching a default if needed.
894
+ *
895
+ * If a value has been configured via `set()` or `configure()`, returns that.
896
+ * Otherwise, calls `defaultFactory()`, caches the result, and returns it.
897
+ */
898
+ static resolve(key, defaultFactory) {
899
+ const existing = _StorageRegistry.entries.get(key);
900
+ if (existing !== void 0) {
901
+ return existing;
902
+ }
903
+ const value = defaultFactory();
904
+ _StorageRegistry.entries.set(key, value);
905
+ return value;
906
+ }
907
+ /**
908
+ * Check if a storage backend has been configured.
909
+ */
910
+ static has(key) {
911
+ return _StorageRegistry.entries.has(key);
912
+ }
913
+ /**
914
+ * Clear all configured storage backends and context.
915
+ * Useful for testing.
916
+ */
917
+ static reset() {
918
+ _StorageRegistry.entries.clear();
919
+ _StorageRegistry._context = void 0;
920
+ }
921
+ };
819
922
  var DEFAULT_CIRCUIT_BREAKER_CONFIG = {
820
923
  failureThreshold: 5,
821
924
  successThreshold: 2,
@@ -1553,7 +1656,6 @@ var DEFAULT_MAX_DELAY_MS = 3e4;
1553
1656
  var Connector = class _Connector {
1554
1657
  // ============ Static Registry ============
1555
1658
  static registry = /* @__PURE__ */ new Map();
1556
- static defaultStorage = new MemoryStorage();
1557
1659
  /**
1558
1660
  * Create and register a new connector
1559
1661
  * @param config - Must include `name` field
@@ -1611,11 +1713,18 @@ var Connector = class _Connector {
1611
1713
  }
1612
1714
  _Connector.registry.clear();
1613
1715
  }
1716
+ /**
1717
+ * Get the default token storage for OAuth connectors.
1718
+ * Resolves from StorageRegistry, falling back to MemoryStorage.
1719
+ */
1720
+ static get defaultStorage() {
1721
+ return StorageRegistry.resolve("oauthTokens", () => new MemoryStorage());
1722
+ }
1614
1723
  /**
1615
1724
  * Set default token storage for OAuth connectors
1616
1725
  */
1617
1726
  static setDefaultStorage(storage) {
1618
- _Connector.defaultStorage = storage;
1727
+ StorageRegistry.set("oauthTokens", storage);
1619
1728
  }
1620
1729
  /**
1621
1730
  * Get all registered connectors