agentwire-dev 1.29.0__tar.gz → 1.29.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (315) hide show
  1. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/CHANGELOG.md +1 -0
  2. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/PKG-INFO +2 -1
  3. agentwire_dev-1.29.2/SECURITY.md +59 -0
  4. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/__init__.py +1 -1
  5. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/config.py +5 -0
  6. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/server.py +94 -36
  7. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/css/desktop.css +273 -0
  8. agentwire_dev-1.29.2/agentwire/static/js/command-palette.js +601 -0
  9. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/desktop-manager.js +14 -0
  10. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/desktop.js +55 -7
  11. agentwire_dev-1.29.2/agentwire/static/js/pinned-message.js +232 -0
  12. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/sidebar/projects-section.js +3 -3
  13. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/windows/chat-window.js +7 -0
  14. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/templates/desktop.html +1 -1
  15. agentwire_dev-1.29.2/docs/decisions/obsidian-second-brain.md +88 -0
  16. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/docs/wiki/INDEX.md +3 -2
  17. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/docs/wiki/deployment/remote-machines.md +3 -3
  18. agentwire_dev-1.29.2/docs/wiki/tts/stt-self-hosted.md +108 -0
  19. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/pyproject.toml +2 -0
  20. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/conftest.py +1 -1
  21. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_cli_safety.py +6 -2
  22. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_history.py +2 -2
  23. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_missions_config.py +5 -5
  24. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_project_config.py +4 -4
  25. agentwire_dev-1.29.0/SECURITY.md +0 -46
  26. agentwire_dev-1.29.0/agentwire/static/js/quicktask-modal.js +0 -267
  27. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/.github/FUNDING.yml +0 -0
  28. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  29. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  30. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/.github/ISSUE_TEMPLATE/question.md +0 -0
  31. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  32. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/.gitignore +0 -0
  33. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/CLA.md +0 -0
  34. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/CODE_OF_CONDUCT.md +0 -0
  35. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/CONTRIBUTING.md +0 -0
  36. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/Dockerfile.local +0 -0
  37. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/Dockerfile.runpod +0 -0
  38. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/LICENSE +0 -0
  39. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/README.md +0 -0
  40. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/RELEASING.md +0 -0
  41. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/SPONSORS.md +0 -0
  42. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/__main__.py +0 -0
  43. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/agents/__init__.py +0 -0
  44. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/agents/base.py +0 -0
  45. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/agents/tmux.py +0 -0
  46. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/cached_status.py +0 -0
  47. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/channels/__init__.py +0 -0
  48. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/channels/base.py +0 -0
  49. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/channels/email.py +0 -0
  50. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/channels/quo.py +0 -0
  51. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/cli_safety.py +0 -0
  52. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/completion.py +0 -0
  53. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/fetch.py +0 -0
  54. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/handoff/__init__.py +0 -0
  55. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/handoff/git_state.py +0 -0
  56. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/handoff/instructions.py +0 -0
  57. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/handoff/parser.py +0 -0
  58. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/handoff/renderer.py +0 -0
  59. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/handoff/schema.py +0 -0
  60. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/history.py +0 -0
  61. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/hooks/__init__.py +0 -0
  62. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/hooks/agentwire-permission.sh +0 -0
  63. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/hooks/damage-control/__init__.py +0 -0
  64. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/hooks/damage-control/audit_logger.py +0 -0
  65. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/hooks/damage-control/bash-tool-damage-control.py +0 -0
  66. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/hooks/damage-control/edit-tool-damage-control.py +0 -0
  67. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/hooks/damage-control/rules/agentwire.yaml +0 -0
  68. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/hooks/damage-control/rules/aws.yaml +0 -0
  69. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/hooks/damage-control/rules/cloud-hosting.yaml +0 -0
  70. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/hooks/damage-control/rules/containers.yaml +0 -0
  71. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/hooks/damage-control/rules/core.yaml +0 -0
  72. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/hooks/damage-control/rules/databases.yaml +0 -0
  73. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/hooks/damage-control/rules/firebase.yaml +0 -0
  74. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/hooks/damage-control/rules/gcp.yaml +0 -0
  75. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/hooks/damage-control/rules/git.yaml +0 -0
  76. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/hooks/damage-control/rules/gws.yaml +0 -0
  77. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/hooks/damage-control/rules/infrastructure.yaml +0 -0
  78. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/hooks/damage-control/rules/remote.yaml +0 -0
  79. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/hooks/damage-control/write-tool-damage-control.py +0 -0
  80. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/hooks/idle-handler.sh +0 -0
  81. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/listen.py +0 -0
  82. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/locking.py +0 -0
  83. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/mcp_server.py +0 -0
  84. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/missions/__init__.py +0 -0
  85. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/missions/cli.py +0 -0
  86. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/missions/config.py +0 -0
  87. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/missions/dispatcher.py +0 -0
  88. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/missions/eligibility.py +0 -0
  89. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/missions/feedback_router.py +0 -0
  90. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/missions/gc.py +0 -0
  91. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/missions/github.py +0 -0
  92. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/missions/naming.py +0 -0
  93. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/missions/state.py +0 -0
  94. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/network.py +0 -0
  95. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/onboarding.py +0 -0
  96. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/overnight.py +0 -0
  97. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/pane_manager.py +0 -0
  98. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/project_config.py +0 -0
  99. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/projects.py +0 -0
  100. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/prompts/__init__.py +0 -0
  101. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/prompts/init.md +0 -0
  102. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/roles/__init__.py +0 -0
  103. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/roles/agentwire.md +0 -0
  104. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/roles/chatbot.md +0 -0
  105. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/roles/init.md +0 -0
  106. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/roles/notifications.md +0 -0
  107. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/roles/orchestrator.md +0 -0
  108. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/roles/task-runner.md +0 -0
  109. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/roles/voice.md +0 -0
  110. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/roles/worker.md +0 -0
  111. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/safety/__init__.py +0 -0
  112. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/safety/_core.py +0 -0
  113. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/scheduler.py +0 -0
  114. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/search.py +0 -0
  115. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/agentwire-Echo--black.png +0 -0
  116. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/agentwire-Echo--transparent.png +0 -0
  117. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/agentwire-Echo.png +0 -0
  118. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/agentwire-email-banner.png +0 -0
  119. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/agentwire-splash-logo-layers--agentwire-text.png +0 -0
  120. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/agentwire-splash-logo-layers--echo-claw-fg.png +0 -0
  121. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/agentwire-splash-logo-layers--echo.png +0 -0
  122. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/agentwire-splash-logo-layers--full--transparent-top.png +0 -0
  123. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/agentwire-splash-logo-layers--full-black.png +0 -0
  124. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/agentwire-splash-logo-layers--telephone-fg.png +0 -0
  125. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/agentwire-splash-logo-layers--telephone.png +0 -0
  126. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/agentwire-splash-logo-layers--transparent-top.png +0 -0
  127. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/agentwire-splash-logo-layers--transparent.png +0 -0
  128. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/agentwire-splash-logo-layers--tree.png +0 -0
  129. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/agentwire-splash-logo-layers.png +0 -0
  130. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/favicon.png +0 -0
  131. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/machines/android.jpeg +0 -0
  132. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/machines/automaton.jpeg +0 -0
  133. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/machines/bot.jpeg +0 -0
  134. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/machines/cyborg.jpeg +0 -0
  135. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/machines/droid.jpeg +0 -0
  136. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/machines/drone.jpeg +0 -0
  137. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/machines/guardian.jpeg +0 -0
  138. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/machines/mech.jpeg +0 -0
  139. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/machines/probe.jpeg +0 -0
  140. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/machines/robot.jpeg +0 -0
  141. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/machines/sentinel.jpeg +0 -0
  142. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/machines/unit.jpeg +0 -0
  143. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/projects/blob.jpeg +0 -0
  144. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/projects/cloud.jpeg +0 -0
  145. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/projects/crystal.jpeg +0 -0
  146. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/projects/cyclops.jpeg +0 -0
  147. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/projects/flame.jpeg +0 -0
  148. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/projects/fuzzy.jpeg +0 -0
  149. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/projects/horned.jpeg +0 -0
  150. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/projects/moon.jpeg +0 -0
  151. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/projects/slime.jpeg +0 -0
  152. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/projects/star.jpeg +0 -0
  153. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/projects/tentacle.jpeg +0 -0
  154. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/projects/winged.jpeg +0 -0
  155. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/sessions/bear.jpeg +0 -0
  156. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/sessions/cat.jpeg +0 -0
  157. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/sessions/crown.jpeg +0 -0
  158. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/sessions/custom/agentwire-portal.png +0 -0
  159. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/sessions/custom/agentwire-tts.png +0 -0
  160. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/sessions/custom/agentwire.png +0 -0
  161. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/sessions/deer.jpeg +0 -0
  162. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/sessions/drone.jpeg +0 -0
  163. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/sessions/eagle.jpeg +0 -0
  164. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/sessions/fox.jpeg +0 -0
  165. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/sessions/hawk.jpeg +0 -0
  166. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/sessions/horse.jpeg +0 -0
  167. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/sessions/lion.jpeg +0 -0
  168. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/sessions/rabbit.jpeg +0 -0
  169. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/sessions/robot.jpeg +0 -0
  170. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/sessions/tiger.jpeg +0 -0
  171. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/icons/sessions/wolf.jpeg +0 -0
  172. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/.gitkeep +0 -0
  173. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/artifact-window.js +0 -0
  174. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/components/icon-picker.js +0 -0
  175. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/components/list-card.js +0 -0
  176. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/components/type-tag.js +0 -0
  177. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/icon-manager.js +0 -0
  178. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/new-project-modal.js +0 -0
  179. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/notifications-panel.js +0 -0
  180. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/safety-shared.js +0 -0
  181. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/safety-window.js +0 -0
  182. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/session-id.js +0 -0
  183. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/session-window.js +0 -0
  184. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/sidebar/artifacts-section.js +0 -0
  185. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/sidebar/config-section.js +0 -0
  186. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/sidebar/machines-section.js +0 -0
  187. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/sidebar/missions-section.js +0 -0
  188. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/sidebar/safety-section.js +0 -0
  189. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/sidebar/scheduler-section.js +0 -0
  190. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/sidebar/services-section.js +0 -0
  191. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/sidebar/sessions-section.js +0 -0
  192. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/sidebar.js +0 -0
  193. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/terminal-font-prefs.js +0 -0
  194. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/tile-manager.js +0 -0
  195. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/utils/auto-refresh.js +0 -0
  196. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/static/js/winbox.bundle.min.js +0 -0
  197. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/stt/__init__.py +0 -0
  198. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/stt/base.py +0 -0
  199. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/stt/server_backend.py +0 -0
  200. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/stt/stt_server.py +0 -0
  201. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/stt/whisperkit.py +0 -0
  202. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/tasks.py +0 -0
  203. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/templates/__init__.py +0 -0
  204. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/templates/base.html +0 -0
  205. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/templates/email_notification.html +0 -0
  206. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/templates/handoff/show-the-story.html.j2 +0 -0
  207. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/templates/handoff/theme.css.j2 +0 -0
  208. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/templates/tmux.conf +0 -0
  209. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/templating.py +0 -0
  210. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/tooldefs/aws.yaml +0 -0
  211. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/tooldefs/docker.yaml +0 -0
  212. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/tooldefs/gcp.yaml +0 -0
  213. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/tooldefs/gh.yaml +0 -0
  214. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/tooldefs/git.yaml +0 -0
  215. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/tooldefs/gws.yaml +0 -0
  216. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/tooldefs/kubectl.yaml +0 -0
  217. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/tooldefs/npm.yaml +0 -0
  218. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/tooldefs/terraform.yaml +0 -0
  219. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/tooldefs/uv.yaml +0 -0
  220. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/tts/__init__.py +0 -0
  221. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/tts/base.py +0 -0
  222. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/tts/engines/__init__.py +0 -0
  223. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/tts/engines/chatterbox.py +0 -0
  224. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/tts/engines/kokoro.py +0 -0
  225. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/tts/engines/qwen_base.py +0 -0
  226. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/tts/engines/qwen_custom.py +0 -0
  227. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/tts/engines/qwen_design.py +0 -0
  228. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/tts/engines/zonos.py +0 -0
  229. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/tts/registry.py +0 -0
  230. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/tts/runpod_handler.py +0 -0
  231. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/tts_server.py +0 -0
  232. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/tunnels.py +0 -0
  233. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/utils/__init__.py +0 -0
  234. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/utils/chunker.py +0 -0
  235. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/utils/file_io.py +0 -0
  236. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/utils/paths.py +0 -0
  237. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/utils/subprocess.py +0 -0
  238. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/validation.py +0 -0
  239. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/voiceclone.py +0 -0
  240. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/voices/darren.wav +0 -0
  241. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/voices/default.wav +0 -0
  242. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/voices/jessica.wav +0 -0
  243. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/voices/lisa.wav +0 -0
  244. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/voices/may.wav +0 -0
  245. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/agentwire/worktree.py +0 -0
  246. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/docs/logo.png +0 -0
  247. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/docs/wiki/architecture.md +0 -0
  248. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/docs/wiki/communication/channels.md +0 -0
  249. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/docs/wiki/communication/hammerspoon.md +0 -0
  250. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/docs/wiki/communication/handoff.md +0 -0
  251. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/docs/wiki/concepts.md +0 -0
  252. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/docs/wiki/deployment/remote-access.md +0 -0
  253. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/docs/wiki/glossary.md +0 -0
  254. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/docs/wiki/integrations/gws-google-workspace-cli.md +0 -0
  255. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/docs/wiki/internals/damage-control.md +0 -0
  256. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/docs/wiki/internals/portal.md +0 -0
  257. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/docs/wiki/internals/shell-escaping.md +0 -0
  258. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/docs/wiki/internals/troubleshooting.md +0 -0
  259. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/docs/wiki/missions.md +0 -0
  260. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/docs/wiki/quickstart.md +0 -0
  261. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/docs/wiki/scheduling/scheduled-workloads.md +0 -0
  262. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/docs/wiki/sessions/claude-code-auto-mode.md +0 -0
  263. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/docs/wiki/sessions/pi.md +0 -0
  264. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/docs/wiki/tts/runpod-tts.md +0 -0
  265. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/docs/wiki/tts/tts-self-hosted.md +0 -0
  266. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/requirements-tts.txt +0 -0
  267. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/templates/launchd/dev.agentwire.mission-dispatcher.plist +0 -0
  268. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/templates/launchd/dev.agentwire.mission-feedback-router.plist +0 -0
  269. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/templates/launchd/dev.agentwire.mission-janitor.plist +0 -0
  270. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/e2e/test_portal_ui.py +0 -0
  271. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/fixtures/sample_agentwire.yml +0 -0
  272. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/fixtures/sample_config.yaml +0 -0
  273. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/fixtures/sample_scheduler.yaml +0 -0
  274. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/integration/test_missions_concurrency.py +0 -0
  275. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/integration/test_missions_lifecycle.py +0 -0
  276. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/integration/test_scheduler_board.py +0 -0
  277. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/integration/test_server_websockets.py +0 -0
  278. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_build_agent_command.py +0 -0
  279. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_channels.py +0 -0
  280. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_cli_commands.py +0 -0
  281. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_cli_output.py +0 -0
  282. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_config.py +0 -0
  283. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_damage_control_hooks.py +0 -0
  284. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_damage_control_sync.py +0 -0
  285. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_file_io.py +0 -0
  286. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_handoff_git_state.py +0 -0
  287. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_handoff_instructions.py +0 -0
  288. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_handoff_parser.py +0 -0
  289. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_handoff_renderer.py +0 -0
  290. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_locking.py +0 -0
  291. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_mcp_server.py +0 -0
  292. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_mcp_tools_args.py +0 -0
  293. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_missions_cli.py +0 -0
  294. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_missions_dispatcher.py +0 -0
  295. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_missions_eligibility.py +0 -0
  296. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_missions_feedback_router.py +0 -0
  297. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_missions_gc.py +0 -0
  298. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_missions_github.py +0 -0
  299. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_missions_naming.py +0 -0
  300. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_missions_state.py +0 -0
  301. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_overnight_resume_flags.py +0 -0
  302. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_portal_api.py +0 -0
  303. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_roles.py +0 -0
  304. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_safety_disabled_rules.py +0 -0
  305. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_safety_escape_hatch.py +0 -0
  306. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_safety_kill_switch.py +0 -0
  307. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_safety_mission_worker.py +0 -0
  308. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_scheduler.py +0 -0
  309. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_scheduler_parsing.py +0 -0
  310. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_search.py +0 -0
  311. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_server_async.py +0 -0
  312. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_server_pure.py +0 -0
  313. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_tasks.py +0 -0
  314. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_templating.py +0 -0
  315. {agentwire_dev-1.29.0 → agentwire_dev-1.29.2}/tests/unit/test_worktree.py +0 -0
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
10
10
  ### Removed
11
11
 
12
12
  - **Workflow engine** — entire `agentwire/workflows/` package (DAG runner, definitions, storage, pi runner, CLI), the `agentwire workflow` CLI subcommand, 5 MCP tools (`workflow_list/validate/run/history/show`), 3 portal endpoints (`/api/workflows/list|runs|runs/{id}`), the Workflows sidebar section + WorkflowWindow + ~230 lines of CSS, the scheduler's `workflow:` dispatch branch (`SchedulerTask.workflow`/`inputs` fields, `_dispatch_workflow_task`, `_render_workflow_inputs`, `_parse_workflow_summary`, `_workflow_failure_state`, validation block), 9 workflow test files plus the workflow-specific cases in `test_scheduler.py`, the `agentwire-workflows` skill, `docs/wiki/scheduling/workflows.md`, and ~120 dirs of historical runs under `~/.agentwire/workflows/`. The user's actual recurring automations all live as scheduler ensure tasks (`task:`); the engine was unused in practice and the empty sidebar surface was just noise. Scheduler is now ensure-only.
13
+ - **On-hold mission docs** — retroactive accounting for the seven on-hold files left behind by #153 and wholesale-deleted in commit `2425847` (2026-05-13) as part of the GitHub-issues-as-SSOT migration: `docs/missions/OBJECTIVE.md` (folded into README + website), `docs/missions/pi-harness-overview.md` (roadmap superseded — phases shipped or moved to research wiki), `docs/missions/pi-workflow-advanced.md` (on-hold-awaiting-usage stance has no scoped plan to track), `docs/missions/pi-workflow-ui.md` (visible portion shipped; speculative remainder unscoped), `docs/missions/later/multi-channel-bus.md` (premise actively rejected — wire surface is now outbound-only), `docs/missions/later/personal-replica.md` (speculative ideation, not a plan), `docs/missions/later/ralph-loop-use-cases.md` (brainstorm artifact). Closes [#154](https://github.com/dotdevdotdev/agentwire-dev/issues/154).
13
14
  - **Inbound channel surface** — entire Telegram bridge (`agentwire/bridges/telegram.py`), Discord channel (`agentwire/channels/discord.py`), Slack channel (`agentwire/channels/slack.py`), Twilio SMS (`agentwire/channels/sms.py`), Webhook (`agentwire/channels/webhook.py`), outbound-Telegram (`agentwire/channels/telegram.py`), channel scaffolding template (`agentwire/channels/_template.py`), all `agentwire {telegram,discord,slack,sms,webhook}` CLI command groups, the `agentwire reply` command, MCP tools `discord_status` / `slack_status` / `sms_send` / `webhook_send`, the portal sidebar "socials" section, the `ServiceChannel` / `MessageQueueManager` / `QueuedMessage` / `compose_session_config` / `inject_instructions` / session-helper plumbing in `channels/base.py`, the TTS/STT primitives on the channel base class, the auto-injected `discord-dm` / `slack-dm` / `channel-admin` roles, the `OutputConfig.notify` task field plus its `_handle_task_notification` dispatcher (voice / alert / webhook / email / command), the doctor's Telegram bridge check, and the `aiogram` optional dep. Wire surface is now outbound-only: **email** (Resend) and **quo** (OpenPhone SMS) remain. Inbound user input flows through the portal. Security review traced the cut: Telegram bridge was secure (refuse-to-start on empty allowlist + silent default-deny), Discord/Slack fail-open on empty allowlist + unauthenticated channel `@mention`; rather than fix the gaps, the whole inbound surface comes out to keep the wire posture outbound-only.
14
15
  - **Anthropic SDK surface** — entire `agentwire/sdk/` package, `agentwire/repl/` (Textual REPL), `agentwire/workflows/runners/{anthropic,human_gate}.py`, `sdk-bypass` / `sdk-prompted` / `sdk-restricted` session types, `sdk-watch` portal window + sidebar section, `--runner` workflow CLI override, and the `claude-agent-sdk` dependency. Anthropic moved Agent SDK + `claude -p` usage out of the monthly subscription tier on 2026-05-13 (now API-billed); the in-tree consumers were too expensive to keep running. The `pi` workflow runner is now the only runner. For Anthropic-quality scheduled work, use a `claude-bypass` tmux session via `.agentwire.yml` + scheduler. Mission [#184](https://github.com/dotdevdotdev/agentwire-dev/issues/184). Findings captured in `~/.agentwire/wiki/` (anthropic-agent-sdk, anthropic-runner-findings, textual-repl-retrospective, workflow-runner-choice, claude-code-print-mode).
15
16
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentwire-dev
3
- Version: 1.29.0
3
+ Version: 1.29.2
4
4
  Summary: Multi-session voice web interface for AI coding agents
5
5
  Project-URL: Homepage, https://agentwire.dev
6
6
  Project-URL: Repository, https://github.com/dotdevdotdev/agentwire-dev
@@ -686,6 +686,7 @@ Classifier: Topic :: Software Development :: User Interfaces
686
686
  Requires-Python: >=3.10
687
687
  Requires-Dist: aiohttp-jinja2>=1.6
688
688
  Requires-Dist: aiohttp>=3.9.0
689
+ Requires-Dist: av>=12.0.0
689
690
  Requires-Dist: jinja2>=3.1.0
690
691
  Requires-Dist: markdown>=3.5
691
692
  Requires-Dist: mcp>=1.2.0
@@ -0,0 +1,59 @@
1
+ # Security Policy
2
+
3
+ ## Reporting a Vulnerability
4
+
5
+ If you discover a security vulnerability in AgentWire, please report it privately.
6
+
7
+ **Do NOT open a public GitHub issue for security vulnerabilities.**
8
+
9
+ ### How to Report
10
+
11
+ Email: security@agentwire.dev
12
+
13
+ Include:
14
+ - Description of the vulnerability
15
+ - Steps to reproduce
16
+ - Potential impact
17
+ - Any suggested fixes (optional)
18
+
19
+ ### What to Expect
20
+
21
+ - **Acknowledgment:** Within 48 hours
22
+ - **Initial Assessment:** Within 1 week
23
+ - **Resolution Timeline:** Depends on severity, typically 30-90 days
24
+
25
+ ### Scope
26
+
27
+ This security policy applies to:
28
+ - The AgentWire CLI (`agentwire` command)
29
+ - The AgentWire portal (web interface)
30
+ - Official AgentWire packages on PyPI
31
+
32
+ ### Out of Scope
33
+
34
+ - Third-party dependencies (report to their maintainers)
35
+ - Self-hosted TTS/STT servers
36
+ - User misconfiguration
37
+
38
+ ## Security Features
39
+
40
+ AgentWire includes built-in security features:
41
+
42
+ - **Damage Control Hooks:** Block 300+ dangerous command patterns
43
+ - **Path Protection:** Prevent access to sensitive files (.env, SSH keys, credentials)
44
+ - **Audit Logging:** All blocked operations are logged
45
+
46
+ See `docs/wiki/internals/damage-control.md` for details.
47
+
48
+ ## Trust Model
49
+
50
+ The portal (HTTPS server bound to `0.0.0.0:8765` by default) **has no built-in authentication or authorization on its API endpoints**. This is by design — agentwire is built for a local-network trust perimeter, typically running on the same machine as the operator's browser or behind a Cloudflare Tunnel + Zero Trust gate (see `docs/wiki/deployment/remote-access.md`).
51
+
52
+ What this means in practice:
53
+
54
+ - **Anyone who can reach the portal port can drive it.** All `/api/*` endpoints (scheduler control, missions dispatch, project deletion, artifact upload, desktop window control) execute without auth.
55
+ - **Do not expose the portal directly to the public internet.** Use either firewall rules limiting access to trusted IPs, or front it with an auth gateway. Cloudflare Tunnel + Zero Trust is the recommended pattern; details in the deployment docs.
56
+ - **Project deletion via `/api/projects/delete`** validates the path is absolute, contains no `..`, contains no shell metacharacters, and is not in a protected list. Local execution uses argv form (no shell); SSH execution uses `shlex.quote` per argument. These mitigations don't substitute for perimeter security — they reduce blast radius if the perimeter fails.
57
+ - **CSRF / Origin checks are not enforced** on state-changing POSTs. A browser inside the trust perimeter that loads attacker-controlled content could be coerced into making requests to the portal. If your portal is reachable from a browser on a less-trusted network, add an origin check or fence it behind an auth proxy.
58
+
59
+ If you need authentication, the recommended path is **Cloudflare Tunnel + Zero Trust** rather than adding auth in-process: identity, MFA, audit, and revocation are all handled upstream and survive process restarts.
@@ -1,3 +1,3 @@
1
1
  """AgentWire - Multi-session voice web interface for AI coding agents."""
2
2
 
3
- __version__ = "1.29.0"
3
+ __version__ = "1.29.2"
@@ -109,6 +109,10 @@ class STTConfig:
109
109
 
110
110
  url: str | None = None # STT server URL (e.g., http://localhost:8100)
111
111
  timeout: int = 30
112
+ # Milliseconds of silence to prepend to the decoded audio before sending
113
+ # to the STT backend. Default 0 — moonshine doesn't need it. Set to ~300
114
+ # if your backend (e.g. older faster-whisper builds) clips the first syllable.
115
+ silence_prepend_ms: int = 0
112
116
 
113
117
 
114
118
  @dataclass
@@ -406,6 +410,7 @@ def _dict_to_config(data: dict) -> Config:
406
410
  stt = STTConfig(
407
411
  url=stt_data.get("url"),
408
412
  timeout=stt_data.get("timeout", 30),
413
+ silence_prepend_ms=int(stt_data.get("silence_prepend_ms", 0)),
409
414
  )
410
415
 
411
416
  # Agent
@@ -2343,39 +2343,49 @@ class AgentWireServer:
2343
2343
  machine = data.get("machine")
2344
2344
  delete_type = data.get("deleteType")
2345
2345
 
2346
- if not path:
2346
+ if not path or not isinstance(path, str):
2347
2347
  return web.json_response({"success": False, "error": "Missing path"})
2348
2348
  if delete_type not in ("config", "folder"):
2349
2349
  return web.json_response({"success": False, "error": "Invalid deleteType"})
2350
2350
 
2351
- # Build the delete command
2351
+ # Path validation: absolute, no traversal, no shell metacharacters.
2352
+ # The endpoint has no auth (local-trust model — see SECURITY.md), so
2353
+ # treat the input as untrusted regardless and reject anything that
2354
+ # could escape argv quoting on either local or remote (SSH) execution.
2355
+ if not path.startswith("/"):
2356
+ return web.json_response({"success": False, "error": "path must be absolute"})
2357
+ if ".." in Path(path).parts:
2358
+ return web.json_response({"success": False, "error": "path may not contain '..'"})
2359
+ if re.search(r"[\s;&|`$<>(){}\[\]\\\"'*?#]", path):
2360
+ return web.json_response({"success": False, "error": "path contains disallowed characters"})
2361
+ if path.rstrip("/") in ("", "/root", "/home", "/Users", "/tmp", "/etc") or path.rstrip("/") in ("~", "$HOME"):
2362
+ return web.json_response({"success": False, "error": "Cannot delete protected paths"})
2363
+
2364
+ # Build argv. For SSH we still need to cross a remote shell, so
2365
+ # quote with shlex; locally we use array form with shell=False.
2352
2366
  if delete_type == "config":
2353
- cmd = f"rm -f '{path}/.agentwire.yml'"
2367
+ target = f"{path.rstrip('/')}/.agentwire.yml"
2368
+ local_argv = ["rm", "-f", target]
2354
2369
  else:
2355
- # Safety check: don't allow deleting root or home
2356
- if path in ("/", "/root", "/home") or path.rstrip("/") in ("~", "$HOME"):
2357
- return web.json_response({"success": False, "error": "Cannot delete protected paths"})
2358
- cmd = f"rm -rf '{path}'"
2370
+ local_argv = ["rm", "-rf", path]
2359
2371
 
2360
- # Execute locally or remotely
2361
2372
  if machine and machine != "local":
2362
- # Remote machine
2373
+ # Remote shell — quote each argv element through shlex.
2374
+ remote_cmd = " ".join(shlex.quote(a) for a in local_argv)
2363
2375
  result = await asyncio.to_thread(
2364
2376
  subprocess.run,
2365
- ["ssh", machine, cmd],
2377
+ ["ssh", machine, remote_cmd],
2366
2378
  capture_output=True,
2367
2379
  text=True,
2368
- timeout=30
2380
+ timeout=30,
2369
2381
  )
2370
2382
  else:
2371
- # Local
2372
2383
  result = await asyncio.to_thread(
2373
2384
  subprocess.run,
2374
- cmd,
2375
- shell=True,
2385
+ local_argv,
2376
2386
  capture_output=True,
2377
2387
  text=True,
2378
- timeout=30
2388
+ timeout=30,
2379
2389
  )
2380
2390
 
2381
2391
  if result.returncode != 0:
@@ -3273,7 +3283,13 @@ projects:
3273
3283
  return web.json_response({"error": str(e)}, status=500)
3274
3284
 
3275
3285
  async def handle_transcribe(self, request: web.Request) -> web.Response:
3276
- """Transcribe audio to text."""
3286
+ """Transcribe audio to text.
3287
+
3288
+ Decodes WebM/Opus uploads in-process via PyAV (no ffmpeg subprocess
3289
+ startup) and resamples to 16 kHz mono PCM16 — the canonical input
3290
+ shape for Whisper- and Moonshine-class models. Optionally prepends a
3291
+ configurable amount of silence (``stt.silence_prepend_ms``, default 0).
3292
+ """
3277
3293
  try:
3278
3294
  reader = await request.multipart()
3279
3295
  audio_field = await reader.next()
@@ -3281,46 +3297,88 @@ projects:
3281
3297
  if audio_field is None:
3282
3298
  return web.json_response({"error": "No audio data"})
3283
3299
 
3284
- # Read audio data
3285
3300
  audio_data = await audio_field.read()
3286
-
3287
3301
  if not audio_data:
3288
3302
  return web.json_response({"error": "Empty audio data"})
3289
3303
 
3290
- # Save webm to temp file
3291
- with tempfile.NamedTemporaryFile(suffix=".webm", delete=False) as f:
3292
- f.write(audio_data)
3293
- webm_path = f.name
3304
+ silence_ms = int(getattr(self.config.stt, "silence_prepend_ms", 0) or 0)
3294
3305
 
3295
- # Convert webm to wav (16kHz mono for Whisper)
3296
- wav_path = webm_path.replace(".webm", ".wav")
3297
3306
  try:
3298
- logger.info("Converting webm to wav: %s -> %s", webm_path, wav_path)
3299
- proc = await asyncio.create_subprocess_exec(
3300
- "ffmpeg", "-i", webm_path,
3301
- "-ar", "16000", "-ac", "1", "-y", wav_path,
3302
- stdout=asyncio.subprocess.DEVNULL,
3303
- stderr=asyncio.subprocess.DEVNULL,
3307
+ wav_data = await asyncio.get_event_loop().run_in_executor(
3308
+ None,
3309
+ self._decode_audio_to_wav,
3310
+ audio_data,
3311
+ silence_ms,
3304
3312
  )
3305
- await proc.wait()
3313
+ except Exception as e:
3314
+ logger.error("Failed to decode audio: %s", e)
3315
+ return web.json_response({"error": "Audio conversion failed"})
3306
3316
 
3307
- if proc.returncode != 0 or not Path(wav_path).exists():
3308
- logger.error("Failed to convert webm to wav (ffmpeg returned %d)", proc.returncode)
3309
- return web.json_response({"error": "Audio conversion failed"})
3317
+ with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as f:
3318
+ f.write(wav_data)
3319
+ wav_path = f.name
3310
3320
 
3311
- # Transcribe the wav file
3321
+ try:
3312
3322
  logger.info("Transcribing %s via %s backend", wav_path, type(self.stt).__name__)
3313
3323
  text = await self.stt.transcribe(Path(wav_path))
3314
3324
  logger.info("Transcription result: %s", text)
3315
3325
  return web.json_response({"text": text})
3316
3326
  finally:
3317
- Path(webm_path).unlink(missing_ok=True)
3318
3327
  Path(wav_path).unlink(missing_ok=True)
3319
3328
 
3320
3329
  except Exception as e:
3321
3330
  logger.error(f"Transcription failed: {e}")
3322
3331
  return web.json_response({"error": str(e)})
3323
3332
 
3333
+ @staticmethod
3334
+ def _decode_audio_to_wav(audio_data: bytes, silence_prepend_ms: int = 0) -> bytes:
3335
+ """Decode arbitrary input audio (WebM/Opus, MP3, M4A, …) to 16 kHz mono PCM16 WAV.
3336
+
3337
+ Replaces the previous ``ffmpeg -i in.webm out.wav`` subprocess. Subprocess
3338
+ cold-start was 100–300 ms before any actual decoding; PyAV uses libav
3339
+ bindings in-process so the only cost is the decoding itself.
3340
+ """
3341
+ import io
3342
+ import wave
3343
+
3344
+ import av # PyAV — declared in pyproject.toml `dependencies`
3345
+
3346
+ target_rate = 16000
3347
+
3348
+ with av.open(io.BytesIO(audio_data), mode="r") as container:
3349
+ if not container.streams.audio:
3350
+ raise RuntimeError("Input contains no audio stream")
3351
+
3352
+ resampler = av.AudioResampler(format="s16", layout="mono", rate=target_rate)
3353
+ pcm_chunks: list[bytes] = []
3354
+
3355
+ def _frame_bytes(f) -> bytes:
3356
+ # AudioFrame.planes[0] may include SIMD alignment padding; slice
3357
+ # to the exact PCM length (samples × channels × bytes_per_sample).
3358
+ bytes_per_sample = f.format.bytes # 2 for s16
3359
+ channels = len(f.layout.channels) # 1 for mono
3360
+ size = f.samples * channels * bytes_per_sample
3361
+ return bytes(f.planes[0])[:size]
3362
+
3363
+ for frame in container.decode(audio=0):
3364
+ for resampled in resampler.resample(frame):
3365
+ pcm_chunks.append(_frame_bytes(resampled))
3366
+ for resampled in resampler.resample(None):
3367
+ pcm_chunks.append(_frame_bytes(resampled))
3368
+
3369
+ if silence_prepend_ms > 0:
3370
+ silence_samples = int(target_rate * silence_prepend_ms / 1000)
3371
+ pcm_chunks.insert(0, b"\x00\x00" * silence_samples)
3372
+
3373
+ pcm_data = b"".join(pcm_chunks)
3374
+ buf = io.BytesIO()
3375
+ with wave.open(buf, "wb") as wav:
3376
+ wav.setnchannels(1)
3377
+ wav.setsampwidth(2) # 16-bit
3378
+ wav.setframerate(target_rate)
3379
+ wav.writeframes(pcm_data)
3380
+ return buf.getvalue()
3381
+
3324
3382
  async def handle_upload(self, request: web.Request) -> web.Response:
3325
3383
  """Upload an image file for attachment to messages."""
3326
3384
  try:
@@ -1162,6 +1162,111 @@ body {
1162
1162
  text-align: center;
1163
1163
  }
1164
1164
 
1165
+ /* =========================================================================
1166
+ Command palette (Cmd/Ctrl+K)
1167
+ ========================================================================= */
1168
+
1169
+ .cmdk-overlay {
1170
+ align-items: flex-start;
1171
+ padding-top: 12vh;
1172
+ }
1173
+
1174
+ .command-palette {
1175
+ width: 560px;
1176
+ max-width: 92vw;
1177
+ display: flex;
1178
+ flex-direction: column;
1179
+ overflow: hidden;
1180
+ }
1181
+
1182
+ .cmdk-search {
1183
+ display: flex;
1184
+ align-items: center;
1185
+ gap: 10px;
1186
+ padding: 12px 16px;
1187
+ border-bottom: 1px solid var(--chrome-border);
1188
+ }
1189
+
1190
+ .cmdk-search-icon {
1191
+ color: var(--text-muted);
1192
+ font-size: 16px;
1193
+ }
1194
+
1195
+ .cmdk-input {
1196
+ flex: 1;
1197
+ background: transparent;
1198
+ border: none;
1199
+ outline: none;
1200
+ color: var(--text);
1201
+ font-size: 16px;
1202
+ font-family: inherit;
1203
+ }
1204
+
1205
+ .cmdk-input::placeholder {
1206
+ color: var(--text-muted);
1207
+ }
1208
+
1209
+ .cmdk-body {
1210
+ padding: 8px;
1211
+ max-height: 50vh;
1212
+ overflow-y: auto;
1213
+ }
1214
+
1215
+ /* Form drill-ins reuse the quicktask form styling. */
1216
+ .cmdk-body .quicktask-form {
1217
+ padding: 8px 8px 4px;
1218
+ }
1219
+
1220
+ .cmdk-item {
1221
+ display: flex;
1222
+ align-items: center;
1223
+ gap: 12px;
1224
+ padding: 10px 12px;
1225
+ border-radius: 6px;
1226
+ cursor: pointer;
1227
+ font-size: 14px;
1228
+ color: var(--text);
1229
+ }
1230
+
1231
+ .cmdk-item-selected {
1232
+ background: var(--accent);
1233
+ color: var(--background);
1234
+ }
1235
+
1236
+ .cmdk-item-icon {
1237
+ width: 18px;
1238
+ text-align: center;
1239
+ opacity: 0.85;
1240
+ }
1241
+
1242
+ .cmdk-item-label {
1243
+ flex: 1;
1244
+ }
1245
+
1246
+ .cmdk-item-sub {
1247
+ font-size: 12px;
1248
+ color: var(--text-muted);
1249
+ }
1250
+
1251
+ .cmdk-item-selected .cmdk-item-sub {
1252
+ color: var(--background);
1253
+ opacity: 0.8;
1254
+ }
1255
+
1256
+ .cmdk-empty {
1257
+ padding: 20px 12px;
1258
+ text-align: center;
1259
+ color: var(--text-muted);
1260
+ font-size: 14px;
1261
+ }
1262
+
1263
+ .cmdk-footer {
1264
+ padding: 8px 16px;
1265
+ border-top: 1px solid var(--chrome-border);
1266
+ font-size: 12px;
1267
+ color: var(--text-muted);
1268
+ }
1269
+
1165
1270
  .sidebar-quicktask {
1166
1271
  background: transparent;
1167
1272
  border: none;
@@ -4601,3 +4706,171 @@ body.sidebar-pinned .sidebar-tab {
4601
4706
  }
4602
4707
 
4603
4708
 
4709
+ /* =========================================================================
4710
+ Pinned Message Panel — floating, draggable, resizable
4711
+ ========================================================================= */
4712
+
4713
+ /* Pin affordance on chat messages — visible on hover, top-right corner. */
4714
+ .chat-message {
4715
+ position: relative;
4716
+ padding-right: 32px;
4717
+ }
4718
+
4719
+ .chat-message-pin-btn {
4720
+ position: absolute;
4721
+ top: 4px;
4722
+ right: 4px;
4723
+ width: 22px;
4724
+ height: 22px;
4725
+ padding: 0;
4726
+ border: 1px solid var(--chrome-border);
4727
+ border-radius: 4px;
4728
+ background: var(--chrome);
4729
+ color: var(--text-muted);
4730
+ font-size: 12px;
4731
+ line-height: 1;
4732
+ cursor: pointer;
4733
+ opacity: 0;
4734
+ transition: opacity 120ms ease, color 120ms ease, background 120ms ease;
4735
+ }
4736
+
4737
+ .chat-message:hover .chat-message-pin-btn,
4738
+ .chat-message:focus-within .chat-message-pin-btn,
4739
+ .chat-message-pin-btn:focus-visible {
4740
+ opacity: 0.9;
4741
+ }
4742
+
4743
+ .chat-message-pin-btn:hover {
4744
+ background: var(--hover);
4745
+ color: var(--accent);
4746
+ opacity: 1;
4747
+ }
4748
+
4749
+ .chat-message-pin-btn[data-pinned="true"] {
4750
+ opacity: 1;
4751
+ color: var(--accent);
4752
+ border-color: var(--accent);
4753
+ }
4754
+
4755
+ /* The floating panel itself. position: fixed keeps it above all winboxes
4756
+ regardless of scroll, typing, or which session window is active. */
4757
+ .pinned-message-panel {
4758
+ position: fixed;
4759
+ display: flex;
4760
+ flex-direction: column;
4761
+ background: var(--chrome);
4762
+ color: var(--text);
4763
+ border: 1px solid var(--chrome-border);
4764
+ border-radius: 8px;
4765
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.55), 0 0 0 1px var(--primary-subtle);
4766
+ z-index: 99998;
4767
+ min-width: 200px;
4768
+ min-height: 140px;
4769
+ overflow: hidden;
4770
+ user-select: text;
4771
+ }
4772
+
4773
+ .pinned-message-panel.dragging,
4774
+ .pinned-message-panel.resizing {
4775
+ user-select: none;
4776
+ }
4777
+
4778
+ .pinned-message-header {
4779
+ display: flex;
4780
+ align-items: center;
4781
+ gap: 8px;
4782
+ padding: 6px 10px;
4783
+ background: var(--background);
4784
+ border-bottom: 1px solid var(--chrome-border);
4785
+ cursor: grab;
4786
+ flex-shrink: 0;
4787
+ }
4788
+
4789
+ .pinned-message-panel.dragging .pinned-message-header {
4790
+ cursor: grabbing;
4791
+ }
4792
+
4793
+ .pinned-message-role {
4794
+ font-size: 11px;
4795
+ text-transform: uppercase;
4796
+ letter-spacing: 0.06em;
4797
+ padding: 2px 6px;
4798
+ border-radius: 4px;
4799
+ background: var(--chrome);
4800
+ color: var(--text-muted);
4801
+ border: 1px solid var(--chrome-border);
4802
+ flex-shrink: 0;
4803
+ }
4804
+
4805
+ .pinned-message-role[data-role="user"] {
4806
+ color: var(--accent);
4807
+ border-color: var(--primary-subtle);
4808
+ }
4809
+
4810
+ .pinned-message-title {
4811
+ flex: 1;
4812
+ font-size: 12px;
4813
+ color: var(--text-muted);
4814
+ text-transform: uppercase;
4815
+ letter-spacing: 0.08em;
4816
+ overflow: hidden;
4817
+ white-space: nowrap;
4818
+ text-overflow: ellipsis;
4819
+ }
4820
+
4821
+ .pinned-message-unpin {
4822
+ width: 22px;
4823
+ height: 22px;
4824
+ padding: 0;
4825
+ border: 1px solid var(--chrome-border);
4826
+ border-radius: 4px;
4827
+ background: transparent;
4828
+ color: var(--text-muted);
4829
+ font-size: 14px;
4830
+ line-height: 1;
4831
+ cursor: pointer;
4832
+ transition: color 120ms ease, background 120ms ease, border-color 120ms ease;
4833
+ flex-shrink: 0;
4834
+ }
4835
+
4836
+ .pinned-message-unpin:hover {
4837
+ color: var(--error);
4838
+ border-color: var(--error);
4839
+ background: var(--hover);
4840
+ }
4841
+
4842
+ .pinned-message-body {
4843
+ flex: 1;
4844
+ overflow: auto;
4845
+ padding: 10px 12px;
4846
+ font-size: 14px;
4847
+ line-height: 1.45;
4848
+ color: var(--text);
4849
+ white-space: pre-wrap;
4850
+ word-break: break-word;
4851
+ }
4852
+
4853
+ /* Corner resize handle — visible on hover. */
4854
+ .pinned-message-resize-handle {
4855
+ position: absolute;
4856
+ right: 0;
4857
+ bottom: 0;
4858
+ width: 16px;
4859
+ height: 16px;
4860
+ cursor: nwse-resize;
4861
+ opacity: 0;
4862
+ transition: opacity 120ms ease;
4863
+ /* Diagonal grip lines drawn with two thin gradients. */
4864
+ background:
4865
+ linear-gradient(135deg, transparent 0 45%, var(--text-muted) 45% 55%, transparent 55% 100%) no-repeat,
4866
+ linear-gradient(135deg, transparent 0 70%, var(--text-muted) 70% 80%, transparent 80% 100%) no-repeat;
4867
+ background-size: 10px 10px, 6px 6px;
4868
+ background-position: bottom 3px right 3px, bottom 3px right 3px;
4869
+ }
4870
+
4871
+ .pinned-message-panel:hover .pinned-message-resize-handle,
4872
+ .pinned-message-panel.resizing .pinned-message-resize-handle {
4873
+ opacity: 0.85;
4874
+ }
4875
+
4876
+