|
28 | 28 | "outputs": [], |
29 | 29 | "source": [ |
30 | 30 | "#| export\n", |
31 | | -"\n", |
| 31 | +"import uuid,json\n", |
32 | 32 | "from importlib import resources\n", |
33 | | -"import uuid\n", |
34 | | -"from fasthtml.common import Div, Script\n", |
35 | | -"import json\n", |
| 33 | +"from fasthtml.common import Div,Script\n", |
36 | 34 | "from claudette import ToolResult\n", |
37 | 35 | "from dialoghelper.core import *\n", |
38 | 36 | "from httpx import post as xpost" |
|
46 | 44 | "outputs": [], |
47 | 45 | "source": [ |
48 | 46 | "#| export\n", |
49 | | -"def _pop_data(data_id, timeout=20, condition=None, fail_msg =\"`_pop_data` failed to return a value.\"):\n", |
50 | | -" result = xpost('http://localhost:5001/pop_data_blocking_', data={'data_id': data_id}, timeout=timeout)\n", |
51 | | -" if result.status_code == 200 and result.text.strip():\n", |
52 | | -" try:\n", |
53 | | -" if (data := result.json()) and (not condition or condition(data)): return data\n", |
54 | | -" except json.JSONDecodeError as e: print(f\"JSON decode error: {e}\")\n", |
55 | | -" raise RuntimeError(fail_msg)" |
| 47 | +"def _pop_data(data_id, timeout=20):\n", |
| 48 | +" params = {'data_id': data_id, 'timeout':timeout}\n", |
| 49 | +" result = xpost('http://localhost:5001/pop_data_blocking_', data=params, timeout=timeout+1)\n", |
| 50 | +" if result.status_code==200 and result.text.strip():\n", |
| 51 | +" if (data := result.json()): return data\n", |
| 52 | +"# except json.JSONDecodeError as e: print(f\"JSON decode error: {e}\")\n", |
| 53 | +" raise RuntimeError(\"No data received\")\n", |
| 54 | +" raise RuntimeError(result.status_code)" |
56 | 55 | ] |
57 | 56 | }, |
58 | 57 | { |
|
63 | 62 | "outputs": [], |
64 | 63 | "source": [ |
65 | 64 | "#| export\n", |
66 | | -"\n", |
67 | 65 | "def iife(code: str) -> str:\n", |
68 | 66 | "\"Wrap javascript code string in an IIFE and execute it via `add_html`\"\n", |
69 | 67 | " trigger_script = f'''\n", |
|
82 | 80 | "outputs": [], |
83 | 81 | "source": [ |
84 | 82 | "#| export\n", |
85 | | -"\n", |
86 | 83 | "_js_loaded = False\n", |
87 | 84 | "\n", |
88 | 85 | "def load_screenshot_js(force=False, timeout=5):\n", |
89 | 86 | "\"Load screenshot capability and wait for confirmation it's ready.\"\n", |
90 | 87 | " global _js_loaded\n", |
91 | 88 | " if _js_loaded and not force: return\n", |
92 | | -" print(\"Loading screenshot.js ...\")\n", |
| 89 | +"# print(\"Loading screenshot.js ...\")\n", |
93 | 90 | " status_id = str(uuid.uuid4())\n", |
94 | | -" js_content = (resources.files('dialoghelper') /'screenshot.js').read_text()\n", |
| 91 | +" js_content = (resources.files('dialoghelper')/'screenshot.js').read_text()\n", |
95 | 92 | " iife(js_content + f'sendDataToServer(\"{status_id}\", {{\"js_status\":\"ready\"}});')\n", |
96 | | -" data = _pop_data(status_id, timeout, condition=lambda d: d.get('js_status') == 'ready', fail_msg=\"Failed to load screenshot.js.\")\n", |
| 93 | +" data = _pop_data(status_id, timeout)\n", |
| 94 | +" if (stat:=data.get('js_status'))!='ready': raise RuntimeError(f\"Failed to load screenshot.js: {stat}\")\n", |
97 | 95 | " _js_loaded = True\n", |
98 | | -" print(\"Screenshot.js loaded and ready\")" |
| 96 | +"# print(\"Screenshot.js loaded and ready\")" |
| 97 | + ] |
| 98 | + }, |
| 99 | + { |
| 100 | +"cell_type":"code", |
| 101 | +"execution_count":null, |
| 102 | +"id":"a6ad43ee", |
| 103 | +"metadata": {}, |
| 104 | +"outputs": [ |
| 105 | + { |
| 106 | +"name":"stdout", |
| 107 | +"output_type":"stream", |
| 108 | +"text": [ |
| 109 | +"Loading screenshot.js ...\n", |
| 110 | +"Screenshot.js loaded and ready\n" |
| 111 | + ] |
| 112 | + } |
| 113 | + ], |
| 114 | +"source": [ |
| 115 | +"# load_screenshot_js()" |
99 | 116 | ] |
100 | 117 | }, |
101 | 118 | { |
|
106 | 123 | "outputs": [], |
107 | 124 | "source": [ |
108 | 125 | "#| export\n", |
109 | | -"\n", |
110 | 126 | "_screen_share_active = False\n", |
111 | 127 | "\n", |
112 | 128 | "def start_screen_share(timeout=45):\n", |
|
115 | 131 | " load_screenshot_js()\n", |
116 | 132 | " status_id = str(uuid.uuid4())\n", |
117 | 133 | " iife(f'startPersistentScreenShare(\"{status_id}\");')\n", |
118 | | -" print(\"Requesting screen share permission ...\")\n", |
119 | | -" data = _pop_data(status_id, timeout, condition=lambda d: d.get('js_status') == 'ready', fail_msg=\"Screen share failed.\")\n", |
| 134 | +"# print(\"Requesting screen share permission ...\")\n", |
| 135 | +" data = _pop_data(status_id, timeout)\n", |
120 | 136 | " js_status = data.get('js_status')\n", |
121 | | -" if js_status =='ready':\n", |
| 137 | +" if js_status=='ready':\n", |
122 | 138 | " _screen_share_active = True\n", |
123 | | -" print(\"Screen share started successfully.\")\n", |
124 | | -" elif js_status == 'error': raise RuntimeError(f\"Screen share failed: {data.get('error', 'Unknown error')}\")\n", |
125 | | -" elif js_status == 'connecting': raise RuntimeError(\"Screen share timed out after {timeout} seconds.\")" |
| 139 | +"# print(\"Screen share started successfully.\")\n", |
| 140 | +" elif js_status=='error': raise RuntimeError(f\"Screen share failed: {data.get('error', 'Unknown error')}\")\n", |
| 141 | +" elif js_status=='connecting': raise RuntimeError(\"Screen share timed out after {timeout} seconds.\")" |
| 142 | + ] |
| 143 | + }, |
| 144 | + { |
| 145 | +"cell_type":"code", |
| 146 | +"execution_count":null, |
| 147 | +"id":"0bed97c1", |
| 148 | +"metadata": {}, |
| 149 | +"outputs": [], |
| 150 | +"source": [ |
| 151 | +"# start_screen_share()" |
126 | 152 | ] |
127 | 153 | }, |
128 | 154 | { |
|
133 | 159 | "outputs": [], |
134 | 160 | "source": [ |
135 | 161 | "#| export\n", |
136 | | -"\n", |
137 | 162 | "def stop_screen_share():\n", |
138 | | -"\"Stop persistent screen sharing session.\"\n", |
139 | | -" global _screen_share_active\n", |
140 | | -" load_screenshot_js()\n", |
141 | | -" iife('stopPersistentScreenShare();')\n", |
142 | | -" _screen_share_active = False\n", |
143 | | -" print(\"Screen share stopped.\")" |
| 163 | +"\"Stop persistent screen sharing session.\"\n", |
| 164 | +"global _screen_share_active\n", |
| 165 | +"load_screenshot_js()\n", |
| 166 | +"iife('stopPersistentScreenShare();')\n", |
| 167 | +"_screen_share_active = False\n", |
| 168 | +"# print(\"Screen share stopped.\")" |
144 | 169 | ] |
145 | 170 | }, |
146 | 171 | { |
|
151 | 176 | "outputs": [], |
152 | 177 | "source": [ |
153 | 178 | "#| export\n", |
154 | | -"\n", |
155 | 179 | "def capture_screen():\n", |
156 | 180 | "\"Capture screenshot, automatically starting screen share if needed.\"\n", |
157 | 181 | " global _screen_share_active\n", |
158 | 182 | " load_screenshot_js()\n", |
159 | 183 | " if not _screen_share_active:\n", |
160 | | -" print(\"🔄 No active screen share, starting one...\")\n", |
| 184 | +"# print(\"🔄 No active screen share, starting one...\")\n", |
161 | 185 | " result = start_screen_share()\n", |
162 | 186 | " if not _screen_share_active: raise RuntimeError(f\"Failed to start screen share: {result}\")\n", |
163 | 187 | " data_id = str(uuid.uuid4())\n", |
164 | 188 | " screenshot_code = f'captureScreenFromStream(\"{data_id}\");'\n", |
165 | | -" print(\"📸 Capturing from persistent stream...\")\n", |
| 189 | +"# print(\"📸 Capturing from persistent stream...\")\n", |
166 | 190 | " iife(screenshot_code)\n", |
167 | | -" data = _pop_data(data_id, timeout=5, condition=lambda d: 'img_data' in d and 'img_type' in d, fail_msg=\"Screenshot capture failed, failed to retrieve data.\")\n", |
| 191 | +" data = _pop_data(data_id, timeout=45)\n", |
168 | 192 | " if 'error' in data: raise RuntimeError(f\"Screenshot failed: {data['error']}\")\n", |
| 193 | +" if not ('img_data' in data and 'img_type' in data):\n", |
| 194 | +" raise RuntimeError(\"Screenshot capture failed, failed to retrieve data.\")\n", |
169 | 195 | " return ToolResult(data=data['img_data'], result_type=data['img_type'])" |
170 | 196 | ] |
| 197 | + }, |
| 198 | + { |
| 199 | +"cell_type":"markdown", |
| 200 | +"id":"f17beb15", |
| 201 | +"metadata": {}, |
| 202 | +"source": [ |
| 203 | +"## export -" |
| 204 | + ] |
| 205 | + }, |
| 206 | + { |
| 207 | +"cell_type":"code", |
| 208 | +"execution_count":null, |
| 209 | +"id":"36548c80", |
| 210 | +"metadata": {}, |
| 211 | +"outputs": [], |
| 212 | +"source": [ |
| 213 | +"#|hide\n", |
| 214 | +"from nbdev import nbdev_export\n", |
| 215 | +"nbdev_export()" |
| 216 | + ] |
| 217 | + }, |
| 218 | + { |
| 219 | +"cell_type":"code", |
| 220 | +"execution_count":null, |
| 221 | +"id":"778f4ad6", |
| 222 | +"metadata": {}, |
| 223 | +"outputs": [], |
| 224 | +"source": [] |
171 | 225 | } |
172 | 226 | ], |
173 | 227 | "metadata": { |
|