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.
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/PKG-INFO +1 -1
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/__init__.py +1 -1
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/__main__.py +187 -45
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/agents/tmux.py +47 -18
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/completion.py +1 -1
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/config.py +22 -0
- agentwire_dev-1.3.0/agentwire/hooks/suppress-bg-notifications.sh → agentwire_dev-1.4.0/agentwire/hooks/idle-handler.sh +9 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/mcp_server.py +858 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/notifications.py +1 -1
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/onboarding.py +59 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/pane_manager.py +14 -6
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/server.py +262 -3
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/css/desktop.css +80 -0
- agentwire_dev-1.4.0/agentwire/static/js/artifact-window.js +211 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/desktop-manager.js +44 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/desktop.js +92 -0
- agentwire_dev-1.4.0/agentwire/static/js/windows/artifacts-window.js +90 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/windows/projects-window.js +1 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/templates/desktop.html +1 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/templates/email_notification.html +12 -4
- agentwire_dev-1.4.0/agentwire/templates/tmux.conf +98 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/TROUBLESHOOTING.md +1 -1
- agentwire_dev-1.4.0/docs/issues/projects-dedup-ignores-machine.md +34 -0
- agentwire_dev-1.4.0/docs/issues/tmux-config-onboarding.md +120 -0
- agentwire_dev-1.4.0/docs/issues/tmux-paste-freeze.md +89 -0
- agentwire_dev-1.4.0/docs/issues/tmux-recommended-config.md +90 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/notification-hooks.md +1 -1
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/pyproject.toml +1 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/.github/FUNDING.yml +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/.github/ISSUE_TEMPLATE/question.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/.github/workflows/ci.yml +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/.github/workflows/publish.yml +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/.gitignore +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/CHANGELOG.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/CLA.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/CODE_OF_CONDUCT.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/CONTRIBUTING.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/Dockerfile.local +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/Dockerfile.runpod +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/LICENSE +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/README.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/RELEASING.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/SECURITY.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/SPONSORS.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/agents/__init__.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/agents/base.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/cached_status.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/cli_safety.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/errors.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/history.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/hooks/__init__.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/hooks/agentwire-permission.sh +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/hooks/damage-control/__init__.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/hooks/damage-control/audit_logger.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/hooks/damage-control/bash-tool-damage-control.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/hooks/damage-control/edit-tool-damage-control.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/hooks/damage-control/patterns.yaml +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/hooks/damage-control/write-tool-damage-control.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/init_agentwire.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/listen.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/locking.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/network.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/project_config.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/projects.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/prompts/__init__.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/prompts/init.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/__init__.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/chatbot.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/claude-delegation.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/claude-worker-haiku.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/claude-worker-sonnet.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/claude-worker.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/glm-delegation.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/glm-worker-flash.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/glm-worker.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/init.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/leader-claude.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/leader-glm.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/leader-openai.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/leader.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/openai-delegation.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/openai-worker-mini.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/openai-worker.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/task-runner.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/voice.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/roles/worker.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-Echo--black.png +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-Echo--transparent.png +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-Echo.png +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-email-banner.png +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-splash-logo-layers--agentwire-text.png +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-splash-logo-layers--echo-claw-fg.png +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-splash-logo-layers--echo.png +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-splash-logo-layers--full--transparent-top.png +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-splash-logo-layers--full-black.png +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-splash-logo-layers--telephone-fg.png +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-splash-logo-layers--telephone.png +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-splash-logo-layers--transparent-top.png +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-splash-logo-layers--tree.png +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/agentwire-splash-logo-layers.png +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/favicon.png +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/machines/android.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/machines/automaton.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/machines/bot.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/machines/cyborg.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/machines/droid.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/machines/drone.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/machines/guardian.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/machines/mech.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/machines/probe.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/machines/robot.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/machines/sentinel.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/machines/unit.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/projects/blob.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/projects/cloud.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/projects/crystal.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/projects/cyclops.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/projects/flame.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/projects/fuzzy.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/projects/horned.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/projects/moon.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/projects/slime.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/projects/star.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/projects/tentacle.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/projects/winged.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/bear.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/cat.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/crown.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/custom/agentwire-portal.png +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/custom/agentwire-tts.png +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/custom/agentwire.png +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/deer.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/drone.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/eagle.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/fox.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/hawk.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/horse.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/lion.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/rabbit.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/robot.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/tiger.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/icons/sessions/wolf.jpeg +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/.gitkeep +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/components/icon-picker.js +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/components/list-card.js +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/components/type-tag.js +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/icon-manager.js +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/list-window.js +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/session-window.js +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/tile-manager.js +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/utils/auto-refresh.js +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/winbox.bundle.min.js +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/windows/chat-window.js +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/windows/config-window.js +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/windows/machines-window.js +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/static/js/windows/sessions-window.js +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/stt/__init__.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/stt/base.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/stt/server_backend.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/stt/stt_server.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/stt/whisperkit.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/tasks.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/templates/__init__.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/templates/base.html +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/templating.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/tts/__init__.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/tts/base.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/tts/engines/__init__.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/tts/engines/chatterbox.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/tts/engines/qwen_base.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/tts/engines/qwen_custom.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/tts/engines/qwen_design.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/tts/registry.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/tts/runpod_handler.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/tts_server.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/tunnels.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/utils/__init__.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/utils/chunker.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/utils/file_io.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/utils/paths.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/utils/subprocess.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/validation.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/voiceclone.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/voices/darren.wav +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/voices/default.wav +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/voices/jessica.wav +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/voices/lisa.wav +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/voices/may.wav +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/agentwire/worktree.py +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/PORTAL.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/SHELL_ESCAPING.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/SPONSORS.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/README.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-agent-hot-swap.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-ambient-context-stream.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-ambient-listening-mode.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-audio-cues.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-checkpoint-commits.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-context-compression-protocol.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-context-window-gauge.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-contextual-bookmarks.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-conversation-archaeology.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-cost-tracking-dashboard.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-cross-session-events.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-delegation-replay.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-device-session-tethering.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-failure-memory.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-notification-escalation.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-periodic-voice-briefings.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-presence-aware-sessions.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-session-drift-detection.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-session-energy-model.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-session-handshake.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-session-momentum.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-session-replay.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-session-snapshots.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-session-templates.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-session-thermal-throttling.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-smart-session-routing.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-spatial-voice-mixing.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-speculative-execution.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-task-pipeline-chaining.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-task-pivot-protocol.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-task-time-budgets.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-voice-activity-zones.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-voice-breakpoints.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-voice-code-review.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-voice-command-undo.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-voice-handoff.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-voice-identity.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-voice-interrupts-v2.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-voice-interrupts.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-voice-macros.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-voice-transcript-logs.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-watchdog-mode.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-worker-fencing.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-worker-file-coordination.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-worker-health-dashboard.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-worker-heartbeat-watchdog.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-worker-progress-streaming.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-worker-proof-of-work.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-worker-warmup.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/brainstorms/idea-x-api-integration.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/critical-analysis.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/demo-script.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/issues/pending-code-changes.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/issues/remote-tts-session-detection.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/logo.png +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/progressive-loading-pattern.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/prompts/agentwire-website.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/releasing.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/remote-access.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/remote-machines.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/runpod-tts.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/scheduled-workloads.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/security/damage-control-migration.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/security/damage-control.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/tmux-hooks.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/tts-self-hosted.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/docs/youtube-channel.md +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/opencode-plugin/agentwire-notify.ts +0 -0
- {agentwire_dev-1.3.0 → agentwire_dev-1.4.0}/requirements-tts.txt +0 -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
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
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,
|
|
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
|
|
2613
|
-
|
|
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
|
-
|
|
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
|
|
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 / "
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
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
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
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 &
|