agentwire-dev 1.21.0__tar.gz → 1.22.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.21.0 → agentwire_dev-1.22.0}/PKG-INFO +1 -1
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/__init__.py +1 -1
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/__main__.py +256 -9
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/config.py +2 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/mcp_server.py +135 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/overnight.py +4 -1
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/project_config.py +6 -2
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/projects.py +87 -0
- agentwire_dev-1.22.0/agentwire/roles/notifications.md +83 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/server.py +174 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/css/desktop.css +105 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/js/desktop-manager.js +9 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/js/desktop.js +9 -0
- agentwire_dev-1.22.0/agentwire/static/js/notifications-panel.js +138 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/js/sidebar/sessions-section.js +4 -1
- agentwire_dev-1.22.0/agentwire/workflows/__init__.py +28 -0
- agentwire_dev-1.22.0/agentwire/workflows/cli.py +328 -0
- agentwire_dev-1.22.0/agentwire/workflows/context.py +52 -0
- agentwire_dev-1.22.0/agentwire/workflows/definitions.py +331 -0
- agentwire_dev-1.22.0/agentwire/workflows/node.py +115 -0
- agentwire_dev-1.22.0/agentwire/workflows/outputs.py +149 -0
- agentwire_dev-1.22.0/agentwire/workflows/pi_runner.py +238 -0
- agentwire_dev-1.22.0/agentwire/workflows/runner.py +364 -0
- agentwire_dev-1.22.0/agentwire/workflows/storage.py +186 -0
- agentwire_dev-1.22.0/docs/pi-zai.md +222 -0
- agentwire_dev-1.22.0/docs/workflows.md +317 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/pyproject.toml +2 -0
- agentwire_dev-1.22.0/tests/integration/test_build_agent_command.py +237 -0
- agentwire_dev-1.22.0/tests/unit/test_workflows.py +467 -0
- agentwire_dev-1.21.0/tests/integration/test_build_agent_command.py +0 -63
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/.github/FUNDING.yml +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/.github/ISSUE_TEMPLATE/question.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/.gitignore +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/CHANGELOG.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/CLA.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/CODE_OF_CONDUCT.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/CONTRIBUTING.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/Dockerfile.local +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/Dockerfile.runpod +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/LICENSE +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/README.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/RELEASING.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/SECURITY.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/SPONSORS.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/agents/__init__.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/agents/base.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/agents/tmux.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/bridges/__init__.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/bridges/telegram.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/cached_status.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/channels/__init__.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/channels/_template.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/channels/base.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/channels/discord.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/channels/email.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/channels/quo.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/channels/slack.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/channels/sms.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/channels/telegram.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/channels/webhook.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/cli_safety.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/completion.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/errors.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/history.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/hooks/__init__.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/hooks/agentwire-permission.sh +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/hooks/damage-control/__init__.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/hooks/damage-control/audit_logger.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/hooks/damage-control/bash-tool-damage-control.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/hooks/damage-control/edit-tool-damage-control.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/hooks/damage-control/rules/agentwire.yaml +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/hooks/damage-control/rules/aws.yaml +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/hooks/damage-control/rules/cloud-hosting.yaml +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/hooks/damage-control/rules/containers.yaml +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/hooks/damage-control/rules/core.yaml +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/hooks/damage-control/rules/databases.yaml +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/hooks/damage-control/rules/firebase.yaml +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/hooks/damage-control/rules/gcp.yaml +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/hooks/damage-control/rules/git.yaml +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/hooks/damage-control/rules/gws.yaml +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/hooks/damage-control/rules/infrastructure.yaml +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/hooks/damage-control/rules/remote.yaml +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/hooks/damage-control/write-tool-damage-control.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/hooks/idle-handler.sh +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/init_agentwire.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/listen.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/locking.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/network.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/onboarding.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/pane_manager.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/prompts/__init__.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/prompts/init.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/roles/__init__.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/roles/agentwire.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/roles/channel-admin.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/roles/chatbot.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/roles/discord-dm.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/roles/init.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/roles/orchestrator.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/roles/slack-dm.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/roles/task-runner.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/roles/voice.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/roles/worker.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/scheduler.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/agentwire-Echo--black.png +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/agentwire-Echo--transparent.png +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/agentwire-Echo.png +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/agentwire-email-banner.png +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/agentwire-splash-logo-layers--agentwire-text.png +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/agentwire-splash-logo-layers--echo-claw-fg.png +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/agentwire-splash-logo-layers--echo.png +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/agentwire-splash-logo-layers--full--transparent-top.png +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/agentwire-splash-logo-layers--full-black.png +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/agentwire-splash-logo-layers--telephone-fg.png +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/agentwire-splash-logo-layers--telephone.png +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/agentwire-splash-logo-layers--transparent-top.png +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/agentwire-splash-logo-layers--transparent.png +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/agentwire-splash-logo-layers--tree.png +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/agentwire-splash-logo-layers.png +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/favicon.png +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/machines/android.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/machines/automaton.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/machines/bot.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/machines/cyborg.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/machines/droid.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/machines/drone.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/machines/guardian.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/machines/mech.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/machines/probe.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/machines/robot.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/machines/sentinel.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/machines/unit.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/projects/blob.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/projects/cloud.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/projects/crystal.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/projects/cyclops.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/projects/flame.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/projects/fuzzy.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/projects/horned.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/projects/moon.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/projects/slime.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/projects/star.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/projects/tentacle.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/projects/winged.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/sessions/bear.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/sessions/cat.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/sessions/crown.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/sessions/custom/agentwire-portal.png +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/sessions/custom/agentwire-tts.png +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/sessions/custom/agentwire.png +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/sessions/deer.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/sessions/drone.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/sessions/eagle.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/sessions/fox.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/sessions/hawk.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/sessions/horse.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/sessions/lion.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/sessions/rabbit.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/sessions/robot.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/sessions/tiger.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/icons/sessions/wolf.jpeg +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/js/.gitkeep +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/js/artifact-window.js +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/js/components/icon-picker.js +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/js/components/list-card.js +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/js/components/type-tag.js +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/js/icon-manager.js +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/js/session-window.js +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/js/sidebar/artifacts-section.js +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/js/sidebar/config-section.js +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/js/sidebar/machines-section.js +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/js/sidebar/projects-section.js +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/js/sidebar/scheduler-section.js +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/js/sidebar/services-section.js +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/js/sidebar/socials-section.js +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/js/sidebar.js +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/js/tile-manager.js +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/js/utils/auto-refresh.js +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/js/winbox.bundle.min.js +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/static/js/windows/chat-window.js +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/stt/__init__.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/stt/base.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/stt/server_backend.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/stt/stt_server.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/stt/whisperkit.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/tasks.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/templates/__init__.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/templates/base.html +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/templates/desktop.html +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/templates/email_notification.html +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/templates/tmux.conf +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/templating.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/tooldefs/aws.yaml +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/tooldefs/docker.yaml +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/tooldefs/gcp.yaml +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/tooldefs/gh.yaml +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/tooldefs/git.yaml +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/tooldefs/gws.yaml +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/tooldefs/kubectl.yaml +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/tooldefs/npm.yaml +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/tooldefs/terraform.yaml +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/tooldefs/uv.yaml +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/tts/__init__.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/tts/base.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/tts/engines/__init__.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/tts/engines/chatterbox.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/tts/engines/kokoro.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/tts/engines/qwen_base.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/tts/engines/qwen_custom.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/tts/engines/qwen_design.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/tts/engines/zonos.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/tts/registry.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/tts/runpod_handler.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/tts_server.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/tunnels.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/utils/__init__.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/utils/chunker.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/utils/file_io.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/utils/paths.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/utils/subprocess.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/validation.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/voiceclone.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/voices/darren.wav +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/voices/default.wav +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/voices/jessica.wav +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/voices/lisa.wav +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/voices/may.wav +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/agentwire/worktree.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/FEATURE-REQUESTS.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/FR-auto-mode-session-type.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/PORTAL.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/SHELL_ESCAPING.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/SPONSORS.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/TROUBLESHOOTING.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/README.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-agent-hot-swap.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-ambient-context-stream.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-ambient-listening-mode.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-audio-cues.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-checkpoint-commits.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-context-compression-protocol.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-context-window-gauge.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-contextual-bookmarks.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-conversation-archaeology.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-cost-tracking-dashboard.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-cross-session-events.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-delegation-replay.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-device-session-tethering.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-failure-memory.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-notification-escalation.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-periodic-voice-briefings.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-presence-aware-sessions.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-session-drift-detection.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-session-energy-model.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-session-handshake.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-session-momentum.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-session-replay.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-session-snapshots.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-session-templates.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-session-thermal-throttling.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-smart-session-routing.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-spatial-voice-mixing.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-speculative-execution.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-task-pipeline-chaining.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-task-pivot-protocol.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-task-time-budgets.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-voice-activity-zones.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-voice-breakpoints.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-voice-code-review.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-voice-command-undo.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-voice-handoff.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-voice-identity.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-voice-interrupts-v2.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-voice-interrupts.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-voice-macros.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-voice-transcript-logs.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-watchdog-mode.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-worker-fencing.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-worker-file-coordination.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-worker-health-dashboard.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-worker-heartbeat-watchdog.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-worker-progress-streaming.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-worker-proof-of-work.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-worker-warmup.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/brainstorms/idea-x-api-integration.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/channels.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/claude-code-auto-mode.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/critical-analysis.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/demo-script.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/gws-google-workspace-cli.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/hammerspoon.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/issues/pending-code-changes.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/issues/projects-dedup-ignores-machine.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/issues/remote-tts-session-detection.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/issues/tmux-config-onboarding.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/issues/tmux-paste-freeze.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/issues/tmux-recommended-config.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/logo.png +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/notification-hooks.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/progressive-loading-pattern.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/prompts/agentwire-website.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/releasing.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/remote-access.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/remote-machines.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/runpod-tts.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/scheduled-workloads.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/security/damage-control-migration.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/security/damage-control.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/tmux-hooks.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/tts-self-hosted.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/docs/youtube-channel.md +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/requirements-tts.txt +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/tests/conftest.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/tests/e2e/test_portal_ui.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/tests/fixtures/sample_agentwire.yml +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/tests/fixtures/sample_config.yaml +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/tests/fixtures/sample_scheduler.yaml +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/tests/integration/test_channels_cli.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/tests/integration/test_cli_commands.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/tests/integration/test_cli_output.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/tests/integration/test_mcp_tools.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/tests/integration/test_portal_api.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/tests/integration/test_scheduler_board.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/tests/unit/test_channels.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/tests/unit/test_cli_safety.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/tests/unit/test_config.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/tests/unit/test_file_io.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/tests/unit/test_history.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/tests/unit/test_locking.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/tests/unit/test_mcp_server.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/tests/unit/test_project_config.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/tests/unit/test_roles.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/tests/unit/test_scheduler.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/tests/unit/test_server_async.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/tests/unit/test_server_pure.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/tests/unit/test_tasks.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/tests/unit/test_templating.py +0 -0
- {agentwire_dev-1.21.0 → agentwire_dev-1.22.0}/tests/unit/test_worktree.py +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import argparse
|
|
4
4
|
import base64
|
|
5
|
-
from dataclasses import dataclass
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
6
|
import datetime
|
|
7
7
|
import importlib.resources
|
|
8
8
|
import json
|
|
@@ -81,15 +81,75 @@ class AgentCommand:
|
|
|
81
81
|
"""Result of building an agent command."""
|
|
82
82
|
command: str # The shell command to execute
|
|
83
83
|
temp_file: str | None = None # Temp file to clean up after agent starts
|
|
84
|
+
env: dict[str, str] = field(default_factory=dict) # Secrets to inject via tmux set-environment (keeps keys out of `ps`)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def inject_session_env(session: str, env: dict[str, str], remote_host: str | None = None) -> None:
|
|
88
|
+
"""Set env vars on a tmux session so panes inherit them without exposing secrets.
|
|
89
|
+
|
|
90
|
+
Using `tmux set-environment -t <session>` keeps API keys out of the command
|
|
91
|
+
string (which would otherwise be visible in `ps auxwww` and shell history).
|
|
92
|
+
"""
|
|
93
|
+
if not env:
|
|
94
|
+
return
|
|
95
|
+
for key, value in env.items():
|
|
96
|
+
if remote_host:
|
|
97
|
+
subprocess.run(
|
|
98
|
+
["ssh", remote_host, "tmux", "set-environment", "-t",
|
|
99
|
+
shlex.quote(session), shlex.quote(key), shlex.quote(value)],
|
|
100
|
+
check=False,
|
|
101
|
+
)
|
|
102
|
+
else:
|
|
103
|
+
subprocess.run(
|
|
104
|
+
["tmux", "set-environment", "-t", session, key, value],
|
|
105
|
+
check=False,
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def parse_env_args(env_args: list[str] | None) -> dict[str, str]:
|
|
110
|
+
"""Parse repeated `--env KEY=VAL` flags into a dict.
|
|
111
|
+
|
|
112
|
+
Raises SystemExit via argparse pattern if an entry lacks `=`.
|
|
113
|
+
"""
|
|
114
|
+
if not env_args:
|
|
115
|
+
return {}
|
|
116
|
+
result: dict[str, str] = {}
|
|
117
|
+
for entry in env_args:
|
|
118
|
+
if "=" not in entry:
|
|
119
|
+
print(f"Error: --env expects KEY=VAL, got {entry!r}", file=sys.stderr)
|
|
120
|
+
sys.exit(2)
|
|
121
|
+
key, value = entry.split("=", 1)
|
|
122
|
+
if not key:
|
|
123
|
+
print(f"Error: --env KEY cannot be empty (got {entry!r})", file=sys.stderr)
|
|
124
|
+
sys.exit(2)
|
|
125
|
+
result[key] = value
|
|
126
|
+
return result
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def build_session_env_shell_fragment(session: str, env: dict[str, str]) -> str:
|
|
130
|
+
"""Build a shell fragment of `tmux set-environment` calls for chained remote commands.
|
|
131
|
+
|
|
132
|
+
Returns a trailing `&& ` string ready to splice into an ssh-executed compound
|
|
133
|
+
command. Empty string if no env.
|
|
134
|
+
"""
|
|
135
|
+
if not env:
|
|
136
|
+
return ""
|
|
137
|
+
parts = []
|
|
138
|
+
for key, value in env.items():
|
|
139
|
+
parts.append(
|
|
140
|
+
f"tmux set-environment -t {shlex.quote(session)} "
|
|
141
|
+
f"{shlex.quote(key)} {shlex.quote(value)}"
|
|
142
|
+
)
|
|
143
|
+
return " && ".join(parts) + " && "
|
|
84
144
|
|
|
85
145
|
|
|
86
146
|
def build_agent_command(session_type: str, roles: list[RoleConfig] | None = None, model: str | None = None) -> AgentCommand:
|
|
87
147
|
"""Build the agent command for a session.
|
|
88
148
|
|
|
89
149
|
Args:
|
|
90
|
-
session_type: Session type (e.g., "claude-bypass", "claude-auto", "bare")
|
|
150
|
+
session_type: Session type (e.g., "claude-bypass", "claude-auto", "pi-zai", "bare")
|
|
91
151
|
roles: Optional list of roles to apply
|
|
92
|
-
model: Optional model override (e.g., "haiku", "sonnet", "opus")
|
|
152
|
+
model: Optional model override (e.g., "haiku", "sonnet", "opus", "glm-5")
|
|
93
153
|
|
|
94
154
|
Returns:
|
|
95
155
|
AgentCommand with the command string and metadata
|
|
@@ -101,6 +161,49 @@ def build_agent_command(session_type: str, roles: list[RoleConfig] | None = None
|
|
|
101
161
|
# Merge roles if provided
|
|
102
162
|
merged = merge_roles(roles) if roles else None
|
|
103
163
|
|
|
164
|
+
# === Pi coding agent via Z.AI GLM ===
|
|
165
|
+
if session_type.startswith("pi-zai"):
|
|
166
|
+
config = load_config()
|
|
167
|
+
zai = config.get("zai", {})
|
|
168
|
+
pi_config = config.get("pi", {})
|
|
169
|
+
|
|
170
|
+
# Pi reads ZAI_API_KEY from env. We inject it via `tmux set-environment`
|
|
171
|
+
# (see inject_session_env) so the key never appears in `ps auxwww`.
|
|
172
|
+
pi_binary = pi_config.get("binary", "pi")
|
|
173
|
+
default_model = pi_config.get("default_model", "glm-5")
|
|
174
|
+
|
|
175
|
+
parts = [pi_binary, "--provider", "zai"]
|
|
176
|
+
parts.extend(["--model", model or default_model])
|
|
177
|
+
|
|
178
|
+
# Permission variants (pi has no permission system to bypass; variants
|
|
179
|
+
# translate to pi's --tools whitelist instead)
|
|
180
|
+
temp_file = None
|
|
181
|
+
if session_type == "pi-zai-restricted":
|
|
182
|
+
parts.extend(["--tools", "read,grep,find,bash"])
|
|
183
|
+
elif session_type == "pi-zai-readonly":
|
|
184
|
+
parts.extend(["--tools", "read,grep,find"])
|
|
185
|
+
elif merged and merged.tools:
|
|
186
|
+
# Translate Claude tool names to pi's lowercase tool names.
|
|
187
|
+
# Pi only supports: read, bash, edit, write, grep, find, ls
|
|
188
|
+
pi_valid = {"read", "bash", "edit", "write", "grep", "find", "ls"}
|
|
189
|
+
pi_tools = [t.lower() for t in merged.tools if t.lower() in pi_valid]
|
|
190
|
+
if pi_tools:
|
|
191
|
+
parts.extend(["--tools", ",".join(pi_tools)])
|
|
192
|
+
|
|
193
|
+
# Role-based system prompt (skipped for restricted/readonly — those are curated contexts)
|
|
194
|
+
if merged and merged.instructions and session_type not in ("pi-zai-restricted", "pi-zai-readonly"):
|
|
195
|
+
f = tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False)
|
|
196
|
+
f.write(merged.instructions)
|
|
197
|
+
f.close()
|
|
198
|
+
temp_file = f.name
|
|
199
|
+
parts.append(f'--append-system-prompt "$(<{temp_file})"')
|
|
200
|
+
|
|
201
|
+
return AgentCommand(
|
|
202
|
+
command=" ".join(parts),
|
|
203
|
+
temp_file=temp_file,
|
|
204
|
+
env={"ZAI_API_KEY": zai.get("api_key", "")},
|
|
205
|
+
)
|
|
206
|
+
|
|
104
207
|
# === Claude Code ===
|
|
105
208
|
if session_type.startswith("claude"):
|
|
106
209
|
parts = ["claude"]
|
|
@@ -277,6 +380,27 @@ def tmux_session_exists(name: str) -> bool:
|
|
|
277
380
|
return result.returncode == 0
|
|
278
381
|
|
|
279
382
|
|
|
383
|
+
def wait_for_shell_prompt(target: str, timeout: float = 2.0) -> None:
|
|
384
|
+
"""Poll tmux capture-pane until the shell has drawn a prompt.
|
|
385
|
+
|
|
386
|
+
Prevents a race where send-keys fires before the shell is ready, causing
|
|
387
|
+
the command to appear in the pre-prompt buffer and again after the prompt
|
|
388
|
+
renders (looks like it ran twice).
|
|
389
|
+
"""
|
|
390
|
+
import time
|
|
391
|
+
deadline = time.monotonic() + timeout
|
|
392
|
+
while time.monotonic() < deadline:
|
|
393
|
+
result = subprocess.run(
|
|
394
|
+
["tmux", "capture-pane", "-t", target, "-p"],
|
|
395
|
+
capture_output=True, text=True,
|
|
396
|
+
)
|
|
397
|
+
if result.returncode == 0 and any(
|
|
398
|
+
c in result.stdout for c in ("$", "%", "#", "❯", "➜", ">")
|
|
399
|
+
):
|
|
400
|
+
return
|
|
401
|
+
time.sleep(0.05)
|
|
402
|
+
|
|
403
|
+
|
|
280
404
|
def _get_session_project_path(session: str) -> Path | None:
|
|
281
405
|
"""Get a session's project path from its tmux working directory.
|
|
282
406
|
|
|
@@ -3403,8 +3527,7 @@ def cmd_new(args) -> int:
|
|
|
3403
3527
|
|
|
3404
3528
|
# Build agent command
|
|
3405
3529
|
agent = build_agent_command(session_type, roles if roles else None)
|
|
3406
|
-
|
|
3407
|
-
|
|
3530
|
+
agent.env.update(parse_env_args(getattr(args, 'env', None)))
|
|
3408
3531
|
|
|
3409
3532
|
agent_cmd = agent.command
|
|
3410
3533
|
|
|
@@ -3425,12 +3548,15 @@ def cmd_new(args) -> int:
|
|
|
3425
3548
|
except Exception as e:
|
|
3426
3549
|
print(f"Warning: Failed to write system prompt to remote: {e}", file=sys.stderr)
|
|
3427
3550
|
|
|
3551
|
+
env_fragment = build_session_env_shell_fragment(session_name, agent.env)
|
|
3552
|
+
|
|
3428
3553
|
# Create session - Agent starts immediately if not bare
|
|
3429
3554
|
if agent_cmd:
|
|
3430
3555
|
create_cmd = (
|
|
3431
3556
|
f"tmux new-session -d -s {shlex.quote(session_name)} -c {shlex.quote(remote_path)} && "
|
|
3432
3557
|
f"tmux send-keys -t {shlex.quote(session_name)} 'cd {shlex.quote(remote_path)}' Enter && "
|
|
3433
3558
|
f"sleep 0.1 && "
|
|
3559
|
+
f"{env_fragment}"
|
|
3434
3560
|
f"tmux send-keys -t {shlex.quote(session_name)} {shlex.quote(agent_cmd)} Enter"
|
|
3435
3561
|
)
|
|
3436
3562
|
else:
|
|
@@ -3571,9 +3697,13 @@ def cmd_new(args) -> int:
|
|
|
3571
3697
|
# Build agent command
|
|
3572
3698
|
model_override = getattr(args, 'model', None)
|
|
3573
3699
|
agent = build_agent_command(session_type, roles if roles else None, model=model_override)
|
|
3700
|
+
agent.env.update(parse_env_args(getattr(args, 'env', None)))
|
|
3574
3701
|
|
|
3575
3702
|
agent_cmd = agent.command
|
|
3576
3703
|
|
|
3704
|
+
# Inject secrets via tmux set-environment (keeps keys out of `ps`)
|
|
3705
|
+
inject_session_env(session_name, agent.env)
|
|
3706
|
+
|
|
3577
3707
|
# Start agent command if not bare
|
|
3578
3708
|
if agent_cmd:
|
|
3579
3709
|
subprocess.run(
|
|
@@ -4071,10 +4201,17 @@ def cmd_spawn(args) -> int:
|
|
|
4071
4201
|
|
|
4072
4202
|
# Build agent command
|
|
4073
4203
|
agent = build_agent_command(session_type_str, roles if roles else None)
|
|
4204
|
+
agent.env.update(parse_env_args(getattr(args, 'env', None)))
|
|
4074
4205
|
|
|
4075
4206
|
agent_cmd = agent.command
|
|
4076
4207
|
|
|
4077
4208
|
try:
|
|
4209
|
+
# Inject secrets onto the parent session before spawning the pane so the
|
|
4210
|
+
# new pane inherits them from tmux (avoids putting keys in `ps`).
|
|
4211
|
+
parent_session = session or pane_manager.get_current_session()
|
|
4212
|
+
if parent_session:
|
|
4213
|
+
inject_session_env(parent_session, agent.env)
|
|
4214
|
+
|
|
4078
4215
|
# Spawn pane first to get the pane index
|
|
4079
4216
|
pane_index = pane_manager.spawn_worker_pane(
|
|
4080
4217
|
session=session,
|
|
@@ -4451,12 +4588,15 @@ def cmd_recreate(args) -> int:
|
|
|
4451
4588
|
|
|
4452
4589
|
# Build agent command using the standard function
|
|
4453
4590
|
agent = build_agent_command(session_type_str)
|
|
4591
|
+
agent.env.update(parse_env_args(getattr(args, 'env', None)))
|
|
4454
4592
|
agent_cmd = agent.command
|
|
4593
|
+
env_fragment = build_session_env_shell_fragment(session_name, agent.env)
|
|
4455
4594
|
|
|
4456
4595
|
create_cmd = (
|
|
4457
4596
|
f"tmux new-session -d -s {shlex.quote(session_name)} -c {shlex.quote(session_path)} && "
|
|
4458
4597
|
f"tmux send-keys -t {shlex.quote(session_name)} 'cd {shlex.quote(session_path)}' Enter && "
|
|
4459
4598
|
f"sleep 0.1 && "
|
|
4599
|
+
f"{env_fragment}"
|
|
4460
4600
|
f"tmux send-keys -t {shlex.quote(session_name)} {shlex.quote(agent_cmd)} Enter"
|
|
4461
4601
|
)
|
|
4462
4602
|
|
|
@@ -4553,6 +4693,7 @@ def cmd_recreate(args) -> int:
|
|
|
4553
4693
|
|
|
4554
4694
|
# Build agent command
|
|
4555
4695
|
agent = build_agent_command(session_type_str, roles)
|
|
4696
|
+
agent.env.update(parse_env_args(getattr(args, 'env', None)))
|
|
4556
4697
|
|
|
4557
4698
|
agent_cmd = agent.command
|
|
4558
4699
|
|
|
@@ -4569,6 +4710,9 @@ def cmd_recreate(args) -> int:
|
|
|
4569
4710
|
)
|
|
4570
4711
|
time.sleep(0.1)
|
|
4571
4712
|
|
|
4713
|
+
# Inject secrets via tmux set-environment (keeps keys out of `ps`)
|
|
4714
|
+
inject_session_env(session_name, agent.env)
|
|
4715
|
+
|
|
4572
4716
|
# Start the agent with appropriate command
|
|
4573
4717
|
if agent_cmd:
|
|
4574
4718
|
subprocess.run(
|
|
@@ -4633,6 +4777,7 @@ def cmd_worktree(args) -> int:
|
|
|
4633
4777
|
'force': False, 'bare': False, 'restricted': False, 'prompted': False,
|
|
4634
4778
|
'type': getattr(args, 'type', None), 'roles': getattr(args, 'roles', None),
|
|
4635
4779
|
'instructions': None, 'persist': False,
|
|
4780
|
+
'env': getattr(args, 'env', None),
|
|
4636
4781
|
})())
|
|
4637
4782
|
|
|
4638
4783
|
# If worktree already exists, reattach
|
|
@@ -4825,13 +4970,16 @@ def cmd_fork(args) -> int:
|
|
|
4825
4970
|
|
|
4826
4971
|
# Build agent command
|
|
4827
4972
|
agent = build_agent_command(session_type_str, roles)
|
|
4973
|
+
agent.env.update(parse_env_args(getattr(args, 'env', None)))
|
|
4828
4974
|
|
|
4829
4975
|
agent_cmd = agent.command
|
|
4976
|
+
env_fragment = build_session_env_shell_fragment(target_session, agent.env)
|
|
4830
4977
|
|
|
4831
4978
|
create_session_cmd = (
|
|
4832
4979
|
f"tmux new-session -d -s {shlex.quote(target_session)} -c {shlex.quote(target_path)} && "
|
|
4833
4980
|
f"tmux send-keys -t {shlex.quote(target_session)} 'cd {shlex.quote(target_path)}' Enter && "
|
|
4834
4981
|
f"sleep 0.1 && "
|
|
4982
|
+
f"{env_fragment}"
|
|
4835
4983
|
f"tmux send-keys -t {shlex.quote(target_session)} {shlex.quote(agent_cmd)} Enter"
|
|
4836
4984
|
)
|
|
4837
4985
|
|
|
@@ -4978,6 +5126,10 @@ def cmd_fork(args) -> int:
|
|
|
4978
5126
|
|
|
4979
5127
|
# Build agent command
|
|
4980
5128
|
agent = build_agent_command(session_type_str, roles)
|
|
5129
|
+
agent.env.update(parse_env_args(getattr(args, 'env', None)))
|
|
5130
|
+
|
|
5131
|
+
# Inject secrets via tmux set-environment (keeps keys out of `ps`)
|
|
5132
|
+
inject_session_env(target_session, agent.env)
|
|
4981
5133
|
|
|
4982
5134
|
agent_cmd = agent.command
|
|
4983
5135
|
if agent_cmd:
|
|
@@ -5091,7 +5243,12 @@ def cmd_fork(args) -> int:
|
|
|
5091
5243
|
|
|
5092
5244
|
# Build agent command
|
|
5093
5245
|
agent = build_agent_command(session_type_str, roles)
|
|
5246
|
+
agent.env.update(parse_env_args(getattr(args, 'env', None)))
|
|
5094
5247
|
agent_cmd = agent.command
|
|
5248
|
+
|
|
5249
|
+
# Inject secrets via tmux set-environment (keeps keys out of `ps`)
|
|
5250
|
+
inject_session_env(target_session, agent.env)
|
|
5251
|
+
|
|
5095
5252
|
if agent_cmd:
|
|
5096
5253
|
subprocess.run(
|
|
5097
5254
|
["tmux", "send-keys", "-t", target_session, agent_cmd, "Enter"],
|
|
@@ -5689,8 +5846,12 @@ def cmd_dev(args) -> int:
|
|
|
5689
5846
|
"tmux", "new-session", "-d", "-s", session_name, "-c", str(project_dir),
|
|
5690
5847
|
])
|
|
5691
5848
|
|
|
5849
|
+
# Inject secrets via tmux set-environment (keeps keys out of `ps`)
|
|
5850
|
+
inject_session_env(session_name, agent.env)
|
|
5851
|
+
|
|
5692
5852
|
# Start agent with agentwire config
|
|
5693
5853
|
if agent_cmd:
|
|
5854
|
+
wait_for_shell_prompt(session_name)
|
|
5694
5855
|
subprocess.run([
|
|
5695
5856
|
"tmux", "send-keys", "-t", session_name, agent_cmd, "Enter",
|
|
5696
5857
|
])
|
|
@@ -6047,6 +6208,23 @@ def cmd_doctor(args) -> int:
|
|
|
6047
6208
|
print(" [..] claude: not found (optional, use --bare sessions or other agents)")
|
|
6048
6209
|
print(" Install: https://github.com/anthropics/claude-code")
|
|
6049
6210
|
|
|
6211
|
+
# Check Pi coding agent (optional, for pi-zai session types)
|
|
6212
|
+
pi_path = shutil.which("pi")
|
|
6213
|
+
if pi_path:
|
|
6214
|
+
try:
|
|
6215
|
+
# Pi prints --version to stderr, so merge with stdout
|
|
6216
|
+
result = subprocess.run(
|
|
6217
|
+
[pi_path, "--version"],
|
|
6218
|
+
capture_output=True, text=True, timeout=5,
|
|
6219
|
+
)
|
|
6220
|
+
pi_version = (result.stdout + result.stderr).strip()
|
|
6221
|
+
print(f" [ok] pi: {pi_path} (v{pi_version})")
|
|
6222
|
+
except Exception:
|
|
6223
|
+
print(f" [ok] pi: {pi_path}")
|
|
6224
|
+
else:
|
|
6225
|
+
print(" [..] pi: not found (optional, required for pi-zai session types)")
|
|
6226
|
+
print(" Install: npm install -g @mariozechner/pi-coding-agent")
|
|
6227
|
+
|
|
6050
6228
|
# 3. Check AgentWire scripts
|
|
6051
6229
|
print("\nChecking AgentWire scripts...")
|
|
6052
6230
|
|
|
@@ -9832,11 +10010,12 @@ def main() -> int:
|
|
|
9832
10010
|
new_parser.add_argument("-p", "--path", help="Working directory (default: ~/projects/<name>)")
|
|
9833
10011
|
new_parser.add_argument("-f", "--force", action="store_true", help="Replace existing session")
|
|
9834
10012
|
# Session type
|
|
9835
|
-
new_parser.add_argument("--type", help="Session type (bare, claude-bypass, claude-prompted, claude-restricted, standard, worker, voice)")
|
|
10013
|
+
new_parser.add_argument("--type", help="Session type (bare, claude-bypass, claude-prompted, claude-restricted, pi-zai, pi-zai-restricted, pi-zai-readonly, standard, worker, voice)")
|
|
9836
10014
|
# Roles
|
|
9837
10015
|
new_parser.add_argument("--roles", help="Comma-separated list of roles (preserves existing config, defaults to agentwire for new projects)")
|
|
9838
10016
|
new_parser.add_argument("--model", help="Model override (e.g., haiku, sonnet, opus)")
|
|
9839
10017
|
new_parser.add_argument("--persist", action="store_true", help="Write --type/--roles to .agentwire.yml (default: session-level override only)")
|
|
10018
|
+
new_parser.add_argument("--env", action="append", metavar="KEY=VAL", help="Inject env var via `tmux set-environment` (repeatable, keeps secrets out of `ps`)")
|
|
9840
10019
|
new_parser.add_argument("--json", action="store_true", help="Output as JSON")
|
|
9841
10020
|
new_parser.set_defaults(func=cmd_new)
|
|
9842
10021
|
|
|
@@ -9867,10 +10046,11 @@ def main() -> int:
|
|
|
9867
10046
|
spawn_parser.add_argument("-s", "--session", help="Target session (default: auto-detect)")
|
|
9868
10047
|
spawn_parser.add_argument("--cwd", help="Working directory (default: current)")
|
|
9869
10048
|
spawn_parser.add_argument("--branch", "-b", help="Create worktree on this branch for isolated commits")
|
|
9870
|
-
spawn_parser.add_argument("--type", help="Session type (claude-bypass, claude-prompted, claude-restricted)")
|
|
10049
|
+
spawn_parser.add_argument("--type", help="Session type (claude-bypass, claude-prompted, claude-restricted, pi-zai, pi-zai-restricted, pi-zai-readonly)")
|
|
9871
10050
|
spawn_parser.add_argument("--roles", default="worker", help="Comma-separated roles (default: worker)")
|
|
9872
10051
|
spawn_parser.add_argument("--no-wait", action="store_true", help="Don't wait for worker to be ready (default: wait up to 30s)")
|
|
9873
10052
|
spawn_parser.add_argument("--timeout", type=int, default=30, help="Seconds to wait for worker ready (default: 30)")
|
|
10053
|
+
spawn_parser.add_argument("--env", action="append", metavar="KEY=VAL", help="Inject env var onto parent session (repeatable)")
|
|
9874
10054
|
spawn_parser.add_argument("--json", action="store_true", help="Output as JSON")
|
|
9875
10055
|
spawn_parser.set_defaults(func=cmd_spawn)
|
|
9876
10056
|
|
|
@@ -9905,7 +10085,8 @@ def main() -> int:
|
|
|
9905
10085
|
recreate_parser = subparsers.add_parser("recreate", help="Destroy and recreate session with fresh worktree")
|
|
9906
10086
|
recreate_parser.add_argument("-s", "--session", required=True, help="Session name (project/branch or project/branch@machine)")
|
|
9907
10087
|
# Session type
|
|
9908
|
-
recreate_parser.add_argument("--type", help="Session type (bare, claude-bypass, claude-prompted, claude-restricted, standard, worker, voice)")
|
|
10088
|
+
recreate_parser.add_argument("--type", help="Session type (bare, claude-bypass, claude-prompted, claude-restricted, pi-zai, pi-zai-restricted, pi-zai-readonly, standard, worker, voice)")
|
|
10089
|
+
recreate_parser.add_argument("--env", action="append", metavar="KEY=VAL", help="Inject env var via `tmux set-environment` (repeatable)")
|
|
9909
10090
|
recreate_parser.add_argument("--json", action="store_true", help="Output as JSON")
|
|
9910
10091
|
recreate_parser.set_defaults(func=cmd_recreate)
|
|
9911
10092
|
|
|
@@ -9914,8 +10095,9 @@ def main() -> int:
|
|
|
9914
10095
|
fork_parser.add_argument("-s", "--source", required=True, help="Source session (project or project/branch)")
|
|
9915
10096
|
fork_parser.add_argument("-t", "--target", required=True, help="Target session (must include branch: project/new-branch)")
|
|
9916
10097
|
# Session type
|
|
9917
|
-
fork_parser.add_argument("--type", help="Session type (bare, claude-bypass, claude-prompted, claude-restricted, standard, worker, voice)")
|
|
10098
|
+
fork_parser.add_argument("--type", help="Session type (bare, claude-bypass, claude-prompted, claude-restricted, pi-zai, pi-zai-restricted, pi-zai-readonly, standard, worker, voice)")
|
|
9918
10099
|
fork_parser.add_argument("--commit", metavar="REF", help="Fork from this commit/ref instead of HEAD (e.g. abc123, main~5)")
|
|
10100
|
+
fork_parser.add_argument("--env", action="append", metavar="KEY=VAL", help="Inject env var via `tmux set-environment` (repeatable)")
|
|
9919
10101
|
fork_parser.add_argument("--json", action="store_true", help="Output as JSON")
|
|
9920
10102
|
fork_parser.set_defaults(func=cmd_fork)
|
|
9921
10103
|
|
|
@@ -9929,6 +10111,7 @@ def main() -> int:
|
|
|
9929
10111
|
wt_parser.add_argument("--project", "-p", help="Path to git repo (default: from config or cwd)")
|
|
9930
10112
|
wt_parser.add_argument("--type", help="Session type override")
|
|
9931
10113
|
wt_parser.add_argument("--roles", help="Comma-separated role names")
|
|
10114
|
+
wt_parser.add_argument("--env", action="append", metavar="KEY=VAL", help="Inject env var via `tmux set-environment` (repeatable)")
|
|
9932
10115
|
wt_parser.add_argument("--json", action="store_true", help="Output as JSON")
|
|
9933
10116
|
wt_parser.set_defaults(func=cmd_worktree)
|
|
9934
10117
|
|
|
@@ -9938,6 +10121,70 @@ def main() -> int:
|
|
|
9938
10121
|
)
|
|
9939
10122
|
dev_parser.set_defaults(func=cmd_dev)
|
|
9940
10123
|
|
|
10124
|
+
# === workflow command group ===
|
|
10125
|
+
from agentwire.workflows.cli import (
|
|
10126
|
+
cmd_workflow_history,
|
|
10127
|
+
cmd_workflow_list,
|
|
10128
|
+
cmd_workflow_run,
|
|
10129
|
+
cmd_workflow_show,
|
|
10130
|
+
cmd_workflow_validate,
|
|
10131
|
+
)
|
|
10132
|
+
|
|
10133
|
+
workflow_parser = subparsers.add_parser("workflow", help="Pi workflow engine")
|
|
10134
|
+
workflow_subparsers = workflow_parser.add_subparsers(dest="workflow_command")
|
|
10135
|
+
|
|
10136
|
+
wf_list = workflow_subparsers.add_parser("list", help="List discoverable workflows")
|
|
10137
|
+
wf_list.add_argument("--json", action="store_true", help="Output as JSON")
|
|
10138
|
+
wf_list.set_defaults(func=cmd_workflow_list)
|
|
10139
|
+
|
|
10140
|
+
wf_validate = workflow_subparsers.add_parser(
|
|
10141
|
+
"validate", help="Validate a workflow YAML without running it"
|
|
10142
|
+
)
|
|
10143
|
+
wf_validate.add_argument("workflow", help="Workflow name or path to YAML")
|
|
10144
|
+
wf_validate.set_defaults(func=cmd_workflow_validate)
|
|
10145
|
+
|
|
10146
|
+
wf_run = workflow_subparsers.add_parser("run", help="Execute a workflow")
|
|
10147
|
+
wf_run.add_argument("workflow", help="Workflow name or path to YAML")
|
|
10148
|
+
wf_run.add_argument(
|
|
10149
|
+
"--input", action="append", metavar="KEY=VALUE",
|
|
10150
|
+
help="Workflow input (repeatable). Overrides --input-file."
|
|
10151
|
+
)
|
|
10152
|
+
wf_run.add_argument(
|
|
10153
|
+
"--input-file", metavar="PATH",
|
|
10154
|
+
help="JSON file with inputs (object mapping name → value)"
|
|
10155
|
+
)
|
|
10156
|
+
wf_run.add_argument("--dry-run", action="store_true", help="Print plan without running")
|
|
10157
|
+
wf_run.add_argument("--verbose", "-v", action="store_true", help="Verbose output")
|
|
10158
|
+
wf_run.add_argument("--json", action="store_true", help="Output as JSON")
|
|
10159
|
+
wf_run.set_defaults(func=cmd_workflow_run)
|
|
10160
|
+
|
|
10161
|
+
wf_history = workflow_subparsers.add_parser(
|
|
10162
|
+
"history", help="List past workflow runs"
|
|
10163
|
+
)
|
|
10164
|
+
wf_history.add_argument(
|
|
10165
|
+
"--workflow", metavar="NAME", help="Filter by workflow name"
|
|
10166
|
+
)
|
|
10167
|
+
wf_history.add_argument(
|
|
10168
|
+
"--limit", type=int, default=20, help="Max runs to show (default: 20)"
|
|
10169
|
+
)
|
|
10170
|
+
wf_history.add_argument("--json", action="store_true", help="Output as JSON")
|
|
10171
|
+
wf_history.set_defaults(func=cmd_workflow_history)
|
|
10172
|
+
|
|
10173
|
+
wf_show = workflow_subparsers.add_parser(
|
|
10174
|
+
"show", help="Inspect a past workflow run"
|
|
10175
|
+
)
|
|
10176
|
+
wf_show.add_argument("run_id", help="Run ID (from `workflow history`)")
|
|
10177
|
+
wf_show.add_argument(
|
|
10178
|
+
"--events", action="store_true",
|
|
10179
|
+
help="Dump raw event JSONL for all nodes",
|
|
10180
|
+
)
|
|
10181
|
+
wf_show.add_argument(
|
|
10182
|
+
"--node", metavar="ID",
|
|
10183
|
+
help="Filter events to one node id (implies --events)",
|
|
10184
|
+
)
|
|
10185
|
+
wf_show.add_argument("--json", action="store_true", help="Output as JSON")
|
|
10186
|
+
wf_show.set_defaults(func=cmd_workflow_show)
|
|
10187
|
+
|
|
9941
10188
|
# === listen command group ===
|
|
9942
10189
|
listen_parser = subparsers.add_parser("listen", help="Voice input recording")
|
|
9943
10190
|
listen_parser.add_argument(
|
|
@@ -74,6 +74,7 @@ class ProjectsConfig:
|
|
|
74
74
|
|
|
75
75
|
dir: Path = field(default_factory=lambda: Path.home() / "projects")
|
|
76
76
|
worktrees: WorktreesConfig = field(default_factory=WorktreesConfig)
|
|
77
|
+
extra: list = field(default_factory=list)
|
|
77
78
|
|
|
78
79
|
def __post_init__(self):
|
|
79
80
|
self.dir = _expand_path(self.dir) or Path.home() / "projects"
|
|
@@ -355,6 +356,7 @@ def _dict_to_config(data: dict) -> Config:
|
|
|
355
356
|
projects = ProjectsConfig(
|
|
356
357
|
dir=projects_data.get("dir", "~/projects"),
|
|
357
358
|
worktrees=worktrees,
|
|
359
|
+
extra=projects_data.get("extra", []),
|
|
358
360
|
)
|
|
359
361
|
|
|
360
362
|
# TTS
|
|
@@ -2457,6 +2457,141 @@ def desktop_layout(windows: list[dict]) -> str:
|
|
|
2457
2457
|
return f"Failed to apply layout: {data.get('error', 'Unknown error')}"
|
|
2458
2458
|
|
|
2459
2459
|
|
|
2460
|
+
@mcp.tool()
|
|
2461
|
+
def portal_notify(text: str, session: str | None = None, priority: str = "normal") -> str:
|
|
2462
|
+
"""Post a toast notification to the portal desktop.
|
|
2463
|
+
|
|
2464
|
+
Creates a persistent visual notification in the bottom-right of the portal.
|
|
2465
|
+
Clicking the toast opens the notifications session for interactive chat.
|
|
2466
|
+
|
|
2467
|
+
Args:
|
|
2468
|
+
text: Notification message text.
|
|
2469
|
+
session: Session name this notification relates to (shown as badge).
|
|
2470
|
+
priority: 'normal' or 'high' (high gets accent border).
|
|
2471
|
+
|
|
2472
|
+
Returns:
|
|
2473
|
+
Notification ID or error description.
|
|
2474
|
+
"""
|
|
2475
|
+
body = {"text": text, "priority": priority}
|
|
2476
|
+
if session:
|
|
2477
|
+
body["session"] = session
|
|
2478
|
+
data = _portal_request("POST", "/api/desktop/notification", body)
|
|
2479
|
+
if data.get("success"):
|
|
2480
|
+
return f"Notification posted (id: {data.get('id')})."
|
|
2481
|
+
return f"Failed to post notification: {data.get('error', 'Unknown error')}"
|
|
2482
|
+
|
|
2483
|
+
|
|
2484
|
+
|
|
2485
|
+
# =============================================================================
|
|
2486
|
+
# Workflow engine tools
|
|
2487
|
+
# =============================================================================
|
|
2488
|
+
|
|
2489
|
+
|
|
2490
|
+
@mcp.tool()
|
|
2491
|
+
def workflow_list() -> str:
|
|
2492
|
+
"""List discoverable pi workflows.
|
|
2493
|
+
|
|
2494
|
+
Returns workflow names, descriptions, and node counts. Workflows live in
|
|
2495
|
+
~/.agentwire/workflows/defs/ or the bundled examples dir.
|
|
2496
|
+
"""
|
|
2497
|
+
data = run_agentwire_cmd(["workflow", "list"])
|
|
2498
|
+
if not data.get("success"):
|
|
2499
|
+
return f"Failed to list workflows: {data.get('error', 'Unknown error')}"
|
|
2500
|
+
|
|
2501
|
+
items = data.get("items", [])
|
|
2502
|
+
if not items:
|
|
2503
|
+
return "No workflows found."
|
|
2504
|
+
|
|
2505
|
+
lines = ["Available workflows:"]
|
|
2506
|
+
for wf in items:
|
|
2507
|
+
name = wf.get("name", "?")
|
|
2508
|
+
desc = wf.get("description", "")
|
|
2509
|
+
count = len(wf.get("nodes", []))
|
|
2510
|
+
lines.append(f" - {name} ({count} node{'s' if count != 1 else ''})"
|
|
2511
|
+
+ (f" — {desc}" if desc else ""))
|
|
2512
|
+
return "\n".join(lines)
|
|
2513
|
+
|
|
2514
|
+
|
|
2515
|
+
@mcp.tool()
|
|
2516
|
+
def workflow_validate(name_or_path: str) -> str:
|
|
2517
|
+
"""Parse + validate a workflow YAML without running it.
|
|
2518
|
+
|
|
2519
|
+
Args:
|
|
2520
|
+
name_or_path: Workflow name (e.g. "echo-chain") or path to YAML file.
|
|
2521
|
+
"""
|
|
2522
|
+
data = run_agentwire_cmd(["workflow", "validate", name_or_path])
|
|
2523
|
+
if data.get("success"):
|
|
2524
|
+
return data.get("output", f"Workflow {name_or_path!r} is valid.")
|
|
2525
|
+
return f"Validation failed: {data.get('output', data.get('error', 'Unknown error'))}"
|
|
2526
|
+
|
|
2527
|
+
|
|
2528
|
+
@mcp.tool()
|
|
2529
|
+
def workflow_run(
|
|
2530
|
+
name: str,
|
|
2531
|
+
inputs: dict | None = None,
|
|
2532
|
+
dry_run: bool = False,
|
|
2533
|
+
) -> dict:
|
|
2534
|
+
"""Execute a pi workflow end-to-end.
|
|
2535
|
+
|
|
2536
|
+
Args:
|
|
2537
|
+
name: Workflow name or path to YAML.
|
|
2538
|
+
inputs: Optional map of input name → value, forwarded as --input KEY=VAL.
|
|
2539
|
+
dry_run: If true, print the execution plan without invoking pi.
|
|
2540
|
+
|
|
2541
|
+
Returns:
|
|
2542
|
+
Full run result as a dict: workflow, run_id, status
|
|
2543
|
+
(success|partial|failure), duration_ms, error, nodes[].
|
|
2544
|
+
"""
|
|
2545
|
+
args = ["workflow", "run", name]
|
|
2546
|
+
for key, value in (inputs or {}).items():
|
|
2547
|
+
args.extend(["--input", f"{key}={value}"])
|
|
2548
|
+
if dry_run:
|
|
2549
|
+
args.append("--dry-run")
|
|
2550
|
+
# pi calls routinely take minutes; default 30s is not enough.
|
|
2551
|
+
return run_agentwire_cmd(args, timeout=600)
|
|
2552
|
+
|
|
2553
|
+
|
|
2554
|
+
@mcp.tool()
|
|
2555
|
+
def workflow_history(workflow: str | None = None, limit: int = 20) -> str:
|
|
2556
|
+
"""List past workflow runs, newest first.
|
|
2557
|
+
|
|
2558
|
+
Args:
|
|
2559
|
+
workflow: Filter to a single workflow name (optional).
|
|
2560
|
+
limit: Max runs to return (default 20).
|
|
2561
|
+
"""
|
|
2562
|
+
args = ["workflow", "history", "--limit", str(limit)]
|
|
2563
|
+
if workflow:
|
|
2564
|
+
args.extend(["--workflow", workflow])
|
|
2565
|
+
data = run_agentwire_cmd(args)
|
|
2566
|
+
if not data.get("success"):
|
|
2567
|
+
return f"Failed to list runs: {data.get('error', 'Unknown error')}"
|
|
2568
|
+
|
|
2569
|
+
runs = data.get("items", [])
|
|
2570
|
+
if not runs:
|
|
2571
|
+
return "No past runs found."
|
|
2572
|
+
|
|
2573
|
+
lines = ["Past runs:"]
|
|
2574
|
+
for run in runs:
|
|
2575
|
+
rid = run.get("run_id", "?")
|
|
2576
|
+
name = run.get("workflow", "?")
|
|
2577
|
+
status = run.get("status", "?")
|
|
2578
|
+
duration_ms = run.get("duration_ms", 0)
|
|
2579
|
+
lines.append(f" - {rid} [{name}] {status} {duration_ms}ms")
|
|
2580
|
+
return "\n".join(lines)
|
|
2581
|
+
|
|
2582
|
+
|
|
2583
|
+
@mcp.tool()
|
|
2584
|
+
def workflow_show(run_id: str) -> dict:
|
|
2585
|
+
"""Fetch metadata for a single past workflow run.
|
|
2586
|
+
|
|
2587
|
+
Args:
|
|
2588
|
+
run_id: Run identifier from `workflow_history`.
|
|
2589
|
+
|
|
2590
|
+
Returns:
|
|
2591
|
+
The run's metadata.json contents (workflow, status, inputs, node
|
|
2592
|
+
summaries with timing + tokens + errors).
|
|
2593
|
+
"""
|
|
2594
|
+
return run_agentwire_cmd(["workflow", "show", run_id])
|
|
2460
2595
|
|
|
2461
2596
|
|
|
2462
2597
|
# =============================================================================
|
|
@@ -498,7 +498,7 @@ def dispatch_item(item: OvernightItem, config) -> bool:
|
|
|
498
498
|
|
|
499
499
|
Returns True if dispatch succeeded.
|
|
500
500
|
"""
|
|
501
|
-
from .__main__ import build_agent_command, _wait_for_agent_ready
|
|
501
|
+
from .__main__ import build_agent_command, _wait_for_agent_ready, inject_session_env
|
|
502
502
|
|
|
503
503
|
project = item.project_path
|
|
504
504
|
session = item.session
|
|
@@ -538,6 +538,9 @@ def dispatch_item(item: OvernightItem, config) -> bool:
|
|
|
538
538
|
_log_event("dispatch_failed", item_id=item.id, error=item.error)
|
|
539
539
|
return False
|
|
540
540
|
|
|
541
|
+
# Inject secrets via tmux set-environment (keeps keys out of `ps`)
|
|
542
|
+
inject_session_env(session, agent.env)
|
|
543
|
+
|
|
541
544
|
# Inject --resume <id> --fork-session
|
|
542
545
|
if item.resume_session_id:
|
|
543
546
|
claude_pos = agent_cmd.rfind("claude")
|