Compare commits
8 Commits
63cf731d1f
...
3477fc639b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3477fc639b | ||
|
|
6f1ab9f30b | ||
|
|
bdc139dfb9 | ||
|
|
4d4fbc96ba | ||
|
|
8c0b76cf53 | ||
|
|
678d6124d7 | ||
|
|
bfd76773e0 | ||
|
|
83af7f6eb9 |
Binary file not shown.
@ -314,7 +314,7 @@ def _config() -> Dict[str, Any]:
|
|||||||
"project_id": project_id,
|
"project_id": project_id,
|
||||||
"project_uuid": os.getenv("PROJECT_UUID"),
|
"project_uuid": os.getenv("PROJECT_UUID"),
|
||||||
"project_header": os.getenv("AI_PROJECT_HEADER", "project-uuid"),
|
"project_header": os.getenv("AI_PROJECT_HEADER", "project-uuid"),
|
||||||
"default_model": os.getenv("AI_DEFAULT_MODEL", "gpt-5-mini"),
|
"default_model": os.getenv("AI_DEFAULT_MODEL", "gpt-5"),
|
||||||
"timeout": int(os.getenv("AI_TIMEOUT", "30")),
|
"timeout": int(os.getenv("AI_TIMEOUT", "30")),
|
||||||
"verify_tls": os.getenv("AI_VERIFY_TLS", "true").lower() not in {"0", "false", "no"},
|
"verify_tls": os.getenv("AI_VERIFY_TLS", "true").lower() not in {"0", "false", "no"},
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
assets/pasted-20251123-151520-06b3bb4c.png
Normal file
BIN
assets/pasted-20251123-151520-06b3bb4c.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 95 KiB |
BIN
assets/pasted-20251123-152623-4856e938.png
Normal file
BIN
assets/pasted-20251123-152623-4856e938.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 125 KiB |
BIN
assets/pasted-20251123-152817-0d338c39.png
Normal file
BIN
assets/pasted-20251123-152817-0d338c39.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
BIN
assets/pasted-20251123-153606-fc72d13a.png
Normal file
BIN
assets/pasted-20251123-153606-fc72d13a.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 226 KiB |
BIN
assets/pasted-20251124-095308-75e5f264.png
Normal file
BIN
assets/pasted-20251124-095308-75e5f264.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 122 KiB |
Binary file not shown.
@ -24,6 +24,12 @@ DEBUG = os.getenv("DJANGO_DEBUG", "true").lower() == "true"
|
|||||||
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
|
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
|
||||||
USE_X_FORWARDED_HOST = True
|
USE_X_FORWARDED_HOST = True
|
||||||
|
|
||||||
|
SESSION_COOKIE_SECURE = True
|
||||||
|
CSRF_COOKIE_SECURE = True
|
||||||
|
SESSION_COOKIE_SAMESITE = "None"
|
||||||
|
CSRF_COOKIE_SAMESITE = "None"
|
||||||
|
|
||||||
|
|
||||||
ALLOWED_HOSTS = [
|
ALLOWED_HOSTS = [
|
||||||
"127.0.0.1",
|
"127.0.0.1",
|
||||||
"localhost",
|
"localhost",
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -4,7 +4,7 @@ from .models import TodoItem
|
|||||||
class TodoItemForm(forms.ModelForm):
|
class TodoItemForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = TodoItem
|
model = TodoItem
|
||||||
fields = ['title', 'description', 'tags', 'status']
|
fields = ['title', 'description', 'tags', 'status', 'deadline']
|
||||||
widgets = {
|
widgets = {
|
||||||
'title': forms.TextInput(attrs={
|
'title': forms.TextInput(attrs={
|
||||||
'class': 'form-control',
|
'class': 'form-control',
|
||||||
@ -21,5 +21,9 @@ class TodoItemForm(forms.ModelForm):
|
|||||||
}),
|
}),
|
||||||
'status': forms.Select(attrs={
|
'status': forms.Select(attrs={
|
||||||
'class': 'form-control'
|
'class': 'form-control'
|
||||||
|
}),
|
||||||
|
'deadline': forms.DateInput(attrs={
|
||||||
|
'class': 'form-control',
|
||||||
|
'type': 'date'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
18
core/migrations/0008_todoitem_deadline.py
Normal file
18
core/migrations/0008_todoitem_deadline.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 5.2.7 on 2025-11-23 15:10
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('core', '0007_conversation_is_generating'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='todoitem',
|
||||||
|
name='deadline',
|
||||||
|
field=models.DateField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
18
core/migrations/0009_alter_todoitem_status.py
Normal file
18
core/migrations/0009_alter_todoitem_status.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 5.2.7 on 2025-11-23 15:32
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('core', '0008_todoitem_deadline'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='todoitem',
|
||||||
|
name='status',
|
||||||
|
field=models.CharField(choices=[('todo', 'To Do'), ('inprogress', 'In Progress'), ('blocked', 'Blocked'), ('delegated', 'Delegated'), ('done', 'Done')], default='todo', max_length=20),
|
||||||
|
),
|
||||||
|
]
|
||||||
Binary file not shown.
Binary file not shown.
@ -13,11 +13,13 @@ class TodoItem(models.Model):
|
|||||||
('todo', 'To Do'),
|
('todo', 'To Do'),
|
||||||
('inprogress', 'In Progress'),
|
('inprogress', 'In Progress'),
|
||||||
('blocked', 'Blocked'),
|
('blocked', 'Blocked'),
|
||||||
|
('delegated', 'Delegated'),
|
||||||
('done', 'Done'),
|
('done', 'Done'),
|
||||||
]
|
]
|
||||||
title = models.CharField(max_length=200)
|
title = models.CharField(max_length=200)
|
||||||
description = models.TextField(blank=True, null=True)
|
description = models.TextField(blank=True, null=True)
|
||||||
tags = models.CharField(max_length=255, blank=True, null=True)
|
tags = models.CharField(max_length=255, blank=True, null=True)
|
||||||
|
deadline = models.DateField(blank=True, null=True)
|
||||||
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='todo')
|
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='todo')
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
updated_at = models.DateTimeField(auto_now=True)
|
updated_at = models.DateTimeField(auto_now=True)
|
||||||
|
|||||||
@ -38,7 +38,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="container mt-5">
|
<main class="{% block container_class %}container{% endblock %} mt-5">
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
{% block title %}Chat{% endblock %}
|
{% block title %}Chat{% endblock %}
|
||||||
|
|
||||||
|
{% block container_class %}container-fluid{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="chat-container">
|
<div class="chat-container">
|
||||||
<!-- Sidebar -->
|
<!-- Sidebar -->
|
||||||
|
|||||||
@ -4,10 +4,7 @@
|
|||||||
{% block title %}AI Task Manager - Home{% endblock %}
|
{% block title %}AI Task Manager - Home{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="hero-section text-center py-5">
|
|
||||||
<h1 class="display-4">AI Task Manager</h1>
|
|
||||||
<p class="lead">Your intelligent assistant for managing tasks and conversations.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-lg-8">
|
<div class="col-lg-8">
|
||||||
@ -28,6 +25,10 @@
|
|||||||
{{ form.tags.label_tag }}
|
{{ form.tags.label_tag }}
|
||||||
{{ form.tags }}
|
{{ form.tags }}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
{{ form.deadline.label_tag }}
|
||||||
|
{{ form.deadline }}
|
||||||
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
{{ form.status.label_tag }}
|
{{ form.status.label_tag }}
|
||||||
{{ form.status }}
|
{{ form.status }}
|
||||||
@ -54,23 +55,28 @@
|
|||||||
<th scope="col">Tags</th>
|
<th scope="col">Tags</th>
|
||||||
<th scope="col">Status</th>
|
<th scope="col">Status</th>
|
||||||
<th scope="col">Created</th>
|
<th scope="col">Created</th>
|
||||||
|
<th scope="col">Deadline</th>
|
||||||
<th scope="col">Actions</th>
|
<th scope="col">Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for item in todo_list %}
|
{% for item in todo_list %}
|
||||||
<tr>
|
<tr class="{% if item.status == 'inprogress' %}table-info{% elif item.status == 'done' %}table-success{% elif item.status == 'blocked' %}table-danger{% elif item.status == 'delegated' %}table-warning{% endif %}">
|
||||||
<td>{{ item.title }}</td>
|
<td>
|
||||||
|
{{ item.title }}
|
||||||
|
<div><span class="task-id text-muted small">#{{ item.id }}</span></div>
|
||||||
|
</td>
|
||||||
<td>{{ item.description|default:"" }}</td>
|
<td>{{ item.description|default:"" }}</td>
|
||||||
<td>
|
<td>
|
||||||
{% if item.tags %}
|
{% if item.tags %}
|
||||||
{% for tag in item.tags.split|slice:":3" %}
|
{% for tag in item.tags.split:','|slice:":3" %}
|
||||||
<span class="badge bg-secondary">{{ tag }}</span>
|
<span class="badge bg-secondary">{{ tag }}</span>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td><span class="badge status-{{ item.status }}">{{ item.get_status_display }}</span></td>
|
<td><span class="badge {% if item.status == 'inprogress' %}bg-info text-dark{% elif item.status == 'done' %}bg-success{% elif item.status == 'blocked' %}bg-danger{% elif item.status == 'delegated' %}bg-warning text-dark{% else %}bg-light text-dark{% endif %}">{{ item.get_status_display }}</span></td>
|
||||||
<td>{{ item.created_at|date:"M d, Y" }}</td>
|
<td>{{ item.created_at|date:"M d, Y" }}</td>
|
||||||
|
<td>{{ item.deadline|date:"M d, Y"|default:"" }}</td>
|
||||||
<td>
|
<td>
|
||||||
<form method="post" action="{% url 'core:delete_task' item.id %}" style="display: inline;">
|
<form method="post" action="{% url 'core:delete_task' item.id %}" style="display: inline;">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
@ -80,7 +86,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
{% empty %}
|
{% empty %}
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="5" class="text-center text-muted py-4">No tasks yet. Add one above!</td>
|
<td colspan="7" class="text-center text-muted py-4">No tasks yet. Add one above!</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@ -4,11 +4,10 @@
|
|||||||
|
|
||||||
{% block title %}AI Task Manager - Kanban Board{% endblock %}
|
{% block title %}AI Task Manager - Kanban Board{% endblock %}
|
||||||
|
|
||||||
|
{% block container_class %}container-fluid{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="hero-section text-center py-5">
|
|
||||||
<h1 class="display-4">Kanban Board</h1>
|
|
||||||
<p class="lead">Visualize your tasks and track progress.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="kanban-board-container">
|
<div class="kanban-board-container">
|
||||||
<div class="loader-overlay" style="display: none;">
|
<div class="loader-overlay" style="display: none;">
|
||||||
@ -29,15 +28,21 @@
|
|||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<button type="submit" class="btn-close" aria-label="Close"></button>
|
<button type="submit" class="btn-close" aria-label="Close"></button>
|
||||||
</form>
|
</form>
|
||||||
<h5 class="card-title h6">{{ item.title }}</h5>
|
<div class="d-flex justify-content-between align-items-start">
|
||||||
|
<h5 class="card-title h6 mb-0">{{ item.title }}</h5>
|
||||||
|
<span class="task-id text-muted small">#{{ item.id }}</span>
|
||||||
|
</div>
|
||||||
<p class="card-text small">{{ item.description|default:""|truncatewords:15 }}</p>
|
<p class="card-text small">{{ item.description|default:""|truncatewords:15 }}</p>
|
||||||
{% if item.tags %}
|
{% if item.tags %}
|
||||||
<div class="tags">
|
<div class="tags">
|
||||||
{% for tag in item.tags.split|slice:":3" %}
|
{% for tag in item.tags.split:','|slice:":3" %}
|
||||||
<span class="badge bg-secondary">{{ tag }}</span>
|
<span class="badge bg-secondary">{{ tag }}</span>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if item.deadline %}
|
||||||
|
<p class="card-text small text-muted mt-2">Deadline: {{ item.deadline|date:"Y-m-d" }}</p>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@ -59,9 +64,6 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
new Sortable(column, {
|
new Sortable(column, {
|
||||||
group: 'kanban',
|
group: 'kanban',
|
||||||
animation: 150,
|
animation: 150,
|
||||||
onStart: function (evt) {
|
|
||||||
document.querySelector('.loader-overlay').style.display = 'flex';
|
|
||||||
},
|
|
||||||
onEnd: function (evt) {
|
onEnd: function (evt) {
|
||||||
const itemEl = evt.item;
|
const itemEl = evt.item;
|
||||||
const toContainer = evt.to;
|
const toContainer = evt.to;
|
||||||
@ -102,9 +104,6 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
// Revert the move in the UI
|
// Revert the move in the UI
|
||||||
fromContainer.insertBefore(itemEl, fromContainer.children[oldIndex]);
|
fromContainer.insertBefore(itemEl, fromContainer.children[oldIndex]);
|
||||||
alert('An error occurred while updating the task. Please try again.');
|
alert('An error occurred while updating the task. Please try again.');
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
document.querySelector('.loader-overlay').style.display = 'none';
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
# core/views.py
|
||||||
|
|
||||||
from django.shortcuts import render, redirect, get_object_or_404
|
from django.shortcuts import render, redirect, get_object_or_404
|
||||||
from django.http import JsonResponse
|
from django.http import JsonResponse
|
||||||
from django.views.decorators.http import require_POST
|
from django.views.decorators.http import require_POST
|
||||||
@ -110,10 +112,12 @@ def execute_command(command_data):
|
|||||||
new_task = TodoItem.objects.create(
|
new_task = TodoItem.objects.create(
|
||||||
title=title,
|
title=title,
|
||||||
description=args.get('description', ''),
|
description=args.get('description', ''),
|
||||||
status=args.get('status', 'todo')
|
status=args.get('status', 'todo'),
|
||||||
|
tags=args.get('tags', ''),
|
||||||
|
deadline=args.get('deadline')
|
||||||
)
|
)
|
||||||
logger.info(f"Command 'add_task' executed successfully. New task ID: {new_task.id}")
|
logger.info(f"Command 'add_task' executed successfully. New task ID: {new_task.id}")
|
||||||
return f"[SYSTEM] Command 'add_task' executed successfully. New task ID: {new_task.id}"
|
return f"[SYSTEM] Command 'add_task' executed successfully. A new task with ID {new_task.id}, title '{new_task.title}', description '{new_task.description}', status '{new_task.status}', tags '{new_task.tags}', and deadline '{new_task.deadline}' has been created."
|
||||||
|
|
||||||
elif command_name == 'edit_task':
|
elif command_name == 'edit_task':
|
||||||
task_id = args.get('task_id')
|
task_id = args.get('task_id')
|
||||||
@ -129,10 +133,14 @@ def execute_command(command_data):
|
|||||||
task.description = args['description']
|
task.description = args['description']
|
||||||
if 'status' in args:
|
if 'status' in args:
|
||||||
task.status = args['status']
|
task.status = args['status']
|
||||||
|
if 'tags' in args:
|
||||||
|
task.tags = args['tags']
|
||||||
|
if 'deadline' in args:
|
||||||
|
task.deadline = args['deadline']
|
||||||
|
|
||||||
task.save()
|
task.save()
|
||||||
logger.info(f"Command 'edit_task' for task ID {task_id} executed successfully.")
|
logger.info(f"Command 'edit_task' for task ID {task_id} executed successfully.")
|
||||||
return f"[SYSTEM] Command 'edit_task' for task ID {task_id} executed successfully."
|
return f"[SYSTEM] Command 'edit_task' for task ID {task_id} executed successfully. The task now has title '{task.title}', description '{task.description}', status '{task.status}', tags '{task.tags}', and deadline '{task.deadline}'."
|
||||||
|
|
||||||
elif command_name == 'delete_task':
|
elif command_name == 'delete_task':
|
||||||
task_id = args.get('task_id')
|
task_id = args.get('task_id')
|
||||||
@ -174,7 +182,7 @@ def run_ai_process_in_background(conversation_id):
|
|||||||
key='custom_instructions',
|
key='custom_instructions',
|
||||||
defaults={'value': ''}
|
defaults={'value': ''}
|
||||||
)
|
)
|
||||||
custom_instructions_text = custom_instructions.value + '\n\n' if custom_instructions.value else ''
|
custom_instructions_text = custom_instructions.value + '''\n\n''' if custom_instructions.value else ''
|
||||||
|
|
||||||
system_message = {
|
system_message = {
|
||||||
"role": "system",
|
"role": "system",
|
||||||
@ -202,14 +210,18 @@ def run_ai_process_in_background(conversation_id):
|
|||||||
* `add_task`: Adds a new task.
|
* `add_task`: Adds a new task.
|
||||||
* `args`:
|
* `args`:
|
||||||
* `title` (string, required): The title of the task.
|
* `title` (string, required): The title of the task.
|
||||||
* `description` (string, optional): The description of the task.
|
* `description` (string, optional): A detailed description of the task.
|
||||||
* `status` (string, optional, default: 'todo'): The status of the task. Can be 'todo', 'inprogress', 'done', 'blocked'.
|
* `status` (string, optional, default: 'todo'): The status of the task. Valid options are 'todo', 'inprogress', 'done', 'blocked'.
|
||||||
|
* `tags` (string, optional): A comma-separated string of tags (e.g., "work,urgent").
|
||||||
|
* `deadline` (string, optional): The deadline for the task in YYYY-MM-DD format.
|
||||||
* `edit_task`: Edits an existing task.
|
* `edit_task`: Edits an existing task.
|
||||||
* `args`:
|
* `args`:
|
||||||
* `task_id` (integer, required): The ID of the task to edit.
|
* `task_id` (integer, required): The ID of the task to edit.
|
||||||
* `title` (string, optional): The new title.
|
* `title` (string, optional): The new title.
|
||||||
* `description` (string, optional): The new description.
|
* `description` (string, optional): The new description.
|
||||||
* `status` (string, optional): The new status.
|
* `status` (string, optional): The new status. Valid options are 'todo', 'inprogress', 'done', 'blocked'.
|
||||||
|
* `tags` (string, optional): The new comma-separated string of tags.
|
||||||
|
* `deadline` (string, optional): The new deadline for the task in YYYY-MM-DD format.
|
||||||
* `delete_task`: Deletes a task.
|
* `delete_task`: Deletes a task.
|
||||||
* `args`:
|
* `args`:
|
||||||
* `task_id` (integer, required): The ID of the task to delete.
|
* `task_id` (integer, required): The ID of the task to delete.
|
||||||
@ -218,7 +230,7 @@ def run_ai_process_in_background(conversation_id):
|
|||||||
|
|
||||||
1. You can issue a series of commands to be executed sequentially.
|
1. You can issue a series of commands to be executed sequentially.
|
||||||
2. The system executes each command and provides a result.
|
2. The system executes each command and provides a result.
|
||||||
3. The loop will stop if you call `send_message` or after a maximum of 7 iterations.
|
3. The loop will stop if you call `send_message` or after a maximum of 31 iterations.
|
||||||
|
|
||||||
**VERY IMPORTANT:**
|
**VERY IMPORTANT:**
|
||||||
- To talk to the user, you MUST use the `send_message` command. This command will STOP the execution loop.
|
- To talk to the user, you MUST use the `send_message` command. This command will STOP the execution loop.
|
||||||
@ -239,14 +251,15 @@ def run_ai_process_in_background(conversation_id):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
* **User:** "add a new task to buy milk"
|
* **User:** "add a new task to buy milk with tag 'personal'"
|
||||||
* **Correct AI Response:**
|
* **Correct AI Response:**
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"command": {
|
"command": {
|
||||||
"name": "add_task",
|
"name": "add_task",
|
||||||
"args": {
|
"args": {
|
||||||
"title": "buy milk"
|
"title": "buy milk",
|
||||||
|
"tags": "personal"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -256,9 +269,11 @@ def run_ai_process_in_background(conversation_id):
|
|||||||
}
|
}
|
||||||
|
|
||||||
tasks = TodoItem.objects.all().order_by('created_at')
|
tasks = TodoItem.objects.all().order_by('created_at')
|
||||||
task_list_str = "\n".join([
|
task_list = []
|
||||||
f"- ID {task.id}: {task.title} (Status: {task.get_status_display()}, Tags: {task.tags or 'None'})" for task in tasks
|
for task in tasks:
|
||||||
])
|
deadline_str = f", Deadline: {task.deadline}" if task.deadline else ""
|
||||||
|
task_list.append(f"- ID {task.id}: {task.title} (Status: {task.get_status_display()}, Tags: {task.tags or 'None'}{deadline_str})")
|
||||||
|
task_list_str = "\n".join(task_list)
|
||||||
|
|
||||||
tasks_context = {
|
tasks_context = {
|
||||||
"role": "system",
|
"role": "system",
|
||||||
@ -267,7 +282,7 @@ def run_ai_process_in_background(conversation_id):
|
|||||||
|
|
||||||
logger.info("Starting AI processing loop...")
|
logger.info("Starting AI processing loop...")
|
||||||
|
|
||||||
for i in range(7): # Loop up to 7 times
|
for i in range(31): # Loop up to 31 times
|
||||||
logger.info(f"AI loop iteration {i+1}")
|
logger.info(f"AI loop iteration {i+1}")
|
||||||
|
|
||||||
response = LocalAIApi.create_response({
|
response = LocalAIApi.create_response({
|
||||||
@ -311,7 +326,7 @@ def run_ai_process_in_background(conversation_id):
|
|||||||
Message.objects.create(conversation=conversation, content=ai_text, sender='ai')
|
Message.objects.create(conversation=conversation, content=ai_text, sender='ai')
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
logger.warning("AI loop finished after 7 iterations without sending a message.")
|
logger.warning("AI loop finished after 31 iterations without sending a message.")
|
||||||
final_message = "I seem to be stuck in a loop. Could you clarify what you'd like me to do?"
|
final_message = "I seem to be stuck in a loop. Could you clarify what you'd like me to do?"
|
||||||
Message.objects.create(conversation=conversation, content=final_message, sender='ai')
|
Message.objects.create(conversation=conversation, content=final_message, sender='ai')
|
||||||
|
|
||||||
@ -404,3 +419,10 @@ def settings_view(request):
|
|||||||
return render(request, 'core/settings.html', {
|
return render(request, 'core/settings.html', {
|
||||||
'custom_instructions': custom_instructions
|
'custom_instructions': custom_instructions
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@require_POST
|
||||||
|
def delete_conversation(request, conversation_id):
|
||||||
|
conversation = get_object_or_404(Conversation, id=conversation_id)
|
||||||
|
conversation.delete()
|
||||||
|
return redirect('core:chat')
|
||||||
|
|||||||
@ -202,9 +202,11 @@ body {
|
|||||||
|
|
||||||
/* System and AI Command Messages */
|
/* System and AI Command Messages */
|
||||||
.message.system .message-content {
|
.message.system .message-content {
|
||||||
background-color: #f8d7da;
|
background-color: #f1f3f5;
|
||||||
color: #721c24;
|
color: #495057;
|
||||||
border: 1px solid #f5c6cb;
|
border: 1px solid #dee2e6;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message.ai_command .message-content {
|
.message.ai_command .message-content {
|
||||||
@ -243,14 +245,13 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.kanban-column {
|
.kanban-column {
|
||||||
flex: 1 1 300px; /* Flex-grow, flex-shrink, and basis */
|
flex: 1 1 18rem;
|
||||||
min-width: 300px;
|
min-width: 16rem;
|
||||||
max-width: 320px;
|
max-width: 18rem;
|
||||||
background-color: #f0f2f5;
|
background-color: #f0f2f5;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
max-height: calc(100vh - 250px); /* Adjust based on your layout */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.kanban-column h2 {
|
.kanban-column h2 {
|
||||||
@ -295,3 +296,12 @@ body {
|
|||||||
box-shadow: 0 8px 16px rgba(0,0,0,0.2);
|
box-shadow: 0 8px 16px rgba(0,0,0,0.2);
|
||||||
transform: rotate(3deg);
|
transform: rotate(3deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.task-id {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanban-card .task-id {
|
||||||
|
margin-top: 0.2rem;
|
||||||
|
}
|
||||||
@ -202,9 +202,11 @@ body {
|
|||||||
|
|
||||||
/* System and AI Command Messages */
|
/* System and AI Command Messages */
|
||||||
.message.system .message-content {
|
.message.system .message-content {
|
||||||
background-color: #f8d7da;
|
background-color: #f1f3f5;
|
||||||
color: #721c24;
|
color: #495057;
|
||||||
border: 1px solid #f5c6cb;
|
border: 1px solid #dee2e6;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message.ai_command .message-content {
|
.message.ai_command .message-content {
|
||||||
@ -243,14 +245,13 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.kanban-column {
|
.kanban-column {
|
||||||
flex: 1 1 300px; /* Flex-grow, flex-shrink, and basis */
|
flex: 1 1 18rem;
|
||||||
min-width: 300px;
|
min-width: 16rem;
|
||||||
max-width: 320px;
|
max-width: 18rem;
|
||||||
background-color: #f0f2f5;
|
background-color: #f0f2f5;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
max-height: calc(100vh - 250px); /* Adjust based on your layout */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.kanban-column h2 {
|
.kanban-column h2 {
|
||||||
@ -295,3 +296,12 @@ body {
|
|||||||
box-shadow: 0 8px 16px rgba(0,0,0,0.2);
|
box-shadow: 0 8px 16px rgba(0,0,0,0.2);
|
||||||
transform: rotate(3deg);
|
transform: rotate(3deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.task-id {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanban-card .task-id {
|
||||||
|
margin-top: 0.2rem;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user