Implement executing tasks

This commit is contained in:
2026-03-03 16:41:28 +00:00
parent d6bd56dace
commit 9c14e51b43
42 changed files with 3410 additions and 121 deletions

View File

@@ -20,14 +20,14 @@ SERVICE_CHOICES = (
)
CHANNEL_SERVICE_CHOICES = SERVICE_CHOICES + (("web", "Web"),)
MBTI_CHOICES = (
("INTJ", "INTJ - Architect"),
("INTJ", "INTJ - Architect"),# ;)
("INTP", "INTP - Logician"),
("ENTJ", "ENTJ - Commander"),
("ENTP", "ENTP - Debater"),
("INFJ", "INFJ - Advocate"),
("INFP", "INFP - Mediator"),
("ENFJ", "ENFJ - Protagonist"),
("ENFP", "ENFP - Campaigner"),
("ENFP", "ENFP - Campaigner"), # <3
("ISTJ", "ISTJ - Logistician"),
("ISFJ", "ISFJ - Defender"),
("ESTJ", "ESTJ - Executive"),
@@ -2227,6 +2227,164 @@ class TaskProviderConfig(models.Model):
]
class ContactAvailabilitySettings(models.Model):
user = models.OneToOneField(
User,
on_delete=models.CASCADE,
related_name="contact_availability_settings",
)
enabled = models.BooleanField(default=True)
show_in_chat = models.BooleanField(default=True)
show_in_groups = models.BooleanField(default=True)
inference_enabled = models.BooleanField(default=True)
retention_days = models.PositiveIntegerField(default=90)
fade_threshold_seconds = models.PositiveIntegerField(default=900)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class ContactAvailabilityEvent(models.Model):
SOURCE_KIND_CHOICES = (
("native_presence", "Native Presence"),
("read_receipt", "Read Receipt"),
("typing_start", "Typing Start"),
("typing_stop", "Typing Stop"),
("message_in", "Message In"),
("message_out", "Message Out"),
("inferred_timeout", "Inferred Timeout"),
)
STATE_CHOICES = (
("available", "Available"),
("unavailable", "Unavailable"),
("unknown", "Unknown"),
("fading", "Fading"),
)
user = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name="contact_availability_events",
)
person = models.ForeignKey(
Person,
on_delete=models.CASCADE,
related_name="availability_events",
)
person_identifier = models.ForeignKey(
PersonIdentifier,
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="availability_events",
)
service = models.CharField(max_length=255, choices=CHANNEL_SERVICE_CHOICES)
source_kind = models.CharField(max_length=32, choices=SOURCE_KIND_CHOICES)
availability_state = models.CharField(max_length=32, choices=STATE_CHOICES)
confidence = models.FloatField(default=0.0)
ts = models.BigIntegerField(db_index=True)
payload = models.JSONField(default=dict, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
indexes = [
models.Index(fields=["user", "person", "ts"]),
models.Index(fields=["user", "service", "ts"]),
models.Index(fields=["user", "availability_state", "ts"]),
]
class ContactAvailabilitySpan(models.Model):
STATE_CHOICES = ContactAvailabilityEvent.STATE_CHOICES
user = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name="contact_availability_spans",
)
person = models.ForeignKey(
Person,
on_delete=models.CASCADE,
related_name="availability_spans",
)
person_identifier = models.ForeignKey(
PersonIdentifier,
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="availability_spans",
)
service = models.CharField(max_length=255, choices=CHANNEL_SERVICE_CHOICES)
state = models.CharField(max_length=32, choices=STATE_CHOICES)
start_ts = models.BigIntegerField(db_index=True)
end_ts = models.BigIntegerField(db_index=True)
confidence_start = models.FloatField(default=0.0)
confidence_end = models.FloatField(default=0.0)
opening_event = models.ForeignKey(
ContactAvailabilityEvent,
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="opening_spans",
)
closing_event = models.ForeignKey(
ContactAvailabilityEvent,
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="closing_spans",
)
payload = models.JSONField(default=dict, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
indexes = [
models.Index(fields=["user", "person", "start_ts"]),
models.Index(fields=["user", "person", "end_ts"]),
models.Index(fields=["user", "service", "start_ts"]),
]
class ExternalChatLink(models.Model):
user = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name="external_chat_links",
)
provider = models.CharField(max_length=64, default="codex_cli")
person = models.ForeignKey(
Person,
on_delete=models.CASCADE,
null=True,
blank=True,
related_name="external_chat_links",
)
person_identifier = models.ForeignKey(
PersonIdentifier,
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="external_chat_links",
)
external_chat_id = models.CharField(max_length=255)
metadata = models.JSONField(default=dict, blank=True)
enabled = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
indexes = [
models.Index(fields=["user", "provider", "external_chat_id"]),
models.Index(fields=["user", "provider", "enabled"]),
]
constraints = [
models.UniqueConstraint(
fields=["user", "provider", "external_chat_id"],
name="unique_external_chat_link_per_provider",
)
]
class TaskCompletionPattern(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="task_completion_patterns")