@agentix-e/nl2spel 1.2.2 → 1.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
@@ -4,7 +4,9 @@
4
4
  >
5
5
  > Zero external deps · Four-layer hybrid architecture · 532 tests · Chinese & English
6
6
 
7
- [![npm](https://img.shields.io/npm/v/@agentix-e/nl2spel)](https://www.npmjs.com/package/@agentix-e/nl2spel)
7
+ [![npm](https://img.shields.io/npm/v/@agentix-e/nl2spel?color=blue)](https://www.npmjs.com/package/@agentix-e/nl2spel)
8
+ [![API Docs](https://img.shields.io/badge/docs-TypeDoc-blue)](https://agentix-e.github.io/nl2spel/api/modules.html)
9
+ [![Coverage](https://img.shields.io/badge/coverage-report-blue)](https://agentix-e.github.io/nl2spel/coverage/)
8
10
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](../../LICENSE)
9
11
 
10
12
  ---
package/dist/index.cjs CHANGED
@@ -41,47 +41,69 @@ module.exports = __toCommonJS(index_exports);
41
41
  // src/provider/provider-registry.ts
42
42
  var ProviderRegistry = class {
43
43
  _providers = [];
44
- /** Register a Provider */
45
- register(provider) {
46
- if (this._providers.some((p) => p.name === provider.name)) {
44
+ _nextIndex = 0;
45
+ /**
46
+ * Register a Provider.
47
+ * @param provider LLMProvider instance
48
+ * @param options.priority User-assigned priority (lower = preferred). Defaults to registration order.
49
+ */
50
+ register(provider, options) {
51
+ if (this._providers.some((p) => p.provider.name === provider.name)) {
47
52
  throw new Error(`Provider '${provider.name}' already registered`);
48
53
  }
49
- this._providers.push(provider);
54
+ this._providers.push({
55
+ provider,
56
+ priority: options?.priority ?? this._nextIndex,
57
+ index: this._nextIndex
58
+ });
59
+ this._nextIndex++;
50
60
  }
51
61
  /** Unregister a Provider */
52
62
  unregister(name) {
53
- this._providers = this._providers.filter((p) => p.name !== name);
63
+ this._providers = this._providers.filter((p) => p.provider.name !== name);
54
64
  }
55
65
  /** Get a Provider by name */
56
66
  get(name) {
57
- return this._providers.find((p) => p.name === name);
67
+ return this._providers.find((p) => p.provider.name === name)?.provider;
58
68
  }
59
69
  /**
60
70
  * Get available Providers sorted by priority.
61
- * Sort rule: offline > low cost > low latency > high accuracy
71
+ * Sort rule: offline first user priority (asc) registration order (asc)
62
72
  */
63
73
  async getPrioritized() {
64
74
  const available = [];
65
- for (const p of this._providers) {
66
- if (await p.isAvailable()) {
67
- available.push(p);
75
+ for (const entry of this._providers) {
76
+ if (await entry.provider.isAvailable()) {
77
+ available.push(entry);
68
78
  }
69
79
  }
70
80
  return available.sort((a, b) => {
71
- const aOffline = a.capabilities.offlineAvailable;
72
- const bOffline = b.capabilities.offlineAvailable;
81
+ const aOffline = a.provider.capabilities.offlineAvailable;
82
+ const bOffline = b.provider.capabilities.offlineAvailable;
73
83
  if (aOffline && !bOffline) return -1;
74
84
  if (!aOffline && bOffline) return 1;
75
- const costA = a.capabilities.estimatedCostPerRequest ?? Infinity;
76
- const costB = b.capabilities.estimatedCostPerRequest ?? Infinity;
77
- if (costA < costB) return -1;
78
- if (costB < costA) return 1;
79
- return a.capabilities.estimatedLatencyMs - b.capabilities.estimatedLatencyMs;
80
- });
85
+ if (a.priority !== b.priority) return a.priority - b.priority;
86
+ return a.index - b.index;
87
+ }).map((entry) => entry.provider);
88
+ }
89
+ /**
90
+ * Explicitly reorder providers by name.
91
+ * Providers not listed retain their position after the reordered ones.
92
+ */
93
+ reorder(providerNames) {
94
+ const orderMap = new Map(providerNames.map((name, i) => [name, i]));
95
+ const maxExisting = this._providers.reduce(
96
+ (max, p) => Math.max(max, p.priority),
97
+ providerNames.length - 1
98
+ );
99
+ for (const entry of this._providers) {
100
+ const explicitIndex = orderMap.get(entry.provider.name);
101
+ entry.priority = explicitIndex ?? maxExisting + entry.index + 1;
102
+ }
81
103
  }
82
104
  /** List all registered Providers */
83
105
  list() {
84
- return [...this._providers];
106
+ return this._providers.map((p) => p.provider);
85
107
  }
86
108
  /** Number of registered Providers */
87
109
  get count() {
package/dist/index.d.cts CHANGED
@@ -38,6 +38,9 @@ interface LLMProvider {
38
38
  }
39
39
  /**
40
40
  * LLMProvider capability declaration.
41
+ *
42
+ * Declares what the provider CAN do — facts the engine can verify.
43
+ * Provider ordering is user-controlled via {@link ProviderRegistry.register} priority.
41
44
  */
42
45
  interface LLMCapabilities {
43
46
  /** Maximum context window (tokens) */
@@ -48,14 +51,8 @@ interface LLMCapabilities {
48
51
  supportsStreaming: boolean;
49
52
  /** Whether Structured Output (JSON mode) is supported */
50
53
  supportsStructuredOutput: boolean;
51
- /** Whether available offline */
54
+ /** Whether available offline (no network required) */
52
55
  offlineAvailable: boolean;
53
- /**
54
- * Estimated cost per request (USD)
55
- */
56
- estimatedCostPerRequest?: number;
57
- /** Estimated latency (ms) */
58
- estimatedLatencyMs: number;
59
56
  }
60
57
  /**
61
58
  * Standardized LLM Prompt structure.
@@ -148,24 +145,36 @@ interface LLMUsage {
148
145
  /**
149
146
  * ProviderRegistry — manages registered LLMProvider instances.
150
147
  *
151
- * Responsibilities:
152
- * 1. Register/unregister Providers
153
- * 2. Sort by priority (offline first > low latency > high accuracy)
154
- * 3. Look up Providers by name (for forced selection)
148
+ * Provider ordering is user-controlled:
149
+ * 1. Offline providers first (engine-enforced — offline capability is a binary fact)
150
+ * 2. User-assigned priority (lower = preferred; default = registration order)
151
+ * 3. Registration order (tiebreaker when priorities are equal)
155
152
  */
156
153
  declare class ProviderRegistry {
157
154
  private _providers;
158
- /** Register a Provider */
159
- register(provider: LLMProvider): void;
155
+ private _nextIndex;
156
+ /**
157
+ * Register a Provider.
158
+ * @param provider LLMProvider instance
159
+ * @param options.priority User-assigned priority (lower = preferred). Defaults to registration order.
160
+ */
161
+ register(provider: LLMProvider, options?: {
162
+ priority?: number;
163
+ }): void;
160
164
  /** Unregister a Provider */
161
165
  unregister(name: string): void;
162
166
  /** Get a Provider by name */
163
167
  get(name: string): LLMProvider | undefined;
164
168
  /**
165
169
  * Get available Providers sorted by priority.
166
- * Sort rule: offline > low cost > low latency > high accuracy
170
+ * Sort rule: offline first user priority (asc) registration order (asc)
167
171
  */
168
172
  getPrioritized(): Promise<LLMProvider[]>;
173
+ /**
174
+ * Explicitly reorder providers by name.
175
+ * Providers not listed retain their position after the reordered ones.
176
+ */
177
+ reorder(providerNames: string[]): void;
169
178
  /** List all registered Providers */
170
179
  list(): LLMProvider[];
171
180
  /** Number of registered Providers */
package/dist/index.d.ts CHANGED
@@ -38,6 +38,9 @@ interface LLMProvider {
38
38
  }
39
39
  /**
40
40
  * LLMProvider capability declaration.
41
+ *
42
+ * Declares what the provider CAN do — facts the engine can verify.
43
+ * Provider ordering is user-controlled via {@link ProviderRegistry.register} priority.
41
44
  */
42
45
  interface LLMCapabilities {
43
46
  /** Maximum context window (tokens) */
@@ -48,14 +51,8 @@ interface LLMCapabilities {
48
51
  supportsStreaming: boolean;
49
52
  /** Whether Structured Output (JSON mode) is supported */
50
53
  supportsStructuredOutput: boolean;
51
- /** Whether available offline */
54
+ /** Whether available offline (no network required) */
52
55
  offlineAvailable: boolean;
53
- /**
54
- * Estimated cost per request (USD)
55
- */
56
- estimatedCostPerRequest?: number;
57
- /** Estimated latency (ms) */
58
- estimatedLatencyMs: number;
59
56
  }
60
57
  /**
61
58
  * Standardized LLM Prompt structure.
@@ -148,24 +145,36 @@ interface LLMUsage {
148
145
  /**
149
146
  * ProviderRegistry — manages registered LLMProvider instances.
150
147
  *
151
- * Responsibilities:
152
- * 1. Register/unregister Providers
153
- * 2. Sort by priority (offline first > low latency > high accuracy)
154
- * 3. Look up Providers by name (for forced selection)
148
+ * Provider ordering is user-controlled:
149
+ * 1. Offline providers first (engine-enforced — offline capability is a binary fact)
150
+ * 2. User-assigned priority (lower = preferred; default = registration order)
151
+ * 3. Registration order (tiebreaker when priorities are equal)
155
152
  */
156
153
  declare class ProviderRegistry {
157
154
  private _providers;
158
- /** Register a Provider */
159
- register(provider: LLMProvider): void;
155
+ private _nextIndex;
156
+ /**
157
+ * Register a Provider.
158
+ * @param provider LLMProvider instance
159
+ * @param options.priority User-assigned priority (lower = preferred). Defaults to registration order.
160
+ */
161
+ register(provider: LLMProvider, options?: {
162
+ priority?: number;
163
+ }): void;
160
164
  /** Unregister a Provider */
161
165
  unregister(name: string): void;
162
166
  /** Get a Provider by name */
163
167
  get(name: string): LLMProvider | undefined;
164
168
  /**
165
169
  * Get available Providers sorted by priority.
166
- * Sort rule: offline > low cost > low latency > high accuracy
170
+ * Sort rule: offline first user priority (asc) registration order (asc)
167
171
  */
168
172
  getPrioritized(): Promise<LLMProvider[]>;
173
+ /**
174
+ * Explicitly reorder providers by name.
175
+ * Providers not listed retain their position after the reordered ones.
176
+ */
177
+ reorder(providerNames: string[]): void;
169
178
  /** List all registered Providers */
170
179
  list(): LLMProvider[];
171
180
  /** Number of registered Providers */
package/dist/index.js CHANGED
@@ -1,47 +1,69 @@
1
1
  // src/provider/provider-registry.ts
2
2
  var ProviderRegistry = class {
3
3
  _providers = [];
4
- /** Register a Provider */
5
- register(provider) {
6
- if (this._providers.some((p) => p.name === provider.name)) {
4
+ _nextIndex = 0;
5
+ /**
6
+ * Register a Provider.
7
+ * @param provider LLMProvider instance
8
+ * @param options.priority User-assigned priority (lower = preferred). Defaults to registration order.
9
+ */
10
+ register(provider, options) {
11
+ if (this._providers.some((p) => p.provider.name === provider.name)) {
7
12
  throw new Error(`Provider '${provider.name}' already registered`);
8
13
  }
9
- this._providers.push(provider);
14
+ this._providers.push({
15
+ provider,
16
+ priority: options?.priority ?? this._nextIndex,
17
+ index: this._nextIndex
18
+ });
19
+ this._nextIndex++;
10
20
  }
11
21
  /** Unregister a Provider */
12
22
  unregister(name) {
13
- this._providers = this._providers.filter((p) => p.name !== name);
23
+ this._providers = this._providers.filter((p) => p.provider.name !== name);
14
24
  }
15
25
  /** Get a Provider by name */
16
26
  get(name) {
17
- return this._providers.find((p) => p.name === name);
27
+ return this._providers.find((p) => p.provider.name === name)?.provider;
18
28
  }
19
29
  /**
20
30
  * Get available Providers sorted by priority.
21
- * Sort rule: offline > low cost > low latency > high accuracy
31
+ * Sort rule: offline first user priority (asc) registration order (asc)
22
32
  */
23
33
  async getPrioritized() {
24
34
  const available = [];
25
- for (const p of this._providers) {
26
- if (await p.isAvailable()) {
27
- available.push(p);
35
+ for (const entry of this._providers) {
36
+ if (await entry.provider.isAvailable()) {
37
+ available.push(entry);
28
38
  }
29
39
  }
30
40
  return available.sort((a, b) => {
31
- const aOffline = a.capabilities.offlineAvailable;
32
- const bOffline = b.capabilities.offlineAvailable;
41
+ const aOffline = a.provider.capabilities.offlineAvailable;
42
+ const bOffline = b.provider.capabilities.offlineAvailable;
33
43
  if (aOffline && !bOffline) return -1;
34
44
  if (!aOffline && bOffline) return 1;
35
- const costA = a.capabilities.estimatedCostPerRequest ?? Infinity;
36
- const costB = b.capabilities.estimatedCostPerRequest ?? Infinity;
37
- if (costA < costB) return -1;
38
- if (costB < costA) return 1;
39
- return a.capabilities.estimatedLatencyMs - b.capabilities.estimatedLatencyMs;
40
- });
45
+ if (a.priority !== b.priority) return a.priority - b.priority;
46
+ return a.index - b.index;
47
+ }).map((entry) => entry.provider);
48
+ }
49
+ /**
50
+ * Explicitly reorder providers by name.
51
+ * Providers not listed retain their position after the reordered ones.
52
+ */
53
+ reorder(providerNames) {
54
+ const orderMap = new Map(providerNames.map((name, i) => [name, i]));
55
+ const maxExisting = this._providers.reduce(
56
+ (max, p) => Math.max(max, p.priority),
57
+ providerNames.length - 1
58
+ );
59
+ for (const entry of this._providers) {
60
+ const explicitIndex = orderMap.get(entry.provider.name);
61
+ entry.priority = explicitIndex ?? maxExisting + entry.index + 1;
62
+ }
41
63
  }
42
64
  /** List all registered Providers */
43
65
  list() {
44
- return [...this._providers];
66
+ return this._providers.map((p) => p.provider);
45
67
  }
46
68
  /** Number of registered Providers */
47
69
  get count() {
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@agentix-e/nl2spel",
3
- "version": "1.2.2",
3
+ "version": "1.3.0",
4
4
  "description": "Natural Language → SpEL Expression Generation Engine — Core",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
8
8
  "exports": {
9
9
  ".": {
10
+ "types": "./dist/index.d.ts",
10
11
  "import": "./dist/index.js",
11
- "require": "./dist/index.cjs",
12
- "types": "./dist/index.d.ts"
12
+ "require": "./dist/index.cjs"
13
13
  }
14
14
  },
15
15
  "files": [
@@ -33,7 +33,7 @@
33
33
  }
34
34
  },
35
35
  "devDependencies": {
36
- "@agentix-e/spel-ts": "^1.1.0",
36
+ "@agentix-e/spel-ts": "^1.2.2",
37
37
  "tsup": "^8.5.1",
38
38
  "typescript": "^5.7.3",
39
39
  "vitest": "^3.0.0"