tailcam 1.8.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tailcam-1.8.3/.dockerignore +23 -0
- tailcam-1.8.3/.github/workflows/desktop.yml +123 -0
- tailcam-1.8.3/.github/workflows/docker-publish.yml +68 -0
- tailcam-1.8.3/.github/workflows/pypi-publish.yml +47 -0
- tailcam-1.8.3/.github/workflows/tests.yml +63 -0
- tailcam-1.8.3/.gitignore +25 -0
- tailcam-1.8.3/Dockerfile +56 -0
- tailcam-1.8.3/LICENSE +21 -0
- tailcam-1.8.3/PKG-INFO +648 -0
- tailcam-1.8.3/README.md +577 -0
- tailcam-1.8.3/TESTING.md +216 -0
- tailcam-1.8.3/browser-extensions/README.md +144 -0
- tailcam-1.8.3/browser-extensions/build.py +132 -0
- tailcam-1.8.3/browser-extensions/chrome/manifest.json +55 -0
- tailcam-1.8.3/browser-extensions/edge/manifest.json +55 -0
- tailcam-1.8.3/browser-extensions/firefox/manifest.json +61 -0
- tailcam-1.8.3/browser-extensions/safari/convert-safari.sh +65 -0
- tailcam-1.8.3/browser-extensions/safari/manifest.json +55 -0
- tailcam-1.8.3/browser-extensions/shared/background.js +499 -0
- tailcam-1.8.3/browser-extensions/shared/glance/glance.css +298 -0
- tailcam-1.8.3/browser-extensions/shared/glance/glance.html +41 -0
- tailcam-1.8.3/browser-extensions/shared/glance/glance.js +438 -0
- tailcam-1.8.3/browser-extensions/shared/icons/icon-128.png +0 -0
- tailcam-1.8.3/browser-extensions/shared/icons/icon-16.png +0 -0
- tailcam-1.8.3/browser-extensions/shared/icons/icon-256.png +0 -0
- tailcam-1.8.3/browser-extensions/shared/icons/icon-32.png +0 -0
- tailcam-1.8.3/browser-extensions/shared/icons/icon-48.png +0 -0
- tailcam-1.8.3/browser-extensions/shared/lib/api.js +267 -0
- tailcam-1.8.3/browser-extensions/shared/lib/compat.js +177 -0
- tailcam-1.8.3/browser-extensions/shared/lib/format.js +79 -0
- tailcam-1.8.3/browser-extensions/shared/lib/settings.js +210 -0
- tailcam-1.8.3/browser-extensions/shared/options/options.css +386 -0
- tailcam-1.8.3/browser-extensions/shared/options/options.html +131 -0
- tailcam-1.8.3/browser-extensions/shared/options/options.js +429 -0
- tailcam-1.8.3/browser-extensions/shared/popup/popup.css +559 -0
- tailcam-1.8.3/browser-extensions/shared/popup/popup.html +51 -0
- tailcam-1.8.3/browser-extensions/shared/popup/popup.js +507 -0
- tailcam-1.8.3/docker/entrypoint.sh +73 -0
- tailcam-1.8.3/docker-compose.yml +49 -0
- tailcam-1.8.3/docs/ai-detection-plan.md +83 -0
- tailcam-1.8.3/docs/design-prototype/DESIGN-README.md +25 -0
- tailcam-1.8.3/docs/design-prototype/design-chat.md +313 -0
- tailcam-1.8.3/docs/design-prototype/js/app.jsx +171 -0
- tailcam-1.8.3/docs/design-prototype/js/icons.jsx +95 -0
- tailcam-1.8.3/docs/design-prototype/js/mock.jsx +399 -0
- tailcam-1.8.3/docs/design-prototype/js/screens1.jsx +293 -0
- tailcam-1.8.3/docs/design-prototype/js/screens2.jsx +297 -0
- tailcam-1.8.3/docs/design-prototype/js/ui.jsx +211 -0
- tailcam-1.8.3/docs/design-prototype/js/viewer.jsx +305 -0
- tailcam-1.8.3/docs/design-prototype/styles.css +445 -0
- tailcam-1.8.3/docs/design-prototype/tweaks-panel.jsx +541 -0
- tailcam-1.8.3/docs/mcp-security.md +121 -0
- tailcam-1.8.3/docs/mcp.md +243 -0
- tailcam-1.8.3/docs/screenshots/README.md +39 -0
- tailcam-1.8.3/docs/screenshots/agents.png +0 -0
- tailcam-1.8.3/docs/screenshots/ai-studio.png +0 -0
- tailcam-1.8.3/docs/screenshots/camera.png +0 -0
- tailcam-1.8.3/docs/screenshots/dashboard.png +0 -0
- tailcam-1.8.3/docs/screenshots/docs.png +0 -0
- tailcam-1.8.3/docs/screenshots/events.png +0 -0
- tailcam-1.8.3/docs/screenshots/gallery.png +0 -0
- tailcam-1.8.3/docs/screenshots/palette.png +0 -0
- tailcam-1.8.3/docs/screenshots/plugins.png +0 -0
- tailcam-1.8.3/docs/screenshots/settings.png +0 -0
- tailcam-1.8.3/docs/screenshots/timelapse.png +0 -0
- tailcam-1.8.3/docs/screenshots/videowall.png +0 -0
- tailcam-1.8.3/docs/superpowers/specs/2026-06-17-tailcam-mcp-design.md +495 -0
- tailcam-1.8.3/docs/tailscale-grants.md +119 -0
- tailcam-1.8.3/docs/web-ui-plan.md +134 -0
- tailcam-1.8.3/examples/mcp/claude_desktop_config.json +12 -0
- tailcam-1.8.3/examples/mcp/codex.config.toml +17 -0
- tailcam-1.8.3/examples/mcp/hermes-openclaw.json +27 -0
- tailcam-1.8.3/examples/notifications/sample-payloads.json +48 -0
- tailcam-1.8.3/examples/plugins/README.md +96 -0
- tailcam-1.8.3/examples/plugins/ntfy_channel.py +64 -0
- tailcam-1.8.3/examples/skills/tailcam-alerts.md +82 -0
- tailcam-1.8.3/install-docker.sh +124 -0
- tailcam-1.8.3/install-linux.sh +429 -0
- tailcam-1.8.3/install-macos.sh +300 -0
- tailcam-1.8.3/install.ps1 +453 -0
- tailcam-1.8.3/marketplace/README.md +42 -0
- tailcam-1.8.3/marketplace/TEMPLATE.py +107 -0
- tailcam-1.8.3/marketplace/build_index.py +79 -0
- tailcam-1.8.3/marketplace/index.json +69 -0
- tailcam-1.8.3/marketplace/plugins/event_logger.py +86 -0
- tailcam-1.8.3/marketplace/plugins/ntfy_notifier.py +91 -0
- tailcam-1.8.3/marketplace/plugins/openai_analyzer.py +145 -0
- tailcam-1.8.3/marketplace/plugins/slack_notifier.py +70 -0
- tailcam-1.8.3/pyproject.toml +122 -0
- tailcam-1.8.3/src/tailcam/__init__.py +3 -0
- tailcam-1.8.3/src/tailcam/__main__.py +4 -0
- tailcam-1.8.3/src/tailcam/activelearning/__init__.py +20 -0
- tailcam-1.8.3/src/tailcam/activelearning/annotations.py +230 -0
- tailcam-1.8.3/src/tailcam/activelearning/backends.py +270 -0
- tailcam-1.8.3/src/tailcam/activelearning/florence.py +246 -0
- tailcam-1.8.3/src/tailcam/activelearning/labelstudio.py +284 -0
- tailcam-1.8.3/src/tailcam/activelearning/qwen.py +298 -0
- tailcam-1.8.3/src/tailcam/activelearning/service.py +656 -0
- tailcam-1.8.3/src/tailcam/ai/__init__.py +8 -0
- tailcam-1.8.3/src/tailcam/ai/analyzer.py +185 -0
- tailcam-1.8.3/src/tailcam/ai/detector.py +367 -0
- tailcam-1.8.3/src/tailcam/ai/pull.py +121 -0
- tailcam-1.8.3/src/tailcam/ai/remote.py +151 -0
- tailcam-1.8.3/src/tailcam/camera/__init__.py +1 -0
- tailcam-1.8.3/src/tailcam/camera/enumerate.py +158 -0
- tailcam-1.8.3/src/tailcam/camera/frame.py +131 -0
- tailcam-1.8.3/src/tailcam/camera/manager.py +261 -0
- tailcam-1.8.3/src/tailcam/camera/properties.py +45 -0
- tailcam-1.8.3/src/tailcam/camera/source.py +376 -0
- tailcam-1.8.3/src/tailcam/camera/transforms.py +101 -0
- tailcam-1.8.3/src/tailcam/camera/worker.py +201 -0
- tailcam-1.8.3/src/tailcam/cli.py +868 -0
- tailcam-1.8.3/src/tailcam/cluster/__init__.py +2 -0
- tailcam-1.8.3/src/tailcam/cluster/fleet.py +57 -0
- tailcam-1.8.3/src/tailcam/cluster/remote_feed.py +227 -0
- tailcam-1.8.3/src/tailcam/cluster/service.py +238 -0
- tailcam-1.8.3/src/tailcam/config.py +538 -0
- tailcam-1.8.3/src/tailcam/desktop/__init__.py +40 -0
- tailcam-1.8.3/src/tailcam/desktop/app.py +182 -0
- tailcam-1.8.3/src/tailcam/desktop/assets/app-icon-512.png +0 -0
- tailcam-1.8.3/src/tailcam/desktop/assets/server_down.html +31 -0
- tailcam-1.8.3/src/tailcam/desktop/assets/tray-icon-template.png +0 -0
- tailcam-1.8.3/src/tailcam/desktop/assets/tray-icon.png +0 -0
- tailcam-1.8.3/src/tailcam/desktop/linux_desktop.py +149 -0
- tailcam-1.8.3/src/tailcam/desktop/macos_bundle.py +144 -0
- tailcam-1.8.3/src/tailcam/desktop/menu.py +92 -0
- tailcam-1.8.3/src/tailcam/desktop/nodes.py +51 -0
- tailcam-1.8.3/src/tailcam/desktop/server.py +96 -0
- tailcam-1.8.3/src/tailcam/desktop/state.py +56 -0
- tailcam-1.8.3/src/tailcam/desktop/tray.py +81 -0
- tailcam-1.8.3/src/tailcam/desktop/updates.py +29 -0
- tailcam-1.8.3/src/tailcam/desktop/window.py +59 -0
- tailcam-1.8.3/src/tailcam/desktop/windows_shortcut.py +136 -0
- tailcam-1.8.3/src/tailcam/hostinfo.py +125 -0
- tailcam-1.8.3/src/tailcam/integrations/__init__.py +1 -0
- tailcam-1.8.3/src/tailcam/integrations/base.py +100 -0
- tailcam-1.8.3/src/tailcam/integrations/homeassistant.py +323 -0
- tailcam-1.8.3/src/tailcam/integrations/homekit.py +329 -0
- tailcam-1.8.3/src/tailcam/logging_setup.py +26 -0
- tailcam-1.8.3/src/tailcam/management/__init__.py +7 -0
- tailcam-1.8.3/src/tailcam/management/audit.py +49 -0
- tailcam-1.8.3/src/tailcam/management/capabilities.py +43 -0
- tailcam-1.8.3/src/tailcam/management/health.py +190 -0
- tailcam-1.8.3/src/tailcam/mcp/__init__.py +56 -0
- tailcam-1.8.3/src/tailcam/mcp/client.py +378 -0
- tailcam-1.8.3/src/tailcam/mcp/errors.py +63 -0
- tailcam-1.8.3/src/tailcam/mcp/prompts.py +109 -0
- tailcam-1.8.3/src/tailcam/mcp/protocol.py +106 -0
- tailcam-1.8.3/src/tailcam/mcp/resources.py +98 -0
- tailcam-1.8.3/src/tailcam/mcp/server.py +289 -0
- tailcam-1.8.3/src/tailcam/mcp/toolctx.py +80 -0
- tailcam-1.8.3/src/tailcam/mcp/tools.py +1151 -0
- tailcam-1.8.3/src/tailcam/mcp/transport_http.py +235 -0
- tailcam-1.8.3/src/tailcam/mcp/transport_stdio.py +95 -0
- tailcam-1.8.3/src/tailcam/media/__init__.py +1 -0
- tailcam-1.8.3/src/tailcam/media/capture_router.py +279 -0
- tailcam-1.8.3/src/tailcam/media/gallery.py +95 -0
- tailcam-1.8.3/src/tailcam/media/recorder.py +247 -0
- tailcam-1.8.3/src/tailcam/media/snapshot.py +66 -0
- tailcam-1.8.3/src/tailcam/media/video_sink.py +248 -0
- tailcam-1.8.3/src/tailcam/migrate.py +126 -0
- tailcam-1.8.3/src/tailcam/motion/__init__.py +1 -0
- tailcam-1.8.3/src/tailcam/motion/detector.py +63 -0
- tailcam-1.8.3/src/tailcam/motion/events.py +39 -0
- tailcam-1.8.3/src/tailcam/motion/worker.py +193 -0
- tailcam-1.8.3/src/tailcam/notify/__init__.py +0 -0
- tailcam-1.8.3/src/tailcam/notify/service.py +262 -0
- tailcam-1.8.3/src/tailcam/paths.py +152 -0
- tailcam-1.8.3/src/tailcam/persistence/__init__.py +1 -0
- tailcam-1.8.3/src/tailcam/persistence/models.py +209 -0
- tailcam-1.8.3/src/tailcam/persistence/store.py +1230 -0
- tailcam-1.8.3/src/tailcam/plugins/__init__.py +0 -0
- tailcam-1.8.3/src/tailcam/plugins/builtin/__init__.py +0 -0
- tailcam-1.8.3/src/tailcam/plugins/builtin/ai_providers.py +34 -0
- tailcam-1.8.3/src/tailcam/plugins/builtin/channels.py +72 -0
- tailcam-1.8.3/src/tailcam/plugins/hookspecs.py +111 -0
- tailcam-1.8.3/src/tailcam/plugins/market.py +259 -0
- tailcam-1.8.3/src/tailcam/plugins/registry.py +140 -0
- tailcam-1.8.3/src/tailcam/plugins/sdk.py +98 -0
- tailcam-1.8.3/src/tailcam/proc.py +25 -0
- tailcam-1.8.3/src/tailcam/security/__init__.py +5 -0
- tailcam-1.8.3/src/tailcam/security/principal.py +167 -0
- tailcam-1.8.3/src/tailcam/service/__init__.py +1 -0
- tailcam-1.8.3/src/tailcam/service/installer.py +364 -0
- tailcam-1.8.3/src/tailcam/streaming/__init__.py +1 -0
- tailcam-1.8.3/src/tailcam/streaming/backend.py +24 -0
- tailcam-1.8.3/src/tailcam/streaming/encoder.py +14 -0
- tailcam-1.8.3/src/tailcam/streaming/mjpeg.py +118 -0
- tailcam-1.8.3/src/tailcam/tailscale/__init__.py +1 -0
- tailcam-1.8.3/src/tailcam/tailscale/client.py +200 -0
- tailcam-1.8.3/src/tailcam/timelapse/__init__.py +7 -0
- tailcam-1.8.3/src/tailcam/timelapse/analyzer.py +169 -0
- tailcam-1.8.3/src/tailcam/timelapse/ffmpeg.py +199 -0
- tailcam-1.8.3/src/tailcam/timelapse/presets.py +64 -0
- tailcam-1.8.3/src/tailcam/timelapse/rife.py +76 -0
- tailcam-1.8.3/src/tailcam/timelapse/service.py +570 -0
- tailcam-1.8.3/src/tailcam/timelapse/worker.py +122 -0
- tailcam-1.8.3/src/tailcam/training/__init__.py +8 -0
- tailcam-1.8.3/src/tailcam/training/engine.py +58 -0
- tailcam-1.8.3/src/tailcam/training/inference.py +351 -0
- tailcam-1.8.3/src/tailcam/training/runner.py +209 -0
- tailcam-1.8.3/src/tailcam/training/service.py +508 -0
- tailcam-1.8.3/src/tailcam/update.py +110 -0
- tailcam-1.8.3/src/tailcam/web/__init__.py +1 -0
- tailcam-1.8.3/src/tailcam/web/app.py +102 -0
- tailcam-1.8.3/src/tailcam/web/context.py +493 -0
- tailcam-1.8.3/src/tailcam/web/deps.py +11 -0
- tailcam-1.8.3/src/tailcam/web/routes_active.py +201 -0
- tailcam-1.8.3/src/tailcam/web/routes_api.py +1884 -0
- tailcam-1.8.3/src/tailcam/web/routes_fleet_v1.py +172 -0
- tailcam-1.8.3/src/tailcam/web/routes_node_v1.py +189 -0
- tailcam-1.8.3/src/tailcam/web/routes_pages.py +46 -0
- tailcam-1.8.3/src/tailcam/web/routes_proxy.py +88 -0
- tailcam-1.8.3/src/tailcam/web/routes_remote.py +162 -0
- tailcam-1.8.3/src/tailcam/web/routes_stream.py +168 -0
- tailcam-1.8.3/src/tailcam/web/schemas.py +960 -0
- tailcam-1.8.3/src/tailcam/web/security.py +126 -0
- tailcam-1.8.3/src/tailcam/web/spa/apple-touch-icon-light.png +0 -0
- tailcam-1.8.3/src/tailcam/web/spa/apple-touch-icon.png +0 -0
- tailcam-1.8.3/src/tailcam/web/spa/assets/index-CEMCQF_y.css +1 -0
- tailcam-1.8.3/src/tailcam/web/spa/assets/index-cqHUOMzL.js +2343 -0
- tailcam-1.8.3/src/tailcam/web/spa/favicon-16.png +0 -0
- tailcam-1.8.3/src/tailcam/web/spa/favicon-32.png +0 -0
- tailcam-1.8.3/src/tailcam/web/spa/favicon.ico +0 -0
- tailcam-1.8.3/src/tailcam/web/spa/favicon.svg +9 -0
- tailcam-1.8.3/src/tailcam/web/spa/icon-192-maskable.png +0 -0
- tailcam-1.8.3/src/tailcam/web/spa/icon-192.png +0 -0
- tailcam-1.8.3/src/tailcam/web/spa/icon-512-light.png +0 -0
- tailcam-1.8.3/src/tailcam/web/spa/icon-512-maskable.png +0 -0
- tailcam-1.8.3/src/tailcam/web/spa/icon-512.png +0 -0
- tailcam-1.8.3/src/tailcam/web/spa/index.html +26 -0
- tailcam-1.8.3/src/tailcam/web/spa/manifest.webmanifest +1 -0
- tailcam-1.8.3/src/tailcam/web/spa/registerSW.js +1 -0
- tailcam-1.8.3/src/tailcam/web/spa/sw.js +1 -0
- tailcam-1.8.3/src/tailcam/web/spa/workbox-abeb32eb.js +1 -0
- tailcam-1.8.3/src/tailcam/web/static/css/app.css +95 -0
- tailcam-1.8.3/src/tailcam/web/static/js/app.js +232 -0
- tailcam-1.8.3/src/tailcam/web/templates/base.html +25 -0
- tailcam-1.8.3/src/tailcam/web/templates/camera.html +78 -0
- tailcam-1.8.3/src/tailcam/web/templates/events.html +23 -0
- tailcam-1.8.3/src/tailcam/web/templates/gallery.html +25 -0
- tailcam-1.8.3/src/tailcam/web/templates/index.html +32 -0
- tailcam-1.8.3/tests/conftest.py +77 -0
- tailcam-1.8.3/tests/test_active_learning.py +474 -0
- tailcam-1.8.3/tests/test_ai.py +85 -0
- tailcam-1.8.3/tests/test_api.py +293 -0
- tailcam-1.8.3/tests/test_audit.py +80 -0
- tailcam-1.8.3/tests/test_audit_round2.py +376 -0
- tailcam-1.8.3/tests/test_browser_extensions.py +108 -0
- tailcam-1.8.3/tests/test_builtin_detection.py +441 -0
- tailcam-1.8.3/tests/test_camera_open.py +165 -0
- tailcam-1.8.3/tests/test_cli.py +51 -0
- tailcam-1.8.3/tests/test_cluster.py +112 -0
- tailcam-1.8.3/tests/test_desktop.py +496 -0
- tailcam-1.8.3/tests/test_detection.py +323 -0
- tailcam-1.8.3/tests/test_detection_routing.py +144 -0
- tailcam-1.8.3/tests/test_docs_ui.py +25 -0
- tailcam-1.8.3/tests/test_enumerate.py +35 -0
- tailcam-1.8.3/tests/test_fleet_api.py +163 -0
- tailcam-1.8.3/tests/test_frame_buffer.py +63 -0
- tailcam-1.8.3/tests/test_frame_consumer.py +74 -0
- tailcam-1.8.3/tests/test_fs_browse.py +31 -0
- tailcam-1.8.3/tests/test_hostinfo.py +87 -0
- tailcam-1.8.3/tests/test_installer_script.py +143 -0
- tailcam-1.8.3/tests/test_integrations.py +154 -0
- tailcam-1.8.3/tests/test_management_health.py +163 -0
- tailcam-1.8.3/tests/test_mcp.py +689 -0
- tailcam-1.8.3/tests/test_mjpeg.py +77 -0
- tailcam-1.8.3/tests/test_motion_detector.py +67 -0
- tailcam-1.8.3/tests/test_node_api.py +94 -0
- tailcam-1.8.3/tests/test_notify.py +118 -0
- tailcam-1.8.3/tests/test_plugin_market.py +307 -0
- tailcam-1.8.3/tests/test_plugins.py +92 -0
- tailcam-1.8.3/tests/test_principal.py +166 -0
- tailcam-1.8.3/tests/test_proc.py +76 -0
- tailcam-1.8.3/tests/test_rename_migration.py +174 -0
- tailcam-1.8.3/tests/test_service_control.py +152 -0
- tailcam-1.8.3/tests/test_storage.py +133 -0
- tailcam-1.8.3/tests/test_storage_node.py +217 -0
- tailcam-1.8.3/tests/test_tailscale.py +139 -0
- tailcam-1.8.3/tests/test_timelapse.py +432 -0
- tailcam-1.8.3/tests/test_timelapse_analyzer.py +189 -0
- tailcam-1.8.3/tests/test_timelapse_printer.py +287 -0
- tailcam-1.8.3/tests/test_training.py +317 -0
- tailcam-1.8.3/tests/test_transforms.py +65 -0
- tailcam-1.8.3/tests/test_update.py +179 -0
- tailcam-1.8.3/tests/test_version.py +35 -0
- tailcam-1.8.3/tests/test_windows.py +109 -0
- tailcam-1.8.3/uninstall-linux.sh +82 -0
- tailcam-1.8.3/uninstall-macos.sh +41 -0
- tailcam-1.8.3/uninstall.ps1 +68 -0
- tailcam-1.8.3/web-ui/README.md +49 -0
- tailcam-1.8.3/web-ui/index.html +25 -0
- tailcam-1.8.3/web-ui/package-lock.json +6170 -0
- tailcam-1.8.3/web-ui/package.json +27 -0
- tailcam-1.8.3/web-ui/public/apple-touch-icon-light.png +0 -0
- tailcam-1.8.3/web-ui/public/apple-touch-icon.png +0 -0
- tailcam-1.8.3/web-ui/public/favicon-16.png +0 -0
- tailcam-1.8.3/web-ui/public/favicon-32.png +0 -0
- tailcam-1.8.3/web-ui/public/favicon.ico +0 -0
- tailcam-1.8.3/web-ui/public/favicon.svg +9 -0
- tailcam-1.8.3/web-ui/public/icon-192-maskable.png +0 -0
- tailcam-1.8.3/web-ui/public/icon-192.png +0 -0
- tailcam-1.8.3/web-ui/public/icon-512-light.png +0 -0
- tailcam-1.8.3/web-ui/public/icon-512-maskable.png +0 -0
- tailcam-1.8.3/web-ui/public/icon-512.png +0 -0
- tailcam-1.8.3/web-ui/src/api/client.ts +423 -0
- tailcam-1.8.3/web-ui/src/api/hooks.ts +752 -0
- tailcam-1.8.3/web-ui/src/app/AppShell.tsx +312 -0
- tailcam-1.8.3/web-ui/src/brand/mark.tsx +57 -0
- tailcam-1.8.3/web-ui/src/brand/source/README.md +15 -0
- tailcam-1.8.3/web-ui/src/brand/source/aperture.svg +14 -0
- tailcam-1.8.3/web-ui/src/brand/source/favicon.svg +9 -0
- tailcam-1.8.3/web-ui/src/brand/source/logo-full.svg +14 -0
- tailcam-1.8.3/web-ui/src/brand/source/reticle.svg +14 -0
- tailcam-1.8.3/web-ui/src/components/ActivityFeed.tsx +63 -0
- tailcam-1.8.3/web-ui/src/components/AnnotationEditor.tsx +197 -0
- tailcam-1.8.3/web-ui/src/components/BootOverlay.tsx +29 -0
- tailcam-1.8.3/web-ui/src/components/CameraTile.tsx +32 -0
- tailcam-1.8.3/web-ui/src/components/CommandPalette.tsx +123 -0
- tailcam-1.8.3/web-ui/src/components/FolderPicker.tsx +102 -0
- tailcam-1.8.3/web-ui/src/components/IntegrationsPanel.tsx +327 -0
- tailcam-1.8.3/web-ui/src/components/LiveViewer.tsx +407 -0
- tailcam-1.8.3/web-ui/src/components/Markdown.tsx +300 -0
- tailcam-1.8.3/web-ui/src/components/NotificationsSettings.tsx +179 -0
- tailcam-1.8.3/web-ui/src/components/PluginsPanel.tsx +55 -0
- tailcam-1.8.3/web-ui/src/components/StoragePanel.tsx +294 -0
- tailcam-1.8.3/web-ui/src/components/StreamingPanel.tsx +73 -0
- tailcam-1.8.3/web-ui/src/components/VideoWall.tsx +115 -0
- tailcam-1.8.3/web-ui/src/components/toast.tsx +80 -0
- tailcam-1.8.3/web-ui/src/components/ui.tsx +240 -0
- tailcam-1.8.3/web-ui/src/docs/index.ts +170 -0
- tailcam-1.8.3/web-ui/src/docs/md/active-learning.md +169 -0
- tailcam-1.8.3/web-ui/src/docs/md/ai-analysis.md +124 -0
- tailcam-1.8.3/web-ui/src/docs/md/api.md +115 -0
- tailcam-1.8.3/web-ui/src/docs/md/cameras.md +105 -0
- tailcam-1.8.3/web-ui/src/docs/md/cli.md +84 -0
- tailcam-1.8.3/web-ui/src/docs/md/configuration.md +185 -0
- tailcam-1.8.3/web-ui/src/docs/md/desktop.md +134 -0
- tailcam-1.8.3/web-ui/src/docs/md/docker.md +172 -0
- tailcam-1.8.3/web-ui/src/docs/md/faq.md +79 -0
- tailcam-1.8.3/web-ui/src/docs/md/fleet.md +127 -0
- tailcam-1.8.3/web-ui/src/docs/md/home-automation.md +86 -0
- tailcam-1.8.3/web-ui/src/docs/md/installation.md +122 -0
- tailcam-1.8.3/web-ui/src/docs/md/mcp-connect.md +126 -0
- tailcam-1.8.3/web-ui/src/docs/md/mcp-overview.md +75 -0
- tailcam-1.8.3/web-ui/src/docs/md/mcp-security.md +93 -0
- tailcam-1.8.3/web-ui/src/docs/md/mcp-tools.md +100 -0
- tailcam-1.8.3/web-ui/src/docs/md/motion-detection.md +71 -0
- tailcam-1.8.3/web-ui/src/docs/md/notifications.md +90 -0
- tailcam-1.8.3/web-ui/src/docs/md/overview.md +45 -0
- tailcam-1.8.3/web-ui/src/docs/md/plugins.md +124 -0
- tailcam-1.8.3/web-ui/src/docs/md/quickstart.md +76 -0
- tailcam-1.8.3/web-ui/src/docs/md/recording-media.md +108 -0
- tailcam-1.8.3/web-ui/src/docs/md/security.md +86 -0
- tailcam-1.8.3/web-ui/src/docs/md/tailscale.md +87 -0
- tailcam-1.8.3/web-ui/src/docs/md/timelapse.md +88 -0
- tailcam-1.8.3/web-ui/src/docs/md/training.md +115 -0
- tailcam-1.8.3/web-ui/src/docs/md/troubleshooting.md +210 -0
- tailcam-1.8.3/web-ui/src/icons.tsx +133 -0
- tailcam-1.8.3/web-ui/src/lib/clipboard.ts +34 -0
- tailcam-1.8.3/web-ui/src/lib/format.ts +35 -0
- tailcam-1.8.3/web-ui/src/lib/nav.ts +6 -0
- tailcam-1.8.3/web-ui/src/lib/version.ts +16 -0
- tailcam-1.8.3/web-ui/src/main.tsx +54 -0
- tailcam-1.8.3/web-ui/src/screens/AiActiveLearningTab.tsx +462 -0
- tailcam-1.8.3/web-ui/src/screens/AiModelsTab.tsx +414 -0
- tailcam-1.8.3/web-ui/src/screens/AiStudio.tsx +383 -0
- tailcam-1.8.3/web-ui/src/screens/AiTrainingTab.tsx +546 -0
- tailcam-1.8.3/web-ui/src/screens/CameraDetail.tsx +506 -0
- tailcam-1.8.3/web-ui/src/screens/Dashboard.tsx +218 -0
- tailcam-1.8.3/web-ui/src/screens/Docs.tsx +164 -0
- tailcam-1.8.3/web-ui/src/screens/Events.tsx +133 -0
- tailcam-1.8.3/web-ui/src/screens/Gallery.tsx +234 -0
- tailcam-1.8.3/web-ui/src/screens/McpSetup.tsx +273 -0
- tailcam-1.8.3/web-ui/src/screens/Plugins.tsx +233 -0
- tailcam-1.8.3/web-ui/src/screens/Settings.tsx +168 -0
- tailcam-1.8.3/web-ui/src/screens/Timelapse.tsx +594 -0
- tailcam-1.8.3/web-ui/src/styles.css +1343 -0
- tailcam-1.8.3/web-ui/src/types.ts +735 -0
- tailcam-1.8.3/web-ui/tsconfig.json +21 -0
- tailcam-1.8.3/web-ui/vite.config.ts +87 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Build context hygiene for the TailCam image.
|
|
2
|
+
.git
|
|
3
|
+
.github
|
|
4
|
+
**/__pycache__/
|
|
5
|
+
**/*.pyc
|
|
6
|
+
.venv/
|
|
7
|
+
venv/
|
|
8
|
+
*.egg-info/
|
|
9
|
+
dist/
|
|
10
|
+
build/
|
|
11
|
+
|
|
12
|
+
# Node — the web UI is rebuilt inside the image's web stage.
|
|
13
|
+
web-ui/node_modules/
|
|
14
|
+
|
|
15
|
+
# Tooling caches and tests aren't needed in the image.
|
|
16
|
+
tests/
|
|
17
|
+
.pytest_cache/
|
|
18
|
+
.mypy_cache/
|
|
19
|
+
.ruff_cache/
|
|
20
|
+
|
|
21
|
+
# Repo-level docs sources (the in-app wiki markdown lives under web-ui/ and is
|
|
22
|
+
# bundled by the web build, so it is NOT excluded here).
|
|
23
|
+
docs/
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
name: desktop-app
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths:
|
|
7
|
+
- "src/tailcam/desktop/**"
|
|
8
|
+
- "src/tailcam/cli.py"
|
|
9
|
+
- "tests/test_desktop.py"
|
|
10
|
+
- "pyproject.toml"
|
|
11
|
+
- ".github/workflows/desktop.yml"
|
|
12
|
+
pull_request:
|
|
13
|
+
paths:
|
|
14
|
+
- "src/tailcam/desktop/**"
|
|
15
|
+
- "src/tailcam/cli.py"
|
|
16
|
+
- "tests/test_desktop.py"
|
|
17
|
+
- "pyproject.toml"
|
|
18
|
+
- ".github/workflows/desktop.yml"
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
linux-core:
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v4
|
|
25
|
+
- uses: actions/setup-python@v5
|
|
26
|
+
with:
|
|
27
|
+
python-version: "3.12"
|
|
28
|
+
- run: pip install -e ".[dev]"
|
|
29
|
+
- run: pytest tests/test_desktop.py -q
|
|
30
|
+
|
|
31
|
+
# The reference GUI platform: real pystray/pywebview stack under xvfb.
|
|
32
|
+
linux-gui:
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
steps:
|
|
35
|
+
- uses: actions/checkout@v4
|
|
36
|
+
- name: System GUI deps
|
|
37
|
+
run: |
|
|
38
|
+
sudo apt-get update
|
|
39
|
+
sudo apt-get install -y xvfb dbus-x11 python3-venv python3-gi python3-gi-cairo \
|
|
40
|
+
gir1.2-gtk-3.0 gir1.2-ayatanaappindicator3-0.1
|
|
41
|
+
sudo apt-get install -y gir1.2-webkit2-4.1 || sudo apt-get install -y gir1.2-webkit2gtk-4.1
|
|
42
|
+
- name: Install (system python sees gi)
|
|
43
|
+
run: |
|
|
44
|
+
python3 -m venv --system-site-packages ~/gui-venv
|
|
45
|
+
~/gui-venv/bin/pip install ".[desktop]"
|
|
46
|
+
- name: Backend + diagnostics checks
|
|
47
|
+
run: |
|
|
48
|
+
xvfb-run -a ~/gui-venv/bin/tailcam app --check
|
|
49
|
+
~/gui-venv/bin/tailcam app --smoke
|
|
50
|
+
~/gui-venv/bin/python -c "
|
|
51
|
+
from tailcam.desktop.linux_desktop import gui_diagnostics
|
|
52
|
+
rows = gui_diagnostics()
|
|
53
|
+
assert all(ok for ok, *_ in rows), rows
|
|
54
|
+
print('all GI probes ok:', [label for _, label, _ in rows])
|
|
55
|
+
"
|
|
56
|
+
- name: Real tray runs under xvfb
|
|
57
|
+
run: |
|
|
58
|
+
set +e
|
|
59
|
+
timeout 10 xvfb-run -a dbus-launch ~/gui-venv/bin/tailcam app --no-window
|
|
60
|
+
code=$?
|
|
61
|
+
set -e
|
|
62
|
+
test "$code" = 124 # stayed alive until timeout = the tray ran
|
|
63
|
+
- name: Launcher entries round-trip
|
|
64
|
+
run: |
|
|
65
|
+
~/gui-venv/bin/tailcam app install --autostart
|
|
66
|
+
test -f ~/.local/share/applications/tailcam.desktop
|
|
67
|
+
test -f ~/.local/share/icons/hicolor/512x512/apps/tailcam.png
|
|
68
|
+
test -f ~/.config/autostart/tailcam-tray.desktop
|
|
69
|
+
grep -q "Exec=.*tailcam.* app" ~/.local/share/applications/tailcam.desktop
|
|
70
|
+
~/gui-venv/bin/tailcam app uninstall
|
|
71
|
+
test ! -f ~/.local/share/applications/tailcam.desktop
|
|
72
|
+
|
|
73
|
+
# The real-Mac gate: generates and validates the actual .app on macOS.
|
|
74
|
+
macos-smoke:
|
|
75
|
+
runs-on: macos-latest
|
|
76
|
+
steps:
|
|
77
|
+
- uses: actions/checkout@v4
|
|
78
|
+
- uses: actions/setup-python@v5
|
|
79
|
+
with:
|
|
80
|
+
python-version: "3.12"
|
|
81
|
+
- run: pip install ".[desktop]"
|
|
82
|
+
- name: Create TailCam.app
|
|
83
|
+
run: tailcam app install
|
|
84
|
+
- name: Validate bundle
|
|
85
|
+
run: |
|
|
86
|
+
plutil -lint ~/Applications/TailCam.app/Contents/Info.plist
|
|
87
|
+
codesign --verify --deep ~/Applications/TailCam.app
|
|
88
|
+
test -x ~/Applications/TailCam.app/Contents/MacOS/TailCam
|
|
89
|
+
python -c "
|
|
90
|
+
from pathlib import Path
|
|
91
|
+
import struct
|
|
92
|
+
icns = (Path.home() / 'Applications/TailCam.app/Contents/Resources/TailCam.icns').read_bytes()
|
|
93
|
+
assert icns[:4] == b'icns' and struct.unpack('>I', icns[4:8])[0] == len(icns)
|
|
94
|
+
print('icns ok,', len(icns), 'bytes')
|
|
95
|
+
"
|
|
96
|
+
- name: Headless self-test
|
|
97
|
+
run: |
|
|
98
|
+
tailcam app --check
|
|
99
|
+
tailcam app --smoke
|
|
100
|
+
|
|
101
|
+
# Windows smoke gate: shortcut generation + backends + headless self-test.
|
|
102
|
+
windows-smoke:
|
|
103
|
+
runs-on: windows-latest
|
|
104
|
+
steps:
|
|
105
|
+
- uses: actions/checkout@v4
|
|
106
|
+
- uses: actions/setup-python@v5
|
|
107
|
+
with:
|
|
108
|
+
python-version: "3.12"
|
|
109
|
+
- run: pip install ".[desktop]"
|
|
110
|
+
- name: Backend + smoke checks
|
|
111
|
+
run: |
|
|
112
|
+
tailcam app --check
|
|
113
|
+
tailcam app --smoke
|
|
114
|
+
- name: Shortcut round-trips
|
|
115
|
+
shell: pwsh
|
|
116
|
+
run: |
|
|
117
|
+
tailcam app install --autostart
|
|
118
|
+
$lnk = "$env:APPDATA\Microsoft\Windows\Start Menu\Programs\TailCam.lnk"
|
|
119
|
+
if (-not (Test-Path $lnk)) { throw "shortcut not created" }
|
|
120
|
+
$run = (Get-ItemProperty "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run").TailCam
|
|
121
|
+
if (-not $run) { throw "autostart Run key missing" }
|
|
122
|
+
tailcam app uninstall
|
|
123
|
+
if (Test-Path $lnk) { throw "shortcut not removed" }
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
name: Publish Docker image
|
|
2
|
+
|
|
3
|
+
# Build the multi-arch TailCam image and publish it to the GitHub Container
|
|
4
|
+
# Registry (GHCR) at ghcr.io/<owner>/tailcam.
|
|
5
|
+
#
|
|
6
|
+
# - push to main -> :latest, :main, :sha-<short>
|
|
7
|
+
# - push a tag vX.Y.Z -> :X.Y.Z, :X.Y, :sha-<short>
|
|
8
|
+
# - manual run -> via the Actions tab
|
|
9
|
+
#
|
|
10
|
+
# Uses the built-in GITHUB_TOKEN — no secrets to configure. The first successful
|
|
11
|
+
# run creates the package; make it public in the repo's Packages settings if you
|
|
12
|
+
# want anonymous `docker pull`.
|
|
13
|
+
|
|
14
|
+
on:
|
|
15
|
+
push:
|
|
16
|
+
branches: [main]
|
|
17
|
+
tags: ["v*"]
|
|
18
|
+
workflow_dispatch:
|
|
19
|
+
|
|
20
|
+
env:
|
|
21
|
+
REGISTRY: ghcr.io
|
|
22
|
+
IMAGE_NAME: ${{ github.repository_owner }}/tailcam
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
build-and-push:
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
permissions:
|
|
28
|
+
contents: read
|
|
29
|
+
packages: write
|
|
30
|
+
steps:
|
|
31
|
+
- name: Checkout
|
|
32
|
+
uses: actions/checkout@v4
|
|
33
|
+
|
|
34
|
+
- name: Set up QEMU (multi-arch)
|
|
35
|
+
uses: docker/setup-qemu-action@v3
|
|
36
|
+
|
|
37
|
+
- name: Set up Buildx
|
|
38
|
+
uses: docker/setup-buildx-action@v3
|
|
39
|
+
|
|
40
|
+
- name: Log in to GHCR
|
|
41
|
+
uses: docker/login-action@v3
|
|
42
|
+
with:
|
|
43
|
+
registry: ${{ env.REGISTRY }}
|
|
44
|
+
username: ${{ github.actor }}
|
|
45
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
46
|
+
|
|
47
|
+
- name: Derive image tags & labels
|
|
48
|
+
id: meta
|
|
49
|
+
uses: docker/metadata-action@v5
|
|
50
|
+
with:
|
|
51
|
+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
52
|
+
tags: |
|
|
53
|
+
type=raw,value=latest,enable={{is_default_branch}}
|
|
54
|
+
type=ref,event=branch
|
|
55
|
+
type=semver,pattern={{version}}
|
|
56
|
+
type=semver,pattern={{major}}.{{minor}}
|
|
57
|
+
type=sha,format=short
|
|
58
|
+
|
|
59
|
+
- name: Build and push
|
|
60
|
+
uses: docker/build-push-action@v6
|
|
61
|
+
with:
|
|
62
|
+
context: .
|
|
63
|
+
platforms: linux/amd64,linux/arm64
|
|
64
|
+
push: true
|
|
65
|
+
tags: ${{ steps.meta.outputs.tags }}
|
|
66
|
+
labels: ${{ steps.meta.outputs.labels }}
|
|
67
|
+
cache-from: type=gha
|
|
68
|
+
cache-to: type=gha,mode=max
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
# Trusted Publishing — no PyPI token in GitHub secrets.
|
|
4
|
+
#
|
|
5
|
+
# One-time setup (https://pypi.org/manage/account/publishing/):
|
|
6
|
+
# PyPI project name: tailcam
|
|
7
|
+
# Owner: FactShin
|
|
8
|
+
# Repository: TailCam
|
|
9
|
+
# Workflow name: pypi-publish.yml
|
|
10
|
+
# Environment: pypi
|
|
11
|
+
#
|
|
12
|
+
# Then create a GitHub Release (tag vX.Y.Z) or run this workflow manually.
|
|
13
|
+
|
|
14
|
+
on:
|
|
15
|
+
release:
|
|
16
|
+
types: [published]
|
|
17
|
+
workflow_dispatch:
|
|
18
|
+
|
|
19
|
+
permissions:
|
|
20
|
+
contents: read
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
pypi:
|
|
24
|
+
name: Build and publish
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
environment:
|
|
27
|
+
name: pypi
|
|
28
|
+
url: https://pypi.org/project/tailcam/
|
|
29
|
+
permissions:
|
|
30
|
+
id-token: write
|
|
31
|
+
contents: read
|
|
32
|
+
steps:
|
|
33
|
+
- name: Checkout
|
|
34
|
+
uses: actions/checkout@v4
|
|
35
|
+
|
|
36
|
+
- name: Set up Python
|
|
37
|
+
uses: actions/setup-python@v5
|
|
38
|
+
with:
|
|
39
|
+
python-version: "3.12"
|
|
40
|
+
|
|
41
|
+
- name: Build sdist and wheel
|
|
42
|
+
run: |
|
|
43
|
+
pip install --upgrade build
|
|
44
|
+
python -m build
|
|
45
|
+
|
|
46
|
+
- name: Publish to PyPI
|
|
47
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
name: tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
concurrency:
|
|
9
|
+
group: tests-${{ github.ref }}
|
|
10
|
+
cancel-in-progress: true
|
|
11
|
+
|
|
12
|
+
env:
|
|
13
|
+
# conftest.py sets this too; explicit here so nothing ever touches hardware.
|
|
14
|
+
TAILCAM_SYNTHETIC: "1"
|
|
15
|
+
PIP_DISABLE_PIP_VERSION_CHECK: "1"
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
lint:
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
timeout-minutes: 15
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
- uses: actions/setup-python@v5
|
|
24
|
+
with:
|
|
25
|
+
python-version: "3.12"
|
|
26
|
+
cache: pip
|
|
27
|
+
- run: pip install -e ".[dev]"
|
|
28
|
+
- run: ruff check src tests
|
|
29
|
+
- run: mypy src/tailcam
|
|
30
|
+
|
|
31
|
+
test:
|
|
32
|
+
runs-on: ubuntu-latest
|
|
33
|
+
timeout-minutes: 20
|
|
34
|
+
steps:
|
|
35
|
+
- uses: actions/checkout@v4
|
|
36
|
+
- uses: actions/setup-python@v5
|
|
37
|
+
with:
|
|
38
|
+
python-version: "3.12"
|
|
39
|
+
cache: pip
|
|
40
|
+
# The integration tests exercise the HomeKit (HAP-python) and MQTT extras.
|
|
41
|
+
- run: pip install -e ".[dev,homekit,mqtt]"
|
|
42
|
+
- run: pytest -q
|
|
43
|
+
|
|
44
|
+
# Windows: the platform-specific layers (installer invariants, service
|
|
45
|
+
# registration, desktop shortcut, self-update) plus the API surface. The
|
|
46
|
+
# camera/V4L2 and timing-sensitive capture suites are Linux-only by nature.
|
|
47
|
+
test-windows:
|
|
48
|
+
runs-on: windows-latest
|
|
49
|
+
timeout-minutes: 20
|
|
50
|
+
steps:
|
|
51
|
+
- uses: actions/checkout@v4
|
|
52
|
+
- uses: actions/setup-python@v5
|
|
53
|
+
with:
|
|
54
|
+
python-version: "3.12"
|
|
55
|
+
cache: pip
|
|
56
|
+
- run: pip install -e ".[dev]"
|
|
57
|
+
# test_desktop.py is POSIX-only by nature (launcher entries, .app bundle)
|
|
58
|
+
# and runs in the desktop-app workflow's linux-core/macos jobs.
|
|
59
|
+
- run: >-
|
|
60
|
+
pytest -q tests/test_windows.py tests/test_installer_script.py
|
|
61
|
+
tests/test_service_control.py tests/test_update.py
|
|
62
|
+
tests/test_hostinfo.py tests/test_version.py tests/test_api.py
|
|
63
|
+
tests/test_storage.py tests/test_cluster.py tests/test_mcp.py
|
tailcam-1.8.3/.gitignore
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*.egg-info/
|
|
4
|
+
.eggs/
|
|
5
|
+
build/
|
|
6
|
+
dist/
|
|
7
|
+
.venv/
|
|
8
|
+
venv/
|
|
9
|
+
.pytest_cache/
|
|
10
|
+
.mypy_cache/
|
|
11
|
+
.ruff_cache/
|
|
12
|
+
*.db
|
|
13
|
+
*.db-wal
|
|
14
|
+
*.db-shm
|
|
15
|
+
.DS_Store
|
|
16
|
+
|
|
17
|
+
# web-ui (Node). The BUILT dashboard at src/anycam/web/spa/ IS committed so
|
|
18
|
+
# pip installs ship it; only Node working dirs are ignored.
|
|
19
|
+
web-ui/node_modules/
|
|
20
|
+
web-ui/dist/
|
|
21
|
+
web-ui/.vite/
|
|
22
|
+
|
|
23
|
+
# browser extensions — assembled packages and Safari converter output
|
|
24
|
+
browser-extensions/safari/.build/
|
|
25
|
+
browser-extensions/safari/TailCamCompanion/
|
tailcam-1.8.3/Dockerfile
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# syntax=docker/dockerfile:1
|
|
2
|
+
#
|
|
3
|
+
# TailCam container image. Multi-stage: build the web UI with Node, then ship a
|
|
4
|
+
# slim Python runtime with Tailscale, OpenCV/ffmpeg libs, and the app installed.
|
|
5
|
+
# See docs/docker.md (or the in-app Docs → "Docker" page) for usage.
|
|
6
|
+
|
|
7
|
+
# ---- Stage 1: build the React dashboard ----
|
|
8
|
+
FROM node:22-slim AS web
|
|
9
|
+
WORKDIR /app/web-ui
|
|
10
|
+
COPY web-ui/package.json web-ui/package-lock.json ./
|
|
11
|
+
RUN npm ci
|
|
12
|
+
COPY web-ui/ ./
|
|
13
|
+
# Vite emits to ../src/tailcam/web/spa (OUT_DIR in vite.config.ts).
|
|
14
|
+
RUN npm run build
|
|
15
|
+
|
|
16
|
+
# ---- Stage 2: Python runtime ----
|
|
17
|
+
FROM python:3.12-slim AS runtime
|
|
18
|
+
|
|
19
|
+
ENV PYTHONUNBUFFERED=1 \
|
|
20
|
+
PIP_NO_CACHE_DIR=1 \
|
|
21
|
+
TAILCAM_DATA_DIR=/data \
|
|
22
|
+
TAILCAM_CONFIG_DIR=/config
|
|
23
|
+
|
|
24
|
+
# Runtime libraries: OpenCV (headless) needs libglib2.0-0; ffmpeg for timelapse
|
|
25
|
+
# encoding; curl/ca-certs to install Tailscale; iptables/iproute2 for tailscaled
|
|
26
|
+
# kernel networking.
|
|
27
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
28
|
+
libglib2.0-0 \
|
|
29
|
+
ffmpeg \
|
|
30
|
+
curl \
|
|
31
|
+
ca-certificates \
|
|
32
|
+
iptables \
|
|
33
|
+
iproute2 \
|
|
34
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
35
|
+
|
|
36
|
+
# Tailscale (tailscale CLI + tailscaled). TailCam shells out to `tailscale serve`.
|
|
37
|
+
RUN curl -fsSL https://tailscale.com/install.sh | sh
|
|
38
|
+
|
|
39
|
+
WORKDIR /app
|
|
40
|
+
COPY pyproject.toml README.md ./
|
|
41
|
+
COPY src/ ./src/
|
|
42
|
+
# Use the freshly built dashboard from the web stage so the image always matches
|
|
43
|
+
# source (overwrites the committed copy under src/tailcam/web/spa).
|
|
44
|
+
COPY --from=web /app/src/tailcam/web/spa ./src/tailcam/web/spa
|
|
45
|
+
RUN pip install .
|
|
46
|
+
|
|
47
|
+
COPY docker/entrypoint.sh /usr/local/bin/tailcam-entrypoint
|
|
48
|
+
RUN chmod +x /usr/local/bin/tailcam-entrypoint
|
|
49
|
+
|
|
50
|
+
# Persist the database/media, the config, and Tailscale node state.
|
|
51
|
+
VOLUME ["/data", "/config", "/var/lib/tailscale"]
|
|
52
|
+
|
|
53
|
+
# Local/LAN HTTP port. Tailnet access goes over tailscaled, not a published port.
|
|
54
|
+
EXPOSE 8088
|
|
55
|
+
|
|
56
|
+
ENTRYPOINT ["/usr/local/bin/tailcam-entrypoint"]
|
tailcam-1.8.3/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 TailCam contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|