@everworker/oneringai 0.1.1 → 0.1.2

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
@@ -22,7 +22,7 @@
22
22
  - 🤖 **Universal Agent** - ⚠️ *Deprecated* - Use `Agent` with plugins instead
23
23
  - 🤖 **Task Agents** - ⚠️ *Deprecated* - Use `Agent` with `WorkingMemoryPluginNextGen`
24
24
  - 🔬 **Research Agent** - ⚠️ *Deprecated* - Use `Agent` with search tools
25
- - 🎯 **Context Management** - Smart strategies (proactive, aggressive, lazy, rolling-window, adaptive)
25
+ - 🎯 **Context Management** - Algorithmic compaction with tool-result-to-memory offloading
26
26
  - 📌 **InContextMemory** - NEW: Live key-value storage directly in LLM context for instant access
27
27
  - 📝 **Persistent Instructions** - NEW: Agent-level custom instructions that persist across sessions on disk
28
28
  - 🛠️ **Agentic Workflows** - Built-in tool calling and multi-turn conversations
@@ -30,6 +30,7 @@
30
30
  - 🔌 **MCP Integration** - NEW: Model Context Protocol client for seamless tool discovery from local and remote servers
31
31
  - 👁️ **Vision Support** - Analyze images with AI across all providers
32
32
  - 📋 **Clipboard Integration** - Paste screenshots directly (like Claude Code!)
33
+ - 🔐 **Scoped Connector Registry** - NEW: Pluggable access control for multi-tenant connector isolation
33
34
  - 🔐 **OAuth 2.0** - Full OAuth support for external APIs with encrypted token storage
34
35
  - 📦 **Vendor Templates** - NEW: Pre-configured auth templates for 43+ services (GitHub, Slack, Stripe, etc.)
35
36
  - 🔄 **Streaming** - Real-time responses with event streams
@@ -578,7 +579,6 @@ const agent = Agent.create({
578
579
  connector: 'openai',
579
580
  model: 'gpt-4',
580
581
  context: {
581
- strategy: 'balanced', // proactive, balanced, lazy
582
582
  features: { workingMemory: true },
583
583
  },
584
584
  });
@@ -629,10 +629,8 @@ const agent = Agent.create({
629
629
  - **Single system message** - All context components combined
630
630
  - **Smart compaction** - Happens once, right before LLM call
631
631
 
632
- **Three compaction strategies:**
633
- - **proactive** - Compact at 70% usage
634
- - **balanced** (default) - Compact at 80% usage
635
- - **lazy** - Compact at 90% usage
632
+ **Compaction strategy:**
633
+ - **algorithmic** (default) - Moves large tool results to Working Memory, limits tool pairs, applies rolling window. Triggers at 75% context usage.
636
634
 
637
635
  **Context preparation:**
638
636
  ```typescript
@@ -966,6 +964,51 @@ const metrics = connector.getMetrics();
966
964
  console.log(`Success rate: ${metrics.successCount / metrics.requestCount * 100}%`);
967
965
  ```
968
966
 
967
+ #### Scoped Connector Registry (NEW)
968
+
969
+ Limit connector visibility by user, group, or tenant in multi-user systems:
970
+
971
+ ```typescript
972
+ import { Connector, ScopedConnectorRegistry } from '@everworker/oneringai';
973
+ import type { IConnectorAccessPolicy } from '@everworker/oneringai';
974
+
975
+ // Define an access policy
976
+ const policy: IConnectorAccessPolicy = {
977
+ canAccess: (connector, context) => {
978
+ const tags = connector.config.tags as string[] | undefined;
979
+ return !!tags && tags.includes(context.tenantId as string);
980
+ },
981
+ };
982
+
983
+ // Set the global policy
984
+ Connector.setAccessPolicy(policy);
985
+
986
+ // Create a scoped view for a specific tenant
987
+ const registry = Connector.scoped({ tenantId: 'acme-corp' });
988
+
989
+ // Only connectors tagged with 'acme-corp' are visible
990
+ registry.list(); // ['acme-openai', 'acme-slack']
991
+ registry.get('other-co'); // throws "not found" (no info leakage)
992
+
993
+ // Use with Agent
994
+ const agent = Agent.create({
995
+ connector: 'acme-openai',
996
+ model: 'gpt-4',
997
+ registry, // Agent resolves connectors through the scoped view
998
+ });
999
+
1000
+ // Use with ConnectorTools
1001
+ const tools = ConnectorTools.for('acme-slack', undefined, { registry });
1002
+ const allTools = ConnectorTools.discoverAll(undefined, { registry });
1003
+ ```
1004
+
1005
+ **Features:**
1006
+ - Pluggable `IConnectorAccessPolicy` interface — bring your own access logic
1007
+ - Opaque context object (`{ userId, tenantId, roles, ... }`) — library imposes no structure
1008
+ - Denied connectors get the same "not found" error — no information leakage
1009
+ - Zero changes to existing API — scoping is entirely opt-in
1010
+ - Works with `Agent.create()`, `ConnectorTools.for()`, and `ConnectorTools.discoverAll()`
1011
+
969
1012
  #### Vendor Templates (NEW)
970
1013
 
971
1014
  Quickly set up connectors for 43+ services with pre-configured authentication templates:
@@ -1196,6 +1239,7 @@ User Code → Connector Registry → Agent → Provider → LLM
1196
1239
  - ✅ Named connectors for easy reference
1197
1240
  - ✅ No API key management in agent code
1198
1241
  - ✅ Same pattern for AI providers AND external APIs
1242
+ - ✅ Scoped registry for multi-tenant access control
1199
1243
 
1200
1244
  ## Troubleshooting
1201
1245
 
@@ -1221,8 +1265,8 @@ MIT License - See [LICENSE](./LICENSE) file.
1221
1265
 
1222
1266
  ---
1223
1267
 
1224
- **Version:** 0.1.0
1225
- **Last Updated:** 2026-02-05
1268
+ **Version:** 0.1.2
1269
+ **Last Updated:** 2026-02-06
1226
1270
 
1227
1271
  For detailed documentation on all features, see the **[Complete User Guide](./USER_GUIDE.md)**.
1228
1272
 
@@ -227,6 +227,57 @@ interface ITokenStorage {
227
227
  hasToken(key: string): Promise<boolean>;
228
228
  }
229
229
 
230
+ /**
231
+ * IConnectorRegistry - Read-only interface for connector lookup
232
+ *
233
+ * Covers the read-only subset of Connector static methods.
234
+ * Used by ScopedConnectorRegistry to provide filtered views
235
+ * and by consumers that only need to read from the registry.
236
+ */
237
+
238
+ interface IConnectorRegistry {
239
+ /** Get a connector by name. Throws if not found (or not accessible). */
240
+ get(name: string): Connector;
241
+ /** Check if a connector exists (and is accessible) */
242
+ has(name: string): boolean;
243
+ /** List all accessible connector names */
244
+ list(): string[];
245
+ /** List all accessible connector instances */
246
+ listAll(): Connector[];
247
+ /** Get number of accessible connectors */
248
+ size(): number;
249
+ /** Get connector descriptions formatted for tool parameters */
250
+ getDescriptionsForTools(): string;
251
+ /** Get connector info map */
252
+ getInfo(): Record<string, {
253
+ displayName: string;
254
+ description: string;
255
+ baseURL: string;
256
+ }>;
257
+ }
258
+
259
+ /**
260
+ * IConnectorAccessPolicy - Pluggable access control for connector registry
261
+ *
262
+ * Policies are sync-only for performance — access checks must be fast
263
+ * and policy data should be in-memory.
264
+ */
265
+
266
+ /**
267
+ * Opaque context passed to access policy checks.
268
+ * Library imposes no structure — consumers define their own shape
269
+ * (e.g., { userId, tenantId, roles }).
270
+ */
271
+ type ConnectorAccessContext = Record<string, unknown>;
272
+ interface IConnectorAccessPolicy {
273
+ /**
274
+ * Check if a connector is accessible in the given context.
275
+ * Receives the full Connector instance so it can inspect
276
+ * config.tags, vendor, serviceType, etc.
277
+ */
278
+ canAccess(connector: Connector, context: ConnectorAccessContext): boolean;
279
+ }
280
+
230
281
  /**
231
282
  * Connector - The single source of truth for authentication
232
283
  *
@@ -305,6 +356,30 @@ declare class Connector {
305
356
  * Get number of registered connectors
306
357
  */
307
358
  static size(): number;
359
+ private static _accessPolicy;
360
+ /**
361
+ * Set a global access policy for connector scoping.
362
+ * Pass null to clear the policy.
363
+ */
364
+ static setAccessPolicy(policy: IConnectorAccessPolicy | null): void;
365
+ /**
366
+ * Get the current global access policy (or null if none set).
367
+ */
368
+ static getAccessPolicy(): IConnectorAccessPolicy | null;
369
+ /**
370
+ * Create a scoped (filtered) view of the connector registry.
371
+ * Requires a global access policy to be set via setAccessPolicy().
372
+ *
373
+ * @param context - Opaque context passed to the policy (e.g., { userId, tenantId })
374
+ * @returns IConnectorRegistry that only exposes accessible connectors
375
+ * @throws Error if no access policy is set
376
+ */
377
+ static scoped(context: ConnectorAccessContext): IConnectorRegistry;
378
+ /**
379
+ * Return the static Connector methods as an IConnectorRegistry object (unfiltered).
380
+ * Useful when code accepts the interface but you want the full admin view.
381
+ */
382
+ static asRegistry(): IConnectorRegistry;
308
383
  /**
309
384
  * Get connector descriptions formatted for tool parameters
310
385
  * Useful for generating dynamic tool descriptions
@@ -760,4 +835,4 @@ declare function getImageModelsWithFeature(feature: keyof IImageModelDescription
760
835
  */
761
836
  declare function calculateImageCost(modelName: string, imageCount: number, quality?: 'standard' | 'hd'): number | null;
762
837
 
763
- export { type AudioFormat as A, type ImageResponse as B, Connector as C, type AspectRatio$1 as D, type OutputFormat as E, type ISourceLinks as F, DEFAULT_CONNECTOR_TIMEOUT as G, DEFAULT_MAX_RETRIES as H, type IBaseModelDescription as I, type JWTConnectorAuth as J, DEFAULT_RETRYABLE_STATUSES as K, DEFAULT_BASE_DELAY_MS as L, DEFAULT_MAX_DELAY_MS as M, type OAuthConnectorAuth as O, type QualityLevel as Q, type StoredToken as S, type VendorOptionSchema as V, Vendor as a, type IImageProvider as b, type ConnectorFetchOptions as c, type ITokenStorage as d, type ConnectorConfig as e, type ConnectorAuth as f, type ConnectorConfigResult as g, VENDORS as h, isVendor as i, ImageGeneration as j, type ImageGenerationCreateOptions as k, type SimpleGenerateOptions as l, type APIKeyConnectorAuth as m, type IImageModelDescription as n, type ImageModelCapabilities as o, type ImageModelPricing as p, IMAGE_MODELS as q, IMAGE_MODEL_REGISTRY as r, getImageModelInfo as s, getImageModelsByVendor as t, getActiveImageModels as u, getImageModelsWithFeature as v, calculateImageCost as w, type ImageGenerateOptions as x, type ImageEditOptions as y, type ImageVariationOptions as z };
838
+ export { type AudioFormat as A, type ImageGenerateOptions as B, type ConnectorAccessContext as C, type ImageEditOptions as D, type ImageVariationOptions as E, type ImageResponse as F, type AspectRatio$1 as G, type OutputFormat as H, type IConnectorRegistry as I, type JWTConnectorAuth as J, type ISourceLinks as K, DEFAULT_CONNECTOR_TIMEOUT as L, DEFAULT_MAX_RETRIES as M, DEFAULT_RETRYABLE_STATUSES as N, type OAuthConnectorAuth as O, DEFAULT_BASE_DELAY_MS as P, type QualityLevel as Q, DEFAULT_MAX_DELAY_MS as R, type StoredToken as S, type VendorOptionSchema as V, type IConnectorAccessPolicy as a, Connector as b, type IBaseModelDescription as c, Vendor as d, type IImageProvider as e, type ConnectorFetchOptions as f, type ITokenStorage as g, type ConnectorConfig as h, type ConnectorAuth as i, type ConnectorConfigResult as j, VENDORS as k, isVendor as l, ImageGeneration as m, type ImageGenerationCreateOptions as n, type SimpleGenerateOptions as o, type APIKeyConnectorAuth as p, type IImageModelDescription as q, type ImageModelCapabilities as r, type ImageModelPricing as s, IMAGE_MODELS as t, IMAGE_MODEL_REGISTRY as u, getImageModelInfo as v, getImageModelsByVendor as w, getActiveImageModels as x, getImageModelsWithFeature as y, calculateImageCost as z };
@@ -227,6 +227,57 @@ interface ITokenStorage {
227
227
  hasToken(key: string): Promise<boolean>;
228
228
  }
229
229
 
230
+ /**
231
+ * IConnectorRegistry - Read-only interface for connector lookup
232
+ *
233
+ * Covers the read-only subset of Connector static methods.
234
+ * Used by ScopedConnectorRegistry to provide filtered views
235
+ * and by consumers that only need to read from the registry.
236
+ */
237
+
238
+ interface IConnectorRegistry {
239
+ /** Get a connector by name. Throws if not found (or not accessible). */
240
+ get(name: string): Connector;
241
+ /** Check if a connector exists (and is accessible) */
242
+ has(name: string): boolean;
243
+ /** List all accessible connector names */
244
+ list(): string[];
245
+ /** List all accessible connector instances */
246
+ listAll(): Connector[];
247
+ /** Get number of accessible connectors */
248
+ size(): number;
249
+ /** Get connector descriptions formatted for tool parameters */
250
+ getDescriptionsForTools(): string;
251
+ /** Get connector info map */
252
+ getInfo(): Record<string, {
253
+ displayName: string;
254
+ description: string;
255
+ baseURL: string;
256
+ }>;
257
+ }
258
+
259
+ /**
260
+ * IConnectorAccessPolicy - Pluggable access control for connector registry
261
+ *
262
+ * Policies are sync-only for performance — access checks must be fast
263
+ * and policy data should be in-memory.
264
+ */
265
+
266
+ /**
267
+ * Opaque context passed to access policy checks.
268
+ * Library imposes no structure — consumers define their own shape
269
+ * (e.g., { userId, tenantId, roles }).
270
+ */
271
+ type ConnectorAccessContext = Record<string, unknown>;
272
+ interface IConnectorAccessPolicy {
273
+ /**
274
+ * Check if a connector is accessible in the given context.
275
+ * Receives the full Connector instance so it can inspect
276
+ * config.tags, vendor, serviceType, etc.
277
+ */
278
+ canAccess(connector: Connector, context: ConnectorAccessContext): boolean;
279
+ }
280
+
230
281
  /**
231
282
  * Connector - The single source of truth for authentication
232
283
  *
@@ -305,6 +356,30 @@ declare class Connector {
305
356
  * Get number of registered connectors
306
357
  */
307
358
  static size(): number;
359
+ private static _accessPolicy;
360
+ /**
361
+ * Set a global access policy for connector scoping.
362
+ * Pass null to clear the policy.
363
+ */
364
+ static setAccessPolicy(policy: IConnectorAccessPolicy | null): void;
365
+ /**
366
+ * Get the current global access policy (or null if none set).
367
+ */
368
+ static getAccessPolicy(): IConnectorAccessPolicy | null;
369
+ /**
370
+ * Create a scoped (filtered) view of the connector registry.
371
+ * Requires a global access policy to be set via setAccessPolicy().
372
+ *
373
+ * @param context - Opaque context passed to the policy (e.g., { userId, tenantId })
374
+ * @returns IConnectorRegistry that only exposes accessible connectors
375
+ * @throws Error if no access policy is set
376
+ */
377
+ static scoped(context: ConnectorAccessContext): IConnectorRegistry;
378
+ /**
379
+ * Return the static Connector methods as an IConnectorRegistry object (unfiltered).
380
+ * Useful when code accepts the interface but you want the full admin view.
381
+ */
382
+ static asRegistry(): IConnectorRegistry;
308
383
  /**
309
384
  * Get connector descriptions formatted for tool parameters
310
385
  * Useful for generating dynamic tool descriptions
@@ -760,4 +835,4 @@ declare function getImageModelsWithFeature(feature: keyof IImageModelDescription
760
835
  */
761
836
  declare function calculateImageCost(modelName: string, imageCount: number, quality?: 'standard' | 'hd'): number | null;
762
837
 
763
- export { type AudioFormat as A, type ImageResponse as B, Connector as C, type AspectRatio$1 as D, type OutputFormat as E, type ISourceLinks as F, DEFAULT_CONNECTOR_TIMEOUT as G, DEFAULT_MAX_RETRIES as H, type IBaseModelDescription as I, type JWTConnectorAuth as J, DEFAULT_RETRYABLE_STATUSES as K, DEFAULT_BASE_DELAY_MS as L, DEFAULT_MAX_DELAY_MS as M, type OAuthConnectorAuth as O, type QualityLevel as Q, type StoredToken as S, type VendorOptionSchema as V, Vendor as a, type IImageProvider as b, type ConnectorFetchOptions as c, type ITokenStorage as d, type ConnectorConfig as e, type ConnectorAuth as f, type ConnectorConfigResult as g, VENDORS as h, isVendor as i, ImageGeneration as j, type ImageGenerationCreateOptions as k, type SimpleGenerateOptions as l, type APIKeyConnectorAuth as m, type IImageModelDescription as n, type ImageModelCapabilities as o, type ImageModelPricing as p, IMAGE_MODELS as q, IMAGE_MODEL_REGISTRY as r, getImageModelInfo as s, getImageModelsByVendor as t, getActiveImageModels as u, getImageModelsWithFeature as v, calculateImageCost as w, type ImageGenerateOptions as x, type ImageEditOptions as y, type ImageVariationOptions as z };
838
+ export { type AudioFormat as A, type ImageGenerateOptions as B, type ConnectorAccessContext as C, type ImageEditOptions as D, type ImageVariationOptions as E, type ImageResponse as F, type AspectRatio$1 as G, type OutputFormat as H, type IConnectorRegistry as I, type JWTConnectorAuth as J, type ISourceLinks as K, DEFAULT_CONNECTOR_TIMEOUT as L, DEFAULT_MAX_RETRIES as M, DEFAULT_RETRYABLE_STATUSES as N, type OAuthConnectorAuth as O, DEFAULT_BASE_DELAY_MS as P, type QualityLevel as Q, DEFAULT_MAX_DELAY_MS as R, type StoredToken as S, type VendorOptionSchema as V, type IConnectorAccessPolicy as a, Connector as b, type IBaseModelDescription as c, Vendor as d, type IImageProvider as e, type ConnectorFetchOptions as f, type ITokenStorage as g, type ConnectorConfig as h, type ConnectorAuth as i, type ConnectorConfigResult as j, VENDORS as k, isVendor as l, ImageGeneration as m, type ImageGenerationCreateOptions as n, type SimpleGenerateOptions as o, type APIKeyConnectorAuth as p, type IImageModelDescription as q, type ImageModelCapabilities as r, type ImageModelPricing as s, IMAGE_MODELS as t, IMAGE_MODEL_REGISTRY as u, getImageModelInfo as v, getImageModelsByVendor as w, getActiveImageModels as x, getImageModelsWithFeature as y, calculateImageCost as z };
@@ -1452,6 +1452,58 @@ var metrics = createMetricsCollector(
1452
1452
  process.env.METRICS_PREFIX || "oneringai"
1453
1453
  );
1454
1454
 
1455
+ // src/core/ScopedConnectorRegistry.ts
1456
+ var ScopedConnectorRegistry = class {
1457
+ constructor(policy, context) {
1458
+ this.policy = policy;
1459
+ this.context = context;
1460
+ }
1461
+ get(name) {
1462
+ if (!Connector.has(name)) {
1463
+ const available = this.list().join(", ") || "none";
1464
+ throw new Error(`Connector '${name}' not found. Available: ${available}`);
1465
+ }
1466
+ const connector = Connector.get(name);
1467
+ if (!this.policy.canAccess(connector, this.context)) {
1468
+ const available = this.list().join(", ") || "none";
1469
+ throw new Error(`Connector '${name}' not found. Available: ${available}`);
1470
+ }
1471
+ return connector;
1472
+ }
1473
+ has(name) {
1474
+ if (!Connector.has(name)) return false;
1475
+ const connector = Connector.get(name);
1476
+ return this.policy.canAccess(connector, this.context);
1477
+ }
1478
+ list() {
1479
+ return this.listAll().map((c) => c.name);
1480
+ }
1481
+ listAll() {
1482
+ return Connector.listAll().filter((c) => this.policy.canAccess(c, this.context));
1483
+ }
1484
+ size() {
1485
+ return this.listAll().length;
1486
+ }
1487
+ getDescriptionsForTools() {
1488
+ const connectors = this.listAll();
1489
+ if (connectors.length === 0) {
1490
+ return "No connectors registered yet.";
1491
+ }
1492
+ return connectors.map((c) => ` - "${c.name}": ${c.displayName} - ${c.config.description || "No description"}`).join("\n");
1493
+ }
1494
+ getInfo() {
1495
+ const info = {};
1496
+ for (const connector of this.listAll()) {
1497
+ info[connector.name] = {
1498
+ displayName: connector.displayName,
1499
+ description: connector.config.description || "",
1500
+ baseURL: connector.baseURL
1501
+ };
1502
+ }
1503
+ return info;
1504
+ }
1505
+ };
1506
+
1455
1507
  // src/core/Connector.ts
1456
1508
  var DEFAULT_CONNECTOR_TIMEOUT = 3e4;
1457
1509
  var DEFAULT_MAX_RETRIES = 3;
@@ -1537,6 +1589,50 @@ var Connector = class _Connector {
1537
1589
  static size() {
1538
1590
  return _Connector.registry.size;
1539
1591
  }
1592
+ // ============ Access Control ============
1593
+ static _accessPolicy = null;
1594
+ /**
1595
+ * Set a global access policy for connector scoping.
1596
+ * Pass null to clear the policy.
1597
+ */
1598
+ static setAccessPolicy(policy) {
1599
+ _Connector._accessPolicy = policy;
1600
+ }
1601
+ /**
1602
+ * Get the current global access policy (or null if none set).
1603
+ */
1604
+ static getAccessPolicy() {
1605
+ return _Connector._accessPolicy;
1606
+ }
1607
+ /**
1608
+ * Create a scoped (filtered) view of the connector registry.
1609
+ * Requires a global access policy to be set via setAccessPolicy().
1610
+ *
1611
+ * @param context - Opaque context passed to the policy (e.g., { userId, tenantId })
1612
+ * @returns IConnectorRegistry that only exposes accessible connectors
1613
+ * @throws Error if no access policy is set
1614
+ */
1615
+ static scoped(context) {
1616
+ if (!_Connector._accessPolicy) {
1617
+ throw new Error("No access policy set. Call Connector.setAccessPolicy() first.");
1618
+ }
1619
+ return new ScopedConnectorRegistry(_Connector._accessPolicy, context);
1620
+ }
1621
+ /**
1622
+ * Return the static Connector methods as an IConnectorRegistry object (unfiltered).
1623
+ * Useful when code accepts the interface but you want the full admin view.
1624
+ */
1625
+ static asRegistry() {
1626
+ return {
1627
+ get: (name) => _Connector.get(name),
1628
+ has: (name) => _Connector.has(name),
1629
+ list: () => _Connector.list(),
1630
+ listAll: () => _Connector.listAll(),
1631
+ size: () => _Connector.size(),
1632
+ getDescriptionsForTools: () => _Connector.getDescriptionsForTools(),
1633
+ getInfo: () => _Connector.getInfo()
1634
+ };
1635
+ }
1540
1636
  /**
1541
1637
  * Get connector descriptions formatted for tool parameters
1542
1638
  * Useful for generating dynamic tool descriptions