agentwire-dev 1.3.0__tar.gz → 1.4.0__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 (265) hide show
  1. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/PKG-INFO +1 -1
  2. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/__init__.py +1 -1
  3. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/__main__.py +187 -45
  4. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/agents/tmux.py +47 -18
  5. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/completion.py +1 -1
  6. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/config.py +22 -0
  7. agentwire_dev-1.3.0/agentwire/hooks/suppress-bg-notifications.sh → agentwire_dev-1.4.0/agentwire/hooks/idle-handler.sh +9 -0
  8. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/mcp_server.py +858 -0
  9. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/notifications.py +1 -1
  10. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/onboarding.py +59 -0
  11. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/pane_manager.py +14 -6
  12. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/server.py +262 -3
  13. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/css/desktop.css +80 -0
  14. agentwire_dev-1.4.0/agentwire/static/js/artifact-window.js +211 -0
  15. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/desktop-manager.js +44 -0
  16. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/desktop.js +92 -0
  17. agentwire_dev-1.4.0/agentwire/static/js/windows/artifacts-window.js +90 -0
  18. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/windows/projects-window.js +1 -0
  19. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/templates/desktop.html +1 -0
  20. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/templates/email_notification.html +12 -4
  21. agentwire_dev-1.4.0/agentwire/templates/tmux.conf +98 -0
  22. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/TROUBLESHOOTING.md +1 -1
  23. agentwire_dev-1.4.0/docs/issues/projects-dedup-ignores-machine.md +34 -0
  24. agentwire_dev-1.4.0/docs/issues/tmux-config-onboarding.md +120 -0
  25. agentwire_dev-1.4.0/docs/issues/tmux-paste-freeze.md +89 -0
  26. agentwire_dev-1.4.0/docs/issues/tmux-recommended-config.md +90 -0
  27. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/notification-hooks.md +1 -1
  28. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/pyproject.toml +1 -0
  29. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/.github/FUNDING.yml +0 -0
  30. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  31. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  32. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/.github/ISSUE_TEMPLATE/question.md +0 -0
  33. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  34. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/.github/workflows/ci.yml +0 -0
  35. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/.github/workflows/publish.yml +0 -0
  36. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/.gitignore +0 -0
  37. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/CHANGELOG.md +0 -0
  38. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/CLA.md +0 -0
  39. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/CODE_OF_CONDUCT.md +0 -0
  40. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/CONTRIBUTING.md +0 -0
  41. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/Dockerfile.local +0 -0
  42. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/Dockerfile.runpod +0 -0
  43. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/LICENSE +0 -0
  44. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/README.md +0 -0
  45. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/RELEASING.md +0 -0
  46. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/SECURITY.md +0 -0
  47. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/SPONSORS.md +0 -0
  48. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/agents/__init__.py +0 -0
  49. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/agents/base.py +0 -0
  50. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/cached_status.py +0 -0
  51. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/cli_safety.py +0 -0
  52. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/errors.py +0 -0
  53. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/history.py +0 -0
  54. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/hooks/__init__.py +0 -0
  55. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/hooks/agentwire-permission.sh +0 -0
  56. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/hooks/damage-control/__init__.py +0 -0
  57. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/hooks/damage-control/audit_logger.py +0 -0
  58. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/hooks/damage-control/bash-tool-damage-control.py +0 -0
  59. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/hooks/damage-control/edit-tool-damage-control.py +0 -0
  60. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/hooks/damage-control/patterns.yaml +0 -0
  61. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/hooks/damage-control/write-tool-damage-control.py +0 -0
  62. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/init_agentwire.py +0 -0
  63. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/listen.py +0 -0
  64. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/locking.py +0 -0
  65. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/network.py +0 -0
  66. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/project_config.py +0 -0
  67. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/projects.py +0 -0
  68. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/prompts/__init__.py +0 -0
  69. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/prompts/init.md +0 -0
  70. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/__init__.py +0 -0
  71. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/chatbot.md +0 -0
  72. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/claude-delegation.md +0 -0
  73. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/claude-worker-haiku.md +0 -0
  74. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/claude-worker-sonnet.md +0 -0
  75. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/claude-worker.md +0 -0
  76. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/glm-delegation.md +0 -0
  77. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/glm-worker-flash.md +0 -0
  78. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/glm-worker.md +0 -0
  79. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/init.md +0 -0
  80. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/leader-claude.md +0 -0
  81. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/leader-glm.md +0 -0
  82. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/leader-openai.md +0 -0
  83. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/leader.md +0 -0
  84. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/openai-delegation.md +0 -0
  85. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/openai-worker-mini.md +0 -0
  86. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/openai-worker.md +0 -0
  87. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/task-runner.md +0 -0
  88. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/voice.md +0 -0
  89. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/worker.md +0 -0
  90. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-Echo--black.png +0 -0
  91. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-Echo--transparent.png +0 -0
  92. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-Echo.png +0 -0
  93. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-email-banner.png +0 -0
  94. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-splash-logo-layers--agentwire-text.png +0 -0
  95. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-splash-logo-layers--echo-claw-fg.png +0 -0
  96. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-splash-logo-layers--echo.png +0 -0
  97. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-splash-logo-layers--full--transparent-top.png +0 -0
  98. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-splash-logo-layers--full-black.png +0 -0
  99. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-splash-logo-layers--telephone-fg.png +0 -0
  100. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-splash-logo-layers--telephone.png +0 -0
  101. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-splash-logo-layers--transparent-top.png +0 -0
  102. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-splash-logo-layers--tree.png +0 -0
  103. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-splash-logo-layers.png +0 -0
  104. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/favicon.png +0 -0
  105. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/machines/android.jpeg +0 -0
  106. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/machines/automaton.jpeg +0 -0
  107. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/machines/bot.jpeg +0 -0
  108. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/machines/cyborg.jpeg +0 -0
  109. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/machines/droid.jpeg +0 -0
  110. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/machines/drone.jpeg +0 -0
  111. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/machines/guardian.jpeg +0 -0
  112. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/machines/mech.jpeg +0 -0
  113. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/machines/probe.jpeg +0 -0
  114. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/machines/robot.jpeg +0 -0
  115. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/machines/sentinel.jpeg +0 -0
  116. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/machines/unit.jpeg +0 -0
  117. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/projects/blob.jpeg +0 -0
  118. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/projects/cloud.jpeg +0 -0
  119. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/projects/crystal.jpeg +0 -0
  120. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/projects/cyclops.jpeg +0 -0
  121. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/projects/flame.jpeg +0 -0
  122. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/projects/fuzzy.jpeg +0 -0
  123. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/projects/horned.jpeg +0 -0
  124. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/projects/moon.jpeg +0 -0
  125. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/projects/slime.jpeg +0 -0
  126. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/projects/star.jpeg +0 -0
  127. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/projects/tentacle.jpeg +0 -0
  128. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/projects/winged.jpeg +0 -0
  129. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/bear.jpeg +0 -0
  130. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/cat.jpeg +0 -0
  131. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/crown.jpeg +0 -0
  132. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/custom/agentwire-portal.png +0 -0
  133. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/custom/agentwire-tts.png +0 -0
  134. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/custom/agentwire.png +0 -0
  135. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/deer.jpeg +0 -0
  136. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/drone.jpeg +0 -0
  137. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/eagle.jpeg +0 -0
  138. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/fox.jpeg +0 -0
  139. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/hawk.jpeg +0 -0
  140. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/horse.jpeg +0 -0
  141. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/lion.jpeg +0 -0
  142. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/rabbit.jpeg +0 -0
  143. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/robot.jpeg +0 -0
  144. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/tiger.jpeg +0 -0
  145. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/wolf.jpeg +0 -0
  146. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/.gitkeep +0 -0
  147. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/components/icon-picker.js +0 -0
  148. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/components/list-card.js +0 -0
  149. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/components/type-tag.js +0 -0
  150. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/icon-manager.js +0 -0
  151. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/list-window.js +0 -0
  152. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/session-window.js +0 -0
  153. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/tile-manager.js +0 -0
  154. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/utils/auto-refresh.js +0 -0
  155. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/winbox.bundle.min.js +0 -0
  156. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/windows/chat-window.js +0 -0
  157. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/windows/config-window.js +0 -0
  158. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/windows/machines-window.js +0 -0
  159. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/windows/sessions-window.js +0 -0
  160. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/stt/__init__.py +0 -0
  161. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/stt/base.py +0 -0
  162. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/stt/server_backend.py +0 -0
  163. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/stt/stt_server.py +0 -0
  164. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/stt/whisperkit.py +0 -0
  165. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/tasks.py +0 -0
  166. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/templates/__init__.py +0 -0
  167. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/templates/base.html +0 -0
  168. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/templating.py +0 -0
  169. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/tts/__init__.py +0 -0
  170. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/tts/base.py +0 -0
  171. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/tts/engines/__init__.py +0 -0
  172. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/tts/engines/chatterbox.py +0 -0
  173. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/tts/engines/qwen_base.py +0 -0
  174. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/tts/engines/qwen_custom.py +0 -0
  175. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/tts/engines/qwen_design.py +0 -0
  176. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/tts/registry.py +0 -0
  177. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/tts/runpod_handler.py +0 -0
  178. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/tts_server.py +0 -0
  179. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/tunnels.py +0 -0
  180. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/utils/__init__.py +0 -0
  181. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/utils/chunker.py +0 -0
  182. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/utils/file_io.py +0 -0
  183. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/utils/paths.py +0 -0
  184. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/utils/subprocess.py +0 -0
  185. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/validation.py +0 -0
  186. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/voiceclone.py +0 -0
  187. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/voices/darren.wav +0 -0
  188. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/voices/default.wav +0 -0
  189. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/voices/jessica.wav +0 -0
  190. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/voices/lisa.wav +0 -0
  191. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/voices/may.wav +0 -0
  192. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/worktree.py +0 -0
  193. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/PORTAL.md +0 -0
  194. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/SHELL_ESCAPING.md +0 -0
  195. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/SPONSORS.md +0 -0
  196. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/README.md +0 -0
  197. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-agent-hot-swap.md +0 -0
  198. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-ambient-context-stream.md +0 -0
  199. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-ambient-listening-mode.md +0 -0
  200. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-audio-cues.md +0 -0
  201. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-checkpoint-commits.md +0 -0
  202. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-context-compression-protocol.md +0 -0
  203. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-context-window-gauge.md +0 -0
  204. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-contextual-bookmarks.md +0 -0
  205. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-conversation-archaeology.md +0 -0
  206. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-cost-tracking-dashboard.md +0 -0
  207. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-cross-session-events.md +0 -0
  208. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-delegation-replay.md +0 -0
  209. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-device-session-tethering.md +0 -0
  210. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-failure-memory.md +0 -0
  211. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-notification-escalation.md +0 -0
  212. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-periodic-voice-briefings.md +0 -0
  213. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-presence-aware-sessions.md +0 -0
  214. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-session-drift-detection.md +0 -0
  215. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-session-energy-model.md +0 -0
  216. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-session-handshake.md +0 -0
  217. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-session-momentum.md +0 -0
  218. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-session-replay.md +0 -0
  219. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-session-snapshots.md +0 -0
  220. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-session-templates.md +0 -0
  221. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-session-thermal-throttling.md +0 -0
  222. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-smart-session-routing.md +0 -0
  223. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-spatial-voice-mixing.md +0 -0
  224. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-speculative-execution.md +0 -0
  225. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-task-pipeline-chaining.md +0 -0
  226. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-task-pivot-protocol.md +0 -0
  227. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-task-time-budgets.md +0 -0
  228. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-voice-activity-zones.md +0 -0
  229. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-voice-breakpoints.md +0 -0
  230. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-voice-code-review.md +0 -0
  231. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-voice-command-undo.md +0 -0
  232. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-voice-handoff.md +0 -0
  233. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-voice-identity.md +0 -0
  234. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-voice-interrupts-v2.md +0 -0
  235. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-voice-interrupts.md +0 -0
  236. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-voice-macros.md +0 -0
  237. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-voice-transcript-logs.md +0 -0
  238. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-watchdog-mode.md +0 -0
  239. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-worker-fencing.md +0 -0
  240. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-worker-file-coordination.md +0 -0
  241. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-worker-health-dashboard.md +0 -0
  242. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-worker-heartbeat-watchdog.md +0 -0
  243. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-worker-progress-streaming.md +0 -0
  244. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-worker-proof-of-work.md +0 -0
  245. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-worker-warmup.md +0 -0
  246. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-x-api-integration.md +0 -0
  247. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/critical-analysis.md +0 -0
  248. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/demo-script.md +0 -0
  249. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/issues/pending-code-changes.md +0 -0
  250. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/issues/remote-tts-session-detection.md +0 -0
  251. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/logo.png +0 -0
  252. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/progressive-loading-pattern.md +0 -0
  253. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/prompts/agentwire-website.md +0 -0
  254. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/releasing.md +0 -0
  255. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/remote-access.md +0 -0
  256. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/remote-machines.md +0 -0
  257. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/runpod-tts.md +0 -0
  258. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/scheduled-workloads.md +0 -0
  259. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/security/damage-control-migration.md +0 -0
  260. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/security/damage-control.md +0 -0
  261. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/tmux-hooks.md +0 -0
  262. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/tts-self-hosted.md +0 -0
  263. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/youtube-channel.md +0 -0
  264. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/opencode-plugin/agentwire-notify.ts +0 -0
  265. {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/requirements-tts.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentwire-dev
3
- Version: 1.3.0
3
+ Version: 1.4.0
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
@@ -1,3 +1,3 @@
1
1
  """AgentWire - Multi-session voice web interface for AI coding agents."""
2
2
 
3
- __version__ = "1.3.0"
3
+ __version__ = "1.4.0"
@@ -331,6 +331,32 @@ def tmux_session_exists(name: str) -> bool:
331
331
  return result.returncode == 0
332
332
 
333
333
 
334
+ def _get_session_project_path(session: str) -> Path | None:
335
+ """Get a session's project path from its tmux working directory.
336
+
337
+ Queries tmux for the session's actual working directory. Falls back to
338
+ deriving it from the session name if the session isn't running.
339
+
340
+ Returns:
341
+ Path to the project directory, or None if not determinable.
342
+ """
343
+ # Try to get the actual working directory from tmux
344
+ if tmux_session_exists(session):
345
+ result = subprocess.run(
346
+ ["tmux", "display-message", "-t", session, "-p", "#{pane_current_path}"],
347
+ capture_output=True,
348
+ text=True,
349
+ )
350
+ if result.returncode == 0 and result.stdout.strip():
351
+ return Path(result.stdout.strip())
352
+
353
+ # Fallback: derive from session name
354
+ config = load_config()
355
+ projects_dir = Path(config.get("projects", {}).get("dir", "~/projects")).expanduser()
356
+ project, _, _ = parse_session_name(session)
357
+ return projects_dir / project
358
+
359
+
334
360
  def tmux_session_has_agent(name: str) -> bool:
335
361
  """Check if a tmux session has an agent running (not just a bare shell).
336
362
 
@@ -2078,6 +2104,68 @@ def cmd_alert(args) -> int:
2078
2104
  return 0
2079
2105
 
2080
2106
 
2107
+ def cmd_open(args) -> int:
2108
+ """Open a URL or local file as an artifact window in the portal.
2109
+
2110
+ Examples:
2111
+ agentwire open dashboard.html --title "Dashboard"
2112
+ agentwire open https://example.com --title "External"
2113
+ agentwire open test.html --artifact-id my-test --json
2114
+ """
2115
+ import json as json_mod
2116
+ import requests
2117
+ import urllib3
2118
+ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
2119
+
2120
+ url = args.url
2121
+ title = args.title
2122
+ artifact_id = getattr(args, 'artifact_id', None)
2123
+ json_output = getattr(args, 'json', False)
2124
+
2125
+ portal_url = _get_portal_url()
2126
+
2127
+ body = {
2128
+ "type": "artifact",
2129
+ "url": url,
2130
+ "title": title,
2131
+ }
2132
+ if artifact_id:
2133
+ body["artifact_id"] = artifact_id
2134
+
2135
+ try:
2136
+ resp = requests.post(
2137
+ f"{portal_url}/api/desktop/window/open",
2138
+ json=body,
2139
+ verify=False,
2140
+ timeout=10,
2141
+ )
2142
+ data = resp.json()
2143
+
2144
+ if json_output:
2145
+ print(json_mod.dumps(data))
2146
+ elif data.get("success"):
2147
+ print(f"Opened artifact window: {title} (id: {data.get('window_id', 'unknown')})")
2148
+ else:
2149
+ print(f"Failed: {data.get('error', 'Unknown error')}", file=sys.stderr)
2150
+ return 1
2151
+
2152
+ except requests.exceptions.ConnectionError:
2153
+ msg = "Portal not reachable. Is it running? (agentwire portal status)"
2154
+ if json_output:
2155
+ print(json_mod.dumps({"success": False, "error": msg}))
2156
+ else:
2157
+ print(msg, file=sys.stderr)
2158
+ return 1
2159
+ except Exception as e:
2160
+ if json_output:
2161
+ print(json_mod.dumps({"success": False, "error": str(e)}))
2162
+ else:
2163
+ print(f"Error: {e}", file=sys.stderr)
2164
+ return 1
2165
+
2166
+ return 0
2167
+
2168
+
2081
2169
  def _handle_voice_notifications(text: str, voice: str, args, session: str | None) -> None:
2082
2170
  """Handle voice notification to parent orchestrators.
2083
2171
 
@@ -2571,14 +2659,26 @@ def cmd_send(args) -> int:
2571
2659
  print(f"Machine '{machine_id}' not found in machines.json", file=sys.stderr)
2572
2660
  return 1
2573
2661
 
2574
- # Build remote command
2662
+ # Build remote command — use load-buffer for anything non-trivial
2575
2663
  quoted_session = shlex.quote(session)
2576
- quoted_prompt = shlex.quote(prompt)
2577
-
2578
- # Send text, sleep, send Enter
2579
- cmd = f"tmux send-keys -t {quoted_session} {quoted_prompt} && sleep 0.5 && tmux send-keys -t {quoted_session} Enter"
2664
+ use_buffer = len(prompt) > 10 or "\n" in prompt
2665
+
2666
+ if use_buffer:
2667
+ import base64
2668
+ encoded = base64.b64encode(prompt.encode()).decode()
2669
+ cmd = (
2670
+ f"echo {shlex.quote(encoded)} | base64 -d > /tmp/aw-send-$$.txt && "
2671
+ f"tmux load-buffer /tmp/aw-send-$$.txt && "
2672
+ f"tmux paste-buffer -t {quoted_session} && "
2673
+ f"rm -f /tmp/aw-send-$$.txt && "
2674
+ f"sleep 0.5 && "
2675
+ f"tmux send-keys -t {quoted_session} Enter"
2676
+ )
2677
+ else:
2678
+ quoted_prompt = shlex.quote(prompt)
2679
+ cmd = f"tmux send-keys -t {quoted_session} -l {quoted_prompt} && sleep 0.5 && tmux send-keys -t {quoted_session} Enter"
2580
2680
 
2581
- # For multi-line text, add another Enter
2681
+ # For multi-line text, Claude Code shows "[Pasted text...]" and waits for Enter
2582
2682
  if "\n" in prompt or len(prompt) > 200:
2583
2683
  cmd += f" && sleep 0.5 && tmux send-keys -t {quoted_session} Enter"
2584
2684
 
@@ -2609,13 +2709,26 @@ def cmd_send(args) -> int:
2609
2709
  print(f"Session '{session}' not found", file=sys.stderr)
2610
2710
  return 1
2611
2711
 
2612
- # Send the prompt via tmux send-keys (text first, then Enter after delay)
2613
- subprocess.run(
2614
- ["tmux", "send-keys", "-t", session, prompt],
2615
- check=True
2616
- )
2712
+ # Send the prompt use load-buffer for anything non-trivial to avoid PTY flooding
2713
+ use_buffer = len(prompt) > 10 or "\n" in prompt
2617
2714
 
2618
- # Wait for text to be fully entered before pressing Enter
2715
+ if use_buffer:
2716
+ import tempfile
2717
+ with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as f:
2718
+ f.write(prompt)
2719
+ temp_path = f.name
2720
+ try:
2721
+ subprocess.run(["tmux", "load-buffer", temp_path], check=True)
2722
+ subprocess.run(["tmux", "paste-buffer", "-t", session], check=True)
2723
+ finally:
2724
+ os.unlink(temp_path)
2725
+ else:
2726
+ subprocess.run(
2727
+ ["tmux", "send-keys", "-t", session, "-l", prompt],
2728
+ check=True
2729
+ )
2730
+
2731
+ # Wait for text to be displayed before pressing Enter
2619
2732
  time.sleep(0.5)
2620
2733
 
2621
2734
  subprocess.run(
@@ -3655,11 +3768,23 @@ def cmd_split(args) -> int:
3655
3768
  print("Error: Not in a tmux session and no --session specified")
3656
3769
  return 1
3657
3770
 
3771
+ # Verify session exists
3772
+ check = subprocess.run(
3773
+ ["tmux", "has-session", "-t", session],
3774
+ capture_output=True
3775
+ )
3776
+ if check.returncode != 0:
3777
+ print(f"Error: Session '{session}' not found")
3778
+ return 1
3779
+
3658
3780
  # Add panes
3659
- for _ in range(count):
3660
- subprocess.run([
3781
+ for i in range(count):
3782
+ result = subprocess.run([
3661
3783
  "tmux", "split-window", "-v", "-t", session, "-c", cwd
3662
- ], capture_output=True)
3784
+ ], capture_output=True, text=True)
3785
+ if result.returncode != 0:
3786
+ print(f"Error: Failed to split pane: {result.stderr.strip()}")
3787
+ return 1
3663
3788
 
3664
3789
  # Apply main-top layout: orchestrator (pane 0) at top with 60%, workers below
3665
3790
  pane_manager._apply_main_top_layout(session)
@@ -3699,17 +3824,30 @@ def cmd_detach(args) -> int:
3699
3824
  )
3700
3825
  session_exists = result.returncode == 0
3701
3826
 
3827
+ # Verify source session exists
3828
+ check = subprocess.run(
3829
+ ["tmux", "has-session", "-t", source_session],
3830
+ capture_output=True
3831
+ )
3832
+ if check.returncode != 0:
3833
+ print(f"Error: Session '{source_session}' not found")
3834
+ return 1
3835
+
3702
3836
  # Move pane to new session
3703
3837
  if session_exists:
3704
3838
  # Move to existing session
3705
- subprocess.run([
3839
+ result = subprocess.run([
3706
3840
  "tmux", "move-pane", "-s", f"{source_session}:{pane_index}", "-t", f"{new_session}:"
3707
- ], capture_output=True)
3841
+ ], capture_output=True, text=True)
3708
3842
  else:
3709
3843
  # Break pane into new session
3710
- subprocess.run([
3844
+ result = subprocess.run([
3711
3845
  "tmux", "break-pane", "-d", "-s", f"{source_session}:{pane_index}", "-t", f"{new_session}:"
3712
- ], capture_output=True)
3846
+ ], capture_output=True, text=True)
3847
+
3848
+ if result.returncode != 0:
3849
+ print(f"Error: Failed to detach pane {pane_index}: {result.stderr.strip()}")
3850
+ return 1
3713
3851
 
3714
3852
  # Re-align remaining panes with main-top layout
3715
3853
  pane_manager._apply_main_top_layout(source_session)
@@ -5416,7 +5554,7 @@ def cmd_doctor(args) -> int:
5416
5554
  print(" Run: agentwire hooks install")
5417
5555
 
5418
5556
  # Check Claude Code idle notification hook
5419
- idle_hook = CLAUDE_HOOKS_DIR / "suppress-bg-notifications.sh"
5557
+ idle_hook = CLAUDE_HOOKS_DIR / "idle-handler.sh"
5420
5558
  if idle_hook.exists():
5421
5559
  print(f" [ok] Idle notification hook: {idle_hook}")
5422
5560
  else:
@@ -6698,14 +6836,11 @@ def cmd_ensure(args) -> int:
6698
6836
  if machine_id:
6699
6837
  return _output_result(False, json_mode, "Remote sessions not yet supported for ensure", exit_code=ENSURE_EXIT_SESSION_ERROR)
6700
6838
 
6701
- # Find project path from --project flag, or derive from session name
6839
+ # Find project path from --project flag, or session's working directory
6702
6840
  if hasattr(args, 'project') and args.project:
6703
6841
  project_path = Path(args.project).expanduser().resolve()
6704
6842
  else:
6705
- config = load_config()
6706
- projects_dir = Path(config.get("projects", {}).get("dir", "~/projects")).expanduser()
6707
- project, branch, _ = parse_session_name(session_name)
6708
- project_path = projects_dir / project
6843
+ project_path = _get_session_project_path(session)
6709
6844
 
6710
6845
  if not project_path.exists():
6711
6846
  return _output_result(False, json_mode, f"Project path not found: {project_path}", exit_code=ENSURE_EXIT_SESSION_ERROR)
@@ -6900,6 +7035,18 @@ def _run_ensure_task(args, session, task, ctx, shell, project_path, timeout, jso
6900
7035
  exit_on_complete=task.exit_on_complete,
6901
7036
  )
6902
7037
 
7038
+ # Find previous summaries for this task to give the agent context
7039
+ summary_glob = f".agentwire/task-summary-{session}-{task.name}-*.md"
7040
+ prev_summaries = sorted(
7041
+ project_path.glob(summary_glob),
7042
+ key=lambda p: p.stat().st_mtime,
7043
+ reverse=True,
7044
+ )[:5]
7045
+ if prev_summaries:
7046
+ prompt += "\n\nPrevious task summaries (consider them when generating your output):"
7047
+ for p in prev_summaries:
7048
+ prompt += f"\n- {p}"
7049
+
6903
7050
  if not json_mode:
6904
7051
  print("Sending task prompt...")
6905
7052
 
@@ -7077,18 +7224,13 @@ def cmd_task_list(args) -> int:
7077
7224
  session = getattr(args, 'session', None)
7078
7225
  json_mode = getattr(args, 'json', False)
7079
7226
 
7080
- # Find project path
7081
- config = load_config()
7082
- projects_dir = Path(config.get("projects", {}).get("dir", "~/projects")).expanduser()
7083
-
7227
+ # Find project path from session's working directory or cwd
7084
7228
  if session:
7085
- project, _, _ = parse_session_name(session)
7086
- project_path = projects_dir / project
7229
+ project_path = _get_session_project_path(session)
7087
7230
  else:
7088
- # Use current directory
7089
7231
  project_path = Path.cwd()
7090
7232
 
7091
- if not project_path.exists():
7233
+ if not project_path or not project_path.exists():
7092
7234
  return _output_result(False, json_mode, f"Project path not found: {project_path}")
7093
7235
 
7094
7236
  tasks = list_tasks(project_path)
@@ -7126,13 +7268,9 @@ def cmd_task_show(args) -> int:
7126
7268
  session = None
7127
7269
  task_name = task_arg
7128
7270
 
7129
- # Find project path
7130
- config = load_config()
7131
- projects_dir = Path(config.get("projects", {}).get("dir", "~/projects")).expanduser()
7132
-
7271
+ # Find project path from session's working directory or cwd
7133
7272
  if session:
7134
- project, _, _ = parse_session_name(session)
7135
- project_path = projects_dir / project
7273
+ project_path = _get_session_project_path(session)
7136
7274
  else:
7137
7275
  project_path = Path.cwd()
7138
7276
 
@@ -7214,13 +7352,9 @@ def cmd_task_validate(args) -> int:
7214
7352
  session = None
7215
7353
  task_name = task_arg
7216
7354
 
7217
- # Find project path
7218
- config = load_config()
7219
- projects_dir = Path(config.get("projects", {}).get("dir", "~/projects")).expanduser()
7220
-
7355
+ # Find project path from session's working directory or cwd
7221
7356
  if session:
7222
- project, _, _ = parse_session_name(session)
7223
- project_path = projects_dir / project
7357
+ project_path = _get_session_project_path(session)
7224
7358
  else:
7225
7359
  project_path = Path.cwd()
7226
7360
 
@@ -7570,6 +7704,14 @@ def main() -> int:
7570
7704
  alert_parser.add_argument("-q", "--quiet", action="store_true", help="Suppress output")
7571
7705
  alert_parser.set_defaults(func=cmd_alert)
7572
7706
 
7707
+ # === open command (artifact windows) ===
7708
+ open_parser = subparsers.add_parser("open", help="Open a URL or local file as an artifact window in the portal")
7709
+ open_parser.add_argument("url", help="URL or filename to open (filenames served from ~/.agentwire/artifacts/)")
7710
+ open_parser.add_argument("--title", "-t", type=str, default="Artifact", help="Window title")
7711
+ open_parser.add_argument("--artifact-id", type=str, help="Unique window ID (auto-generated if omitted)")
7712
+ open_parser.add_argument("--json", action="store_true", help="Output JSON")
7713
+ open_parser.set_defaults(func=cmd_open)
7714
+
7573
7715
  # === email command ===
7574
7716
  from agentwire.notifications import cmd_email
7575
7717
  email_parser = subparsers.add_parser("email", help="Send branded email notification via Resend")
@@ -338,30 +338,59 @@ class TmuxAgent(AgentBackend):
338
338
 
339
339
  def send_input(self, name: str, text: str) -> bool:
340
340
  """Send input to a tmux session (text + Enter)."""
341
+ import os
342
+ import tempfile
341
343
  import time
342
344
  session_name, machine = self._parse_session_name(name)
343
345
 
346
+ use_buffer = len(text) > 10 or "\n" in text
347
+
344
348
  if machine:
345
- # Use base64 encoding for safe transmission of complex text
346
- import base64
347
- encoded = base64.b64encode(text.encode()).decode()
348
- cmd = (
349
- f"echo {shlex.quote(encoded)} | base64 -d | "
350
- f"xargs -0 tmux send-keys -t {shlex.quote(session_name)} -l && "
351
- f"sleep 0.2 && "
352
- f"tmux send-keys -t {shlex.quote(session_name)} Enter"
353
- )
349
+ if use_buffer:
350
+ # Use base64 + load-buffer on remote to avoid PTY flooding
351
+ import base64
352
+ encoded = base64.b64encode(text.encode()).decode()
353
+ cmd = (
354
+ f"echo {shlex.quote(encoded)} | base64 -d > /tmp/aw-send-$$.txt && "
355
+ f"tmux load-buffer /tmp/aw-send-$$.txt && "
356
+ f"tmux paste-buffer -t {shlex.quote(session_name)} && "
357
+ f"rm -f /tmp/aw-send-$$.txt && "
358
+ f"sleep 0.2 && "
359
+ f"tmux send-keys -t {shlex.quote(session_name)} Enter"
360
+ )
361
+ else:
362
+ cmd = (
363
+ f"tmux send-keys -t {shlex.quote(session_name)} -l {shlex.quote(text)} && "
364
+ f"sleep 0.2 && "
365
+ f"tmux send-keys -t {shlex.quote(session_name)} Enter"
366
+ )
354
367
  result = self._run_remote(machine, cmd)
355
368
  else:
356
- # Send text literally (no special char interpretation)
357
- result = self._run_local([
358
- "tmux", "send-keys",
359
- "-t", session_name,
360
- "-l", text,
361
- ])
362
- if result.returncode != 0:
363
- logger.error(f"Failed to send input: {result.stderr}")
364
- return False
369
+ if use_buffer:
370
+ # Write to temp file, load into tmux buffer, paste as single unit
371
+ with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as f:
372
+ f.write(text)
373
+ temp_path = f.name
374
+ try:
375
+ result = self._run_local(["tmux", "load-buffer", temp_path])
376
+ if result.returncode != 0:
377
+ logger.error(f"Failed to load buffer: {result.stderr}")
378
+ return False
379
+ result = self._run_local(["tmux", "paste-buffer", "-t", session_name])
380
+ if result.returncode != 0:
381
+ logger.error(f"Failed to paste buffer: {result.stderr}")
382
+ return False
383
+ finally:
384
+ os.unlink(temp_path)
385
+ else:
386
+ result = self._run_local([
387
+ "tmux", "send-keys",
388
+ "-t", session_name,
389
+ "-l", text,
390
+ ])
391
+ if result.returncode != 0:
392
+ logger.error(f"Failed to send input: {result.stderr}")
393
+ return False
365
394
 
366
395
  # Small delay before Enter
367
396
  time.sleep(0.2)
@@ -80,7 +80,7 @@ def generate_summary_filename(session: str, task_name: str) -> str:
80
80
  Relative path like .agentwire/task-summary-mysession-2024-01-15T07-00-00.md
81
81
  """
82
82
  timestamp = datetime.now().strftime("%Y-%m-%dT%H-%M-%S")
83
- return f".agentwire/task-summary-{session}-{timestamp}.md"
83
+ return f".agentwire/task-summary-{session}-{task_name}-{timestamp}.md"
84
84
 
85
85
 
86
86
  # =============================================================================
@@ -149,6 +149,19 @@ class UploadsConfig:
149
149
  self.dir = _expand_path(self.dir) or self.dir
150
150
 
151
151
 
152
+ @dataclass
153
+ class ArtifactsConfig:
154
+ """Artifacts directory for agent-generated HTML content."""
155
+
156
+ dir: Path = field(
157
+ default_factory=lambda: Path.home() / ".agentwire" / "artifacts"
158
+ )
159
+ max_size_mb: int = 10
160
+
161
+ def __post_init__(self):
162
+ self.dir = _expand_path(self.dir) or self.dir
163
+
164
+
152
165
  @dataclass
153
166
  class PortalConfig:
154
167
  """Portal connection settings (for remote machines)."""
@@ -213,6 +226,7 @@ class Config:
213
226
  agent: AgentConfig = field(default_factory=AgentConfig)
214
227
  machines: MachinesConfig = field(default_factory=MachinesConfig)
215
228
  uploads: UploadsConfig = field(default_factory=UploadsConfig)
229
+ artifacts: ArtifactsConfig = field(default_factory=ArtifactsConfig)
216
230
  portal: PortalConfig = field(default_factory=PortalConfig)
217
231
  services: ServicesConfig = field(default_factory=ServicesConfig)
218
232
  session: SessionConfig = field(default_factory=SessionConfig)
@@ -349,6 +363,13 @@ def _dict_to_config(data: dict) -> Config:
349
363
  cleanup_days=uploads_data.get("cleanup_days", 7),
350
364
  )
351
365
 
366
+ # Artifacts
367
+ artifacts_data = data.get("artifacts", {})
368
+ artifacts = ArtifactsConfig(
369
+ dir=artifacts_data.get("dir", "~/.agentwire/artifacts"),
370
+ max_size_mb=artifacts_data.get("max_size_mb", 10),
371
+ )
372
+
352
373
  # Portal
353
374
  portal_data = data.get("portal", {})
354
375
  portal = PortalConfig(
@@ -400,6 +421,7 @@ def _dict_to_config(data: dict) -> Config:
400
421
  agent=agent,
401
422
  machines=machines,
402
423
  uploads=uploads,
424
+ artifacts=artifacts,
403
425
  portal=portal,
404
426
  services=services,
405
427
  notifications=notifications,
@@ -198,6 +198,10 @@ complete | incomplete | error
198
198
  sleep 1
199
199
  $AGENTWIRE send -s "$tmux_session" "/exit" >/dev/null 2>&1
200
200
 
201
+ # Clean up task context file so it doesn't haunt future sessions
202
+ rm "$task_context_file" 2>/dev/null
203
+ echo "[$(date -Iseconds)] TASK: cleaned up task context" >> "$dlog"
204
+
201
205
  # Wait for Claude to exit, then kill the tmux session
202
206
  sleep 3
203
207
  echo "[$(date -Iseconds)] TASK: killing tmux session" >> "$dlog"
@@ -219,6 +223,11 @@ complete | incomplete | error
219
223
  echo "[$(date -Iseconds)] TASK-ORPHAN: found summary at $recent_summary, exiting session" >> "$dlog"
220
224
  sleep 1
221
225
  $AGENTWIRE send -s "$tmux_session" "/exit" >/dev/null 2>&1
226
+
227
+ # Clean up orphan summary so it doesn't trigger again
228
+ rm "$recent_summary" 2>/dev/null
229
+ echo "[$(date -Iseconds)] TASK-ORPHAN: cleaned up orphan summary" >> "$dlog"
230
+
222
231
  sleep 3
223
232
  echo "[$(date -Iseconds)] TASK-ORPHAN: killing tmux session" >> "$dlog"
224
233
  tmux kill-session -t "$tmux_session" 2>/dev/null &