Lightweight containerized prosody tooling + moved auth scripts + xmpp reconnect/auth stabilization
This commit is contained in:
91
core/tasks/codex_approval.py
Normal file
91
core/tasks/codex_approval.py
Normal file
@@ -0,0 +1,91 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
|
||||
from asgiref.sync import async_to_sync
|
||||
|
||||
from core.clients.transport import send_message_raw
|
||||
from core.models import CodexPermissionRequest, ExternalSyncEvent, TaskProviderConfig
|
||||
|
||||
|
||||
def _deterministic_approval_key(idempotency_key: str) -> str:
|
||||
digest = hashlib.sha1(str(idempotency_key or "").encode("utf-8")).hexdigest()[:12]
|
||||
return f"pre-{digest}"
|
||||
|
||||
|
||||
def queue_codex_event_with_pre_approval(
|
||||
*,
|
||||
user,
|
||||
run,
|
||||
task,
|
||||
task_event,
|
||||
action: str,
|
||||
provider_payload: dict,
|
||||
idempotency_key: str,
|
||||
) -> tuple[ExternalSyncEvent, CodexPermissionRequest]:
|
||||
approval_key = _deterministic_approval_key(idempotency_key)
|
||||
waiting_event, _ = ExternalSyncEvent.objects.update_or_create(
|
||||
idempotency_key=f"codex_waiting:{idempotency_key}",
|
||||
defaults={
|
||||
"user": user,
|
||||
"task": task,
|
||||
"task_event": task_event,
|
||||
"provider": "codex_cli",
|
||||
"status": "waiting_approval",
|
||||
"payload": {
|
||||
"action": str(action or "append_update"),
|
||||
"provider_payload": dict(provider_payload or {}),
|
||||
},
|
||||
"error": "",
|
||||
},
|
||||
)
|
||||
run.status = "waiting_approval"
|
||||
run.error = ""
|
||||
run.save(update_fields=["status", "error", "updated_at"])
|
||||
|
||||
request, _ = CodexPermissionRequest.objects.update_or_create(
|
||||
approval_key=approval_key,
|
||||
defaults={
|
||||
"user": user,
|
||||
"codex_run": run,
|
||||
"external_sync_event": waiting_event,
|
||||
"summary": "Pre-submit approval required before sending to Codex",
|
||||
"requested_permissions": {
|
||||
"type": "pre_submit",
|
||||
"provider": "codex_cli",
|
||||
"action": str(action or "append_update"),
|
||||
},
|
||||
"resume_payload": {
|
||||
"gate_type": "pre_submit",
|
||||
"action": str(action or "append_update"),
|
||||
"provider_payload": dict(provider_payload or {}),
|
||||
"idempotency_key": str(idempotency_key or ""),
|
||||
},
|
||||
"status": "pending",
|
||||
"resolved_at": None,
|
||||
"resolved_by_identifier": "",
|
||||
"resolution_note": "",
|
||||
},
|
||||
)
|
||||
|
||||
cfg = TaskProviderConfig.objects.filter(user=user, provider="codex_cli", enabled=True).first()
|
||||
settings_payload = dict(getattr(cfg, "settings", {}) or {})
|
||||
approver_service = str(settings_payload.get("approver_service") or "").strip().lower()
|
||||
approver_identifier = str(settings_payload.get("approver_identifier") or "").strip()
|
||||
if approver_service and approver_identifier:
|
||||
try:
|
||||
async_to_sync(send_message_raw)(
|
||||
approver_service,
|
||||
approver_identifier,
|
||||
text=(
|
||||
f"[codex approval] key={approval_key}\n"
|
||||
"summary=Pre-submit approval required before sending to Codex\n"
|
||||
"requested=pre_submit\n"
|
||||
f"use: .codex approve {approval_key} or .codex deny {approval_key}"
|
||||
),
|
||||
attachments=[],
|
||||
metadata={"origin_tag": f"codex-pre-approval:{approval_key}"},
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
return waiting_event, request
|
||||
Reference in New Issue
Block a user