bazaar-compute-node 0.1.36__tar.gz → 0.1.37__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 (178) hide show
  1. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/PKG-INFO +1 -1
  2. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/pyproject.toml +1 -1
  3. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/pyproject.toml.orig +1 -1
  4. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/app/agent.py +1 -1
  5. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/app/application.py +11 -6
  6. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/app/resource_dispatch.py +14 -4
  7. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/app/system_service.py +11 -70
  8. bazaar_compute_node-0.1.37/src/bazaar_compute_node/app/upgrade.py +151 -0
  9. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/bcc.py +14 -3
  10. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/orchestration/turn.py +4 -0
  11. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/resources/inbox_notice.tpl +1 -1
  12. bazaar_compute_node-0.1.37/src/bazaar_compute_node/resources/system_service/windows.ps1 +98 -0
  13. bazaar_compute_node-0.1.36/src/bazaar_compute_node/app/upgrade.py +0 -321
  14. bazaar_compute_node-0.1.36/src/bazaar_compute_node/resources/system_service/replace_managed_file.ps1 +0 -16
  15. bazaar_compute_node-0.1.36/src/bazaar_compute_node/resources/system_service/windows.ps1 +0 -157
  16. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/LICENSE +0 -0
  17. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/README.md +0 -0
  18. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/__init__.py +0 -0
  19. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/app/__init__.py +0 -0
  20. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/app/agent_management.py +0 -0
  21. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/app/attachments.py +0 -0
  22. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/app/command.py +0 -0
  23. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/app/config.py +0 -0
  24. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/app/registry.py +0 -0
  25. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/app/transport.py +0 -0
  26. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/app/version_check.py +0 -0
  27. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/app/windows_pipe.py +0 -0
  28. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/app/wrapper.py +0 -0
  29. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/cli.py +0 -0
  30. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/__init__.py +0 -0
  31. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/claude/__init__.py +0 -0
  32. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/claude/approval.py +0 -0
  33. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/claude/client.py +0 -0
  34. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/claude/events.py +0 -0
  35. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/claude/plugin.py +0 -0
  36. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/claude/process.py +0 -0
  37. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/claude/protocol.py +0 -0
  38. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/claude/runtime.py +0 -0
  39. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/codex/__init__.py +0 -0
  40. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/codex/approval.py +0 -0
  41. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/codex/client.py +0 -0
  42. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/codex/events.py +0 -0
  43. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/codex/plugin.py +0 -0
  44. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/codex/process.py +0 -0
  45. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/codex/protocol.py +0 -0
  46. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/codex/runtime.py +0 -0
  47. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/lark/__init__.py +0 -0
  48. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/lark/api.py +0 -0
  49. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/lark/approval.py +0 -0
  50. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/lark/attachments.py +0 -0
  51. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/lark/channel.py +0 -0
  52. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/lark/frame.py +0 -0
  53. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/lark/identity.py +0 -0
  54. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/lark/outbound.py +0 -0
  55. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/lark/plugin.py +0 -0
  56. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/lark/transport.py +0 -0
  57. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/logging/__init__.py +0 -0
  58. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/logging/audit.py +0 -0
  59. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/logging/plugin.py +0 -0
  60. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/__init__.py +0 -0
  61. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/codec.py +0 -0
  62. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/database.py +0 -0
  63. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/executor.py +0 -0
  64. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/__init__.py +0 -0
  65. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/model.py +0 -0
  66. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/registry.py +0 -0
  67. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/v01_initial_node_schema.py +0 -0
  68. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/v02_session_mapping_indexes.py +0 -0
  69. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/v03_message_log_indexes.py +0 -0
  70. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/v04_runtime_attempt_facts.py +0 -0
  71. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/v05_inbound_message_references.py +0 -0
  72. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/v06_inbound_message_reference_integrity.py +0 -0
  73. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/v07_inbound_provider_identity.py +0 -0
  74. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/v08_transient_stream_events.py +0 -0
  75. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/v09_remove_runtime_events.py +0 -0
  76. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/v10_add_outbound_attachments.py +0 -0
  77. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/v11_remove_runtime_session_mapping.py +0 -0
  78. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/v12_add_reminders.py +0 -0
  79. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/v13_add_agent_ownership.py +0 -0
  80. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/v14_add_inbox_discovery_indexes.py +0 -0
  81. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/v15_add_handoffs.py +0 -0
  82. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/v16_remove_outbound_drafts.py +0 -0
  83. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/v17_remove_agent_identity_triggers.py +0 -0
  84. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/v18_unify_messages.py +0 -0
  85. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/v19_reminder_system_messages.py +0 -0
  86. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/v20_remove_freshness_persistence.py +0 -0
  87. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/v21_remove_handoffs.py +0 -0
  88. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/v22_readable_targets.py +0 -0
  89. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/v23_persist_sender_identity.py +0 -0
  90. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/migrations/v24_persist_sender_display_name.py +0 -0
  91. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/plugin.py +0 -0
  92. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/reminder_codec.py +0 -0
  93. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/repository/__init__.py +0 -0
  94. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/repository/base.py +0 -0
  95. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/repository/facade.py +0 -0
  96. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/repository/messages.py +0 -0
  97. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/repository/reminders.py +0 -0
  98. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/repository/sessions.py +0 -0
  99. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/sqlite/storage.py +0 -0
  100. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/telegram/__init__.py +0 -0
  101. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/telegram/api.py +0 -0
  102. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/telegram/approval.py +0 -0
  103. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/telegram/attachments.py +0 -0
  104. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/telegram/channel.py +0 -0
  105. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/telegram/identity.py +0 -0
  106. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/telegram/markdown.py +0 -0
  107. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/telegram/outbound.py +0 -0
  108. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/telegram/plugin.py +0 -0
  109. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/wecom/__init__.py +0 -0
  110. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/wecom/channel.py +0 -0
  111. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/wecom/markdown.py +0 -0
  112. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/wecom/outbound.py +0 -0
  113. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/contrib/wecom/plugin.py +0 -0
  114. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/__init__.py +0 -0
  115. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/approval.py +0 -0
  116. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/audit.py +0 -0
  117. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/channel.py +0 -0
  118. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/client.py +0 -0
  119. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/command.py +0 -0
  120. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/concurrency.py +0 -0
  121. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/correlation.py +0 -0
  122. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/inbox.py +0 -0
  123. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/instruction.py +0 -0
  124. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/lifecycle.py +0 -0
  125. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/models/__init__.py +0 -0
  126. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/models/entities.py +0 -0
  127. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/models/reminder.py +0 -0
  128. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/models/reminder_owner.py +0 -0
  129. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/models/states.py +0 -0
  130. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/observability.py +0 -0
  131. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/orchestration/__init__.py +0 -0
  132. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/orchestration/command.py +0 -0
  133. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/orchestration/delivery.py +0 -0
  134. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/orchestration/error_feedback.py +0 -0
  135. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/orchestration/reminder.py +0 -0
  136. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/orchestration/reminder_command.py +0 -0
  137. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/orchestration/runtime_pool.py +0 -0
  138. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/orchestration/services.py +0 -0
  139. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/orchestration/session.py +0 -0
  140. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/orchestration/upgrade_notice.py +0 -0
  141. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/outcomes.py +0 -0
  142. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/paths.py +0 -0
  143. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/reminder.py +0 -0
  144. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/reminder_schedule.py +0 -0
  145. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/restart.py +0 -0
  146. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/runtime.py +0 -0
  147. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/storage.py +0 -0
  148. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/timerwheel.py +0 -0
  149. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/utils/__init__.py +0 -0
  150. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/core/utils/line_reader.py +0 -0
  151. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/i18n/__init__.py +0 -0
  152. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/i18n/catalog.py +0 -0
  153. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/rendering.py +0 -0
  154. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/resources/bcc/check.tpl +0 -0
  155. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/resources/bcc/error.tpl +0 -0
  156. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/resources/bcc/inbox_list.tpl +0 -0
  157. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/resources/bcc/inbox_target.tpl +0 -0
  158. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/resources/bcc/read.tpl +0 -0
  159. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/resources/bcc/reminder_list.tpl +0 -0
  160. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/resources/bcc/reminder_mutation.tpl +0 -0
  161. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/resources/bcc/reminder_schedule.tpl +0 -0
  162. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/resources/bcc/unfollow.tpl +0 -0
  163. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/resources/bcc/upgrade.tpl +0 -0
  164. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/resources/bcc/version.tpl +0 -0
  165. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/resources/command/attachment_suffix.tpl +0 -0
  166. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/resources/command/check_message.tpl +0 -0
  167. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/resources/command/freshness_hold.tpl +0 -0
  168. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/resources/command/read_message.tpl +0 -0
  169. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/resources/command/send_result.tpl +0 -0
  170. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/resources/command/sender.tpl +0 -0
  171. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/resources/developer_instructions.md +0 -0
  172. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/resources/locales/en.toml +0 -0
  173. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/resources/locales/zh-CN.toml +0 -0
  174. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/resources/system_service/launchd.plist +0 -0
  175. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/resources/system_service/launchd.sh +0 -0
  176. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/resources/system_service/systemd.service +0 -0
  177. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/src/bazaar_compute_node/resources/system_service/windows.vbs +0 -0
  178. {bazaar_compute_node-0.1.36 → bazaar_compute_node-0.1.37}/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.1.36
3
+ Version: 0.1.37
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "bazaar-compute-node"
3
- version = "0.1.36"
3
+ version = "0.1.37"
4
4
  description = "Runtime-agnostic computer node daemon for agents and channels."
5
5
  readme = "README.md"
6
6
  license = "AGPL-3.0-only"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "bazaar-compute-node"
3
- version = "0.1.36"
3
+ version = "0.1.37"
4
4
  description = "Runtime-agnostic computer node daemon for agents and channels."
5
5
  readme = "README.md"
6
6
  license = "AGPL-3.0-only"
@@ -79,7 +79,7 @@ class AgentApplication:
79
79
  endpoint: Callable[[], str],
80
80
  timeout_budget: TimeoutBudget,
81
81
  translator: Translator,
82
- upgrade_service: UpgradeService,
82
+ upgrade_service: UpgradeService | None,
83
83
  upgrade_notice: Callable[[], tuple[str, str] | None] = lambda: None,
84
84
  ) -> None:
85
85
  self.configuration = configuration
@@ -24,7 +24,7 @@ from .agent import AgentApplication
24
24
  from .config import AgentConfiguration, NodeConfiguration
25
25
  from .registry import AdapterRegistry, SharedAdapterFactories
26
26
  from .transport import LocalCommandServer
27
- from .upgrade import UpgradeService, discard_replaced_release
27
+ from .upgrade import UpgradeService
28
28
  from .version_check import VersionWatcher
29
29
 
30
30
 
@@ -94,10 +94,16 @@ class NodeApplication:
94
94
  request_timeout_seconds=self.timeout_budget.command_seconds,
95
95
  )
96
96
  self._restart_requested = False
97
- self.upgrade_service = UpgradeService(
98
- available_version=self.version_watcher.available_version,
99
- installed_version=__version__,
100
- request_restart=self.request_restart,
97
+ # Windows has nothing that brings the node back after it exits, so
98
+ # there it offers no upgrade command at all
99
+ self.upgrade_service = (
100
+ None
101
+ if os.name == "nt"
102
+ else UpgradeService(
103
+ available_version=self.version_watcher.available_version,
104
+ installed_version=__version__,
105
+ request_restart=self.request_restart,
106
+ )
101
107
  )
102
108
  self.command_server = LocalCommandServer(
103
109
  self._dispatch,
@@ -155,7 +161,6 @@ class NodeApplication:
155
161
  raise
156
162
  self._ready = True
157
163
  self._accepting = True
158
- await asyncio.to_thread(discard_replaced_release, __version__)
159
164
  started_count = len(self.agents)
160
165
  failed_count = len(self.configuration.agents) - started_count
161
166
  self._log(
@@ -195,7 +195,7 @@ class CommandDispatcher(_MessageCommandDispatcher):
195
195
  reminder_service: IReminderService,
196
196
  timeout_budget: TimeoutBudget,
197
197
  session_binding_validator: SessionBindingValidator | None = None,
198
- upgrade_service: UpgradeService,
198
+ upgrade_service: UpgradeService | None,
199
199
  ) -> None:
200
200
  super().__init__(
201
201
  service,
@@ -247,6 +247,14 @@ class CommandDispatcher(_MessageCommandDispatcher):
247
247
  if resource == "inbox":
248
248
  return await super()._dispatch_command(raw_request)
249
249
  if resource == "node":
250
+ upgrade_service = self._upgrade_service
251
+ if upgrade_service is None:
252
+ # nothing on this platform would bring the node back after an
253
+ # upgrade exits it, so the Agent is given no upgrade to run
254
+ raise CommandDispatchError(
255
+ "UNKNOWN_RESOURCE",
256
+ f"unsupported command resource: {resource}",
257
+ )
250
258
  if command not in {"upgrade", "version"}:
251
259
  raise CommandDispatchError(
252
260
  "UNKNOWN_COMMAND",
@@ -256,7 +264,7 @@ class CommandDispatcher(_MessageCommandDispatcher):
256
264
  return {
257
265
  "ok": True,
258
266
  "result": {
259
- "version": self._upgrade_service.installed_version,
267
+ "version": upgrade_service.installed_version,
260
268
  },
261
269
  }
262
270
  request = _parse_command_request(
@@ -275,6 +283,7 @@ class CommandDispatcher(_MessageCommandDispatcher):
275
283
  return await self._dispatch_upgrade(
276
284
  session_id,
277
285
  cast(_NodeUpgradeRequest, request),
286
+ upgrade_service,
278
287
  )
279
288
  if resource != "reminder":
280
289
  raise CommandDispatchError(
@@ -311,6 +320,7 @@ class CommandDispatcher(_MessageCommandDispatcher):
311
320
  self,
312
321
  session_id: str,
313
322
  request: _NodeUpgradeRequest,
323
+ upgrade_service: UpgradeService,
314
324
  ) -> Mapping[str, object]:
315
325
  async def wake_after(upgrade_version: str) -> str | None:
316
326
  # the reminder is how the Agent is prompted to check the node over
@@ -335,7 +345,7 @@ class CommandDispatcher(_MessageCommandDispatcher):
335
345
  return result.reminder.reminder_id
336
346
 
337
347
  try:
338
- upgrade_version, reminder_id = await self._upgrade_service.upgrade(
348
+ upgrade_version, reminder_id = await upgrade_service.upgrade(
339
349
  wake_after=wake_after,
340
350
  )
341
351
  except UpgradeUnavailable as error:
@@ -355,7 +365,7 @@ class CommandDispatcher(_MessageCommandDispatcher):
355
365
  return {
356
366
  "ok": True,
357
367
  "result": {
358
- "installed_version": self._upgrade_service.installed_version,
368
+ "installed_version": upgrade_service.installed_version,
359
369
  "upgrade_version": upgrade_version,
360
370
  "reminder_id": reminder_id,
361
371
  },
@@ -6,7 +6,6 @@ import getpass
6
6
  import locale
7
7
  import os
8
8
  import platform
9
- import re
10
9
  import shlex
11
10
  import shutil
12
11
  import subprocess
@@ -16,9 +15,7 @@ import time
16
15
  from dataclasses import dataclass
17
16
  from pathlib import Path
18
17
 
19
- from .. import __distribution__
20
18
  from ..core.paths import resolve_data_dir
21
- from ..core.restart import RESTART_EXIT_CODE
22
19
  from ..i18n import Translator, create_translator
23
20
  from ..rendering import TextTemplate
24
21
  from .config import ConfigurationError, load_control_configuration, resolve_config_path
@@ -28,10 +25,6 @@ SYSTEMD_UNIT_NAME = "bcn.service"
28
25
  LAUNCHD_LABEL = "io.github.yuchanns.bazaar-compute-node"
29
26
  WINDOWS_TASK_NAME = r"\BazaarComputeNode"
30
27
  MANAGED_MARKER = "Managed by bazaar-compute-node."
31
- # raised whenever a managed file's content changes, so an upgrade can tell that
32
- # the installed copy predates what this release expects of it
33
- TEMPLATE_REVISION = 1
34
- MANAGED_MARKER_LINE = f"{MANAGED_MARKER} template-revision={TEMPLATE_REVISION}"
35
28
  WINDOWS_STOP_ATTEMPTS = 100
36
29
  WINDOWS_STOP_INTERVAL = 0.05
37
30
 
@@ -180,7 +173,7 @@ def _powershell_literal(path: Path | str | None) -> str:
180
173
  def _render_systemd_unit(context: SystemServiceContext) -> str:
181
174
  return _SYSTEMD_UNIT_TEMPLATE.render(
182
175
  {
183
- "managed_marker": MANAGED_MARKER_LINE,
176
+ "managed_marker": MANAGED_MARKER,
184
177
  "executable": _systemd_quote(_require_executable(context)),
185
178
  "config_path": _systemd_quote(context.config_path),
186
179
  "data_dir": _systemd_quote(context.data_dir),
@@ -192,7 +185,7 @@ def _render_systemd_unit(context: SystemServiceContext) -> str:
192
185
 
193
186
 
194
187
  def _render_launchd_wrapper() -> str:
195
- return _LAUNCHD_WRAPPER_TEMPLATE.render({"managed_marker": MANAGED_MARKER_LINE})
188
+ return _LAUNCHD_WRAPPER_TEMPLATE.render({"managed_marker": MANAGED_MARKER})
196
189
 
197
190
 
198
191
  def _render_launchd_plist(
@@ -202,7 +195,7 @@ def _render_launchd_plist(
202
195
  return _LAUNCHD_PLIST_TEMPLATE.render(
203
196
  {
204
197
  "label": LAUNCHD_LABEL,
205
- "managed_marker": MANAGED_MARKER_LINE,
198
+ "managed_marker": MANAGED_MARKER,
206
199
  "wrapper_path": str(wrapper_path),
207
200
  "data_dir": str(context.data_dir),
208
201
  "config_path": str(context.config_path),
@@ -215,70 +208,18 @@ def _render_launchd_plist(
215
208
  ).encode("utf-8")
216
209
 
217
210
 
218
- def render_windows_wrapper(
219
- *,
220
- executable: str,
221
- config_path: str,
222
- environment_script: str,
223
- log_path: str,
224
- ) -> str:
225
- """Render the launcher from PowerShell literals, however they were obtained."""
226
-
211
+ def _render_windows_wrapper(context: SystemServiceContext) -> str:
227
212
  return _WINDOWS_WRAPPER_TEMPLATE.render(
228
213
  {
229
- "managed_marker": MANAGED_MARKER_LINE,
230
- "executable": executable,
231
- "config_path": config_path,
232
- "environment_script": environment_script,
233
- "log_path": log_path,
234
- "distribution": _powershell_literal(__distribution__),
235
- "restart_exit_code": RESTART_EXIT_CODE,
214
+ "managed_marker": MANAGED_MARKER,
215
+ "executable": _powershell_literal(_require_executable(context)),
216
+ "config_path": _powershell_literal(context.config_path),
217
+ "environment_script": _powershell_literal(context.env_file),
218
+ "log_path": _powershell_literal(context.log_path),
236
219
  }
237
220
  )
238
221
 
239
222
 
240
- def _render_windows_wrapper(context: SystemServiceContext) -> str:
241
- return render_windows_wrapper(
242
- executable=_powershell_literal(_require_executable(context)),
243
- config_path=_powershell_literal(context.config_path),
244
- environment_script=_powershell_literal(context.env_file),
245
- log_path=_powershell_literal(context.log_path),
246
- )
247
-
248
-
249
- def windows_wrapper_path() -> Path:
250
- """Return where the launcher lives, without needing the install arguments."""
251
-
252
- return resolve_data_dir() / "bcn-system-service.ps1"
253
-
254
-
255
- def windows_tool_directory() -> Path | None:
256
- """Return the directory uv keeps its installed tools in, where there is one."""
257
-
258
- configured = os.environ.get("UV_TOOL_DIR")
259
- if configured:
260
- return Path(configured).expanduser()
261
- app_data = os.environ.get("APPDATA")
262
- return None if not app_data else Path(app_data) / "uv" / "tools"
263
-
264
-
265
- def windows_live_directory() -> Path | None:
266
- """Return the installed tool directory an upgrade swaps into place."""
267
-
268
- tools = windows_tool_directory()
269
- return None if tools is None else tools / __distribution__
270
-
271
-
272
- def installed_template_revision(content: str) -> int | None:
273
- """Read the revision a managed file was written from, if it declares one."""
274
-
275
- first_line = content.splitlines()[0] if content else ""
276
- if MANAGED_MARKER not in first_line:
277
- return None
278
- match = re.search(r"template-revision=(\d+)", first_line)
279
- return int(match.group(1)) if match is not None else None
280
-
281
-
282
223
  def _vbs_literal(value: Path | str) -> str:
283
224
  return '"' + str(value).replace('"', '""') + '"'
284
225
 
@@ -290,7 +231,7 @@ def _render_windows_launcher(wrapper_path: Path) -> str:
290
231
  )
291
232
  return _WINDOWS_LAUNCHER_TEMPLATE.render(
292
233
  {
293
- "managed_marker": MANAGED_MARKER_LINE,
234
+ "managed_marker": MANAGED_MARKER,
294
235
  "command": command,
295
236
  }
296
237
  )
@@ -303,7 +244,7 @@ def _render_windows_task(
303
244
  rendered = _WINDOWS_TASK_TEMPLATE.render(
304
245
  {
305
246
  "user": context.user,
306
- "managed_marker": MANAGED_MARKER_LINE,
247
+ "managed_marker": MANAGED_MARKER,
307
248
  "arguments": f'//B //Nologo "{launcher_path}"',
308
249
  "data_dir": str(context.data_dir),
309
250
  }
@@ -0,0 +1,151 @@
1
+ """Install a newer bcn release and hand this node over to it."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ import os
7
+ import shutil
8
+ import subprocess
9
+ from collections.abc import Awaitable, Callable, Mapping
10
+
11
+ from packaging.version import InvalidVersion, Version
12
+
13
+ from .. import __distribution__
14
+
15
+ # uv writes UTF-8 whatever the console is set to, so a node in a non-UTF-8
16
+ # locale would otherwise report its diagnostics as mojibake
17
+ _UV_OUTPUT_ENCODING = "utf-8"
18
+
19
+
20
+ class UpgradeError(RuntimeError):
21
+ """Raised when the node cannot install or hand over to the new release."""
22
+
23
+
24
+ class UpgradeUnavailable(UpgradeError):
25
+ """Raised when no newer release has been announced."""
26
+
27
+
28
+ def _uv_executable() -> str:
29
+ executable = shutil.which("uv")
30
+ if executable is None:
31
+ # a node started by a service manager inherits that manager's PATH,
32
+ # which often does not include wherever uv was installed, so this says
33
+ # nothing about whether uv exists on the machine
34
+ raise UpgradeError(
35
+ "uv is not on this node's PATH, so the release cannot be "
36
+ "installed; add the directory holding uv to the PATH the node "
37
+ "runs with, then try again"
38
+ )
39
+ return executable
40
+
41
+
42
+ def _run(
43
+ command: list[str],
44
+ *,
45
+ env: Mapping[str, str] | None = None,
46
+ encoding: str | None = None,
47
+ ) -> None:
48
+ # no deadline: uv already gives up on a request that never answers, and a
49
+ # second limit would only cut short an install that was merely slow
50
+ result = subprocess.run(
51
+ command,
52
+ capture_output=True,
53
+ check=False,
54
+ text=True,
55
+ encoding=encoding,
56
+ errors="replace",
57
+ env=None if env is None else {**os.environ, **env},
58
+ )
59
+ if result.returncode != 0:
60
+ detail = (result.stderr or result.stdout).strip()
61
+ suffix = f": {detail}" if detail else ""
62
+ raise UpgradeError(
63
+ f"upgrade command failed ({result.returncode}): {' '.join(command)}{suffix}"
64
+ )
65
+
66
+
67
+ def _install(version: str) -> None:
68
+ _run(
69
+ [
70
+ _uv_executable(),
71
+ "tool",
72
+ "install",
73
+ "--force",
74
+ # the release was announced by PyPI's own API minutes ago, while uv
75
+ # resolves against a separately cached index that can still predate
76
+ # it and would then report the version as one that does not exist
77
+ "--refresh-package",
78
+ __distribution__,
79
+ f"{__distribution__}=={version}",
80
+ ],
81
+ encoding=_UV_OUTPUT_ENCODING,
82
+ )
83
+
84
+
85
+ class UpgradeService:
86
+ """Install the release the user agreed to, then hand the node over to it."""
87
+
88
+ def __init__(
89
+ self,
90
+ *,
91
+ available_version: Callable[[], str | None],
92
+ installed_version: str,
93
+ request_restart: Callable[[], None],
94
+ ) -> None:
95
+ self._available_version = available_version
96
+ self._installed_version = installed_version
97
+ self._request_restart = request_restart
98
+ self._lock = asyncio.Lock()
99
+
100
+ @property
101
+ def installed_version(self) -> str:
102
+ return self._installed_version
103
+
104
+ def available_version(self) -> str | None:
105
+ return self._available_version()
106
+
107
+ async def upgrade(
108
+ self,
109
+ *,
110
+ wake_after: Callable[[str], Awaitable[str | None]],
111
+ ) -> tuple[str, str | None]:
112
+ """Install the release on offer and hand the node over to it.
113
+
114
+ The whole thing is one transaction. Two sessions can accept an offer at
115
+ the same time, and by then the offers need not even name the same
116
+ release; letting the second in before the first has asked to restart
117
+ would boot a version nobody was told about, and an install cannot be
118
+ called back once its thread is running.
119
+
120
+ ``wake_after`` records how the Agent is prompted to check the node over
121
+ afterwards, and returns the reminder it left, or None if it could not
122
+ leave one.
123
+ """
124
+
125
+ async with self._lock:
126
+ version = self.available_version()
127
+ if version is None:
128
+ raise UpgradeUnavailable(
129
+ "No newer release has been announced for this node."
130
+ )
131
+ try:
132
+ Version(version)
133
+ except InvalidVersion as error:
134
+ raise UpgradeError(f"{version!r} is not a release version") from error
135
+ await self.install(version)
136
+ reminder_id = await wake_after(version)
137
+ # the node cannot restart itself from the inside: on Windows the
138
+ # stop it would ask for kills the process tree it is asking from.
139
+ # Exiting is the one thing it can do that its host watches for.
140
+ self._request_restart()
141
+ return version, reminder_id
142
+
143
+ async def install(self, version: str) -> None:
144
+ await asyncio.to_thread(_install, version)
145
+
146
+
147
+ __all__ = [
148
+ "UpgradeError",
149
+ "UpgradeService",
150
+ "UpgradeUnavailable",
151
+ ]
@@ -24,6 +24,10 @@ from .app.transport import LocalCommandClient
24
24
  from .core.reminder import format_utc_timestamp
25
25
  from .rendering import TextTemplate
26
26
 
27
+ # Windows has nothing that brings the node back after an upgrade exits it, so
28
+ # there the node offers no upgrade and the commands would only ever be refused
29
+ _NODE_COMMANDS_HIDDEN = os.name == "nt"
30
+
27
31
 
28
32
  class BccCommandError(RuntimeError):
29
33
  def __init__(
@@ -47,8 +51,8 @@ def build_parser() -> argparse.ArgumentParser:
47
51
  description=(
48
52
  "Session-scoped collaboration commands for a Bazaar Compute Node. "
49
53
  "Use these commands from the current agent session to inspect messages, "
50
- "send replies, manage thread attention, schedule "
51
- "persistent reminders, and upgrade this node."
54
+ "send replies, manage thread attention, and schedule "
55
+ "persistent reminders."
52
56
  ),
53
57
  epilog=(
54
58
  "Run `bcc <resource> --help` or "
@@ -58,7 +62,11 @@ def build_parser() -> argparse.ArgumentParser:
58
62
  subparsers = parser.add_subparsers(
59
63
  dest="resource",
60
64
  required=True,
61
- metavar="{message,inbox,thread,reminder,node}",
65
+ metavar=(
66
+ "{message,inbox,thread,reminder}"
67
+ if _NODE_COMMANDS_HIDDEN
68
+ else "{message,inbox,thread,reminder,node}"
69
+ ),
62
70
  title="resources",
63
71
  )
64
72
 
@@ -330,6 +338,9 @@ def build_parser() -> argparse.ArgumentParser:
330
338
  help="Reminder id (full uuid)",
331
339
  )
332
340
 
341
+ if _NODE_COMMANDS_HIDDEN:
342
+ return parser
343
+
333
344
  node_parser = subparsers.add_parser(
334
345
  "node",
335
346
  help="Operations on the node this session runs on",
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import asyncio
4
4
  import logging
5
+ import os
5
6
  from collections.abc import Awaitable, Callable, Sequence
6
7
  from dataclasses import dataclass, replace
7
8
 
@@ -144,6 +145,9 @@ def inbox_notice(
144
145
  "rows": [row[2] for row in rows],
145
146
  "upgrade_version": upgrade_version,
146
147
  "installed_version": installed_version,
148
+ # Windows has nothing that would bring the node back after an
149
+ # upgrade exits it, so there the user runs the commands themselves
150
+ "manual_upgrade": os.name == "nt",
147
151
  "closing_bracket_on_own_line": closing_bracket_on_own_line,
148
152
  }
149
153
  )
@@ -1,5 +1,5 @@
1
1
  [inbox notice:
2
2
  Inbox update: {{ total_unread_count }} unread {{ "message" if total_unread_count == 1 else "messages" }} total; {{ rows | length }} changed {{ "target" if rows | length == 1 else "targets" }}{% for row in rows %}
3
3
  {{ row.target }} pending: {{ row.pending_count }} {{ "message" if row.pending_count == 1 else "messages" }} · first msg={{ row.first_id }}{% if row.latest_sender is not none %} · latest sender @{{ row.latest_sender }}{% endif %} · latest msg={{ row.latest_id }}{% for flag in row.flags %} · {{ "you were mentioned" if flag == "mention" else flag }}{% endfor %}{% endfor %}{% if upgrade_version is not none and installed_version is not none %}
4
- Upgrade available: {{ distribution }} {{ upgrade_version }} (installed {{ installed_version }}). Mention it in passing when you reply and offer to upgrade; if the user agrees, run `bcc node upgrade`. If they do not want it, just carry on.{% endif %}{% if closing_bracket_on_own_line %}
4
+ Upgrade available: {{ distribution }} {{ upgrade_version }} (installed {{ installed_version }}). Mention it in passing when you reply and offer to upgrade. {% if manual_upgrade %}Upgrading is theirs to run on this platform: if they want it, give them these three commands in this order, and say the second one needs the node stopped: `bcn system-service stop`, `uv tool install --force --refresh-package {{ distribution }} {{ distribution }}=={{ upgrade_version }}`, `bcn system-service start`.{% else %}If the user agrees, run `bcc node upgrade`.{% endif %} If they do not want it, just carry on.{% endif %}{% if closing_bracket_on_own_line %}
5
5
  {% endif %}]{{ "" -}}
@@ -0,0 +1,98 @@
1
+ # {{ managed_marker }}
2
+ $ErrorActionPreference = 'Stop'
3
+
4
+ $executable = {{ executable }}
5
+ $configPath = {{ config_path }}
6
+ $environmentScript = {{ environment_script }}
7
+ $logPath = {{ log_path }}
8
+
9
+ try {
10
+ Add-Type -TypeDefinition @'
11
+ using System;
12
+ using System.Diagnostics;
13
+ using System.IO;
14
+ using System.Threading.Tasks;
15
+
16
+ public static class BcnNoWindowProcess
17
+ {
18
+ public static int Run(string executable, string configPath, string logPath)
19
+ {
20
+ ProcessStartInfo startInfo = new ProcessStartInfo();
21
+ startInfo.FileName = executable;
22
+ startInfo.Arguments = "run --config \"" + configPath + "\"";
23
+ startInfo.UseShellExecute = false;
24
+ startInfo.CreateNoWindow = true;
25
+ startInfo.RedirectStandardInput = true;
26
+ startInfo.RedirectStandardOutput = true;
27
+ startInfo.RedirectStandardError = true;
28
+
29
+ using (Process process = new Process())
30
+ using (FileStream logStream = new FileStream(
31
+ logPath,
32
+ FileMode.Append,
33
+ FileAccess.Write,
34
+ FileShare.ReadWrite | FileShare.Delete
35
+ ))
36
+ {
37
+ process.StartInfo = startInfo;
38
+ process.Start();
39
+ process.StandardInput.Close();
40
+
41
+ object writeLock = new object();
42
+ Task stdoutTask = CopyToLogAsync(
43
+ process.StandardOutput.BaseStream,
44
+ logStream,
45
+ writeLock
46
+ );
47
+ Task stderrTask = CopyToLogAsync(
48
+ process.StandardError.BaseStream,
49
+ logStream,
50
+ writeLock
51
+ );
52
+
53
+ process.WaitForExit();
54
+ Task.WaitAll(stdoutTask, stderrTask);
55
+ return process.ExitCode;
56
+ }
57
+ }
58
+
59
+ private static async Task CopyToLogAsync(
60
+ Stream source,
61
+ Stream destination,
62
+ object writeLock
63
+ )
64
+ {
65
+ byte[] buffer = new byte[8192];
66
+ int bytesRead;
67
+ while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length)) > 0)
68
+ {
69
+ lock (writeLock)
70
+ {
71
+ destination.Write(buffer, 0, bytesRead);
72
+ destination.Flush();
73
+ }
74
+ }
75
+ }
76
+ }
77
+ '@
78
+ } catch {
79
+ $_ | Out-String | Add-Content -LiteralPath $logPath -Encoding utf8
80
+ exit 1
81
+ }
82
+
83
+ if ($environmentScript -and (Test-Path -LiteralPath $environmentScript)) {
84
+ try {
85
+ . $environmentScript
86
+ } catch {
87
+ $_ | Out-String | Add-Content -LiteralPath $logPath -Encoding utf8
88
+ exit 1
89
+ }
90
+ }
91
+
92
+ try {
93
+ $exitCode = [BcnNoWindowProcess]::Run($executable, $configPath, $logPath)
94
+ } catch {
95
+ $_ | Out-String | Add-Content -LiteralPath $logPath -Encoding utf8
96
+ exit 1
97
+ }
98
+ exit $exitCode