bazaar-compute-node 0.1.26__tar.gz → 0.1.28__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.
Files changed (144) hide show
  1. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/PKG-INFO +2 -1
  2. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/pyproject.toml +2 -1
  3. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/pyproject.toml.orig +2 -1
  4. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/app/agent.py +4 -26
  5. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/app/application.py +10 -5
  6. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/app/command.py +94 -52
  7. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/app/resource_dispatch.py +3 -197
  8. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/bcc.py +14 -216
  9. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/lark/api.py +12 -0
  10. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/lark/approval.py +7 -3
  11. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/lark/channel.py +129 -2
  12. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/codec.py +19 -65
  13. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/migrations/__init__.py +2 -0
  14. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/migrations/registry.py +10 -0
  15. bazaar_compute_node-0.1.28/src/bazaar_compute_node/contrib/sqlite/migrations/v19_reminder_system_messages.py +226 -0
  16. bazaar_compute_node-0.1.28/src/bazaar_compute_node/contrib/sqlite/migrations/v20_remove_freshness_persistence.py +162 -0
  17. bazaar_compute_node-0.1.28/src/bazaar_compute_node/contrib/sqlite/migrations/v21_remove_handoffs.py +14 -0
  18. bazaar_compute_node-0.1.28/src/bazaar_compute_node/contrib/sqlite/migrations/v22_readable_targets.py +20 -0
  19. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/reminder_codec.py +2 -19
  20. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/repository/base.py +19 -0
  21. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/repository/facade.py +19 -19
  22. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/repository/messages.py +177 -27
  23. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/repository/reminders.py +61 -251
  24. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/repository/sessions.py +17 -18
  25. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/storage.py +12 -25
  26. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/telegram/approval.py +12 -9
  27. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/telegram/channel.py +71 -0
  28. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/command.py +45 -44
  29. bazaar_compute_node-0.1.28/src/bazaar_compute_node/core/instruction.py +52 -0
  30. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/models/__init__.py +6 -6
  31. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/models/entities.py +79 -170
  32. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/models/reminder.py +0 -76
  33. bazaar_compute_node-0.1.28/src/bazaar_compute_node/core/models/reminder_owner.py +28 -0
  34. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/models/states.py +8 -18
  35. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/orchestration/command.py +155 -102
  36. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/orchestration/error_feedback.py +3 -1
  37. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/orchestration/reminder.py +64 -35
  38. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/orchestration/reminder_command.py +0 -24
  39. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/orchestration/session.py +84 -182
  40. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/orchestration/turn.py +62 -23
  41. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/reminder.py +25 -37
  42. bazaar_compute_node-0.1.28/src/bazaar_compute_node/core/storage.py +763 -0
  43. bazaar_compute_node-0.1.28/src/bazaar_compute_node/i18n/catalog.py +79 -0
  44. bazaar_compute_node-0.1.28/src/bazaar_compute_node/rendering.py +86 -0
  45. bazaar_compute_node-0.1.26/src/bazaar_compute_node/core/instruction.py → bazaar_compute_node-0.1.28/src/bazaar_compute_node/resources/developer_instructions.md +25 -117
  46. bazaar_compute_node-0.1.28/src/bazaar_compute_node/resources/locales/en.toml +49 -0
  47. bazaar_compute_node-0.1.28/src/bazaar_compute_node/resources/locales/zh-CN.toml +49 -0
  48. bazaar_compute_node-0.1.26/src/bazaar_compute_node/contrib/sqlite/handoff_codec.py +0 -24
  49. bazaar_compute_node-0.1.26/src/bazaar_compute_node/contrib/sqlite/repository/handoffs.py +0 -140
  50. bazaar_compute_node-0.1.26/src/bazaar_compute_node/core/handoff.py +0 -49
  51. bazaar_compute_node-0.1.26/src/bazaar_compute_node/core/models/handoff.py +0 -26
  52. bazaar_compute_node-0.1.26/src/bazaar_compute_node/core/models/reminder_owner.py +0 -59
  53. bazaar_compute_node-0.1.26/src/bazaar_compute_node/core/orchestration/handoff_command.py +0 -245
  54. bazaar_compute_node-0.1.26/src/bazaar_compute_node/core/storage.py +0 -753
  55. bazaar_compute_node-0.1.26/src/bazaar_compute_node/i18n/catalog.py +0 -46
  56. bazaar_compute_node-0.1.26/src/bazaar_compute_node/i18n/english.py +0 -88
  57. bazaar_compute_node-0.1.26/src/bazaar_compute_node/i18n/schinese.py +0 -74
  58. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/LICENSE +0 -0
  59. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/README.md +0 -0
  60. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/__init__.py +0 -0
  61. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/app/__init__.py +0 -0
  62. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/app/agent_management.py +0 -0
  63. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/app/attachments.py +0 -0
  64. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/app/config.py +0 -0
  65. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/app/registry.py +0 -0
  66. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/app/system_service.py +0 -0
  67. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/app/transport.py +0 -0
  68. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/app/windows_pipe.py +0 -0
  69. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/app/wrapper.py +0 -0
  70. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/cli.py +0 -0
  71. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/__init__.py +0 -0
  72. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/codex/__init__.py +0 -0
  73. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/codex/approval.py +0 -0
  74. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/codex/client.py +0 -0
  75. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/codex/events.py +0 -0
  76. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/codex/plugin.py +0 -0
  77. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/codex/process.py +0 -0
  78. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/codex/protocol.py +0 -0
  79. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/codex/runtime.py +0 -0
  80. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/lark/__init__.py +0 -0
  81. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/lark/attachments.py +0 -0
  82. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/lark/frame.py +0 -0
  83. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/lark/identity.py +0 -0
  84. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/lark/outbound.py +0 -0
  85. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/lark/plugin.py +0 -0
  86. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/lark/transport.py +0 -0
  87. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/logging/__init__.py +0 -0
  88. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/logging/audit.py +0 -0
  89. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/logging/plugin.py +0 -0
  90. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/__init__.py +0 -0
  91. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/database.py +0 -0
  92. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/executor.py +0 -0
  93. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/migrations/model.py +0 -0
  94. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/migrations/v01_initial_node_schema.py +0 -0
  95. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/migrations/v02_session_mapping_indexes.py +0 -0
  96. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/migrations/v03_message_log_indexes.py +0 -0
  97. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/migrations/v04_runtime_attempt_facts.py +0 -0
  98. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/migrations/v05_inbound_message_references.py +0 -0
  99. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/migrations/v06_inbound_message_reference_integrity.py +0 -0
  100. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/migrations/v07_inbound_provider_identity.py +0 -0
  101. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/migrations/v08_transient_stream_events.py +0 -0
  102. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/migrations/v09_remove_runtime_events.py +0 -0
  103. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/migrations/v10_add_outbound_attachments.py +0 -0
  104. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/migrations/v11_remove_runtime_session_mapping.py +0 -0
  105. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/migrations/v12_add_reminders.py +0 -0
  106. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/migrations/v13_add_agent_ownership.py +0 -0
  107. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/migrations/v14_add_inbox_discovery_indexes.py +0 -0
  108. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/migrations/v15_add_handoffs.py +0 -0
  109. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/migrations/v16_remove_outbound_drafts.py +0 -0
  110. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/migrations/v17_remove_agent_identity_triggers.py +0 -0
  111. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/migrations/v18_unify_messages.py +0 -0
  112. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/plugin.py +0 -0
  113. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/sqlite/repository/__init__.py +0 -0
  114. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/telegram/__init__.py +0 -0
  115. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/telegram/api.py +0 -0
  116. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/telegram/attachments.py +0 -0
  117. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/telegram/identity.py +0 -0
  118. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/telegram/markdown.py +0 -0
  119. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/telegram/outbound.py +0 -0
  120. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/telegram/plugin.py +0 -0
  121. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/wecom/__init__.py +0 -0
  122. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/wecom/channel.py +0 -0
  123. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/wecom/markdown.py +0 -0
  124. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/wecom/outbound.py +0 -0
  125. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/contrib/wecom/plugin.py +0 -0
  126. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/__init__.py +0 -0
  127. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/approval.py +0 -0
  128. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/audit.py +0 -0
  129. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/channel.py +0 -0
  130. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/client.py +0 -0
  131. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/concurrency.py +0 -0
  132. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/correlation.py +0 -0
  133. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/inbox.py +0 -0
  134. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/lifecycle.py +0 -0
  135. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/observability.py +0 -0
  136. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/orchestration/__init__.py +0 -0
  137. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/orchestration/delivery.py +0 -0
  138. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/orchestration/services.py +0 -0
  139. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/outcomes.py +0 -0
  140. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/paths.py +0 -0
  141. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/reminder_schedule.py +0 -0
  142. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/runtime.py +0 -0
  143. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/core/timerwheel.py +0 -0
  144. {bazaar_compute_node-0.1.26 → bazaar_compute_node-0.1.28}/src/bazaar_compute_node/i18n/__init__.py +0 -0
@@ -1,12 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bazaar-compute-node
3
- Version: 0.1.26
3
+ Version: 0.1.28
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
7
7
  Requires-Dist: aiohttp>=3.12.0
8
8
  Requires-Dist: aiosqlite>=0.20.0
9
9
  Requires-Dist: cryptography>=45.0.0
10
+ Requires-Dist: jinja2>=3.1.6
10
11
  Requires-Dist: pydantic>=2.0.0
11
12
  Requires-Dist: protobug==1.0.0
12
13
  Requires-Dist: tzdata>=2024.1 ; sys_platform == 'win32'
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "bazaar-compute-node"
3
- version = "0.1.26"
3
+ version = "0.1.28"
4
4
  description = "Runtime-agnostic computer node daemon for agents and channels."
5
5
  readme = "README.md"
6
6
  license = "AGPL-3.0-only"
@@ -10,6 +10,7 @@ dependencies = [
10
10
  "aiohttp>=3.12.0",
11
11
  "aiosqlite>=0.20.0",
12
12
  "cryptography>=45.0.0",
13
+ "jinja2>=3.1.6",
13
14
  "pydantic>=2.0.0",
14
15
  "protobug==1.0.0",
15
16
  "tzdata>=2024.1; sys_platform == 'win32'",
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "bazaar-compute-node"
3
- version = "0.1.26"
3
+ version = "0.1.28"
4
4
  description = "Runtime-agnostic computer node daemon for agents and channels."
5
5
  readme = "README.md"
6
6
  license = "AGPL-3.0-only"
@@ -10,6 +10,7 @@ dependencies = [
10
10
  "aiohttp>=3.12.0",
11
11
  "aiosqlite>=0.20.0",
12
12
  "cryptography>=45.0.0",
13
+ "jinja2>=3.1.6",
13
14
  "pydantic>=2.0.0",
14
15
  "protobug==1.0.0",
15
16
  "tzdata>=2024.1; sys_platform == 'win32'",
@@ -10,21 +10,17 @@ import secrets
10
10
  from collections.abc import Callable, Mapping, Sequence
11
11
  from dataclasses import dataclass
12
12
  from pathlib import Path
13
- from time import time_ns
14
- from typing import cast
15
13
 
16
14
  from ..core.channel import AgentScopedChannel, ChannelContext, IChannel
17
15
  from ..core.concurrency import ISessionConcurrency, SessionLockRegistry
18
16
  from ..core.lifecycle import TimeoutBudget
19
- from ..core.models import RuntimeSession
17
+ from ..core.models import InboundAttachment, Message, RuntimeSession
20
18
  from ..core.observability import IAudit
21
19
  from ..core.orchestration import SessionOrchestrator
22
- from ..core.orchestration.handoff_command import HandoffCommandService
23
20
  from ..core.orchestration.reminder_command import ReminderCommandService
24
- from ..core.orchestration.services import SessionAuditRecorder
25
21
  from ..core.paths import resolve_workspace_dir
26
22
  from ..core.runtime import IRuntime, RuntimeCommandContext
27
- from ..core.storage import IHandoffStorageScope, IStorageScope
23
+ from ..core.storage import IStorageScope
28
24
  from ..core.timerwheel import TimerWheel
29
25
  from ..i18n import Translator
30
26
  from .attachments import AttachmentMaterializer
@@ -82,7 +78,6 @@ class AgentApplication:
82
78
  self.agent_id = configuration.id
83
79
  self.name = configuration.name
84
80
  self.storage = storage
85
- self._handoff_storage = cast(IHandoffStorageScope, storage)
86
81
  self.audit = audit
87
82
  self.timer_wheel = timer_wheel
88
83
  self.timeout_budget = timeout_budget
@@ -152,7 +147,6 @@ class AgentApplication:
152
147
  channel=self.channel,
153
148
  runtime=self.runtime,
154
149
  storage=self.storage,
155
- handoff_storage=self._handoff_storage,
156
150
  audit=self.audit,
157
151
  timeout_budget=self.timeout_budget,
158
152
  timer_wheel=self.timer_wheel,
@@ -167,16 +161,6 @@ class AgentApplication:
167
161
  concurrency=reminder_concurrency,
168
162
  poke=reminder_poke,
169
163
  )
170
- self.handoff_service = HandoffCommandService(
171
- storage=self._handoff_storage,
172
- audit=SessionAuditRecorder(
173
- sink=self.audit,
174
- timeout_budget=self.timeout_budget,
175
- clock=lambda: time_ns() // 1_000_000,
176
- ),
177
- publish_wake=self.publish_handoff_wake,
178
- node_id=lambda: self.agent_id,
179
- )
180
164
  self._provider_control_handler = (
181
165
  factories.control(self._adapter_context())
182
166
  if factories.control is not None
@@ -185,7 +169,6 @@ class AgentApplication:
185
169
  self.command_dispatcher = CommandDispatcher(
186
170
  self.orchestrator.command_service,
187
171
  reminder_service=self.reminder_service,
188
- handoff_service=self.handoff_service,
189
172
  timeout_budget=self.timeout_budget,
190
173
  control_handler=(
191
174
  self._handle_control
@@ -281,15 +264,10 @@ class AgentApplication:
281
264
  return False
282
265
  return await self.storage.get_bcn_session(session_id) is not None
283
266
 
284
- async def publish_reminder_wake(self, session_id: str) -> None:
285
- if not self._started:
286
- raise RuntimeError("Agent application is not started")
287
- await self.orchestrator.publish_reminder_wake(session_id)
288
-
289
- async def publish_handoff_wake(self, session_id: str) -> None:
267
+ async def publish_inbox_wake(self, message: Message[InboundAttachment]) -> None:
290
268
  if not self._started:
291
269
  raise RuntimeError("Agent application is not started")
292
- await self.orchestrator.publish_handoff_wake(session_id)
270
+ await self.orchestrator.publish_inbox_wake(message)
293
271
 
294
272
  def health_record(self) -> dict[str, object]:
295
273
  return {
@@ -11,6 +11,7 @@ from pathlib import Path
11
11
 
12
12
  from ..core.concurrency import SessionLockRegistry
13
13
  from ..core.lifecycle import TimeoutBudget
14
+ from ..core.models import InboundAttachment, Message
14
15
  from ..core.observability import IAudit
15
16
  from ..core.orchestration import ReminderScheduler
16
17
  from ..core.paths import resolve_data_dir
@@ -77,7 +78,7 @@ class NodeApplication:
77
78
  storage=self.storage,
78
79
  timer_wheel=self.timer_wheel,
79
80
  concurrency=self._reminder_concurrency,
80
- publish_wake=self._publish_reminder_wake,
81
+ publish_wake=self._publish_inbox_wake,
81
82
  )
82
83
  self.command_server = LocalCommandServer(
83
84
  self._dispatch,
@@ -246,24 +247,28 @@ class NodeApplication:
246
247
  pass
247
248
  await self._stopped.wait()
248
249
 
249
- async def _publish_reminder_wake(self, agent_id: str, session_id: str) -> bool:
250
+ async def _publish_inbox_wake(
251
+ self,
252
+ agent_id: str,
253
+ message: Message[InboundAttachment],
254
+ ) -> bool:
250
255
  agent = self.agents.get(agent_id)
251
256
  if agent is None or not agent.started:
252
257
  self._log(
253
258
  "reminder.wake.agent_unavailable",
254
259
  agent_id=agent_id,
255
- owner_session_id=session_id,
260
+ owner_session_id=message.session_id,
256
261
  )
257
262
  return False
258
263
  try:
259
- await agent.publish_reminder_wake(session_id)
264
+ await agent.publish_inbox_wake(message)
260
265
  except asyncio.CancelledError:
261
266
  raise
262
267
  except Exception as error: # noqa: BLE001
263
268
  self._log(
264
269
  "reminder.wake.failed",
265
270
  agent_id=agent_id,
266
- owner_session_id=session_id,
271
+ owner_session_id=message.session_id,
267
272
  error_type=type(error).__name__,
268
273
  error=_safe_error(error),
269
274
  )
@@ -21,8 +21,9 @@ from ..core.command import (
21
21
  ICommandService,
22
22
  InboxListResult,
23
23
  MessageSendFreshnessHold,
24
- MessageSendHandoffRequired,
24
+ MessageSendSuccess,
25
25
  SessionNotFoundError,
26
+ TargetProjection,
26
27
  )
27
28
  from ..core.lifecycle import TimeoutBudget
28
29
  from ..core.models import (
@@ -63,7 +64,14 @@ def _serialize_attachment(
63
64
  }
64
65
 
65
66
 
66
- def serialize_message(message: Message) -> dict[str, object]:
67
+ def serialize_message(
68
+ message: Message,
69
+ target_projections: tuple[TargetProjection, ...] = (),
70
+ ) -> dict[str, object]:
71
+ targets = {
72
+ projection.canonical_target: projection.display_target
73
+ for projection in target_projections
74
+ }
67
75
  return {
68
76
  "seq": message.seq,
69
77
  "message_id": message.message_id,
@@ -80,7 +88,24 @@ def serialize_message(message: Message) -> dict[str, object]:
80
88
  else {"id": message.sender.id, "name": message.sender.name}
81
89
  ),
82
90
  "sender_kind": message.sender_kind.value,
91
+ "system_message_kind": (
92
+ None
93
+ if message.system_message_kind is None
94
+ else message.system_message_kind.value
95
+ ),
96
+ "system_message_source_target": (
97
+ targets.get(source_target, source_target)
98
+ if isinstance(
99
+ source_target := message.metadata.get("system_message_source_target"),
100
+ str,
101
+ )
102
+ else None
103
+ ),
104
+ "system_message_source_message_id": message.metadata.get(
105
+ "system_message_source_message_id"
106
+ ),
83
107
  "message_type": message.message_type,
108
+ "target": targets.get(message.target, message.target),
84
109
  "canonical_target": message.target,
85
110
  "target_kind": message.target_kind.value,
86
111
  "mentions_agent": message.mentions_agent,
@@ -437,10 +462,11 @@ class CommandDispatcher:
437
462
  "ok": True,
438
463
  "result": {
439
464
  "messages": [
440
- serialize_message(message) for message in result.messages
465
+ serialize_message(message, result.target_projections)
466
+ for message in result.messages
441
467
  ],
442
468
  "referenced_messages": [
443
- serialize_message(message)
469
+ serialize_message(message, result.target_projections)
444
470
  for message in result.referenced_messages
445
471
  ],
446
472
  "snapshot_seq": result.snapshot_seq,
@@ -461,7 +487,7 @@ class CommandDispatcher:
461
487
  request = cast(_MessageReadRequest, request)
462
488
  result = await self._service.read(
463
489
  session_id,
464
- target=request.target,
490
+ raw_target=request.target,
465
491
  around_message_id=request.around_message_id,
466
492
  limit=request.limit,
467
493
  )
@@ -469,10 +495,11 @@ class CommandDispatcher:
469
495
  "ok": True,
470
496
  "result": {
471
497
  "messages": [
472
- serialize_message(message) for message in result.messages
498
+ serialize_message(message, result.target_projections)
499
+ for message in result.messages
473
500
  ],
474
501
  "referenced_messages": [
475
- serialize_message(message)
502
+ serialize_message(message, result.target_projections)
476
503
  for message in result.referenced_messages
477
504
  ],
478
505
  "snapshot_seq": result.snapshot_seq,
@@ -486,7 +513,7 @@ class CommandDispatcher:
486
513
  result = await self._service.send(
487
514
  session_id=session_id,
488
515
  command_id=request.command_id,
489
- target=request.target,
516
+ raw_target=request.target,
490
517
  body=request.body,
491
518
  created_at_ms=request.created_at_ms,
492
519
  attachment_paths=tuple(request.attachment_paths),
@@ -498,27 +525,25 @@ class CommandDispatcher:
498
525
  "ok": True,
499
526
  "result": {"text": format_freshness_hold(result)},
500
527
  }
501
- if isinstance(result, MessageSendHandoffRequired):
502
- return {
503
- "ok": True,
504
- "result": {"text": format_cross_session_hold(result.target)},
505
- }
506
- delivery_state = result.delivery_state
528
+ if not isinstance(result, MessageSendSuccess):
529
+ raise AssertionError("message send returned an unsupported result")
530
+ message = result.message
531
+ delivery_state = message.delivery_state
507
532
  if delivery_state is None:
508
533
  raise RuntimeError("outbound message has no delivery state")
509
534
  if delivery_state is OutboundDeliveryState.SENT:
510
535
  text = (
511
- f"Message sent to {result.target}. Message ID: {result.message_id}"
536
+ f"Message sent to {result.target}. Message ID: {message.message_id}"
512
537
  )
513
538
  elif delivery_state is OutboundDeliveryState.QUEUED:
514
539
  text = (
515
540
  f"Message queued to {result.target}. "
516
- f"Message ID: {result.message_id}"
541
+ f"Message ID: {message.message_id}"
517
542
  )
518
543
  elif delivery_state is OutboundDeliveryState.PARTIAL:
519
544
  raise CommandDispatchError(
520
545
  "SEND_PARTIAL",
521
- result.error_message
546
+ message.error_message
522
547
  or "Message delivery was only partially confirmed.",
523
548
  next_action=(
524
549
  "Do not retry the complete message automatically; reconcile "
@@ -528,13 +553,13 @@ class CommandDispatcher:
528
553
  elif delivery_state is OutboundDeliveryState.UNKNOWN:
529
554
  raise CommandDispatchError(
530
555
  "SEND_UNKNOWN",
531
- result.error_message or "Message delivery outcome is unknown.",
556
+ message.error_message or "Message delivery outcome is unknown.",
532
557
  next_action="Reconcile channel delivery before retrying.",
533
558
  )
534
559
  elif delivery_state is OutboundDeliveryState.FAILED:
535
560
  raise CommandDispatchError(
536
561
  "SEND_FAILED",
537
- result.error_message or "Message delivery failed.",
562
+ message.error_message or "Message delivery failed.",
538
563
  next_action="Fix the provider error before retrying.",
539
564
  )
540
565
  else:
@@ -548,8 +573,14 @@ class CommandDispatcher:
548
573
 
549
574
  if resource == "thread" and command == "unfollow":
550
575
  request = cast(_ThreadUnfollowRequest, request)
551
- changed = await self._service.unfollow(session_id, target=request.target)
552
- return {"ok": True, "result": {"changed": changed}}
576
+ result = await self._service.unfollow(
577
+ session_id,
578
+ raw_target=request.target,
579
+ )
580
+ return {
581
+ "ok": True,
582
+ "result": {"target": result.target, "changed": result.changed},
583
+ }
553
584
 
554
585
  raise AssertionError("validated command route has no handler")
555
586
 
@@ -573,7 +604,7 @@ def _message_timestamp(message: Mapping[str, object]) -> int:
573
604
  def _message_header_fields(
574
605
  message: Mapping[str, object],
575
606
  ) -> tuple[str, str, str, str, str | None, str]:
576
- target = cast(str, message["canonical_target"])
607
+ target = cast(str, message["target"])
577
608
  message_id = cast(str, message["message_id"])
578
609
  sender_kind = cast(str, message["sender_kind"])
579
610
  sender_value = message["sender"]
@@ -622,17 +653,45 @@ def format_check_message(message: Mapping[str, object]) -> str:
622
653
  target, message_id, timestamp, sender_kind, sender, body = _message_header_fields(
623
654
  message
624
655
  )
625
- line = (
626
- f"[target={target} msg={message_id} time={timestamp} "
627
- f"type={sender_kind} mentioned={str(message['mentions_agent']).lower()}"
628
- )
656
+ line = f"[target={target} msg={message_id} time={timestamp} type={sender_kind}"
629
657
  reply_to_message_id = message["reply_to_message_id"]
630
658
  if reply_to_message_id is not None:
631
659
  line += f" reply_to={cast(str, reply_to_message_id)}"
632
660
  line += "] "
633
661
  if sender is not None:
634
- line += f"{sender} "
635
- return line + body + _attachment_suffix(message)
662
+ line += f"{sender}: "
663
+ rendered = line + body + _attachment_suffix(message)
664
+ if message.get("system_message_kind") == "reminder":
665
+ operation = (
666
+ "(to snooze/update/cancel: bcc reminder --help)"
667
+ if "\nNext iteration: " in body
668
+ else "(to snooze/cancel: bcc reminder --help)"
669
+ )
670
+ rendered += (
671
+ f"\n{operation}"
672
+ "\nRespond as appropriate. Complete all your work before stopping."
673
+ "\nReply in the channel or create/reply in a thread as appropriate; "
674
+ "use each message's `target` and `msg` fields to choose the exact target."
675
+ )
676
+ elif message.get("system_message_kind") == "handoff":
677
+ source_target = cast(str, message["system_message_source_target"])
678
+ source_message_id = cast(
679
+ str,
680
+ message["system_message_source_message_id"],
681
+ )
682
+ rendered += (
683
+ "\nTo understand why this message was sent, inspect the source context:"
684
+ "\n bcc message read --target "
685
+ f"{json.dumps(source_target)} --around {json.dumps(source_message_id)}"
686
+ "\nIf you have no objection to why the message was sent, do not announce "
687
+ "or explain the handoff, and do not repeat or respond to the referenced "
688
+ "message; it has already been delivered. Continue only work already in "
689
+ "progress in this conversation that is independent of that message; if "
690
+ "there is none, stop."
691
+ "\nMention the handoff only when its reason is unclear, conflicts with "
692
+ "the current conversation, or requires a decision."
693
+ )
694
+ return rendered
636
695
 
637
696
 
638
697
  def format_read_message(
@@ -650,21 +709,24 @@ def format_read_message(
650
709
  f"time={timestamp}",
651
710
  f"type={sender_kind}",
652
711
  f"replyTarget={target}",
653
- f"mentioned={str(message['mentions_agent']).lower()}",
654
712
  ]
655
713
  reply_to_message_id = message["reply_to_message_id"]
656
714
  if reply_to_message_id is not None:
657
715
  fields.append(f"replyTo={cast(str, reply_to_message_id)}")
658
716
  line = f"[{index}/{count} {' '.join(fields)}] "
659
717
  if sender is not None:
660
- line += f"{sender} "
718
+ line += f"{sender}: "
661
719
  return line + body + _attachment_suffix(message)
662
720
 
663
721
 
664
722
  def format_freshness_hold(result: MessageSendFreshnessHold) -> str:
665
- messages = [serialize_message(message) for message in result.messages]
723
+ messages = [
724
+ serialize_message(message, result.target_projections)
725
+ for message in result.messages
726
+ ]
666
727
  referenced_messages = [
667
- serialize_message(message) for message in result.referenced_messages
728
+ serialize_message(message, result.target_projections)
729
+ for message in result.referenced_messages
668
730
  ]
669
731
  shown = len(messages)
670
732
  total = result.newer_message_total
@@ -718,23 +780,3 @@ def format_freshness_hold(result: MessageSendFreshnessHold) -> str:
718
780
  )
719
781
  )
720
782
  return "\n".join(lines)
721
-
722
-
723
- def format_cross_session_hold(target: str) -> str:
724
- quoted_target = json.dumps(target)
725
- return "\n".join(
726
- (
727
- "Your message was not sent because the target belongs to another conversation.",
728
- "",
729
- (
730
- "To continue this work in the target conversation, send a "
731
- "self-contained handoff:"
732
- ),
733
- f" bcc handoff send --target {quoted_target} <<'BCCMSG'",
734
- " enough context to understand the background, goal, and next action",
735
- " BCCMSG",
736
- "This creates a handoff notice that wakes you in that conversation.",
737
- "",
738
- "You can also choose not to send anything.",
739
- )
740
- )