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.
Files changed (382) hide show
  1. tailcam-1.8.3/.dockerignore +23 -0
  2. tailcam-1.8.3/.github/workflows/desktop.yml +123 -0
  3. tailcam-1.8.3/.github/workflows/docker-publish.yml +68 -0
  4. tailcam-1.8.3/.github/workflows/pypi-publish.yml +47 -0
  5. tailcam-1.8.3/.github/workflows/tests.yml +63 -0
  6. tailcam-1.8.3/.gitignore +25 -0
  7. tailcam-1.8.3/Dockerfile +56 -0
  8. tailcam-1.8.3/LICENSE +21 -0
  9. tailcam-1.8.3/PKG-INFO +648 -0
  10. tailcam-1.8.3/README.md +577 -0
  11. tailcam-1.8.3/TESTING.md +216 -0
  12. tailcam-1.8.3/browser-extensions/README.md +144 -0
  13. tailcam-1.8.3/browser-extensions/build.py +132 -0
  14. tailcam-1.8.3/browser-extensions/chrome/manifest.json +55 -0
  15. tailcam-1.8.3/browser-extensions/edge/manifest.json +55 -0
  16. tailcam-1.8.3/browser-extensions/firefox/manifest.json +61 -0
  17. tailcam-1.8.3/browser-extensions/safari/convert-safari.sh +65 -0
  18. tailcam-1.8.3/browser-extensions/safari/manifest.json +55 -0
  19. tailcam-1.8.3/browser-extensions/shared/background.js +499 -0
  20. tailcam-1.8.3/browser-extensions/shared/glance/glance.css +298 -0
  21. tailcam-1.8.3/browser-extensions/shared/glance/glance.html +41 -0
  22. tailcam-1.8.3/browser-extensions/shared/glance/glance.js +438 -0
  23. tailcam-1.8.3/browser-extensions/shared/icons/icon-128.png +0 -0
  24. tailcam-1.8.3/browser-extensions/shared/icons/icon-16.png +0 -0
  25. tailcam-1.8.3/browser-extensions/shared/icons/icon-256.png +0 -0
  26. tailcam-1.8.3/browser-extensions/shared/icons/icon-32.png +0 -0
  27. tailcam-1.8.3/browser-extensions/shared/icons/icon-48.png +0 -0
  28. tailcam-1.8.3/browser-extensions/shared/lib/api.js +267 -0
  29. tailcam-1.8.3/browser-extensions/shared/lib/compat.js +177 -0
  30. tailcam-1.8.3/browser-extensions/shared/lib/format.js +79 -0
  31. tailcam-1.8.3/browser-extensions/shared/lib/settings.js +210 -0
  32. tailcam-1.8.3/browser-extensions/shared/options/options.css +386 -0
  33. tailcam-1.8.3/browser-extensions/shared/options/options.html +131 -0
  34. tailcam-1.8.3/browser-extensions/shared/options/options.js +429 -0
  35. tailcam-1.8.3/browser-extensions/shared/popup/popup.css +559 -0
  36. tailcam-1.8.3/browser-extensions/shared/popup/popup.html +51 -0
  37. tailcam-1.8.3/browser-extensions/shared/popup/popup.js +507 -0
  38. tailcam-1.8.3/docker/entrypoint.sh +73 -0
  39. tailcam-1.8.3/docker-compose.yml +49 -0
  40. tailcam-1.8.3/docs/ai-detection-plan.md +83 -0
  41. tailcam-1.8.3/docs/design-prototype/DESIGN-README.md +25 -0
  42. tailcam-1.8.3/docs/design-prototype/design-chat.md +313 -0
  43. tailcam-1.8.3/docs/design-prototype/js/app.jsx +171 -0
  44. tailcam-1.8.3/docs/design-prototype/js/icons.jsx +95 -0
  45. tailcam-1.8.3/docs/design-prototype/js/mock.jsx +399 -0
  46. tailcam-1.8.3/docs/design-prototype/js/screens1.jsx +293 -0
  47. tailcam-1.8.3/docs/design-prototype/js/screens2.jsx +297 -0
  48. tailcam-1.8.3/docs/design-prototype/js/ui.jsx +211 -0
  49. tailcam-1.8.3/docs/design-prototype/js/viewer.jsx +305 -0
  50. tailcam-1.8.3/docs/design-prototype/styles.css +445 -0
  51. tailcam-1.8.3/docs/design-prototype/tweaks-panel.jsx +541 -0
  52. tailcam-1.8.3/docs/mcp-security.md +121 -0
  53. tailcam-1.8.3/docs/mcp.md +243 -0
  54. tailcam-1.8.3/docs/screenshots/README.md +39 -0
  55. tailcam-1.8.3/docs/screenshots/agents.png +0 -0
  56. tailcam-1.8.3/docs/screenshots/ai-studio.png +0 -0
  57. tailcam-1.8.3/docs/screenshots/camera.png +0 -0
  58. tailcam-1.8.3/docs/screenshots/dashboard.png +0 -0
  59. tailcam-1.8.3/docs/screenshots/docs.png +0 -0
  60. tailcam-1.8.3/docs/screenshots/events.png +0 -0
  61. tailcam-1.8.3/docs/screenshots/gallery.png +0 -0
  62. tailcam-1.8.3/docs/screenshots/palette.png +0 -0
  63. tailcam-1.8.3/docs/screenshots/plugins.png +0 -0
  64. tailcam-1.8.3/docs/screenshots/settings.png +0 -0
  65. tailcam-1.8.3/docs/screenshots/timelapse.png +0 -0
  66. tailcam-1.8.3/docs/screenshots/videowall.png +0 -0
  67. tailcam-1.8.3/docs/superpowers/specs/2026-06-17-tailcam-mcp-design.md +495 -0
  68. tailcam-1.8.3/docs/tailscale-grants.md +119 -0
  69. tailcam-1.8.3/docs/web-ui-plan.md +134 -0
  70. tailcam-1.8.3/examples/mcp/claude_desktop_config.json +12 -0
  71. tailcam-1.8.3/examples/mcp/codex.config.toml +17 -0
  72. tailcam-1.8.3/examples/mcp/hermes-openclaw.json +27 -0
  73. tailcam-1.8.3/examples/notifications/sample-payloads.json +48 -0
  74. tailcam-1.8.3/examples/plugins/README.md +96 -0
  75. tailcam-1.8.3/examples/plugins/ntfy_channel.py +64 -0
  76. tailcam-1.8.3/examples/skills/tailcam-alerts.md +82 -0
  77. tailcam-1.8.3/install-docker.sh +124 -0
  78. tailcam-1.8.3/install-linux.sh +429 -0
  79. tailcam-1.8.3/install-macos.sh +300 -0
  80. tailcam-1.8.3/install.ps1 +453 -0
  81. tailcam-1.8.3/marketplace/README.md +42 -0
  82. tailcam-1.8.3/marketplace/TEMPLATE.py +107 -0
  83. tailcam-1.8.3/marketplace/build_index.py +79 -0
  84. tailcam-1.8.3/marketplace/index.json +69 -0
  85. tailcam-1.8.3/marketplace/plugins/event_logger.py +86 -0
  86. tailcam-1.8.3/marketplace/plugins/ntfy_notifier.py +91 -0
  87. tailcam-1.8.3/marketplace/plugins/openai_analyzer.py +145 -0
  88. tailcam-1.8.3/marketplace/plugins/slack_notifier.py +70 -0
  89. tailcam-1.8.3/pyproject.toml +122 -0
  90. tailcam-1.8.3/src/tailcam/__init__.py +3 -0
  91. tailcam-1.8.3/src/tailcam/__main__.py +4 -0
  92. tailcam-1.8.3/src/tailcam/activelearning/__init__.py +20 -0
  93. tailcam-1.8.3/src/tailcam/activelearning/annotations.py +230 -0
  94. tailcam-1.8.3/src/tailcam/activelearning/backends.py +270 -0
  95. tailcam-1.8.3/src/tailcam/activelearning/florence.py +246 -0
  96. tailcam-1.8.3/src/tailcam/activelearning/labelstudio.py +284 -0
  97. tailcam-1.8.3/src/tailcam/activelearning/qwen.py +298 -0
  98. tailcam-1.8.3/src/tailcam/activelearning/service.py +656 -0
  99. tailcam-1.8.3/src/tailcam/ai/__init__.py +8 -0
  100. tailcam-1.8.3/src/tailcam/ai/analyzer.py +185 -0
  101. tailcam-1.8.3/src/tailcam/ai/detector.py +367 -0
  102. tailcam-1.8.3/src/tailcam/ai/pull.py +121 -0
  103. tailcam-1.8.3/src/tailcam/ai/remote.py +151 -0
  104. tailcam-1.8.3/src/tailcam/camera/__init__.py +1 -0
  105. tailcam-1.8.3/src/tailcam/camera/enumerate.py +158 -0
  106. tailcam-1.8.3/src/tailcam/camera/frame.py +131 -0
  107. tailcam-1.8.3/src/tailcam/camera/manager.py +261 -0
  108. tailcam-1.8.3/src/tailcam/camera/properties.py +45 -0
  109. tailcam-1.8.3/src/tailcam/camera/source.py +376 -0
  110. tailcam-1.8.3/src/tailcam/camera/transforms.py +101 -0
  111. tailcam-1.8.3/src/tailcam/camera/worker.py +201 -0
  112. tailcam-1.8.3/src/tailcam/cli.py +868 -0
  113. tailcam-1.8.3/src/tailcam/cluster/__init__.py +2 -0
  114. tailcam-1.8.3/src/tailcam/cluster/fleet.py +57 -0
  115. tailcam-1.8.3/src/tailcam/cluster/remote_feed.py +227 -0
  116. tailcam-1.8.3/src/tailcam/cluster/service.py +238 -0
  117. tailcam-1.8.3/src/tailcam/config.py +538 -0
  118. tailcam-1.8.3/src/tailcam/desktop/__init__.py +40 -0
  119. tailcam-1.8.3/src/tailcam/desktop/app.py +182 -0
  120. tailcam-1.8.3/src/tailcam/desktop/assets/app-icon-512.png +0 -0
  121. tailcam-1.8.3/src/tailcam/desktop/assets/server_down.html +31 -0
  122. tailcam-1.8.3/src/tailcam/desktop/assets/tray-icon-template.png +0 -0
  123. tailcam-1.8.3/src/tailcam/desktop/assets/tray-icon.png +0 -0
  124. tailcam-1.8.3/src/tailcam/desktop/linux_desktop.py +149 -0
  125. tailcam-1.8.3/src/tailcam/desktop/macos_bundle.py +144 -0
  126. tailcam-1.8.3/src/tailcam/desktop/menu.py +92 -0
  127. tailcam-1.8.3/src/tailcam/desktop/nodes.py +51 -0
  128. tailcam-1.8.3/src/tailcam/desktop/server.py +96 -0
  129. tailcam-1.8.3/src/tailcam/desktop/state.py +56 -0
  130. tailcam-1.8.3/src/tailcam/desktop/tray.py +81 -0
  131. tailcam-1.8.3/src/tailcam/desktop/updates.py +29 -0
  132. tailcam-1.8.3/src/tailcam/desktop/window.py +59 -0
  133. tailcam-1.8.3/src/tailcam/desktop/windows_shortcut.py +136 -0
  134. tailcam-1.8.3/src/tailcam/hostinfo.py +125 -0
  135. tailcam-1.8.3/src/tailcam/integrations/__init__.py +1 -0
  136. tailcam-1.8.3/src/tailcam/integrations/base.py +100 -0
  137. tailcam-1.8.3/src/tailcam/integrations/homeassistant.py +323 -0
  138. tailcam-1.8.3/src/tailcam/integrations/homekit.py +329 -0
  139. tailcam-1.8.3/src/tailcam/logging_setup.py +26 -0
  140. tailcam-1.8.3/src/tailcam/management/__init__.py +7 -0
  141. tailcam-1.8.3/src/tailcam/management/audit.py +49 -0
  142. tailcam-1.8.3/src/tailcam/management/capabilities.py +43 -0
  143. tailcam-1.8.3/src/tailcam/management/health.py +190 -0
  144. tailcam-1.8.3/src/tailcam/mcp/__init__.py +56 -0
  145. tailcam-1.8.3/src/tailcam/mcp/client.py +378 -0
  146. tailcam-1.8.3/src/tailcam/mcp/errors.py +63 -0
  147. tailcam-1.8.3/src/tailcam/mcp/prompts.py +109 -0
  148. tailcam-1.8.3/src/tailcam/mcp/protocol.py +106 -0
  149. tailcam-1.8.3/src/tailcam/mcp/resources.py +98 -0
  150. tailcam-1.8.3/src/tailcam/mcp/server.py +289 -0
  151. tailcam-1.8.3/src/tailcam/mcp/toolctx.py +80 -0
  152. tailcam-1.8.3/src/tailcam/mcp/tools.py +1151 -0
  153. tailcam-1.8.3/src/tailcam/mcp/transport_http.py +235 -0
  154. tailcam-1.8.3/src/tailcam/mcp/transport_stdio.py +95 -0
  155. tailcam-1.8.3/src/tailcam/media/__init__.py +1 -0
  156. tailcam-1.8.3/src/tailcam/media/capture_router.py +279 -0
  157. tailcam-1.8.3/src/tailcam/media/gallery.py +95 -0
  158. tailcam-1.8.3/src/tailcam/media/recorder.py +247 -0
  159. tailcam-1.8.3/src/tailcam/media/snapshot.py +66 -0
  160. tailcam-1.8.3/src/tailcam/media/video_sink.py +248 -0
  161. tailcam-1.8.3/src/tailcam/migrate.py +126 -0
  162. tailcam-1.8.3/src/tailcam/motion/__init__.py +1 -0
  163. tailcam-1.8.3/src/tailcam/motion/detector.py +63 -0
  164. tailcam-1.8.3/src/tailcam/motion/events.py +39 -0
  165. tailcam-1.8.3/src/tailcam/motion/worker.py +193 -0
  166. tailcam-1.8.3/src/tailcam/notify/__init__.py +0 -0
  167. tailcam-1.8.3/src/tailcam/notify/service.py +262 -0
  168. tailcam-1.8.3/src/tailcam/paths.py +152 -0
  169. tailcam-1.8.3/src/tailcam/persistence/__init__.py +1 -0
  170. tailcam-1.8.3/src/tailcam/persistence/models.py +209 -0
  171. tailcam-1.8.3/src/tailcam/persistence/store.py +1230 -0
  172. tailcam-1.8.3/src/tailcam/plugins/__init__.py +0 -0
  173. tailcam-1.8.3/src/tailcam/plugins/builtin/__init__.py +0 -0
  174. tailcam-1.8.3/src/tailcam/plugins/builtin/ai_providers.py +34 -0
  175. tailcam-1.8.3/src/tailcam/plugins/builtin/channels.py +72 -0
  176. tailcam-1.8.3/src/tailcam/plugins/hookspecs.py +111 -0
  177. tailcam-1.8.3/src/tailcam/plugins/market.py +259 -0
  178. tailcam-1.8.3/src/tailcam/plugins/registry.py +140 -0
  179. tailcam-1.8.3/src/tailcam/plugins/sdk.py +98 -0
  180. tailcam-1.8.3/src/tailcam/proc.py +25 -0
  181. tailcam-1.8.3/src/tailcam/security/__init__.py +5 -0
  182. tailcam-1.8.3/src/tailcam/security/principal.py +167 -0
  183. tailcam-1.8.3/src/tailcam/service/__init__.py +1 -0
  184. tailcam-1.8.3/src/tailcam/service/installer.py +364 -0
  185. tailcam-1.8.3/src/tailcam/streaming/__init__.py +1 -0
  186. tailcam-1.8.3/src/tailcam/streaming/backend.py +24 -0
  187. tailcam-1.8.3/src/tailcam/streaming/encoder.py +14 -0
  188. tailcam-1.8.3/src/tailcam/streaming/mjpeg.py +118 -0
  189. tailcam-1.8.3/src/tailcam/tailscale/__init__.py +1 -0
  190. tailcam-1.8.3/src/tailcam/tailscale/client.py +200 -0
  191. tailcam-1.8.3/src/tailcam/timelapse/__init__.py +7 -0
  192. tailcam-1.8.3/src/tailcam/timelapse/analyzer.py +169 -0
  193. tailcam-1.8.3/src/tailcam/timelapse/ffmpeg.py +199 -0
  194. tailcam-1.8.3/src/tailcam/timelapse/presets.py +64 -0
  195. tailcam-1.8.3/src/tailcam/timelapse/rife.py +76 -0
  196. tailcam-1.8.3/src/tailcam/timelapse/service.py +570 -0
  197. tailcam-1.8.3/src/tailcam/timelapse/worker.py +122 -0
  198. tailcam-1.8.3/src/tailcam/training/__init__.py +8 -0
  199. tailcam-1.8.3/src/tailcam/training/engine.py +58 -0
  200. tailcam-1.8.3/src/tailcam/training/inference.py +351 -0
  201. tailcam-1.8.3/src/tailcam/training/runner.py +209 -0
  202. tailcam-1.8.3/src/tailcam/training/service.py +508 -0
  203. tailcam-1.8.3/src/tailcam/update.py +110 -0
  204. tailcam-1.8.3/src/tailcam/web/__init__.py +1 -0
  205. tailcam-1.8.3/src/tailcam/web/app.py +102 -0
  206. tailcam-1.8.3/src/tailcam/web/context.py +493 -0
  207. tailcam-1.8.3/src/tailcam/web/deps.py +11 -0
  208. tailcam-1.8.3/src/tailcam/web/routes_active.py +201 -0
  209. tailcam-1.8.3/src/tailcam/web/routes_api.py +1884 -0
  210. tailcam-1.8.3/src/tailcam/web/routes_fleet_v1.py +172 -0
  211. tailcam-1.8.3/src/tailcam/web/routes_node_v1.py +189 -0
  212. tailcam-1.8.3/src/tailcam/web/routes_pages.py +46 -0
  213. tailcam-1.8.3/src/tailcam/web/routes_proxy.py +88 -0
  214. tailcam-1.8.3/src/tailcam/web/routes_remote.py +162 -0
  215. tailcam-1.8.3/src/tailcam/web/routes_stream.py +168 -0
  216. tailcam-1.8.3/src/tailcam/web/schemas.py +960 -0
  217. tailcam-1.8.3/src/tailcam/web/security.py +126 -0
  218. tailcam-1.8.3/src/tailcam/web/spa/apple-touch-icon-light.png +0 -0
  219. tailcam-1.8.3/src/tailcam/web/spa/apple-touch-icon.png +0 -0
  220. tailcam-1.8.3/src/tailcam/web/spa/assets/index-CEMCQF_y.css +1 -0
  221. tailcam-1.8.3/src/tailcam/web/spa/assets/index-cqHUOMzL.js +2343 -0
  222. tailcam-1.8.3/src/tailcam/web/spa/favicon-16.png +0 -0
  223. tailcam-1.8.3/src/tailcam/web/spa/favicon-32.png +0 -0
  224. tailcam-1.8.3/src/tailcam/web/spa/favicon.ico +0 -0
  225. tailcam-1.8.3/src/tailcam/web/spa/favicon.svg +9 -0
  226. tailcam-1.8.3/src/tailcam/web/spa/icon-192-maskable.png +0 -0
  227. tailcam-1.8.3/src/tailcam/web/spa/icon-192.png +0 -0
  228. tailcam-1.8.3/src/tailcam/web/spa/icon-512-light.png +0 -0
  229. tailcam-1.8.3/src/tailcam/web/spa/icon-512-maskable.png +0 -0
  230. tailcam-1.8.3/src/tailcam/web/spa/icon-512.png +0 -0
  231. tailcam-1.8.3/src/tailcam/web/spa/index.html +26 -0
  232. tailcam-1.8.3/src/tailcam/web/spa/manifest.webmanifest +1 -0
  233. tailcam-1.8.3/src/tailcam/web/spa/registerSW.js +1 -0
  234. tailcam-1.8.3/src/tailcam/web/spa/sw.js +1 -0
  235. tailcam-1.8.3/src/tailcam/web/spa/workbox-abeb32eb.js +1 -0
  236. tailcam-1.8.3/src/tailcam/web/static/css/app.css +95 -0
  237. tailcam-1.8.3/src/tailcam/web/static/js/app.js +232 -0
  238. tailcam-1.8.3/src/tailcam/web/templates/base.html +25 -0
  239. tailcam-1.8.3/src/tailcam/web/templates/camera.html +78 -0
  240. tailcam-1.8.3/src/tailcam/web/templates/events.html +23 -0
  241. tailcam-1.8.3/src/tailcam/web/templates/gallery.html +25 -0
  242. tailcam-1.8.3/src/tailcam/web/templates/index.html +32 -0
  243. tailcam-1.8.3/tests/conftest.py +77 -0
  244. tailcam-1.8.3/tests/test_active_learning.py +474 -0
  245. tailcam-1.8.3/tests/test_ai.py +85 -0
  246. tailcam-1.8.3/tests/test_api.py +293 -0
  247. tailcam-1.8.3/tests/test_audit.py +80 -0
  248. tailcam-1.8.3/tests/test_audit_round2.py +376 -0
  249. tailcam-1.8.3/tests/test_browser_extensions.py +108 -0
  250. tailcam-1.8.3/tests/test_builtin_detection.py +441 -0
  251. tailcam-1.8.3/tests/test_camera_open.py +165 -0
  252. tailcam-1.8.3/tests/test_cli.py +51 -0
  253. tailcam-1.8.3/tests/test_cluster.py +112 -0
  254. tailcam-1.8.3/tests/test_desktop.py +496 -0
  255. tailcam-1.8.3/tests/test_detection.py +323 -0
  256. tailcam-1.8.3/tests/test_detection_routing.py +144 -0
  257. tailcam-1.8.3/tests/test_docs_ui.py +25 -0
  258. tailcam-1.8.3/tests/test_enumerate.py +35 -0
  259. tailcam-1.8.3/tests/test_fleet_api.py +163 -0
  260. tailcam-1.8.3/tests/test_frame_buffer.py +63 -0
  261. tailcam-1.8.3/tests/test_frame_consumer.py +74 -0
  262. tailcam-1.8.3/tests/test_fs_browse.py +31 -0
  263. tailcam-1.8.3/tests/test_hostinfo.py +87 -0
  264. tailcam-1.8.3/tests/test_installer_script.py +143 -0
  265. tailcam-1.8.3/tests/test_integrations.py +154 -0
  266. tailcam-1.8.3/tests/test_management_health.py +163 -0
  267. tailcam-1.8.3/tests/test_mcp.py +689 -0
  268. tailcam-1.8.3/tests/test_mjpeg.py +77 -0
  269. tailcam-1.8.3/tests/test_motion_detector.py +67 -0
  270. tailcam-1.8.3/tests/test_node_api.py +94 -0
  271. tailcam-1.8.3/tests/test_notify.py +118 -0
  272. tailcam-1.8.3/tests/test_plugin_market.py +307 -0
  273. tailcam-1.8.3/tests/test_plugins.py +92 -0
  274. tailcam-1.8.3/tests/test_principal.py +166 -0
  275. tailcam-1.8.3/tests/test_proc.py +76 -0
  276. tailcam-1.8.3/tests/test_rename_migration.py +174 -0
  277. tailcam-1.8.3/tests/test_service_control.py +152 -0
  278. tailcam-1.8.3/tests/test_storage.py +133 -0
  279. tailcam-1.8.3/tests/test_storage_node.py +217 -0
  280. tailcam-1.8.3/tests/test_tailscale.py +139 -0
  281. tailcam-1.8.3/tests/test_timelapse.py +432 -0
  282. tailcam-1.8.3/tests/test_timelapse_analyzer.py +189 -0
  283. tailcam-1.8.3/tests/test_timelapse_printer.py +287 -0
  284. tailcam-1.8.3/tests/test_training.py +317 -0
  285. tailcam-1.8.3/tests/test_transforms.py +65 -0
  286. tailcam-1.8.3/tests/test_update.py +179 -0
  287. tailcam-1.8.3/tests/test_version.py +35 -0
  288. tailcam-1.8.3/tests/test_windows.py +109 -0
  289. tailcam-1.8.3/uninstall-linux.sh +82 -0
  290. tailcam-1.8.3/uninstall-macos.sh +41 -0
  291. tailcam-1.8.3/uninstall.ps1 +68 -0
  292. tailcam-1.8.3/web-ui/README.md +49 -0
  293. tailcam-1.8.3/web-ui/index.html +25 -0
  294. tailcam-1.8.3/web-ui/package-lock.json +6170 -0
  295. tailcam-1.8.3/web-ui/package.json +27 -0
  296. tailcam-1.8.3/web-ui/public/apple-touch-icon-light.png +0 -0
  297. tailcam-1.8.3/web-ui/public/apple-touch-icon.png +0 -0
  298. tailcam-1.8.3/web-ui/public/favicon-16.png +0 -0
  299. tailcam-1.8.3/web-ui/public/favicon-32.png +0 -0
  300. tailcam-1.8.3/web-ui/public/favicon.ico +0 -0
  301. tailcam-1.8.3/web-ui/public/favicon.svg +9 -0
  302. tailcam-1.8.3/web-ui/public/icon-192-maskable.png +0 -0
  303. tailcam-1.8.3/web-ui/public/icon-192.png +0 -0
  304. tailcam-1.8.3/web-ui/public/icon-512-light.png +0 -0
  305. tailcam-1.8.3/web-ui/public/icon-512-maskable.png +0 -0
  306. tailcam-1.8.3/web-ui/public/icon-512.png +0 -0
  307. tailcam-1.8.3/web-ui/src/api/client.ts +423 -0
  308. tailcam-1.8.3/web-ui/src/api/hooks.ts +752 -0
  309. tailcam-1.8.3/web-ui/src/app/AppShell.tsx +312 -0
  310. tailcam-1.8.3/web-ui/src/brand/mark.tsx +57 -0
  311. tailcam-1.8.3/web-ui/src/brand/source/README.md +15 -0
  312. tailcam-1.8.3/web-ui/src/brand/source/aperture.svg +14 -0
  313. tailcam-1.8.3/web-ui/src/brand/source/favicon.svg +9 -0
  314. tailcam-1.8.3/web-ui/src/brand/source/logo-full.svg +14 -0
  315. tailcam-1.8.3/web-ui/src/brand/source/reticle.svg +14 -0
  316. tailcam-1.8.3/web-ui/src/components/ActivityFeed.tsx +63 -0
  317. tailcam-1.8.3/web-ui/src/components/AnnotationEditor.tsx +197 -0
  318. tailcam-1.8.3/web-ui/src/components/BootOverlay.tsx +29 -0
  319. tailcam-1.8.3/web-ui/src/components/CameraTile.tsx +32 -0
  320. tailcam-1.8.3/web-ui/src/components/CommandPalette.tsx +123 -0
  321. tailcam-1.8.3/web-ui/src/components/FolderPicker.tsx +102 -0
  322. tailcam-1.8.3/web-ui/src/components/IntegrationsPanel.tsx +327 -0
  323. tailcam-1.8.3/web-ui/src/components/LiveViewer.tsx +407 -0
  324. tailcam-1.8.3/web-ui/src/components/Markdown.tsx +300 -0
  325. tailcam-1.8.3/web-ui/src/components/NotificationsSettings.tsx +179 -0
  326. tailcam-1.8.3/web-ui/src/components/PluginsPanel.tsx +55 -0
  327. tailcam-1.8.3/web-ui/src/components/StoragePanel.tsx +294 -0
  328. tailcam-1.8.3/web-ui/src/components/StreamingPanel.tsx +73 -0
  329. tailcam-1.8.3/web-ui/src/components/VideoWall.tsx +115 -0
  330. tailcam-1.8.3/web-ui/src/components/toast.tsx +80 -0
  331. tailcam-1.8.3/web-ui/src/components/ui.tsx +240 -0
  332. tailcam-1.8.3/web-ui/src/docs/index.ts +170 -0
  333. tailcam-1.8.3/web-ui/src/docs/md/active-learning.md +169 -0
  334. tailcam-1.8.3/web-ui/src/docs/md/ai-analysis.md +124 -0
  335. tailcam-1.8.3/web-ui/src/docs/md/api.md +115 -0
  336. tailcam-1.8.3/web-ui/src/docs/md/cameras.md +105 -0
  337. tailcam-1.8.3/web-ui/src/docs/md/cli.md +84 -0
  338. tailcam-1.8.3/web-ui/src/docs/md/configuration.md +185 -0
  339. tailcam-1.8.3/web-ui/src/docs/md/desktop.md +134 -0
  340. tailcam-1.8.3/web-ui/src/docs/md/docker.md +172 -0
  341. tailcam-1.8.3/web-ui/src/docs/md/faq.md +79 -0
  342. tailcam-1.8.3/web-ui/src/docs/md/fleet.md +127 -0
  343. tailcam-1.8.3/web-ui/src/docs/md/home-automation.md +86 -0
  344. tailcam-1.8.3/web-ui/src/docs/md/installation.md +122 -0
  345. tailcam-1.8.3/web-ui/src/docs/md/mcp-connect.md +126 -0
  346. tailcam-1.8.3/web-ui/src/docs/md/mcp-overview.md +75 -0
  347. tailcam-1.8.3/web-ui/src/docs/md/mcp-security.md +93 -0
  348. tailcam-1.8.3/web-ui/src/docs/md/mcp-tools.md +100 -0
  349. tailcam-1.8.3/web-ui/src/docs/md/motion-detection.md +71 -0
  350. tailcam-1.8.3/web-ui/src/docs/md/notifications.md +90 -0
  351. tailcam-1.8.3/web-ui/src/docs/md/overview.md +45 -0
  352. tailcam-1.8.3/web-ui/src/docs/md/plugins.md +124 -0
  353. tailcam-1.8.3/web-ui/src/docs/md/quickstart.md +76 -0
  354. tailcam-1.8.3/web-ui/src/docs/md/recording-media.md +108 -0
  355. tailcam-1.8.3/web-ui/src/docs/md/security.md +86 -0
  356. tailcam-1.8.3/web-ui/src/docs/md/tailscale.md +87 -0
  357. tailcam-1.8.3/web-ui/src/docs/md/timelapse.md +88 -0
  358. tailcam-1.8.3/web-ui/src/docs/md/training.md +115 -0
  359. tailcam-1.8.3/web-ui/src/docs/md/troubleshooting.md +210 -0
  360. tailcam-1.8.3/web-ui/src/icons.tsx +133 -0
  361. tailcam-1.8.3/web-ui/src/lib/clipboard.ts +34 -0
  362. tailcam-1.8.3/web-ui/src/lib/format.ts +35 -0
  363. tailcam-1.8.3/web-ui/src/lib/nav.ts +6 -0
  364. tailcam-1.8.3/web-ui/src/lib/version.ts +16 -0
  365. tailcam-1.8.3/web-ui/src/main.tsx +54 -0
  366. tailcam-1.8.3/web-ui/src/screens/AiActiveLearningTab.tsx +462 -0
  367. tailcam-1.8.3/web-ui/src/screens/AiModelsTab.tsx +414 -0
  368. tailcam-1.8.3/web-ui/src/screens/AiStudio.tsx +383 -0
  369. tailcam-1.8.3/web-ui/src/screens/AiTrainingTab.tsx +546 -0
  370. tailcam-1.8.3/web-ui/src/screens/CameraDetail.tsx +506 -0
  371. tailcam-1.8.3/web-ui/src/screens/Dashboard.tsx +218 -0
  372. tailcam-1.8.3/web-ui/src/screens/Docs.tsx +164 -0
  373. tailcam-1.8.3/web-ui/src/screens/Events.tsx +133 -0
  374. tailcam-1.8.3/web-ui/src/screens/Gallery.tsx +234 -0
  375. tailcam-1.8.3/web-ui/src/screens/McpSetup.tsx +273 -0
  376. tailcam-1.8.3/web-ui/src/screens/Plugins.tsx +233 -0
  377. tailcam-1.8.3/web-ui/src/screens/Settings.tsx +168 -0
  378. tailcam-1.8.3/web-ui/src/screens/Timelapse.tsx +594 -0
  379. tailcam-1.8.3/web-ui/src/styles.css +1343 -0
  380. tailcam-1.8.3/web-ui/src/types.ts +735 -0
  381. tailcam-1.8.3/web-ui/tsconfig.json +21 -0
  382. 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
@@ -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/
@@ -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.