socialcli 0.3.0__tar.gz → 0.3.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {socialcli-0.3.0 → socialcli-0.3.2}/.gitignore +3 -0
- socialcli-0.3.2/LICENSE +48 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/PKG-INFO +12 -13
- {socialcli-0.3.0 → socialcli-0.3.2}/README.md +7 -5
- socialcli-0.3.2/pyproject.toml +183 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/agent_errors.py +75 -4
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/agent_guide.py +4 -4
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/engagement.py +69 -8
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/engagement_cli.py +23 -3
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/identity.py +30 -13
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/inbox.py +5 -1
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/inventory.py +4 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/batches.py +20 -10
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/changes.py +30 -15
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/community_changes.py +4 -2
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/snippet_readback.py +9 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/youtube_community.py +4 -4
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/youtube_resources.py +13 -3
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/media_preflight.py +7 -2
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/operation_output.py +3 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/postfile.py +12 -14
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/read_reports.py +4 -1
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/ui/assets/agent-manual.md +83 -20
- socialcli-0.3.2/socialctl/ui/assets/agents.md +33 -0
- socialcli-0.3.0/pyproject.toml +0 -51
- socialcli-0.3.0/socialctl/connection_service/__main__.py +0 -33
- socialcli-0.3.0/socialctl/connection_service/app.py +0 -496
- socialcli-0.3.0/socialctl/connection_service/assets/PLATFORM-LOGOS-LICENSE.txt +0 -50
- socialcli-0.3.0/socialctl/connection_service/assets/connection.css +0 -75
- socialcli-0.3.0/socialctl/connection_service/assets/facebook.webp +0 -0
- socialcli-0.3.0/socialctl/connection_service/assets/instagram.svg +0 -194
- socialcli-0.3.0/socialctl/connection_service/assets/socialcli-logo.png +0 -0
- socialcli-0.3.0/socialctl/connection_service/assets/tiktok.png +0 -0
- socialcli-0.3.0/socialctl/connection_service/assets/youtube.svg +0 -1
- socialcli-0.3.0/socialctl/connection_service/landing.py +0 -146
- socialcli-0.3.0/socialctl/connection_service/legacy.py +0 -48
- socialcli-0.3.0/socialctl/connection_service/peer.py +0 -13
- socialcli-0.3.0/socialctl/connection_service/providers.py +0 -324
- socialcli-0.3.0/socialctl/connection_service/settings.py +0 -76
- socialcli-0.3.0/socialctl/connection_service/store.py +0 -124
- socialcli-0.3.0/socialctl/connections/__init__.py +0 -0
- socialcli-0.3.0/socialctl/saas/__init__.py +0 -1
- socialcli-0.3.0/socialctl/saas/access.py +0 -75
- socialcli-0.3.0/socialctl/saas/auth.py +0 -213
- socialcli-0.3.0/socialctl/saas/backup.py +0 -124
- socialcli-0.3.0/socialctl/saas/billing.py +0 -327
- socialcli-0.3.0/socialctl/saas/billing_enrollment.py +0 -1237
- socialcli-0.3.0/socialctl/saas/billing_enrollment_schema.py +0 -519
- socialcli-0.3.0/socialctl/saas/billing_inventory.py +0 -775
- socialcli-0.3.0/socialctl/saas/billing_reconcile.py +0 -127
- socialcli-0.3.0/socialctl/saas/billing_routes.py +0 -27
- socialcli-0.3.0/socialctl/saas/budget.py +0 -66
- socialcli-0.3.0/socialctl/saas/connections.py +0 -374
- socialcli-0.3.0/socialctl/saas/consent.py +0 -52
- socialcli-0.3.0/socialctl/saas/lifecycle.py +0 -341
- socialcli-0.3.0/socialctl/saas/mail.py +0 -89
- socialcli-0.3.0/socialctl/saas/maintenance.py +0 -68
- socialcli-0.3.0/socialctl/saas/meta_user.py +0 -298
- socialcli-0.3.0/socialctl/saas/meta_webhooks.py +0 -358
- socialcli-0.3.0/socialctl/saas/migration.py +0 -107
- socialcli-0.3.0/socialctl/saas/models.py +0 -8
- socialcli-0.3.0/socialctl/saas/operations.py +0 -102
- socialcli-0.3.0/socialctl/saas/pages.py +0 -126
- socialcli-0.3.0/socialctl/saas/pairing.py +0 -158
- socialcli-0.3.0/socialctl/saas/permissions.py +0 -57
- socialcli-0.3.0/socialctl/saas/reminders.py +0 -128
- socialcli-0.3.0/socialctl/saas/renewal.py +0 -74
- socialcli-0.3.0/socialctl/saas/restore_guard.py +0 -229
- socialcli-0.3.0/socialctl/saas/revocation.py +0 -97
- socialcli-0.3.0/socialctl/saas/rotation.py +0 -114
- socialcli-0.3.0/socialctl/saas/routes.py +0 -221
- socialcli-0.3.0/socialctl/saas/settings.py +0 -34
- socialcli-0.3.0/socialctl/saas/store.py +0 -106
- socialcli-0.3.0/socialctl/saas/temporary_media.py +0 -245
- socialcli-0.3.0/socialctl/saas/webhooks.py +0 -76
- socialcli-0.3.0/socialctl/ui/assets/agents.md +0 -27
- socialcli-0.3.0/socialctl/ui/assets/components.css +0 -20
- socialcli-0.3.0/socialctl/ui/assets/connection-layout.css +0 -53
- socialcli-0.3.0/socialctl/ui/assets/otp.template.html +0 -10
- socialcli-0.3.0/socialctl/ui/assets/tokens.css +0 -1
- socialcli-0.3.0/socialctl/ui/assets/trial.template.html +0 -11
- socialcli-0.3.0/socialctl/ui/assets/web-layout.css +0 -38
- socialcli-0.3.0/socialctl/ui/email/otp.html +0 -10
- socialcli-0.3.0/socialctl/ui/email/trial.html +0 -11
- /socialcli-0.3.0/LICENSE → /socialcli-0.3.2/LICENSE-MIT-LEGACY +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/__init__.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/__main__.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/adapters/__init__.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/adapters/base.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/adapters/errores.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/adapters/facebook.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/adapters/instagram.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/adapters/tiktok.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/adapters/youtube.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/approval_cli.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/auth.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/authflow.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/brands.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/capabilities.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/capabilities.yml +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/cli.py +0 -0
- {socialcli-0.3.0/socialctl/connection_service → socialcli-0.3.2/socialctl/connections}/__init__.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/connections/account_cli.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/connections/cli.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/connections/client.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/connections/credential_cli.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/connections/credential_store.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/connections/file_store.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/connections/keychain.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/connections/meta_user.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/connections/rotation_cli.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/connections/saas_client.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/connections/temporary_media.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/delivery_options.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/executor.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/formatter.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/hosted_media.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/inbox_cli.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/inventory_cli.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/inventory_sources.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/__init__.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/batch_cli.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/cli.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/comments_cli.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/community_batch_cli.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/community_batches.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/community_cli.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/community_schema.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/facebook_groups.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/groups_cli.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/inbox_readers.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/meta_changes.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/meta_cli.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/meta_client.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/meta_comment_inbox.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/meta_comments.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/meta_errors.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/meta_pagination.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/meta_schema.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/meta_webhooks.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/metadata_parts.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/owned_assets.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/owned_changes.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/owned_cli.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/owned_reorder.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/owned_schema.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/reply_context.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/reply_evidence.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/resource_changes.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/resource_cli.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/stories.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/stories_cli.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/youtube.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/youtube_metadata.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/management/youtube_owned.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/media.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/media_cli.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/media_ingress.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/media_registry.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/media_requirements.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/metricas/__init__.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/metricas/almacen.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/metricas/analytics_changes.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/metricas/analytics_cli.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/metricas/analytics_client.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/metricas/analytics_ingest.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/metricas/analytics_schema.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/metricas/base.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/metricas/facebook.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/metricas/insights.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/metricas/instagram.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/metricas/modelos.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/metricas/piezas.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/metricas/reach.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/metricas/reporting_client.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/metricas/resumen.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/metricas/slugs.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/metricas/tiktok.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/metricas/youtube.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/migration_cli.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/migration_files.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/models.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/native_schedule/__init__.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/native_schedule/api_delivery.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/native_schedule/api_reconcile.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/native_schedule/approval.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/native_schedule/cadence.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/native_schedule/cli.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/native_schedule/dispatcher.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/native_schedule/facebook.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/native_schedule/facebook_reels.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/native_schedule/first_comment.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/native_schedule/handoff.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/native_schedule/instagram_delivery.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/native_schedule/instagram_runtime.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/native_schedule/inventory.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/native_schedule/migration.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/native_schedule/models.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/native_schedule/reconcile.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/native_schedule/remote_data.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/native_schedule/report.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/native_schedule/store.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/native_schedule/verification.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/native_schedule/youtube.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/plantillas/accounts.yml +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/plantillas/brand.md +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/plantillas/estrategia.md +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/preflight.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/publication_policy.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/publication_status.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/publication_steps.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/publish_output.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/publisher.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/queue_migration.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/read_budget.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/rutas.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/schedule_remote.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/schedule_sqlite.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/scheduler.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/scheduler_launchd.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/scheduler_systemd.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/source_links.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/ui/__init__.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/upload_consent.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/workspace.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/youtube_data.py +0 -0
- {socialcli-0.3.0 → socialcli-0.3.2}/socialctl/youtube_data_service.py +0 -0
socialcli-0.3.2/LICENSE
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
SocialCli Proprietary Software License
|
|
2
|
+
Version 1 — October 24, 2026
|
|
3
|
+
Copyright (c) 2026 Engels Florentino. All rights reserved.
|
|
4
|
+
SocialCli is operated by Florentino.pro.
|
|
5
|
+
|
|
6
|
+
1. Scope
|
|
7
|
+
This license applies to SocialCli releases beginning with version 0.3.2 and
|
|
8
|
+
subsequent releases that include this license. It does not revoke or restrict
|
|
9
|
+
rights already granted for earlier MIT-licensed releases. The historical MIT
|
|
10
|
+
notice is preserved in LICENSE-MIT-LEGACY. Third-party components remain subject
|
|
11
|
+
to their own licenses; this license does not replace those terms.
|
|
12
|
+
|
|
13
|
+
2. Authorized client use
|
|
14
|
+
You may download, install, run and make necessary backup copies of the official
|
|
15
|
+
SocialCli client to access the SocialCli hosted service through an authorized
|
|
16
|
+
account. You may use it for your personal or business social accounts, including
|
|
17
|
+
accounts you are authorized to manage for clients. You may let your authorized
|
|
18
|
+
AI agents operate the client under your supervision and the same account terms.
|
|
19
|
+
Service access requires an eligible trial, subscription or other access expressly
|
|
20
|
+
granted by Florentino.pro. Installing the client does not grant service access,
|
|
21
|
+
provider credentials, unlimited usage or ownership of the software.
|
|
22
|
+
|
|
23
|
+
3. Reserved rights
|
|
24
|
+
Except as expressly allowed above, required by applicable law, or separately
|
|
25
|
+
agreed in writing by the copyright holder, you may not redistribute, sublicense,
|
|
26
|
+
sell, rent or offer this software as a service; modify or use it to build or run
|
|
27
|
+
a competing product or hosted service; bypass access, subscription or security
|
|
28
|
+
controls; or remove copyright, license or attribution notices. No license to the
|
|
29
|
+
private server implementation is granted to customers. No trademark rights in
|
|
30
|
+
SocialCli or Florentino.pro are granted. You retain your rights in your content
|
|
31
|
+
and data. These restrictions do not limit rights separately granted under the
|
|
32
|
+
legacy MIT license or a third-party license.
|
|
33
|
+
|
|
34
|
+
4. Service terms
|
|
35
|
+
Use of the hosted service is also subject to https://socialcli.app/terms.html.
|
|
36
|
+
Your subscription pays for service access, not ownership of or redistribution
|
|
37
|
+
rights to the software. Account eligibility and access are determined by the
|
|
38
|
+
service, not by a local client setting.
|
|
39
|
+
|
|
40
|
+
5. Warranty and liability
|
|
41
|
+
To the maximum extent permitted by applicable law, this software is provided
|
|
42
|
+
"AS IS", without warranties of any kind, including merchantability, fitness
|
|
43
|
+
for a particular purpose and noninfringement. The copyright holder and operator
|
|
44
|
+
are not liable for indirect, incidental, special or consequential damages
|
|
45
|
+
arising from use of the software. Nothing in this license excludes or limits
|
|
46
|
+
rights, remedies or liabilities that cannot lawfully be excluded or limited.
|
|
47
|
+
|
|
48
|
+
For additional permissions, contact admin@socialcli.app.
|
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: socialcli
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: SocialCli: publish and manage creator-owned social content from the terminal.
|
|
5
5
|
Project-URL: Homepage, https://socialcli.app
|
|
6
|
-
Project-URL:
|
|
7
|
-
Project-URL:
|
|
8
|
-
License-Expression:
|
|
6
|
+
Project-URL: Documentation, https://socialcli.app/ai-agents.html
|
|
7
|
+
Project-URL: Terms, https://socialcli.app/terms.html
|
|
8
|
+
License-Expression: LicenseRef-SocialCli-Proprietary
|
|
9
9
|
License-File: LICENSE
|
|
10
|
+
License-File: LICENSE-MIT-LEGACY
|
|
10
11
|
Requires-Python: >=3.11
|
|
11
12
|
Requires-Dist: httpx>=0.28.1
|
|
12
13
|
Requires-Dist: keyring>=25.0
|
|
13
14
|
Requires-Dist: pydantic>=2.13.5
|
|
14
15
|
Requires-Dist: pyyaml>=6.0.3
|
|
15
16
|
Requires-Dist: typer>=0.27.2
|
|
16
|
-
Provides-Extra: connection-server
|
|
17
|
-
Requires-Dist: cryptography>=43; extra == 'connection-server'
|
|
18
|
-
Requires-Dist: fastapi>=0.115; extra == 'connection-server'
|
|
19
|
-
Requires-Dist: uvicorn>=0.30; extra == 'connection-server'
|
|
20
17
|
Provides-Extra: headless-credentials
|
|
21
18
|
Requires-Dist: cryptography>=43; extra == 'headless-credentials'
|
|
22
19
|
Description-Content-Type: text/markdown
|
|
@@ -25,7 +22,7 @@ Description-Content-Type: text/markdown
|
|
|
25
22
|
|
|
26
23
|
# SocialCli
|
|
27
24
|
|
|
28
|
-
**Current
|
|
25
|
+
**Current stable version: 0.3.1 (published on PyPI). Source preparation: 0.3.2.** SocialCli SaaS is the current SocialCli
|
|
29
26
|
product. The repository root on `main` is its single development workspace;
|
|
30
27
|
the CLI, hosted connection service and account/billing components live together
|
|
31
28
|
here. Earlier versions remain in Git history for reference and migration.
|
|
@@ -61,9 +58,9 @@ Stripe uses test mode. Planned access costs
|
|
|
61
58
|
USD 10/month after 14 free days from the first successful connection. No real
|
|
62
59
|
subscriptions are collected in this pilot.
|
|
63
60
|
|
|
64
|
-
The current client
|
|
65
|
-
|
|
66
|
-
|
|
61
|
+
The current stable client is **0.3.1**, published on TestPyPI and PyPI after
|
|
62
|
+
reviewed CI, matching artifact hashes and clean-install verification.
|
|
63
|
+
The hosted service is managed and verified separately from the CLI release. The client's wheel and
|
|
67
64
|
source archive are verified against the
|
|
68
65
|
reviewed build hashes before publication. Provider commercial approvals and live
|
|
69
66
|
billing cutover remain separate from package publication. See the
|
|
@@ -141,7 +138,9 @@ Metrics and management permissions are separate from publishing permissions. A v
|
|
|
141
138
|
|
|
142
139
|
Read [CONTRIBUTING.md](CONTRIBUTING.md). For questions or bugs, open an [issue](https://github.com/engels-florentino/SocialCli/issues) without tokens, keys, `.env` files or private logs. Report vulnerabilities through the private channel described in [SECURITY.md](SECURITY.md).
|
|
143
140
|
|
|
144
|
-
[
|
|
141
|
+
[Proprietary license](LICENSE) for 0.3.2 and later. Earlier releases retain their
|
|
142
|
+
[MIT license](LICENSE-MIT-LEGACY). The hosted server is private and is not included
|
|
143
|
+
in public client distributions. SocialCli is not affiliated with the platforms it integrates.
|
|
145
144
|
|
|
146
145
|
## Account, media and scheduling
|
|
147
146
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# SocialCli
|
|
4
4
|
|
|
5
|
-
**Current
|
|
5
|
+
**Current stable version: 0.3.1 (published on PyPI). Source preparation: 0.3.2.** SocialCli SaaS is the current SocialCli
|
|
6
6
|
product. The repository root on `main` is its single development workspace;
|
|
7
7
|
the CLI, hosted connection service and account/billing components live together
|
|
8
8
|
here. Earlier versions remain in Git history for reference and migration.
|
|
@@ -38,9 +38,9 @@ Stripe uses test mode. Planned access costs
|
|
|
38
38
|
USD 10/month after 14 free days from the first successful connection. No real
|
|
39
39
|
subscriptions are collected in this pilot.
|
|
40
40
|
|
|
41
|
-
The current client
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
The current stable client is **0.3.1**, published on TestPyPI and PyPI after
|
|
42
|
+
reviewed CI, matching artifact hashes and clean-install verification.
|
|
43
|
+
The hosted service is managed and verified separately from the CLI release. The client's wheel and
|
|
44
44
|
source archive are verified against the
|
|
45
45
|
reviewed build hashes before publication. Provider commercial approvals and live
|
|
46
46
|
billing cutover remain separate from package publication. See the
|
|
@@ -118,7 +118,9 @@ Metrics and management permissions are separate from publishing permissions. A v
|
|
|
118
118
|
|
|
119
119
|
Read [CONTRIBUTING.md](CONTRIBUTING.md). For questions or bugs, open an [issue](https://github.com/engels-florentino/SocialCli/issues) without tokens, keys, `.env` files or private logs. Report vulnerabilities through the private channel described in [SECURITY.md](SECURITY.md).
|
|
120
120
|
|
|
121
|
-
[
|
|
121
|
+
[Proprietary license](LICENSE) for 0.3.2 and later. Earlier releases retain their
|
|
122
|
+
[MIT license](LICENSE-MIT-LEGACY). The hosted server is private and is not included
|
|
123
|
+
in public client distributions. SocialCli is not affiliated with the platforms it integrates.
|
|
122
124
|
|
|
123
125
|
## Account, media and scheduling
|
|
124
126
|
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "socialcli"
|
|
3
|
+
version = "0.3.2"
|
|
4
|
+
description = "SocialCli: publish and manage creator-owned social content from the terminal."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "LicenseRef-SocialCli-Proprietary"
|
|
7
|
+
license-files = ["LICENSE", "LICENSE-MIT-LEGACY"]
|
|
8
|
+
requires-python = ">=3.11"
|
|
9
|
+
dependencies = [
|
|
10
|
+
"httpx>=0.28.1",
|
|
11
|
+
"keyring>=25.0",
|
|
12
|
+
"pydantic>=2.13.5",
|
|
13
|
+
"pyyaml>=6.0.3",
|
|
14
|
+
"typer>=0.27.2",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[project.scripts]
|
|
18
|
+
socialcli = "socialctl.cli:app"
|
|
19
|
+
socialctl = "socialctl.cli:app"
|
|
20
|
+
|
|
21
|
+
[project.urls]
|
|
22
|
+
Homepage = "https://socialcli.app"
|
|
23
|
+
Documentation = "https://socialcli.app/ai-agents.html"
|
|
24
|
+
Terms = "https://socialcli.app/terms.html"
|
|
25
|
+
|
|
26
|
+
[project.optional-dependencies]
|
|
27
|
+
headless-credentials = ["cryptography>=43"]
|
|
28
|
+
|
|
29
|
+
[dependency-groups]
|
|
30
|
+
dev = [
|
|
31
|
+
"cryptography>=43",
|
|
32
|
+
"fastapi>=0.115",
|
|
33
|
+
"pytest>=9.1.1",
|
|
34
|
+
"respx>=0.23.1",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
[build-system]
|
|
38
|
+
requires = ["hatchling>=1.27"]
|
|
39
|
+
build-backend = "hatchling.build"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# Public client boundary. New modules require explicit review before distribution.
|
|
43
|
+
[tool.hatch.build]
|
|
44
|
+
only-include = [
|
|
45
|
+
"socialctl/__init__.py",
|
|
46
|
+
"socialctl/__main__.py",
|
|
47
|
+
"socialctl/agent_errors.py",
|
|
48
|
+
"socialctl/agent_guide.py",
|
|
49
|
+
"socialctl/approval_cli.py",
|
|
50
|
+
"socialctl/auth.py",
|
|
51
|
+
"socialctl/authflow.py",
|
|
52
|
+
"socialctl/brands.py",
|
|
53
|
+
"socialctl/capabilities.py",
|
|
54
|
+
"socialctl/cli.py",
|
|
55
|
+
"socialctl/delivery_options.py",
|
|
56
|
+
"socialctl/engagement.py",
|
|
57
|
+
"socialctl/engagement_cli.py",
|
|
58
|
+
"socialctl/executor.py",
|
|
59
|
+
"socialctl/formatter.py",
|
|
60
|
+
"socialctl/hosted_media.py",
|
|
61
|
+
"socialctl/identity.py",
|
|
62
|
+
"socialctl/inbox.py",
|
|
63
|
+
"socialctl/inbox_cli.py",
|
|
64
|
+
"socialctl/inventory.py",
|
|
65
|
+
"socialctl/inventory_cli.py",
|
|
66
|
+
"socialctl/inventory_sources.py",
|
|
67
|
+
"socialctl/media.py",
|
|
68
|
+
"socialctl/media_cli.py",
|
|
69
|
+
"socialctl/media_ingress.py",
|
|
70
|
+
"socialctl/media_preflight.py",
|
|
71
|
+
"socialctl/media_registry.py",
|
|
72
|
+
"socialctl/media_requirements.py",
|
|
73
|
+
"socialctl/migration_cli.py",
|
|
74
|
+
"socialctl/migration_files.py",
|
|
75
|
+
"socialctl/models.py",
|
|
76
|
+
"socialctl/operation_output.py",
|
|
77
|
+
"socialctl/postfile.py",
|
|
78
|
+
"socialctl/preflight.py",
|
|
79
|
+
"socialctl/publication_policy.py",
|
|
80
|
+
"socialctl/publication_status.py",
|
|
81
|
+
"socialctl/publication_steps.py",
|
|
82
|
+
"socialctl/publish_output.py",
|
|
83
|
+
"socialctl/publisher.py",
|
|
84
|
+
"socialctl/queue_migration.py",
|
|
85
|
+
"socialctl/read_budget.py",
|
|
86
|
+
"socialctl/read_reports.py",
|
|
87
|
+
"socialctl/rutas.py",
|
|
88
|
+
"socialctl/schedule_remote.py",
|
|
89
|
+
"socialctl/schedule_sqlite.py",
|
|
90
|
+
"socialctl/scheduler.py",
|
|
91
|
+
"socialctl/scheduler_launchd.py",
|
|
92
|
+
"socialctl/scheduler_systemd.py",
|
|
93
|
+
"socialctl/source_links.py",
|
|
94
|
+
"socialctl/upload_consent.py",
|
|
95
|
+
"socialctl/workspace.py",
|
|
96
|
+
"socialctl/youtube_data.py",
|
|
97
|
+
"socialctl/youtube_data_service.py",
|
|
98
|
+
"socialctl/adapters",
|
|
99
|
+
"socialctl/connections",
|
|
100
|
+
"socialctl/management",
|
|
101
|
+
"socialctl/metricas",
|
|
102
|
+
"socialctl/native_schedule",
|
|
103
|
+
"socialctl/plantillas",
|
|
104
|
+
"socialctl/capabilities.yml",
|
|
105
|
+
"socialctl/ui/__init__.py",
|
|
106
|
+
"socialctl/ui/assets/agents.md",
|
|
107
|
+
"socialctl/ui/assets/agent-manual.md"
|
|
108
|
+
]
|
|
109
|
+
exclude = ["**/.env", "**/.env.*", "**/*.env", "**/.secrets/**", "**/__pycache__/**", "**/*.pyc", "**/*.key", "**/*.pem", "**/*.sqlite3*"]
|
|
110
|
+
|
|
111
|
+
[tool.hatch.build.targets.wheel]
|
|
112
|
+
dev-mode-dirs = ["."]
|
|
113
|
+
|
|
114
|
+
[tool.hatch.build.targets.sdist]
|
|
115
|
+
only-include = [
|
|
116
|
+
"socialctl/__init__.py",
|
|
117
|
+
"socialctl/__main__.py",
|
|
118
|
+
"socialctl/agent_errors.py",
|
|
119
|
+
"socialctl/agent_guide.py",
|
|
120
|
+
"socialctl/approval_cli.py",
|
|
121
|
+
"socialctl/auth.py",
|
|
122
|
+
"socialctl/authflow.py",
|
|
123
|
+
"socialctl/brands.py",
|
|
124
|
+
"socialctl/capabilities.py",
|
|
125
|
+
"socialctl/cli.py",
|
|
126
|
+
"socialctl/delivery_options.py",
|
|
127
|
+
"socialctl/engagement.py",
|
|
128
|
+
"socialctl/engagement_cli.py",
|
|
129
|
+
"socialctl/executor.py",
|
|
130
|
+
"socialctl/formatter.py",
|
|
131
|
+
"socialctl/hosted_media.py",
|
|
132
|
+
"socialctl/identity.py",
|
|
133
|
+
"socialctl/inbox.py",
|
|
134
|
+
"socialctl/inbox_cli.py",
|
|
135
|
+
"socialctl/inventory.py",
|
|
136
|
+
"socialctl/inventory_cli.py",
|
|
137
|
+
"socialctl/inventory_sources.py",
|
|
138
|
+
"socialctl/media.py",
|
|
139
|
+
"socialctl/media_cli.py",
|
|
140
|
+
"socialctl/media_ingress.py",
|
|
141
|
+
"socialctl/media_preflight.py",
|
|
142
|
+
"socialctl/media_registry.py",
|
|
143
|
+
"socialctl/media_requirements.py",
|
|
144
|
+
"socialctl/migration_cli.py",
|
|
145
|
+
"socialctl/migration_files.py",
|
|
146
|
+
"socialctl/models.py",
|
|
147
|
+
"socialctl/operation_output.py",
|
|
148
|
+
"socialctl/postfile.py",
|
|
149
|
+
"socialctl/preflight.py",
|
|
150
|
+
"socialctl/publication_policy.py",
|
|
151
|
+
"socialctl/publication_status.py",
|
|
152
|
+
"socialctl/publication_steps.py",
|
|
153
|
+
"socialctl/publish_output.py",
|
|
154
|
+
"socialctl/publisher.py",
|
|
155
|
+
"socialctl/queue_migration.py",
|
|
156
|
+
"socialctl/read_budget.py",
|
|
157
|
+
"socialctl/read_reports.py",
|
|
158
|
+
"socialctl/rutas.py",
|
|
159
|
+
"socialctl/schedule_remote.py",
|
|
160
|
+
"socialctl/schedule_sqlite.py",
|
|
161
|
+
"socialctl/scheduler.py",
|
|
162
|
+
"socialctl/scheduler_launchd.py",
|
|
163
|
+
"socialctl/scheduler_systemd.py",
|
|
164
|
+
"socialctl/source_links.py",
|
|
165
|
+
"socialctl/upload_consent.py",
|
|
166
|
+
"socialctl/workspace.py",
|
|
167
|
+
"socialctl/youtube_data.py",
|
|
168
|
+
"socialctl/youtube_data_service.py",
|
|
169
|
+
"socialctl/adapters",
|
|
170
|
+
"socialctl/connections",
|
|
171
|
+
"socialctl/management",
|
|
172
|
+
"socialctl/metricas",
|
|
173
|
+
"socialctl/native_schedule",
|
|
174
|
+
"socialctl/plantillas",
|
|
175
|
+
"socialctl/capabilities.yml",
|
|
176
|
+
"socialctl/ui/__init__.py",
|
|
177
|
+
"socialctl/ui/assets/agents.md",
|
|
178
|
+
"socialctl/ui/assets/agent-manual.md",
|
|
179
|
+
"pyproject.toml",
|
|
180
|
+
"README.md",
|
|
181
|
+
"LICENSE",
|
|
182
|
+
"LICENSE-MIT-LEGACY"
|
|
183
|
+
]
|
|
@@ -32,6 +32,10 @@ _ACTIONS = {
|
|
|
32
32
|
# Only fixed internal codes acquire action semantics. Provider text is diagnostic,
|
|
33
33
|
# never a command, an expiry signal or evidence that a write was not accepted.
|
|
34
34
|
_CATALOG = {
|
|
35
|
+
'reply_history_purged': ('user_action', 'Prior reply evidence was removed by retention. Review the preserved journal and platform before any new draft. Do not delete replay-blocking markers or repeat an uncertain write.'),
|
|
36
|
+
'dry_run_required': ('correct_input', 'inbox-draft requires --dry-run to prepare a preview. No provider content write was started.'),
|
|
37
|
+
'reply_input_invalid': ('correct_input', 'Use a version 1 reply file with a nonempty replies list (1–100 items). Each reply requires platform, account_id, comment_id and text. media_id is read from the inbox, not supplied in this file.'),
|
|
38
|
+
'target_validation_failed': ('inspect', 'Local target verification failed. Inspect the diagnostic reason; this does not establish a provider rejection or invalid credentials.'),
|
|
35
39
|
'approval_mismatch': ('user_action', 'The supplied approval does not match this exact preview. Obtain the owner approval before applying.'),
|
|
36
40
|
'approval_required': ('user_action', 'Show the complete preview and obtain explicit approval of its exact fingerprint.'),
|
|
37
41
|
'operation_cancelled': ('inspect', 'Approval was cancelled. No write was started by this command.'),
|
|
@@ -108,6 +112,7 @@ def error_document(exc: BaseException, *, read_only: bool) -> dict:
|
|
|
108
112
|
from socialctl.management.meta_schema import MetaError, MetaUncertain
|
|
109
113
|
from socialctl.metricas.base import SinPermiso
|
|
110
114
|
from socialctl.youtube_data import YouTubeDataBusy, YouTubeDataCleanupError
|
|
115
|
+
from socialctl.identity import ReadError
|
|
111
116
|
|
|
112
117
|
# A read flow may refresh a token via POST. A lost response to that operation
|
|
113
118
|
# cannot be classified as a harmless GET retry merely from the CLI command.
|
|
@@ -124,7 +129,7 @@ def error_document(exc: BaseException, *, read_only: bool) -> dict:
|
|
|
124
129
|
429:'rate_limited',503:'provider_unavailable'}.get(exc.status,'service_rejected')
|
|
125
130
|
elif isinstance(exc, (ResourceUncertain, YouTubeUpdateUncertain, CommentUncertain, MetaUncertain)):
|
|
126
131
|
code = 'operation_uncertain'
|
|
127
|
-
elif isinstance(exc, (AuthError, YouTubeManagementError, ResourceError, CommentError, MetaError)) and getattr(exc, '_socialcli_error_code', None) is not None:
|
|
132
|
+
elif isinstance(exc, (AuthError, YouTubeManagementError, ChangeError, ResourceError, CommentError, MetaError, ReadError)) and getattr(exc, '_socialcli_error_code', None) is not None:
|
|
128
133
|
code = exc._socialcli_error_code
|
|
129
134
|
elif isinstance(exc, ReadDeadlineExceeded): code = 'read_deadline'
|
|
130
135
|
elif isinstance(exc, ReadResponseTooLarge): code = 'response_too_large'
|
|
@@ -144,21 +149,66 @@ def error_document(exc: BaseException, *, read_only: bool) -> dict:
|
|
|
144
149
|
429:'rate_limited'}.get(status,'provider_unavailable' if status>=500 else 'request_rejected')
|
|
145
150
|
if type(status) is int else 'operation_rejected')
|
|
146
151
|
elif isinstance(exc, httpx.RequestError): code = 'provider_response_invalid'
|
|
152
|
+
elif isinstance(exc, ReadError):
|
|
153
|
+
code = {'credentials_missing': 'authorization_unavailable', 'credentials_expired': 'authorization_unavailable',
|
|
154
|
+
'permission_denied': 'permissions_required', 'rate_limited': 'rate_limited',
|
|
155
|
+
'timeout': 'transport_failure', 'transport_error': 'transport_failure',
|
|
156
|
+
'invalid_response': 'provider_response_invalid', 'provider_error': 'provider_unavailable',
|
|
157
|
+
'configuration_missing': 'account_not_configured'}.get(exc.code, 'target_validation_failed')
|
|
158
|
+
elif isinstance(exc, ResourceError): code = 'target_validation_failed'
|
|
147
159
|
elif isinstance(exc, ChangeError): code = 'operation_rejected'
|
|
148
160
|
elif isinstance(exc, YouTubeDataBusy): code = 'local_data_busy'
|
|
149
161
|
elif isinstance(exc, (OSError, YouTubeDataCleanupError)): code = 'storage_failure'
|
|
150
162
|
elif isinstance(exc, ValueError): code = 'invalid_local_state'
|
|
151
163
|
else: code = 'operation_failed'
|
|
152
|
-
|
|
164
|
+
result = error_for_code(code,read_only=read_only)
|
|
165
|
+
# Local validation is not evidence of a rejection by the hosted service.
|
|
166
|
+
if code == 'operation_rejected' and not isinstance(exc, ServiceRejected):
|
|
167
|
+
result['message'] = _CATALOG[code][1]
|
|
168
|
+
diagnostic = safe_diagnostic(getattr(exc, '_socialcli_diagnostic', None))
|
|
169
|
+
if isinstance(exc, ChangeError) and not diagnostic:
|
|
170
|
+
diagnostic = {'source': 'local'}
|
|
171
|
+
if isinstance(exc, ServiceRejected):
|
|
172
|
+
diagnostic.update(source='socialcli', http_status=exc.status)
|
|
173
|
+
elif isinstance(exc, httpx.HTTPStatusError):
|
|
174
|
+
diagnostic.update(http_status=exc.response.status_code, request_method=exc.request.method)
|
|
175
|
+
if diagnostic:
|
|
176
|
+
result['diagnostic'] = safe_diagnostic(diagnostic)
|
|
177
|
+
return result
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def safe_diagnostic(value):
|
|
181
|
+
"""Allow only fixed machine labels, never URLs, bodies, headers or prose."""
|
|
182
|
+
if not isinstance(value, dict):
|
|
183
|
+
return {}
|
|
184
|
+
allowed = {
|
|
185
|
+
'source': {'local', 'socialcli', 'youtube'},
|
|
186
|
+
'stage': {'input_validation', 'workspace_read', 'file_read', 'credential_read', 'identity_read', 'provider_read', 'provider_write', 'target_read', 'reply_coverage', 'proposal_preparation', 'baseline_check', 'readback'},
|
|
187
|
+
'request_method': {'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE'},
|
|
188
|
+
'operation': {'channels', 'videos', 'comments', 'commentThreads', 'playlistItems'},
|
|
189
|
+
'write_state': {'not_started', 'unknown', 'accepted'},
|
|
190
|
+
'content_write_state': {'not_started'},
|
|
191
|
+
'reason': {'thread_unverifiable', 'thread_identity_mismatch', 'thread_total_unverifiable', 'comment_binding_mismatch', 'parent_mismatch', 'replies_not_allowed', 'incomplete_reply_list', 'readback_mismatch'},
|
|
192
|
+
'provider_reason': {'commentsDisabled', 'quotaExceeded', 'dailyLimitExceeded', 'rateLimitExceeded', 'userRateLimitExceeded', 'insufficientPermissions', 'forbidden', 'authError', 'invalidValue', 'videoNotFound', 'commentNotFound', 'commentThreadNotFound', 'processingFailure', 'operationNotSupported'},
|
|
193
|
+
}
|
|
194
|
+
clean = {key: val for key, val in value.items()
|
|
195
|
+
if key in allowed and isinstance(val, str) and val in allowed[key]}
|
|
196
|
+
status = value.get('http_status')
|
|
197
|
+
if type(status) is int and 100 <= status <= 599:
|
|
198
|
+
clean['http_status'] = status
|
|
199
|
+
return clean
|
|
153
200
|
|
|
154
201
|
|
|
155
202
|
def with_error_code(wrapper: Exception, cause: BaseException, *, read_only: bool,
|
|
156
203
|
fallback: str | None = None) -> Exception:
|
|
157
204
|
"""Keep only a fixed code across a sanitized wrapper, never raw exception data."""
|
|
158
|
-
|
|
205
|
+
detail = error_document(cause, read_only=read_only)
|
|
206
|
+
code = detail['code']
|
|
159
207
|
if code == 'operation_failed' and fallback is not None:
|
|
160
208
|
code = error_for_code(fallback, read_only=read_only)['code']
|
|
161
209
|
wrapper._socialcli_error_code = code
|
|
210
|
+
if detail.get('diagnostic'):
|
|
211
|
+
wrapper._socialcli_diagnostic = detail['diagnostic']
|
|
162
212
|
return wrapper
|
|
163
213
|
|
|
164
214
|
|
|
@@ -166,7 +216,28 @@ def with_http_error_code(wrapper: Exception, response, *, read_only: bool) -> Ex
|
|
|
166
216
|
import httpx
|
|
167
217
|
cause = httpx.HTTPStatusError('Provider request rejected', request=response.request,
|
|
168
218
|
response=response)
|
|
169
|
-
|
|
219
|
+
wrapper = with_error_code(wrapper, cause, read_only=read_only)
|
|
220
|
+
if response.request.url.host == 'www.googleapis.com':
|
|
221
|
+
diagnostic = {'source': 'youtube', 'http_status': response.status_code,
|
|
222
|
+
'request_method': response.request.method,
|
|
223
|
+
'stage': 'provider_read' if read_only else 'provider_write',
|
|
224
|
+
'operation': response.request.url.path.rsplit('/', 1)[-1],
|
|
225
|
+
'write_state': 'not_started' if read_only else 'unknown'}
|
|
226
|
+
try:
|
|
227
|
+
reasons = response.json().get('error', {}).get('errors', [])
|
|
228
|
+
for row in reasons[:16]:
|
|
229
|
+
reason = safe_diagnostic({'provider_reason': row.get('reason')}) if isinstance(row, dict) else {}
|
|
230
|
+
if reason:
|
|
231
|
+
diagnostic.update(reason)
|
|
232
|
+
if reason['provider_reason'] in {'quotaExceeded', 'dailyLimitExceeded', 'rateLimitExceeded', 'userRateLimitExceeded'}:
|
|
233
|
+
wrapper._socialcli_error_code = 'rate_limited' if read_only else 'operation_uncertain'
|
|
234
|
+
elif reason['provider_reason'] == 'commentsDisabled' and read_only:
|
|
235
|
+
wrapper._socialcli_error_code = 'comments_disabled'
|
|
236
|
+
break
|
|
237
|
+
except (ValueError, TypeError, AttributeError):
|
|
238
|
+
pass
|
|
239
|
+
wrapper._socialcli_diagnostic = safe_diagnostic(diagnostic)
|
|
240
|
+
return wrapper
|
|
170
241
|
|
|
171
242
|
|
|
172
243
|
def emit_error(exc: Exception, *, read_only: bool) -> None:
|
|
@@ -3,11 +3,11 @@ from importlib.resources import files
|
|
|
3
3
|
import re
|
|
4
4
|
|
|
5
5
|
TOPICS={
|
|
6
|
-
'setup':('Install the reviewed
|
|
6
|
+
'setup':('What agents can do','Install the reviewed release','Authorize the installation, then the social account','Persist and recover','Publication gate','Explicit approval and preflight'),
|
|
7
7
|
'publish':('Publication gate','Temporary Instagram media','Canonical publishing workflow','Check supplied media locally','Explicit approval and preflight'),
|
|
8
8
|
'schedule':('Publication gate','Temporary Instagram media','Scheduling and temporary media','Native scheduling input examples (offline)','Explicit approval and preflight'),
|
|
9
|
-
'inbox':('Publication gate','Read metrics and prepare engagement','Read diagnostics','Comment API
|
|
10
|
-
'errors':('Persist and recover','Recovery and error actions','Read diagnostics','Comment API
|
|
9
|
+
'inbox':('Publication gate','Read metrics and prepare engagement','Read diagnostics','Comment API evidence and limits','Explicit approval and preflight','Resumable batches and reply context','Purged reply history'),
|
|
10
|
+
'errors':('Persist and recover','Recovery and error actions','Read diagnostics','Comment API evidence and limits','Explicit approval and preflight','Resumable batches and reply context','Purged reply history'),
|
|
11
11
|
'permissions':('Installation connection access',),
|
|
12
12
|
}
|
|
13
13
|
|
|
@@ -20,4 +20,4 @@ def guide(topic):
|
|
|
20
20
|
sections=re.split(r'(?=^## )',full,flags=re.MULTILINE)
|
|
21
21
|
chosen=[section for section in sections if any(section.startswith('## '+heading) for heading in TOPICS[topic])]
|
|
22
22
|
return ('# SocialCli agent guide: '+topic+'\n\n'+''.join(chosen)+
|
|
23
|
-
'\nNext: socialcli agent-guide publish; socialcli agent-guide schedule; socialcli agent-guide inbox; socialcli agent-guide errors.\n')
|
|
23
|
+
'\nNext: socialcli agent-guide publish; socialcli agent-guide schedule; socialcli agent-guide inbox; socialcli agent-guide errors; socialcli agent-guide permissions; socialcli agent-guide all.\n')
|