dialoghelper 0.0.27__tar.gz → 0.0.28__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.

Potentially problematic release.


This version of dialoghelper might be problematic. Click here for more details.

Files changed (22) hide show
  1. {dialoghelper-0.0.27 → dialoghelper-0.0.28}/MANIFEST.in +1 -0
  2. {dialoghelper-0.0.27/dialoghelper.egg-info → dialoghelper-0.0.28}/PKG-INFO +2 -1
  3. dialoghelper-0.0.28/dialoghelper/__init__.py +2 -0
  4. dialoghelper-0.0.28/dialoghelper/screenshot.js +129 -0
  5. {dialoghelper-0.0.27 → dialoghelper-0.0.28/dialoghelper.egg-info}/PKG-INFO +2 -1
  6. {dialoghelper-0.0.27 → dialoghelper-0.0.28}/dialoghelper.egg-info/SOURCES.txt +1 -0
  7. {dialoghelper-0.0.27 → dialoghelper-0.0.28}/dialoghelper.egg-info/requires.txt +1 -0
  8. {dialoghelper-0.0.27 → dialoghelper-0.0.28}/settings.ini +2 -1
  9. dialoghelper-0.0.27/dialoghelper/__init__.py +0 -2
  10. {dialoghelper-0.0.27 → dialoghelper-0.0.28}/LICENSE +0 -0
  11. {dialoghelper-0.0.27 → dialoghelper-0.0.28}/README.md +0 -0
  12. {dialoghelper-0.0.27 → dialoghelper-0.0.28}/dialoghelper/_modidx.py +0 -0
  13. {dialoghelper-0.0.27 → dialoghelper-0.0.28}/dialoghelper/core.py +0 -0
  14. {dialoghelper-0.0.27 → dialoghelper-0.0.28}/dialoghelper/db_dc.py +0 -0
  15. {dialoghelper-0.0.27 → dialoghelper-0.0.28}/dialoghelper/experimental.py +0 -0
  16. {dialoghelper-0.0.27 → dialoghelper-0.0.28}/dialoghelper.egg-info/dependency_links.txt +0 -0
  17. {dialoghelper-0.0.27 → dialoghelper-0.0.28}/dialoghelper.egg-info/entry_points.txt +0 -0
  18. {dialoghelper-0.0.27 → dialoghelper-0.0.28}/dialoghelper.egg-info/not-zip-safe +0 -0
  19. {dialoghelper-0.0.27 → dialoghelper-0.0.28}/dialoghelper.egg-info/top_level.txt +0 -0
  20. {dialoghelper-0.0.27 → dialoghelper-0.0.28}/pyproject.toml +0 -0
  21. {dialoghelper-0.0.27 → dialoghelper-0.0.28}/setup.cfg +0 -0
  22. {dialoghelper-0.0.27 → dialoghelper-0.0.28}/setup.py +0 -0
@@ -2,4 +2,5 @@ include settings.ini
2
2
  include LICENSE
3
3
  include CONTRIBUTING.md
4
4
  include README.md
5
+ include dialoghelper/*.js
5
6
  recursive-exclude * __pycache__
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dialoghelper
3
- Version: 0.0.27
3
+ Version: 0.0.28
4
4
  Summary: Helper functions for solveit dialogs
5
5
  Home-page: https://github.com/AnswerDotAI/dialoghelper
6
6
  Author: Jeremy Howard
@@ -24,6 +24,7 @@ Requires-Dist: ghapi
24
24
  Requires-Dist: ipykernel-helper
25
25
  Requires-Dist: claudette
26
26
  Provides-Extra: dev
27
+ Requires-Dist: python-fasthtml; extra == "dev"
27
28
  Dynamic: author
28
29
  Dynamic: author-email
29
30
  Dynamic: classifier
@@ -0,0 +1,2 @@
1
+ __version__ = "0.0.28"
2
+ from .core import *
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Screenshot capture functionality for dialoghelper
3
+ * Provides persistent screen sharing with HTTP polling for screenshots
4
+ */
5
+
6
+ let persistentStream = null;
7
+ let streamStatus = "disconnected"; // 'disconnected', 'connecting', 'connected', 'error'
8
+
9
+ function sendDataToServer(dataId, data) {
10
+ return fetch('/push_data_blocking_', {
11
+ method: 'POST',
12
+ headers: {'Content-Type': 'application/json'},
13
+ body: JSON.stringify({data_id: dataId, ...data})
14
+ });
15
+ }
16
+
17
+ async function streamToBlob(stream, maxWidth = 1280, maxHeight = 1024) {
18
+ return new Promise((resolve, reject) => {
19
+ const video = document.createElement("video");
20
+ video.srcObject = stream;
21
+ video.muted = true;
22
+ video.playsInline = true;
23
+ video.addEventListener("loadedmetadata", () => {
24
+ // Downscale to maxWidth x maxHeight using canvas
25
+ const videoWidth = video.videoWidth;
26
+ const videoHeight = video.videoHeight;
27
+ const scaleX = maxWidth / videoWidth;
28
+ const scaleY = maxHeight / videoHeight;
29
+ const scale = Math.min(scaleX, scaleY, 1); // don't upscale
30
+ const newWidth = Math.floor(videoWidth * scale);
31
+ const newHeight = Math.floor(videoHeight * scale);
32
+ const canvas = document.createElement("canvas");
33
+ canvas.width = newWidth;
34
+ canvas.height = newHeight;
35
+ const ctx = canvas.getContext("2d");
36
+ ctx.drawImage(video, 0, 0, newWidth, newHeight);
37
+ canvas.toBlob(resolve, "image/png");
38
+ });
39
+ video.addEventListener("error", reject);
40
+ video.play().catch(reject);
41
+ });
42
+ }
43
+
44
+ async function waitForGetDisplayMedia(timeout = 30000) {
45
+ const start = Date.now();
46
+ while (Date.now() - start < timeout) {
47
+ if (navigator.mediaDevices && navigator.mediaDevices.getDisplayMedia) { return true; }
48
+ await new Promise((resolve) => setTimeout(resolve, 100));
49
+ }
50
+ throw new Error("getDisplayMedia not available after timeout");
51
+ }
52
+
53
+ async function startPersistentScreenShare(statusId = null) {
54
+ try {
55
+ await waitForGetDisplayMedia();
56
+ persistentStream = await navigator.mediaDevices.getDisplayMedia({
57
+ video: { mediaSource: "screen", displaySurface: "monitor" }, audio: false,
58
+ });
59
+ persistentStream.getVideoTracks()[0].addEventListener("ended", () => {
60
+ console.log("Screen share ended by user");
61
+ stopPersistentScreenShare();
62
+ });
63
+ console.log("✅ Persistent screen share started");
64
+ if (statusId) { sendDataToServer(statusId, { js_status: "ready" }); }
65
+ streamStatus = "connected";
66
+ return { status: "success", message: "Screen share started" };
67
+ } catch (error) {
68
+ console.error("Failed to start persistent screen share:", error);
69
+ if (statusId) { sendDataToServer(statusId, { js_status: "error", error: error.message }); }
70
+ return { status: "error", message: error.message };
71
+ }
72
+ }
73
+
74
+ function stopPersistentScreenShare() {
75
+ if (persistentStream) {
76
+ persistentStream.getTracks().forEach((track) => track.stop());
77
+ persistentStream = null;
78
+ }
79
+ streamStatus = "disconnected";
80
+ console.log("🛑 Persistent screen share stopped");
81
+ return { status: "success", message: "Screen share stopped" };
82
+ }
83
+
84
+ function blobToBase64(blob) {
85
+ return new Promise((resolve, reject) => {
86
+ const reader = new FileReader();
87
+ reader.onload = () => resolve(reader.result);
88
+ reader.onerror = reject;
89
+ reader.readAsDataURL(blob);
90
+ });
91
+ }
92
+
93
+ async function processScreenshotBlob(blob, dataId) {
94
+ const base64String = await blobToBase64(blob);
95
+ const blob_type = blob.type || "image/png";
96
+ const b64data = base64String.split(",")[1]; // Remove the data URL prefix
97
+ return {
98
+ data_id: dataId,
99
+ size: blob.size,
100
+ img_type: blob_type,
101
+ img_data: b64data,
102
+ };
103
+ }
104
+
105
+ async function captureScreenFromStream(dataId) {
106
+ console.log("Executing screenshot from persistent stream");
107
+ try {
108
+ if (!persistentStream || streamStatus !== "connected") {
109
+ console.log("Stream status:", streamStatus);
110
+ console.log("Persistent stream:", persistentStream);
111
+ throw new Error("No active screen share. Call startPersistentScreenShare() first.");
112
+ }
113
+ const blob = await streamToBlob(persistentStream);
114
+ const result = await processScreenshotBlob(blob, dataId);
115
+ console.log("Screenshot result:", result);
116
+ const pushResponse = await sendDataToServer(dataId, result)
117
+ if (pushResponse.ok) { console.log("✅ Screenshot data pushed to server"); }
118
+ else { console.log("❌ Failed to push screenshot data"); }
119
+ } catch (error) {
120
+ console.error("Screenshot error:", error);
121
+ sendDataToServer(dataId, { error: error.message });
122
+ }
123
+ console.log("Finished executing screenshot");
124
+ }
125
+
126
+ window.startPersistentScreenShare = startPersistentScreenShare;
127
+ window.stopPersistentScreenShare = stopPersistentScreenShare;
128
+ window.captureScreenFromStream = captureScreenFromStream;
129
+ window.getStreamStatus = () => streamStatus;
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dialoghelper
3
- Version: 0.0.27
3
+ Version: 0.0.28
4
4
  Summary: Helper functions for solveit dialogs
5
5
  Home-page: https://github.com/AnswerDotAI/dialoghelper
6
6
  Author: Jeremy Howard
@@ -24,6 +24,7 @@ Requires-Dist: ghapi
24
24
  Requires-Dist: ipykernel-helper
25
25
  Requires-Dist: claudette
26
26
  Provides-Extra: dev
27
+ Requires-Dist: python-fasthtml; extra == "dev"
27
28
  Dynamic: author
28
29
  Dynamic: author-email
29
30
  Dynamic: classifier
@@ -9,6 +9,7 @@ dialoghelper/_modidx.py
9
9
  dialoghelper/core.py
10
10
  dialoghelper/db_dc.py
11
11
  dialoghelper/experimental.py
12
+ dialoghelper/screenshot.js
12
13
  dialoghelper.egg-info/PKG-INFO
13
14
  dialoghelper.egg-info/SOURCES.txt
14
15
  dialoghelper.egg-info/dependency_links.txt
@@ -5,3 +5,4 @@ ipykernel-helper
5
5
  claudette
6
6
 
7
7
  [dev]
8
+ python-fasthtml
@@ -1,11 +1,12 @@
1
1
  [DEFAULT]
2
2
  repo = dialoghelper
3
3
  lib_name = dialoghelper
4
- version = 0.0.27
4
+ version = 0.0.28
5
5
  min_python = 3.9
6
6
  license = apache2
7
7
  black_formatting = False
8
8
  requirements = fastcore>=1.8.5 fastlite ghapi ipykernel-helper claudette
9
+ dev_requirements = python-fasthtml
9
10
  doc_path = _docs
10
11
  lib_path = dialoghelper
11
12
  nbs_path = nbs
@@ -1,2 +0,0 @@
1
- __version__ = "0.0.27"
2
- from .core import *
File without changes
File without changes
File without changes
File without changes