Upload folder using huggingface_hub (part 2)
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +233 -0
- docker/base/Dockerfile +3 -40
- docker/base/build.txt +3 -18
- docker/base/fs/etc/searxng/limiter.toml +3 -33
- docker/base/fs/etc/searxng/settings.yml +3 -91
- docker/base/fs/ins/after_install.sh +3 -5
- docker/base/fs/ins/configure_ssh.sh +3 -6
- docker/base/fs/ins/install_base_packages1.sh +3 -11
- docker/base/fs/ins/install_base_packages2.sh +3 -10
- docker/base/fs/ins/install_base_packages3.sh +3 -13
- docker/base/fs/ins/install_base_packages4.sh +3 -9
- docker/base/fs/ins/install_python.sh +3 -73
- docker/base/fs/ins/install_searxng.sh +3 -29
- docker/base/fs/ins/install_searxng2.sh +3 -36
- docker/run/AGENTS.md +3 -43
- docker/run/Dockerfile +3 -36
- docker/run/build.txt +3 -42
- docker/run/docker-compose.yml +3 -14
- docker/run/fs/etc/nginx/nginx.conf +3 -31
- docker/run/fs/etc/searxng/limiter.toml +3 -33
- docker/run/fs/etc/searxng/settings.yml +3 -98
- docker/run/fs/etc/supervisor/conf.d/supervisord.conf +3 -95
- docker/run/fs/exe/huggingface-entrypoint.sh +3 -42
- docker/run/fs/exe/initialize.sh +3 -63
- docker/run/fs/exe/node_eval.js +3 -62
- docker/run/fs/exe/run_A0.sh +3 -7
- docker/run/fs/exe/run_searxng.sh +3 -10
- docker/run/fs/exe/run_tunnel_api.sh +3 -18
- docker/run/fs/exe/self_update_manager.py +3 -1507
- docker/run/fs/exe/supervisor_event_listener.py +3 -47
- docker/run/fs/exe/trigger_self_update.sh +3 -6
- docker/run/fs/ins/copy_A0.sh +3 -12
- docker/run/fs/ins/install_A0.sh +3 -44
- docker/run/fs/ins/install_A02.sh +3 -17
- docker/run/fs/ins/install_additional.sh +3 -94
- docker/run/fs/ins/install_playwright.sh +3 -13
- docker/run/fs/ins/post_install.sh +3 -6
- docker/run/fs/ins/pre_install.sh +3 -13
- docker/run/fs/ins/setup_ssh.sh +3 -7
- docker/run/fs/ins/setup_venv.sh +3 -12
- docker/run/fs/per/root/.bashrc +3 -9
- docker/run/fs/per/root/.profile +3 -9
- docs/AGENTS.md +3 -35
- docs/README.md +3 -159
- docs/developer/architecture.md +3 -32
- docs/developer/connectivity.md +3 -55
- docs/developer/contributing-skills.md +3 -395
- docs/developer/extensions.md +3 -46
- docs/developer/mcp-configuration.md +3 -80
- docs/developer/notifications.md +3 -133
.gitattributes
CHANGED
|
@@ -1,3 +1,236 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
oid sha256:56c89d9018842070bb8dd1397378f26b814d30f4f7c56d8ff8788dbae1f83682
|
| 3 |
size 72
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
oid sha256:56c89d9018842070bb8dd1397378f26b814d30f4f7c56d8ff8788dbae1f83682
|
| 3 |
size 72
|
| 4 |
+
docker/base/Dockerfile filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
docker/base/build.txt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
docker/base/fs/etc/searxng/limiter.toml filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
docker/base/fs/etc/searxng/settings.yml filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
docker/base/fs/ins/after_install.sh filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
docker/base/fs/ins/configure_ssh.sh filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
docker/base/fs/ins/install_base_packages1.sh filter=lfs diff=lfs merge=lfs -text
|
| 11 |
+
docker/base/fs/ins/install_base_packages2.sh filter=lfs diff=lfs merge=lfs -text
|
| 12 |
+
docker/base/fs/ins/install_base_packages3.sh filter=lfs diff=lfs merge=lfs -text
|
| 13 |
+
docker/base/fs/ins/install_base_packages4.sh filter=lfs diff=lfs merge=lfs -text
|
| 14 |
+
docker/base/fs/ins/install_python.sh filter=lfs diff=lfs merge=lfs -text
|
| 15 |
+
docker/base/fs/ins/install_searxng.sh filter=lfs diff=lfs merge=lfs -text
|
| 16 |
+
docker/base/fs/ins/install_searxng2.sh filter=lfs diff=lfs merge=lfs -text
|
| 17 |
+
docker/run/AGENTS.md filter=lfs diff=lfs merge=lfs -text
|
| 18 |
+
docker/run/Dockerfile filter=lfs diff=lfs merge=lfs -text
|
| 19 |
+
docker/run/build.txt filter=lfs diff=lfs merge=lfs -text
|
| 20 |
+
docker/run/docker-compose.yml filter=lfs diff=lfs merge=lfs -text
|
| 21 |
+
docker/run/fs/etc/nginx/nginx.conf filter=lfs diff=lfs merge=lfs -text
|
| 22 |
+
docker/run/fs/etc/searxng/limiter.toml filter=lfs diff=lfs merge=lfs -text
|
| 23 |
+
docker/run/fs/etc/searxng/settings.yml filter=lfs diff=lfs merge=lfs -text
|
| 24 |
+
docker/run/fs/etc/supervisor/conf.d/supervisord.conf filter=lfs diff=lfs merge=lfs -text
|
| 25 |
+
docker/run/fs/exe/huggingface-entrypoint.sh filter=lfs diff=lfs merge=lfs -text
|
| 26 |
+
docker/run/fs/exe/initialize.sh filter=lfs diff=lfs merge=lfs -text
|
| 27 |
+
docker/run/fs/exe/node_eval.js filter=lfs diff=lfs merge=lfs -text
|
| 28 |
+
docker/run/fs/exe/run_A0.sh filter=lfs diff=lfs merge=lfs -text
|
| 29 |
+
docker/run/fs/exe/run_searxng.sh filter=lfs diff=lfs merge=lfs -text
|
| 30 |
+
docker/run/fs/exe/run_tunnel_api.sh filter=lfs diff=lfs merge=lfs -text
|
| 31 |
+
docker/run/fs/exe/self_update_manager.py filter=lfs diff=lfs merge=lfs -text
|
| 32 |
+
docker/run/fs/exe/supervisor_event_listener.py filter=lfs diff=lfs merge=lfs -text
|
| 33 |
+
docker/run/fs/exe/trigger_self_update.sh filter=lfs diff=lfs merge=lfs -text
|
| 34 |
+
docker/run/fs/ins/copy_A0.sh filter=lfs diff=lfs merge=lfs -text
|
| 35 |
+
docker/run/fs/ins/install_A0.sh filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
docker/run/fs/ins/install_A02.sh filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
docker/run/fs/ins/install_additional.sh filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
docker/run/fs/ins/install_playwright.sh filter=lfs diff=lfs merge=lfs -text
|
| 39 |
+
docker/run/fs/ins/post_install.sh filter=lfs diff=lfs merge=lfs -text
|
| 40 |
+
docker/run/fs/ins/pre_install.sh filter=lfs diff=lfs merge=lfs -text
|
| 41 |
+
docker/run/fs/ins/setup_ssh.sh filter=lfs diff=lfs merge=lfs -text
|
| 42 |
+
docker/run/fs/ins/setup_venv.sh filter=lfs diff=lfs merge=lfs -text
|
| 43 |
+
docker/run/fs/per/root/.bashrc filter=lfs diff=lfs merge=lfs -text
|
| 44 |
+
docker/run/fs/per/root/.profile filter=lfs diff=lfs merge=lfs -text
|
| 45 |
+
docs/AGENTS.md filter=lfs diff=lfs merge=lfs -text
|
| 46 |
+
docs/README.md filter=lfs diff=lfs merge=lfs -text
|
| 47 |
+
docs/developer/architecture.md filter=lfs diff=lfs merge=lfs -text
|
| 48 |
+
docs/developer/connectivity.md filter=lfs diff=lfs merge=lfs -text
|
| 49 |
+
docs/developer/contributing-skills.md filter=lfs diff=lfs merge=lfs -text
|
| 50 |
+
docs/developer/extensions.md filter=lfs diff=lfs merge=lfs -text
|
| 51 |
+
docs/developer/mcp-configuration.md filter=lfs diff=lfs merge=lfs -text
|
| 52 |
+
docs/developer/notifications.md filter=lfs diff=lfs merge=lfs -text
|
| 53 |
+
docs/developer/plugins.md filter=lfs diff=lfs merge=lfs -text
|
| 54 |
+
docs/developer/sharing-and-safety.md filter=lfs diff=lfs merge=lfs -text
|
| 55 |
+
docs/developer/websockets.md filter=lfs diff=lfs merge=lfs -text
|
| 56 |
+
docs/guides/a0-cli-connector.md filter=lfs diff=lfs merge=lfs -text
|
| 57 |
+
docs/guides/a2a-setup.md filter=lfs diff=lfs merge=lfs -text
|
| 58 |
+
docs/guides/agent-profiles.md filter=lfs diff=lfs merge=lfs -text
|
| 59 |
+
docs/guides/api-integration.md filter=lfs diff=lfs merge=lfs -text
|
| 60 |
+
docs/guides/browser.md filter=lfs diff=lfs merge=lfs -text
|
| 61 |
+
docs/guides/contribution.md filter=lfs diff=lfs merge=lfs -text
|
| 62 |
+
docs/guides/create-plugin.md filter=lfs diff=lfs merge=lfs -text
|
| 63 |
+
docs/guides/desktop.md filter=lfs diff=lfs merge=lfs -text
|
| 64 |
+
docs/guides/launcher.md filter=lfs diff=lfs merge=lfs -text
|
| 65 |
+
docs/guides/local-model-tool-use.md filter=lfs diff=lfs merge=lfs -text
|
| 66 |
+
docs/guides/mcp-setup.md filter=lfs diff=lfs merge=lfs -text
|
| 67 |
+
docs/guides/memory.md filter=lfs diff=lfs merge=lfs -text
|
| 68 |
+
docs/guides/model-presets.md filter=lfs diff=lfs merge=lfs -text
|
| 69 |
+
docs/guides/onboarding.md filter=lfs diff=lfs merge=lfs -text
|
| 70 |
+
docs/guides/projects.md filter=lfs diff=lfs merge=lfs -text
|
| 71 |
+
docs/guides/self-update.md filter=lfs diff=lfs merge=lfs -text
|
| 72 |
+
docs/guides/skills.md filter=lfs diff=lfs merge=lfs -text
|
| 73 |
+
docs/guides/troubleshooting.md filter=lfs diff=lfs merge=lfs -text
|
| 74 |
+
docs/guides/usage.md filter=lfs diff=lfs merge=lfs -text
|
| 75 |
+
docs/quickstart.md filter=lfs diff=lfs merge=lfs -text
|
| 76 |
+
docs/res/a0-vector-graphics/banner.svg filter=lfs diff=lfs merge=lfs -text
|
| 77 |
+
docs/res/a0-vector-graphics/dark.svg filter=lfs diff=lfs merge=lfs -text
|
| 78 |
+
docs/res/a0-vector-graphics/darkSymbol.svg filter=lfs diff=lfs merge=lfs -text
|
| 79 |
+
docs/res/a0-vector-graphics/horizontal_banner.svg filter=lfs diff=lfs merge=lfs -text
|
| 80 |
+
docs/res/a0-vector-graphics/light.svg filter=lfs diff=lfs merge=lfs -text
|
| 81 |
+
docs/res/a0-vector-graphics/lightSymbol.svg filter=lfs diff=lfs merge=lfs -text
|
| 82 |
+
docs/res/banner.png filter=lfs diff=lfs merge=lfs -text
|
| 83 |
+
docs/res/banner_high.png filter=lfs diff=lfs merge=lfs -text
|
| 84 |
+
docs/res/dark.svg filter=lfs diff=lfs merge=lfs -text
|
| 85 |
+
docs/res/dev/devinst-1.png filter=lfs diff=lfs merge=lfs -text
|
| 86 |
+
docs/res/dev/devinst-11.png filter=lfs diff=lfs merge=lfs -text
|
| 87 |
+
docs/res/dev/devinst-12.png filter=lfs diff=lfs merge=lfs -text
|
| 88 |
+
docs/res/dev/devinst-13.png filter=lfs diff=lfs merge=lfs -text
|
| 89 |
+
docs/res/dev/devinst-14.png filter=lfs diff=lfs merge=lfs -text
|
| 90 |
+
docs/res/dev/devinst-3.png filter=lfs diff=lfs merge=lfs -text
|
| 91 |
+
docs/res/dev/devinst-4.png filter=lfs diff=lfs merge=lfs -text
|
| 92 |
+
docs/res/dev/devinst-5.png filter=lfs diff=lfs merge=lfs -text
|
| 93 |
+
docs/res/dev/devinst-6.png filter=lfs diff=lfs merge=lfs -text
|
| 94 |
+
docs/res/dev/devinst-7.png filter=lfs diff=lfs merge=lfs -text
|
| 95 |
+
docs/res/dev/devinst-8.png filter=lfs diff=lfs merge=lfs -text
|
| 96 |
+
docs/res/dev/devinst-9.png filter=lfs diff=lfs merge=lfs -text
|
| 97 |
+
docs/res/favicon.png filter=lfs diff=lfs merge=lfs -text
|
| 98 |
+
docs/res/favicon_round.png filter=lfs diff=lfs merge=lfs -text
|
| 99 |
+
docs/res/header.png filter=lfs diff=lfs merge=lfs -text
|
| 100 |
+
docs/res/install_guide.png filter=lfs diff=lfs merge=lfs -text
|
| 101 |
+
docs/res/profiles.png filter=lfs diff=lfs merge=lfs -text
|
| 102 |
+
docs/res/quickstart/image-24.png filter=lfs diff=lfs merge=lfs -text
|
| 103 |
+
docs/res/quickstart/ui_chat_management.png filter=lfs diff=lfs merge=lfs -text
|
| 104 |
+
docs/res/quickstart/ui_newchat1.png filter=lfs diff=lfs merge=lfs -text
|
| 105 |
+
docs/res/settings-page-ui1.png filter=lfs diff=lfs merge=lfs -text
|
| 106 |
+
docs/res/setup/1-docker-image-search.png filter=lfs diff=lfs merge=lfs -text
|
| 107 |
+
docs/res/setup/2-docker-image-run-3.png filter=lfs diff=lfs merge=lfs -text
|
| 108 |
+
docs/res/setup/2-docker-image-run.png filter=lfs diff=lfs merge=lfs -text
|
| 109 |
+
docs/res/setup/3-docker-port-mapping.png filter=lfs diff=lfs merge=lfs -text
|
| 110 |
+
docs/res/setup/4-docker-container-started.png filter=lfs diff=lfs merge=lfs -text
|
| 111 |
+
docs/res/setup/5-docker-click-to-open.png filter=lfs diff=lfs merge=lfs -text
|
| 112 |
+
docs/res/setup/6-docker-a0-running-new.png filter=lfs diff=lfs merge=lfs -text
|
| 113 |
+
docs/res/setup/9-rfc-devpage-on-docker-instance-1.png filter=lfs diff=lfs merge=lfs -text
|
| 114 |
+
docs/res/setup/9-rfc-devpage-on-local-sbs-1.png filter=lfs diff=lfs merge=lfs -text
|
| 115 |
+
docs/res/setup/a2a/a2a-conn.png filter=lfs diff=lfs merge=lfs -text
|
| 116 |
+
docs/res/setup/a2a/a2a2.png filter=lfs diff=lfs merge=lfs -text
|
| 117 |
+
docs/res/setup/docker-delete-image-1.png filter=lfs diff=lfs merge=lfs -text
|
| 118 |
+
docs/res/setup/image-1.png filter=lfs diff=lfs merge=lfs -text
|
| 119 |
+
docs/res/setup/image-10.png filter=lfs diff=lfs merge=lfs -text
|
| 120 |
+
docs/res/setup/image-11.png filter=lfs diff=lfs merge=lfs -text
|
| 121 |
+
docs/res/setup/image-12.png filter=lfs diff=lfs merge=lfs -text
|
| 122 |
+
docs/res/setup/image-13.png filter=lfs diff=lfs merge=lfs -text
|
| 123 |
+
docs/res/setup/image-14-u.png filter=lfs diff=lfs merge=lfs -text
|
| 124 |
+
docs/res/setup/image-14.png filter=lfs diff=lfs merge=lfs -text
|
| 125 |
+
docs/res/setup/image-15.png filter=lfs diff=lfs merge=lfs -text
|
| 126 |
+
docs/res/setup/image-16.png filter=lfs diff=lfs merge=lfs -text
|
| 127 |
+
docs/res/setup/image-17.png filter=lfs diff=lfs merge=lfs -text
|
| 128 |
+
docs/res/setup/image-18.png filter=lfs diff=lfs merge=lfs -text
|
| 129 |
+
docs/res/setup/image-2.png filter=lfs diff=lfs merge=lfs -text
|
| 130 |
+
docs/res/setup/image-20.png filter=lfs diff=lfs merge=lfs -text
|
| 131 |
+
docs/res/setup/image-21.png filter=lfs diff=lfs merge=lfs -text
|
| 132 |
+
docs/res/setup/image-22-1.png filter=lfs diff=lfs merge=lfs -text
|
| 133 |
+
docs/res/setup/image-23-1.png filter=lfs diff=lfs merge=lfs -text
|
| 134 |
+
docs/res/setup/image-3.png filter=lfs diff=lfs merge=lfs -text
|
| 135 |
+
docs/res/setup/image-4.png filter=lfs diff=lfs merge=lfs -text
|
| 136 |
+
docs/res/setup/image-5.png filter=lfs diff=lfs merge=lfs -text
|
| 137 |
+
docs/res/setup/image-6.png filter=lfs diff=lfs merge=lfs -text
|
| 138 |
+
docs/res/setup/image-7.png filter=lfs diff=lfs merge=lfs -text
|
| 139 |
+
docs/res/setup/image-8.png filter=lfs diff=lfs merge=lfs -text
|
| 140 |
+
docs/res/setup/image-9.png filter=lfs diff=lfs merge=lfs -text
|
| 141 |
+
docs/res/setup/image.png filter=lfs diff=lfs merge=lfs -text
|
| 142 |
+
docs/res/setup/macsocket.png filter=lfs diff=lfs merge=lfs -text
|
| 143 |
+
docs/res/setup/mcp/mcp-example-config.png filter=lfs diff=lfs merge=lfs -text
|
| 144 |
+
docs/res/setup/mcp/mcp-open-config.png filter=lfs diff=lfs merge=lfs -text
|
| 145 |
+
docs/res/setup/oses/apple.png filter=lfs diff=lfs merge=lfs -text
|
| 146 |
+
docs/res/setup/oses/linux.png filter=lfs diff=lfs merge=lfs -text
|
| 147 |
+
docs/res/setup/oses/windows.png filter=lfs diff=lfs merge=lfs -text
|
| 148 |
+
docs/res/setup/settings/1-agentConfig.png filter=lfs diff=lfs merge=lfs -text
|
| 149 |
+
docs/res/setup/settings/2-chat-model.png filter=lfs diff=lfs merge=lfs -text
|
| 150 |
+
docs/res/setup/settings/3-auth.png filter=lfs diff=lfs merge=lfs -text
|
| 151 |
+
docs/res/setup/settings/4-local-models.png filter=lfs diff=lfs merge=lfs -text
|
| 152 |
+
docs/res/setup/thumb_setup.png filter=lfs diff=lfs merge=lfs -text
|
| 153 |
+
docs/res/setup/update-initialize.png filter=lfs diff=lfs merge=lfs -text
|
| 154 |
+
docs/res/splash.webp filter=lfs diff=lfs merge=lfs -text
|
| 155 |
+
docs/res/splash_wide.png filter=lfs diff=lfs merge=lfs -text
|
| 156 |
+
docs/res/thumbnail-install.webp filter=lfs diff=lfs merge=lfs -text
|
| 157 |
+
docs/res/time-travel.png filter=lfs diff=lfs merge=lfs -text
|
| 158 |
+
docs/res/ui_screen2.png filter=lfs diff=lfs merge=lfs -text
|
| 159 |
+
docs/res/usage/a0-cli/a0-cli-browser-host-mode.png filter=lfs diff=lfs merge=lfs -text
|
| 160 |
+
docs/res/usage/a0-cli/a0-cli-browser-privacy.png filter=lfs diff=lfs merge=lfs -text
|
| 161 |
+
docs/res/usage/a0-cli/a0-cli-browser-status.png filter=lfs diff=lfs merge=lfs -text
|
| 162 |
+
docs/res/usage/a0-cli/a0-cli-command-browser.png filter=lfs diff=lfs merge=lfs -text
|
| 163 |
+
docs/res/usage/a0-cli/a0-cli-command-palette.png filter=lfs diff=lfs merge=lfs -text
|
| 164 |
+
docs/res/usage/a0-cli/a0-cli-host-picker.png filter=lfs diff=lfs merge=lfs -text
|
| 165 |
+
docs/res/usage/a0-cli/a0-cli-permissions.png filter=lfs diff=lfs merge=lfs -text
|
| 166 |
+
docs/res/usage/a0-cli/a0-cli-profile-created.png filter=lfs diff=lfs merge=lfs -text
|
| 167 |
+
docs/res/usage/a0-cli/a0-cli-profile-menu.png filter=lfs diff=lfs merge=lfs -text
|
| 168 |
+
docs/res/usage/a0-cli/a0-cli-start.png filter=lfs diff=lfs merge=lfs -text
|
| 169 |
+
docs/res/usage/action-btns.png filter=lfs diff=lfs merge=lfs -text
|
| 170 |
+
docs/res/usage/api-int/api-int-1.png filter=lfs diff=lfs merge=lfs -text
|
| 171 |
+
docs/res/usage/api-int/api-int-2image-gen-api2.png filter=lfs diff=lfs merge=lfs -text
|
| 172 |
+
docs/res/usage/api-int/api-int-3-api-key-missing-secrets.png filter=lfs diff=lfs merge=lfs -text
|
| 173 |
+
docs/res/usage/api-int/api-int-4-secrets-setting.png filter=lfs diff=lfs merge=lfs -text
|
| 174 |
+
docs/res/usage/api-int/api-int-5-finish.png filter=lfs diff=lfs merge=lfs -text
|
| 175 |
+
docs/res/usage/attachments-1.png filter=lfs diff=lfs merge=lfs -text
|
| 176 |
+
docs/res/usage/attachments-2.png filter=lfs diff=lfs merge=lfs -text
|
| 177 |
+
docs/res/usage/browser/browser-annotation-comment.png filter=lfs diff=lfs merge=lfs -text
|
| 178 |
+
docs/res/usage/browser/browser-canvas-example.png filter=lfs diff=lfs merge=lfs -text
|
| 179 |
+
docs/res/usage/browser/browser-canvas-wide.png filter=lfs diff=lfs merge=lfs -text
|
| 180 |
+
docs/res/usage/browser/browser-plugin-settings.png filter=lfs diff=lfs merge=lfs -text
|
| 181 |
+
docs/res/usage/browser/browser-tool-history-expanded.png filter=lfs diff=lfs merge=lfs -text
|
| 182 |
+
docs/res/usage/browser/browser-toolbar-settings.png filter=lfs diff=lfs merge=lfs -text
|
| 183 |
+
docs/res/usage/browser/host-browser-remote-debugging-allow.png filter=lfs diff=lfs merge=lfs -text
|
| 184 |
+
docs/res/usage/browser/host-browser-remote-debugging-setting.png filter=lfs diff=lfs merge=lfs -text
|
| 185 |
+
docs/res/usage/file-browser.png filter=lfs diff=lfs merge=lfs -text
|
| 186 |
+
docs/res/usage/file-edit.png filter=lfs diff=lfs merge=lfs -text
|
| 187 |
+
docs/res/usage/first-task.png filter=lfs diff=lfs merge=lfs -text
|
| 188 |
+
docs/res/usage/launcher/launcher-installs.png filter=lfs diff=lfs merge=lfs -text
|
| 189 |
+
docs/res/usage/launcher/launcher-runtime-setup.png filter=lfs diff=lfs merge=lfs -text
|
| 190 |
+
docs/res/usage/memory-dashboard.png filter=lfs diff=lfs merge=lfs -text
|
| 191 |
+
docs/res/usage/memory-editing.png filter=lfs diff=lfs merge=lfs -text
|
| 192 |
+
docs/res/usage/multi-agent.png filter=lfs diff=lfs merge=lfs -text
|
| 193 |
+
docs/res/usage/nudge.png filter=lfs diff=lfs merge=lfs -text
|
| 194 |
+
docs/res/usage/onboarding/onboarding-account-provider.png filter=lfs diff=lfs merge=lfs -text
|
| 195 |
+
docs/res/usage/onboarding/onboarding-agent-zero-api-key-model.png filter=lfs diff=lfs merge=lfs -text
|
| 196 |
+
docs/res/usage/onboarding/onboarding-agent-zero-api-model-dropdown.png filter=lfs diff=lfs merge=lfs -text
|
| 197 |
+
docs/res/usage/onboarding/onboarding-cloud-provider.png filter=lfs diff=lfs merge=lfs -text
|
| 198 |
+
docs/res/usage/onboarding/onboarding-local-ollama-main.png filter=lfs diff=lfs merge=lfs -text
|
| 199 |
+
docs/res/usage/onboarding/onboarding-model-gate.png filter=lfs diff=lfs merge=lfs -text
|
| 200 |
+
docs/res/usage/onboarding/onboarding-ready.png filter=lfs diff=lfs merge=lfs -text
|
| 201 |
+
docs/res/usage/onboarding/onboarding-start.png filter=lfs diff=lfs merge=lfs -text
|
| 202 |
+
docs/res/usage/onboarding/onboarding-utility-same-model.png filter=lfs diff=lfs merge=lfs -text
|
| 203 |
+
docs/res/usage/projects/projects-activate-project.png filter=lfs diff=lfs merge=lfs -text
|
| 204 |
+
docs/res/usage/projects/projects-creation.png filter=lfs diff=lfs merge=lfs -text
|
| 205 |
+
docs/res/usage/projects/projects-desc-and-instructions.png filter=lfs diff=lfs merge=lfs -text
|
| 206 |
+
docs/res/usage/projects/projects-first-ops.png filter=lfs diff=lfs merge=lfs -text
|
| 207 |
+
docs/res/usage/projects/projects-git-projects-tree.png filter=lfs diff=lfs merge=lfs -text
|
| 208 |
+
docs/res/usage/projects/projects-gitprojects-clone.png filter=lfs diff=lfs merge=lfs -text
|
| 209 |
+
docs/res/usage/restart.png filter=lfs diff=lfs merge=lfs -text
|
| 210 |
+
docs/res/usage/tasks/edit-task.png filter=lfs diff=lfs merge=lfs -text
|
| 211 |
+
docs/res/usage/tasks/scheduler-1.png filter=lfs diff=lfs merge=lfs -text
|
| 212 |
+
docs/res/usage/ui-context1.png filter=lfs diff=lfs merge=lfs -text
|
| 213 |
+
docs/res/usage/ui-history1.png filter=lfs diff=lfs merge=lfs -text
|
| 214 |
+
docs/res/usage/ui-katex-2.png filter=lfs diff=lfs merge=lfs -text
|
| 215 |
+
docs/res/usage/ui-settings-5-speech-to-text.png filter=lfs diff=lfs merge=lfs -text
|
| 216 |
+
docs/res/usage/ui-tts-stop-speech1.png filter=lfs diff=lfs merge=lfs -text
|
| 217 |
+
docs/res/usage/updating/self-update-v1-to-v2-warning.png filter=lfs diff=lfs merge=lfs -text
|
| 218 |
+
docs/res/usage/updating/self-update-v2-current.png filter=lfs diff=lfs merge=lfs -text
|
| 219 |
+
docs/res/usage/webui/agent-editor-advanced-prompts.png filter=lfs diff=lfs merge=lfs -text
|
| 220 |
+
docs/res/usage/webui/agent-editor-advanced-tools.png filter=lfs diff=lfs merge=lfs -text
|
| 221 |
+
docs/res/usage/webui/agent-editor-easy-permissions.png filter=lfs diff=lfs merge=lfs -text
|
| 222 |
+
docs/res/usage/webui/agent-editor-easy.png filter=lfs diff=lfs merge=lfs -text
|
| 223 |
+
docs/res/usage/webui/agent-editor-review.png filter=lfs diff=lfs merge=lfs -text
|
| 224 |
+
docs/res/usage/webui/agent-profile-manager.png filter=lfs diff=lfs merge=lfs -text
|
| 225 |
+
docs/res/usage/webui/agent-profile-selector.png filter=lfs diff=lfs merge=lfs -text
|
| 226 |
+
docs/res/usage/webui/chat-more-actions-skills.png filter=lfs diff=lfs merge=lfs -text
|
| 227 |
+
docs/res/usage/webui/dashboard.png filter=lfs diff=lfs merge=lfs -text
|
| 228 |
+
docs/res/usage/webui/desktop-canvas.png filter=lfs diff=lfs merge=lfs -text
|
| 229 |
+
docs/res/usage/webui/desktop-new-menu.png filter=lfs diff=lfs merge=lfs -text
|
| 230 |
+
docs/res/usage/webui/desktop-writer.png filter=lfs diff=lfs merge=lfs -text
|
| 231 |
+
docs/res/usage/webui/memory-dashboard-controls.png filter=lfs diff=lfs merge=lfs -text
|
| 232 |
+
docs/res/usage/webui/model-preset-selector.png filter=lfs diff=lfs merge=lfs -text
|
| 233 |
+
docs/res/usage/webui/model-presets-add.png filter=lfs diff=lfs merge=lfs -text
|
| 234 |
+
docs/res/usage/webui/model-presets-editor.png filter=lfs diff=lfs merge=lfs -text
|
| 235 |
+
docs/res/usage/webui/project-active-chat.png filter=lfs diff=lfs merge=lfs -text
|
| 236 |
+
docs/res/usage/webui/project-create-filled.png filter=lfs diff=lfs merge=lfs -text
|
docker/base/Dockerfile
CHANGED
|
@@ -1,40 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
# Set locale to en_US.UTF-8 and timezone to UTC
|
| 6 |
-
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y locales tzdata
|
| 7 |
-
RUN sed -i -e 's/# \(en_US\.UTF-8 .*\)/\1/' /etc/locale.gen && \
|
| 8 |
-
dpkg-reconfigure --frontend=noninteractive locales && \
|
| 9 |
-
update-locale LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8
|
| 10 |
-
RUN ln -sf /usr/share/zoneinfo/UTC /etc/localtime
|
| 11 |
-
RUN echo "UTC" > /etc/timezone
|
| 12 |
-
RUN dpkg-reconfigure -f noninteractive tzdata
|
| 13 |
-
ENV LANG=en_US.UTF-8
|
| 14 |
-
ENV LANGUAGE=en_US:en
|
| 15 |
-
ENV LC_ALL=en_US.UTF-8
|
| 16 |
-
ENV TZ=UTC
|
| 17 |
-
|
| 18 |
-
# Copy contents of the project to /
|
| 19 |
-
COPY ./fs/ /
|
| 20 |
-
|
| 21 |
-
# install packages software (split for better cache management)
|
| 22 |
-
RUN bash /ins/install_base_packages1.sh
|
| 23 |
-
RUN bash /ins/install_base_packages2.sh
|
| 24 |
-
RUN bash /ins/install_base_packages3.sh
|
| 25 |
-
RUN bash /ins/install_base_packages4.sh
|
| 26 |
-
|
| 27 |
-
# install python after packages to ensure version overriding
|
| 28 |
-
RUN bash /ins/install_python.sh
|
| 29 |
-
|
| 30 |
-
# install searxng
|
| 31 |
-
RUN bash /ins/install_searxng.sh
|
| 32 |
-
|
| 33 |
-
# configure ssh
|
| 34 |
-
RUN bash /ins/configure_ssh.sh
|
| 35 |
-
|
| 36 |
-
# after install
|
| 37 |
-
RUN bash /ins/after_install.sh
|
| 38 |
-
|
| 39 |
-
# Keep container running infinitely
|
| 40 |
-
CMD ["tail", "-f", "/dev/null"]
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:234bdf6caffd5a7ddac176efea5b3060f1de4d38f26790277876370304b05034
|
| 3 |
+
size 1196
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/base/build.txt
CHANGED
|
@@ -1,18 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
# local image without cache
|
| 5 |
-
docker build -t agent-zero-base:local --no-cache .
|
| 6 |
-
|
| 7 |
-
# dockerhub push:
|
| 8 |
-
|
| 9 |
-
docker login
|
| 10 |
-
|
| 11 |
-
# with cache
|
| 12 |
-
docker buildx build -t agent0ai/agent-zero-base:latest --platform linux/amd64,linux/arm64 --push --build-arg CACHE_DATE=$(date +%Y-%m-%d:%H:%M:%S) .
|
| 13 |
-
|
| 14 |
-
# without cache
|
| 15 |
-
docker buildx build -t agent0ai/agent-zero-base:latest --platform linux/amd64,linux/arm64 --push --build-arg CACHE_DATE=$(date +%Y-%m-%d:%H:%M:%S) --no-cache .
|
| 16 |
-
|
| 17 |
-
# plain output
|
| 18 |
-
--progress=plain
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:7e6132c3b52e84a646dfc752ccea6a278c01ef1f6b1c7d20a217496cb0dda743
|
| 3 |
+
size 608
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/base/fs/etc/searxng/limiter.toml
CHANGED
|
@@ -1,33 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
# The prefix defines the number of leading bits in an address that are compared
|
| 6 |
-
# to determine whether or not an address is part of a (client) network.
|
| 7 |
-
ipv4_prefix = 32
|
| 8 |
-
ipv6_prefix = 48
|
| 9 |
-
|
| 10 |
-
[botdetection.ip_limit]
|
| 11 |
-
# To get unlimited access in a local network, by default link-local addresses
|
| 12 |
-
# (networks) are not monitored by the ip_limit
|
| 13 |
-
filter_link_local = false
|
| 14 |
-
|
| 15 |
-
# Activate link_token method in the ip_limit method
|
| 16 |
-
link_token = false
|
| 17 |
-
|
| 18 |
-
[botdetection.ip_lists]
|
| 19 |
-
# In the limiter, the ip_lists method has priority over all other methods.
|
| 20 |
-
# If an IP is in the pass_ip list, it has unrestricted access and is not
|
| 21 |
-
# checked if, for example, the "user agent" suggests a bot (e.g., curl).
|
| 22 |
-
block_ip = [
|
| 23 |
-
# '93.184.216.34', # Example IPv4 address
|
| 24 |
-
# '257.1.1.1', # Invalid IP --> will be ignored, logged in ERROR class
|
| 25 |
-
]
|
| 26 |
-
pass_ip = [
|
| 27 |
-
# '192.168.0.0/16', # IPv4 private network
|
| 28 |
-
# 'fe80::/10', # IPv6 link-local; overrides botdetection.ip_limit.filter_link_local
|
| 29 |
-
]
|
| 30 |
-
|
| 31 |
-
# Activate passlist of (hardcoded) IPs from the SearXNG organization,
|
| 32 |
-
# e.g., `check.searx.space`.
|
| 33 |
-
pass_searxng_org = true
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:0823d3680c926766580465b06b07ffb2198c9e4e53ca56a2ca3a45fc4a5811be
|
| 3 |
+
size 1199
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/base/fs/etc/searxng/settings.yml
CHANGED
|
@@ -1,91 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
# variant payloads that break the 2026.04 searxng bootstrap init path.
|
| 5 |
-
use_default_settings:
|
| 6 |
-
engines:
|
| 7 |
-
remove:
|
| 8 |
-
- wikidata
|
| 9 |
-
|
| 10 |
-
general:
|
| 11 |
-
debug: false
|
| 12 |
-
instance_name: "SearXNG"
|
| 13 |
-
|
| 14 |
-
search:
|
| 15 |
-
safe_search: 0
|
| 16 |
-
# autocomplete: 'duckduckgo'
|
| 17 |
-
formats:
|
| 18 |
-
- json
|
| 19 |
-
# - html
|
| 20 |
-
|
| 21 |
-
server:
|
| 22 |
-
# Is overwritten by ${SEARXNG_SECRET}
|
| 23 |
-
secret_key: "dummy"
|
| 24 |
-
port: 55510
|
| 25 |
-
limiter: false
|
| 26 |
-
image_proxy: false
|
| 27 |
-
# public URL of the instance, to ensure correct inbound links. Is overwritten
|
| 28 |
-
# by ${SEARXNG_URL}.
|
| 29 |
-
# base_url: http://example.com/location
|
| 30 |
-
|
| 31 |
-
# redis:
|
| 32 |
-
# # URL to connect redis database. Is overwritten by ${SEARXNG_REDIS_URL}.
|
| 33 |
-
# url: unix:///usr/local/searxng-redis/run/redis.sock?db=0
|
| 34 |
-
|
| 35 |
-
ui:
|
| 36 |
-
static_use_hash: true
|
| 37 |
-
|
| 38 |
-
# preferences:
|
| 39 |
-
# lock:
|
| 40 |
-
# - autocomplete
|
| 41 |
-
# - method
|
| 42 |
-
|
| 43 |
-
enabled_plugins:
|
| 44 |
-
- 'Hash plugin'
|
| 45 |
-
- 'Self Informations'
|
| 46 |
-
- 'Tracker URL remover'
|
| 47 |
-
# - 'Ahmia blacklist'
|
| 48 |
-
# - 'Hostnames plugin' # see 'hostnames' configuration below
|
| 49 |
-
# - 'Open Access DOI rewrite'
|
| 50 |
-
|
| 51 |
-
# plugins:
|
| 52 |
-
# - only_show_green_results
|
| 53 |
-
|
| 54 |
-
# hostnames:
|
| 55 |
-
# replace:
|
| 56 |
-
# '(.*\.)?youtube\.com$': 'invidious.example.com'
|
| 57 |
-
# '(.*\.)?youtu\.be$': 'invidious.example.com'
|
| 58 |
-
# remove:
|
| 59 |
-
# - '(.*\.)?facebook.com$'
|
| 60 |
-
# low_priority:
|
| 61 |
-
# - '(.*\.)?google\.com$'
|
| 62 |
-
# high_priority:
|
| 63 |
-
# - '(.*\.)?wikipedia.org$'
|
| 64 |
-
|
| 65 |
-
engines:
|
| 66 |
-
|
| 67 |
-
- name: ahmia
|
| 68 |
-
disabled: true
|
| 69 |
-
inactive: true
|
| 70 |
-
|
| 71 |
-
- name: torch
|
| 72 |
-
disabled: true
|
| 73 |
-
inactive: true
|
| 74 |
-
|
| 75 |
-
# - name: fdroid
|
| 76 |
-
# disabled: false
|
| 77 |
-
#
|
| 78 |
-
# - name: apk mirror
|
| 79 |
-
# disabled: false
|
| 80 |
-
#
|
| 81 |
-
# - name: mediathekviewweb
|
| 82 |
-
# categories: TV
|
| 83 |
-
# disabled: false
|
| 84 |
-
#
|
| 85 |
-
# - name: invidious
|
| 86 |
-
# disabled: false
|
| 87 |
-
# base_url:
|
| 88 |
-
# - https://invidious.snopyta.org
|
| 89 |
-
# - https://invidious.tiekoetter.com
|
| 90 |
-
# - https://invidio.xamh.de
|
| 91 |
-
# - https://inv.riverside.rocks
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:285a75924555f7ce3e2c31020eb0ea48d9d86cdaae5488b4eedf07b0d3006d89
|
| 3 |
+
size 1890
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/base/fs/ins/after_install.sh
CHANGED
|
@@ -1,5 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
# clean up apt cache
|
| 5 |
-
sudo apt-get clean
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:307cbee5297787e5f380cd77003e559f66e5f18aa88e8dc8ea07c94971ad7af5
|
| 3 |
+
size 60
|
|
|
|
|
|
docker/base/fs/ins/configure_ssh.sh
CHANGED
|
@@ -1,6 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
# Set up SSH
|
| 5 |
-
mkdir -p /var/run/sshd && \
|
| 6 |
-
sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:16e50ddfdac1068376d23490242d51cfbad1297a3a686b2c70fbebe54b5c95d8
|
| 3 |
+
size 152
|
|
|
|
|
|
|
|
|
docker/base/fs/ins/install_base_packages1.sh
CHANGED
|
@@ -1,11 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
echo "====================BASE PACKAGES1 START===================="
|
| 5 |
-
|
| 6 |
-
apt-get update && apt-get upgrade -y
|
| 7 |
-
|
| 8 |
-
apt-get install -y --no-install-recommends \
|
| 9 |
-
sudo curl wget git cron unzip 7zip
|
| 10 |
-
|
| 11 |
-
echo "====================BASE PACKAGES1 END===================="
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a8fdbbaf67375fd8ce6691a7e5dafef875649687b8355ab3c4f9fefbb4cdb1ca
|
| 3 |
+
size 278
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/base/fs/ins/install_base_packages2.sh
CHANGED
|
@@ -1,10 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
echo "====================BASE PACKAGES2 START===================="
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
apt-get install -y --no-install-recommends \
|
| 8 |
-
openssh-server ffmpeg supervisor
|
| 9 |
-
|
| 10 |
-
echo "====================BASE PACKAGES2 END===================="
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:91b5a734921d9be8fe70705f9d8a1c6ce731ef718b8bfb1cd92d5133498a4c59
|
| 3 |
+
size 239
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/base/fs/ins/install_base_packages3.sh
CHANGED
|
@@ -1,13 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
echo "====================BASE PACKAGES3 START===================="
|
| 5 |
-
|
| 6 |
-
apt-get install -y --no-install-recommends \
|
| 7 |
-
nodejs npm
|
| 8 |
-
|
| 9 |
-
echo "====================BASE PACKAGES3 NPM===================="
|
| 10 |
-
|
| 11 |
-
# we shall not install npx separately, it's discontinued and some versions are broken
|
| 12 |
-
# npm i -g npx
|
| 13 |
-
echo "====================BASE PACKAGES3 END===================="
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:964b5a3d7f2afdaf2e27bf60bb28e77b6bcc8d19476722615d47254529e352c7
|
| 3 |
+
size 384
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/base/fs/ins/install_base_packages4.sh
CHANGED
|
@@ -1,9 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
echo "====================BASE PACKAGES4 START===================="
|
| 5 |
-
|
| 6 |
-
apt-get install -y --no-install-recommends \
|
| 7 |
-
tesseract-ocr tesseract-ocr-script-latn poppler-utils
|
| 8 |
-
|
| 9 |
-
echo "====================BASE PACKAGES4 END===================="
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:2d7ac6e3c9ed2b10e886ef56de073e35643981181e1f9b77b22e9541d771b7ce
|
| 3 |
+
size 258
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/base/fs/ins/install_python.sh
CHANGED
|
@@ -1,73 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
echo "====================PYTHON START===================="
|
| 5 |
-
|
| 6 |
-
echo "====================PYTHON 3.13===================="
|
| 7 |
-
|
| 8 |
-
apt clean && apt-get update && apt-get -y upgrade
|
| 9 |
-
|
| 10 |
-
# install python 3.13 globally
|
| 11 |
-
apt-get install -y --no-install-recommends \
|
| 12 |
-
python3.13 python3.13-venv
|
| 13 |
-
#python3.13-dev
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
echo "====================PYTHON 3.13 VENV===================="
|
| 17 |
-
|
| 18 |
-
# create and activate default venv
|
| 19 |
-
python3.13 -m venv /opt/venv
|
| 20 |
-
source /opt/venv/bin/activate
|
| 21 |
-
|
| 22 |
-
# upgrade pip and install static packages
|
| 23 |
-
pip install --no-cache-dir --upgrade pip pipx ipython requests
|
| 24 |
-
|
| 25 |
-
echo "====================PYTHON PYVENV===================="
|
| 26 |
-
|
| 27 |
-
# Install pyenv build dependencies.
|
| 28 |
-
apt-get install -y --no-install-recommends \
|
| 29 |
-
make build-essential libssl-dev zlib1g-dev libbz2-dev \
|
| 30 |
-
libreadline-dev libsqlite3-dev wget curl llvm \
|
| 31 |
-
libncursesw5-dev xz-utils tk-dev libxml2-dev \
|
| 32 |
-
libxmlsec1-dev libffi-dev liblzma-dev
|
| 33 |
-
|
| 34 |
-
# Install pyenv globally
|
| 35 |
-
git clone https://github.com/pyenv/pyenv.git /opt/pyenv
|
| 36 |
-
|
| 37 |
-
# Setup environment variables for pyenv to be available system-wide
|
| 38 |
-
cat > /etc/profile.d/pyenv.sh <<'EOF'
|
| 39 |
-
export PYENV_ROOT="/opt/pyenv"
|
| 40 |
-
export PATH="$PYENV_ROOT/bin:$PATH"
|
| 41 |
-
eval "$(pyenv init --path)"
|
| 42 |
-
EOF
|
| 43 |
-
|
| 44 |
-
# fix permissions
|
| 45 |
-
chmod +x /etc/profile.d/pyenv.sh
|
| 46 |
-
|
| 47 |
-
# Source pyenv environment to make it available in this script
|
| 48 |
-
source /etc/profile.d/pyenv.sh
|
| 49 |
-
|
| 50 |
-
# Install Python 3.12.4
|
| 51 |
-
echo "====================PYENV 3.12 VENV===================="
|
| 52 |
-
pyenv install 3.12.4
|
| 53 |
-
|
| 54 |
-
/opt/pyenv/versions/3.12.4/bin/python -m venv /opt/venv-a0
|
| 55 |
-
source /opt/venv-a0/bin/activate
|
| 56 |
-
|
| 57 |
-
# upgrade pip and install static packages
|
| 58 |
-
pip install --no-cache-dir --upgrade pip pipx
|
| 59 |
-
|
| 60 |
-
# Install some packages in specific variants
|
| 61 |
-
pip install --no-cache-dir \
|
| 62 |
-
torch==2.4.0 \
|
| 63 |
-
torchvision==0.19.0 \
|
| 64 |
-
--index-url https://download.pytorch.org/whl/cpu
|
| 65 |
-
|
| 66 |
-
echo "====================PYTHON UV ===================="
|
| 67 |
-
|
| 68 |
-
curl -Ls https://astral.sh/uv/install.sh | UV_INSTALL_DIR=/usr/local/bin sh
|
| 69 |
-
|
| 70 |
-
# clean up pip cache
|
| 71 |
-
pip cache purge
|
| 72 |
-
|
| 73 |
-
echo "====================PYTHON END===================="
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:9c83793cf9f40cc2f1c318e3014f53b540e1056954eba409bc13712b0fc8579d
|
| 3 |
+
size 2068
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/base/fs/ins/install_searxng.sh
CHANGED
|
@@ -1,29 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
echo "====================SEARXNG1 START===================="
|
| 5 |
-
|
| 6 |
-
# Install necessary packages
|
| 7 |
-
apt-get install -y \
|
| 8 |
-
git build-essential libxslt-dev zlib1g-dev libffi-dev libssl-dev
|
| 9 |
-
# python3.12-babel uwsgi uwsgi-plugin-python3
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
# Add the searxng system user
|
| 13 |
-
useradd --shell /bin/bash --system \
|
| 14 |
-
--home-dir "/usr/local/searxng" \
|
| 15 |
-
--comment 'Privacy-respecting metasearch engine' \
|
| 16 |
-
searxng
|
| 17 |
-
|
| 18 |
-
# Add the searxng user to the sudo group
|
| 19 |
-
usermod -aG sudo searxng
|
| 20 |
-
|
| 21 |
-
# Create the searxng directory and set ownership
|
| 22 |
-
mkdir "/usr/local/searxng"
|
| 23 |
-
chown -R "searxng:searxng" "/usr/local/searxng"
|
| 24 |
-
|
| 25 |
-
echo "====================SEARXNG1 END===================="
|
| 26 |
-
|
| 27 |
-
# Start a new shell as the searxng user and run the installation script
|
| 28 |
-
su - searxng -c "bash /ins/install_searxng2.sh"
|
| 29 |
-
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:b9fdb44b3ed98908f44fdc0dda73946afe22a12e56067863da837bfefc528b8e
|
| 3 |
+
size 800
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/base/fs/ins/install_searxng2.sh
CHANGED
|
@@ -1,36 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
echo "====================SEARXNG2 START===================="
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
# clone SearXNG repo
|
| 8 |
-
git clone "https://github.com/searxng/searxng" \
|
| 9 |
-
"/usr/local/searxng/searxng-src"
|
| 10 |
-
|
| 11 |
-
echo "====================SEARXNG2 VENV===================="
|
| 12 |
-
|
| 13 |
-
# create virtualenv:
|
| 14 |
-
python3.13 -m venv "/usr/local/searxng/searx-pyenv"
|
| 15 |
-
|
| 16 |
-
# make it default
|
| 17 |
-
echo ". /usr/local/searxng/searx-pyenv/bin/activate" \
|
| 18 |
-
>> "/usr/local/searxng/.profile"
|
| 19 |
-
|
| 20 |
-
# activate venv
|
| 21 |
-
source "/usr/local/searxng/searx-pyenv/bin/activate"
|
| 22 |
-
|
| 23 |
-
echo "====================SEARXNG2 INST===================="
|
| 24 |
-
|
| 25 |
-
# update pip's boilerplate
|
| 26 |
-
pip install --no-cache-dir -U pip setuptools wheel pyyaml lxml msgspec typing_extensions
|
| 27 |
-
|
| 28 |
-
# jump to SearXNG's working tree and install SearXNG into virtualenv
|
| 29 |
-
cd "/usr/local/searxng/searxng-src"
|
| 30 |
-
# pip install --no-cache-dir --use-pep517 --no-build-isolation -e .
|
| 31 |
-
pip install --no-cache-dir --use-pep517 --no-build-isolation .
|
| 32 |
-
|
| 33 |
-
# cleanup cache
|
| 34 |
-
pip cache purge
|
| 35 |
-
|
| 36 |
-
echo "====================SEARXNG2 END===================="
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ea486499849de2f7bc02febb8cac390b94d01e10dcdf3415f9b126c5f1be6726
|
| 3 |
+
size 1048
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/run/AGENTS.md
CHANGED
|
@@ -1,43 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
- Own the runnable Agent Zero image context and local compose example.
|
| 6 |
-
- Install Agent Zero from a selected branch onto the base image and prepare runtime entrypoints.
|
| 7 |
-
|
| 8 |
-
## Ownership
|
| 9 |
-
|
| 10 |
-
- `Dockerfile` owns branch-based image assembly, exposed ports, and container startup command.
|
| 11 |
-
- `docker-compose.yml` owns the local compose service example.
|
| 12 |
-
- `build.txt` owns maintainer build and push command notes.
|
| 13 |
-
- `fs/exe/` owns runtime entrypoint, supervisor, self-update, Node eval, and service scripts.
|
| 14 |
-
- `fs/exe/huggingface-entrypoint.sh` owns Space-specific startup defaults, including disabling outbound Cloudflare tunnels and enabling A2A.
|
| 15 |
-
- `fs/ins/` owns preinstall, installation, virtualenv, Playwright, SSH, and postinstall scripts.
|
| 16 |
-
- Files under `fs/` are copied to container root during the runtime build.
|
| 17 |
-
|
| 18 |
-
## Local Contracts
|
| 19 |
-
|
| 20 |
-
- `BRANCH` is required for branch-based Docker builds.
|
| 21 |
-
- Preserve exposed ports for SSH, HTTP, and tunneled services unless docs and workflows are updated together.
|
| 22 |
-
- Keep the two-runtime Python model aligned with the root contract.
|
| 23 |
-
- Keep runtime desktop packages on `kali-last-snapshot`; carry the rolling base's matching ATK introspection package into that transaction, then pin the verified Python 3.13-compatible LibreOffice and complete Xpra runtime versions in `fs/ins/install_additional.sh` for both published architectures.
|
| 24 |
-
- Do not bake secrets, local `.env` values, or user data into the image.
|
| 25 |
-
- Runtime startup must ensure `/a0/usr/uploads` exists before supervised services start.
|
| 26 |
-
- Runtime startup raises the soft open-file limit toward `A0_NOFILE_LIMIT` (default `65535`) before supervisord starts, bounded by the container hard limit.
|
| 27 |
-
- Self-update user-data backups skip Time Travel shadow history under `usr/.time_travel/` and transient Desktop agent state.
|
| 28 |
-
- Self-update waits up to 180 seconds for the updated or restored WebUI health check by default; `A0_SELF_UPDATE_HEALTH_TIMEOUT_SECONDS` may override it.
|
| 29 |
-
- Successful or already-current self-updates refresh an installed Codex CLI with npm on a best-effort basis; missing CLIs and registry failures must not block Agent Zero startup.
|
| 30 |
-
|
| 31 |
-
## Work Guidance
|
| 32 |
-
|
| 33 |
-
- Keep startup scripts explicit about framework runtime versus execution runtime.
|
| 34 |
-
- Coordinate tag, branch, and publishing changes with GitHub workflow automation.
|
| 35 |
-
|
| 36 |
-
## Verification
|
| 37 |
-
|
| 38 |
-
- Build `docker/run` when changing Dockerfile or install scripts.
|
| 39 |
-
- Smoke-test container startup after entrypoint, supervisor, port, or compose changes.
|
| 40 |
-
|
| 41 |
-
## Child DOX Index
|
| 42 |
-
|
| 43 |
-
No child DOX files.
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:17bbe98c21959fe36a5b7fe507d326495d066b9cd55358e6244b65c9b375ec6f
|
| 3 |
+
size 2574
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/run/Dockerfile
CHANGED
|
@@ -1,36 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
FROM agent0ai/agent-zero-base:latest
|
| 5 |
-
|
| 6 |
-
# Check if the argument is provided, else throw an error
|
| 7 |
-
ARG BRANCH
|
| 8 |
-
RUN if [ -z "$BRANCH" ]; then echo "ERROR: BRANCH is not set!" >&2; exit 1; fi
|
| 9 |
-
ENV BRANCH=$BRANCH
|
| 10 |
-
|
| 11 |
-
# Copy filesystem files to root
|
| 12 |
-
COPY ./fs/ /
|
| 13 |
-
|
| 14 |
-
# pre installation steps
|
| 15 |
-
RUN bash /ins/pre_install.sh $BRANCH
|
| 16 |
-
|
| 17 |
-
# install A0
|
| 18 |
-
RUN bash /ins/install_A0.sh $BRANCH
|
| 19 |
-
|
| 20 |
-
# install additional software
|
| 21 |
-
RUN bash /ins/install_additional.sh $BRANCH
|
| 22 |
-
|
| 23 |
-
# cleanup repo and install A0 without caching, this speeds up builds
|
| 24 |
-
ARG CACHE_DATE=none
|
| 25 |
-
RUN echo "cache buster $CACHE_DATE" && bash /ins/install_A02.sh $BRANCH
|
| 26 |
-
|
| 27 |
-
# post installation steps
|
| 28 |
-
RUN bash /ins/post_install.sh $BRANCH
|
| 29 |
-
|
| 30 |
-
# Expose ports
|
| 31 |
-
EXPOSE 22 80 9000-9009
|
| 32 |
-
|
| 33 |
-
RUN chmod +x /exe/initialize.sh /exe/run_A0.sh /exe/run_searxng.sh /exe/run_tunnel_api.sh /exe/trigger_self_update.sh
|
| 34 |
-
|
| 35 |
-
# initialize runtime and switch to supervisord
|
| 36 |
-
CMD ["/exe/initialize.sh", "$BRANCH"]
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:e3ae715c51dbf449efa619d79149742eb9bae802d722a75b8476b0a32ba3e8dd
|
| 3 |
+
size 1016
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/run/build.txt
CHANGED
|
@@ -1,42 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
# local development image based on local files with smart cache
|
| 6 |
-
docker build -f DockerfileLocal -t agent-zero-local --build-arg CACHE_DATE=$(date +%Y-%m-%d:%H:%M:%S) .
|
| 7 |
-
|
| 8 |
-
# local development image based on local files without cache
|
| 9 |
-
docker build -f DockerfileLocal -t agent-zero-local --no-cache .
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
# GIT BASED BUILDS
|
| 13 |
-
# Run these commands from the /docker/run directory
|
| 14 |
-
|
| 15 |
-
# local image based on development branch instead of local files
|
| 16 |
-
docker build -t agent-zero-development --build-arg BRANCH=development --build-arg CACHE_DATE=$(date +%Y-%m-%d:%H:%M:%S) .
|
| 17 |
-
|
| 18 |
-
# local image based on testing branch instead of local files
|
| 19 |
-
docker build -t agent-zero-testing --build-arg BRANCH=testing --build-arg CACHE_DATE=$(date +%Y-%m-%d:%H:%M:%S) .
|
| 20 |
-
|
| 21 |
-
# local image based on main branch instead of local files
|
| 22 |
-
docker build -t agent-zero-main --build-arg BRANCH=main --build-arg CACHE_DATE=$(date +%Y-%m-%d:%H:%M:%S) .
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
# DOCKERHUB PUSH
|
| 27 |
-
# Run these commands from the /docker/run directory
|
| 28 |
-
|
| 29 |
-
docker login
|
| 30 |
-
|
| 31 |
-
# development:
|
| 32 |
-
docker buildx build -t agent0ai/agent-zero:development --platform linux/amd64,linux/arm64 --push --build-arg BRANCH=development --build-arg CACHE_DATE=$(date +%Y-%m-%d:%H:%M:%S) .
|
| 33 |
-
|
| 34 |
-
# testing:
|
| 35 |
-
docker buildx build -t agent0ai/agent-zero:testing --platform linux/amd64,linux/arm64 --push --build-arg BRANCH=testing --build-arg CACHE_DATE=$(date +%Y-%m-%d:%H:%M:%S) .
|
| 36 |
-
|
| 37 |
-
# main
|
| 38 |
-
docker buildx build -t agent0ai/agent-zero:vx.x.x -t agent0ai/agent-zero:latest --platform linux/amd64,linux/arm64 --push --build-arg BRANCH=main --build-arg CACHE_DATE=$(date +%Y-%m-%d:%H:%M:%S) .
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
# plain output
|
| 42 |
-
--progress=plain
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:75dc51ca78f49f9860ab89813aedc3d37d7f7003863b465a6c02655729c25ae0
|
| 3 |
+
size 1671
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/run/docker-compose.yml
CHANGED
|
@@ -1,14 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
image: agent0ai/agent-zero:latest
|
| 5 |
-
volumes:
|
| 6 |
-
- ./agent-zero:/a0
|
| 7 |
-
ports:
|
| 8 |
-
- "50080:80"
|
| 9 |
-
ulimits:
|
| 10 |
-
nofile:
|
| 11 |
-
soft: 65535
|
| 12 |
-
hard: 65535
|
| 13 |
-
extra_hosts:
|
| 14 |
-
- "host.docker.internal:host-gateway"
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a7d6aec3bf1bc9e292ccf8f1dafe513bfb869d5093244cad97b8441375edeca6
|
| 3 |
+
size 289
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/run/fs/etc/nginx/nginx.conf
CHANGED
|
@@ -1,31 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
events {
|
| 6 |
-
use epoll;
|
| 7 |
-
worker_connections 128;
|
| 8 |
-
}
|
| 9 |
-
|
| 10 |
-
error_log /var/log/nginx/error.log info;
|
| 11 |
-
|
| 12 |
-
http {
|
| 13 |
-
server_tokens off;
|
| 14 |
-
include mime.types;
|
| 15 |
-
charset utf-8;
|
| 16 |
-
|
| 17 |
-
access_log /var/log/nginx/access.log combined;
|
| 18 |
-
|
| 19 |
-
server {
|
| 20 |
-
server_name 127.0.0.1:31735;
|
| 21 |
-
listen 127.0.0.1:31735;
|
| 22 |
-
|
| 23 |
-
error_page 500 502 503 504 /50x.html;
|
| 24 |
-
|
| 25 |
-
location / {
|
| 26 |
-
root /;
|
| 27 |
-
}
|
| 28 |
-
|
| 29 |
-
}
|
| 30 |
-
|
| 31 |
-
}
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:f9e58e00c90a7bbe25c26087c7c52ff49dcdbedce331cc4ac24f980104743337
|
| 3 |
+
size 545
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/run/fs/etc/searxng/limiter.toml
CHANGED
|
@@ -1,33 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
# The prefix defines the number of leading bits in an address that are compared
|
| 6 |
-
# to determine whether or not an address is part of a (client) network.
|
| 7 |
-
ipv4_prefix = 32
|
| 8 |
-
ipv6_prefix = 48
|
| 9 |
-
|
| 10 |
-
[botdetection.ip_limit]
|
| 11 |
-
# To get unlimited access in a local network, by default link-local addresses
|
| 12 |
-
# (networks) are not monitored by the ip_limit
|
| 13 |
-
filter_link_local = false
|
| 14 |
-
|
| 15 |
-
# Activate link_token method in the ip_limit method
|
| 16 |
-
link_token = false
|
| 17 |
-
|
| 18 |
-
[botdetection.ip_lists]
|
| 19 |
-
# In the limiter, the ip_lists method has priority over all other methods.
|
| 20 |
-
# If an IP is in the pass_ip list, it has unrestricted access and is not
|
| 21 |
-
# checked if, for example, the "user agent" suggests a bot (e.g., curl).
|
| 22 |
-
block_ip = [
|
| 23 |
-
# '93.184.216.34', # Example IPv4 address
|
| 24 |
-
# '257.1.1.1', # Invalid IP --> will be ignored, logged in ERROR class
|
| 25 |
-
]
|
| 26 |
-
pass_ip = [
|
| 27 |
-
# '192.168.0.0/16', # IPv4 private network
|
| 28 |
-
# 'fe80::/10', # IPv6 link-local; overrides botdetection.ip_limit.filter_link_local
|
| 29 |
-
]
|
| 30 |
-
|
| 31 |
-
# Activate passlist of (hardcoded) IPs from the SearXNG organization,
|
| 32 |
-
# e.g., `check.searx.space`.
|
| 33 |
-
pass_searxng_org = true
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:0823d3680c926766580465b06b07ffb2198c9e4e53ca56a2ca3a45fc4a5811be
|
| 3 |
+
size 1199
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/run/fs/etc/searxng/settings.yml
CHANGED
|
@@ -1,98 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
engines:
|
| 5 |
-
remove:
|
| 6 |
-
- radio browser
|
| 7 |
-
- wikidata
|
| 8 |
-
# TODO enable radio_browser when it works again
|
| 9 |
-
# currently it crashes on x86 on gethostbyaddr
|
| 10 |
-
|
| 11 |
-
general:
|
| 12 |
-
debug: false
|
| 13 |
-
instance_name: "SearXNG"
|
| 14 |
-
|
| 15 |
-
search:
|
| 16 |
-
safe_search: 0
|
| 17 |
-
# autocomplete: 'duckduckgo'
|
| 18 |
-
formats:
|
| 19 |
-
- json
|
| 20 |
-
# - html
|
| 21 |
-
|
| 22 |
-
server:
|
| 23 |
-
# Is overwritten by ${SEARXNG_SECRET}
|
| 24 |
-
secret_key: "dummy"
|
| 25 |
-
port: 55510
|
| 26 |
-
limiter: false
|
| 27 |
-
image_proxy: false
|
| 28 |
-
# public URL of the instance, to ensure correct inbound links. Is overwritten
|
| 29 |
-
# by ${SEARXNG_URL}.
|
| 30 |
-
# base_url: http://example.com/location
|
| 31 |
-
|
| 32 |
-
# redis:
|
| 33 |
-
# # URL to connect redis database. Is overwritten by ${SEARXNG_REDIS_URL}.
|
| 34 |
-
# url: unix:///usr/local/searxng-redis/run/redis.sock?db=0
|
| 35 |
-
|
| 36 |
-
ui:
|
| 37 |
-
static_use_hash: true
|
| 38 |
-
|
| 39 |
-
# preferences:
|
| 40 |
-
# lock:
|
| 41 |
-
# - autocomplete
|
| 42 |
-
# - method
|
| 43 |
-
|
| 44 |
-
enabled_plugins:
|
| 45 |
-
- 'Hash plugin'
|
| 46 |
-
- 'Self Informations'
|
| 47 |
-
- 'Tracker URL remover'
|
| 48 |
-
# - 'Ahmia blacklist'
|
| 49 |
-
# - 'Hostnames plugin' # see 'hostnames' configuration below
|
| 50 |
-
# - 'Open Access DOI rewrite'
|
| 51 |
-
|
| 52 |
-
# plugins:
|
| 53 |
-
# - only_show_green_results
|
| 54 |
-
|
| 55 |
-
# hostnames:
|
| 56 |
-
# replace:
|
| 57 |
-
# '(.*\.)?youtube\.com$': 'invidious.example.com'
|
| 58 |
-
# '(.*\.)?youtu\.be$': 'invidious.example.com'
|
| 59 |
-
# remove:
|
| 60 |
-
# - '(.*\.)?facebook.com$'
|
| 61 |
-
# low_priority:
|
| 62 |
-
# - '(.*\.)?google\.com$'
|
| 63 |
-
# high_priority:
|
| 64 |
-
# - '(.*\.)?wikipedia.org$'
|
| 65 |
-
|
| 66 |
-
engines:
|
| 67 |
-
- name: radio browser
|
| 68 |
-
engine: radio_browser
|
| 69 |
-
disabled: true
|
| 70 |
-
inactive: true
|
| 71 |
-
|
| 72 |
-
- name: ahmia
|
| 73 |
-
disabled: true
|
| 74 |
-
inactive: true
|
| 75 |
-
|
| 76 |
-
- name: torch
|
| 77 |
-
disabled: true
|
| 78 |
-
inactive: true
|
| 79 |
-
# TODO enable radio_browser when it works again
|
| 80 |
-
# currently it crashes on x86 on gethostbyaddr
|
| 81 |
-
|
| 82 |
-
# - name: fdroid
|
| 83 |
-
# disabled: false
|
| 84 |
-
#
|
| 85 |
-
# - name: apk mirror
|
| 86 |
-
# disabled: false
|
| 87 |
-
#
|
| 88 |
-
# - name: mediathekviewweb
|
| 89 |
-
# categories: TV
|
| 90 |
-
# disabled: false
|
| 91 |
-
#
|
| 92 |
-
# - name: invidious
|
| 93 |
-
# disabled: false
|
| 94 |
-
# base_url:
|
| 95 |
-
# - https://invidious.snopyta.org
|
| 96 |
-
# - https://invidious.tiekoetter.com
|
| 97 |
-
# - https://invidio.xamh.de
|
| 98 |
-
# - https://inv.riverside.rocks
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:b06e7385e5a7a2e2daad711852551cd82c3c2d7923c1cd5d55ddd085e7a04fad
|
| 3 |
+
size 2055
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/run/fs/etc/supervisor/conf.d/supervisord.conf
CHANGED
|
@@ -1,95 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
logfile=/dev/stdout
|
| 5 |
-
logfile_maxbytes=0
|
| 6 |
-
pidfile=/var/run/supervisord.pid
|
| 7 |
-
exitcodes=0,2
|
| 8 |
-
directory=/
|
| 9 |
-
|
| 10 |
-
[unix_http_server]
|
| 11 |
-
file=/var/run/supervisor.sock
|
| 12 |
-
chmod=0777
|
| 13 |
-
|
| 14 |
-
[rpcinterface:supervisor]
|
| 15 |
-
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
|
| 16 |
-
|
| 17 |
-
[supervisorctl]
|
| 18 |
-
serverurl=unix:///var/run/supervisor.sock
|
| 19 |
-
|
| 20 |
-
[program:run_sshd]
|
| 21 |
-
command=/usr/sbin/sshd -D
|
| 22 |
-
environment=
|
| 23 |
-
stopwaitsecs=1
|
| 24 |
-
stdout_logfile=/dev/stdout
|
| 25 |
-
stdout_logfile_maxbytes=0
|
| 26 |
-
stderr_logfile=/dev/stderr
|
| 27 |
-
stderr_logfile_maxbytes=0
|
| 28 |
-
autorestart=true
|
| 29 |
-
startretries=3
|
| 30 |
-
stopasgroup=true
|
| 31 |
-
killasgroup=true
|
| 32 |
-
|
| 33 |
-
[program:run_cron]
|
| 34 |
-
command=/usr/sbin/cron -f
|
| 35 |
-
environment=
|
| 36 |
-
stopwaitsecs=1
|
| 37 |
-
stdout_logfile=/dev/stdout
|
| 38 |
-
stdout_logfile_maxbytes=0
|
| 39 |
-
stderr_logfile=/dev/stderr
|
| 40 |
-
stderr_logfile_maxbytes=0
|
| 41 |
-
autorestart=true
|
| 42 |
-
startretries=3
|
| 43 |
-
stopasgroup=true
|
| 44 |
-
killasgroup=true
|
| 45 |
-
|
| 46 |
-
[program:run_searxng]
|
| 47 |
-
command=/exe/run_searxng.sh
|
| 48 |
-
environment=SEARXNG_SETTINGS_PATH=/etc/searxng/settings.yml
|
| 49 |
-
user=searxng
|
| 50 |
-
directory=/usr/local/searxng/searxng-src
|
| 51 |
-
stopwaitsecs=1
|
| 52 |
-
stdout_logfile=/dev/stdout
|
| 53 |
-
stdout_logfile_maxbytes=0
|
| 54 |
-
stderr_logfile=/dev/stderr
|
| 55 |
-
stderr_logfile_maxbytes=0
|
| 56 |
-
autorestart=true
|
| 57 |
-
startretries=3
|
| 58 |
-
stopasgroup=true
|
| 59 |
-
killasgroup=true
|
| 60 |
-
|
| 61 |
-
[program:run_ui]
|
| 62 |
-
command=/exe/run_A0.sh
|
| 63 |
-
environment=
|
| 64 |
-
user=root
|
| 65 |
-
stopwaitsecs=60
|
| 66 |
-
stdout_logfile=/dev/stdout
|
| 67 |
-
stdout_logfile_maxbytes=0
|
| 68 |
-
stderr_logfile=/dev/stderr
|
| 69 |
-
stderr_logfile_maxbytes=0
|
| 70 |
-
autorestart=true
|
| 71 |
-
startretries=3
|
| 72 |
-
stopasgroup=true
|
| 73 |
-
killasgroup=true
|
| 74 |
-
|
| 75 |
-
[program:run_tunnel_api]
|
| 76 |
-
command=/exe/run_tunnel_api.sh
|
| 77 |
-
environment=
|
| 78 |
-
user=root
|
| 79 |
-
stopwaitsecs=60
|
| 80 |
-
stdout_logfile=/dev/stdout
|
| 81 |
-
stdout_logfile_maxbytes=0
|
| 82 |
-
stderr_logfile=/dev/stderr
|
| 83 |
-
stderr_logfile_maxbytes=0
|
| 84 |
-
autorestart=true
|
| 85 |
-
startretries=3
|
| 86 |
-
stopasgroup=true
|
| 87 |
-
killasgroup=true
|
| 88 |
-
|
| 89 |
-
[eventlistener:the_listener]
|
| 90 |
-
command=python3 /exe/supervisor_event_listener.py
|
| 91 |
-
events=PROCESS_STATE_FATAL
|
| 92 |
-
stdout_logfile=/dev/stdout
|
| 93 |
-
stdout_logfile_maxbytes=0
|
| 94 |
-
stderr_logfile=/dev/stderr
|
| 95 |
-
stderr_logfile_maxbytes=0
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:056f6fddc74b8dae60f17e99049605871faf6b1722b199447bd159d156663dd3
|
| 3 |
+
size 1941
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/run/fs/exe/huggingface-entrypoint.sh
CHANGED
|
@@ -1,42 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
# Hugging Face provides the public HTTPS edge; never start an outbound tunnel.
|
| 5 |
-
if [ "${A0_CLOUDFLARE_DISABLED:-true}" != "true" ]; then
|
| 6 |
-
echo "A0_CLOUDFLARE_DISABLED must remain true on Hugging Face Spaces." >&2
|
| 7 |
-
exit 1
|
| 8 |
-
fi
|
| 9 |
-
|
| 10 |
-
mkdir -p /a0/usr
|
| 11 |
-
|
| 12 |
-
# Settings normalization fills all other defaults. This deployment default makes
|
| 13 |
-
# the authenticated A2A endpoint available immediately after the Space starts.
|
| 14 |
-
python3 - <<'PY'
|
| 15 |
-
import json
|
| 16 |
-
import os
|
| 17 |
-
from pathlib import Path
|
| 18 |
-
|
| 19 |
-
settings_path = Path("/a0/usr/settings.json")
|
| 20 |
-
try:
|
| 21 |
-
settings = json.loads(settings_path.read_text(encoding="utf-8"))
|
| 22 |
-
except (FileNotFoundError, json.JSONDecodeError):
|
| 23 |
-
settings = {}
|
| 24 |
-
|
| 25 |
-
settings["a2a_server_enabled"] = True
|
| 26 |
-
if api_key := os.environ.get("SPYNEL_AGENT_ZERO_API_KEY", "").strip():
|
| 27 |
-
# Use one secret for the loopback client and the existing API-key verifier.
|
| 28 |
-
# It is persisted in the private runtime settings file and never printed.
|
| 29 |
-
settings["mcp_server_token"] = api_key
|
| 30 |
-
settings_path.write_text(json.dumps(settings, indent=2) + "\n", encoding="utf-8")
|
| 31 |
-
PY
|
| 32 |
-
|
| 33 |
-
echo "Space URL: ${A0_PUBLIC_URL:-https://leon4gr45-agent.hf.space}"
|
| 34 |
-
echo "A2A enabled at /a2a; authenticated incoming API enabled at /api_message."
|
| 35 |
-
echo "Starting Agent Zero as uid=$(id -u) on ${WEB_UI_HOST:-0.0.0.0}:${WEB_UI_PORT:-7860}."
|
| 36 |
-
|
| 37 |
-
# The general Docker initializer is intentionally not used in a Space: it starts
|
| 38 |
-
# privileged SSH/cron/supervisor services and inherited images may include
|
| 39 |
-
# password initialization. Space dependencies and model data are installed at
|
| 40 |
-
# image-build time, so runtime package installation is disabled by the image.
|
| 41 |
-
cd /a0
|
| 42 |
-
exec /opt/venv-a0/bin/python run_ui.py
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:f23cde5677afd1c14ea00d92d8c827198d6b18adb3b70f967875d2577396a126
|
| 3 |
+
size 1689
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/run/fs/exe/initialize.sh
CHANGED
|
@@ -1,63 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
# branch from parameter
|
| 6 |
-
if [ -z "$1" ]; then
|
| 7 |
-
echo "Error: Branch parameter is empty. Please provide a valid branch name."
|
| 8 |
-
exit 1
|
| 9 |
-
fi
|
| 10 |
-
BRANCH="$1"
|
| 11 |
-
|
| 12 |
-
raise_open_file_limit() {
|
| 13 |
-
local requested="${A0_NOFILE_LIMIT:-65535}"
|
| 14 |
-
local soft
|
| 15 |
-
local hard
|
| 16 |
-
local target
|
| 17 |
-
|
| 18 |
-
if ! [[ "$requested" =~ ^[0-9]+$ ]] || [ "$requested" -lt 1 ]; then
|
| 19 |
-
echo "Warning: invalid A0_NOFILE_LIMIT='$requested'; keeping open file limit at $(ulimit -S -n)." >&2
|
| 20 |
-
return
|
| 21 |
-
fi
|
| 22 |
-
|
| 23 |
-
soft="$(ulimit -S -n)"
|
| 24 |
-
hard="$(ulimit -H -n)"
|
| 25 |
-
|
| 26 |
-
if [ "$soft" = "unlimited" ]; then
|
| 27 |
-
echo "Open file limit is already unlimited."
|
| 28 |
-
return
|
| 29 |
-
fi
|
| 30 |
-
|
| 31 |
-
target="$requested"
|
| 32 |
-
if [ "$hard" != "unlimited" ] && [ "$target" -gt "$hard" ]; then
|
| 33 |
-
target="$hard"
|
| 34 |
-
fi
|
| 35 |
-
|
| 36 |
-
if [ "$target" -gt "$soft" ]; then
|
| 37 |
-
if ulimit -S -n "$target"; then
|
| 38 |
-
echo "Raised open file soft limit from $soft to $(ulimit -S -n) (hard: $hard)."
|
| 39 |
-
else
|
| 40 |
-
echo "Warning: failed to raise open file soft limit from $soft to $target (hard: $hard)." >&2
|
| 41 |
-
fi
|
| 42 |
-
else
|
| 43 |
-
echo "Open file soft limit is $soft (target: $requested, hard: $hard)."
|
| 44 |
-
fi
|
| 45 |
-
}
|
| 46 |
-
|
| 47 |
-
raise_open_file_limit
|
| 48 |
-
|
| 49 |
-
# Copy all contents from persistent /per to root directory (/) without overwriting
|
| 50 |
-
cp -r --no-preserve=ownership,mode /per/* /
|
| 51 |
-
|
| 52 |
-
# Ensure upload storage exists before API and connector callers can reference it.
|
| 53 |
-
mkdir -p /a0/usr/uploads
|
| 54 |
-
|
| 55 |
-
# allow execution of /root/.bashrc and /root/.profile
|
| 56 |
-
chmod 444 /root/.bashrc
|
| 57 |
-
chmod 444 /root/.profile
|
| 58 |
-
|
| 59 |
-
# update package list to save time later
|
| 60 |
-
apt-get update > /dev/null 2>&1 &
|
| 61 |
-
|
| 62 |
-
# let supervisord handle the services
|
| 63 |
-
exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:1fc7c1d54b3d7e6174087f9b63e4b73fc87fd836dc159e544349d73601441d5b
|
| 3 |
+
size 1774
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/run/fs/exe/node_eval.js
CHANGED
|
@@ -1,62 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
const path = require('path');
|
| 5 |
-
const Module = require('module');
|
| 6 |
-
|
| 7 |
-
// Enhance `require` to search CWD first, then globally
|
| 8 |
-
function customRequire(moduleName) {
|
| 9 |
-
try {
|
| 10 |
-
// Try resolving from CWD's node_modules using Node's require.resolve
|
| 11 |
-
const cwdPath = require.resolve(moduleName, { paths: [path.join(process.cwd(), 'node_modules')] });
|
| 12 |
-
// console.log("resolved path:", cwdPath);
|
| 13 |
-
return require(cwdPath);
|
| 14 |
-
} catch (cwdErr) {
|
| 15 |
-
try {
|
| 16 |
-
// Try resolving as a global module
|
| 17 |
-
return require(moduleName);
|
| 18 |
-
} catch (globalErr) {
|
| 19 |
-
console.error(`Cannot find module: ${moduleName}`);
|
| 20 |
-
throw globalErr;
|
| 21 |
-
}
|
| 22 |
-
}
|
| 23 |
-
}
|
| 24 |
-
|
| 25 |
-
// Create the VM context
|
| 26 |
-
const context = vm.createContext({
|
| 27 |
-
...global,
|
| 28 |
-
require: customRequire, // Use the custom require
|
| 29 |
-
__filename: path.join(process.cwd(), 'eval.js'),
|
| 30 |
-
__dirname: process.cwd(),
|
| 31 |
-
module: { exports: {} },
|
| 32 |
-
exports: module.exports,
|
| 33 |
-
console: console,
|
| 34 |
-
process: process,
|
| 35 |
-
Buffer: Buffer,
|
| 36 |
-
setTimeout: setTimeout,
|
| 37 |
-
setInterval: setInterval,
|
| 38 |
-
setImmediate: setImmediate,
|
| 39 |
-
clearTimeout: clearTimeout,
|
| 40 |
-
clearInterval: clearInterval,
|
| 41 |
-
clearImmediate: clearImmediate,
|
| 42 |
-
});
|
| 43 |
-
|
| 44 |
-
// Retrieve the code from the command-line argument
|
| 45 |
-
const code = process.argv[2];
|
| 46 |
-
|
| 47 |
-
const wrappedCode = `
|
| 48 |
-
(async function() {
|
| 49 |
-
try {
|
| 50 |
-
const __result__ = await eval(${JSON.stringify(code)});
|
| 51 |
-
if (__result__ !== undefined) console.log('Out[1]:', __result__);
|
| 52 |
-
} catch (error) {
|
| 53 |
-
console.error(error);
|
| 54 |
-
}
|
| 55 |
-
})();
|
| 56 |
-
`;
|
| 57 |
-
|
| 58 |
-
vm.runInContext(wrappedCode, context, {
|
| 59 |
-
filename: 'eval.js',
|
| 60 |
-
lineOffset: -2,
|
| 61 |
-
columnOffset: 0,
|
| 62 |
-
}).catch(console.error);
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:b6ddc75ed432d14246ac6c5682634d7467ec632368f163530cbcc46b7b8c3499
|
| 3 |
+
size 1659
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/run/fs/exe/run_A0.sh
CHANGED
|
@@ -1,7 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
. "/ins/copy_A0.sh" "$@"
|
| 5 |
-
|
| 6 |
-
echo "Starting A0 bootstrap manager..."
|
| 7 |
-
exec python /exe/self_update_manager.py docker-run-ui
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:bbc42594385f5c3187721ce83b2c69886e707bcfd03acee7fc00f0c6763f5ff0
|
| 3 |
+
size 161
|
|
|
|
|
|
|
|
|
|
|
|
docker/run/fs/exe/run_searxng.sh
CHANGED
|
@@ -1,10 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
cd /usr/local/searxng/searxng-src
|
| 5 |
-
export SEARXNG_SETTINGS_PATH="/etc/searxng/settings.yml"
|
| 6 |
-
|
| 7 |
-
# activate venv
|
| 8 |
-
source "/usr/local/searxng/searx-pyenv/bin/activate"
|
| 9 |
-
|
| 10 |
-
exec python /usr/local/searxng/searxng-src/searx/webapp.py
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:aa30cf09ba3759f0ec369bb7559347d8478e412cd34f46e1be8ab5bcf4ba561f
|
| 3 |
+
size 249
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/run/fs/exe/run_tunnel_api.sh
CHANGED
|
@@ -1,18 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
echo "Starting tunnel API..."
|
| 5 |
-
|
| 6 |
-
sleep 1
|
| 7 |
-
while [ ! -f /a0/run_tunnel.py ]; do
|
| 8 |
-
echo "Waiting for /a0/run_tunnel.py to be available..."
|
| 9 |
-
sleep 1
|
| 10 |
-
done
|
| 11 |
-
|
| 12 |
-
. "/ins/setup_venv.sh" "$@"
|
| 13 |
-
|
| 14 |
-
exec python /a0/run_tunnel.py \
|
| 15 |
-
--dockerized=true \
|
| 16 |
-
--port=80 \
|
| 17 |
-
--tunnel_api_port=55520 \
|
| 18 |
-
--host="0.0.0.0"
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:1fda7945842d129c82a418731ea0f9f04fc8c196caf19201675375605699a0d3
|
| 3 |
+
size 353
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/run/fs/exe/self_update_manager.py
CHANGED
|
@@ -1,1507 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
import argparse
|
| 5 |
-
import importlib.util
|
| 6 |
-
import json
|
| 7 |
-
import os
|
| 8 |
-
import re
|
| 9 |
-
import shutil
|
| 10 |
-
import signal
|
| 11 |
-
import stat
|
| 12 |
-
import subprocess
|
| 13 |
-
import sys
|
| 14 |
-
import tempfile
|
| 15 |
-
import time
|
| 16 |
-
import urllib.error
|
| 17 |
-
import urllib.request
|
| 18 |
-
import zipfile
|
| 19 |
-
from datetime import UTC, datetime
|
| 20 |
-
from pathlib import Path
|
| 21 |
-
from typing import Any
|
| 22 |
-
|
| 23 |
-
import yaml
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
OFFICIAL_REPO_URL = os.environ.get(
|
| 27 |
-
"A0_SELF_UPDATE_REMOTE_URL",
|
| 28 |
-
"https://github.com/agent0ai/agent-zero.git",
|
| 29 |
-
)
|
| 30 |
-
REPO_DIR = Path("/a0")
|
| 31 |
-
TRIGGER_FILE = Path("/exe/a0-self-update.yaml")
|
| 32 |
-
STATUS_FILE = Path("/exe/a0-self-update-status.yaml")
|
| 33 |
-
LOG_FILE = Path("/exe/a0-self-update.log")
|
| 34 |
-
DEFAULT_HEALTH_URL = os.environ.get(
|
| 35 |
-
"A0_SELF_UPDATE_HEALTH_URL",
|
| 36 |
-
"http://127.0.0.1:80/api/health",
|
| 37 |
-
)
|
| 38 |
-
DEFAULT_HEALTH_TIMEOUT_SECONDS = int(
|
| 39 |
-
os.environ.get("A0_SELF_UPDATE_HEALTH_TIMEOUT_SECONDS", "180")
|
| 40 |
-
)
|
| 41 |
-
DEFAULT_HEALTH_POLL_INTERVAL_SECONDS = float(
|
| 42 |
-
os.environ.get("A0_SELF_UPDATE_HEALTH_POLL_INTERVAL_SECONDS", "2")
|
| 43 |
-
)
|
| 44 |
-
DEFAULT_BACKUP_DIR = "/root/update-backups"
|
| 45 |
-
DEFAULT_BACKUP_CONFLICT_POLICY = "rename"
|
| 46 |
-
BACKUP_CONFLICT_POLICIES = {"rename", "overwrite", "fail"}
|
| 47 |
-
MIN_SELECTOR_VERSION = (1, 0)
|
| 48 |
-
LATEST_SELECTOR_TAG = "latest"
|
| 49 |
-
DESKTOP_PROFILE_STATE_RELATIVE_DIRS = (
|
| 50 |
-
Path("usr/plugins/_desktop/profiles"),
|
| 51 |
-
Path("usr/_desktop/profiles"),
|
| 52 |
-
Path("tmp/_office/desktop/profiles"),
|
| 53 |
-
)
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
def now_iso() -> str:
|
| 57 |
-
return datetime.now(UTC).isoformat().replace("+00:00", "Z")
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
class AttemptLogger:
|
| 61 |
-
def __init__(self, path: Path):
|
| 62 |
-
self.path = path
|
| 63 |
-
|
| 64 |
-
def reset(self) -> None:
|
| 65 |
-
self.path.parent.mkdir(parents=True, exist_ok=True)
|
| 66 |
-
self.path.write_text("", encoding="utf-8")
|
| 67 |
-
|
| 68 |
-
def log(self, message: str = "") -> None:
|
| 69 |
-
line = f"[{now_iso()}] {message}".rstrip()
|
| 70 |
-
print(f"[a0-self-update] {message}", flush=True)
|
| 71 |
-
with self.path.open("a", encoding="utf-8") as handle:
|
| 72 |
-
handle.write(line + "\n")
|
| 73 |
-
|
| 74 |
-
def log_block(self, title: str, content: str) -> None:
|
| 75 |
-
cleaned = content.rstrip()
|
| 76 |
-
self.log(f"{title}:")
|
| 77 |
-
if not cleaned:
|
| 78 |
-
self.log("(empty)")
|
| 79 |
-
return
|
| 80 |
-
with self.path.open("a", encoding="utf-8") as handle:
|
| 81 |
-
for line in cleaned.splitlines():
|
| 82 |
-
handle.write(f" {line}\n")
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
class NullLogger:
|
| 86 |
-
def reset(self) -> None:
|
| 87 |
-
return
|
| 88 |
-
|
| 89 |
-
def log(self, message: str = "") -> None:
|
| 90 |
-
return
|
| 91 |
-
|
| 92 |
-
def log_block(self, title: str, content: str) -> None:
|
| 93 |
-
return
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
def load_yaml(path: Path) -> dict[str, Any] | None:
|
| 97 |
-
if not path.exists():
|
| 98 |
-
return None
|
| 99 |
-
loaded = yaml.safe_load(path.read_text(encoding="utf-8"))
|
| 100 |
-
return loaded if isinstance(loaded, dict) else None
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
def write_yaml(path: Path, payload: dict[str, Any]) -> None:
|
| 104 |
-
path.parent.mkdir(parents=True, exist_ok=True)
|
| 105 |
-
path.write_text(
|
| 106 |
-
yaml.safe_dump(payload, allow_unicode=True, sort_keys=False),
|
| 107 |
-
encoding="utf-8",
|
| 108 |
-
)
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
def write_status(payload: dict[str, Any]) -> None:
|
| 112 |
-
write_yaml(STATUS_FILE, payload)
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
def git_output(repo_dir: Path, *args: str) -> str:
|
| 116 |
-
completed = subprocess.run(
|
| 117 |
-
["git", "-C", str(repo_dir), *args],
|
| 118 |
-
check=True,
|
| 119 |
-
text=True,
|
| 120 |
-
capture_output=True,
|
| 121 |
-
env={**os.environ, "GIT_TERMINAL_PROMPT": "0"},
|
| 122 |
-
)
|
| 123 |
-
return completed.stdout.strip()
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
def normalize_describe_to_version(describe: str) -> str:
|
| 127 |
-
match = re.fullmatch(r"(.+)-\d+-g[0-9a-f]+", describe)
|
| 128 |
-
if match:
|
| 129 |
-
return match.group(1)
|
| 130 |
-
return describe
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
def split_describe_version(describe: str) -> tuple[str, int]:
|
| 134 |
-
normalized = describe.strip()
|
| 135 |
-
match = re.fullmatch(r"(.+)-(\d+)-g[0-9a-f]+", normalized)
|
| 136 |
-
if not match:
|
| 137 |
-
return normalized, 0
|
| 138 |
-
return match.group(1), int(match.group(2))
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
def parse_selector_version(tag: str) -> tuple[int, int] | None:
|
| 142 |
-
match = re.fullmatch(r"v(\d+)\.(\d+)", tag.strip())
|
| 143 |
-
if not match:
|
| 144 |
-
return None
|
| 145 |
-
return int(match.group(1)), int(match.group(2))
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
def is_valid_selector_tag(tag: str) -> bool:
|
| 149 |
-
return parse_selector_version(tag) is not None
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
def is_supported_selector_tag(tag: str) -> bool:
|
| 153 |
-
parsed = parse_selector_version(tag)
|
| 154 |
-
return parsed is not None and parsed >= MIN_SELECTOR_VERSION
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
def sort_selector_supported_tags(tags: list[str]) -> list[str]:
|
| 158 |
-
return sorted(
|
| 159 |
-
tags,
|
| 160 |
-
key=lambda tag: parse_selector_version(tag) or (-1, -1),
|
| 161 |
-
reverse=True,
|
| 162 |
-
)
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
def parse_major_version(tag: str) -> int | None:
|
| 166 |
-
match = re.fullmatch(r"v(\d+)(?:[.-].*)?", tag.strip())
|
| 167 |
-
if not match:
|
| 168 |
-
return None
|
| 169 |
-
return int(match.group(1))
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
def is_latest_selector_tag(tag: str) -> bool:
|
| 173 |
-
return tag.strip().lower() == LATEST_SELECTOR_TAG
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
def get_tag_commit_ref(tag: str) -> str:
|
| 177 |
-
return f"refs/tags/{tag}^{{commit}}"
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
def build_default_backup_name() -> str:
|
| 181 |
-
timestamp = datetime.now(UTC).strftime("%Y%m%d-%H%M%S")
|
| 182 |
-
return f"usr-{timestamp}.zip"
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
def normalize_requested_tag(tag: str) -> str:
|
| 186 |
-
normalized = (tag or "").strip()
|
| 187 |
-
if not normalized:
|
| 188 |
-
return LATEST_SELECTOR_TAG
|
| 189 |
-
if is_latest_selector_tag(normalized):
|
| 190 |
-
return LATEST_SELECTOR_TAG
|
| 191 |
-
if not is_valid_selector_tag(normalized):
|
| 192 |
-
raise ValueError("Release tag must use the format vX.Y.")
|
| 193 |
-
if not is_supported_selector_tag(normalized):
|
| 194 |
-
raise ValueError("Release tag must be v1.0 or newer.")
|
| 195 |
-
return normalized
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
def normalize_backup_conflict_policy(conflict_policy: str) -> str:
|
| 199 |
-
normalized = (conflict_policy or DEFAULT_BACKUP_CONFLICT_POLICY).strip().lower()
|
| 200 |
-
if normalized not in BACKUP_CONFLICT_POLICIES:
|
| 201 |
-
raise ValueError("Backup conflict policy must be one of: rename, overwrite, fail.")
|
| 202 |
-
return normalized
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
def get_latest_same_major_tag(
|
| 206 |
-
repo_dir: Path,
|
| 207 |
-
*,
|
| 208 |
-
branch_ref: str,
|
| 209 |
-
current_version: str,
|
| 210 |
-
) -> str:
|
| 211 |
-
current_major = parse_major_version(current_version)
|
| 212 |
-
if current_major is None:
|
| 213 |
-
raise RuntimeError(
|
| 214 |
-
f"Could not determine the installed major version from {current_version}. "
|
| 215 |
-
"Use an explicit tag instead of latest."
|
| 216 |
-
)
|
| 217 |
-
|
| 218 |
-
output = git_output(repo_dir, "tag", "--merged", branch_ref)
|
| 219 |
-
same_major_tags = [
|
| 220 |
-
tag
|
| 221 |
-
for tag in (line.strip() for line in output.splitlines())
|
| 222 |
-
if is_supported_selector_tag(tag) and parse_major_version(tag) == current_major
|
| 223 |
-
]
|
| 224 |
-
if not same_major_tags:
|
| 225 |
-
raise RuntimeError(
|
| 226 |
-
f"No v{current_major}.x release tags are reachable from branch "
|
| 227 |
-
f"{branch_ref.rsplit('/', 1)[-1]}."
|
| 228 |
-
)
|
| 229 |
-
return sort_selector_supported_tags(same_major_tags)[0]
|
| 230 |
-
|
| 231 |
-
|
| 232 |
-
def ensure_latest_target_matches_current_major(
|
| 233 |
-
*,
|
| 234 |
-
branch: str,
|
| 235 |
-
current_version: str,
|
| 236 |
-
target_version: str,
|
| 237 |
-
) -> None:
|
| 238 |
-
current_major = parse_major_version(current_version)
|
| 239 |
-
if current_major is None:
|
| 240 |
-
raise RuntimeError(
|
| 241 |
-
f"Could not determine the installed major version from {current_version}. "
|
| 242 |
-
"Use an explicit tag instead of latest."
|
| 243 |
-
)
|
| 244 |
-
|
| 245 |
-
target_major = parse_major_version(target_version)
|
| 246 |
-
if target_major is None or not is_supported_selector_tag(target_version):
|
| 247 |
-
raise RuntimeError(
|
| 248 |
-
f"Could not resolve latest on branch {branch} to a supported vX.Y release. "
|
| 249 |
-
"Use an explicit tag instead."
|
| 250 |
-
)
|
| 251 |
-
|
| 252 |
-
if target_major != current_major:
|
| 253 |
-
raise RuntimeError(
|
| 254 |
-
f"Latest on branch {branch} resolves to {target_version}, but the installed "
|
| 255 |
-
f"version is {current_version}. Use an explicit tag to change major versions."
|
| 256 |
-
)
|
| 257 |
-
|
| 258 |
-
|
| 259 |
-
def get_repo_version_info(repo_dir: Path) -> dict[str, str]:
|
| 260 |
-
describe = git_output(repo_dir, "describe", "--tags", "--always")
|
| 261 |
-
commit = git_output(repo_dir, "rev-parse", "HEAD")
|
| 262 |
-
branch = git_optional_output(repo_dir, "branch", "--show-current")
|
| 263 |
-
return {
|
| 264 |
-
"branch": branch,
|
| 265 |
-
"describe": describe,
|
| 266 |
-
"short_tag": normalize_describe_to_version(describe),
|
| 267 |
-
"commit": commit,
|
| 268 |
-
"short_commit": commit[:7],
|
| 269 |
-
}
|
| 270 |
-
|
| 271 |
-
|
| 272 |
-
def git_optional_output(repo_dir: Path, *args: str) -> str:
|
| 273 |
-
completed = subprocess.run(
|
| 274 |
-
["git", "-C", str(repo_dir), *args],
|
| 275 |
-
check=False,
|
| 276 |
-
text=True,
|
| 277 |
-
capture_output=True,
|
| 278 |
-
env={**os.environ, "GIT_TERMINAL_PROMPT": "0"},
|
| 279 |
-
)
|
| 280 |
-
if completed.returncode != 0:
|
| 281 |
-
return ""
|
| 282 |
-
return completed.stdout.strip()
|
| 283 |
-
|
| 284 |
-
|
| 285 |
-
def remove_path(path: Path) -> None:
|
| 286 |
-
if path.is_symlink() or path.is_file():
|
| 287 |
-
path.unlink(missing_ok=True)
|
| 288 |
-
return
|
| 289 |
-
if path.exists():
|
| 290 |
-
shutil.rmtree(path)
|
| 291 |
-
|
| 292 |
-
|
| 293 |
-
def get_repo_relative_path(repo_dir: Path, path: Path) -> str | None:
|
| 294 |
-
try:
|
| 295 |
-
return path.resolve().relative_to(repo_dir.resolve()).as_posix()
|
| 296 |
-
except ValueError:
|
| 297 |
-
return None
|
| 298 |
-
|
| 299 |
-
|
| 300 |
-
def sanitize_filename(name: str, default_name: str) -> str:
|
| 301 |
-
raw = (name or "").strip()
|
| 302 |
-
if not raw:
|
| 303 |
-
raw = default_name
|
| 304 |
-
raw = Path(raw).name
|
| 305 |
-
raw = re.sub(r"[^A-Za-z0-9._-]+", "-", raw).strip(".-") or default_name
|
| 306 |
-
if not raw.lower().endswith(".zip"):
|
| 307 |
-
raw = f"{raw}.zip"
|
| 308 |
-
return raw
|
| 309 |
-
|
| 310 |
-
|
| 311 |
-
def resolve_backup_destination(
|
| 312 |
-
directory: Path,
|
| 313 |
-
filename: str,
|
| 314 |
-
conflict_policy: str,
|
| 315 |
-
) -> Path:
|
| 316 |
-
normalized_policy = conflict_policy.strip().lower()
|
| 317 |
-
directory.mkdir(parents=True, exist_ok=True)
|
| 318 |
-
destination = directory / filename
|
| 319 |
-
if not destination.exists():
|
| 320 |
-
return destination
|
| 321 |
-
|
| 322 |
-
if normalized_policy == "overwrite":
|
| 323 |
-
remove_path(destination)
|
| 324 |
-
return destination
|
| 325 |
-
if normalized_policy == "fail":
|
| 326 |
-
raise FileExistsError(f"Backup file already exists: {destination}")
|
| 327 |
-
if normalized_policy != "rename":
|
| 328 |
-
raise ValueError("backup_conflict_policy must be rename, overwrite, or fail.")
|
| 329 |
-
|
| 330 |
-
stem = destination.stem
|
| 331 |
-
suffix = destination.suffix
|
| 332 |
-
index = 2
|
| 333 |
-
while True:
|
| 334 |
-
candidate = directory / f"{stem}-{index}{suffix}"
|
| 335 |
-
if not candidate.exists():
|
| 336 |
-
return candidate
|
| 337 |
-
index += 1
|
| 338 |
-
|
| 339 |
-
|
| 340 |
-
def create_usr_backup(
|
| 341 |
-
*,
|
| 342 |
-
repo_dir: Path,
|
| 343 |
-
backup_path: str,
|
| 344 |
-
backup_name: str,
|
| 345 |
-
conflict_policy: str,
|
| 346 |
-
logger: AttemptLogger,
|
| 347 |
-
) -> Path:
|
| 348 |
-
usr_dir = repo_dir / "usr"
|
| 349 |
-
if not usr_dir.exists():
|
| 350 |
-
raise FileNotFoundError(f"User directory not found: {usr_dir}")
|
| 351 |
-
|
| 352 |
-
destination_dir = Path(backup_path)
|
| 353 |
-
if not destination_dir.is_absolute():
|
| 354 |
-
destination_dir = (repo_dir / destination_dir).resolve()
|
| 355 |
-
else:
|
| 356 |
-
destination_dir = destination_dir.resolve()
|
| 357 |
-
destination_name = sanitize_filename(backup_name, "agent-zero-usr-backup.zip")
|
| 358 |
-
destination = resolve_backup_destination(destination_dir, destination_name, conflict_policy)
|
| 359 |
-
|
| 360 |
-
temp_fd, temp_path = tempfile.mkstemp(suffix=".zip")
|
| 361 |
-
os.close(temp_fd)
|
| 362 |
-
temporary_backup = Path(temp_path)
|
| 363 |
-
|
| 364 |
-
try:
|
| 365 |
-
with zipfile.ZipFile(
|
| 366 |
-
temporary_backup,
|
| 367 |
-
"w",
|
| 368 |
-
compression=zipfile.ZIP_DEFLATED,
|
| 369 |
-
compresslevel=6,
|
| 370 |
-
) as archive:
|
| 371 |
-
for root, dirs, files in os.walk(usr_dir):
|
| 372 |
-
root_path = Path(root)
|
| 373 |
-
root_relative = root_path.relative_to(usr_dir)
|
| 374 |
-
dirs[:] = [
|
| 375 |
-
dirname
|
| 376 |
-
for dirname in dirs
|
| 377 |
-
if not should_exclude_from_usr_backup(
|
| 378 |
-
root_relative / dirname,
|
| 379 |
-
logger,
|
| 380 |
-
)
|
| 381 |
-
]
|
| 382 |
-
for filename in files:
|
| 383 |
-
source_file = root_path / filename
|
| 384 |
-
if not should_include_usr_backup_entry(source_file, logger):
|
| 385 |
-
continue
|
| 386 |
-
archive_name = Path("usr") / source_file.relative_to(usr_dir)
|
| 387 |
-
try:
|
| 388 |
-
archive.write(source_file, archive_name.as_posix())
|
| 389 |
-
except FileNotFoundError:
|
| 390 |
-
logger.log(f"Skipping vanished usr backup entry: {source_file}")
|
| 391 |
-
except OSError as exc:
|
| 392 |
-
logger.log(f"Skipping usr backup entry after read error: {source_file}: {exc}")
|
| 393 |
-
|
| 394 |
-
destination.parent.mkdir(parents=True, exist_ok=True)
|
| 395 |
-
shutil.move(str(temporary_backup), str(destination))
|
| 396 |
-
logger.log(f"Created usr backup at {destination}")
|
| 397 |
-
return destination
|
| 398 |
-
finally:
|
| 399 |
-
if temporary_backup.exists():
|
| 400 |
-
temporary_backup.unlink(missing_ok=True)
|
| 401 |
-
|
| 402 |
-
|
| 403 |
-
def should_exclude_from_usr_backup(
|
| 404 |
-
relative_dir: Path,
|
| 405 |
-
logger: AttemptLogger,
|
| 406 |
-
) -> bool:
|
| 407 |
-
parts = relative_dir.parts
|
| 408 |
-
if parts and parts[0] == ".time_travel":
|
| 409 |
-
logger.log(
|
| 410 |
-
f"Skipping Time Travel history during usr backup: {Path('usr') / relative_dir}"
|
| 411 |
-
)
|
| 412 |
-
return True
|
| 413 |
-
if (
|
| 414 |
-
len(parts) >= 6
|
| 415 |
-
and parts[0] == "plugins"
|
| 416 |
-
and parts[1] == "_desktop"
|
| 417 |
-
and parts[2] == "profiles"
|
| 418 |
-
and parts[-2] == ".ssh"
|
| 419 |
-
and parts[-1] == "agent"
|
| 420 |
-
):
|
| 421 |
-
logger.log(f"Skipping transient usr backup directory: {Path('usr') / relative_dir}")
|
| 422 |
-
return True
|
| 423 |
-
return False
|
| 424 |
-
|
| 425 |
-
|
| 426 |
-
def should_include_usr_backup_entry(source_file: Path, logger: AttemptLogger) -> bool:
|
| 427 |
-
try:
|
| 428 |
-
source_stat = source_file.lstat()
|
| 429 |
-
except FileNotFoundError:
|
| 430 |
-
logger.log(f"Skipping vanished usr backup entry: {source_file}")
|
| 431 |
-
return False
|
| 432 |
-
except OSError as exc:
|
| 433 |
-
logger.log(f"Skipping unreadable usr backup entry: {source_file}: {exc}")
|
| 434 |
-
return False
|
| 435 |
-
|
| 436 |
-
if stat.S_ISLNK(source_stat.st_mode):
|
| 437 |
-
try:
|
| 438 |
-
target_stat = source_file.stat()
|
| 439 |
-
except FileNotFoundError:
|
| 440 |
-
logger.log(f"Skipping broken symlink during usr backup: {source_file}")
|
| 441 |
-
return False
|
| 442 |
-
except OSError as exc:
|
| 443 |
-
logger.log(
|
| 444 |
-
f"Skipping unreadable symlink target during usr backup: {source_file}: {exc}"
|
| 445 |
-
)
|
| 446 |
-
return False
|
| 447 |
-
if not stat.S_ISREG(target_stat.st_mode):
|
| 448 |
-
logger.log(
|
| 449 |
-
f"Skipping non-regular symlink target during usr backup: {source_file}"
|
| 450 |
-
)
|
| 451 |
-
return False
|
| 452 |
-
return True
|
| 453 |
-
|
| 454 |
-
if not stat.S_ISREG(source_stat.st_mode):
|
| 455 |
-
logger.log(f"Skipping non-regular usr backup entry: {source_file}")
|
| 456 |
-
return False
|
| 457 |
-
|
| 458 |
-
return True
|
| 459 |
-
|
| 460 |
-
|
| 461 |
-
def clean_transient_desktop_agent_state(
|
| 462 |
-
repo_dir: Path,
|
| 463 |
-
logger: AttemptLogger,
|
| 464 |
-
) -> None:
|
| 465 |
-
profile_roots = 0
|
| 466 |
-
removed = 0
|
| 467 |
-
for relative_root in DESKTOP_PROFILE_STATE_RELATIVE_DIRS:
|
| 468 |
-
profile_root = repo_dir / relative_root
|
| 469 |
-
if not _is_cleanup_directory(
|
| 470 |
-
profile_root,
|
| 471 |
-
logger,
|
| 472 |
-
"Desktop profile state",
|
| 473 |
-
missing_ok=True,
|
| 474 |
-
):
|
| 475 |
-
continue
|
| 476 |
-
profile_roots += 1
|
| 477 |
-
try:
|
| 478 |
-
profiles = list(profile_root.iterdir())
|
| 479 |
-
except OSError as exc:
|
| 480 |
-
logger.log(f"Desktop profile state could not be listed: {profile_root}: {exc}")
|
| 481 |
-
continue
|
| 482 |
-
for profile_dir in profiles:
|
| 483 |
-
if not _is_cleanup_directory(profile_dir, logger, "Desktop profile"):
|
| 484 |
-
continue
|
| 485 |
-
removed += _clean_directory_entries(
|
| 486 |
-
profile_dir / ".ssh" / "agent",
|
| 487 |
-
logger,
|
| 488 |
-
label="desktop SSH agent",
|
| 489 |
-
)
|
| 490 |
-
removed += _clean_gnupg_agent_entries(profile_dir / ".gnupg", logger)
|
| 491 |
-
|
| 492 |
-
if removed:
|
| 493 |
-
logger.log(f"Removed {removed} transient desktop agent entries.")
|
| 494 |
-
elif profile_roots:
|
| 495 |
-
logger.log("Transient desktop agent state already clean.")
|
| 496 |
-
else:
|
| 497 |
-
logger.log("No desktop profile runtime state found, skipping transient agent cleanup.")
|
| 498 |
-
|
| 499 |
-
|
| 500 |
-
def _clean_gnupg_agent_entries(gnupg_dir: Path, logger: AttemptLogger) -> int:
|
| 501 |
-
if not _is_cleanup_directory(gnupg_dir, logger, "desktop GnuPG state", missing_ok=True):
|
| 502 |
-
return 0
|
| 503 |
-
try:
|
| 504 |
-
entries = list(gnupg_dir.iterdir())
|
| 505 |
-
except OSError as exc:
|
| 506 |
-
logger.log(f"Desktop GnuPG state could not be listed: {gnupg_dir}: {exc}")
|
| 507 |
-
return 0
|
| 508 |
-
|
| 509 |
-
removed = 0
|
| 510 |
-
for entry in entries:
|
| 511 |
-
if not entry.name.startswith("S.gpg-agent"):
|
| 512 |
-
continue
|
| 513 |
-
try:
|
| 514 |
-
entry_stat = entry.lstat()
|
| 515 |
-
except FileNotFoundError:
|
| 516 |
-
continue
|
| 517 |
-
except OSError as exc:
|
| 518 |
-
logger.log(f"Skipping transient desktop GnuPG agent entry after stat error: {entry}: {exc}")
|
| 519 |
-
continue
|
| 520 |
-
if stat.S_ISREG(entry_stat.st_mode):
|
| 521 |
-
continue
|
| 522 |
-
if _remove_cleanup_entry(entry, entry_stat, logger, label="desktop GnuPG agent"):
|
| 523 |
-
removed += 1
|
| 524 |
-
return removed
|
| 525 |
-
|
| 526 |
-
|
| 527 |
-
def _clean_directory_entries(directory: Path, logger: AttemptLogger, *, label: str) -> int:
|
| 528 |
-
if not _is_cleanup_directory(directory, logger, label, missing_ok=True):
|
| 529 |
-
return 0
|
| 530 |
-
try:
|
| 531 |
-
entries = list(directory.iterdir())
|
| 532 |
-
except OSError as exc:
|
| 533 |
-
logger.log(f"Transient {label} directory could not be listed: {directory}: {exc}")
|
| 534 |
-
return 0
|
| 535 |
-
|
| 536 |
-
removed = 0
|
| 537 |
-
for entry in entries:
|
| 538 |
-
try:
|
| 539 |
-
entry_stat = entry.lstat()
|
| 540 |
-
except FileNotFoundError:
|
| 541 |
-
continue
|
| 542 |
-
except OSError as exc:
|
| 543 |
-
logger.log(f"Skipping transient {label} entry after stat error: {entry}: {exc}")
|
| 544 |
-
continue
|
| 545 |
-
if _remove_cleanup_entry(entry, entry_stat, logger, label=label):
|
| 546 |
-
removed += 1
|
| 547 |
-
return removed
|
| 548 |
-
|
| 549 |
-
|
| 550 |
-
def _is_cleanup_directory(
|
| 551 |
-
directory: Path,
|
| 552 |
-
logger: AttemptLogger,
|
| 553 |
-
label: str,
|
| 554 |
-
*,
|
| 555 |
-
missing_ok: bool = False,
|
| 556 |
-
) -> bool:
|
| 557 |
-
try:
|
| 558 |
-
directory_stat = directory.lstat()
|
| 559 |
-
except FileNotFoundError:
|
| 560 |
-
if not missing_ok:
|
| 561 |
-
logger.log(f"{label} directory not found, skipping: {directory}")
|
| 562 |
-
return False
|
| 563 |
-
except OSError as exc:
|
| 564 |
-
logger.log(f"{label} directory could not be inspected: {directory}: {exc}")
|
| 565 |
-
return False
|
| 566 |
-
|
| 567 |
-
if stat.S_ISLNK(directory_stat.st_mode) or not stat.S_ISDIR(directory_stat.st_mode):
|
| 568 |
-
logger.log(f"{label} path is not a directory, skipping: {directory}")
|
| 569 |
-
return False
|
| 570 |
-
return True
|
| 571 |
-
|
| 572 |
-
|
| 573 |
-
def _remove_cleanup_entry(
|
| 574 |
-
entry: Path,
|
| 575 |
-
entry_stat: os.stat_result,
|
| 576 |
-
logger: AttemptLogger,
|
| 577 |
-
*,
|
| 578 |
-
label: str,
|
| 579 |
-
) -> bool:
|
| 580 |
-
try:
|
| 581 |
-
if stat.S_ISDIR(entry_stat.st_mode):
|
| 582 |
-
shutil.rmtree(entry)
|
| 583 |
-
else:
|
| 584 |
-
entry.unlink(missing_ok=True)
|
| 585 |
-
return True
|
| 586 |
-
except FileNotFoundError:
|
| 587 |
-
return False
|
| 588 |
-
except OSError as exc:
|
| 589 |
-
logger.log(f"Skipping transient {label} entry after error: {entry}: {exc}")
|
| 590 |
-
return False
|
| 591 |
-
|
| 592 |
-
|
| 593 |
-
def run_command(
|
| 594 |
-
command: list[str],
|
| 595 |
-
*,
|
| 596 |
-
cwd: Path | None,
|
| 597 |
-
logger: AttemptLogger,
|
| 598 |
-
error_message: str | None = None,
|
| 599 |
-
) -> subprocess.CompletedProcess[str]:
|
| 600 |
-
logger.log(f"$ {' '.join(command)}")
|
| 601 |
-
completed = subprocess.run(
|
| 602 |
-
command,
|
| 603 |
-
cwd=cwd,
|
| 604 |
-
text=True,
|
| 605 |
-
capture_output=True,
|
| 606 |
-
env={**os.environ, "GIT_TERMINAL_PROMPT": "0"},
|
| 607 |
-
)
|
| 608 |
-
if completed.stdout:
|
| 609 |
-
logger.log_block("stdout", completed.stdout)
|
| 610 |
-
if completed.stderr:
|
| 611 |
-
logger.log_block("stderr", completed.stderr)
|
| 612 |
-
if completed.returncode != 0:
|
| 613 |
-
raise RuntimeError(
|
| 614 |
-
error_message
|
| 615 |
-
or f"Command failed with exit code {completed.returncode}: {' '.join(command)}"
|
| 616 |
-
)
|
| 617 |
-
return completed
|
| 618 |
-
|
| 619 |
-
|
| 620 |
-
def clean_uv_cache(logger: AttemptLogger) -> None:
|
| 621 |
-
uv_path = shutil.which("uv")
|
| 622 |
-
if not uv_path:
|
| 623 |
-
logger.log("uv executable not found, skipping uv cache clean.")
|
| 624 |
-
return
|
| 625 |
-
|
| 626 |
-
logger.log("Cleaning uv cache before continuing self-update startup.")
|
| 627 |
-
try:
|
| 628 |
-
run_command(
|
| 629 |
-
[uv_path, "cache", "clean"],
|
| 630 |
-
cwd=None,
|
| 631 |
-
logger=logger,
|
| 632 |
-
error_message="Failed to clean uv cache during self-update.",
|
| 633 |
-
)
|
| 634 |
-
except Exception as exc:
|
| 635 |
-
logger.log(f"uv cache clean skipped after error: {exc}")
|
| 636 |
-
|
| 637 |
-
|
| 638 |
-
def refresh_codex_cli(logger: AttemptLogger) -> None:
|
| 639 |
-
codex_path = shutil.which("codex")
|
| 640 |
-
if not codex_path:
|
| 641 |
-
logger.log("Codex CLI not installed, skipping Codex refresh.")
|
| 642 |
-
return
|
| 643 |
-
|
| 644 |
-
npm_path = shutil.which("npm")
|
| 645 |
-
if not npm_path:
|
| 646 |
-
logger.log("npm executable not found, skipping Codex refresh.")
|
| 647 |
-
return
|
| 648 |
-
|
| 649 |
-
logger.log("Refreshing the installed Codex CLI after self-update.")
|
| 650 |
-
try:
|
| 651 |
-
run_command(
|
| 652 |
-
[npm_path, "install", "--global", "@openai/codex@latest"],
|
| 653 |
-
cwd=None,
|
| 654 |
-
logger=logger,
|
| 655 |
-
error_message="Failed to refresh the installed Codex CLI.",
|
| 656 |
-
)
|
| 657 |
-
except Exception as exc:
|
| 658 |
-
logger.log(f"Codex CLI refresh skipped after error: {exc}")
|
| 659 |
-
|
| 660 |
-
|
| 661 |
-
def has_local_rollback_changes(repo_dir: Path) -> bool:
|
| 662 |
-
status = git_output(repo_dir, "status", "--porcelain=v1", "--untracked-files=all")
|
| 663 |
-
return bool(status.strip())
|
| 664 |
-
|
| 665 |
-
|
| 666 |
-
def get_top_stash_ref(repo_dir: Path) -> str:
|
| 667 |
-
return git_optional_output(repo_dir, "stash", "list", "--format=%gd", "-n", "1")
|
| 668 |
-
|
| 669 |
-
|
| 670 |
-
def create_rollback_stash(repo_dir: Path, logger: AttemptLogger) -> str | None:
|
| 671 |
-
if not has_local_rollback_changes(repo_dir):
|
| 672 |
-
logger.log("No tracked or non-ignored untracked changes need rollback protection.")
|
| 673 |
-
return None
|
| 674 |
-
|
| 675 |
-
previous_top = get_top_stash_ref(repo_dir)
|
| 676 |
-
message = f"a0-self-update rollback snapshot {now_iso()}"
|
| 677 |
-
run_command(
|
| 678 |
-
[
|
| 679 |
-
"git",
|
| 680 |
-
"-C",
|
| 681 |
-
str(repo_dir),
|
| 682 |
-
"stash",
|
| 683 |
-
"push",
|
| 684 |
-
"--include-untracked",
|
| 685 |
-
"--message",
|
| 686 |
-
message,
|
| 687 |
-
],
|
| 688 |
-
cwd=None,
|
| 689 |
-
logger=logger,
|
| 690 |
-
error_message="Failed to save local tracked/untracked changes before updating.",
|
| 691 |
-
)
|
| 692 |
-
stash_ref = get_top_stash_ref(repo_dir)
|
| 693 |
-
if not stash_ref or stash_ref == previous_top:
|
| 694 |
-
raise RuntimeError("Failed to create the pre-update rollback stash.")
|
| 695 |
-
logger.log(
|
| 696 |
-
f"Saved local tracked/untracked changes into {stash_ref}. "
|
| 697 |
-
"Ignored files stay in place and are not stashed."
|
| 698 |
-
)
|
| 699 |
-
return stash_ref
|
| 700 |
-
|
| 701 |
-
|
| 702 |
-
def drop_stash(repo_dir: Path, stash_ref: str, logger: AttemptLogger) -> None:
|
| 703 |
-
if not stash_ref:
|
| 704 |
-
return
|
| 705 |
-
run_command(
|
| 706 |
-
["git", "-C", str(repo_dir), "stash", "drop", stash_ref],
|
| 707 |
-
cwd=None,
|
| 708 |
-
logger=logger,
|
| 709 |
-
error_message=f"Failed to drop temporary rollback stash {stash_ref}.",
|
| 710 |
-
)
|
| 711 |
-
|
| 712 |
-
|
| 713 |
-
def apply_stash(repo_dir: Path, stash_ref: str, logger: AttemptLogger) -> None:
|
| 714 |
-
if not stash_ref:
|
| 715 |
-
return
|
| 716 |
-
run_command(
|
| 717 |
-
["git", "-C", str(repo_dir), "stash", "apply", "--index", stash_ref],
|
| 718 |
-
cwd=None,
|
| 719 |
-
logger=logger,
|
| 720 |
-
error_message=(
|
| 721 |
-
f"Failed to restore local tracked/untracked changes from {stash_ref}. "
|
| 722 |
-
"The stash entry has been kept so it can be recovered manually."
|
| 723 |
-
),
|
| 724 |
-
)
|
| 725 |
-
try:
|
| 726 |
-
drop_stash(repo_dir, stash_ref, logger)
|
| 727 |
-
except Exception as exc:
|
| 728 |
-
logger.log(
|
| 729 |
-
f"Rollback stash {stash_ref} was restored but could not be dropped automatically: {exc}"
|
| 730 |
-
)
|
| 731 |
-
|
| 732 |
-
|
| 733 |
-
def clean_repo_worktree(
|
| 734 |
-
repo_dir: Path,
|
| 735 |
-
logger: AttemptLogger,
|
| 736 |
-
*,
|
| 737 |
-
exclude_paths: list[Path] | None = None,
|
| 738 |
-
) -> None:
|
| 739 |
-
command = ["git", "-C", str(repo_dir), "clean", "-ffd"]
|
| 740 |
-
for path in exclude_paths or []:
|
| 741 |
-
relative_path = get_repo_relative_path(repo_dir, path)
|
| 742 |
-
if relative_path:
|
| 743 |
-
command.extend(["-e", relative_path])
|
| 744 |
-
run_command(
|
| 745 |
-
command,
|
| 746 |
-
cwd=None,
|
| 747 |
-
logger=logger,
|
| 748 |
-
error_message="Failed to remove leftover non-ignored files after checkout.",
|
| 749 |
-
)
|
| 750 |
-
|
| 751 |
-
|
| 752 |
-
def fetch_release_refs(repo_dir: Path, branch: str, tag: str, logger: AttemptLogger) -> None:
|
| 753 |
-
remote_branch_ref = f"refs/remotes/a0-self-update/{branch}"
|
| 754 |
-
tag_commit_ref = get_tag_commit_ref(tag)
|
| 755 |
-
logger.log(f"Fetching branch {branch} and tag {tag} from {OFFICIAL_REPO_URL}")
|
| 756 |
-
run_command(
|
| 757 |
-
[
|
| 758 |
-
"git",
|
| 759 |
-
"-C",
|
| 760 |
-
str(repo_dir),
|
| 761 |
-
"fetch",
|
| 762 |
-
"--force",
|
| 763 |
-
OFFICIAL_REPO_URL,
|
| 764 |
-
f"+refs/heads/{branch}:{remote_branch_ref}",
|
| 765 |
-
f"+refs/tags/{tag}:refs/tags/{tag}",
|
| 766 |
-
],
|
| 767 |
-
cwd=None,
|
| 768 |
-
logger=logger,
|
| 769 |
-
error_message=f"Failed to fetch branch {branch} and tag {tag} from the official repository.",
|
| 770 |
-
)
|
| 771 |
-
run_command(
|
| 772 |
-
[
|
| 773 |
-
"git",
|
| 774 |
-
"-C",
|
| 775 |
-
str(repo_dir),
|
| 776 |
-
"merge-base",
|
| 777 |
-
"--is-ancestor",
|
| 778 |
-
tag_commit_ref,
|
| 779 |
-
remote_branch_ref,
|
| 780 |
-
],
|
| 781 |
-
cwd=None,
|
| 782 |
-
logger=logger,
|
| 783 |
-
error_message=f"Requested tag {tag} is not reachable from official branch {branch}.",
|
| 784 |
-
)
|
| 785 |
-
|
| 786 |
-
|
| 787 |
-
def fetch_branch_refs(repo_dir: Path, branch: str, logger: AttemptLogger) -> str:
|
| 788 |
-
remote_branch_ref = f"refs/remotes/a0-self-update/{branch}"
|
| 789 |
-
logger.log(f"Fetching branch {branch} and tags from {OFFICIAL_REPO_URL}")
|
| 790 |
-
run_command(
|
| 791 |
-
[
|
| 792 |
-
"git",
|
| 793 |
-
"-C",
|
| 794 |
-
str(repo_dir),
|
| 795 |
-
"fetch",
|
| 796 |
-
"--force",
|
| 797 |
-
"--tags",
|
| 798 |
-
OFFICIAL_REPO_URL,
|
| 799 |
-
f"+refs/heads/{branch}:{remote_branch_ref}",
|
| 800 |
-
],
|
| 801 |
-
cwd=None,
|
| 802 |
-
logger=logger,
|
| 803 |
-
error_message=f"Failed to fetch branch {branch} from the official repository.",
|
| 804 |
-
)
|
| 805 |
-
return remote_branch_ref
|
| 806 |
-
|
| 807 |
-
|
| 808 |
-
def resolve_requested_target(
|
| 809 |
-
repo_dir: Path,
|
| 810 |
-
branch: str,
|
| 811 |
-
tag: str,
|
| 812 |
-
current_version: str,
|
| 813 |
-
logger: AttemptLogger,
|
| 814 |
-
) -> dict[str, str]:
|
| 815 |
-
normalized_tag = tag.strip()
|
| 816 |
-
|
| 817 |
-
if not is_latest_selector_tag(normalized_tag):
|
| 818 |
-
fetch_release_refs(repo_dir, branch, normalized_tag, logger)
|
| 819 |
-
tag_commit_ref = get_tag_commit_ref(normalized_tag)
|
| 820 |
-
return {
|
| 821 |
-
"requested_tag": normalized_tag,
|
| 822 |
-
"effective_tag": normalized_tag,
|
| 823 |
-
"target_ref": f"refs/tags/{normalized_tag}",
|
| 824 |
-
"expected_short_tag": normalized_tag,
|
| 825 |
-
"expected_commit": git_output(repo_dir, "rev-parse", tag_commit_ref),
|
| 826 |
-
"target_description": f"tag {normalized_tag}",
|
| 827 |
-
}
|
| 828 |
-
|
| 829 |
-
remote_branch_ref = fetch_branch_refs(repo_dir, branch, logger)
|
| 830 |
-
if branch == "main":
|
| 831 |
-
effective_tag = get_latest_same_major_tag(
|
| 832 |
-
repo_dir,
|
| 833 |
-
branch_ref=remote_branch_ref,
|
| 834 |
-
current_version=current_version,
|
| 835 |
-
)
|
| 836 |
-
tag_commit_ref = get_tag_commit_ref(effective_tag)
|
| 837 |
-
logger.log(f"Resolved latest on main to tag {effective_tag}")
|
| 838 |
-
return {
|
| 839 |
-
"requested_tag": LATEST_SELECTOR_TAG,
|
| 840 |
-
"effective_tag": effective_tag,
|
| 841 |
-
"target_ref": f"refs/tags/{effective_tag}",
|
| 842 |
-
"expected_short_tag": effective_tag,
|
| 843 |
-
"expected_commit": git_output(repo_dir, "rev-parse", tag_commit_ref),
|
| 844 |
-
"target_description": f"latest tag {effective_tag}",
|
| 845 |
-
}
|
| 846 |
-
|
| 847 |
-
head_describe = git_output(repo_dir, "describe", "--tags", "--always", remote_branch_ref)
|
| 848 |
-
head_short_tag = normalize_describe_to_version(head_describe)
|
| 849 |
-
head_commit = git_output(repo_dir, "rev-parse", remote_branch_ref)
|
| 850 |
-
ensure_latest_target_matches_current_major(
|
| 851 |
-
branch=branch,
|
| 852 |
-
current_version=current_version,
|
| 853 |
-
target_version=head_short_tag,
|
| 854 |
-
)
|
| 855 |
-
logger.log(
|
| 856 |
-
f"Resolved latest on branch {branch} to commit {head_commit[:7]} ({head_describe})"
|
| 857 |
-
)
|
| 858 |
-
return {
|
| 859 |
-
"requested_tag": LATEST_SELECTOR_TAG,
|
| 860 |
-
"effective_tag": head_short_tag,
|
| 861 |
-
"target_ref": remote_branch_ref,
|
| 862 |
-
"expected_short_tag": head_short_tag,
|
| 863 |
-
"expected_commit": head_commit,
|
| 864 |
-
"target_description": f"latest branch state {head_describe}",
|
| 865 |
-
}
|
| 866 |
-
|
| 867 |
-
|
| 868 |
-
def checkout_target_release(
|
| 869 |
-
repo_dir: Path,
|
| 870 |
-
branch: str,
|
| 871 |
-
target_ref: str,
|
| 872 |
-
target_description: str,
|
| 873 |
-
logger: AttemptLogger,
|
| 874 |
-
*,
|
| 875 |
-
exclude_paths: list[Path] | None = None,
|
| 876 |
-
) -> None:
|
| 877 |
-
logger.log(f"Checking out branch {branch} at {target_description}")
|
| 878 |
-
run_command(
|
| 879 |
-
[
|
| 880 |
-
"git",
|
| 881 |
-
"-C",
|
| 882 |
-
str(repo_dir),
|
| 883 |
-
"checkout",
|
| 884 |
-
"-B",
|
| 885 |
-
branch,
|
| 886 |
-
target_ref,
|
| 887 |
-
],
|
| 888 |
-
cwd=None,
|
| 889 |
-
logger=logger,
|
| 890 |
-
error_message=f"Failed to check out requested {target_description} on branch {branch}.",
|
| 891 |
-
)
|
| 892 |
-
clean_repo_worktree(repo_dir, logger, exclude_paths=exclude_paths)
|
| 893 |
-
|
| 894 |
-
|
| 895 |
-
def restore_git_state(
|
| 896 |
-
repo_dir: Path,
|
| 897 |
-
*,
|
| 898 |
-
head: str,
|
| 899 |
-
branch: str,
|
| 900 |
-
logger: AttemptLogger,
|
| 901 |
-
exclude_paths: list[Path] | None = None,
|
| 902 |
-
) -> None:
|
| 903 |
-
logger.log(f"Restoring repository state to commit {head}")
|
| 904 |
-
if branch:
|
| 905 |
-
run_command(
|
| 906 |
-
[
|
| 907 |
-
"git",
|
| 908 |
-
"-C",
|
| 909 |
-
str(repo_dir),
|
| 910 |
-
"checkout",
|
| 911 |
-
"-B",
|
| 912 |
-
branch,
|
| 913 |
-
head,
|
| 914 |
-
],
|
| 915 |
-
cwd=None,
|
| 916 |
-
logger=logger,
|
| 917 |
-
error_message=f"Failed to restore branch {branch} to commit {head}.",
|
| 918 |
-
)
|
| 919 |
-
else:
|
| 920 |
-
run_command(
|
| 921 |
-
[
|
| 922 |
-
"git",
|
| 923 |
-
"-C",
|
| 924 |
-
str(repo_dir),
|
| 925 |
-
"checkout",
|
| 926 |
-
"--detach",
|
| 927 |
-
head,
|
| 928 |
-
],
|
| 929 |
-
cwd=None,
|
| 930 |
-
logger=logger,
|
| 931 |
-
error_message=f"Failed to restore detached HEAD at commit {head}.",
|
| 932 |
-
)
|
| 933 |
-
clean_repo_worktree(repo_dir, logger, exclude_paths=exclude_paths)
|
| 934 |
-
|
| 935 |
-
|
| 936 |
-
def launch_ui_process(repo_dir: Path, logger: AttemptLogger) -> subprocess.Popen[bytes]:
|
| 937 |
-
run_office_cleanup_hook(repo_dir, logger)
|
| 938 |
-
|
| 939 |
-
prepare_script = repo_dir / "prepare.py"
|
| 940 |
-
if prepare_script.exists():
|
| 941 |
-
logger.log("Running prepare.py before UI start")
|
| 942 |
-
run_command([sys.executable, str(prepare_script), "--dockerized=true"], cwd=repo_dir, logger=logger)
|
| 943 |
-
else:
|
| 944 |
-
logger.log("prepare.py not found, skipping prepare step")
|
| 945 |
-
|
| 946 |
-
logger.log("Starting Agent Zero UI")
|
| 947 |
-
return subprocess.Popen(
|
| 948 |
-
[
|
| 949 |
-
sys.executable,
|
| 950 |
-
str(repo_dir / "run_ui.py"),
|
| 951 |
-
"--dockerized=true",
|
| 952 |
-
"--port=80",
|
| 953 |
-
"--host=0.0.0.0",
|
| 954 |
-
],
|
| 955 |
-
cwd=repo_dir,
|
| 956 |
-
)
|
| 957 |
-
|
| 958 |
-
|
| 959 |
-
def run_office_cleanup_hook(repo_dir: Path, logger: AttemptLogger) -> None:
|
| 960 |
-
hook_path = repo_dir / "plugins" / "_office" / "hooks.py"
|
| 961 |
-
if not hook_path.exists():
|
| 962 |
-
return
|
| 963 |
-
try:
|
| 964 |
-
if str(repo_dir) not in sys.path:
|
| 965 |
-
sys.path.insert(0, str(repo_dir))
|
| 966 |
-
spec = importlib.util.spec_from_file_location("a0_office_hooks", hook_path)
|
| 967 |
-
if spec is None or spec.loader is None:
|
| 968 |
-
logger.log("Office cleanup hook could not be loaded.")
|
| 969 |
-
return
|
| 970 |
-
module = importlib.util.module_from_spec(spec)
|
| 971 |
-
spec.loader.exec_module(module)
|
| 972 |
-
cleanup = getattr(module, "cleanup_stale_runtime_state", None)
|
| 973 |
-
if not callable(cleanup):
|
| 974 |
-
return
|
| 975 |
-
result = cleanup()
|
| 976 |
-
if isinstance(result, dict) and result.get("errors"):
|
| 977 |
-
logger.log(f"Office cleanup hook reported errors: {result.get('errors')}")
|
| 978 |
-
else:
|
| 979 |
-
logger.log("Office cleanup hook completed.")
|
| 980 |
-
except Exception as exc:
|
| 981 |
-
logger.log(f"Office cleanup hook skipped after error: {exc}")
|
| 982 |
-
|
| 983 |
-
|
| 984 |
-
def wait_for_health(
|
| 985 |
-
process: subprocess.Popen[bytes],
|
| 986 |
-
*,
|
| 987 |
-
health_url: str,
|
| 988 |
-
timeout_seconds: int,
|
| 989 |
-
poll_interval_seconds: float,
|
| 990 |
-
expected_version: str | None = None,
|
| 991 |
-
expected_commit: str | None = None,
|
| 992 |
-
logger: AttemptLogger,
|
| 993 |
-
) -> tuple[bool, dict[str, Any] | str]:
|
| 994 |
-
deadline = time.monotonic() + timeout_seconds
|
| 995 |
-
last_error = "Health check did not return a successful response."
|
| 996 |
-
|
| 997 |
-
while time.monotonic() < deadline:
|
| 998 |
-
if process.poll() is not None:
|
| 999 |
-
return (
|
| 1000 |
-
False,
|
| 1001 |
-
f"UI process exited with code {process.returncode} before passing the health check.",
|
| 1002 |
-
)
|
| 1003 |
-
try:
|
| 1004 |
-
request = urllib.request.Request(
|
| 1005 |
-
health_url,
|
| 1006 |
-
headers={"Cache-Control": "no-cache"},
|
| 1007 |
-
method="GET",
|
| 1008 |
-
)
|
| 1009 |
-
with urllib.request.urlopen(request, timeout=5) as response:
|
| 1010 |
-
body = response.read().decode("utf-8")
|
| 1011 |
-
payload = json.loads(body) if body else {}
|
| 1012 |
-
git_info = payload.get("gitinfo") or {}
|
| 1013 |
-
current_version = (git_info.get("short_tag") or "").strip()
|
| 1014 |
-
current_commit = (git_info.get("commit_hash") or "").strip()
|
| 1015 |
-
if expected_commit and current_commit and current_commit != expected_commit:
|
| 1016 |
-
last_error = (
|
| 1017 |
-
f"Health check responded, but commit {current_commit} does not match "
|
| 1018 |
-
f"expected {expected_commit}."
|
| 1019 |
-
)
|
| 1020 |
-
elif expected_version and current_version and current_version != expected_version:
|
| 1021 |
-
last_error = (
|
| 1022 |
-
f"Health check responded, but version {current_version} does not match "
|
| 1023 |
-
f"expected {expected_version}."
|
| 1024 |
-
)
|
| 1025 |
-
elif response.status == 200:
|
| 1026 |
-
logger.log(f"Health check passed at {health_url}")
|
| 1027 |
-
return True, payload
|
| 1028 |
-
except (urllib.error.URLError, TimeoutError, ValueError, json.JSONDecodeError) as exc:
|
| 1029 |
-
last_error = str(exc)
|
| 1030 |
-
|
| 1031 |
-
time.sleep(poll_interval_seconds)
|
| 1032 |
-
|
| 1033 |
-
return False, last_error
|
| 1034 |
-
|
| 1035 |
-
|
| 1036 |
-
def terminate_process(process: subprocess.Popen[bytes], timeout_seconds: int = 20) -> None:
|
| 1037 |
-
if process.poll() is not None:
|
| 1038 |
-
return
|
| 1039 |
-
process.terminate()
|
| 1040 |
-
try:
|
| 1041 |
-
process.wait(timeout=timeout_seconds)
|
| 1042 |
-
except subprocess.TimeoutExpired:
|
| 1043 |
-
process.kill()
|
| 1044 |
-
process.wait(timeout=5)
|
| 1045 |
-
|
| 1046 |
-
|
| 1047 |
-
def wait_for_process(process: subprocess.Popen[bytes]) -> int:
|
| 1048 |
-
def forward_signal(signum, _frame) -> None:
|
| 1049 |
-
if process.poll() is None:
|
| 1050 |
-
process.send_signal(signum)
|
| 1051 |
-
|
| 1052 |
-
for sig in (signal.SIGTERM, signal.SIGINT):
|
| 1053 |
-
try:
|
| 1054 |
-
signal.signal(sig, forward_signal)
|
| 1055 |
-
except ValueError:
|
| 1056 |
-
pass
|
| 1057 |
-
|
| 1058 |
-
return process.wait()
|
| 1059 |
-
|
| 1060 |
-
|
| 1061 |
-
def record_result(
|
| 1062 |
-
*,
|
| 1063 |
-
status: str,
|
| 1064 |
-
message: str,
|
| 1065 |
-
request_data: dict[str, Any],
|
| 1066 |
-
source_info: dict[str, str],
|
| 1067 |
-
current_version: str,
|
| 1068 |
-
started_at: str,
|
| 1069 |
-
backup_zip_path: str = "",
|
| 1070 |
-
rollback_applied: bool = False,
|
| 1071 |
-
error: str = "",
|
| 1072 |
-
) -> None:
|
| 1073 |
-
payload: dict[str, Any] = {
|
| 1074 |
-
"status": status,
|
| 1075 |
-
"message": message,
|
| 1076 |
-
"branch": str(request_data.get("branch", "")),
|
| 1077 |
-
"tag": str(request_data.get("tag", "")),
|
| 1078 |
-
"source_version": source_info["short_tag"],
|
| 1079 |
-
"source_commit": source_info["commit"],
|
| 1080 |
-
"current_version": current_version,
|
| 1081 |
-
"requested_at": str(request_data.get("requested_at", "")),
|
| 1082 |
-
"started_at": started_at,
|
| 1083 |
-
"finished_at": now_iso(),
|
| 1084 |
-
"log_file_path": str(LOG_FILE),
|
| 1085 |
-
"update_file_path": str(TRIGGER_FILE),
|
| 1086 |
-
"rollback_applied": rollback_applied,
|
| 1087 |
-
}
|
| 1088 |
-
if backup_zip_path:
|
| 1089 |
-
payload["backup_zip_path"] = backup_zip_path
|
| 1090 |
-
if error:
|
| 1091 |
-
payload["error"] = error
|
| 1092 |
-
write_status(payload)
|
| 1093 |
-
|
| 1094 |
-
|
| 1095 |
-
def execute_pending_update(
|
| 1096 |
-
request_data: dict[str, Any],
|
| 1097 |
-
*,
|
| 1098 |
-
logger: AttemptLogger,
|
| 1099 |
-
) -> subprocess.Popen[bytes]:
|
| 1100 |
-
source_info = get_repo_version_info(REPO_DIR)
|
| 1101 |
-
started_at = now_iso()
|
| 1102 |
-
backup_zip_path = ""
|
| 1103 |
-
stash_ref: str | None = None
|
| 1104 |
-
repository_changed = False
|
| 1105 |
-
branch = str(request_data.get("branch", "")).strip()
|
| 1106 |
-
tag = str(request_data.get("tag", "")).strip()
|
| 1107 |
-
backup_exclusions: list[Path] = []
|
| 1108 |
-
resolved_target: dict[str, str] | None = None
|
| 1109 |
-
|
| 1110 |
-
try:
|
| 1111 |
-
if not branch:
|
| 1112 |
-
raise ValueError("Update file is missing the branch field.")
|
| 1113 |
-
if not tag:
|
| 1114 |
-
raise ValueError("Update file is missing the tag field.")
|
| 1115 |
-
|
| 1116 |
-
stash_ref = create_rollback_stash(REPO_DIR, logger)
|
| 1117 |
-
|
| 1118 |
-
if bool(request_data.get("backup_usr", True)):
|
| 1119 |
-
backup_destination = create_usr_backup(
|
| 1120 |
-
repo_dir=REPO_DIR,
|
| 1121 |
-
backup_path=str(request_data.get("backup_path", "/root/update-backups")),
|
| 1122 |
-
backup_name=str(request_data.get("backup_name", "agent-zero-usr-backup.zip")),
|
| 1123 |
-
conflict_policy=str(request_data.get("backup_conflict_policy", "rename")),
|
| 1124 |
-
logger=logger,
|
| 1125 |
-
)
|
| 1126 |
-
backup_zip_path = str(backup_destination)
|
| 1127 |
-
backup_exclusions.append(backup_destination)
|
| 1128 |
-
|
| 1129 |
-
resolved_target = resolve_requested_target(
|
| 1130 |
-
REPO_DIR,
|
| 1131 |
-
branch,
|
| 1132 |
-
tag,
|
| 1133 |
-
source_info["short_tag"],
|
| 1134 |
-
logger,
|
| 1135 |
-
)
|
| 1136 |
-
|
| 1137 |
-
repository_changed = True
|
| 1138 |
-
logger.log(
|
| 1139 |
-
"Applying the requested release with native Git checkout. "
|
| 1140 |
-
"Ignored files remain untouched; tracked files and non-ignored leftovers are replaced."
|
| 1141 |
-
)
|
| 1142 |
-
checkout_target_release(
|
| 1143 |
-
REPO_DIR,
|
| 1144 |
-
branch,
|
| 1145 |
-
resolved_target["target_ref"],
|
| 1146 |
-
resolved_target["target_description"],
|
| 1147 |
-
logger,
|
| 1148 |
-
exclude_paths=backup_exclusions,
|
| 1149 |
-
)
|
| 1150 |
-
|
| 1151 |
-
current_info = get_repo_version_info(REPO_DIR)
|
| 1152 |
-
if resolved_target.get("expected_commit") and current_info["commit"] != resolved_target["expected_commit"]:
|
| 1153 |
-
raise RuntimeError(
|
| 1154 |
-
"Git checkout completed but the repository commit does not match the requested target. "
|
| 1155 |
-
f"Expected {resolved_target['expected_commit']}, got {current_info['commit']}."
|
| 1156 |
-
)
|
| 1157 |
-
if resolved_target.get("expected_short_tag") and current_info["short_tag"] != resolved_target["expected_short_tag"]:
|
| 1158 |
-
raise RuntimeError(
|
| 1159 |
-
"Git checkout completed but the repository version does not match the requested tag. "
|
| 1160 |
-
f"Expected {resolved_target['expected_short_tag']}, got {current_info['short_tag']}."
|
| 1161 |
-
)
|
| 1162 |
-
|
| 1163 |
-
updated_process = launch_ui_process(REPO_DIR, logger)
|
| 1164 |
-
healthy, details = wait_for_health(
|
| 1165 |
-
updated_process,
|
| 1166 |
-
health_url=DEFAULT_HEALTH_URL,
|
| 1167 |
-
timeout_seconds=DEFAULT_HEALTH_TIMEOUT_SECONDS,
|
| 1168 |
-
poll_interval_seconds=DEFAULT_HEALTH_POLL_INTERVAL_SECONDS,
|
| 1169 |
-
expected_version=resolved_target.get("expected_short_tag"),
|
| 1170 |
-
expected_commit=resolved_target.get("expected_commit"),
|
| 1171 |
-
logger=logger,
|
| 1172 |
-
)
|
| 1173 |
-
if healthy:
|
| 1174 |
-
refresh_codex_cli(logger)
|
| 1175 |
-
record_result(
|
| 1176 |
-
status="success",
|
| 1177 |
-
message=f"Updated Agent Zero to branch {branch}, {resolved_target['target_description']}.",
|
| 1178 |
-
request_data=request_data,
|
| 1179 |
-
source_info=source_info,
|
| 1180 |
-
current_version=current_info["short_tag"],
|
| 1181 |
-
started_at=started_at,
|
| 1182 |
-
backup_zip_path=backup_zip_path,
|
| 1183 |
-
rollback_applied=False,
|
| 1184 |
-
)
|
| 1185 |
-
if stash_ref:
|
| 1186 |
-
logger.log(
|
| 1187 |
-
f"Update succeeded, dropping temporary rollback stash {stash_ref}. "
|
| 1188 |
-
"Tracked and non-ignored local changes were not reapplied."
|
| 1189 |
-
)
|
| 1190 |
-
try:
|
| 1191 |
-
drop_stash(REPO_DIR, stash_ref, logger)
|
| 1192 |
-
except Exception as exc:
|
| 1193 |
-
logger.log(
|
| 1194 |
-
f"Temporary rollback stash {stash_ref} could not be dropped automatically: {exc}"
|
| 1195 |
-
)
|
| 1196 |
-
return updated_process
|
| 1197 |
-
|
| 1198 |
-
logger.log(f"Updated UI failed health check, rolling back: {details}")
|
| 1199 |
-
terminate_process(updated_process)
|
| 1200 |
-
restore_git_state(
|
| 1201 |
-
REPO_DIR,
|
| 1202 |
-
head=source_info["commit"],
|
| 1203 |
-
branch=source_info.get("branch", ""),
|
| 1204 |
-
logger=logger,
|
| 1205 |
-
exclude_paths=backup_exclusions,
|
| 1206 |
-
)
|
| 1207 |
-
apply_stash(REPO_DIR, stash_ref or "", logger)
|
| 1208 |
-
stash_ref = None
|
| 1209 |
-
|
| 1210 |
-
rollback_process = launch_ui_process(REPO_DIR, logger)
|
| 1211 |
-
rollback_healthy, rollback_details = wait_for_health(
|
| 1212 |
-
rollback_process,
|
| 1213 |
-
health_url=DEFAULT_HEALTH_URL,
|
| 1214 |
-
timeout_seconds=DEFAULT_HEALTH_TIMEOUT_SECONDS,
|
| 1215 |
-
poll_interval_seconds=DEFAULT_HEALTH_POLL_INTERVAL_SECONDS,
|
| 1216 |
-
expected_version=source_info["short_tag"],
|
| 1217 |
-
logger=logger,
|
| 1218 |
-
)
|
| 1219 |
-
|
| 1220 |
-
if rollback_healthy:
|
| 1221 |
-
record_result(
|
| 1222 |
-
status="rolled_back",
|
| 1223 |
-
message=(
|
| 1224 |
-
"Updated version failed its health check and the previous version was restored. "
|
| 1225 |
-
f"Reason: {details}"
|
| 1226 |
-
),
|
| 1227 |
-
request_data=request_data,
|
| 1228 |
-
source_info=source_info,
|
| 1229 |
-
current_version=source_info["short_tag"],
|
| 1230 |
-
started_at=started_at,
|
| 1231 |
-
backup_zip_path=backup_zip_path,
|
| 1232 |
-
rollback_applied=True,
|
| 1233 |
-
error=str(details),
|
| 1234 |
-
)
|
| 1235 |
-
return rollback_process
|
| 1236 |
-
|
| 1237 |
-
terminate_process(rollback_process)
|
| 1238 |
-
record_result(
|
| 1239 |
-
status="rollback_failed",
|
| 1240 |
-
message=(
|
| 1241 |
-
"Updated version failed its health check and rollback also failed to become healthy."
|
| 1242 |
-
),
|
| 1243 |
-
request_data=request_data,
|
| 1244 |
-
source_info=source_info,
|
| 1245 |
-
current_version=source_info["short_tag"],
|
| 1246 |
-
started_at=started_at,
|
| 1247 |
-
backup_zip_path=backup_zip_path,
|
| 1248 |
-
rollback_applied=True,
|
| 1249 |
-
error=f"Update error: {details}. Rollback error: {rollback_details}",
|
| 1250 |
-
)
|
| 1251 |
-
raise RuntimeError(str(rollback_details))
|
| 1252 |
-
except Exception as exc:
|
| 1253 |
-
restore_error = ""
|
| 1254 |
-
if repository_changed or stash_ref:
|
| 1255 |
-
logger.log(f"Restoring pre-update repository state after error: {exc}")
|
| 1256 |
-
try:
|
| 1257 |
-
restore_git_state(
|
| 1258 |
-
REPO_DIR,
|
| 1259 |
-
head=source_info["commit"],
|
| 1260 |
-
branch=source_info.get("branch", ""),
|
| 1261 |
-
logger=logger,
|
| 1262 |
-
exclude_paths=backup_exclusions,
|
| 1263 |
-
)
|
| 1264 |
-
if stash_ref:
|
| 1265 |
-
apply_stash(REPO_DIR, stash_ref, logger)
|
| 1266 |
-
stash_ref = None
|
| 1267 |
-
except Exception as restore_exc:
|
| 1268 |
-
restore_error = str(restore_exc)
|
| 1269 |
-
logger.log(f"Automatic restore failed: {restore_exc}")
|
| 1270 |
-
|
| 1271 |
-
failure_message = str(exc)
|
| 1272 |
-
if restore_error:
|
| 1273 |
-
failure_message = f"{failure_message} | Restore error: {restore_error}"
|
| 1274 |
-
|
| 1275 |
-
failure_status = "failed"
|
| 1276 |
-
if repository_changed:
|
| 1277 |
-
failure_status = "rollback_failed" if restore_error else "rolled_back"
|
| 1278 |
-
|
| 1279 |
-
record_result(
|
| 1280 |
-
status=failure_status,
|
| 1281 |
-
message=failure_message,
|
| 1282 |
-
request_data=request_data,
|
| 1283 |
-
source_info=source_info,
|
| 1284 |
-
current_version=source_info["short_tag"],
|
| 1285 |
-
started_at=started_at,
|
| 1286 |
-
backup_zip_path=backup_zip_path,
|
| 1287 |
-
rollback_applied=repository_changed,
|
| 1288 |
-
error=failure_message,
|
| 1289 |
-
)
|
| 1290 |
-
logger.log(f"Update flow failed: {failure_message}")
|
| 1291 |
-
return launch_ui_process(REPO_DIR, logger)
|
| 1292 |
-
|
| 1293 |
-
|
| 1294 |
-
def load_request_file() -> tuple[dict[str, Any] | None, str]:
|
| 1295 |
-
if not TRIGGER_FILE.exists():
|
| 1296 |
-
return None, ""
|
| 1297 |
-
raw_text = TRIGGER_FILE.read_text(encoding="utf-8")
|
| 1298 |
-
try:
|
| 1299 |
-
loaded = yaml.safe_load(raw_text)
|
| 1300 |
-
return (loaded if isinstance(loaded, dict) else None), raw_text
|
| 1301 |
-
finally:
|
| 1302 |
-
TRIGGER_FILE.unlink(missing_ok=True)
|
| 1303 |
-
|
| 1304 |
-
|
| 1305 |
-
def queue_update_request(
|
| 1306 |
-
*,
|
| 1307 |
-
branch: str = "main",
|
| 1308 |
-
tag: str = LATEST_SELECTOR_TAG,
|
| 1309 |
-
backup_usr: bool = True,
|
| 1310 |
-
backup_path: str = DEFAULT_BACKUP_DIR,
|
| 1311 |
-
backup_name: str = "",
|
| 1312 |
-
backup_conflict_policy: str = DEFAULT_BACKUP_CONFLICT_POLICY,
|
| 1313 |
-
) -> dict[str, Any]:
|
| 1314 |
-
source_info = get_repo_version_info(REPO_DIR)
|
| 1315 |
-
normalized_branch = (branch or "").strip().lower() or "main"
|
| 1316 |
-
normalized_tag = normalize_requested_tag(tag)
|
| 1317 |
-
normalized_policy = normalize_backup_conflict_policy(backup_conflict_policy)
|
| 1318 |
-
normalized_backup_path = (backup_path or "").strip() or DEFAULT_BACKUP_DIR
|
| 1319 |
-
normalized_backup_name = sanitize_filename(
|
| 1320 |
-
backup_name,
|
| 1321 |
-
build_default_backup_name(),
|
| 1322 |
-
)
|
| 1323 |
-
|
| 1324 |
-
payload = {
|
| 1325 |
-
"branch": normalized_branch,
|
| 1326 |
-
"tag": normalized_tag,
|
| 1327 |
-
"source_version": source_info["short_tag"],
|
| 1328 |
-
"source_describe": source_info["describe"],
|
| 1329 |
-
"source_commit": source_info["commit"],
|
| 1330 |
-
"requested_at": now_iso(),
|
| 1331 |
-
"backup_usr": bool(backup_usr),
|
| 1332 |
-
"backup_path": normalized_backup_path,
|
| 1333 |
-
"backup_name": normalized_backup_name,
|
| 1334 |
-
"backup_conflict_policy": normalized_policy,
|
| 1335 |
-
}
|
| 1336 |
-
write_yaml(TRIGGER_FILE, payload)
|
| 1337 |
-
return payload
|
| 1338 |
-
|
| 1339 |
-
|
| 1340 |
-
def installed_target_matches_request(
|
| 1341 |
-
current_info: dict[str, str],
|
| 1342 |
-
*,
|
| 1343 |
-
requested_branch: str,
|
| 1344 |
-
requested_tag: str,
|
| 1345 |
-
) -> bool:
|
| 1346 |
-
normalized_tag = requested_tag.strip()
|
| 1347 |
-
if not normalized_tag or is_latest_selector_tag(normalized_tag):
|
| 1348 |
-
return False
|
| 1349 |
-
|
| 1350 |
-
current_branch = current_info.get("branch", "").strip()
|
| 1351 |
-
if requested_branch.strip() and current_branch != requested_branch.strip():
|
| 1352 |
-
return False
|
| 1353 |
-
|
| 1354 |
-
return current_info.get("describe", "").strip() == normalized_tag
|
| 1355 |
-
|
| 1356 |
-
|
| 1357 |
-
def trigger_update_command(args: list[str]) -> int:
|
| 1358 |
-
parser = argparse.ArgumentParser(
|
| 1359 |
-
prog="trigger_self_update.sh",
|
| 1360 |
-
description="Queue an Agent Zero self-update for the next startup attempt.",
|
| 1361 |
-
)
|
| 1362 |
-
parser.add_argument(
|
| 1363 |
-
"branch",
|
| 1364 |
-
nargs="?",
|
| 1365 |
-
default="main",
|
| 1366 |
-
help="Target official branch. Default: main",
|
| 1367 |
-
)
|
| 1368 |
-
parser.add_argument(
|
| 1369 |
-
"tag",
|
| 1370 |
-
nargs="?",
|
| 1371 |
-
default=LATEST_SELECTOR_TAG,
|
| 1372 |
-
help='Target release tag such as v1.10 or "latest". Default: latest',
|
| 1373 |
-
)
|
| 1374 |
-
parser.add_argument(
|
| 1375 |
-
"--backup-dir",
|
| 1376 |
-
default=DEFAULT_BACKUP_DIR,
|
| 1377 |
-
help=f"Directory for the usr backup zip. Default: {DEFAULT_BACKUP_DIR}",
|
| 1378 |
-
)
|
| 1379 |
-
parser.add_argument(
|
| 1380 |
-
"--backup-name",
|
| 1381 |
-
default="",
|
| 1382 |
-
help="Backup zip filename. Default: autogenerated usr-YYYYMMDD-HHMMSS.zip",
|
| 1383 |
-
)
|
| 1384 |
-
parser.add_argument(
|
| 1385 |
-
"--backup-conflict-policy",
|
| 1386 |
-
default=DEFAULT_BACKUP_CONFLICT_POLICY,
|
| 1387 |
-
choices=sorted(BACKUP_CONFLICT_POLICIES),
|
| 1388 |
-
help="How to handle an existing backup zip. Default: rename",
|
| 1389 |
-
)
|
| 1390 |
-
parser.add_argument(
|
| 1391 |
-
"--no-backup",
|
| 1392 |
-
action="store_true",
|
| 1393 |
-
help="Skip creating a usr backup before the update.",
|
| 1394 |
-
)
|
| 1395 |
-
parsed = parser.parse_args(args)
|
| 1396 |
-
|
| 1397 |
-
try:
|
| 1398 |
-
payload = queue_update_request(
|
| 1399 |
-
branch=parsed.branch,
|
| 1400 |
-
tag=parsed.tag,
|
| 1401 |
-
backup_usr=not parsed.no_backup,
|
| 1402 |
-
backup_path=parsed.backup_dir,
|
| 1403 |
-
backup_name=parsed.backup_name,
|
| 1404 |
-
backup_conflict_policy=parsed.backup_conflict_policy,
|
| 1405 |
-
)
|
| 1406 |
-
except Exception as exc:
|
| 1407 |
-
print(f"Failed to queue self-update: {exc}", file=sys.stderr)
|
| 1408 |
-
return 1
|
| 1409 |
-
|
| 1410 |
-
print("Queued Agent Zero self-update for the next startup attempt.")
|
| 1411 |
-
print(f"Branch: {payload['branch']}")
|
| 1412 |
-
print(f"Version: {payload['tag']}")
|
| 1413 |
-
if payload["backup_usr"]:
|
| 1414 |
-
print(f"Backup dir: {payload['backup_path']}")
|
| 1415 |
-
print(f"Backup name: {payload['backup_name']}")
|
| 1416 |
-
print(f"Backup conflict policy: {payload['backup_conflict_policy']}")
|
| 1417 |
-
else:
|
| 1418 |
-
print("Backup: disabled")
|
| 1419 |
-
print(f"Trigger file: {TRIGGER_FILE}")
|
| 1420 |
-
print(f"Log file: {LOG_FILE}")
|
| 1421 |
-
print("Restart the container or Agent Zero process to apply it.")
|
| 1422 |
-
return 0
|
| 1423 |
-
|
| 1424 |
-
|
| 1425 |
-
def docker_run_ui() -> int:
|
| 1426 |
-
request_data, raw_text = load_request_file()
|
| 1427 |
-
logger = AttemptLogger(LOG_FILE)
|
| 1428 |
-
quiet_logger = NullLogger()
|
| 1429 |
-
|
| 1430 |
-
if request_data:
|
| 1431 |
-
logger.reset()
|
| 1432 |
-
logger.log(f"Consumed update file at {TRIGGER_FILE}")
|
| 1433 |
-
logger.log_block("Trigger file content", raw_text)
|
| 1434 |
-
clean_uv_cache(logger)
|
| 1435 |
-
try:
|
| 1436 |
-
clean_transient_desktop_agent_state(REPO_DIR, logger)
|
| 1437 |
-
except Exception as exc:
|
| 1438 |
-
logger.log(f"Transient desktop agent cleanup skipped after error: {exc}")
|
| 1439 |
-
|
| 1440 |
-
try:
|
| 1441 |
-
current = get_repo_version_info(REPO_DIR)
|
| 1442 |
-
requested_branch = str(request_data.get("branch", "")).strip()
|
| 1443 |
-
requested_tag = str(request_data.get("tag", "")).strip()
|
| 1444 |
-
if installed_target_matches_request(
|
| 1445 |
-
current,
|
| 1446 |
-
requested_branch=requested_branch,
|
| 1447 |
-
requested_tag=requested_tag,
|
| 1448 |
-
):
|
| 1449 |
-
logger.log(
|
| 1450 |
-
"Requested tag already matches the installed version, skipping file replacement."
|
| 1451 |
-
)
|
| 1452 |
-
refresh_codex_cli(logger)
|
| 1453 |
-
record_result(
|
| 1454 |
-
status="skipped",
|
| 1455 |
-
message="Requested tag already matches the installed version.",
|
| 1456 |
-
request_data=request_data,
|
| 1457 |
-
source_info=current,
|
| 1458 |
-
current_version=current["short_tag"],
|
| 1459 |
-
started_at=now_iso(),
|
| 1460 |
-
rollback_applied=False,
|
| 1461 |
-
)
|
| 1462 |
-
process = launch_ui_process(REPO_DIR, logger)
|
| 1463 |
-
else:
|
| 1464 |
-
process = execute_pending_update(request_data, logger=logger)
|
| 1465 |
-
except Exception as exc:
|
| 1466 |
-
logger.log(f"Self-update bootstrap failed unexpectedly: {exc}")
|
| 1467 |
-
process = launch_ui_process(REPO_DIR, logger)
|
| 1468 |
-
elif raw_text:
|
| 1469 |
-
logger.reset()
|
| 1470 |
-
logger.log(f"Consumed invalid update file at {TRIGGER_FILE}")
|
| 1471 |
-
logger.log_block("Trigger file content", raw_text)
|
| 1472 |
-
source_info = get_repo_version_info(REPO_DIR)
|
| 1473 |
-
record_result(
|
| 1474 |
-
status="failed",
|
| 1475 |
-
message="Update file was not valid YAML.",
|
| 1476 |
-
request_data={},
|
| 1477 |
-
source_info=source_info,
|
| 1478 |
-
current_version=source_info["short_tag"],
|
| 1479 |
-
started_at=now_iso(),
|
| 1480 |
-
rollback_applied=False,
|
| 1481 |
-
error="Update file was not valid YAML.",
|
| 1482 |
-
)
|
| 1483 |
-
process = launch_ui_process(REPO_DIR, logger)
|
| 1484 |
-
else:
|
| 1485 |
-
process = launch_ui_process(REPO_DIR, quiet_logger)
|
| 1486 |
-
|
| 1487 |
-
return wait_for_process(process)
|
| 1488 |
-
|
| 1489 |
-
|
| 1490 |
-
def main(argv: list[str] | None = None) -> int:
|
| 1491 |
-
args = list(argv if argv is not None else sys.argv[1:])
|
| 1492 |
-
if not args or args[0] == "docker-run-ui":
|
| 1493 |
-
return docker_run_ui()
|
| 1494 |
-
if args[0] == "trigger-update":
|
| 1495 |
-
return trigger_update_command(args[1:])
|
| 1496 |
-
if args[0] == "refresh-codex":
|
| 1497 |
-
refresh_codex_cli(AttemptLogger(LOG_FILE))
|
| 1498 |
-
return 0
|
| 1499 |
-
if args[0] in {"-h", "--help"}:
|
| 1500 |
-
print("Usage: self_update_manager.py [docker-run-ui | trigger-update ... | refresh-codex]")
|
| 1501 |
-
return 0
|
| 1502 |
-
print(f"Unknown command: {args[0]}", file=sys.stderr)
|
| 1503 |
-
return 1
|
| 1504 |
-
|
| 1505 |
-
|
| 1506 |
-
if __name__ == "__main__":
|
| 1507 |
-
raise SystemExit(main())
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:f382c6ca87739be6bd9353616a6edc05a4eeaa0e02a6b7f970cb9f5ee25d90b4
|
| 3 |
+
size 50698
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/run/fs/exe/supervisor_event_listener.py
CHANGED
|
@@ -1,47 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
import logging
|
| 5 |
-
import subprocess
|
| 6 |
-
import time
|
| 7 |
-
|
| 8 |
-
from supervisor.childutils import listener # type: ignore
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
def main(args):
|
| 12 |
-
logging.basicConfig(stream=sys.stderr, level=logging.DEBUG, format='%(asctime)s %(levelname)s %(filename)s: %(message)s')
|
| 13 |
-
logger = logging.getLogger("supervisord-watchdog")
|
| 14 |
-
debug_mode = True if 'DEBUG' in os.environ else False
|
| 15 |
-
|
| 16 |
-
while True:
|
| 17 |
-
logger.info("Listening for events...")
|
| 18 |
-
headers, body = listener.wait(sys.stdin, sys.stdout)
|
| 19 |
-
body = dict([pair.split(":") for pair in body.split(" ")])
|
| 20 |
-
|
| 21 |
-
logger.debug("Headers: %r", repr(headers))
|
| 22 |
-
logger.debug("Body: %r", repr(body))
|
| 23 |
-
logger.debug("Args: %r", repr(args))
|
| 24 |
-
|
| 25 |
-
if debug_mode:
|
| 26 |
-
continue
|
| 27 |
-
|
| 28 |
-
try:
|
| 29 |
-
if headers["eventname"] == "PROCESS_STATE_FATAL":
|
| 30 |
-
logger.info("Process entered FATAL state...")
|
| 31 |
-
if not args or body["processname"] in args:
|
| 32 |
-
logger.error("Killing off supervisord instance ...")
|
| 33 |
-
_ = subprocess.call(["/bin/kill", "-15", "1"], stdout=sys.stderr)
|
| 34 |
-
logger.info("Sent TERM signal to init process")
|
| 35 |
-
time.sleep(5)
|
| 36 |
-
logger.critical("Why am I still alive? Send KILL to all processes...")
|
| 37 |
-
_ = subprocess.call(["/bin/kill", "-9", "-1"], stdout=sys.stderr)
|
| 38 |
-
except Exception as e:
|
| 39 |
-
logger.critical("Unexpected Exception: %s", str(e))
|
| 40 |
-
listener.fail(sys.stdout)
|
| 41 |
-
exit(1)
|
| 42 |
-
else:
|
| 43 |
-
listener.ok(sys.stdout)
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
if __name__ == '__main__':
|
| 47 |
-
main(sys.argv[1:])
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:9ff1c038b17944bf5b5d77ce5cce96fde37553a57700f13369716a39250ebb35
|
| 3 |
+
size 1670
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/run/fs/exe/trigger_self_update.sh
CHANGED
|
@@ -1,6 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
| 5 |
-
|
| 6 |
-
exec python3 "$SCRIPT_DIR/self_update_manager.py" trigger-update "$@"
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:4d011f44c92f138c0fdc4042fd04bd396f19796a11731b1ed3d5357722ee19fd
|
| 3 |
+
size 146
|
|
|
|
|
|
|
|
|
docker/run/fs/ins/copy_A0.sh
CHANGED
|
@@ -1,12 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
# Paths
|
| 5 |
-
SOURCE_DIR="/git/agent-zero"
|
| 6 |
-
TARGET_DIR="/a0"
|
| 7 |
-
|
| 8 |
-
# Copy repository files if run_ui.py is missing in /a0 (if the volume is mounted)
|
| 9 |
-
if [ ! -f "$TARGET_DIR/run_ui.py" ]; then
|
| 10 |
-
echo "Copying files from $SOURCE_DIR to $TARGET_DIR..."
|
| 11 |
-
cp -rn --no-preserve=ownership,mode "$SOURCE_DIR/." "$TARGET_DIR"
|
| 12 |
-
fi
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:bb5bc666dfb5c75d664be6c2e87a547016b36c68d821c583be59dd3168009041
|
| 3 |
+
size 331
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/run/fs/ins/install_A0.sh
CHANGED
|
@@ -1,44 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
# Exit immediately if a command exits with a non-zero status.
|
| 5 |
-
# set -e
|
| 6 |
-
|
| 7 |
-
# branch from parameter
|
| 8 |
-
if [ -z "$1" ]; then
|
| 9 |
-
echo "Error: Branch parameter is empty. Please provide a valid branch name."
|
| 10 |
-
exit 1
|
| 11 |
-
fi
|
| 12 |
-
BRANCH="$1"
|
| 13 |
-
|
| 14 |
-
if [ "$BRANCH" = "local" ]; then
|
| 15 |
-
# For local branch, use the files
|
| 16 |
-
echo "Using local dev files in /git/agent-zero"
|
| 17 |
-
# List all files recursively in the target directory
|
| 18 |
-
# echo "All files in /git/agent-zero (recursive):"
|
| 19 |
-
# find "/git/agent-zero" -type f | sort
|
| 20 |
-
else
|
| 21 |
-
# For other branches, clone from GitHub
|
| 22 |
-
echo "Cloning repository from branch $BRANCH..."
|
| 23 |
-
git clone -b "$BRANCH" "https://github.com/agent0ai/agent-zero" "/git/agent-zero" || {
|
| 24 |
-
echo "CRITICAL ERROR: Failed to clone repository. Branch: $BRANCH"
|
| 25 |
-
exit 1
|
| 26 |
-
}
|
| 27 |
-
fi
|
| 28 |
-
|
| 29 |
-
. "/ins/setup_venv.sh" "$@"
|
| 30 |
-
|
| 31 |
-
# moved to base image
|
| 32 |
-
# # Ensure the virtual environment and pip setup
|
| 33 |
-
# pip install --upgrade pip ipython requests
|
| 34 |
-
# # Install some packages in specific variants
|
| 35 |
-
# pip install torch --index-url https://download.pytorch.org/whl/cpu
|
| 36 |
-
|
| 37 |
-
# Install remaining A0 python packages
|
| 38 |
-
uv pip install -r /git/agent-zero/requirements.txt
|
| 39 |
-
|
| 40 |
-
# install playwright
|
| 41 |
-
bash /ins/install_playwright.sh "$@"
|
| 42 |
-
|
| 43 |
-
# Preload A0
|
| 44 |
-
python /git/agent-zero/preload.py --dockerized=true
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:02ac5d3e1c0f33de9956752ae32225e90eccc087e7307c6e0d40056604448622
|
| 3 |
+
size 1294
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/run/fs/ins/install_A02.sh
CHANGED
|
@@ -1,17 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
# cachebuster script, this helps speed up docker builds
|
| 5 |
-
|
| 6 |
-
# remove repo (if not local branch)
|
| 7 |
-
if [ "$1" != "local" ]; then
|
| 8 |
-
rm -rf /git/agent-zero
|
| 9 |
-
fi
|
| 10 |
-
|
| 11 |
-
# run the original install script again
|
| 12 |
-
bash /ins/install_A0.sh "$@"
|
| 13 |
-
|
| 14 |
-
# remove python packages cache
|
| 15 |
-
. "/ins/setup_venv.sh" "$@"
|
| 16 |
-
pip cache purge
|
| 17 |
-
uv cache prune
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:fd65145eed86f46ad4c83ef95ff1710bb213fc8b2f3c010210d8c1a1364e2576
|
| 3 |
+
size 332
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/run/fs/ins/install_additional.sh
CHANGED
|
@@ -1,94 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
# install playwright - moved to install A0
|
| 5 |
-
# bash /ins/install_playwright.sh "$@"
|
| 6 |
-
|
| 7 |
-
# searxng - moved to base image
|
| 8 |
-
# bash /ins/install_searxng.sh "$@"
|
| 9 |
-
|
| 10 |
-
if ! command -v apt-get >/dev/null 2>&1; then
|
| 11 |
-
echo "apt-get unavailable; skipping LibreOffice install"
|
| 12 |
-
exit 0
|
| 13 |
-
fi
|
| 14 |
-
|
| 15 |
-
KALI_SUITE="kali-last-snapshot"
|
| 16 |
-
LIBREOFFICE_VERSION="4:26.2.4.2-1"
|
| 17 |
-
XPRA_VERSION="6.5.2-r0-1"
|
| 18 |
-
arch="$(dpkg --print-architecture)"
|
| 19 |
-
|
| 20 |
-
XPRA_HTML5_VERSION="19-r1-1"
|
| 21 |
-
if [ "$arch" = "arm64" ]; then
|
| 22 |
-
XPRA_HTML5_VERSION="21-r1-1"
|
| 23 |
-
fi
|
| 24 |
-
|
| 25 |
-
LIBREOFFICE_PACKAGES=(
|
| 26 |
-
"libreoffice-core=$LIBREOFFICE_VERSION"
|
| 27 |
-
"libreoffice-writer=$LIBREOFFICE_VERSION"
|
| 28 |
-
"libreoffice-calc=$LIBREOFFICE_VERSION"
|
| 29 |
-
"libreoffice-impress=$LIBREOFFICE_VERSION"
|
| 30 |
-
"libreoffice-gtk3=$LIBREOFFICE_VERSION"
|
| 31 |
-
"python3-uno=$LIBREOFFICE_VERSION"
|
| 32 |
-
)
|
| 33 |
-
XPRA_PACKAGES=(
|
| 34 |
-
"xpra-common=$XPRA_VERSION"
|
| 35 |
-
"xpra-server=$XPRA_VERSION"
|
| 36 |
-
"xpra-client=$XPRA_VERSION"
|
| 37 |
-
"xpra-client-gtk3=$XPRA_VERSION"
|
| 38 |
-
"xpra-x11=$XPRA_VERSION"
|
| 39 |
-
"xpra-html5=$XPRA_HTML5_VERSION"
|
| 40 |
-
)
|
| 41 |
-
|
| 42 |
-
apt-get update
|
| 43 |
-
ATK_VERSION="$(dpkg-query -W -f='${Version}' libatk1.0-0t64)"
|
| 44 |
-
ATK_GIR_PACKAGE="/tmp/gir1.2-atk-1.0_${ATK_VERSION}_${arch}.deb"
|
| 45 |
-
(cd /tmp && apt-get download "gir1.2-atk-1.0=$ATK_VERSION")
|
| 46 |
-
|
| 47 |
-
for source in /etc/apt/sources.list /etc/apt/sources.list.d/kali.sources; do
|
| 48 |
-
[ ! -f "$source" ] || sed -i "s/kali-rolling/$KALI_SUITE/g" "$source"
|
| 49 |
-
done
|
| 50 |
-
|
| 51 |
-
apt-get update
|
| 52 |
-
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends ca-certificates wget
|
| 53 |
-
wget -O /usr/share/keyrings/xpra.asc https://xpra.org/xpra.asc
|
| 54 |
-
cat >/etc/apt/sources.list.d/xpra.sources <<EOF
|
| 55 |
-
Types: deb
|
| 56 |
-
URIs: https://xpra.org
|
| 57 |
-
Suites: trixie
|
| 58 |
-
Components: main
|
| 59 |
-
Signed-By: /usr/share/keyrings/xpra.asc
|
| 60 |
-
Architectures: $arch
|
| 61 |
-
EOF
|
| 62 |
-
apt-get update
|
| 63 |
-
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
| 64 |
-
"$ATK_GIR_PACKAGE" \
|
| 65 |
-
gir1.2-gtk-3.0 \
|
| 66 |
-
"${LIBREOFFICE_PACKAGES[@]}" \
|
| 67 |
-
"${XPRA_PACKAGES[@]}" \
|
| 68 |
-
xfce4-session \
|
| 69 |
-
xfwm4 \
|
| 70 |
-
xfce4-panel \
|
| 71 |
-
xfdesktop4 \
|
| 72 |
-
xfce4-settings \
|
| 73 |
-
thunar \
|
| 74 |
-
gvfs \
|
| 75 |
-
libglib2.0-bin \
|
| 76 |
-
xfce4-terminal \
|
| 77 |
-
x11-xserver-utils \
|
| 78 |
-
x11-utils \
|
| 79 |
-
x11-apps \
|
| 80 |
-
xdotool \
|
| 81 |
-
xclip \
|
| 82 |
-
xauth \
|
| 83 |
-
xvfb \
|
| 84 |
-
dbus-x11 \
|
| 85 |
-
fonts-dejavu \
|
| 86 |
-
fonts-liberation \
|
| 87 |
-
fonts-crosextra-caladea \
|
| 88 |
-
fonts-crosextra-carlito \
|
| 89 |
-
fonts-noto-core \
|
| 90 |
-
fonts-noto-cjk \
|
| 91 |
-
fonts-noto-color-emoji
|
| 92 |
-
|
| 93 |
-
rm -f "$ATK_GIR_PACKAGE"
|
| 94 |
-
rm -rf /var/lib/apt/lists/*
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a9d95cfdeef8d7b0fd8f21cce0662d06b047b914dbc294fb7e90d43ce7cc193f
|
| 3 |
+
size 2351
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/run/fs/ins/install_playwright.sh
CHANGED
|
@@ -1,13 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
# activate venv
|
| 5 |
-
. "/ins/setup_venv.sh" "$@"
|
| 6 |
-
|
| 7 |
-
# set PW installation path to temporary Browser runtime storage
|
| 8 |
-
export PLAYWRIGHT_BROWSERS_PATH=/a0/tmp/playwright
|
| 9 |
-
mkdir -p "$PLAYWRIGHT_BROWSERS_PATH"
|
| 10 |
-
|
| 11 |
-
# preinstall Chromium for fresh images; the Browser hook also reconciles self-updated installs
|
| 12 |
-
apt-get install -y fonts-unifont libnss3 libnspr4 libatk1.0-0 libatspi2.0-0 libxcomposite1 libxdamage1 libatk-bridge2.0-0 libcups2
|
| 13 |
-
patchright install chromium --no-shell
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:b9658612a888db9185d04b10ec494610ee8815f6f2af2150bd8af7626d4ebf6d
|
| 3 |
+
size 483
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/run/fs/ins/post_install.sh
CHANGED
|
@@ -1,6 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
# Cleanup package list
|
| 5 |
-
rm -rf /var/lib/apt/lists/*
|
| 6 |
-
apt-get clean
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:0376af94660898f1c53428fe141a801baf201c5384503b91f0f86f776ebb4245
|
| 3 |
+
size 84
|
|
|
|
|
|
|
|
|
docker/run/fs/ins/pre_install.sh
CHANGED
|
@@ -1,13 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
# update apt
|
| 5 |
-
apt-get update
|
| 6 |
-
|
| 7 |
-
# fix permissions for cron files if any
|
| 8 |
-
if [ -f /etc/cron.d/* ]; then
|
| 9 |
-
chmod 0644 /etc/cron.d/*
|
| 10 |
-
fi
|
| 11 |
-
|
| 12 |
-
# Prepare SSH daemon
|
| 13 |
-
bash /ins/setup_ssh.sh "$@"
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6763aa5590db64648382903da34388531630c711c7cd58c84735746b6c97cce9
|
| 3 |
+
size 201
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/run/fs/ins/setup_ssh.sh
CHANGED
|
@@ -1,7 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
# Set up SSH
|
| 5 |
-
mkdir -p /var/run/sshd && \
|
| 6 |
-
# echo 'root:toor' | chpasswd && \
|
| 7 |
-
sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:838d4044464ff4dbcbf09a1d05e16189a5678963283591bee446a37a37c984f9
|
| 3 |
+
size 191
|
|
|
|
|
|
|
|
|
|
|
|
docker/run/fs/ins/setup_venv.sh
CHANGED
|
@@ -1,12 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
# this has to be ready from base image
|
| 5 |
-
# if [ ! -d /opt/venv ]; then
|
| 6 |
-
# # Create and activate Python virtual environment
|
| 7 |
-
# python3.12 -m venv /opt/venv
|
| 8 |
-
# source /opt/venv/bin/activate
|
| 9 |
-
# else
|
| 10 |
-
# source /opt/venv/bin/activate
|
| 11 |
-
# fi
|
| 12 |
-
source /opt/venv-a0/bin/activate
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ad753d8637f7cd7b0186bc012434f2ce4834c62942b032d1b93a0facd2b7eed2
|
| 3 |
+
size 295
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/run/fs/per/root/.bashrc
CHANGED
|
@@ -1,9 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
if [ -f /etc/bashrc ]; then
|
| 5 |
-
. /etc/bashrc
|
| 6 |
-
fi
|
| 7 |
-
|
| 8 |
-
# Activate the virtual environment
|
| 9 |
-
source /opt/venv/bin/activate
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d29ad830f8c27e14002e059df2bd7a57138cf59e109e492b9727a3226f86573a
|
| 3 |
+
size 154
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/run/fs/per/root/.profile
CHANGED
|
@@ -1,9 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
if [ -f /etc/bashrc ]; then
|
| 5 |
-
. /etc/bashrc
|
| 6 |
-
fi
|
| 7 |
-
|
| 8 |
-
# Activate the virtual environment
|
| 9 |
-
source /opt/venv/bin/activate
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d29ad830f8c27e14002e059df2bd7a57138cf59e109e492b9727a3226f86573a
|
| 3 |
+
size 154
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/AGENTS.md
CHANGED
|
@@ -1,35 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
- Own human-facing documentation, screenshots, setup guides, developer guides, and documentation assets.
|
| 6 |
-
- Keep docs accurate to current source behavior and practical user workflows.
|
| 7 |
-
|
| 8 |
-
## Ownership
|
| 9 |
-
|
| 10 |
-
- `README.md`, `quickstart.md`, `guides/`, and `setup/` cover user-facing setup and workflows.
|
| 11 |
-
- `developer/` covers compact developer references and source handoffs.
|
| 12 |
-
- `plans/` covers implementation plans, migration notes, and staged technical roadmaps.
|
| 13 |
-
- `res/` contains documentation images and other documentation assets.
|
| 14 |
-
|
| 15 |
-
## Local Contracts
|
| 16 |
-
|
| 17 |
-
- Prefer local docs for practical workflows and direct users to DeepWiki for source-linked internals when appropriate.
|
| 18 |
-
- Do not document secrets, private deployment details, unreleased credentials, or user-specific runtime state.
|
| 19 |
-
- Screenshots and assets must be relevant to the documented UI state and should be updated when UI changes make them misleading.
|
| 20 |
-
- Keep links relative inside the docs tree unless they intentionally point to external community or reference resources.
|
| 21 |
-
|
| 22 |
-
## Work Guidance
|
| 23 |
-
|
| 24 |
-
- Update docs in the same change when user-visible behavior, setup steps, settings names, plugin workflows, or UI labels change.
|
| 25 |
-
- Keep user guides task-oriented and avoid duplicating architecture contracts already owned by source-adjacent DOX files.
|
| 26 |
-
- When editing screenshots or binary assets, avoid unrelated metadata churn.
|
| 27 |
-
|
| 28 |
-
## Verification
|
| 29 |
-
|
| 30 |
-
- Check changed internal links manually or with an available link checker.
|
| 31 |
-
- For setup or Docker docs, verify commands against current scripts and Docker files.
|
| 32 |
-
|
| 33 |
-
## Child DOX Index
|
| 34 |
-
|
| 35 |
-
No child DOX files.
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:e058179b520b1f87231b052f58d4e250898631afc13d41c78adf72de691b9126
|
| 3 |
+
size 1625
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/README.md
CHANGED
|
@@ -1,159 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
Welcome to the Agent Zero documentation hub. Start with the practical guides
|
| 5 |
-
below: install it, open the Web UI, connect your host machine when needed, and
|
| 6 |
-
learn the main workflows by sight.
|
| 7 |
-
|
| 8 |
-
For architecture and source-linked internals, use
|
| 9 |
-
[DeepWiki for Agent Zero](https://deepwiki.com/agent0ai/agent-zero). The local
|
| 10 |
-
docs focus on practical setup, screenshots, and user workflows.
|
| 11 |
-
|
| 12 |
-
## Quick Start
|
| 13 |
-
|
| 14 |
-
- **[Quickstart Guide](quickstart.md):** Get up and running in 5 minutes with Agent Zero.
|
| 15 |
-
- **[Agent Zero Launcher](guides/launcher.md):** Use the desktop app to set up Docker, install Agent Zero, open Instances, or connect a remote Instance.
|
| 16 |
-
- **[First-Run Onboarding](guides/onboarding.md):** Choose Cloud, AI account, or Local access, then select main and utility models.
|
| 17 |
-
- **[Installation Guide](setup/installation.md):** A0 Launcher downloads, A0 Install, direct Docker, updates, and advanced Docker setup (includes [How to Update](setup/installation.md#how-to-update-agent-zero)).
|
| 18 |
-
- **[A0 CLI Connector](guides/a0-cli-connector.md):** Install the host connector for a running Agent Zero instance, use the command palette, and switch Browser modes.
|
| 19 |
-
- **[Self Update](guides/self-update.md):** How the in-app updater works (technical reference).
|
| 20 |
-
- **[VPS Deployment](setup/vps-deployment.md):** Deploy Agent Zero on a remote server.
|
| 21 |
-
- **[Development Setup](setup/dev-setup.md):** Set up a local development environment.
|
| 22 |
-
|
| 23 |
-
## User Guides
|
| 24 |
-
|
| 25 |
-
- **[Usage Guide](guides/usage.md):** Practical tour of Agent Zero's main workflows.
|
| 26 |
-
- **[Agent Zero Launcher](guides/launcher.md):** Fresh-machine Launcher walkthrough, Docker setup gate, Installs, Instances, and docs screenshot capture with Playwright/Electron.
|
| 27 |
-
- **[First-Run Onboarding](guides/onboarding.md):** Set up OpenRouter, our proxy API or another provider with the guided wizard.
|
| 28 |
-
- **[Browser Guide](guides/browser.md):** Use the built-in Browser, live Canvas surface, annotations, screenshots, host browser mode, and extensions.
|
| 29 |
-
- **[Desktop Guide](guides/desktop.md):** Use the built-in Linux desktop, GUI apps, and LibreOffice Writer/Calc/Impress Cowork.
|
| 30 |
-
- **[A0 CLI Connector](guides/a0-cli-connector.md):** Terminal-first host connector for Agent Zero, with screenshots of the host picker, connected shell, command palette, and Browser modes.
|
| 31 |
-
- **[Create a Small Plugin](guides/create-plugin.md):** Build and review a tiny Web UI plugin that adds an unread dot to the chat list.
|
| 32 |
-
- **[Skills Guide](guides/skills.md):** Open the Skills selector, add active skills, and remove prompt protocol entries you no longer need.
|
| 33 |
-
- **[Agent Profiles](guides/agent-profiles.md):** Create and manage profiles in Easy or Advanced mode, set project availability, and control Tool, MCP, and Skill access.
|
| 34 |
-
- **[Model Presets](guides/model-presets.md):** Create simple named shortcuts for model setups.
|
| 35 |
-
- **[Memory Guide](guides/memory.md):** Search, edit, delete, and curate memories so useful context does not become stale noise.
|
| 36 |
-
- **[Projects Tutorial](guides/projects.md):** Learn to create isolated workspaces with dedicated context and memory.
|
| 37 |
-
- **[API Integration](guides/api-integration.md):** Add external APIs without writing code.
|
| 38 |
-
- **[MCP Setup](guides/mcp-setup.md):** Configure Model Context Protocol servers.
|
| 39 |
-
- **[A2A Setup](guides/a2a-setup.md):** Enable agent-to-agent communication.
|
| 40 |
-
- **[Troubleshooting](guides/troubleshooting.md):** Solutions to common issues and FAQs.
|
| 41 |
-
|
| 42 |
-
## Technical Reference
|
| 43 |
-
|
| 44 |
-
- **[DeepWiki for Agent Zero](https://deepwiki.com/agent0ai/agent-zero):** Architecture, Web UI internals, plugin lifecycle, backend APIs, deployment details, and source-linked explanations.
|
| 45 |
-
- **[Architecture](developer/architecture.md):** Short local handoff to DeepWiki plus practical starting points.
|
| 46 |
-
- **[Plugins](developer/plugins.md):** Compact plugin starting points and sharing checklist.
|
| 47 |
-
- **[Extensions](developer/extensions.md):** Short guide for when an extension is the right tool.
|
| 48 |
-
- **[Connectivity](developer/connectivity.md):** Choose between A0 CLI, MCP, A2A, and external APIs.
|
| 49 |
-
- **[WebSockets](developer/websockets.md):** Short local handoff to DeepWiki and source files.
|
| 50 |
-
- **[MCP Configuration](developer/mcp-configuration.md):** Compact reference for MCP JSON.
|
| 51 |
-
- **[Notifications](developer/notifications.md):** Notification system architecture and setup.
|
| 52 |
-
- **[Contributing Skills](developer/contributing-skills.md):** Create and share agent skills.
|
| 53 |
-
- **[Contributing Guide](guides/contribution.md):** Contribute to the Agent Zero project.
|
| 54 |
-
|
| 55 |
-
## Community & Support
|
| 56 |
-
|
| 57 |
-
- **Join the Community:** Connect with other users on [Discord](https://discord.gg/B8KZKNsPpj) to discuss ideas, ask questions, and collaborate.
|
| 58 |
-
- **Share Your Work:** Show off your Agent Zero creations and workflows in the [Show and Tell](https://github.com/agent0ai/agent-zero/discussions/categories/show-and-tell) area.
|
| 59 |
-
- **Report Issues:** Use the [GitHub issue tracker](https://github.com/agent0ai/agent-zero/issues) to report bugs or suggest features.
|
| 60 |
-
- **Follow Updates:** Subscribe to the [YouTube channel](https://www.youtube.com/@AgentZeroFW) for tutorials and release videos.
|
| 61 |
-
|
| 62 |
-
---
|
| 63 |
-
|
| 64 |
-
## Table of Contents
|
| 65 |
-
|
| 66 |
-
- [Quick Start](#quick-start)
|
| 67 |
-
- [Quickstart Guide](quickstart.md)
|
| 68 |
-
- [Agent Zero Launcher](guides/launcher.md)
|
| 69 |
-
- [First-Run Onboarding](guides/onboarding.md)
|
| 70 |
-
- [Installation Guide](setup/installation.md)
|
| 71 |
-
- [How to Update Agent Zero](setup/installation.md#how-to-update-agent-zero)
|
| 72 |
-
- [Manual Installation (Advanced)](setup/installation.md#manual-installation-advanced)
|
| 73 |
-
- [Step 1: Install Docker Desktop](setup/installation.md#step-1-install-docker-desktop)
|
| 74 |
-
- [Windows Installation](setup/installation.md#windows-installation)
|
| 75 |
-
- [macOS Installation](setup/installation.md#macos-installation)
|
| 76 |
-
- [Linux Installation](setup/installation.md#linux-installation)
|
| 77 |
-
- [Step 2: Run Agent Zero](setup/installation.md#step-2-run-agent-zero)
|
| 78 |
-
- [Pull Docker Image](setup/installation.md#21-pull-the-agent-zero-docker-image)
|
| 79 |
-
- [Map Folders for Persistence](setup/installation.md#22-optional-map-folders-for-persistence)
|
| 80 |
-
- [Run the Container](setup/installation.md#23-run-the-container)
|
| 81 |
-
- [Access the Web UI](setup/installation.md#24-access-the-web-ui)
|
| 82 |
-
- [Step 3: Configure Agent Zero](setup/installation.md#step-3-configure-agent-zero)
|
| 83 |
-
- [Settings Configuration](setup/installation.md#settings-configuration)
|
| 84 |
-
- [Agent Configuration](setup/installation.md#agent-configuration)
|
| 85 |
-
- [Chat Model Settings](setup/installation.md#chat-model-settings)
|
| 86 |
-
- [API Keys](setup/installation.md#api-keys)
|
| 87 |
-
- [Authentication](setup/installation.md#authentication)
|
| 88 |
-
- [Choosing Your LLMs](setup/installation.md#choosing-your-llms)
|
| 89 |
-
- [Installing Ollama (Local Models)](setup/installation.md#installing-and-using-ollama-local-models)
|
| 90 |
-
- [Using on Mobile Devices](setup/installation.md#using-agent-zero-on-your-mobile-device)
|
| 91 |
-
- [Self Update (technical)](guides/self-update.md)
|
| 92 |
-
- [VPS Deployment](setup/vps-deployment.md)
|
| 93 |
-
- [Development Setup](setup/dev-setup.md)
|
| 94 |
-
- [A0 CLI Connector](guides/a0-cli-connector.md)
|
| 95 |
-
|
| 96 |
-
- [User Guides](#user-guides)
|
| 97 |
-
- [Usage Guide](guides/usage.md)
|
| 98 |
-
- [Basic Operations](guides/usage.md#basic-operations)
|
| 99 |
-
- [Plugins And Plugin Hub](guides/usage.md#plugins-and-plugin-hub)
|
| 100 |
-
- [Skills, Agent Profiles, And Model Presets](guides/usage.md#skills-agent-profiles-and-model-presets)
|
| 101 |
-
- [Skills](guides/usage.md#skills)
|
| 102 |
-
- [Agent Profiles](guides/usage.md#agent-profiles)
|
| 103 |
-
- [Model Presets](guides/usage.md#model-presets)
|
| 104 |
-
- [File Attachments](guides/usage.md#file-attachments)
|
| 105 |
-
- [Tool Usage](guides/usage.md#tool-usage)
|
| 106 |
-
- [Browser Tool And Surface](guides/usage.md#browser-tool-and-surface)
|
| 107 |
-
- [Desktop Surface](guides/usage.md#desktop-surface)
|
| 108 |
-
- [Agent-To-Agent Communication](guides/usage.md#agent-to-agent-communication)
|
| 109 |
-
- [Multi-Agent Cooperation](guides/usage.md#multi-agent-cooperation)
|
| 110 |
-
- [Projects](guides/usage.md#projects)
|
| 111 |
-
- [Tasks And Scheduling](guides/usage.md#tasks-and-scheduling)
|
| 112 |
-
- [Secrets And Variables](guides/usage.md#secrets-and-variables)
|
| 113 |
-
- [Remote Access Via Tunneling](guides/usage.md#remote-access-via-tunneling)
|
| 114 |
-
- [Voice Interface](guides/usage.md#voice-interface)
|
| 115 |
-
- [Mathematical Expressions](guides/usage.md#mathematical-expressions)
|
| 116 |
-
- [File Browser](guides/usage.md#file-browser)
|
| 117 |
-
- [Memory Management](guides/usage.md#memory-management)
|
| 118 |
-
- [Backup And Restore](guides/usage.md#backup-and-restore)
|
| 119 |
-
- [Agent Zero Launcher](guides/launcher.md)
|
| 120 |
-
- [Browser Guide](guides/browser.md)
|
| 121 |
-
- [Desktop Guide](guides/desktop.md)
|
| 122 |
-
- [A0 CLI Connector](guides/a0-cli-connector.md)
|
| 123 |
-
- [Create a Small Plugin](guides/create-plugin.md)
|
| 124 |
-
- [Skills Guide](guides/skills.md)
|
| 125 |
-
- [Agent Profiles](guides/agent-profiles.md)
|
| 126 |
-
- [Model Presets](guides/model-presets.md)
|
| 127 |
-
- [Memory Guide](guides/memory.md)
|
| 128 |
-
- [Projects Tutorial](guides/projects.md)
|
| 129 |
-
- [API Integration](guides/api-integration.md)
|
| 130 |
-
- [MCP Setup](guides/mcp-setup.md)
|
| 131 |
-
- [A2A Setup](guides/a2a-setup.md)
|
| 132 |
-
- [Troubleshooting](guides/troubleshooting.md)
|
| 133 |
-
|
| 134 |
-
- [Technical Reference](#technical-reference)
|
| 135 |
-
- [DeepWiki for Agent Zero](https://deepwiki.com/agent0ai/agent-zero)
|
| 136 |
-
- [Architecture](developer/architecture.md)
|
| 137 |
-
- [Plugins](developer/plugins.md)
|
| 138 |
-
- [Extensions](developer/extensions.md)
|
| 139 |
-
- [Connectivity](developer/connectivity.md)
|
| 140 |
-
- [WebSockets](developer/websockets.md)
|
| 141 |
-
- [MCP Configuration](developer/mcp-configuration.md)
|
| 142 |
-
- [Notifications](developer/notifications.md)
|
| 143 |
-
- [Contributing Skills](developer/contributing-skills.md)
|
| 144 |
-
- [Contributing Guide](guides/contribution.md)
|
| 145 |
-
|
| 146 |
-
---
|
| 147 |
-
|
| 148 |
-
## Documentation Ownership
|
| 149 |
-
|
| 150 |
-
| Content type | Home |
|
| 151 |
-
| --- | --- |
|
| 152 |
-
| Setup, screenshots, and everyday workflows | These docs |
|
| 153 |
-
| Architecture and source-linked internals | [DeepWiki](https://deepwiki.com/agent0ai/agent-zero) |
|
| 154 |
-
| Exact behavior | The current source code |
|
| 155 |
-
| Community help and examples | Discord, Skool, GitHub discussions |
|
| 156 |
-
|
| 157 |
-
### Your journey with Agent Zero starts now!
|
| 158 |
-
|
| 159 |
-
Ready to dive in? Start with the [Quickstart Guide](quickstart.md) for the fastest path to your first chat, or follow the [Installation Guide](setup/installation.md) for a detailed setup walkthrough.
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:5acb9756eca09fa8de40d237bfead984b1071ee24a9838bfb0c8fd3ca24f6f8b
|
| 3 |
+
size 10383
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/developer/architecture.md
CHANGED
|
@@ -1,32 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
[DeepWiki for Agent Zero](https://deepwiki.com/agent0ai/agent-zero).
|
| 5 |
-
|
| 6 |
-
Use DeepWiki when you want source-linked explanations of:
|
| 7 |
-
|
| 8 |
-
- the agent loop and message flow;
|
| 9 |
-
- Web UI internals;
|
| 10 |
-
- plugin discovery and lifecycle;
|
| 11 |
-
- projects, memory, tools, and scheduler internals;
|
| 12 |
-
- backend APIs and WebSocket behavior;
|
| 13 |
-
- deployment and runtime structure.
|
| 14 |
-
|
| 15 |
-
This local page intentionally stays short so the repository does not maintain a
|
| 16 |
-
second, stale architecture manual.
|
| 17 |
-
|
| 18 |
-
## Practical Starting Points
|
| 19 |
-
|
| 20 |
-
| Goal | Start here |
|
| 21 |
-
| --- | --- |
|
| 22 |
-
| Install or update Agent Zero | [Installation Guide](../setup/installation.md) |
|
| 23 |
-
| Learn the Web UI | [Usage Guide](../guides/usage.md) |
|
| 24 |
-
| Create a focused workspace | [Projects Guide](../guides/projects.md) |
|
| 25 |
-
| Use the Browser | [Browser Guide](../guides/browser.md) |
|
| 26 |
-
| Connect host files and shell | [A0 CLI Connector](../guides/a0-cli-connector.md) |
|
| 27 |
-
| Build plugins | [Plugins](plugins.md) |
|
| 28 |
-
| Build extensions | [Extensions](extensions.md) |
|
| 29 |
-
| Configure MCP | [MCP Configuration](mcp-configuration.md) |
|
| 30 |
-
|
| 31 |
-
If you are changing core behavior, read the relevant DeepWiki page first, then
|
| 32 |
-
inspect the source in this repository before editing.
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:fe7e91408016bf1d7d6e1c172a5beadb9681e62e7522231fbfebbb04fc9c40c5
|
| 3 |
+
size 1235
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/developer/connectivity.md
CHANGED
|
@@ -1,55 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
For source-linked architecture and endpoint internals, use
|
| 6 |
-
[DeepWiki for Agent Zero](https://deepwiki.com/agent0ai/agent-zero). The local
|
| 7 |
-
docs should not duplicate the full connectivity architecture.
|
| 8 |
-
|
| 9 |
-
## Choose The Right Path
|
| 10 |
-
|
| 11 |
-
| Need | Start here |
|
| 12 |
-
| --- | --- |
|
| 13 |
-
| Let Agent Zero work on your host files, shell, or browser | [A0 CLI Connector](../guides/a0-cli-connector.md) |
|
| 14 |
-
| Add a third-party tool through MCP | [MCP Setup](../guides/mcp-setup.md) |
|
| 15 |
-
| Let another agent talk to Agent Zero | [A2A Setup](../guides/a2a-setup.md) |
|
| 16 |
-
| Add an external API for one workflow | [API Integration](../guides/api-integration.md) |
|
| 17 |
-
| Study API, MCP, or A2A internals | [DeepWiki](https://deepwiki.com/agent0ai/agent-zero) |
|
| 18 |
-
|
| 19 |
-
## External API Basics
|
| 20 |
-
|
| 21 |
-
You can find your API token in Agent Zero under **Settings > External Services**.
|
| 22 |
-
|
| 23 |
-
Common external endpoints include:
|
| 24 |
-
|
| 25 |
-
| Endpoint | Use it for |
|
| 26 |
-
| --- | --- |
|
| 27 |
-
| `POST /api_message` | Send a message to Agent Zero. |
|
| 28 |
-
| `GET/POST /api_log_get` | Read chat logs. |
|
| 29 |
-
| `POST /api_terminate_chat` | Stop a running chat. |
|
| 30 |
-
| `POST /api_reset_chat` | Reset a chat. |
|
| 31 |
-
| `POST /api_files_get` | Retrieve files. |
|
| 32 |
-
|
| 33 |
-
External API calls use the `X-API-KEY` header.
|
| 34 |
-
|
| 35 |
-
> [!TIP]
|
| 36 |
-
> For exact request and response details, check the current source or the
|
| 37 |
-
> matching DeepWiki page. That keeps the API reference tied to the code that is
|
| 38 |
-
> actually running.
|
| 39 |
-
|
| 40 |
-
## MCP And A2A
|
| 41 |
-
|
| 42 |
-
Use MCP when you want Agent Zero to call tools from another app or service.
|
| 43 |
-
|
| 44 |
-
Use A2A when you want another agent to talk to Agent Zero as a collaborator.
|
| 45 |
-
|
| 46 |
-
Both use the same Agent Zero instance and can be project-aware when configured
|
| 47 |
-
that way.
|
| 48 |
-
|
| 49 |
-
## Related
|
| 50 |
-
|
| 51 |
-
- [A0 CLI Connector](../guides/a0-cli-connector.md)
|
| 52 |
-
- [MCP Setup](../guides/mcp-setup.md)
|
| 53 |
-
- [A2A Setup](../guides/a2a-setup.md)
|
| 54 |
-
- [API Integration](../guides/api-integration.md)
|
| 55 |
-
- [DeepWiki for Agent Zero](https://deepwiki.com/agent0ai/agent-zero)
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:c0b8be750e59d57424cf3077ea07d71020f7c1e727eb72d58e203f51d5def254
|
| 3 |
+
size 1968
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/developer/contributing-skills.md
CHANGED
|
@@ -1,395 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
---
|
| 6 |
-
|
| 7 |
-
## What is a Skill?
|
| 8 |
-
|
| 9 |
-
A **Skill** is a contextual expertise module that provides the AI agent with specialized knowledge and procedures for specific tasks. Unlike tools (which are always loaded), skills are **surfaced via description/tag matching** when relevant, making them token-efficient and context-aware.
|
| 10 |
-
|
| 11 |
-
### Skills vs Tools vs Knowledge
|
| 12 |
-
|
| 13 |
-
| Aspect | Skills | Tools | Knowledge |
|
| 14 |
-
|--------|--------|-------|-----------|
|
| 15 |
-
| **Loading** | Description/tag matching | Always in prompt | Semantic recall |
|
| 16 |
-
| **Purpose** | Procedures & expertise | Actions & functions | Facts & data |
|
| 17 |
-
| **Format** | SKILL.md (YAML + Markdown) | Python/code | Text/documents |
|
| 18 |
-
| **When to use** | "How to do X" | "Do X now" | "What is X" |
|
| 19 |
-
|
| 20 |
-
### Cross-Platform Compatibility
|
| 21 |
-
|
| 22 |
-
The SKILL.md standard is compatible with:
|
| 23 |
-
- **Agent Zero** (this project)
|
| 24 |
-
- **Claude Code** (Anthropic)
|
| 25 |
-
- **Cursor** (AI IDE)
|
| 26 |
-
- **OpenAI Codex CLI**
|
| 27 |
-
- **GitHub Copilot**
|
| 28 |
-
- **Goose** (Block)
|
| 29 |
-
|
| 30 |
-
Skills you create here can be used in any of these platforms!
|
| 31 |
-
|
| 32 |
-
---
|
| 33 |
-
|
| 34 |
-
## Quick Start
|
| 35 |
-
|
| 36 |
-
### Using the CLI (Recommended)
|
| 37 |
-
|
| 38 |
-
```bash
|
| 39 |
-
# Create a new skill interactively
|
| 40 |
-
python -m helpers.skills_cli create my-skill-name
|
| 41 |
-
|
| 42 |
-
# List all available skills
|
| 43 |
-
python -m helpers.skills_cli list
|
| 44 |
-
|
| 45 |
-
# Validate a skill
|
| 46 |
-
python -m helpers.skills_cli validate my-skill-name
|
| 47 |
-
|
| 48 |
-
# Search skills
|
| 49 |
-
python -m helpers.skills_cli search "keyword"
|
| 50 |
-
```
|
| 51 |
-
|
| 52 |
-
### Manual Creation
|
| 53 |
-
|
| 54 |
-
1. Create a folder in `usr/skills/` with your skill name
|
| 55 |
-
2. Add a `SKILL.md` file with YAML frontmatter
|
| 56 |
-
3. Optionally add supporting scripts (`.py`, `.sh`, `.js`)
|
| 57 |
-
|
| 58 |
-
---
|
| 59 |
-
|
| 60 |
-
## SKILL.md Standard
|
| 61 |
-
|
| 62 |
-
Every skill must have a `SKILL.md` file with this structure:
|
| 63 |
-
|
| 64 |
-
```markdown
|
| 65 |
-
---
|
| 66 |
-
name: "skill-name"
|
| 67 |
-
description: "A clear, concise description of what this skill does and when to use it"
|
| 68 |
-
version: "1.0.0"
|
| 69 |
-
author: "Your Name <email@example.com>"
|
| 70 |
-
license: "MIT"
|
| 71 |
-
tags: ["category", "purpose", "technology"]
|
| 72 |
-
triggers:
|
| 73 |
-
- "keyword that activates this skill"
|
| 74 |
-
- "another trigger phrase"
|
| 75 |
-
allowed_tools:
|
| 76 |
-
- tool_name
|
| 77 |
-
- another_tool
|
| 78 |
-
metadata:
|
| 79 |
-
complexity: "beginner|intermediate|advanced"
|
| 80 |
-
category: "development|devops|data|productivity|creative"
|
| 81 |
-
estimated_time: "5 minutes"
|
| 82 |
-
---
|
| 83 |
-
|
| 84 |
-
# Skill Name
|
| 85 |
-
|
| 86 |
-
## Overview
|
| 87 |
-
|
| 88 |
-
Brief description of what this skill accomplishes.
|
| 89 |
-
|
| 90 |
-
## When to Use
|
| 91 |
-
|
| 92 |
-
- Situation 1 where this skill applies
|
| 93 |
-
- Situation 2 where this skill applies
|
| 94 |
-
|
| 95 |
-
## Instructions
|
| 96 |
-
|
| 97 |
-
### Step 1: First Step
|
| 98 |
-
|
| 99 |
-
Detailed instructions...
|
| 100 |
-
|
| 101 |
-
### Step 2: Second Step
|
| 102 |
-
|
| 103 |
-
More instructions...
|
| 104 |
-
|
| 105 |
-
## Examples
|
| 106 |
-
|
| 107 |
-
### Example 1: Basic Usage
|
| 108 |
-
|
| 109 |
-
\`\`\`python
|
| 110 |
-
# Code example
|
| 111 |
-
\`\`\`
|
| 112 |
-
|
| 113 |
-
### Example 2: Advanced Usage
|
| 114 |
-
|
| 115 |
-
\`\`\`python
|
| 116 |
-
# Advanced code example
|
| 117 |
-
\`\`\`
|
| 118 |
-
|
| 119 |
-
## Common Pitfalls
|
| 120 |
-
|
| 121 |
-
- Pitfall 1 and how to avoid it
|
| 122 |
-
- Pitfall 2 and how to avoid it
|
| 123 |
-
|
| 124 |
-
## Related Skills
|
| 125 |
-
|
| 126 |
-
- `related-skill-1`
|
| 127 |
-
- `related-skill-2`
|
| 128 |
-
```
|
| 129 |
-
|
| 130 |
-
### Required Fields
|
| 131 |
-
|
| 132 |
-
| Field | Description |
|
| 133 |
-
|-------|-------------|
|
| 134 |
-
| `name` | Unique identifier (lowercase, hyphens allowed) |
|
| 135 |
-
| `description` | What the skill does (used for semantic matching) |
|
| 136 |
-
|
| 137 |
-
### Optional Fields
|
| 138 |
-
|
| 139 |
-
| Field | Description |
|
| 140 |
-
|-------|-------------|
|
| 141 |
-
| `version` | Semantic version (e.g., "1.0.0") |
|
| 142 |
-
| `author` | Your name and email |
|
| 143 |
-
| `license` | License (MIT, Apache-2.0, etc.) |
|
| 144 |
-
| `tags` | Categories for discovery |
|
| 145 |
-
| `triggers` | Phrases that activate this skill |
|
| 146 |
-
| `allowed_tools` | Tools this skill can use |
|
| 147 |
-
| `metadata` | Additional structured data |
|
| 148 |
-
|
| 149 |
-
---
|
| 150 |
-
|
| 151 |
-
## Creating Your First Skill
|
| 152 |
-
|
| 153 |
-
### Step 1: Identify the Need
|
| 154 |
-
|
| 155 |
-
Ask yourself:
|
| 156 |
-
- What expertise would help the agent?
|
| 157 |
-
- When should this skill be activated?
|
| 158 |
-
- What steps should the agent follow?
|
| 159 |
-
|
| 160 |
-
### Step 2: Create the Structure
|
| 161 |
-
|
| 162 |
-
```bash
|
| 163 |
-
# Using CLI
|
| 164 |
-
python -m helpers.skills_cli create my-awesome-skill
|
| 165 |
-
|
| 166 |
-
# Or manually
|
| 167 |
-
mkdir -p usr/skills/my-awesome-skill
|
| 168 |
-
touch usr/skills/my-awesome-skill/SKILL.md
|
| 169 |
-
```
|
| 170 |
-
|
| 171 |
-
### Step 3: Write the SKILL.md
|
| 172 |
-
|
| 173 |
-
```markdown
|
| 174 |
-
---
|
| 175 |
-
name: "my-awesome-skill"
|
| 176 |
-
description: "Helps with [specific task] when [specific situation]"
|
| 177 |
-
version: "1.0.0"
|
| 178 |
-
author: "Your Name"
|
| 179 |
-
tags: ["category"]
|
| 180 |
-
---
|
| 181 |
-
|
| 182 |
-
# My Awesome Skill
|
| 183 |
-
|
| 184 |
-
## When to Use
|
| 185 |
-
|
| 186 |
-
Use this skill when you need to [specific task].
|
| 187 |
-
|
| 188 |
-
## Instructions
|
| 189 |
-
|
| 190 |
-
1. First, do this...
|
| 191 |
-
2. Then, do that...
|
| 192 |
-
3. Finally, verify by...
|
| 193 |
-
|
| 194 |
-
## Examples
|
| 195 |
-
|
| 196 |
-
### Example: Basic Case
|
| 197 |
-
|
| 198 |
-
[Show a complete example]
|
| 199 |
-
```
|
| 200 |
-
|
| 201 |
-
### Step 4: Add Supporting Files (Optional)
|
| 202 |
-
|
| 203 |
-
If your skill needs scripts:
|
| 204 |
-
|
| 205 |
-
```
|
| 206 |
-
my-awesome-skill/
|
| 207 |
-
├── SKILL.md # Required
|
| 208 |
-
├── helper.py # Optional Python script
|
| 209 |
-
├── setup.sh # Optional shell script
|
| 210 |
-
└── templates/ # Optional templates folder
|
| 211 |
-
└── config.json
|
| 212 |
-
```
|
| 213 |
-
|
| 214 |
-
Reference them in your SKILL.md:
|
| 215 |
-
|
| 216 |
-
```markdown
|
| 217 |
-
## Scripts
|
| 218 |
-
|
| 219 |
-
This skill includes helper scripts:
|
| 220 |
-
- `helper.py` - Does X
|
| 221 |
-
- `setup.sh` - Sets up Y
|
| 222 |
-
```
|
| 223 |
-
|
| 224 |
-
### Step 5: Test Your Skill
|
| 225 |
-
|
| 226 |
-
```bash
|
| 227 |
-
# Validate the skill
|
| 228 |
-
python -m helpers.skills_cli validate my-awesome-skill
|
| 229 |
-
|
| 230 |
-
# Test in Agent Zero
|
| 231 |
-
# Start the agent and ask it to perform the task your skill handles
|
| 232 |
-
```
|
| 233 |
-
|
| 234 |
-
---
|
| 235 |
-
|
| 236 |
-
## Best Practices
|
| 237 |
-
|
| 238 |
-
### Writing Effective Descriptions
|
| 239 |
-
|
| 240 |
-
The `description` field is crucial for semantic matching. Make it:
|
| 241 |
-
|
| 242 |
-
**Good:**
|
| 243 |
-
```yaml
|
| 244 |
-
description: "Guides systematic debugging of Python applications using print statements, debugger, and logging to identify root causes"
|
| 245 |
-
```
|
| 246 |
-
|
| 247 |
-
**Bad:**
|
| 248 |
-
```yaml
|
| 249 |
-
description: "Helps with debugging"
|
| 250 |
-
```
|
| 251 |
-
|
| 252 |
-
### Structuring Instructions
|
| 253 |
-
|
| 254 |
-
1. **Be Specific** - Avoid vague instructions
|
| 255 |
-
2. **Use Steps** - Number your steps clearly
|
| 256 |
-
3. **Include Examples** - Show, don't just tell
|
| 257 |
-
4. **Anticipate Errors** - Include troubleshooting
|
| 258 |
-
|
| 259 |
-
### Semantic Triggers
|
| 260 |
-
|
| 261 |
-
Design your description and content so the skill is recalled when relevant:
|
| 262 |
-
|
| 263 |
-
```yaml
|
| 264 |
-
# Include synonyms and related terms
|
| 265 |
-
description: "Helps create REST APIs, web services, HTTP endpoints, and backend routes using FastAPI, Flask, or Express"
|
| 266 |
-
```
|
| 267 |
-
|
| 268 |
-
### Keep Skills Focused
|
| 269 |
-
|
| 270 |
-
One skill = one expertise area. If your skill is getting too long, split it:
|
| 271 |
-
|
| 272 |
-
- `api-design` - API structure and patterns
|
| 273 |
-
- `api-security` - API authentication and authorization
|
| 274 |
-
- `api-testing` - API testing strategies
|
| 275 |
-
|
| 276 |
-
---
|
| 277 |
-
|
| 278 |
-
## Testing Skills
|
| 279 |
-
|
| 280 |
-
### Local Testing
|
| 281 |
-
|
| 282 |
-
1. **Validate Structure:**
|
| 283 |
-
```bash
|
| 284 |
-
python -m helpers.skills_cli validate my-skill
|
| 285 |
-
```
|
| 286 |
-
|
| 287 |
-
2. **Test Semantic Recall:**
|
| 288 |
-
Start Agent Zero and ask questions that should trigger your skill.
|
| 289 |
-
|
| 290 |
-
3. **Verify Instructions:**
|
| 291 |
-
Follow your own instructions manually to ensure they work.
|
| 292 |
-
|
| 293 |
-
---
|
| 294 |
-
|
| 295 |
-
## Sharing Skills
|
| 296 |
-
|
| 297 |
-
### Contributing to Agent Zero
|
| 298 |
-
|
| 299 |
-
1. **Fork the Repository:**
|
| 300 |
-
```bash
|
| 301 |
-
git clone https://github.com/agent0ai/agent-zero.git
|
| 302 |
-
cd agent-zero
|
| 303 |
-
```
|
| 304 |
-
|
| 305 |
-
2. **Create Your Skill:**
|
| 306 |
-
```bash
|
| 307 |
-
python -m helpers.skills_cli create my-skill
|
| 308 |
-
# Edit usr/skills/my-skill/SKILL.md
|
| 309 |
-
```
|
| 310 |
-
|
| 311 |
-
3. **Move to Default (for contribution):**
|
| 312 |
-
```bash
|
| 313 |
-
mv usr/skills/my-skill skills/my-skill
|
| 314 |
-
```
|
| 315 |
-
|
| 316 |
-
4. **Create a Pull Request:**
|
| 317 |
-
- Branch: `feat/skill-my-skill-name`
|
| 318 |
-
- Title: `feat(skills): add my-skill-name skill`
|
| 319 |
-
- Description: Explain what the skill does and why it's useful
|
| 320 |
-
|
| 321 |
-
### Publishing Skills
|
| 322 |
-
|
| 323 |
-
Share your skills on [skillsmp.com](https://skillsmp.com) or [skills.sh](https://skills.sh):
|
| 324 |
-
|
| 325 |
-
1. Create a GitHub repository for your skill
|
| 326 |
-
2. Ensure it follows the SKILL.md standard
|
| 327 |
-
3. Submit via their contribution process
|
| 328 |
-
|
| 329 |
-
### Creating a Skills Collection
|
| 330 |
-
|
| 331 |
-
For multiple related skills, create a repository:
|
| 332 |
-
|
| 333 |
-
```
|
| 334 |
-
my-skills-collection/
|
| 335 |
-
├── README.md
|
| 336 |
-
├── skills/
|
| 337 |
-
│ ├── skill-1/
|
| 338 |
-
│ │ └── SKILL.md
|
| 339 |
-
│ ├── skill-2/
|
| 340 |
-
│ │ └── SKILL.md
|
| 341 |
-
│ └── skill-3/
|
| 342 |
-
│ └── SKILL.md
|
| 343 |
-
└── LICENSE
|
| 344 |
-
```
|
| 345 |
-
|
| 346 |
-
---
|
| 347 |
-
|
| 348 |
-
## Community Guidelines
|
| 349 |
-
|
| 350 |
-
### Quality Standards
|
| 351 |
-
|
| 352 |
-
- **Tested** - Skills must be tested before submission
|
| 353 |
-
- **Documented** - Clear instructions and examples
|
| 354 |
-
- **Focused** - One expertise per skill
|
| 355 |
-
- **Original** - Don't duplicate existing skills
|
| 356 |
-
|
| 357 |
-
### Naming Conventions
|
| 358 |
-
|
| 359 |
-
- Use lowercase with hyphens: `my-skill-name`
|
| 360 |
-
- Be descriptive: `python-debugging` not `debug`
|
| 361 |
-
- Avoid generic names: `fastapi-crud` not `api`
|
| 362 |
-
|
| 363 |
-
### License
|
| 364 |
-
|
| 365 |
-
- Include a license (MIT recommended for maximum compatibility)
|
| 366 |
-
- Respect licenses of any code you include
|
| 367 |
-
- Don't include proprietary or copyrighted content
|
| 368 |
-
|
| 369 |
-
---
|
| 370 |
-
|
| 371 |
-
## FAQ
|
| 372 |
-
|
| 373 |
-
### Q: Where should I put my skills?
|
| 374 |
-
|
| 375 |
-
**A:** During development, use `usr/skills/`. For contribution, move to `skills/`.
|
| 376 |
-
|
| 377 |
-
### Q: How are skills discovered?
|
| 378 |
-
|
| 379 |
-
**A:** Skills are matched against their name, description, and tags for the current query. They are not indexed into vector memory.
|
| 380 |
-
|
| 381 |
-
### Q: Can I use skills from other platforms?
|
| 382 |
-
|
| 383 |
-
**A:** Yes! The SKILL.md standard is cross-platform. Skills from Claude Code, Cursor, or other compatible platforms can be copied directly to `usr/skills/`.
|
| 384 |
-
|
| 385 |
-
### Q: How do I update a skill?
|
| 386 |
-
|
| 387 |
-
**A:** Edit the SKILL.md file and increment the version number. Changes take effect on agent restart.
|
| 388 |
-
|
| 389 |
-
### Q: Can skills call other skills?
|
| 390 |
-
|
| 391 |
-
**A:** Skills don't directly call each other, but the agent may combine multiple skills when appropriate for a task.
|
| 392 |
-
|
| 393 |
-
---
|
| 394 |
-
|
| 395 |
-
Happy skill building! 🚀
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:50705bc9123c5c9962e9a0582b466c5bdfa342770f832503fe58cb77b51f4fa8
|
| 3 |
+
size 9033
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/developer/extensions.md
CHANGED
|
@@ -1,46 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
If you are new, start with plugins instead. Plugins are easier to create, test,
|
| 6 |
-
disable, and remove.
|
| 7 |
-
|
| 8 |
-
Architecture details, extension points, and source-linked explanations now live
|
| 9 |
-
in [DeepWiki for Agent Zero](https://deepwiki.com/agent0ai/agent-zero). This
|
| 10 |
-
local page stays short on purpose.
|
| 11 |
-
|
| 12 |
-
## Start Here
|
| 13 |
-
|
| 14 |
-
| Goal | Start here |
|
| 15 |
-
| --- | --- |
|
| 16 |
-
| Add a small user-facing feature | [Create a Small Plugin](../guides/create-plugin.md) |
|
| 17 |
-
| Change agent behavior for a project | [Projects](../guides/projects.md) |
|
| 18 |
-
| Create a specialized agent style | [Agent Profiles](../guides/agent-profiles.md) |
|
| 19 |
-
| Study extension internals | [DeepWiki](https://deepwiki.com/agent0ai/agent-zero) |
|
| 20 |
-
|
| 21 |
-
## When Extensions Make Sense
|
| 22 |
-
|
| 23 |
-
Use an extension only when a normal plugin, project instruction, skill, or agent
|
| 24 |
-
profile is not enough.
|
| 25 |
-
|
| 26 |
-
Good extension candidates:
|
| 27 |
-
|
| 28 |
-
- adding behavior at a specific lifecycle point;
|
| 29 |
-
- shaping prompts in a reusable way;
|
| 30 |
-
- integrating tightly with core tools;
|
| 31 |
-
- preparing framework-owned state before a task starts.
|
| 32 |
-
|
| 33 |
-
Avoid extensions for simple UI changes, one-off scripts, or work that should be
|
| 34 |
-
easy to remove. A plugin is usually the cleaner home for that.
|
| 35 |
-
|
| 36 |
-
## Maintenance Rule
|
| 37 |
-
|
| 38 |
-
Keep extension changes small and easy to explain. If a reader needs the full
|
| 39 |
-
architecture to understand why the extension exists, link to the relevant
|
| 40 |
-
DeepWiki page instead of copying the architecture into this repository.
|
| 41 |
-
|
| 42 |
-
## Related
|
| 43 |
-
|
| 44 |
-
- [Create a Small Plugin](../guides/create-plugin.md)
|
| 45 |
-
- [Agent Profiles](../guides/agent-profiles.md)
|
| 46 |
-
- [DeepWiki for Agent Zero](https://deepwiki.com/agent0ai/agent-zero)
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:bb77856495cd10198eca601ba2ea1cfd4043470d966522462d9589fc9a908aff
|
| 3 |
+
size 1682
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/developer/mcp-configuration.md
CHANGED
|
@@ -1,80 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
This page is for people who need to paste or review MCP JSON by hand. MCP
|
| 6 |
-
architecture and source-linked internals live in
|
| 7 |
-
[DeepWiki for Agent Zero](https://deepwiki.com/agent0ai/agent-zero).
|
| 8 |
-
|
| 9 |
-
## Basic Shape
|
| 10 |
-
|
| 11 |
-
Command-based MCP tool:
|
| 12 |
-
|
| 13 |
-
```json
|
| 14 |
-
{
|
| 15 |
-
"mcpServers": {
|
| 16 |
-
"sqlite": {
|
| 17 |
-
"command": "uvx",
|
| 18 |
-
"args": ["mcp-server-sqlite", "--db-path", "/root/db.sqlite"]
|
| 19 |
-
}
|
| 20 |
-
}
|
| 21 |
-
}
|
| 22 |
-
```
|
| 23 |
-
|
| 24 |
-
URL-based MCP tool:
|
| 25 |
-
|
| 26 |
-
```json
|
| 27 |
-
{
|
| 28 |
-
"mcpServers": {
|
| 29 |
-
"external-api": {
|
| 30 |
-
"url": "https://api.example.com/mcp",
|
| 31 |
-
"headers": {
|
| 32 |
-
"Authorization": "Bearer YOUR_API_KEY"
|
| 33 |
-
}
|
| 34 |
-
}
|
| 35 |
-
}
|
| 36 |
-
}
|
| 37 |
-
```
|
| 38 |
-
|
| 39 |
-
## Common Fields
|
| 40 |
-
|
| 41 |
-
| Field | Meaning |
|
| 42 |
-
| --- | --- |
|
| 43 |
-
| `command` | Starts a local MCP tool from a command. |
|
| 44 |
-
| `args` | Arguments passed to that command. |
|
| 45 |
-
| `url` | Connects to an MCP tool that is already running. |
|
| 46 |
-
| `headers` | Optional HTTP headers, often used for authentication. |
|
| 47 |
-
| `env` | Optional environment variables for command-based tools. |
|
| 48 |
-
| `disabled` | Temporarily turns one MCP entry off. |
|
| 49 |
-
|
| 50 |
-
Use `command` for local tools and `url` for tools that are already running
|
| 51 |
-
somewhere else.
|
| 52 |
-
|
| 53 |
-
## Docker Addresses
|
| 54 |
-
|
| 55 |
-
If Agent Zero runs in Docker, remember that "localhost" means the container, not
|
| 56 |
-
always your host machine.
|
| 57 |
-
|
| 58 |
-
| Where the MCP tool runs | Address to use from Agent Zero |
|
| 59 |
-
| --- | --- |
|
| 60 |
-
| Host machine on macOS or Windows | `host.docker.internal` |
|
| 61 |
-
| Another container | The container name on the same Docker network |
|
| 62 |
-
| Remote machine | Its reachable HTTPS URL |
|
| 63 |
-
| Inside Agent Zero's container | A command-based config |
|
| 64 |
-
|
| 65 |
-
On Linux, `host.docker.internal` may need extra Docker setup. Running the MCP
|
| 66 |
-
tool in the same Docker network is often simpler.
|
| 67 |
-
|
| 68 |
-
## Safety
|
| 69 |
-
|
| 70 |
-
- Use MCP tools you trust.
|
| 71 |
-
- Keep real API keys out of public screenshots and repositories.
|
| 72 |
-
- Prefer project secrets or environment variables for credentials.
|
| 73 |
-
- Remove MCP tools you no longer use.
|
| 74 |
-
|
| 75 |
-
## Related
|
| 76 |
-
|
| 77 |
-
- [MCP Setup](../guides/mcp-setup.md)
|
| 78 |
-
- [Browser Guide](../guides/browser.md)
|
| 79 |
-
- [A0 CLI Connector](../guides/a0-cli-connector.md)
|
| 80 |
-
- [DeepWiki for Agent Zero](https://deepwiki.com/agent0ai/agent-zero)
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d6f96af40a0fc64e275bdc8878d9a2b75d98d819c8301d79c8f1624528b4ec22
|
| 3 |
+
size 2182
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/developer/notifications.md
CHANGED
|
@@ -1,133 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
> [!TIP]
|
| 6 |
-
> Notifications pair well with scheduled tasks. See [Tasks & Scheduling](../guides/usage.md#tasks-and-scheduling) for automation patterns.
|
| 7 |
-
|
| 8 |
-
## Backend Usage
|
| 9 |
-
|
| 10 |
-
Use `AgentNotification` helper methods anywhere in your Python code:
|
| 11 |
-
|
| 12 |
-
```python
|
| 13 |
-
from helpers.notification import AgentNotification
|
| 14 |
-
|
| 15 |
-
# Basic notifications
|
| 16 |
-
AgentNotification.info("Operation completed")
|
| 17 |
-
AgentNotification.success("File saved successfully", "File Manager")
|
| 18 |
-
AgentNotification.warning("High CPU usage detected", "System Monitor")
|
| 19 |
-
AgentNotification.error("Connection failed", "Network Error")
|
| 20 |
-
AgentNotification.progress("Processing files...", "Task Progress")
|
| 21 |
-
|
| 22 |
-
# With details and custom display time
|
| 23 |
-
AgentNotification.info(
|
| 24 |
-
message="System backup completed",
|
| 25 |
-
title="Backup Manager",
|
| 26 |
-
detail="<p>Backup size: <strong>2.4 GB</strong></p>",
|
| 27 |
-
display_time=8 # seconds
|
| 28 |
-
)
|
| 29 |
-
|
| 30 |
-
# Grouped notifications (replaces previous in same group)
|
| 31 |
-
AgentNotification.progress("Download: 25%", "File Download", group="download-status")
|
| 32 |
-
AgentNotification.progress("Download: 75%", "File Download", group="download-status") # Replaces previous
|
| 33 |
-
AgentNotification.progress("Download: Complete!", "File Download", group="download-status") # Replaces previous
|
| 34 |
-
```
|
| 35 |
-
|
| 36 |
-
## Frontend Usage
|
| 37 |
-
|
| 38 |
-
Use the notification store in Alpine.js components:
|
| 39 |
-
|
| 40 |
-
```javascript
|
| 41 |
-
// Basic notifications
|
| 42 |
-
$store.notificationStore.info("User logged in")
|
| 43 |
-
$store.notificationStore.success("Settings saved", "Configuration")
|
| 44 |
-
$store.notificationStore.warning("Session expiring soon")
|
| 45 |
-
$store.notificationStore.error("Failed to load data")
|
| 46 |
-
|
| 47 |
-
// With grouping
|
| 48 |
-
$store.notificationStore.info("Connecting...", "Status", "", 3, "connection")
|
| 49 |
-
$store.notificationStore.success("Connected!", "Status", "", 3, "connection") // Replaces previous
|
| 50 |
-
|
| 51 |
-
// Frontend notifications with backend persistence (new feature!)
|
| 52 |
-
$store.notificationStore.frontendError("Database timeout", "Connection Error")
|
| 53 |
-
$store.notificationStore.frontendWarning("High memory usage", "Performance")
|
| 54 |
-
$store.notificationStore.frontendInfo("Cache cleared", "System")
|
| 55 |
-
```
|
| 56 |
-
|
| 57 |
-
## Frontend Notifications with Backend Sync
|
| 58 |
-
|
| 59 |
-
**New Feature**: Frontend notifications now automatically sync to the backend when connected, providing persistent history and cross-session availability.
|
| 60 |
-
|
| 61 |
-
### How it Works:
|
| 62 |
-
- **Backend Connected**: Notifications are sent to backend and appear via polling (persistent)
|
| 63 |
-
- **Backend Disconnected**: Notifications show as frontend-only toasts (temporary)
|
| 64 |
-
- **Automatic Fallback**: Seamless degradation when backend is unavailable
|
| 65 |
-
|
| 66 |
-
### Global Functions:
|
| 67 |
-
```javascript
|
| 68 |
-
// These functions automatically try backend first, then fallback to frontend-only
|
| 69 |
-
toastFrontendError("Server unreachable", "Connection Error")
|
| 70 |
-
toastFrontendWarning("Slow connection detected")
|
| 71 |
-
toastFrontendInfo("Reconnected successfully")
|
| 72 |
-
```
|
| 73 |
-
|
| 74 |
-
## HTML Usage
|
| 75 |
-
|
| 76 |
-
```html
|
| 77 |
-
<button @click="$store.notificationStore.success('Task completed!')">
|
| 78 |
-
Complete Task
|
| 79 |
-
</button>
|
| 80 |
-
|
| 81 |
-
<button @click="$store.notificationStore.warning('Progress: 50%', 'Upload', '', 5, 'upload-progress')">
|
| 82 |
-
Update Progress
|
| 83 |
-
</button>
|
| 84 |
-
|
| 85 |
-
<!-- Frontend notifications with backend sync -->
|
| 86 |
-
<button @click="$store.notificationStore.frontendError('Connection failed', 'Network')">
|
| 87 |
-
Report Connection Error
|
| 88 |
-
</button>
|
| 89 |
-
```
|
| 90 |
-
|
| 91 |
-
## Notification Groups
|
| 92 |
-
|
| 93 |
-
Groups ensure only the latest notification from each group is shown in the toast stack:
|
| 94 |
-
|
| 95 |
-
```python
|
| 96 |
-
# Progress updates - each new notification replaces the previous one
|
| 97 |
-
AgentNotification.info("Starting backup...", group="backup-status")
|
| 98 |
-
AgentNotification.progress("Backup: 30%", group="backup-status") # Replaces previous
|
| 99 |
-
AgentNotification.progress("Backup: 80%", group="backup-status") # Replaces previous
|
| 100 |
-
AgentNotification.success("Backup complete!", group="backup-status") # Replaces previous
|
| 101 |
-
|
| 102 |
-
# Connection status - only show current state
|
| 103 |
-
AgentNotification.warning("Disconnected", group="network")
|
| 104 |
-
AgentNotification.info("Reconnecting...", group="network") # Replaces previous
|
| 105 |
-
AgentNotification.success("Connected", group="network") # Replaces previous
|
| 106 |
-
```
|
| 107 |
-
|
| 108 |
-
## Parameters
|
| 109 |
-
|
| 110 |
-
All notification methods support these parameters:
|
| 111 |
-
|
| 112 |
-
- `message` (required): Main notification text
|
| 113 |
-
- `title` (optional): Notification title
|
| 114 |
-
- `detail` (optional): HTML content for expandable details
|
| 115 |
-
- `display_time` (optional): Toast display duration in seconds (default: 3)
|
| 116 |
-
- `group` (optional): Group identifier for replacement behavior
|
| 117 |
-
|
| 118 |
-
## Types
|
| 119 |
-
|
| 120 |
-
- **info** (ℹ️): General information
|
| 121 |
-
- **success** (✅): Successful operations
|
| 122 |
-
- **warning** (⚠️): Important alerts
|
| 123 |
-
- **error** (❌): Error conditions
|
| 124 |
-
- **progress** (⏳): Ongoing operations
|
| 125 |
-
|
| 126 |
-
## Behavior
|
| 127 |
-
|
| 128 |
-
- **Toast Display**: Notifications appear as toasts in the bottom-right corner
|
| 129 |
-
- **Persistent History**: All notifications (including synced frontend ones) are stored in notification history
|
| 130 |
-
- **Modal Access**: Full history accessible via the bell icon
|
| 131 |
-
- **Auto-dismiss**: Toasts automatically disappear after `display_time`
|
| 132 |
-
- **Group Replacement**: Notifications with the same group replace previous ones immediately
|
| 133 |
-
- **Backend Sync**: Frontend notifications automatically sync to backend when connected
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:f9cececccc005a4c071574c5706cb157e744f60cbba1e0cceaa442936caf78fc
|
| 3 |
+
size 5212
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|