appkit-assistant 0.16.3__py3-none-any.whl → 0.17.1__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.
- appkit_assistant/backend/file_manager.py +117 -0
- appkit_assistant/backend/models.py +12 -0
- appkit_assistant/backend/processors/claude_base.py +178 -0
- appkit_assistant/backend/processors/claude_responses_processor.py +923 -0
- appkit_assistant/backend/processors/gemini_base.py +84 -0
- appkit_assistant/backend/processors/gemini_responses_processor.py +726 -0
- appkit_assistant/backend/processors/lorem_ipsum_processor.py +2 -0
- appkit_assistant/backend/processors/openai_base.py +10 -10
- appkit_assistant/backend/processors/openai_chat_completion_processor.py +25 -8
- appkit_assistant/backend/processors/openai_responses_processor.py +22 -15
- appkit_assistant/{logic → backend}/response_accumulator.py +58 -11
- appkit_assistant/components/__init__.py +2 -0
- appkit_assistant/components/composer.py +99 -12
- appkit_assistant/components/message.py +218 -50
- appkit_assistant/components/thread.py +2 -1
- appkit_assistant/configuration.py +2 -0
- appkit_assistant/state/thread_state.py +239 -5
- {appkit_assistant-0.16.3.dist-info → appkit_assistant-0.17.1.dist-info}/METADATA +4 -1
- {appkit_assistant-0.16.3.dist-info → appkit_assistant-0.17.1.dist-info}/RECORD +20 -15
- {appkit_assistant-0.16.3.dist-info → appkit_assistant-0.17.1.dist-info}/WHEEL +0 -0
|
@@ -14,10 +14,12 @@ import json
|
|
|
14
14
|
import logging
|
|
15
15
|
import uuid
|
|
16
16
|
from collections.abc import AsyncGenerator
|
|
17
|
+
from datetime import UTC, datetime
|
|
17
18
|
from typing import Any
|
|
18
19
|
|
|
19
20
|
import reflex as rx
|
|
20
21
|
|
|
22
|
+
from appkit_assistant.backend import file_manager
|
|
21
23
|
from appkit_assistant.backend.model_manager import ModelManager
|
|
22
24
|
from appkit_assistant.backend.models import (
|
|
23
25
|
AIModel,
|
|
@@ -31,10 +33,11 @@ from appkit_assistant.backend.models import (
|
|
|
31
33
|
ThinkingType,
|
|
32
34
|
ThreadModel,
|
|
33
35
|
ThreadStatus,
|
|
36
|
+
UploadedFile,
|
|
34
37
|
)
|
|
35
38
|
from appkit_assistant.backend.repositories import mcp_server_repo
|
|
39
|
+
from appkit_assistant.backend.response_accumulator import ResponseAccumulator
|
|
36
40
|
from appkit_assistant.backend.services.thread_service import ThreadService
|
|
37
|
-
from appkit_assistant.logic.response_accumulator import ResponseAccumulator
|
|
38
41
|
from appkit_assistant.state.thread_list_state import ThreadListState
|
|
39
42
|
from appkit_commons.database.session import get_asyncdb_session
|
|
40
43
|
from appkit_user.authentication.states import UserSession
|
|
@@ -69,6 +72,13 @@ class ThreadState(rx.State):
|
|
|
69
72
|
thinking_expanded: bool = False
|
|
70
73
|
current_activity: str = ""
|
|
71
74
|
|
|
75
|
+
# File upload state
|
|
76
|
+
uploaded_files: list[UploadedFile] = []
|
|
77
|
+
|
|
78
|
+
# Editing state
|
|
79
|
+
editing_message_id: str | None = None
|
|
80
|
+
edited_message_content: str = ""
|
|
81
|
+
|
|
72
82
|
# Internal logic helper (not reactive)
|
|
73
83
|
@property
|
|
74
84
|
def _thread_service(self) -> ThreadService:
|
|
@@ -97,6 +107,7 @@ class ThreadState(rx.State):
|
|
|
97
107
|
_initialized: bool = False
|
|
98
108
|
_current_user_id: str = ""
|
|
99
109
|
_skip_user_message: bool = False # Skip adding user message (for OAuth resend)
|
|
110
|
+
_pending_file_cleanup: list[str] = [] # Files to delete after processing
|
|
100
111
|
|
|
101
112
|
# -------------------------------------------------------------------------
|
|
102
113
|
# Computed properties
|
|
@@ -135,6 +146,14 @@ class ThreadState(rx.State):
|
|
|
135
146
|
model = ModelManager().get_model(self.selected_model)
|
|
136
147
|
return model.supports_tools if model else False
|
|
137
148
|
|
|
149
|
+
@rx.var
|
|
150
|
+
def selected_model_supports_attachments(self) -> bool:
|
|
151
|
+
"""Check if the currently selected model supports attachments."""
|
|
152
|
+
if not self.selected_model:
|
|
153
|
+
return False
|
|
154
|
+
model = ModelManager().get_model(self.selected_model)
|
|
155
|
+
return model.supports_attachments if model else False
|
|
156
|
+
|
|
138
157
|
@rx.var
|
|
139
158
|
def get_unique_reasoning_sessions(self) -> list[str]:
|
|
140
159
|
"""Get unique reasoning session IDs."""
|
|
@@ -432,11 +451,131 @@ class ThreadState(rx.State):
|
|
|
432
451
|
self.thinking_items = []
|
|
433
452
|
self.image_chunks = []
|
|
434
453
|
self.show_thinking = False
|
|
454
|
+
self._clear_uploaded_files()
|
|
455
|
+
|
|
456
|
+
# -------------------------------------------------------------------------
|
|
457
|
+
# File upload handling
|
|
458
|
+
# -------------------------------------------------------------------------
|
|
459
|
+
|
|
460
|
+
@rx.event
|
|
461
|
+
async def handle_upload(self, files: list[rx.UploadFile]) -> None:
|
|
462
|
+
"""Handle uploaded files from the browser.
|
|
463
|
+
|
|
464
|
+
Moves files to user-specific directory and adds them to state.
|
|
465
|
+
"""
|
|
466
|
+
user_session: UserSession = await self.get_state(UserSession)
|
|
467
|
+
user_id = user_session.user.user_id if user_session.user else "anonymous"
|
|
468
|
+
|
|
469
|
+
for upload_file in files:
|
|
470
|
+
try:
|
|
471
|
+
# Save uploaded file to disk first
|
|
472
|
+
upload_data = await upload_file.read()
|
|
473
|
+
temp_path = rx.get_upload_dir() / upload_file.filename
|
|
474
|
+
temp_path.parent.mkdir(parents=True, exist_ok=True)
|
|
475
|
+
temp_path.write_bytes(upload_data)
|
|
476
|
+
|
|
477
|
+
# Move to user directory
|
|
478
|
+
final_path = file_manager.move_to_user_directory(
|
|
479
|
+
str(temp_path), str(user_id)
|
|
480
|
+
)
|
|
481
|
+
file_size = file_manager.get_file_size(final_path)
|
|
482
|
+
|
|
483
|
+
uploaded = UploadedFile(
|
|
484
|
+
filename=upload_file.filename,
|
|
485
|
+
file_path=final_path,
|
|
486
|
+
size=file_size,
|
|
487
|
+
)
|
|
488
|
+
self.uploaded_files = [*self.uploaded_files, uploaded]
|
|
489
|
+
logger.info("Uploaded file: %s", upload_file.filename)
|
|
490
|
+
except Exception as e:
|
|
491
|
+
logger.error("Failed to upload file %s: %s", upload_file.filename, e)
|
|
492
|
+
|
|
493
|
+
@rx.event
|
|
494
|
+
def remove_file_from_prompt(self, file_path: str) -> None:
|
|
495
|
+
"""Remove an uploaded file from the prompt."""
|
|
496
|
+
# Delete the file from disk
|
|
497
|
+
file_manager.cleanup_uploaded_files([file_path])
|
|
498
|
+
# Remove from state
|
|
499
|
+
self.uploaded_files = [
|
|
500
|
+
f for f in self.uploaded_files if f.file_path != file_path
|
|
501
|
+
]
|
|
502
|
+
logger.debug("Removed uploaded file: %s", file_path)
|
|
503
|
+
|
|
504
|
+
def _clear_uploaded_files(self) -> None:
|
|
505
|
+
"""Clear all uploaded files from state and disk."""
|
|
506
|
+
if not self.uploaded_files:
|
|
507
|
+
return
|
|
508
|
+
count = len(self.uploaded_files)
|
|
509
|
+
file_paths = [f.file_path for f in self.uploaded_files]
|
|
510
|
+
file_manager.cleanup_uploaded_files(file_paths)
|
|
511
|
+
self.uploaded_files = []
|
|
512
|
+
logger.debug("Cleared %d uploaded files", count)
|
|
435
513
|
|
|
436
514
|
# -------------------------------------------------------------------------
|
|
437
515
|
# Message processing
|
|
438
516
|
# -------------------------------------------------------------------------
|
|
439
517
|
|
|
518
|
+
@rx.event
|
|
519
|
+
def set_editing_mode(self, message_id: str, content: str) -> None:
|
|
520
|
+
"""Enable editing mode for a message."""
|
|
521
|
+
self.editing_message_id = message_id
|
|
522
|
+
self.edited_message_content = content
|
|
523
|
+
|
|
524
|
+
@rx.event
|
|
525
|
+
def set_edited_message_content(self, content: str) -> None:
|
|
526
|
+
"""Set the content of the message currently being edited."""
|
|
527
|
+
self.edited_message_content = content
|
|
528
|
+
|
|
529
|
+
@rx.event
|
|
530
|
+
def cancel_edit(self) -> None:
|
|
531
|
+
"""Cancel editing mode."""
|
|
532
|
+
self.editing_message_id = None
|
|
533
|
+
self.edited_message_content = ""
|
|
534
|
+
|
|
535
|
+
@rx.event(background=True)
|
|
536
|
+
async def submit_edited_message(self) -> AsyncGenerator[Any, Any]:
|
|
537
|
+
"""Submit edited message."""
|
|
538
|
+
async with self:
|
|
539
|
+
content = self.edited_message_content.strip()
|
|
540
|
+
if len(content) < 1:
|
|
541
|
+
yield rx.toast.error(
|
|
542
|
+
"Nachricht darf nicht leer sein", position="top-right"
|
|
543
|
+
)
|
|
544
|
+
return
|
|
545
|
+
|
|
546
|
+
# Find message index
|
|
547
|
+
msg_index = -1
|
|
548
|
+
for i, m in enumerate(self.messages):
|
|
549
|
+
if m.id == self.editing_message_id:
|
|
550
|
+
msg_index = i
|
|
551
|
+
break
|
|
552
|
+
|
|
553
|
+
if msg_index == -1:
|
|
554
|
+
self.cancel_edit()
|
|
555
|
+
return
|
|
556
|
+
|
|
557
|
+
target_message = self.messages[msg_index]
|
|
558
|
+
|
|
559
|
+
# Update message
|
|
560
|
+
target_message.original_text = (
|
|
561
|
+
target_message.original_text or target_message.text
|
|
562
|
+
)
|
|
563
|
+
target_message.text = content
|
|
564
|
+
|
|
565
|
+
# Remove all messages AFTER this one
|
|
566
|
+
self.messages = self.messages[: msg_index + 1]
|
|
567
|
+
|
|
568
|
+
# Set prompt to bypass empty check in _begin_message_processing
|
|
569
|
+
self.prompt = content
|
|
570
|
+
self._skip_user_message = True
|
|
571
|
+
|
|
572
|
+
# Clear edit state
|
|
573
|
+
self.editing_message_id = None
|
|
574
|
+
self.edited_message_content = ""
|
|
575
|
+
|
|
576
|
+
# Trigger processing
|
|
577
|
+
await self._process_message()
|
|
578
|
+
|
|
440
579
|
@rx.event(background=True)
|
|
441
580
|
async def submit_message(self) -> AsyncGenerator[Any, Any]:
|
|
442
581
|
"""Submit a message and process the response."""
|
|
@@ -451,6 +590,76 @@ class ThreadState(rx.State):
|
|
|
451
590
|
}
|
|
452
591
|
""")
|
|
453
592
|
|
|
593
|
+
@rx.event(background=True)
|
|
594
|
+
async def delete_message(self, message_id: str) -> None:
|
|
595
|
+
"""Delete a message from the conversation."""
|
|
596
|
+
async with self:
|
|
597
|
+
self.messages = [m for m in self.messages if m.id != message_id]
|
|
598
|
+
self._thread.messages = self.messages
|
|
599
|
+
|
|
600
|
+
if self._thread.state != ThreadStatus.NEW:
|
|
601
|
+
await self._thread_service.save_thread(
|
|
602
|
+
self._thread, self.current_user_id
|
|
603
|
+
)
|
|
604
|
+
|
|
605
|
+
@rx.event
|
|
606
|
+
def copy_message(self, text: str) -> list[Any]:
|
|
607
|
+
"""Copy message text to clipboard."""
|
|
608
|
+
return [
|
|
609
|
+
rx.set_clipboard(text),
|
|
610
|
+
rx.toast.success("Nachricht kopiert"),
|
|
611
|
+
]
|
|
612
|
+
|
|
613
|
+
@rx.event
|
|
614
|
+
def download_message(self, text: str, message_id: str) -> Any:
|
|
615
|
+
"""Download message as markdown file."""
|
|
616
|
+
timestamp = datetime.now(UTC).strftime("%Y%m%d_%H%M%S")
|
|
617
|
+
filename = (
|
|
618
|
+
f"message_{message_id}_{timestamp}.md"
|
|
619
|
+
if message_id
|
|
620
|
+
else f"message_{timestamp}.md"
|
|
621
|
+
)
|
|
622
|
+
|
|
623
|
+
# Use JavaScript to trigger download
|
|
624
|
+
return rx.call_script(f"""
|
|
625
|
+
const blob = new Blob([{json.dumps(text)}], {{type: 'text/markdown'}});
|
|
626
|
+
const url = URL.createObjectURL(blob);
|
|
627
|
+
const a = document.createElement('a');
|
|
628
|
+
a.href = url;
|
|
629
|
+
a.download = '{filename}';
|
|
630
|
+
document.body.appendChild(a);
|
|
631
|
+
a.click();
|
|
632
|
+
document.body.removeChild(a);
|
|
633
|
+
URL.revokeObjectURL(url);
|
|
634
|
+
""")
|
|
635
|
+
|
|
636
|
+
@rx.event(background=True)
|
|
637
|
+
async def retry_message(self, message_id: str) -> None:
|
|
638
|
+
"""Retry generating a message."""
|
|
639
|
+
async with self:
|
|
640
|
+
# Find message index
|
|
641
|
+
index = -1
|
|
642
|
+
for i, msg in enumerate(self.messages):
|
|
643
|
+
if msg.id == message_id:
|
|
644
|
+
index = i
|
|
645
|
+
break
|
|
646
|
+
|
|
647
|
+
if index == -1:
|
|
648
|
+
return
|
|
649
|
+
|
|
650
|
+
# Keep context up to this message
|
|
651
|
+
# effectively removing this message and everything after
|
|
652
|
+
self.messages = self.messages[:index]
|
|
653
|
+
|
|
654
|
+
# Set prompt to bypass check (content checks)
|
|
655
|
+
self.prompt = "Regenerate"
|
|
656
|
+
|
|
657
|
+
# Flag to skip adding a new user message
|
|
658
|
+
self._skip_user_message = True
|
|
659
|
+
|
|
660
|
+
# Trigger processing directly
|
|
661
|
+
await self._process_message()
|
|
662
|
+
|
|
454
663
|
async def _process_message(self) -> None:
|
|
455
664
|
"""Process the current message and stream the response."""
|
|
456
665
|
logger.debug("Processing message: %s", self.prompt)
|
|
@@ -458,7 +667,7 @@ class ThreadState(rx.State):
|
|
|
458
667
|
start = await self._begin_message_processing()
|
|
459
668
|
if not start:
|
|
460
669
|
return
|
|
461
|
-
current_prompt, selected_model, mcp_servers, is_new_thread = start
|
|
670
|
+
current_prompt, selected_model, mcp_servers, file_paths, is_new_thread = start
|
|
462
671
|
|
|
463
672
|
processor = ModelManager().get_processor_for_model(selected_model)
|
|
464
673
|
if not processor:
|
|
@@ -475,11 +684,16 @@ class ThreadState(rx.State):
|
|
|
475
684
|
accumulator = ResponseAccumulator()
|
|
476
685
|
accumulator.attach_messages_ref(self.messages)
|
|
477
686
|
|
|
687
|
+
# Clear uploaded files from UI and mark for cleanup after processing
|
|
688
|
+
self.uploaded_files = []
|
|
689
|
+
self._pending_file_cleanup = file_paths
|
|
690
|
+
|
|
478
691
|
first_response_received = False
|
|
479
692
|
try:
|
|
480
693
|
async for chunk in processor.process(
|
|
481
694
|
self.messages,
|
|
482
695
|
selected_model,
|
|
696
|
+
files=file_paths or None,
|
|
483
697
|
mcp_servers=mcp_servers,
|
|
484
698
|
user_id=user_id,
|
|
485
699
|
):
|
|
@@ -506,7 +720,7 @@ class ThreadState(rx.State):
|
|
|
506
720
|
|
|
507
721
|
async def _begin_message_processing(
|
|
508
722
|
self,
|
|
509
|
-
) -> tuple[str, str, list[MCPServer], bool] | None:
|
|
723
|
+
) -> tuple[str, str, list[MCPServer], list[str], bool] | None:
|
|
510
724
|
"""Prepare state for sending a message. Returns None if no-op."""
|
|
511
725
|
async with self:
|
|
512
726
|
current_prompt = self.prompt.strip()
|
|
@@ -523,12 +737,21 @@ class ThreadState(rx.State):
|
|
|
523
737
|
|
|
524
738
|
is_new_thread = self._thread.state == ThreadStatus.NEW
|
|
525
739
|
|
|
740
|
+
# Capture file paths before clearing
|
|
741
|
+
file_paths = [f.file_path for f in self.uploaded_files]
|
|
742
|
+
# Capture filenames for message display
|
|
743
|
+
attachment_names = [f.filename for f in self.uploaded_files]
|
|
744
|
+
|
|
526
745
|
# Add user message unless skipped (e.g., OAuth resend)
|
|
527
746
|
if self._skip_user_message:
|
|
528
747
|
self._skip_user_message = False
|
|
529
748
|
else:
|
|
530
749
|
self.messages.append(
|
|
531
|
-
Message(
|
|
750
|
+
Message(
|
|
751
|
+
text=current_prompt,
|
|
752
|
+
type=MessageType.HUMAN,
|
|
753
|
+
attachments=attachment_names,
|
|
754
|
+
)
|
|
532
755
|
)
|
|
533
756
|
# Always add assistant placeholder
|
|
534
757
|
self.messages.append(Message(text="", type=MessageType.ASSISTANT))
|
|
@@ -540,7 +763,13 @@ class ThreadState(rx.State):
|
|
|
540
763
|
return None
|
|
541
764
|
|
|
542
765
|
mcp_servers = self.selected_mcp_servers
|
|
543
|
-
return
|
|
766
|
+
return (
|
|
767
|
+
current_prompt,
|
|
768
|
+
selected_model,
|
|
769
|
+
mcp_servers,
|
|
770
|
+
file_paths,
|
|
771
|
+
is_new_thread,
|
|
772
|
+
)
|
|
544
773
|
|
|
545
774
|
async def _stop_processing_with_error(self, error_msg: str) -> None:
|
|
546
775
|
"""Stop processing and show an error message."""
|
|
@@ -650,6 +879,11 @@ class ThreadState(rx.State):
|
|
|
650
879
|
self.processing = False
|
|
651
880
|
self.current_activity = ""
|
|
652
881
|
|
|
882
|
+
# Clean up uploaded files from disk
|
|
883
|
+
if self._pending_file_cleanup:
|
|
884
|
+
file_manager.cleanup_uploaded_files(self._pending_file_cleanup)
|
|
885
|
+
self._pending_file_cleanup = []
|
|
886
|
+
|
|
653
887
|
def _handle_auth_required_from_accumulator(
|
|
654
888
|
self, accumulator: ResponseAccumulator
|
|
655
889
|
) -> None:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: appkit-assistant
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.17.1
|
|
4
4
|
Summary: Add your description here
|
|
5
5
|
Project-URL: Homepage, https://github.com/jenreh/appkit
|
|
6
6
|
Project-URL: Documentation, https://github.com/jenreh/appkit/tree/main/docs
|
|
@@ -16,9 +16,12 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
16
16
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
17
|
Classifier: Topic :: Software Development :: User Interfaces
|
|
18
18
|
Requires-Python: >=3.13
|
|
19
|
+
Requires-Dist: anthropic>=0.40.0
|
|
19
20
|
Requires-Dist: appkit-commons
|
|
20
21
|
Requires-Dist: appkit-mantine
|
|
21
22
|
Requires-Dist: appkit-ui
|
|
23
|
+
Requires-Dist: google-genai>=1.52.0
|
|
24
|
+
Requires-Dist: mcp>=1.0.0
|
|
22
25
|
Requires-Dist: openai>=2.3.0
|
|
23
26
|
Requires-Dist: reflex>=0.8.22
|
|
24
27
|
Description-Content-Type: text/markdown
|
|
@@ -1,34 +1,39 @@
|
|
|
1
|
-
appkit_assistant/configuration.py,sha256=
|
|
1
|
+
appkit_assistant/configuration.py,sha256=Wpo3EuGWQrV0WIQnAhkj19PzgGkJoAde5ky-MA7kJwg,429
|
|
2
2
|
appkit_assistant/pages.py,sha256=gDvBweUO2WjrhP1RE5AAkjL1_S-givWr3CkkGZKws_E,471
|
|
3
|
+
appkit_assistant/backend/file_manager.py,sha256=54SYphu6FsxbEYuMx8ohQiSAeY2gGDV1q3S6RZuNku0,3153
|
|
3
4
|
appkit_assistant/backend/mcp_auth_service.py,sha256=lYQEe4yOZ48ear6dvcuOXsaOc6RClIBMsOOkV7SG5Aw,27768
|
|
4
5
|
appkit_assistant/backend/model_manager.py,sha256=fmv3yP63LxDnne4vjT7IzETTI2aSxViC2FSUfHQajlk,4382
|
|
5
|
-
appkit_assistant/backend/models.py,sha256=
|
|
6
|
+
appkit_assistant/backend/models.py,sha256=GCFWUUPsVspcFEv9naQ8n2bMU8FzMNrmqm3VgW1Fqfw,8346
|
|
6
7
|
appkit_assistant/backend/processor.py,sha256=LtkkC6v0idNtbuMm3Sw5J9zIjYqtNhtxYxjYefPSS9A,2135
|
|
7
8
|
appkit_assistant/backend/repositories.py,sha256=R-7kYdxg4RWQrTEOU4tbcOEhJA_FlesWrt65UpItRSU,5547
|
|
9
|
+
appkit_assistant/backend/response_accumulator.py,sha256=BCK-Ut_Wmo7rhEqOb7QlqXO8TrtANjL80FbX_AvMl1Q,10056
|
|
8
10
|
appkit_assistant/backend/system_prompt_cache.py,sha256=83OIyixeTb3HKOy3XIzPyTAE-G2JyqrfcG8xVeTS2Ls,5514
|
|
9
|
-
appkit_assistant/backend/processors/
|
|
10
|
-
appkit_assistant/backend/processors/
|
|
11
|
-
appkit_assistant/backend/processors/
|
|
12
|
-
appkit_assistant/backend/processors/
|
|
11
|
+
appkit_assistant/backend/processors/claude_base.py,sha256=j0DhBn8EVAjW_bfCghXaEHyORO1raUNdQeemVWCKJlA,5376
|
|
12
|
+
appkit_assistant/backend/processors/claude_responses_processor.py,sha256=_quuN5FRsPSpQjaNIceN-Z66Fb3RnhXtcsS4gE0NrPA,32980
|
|
13
|
+
appkit_assistant/backend/processors/gemini_base.py,sha256=ijCa8-_xdddD6ms_pkUjCj5kHZOoQ1wfw-7AhhXu6vo,2286
|
|
14
|
+
appkit_assistant/backend/processors/gemini_responses_processor.py,sha256=V5jZ83a3vi60aFTtRnbwP2q1PyEGw1iB6dYne-4CgI4,26484
|
|
15
|
+
appkit_assistant/backend/processors/lorem_ipsum_processor.py,sha256=WR4s1RyOi5xgWVpre04xoxoMLIAINkpdvRCkSfNuoMc,4699
|
|
16
|
+
appkit_assistant/backend/processors/openai_base.py,sha256=TBQCZW7RxaPMag_DX_tpLyMpZ_PZ_KiO8_sFN49OCpk,4424
|
|
17
|
+
appkit_assistant/backend/processors/openai_chat_completion_processor.py,sha256=XFp_V9Yp4KcTmicbCe3fl_3G2tP5Ffm-xLVqW50HyQw,4629
|
|
18
|
+
appkit_assistant/backend/processors/openai_responses_processor.py,sha256=hysK7mlsG2t8SfltQpCvKA6MxpeIomRMGX-tSMaUshc,29492
|
|
13
19
|
appkit_assistant/backend/processors/perplexity_processor.py,sha256=weHukv78MSCF_uSCKGSMpNYHsET9OB8IhpvUiMfPQ8A,3355
|
|
14
20
|
appkit_assistant/backend/services/thread_service.py,sha256=LpM8ZZHt1o4MYEKzH_XPURSi3qS6p3pAQA53tOE53MU,4663
|
|
15
|
-
appkit_assistant/components/__init__.py,sha256=
|
|
16
|
-
appkit_assistant/components/composer.py,sha256=
|
|
21
|
+
appkit_assistant/components/__init__.py,sha256=ptv0wShA4CHjgNpehlHqgoinCl-yyofjkV6rTTNIRHE,954
|
|
22
|
+
appkit_assistant/components/composer.py,sha256=jQNZd8Y0eQgbfC3d1AV1osRNnwfztEpXtrFp7aagXaY,7190
|
|
17
23
|
appkit_assistant/components/composer_key_handler.py,sha256=KyZYyhxzFR8DH_7F_DrvTFNT6v5kG6JihlGTmCv2wv0,1028
|
|
18
24
|
appkit_assistant/components/mcp_oauth.py,sha256=puLwxAhmF25BjnZMdJbKIfC6bFXK2D8LybOX0kD7Ri4,1737
|
|
19
25
|
appkit_assistant/components/mcp_server_dialogs.py,sha256=afIImmhfrNyLmxDZBpCxHxvD8HKpDanIloLEC8dJgro,23444
|
|
20
26
|
appkit_assistant/components/mcp_server_table.py,sha256=1dziN7hDDvE8Y3XcdIs0wUPv1H64kP9gRAEjgH9Yvzo,2323
|
|
21
|
-
appkit_assistant/components/message.py,sha256=
|
|
27
|
+
appkit_assistant/components/message.py,sha256=SJcwWfSw5XxiSHtKirJUun9jkx3-ATpZ0AHLv82KwXc,19824
|
|
22
28
|
appkit_assistant/components/system_prompt_editor.py,sha256=REl33zFmcpYRe9kxvFrBRYg40dV4L4FtVC_3ibLsmrU,2940
|
|
23
|
-
appkit_assistant/components/thread.py,sha256
|
|
29
|
+
appkit_assistant/components/thread.py,sha256=-KK1vcEmITR_oDGLbQhIa2WxRCVxEqel12m4haS7y9w,8461
|
|
24
30
|
appkit_assistant/components/threadlist.py,sha256=1xVakSTQYi5-wgED3fTJVggeIjL_fkthehce0wKUYtM,4896
|
|
25
31
|
appkit_assistant/components/tools_modal.py,sha256=12iiAVahy3j4JwjGfRlegVEa4ePhGsEu7Bq92JLn1ZI,3353
|
|
26
|
-
appkit_assistant/logic/response_accumulator.py,sha256=85NKtIxpWVsI4rDkNAy_U34uavY8NoUEp9n2kO0ief4,8060
|
|
27
32
|
appkit_assistant/state/mcp_oauth_state.py,sha256=6MofExrbOOEl_YUcUOqcSTN3h7KAaERI5IdVfXdVUVs,7669
|
|
28
33
|
appkit_assistant/state/mcp_server_state.py,sha256=3AFvy53xx_eLTxw-LfJklPTgq4Ohqu4xs1QlLs-kU4U,11387
|
|
29
34
|
appkit_assistant/state/system_prompt_state.py,sha256=zdnYrTnl7EszALRiodu6pcuQUd2tmtPG1eJ10j_OotI,7705
|
|
30
35
|
appkit_assistant/state/thread_list_state.py,sha256=DEOR5Nklj1qfYaxSRMXCZdZRv2iq2Jb37JSg739_wL4,10250
|
|
31
|
-
appkit_assistant/state/thread_state.py,sha256=
|
|
32
|
-
appkit_assistant-0.
|
|
33
|
-
appkit_assistant-0.
|
|
34
|
-
appkit_assistant-0.
|
|
36
|
+
appkit_assistant/state/thread_state.py,sha256=Hz7vRsBJ2cTV_xENuMoZBVSo2FGbR4uovdwiXF1zixk,39292
|
|
37
|
+
appkit_assistant-0.17.1.dist-info/METADATA,sha256=t0hdCrMbCpvbETpblS3bmLtJ0ltfMXhGI9MTOtnrzII,9498
|
|
38
|
+
appkit_assistant-0.17.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
39
|
+
appkit_assistant-0.17.1.dist-info/RECORD,,
|
|
File without changes
|