dtSpark 1.0.11__py3-none-any.whl → 1.1.0a1__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.
dtSpark/_version.txt CHANGED
@@ -1 +1 @@
1
- 1.0.11
1
+ 1.1.0a1
@@ -779,6 +779,27 @@ class AWSBedrockCLI(AbstractApp):
779
779
  'enabled': self.settings.get('embedded_tools.filesystem.enabled', False),
780
780
  'allowed_path': self.settings.get('embedded_tools.filesystem.allowed_path', './'),
781
781
  'access_mode': self.settings.get('embedded_tools.filesystem.access_mode', 'read')
782
+ },
783
+ 'documents': {
784
+ 'enabled': self.settings.get('embedded_tools.documents.enabled', False),
785
+ 'allowed_path': self.settings.get('embedded_tools.documents.allowed_path', './'),
786
+ 'access_mode': self.settings.get('embedded_tools.documents.access_mode', 'read'),
787
+ 'max_file_size_mb': self.settings.get('embedded_tools.documents.max_file_size_mb', 50),
788
+ 'reading': {
789
+ 'max_pdf_pages': self.settings.get('embedded_tools.documents.reading.max_pdf_pages', 100),
790
+ 'max_excel_rows': self.settings.get('embedded_tools.documents.reading.max_excel_rows', 10000)
791
+ },
792
+ 'creation': {
793
+ 'templates_path': self.settings.get('embedded_tools.documents.creation.templates_path'),
794
+ 'default_author': self.settings.get('embedded_tools.documents.creation.default_author')
795
+ }
796
+ },
797
+ 'archives': {
798
+ 'enabled': self.settings.get('embedded_tools.archives.enabled', False),
799
+ 'allowed_path': self.settings.get('embedded_tools.archives.allowed_path', './'),
800
+ 'access_mode': self.settings.get('embedded_tools.archives.access_mode', 'read'),
801
+ 'max_file_size_mb': self.settings.get('embedded_tools.archives.max_file_size_mb', 100),
802
+ 'max_files_to_list': self.settings.get('embedded_tools.archives.max_files_to_list', 1000)
782
803
  }
783
804
  }
784
805
  }
@@ -252,9 +252,19 @@ async def command_info(
252
252
  "tokens_sent": conv.get('tokens_sent', 0),
253
253
  "tokens_received": conv.get('tokens_received', 0),
254
254
  "total_tokens": conv.get('tokens_sent', 0) + conv.get('tokens_received', 0),
255
+ "instructions": conv.get('instructions', ''),
255
256
  },
256
257
  "model_usage": model_usage,
257
258
  "files": [f['filename'] for f in files],
259
+ "attached_files": [
260
+ {
261
+ "id": f['id'],
262
+ "filename": f['filename'],
263
+ "size_bytes": f.get('size_bytes', 0),
264
+ "mime_type": f.get('mime_type', 'application/octet-stream'),
265
+ }
266
+ for f in files
267
+ ],
258
268
  "mcp_servers": mcp_servers,
259
269
  "rollup_settings": rollup_info,
260
270
  },
@@ -570,6 +580,143 @@ async def toggle_mcp_server(
570
580
  raise HTTPException(status_code=500, detail=str(e))
571
581
 
572
582
 
583
+ @router.post("/chat/{conversation_id}/command/instructions")
584
+ async def update_instructions(
585
+ request: Request,
586
+ conversation_id: int,
587
+ instructions: str = Form(""),
588
+ session_id: str = Depends(get_current_session),
589
+ ):
590
+ """
591
+ Update conversation instructions/system prompt.
592
+
593
+ Args:
594
+ request: FastAPI request
595
+ conversation_id: ID of the conversation
596
+ instructions: New instructions text (empty to clear)
597
+ session_id: Current session ID
598
+
599
+ Returns:
600
+ CommandResponse with status
601
+ """
602
+ try:
603
+ app_instance = request.app.state.app_instance
604
+
605
+ # Check if conversation is predefined
606
+ if app_instance.database.is_conversation_predefined(conversation_id):
607
+ return CommandResponse(
608
+ command="instructions",
609
+ status="error",
610
+ message="Cannot modify instructions for predefined conversations",
611
+ data=None,
612
+ )
613
+
614
+ # Set conversation context if needed
615
+ if app_instance.conversation_manager.current_conversation_id != conversation_id:
616
+ app_instance.conversation_manager.load_conversation(conversation_id)
617
+
618
+ # Update instructions (None to clear, or the text)
619
+ new_instructions = instructions.strip() if instructions.strip() else None
620
+ success = app_instance.conversation_manager.update_instructions(new_instructions)
621
+
622
+ if success:
623
+ return CommandResponse(
624
+ command="instructions",
625
+ status="success",
626
+ message="Instructions updated successfully",
627
+ data={"instructions": new_instructions},
628
+ )
629
+ else:
630
+ return CommandResponse(
631
+ command="instructions",
632
+ status="error",
633
+ message="Failed to update instructions",
634
+ data=None,
635
+ )
636
+
637
+ except Exception as e:
638
+ logger.error(f"Error updating instructions for conversation {conversation_id}: {e}")
639
+ raise HTTPException(status_code=500, detail=str(e))
640
+
641
+
642
+ @router.post("/chat/{conversation_id}/command/deletefiles")
643
+ async def delete_files(
644
+ request: Request,
645
+ conversation_id: int,
646
+ session_id: str = Depends(get_current_session),
647
+ ):
648
+ """
649
+ Delete attached files from a conversation.
650
+
651
+ Args:
652
+ request: FastAPI request
653
+ conversation_id: ID of the conversation
654
+ session_id: Current session ID
655
+
656
+ Returns:
657
+ CommandResponse with deletion status
658
+ """
659
+ try:
660
+ app_instance = request.app.state.app_instance
661
+
662
+ # Check if conversation is predefined
663
+ if app_instance.database.is_conversation_predefined(conversation_id):
664
+ return CommandResponse(
665
+ command="deletefiles",
666
+ status="error",
667
+ message="Cannot delete files from predefined conversations",
668
+ data=None,
669
+ )
670
+
671
+ # Parse JSON body for file_ids
672
+ body = await request.json()
673
+ file_ids = body.get('file_ids', [])
674
+
675
+ if not file_ids:
676
+ return CommandResponse(
677
+ command="deletefiles",
678
+ status="error",
679
+ message="No file IDs provided",
680
+ data=None,
681
+ )
682
+
683
+ # Delete each file
684
+ deleted_count = 0
685
+ failed_ids = []
686
+
687
+ for file_id in file_ids:
688
+ try:
689
+ if app_instance.database.delete_file(file_id):
690
+ deleted_count += 1
691
+ else:
692
+ failed_ids.append(file_id)
693
+ except Exception as e:
694
+ logger.warning(f"Failed to delete file {file_id}: {e}")
695
+ failed_ids.append(file_id)
696
+
697
+ if deleted_count > 0:
698
+ return CommandResponse(
699
+ command="deletefiles",
700
+ status="success",
701
+ message=f"Deleted {deleted_count} file(s)",
702
+ data={
703
+ "deleted_count": deleted_count,
704
+ "failed_ids": failed_ids,
705
+ },
706
+ )
707
+ else:
708
+ return CommandResponse(
709
+ command="deletefiles",
710
+ status="error",
711
+ message="Failed to delete files",
712
+ data={"failed_ids": failed_ids},
713
+ )
714
+
715
+ except Exception as e:
716
+ logger.error(f"Error deleting files for conversation {conversation_id}: {e}")
717
+ raise HTTPException(status_code=500, detail=str(e))
718
+
719
+
573
720
  @router.post("/chat/permission/respond")
574
721
  async def respond_to_permission_request(
575
722
  request: Request,
@@ -114,12 +114,28 @@ document.getElementById('infoModal').addEventListener('show.bs.modal', function(
114
114
  <button class="list-group-item list-group-item-action" onclick="executeCommand('export')">
115
115
  <i class="bi bi-download"></i> Export Conversation
116
116
  </button>
117
+ <button class="list-group-item list-group-item-action" onclick="executeCommand('attach')">
118
+ <i class="bi bi-paperclip"></i> Attach Files
119
+ </button>
120
+ <button class="list-group-item list-group-item-action" onclick="executeCommand('instructions')">
121
+ <i class="bi bi-card-text"></i> Change Instructions
122
+ </button>
123
+ <button class="list-group-item list-group-item-action" onclick="executeCommand('copy')">
124
+ <i class="bi bi-clipboard"></i> Copy Last Response
125
+ </button>
117
126
  <button class="list-group-item list-group-item-action" onclick="executeCommand('mcpaudit')">
118
127
  <i class="bi bi-shield-check"></i> MCP Audit Log
119
128
  </button>
120
129
  <button class="list-group-item list-group-item-action" onclick="executeCommand('mcpservers')">
121
130
  <i class="bi bi-hdd-network"></i> MCP Server Management
122
131
  </button>
132
+ <hr class="my-2">
133
+ <button class="list-group-item list-group-item-action" onclick="executeCommand('deletefiles')">
134
+ <i class="bi bi-file-earmark-x text-warning"></i> Delete Attached Files
135
+ </button>
136
+ <button class="list-group-item list-group-item-action text-danger" onclick="executeCommand('delete')">
137
+ <i class="bi bi-trash"></i> Delete Conversation
138
+ </button>
123
139
  </div>
124
140
  </div>
125
141
  </div>
@@ -197,6 +213,21 @@ async function executeCommand(command) {
197
213
  case 'changemodel':
198
214
  await showChangeModelModal();
199
215
  break;
216
+ case 'attach':
217
+ await showAttachFilesModal();
218
+ break;
219
+ case 'instructions':
220
+ await showInstructionsModal();
221
+ break;
222
+ case 'copy':
223
+ await copyLastResponse();
224
+ break;
225
+ case 'deletefiles':
226
+ await showDeleteFilesModal();
227
+ break;
228
+ case 'delete':
229
+ await confirmDeleteConversation();
230
+ break;
200
231
  case 'mcpaudit':
201
232
  await showMCPAuditModal();
202
233
  break;
@@ -810,5 +841,274 @@ async function performAttachFiles() {
810
841
  function attachFiles() {
811
842
  showAttachFilesModal();
812
843
  }
844
+
845
+ // Show instructions modal
846
+ async function showInstructionsModal() {
847
+ try {
848
+ // Load current instructions
849
+ const response = await fetch(`/api/chat/${conversationId}/command/info`, {
850
+ method: 'POST'
851
+ });
852
+ const data = await response.json();
853
+ const currentInstructions = data.data.conversation.instructions || '';
854
+
855
+ const modalHTML = `
856
+ <div class="modal fade" id="instructionsModal" tabindex="-1">
857
+ <div class="modal-dialog modal-lg">
858
+ <div class="modal-content">
859
+ <div class="modal-header">
860
+ <h5 class="modal-title"><i class="bi bi-card-text"></i> Change Instructions</h5>
861
+ <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
862
+ </div>
863
+ <div class="modal-body">
864
+ <div class="mb-3">
865
+ <label for="instructions-text" class="form-label">System Instructions / Prompt</label>
866
+ <textarea class="form-control" id="instructions-text" rows="10"
867
+ placeholder="Enter system instructions for this conversation...">${escapeHtml(currentInstructions)}</textarea>
868
+ <div class="form-text">These instructions are sent as a system prompt with each message.</div>
869
+ </div>
870
+ </div>
871
+ <div class="modal-footer">
872
+ <button type="button" class="btn btn-outline-warning" onclick="clearInstructions()">
873
+ <i class="bi bi-eraser"></i> Clear
874
+ </button>
875
+ <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
876
+ <button type="button" class="btn btn-primary" onclick="saveInstructions()">
877
+ <i class="bi bi-check-lg"></i> Save
878
+ </button>
879
+ </div>
880
+ </div>
881
+ </div>
882
+ </div>
883
+ `;
884
+
885
+ // Remove old modal if exists
886
+ const oldModal = document.getElementById('instructionsModal');
887
+ if (oldModal) oldModal.remove();
888
+
889
+ document.body.insertAdjacentHTML('beforeend', modalHTML);
890
+ const modal = new bootstrap.Modal(document.getElementById('instructionsModal'));
891
+ modal.show();
892
+ } catch (error) {
893
+ showToast('Failed to load instructions', 'error');
894
+ }
895
+ }
896
+
897
+ async function saveInstructions() {
898
+ const instructions = document.getElementById('instructions-text').value;
899
+
900
+ try {
901
+ const formData = new FormData();
902
+ formData.append('instructions', instructions);
903
+
904
+ const response = await fetch(`/api/chat/${conversationId}/command/instructions`, {
905
+ method: 'POST',
906
+ body: formData
907
+ });
908
+
909
+ const data = await response.json();
910
+
911
+ if (data.status === 'success') {
912
+ bootstrap.Modal.getInstance(document.getElementById('instructionsModal')).hide();
913
+ showToast('Instructions updated successfully', 'success');
914
+ } else {
915
+ showToast(data.message || 'Failed to update instructions', 'error');
916
+ }
917
+ } catch (error) {
918
+ showToast('Failed to update instructions', 'error');
919
+ }
920
+ }
921
+
922
+ async function clearInstructions() {
923
+ if (!confirm('Are you sure you want to clear the instructions?')) return;
924
+
925
+ try {
926
+ const formData = new FormData();
927
+ formData.append('instructions', '');
928
+
929
+ const response = await fetch(`/api/chat/${conversationId}/command/instructions`, {
930
+ method: 'POST',
931
+ body: formData
932
+ });
933
+
934
+ const data = await response.json();
935
+
936
+ if (data.status === 'success') {
937
+ document.getElementById('instructions-text').value = '';
938
+ showToast('Instructions cleared', 'success');
939
+ } else {
940
+ showToast(data.message || 'Failed to clear instructions', 'error');
941
+ }
942
+ } catch (error) {
943
+ showToast('Failed to clear instructions', 'error');
944
+ }
945
+ }
946
+
947
+ // Copy last response to clipboard
948
+ async function copyLastResponse() {
949
+ // Find the last assistant message in the chat
950
+ const chatContainer = document.getElementById('chat-container');
951
+ const assistantMessages = chatContainer.querySelectorAll('.assistant-message');
952
+
953
+ if (assistantMessages.length === 0) {
954
+ showToast('No assistant response to copy', 'warning');
955
+ return;
956
+ }
957
+
958
+ const lastMessage = assistantMessages[assistantMessages.length - 1];
959
+ const messageContent = lastMessage.querySelector('.message-content');
960
+
961
+ if (!messageContent) {
962
+ showToast('No content to copy', 'warning');
963
+ return;
964
+ }
965
+
966
+ try {
967
+ // Get the text content, preserving some formatting
968
+ const text = messageContent.innerText || messageContent.textContent;
969
+ await navigator.clipboard.writeText(text);
970
+ showToast('Response copied to clipboard', 'success');
971
+ } catch (error) {
972
+ // Fallback for older browsers
973
+ const textarea = document.createElement('textarea');
974
+ textarea.value = messageContent.innerText || messageContent.textContent;
975
+ document.body.appendChild(textarea);
976
+ textarea.select();
977
+ document.execCommand('copy');
978
+ document.body.removeChild(textarea);
979
+ showToast('Response copied to clipboard', 'success');
980
+ }
981
+ }
982
+
983
+ // Show delete files modal
984
+ async function showDeleteFilesModal() {
985
+ try {
986
+ // Load attached files
987
+ const response = await fetch(`/api/chat/${conversationId}/command/info`, {
988
+ method: 'POST'
989
+ });
990
+ const data = await response.json();
991
+ const files = data.data.attached_files || [];
992
+
993
+ if (files.length === 0) {
994
+ showToast('No files attached to this conversation', 'info');
995
+ return;
996
+ }
997
+
998
+ let filesHTML = '';
999
+ files.forEach(file => {
1000
+ filesHTML += `
1001
+ <div class="form-check">
1002
+ <input class="form-check-input file-delete-checkbox" type="checkbox" value="${file.id}" id="file-${file.id}">
1003
+ <label class="form-check-label" for="file-${file.id}">
1004
+ <i class="bi bi-file-earmark"></i> ${escapeHtml(file.filename)}
1005
+ <span class="text-muted small">(${(file.size_bytes / 1024).toFixed(2)} KB)</span>
1006
+ </label>
1007
+ </div>
1008
+ `;
1009
+ });
1010
+
1011
+ const modalHTML = `
1012
+ <div class="modal fade" id="deleteFilesModal" tabindex="-1">
1013
+ <div class="modal-dialog">
1014
+ <div class="modal-content">
1015
+ <div class="modal-header">
1016
+ <h5 class="modal-title"><i class="bi bi-file-earmark-x text-warning"></i> Delete Attached Files</h5>
1017
+ <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
1018
+ </div>
1019
+ <div class="modal-body">
1020
+ <p>Select files to delete:</p>
1021
+ <div class="mb-3">
1022
+ <button class="btn btn-sm btn-outline-secondary me-2" onclick="toggleAllDeleteFiles(true)">Select All</button>
1023
+ <button class="btn btn-sm btn-outline-secondary" onclick="toggleAllDeleteFiles(false)">Deselect All</button>
1024
+ </div>
1025
+ <div id="delete-files-list">
1026
+ ${filesHTML}
1027
+ </div>
1028
+ </div>
1029
+ <div class="modal-footer">
1030
+ <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
1031
+ <button type="button" class="btn btn-danger" onclick="performDeleteFiles()">
1032
+ <i class="bi bi-trash"></i> Delete Selected
1033
+ </button>
1034
+ </div>
1035
+ </div>
1036
+ </div>
1037
+ </div>
1038
+ `;
1039
+
1040
+ // Remove old modal if exists
1041
+ const oldModal = document.getElementById('deleteFilesModal');
1042
+ if (oldModal) oldModal.remove();
1043
+
1044
+ document.body.insertAdjacentHTML('beforeend', modalHTML);
1045
+ const modal = new bootstrap.Modal(document.getElementById('deleteFilesModal'));
1046
+ modal.show();
1047
+ } catch (error) {
1048
+ showToast('Failed to load attached files', 'error');
1049
+ }
1050
+ }
1051
+
1052
+ function toggleAllDeleteFiles(checked) {
1053
+ document.querySelectorAll('.file-delete-checkbox').forEach(cb => cb.checked = checked);
1054
+ }
1055
+
1056
+ async function performDeleteFiles() {
1057
+ const checkboxes = document.querySelectorAll('.file-delete-checkbox:checked');
1058
+ const fileIds = Array.from(checkboxes).map(cb => cb.value);
1059
+
1060
+ if (fileIds.length === 0) {
1061
+ showToast('Please select at least one file to delete', 'warning');
1062
+ return;
1063
+ }
1064
+
1065
+ if (!confirm(`Are you sure you want to delete ${fileIds.length} file(s)?`)) return;
1066
+
1067
+ try {
1068
+ const response = await fetch(`/api/chat/${conversationId}/command/deletefiles`, {
1069
+ method: 'POST',
1070
+ headers: {
1071
+ 'Content-Type': 'application/json'
1072
+ },
1073
+ body: JSON.stringify({ file_ids: fileIds.map(id => parseInt(id)) })
1074
+ });
1075
+
1076
+ const data = await response.json();
1077
+
1078
+ if (data.status === 'success') {
1079
+ bootstrap.Modal.getInstance(document.getElementById('deleteFilesModal')).hide();
1080
+ showToast(`Deleted ${data.data.deleted_count} file(s)`, 'success');
1081
+ } else {
1082
+ showToast(data.message || 'Failed to delete files', 'error');
1083
+ }
1084
+ } catch (error) {
1085
+ showToast('Failed to delete files', 'error');
1086
+ }
1087
+ }
1088
+
1089
+ // Confirm and delete conversation
1090
+ async function confirmDeleteConversation() {
1091
+ if (!confirm('Are you sure you want to delete this conversation? This cannot be undone.')) return;
1092
+
1093
+ try {
1094
+ const response = await fetch(`/api/conversations/${conversationId}`, {
1095
+ method: 'DELETE'
1096
+ });
1097
+
1098
+ const data = await response.json();
1099
+
1100
+ if (data.status === 'success') {
1101
+ showToast('Conversation deleted', 'success');
1102
+ // Redirect to main menu after a short delay
1103
+ setTimeout(() => {
1104
+ window.location.href = '/';
1105
+ }, 1000);
1106
+ } else {
1107
+ showToast(data.message || 'Failed to delete conversation', 'error');
1108
+ }
1109
+ } catch (error) {
1110
+ showToast('Failed to delete conversation', 'error');
1111
+ }
1112
+ }
813
1113
  </script>
814
1114
  {% endblock %}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dtSpark
3
- Version: 1.0.11
3
+ Version: 1.1.0a1
4
4
  Summary: Secure Personal AI Research Kit - Multi-provider LLM CLI/Web interface with MCP tool integration
5
5
  Home-page: https://github.com/digital-thought/dtSpark
6
6
  Author: Matthew Westwood-Hill
@@ -4,7 +4,7 @@ dtSpark/_full_name.txt,sha256=wsMYXtT12WMrY9gT1JHiKdE4k7H59psECS6cSD07giQ,31
4
4
  dtSpark/_licence.txt,sha256=Mvt5wkOkst8VGlk48vwN3CgHwMHLfmplKSPOUEbTfOw,1071
5
5
  dtSpark/_metadata.yaml,sha256=h3PQd2QsY5yUBzS2b6EueTwkmd57svsbAKcwDVVEfIo,188
6
6
  dtSpark/_name.txt,sha256=kDZC5_a3iMKIPOUvtLXl0C9N5DiOfgUCsecwTUnkJhs,7
7
- dtSpark/_version.txt,sha256=OxBuL_h-WO1Fs2nUH18IShggUgRLibuf9Yral-IGYn8,7
7
+ dtSpark/_version.txt,sha256=hfp31eFAhdQ4qbzp72MNun0WOiS5Gps8p-hsIiWM7Ig,8
8
8
  dtSpark/cli_interface.py,sha256=aB-rFAh6o8GOwwecx-rSHEj3W4bmQHp51OPEBtC2CEw,96911
9
9
  dtSpark/conversation_manager.py,sha256=e1aTJpUjxV96G9xrssJl1ujPJMZZwtfufQ8ZDb1WyAI,132270
10
10
  dtSpark/launch.py,sha256=j8XYpmDswWUIzhpMc32E0Fhbhk_qhOQUAwJSpqh37f0,892
@@ -14,7 +14,7 @@ dtSpark/aws/bedrock.py,sha256=j1OknN76LehIMRmoqzx8G3DUSqk2IsO3Fiy5AxQp7Fw,24250
14
14
  dtSpark/aws/costs.py,sha256=eyjigH_Yef7g5cKqhR2QUx_7y4E6-NsLd9-WL52I2vM,11931
15
15
  dtSpark/aws/pricing.py,sha256=pk85e--C5Iz0Y-6iWv_VfENAnrcWQ_9XK0fJQSlk5Xk,23388
16
16
  dtSpark/core/__init__.py,sha256=kORX-9C7L91WxMTMUHXr3Yc09rb6oJNzEH5_KDRdgqM,477
17
- dtSpark/core/application.py,sha256=QMOqbJ-PUKrhKUBYKWM-LBUpG7uW6Cebs35000OLqGw,169755
17
+ dtSpark/core/application.py,sha256=tYAfP0QGuvRnqxT4gBcRqqIf0NPwkjIVRucBIYOK5SQ,171425
18
18
  dtSpark/core/context_compaction.py,sha256=FWN352EW8n-eWv0MzbOiWIiKcooRxeIAb7611eN-kdY,31898
19
19
  dtSpark/daemon/__init__.py,sha256=xdKEyMsNXgIv6nNerpDcwf94c80n-BFoJFaucWxVF64,3300
20
20
  dtSpark/daemon/__main__.py,sha256=sRNG4RJ-Ejvd-f7OAU5slPOtxVpCoC2OfazdTJro69Q,170
@@ -71,7 +71,7 @@ dtSpark/web/ssl_utils.py,sha256=keDhLzEbc9REUGSdMls0vxBV3yPunR490u4j6EvB8dg,6624
71
71
  dtSpark/web/web_interface.py,sha256=Jl50HxTatj6yzKFBvOxp51jlhNe3CqOqnBjT1uL8HEw,4713
72
72
  dtSpark/web/endpoints/__init__.py,sha256=uOTiOKx6IDZ2kc0-2GS2hqZD2qX6KtwAhMMZQbS7pWc,356
73
73
  dtSpark/web/endpoints/autonomous_actions.py,sha256=tHJtFvJJtpr34LujQu-udZvT4vY5TpJB3Sn0WPJ8giM,36588
74
- dtSpark/web/endpoints/chat.py,sha256=w4Vi3X2e7orID0Ny5xF7vyTHe9mk8gaH7o67GB50psc,20641
74
+ dtSpark/web/endpoints/chat.py,sha256=Xb8FOsmHvw2S3ju1wpET1XOAOR0P5pC1qGoYMhNG0xg,25560
75
75
  dtSpark/web/endpoints/conversations.py,sha256=uFNpd_9DF1jqTEKFd9qRWK-uffXyTwz4Px9JIur_128,11728
76
76
  dtSpark/web/endpoints/main_menu.py,sha256=54KYz86-jj9KXeBLbqEq-OOuxg2Cs4Hbnd_Z48MdB9M,20363
77
77
  dtSpark/web/endpoints/streaming.py,sha256=vhpLefhc1PUDlmZ3Lx4IXizZfHy45zPgv5POhb-TdFU,14581
@@ -82,15 +82,15 @@ dtSpark/web/static/js/main.js,sha256=A5m_VDyEzMcfCL9nnId2oCtFecvWRlpedzzPbt34QGY
82
82
  dtSpark/web/static/js/sse-client.js,sha256=-YyRXNzSoQWrNLDvT8xGXtbgll_1JiP8p398OtQU7H8,8438
83
83
  dtSpark/web/templates/actions.html,sha256=KHJ552XjwPCCOrz0WUkehRzNwuBkS7qVpsAoCx1lGZI,18852
84
84
  dtSpark/web/templates/base.html,sha256=ne7kY8mnT5GpGDcxokQhNsn6H4tVksBE9BsXcJAsdmI,3765
85
- dtSpark/web/templates/chat.html,sha256=OQiqmOV-Q71MxXt7M7yLcCGH0Jyhen4p3hLqU6829aw,32655
85
+ dtSpark/web/templates/chat.html,sha256=wMDna_73e9kulTR8OKzg-uSotkp9EXP4zIJh0bDe9o0,45073
86
86
  dtSpark/web/templates/conversations.html,sha256=URJX3W5-MjUjuUAXixziY1yFG-T6Ho5_u9Up7FcH70E,13004
87
87
  dtSpark/web/templates/goodbye.html,sha256=4VnUgq6gHCMeJuty51qq8SZuTtpEMMUOsgTBut37Mc8,2825
88
88
  dtSpark/web/templates/login.html,sha256=OkLf_uzMYhl_o9ER1RQZc8ch6-bCaiOokEhKbeEl8E8,3274
89
89
  dtSpark/web/templates/main_menu.html,sha256=_tK5QBLzSmJY_j2qHFHk0c1fz9YyRr3i4ZLIhTzNEUU,39246
90
90
  dtSpark/web/templates/new_conversation.html,sha256=hoiQ4Ew3lpFWHTsYza0JiBqqWJs7St7jTusKDnxRR8w,6844
91
- dtspark-1.0.11.dist-info/licenses/LICENSE,sha256=jIuWlmbirwQabTwxfzE7SXT1LpCG-y_GRQ3VnoRTKgo,1101
92
- dtspark-1.0.11.dist-info/METADATA,sha256=rzA9ESvbYVuSdEgfIHcaVH2CZ3cDK6wuysXvUsQWzH4,6261
93
- dtspark-1.0.11.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
94
- dtspark-1.0.11.dist-info/entry_points.txt,sha256=IpIwa_a6XY8Z2w7DtgYAhpFHHEbha-zhLkyttWd3zpw,76
95
- dtspark-1.0.11.dist-info/top_level.txt,sha256=x-6lMA6vNuxyDNJGNOKI4dyy7L0kOb9V98I5z46bJVY,8
96
- dtspark-1.0.11.dist-info/RECORD,,
91
+ dtspark-1.1.0a1.dist-info/licenses/LICENSE,sha256=jIuWlmbirwQabTwxfzE7SXT1LpCG-y_GRQ3VnoRTKgo,1101
92
+ dtspark-1.1.0a1.dist-info/METADATA,sha256=maCoXtYpyuo_aFSScJQ94rZWy-cMwVQMTnCciwA6efo,6262
93
+ dtspark-1.1.0a1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
94
+ dtspark-1.1.0a1.dist-info/entry_points.txt,sha256=IpIwa_a6XY8Z2w7DtgYAhpFHHEbha-zhLkyttWd3zpw,76
95
+ dtspark-1.1.0a1.dist-info/top_level.txt,sha256=x-6lMA6vNuxyDNJGNOKI4dyy7L0kOb9V98I5z46bJVY,8
96
+ dtspark-1.1.0a1.dist-info/RECORD,,