bazaar-compute-node 0.2.0rc1__tar.gz → 0.2.0rc3__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.
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/PKG-INFO +5 -2
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/README.md +4 -1
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/pyproject.toml +1 -1
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/pyproject.toml.orig +1 -1
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/app/agent.py +9 -1
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/lark/api.py +33 -6
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/lark/approval.py +14 -4
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/lark/channel.py +26 -1
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/lark/outbound.py +7 -3
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/repository/messages.py +56 -2
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/storage.py +1 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/telegram/api.py +5 -2
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/telegram/approval.py +9 -3
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/telegram/channel.py +68 -1
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/telegram/identity.py +19 -3
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/telegram/outbound.py +2 -1
- bazaar_compute_node-0.2.0rc3/src/bazaar_compute_node/contrib/telegram/plugin.py +43 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/wecom/channel.py +14 -0
- bazaar_compute_node-0.2.0rc3/src/bazaar_compute_node/core/audit.py +153 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/channel.py +46 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/orchestration/command.py +83 -5
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/orchestration/delivery.py +5 -1
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/orchestration/error_feedback.py +1 -2
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/orchestration/orchestrator.py +5 -9
- bazaar_compute_node-0.2.0rc3/src/bazaar_compute_node/core/orchestration/services.py +30 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/orchestration/turn.py +1 -2
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/storage.py +21 -8
- bazaar_compute_node-0.2.0rc1/src/bazaar_compute_node/contrib/telegram/plugin.py +0 -23
- bazaar_compute_node-0.2.0rc1/src/bazaar_compute_node/core/audit.py +0 -70
- bazaar_compute_node-0.2.0rc1/src/bazaar_compute_node/core/orchestration/services.py +0 -118
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/LICENSE +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/__init__.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/app/__init__.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/app/agent_management.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/app/application.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/app/attachments.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/app/command.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/app/config.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/app/registry.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/app/resource_dispatch.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/app/system_service.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/app/transport.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/app/upgrade.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/app/usage.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/app/version_check.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/app/windows_pipe.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/app/wrapper.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/bcc.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/cli.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/cmd/__init__.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/cmd/bcc/__init__.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/cmd/bcc/_client.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/cmd/bcc/_format.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/cmd/bcc/inbox.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/cmd/bcc/message.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/cmd/bcc/node.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/cmd/bcc/reminder.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/cmd/bcc/thread.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/cmd/bcn/__init__.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/cmd/bcn/_options.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/cmd/bcn/_runner.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/cmd/bcn/agent.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/cmd/bcn/node.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/cmd/bcn/service.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/__init__.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/claude/__init__.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/claude/approval.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/claude/client.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/claude/events.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/claude/plugin.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/claude/process.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/claude/protocol.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/claude/runtime.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/codex/__init__.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/codex/approval.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/codex/client.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/codex/events.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/codex/plugin.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/codex/process.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/codex/protocol.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/codex/runtime.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/lark/__init__.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/lark/attachments.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/lark/frame.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/lark/identity.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/lark/plugin.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/lark/transport.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/logging/__init__.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/logging/audit.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/logging/plugin.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/__init__.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/codec.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/database.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/executor.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/__init__.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/model.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/registry.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/v01_initial_node_schema.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/v02_session_mapping_indexes.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/v03_message_log_indexes.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/v04_runtime_attempt_facts.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/v05_inbound_message_references.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/v06_inbound_message_reference_integrity.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/v07_inbound_provider_identity.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/v08_transient_stream_events.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/v09_remove_runtime_events.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/v10_add_outbound_attachments.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/v11_remove_runtime_session_mapping.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/v12_add_reminders.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/v13_add_agent_ownership.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/v14_add_inbox_discovery_indexes.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/v15_add_handoffs.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/v16_remove_outbound_drafts.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/v17_remove_agent_identity_triggers.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/v18_unify_messages.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/v19_reminder_system_messages.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/v20_remove_freshness_persistence.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/v21_remove_handoffs.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/v22_readable_targets.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/v23_persist_sender_identity.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/v24_persist_sender_display_name.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/v25_rename_sessions_to_threads.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/migrations/v26_remove_handoff_messages.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/plugin.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/reminder_codec.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/repository/__init__.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/repository/base.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/repository/facade.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/repository/reminders.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/sqlite/repository/sessions.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/telegram/__init__.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/telegram/attachments.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/telegram/markdown.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/wecom/__init__.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/wecom/outbound.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/contrib/wecom/plugin.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/__init__.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/actor.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/agent.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/approval.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/client.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/command.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/concurrency.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/correlation.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/inbox.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/instruction.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/lifecycle.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/models/__init__.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/models/entities.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/models/events.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/models/reminder.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/models/reminder_owner.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/models/states.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/observability.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/orchestration/__init__.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/orchestration/reminder.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/orchestration/reminder_command.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/orchestration/upgrade_notice.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/outcomes.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/paths.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/reminder.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/reminder_schedule.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/restart.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/runtime.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/timerwheel.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/utils/__init__.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/utils/clock.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/utils/line_reader.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/utils/markdown.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/utils/sanitization.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/core/utils/text.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/i18n/__init__.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/i18n/catalog.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/rendering.py +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/approval_no_person.tpl +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/bcc/check.tpl +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/bcc/error.tpl +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/bcc/inbox_check.tpl +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/bcc/read.tpl +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/bcc/reminder_list.tpl +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/bcc/reminder_mutation.tpl +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/bcc/reminder_schedule.tpl +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/bcc/unfollow.tpl +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/bcc/upgrade.tpl +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/bcc/version.tpl +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/command/attachment_suffix.tpl +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/command/check_message.tpl +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/command/freshness_hold.tpl +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/command/read_message.tpl +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/command/send_result.tpl +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/command/sender.tpl +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/developer_instructions.md +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/inbox_notice.tpl +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/locales/en.toml +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/locales/zh-CN.toml +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/system_service/launchd.plist +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/system_service/launchd.sh +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/system_service/systemd.service +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/system_service/windows.ps1 +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/system_service/windows.vbs +0 -0
- {bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/resources/system_service/windows.xml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bazaar-compute-node
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.0rc3
|
|
4
4
|
Summary: Runtime-agnostic computer node daemon for agents and channels.
|
|
5
5
|
License-Expression: AGPL-3.0-only
|
|
6
6
|
License-File: LICENSE
|
|
@@ -51,11 +51,14 @@ bcn --version
|
|
|
51
51
|
uv tool upgrade bazaar-compute-node
|
|
52
52
|
|
|
53
53
|
# Add an Agent / 添加 Agent
|
|
54
|
+
# allowed_sender_ids holds the Telegram user ids allowed to open a private chat
|
|
55
|
+
# allowed_sender_ids 是允许与其私聊的 Telegram 用户 id
|
|
54
56
|
bcn agent add \
|
|
55
57
|
--name Tifa \
|
|
56
58
|
--channel telegram \
|
|
57
59
|
--runtime codex \
|
|
58
|
-
--set channel.token_env=BCN_TELEGRAM_TIFA_TOKEN
|
|
60
|
+
--set channel.token_env=BCN_TELEGRAM_TIFA_TOKEN \
|
|
61
|
+
--set channel.allowed_sender_ids=[123456789]
|
|
59
62
|
|
|
60
63
|
# Configure the runtime environment / 配置运行时环境
|
|
61
64
|
# Example file content / 示例文件内容:
|
|
@@ -32,11 +32,14 @@ bcn --version
|
|
|
32
32
|
uv tool upgrade bazaar-compute-node
|
|
33
33
|
|
|
34
34
|
# Add an Agent / 添加 Agent
|
|
35
|
+
# allowed_sender_ids holds the Telegram user ids allowed to open a private chat
|
|
36
|
+
# allowed_sender_ids 是允许与其私聊的 Telegram 用户 id
|
|
35
37
|
bcn agent add \
|
|
36
38
|
--name Tifa \
|
|
37
39
|
--channel telegram \
|
|
38
40
|
--runtime codex \
|
|
39
|
-
--set channel.token_env=BCN_TELEGRAM_TIFA_TOKEN
|
|
41
|
+
--set channel.token_env=BCN_TELEGRAM_TIFA_TOKEN \
|
|
42
|
+
--set channel.allowed_sender_ids=[123456789]
|
|
40
43
|
|
|
41
44
|
# Configure the runtime environment / 配置运行时环境
|
|
42
45
|
# Example file content / 示例文件内容:
|
{bazaar_compute_node-0.2.0rc1 → bazaar_compute_node-0.2.0rc3}/src/bazaar_compute_node/app/agent.py
RENAMED
|
@@ -13,6 +13,7 @@ from functools import partial
|
|
|
13
13
|
from pathlib import Path
|
|
14
14
|
|
|
15
15
|
from ..core.actor import Actor, Actors, Agent, Thread
|
|
16
|
+
from ..core.audit import AuditRecorder
|
|
16
17
|
from ..core.channel import Channel, ChannelContext, IChannel
|
|
17
18
|
from ..core.concurrency import IThreadConcurrency, ThreadLockRegistry
|
|
18
19
|
from ..core.lifecycle import TimeoutBudget
|
|
@@ -28,6 +29,7 @@ from ..core.paths import resolve_workspace_dir
|
|
|
28
29
|
from ..core.runtime import IRuntime, RuntimeCommandContext
|
|
29
30
|
from ..core.storage import IStorageScope
|
|
30
31
|
from ..core.timerwheel import TimerWheel
|
|
32
|
+
from ..core.utils.clock import now_ms
|
|
31
33
|
from ..i18n import Translator
|
|
32
34
|
from .attachments import AttachmentMaterializer
|
|
33
35
|
from .command import CommandDispatchError
|
|
@@ -104,6 +106,11 @@ class AgentApplication:
|
|
|
104
106
|
self.workspace_path,
|
|
105
107
|
self._referenced_attachment_paths,
|
|
106
108
|
)
|
|
109
|
+
self._audit_recorder = AuditRecorder(
|
|
110
|
+
sink=audit,
|
|
111
|
+
timeout_budget=timeout_budget,
|
|
112
|
+
clock=now_ms,
|
|
113
|
+
)
|
|
107
114
|
provider_channel = factories.channel.build(
|
|
108
115
|
ChannelContext(
|
|
109
116
|
agent_id=self.agent_id,
|
|
@@ -112,6 +119,7 @@ class AgentApplication:
|
|
|
112
119
|
workspace=self.workspace_path,
|
|
113
120
|
translator=self.translator,
|
|
114
121
|
timer_wheel=self.timer_wheel,
|
|
122
|
+
audit=self._audit_recorder,
|
|
115
123
|
)
|
|
116
124
|
)
|
|
117
125
|
self.channel: IChannel = Channel(self.agent_id, provider_channel)
|
|
@@ -163,7 +171,7 @@ class AgentApplication:
|
|
|
163
171
|
channel=self.channel,
|
|
164
172
|
runtimes=self.runtimes,
|
|
165
173
|
storage=self.storage,
|
|
166
|
-
audit=self.
|
|
174
|
+
audit=self._audit_recorder,
|
|
167
175
|
timeout_budget=self.timeout_budget,
|
|
168
176
|
timer_wheel=self.timer_wheel,
|
|
169
177
|
runtime_idle_timeout_ms=(
|
|
@@ -15,6 +15,15 @@ import aiohttp
|
|
|
15
15
|
from ...core.timerwheel import TimerWheel
|
|
16
16
|
from ...core.utils.clock import remaining
|
|
17
17
|
|
|
18
|
+
|
|
19
|
+
@dataclass(frozen=True, slots=True)
|
|
20
|
+
class LarkSentMessage:
|
|
21
|
+
"""What the provider says about a message it just accepted."""
|
|
22
|
+
|
|
23
|
+
message_id: str
|
|
24
|
+
chat_id: str | None
|
|
25
|
+
|
|
26
|
+
|
|
18
27
|
_CONNECT_TIMEOUT_SECONDS = 10.0
|
|
19
28
|
_HTTP_METHODS = frozenset({"GET", "POST", "PUT", "DELETE"})
|
|
20
29
|
_MAX_ERROR_MESSAGE = 256
|
|
@@ -412,12 +421,13 @@ class LarkApi:
|
|
|
412
421
|
content: str,
|
|
413
422
|
uuid: str,
|
|
414
423
|
timeout: float,
|
|
415
|
-
|
|
424
|
+
receive_id_type: str = "chat_id",
|
|
425
|
+
) -> LarkSentMessage:
|
|
416
426
|
body = await self._post_json(
|
|
417
427
|
"message_create",
|
|
418
428
|
"/open-apis/im/v1/messages",
|
|
419
429
|
timeout=timeout,
|
|
420
|
-
params={"receive_id_type":
|
|
430
|
+
params={"receive_id_type": receive_id_type},
|
|
421
431
|
json_body={
|
|
422
432
|
"receive_id": chat_id,
|
|
423
433
|
"msg_type": message_type,
|
|
@@ -425,7 +435,10 @@ class LarkApi:
|
|
|
425
435
|
"uuid": uuid,
|
|
426
436
|
},
|
|
427
437
|
)
|
|
428
|
-
return
|
|
438
|
+
return LarkSentMessage(
|
|
439
|
+
message_id=_response_id(body, "message_create", "message_id"),
|
|
440
|
+
chat_id=_optional_response_text(body, "chat_id"),
|
|
441
|
+
)
|
|
429
442
|
|
|
430
443
|
async def reply_message(
|
|
431
444
|
self,
|
|
@@ -436,7 +449,7 @@ class LarkApi:
|
|
|
436
449
|
reply_in_thread: bool,
|
|
437
450
|
uuid: str,
|
|
438
451
|
timeout: float,
|
|
439
|
-
) ->
|
|
452
|
+
) -> LarkSentMessage:
|
|
440
453
|
body = await self._post_json(
|
|
441
454
|
"message_reply",
|
|
442
455
|
f"/open-apis/im/v1/messages/{quote(message_id, safe='')}/reply",
|
|
@@ -448,7 +461,10 @@ class LarkApi:
|
|
|
448
461
|
"uuid": uuid,
|
|
449
462
|
},
|
|
450
463
|
)
|
|
451
|
-
return
|
|
464
|
+
return LarkSentMessage(
|
|
465
|
+
message_id=_response_id(body, "message_reply", "message_id"),
|
|
466
|
+
chat_id=_optional_response_text(body, "chat_id"),
|
|
467
|
+
)
|
|
452
468
|
|
|
453
469
|
async def reply_card(
|
|
454
470
|
self,
|
|
@@ -458,7 +474,7 @@ class LarkApi:
|
|
|
458
474
|
reply_in_thread: bool,
|
|
459
475
|
uuid: str,
|
|
460
476
|
timeout: float,
|
|
461
|
-
) ->
|
|
477
|
+
) -> LarkSentMessage:
|
|
462
478
|
return await self.reply_message(
|
|
463
479
|
message_id=message_id,
|
|
464
480
|
message_type="interactive",
|
|
@@ -913,6 +929,17 @@ def _provider_message(value: object) -> str:
|
|
|
913
929
|
return value[:_MAX_ERROR_MESSAGE]
|
|
914
930
|
|
|
915
931
|
|
|
932
|
+
def _optional_response_text(
|
|
933
|
+
body: Mapping[str, object],
|
|
934
|
+
field_name: str,
|
|
935
|
+
) -> str | None:
|
|
936
|
+
data = body.get("data")
|
|
937
|
+
value = data.get(field_name) if isinstance(data, Mapping) else None
|
|
938
|
+
if not isinstance(value, str) or not value or "\r" in value or "\n" in value:
|
|
939
|
+
return None
|
|
940
|
+
return value
|
|
941
|
+
|
|
942
|
+
|
|
916
943
|
def _response_id(
|
|
917
944
|
body: Mapping[str, object],
|
|
918
945
|
method: str,
|
|
@@ -36,6 +36,7 @@ class _PendingApproval:
|
|
|
36
36
|
token: str
|
|
37
37
|
thread: LarkThreadIdentity
|
|
38
38
|
expected_sender_id: str
|
|
39
|
+
callback_chat_id: str
|
|
39
40
|
prompt_message_id: str | None
|
|
40
41
|
future: asyncio.Future[ApprovalResult]
|
|
41
42
|
|
|
@@ -135,6 +136,7 @@ class LarkApprovalChannel(LarkChannel):
|
|
|
135
136
|
token=secrets.token_urlsafe(18),
|
|
136
137
|
thread=thread,
|
|
137
138
|
expected_sender_id=request.provider_sender_id,
|
|
139
|
+
callback_chat_id=thread.chat_id,
|
|
138
140
|
prompt_message_id=None,
|
|
139
141
|
future=loop.create_future(),
|
|
140
142
|
)
|
|
@@ -154,7 +156,7 @@ class LarkApprovalChannel(LarkChannel):
|
|
|
154
156
|
)
|
|
155
157
|
budget = remaining(deadline)
|
|
156
158
|
if reply_to_message_id is not None:
|
|
157
|
-
|
|
159
|
+
sent = await api.reply_message(
|
|
158
160
|
message_id=reply_to_message_id,
|
|
159
161
|
message_type="interactive",
|
|
160
162
|
content=content,
|
|
@@ -163,14 +165,22 @@ class LarkApprovalChannel(LarkChannel):
|
|
|
163
165
|
timeout=budget,
|
|
164
166
|
)
|
|
165
167
|
else:
|
|
166
|
-
|
|
168
|
+
sent = await api.send_message(
|
|
167
169
|
chat_id=thread.chat_id,
|
|
170
|
+
# A one-to-one chat is named by the peer, so the id that
|
|
171
|
+
# addresses it is an `ou_`; card callbacks report the `oc_`
|
|
172
|
+
# the provider gave that chat, which only the send tells us.
|
|
173
|
+
receive_id_type=(
|
|
174
|
+
"open_id" if thread.chat_id.startswith("ou_") else "chat_id"
|
|
175
|
+
),
|
|
168
176
|
message_type="interactive",
|
|
169
177
|
content=content,
|
|
170
178
|
uuid=uuid4().hex,
|
|
171
179
|
timeout=budget,
|
|
172
180
|
)
|
|
173
|
-
|
|
181
|
+
if sent.chat_id is not None:
|
|
182
|
+
pending.callback_chat_id = sent.chat_id
|
|
183
|
+
prompt_message_id = _provider_text(sent.message_id)
|
|
174
184
|
if prompt_message_id is None:
|
|
175
185
|
raise ValueError("Lark approval prompt has no message_id")
|
|
176
186
|
if (
|
|
@@ -237,7 +247,7 @@ class LarkApprovalChannel(LarkChannel):
|
|
|
237
247
|
resolved_callback_text(self._translator, state),
|
|
238
248
|
toast_type="warning",
|
|
239
249
|
)
|
|
240
|
-
if chat_id != pending.
|
|
250
|
+
if chat_id != pending.callback_chat_id or (
|
|
241
251
|
pending.prompt_message_id is not None
|
|
242
252
|
and message_id != pending.prompt_message_id
|
|
243
253
|
):
|
|
@@ -17,6 +17,7 @@ from ...core.channel import (
|
|
|
17
17
|
ChannelDeliveryReceipt,
|
|
18
18
|
ChannelIdentity,
|
|
19
19
|
ChannelSendRequest,
|
|
20
|
+
DmAddress,
|
|
20
21
|
IChannel,
|
|
21
22
|
)
|
|
22
23
|
from ...core.models import (
|
|
@@ -414,7 +415,15 @@ class LarkChannel(IChannel):
|
|
|
414
415
|
)
|
|
415
416
|
thread_identity = LarkThreadIdentity(
|
|
416
417
|
bot_open_id=fields.identity.open_id,
|
|
417
|
-
|
|
418
|
+
# A one-to-one chat is named by the peer, not by the `oc_` id the
|
|
419
|
+
# provider gives that chat: the peer is the only part of it we can
|
|
420
|
+
# know before the chat exists, so a conversation opened from
|
|
421
|
+
# `dm:@name` and one the peer starts are the same conversation.
|
|
422
|
+
chat_id=(
|
|
423
|
+
fields.sender_open_id
|
|
424
|
+
if target_kind is ChannelTargetKind.DM
|
|
425
|
+
else fields.chat_id
|
|
426
|
+
),
|
|
418
427
|
thread_id=thread_id,
|
|
419
428
|
)
|
|
420
429
|
presentation = None
|
|
@@ -954,6 +963,20 @@ class LarkChannel(IChannel):
|
|
|
954
963
|
except LarkApiError, LarkTransportError, TimeoutError:
|
|
955
964
|
self._typing_failures += 1
|
|
956
965
|
|
|
966
|
+
def dm_address(
|
|
967
|
+
self, sender: SenderIdentity, *, sender_kind: SenderKind
|
|
968
|
+
) -> DmAddress | None:
|
|
969
|
+
del sender_kind
|
|
970
|
+
identity = self._identity
|
|
971
|
+
if identity is None or sender.id is None:
|
|
972
|
+
return None
|
|
973
|
+
thread = LarkThreadIdentity(bot_open_id=identity.open_id, chat_id=sender.id)
|
|
974
|
+
return DmAddress(
|
|
975
|
+
channel_session_id=thread.channel_session_id,
|
|
976
|
+
thread_id=thread.session_id,
|
|
977
|
+
provider_thread_id=thread.provider_thread_id,
|
|
978
|
+
)
|
|
979
|
+
|
|
957
980
|
async def send(
|
|
958
981
|
self,
|
|
959
982
|
request: ChannelSendRequest,
|
|
@@ -1089,6 +1112,7 @@ class _EventFields:
|
|
|
1089
1112
|
provider_message_id: str
|
|
1090
1113
|
chat_id: str
|
|
1091
1114
|
chat_type: str
|
|
1115
|
+
sender_open_id: str
|
|
1092
1116
|
sender_type: str
|
|
1093
1117
|
|
|
1094
1118
|
|
|
@@ -1147,6 +1171,7 @@ def _read_event(
|
|
|
1147
1171
|
provider_message_id=provider_message_id,
|
|
1148
1172
|
chat_id=chat_id,
|
|
1149
1173
|
chat_type=chat_type,
|
|
1174
|
+
sender_open_id=sender_open_id,
|
|
1150
1175
|
sender_type=sender_type,
|
|
1151
1176
|
)
|
|
1152
1177
|
|
|
@@ -375,7 +375,7 @@ async def _send_message_part(
|
|
|
375
375
|
return None, TimeoutError("Lark delivery deadline expired")
|
|
376
376
|
try:
|
|
377
377
|
if reply_anchor is not None:
|
|
378
|
-
|
|
378
|
+
sent = await api.reply_message(
|
|
379
379
|
message_id=reply_anchor,
|
|
380
380
|
message_type=message_type,
|
|
381
381
|
content=content,
|
|
@@ -384,8 +384,12 @@ async def _send_message_part(
|
|
|
384
384
|
timeout=timeout,
|
|
385
385
|
)
|
|
386
386
|
else:
|
|
387
|
-
|
|
387
|
+
sent = await api.send_message(
|
|
388
388
|
chat_id=thread.chat_id,
|
|
389
|
+
# Lark ids carry their kind in the prefix: `ou_` a user, `oc_` a chat.
|
|
390
|
+
receive_id_type=(
|
|
391
|
+
"open_id" if thread.chat_id.startswith("ou_") else "chat_id"
|
|
392
|
+
),
|
|
389
393
|
message_type=message_type,
|
|
390
394
|
content=content,
|
|
391
395
|
uuid=str(uuid4()),
|
|
@@ -395,7 +399,7 @@ async def _send_message_part(
|
|
|
395
399
|
raise
|
|
396
400
|
except Exception as error: # noqa: BLE001
|
|
397
401
|
return None, error
|
|
398
|
-
return
|
|
402
|
+
return sent.message_id, None
|
|
399
403
|
|
|
400
404
|
|
|
401
405
|
def _finish_failure(
|
|
@@ -21,7 +21,9 @@ from ....core.models import (
|
|
|
21
21
|
SenderKind,
|
|
22
22
|
)
|
|
23
23
|
from ....core.storage import (
|
|
24
|
+
AmbiguousInboxTargetError,
|
|
24
25
|
InboxTargetResolutionError,
|
|
26
|
+
KnownSender,
|
|
25
27
|
ResolvedInboxTarget,
|
|
26
28
|
UnreadMessageOwner,
|
|
27
29
|
)
|
|
@@ -331,9 +333,13 @@ class MessageOperations(RepositoryBase):
|
|
|
331
333
|
f"AND ({predicate}) ORDER BY thread.id",
|
|
332
334
|
parameters,
|
|
333
335
|
)
|
|
334
|
-
if len(rows)
|
|
336
|
+
if len(rows) > 1:
|
|
337
|
+
raise AmbiguousInboxTargetError(
|
|
338
|
+
"inbox target resolves to more than one owned session"
|
|
339
|
+
)
|
|
340
|
+
if not rows:
|
|
335
341
|
raise InboxTargetResolutionError(
|
|
336
|
-
"inbox target does not resolve to
|
|
342
|
+
"inbox target does not resolve to an owned session"
|
|
337
343
|
)
|
|
338
344
|
target = thread_from_row(rows[0])
|
|
339
345
|
channel_session = cast(
|
|
@@ -363,6 +369,54 @@ class MessageOperations(RepositoryBase):
|
|
|
363
369
|
handle_is_unique=handle_is_unique,
|
|
364
370
|
)
|
|
365
371
|
|
|
372
|
+
async def find_known_sender(self, token: str) -> KnownSender | None:
|
|
373
|
+
"""Find a sender this Agent has heard from, by what its `@` renders as.
|
|
374
|
+
|
|
375
|
+
`sender` carries the handle when the provider offers one and `sender_id`
|
|
376
|
+
the provider identity otherwise, which is the same order the `@` position
|
|
377
|
+
is rendered in. Matching follows that order so the more specific value
|
|
378
|
+
decides first. The display name is deliberately not a key: it is not
|
|
379
|
+
unique, and addressing by it would let one name reach several people.
|
|
380
|
+
"""
|
|
381
|
+
|
|
382
|
+
for predicate, parameter in (
|
|
383
|
+
("LOWER(sender) = LOWER(?)", token),
|
|
384
|
+
("sender_id = ?", token),
|
|
385
|
+
):
|
|
386
|
+
row = await self.fetchone(
|
|
387
|
+
"SELECT sender, sender_id, sender_display_name, channel, "
|
|
388
|
+
"metadata_json "
|
|
389
|
+
"FROM messages "
|
|
390
|
+
"WHERE agent_id = /*agent_id*/? "
|
|
391
|
+
"AND direction = ? "
|
|
392
|
+
f"AND {predicate} "
|
|
393
|
+
"ORDER BY seq DESC LIMIT 1",
|
|
394
|
+
(MessageDirection.INBOUND.value, parameter),
|
|
395
|
+
)
|
|
396
|
+
if row is None:
|
|
397
|
+
continue
|
|
398
|
+
sender = cast(str | None, row["sender"])
|
|
399
|
+
sender_id = cast(str | None, row["sender_id"])
|
|
400
|
+
if sender is None and sender_id is None:
|
|
401
|
+
continue
|
|
402
|
+
metadata_json = cast(str | None, row["metadata_json"])
|
|
403
|
+
sender_kind = SenderKind.UNKNOWN
|
|
404
|
+
if metadata_json:
|
|
405
|
+
stored_kind = json.loads(metadata_json).get(
|
|
406
|
+
"sender_kind", SenderKind.UNKNOWN.value
|
|
407
|
+
)
|
|
408
|
+
sender_kind = SenderKind(cast(str, stored_kind))
|
|
409
|
+
return KnownSender(
|
|
410
|
+
sender=SenderIdentity(
|
|
411
|
+
id=sender_id,
|
|
412
|
+
name=sender,
|
|
413
|
+
display_name=cast(str | None, row["sender_display_name"]),
|
|
414
|
+
),
|
|
415
|
+
channel=cast(str, row["channel"]),
|
|
416
|
+
sender_kind=sender_kind,
|
|
417
|
+
)
|
|
418
|
+
return None
|
|
419
|
+
|
|
366
420
|
async def find_message(
|
|
367
421
|
self,
|
|
368
422
|
channel: str,
|
|
@@ -87,12 +87,15 @@ class TelegramBotApi:
|
|
|
87
87
|
async def send_chat_action(
|
|
88
88
|
self,
|
|
89
89
|
*,
|
|
90
|
-
chat_id: int,
|
|
90
|
+
chat_id: int | str,
|
|
91
91
|
action: str,
|
|
92
92
|
message_thread_id: int | None = None,
|
|
93
93
|
timeout: float,
|
|
94
94
|
) -> None:
|
|
95
|
-
if
|
|
95
|
+
if isinstance(chat_id, str):
|
|
96
|
+
if not chat_id:
|
|
97
|
+
raise ValueError("Telegram chat_id text must be non-empty")
|
|
98
|
+
elif not isinstance(chat_id, int) or isinstance(chat_id, bool) or chat_id == 0:
|
|
96
99
|
raise ValueError("Telegram chat_id must be a non-zero integer")
|
|
97
100
|
if not isinstance(action, str) or not action:
|
|
98
101
|
raise ValueError("Telegram chat action must be non-empty")
|
|
@@ -27,7 +27,7 @@ _RESOLVED_TOKEN_LIMIT = 256
|
|
|
27
27
|
class _PendingApproval:
|
|
28
28
|
request_id: str
|
|
29
29
|
token: str
|
|
30
|
-
chat_id: int
|
|
30
|
+
chat_id: int | str
|
|
31
31
|
topic_id: int
|
|
32
32
|
markdown: str
|
|
33
33
|
prompt_message_id: int | None
|
|
@@ -36,8 +36,14 @@ class _PendingApproval:
|
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
class TelegramApprovalChannel(TelegramChannel):
|
|
39
|
-
def __init__(
|
|
40
|
-
|
|
39
|
+
def __init__(
|
|
40
|
+
self,
|
|
41
|
+
context: ChannelContext,
|
|
42
|
+
*,
|
|
43
|
+
token: str,
|
|
44
|
+
allowed_sender_ids: frozenset[int],
|
|
45
|
+
) -> None:
|
|
46
|
+
super().__init__(context, token=token, allowed_sender_ids=allowed_sender_ids)
|
|
41
47
|
self._translator: Translator = context.translator or create_translator(ENGLISH)
|
|
42
48
|
self._pending_approvals: dict[str, _PendingApproval] = {}
|
|
43
49
|
self._approval_tokens_by_request: dict[str, str] = {}
|
|
@@ -15,8 +15,10 @@ from ...core.channel import (
|
|
|
15
15
|
ChannelDeliveryReceipt,
|
|
16
16
|
ChannelIdentity,
|
|
17
17
|
ChannelSendRequest,
|
|
18
|
+
DmAddress,
|
|
18
19
|
IChannel,
|
|
19
20
|
)
|
|
21
|
+
from ...core.correlation import CorrelationContext
|
|
20
22
|
from ...core.models import (
|
|
21
23
|
ApprovalDecision,
|
|
22
24
|
ApprovalResult,
|
|
@@ -28,6 +30,7 @@ from ...core.models import (
|
|
|
28
30
|
InboundAttachment,
|
|
29
31
|
Message,
|
|
30
32
|
MessageDirection,
|
|
33
|
+
RuntimeEventState,
|
|
31
34
|
RuntimeOutputEvent,
|
|
32
35
|
SenderIdentity,
|
|
33
36
|
SenderKind,
|
|
@@ -44,6 +47,7 @@ from ...core.models import (
|
|
|
44
47
|
TurnUnknown,
|
|
45
48
|
UsageUpdated,
|
|
46
49
|
)
|
|
50
|
+
from ...core.observability import LogLevel
|
|
47
51
|
from ...core.outcomes import ProviderCallResult, ProviderCallStatus
|
|
48
52
|
from ...core.timerwheel import TimerWheel
|
|
49
53
|
from .api import TelegramApiError, TelegramBotApi, TelegramTransportError
|
|
@@ -95,9 +99,16 @@ class _InboundUpdate:
|
|
|
95
99
|
|
|
96
100
|
|
|
97
101
|
class TelegramChannel(IChannel):
|
|
98
|
-
def __init__(
|
|
102
|
+
def __init__(
|
|
103
|
+
self,
|
|
104
|
+
context: ChannelContext,
|
|
105
|
+
*,
|
|
106
|
+
token: str,
|
|
107
|
+
allowed_sender_ids: frozenset[int],
|
|
108
|
+
) -> None:
|
|
99
109
|
self._context = context
|
|
100
110
|
self._token = token
|
|
111
|
+
self._allowed_sender_ids = allowed_sender_ids
|
|
101
112
|
self._timer_wheel: TimerWheel | None = context.timer_wheel
|
|
102
113
|
self._started_at_s = time_ns() // 1_000_000_000
|
|
103
114
|
self._inbound: asyncio.Queue[Message | object] = asyncio.Queue()
|
|
@@ -431,6 +442,37 @@ class TelegramChannel(IChannel):
|
|
|
431
442
|
exc_info=(type(error), error, error.__traceback__),
|
|
432
443
|
)
|
|
433
444
|
|
|
445
|
+
def dm_address(
|
|
446
|
+
self, sender: SenderIdentity, *, sender_kind: SenderKind
|
|
447
|
+
) -> DmAddress | None:
|
|
448
|
+
bot_id = self._bot_id
|
|
449
|
+
if bot_id is None:
|
|
450
|
+
return None
|
|
451
|
+
chat_id: int | str
|
|
452
|
+
# sendMessage accepts an @username only for a bot, supergroup or
|
|
453
|
+
# channel; a person is still addressable by numeric id alone.
|
|
454
|
+
if sender_kind is SenderKind.AGENT and sender.name is not None:
|
|
455
|
+
chat_id = f"@{sender.name}"
|
|
456
|
+
# A message a channel or an anonymous admin posted to a group carries
|
|
457
|
+
# that chat's id and no `from`, so its kind is unknown; addressing it
|
|
458
|
+
# would publish the DM back into the group it came from.
|
|
459
|
+
elif (
|
|
460
|
+
sender_kind in {SenderKind.HUMAN, SenderKind.AGENT}
|
|
461
|
+
and sender.id is not None
|
|
462
|
+
):
|
|
463
|
+
try:
|
|
464
|
+
chat_id = int(sender.id)
|
|
465
|
+
except ValueError:
|
|
466
|
+
return None
|
|
467
|
+
else:
|
|
468
|
+
return None
|
|
469
|
+
identity = TelegramThreadIdentity(bot_id=bot_id, chat_id=chat_id, topic_id=0)
|
|
470
|
+
return DmAddress(
|
|
471
|
+
channel_session_id=identity.channel_session_id,
|
|
472
|
+
thread_id=identity.session_id,
|
|
473
|
+
provider_thread_id=identity.provider_thread_id,
|
|
474
|
+
)
|
|
475
|
+
|
|
434
476
|
async def send(
|
|
435
477
|
self,
|
|
436
478
|
request: ChannelSendRequest,
|
|
@@ -653,6 +695,31 @@ class TelegramChannel(IChannel):
|
|
|
653
695
|
chat_type = chat.get("type")
|
|
654
696
|
if chat_type not in {"private", "group", "supergroup"}:
|
|
655
697
|
return "unsupported_chat_type"
|
|
698
|
+
# Anyone on Telegram can open a private chat with a bot. A group has to
|
|
699
|
+
# be joined, so only the private case is closed here.
|
|
700
|
+
if chat_type == "private" and not (
|
|
701
|
+
isinstance(provider_sender, Mapping)
|
|
702
|
+
and provider_sender.get("id") in self._allowed_sender_ids
|
|
703
|
+
):
|
|
704
|
+
audit = self._context.audit
|
|
705
|
+
if audit is not None:
|
|
706
|
+
await audit.append(
|
|
707
|
+
event_name="channel.inbound.rejected",
|
|
708
|
+
state=RuntimeEventState.COMPLETED,
|
|
709
|
+
correlation=CorrelationContext(
|
|
710
|
+
node_id=self._context.agent_id,
|
|
711
|
+
channel=self.name,
|
|
712
|
+
),
|
|
713
|
+
level=LogLevel.WARNING,
|
|
714
|
+
metadata={
|
|
715
|
+
"reason": "unauthorized_sender",
|
|
716
|
+
"telegram_sender_id": provider_sender.get("id")
|
|
717
|
+
if isinstance(provider_sender, Mapping)
|
|
718
|
+
else None,
|
|
719
|
+
"telegram_chat_id": chat.get("id"),
|
|
720
|
+
},
|
|
721
|
+
)
|
|
722
|
+
return "unauthorized_sender"
|
|
656
723
|
chat_id = chat.get("id")
|
|
657
724
|
provider_message_id = message.get("message_id")
|
|
658
725
|
provider_time_s = message.get("date")
|
|
@@ -8,14 +8,24 @@ _PROVIDER_PREFIX = "telegram"
|
|
|
8
8
|
|
|
9
9
|
@dataclass(frozen=True, slots=True)
|
|
10
10
|
class TelegramThreadIdentity:
|
|
11
|
+
"""A Telegram conversation, addressed the way Telegram itself addresses it.
|
|
12
|
+
|
|
13
|
+
`chat_id` is the numeric id of a chat this bot has seen, or an `@username`
|
|
14
|
+
for a peer it has not: Bot API accepts either as `chat_id`, and a username
|
|
15
|
+
is the only address available before the first message arrives.
|
|
16
|
+
"""
|
|
17
|
+
|
|
11
18
|
bot_id: int
|
|
12
|
-
chat_id: int
|
|
19
|
+
chat_id: int | str
|
|
13
20
|
topic_id: int
|
|
14
21
|
|
|
15
22
|
def __post_init__(self) -> None:
|
|
16
23
|
if self.bot_id <= 0:
|
|
17
24
|
raise ValueError("Telegram bot_id must be positive")
|
|
18
|
-
if self.chat_id
|
|
25
|
+
if isinstance(self.chat_id, str):
|
|
26
|
+
if not self.chat_id.startswith("@") or len(self.chat_id) < 2:
|
|
27
|
+
raise ValueError("Telegram chat_id text must be an @username")
|
|
28
|
+
elif self.chat_id == 0:
|
|
19
29
|
raise ValueError("Telegram chat_id must be non-zero")
|
|
20
30
|
if self.topic_id < 0:
|
|
21
31
|
raise ValueError("Telegram topic_id must be non-negative")
|
|
@@ -56,12 +66,18 @@ def parse_provider_thread_id(value: str) -> TelegramThreadIdentity:
|
|
|
56
66
|
parts = value.split(":")
|
|
57
67
|
if len(parts) != 4 or parts[0] != _PROVIDER_PREFIX:
|
|
58
68
|
raise ValueError("Telegram provider_thread_id has invalid format")
|
|
69
|
+
chat_id: int | str = parts[2]
|
|
59
70
|
try:
|
|
60
|
-
bot_id
|
|
71
|
+
bot_id = int(parts[1])
|
|
72
|
+
topic_id = int(parts[3])
|
|
61
73
|
except ValueError as error:
|
|
62
74
|
raise ValueError(
|
|
63
75
|
"Telegram provider_thread_id contains invalid integers"
|
|
64
76
|
) from error
|
|
77
|
+
try:
|
|
78
|
+
chat_id = int(chat_id)
|
|
79
|
+
except ValueError:
|
|
80
|
+
pass
|
|
65
81
|
return TelegramThreadIdentity(bot_id=bot_id, chat_id=chat_id, topic_id=topic_id)
|
|
66
82
|
|
|
67
83
|
|
|
@@ -64,8 +64,9 @@ class TelegramOutboundChannel(TelegramApprovalChannel):
|
|
|
64
64
|
context: ChannelContext,
|
|
65
65
|
*,
|
|
66
66
|
token: str,
|
|
67
|
+
allowed_sender_ids: frozenset[int],
|
|
67
68
|
) -> None:
|
|
68
|
-
super().__init__(context, token=token)
|
|
69
|
+
super().__init__(context, token=token, allowed_sender_ids=allowed_sender_ids)
|
|
69
70
|
self._outbound_requests = 0
|
|
70
71
|
self._outbound_confirmed_requests = 0
|
|
71
72
|
self._outbound_partial_requests = 0
|