dialoghelper 0.0.23__py3-none-any.whl → 0.0.37__py3-none-any.whl
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.
- dialoghelper/__init__.py +1 -1
- dialoghelper/_modidx.py +17 -5
- dialoghelper/core.py +219 -56
- dialoghelper/experimental.py +23 -50
- dialoghelper/screenshot.js +33 -0
- {dialoghelper-0.0.23.dist-info → dialoghelper-0.0.37.dist-info}/METADATA +7 -2
- dialoghelper-0.0.37.dist-info/RECORD +12 -0
- dialoghelper-0.0.23.dist-info/RECORD +0 -11
- {dialoghelper-0.0.23.dist-info → dialoghelper-0.0.37.dist-info}/WHEEL +0 -0
- {dialoghelper-0.0.23.dist-info → dialoghelper-0.0.37.dist-info}/entry_points.txt +0 -0
- {dialoghelper-0.0.23.dist-info → dialoghelper-0.0.37.dist-info}/licenses/LICENSE +0 -0
- {dialoghelper-0.0.23.dist-info → dialoghelper-0.0.37.dist-info}/top_level.txt +0 -0
dialoghelper/__init__.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
__version__ = "0.0.
|
|
1
|
+
__version__ = "0.0.37"
|
|
2
2
|
from .core import *
|
dialoghelper/_modidx.py
CHANGED
|
@@ -6,12 +6,18 @@ d = { 'settings': { 'branch': 'main',
|
|
|
6
6
|
'git_url': 'https://github.com/AnswerDotAI/dialoghelper',
|
|
7
7
|
'lib_path': 'dialoghelper'},
|
|
8
8
|
'syms': { 'dialoghelper.core': { 'dialoghelper.core._add_msg_unsafe': ('core.html#_add_msg_unsafe', 'dialoghelper/core.py'),
|
|
9
|
+
'dialoghelper.core._find_frame_dict': ('core.html#_find_frame_dict', 'dialoghelper/core.py'),
|
|
9
10
|
'dialoghelper.core._umsg': ('core.html#_umsg', 'dialoghelper/core.py'),
|
|
10
11
|
'dialoghelper.core.add_html': ('core.html#add_html', 'dialoghelper/core.py'),
|
|
11
12
|
'dialoghelper.core.add_msg': ('core.html#add_msg', 'dialoghelper/core.py'),
|
|
13
|
+
'dialoghelper.core.add_styles': ('core.html#add_styles', 'dialoghelper/core.py'),
|
|
14
|
+
'dialoghelper.core.ast_grep': ('core.html#ast_grep', 'dialoghelper/core.py'),
|
|
15
|
+
'dialoghelper.core.ast_py': ('core.html#ast_py', 'dialoghelper/core.py'),
|
|
12
16
|
'dialoghelper.core.call_endp': ('core.html#call_endp', 'dialoghelper/core.py'),
|
|
13
17
|
'dialoghelper.core.curr_dialog': ('core.html#curr_dialog', 'dialoghelper/core.py'),
|
|
14
18
|
'dialoghelper.core.del_msg': ('core.html#del_msg', 'dialoghelper/core.py'),
|
|
19
|
+
'dialoghelper.core.fc_tool_info': ('core.html#fc_tool_info', 'dialoghelper/core.py'),
|
|
20
|
+
'dialoghelper.core.find_dname': ('core.html#find_dname', 'dialoghelper/core.py'),
|
|
15
21
|
'dialoghelper.core.find_msg_id': ('core.html#find_msg_id', 'dialoghelper/core.py'),
|
|
16
22
|
'dialoghelper.core.find_msgs': ('core.html#find_msgs', 'dialoghelper/core.py'),
|
|
17
23
|
'dialoghelper.core.find_var': ('core.html#find_var', 'dialoghelper/core.py'),
|
|
@@ -22,13 +28,19 @@ d = { 'settings': { 'branch': 'main',
|
|
|
22
28
|
'dialoghelper.core.load_gist': ('core.html#load_gist', 'dialoghelper/core.py'),
|
|
23
29
|
'dialoghelper.core.mk_toollist': ('core.html#mk_toollist', 'dialoghelper/core.py'),
|
|
24
30
|
'dialoghelper.core.msg_idx': ('core.html#msg_idx', 'dialoghelper/core.py'),
|
|
31
|
+
'dialoghelper.core.msg_insert_line': ('core.html#msg_insert_line', 'dialoghelper/core.py'),
|
|
32
|
+
'dialoghelper.core.msg_replace_lines': ('core.html#msg_replace_lines', 'dialoghelper/core.py'),
|
|
33
|
+
'dialoghelper.core.msg_str_replace': ('core.html#msg_str_replace', 'dialoghelper/core.py'),
|
|
34
|
+
'dialoghelper.core.msg_strs_replace': ('core.html#msg_strs_replace', 'dialoghelper/core.py'),
|
|
25
35
|
'dialoghelper.core.read_msg': ('core.html#read_msg', 'dialoghelper/core.py'),
|
|
36
|
+
'dialoghelper.core.run_msg': ('core.html#run_msg', 'dialoghelper/core.py'),
|
|
37
|
+
'dialoghelper.core.set_var': ('core.html#set_var', 'dialoghelper/core.py'),
|
|
26
38
|
'dialoghelper.core.tool_info': ('core.html#tool_info', 'dialoghelper/core.py'),
|
|
27
|
-
'dialoghelper.core.update_msg': ('core.html#update_msg', 'dialoghelper/core.py')
|
|
39
|
+
'dialoghelper.core.update_msg': ('core.html#update_msg', 'dialoghelper/core.py'),
|
|
40
|
+
'dialoghelper.core.url2note': ('core.html#url2note', 'dialoghelper/core.py')},
|
|
28
41
|
'dialoghelper.db_dc': {},
|
|
29
|
-
'dialoghelper.experimental': { 'dialoghelper.experimental.
|
|
30
|
-
'dialoghelper/experimental.py'),
|
|
31
|
-
'dialoghelper.experimental.capture_screen': ( 'experimental.html#capture_screen',
|
|
42
|
+
'dialoghelper.experimental': { 'dialoghelper.experimental.capture_screen': ( 'experimental.html#capture_screen',
|
|
32
43
|
'dialoghelper/experimental.py'),
|
|
33
|
-
'dialoghelper.experimental.
|
|
44
|
+
'dialoghelper.experimental.iife': ('experimental.html#iife', 'dialoghelper/experimental.py'),
|
|
45
|
+
'dialoghelper.experimental.start_share': ( 'experimental.html#start_share',
|
|
34
46
|
'dialoghelper/experimental.py')}}}
|
dialoghelper/core.py
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/00_core.ipynb.
|
|
2
2
|
|
|
3
3
|
# %% auto 0
|
|
4
|
-
__all__ = ['
|
|
5
|
-
'
|
|
6
|
-
'
|
|
4
|
+
__all__ = ['md_cls_d', 'dh_settings', 'Placements', 'empty', 'add_styles', 'find_var', 'set_var', 'call_endp', 'find_dname',
|
|
5
|
+
'find_msg_id', 'curr_dialog', 'msg_idx', 'find_msgs', 'add_html', 'read_msg', 'add_msg', 'del_msg',
|
|
6
|
+
'update_msg', 'run_msg', 'url2note', 'ast_py', 'ast_grep', 'msg_insert_line', 'msg_str_replace',
|
|
7
|
+
'msg_strs_replace', 'msg_replace_lines', 'load_gist', 'gist_file', 'import_string', 'is_usable_tool',
|
|
8
|
+
'mk_toollist', 'import_gist', 'tool_info', 'fc_tool_info']
|
|
7
9
|
|
|
8
10
|
# %% ../nbs/00_core.ipynb
|
|
9
|
-
import json,
|
|
11
|
+
import json,importlib,linecache,re,inspect
|
|
10
12
|
from typing import Dict
|
|
11
13
|
from tempfile import TemporaryDirectory
|
|
12
14
|
from ipykernel_helper import *
|
|
@@ -20,87 +22,128 @@ from fastlite import *
|
|
|
20
22
|
from fastcore.xtras import asdict
|
|
21
23
|
from inspect import currentframe,Parameter,signature
|
|
22
24
|
from httpx import get as xget, post as xpost
|
|
23
|
-
from .core import __all__ as _all
|
|
24
25
|
from IPython.display import display,Markdown
|
|
26
|
+
from monsterui.all import franken_class_map,apply_classes
|
|
27
|
+
from fasthtml.common import Safe
|
|
25
28
|
|
|
26
29
|
# %% ../nbs/00_core.ipynb
|
|
27
|
-
|
|
30
|
+
md_cls_d = {
|
|
31
|
+
**{f'h{i}': f'uk-h{i}' for i in range(1,5)},
|
|
32
|
+
'a': "uk-link",
|
|
33
|
+
'blockquote': "uk-blockquote",
|
|
34
|
+
'hr':'uk-divider-icon',
|
|
35
|
+
'table':'uk-table uk-table-sm uk-table-middle uk-table-divider border [&_tr]:divide-x w-[80%] mx-auto',
|
|
36
|
+
'ol': 'uk-list uk-list-decimal space-y-0',
|
|
37
|
+
'ul': 'uk-list uk-list-bullet space-y-0',
|
|
38
|
+
'p': 'leading-tight',
|
|
39
|
+
'li': 'leading-tight',
|
|
40
|
+
'pre': '', 'pre code': '',
|
|
41
|
+
'code': 'tracking-tight'
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
def add_styles(s:str, cls_map:dict=None):
|
|
45
|
+
"Add solveit styles to `s`"
|
|
46
|
+
return Safe(apply_classes(s, class_map=cls_map or md_cls_d))
|
|
28
47
|
|
|
29
48
|
# %% ../nbs/00_core.ipynb
|
|
30
|
-
def
|
|
31
|
-
"
|
|
32
|
-
frame = currentframe()
|
|
49
|
+
def _find_frame_dict(var:str):
|
|
50
|
+
"Find the dict (globals or locals) containing var"
|
|
51
|
+
frame = currentframe().f_back.f_back
|
|
33
52
|
while frame:
|
|
34
|
-
|
|
35
|
-
if dv: return dv
|
|
53
|
+
if var in frame.f_globals: return frame.f_globals
|
|
36
54
|
frame = frame.f_back
|
|
37
55
|
raise ValueError(f"Could not find {var} in any scope")
|
|
38
56
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
57
|
+
def find_var(var:str):
|
|
58
|
+
"Search for var in all frames of the call stack"
|
|
59
|
+
return _find_frame_dict(var)[var]
|
|
60
|
+
|
|
61
|
+
def set_var(var:str, val):
|
|
62
|
+
"Set var to val after finding it in all frames of the call stack"
|
|
63
|
+
_find_frame_dict(var)[var] = val
|
|
44
64
|
|
|
45
65
|
# %% ../nbs/00_core.ipynb
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
):
|
|
49
|
-
|
|
50
|
-
|
|
66
|
+
dh_settings = {'port':5001}
|
|
67
|
+
|
|
68
|
+
def call_endp(path, dname='', json=False, raiseex=False, **data):
|
|
69
|
+
if not dname: dname = find_dname()
|
|
70
|
+
data['dlg_name'] = dname
|
|
71
|
+
res = xpost(f'http://localhost:{dh_settings["port"]}/{path}', data=data)
|
|
72
|
+
if raiseex: res.raise_for_status()
|
|
73
|
+
try: return res.json() if json else res.text
|
|
74
|
+
except Exception as e: return str(e)
|
|
51
75
|
|
|
52
76
|
# %% ../nbs/00_core.ipynb
|
|
53
|
-
def
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
limit:int=None, # Optionally limit number of returned items
|
|
57
|
-
include_output:bool=True # Include output in returned dict?
|
|
58
|
-
):
|
|
59
|
-
"Find `list[dict]` of messages in current specific dialog that contain the given information. To refer to a message found later, use its `id` field."
|
|
60
|
-
res = call_endp('find_msgs_', json=True, re_pattern=re_pattern, msg_type=msg_type, limit=limit)['msgs']
|
|
61
|
-
if not include_output:
|
|
62
|
-
for o in res: o.pop('output', None)
|
|
63
|
-
return res
|
|
77
|
+
def find_dname():
|
|
78
|
+
"Get the message id by searching the call stack for __dialog_id."
|
|
79
|
+
return find_var('__dialog_name')
|
|
64
80
|
|
|
65
81
|
# %% ../nbs/00_core.ipynb
|
|
66
82
|
def find_msg_id():
|
|
67
83
|
"Get the message id by searching the call stack for __dialog_id."
|
|
68
84
|
return find_var('__msg_id')
|
|
69
85
|
|
|
86
|
+
# %% ../nbs/00_core.ipynb
|
|
87
|
+
def curr_dialog(
|
|
88
|
+
with_messages:bool=False, # Include messages as well?
|
|
89
|
+
dname:str='' # Running dialog to get info for; defaults to current dialog
|
|
90
|
+
):
|
|
91
|
+
"Get the current dialog info."
|
|
92
|
+
res = call_endp('curr_dialog_', dname, json=True, with_messages=with_messages)
|
|
93
|
+
if res: return {'name': res['name'], 'mode': res['mode']}
|
|
94
|
+
|
|
70
95
|
# %% ../nbs/00_core.ipynb
|
|
71
96
|
def msg_idx(
|
|
72
97
|
msgid=None, # Message id to find (defaults to current message)
|
|
98
|
+
dname:str='' # Running dialog to get info for; defaults to current dialog
|
|
73
99
|
):
|
|
74
100
|
"Get absolute index of message in dialog."
|
|
75
101
|
if not msgid: msgid = find_msg_id()
|
|
76
|
-
return call_endp('msg_idx_', json=True, msgid=msgid)['msgid']
|
|
102
|
+
return call_endp('msg_idx_', dname, json=True, msgid=msgid)['msgid']
|
|
77
103
|
|
|
78
104
|
# %% ../nbs/00_core.ipynb
|
|
79
|
-
def
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
105
|
+
def find_msgs(
|
|
106
|
+
re_pattern:str='', # Optional regex to search for (re.DOTALL+re.MULTILINE is used)
|
|
107
|
+
msg_type:str=None, # optional limit by message type ('code', 'note', or 'prompt')
|
|
108
|
+
limit:int=None, # Optionally limit number of returned items
|
|
109
|
+
include_output:bool=True, # Include output in returned dict?
|
|
110
|
+
dname:str='' # Running dialog to get info for; defaults to current dialog
|
|
111
|
+
):
|
|
112
|
+
"Find `list[dict]` of messages in current specific dialog that contain the given information. To refer to a message found later, use its `id` field."
|
|
113
|
+
res = call_endp('find_msgs_', dname, json=True, re_pattern=re_pattern, msg_type=msg_type, limit=limit)['msgs']
|
|
114
|
+
if not include_output:
|
|
115
|
+
for o in res: o.pop('output', None)
|
|
116
|
+
return res
|
|
87
117
|
|
|
88
118
|
# %% ../nbs/00_core.ipynb
|
|
89
119
|
def add_html(
|
|
90
120
|
content:str, # The HTML to send to the client (generally should include hx-swap-oob)
|
|
121
|
+
dname:str='' # Running dialog to get info for; defaults to current dialog
|
|
91
122
|
):
|
|
92
123
|
"Send HTML to the browser to be swapped into the DOM"
|
|
93
|
-
call_endp('add_html_', content=to_xml(content))
|
|
124
|
+
call_endp('add_html_', dname, content=to_xml(content))
|
|
94
125
|
|
|
95
126
|
# %% ../nbs/00_core.ipynb
|
|
96
|
-
|
|
97
|
-
msgid:str=None, # id of message that placement is relative to (if None, uses current message)
|
|
98
|
-
):
|
|
99
|
-
"Delete a message from the dialog. Be sure to pass a `sid`, not a `mid`."
|
|
100
|
-
call_endp('rm_msg_', raiseex=True, msid=msgid)
|
|
127
|
+
Placements = str_enum('Placements', 'add_after', 'add_before', 'at_start', 'at_end')
|
|
101
128
|
|
|
102
129
|
# %% ../nbs/00_core.ipynb
|
|
103
|
-
|
|
130
|
+
def read_msg(
|
|
131
|
+
n:int=-1, # Message index (if relative, +ve is downwards)
|
|
132
|
+
relative:bool=True, # Is `n` relative to current message (True) or absolute (False)?
|
|
133
|
+
msgid:str=None, # Message id to find (defaults to current message)
|
|
134
|
+
view_range:list[int,int]=None, # Optional 1-indexed (start, end) line range for files, end=-1 for EOF
|
|
135
|
+
nums:bool=False, # Whether to show line numbers
|
|
136
|
+
dname:str='' # Running dialog to get info for; defaults to current dialog
|
|
137
|
+
):
|
|
138
|
+
"""Get the message indexed in the current dialog.
|
|
139
|
+
- To get the exact message use `n=0` and `relative=True` together with `msgid`.
|
|
140
|
+
- To get a relative message use `n` (relative position index).
|
|
141
|
+
- To get the nth message use `n` with `relative=False`, e.g `n=0` first message, `n=-1` last message."""
|
|
142
|
+
if not msgid: msgid = find_msg_id()
|
|
143
|
+
data = dict(n=n, relative=relative, msgid=msgid)
|
|
144
|
+
if view_range: data['view_range'] = view_range # None gets converted to '' so we avoid passing it to use the p.default
|
|
145
|
+
if nums: data['nums'] = nums
|
|
146
|
+
return call_endp('read_msg_', dname, json=True, **data)
|
|
104
147
|
|
|
105
148
|
# %% ../nbs/00_core.ipynb
|
|
106
149
|
def add_msg(
|
|
@@ -116,13 +159,24 @@ def add_msg(
|
|
|
116
159
|
o_collapsed: int | None = 0, # Collapse output?
|
|
117
160
|
heading_collapsed: int | None = 0, # Collapse heading section?
|
|
118
161
|
pinned: int | None = 0, # Pin to context?
|
|
162
|
+
dname:str='' # Running dialog to get info for; defaults to current dialog
|
|
119
163
|
):
|
|
120
164
|
"Add/update a message to the queue to show after code execution completes."
|
|
121
165
|
if placement not in ('at_start','at_end') and not msgid: msgid = find_msg_id()
|
|
122
|
-
|
|
123
|
-
'add_relative_', content=content, placement=placement, msgid=msgid, msg_type=msg_type, output=output,
|
|
166
|
+
res = call_endp(
|
|
167
|
+
'add_relative_', dname, content=content, placement=placement, msgid=msgid, msg_type=msg_type, output=output,
|
|
124
168
|
time_run=time_run, is_exported=is_exported, skipped=skipped, pinned=pinned,
|
|
125
169
|
i_collapsed=i_collapsed, o_collapsed=o_collapsed, heading_collapsed=heading_collapsed)
|
|
170
|
+
set_var('__msg_id', res)
|
|
171
|
+
return res
|
|
172
|
+
|
|
173
|
+
# %% ../nbs/00_core.ipynb
|
|
174
|
+
def del_msg(
|
|
175
|
+
msgid:str=None, # id of message to delete
|
|
176
|
+
dname:str='' # Running dialog to get info for; defaults to current dialog
|
|
177
|
+
):
|
|
178
|
+
"Delete a message from the dialog."
|
|
179
|
+
call_endp('rm_msg_', dname, raiseex=True, msid=msgid)
|
|
126
180
|
|
|
127
181
|
# %% ../nbs/00_core.ipynb
|
|
128
182
|
@delegates(add_msg)
|
|
@@ -131,13 +185,16 @@ def _add_msg_unsafe(
|
|
|
131
185
|
placement:str='add_after', # Can be 'add_after', 'add_before', 'at_start', 'at_end'
|
|
132
186
|
msgid:str=None, # id of message that placement is relative to (if None, uses current message)
|
|
133
187
|
run:bool=False, # For prompts, send it to the AI; for code, execute it (*DANGEROUS -- be careful of what you run!)
|
|
188
|
+
dname:str='', # Running dialog to get info for; defaults to current dialog
|
|
134
189
|
**kwargs
|
|
135
190
|
):
|
|
136
191
|
"""Add/update a message to the queue to show after code execution completes, and optionally run it. Be sure to pass a `sid` (stable id) not a `mid` (which is used only for sorting, and can change).
|
|
137
192
|
*WARNING*--This can execute arbitrary code, so check carefully what you run!--*WARNING"""
|
|
138
193
|
if placement not in ('at_start','at_end') and not msgid: msgid = find_msg_id()
|
|
139
|
-
|
|
140
|
-
'add_relative_', content=content, placement=placement, msgid=msgid, run=run, **kwargs)
|
|
194
|
+
res = call_endp(
|
|
195
|
+
'add_relative_', dname, content=content, placement=placement, msgid=msgid, run=run, **kwargs)
|
|
196
|
+
set_var('__msg_id', res)
|
|
197
|
+
return res
|
|
141
198
|
|
|
142
199
|
# %% ../nbs/00_core.ipynb
|
|
143
200
|
def _umsg(
|
|
@@ -158,12 +215,93 @@ def _umsg(
|
|
|
158
215
|
def update_msg(
|
|
159
216
|
msgid:str=None, # id of message to update (if None, uses current message)
|
|
160
217
|
msg:Optional[Dict]=None, # Dictionary of field keys/values to update
|
|
218
|
+
dname:str='', # Running dialog to get info for; defaults to current dialog
|
|
161
219
|
**kwargs):
|
|
162
220
|
"""Update an existing message. Provide either `msg` OR field key/values to update.
|
|
163
|
-
Use `content` param to update contents.
|
|
164
|
-
Only include parameters to update--missing ones will be left unchanged."""
|
|
221
|
+
- Use `content` param to update contents.
|
|
222
|
+
- Only include parameters to update--missing ones will be left unchanged."""
|
|
165
223
|
if not msgid and not msg: raise TypeError("update_msg needs either a dict message or `msgid=`")
|
|
166
|
-
|
|
224
|
+
res = call_endp('add_relative_', dname, placement='update', msgid=msgid, **kwargs)
|
|
225
|
+
set_var('__msg_id', res)
|
|
226
|
+
return res
|
|
227
|
+
|
|
228
|
+
# %% ../nbs/00_core.ipynb
|
|
229
|
+
def run_msg(
|
|
230
|
+
msgid:str=None, # id of message to execute
|
|
231
|
+
dname:str='' # Running dialog to get info for; defaults to current dialog
|
|
232
|
+
):
|
|
233
|
+
"Adds a message to the run queue. Use read_msg to see the output once it runs."
|
|
234
|
+
return call_endp('add_runq_', dname, msgid=msgid, api=True)
|
|
235
|
+
|
|
236
|
+
# %% ../nbs/00_core.ipynb
|
|
237
|
+
def url2note(
|
|
238
|
+
url:str, # URL to read
|
|
239
|
+
extract_section:bool=True, # If url has an anchor, return only that section
|
|
240
|
+
selector:str=None # Select section(s) using BeautifulSoup.select (overrides extract_section)
|
|
241
|
+
):
|
|
242
|
+
"Read URL as markdown, and add a note below current message with the result"
|
|
243
|
+
res = read_url(url, as_md=True, extract_section=extract_section, selector=selector)
|
|
244
|
+
return add_msg(res)
|
|
245
|
+
|
|
246
|
+
# %% ../nbs/00_core.ipynb
|
|
247
|
+
def ast_py(code:str):
|
|
248
|
+
"Get an SgRoot root node for python `code`"
|
|
249
|
+
from ast_grep_py import SgRoot
|
|
250
|
+
return SgRoot(code, "python").root()
|
|
251
|
+
|
|
252
|
+
# %% ../nbs/00_core.ipynb
|
|
253
|
+
def ast_grep(
|
|
254
|
+
pattern:str, # ast-grep pattern to search
|
|
255
|
+
path=".", # path to recursively search for files
|
|
256
|
+
lang="python" # language to search/scan
|
|
257
|
+
):
|
|
258
|
+
"Use the `ast-grep` command to find `pattern` in `path`"
|
|
259
|
+
import json, subprocess
|
|
260
|
+
cmd = f"ast-grep --pattern '{pattern}' --lang {lang} --json=compact"
|
|
261
|
+
if path != ".": cmd = f"cd {path} && {cmd}"
|
|
262
|
+
res = subprocess.run(cmd, shell=True, capture_output=True, text=True)
|
|
263
|
+
return json.loads(res.stdout) if res.stdout else res.stderr
|
|
264
|
+
|
|
265
|
+
# %% ../nbs/00_core.ipynb
|
|
266
|
+
def msg_insert_line(
|
|
267
|
+
msgid:str, # Message id to edit
|
|
268
|
+
insert_line: int, # The line number after which to insert the text (0 for beginning of file)
|
|
269
|
+
new_str: str, # The text to insert
|
|
270
|
+
dname:str='' # Running dialog to get info for; defaults to current dialog
|
|
271
|
+
):
|
|
272
|
+
"Insert text at a specific line number in a message"
|
|
273
|
+
return call_endp('msg_insert_line_', dname, json=True, msgid=msgid, insert_line=insert_line, new_str=new_str)
|
|
274
|
+
|
|
275
|
+
# %% ../nbs/00_core.ipynb
|
|
276
|
+
def msg_str_replace(
|
|
277
|
+
msgid:str, # Message id to edit
|
|
278
|
+
old_str: str, # Text to find and replace
|
|
279
|
+
new_str: str, # Text to replace with
|
|
280
|
+
dname:str='' # Running dialog to get info for; defaults to current dialog
|
|
281
|
+
):
|
|
282
|
+
"Replace first occurrence of old_str with new_str in a message"
|
|
283
|
+
return call_endp('msg_str_replace_', dname, json=True, msgid=msgid, old_str=old_str, new_str=new_str)
|
|
284
|
+
|
|
285
|
+
# %% ../nbs/00_core.ipynb
|
|
286
|
+
def msg_strs_replace(
|
|
287
|
+
msgid:str, # Message id to edit
|
|
288
|
+
old_strs:list[str], # List of strings to find and replace
|
|
289
|
+
new_strs:list[str], # List of replacement strings (must match length of old_strs)
|
|
290
|
+
dname:str='' # Running dialog to get info for; defaults to current dialog
|
|
291
|
+
):
|
|
292
|
+
"Replace multiple strings simultaneously in a message"
|
|
293
|
+
return call_endp('msg_strs_replace_', dname, json=True, msgid=msgid, old_strs=old_strs, new_strs=new_strs)
|
|
294
|
+
|
|
295
|
+
# %% ../nbs/00_core.ipynb
|
|
296
|
+
def msg_replace_lines(
|
|
297
|
+
msgid:str, # Message id to edit
|
|
298
|
+
start_line:int, # Starting line number to replace (1-based indexing)
|
|
299
|
+
end_line:int, # Ending line number to replace (1-based indexing, inclusive)
|
|
300
|
+
new_content:str, # New content to replace the specified lines
|
|
301
|
+
dname:str='' # Running dialog to get info for; defaults to current dialog
|
|
302
|
+
):
|
|
303
|
+
"Replace a range of lines with new content in a message"
|
|
304
|
+
return call_endp('msg_replace_lines_', dname, json=True, msgid=msgid, start_line=start_line, end_line=end_line, new_content=new_content)
|
|
167
305
|
|
|
168
306
|
# %% ../nbs/00_core.ipynb
|
|
169
307
|
def load_gist(gist_id:str):
|
|
@@ -240,8 +378,33 @@ def tool_info():
|
|
|
240
378
|
- &`add_html`: Send HTML to the browser to be swapped into the DOM using hx-swap-oob.
|
|
241
379
|
- &`find_msg_id`: Get the current message id.
|
|
242
380
|
- &`find_msgs`: Find messages in current specific dialog that contain the given information.
|
|
381
|
+
- (solveit can often get this id directly from its context, and will not need to use this if the required information is already available to it.)
|
|
243
382
|
- &`read_msg`: Get the message indexed in the current dialog.
|
|
383
|
+
- To get the exact message use `n=0` and `relative=True` together with `msgid`.
|
|
384
|
+
- To get a relative message use `n` (relative position index).
|
|
385
|
+
- To get the nth message use `n` with `relative=False`, e.g `n=0` first message, `n=-1` last message.
|
|
244
386
|
- &`del_msg`: Delete a message from the dialog.
|
|
245
387
|
- &`add_msg`: Add/update a message to the queue to show after code execution completes.
|
|
246
|
-
- &`update_msg`: Update an existing message.
|
|
388
|
+
- &`update_msg`: Update an existing message.
|
|
389
|
+
- &`url2note`: Read URL as markdown, and add a note below current message with the result
|
|
390
|
+
- &`msg_insert_line`: Insert text at a specific location in a message.
|
|
391
|
+
- &`msg_str_replace`: Find and replace text in a message.
|
|
392
|
+
- &`msg_strs_replace`: Find and replace multiple strings in a message.
|
|
393
|
+
- &`msg_replace_lines`: Replace a range of lines in a message with new content.
|
|
394
|
+
- Always first use `read_msg( msgid=msgid, n=0, relative=True, nums=True)` to view the content with line numbers.'''
|
|
395
|
+
add_msg(cts)
|
|
396
|
+
|
|
397
|
+
# %% ../nbs/00_core.ipynb
|
|
398
|
+
def fc_tool_info():
|
|
399
|
+
cts='''Tools available from `fastcore.tools`:
|
|
400
|
+
|
|
401
|
+
- &`rg`: Run the `rg` command with the args in `argstr` (no need to backslash escape)
|
|
402
|
+
- &`sed`: Run the `sed` command with the args in `argstr` (e.g for reading a section of a file)
|
|
403
|
+
- &`view`: View directory or file contents with optional line range and numbers
|
|
404
|
+
- &`create`: Creates a new file with the given content at the specified path
|
|
405
|
+
- &`insert`: Insert new_str at specified line number
|
|
406
|
+
- &`str_replace`: Replace first occurrence of old_str with new_str in file
|
|
407
|
+
- &`strs_replace`: Replace for each str pair in old_strs,new_strs
|
|
408
|
+
- &`replace_lines`: Replace lines in file using start and end line-numbers'''
|
|
247
409
|
add_msg(cts)
|
|
410
|
+
add_msg('from fastcore.tools import *', msg_type='code')
|
dialoghelper/experimental.py
CHANGED
|
@@ -3,66 +3,39 @@
|
|
|
3
3
|
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/01_experimental.ipynb.
|
|
4
4
|
|
|
5
5
|
# %% auto 0
|
|
6
|
-
__all__ = ['
|
|
6
|
+
__all__ = ['iife', 'start_share', 'capture_screen']
|
|
7
7
|
|
|
8
8
|
# %% ../nbs/01_experimental.ipynb
|
|
9
|
-
from importlib import resources
|
|
10
|
-
import uuid
|
|
11
|
-
from fasthtml.common import Div, Script
|
|
12
|
-
from time import sleep
|
|
13
|
-
import base64
|
|
14
|
-
import json
|
|
15
|
-
import time
|
|
16
|
-
from claudette import ToolResult
|
|
17
9
|
from .core import *
|
|
18
|
-
from
|
|
19
|
-
from
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
10
|
+
from fastcore.all import *
|
|
11
|
+
from fasthtml.common import Div,Script
|
|
12
|
+
from httpx import post as xpost
|
|
13
|
+
from importlib import resources
|
|
14
|
+
from lisette.core import *
|
|
23
15
|
|
|
24
|
-
|
|
25
|
-
"Load screenshot capability if not already present."
|
|
26
|
-
global _js_loaded
|
|
27
|
-
if _js_loaded:
|
|
28
|
-
print("screenshot.js already loaded")
|
|
29
|
-
return
|
|
30
|
-
js_content = (resources.files('dialoghelper') / 'screenshot.js').read_text()
|
|
31
|
-
add_html(Div(Script(js_content), hx_swap_oob='beforeend:#js-script'))
|
|
32
|
-
print("Added screenshot.js")
|
|
33
|
-
_js_loaded = True
|
|
16
|
+
import base64,json,uuid,time
|
|
34
17
|
|
|
35
18
|
# %% ../nbs/01_experimental.ipynb
|
|
36
|
-
def
|
|
37
|
-
"Wrap javascript code string in an IIFE"
|
|
38
|
-
|
|
19
|
+
def iife(code: str) -> str:
|
|
20
|
+
"Wrap javascript code string in an IIFE and execute it via `add_html`"
|
|
21
|
+
trigger_script = f'''
|
|
39
22
|
(async () => {{
|
|
40
23
|
{code}
|
|
41
24
|
}})();
|
|
42
25
|
'''
|
|
26
|
+
add_html(Div(Script(trigger_script), hx_swap_oob=f'beforeend:#js-script'))
|
|
27
|
+
|
|
28
|
+
# %% ../nbs/01_experimental.ipynb
|
|
29
|
+
def start_share():
|
|
30
|
+
iife((resources.files('dialoghelper')/'screenshot.js').read_text())
|
|
31
|
+
iife('await setupVideoStream();')
|
|
43
32
|
|
|
44
33
|
# %% ../nbs/01_experimental.ipynb
|
|
45
34
|
def capture_screen():
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
for attempt in range(max_attempts):
|
|
54
|
-
result = xpost('http://localhost:5001/pop_data_', data={'data_id': data_id})
|
|
55
|
-
if result.status_code == 200:
|
|
56
|
-
try:
|
|
57
|
-
if not result.text.strip():
|
|
58
|
-
time.sleep(0.5)
|
|
59
|
-
continue
|
|
60
|
-
data = result.json() # data is a dict
|
|
61
|
-
if 'error' in data: return f"Screenshot failed: {data['error']}"
|
|
62
|
-
if 'img_data' in data and 'img_type' in data:
|
|
63
|
-
return ToolResult(data=data['img_data'], result_type=data['img_type'])
|
|
64
|
-
return f"Screenshot data incomplete: {data}"
|
|
65
|
-
except json.JSONDecodeError as e: print(f"JSON decode error: {e}, Raw text: '{result.text}'")
|
|
66
|
-
except Exception as e: print(f"Error processing screenshot data: {e}")
|
|
67
|
-
time.sleep(0.5)
|
|
68
|
-
return "Screenshot capture timed out"
|
|
35
|
+
'Capture screenshot, automatically starting screen share if needed.'
|
|
36
|
+
idx = uuid.uuid4()
|
|
37
|
+
iife(f"pushData('{idx}', {{img_data: await getScreenshot()}});")
|
|
38
|
+
time.sleep(0.5)
|
|
39
|
+
d = dict2obj(xpost('http://localhost:5001/pop_data_blocking_', data={'data_id': idx}).json())
|
|
40
|
+
if 'img_data' in d: return ToolResponse([{'type': 'image_url', 'image_url': d.img_data}])
|
|
41
|
+
else: return f'Capture failed: {d.error}'
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
async function setupVideoStream() {
|
|
2
|
+
vstream = await navigator.mediaDevices.getDisplayMedia();
|
|
3
|
+
window.vtrack = vstream.getVideoTracks()[0];
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
async function getScreenshot(maxWidth = 1280, maxHeight = 1024) {
|
|
7
|
+
if (window?.vtrack) {
|
|
8
|
+
const cap = new ImageCapture(window.vtrack);
|
|
9
|
+
const img = await cap.grabFrame();
|
|
10
|
+
// rescale and convert to b64
|
|
11
|
+
const scaleX = maxWidth / img.width;
|
|
12
|
+
const scaleY = maxHeight / img.height;
|
|
13
|
+
const scale = Math.min(scaleX, scaleY, 1); // don't upscale
|
|
14
|
+
const newWidth = Math.floor(img.width * scale);
|
|
15
|
+
const newHeight = Math.floor(img.height * scale);
|
|
16
|
+
const c = document.createElement('canvas');
|
|
17
|
+
c.width = newWidth; c.height = newHeight;
|
|
18
|
+
c.getContext('2d').drawImage(img, 0, 0, newWidth, newHeight);
|
|
19
|
+
return c.toDataURL();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function pushData(dataId, data) {
|
|
24
|
+
return fetch('/push_data_blocking_', {
|
|
25
|
+
method: 'POST',
|
|
26
|
+
headers: {'Content-Type': 'application/json'},
|
|
27
|
+
body: JSON.stringify({data_id: dataId, ...data})
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
window.setupVideoStream = setupVideoStream;
|
|
32
|
+
window.getScreenshot = getScreenshot;
|
|
33
|
+
window.pushData = pushData;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dialoghelper
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.37
|
|
4
4
|
Summary: Helper functions for solveit dialogs
|
|
5
5
|
Home-page: https://github.com/AnswerDotAI/dialoghelper
|
|
6
6
|
Author: Jeremy Howard
|
|
@@ -18,12 +18,17 @@ Classifier: License :: OSI Approved :: Apache Software License
|
|
|
18
18
|
Requires-Python: >=3.9
|
|
19
19
|
Description-Content-Type: text/markdown
|
|
20
20
|
License-File: LICENSE
|
|
21
|
-
Requires-Dist: fastcore>=1.8.
|
|
21
|
+
Requires-Dist: fastcore>=1.8.10
|
|
22
22
|
Requires-Dist: fastlite
|
|
23
23
|
Requires-Dist: ghapi
|
|
24
24
|
Requires-Dist: ipykernel-helper
|
|
25
25
|
Requires-Dist: claudette
|
|
26
|
+
Requires-Dist: ast-grep-cli
|
|
27
|
+
Requires-Dist: ast-grep-py
|
|
28
|
+
Requires-Dist: MonsterUI
|
|
29
|
+
Requires-Dist: lisette>=0.0.13
|
|
26
30
|
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: python-fasthtml; extra == "dev"
|
|
27
32
|
Dynamic: author
|
|
28
33
|
Dynamic: author-email
|
|
29
34
|
Dynamic: classifier
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
dialoghelper/__init__.py,sha256=38YNAJyeXf7hteiqxTtdpbcKxmqYNHn5TJE6Yfg5Ks4,43
|
|
2
|
+
dialoghelper/_modidx.py,sha256=a_9jKSOoEZsMp0piUBSKFNxtbGt9XMWnRoPhUaK4jls,4832
|
|
3
|
+
dialoghelper/core.py,sha256=Kc5T6tpaGimEYt3dqi9lY2XiAVCMVRrqdGrAvGsNsxc,18867
|
|
4
|
+
dialoghelper/db_dc.py,sha256=mi2Q2am_SoAPGpNQg7KPFS5pR9WEapRXT8ypkNmMfw0,2330
|
|
5
|
+
dialoghelper/experimental.py,sha256=k-vCuRzzWYrKCg-zi_EJmUPp40s_O3ji3eF1Bn27YGE,1351
|
|
6
|
+
dialoghelper/screenshot.js,sha256=nzmnO3bon1d_6pvgGOUY-EQb_IlqCA8_X5vx7JT_M5M,1194
|
|
7
|
+
dialoghelper-0.0.37.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
8
|
+
dialoghelper-0.0.37.dist-info/METADATA,sha256=QaYuRY5KHLblAlH47AFW7j6BIRbBl69PxdqH3Hixf_A,2749
|
|
9
|
+
dialoghelper-0.0.37.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
10
|
+
dialoghelper-0.0.37.dist-info/entry_points.txt,sha256=wvDeX-XTS_XVjWiiPQe6yVfmyNwy9eCr36ewp9baFIg,46
|
|
11
|
+
dialoghelper-0.0.37.dist-info/top_level.txt,sha256=VXLlkgltFs_q-XB9imt2G64I_-MPm1RnxlpvUWPuLKM,13
|
|
12
|
+
dialoghelper-0.0.37.dist-info/RECORD,,
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
dialoghelper/__init__.py,sha256=AqD8emlypM0LZM9Km2Wj1qvaXCNpm0U46JDDXPEy5d8,43
|
|
2
|
-
dialoghelper/_modidx.py,sha256=dqZjsj-FkFgiTcIeiCB7rSCpUzStGILPMqC0NRt4jO4,3402
|
|
3
|
-
dialoghelper/core.py,sha256=3zWfyFZPDkzHVIh2sjI4PESpezXhOKMnWNqOJ1zXXBA,10859
|
|
4
|
-
dialoghelper/db_dc.py,sha256=mi2Q2am_SoAPGpNQg7KPFS5pR9WEapRXT8ypkNmMfw0,2330
|
|
5
|
-
dialoghelper/experimental.py,sha256=6tDnbY3JBA8MLdzMZ18uCHnT5BapgzH61sGxfUt8HQ8,2459
|
|
6
|
-
dialoghelper-0.0.23.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
7
|
-
dialoghelper-0.0.23.dist-info/METADATA,sha256=wQW5EBgPIq4cQbqNn7EqZ2Qm8nv4VxgAwUUEXvwRnbk,2590
|
|
8
|
-
dialoghelper-0.0.23.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
9
|
-
dialoghelper-0.0.23.dist-info/entry_points.txt,sha256=wvDeX-XTS_XVjWiiPQe6yVfmyNwy9eCr36ewp9baFIg,46
|
|
10
|
-
dialoghelper-0.0.23.dist-info/top_level.txt,sha256=VXLlkgltFs_q-XB9imt2G64I_-MPm1RnxlpvUWPuLKM,13
|
|
11
|
-
dialoghelper-0.0.23.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|