feat(photo-editor): NL editor planner, image ops, email/gallery server

Server-side photo editor: natural-language editor agent route
(/api/editor/agent), photo_editor tool family + style guide, image-op
provider proxy with progress, email server hardening, gallery/hwfit
routes, and graceful shutdown.

Source: vendor/photocraft (ad1cff44) editor-server files, merged onto
upstream/dev (a8c147b2). Conflict resolution documented in
pr_work/B_conflicts.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
pewdiepie-archdaemon
2026-10-15 11:57:00 +00:00
co-authored by Claude Opus 5.5
parent c74f475679
commit eb940f24a3
46 changed files with 9662 additions and 725 deletions
+12 -12
View File
@@ -89,8 +89,8 @@ async def test_test_connection_oauth_account_uses_xoauth2_for_imap_and_smtp():
with mock.patch("core.database.SessionLocal", Factory), \
mock.patch("routes.email_routes._open_imap_connection", return_value=mock_imap_conn), \
mock.patch("routes.email_routes._PolicySMTP", return_value=mock_smtp_conn), \
mock.patch("routes.email_routes._PolicySMTP_SSL", return_value=mock_smtp_conn), \
mock.patch("routes.email_routes.smtplib.SMTP", return_value=mock_smtp_conn), \
mock.patch("routes.email_routes.smtplib.SMTP_SSL", return_value=mock_smtp_conn), \
mock.patch("routes.email_routes._get_valid_google_token", return_value="ya29.live") as token_getter:
result = await test_conn(req=_FakeReq(), owner="alice")
@@ -141,8 +141,8 @@ async def test_test_connection_password_account_still_uses_login():
with mock.patch("core.database.SessionLocal", Factory), \
mock.patch("routes.email_routes._open_imap_connection", return_value=mock_imap_conn), \
mock.patch("routes.email_routes._PolicySMTP", return_value=mock_smtp_conn), \
mock.patch("routes.email_routes._PolicySMTP_SSL", return_value=mock_smtp_conn):
mock.patch("routes.email_routes.smtplib.SMTP", return_value=mock_smtp_conn), \
mock.patch("routes.email_routes.smtplib.SMTP_SSL", return_value=mock_smtp_conn):
result = await test_conn(req=_FakeReq(), owner="alice")
assert result["ok"] is True
@@ -187,8 +187,8 @@ async def test_test_connection_rejects_non_google_hosts_before_oauth_auth():
with mock.patch("core.database.SessionLocal", Factory), \
mock.patch("routes.email_routes._open_imap_connection") as open_imap, \
mock.patch("routes.email_routes._PolicySMTP") as open_smtp, \
mock.patch("routes.email_routes._PolicySMTP_SSL") as open_smtp_ssl, \
mock.patch("routes.email_routes.smtplib.SMTP") as open_smtp, \
mock.patch("routes.email_routes.smtplib.SMTP_SSL") as open_smtp_ssl, \
mock.patch("routes.email_routes._get_valid_google_token") as token_getter:
result = await test_conn(req=_FakeReq(), owner="alice")
@@ -238,8 +238,8 @@ async def test_test_connection_rejects_insecure_oauth_transports_before_auth():
with mock.patch("core.database.SessionLocal", Factory), \
mock.patch("routes.email_routes._open_imap_connection") as open_imap, \
mock.patch("routes.email_routes._PolicySMTP") as open_smtp, \
mock.patch("routes.email_routes._PolicySMTP_SSL") as open_smtp_ssl, \
mock.patch("routes.email_routes.smtplib.SMTP") as open_smtp, \
mock.patch("routes.email_routes.smtplib.SMTP_SSL") as open_smtp_ssl, \
mock.patch("routes.email_routes._get_valid_google_token") as token_getter:
result = await test_conn(req=_FakeReq(), owner="alice")
@@ -336,10 +336,10 @@ async def test_test_connection_verifies_imap_tls_before_loading_oauth_token(
"routes.email_routes.ssl.create_default_context",
return_value=context,
), mock.patch(
"routes.email_helpers._PolicyIMAP4",
"routes.email_helpers.imaplib.IMAP4",
return_value=starttls_conn,
) as imap_cls, mock.patch(
"routes.email_helpers._PolicyIMAP4_SSL",
"routes.email_helpers.imaplib.IMAP4_SSL",
side_effect=ssl.SSLCertVerificationError("untrusted certificate"),
) as imap_ssl_cls, mock.patch(
"routes.email_routes._get_valid_google_token"
@@ -412,10 +412,10 @@ async def test_test_connection_verifies_smtp_tls_before_loading_oauth_token(
"routes.email_routes.ssl.create_default_context",
return_value=context,
), mock.patch(
"routes.email_routes._PolicySMTP",
"routes.email_routes.smtplib.SMTP",
return_value=starttls_smtp,
) as smtp_cls, mock.patch(
"routes.email_routes._PolicySMTP_SSL",
"routes.email_routes.smtplib.SMTP_SSL",
side_effect=ssl.SSLCertVerificationError("untrusted certificate"),
) as smtp_ssl_cls, mock.patch(
"routes.email_routes._get_valid_google_token"