Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -341,3 +341,6 @@ poetry.toml
pyrightconfig.json

frontend/public/script.js

# created in dev builds...
frontend/public/script.js.map
2 changes: 2 additions & 0 deletions backend/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ async def handle_send_message(sid: str, json_data: dict[str, Any]) -> None:

message_id = json_data.get('id', str(uuid4()))
context_id = json_data.get('contextId')
task_id = json_data.get('taskId')

if sid not in clients:
await sio.emit(
Expand All @@ -303,6 +304,7 @@ async def handle_send_message(sid: str, json_data: dict[str, Any]) -> None:
parts=[TextPart(text=str(message_text))], # type: ignore[list-item]
message_id=message_id,
context_id=context_id,
task_id=task_id,
)
payload = MessageSendParams(
message=message,
Expand Down
3 changes: 2 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"main": "index.js",
"scripts": {
"build": "esbuild src/script.ts --bundle --outfile=public/script.js --platform=browser",
"dev": "esbuild src/script.ts --bundle --outfile=public/script.js --platform=browser --sourcemap",
"lint": "gts lint",
"clean": "gts clean",
"compile": "tsc",
Expand All @@ -27,4 +28,4 @@
"gts": "^6.0.2",
"typescript": "^5.8.3"
}
}
}
4 changes: 4 additions & 0 deletions frontend/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ <h2 class="chat-header">Chat</h2>
<div class="chat-input-container">
<input type="text" id="chat-input" placeholder="Type a message..." disabled>
<button id="send-btn" disabled>Send</button>
<label id="use-taskid-label" class="use-taskid-label hidden">
<input type="checkbox" id="use-taskid-checkbox" disabled>
use previous <code>taskId</code>
</label>
</div>
</div>
</div>
Expand Down
12 changes: 12 additions & 0 deletions frontend/public/styles.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
/* Use-taskid-label styles */
.use-taskid-label {
align-items: center;
gap: 4px;
margin-left: 10px;
font-size: 0.95em;
display: flex;
}

.hidden {
display: none;
}
html,
body {
height: 100%;
Expand Down
54 changes: 46 additions & 8 deletions frontend/src/script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ document.addEventListener('DOMContentLoaded', () => {
const chatInput = document.getElementById('chat-input') as HTMLInputElement;
const sendBtn = document.getElementById('send-btn') as HTMLButtonElement;
const chatMessages = document.getElementById('chat-messages') as HTMLElement;
const useTaskIdCheckbox = document.getElementById(
'use-taskid-checkbox',
) as HTMLInputElement;
const useTaskIdLabel = document.getElementById(
'use-taskid-label',
) as HTMLLabelElement;
const debugConsole = document.getElementById('debug-console') as HTMLElement;
const debugHandle = document.getElementById('debug-handle') as HTMLElement;
const debugContent = document.getElementById('debug-content') as HTMLElement;
Expand Down Expand Up @@ -128,7 +134,7 @@ document.addEventListener('DOMContentLoaded', () => {
collapsibleContent.classList.toggle('collapsed');
collapsibleContent.style.overflow = 'hidden';
});

collapsibleContent.addEventListener('transitionend', () => {
if (!collapsibleContent.classList.contains('collapsed')) {
collapsibleContent.style.overflow = 'auto';
Expand Down Expand Up @@ -258,6 +264,20 @@ document.addEventListener('DOMContentLoaded', () => {
chatInput.disabled = true;
sendBtn.disabled = true;

// Hide and disable the use-taskid checkbox and clear chat messages
if (useTaskIdLabel && useTaskIdCheckbox) {
useTaskIdLabel.classList.add('hidden');
useTaskIdCheckbox.disabled = true;
useTaskIdCheckbox.checked = false;
}
if (chatMessages) {
chatMessages.innerHTML =
'<p class="placeholder-text">Messages will appear here.</p>';
}

contextId = null;
previousTaskId = null;

// Get custom headers
const customHeaders = getCustomHeaders();

Expand Down Expand Up @@ -336,30 +356,37 @@ document.addEventListener('DOMContentLoaded', () => {
);

let contextId: string | null = null;
let previousTaskId: string | null = null;

const sendMessage = () => {
const messageText = chatInput.value;
if (messageText.trim() && !chatInput.disabled) {
// Sanitize the user's input before doing anything else
const sanitizedMessage = DOMPurify.sanitize(messageText);

// Optional but recommended: prevent sending messages that are empty after sanitization
if (!sanitizedMessage.trim()) {
chatInput.value = '';
return;
}

const messageId = `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;

// Use the sanitized message when displaying it locally
appendMessage('user', sanitizedMessage, messageId);
// Use the sanitized message when sending it to the server
socket.emit('send_message', {

// Prepare payload
const payload: Record<string, unknown> = {
message: sanitizedMessage,
id: messageId,
contextId,
});
};
if (useTaskIdCheckbox && useTaskIdCheckbox.checked && previousTaskId) {
payload.taskId = previousTaskId;
}

// Use the sanitized message when sending it to the server
socket.emit('send_message', payload);
chatInput.value = '';
}
};
Expand All @@ -373,6 +400,17 @@ document.addEventListener('DOMContentLoaded', () => {
const displayMessageId = `display-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
messageJsonStore[displayMessageId] = event;

// Show and enable the use-taskid checkbox if a response is received
if (useTaskIdLabel && useTaskIdCheckbox) {
useTaskIdLabel.classList.remove('hidden');
useTaskIdCheckbox.disabled = false;
}

// Store previous task_id if present
if (event.kind === 'task') {
previousTaskId = event.id;
}

const validationErrors = event.validation_errors || [];

if (event.error) {
Expand Down