aisbf 0.2.2__tar.gz → 0.2.4__tar.gz
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.
- {aisbf-0.2.2/aisbf.egg-info → aisbf-0.2.4}/PKG-INFO +1 -1
- {aisbf-0.2.2 → aisbf-0.2.4}/aisbf/config.py +57 -1
- aisbf-0.2.4/aisbf/handlers.py +664 -0
- {aisbf-0.2.2 → aisbf-0.2.4}/aisbf/providers.py +164 -9
- {aisbf-0.2.2 → aisbf-0.2.4/aisbf.egg-info}/PKG-INFO +1 -1
- aisbf-0.2.4/main.py +421 -0
- {aisbf-0.2.2 → aisbf-0.2.4}/pyproject.toml +1 -1
- {aisbf-0.2.2 → aisbf-0.2.4}/setup.py +1 -1
- aisbf-0.2.2/aisbf/handlers.py +0 -383
- aisbf-0.2.2/main.py +0 -214
- {aisbf-0.2.2 → aisbf-0.2.4}/LICENSE.txt +0 -0
- {aisbf-0.2.2 → aisbf-0.2.4}/MANIFEST.in +0 -0
- {aisbf-0.2.2 → aisbf-0.2.4}/README.md +0 -0
- {aisbf-0.2.2 → aisbf-0.2.4}/aisbf/__init__.py +0 -0
- {aisbf-0.2.2 → aisbf-0.2.4}/aisbf/models.py +0 -0
- {aisbf-0.2.2 → aisbf-0.2.4}/aisbf.egg-info/SOURCES.txt +0 -0
- {aisbf-0.2.2 → aisbf-0.2.4}/aisbf.egg-info/dependency_links.txt +0 -0
- {aisbf-0.2.2 → aisbf-0.2.4}/aisbf.egg-info/entry_points.txt +0 -0
- {aisbf-0.2.2 → aisbf-0.2.4}/aisbf.egg-info/requires.txt +0 -0
- {aisbf-0.2.2 → aisbf-0.2.4}/aisbf.egg-info/top_level.txt +0 -0
- {aisbf-0.2.2 → aisbf-0.2.4}/aisbf.sh +0 -0
- {aisbf-0.2.2 → aisbf-0.2.4}/cli.py +0 -0
- {aisbf-0.2.2 → aisbf-0.2.4}/config/autoselect.json +0 -0
- {aisbf-0.2.2 → aisbf-0.2.4}/config/autoselect.md +0 -0
- {aisbf-0.2.2 → aisbf-0.2.4}/config/providers.json +0 -0
- {aisbf-0.2.2 → aisbf-0.2.4}/config/rotations.json +0 -0
- {aisbf-0.2.2 → aisbf-0.2.4}/requirements.txt +0 -0
- {aisbf-0.2.2 → aisbf-0.2.4}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aisbf
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: AISBF - AI Service Broker Framework || AI Should Be Free - A modular proxy server for managing multiple AI provider integrations
|
|
5
5
|
Home-page: https://git.nexlab.net/nexlab/aisbf.git
|
|
6
6
|
Author: AISBF Contributors
|
|
@@ -34,6 +34,7 @@ class ProviderConfig(BaseModel):
|
|
|
34
34
|
endpoint: str
|
|
35
35
|
type: str
|
|
36
36
|
api_key_required: bool
|
|
37
|
+
rate_limit: float = 0.0
|
|
37
38
|
|
|
38
39
|
class RotationConfig(BaseModel):
|
|
39
40
|
providers: List[Dict]
|
|
@@ -111,32 +112,78 @@ class Config:
|
|
|
111
112
|
print(f"Created default config file: {dst}")
|
|
112
113
|
|
|
113
114
|
def _load_providers(self):
|
|
115
|
+
import logging
|
|
116
|
+
logger = logging.getLogger(__name__)
|
|
117
|
+
logger.info(f"=== Config._load_providers START ===")
|
|
118
|
+
|
|
114
119
|
providers_path = Path.home() / '.aisbf' / 'providers.json'
|
|
120
|
+
logger.info(f"Looking for providers at: {providers_path}")
|
|
121
|
+
|
|
115
122
|
if not providers_path.exists():
|
|
123
|
+
logger.info(f"User config not found, falling back to source config")
|
|
116
124
|
# Fallback to source config if user config doesn't exist
|
|
117
125
|
try:
|
|
118
126
|
source_dir = self._get_config_source_dir()
|
|
119
127
|
providers_path = source_dir / 'providers.json'
|
|
128
|
+
logger.info(f"Using source config at: {providers_path}")
|
|
120
129
|
except FileNotFoundError:
|
|
130
|
+
logger.error("Could not find providers.json configuration file")
|
|
121
131
|
raise FileNotFoundError("Could not find providers.json configuration file")
|
|
122
132
|
|
|
133
|
+
logger.info(f"Loading providers from: {providers_path}")
|
|
123
134
|
with open(providers_path) as f:
|
|
124
135
|
data = json.load(f)
|
|
125
136
|
self.providers = {k: ProviderConfig(**v) for k, v in data['providers'].items()}
|
|
137
|
+
logger.info(f"Loaded {len(self.providers)} providers: {list(self.providers.keys())}")
|
|
138
|
+
for provider_id, provider_config in self.providers.items():
|
|
139
|
+
logger.info(f" - {provider_id}: type={provider_config.type}, endpoint={provider_config.endpoint}")
|
|
140
|
+
logger.info(f"=== Config._load_providers END ===")
|
|
126
141
|
|
|
127
142
|
def _load_rotations(self):
|
|
143
|
+
import logging
|
|
144
|
+
logger = logging.getLogger(__name__)
|
|
145
|
+
logger.info(f"=== Config._load_rotations START ===")
|
|
146
|
+
|
|
128
147
|
rotations_path = Path.home() / '.aisbf' / 'rotations.json'
|
|
148
|
+
logger.info(f"Looking for rotations at: {rotations_path}")
|
|
149
|
+
|
|
129
150
|
if not rotations_path.exists():
|
|
151
|
+
logger.info(f"User config not found, falling back to source config")
|
|
130
152
|
# Fallback to source config if user config doesn't exist
|
|
131
153
|
try:
|
|
132
154
|
source_dir = self._get_config_source_dir()
|
|
133
155
|
rotations_path = source_dir / 'rotations.json'
|
|
156
|
+
logger.info(f"Using source config at: {rotations_path}")
|
|
134
157
|
except FileNotFoundError:
|
|
158
|
+
logger.error("Could not find rotations.json configuration file")
|
|
135
159
|
raise FileNotFoundError("Could not find rotations.json configuration file")
|
|
136
160
|
|
|
161
|
+
logger.info(f"Loading rotations from: {rotations_path}")
|
|
137
162
|
with open(rotations_path) as f:
|
|
138
163
|
data = json.load(f)
|
|
139
164
|
self.rotations = {k: RotationConfig(**v) for k, v in data['rotations'].items()}
|
|
165
|
+
logger.info(f"Loaded {len(self.rotations)} rotations: {list(self.rotations.keys())}")
|
|
166
|
+
|
|
167
|
+
# Validate that all providers referenced in rotations exist
|
|
168
|
+
logger.info(f"=== VALIDATING ROTATION PROVIDERS ===")
|
|
169
|
+
available_providers = list(self.providers.keys())
|
|
170
|
+
logger.info(f"Available providers: {available_providers}")
|
|
171
|
+
|
|
172
|
+
for rotation_id, rotation_config in self.rotations.items():
|
|
173
|
+
logger.info(f"Validating rotation: {rotation_id}")
|
|
174
|
+
for provider in rotation_config.providers:
|
|
175
|
+
provider_id = provider['provider_id']
|
|
176
|
+
if provider_id not in self.providers:
|
|
177
|
+
logger.warning(f"!!! CONFIGURATION WARNING !!!")
|
|
178
|
+
logger.warning(f"Rotation '{rotation_id}' references provider '{provider_id}' which is NOT defined in providers.json")
|
|
179
|
+
logger.warning(f"Available providers: {available_providers}")
|
|
180
|
+
logger.warning(f"This provider will be SKIPPED during rotation requests")
|
|
181
|
+
logger.warning(f"Please add the provider to providers.json or remove it from the rotation configuration")
|
|
182
|
+
logger.warning(f"!!! END WARNING !!!")
|
|
183
|
+
else:
|
|
184
|
+
logger.info(f" ✓ Provider '{provider_id}' is available")
|
|
185
|
+
|
|
186
|
+
logger.info(f"=== Config._load_rotations END ===")
|
|
140
187
|
|
|
141
188
|
def _load_autoselect(self):
|
|
142
189
|
autoselect_path = Path.home() / '.aisbf' / 'autoselect.json'
|
|
@@ -162,7 +209,16 @@ class Config:
|
|
|
162
209
|
}
|
|
163
210
|
|
|
164
211
|
def get_provider(self, provider_id: str) -> ProviderConfig:
|
|
165
|
-
|
|
212
|
+
import logging
|
|
213
|
+
logger = logging.getLogger(__name__)
|
|
214
|
+
logger.info(f"Config.get_provider called with provider_id: {provider_id}")
|
|
215
|
+
logger.info(f"Available providers: {list(self.providers.keys())}")
|
|
216
|
+
result = self.providers.get(provider_id)
|
|
217
|
+
if result:
|
|
218
|
+
logger.info(f"Found provider: {result}")
|
|
219
|
+
else:
|
|
220
|
+
logger.warning(f"Provider {provider_id} not found!")
|
|
221
|
+
return result
|
|
166
222
|
|
|
167
223
|
def get_rotation(self, rotation_id: str) -> RotationConfig:
|
|
168
224
|
return self.rotations.get(rotation_id)
|