ayechat-dev 0.36.9.20260204171331__py3-none-any.whl → 0.36.9.20260205235944__py3-none-any.whl
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.
- aye/controller/llm_invoker.py +65 -55
- aye/model/config.py +5 -0
- aye/plugins/databricks_model.py +2 -1
- aye/plugins/local_model.py +0 -45
- {ayechat_dev-0.36.9.20260204171331.dist-info → ayechat_dev-0.36.9.20260205235944.dist-info}/METADATA +1 -1
- {ayechat_dev-0.36.9.20260204171331.dist-info → ayechat_dev-0.36.9.20260205235944.dist-info}/RECORD +10 -10
- {ayechat_dev-0.36.9.20260204171331.dist-info → ayechat_dev-0.36.9.20260205235944.dist-info}/WHEEL +0 -0
- {ayechat_dev-0.36.9.20260204171331.dist-info → ayechat_dev-0.36.9.20260205235944.dist-info}/entry_points.txt +0 -0
- {ayechat_dev-0.36.9.20260204171331.dist-info → ayechat_dev-0.36.9.20260205235944.dist-info}/licenses/LICENSE +0 -0
- {ayechat_dev-0.36.9.20260204171331.dist-info → ayechat_dev-0.36.9.20260205235944.dist-info}/top_level.txt +0 -0
aye/controller/llm_invoker.py
CHANGED
|
@@ -13,12 +13,16 @@ from aye.model.source_collector import collect_sources
|
|
|
13
13
|
from aye.model.auth import get_user_config
|
|
14
14
|
from aye.model.offline_llm_manager import is_offline_model
|
|
15
15
|
from aye.controller.util import is_truncated_json
|
|
16
|
-
from aye.model.config import SYSTEM_PROMPT, MODELS, DEFAULT_MAX_OUTPUT_TOKENS, DEFAULT_CONTEXT_TARGET_KB
|
|
16
|
+
from aye.model.config import SYSTEM_PROMPT, MODELS, DEFAULT_MAX_OUTPUT_TOKENS, DEFAULT_CONTEXT_TARGET_KB, CONTEXT_HARD_LIMIT_KB
|
|
17
17
|
from aye.model import telemetry
|
|
18
18
|
|
|
19
19
|
import os
|
|
20
20
|
|
|
21
21
|
|
|
22
|
+
def _is_verbose():
|
|
23
|
+
return get_user_config("verbose", "off").lower() == "on"
|
|
24
|
+
|
|
25
|
+
|
|
22
26
|
def _is_debug():
|
|
23
27
|
return get_user_config("debug", "off").lower() == "on"
|
|
24
28
|
|
|
@@ -77,7 +81,7 @@ def _get_context_hard_limit(model_id: str) -> int:
|
|
|
77
81
|
model_config = _get_model_config(model_id)
|
|
78
82
|
if model_config and "max_prompt_kb" in model_config:
|
|
79
83
|
return model_config["max_prompt_kb"] * 1024
|
|
80
|
-
return
|
|
84
|
+
return CONTEXT_HARD_LIMIT_KB * 1024
|
|
81
85
|
|
|
82
86
|
|
|
83
87
|
def _filter_ground_truth(files: Dict[str, str], conf: Any, verbose: bool) -> Dict[str, str]:
|
|
@@ -134,6 +138,8 @@ def _get_rag_context_files(prompt: str, conf: Any, verbose: bool) -> Dict[str, s
|
|
|
134
138
|
|
|
135
139
|
context_target_size = _get_context_target_size(conf.selected_model)
|
|
136
140
|
context_hard_limit = _get_context_hard_limit(conf.selected_model)
|
|
141
|
+
#context_target_size = DEFAULT_CONTEXT_TARGET_KB #_get_context_target_size(conf.selected_model)
|
|
142
|
+
#context_hard_limit = CONTEXT_HARD_LIMIT_KB # _get_context_hard_limit(conf.selected_model)
|
|
137
143
|
|
|
138
144
|
if _is_debug():
|
|
139
145
|
rprint(f"[yellow]Context target: {context_target_size / 1024:.1f}KB, hard limit: {context_hard_limit / 1024:.1f}KB[/]")
|
|
@@ -298,50 +304,54 @@ def invoke_llm(
|
|
|
298
304
|
model_config = _get_model_config(conf.selected_model)
|
|
299
305
|
max_output_tokens = model_config.get("max_output_tokens", DEFAULT_MAX_OUTPUT_TOKENS) if model_config else DEFAULT_MAX_OUTPUT_TOKENS
|
|
300
306
|
|
|
301
|
-
#
|
|
302
|
-
local_response = plugin_manager.handle_command("local_model_invoke", {
|
|
303
|
-
"prompt": prompt,
|
|
304
|
-
"model_id": conf.selected_model,
|
|
305
|
-
"source_files": source_files,
|
|
306
|
-
"chat_id": chat_id,
|
|
307
|
-
"root": conf.root,
|
|
308
|
-
"system_prompt": system_prompt,
|
|
309
|
-
"max_output_tokens": max_output_tokens
|
|
310
|
-
})
|
|
311
|
-
|
|
312
|
-
if local_response is not None:
|
|
313
|
-
return LLMResponse(
|
|
314
|
-
summary=local_response.get("summary", ""),
|
|
315
|
-
updated_files=local_response.get("updated_files", []),
|
|
316
|
-
chat_id=None,
|
|
317
|
-
source=LLMSource.LOCAL
|
|
318
|
-
)
|
|
319
|
-
|
|
320
|
-
# 2. API call with spinner + streaming display
|
|
321
|
-
if _is_debug():
|
|
322
|
-
print(f"[DEBUG] Processing chat message with chat_id={chat_id or -1}, model={conf.selected_model}")
|
|
323
|
-
|
|
324
|
-
telemetry_payload = telemetry.build_payload(top_n=20) if telemetry.is_enabled() else None
|
|
325
|
-
|
|
326
|
-
# Create spinner - will be stopped when streaming starts
|
|
307
|
+
# Create spinner - will be shown for ALL model types (local, databricks, API)
|
|
327
308
|
spinner = StoppableSpinner(
|
|
328
309
|
console,
|
|
329
310
|
messages=DEFAULT_THINKING_MESSAGES,
|
|
330
311
|
interval=15.0
|
|
331
312
|
)
|
|
332
313
|
|
|
314
|
+
# For API calls, we also have streaming display
|
|
315
|
+
streaming_display: Optional[StreamingResponseDisplay] = None
|
|
316
|
+
|
|
333
317
|
def stop_spinner():
|
|
334
|
-
"""Callback to stop spinner when first content arrives."""
|
|
318
|
+
"""Callback to stop spinner when first content arrives (for streaming API)."""
|
|
335
319
|
spinner.stop()
|
|
336
|
-
|
|
337
|
-
# Create streaming display with callback to stop spinner on first content
|
|
338
|
-
streaming_display = StreamingResponseDisplay(on_first_content=stop_spinner)
|
|
339
|
-
stream_callback = create_streaming_callback(streaming_display)
|
|
340
320
|
|
|
341
321
|
try:
|
|
342
|
-
# Start the spinner before
|
|
322
|
+
# Start the spinner before ANY LLM call (local or API)
|
|
343
323
|
spinner.start()
|
|
344
324
|
|
|
325
|
+
# 1. Try local/offline model plugins first
|
|
326
|
+
local_response = plugin_manager.handle_command("local_model_invoke", {
|
|
327
|
+
"prompt": prompt,
|
|
328
|
+
"model_id": conf.selected_model,
|
|
329
|
+
"source_files": source_files,
|
|
330
|
+
"chat_id": chat_id,
|
|
331
|
+
"root": conf.root,
|
|
332
|
+
"system_prompt": system_prompt,
|
|
333
|
+
"max_output_tokens": max_output_tokens
|
|
334
|
+
})
|
|
335
|
+
|
|
336
|
+
if local_response is not None:
|
|
337
|
+
# Local model handled the request - spinner will be stopped in finally block
|
|
338
|
+
return LLMResponse(
|
|
339
|
+
summary=local_response.get("summary", ""),
|
|
340
|
+
updated_files=local_response.get("updated_files", []),
|
|
341
|
+
chat_id=None,
|
|
342
|
+
source=LLMSource.LOCAL
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
# 2. API call with streaming display
|
|
346
|
+
if _is_debug():
|
|
347
|
+
print(f"[DEBUG] Processing chat message with chat_id={chat_id or -1}, model={conf.selected_model}")
|
|
348
|
+
|
|
349
|
+
telemetry_payload = telemetry.build_payload(top_n=20) if telemetry.is_enabled() else None
|
|
350
|
+
|
|
351
|
+
# Create streaming display with callback to stop spinner on first content
|
|
352
|
+
streaming_display = StreamingResponseDisplay(on_first_content=stop_spinner)
|
|
353
|
+
stream_callback = create_streaming_callback(streaming_display)
|
|
354
|
+
|
|
345
355
|
api_resp = cli_invoke(
|
|
346
356
|
message=prompt,
|
|
347
357
|
chat_id=chat_id or -1,
|
|
@@ -352,29 +362,29 @@ def invoke_llm(
|
|
|
352
362
|
telemetry=telemetry_payload,
|
|
353
363
|
on_stream_update=stream_callback
|
|
354
364
|
)
|
|
355
|
-
finally:
|
|
356
|
-
# Ensure spinner is stopped (in case no streaming content was received)
|
|
357
|
-
spinner.stop()
|
|
358
|
-
|
|
359
|
-
# Always stop the streaming display when done
|
|
360
|
-
if streaming_display.is_active():
|
|
361
|
-
streaming_display.stop()
|
|
362
365
|
|
|
363
|
-
|
|
364
|
-
|
|
366
|
+
if telemetry_payload is not None:
|
|
367
|
+
telemetry.reset()
|
|
365
368
|
|
|
366
|
-
|
|
367
|
-
|
|
369
|
+
if _is_debug():
|
|
370
|
+
print(f"[DEBUG] Chat message processed, response keys: {api_resp.keys() if api_resp else 'None'}")
|
|
368
371
|
|
|
369
|
-
|
|
370
|
-
|
|
372
|
+
# Check if we already displayed the response via streaming
|
|
373
|
+
streamed_summary = bool(api_resp.get("_streamed_summary")) if isinstance(api_resp, dict) else False
|
|
371
374
|
|
|
372
|
-
|
|
373
|
-
|
|
375
|
+
# 3. Parse API response
|
|
376
|
+
assistant_resp, new_chat_id = _parse_api_response(api_resp)
|
|
374
377
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
378
|
+
return LLMResponse(
|
|
379
|
+
summary="" if streamed_summary else assistant_resp.get("answer_summary", ""),
|
|
380
|
+
updated_files=assistant_resp.get("source_files", []),
|
|
381
|
+
chat_id=new_chat_id,
|
|
382
|
+
source=LLMSource.API
|
|
383
|
+
)
|
|
384
|
+
finally:
|
|
385
|
+
# Ensure spinner is stopped for ALL code paths (local model, API, or error)
|
|
386
|
+
spinner.stop()
|
|
387
|
+
|
|
388
|
+
# Stop the streaming display if it was created and is active
|
|
389
|
+
if streaming_display is not None and streaming_display.is_active():
|
|
390
|
+
streaming_display.stop()
|
aye/model/config.py
CHANGED
|
@@ -17,12 +17,17 @@ SMALL_PROJECT_FILE_LIMIT = 200
|
|
|
17
17
|
# Projects smaller than this will skip RAG and include all files directly.
|
|
18
18
|
# Set to match default max_prompt_kb (170KB) so all files can fit in context.
|
|
19
19
|
SMALL_PROJECT_TOTAL_SIZE_LIMIT = 170 * 1024 # 170KB
|
|
20
|
+
#SMALL_PROJECT_TOTAL_SIZE_LIMIT = 100 * 1024 # 170KB
|
|
20
21
|
|
|
21
22
|
# Default maximum output tokens for LLM responses
|
|
22
23
|
DEFAULT_MAX_OUTPUT_TOKENS = 32000
|
|
24
|
+
#DEFAULT_MAX_OUTPUT_TOKENS = 16000
|
|
23
25
|
|
|
24
26
|
# Default context target size in KB (used when model doesn't specify one)
|
|
25
27
|
DEFAULT_CONTEXT_TARGET_KB = 150
|
|
28
|
+
#DEFAULT_CONTEXT_TARGET_KB = 20
|
|
29
|
+
|
|
30
|
+
CONTEXT_HARD_LIMIT_KB = 170
|
|
26
31
|
|
|
27
32
|
# Shared system prompt for all LLM interactions
|
|
28
33
|
SYSTEM_PROMPT = (
|
aye/plugins/databricks_model.py
CHANGED
|
@@ -245,7 +245,8 @@ class DatabricksModelPlugin(Plugin):
|
|
|
245
245
|
try:
|
|
246
246
|
with httpx.Client(timeout=LLM_TIMEOUT) as client:
|
|
247
247
|
response = client.post(api_url, json=payload, headers=headers)
|
|
248
|
-
if self.
|
|
248
|
+
if self.verbose and response.status_code != 200:
|
|
249
|
+
print(f"Status code: {response.status_code}")
|
|
249
250
|
print("-----------------")
|
|
250
251
|
print(response.text)
|
|
251
252
|
print("-----------------")
|
aye/plugins/local_model.py
CHANGED
|
@@ -136,48 +136,6 @@ class LocalModelPlugin(Plugin):
|
|
|
136
136
|
"updated_files": []
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
def _handle_databricks(self, prompt: str, source_files: Dict[str, str], chat_id: Optional[int] = None, system_prompt: Optional[str] = None, max_output_tokens: int = DEFAULT_MAX_OUTPUT_TOKENS) -> Optional[Dict[str, Any]]:
|
|
140
|
-
api_url = os.environ.get("AYE_DBX_API_URL")
|
|
141
|
-
api_key = os.environ.get("AYE_DBX_API_KEY")
|
|
142
|
-
model_name = os.environ.get("AYE_DBX_MODEL", "gpt-3.5-turbo")
|
|
143
|
-
|
|
144
|
-
if not api_url or not api_key:
|
|
145
|
-
return None
|
|
146
|
-
|
|
147
|
-
conv_id = self._get_conversation_id(chat_id)
|
|
148
|
-
if conv_id not in self.chat_history:
|
|
149
|
-
self.chat_history[conv_id] = []
|
|
150
|
-
|
|
151
|
-
user_message = self._build_user_message(prompt, source_files)
|
|
152
|
-
effective_system_prompt = system_prompt if system_prompt else SYSTEM_PROMPT
|
|
153
|
-
|
|
154
|
-
messages = [{"role": "system", "content": effective_system_prompt}] + self.chat_history[conv_id] + [{"role": "user", "content": user_message}]
|
|
155
|
-
|
|
156
|
-
headers = {"Content-Type": "application/json", "Authorization": f"Bearer {api_key}"}
|
|
157
|
-
payload = {"model": model_name, "messages": messages, "temperature": 0.7, "max_tokens": max_output_tokens, "response_format": {"type": "json_object"}}
|
|
158
|
-
|
|
159
|
-
try:
|
|
160
|
-
with httpx.Client(timeout=LLM_TIMEOUT) as client:
|
|
161
|
-
response = client.post(api_url, json=payload, headers=headers)
|
|
162
|
-
response.raise_for_status()
|
|
163
|
-
result = response.json()
|
|
164
|
-
if result.get("choices") and result["choices"][0].get("message"):
|
|
165
|
-
generated_text = result["choices"][0]["message"]["content"][0]["text"]
|
|
166
|
-
self.chat_history[conv_id].append({"role": "user", "content": user_message})
|
|
167
|
-
self.chat_history[conv_id].append({"role": "assistant", "content": generated_text})
|
|
168
|
-
self._save_history()
|
|
169
|
-
return self._parse_llm_response(generated_text)
|
|
170
|
-
return self._create_error_response("Failed to get a valid response from the Databricks API")
|
|
171
|
-
except httpx.HTTPStatusError as e:
|
|
172
|
-
error_msg = f"DBX API error: {e.response.status_code}"
|
|
173
|
-
try:
|
|
174
|
-
error_detail = e.response.json()
|
|
175
|
-
if "error" in error_detail:
|
|
176
|
-
error_msg += f" - {error_detail['error'].get('message', str(error_detail['error']))}"
|
|
177
|
-
except: error_msg += f" - {e.response.text[:200]}"
|
|
178
|
-
return self._create_error_response(error_msg)
|
|
179
|
-
except Exception as e:
|
|
180
|
-
return self._create_error_response(f"Error calling Databricks API: {str(e)}")
|
|
181
139
|
|
|
182
140
|
def _handle_openai_compatible(self, prompt: str, source_files: Dict[str, str], chat_id: Optional[int] = None, system_prompt: Optional[str] = None, max_output_tokens: int = DEFAULT_MAX_OUTPUT_TOKENS) -> Optional[Dict[str, Any]]:
|
|
183
141
|
"""Handle OpenAI-compatible API endpoints.
|
|
@@ -288,9 +246,6 @@ class LocalModelPlugin(Plugin):
|
|
|
288
246
|
result = self._handle_openai_compatible(prompt, source_files, chat_id, system_prompt, max_output_tokens)
|
|
289
247
|
if result is not None: return result
|
|
290
248
|
|
|
291
|
-
result = self._handle_databricks(prompt, source_files, chat_id, system_prompt, max_output_tokens)
|
|
292
|
-
if result is not None: return result
|
|
293
|
-
|
|
294
249
|
if model_id == "google/gemini-2.5-pro":
|
|
295
250
|
return self._handle_gemini_pro_25(prompt, source_files, chat_id, system_prompt, max_output_tokens)
|
|
296
251
|
|
{ayechat_dev-0.36.9.20260204171331.dist-info → ayechat_dev-0.36.9.20260205235944.dist-info}/RECORD
RENAMED
|
@@ -6,7 +6,7 @@ aye/controller/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
6
6
|
aye/controller/command_handlers.py,sha256=S_HOYY91lbLkGtCkby28T8qUFPNtfy-CbOGn9VGZtTo,17446
|
|
7
7
|
aye/controller/commands.py,sha256=sXmK_sgNBrw9Fs7mKcr93-wsu740ZlvWSisQfS-1EUE,12278
|
|
8
8
|
aye/controller/llm_handler.py,sha256=gY3X2rHcvhPp8iqp_Vor7QpbwHltmcm_Uu9MWF1Z598,7120
|
|
9
|
-
aye/controller/llm_invoker.py,sha256=
|
|
9
|
+
aye/controller/llm_invoker.py,sha256=1TMsF5q9HT5r8F4zZ5HQo_g_eYyt7uBX4d46QsUHY4k,14868
|
|
10
10
|
aye/controller/plugin_manager.py,sha256=9ZuITyA5sQJJJU-IntLQ1SsxXsDnbgZKPOF4e9VmsEU,3018
|
|
11
11
|
aye/controller/repl.py,sha256=nSlzAHD8MQlQ7vnpBTLVzA1jQ8jkNjxUnUoqE31chxY,27028
|
|
12
12
|
aye/controller/tutorial.py,sha256=lc92jOcJOYCVrrjTEF0Suk4-8jn-ku98kTJEIL8taUA,7254
|
|
@@ -16,7 +16,7 @@ aye/model/api.py,sha256=HhSMQQ_szdC2ZPOSfNsJRbs1FRwb6WyYIeLejB2ScbA,13272
|
|
|
16
16
|
aye/model/ast_chunker.py,sha256=rVcDdynVUXXyxWVgtUcsee_STqB7SAwP776ktWTlYig,4462
|
|
17
17
|
aye/model/auth.py,sha256=ozV_uQxdqXtUoWO3nZwpzVnDOIfnRAmSMC6W0N724vE,4800
|
|
18
18
|
aye/model/autodiff_config.py,sha256=b8pyudkJFYXF5JWPxft0bH5uazeCab9i-A11dNt1d7U,931
|
|
19
|
-
aye/model/config.py,sha256=
|
|
19
|
+
aye/model/config.py,sha256=s9c5w4bmOegpNu2CM1z8ITWUbsEzMaX9_BliqHr7KLA,9430
|
|
20
20
|
aye/model/download_plugins.py,sha256=6omyFGdxlEIb7tKPLq4rRVrRYeCPUUCE8aZHvJAKGSc,4442
|
|
21
21
|
aye/model/file_processor.py,sha256=b7YGvHAmhGto9JbtzcfrsdkFtksHbosYt-42EnR22Uo,2131
|
|
22
22
|
aye/model/ignore_patterns.py,sha256=AhcnZuU9_a77Q4yKFRTG6yIrDG4HcECwdY7D1NQkBDY,2767
|
|
@@ -43,8 +43,8 @@ aye/plugins/__init__.py,sha256=dSTxs461ICx0O1tbCBCca0W_7QIAa0Yt9PQhHiT5uZQ,173
|
|
|
43
43
|
aye/plugins/at_file_completer.py,sha256=uNS4gWpfKvn9_nGxZbhQVjVg_S82g977gfBR-pL3XrQ,19582
|
|
44
44
|
aye/plugins/auto_detect_mask.py,sha256=gZKH4qkR-A73uKpMkPXhlgI452Ae_2YG1nHtaIkOvwM,6864
|
|
45
45
|
aye/plugins/completer.py,sha256=qhxke5Q76P2u0LojSIL3V48RTNG5tWL-5-TK5tNutrE,13893
|
|
46
|
-
aye/plugins/databricks_model.py,sha256=
|
|
47
|
-
aye/plugins/local_model.py,sha256=
|
|
46
|
+
aye/plugins/databricks_model.py,sha256=TpERRIZKh_vJBVu630ModfT2geMXwEEX5XDqzlLt7dI,12494
|
|
47
|
+
aye/plugins/local_model.py,sha256=u3cVLkAD2XGaEvXEFKnmZcDhmqFOi1aqD0ocgysxwCc,12036
|
|
48
48
|
aye/plugins/offline_llm.py,sha256=qFmd1e8Lbl7yiMgXpXjOQkQTNxOk0_WXU7km2DTKXGY,13357
|
|
49
49
|
aye/plugins/plugin_base.py,sha256=t5hTOnA0dZC237BnseAgdXbOqErlSCNLUo_Uul09TSw,1673
|
|
50
50
|
aye/plugins/shell_executor.py,sha256=a0mlZnQeURONdtPM7iageTcQ8PiNLQbjxoY54EsS32o,7502
|
|
@@ -55,9 +55,9 @@ aye/presenter/diff_presenter.py,sha256=cbxfOEqGomPTDvQpKdybfYeNUD2DYVAl85j1uy5--
|
|
|
55
55
|
aye/presenter/repl_ui.py,sha256=PVENlAQM_tm_k2dANsmQH6I8ATMVXhrdj_hNzc38pSw,8156
|
|
56
56
|
aye/presenter/streaming_ui.py,sha256=_3tBEuNH9UQ9Gyq2yuvRfX4SWVkcGMYirEUGj-MXVJ0,12768
|
|
57
57
|
aye/presenter/ui_utils.py,sha256=6KXR4_ZZZUdF5pCHrPqO8yywlQk7AOzWe-2B4Wj_-ZQ,5441
|
|
58
|
-
ayechat_dev-0.36.9.
|
|
59
|
-
ayechat_dev-0.36.9.
|
|
60
|
-
ayechat_dev-0.36.9.
|
|
61
|
-
ayechat_dev-0.36.9.
|
|
62
|
-
ayechat_dev-0.36.9.
|
|
63
|
-
ayechat_dev-0.36.9.
|
|
58
|
+
ayechat_dev-0.36.9.20260205235944.dist-info/licenses/LICENSE,sha256=U1ou6lkMKmPo16-E9YowIu3goU7sOWKUprGo0AOA72s,1065
|
|
59
|
+
ayechat_dev-0.36.9.20260205235944.dist-info/METADATA,sha256=5Q9LhxUYe4U-aCCtJqe4zSXokZWji5uVCwdMgjgWqL0,7718
|
|
60
|
+
ayechat_dev-0.36.9.20260205235944.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
61
|
+
ayechat_dev-0.36.9.20260205235944.dist-info/entry_points.txt,sha256=KGsOma6szoefNN6vHozg3Pbf1fjZ7ZbmwrOiVwBd0Ik,41
|
|
62
|
+
ayechat_dev-0.36.9.20260205235944.dist-info/top_level.txt,sha256=7WZL0LOx4-GKKvgU1mtI5s4Dhk2OdieVZZvVnxFJHr8,4
|
|
63
|
+
ayechat_dev-0.36.9.20260205235944.dist-info/RECORD,,
|
{ayechat_dev-0.36.9.20260204171331.dist-info → ayechat_dev-0.36.9.20260205235944.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|