from dialoghelper import *dialoghelper
from fastcore import toolsHelpers
add_styles
add_styles (s:str, cls_map:dict=None)
Add solveit styles to s
import mistletoe
from fasthtml.common import shows = mistletoe.markdown("### hi\n\n- first\n- *second*")
s'<h3>hi</h3>\n<ul>\n<li>first</li>\n<li><em>second</em></li>\n</ul>\n'
show(s)hi
- first
- second
show(add_styles(s))hi
- first
- second
Basics
set_var
set_var (var:str, val)
Set var to val after finding it in all frames of the call stack
find_var
find_var (var:str)
Search for var in all frames of the call stack
a = 1
find_var('a')1
set_var('a', 42)
a42
# dh_settings = {'port':6001}find_msg_id
find_msg_id ()
*Get the message id by searching the call stack for __msg_id.*
find_dname
find_dname (dname=None)
*Get the message id by searching the call stack for __dialog_id.*
find_dname()'aai-ws/dialoghelper/nbs/00_core'
find_dname('index')'aai-ws/dialoghelper/nbs/index'
find_dname('../index')'aai-ws/dialoghelper/index'
find_dname('/foo/bar')'foo/bar'
call_endp
call_endp (path, dname='', json=False, raiseex=False, id=None, **data)
find_msg_id()'_9cbd170d'
curr_dialog
curr_dialog (with_messages:bool=False, dname:str='')
Get the current dialog info.
| Type | Default | Details | |
|---|---|---|---|
| with_messages | bool | False | Include messages as well? |
| dname | str | Dialog to get info for; defaults to current dialog |
msg_idx
msg_idx (id=None, dname:str='')
Get absolute index of message in dialog.
| Type | Default | Details | |
|---|---|---|---|
| id | NoneType | None | Message id to find (defaults to current message) |
| dname | str | Dialog to get message index from; defaults to current dialog |
msg_idx()26
add_scr
add_scr (scr, oob='beforeend:#js-script')
Swap a script element to the end of the js-script element
iife
iife (code:str)
Wrap javascript code string in an IIFE and execute it via add_html
pop_data
pop_data (idx, timeout=15)
fire_event
fire_event (evt:str, data=None)
event_get
event_get (evt:str, timeout=15, data=None)
Call fire_event and then pop_data to get a response
View/edit dialog
find_msgs
find_msgs (re_pattern:str='', msg_type:str=None, limit:int=None, include_output:bool=True, dname:str='')
Find list[dict] of messages in requested dialog that contain the given information. Call with no args to see the full dialog. Often it is more efficient to call once with no re_pattern to see the whole dialog at once, so you can then use the full context from then on. If dname is None, the current dialog is used. If it is an open dialog, it will be updated interactively with real-time updates to the browser. If it is a closed dialog, it will be updated on disk. Dialog names must be paths relative to the solveit root directory (if starting with /) or relative to the current dialog (if not starting with /), and should not include the .ipynb extension. Message ids are identical to those in LLM chat history, so do NOT call this to view a specific message if it’s in the chat history–instead use read_msgid. Note that LLM chat history only includes messages above the current prompt, whereas find_msgs can access all messages. To refer to a found message from code or tools, use its id field.
| Type | Default | Details | |
|---|---|---|---|
| re_pattern | str | Optional regex to search for (re.DOTALL+re.MULTILINE is used) | |
| msg_type | str | None | optional limit by message type (‘code’, ‘note’, or ‘prompt’) |
| limit | int | None | Optionally limit number of returned items |
| include_output | bool | True | Include output in returned dict? |
| dname | str | Dialog to get info for; defaults to current dialog |
# NB: must have a dialogue open including a message with this text in its content
txt = 'tools'
found = find_msgs(txt)found[0]['content']'import json,importlib,linecache,re,inspect,uuid\nfrom typing import Dict\nfrom tempfile import TemporaryDirectory\nfrom ipykernel_helper import *\nfrom dataclasses import dataclass\nfrom os.path import normpath\nfrom fastcore.xml import to_xml\n\nfrom fastcore.utils import *\nfrom fastcore.meta import delegates\nfrom ghapi.all import *\nfrom fastcore.xtras import asdict\nfrom inspect import currentframe,Parameter,signature\nfrom httpx import get as xget, post as xpost\nfrom IPython.display import display,Markdown\nfrom monsterui.all import franken_class_map,apply_classes\nfrom fasthtml.common import Safe,Script,Div\nfrom toolslm.xml import *'
add_html
add_html (content:str, dname:str='')
Send HTML to the browser to be swapped into the DOM
| Type | Default | Details | |
|---|---|---|---|
| content | str | The HTML to send to the client (generally should include hx-swap-oob) | |
| dname | str | Dialog to get info for; defaults to current dialog |
from fasthtml.common import *add_html(Div(P('Hi'), hx_swap_oob='beforeend:#dialog-container')){'success': 'Content added to DOM'}
read_msg
read_msg (n:int=-1, relative:bool=True, id:str=None, view_range:list[int,int]=None, nums:bool=False, dname:str='')
Get the message indexed in the current dialog. - To get the exact message use n=0 and relative=True together with id. - To get a relative message use n (relative position index). - To get the nth message use n with relative=False, e.g n=0 first message, n=-1 last message. If dname is None, the current dialog is used. If it is an open dialog, it will be updated interactively with real-time updates to the browser. If it is a closed dialog, it will be updated on disk. Dialog names must be paths relative to the solveit root directory (if starting with /) or relative to the current dialog (if not starting with /), and should not include the .ipynb extension.
| Type | Default | Details | |
|---|---|---|---|
| n | int | -1 | Message index (if relative, +ve is downwards) |
| relative | bool | True | Is n relative to current message (True) or absolute (False)? |
| id | str | None | Message id to find (defaults to current message) |
| view_range | list | None | Optional 1-indexed (start, end) line range for files, end=-1 for EOF |
| nums | bool | False | Whether to show line numbers |
| dname | str | Dialog to get info for; defaults to current dialog |
read_msgid
read_msgid (id:str, view_range:list[int,int]=None, nums:bool=False, dname:str='')
Get message id. Message IDs can be view directly in LLM chat history/context, or found in find_msgs results. If dname is None, the current dialog is used. If it is an open dialog, it will be updated interactively with real-time updates to the browser. If it is a closed dialog, it will be updated on disk. Dialog names must be paths relative to the solveit root directory (if starting with /) or relative to the current dialog (if not starting with /), and should not include the .ipynb extension.
| Type | Default | Details | |
|---|---|---|---|
| id | str | Message id to find | |
| view_range | list | None | Optional 1-indexed (start, end) line range for files, end=-1 for EOF |
| nums | bool | False | Whether to show line numbers |
| dname | str | Dialog to get message from; defaults to current dialog |
add_msg
add_msg (content:str, placement:str='add_after', id:str=None, msg_type:str='note', output:str='', time_run:str|None='', is_exported:int|None=0, skipped:int|None=0, i_collapsed:int|None=0, o_collapsed:int|None=0, heading_collapsed:int|None=0, pinned:int|None=0, dname:str='')
Add/update a message to the queue to show after code execution completes. If dname is None, the current dialog is used. If it is an open dialog, it will be updated interactively with real-time updates to the browser. If it is a closed dialog, it will be updated on disk. Dialog names must be paths relative to the solveit root directory (if starting with /) or relative to the current dialog (if not starting with /), and should not include the .ipynb extension.
| Type | Default | Details | |
|---|---|---|---|
| content | str | Content of the message (i.e the message prompt, code, or note text) | |
| placement | str | add_after | Can be ‘add_after’, ‘add_before’, ‘at_start’, ‘at_end’ |
| id | str | None | id of message that placement is relative to (if None, uses current message; note: each add_msg updates “current” to the newly created message) |
| msg_type | str | note | Message type, can be ‘code’, ‘note’, or ‘prompt’ |
| output | str | Prompt/code output; Code outputs must be .ipynb-compatible JSON array | |
| time_run | str | None | When was message executed | |
| is_exported | int | None | 0 | Export message to a module? |
| skipped | int | None | 0 | Hide message from prompt? |
| i_collapsed | int | None | 0 | Collapse input? |
| o_collapsed | int | None | 0 | Collapse output? |
| heading_collapsed | int | None | 0 | Collapse heading section? |
| pinned | int | None | 0 | Pin to context? |
| dname | str | Dialog to get info for; defaults to current dialog |
print(__msg_id)
_id = add_msg('testing')
print(__msg_id)_9c544573
_364a3505
print(read_msg().content)testing
read_msg (and all endpoints that return json) wrap responses in dict2obj, so you can use either dict or object syntax.
# dh_settings['dname'] = 'tmp'
# _id = add_msg('testing', placement='at_end')
# print(_id)
# del(dh_settings['dname'])del_msg
del_msg (id:str=None, dname:str='')
Delete a message from the dialog.
| Type | Default | Details | |
|---|---|---|---|
| id | str | None | id of message to delete |
| dname | str | Dialog to get info for; defaults to current dialog |
del_msg(_id){'status': 'success'}_id = _add_msg_unsafe('1+1', run=True, msg_type='code')del_msg(_id){'status': 'success'}_id = _add_msg_unsafe('Hi', run=True, msg_type='prompt')del_msg(_id){'status': 'success'}update_msg
update_msg (id:str=None, msg:Optional[Dict]=None, dname:str='', content:str|None=None, msg_type:str|None=None, output:str|None=None, time_run:str|None=None, is_exported:int|None=None, skipped:int|None=None, i_collapsed:int|None=None, o_collapsed:int|None=None, heading_collapsed:int|None=None, pinned:int|None=None)
Update an existing message. Provide either msg OR field key/values to update. - Use content param to update contents. - Only include parameters to update–missing ones will be left unchanged. If dname is None, the current dialog is used. If it is an open dialog, it will be updated interactively with real-time updates to the browser. If it is a closed dialog, it will be updated on disk. Dialog names must be paths relative to the solveit root directory (if starting with /) or relative to the current dialog (if not starting with /), and should not include the .ipynb extension.
| Type | Default | Details | |
|---|---|---|---|
| id | str | None | id of message to update (if None, uses current message) |
| msg | Optional | None | Dictionary of field keys/values to update |
| dname | str | Dialog to get info for; defaults to current dialog | |
| content | str | None | None | Content of the message (i.e the message prompt, code, or note text) |
| msg_type | str | None | None | Message type, can be ‘code’, ‘note’, or ‘prompt’ |
| output | str | None | None | Prompt/code output; Code outputs must be .ipynb-compatible JSON array |
| time_run | str | None | None | When was message executed |
| is_exported | int | None | None | Export message to a module? |
| skipped | int | None | None | Hide message from prompt? |
| i_collapsed | int | None | None | Collapse input? |
| o_collapsed | int | None | None | Collapse output? |
| heading_collapsed | int | None | None | Collapse heading section? |
| pinned | int | None | None | Pin to context? |
_id = add_msg('testing')_id = update_msg(_id, content='toasting')_id = update_msg(_id, skipped=1)msg = read_msgid(_id)
msg['content'] = 'toasted'
update_msg(msg=msg)'_894a270c'
del_msg(_id){'status': 'success'}_edit_id = add_msg('This message should be found.\n\nThis is a multiline message.')print(read_msg()['content'])This message should be found.
This is a multiline message.
print(read_msg(n=0, id=_edit_id, nums=True)['content']) 1 │ This message should be found.
2 │
3 │ This is a multiline message.
print(read_msg(n=0, id=_edit_id, nums=True, view_range=[2,3])['content']) 2 │
3 │ This is a multiline message.
run_msg
run_msg (ids:str=None, dname:str='')
Adds a message to the run queue. Use read_msg to see the output once it runs.
| Type | Default | Details | |
|---|---|---|---|
| ids | str | None | Comma-separated ids of message(s) to execute |
| dname | str | Running dialog to get info for; defaults to current dialog. (Note dialog must be running for this function) |
1+12
codeid = read_msg()['id']run_msg(codeid)'{"status":"queued"}'
copy_msg
copy_msg (ids:str=None, cut:bool=False, dname:str='')
Add ids to clipboard.
| Type | Default | Details | |
|---|---|---|---|
| ids | str | None | Comma-separated ids of message(s) to copy |
| cut | bool | False | Cut message(s)? (If not, copies) |
| dname | str | Running dialog to copy messages from; defaults to current dialog. (Note dialog must be running for this function) |
paste_msg
paste_msg (id:str=None, after:bool=True, dname:str='')
Paste clipboard msg(s) after/before the current selected msg (id).
| Type | Default | Details | |
|---|---|---|---|
| id | str | None | Message id to paste next to |
| after | bool | True | Paste after id? (If not, pastes before) |
| dname | str | Running dialog to copy messages from; defaults to current dialog. (Note dialog must be running for this function) |
copy_msg(codeid){'success': 'complete'}
tgt = read_msg()['id']paste_msg(tgt){'success': 'complete'}
newmsg = read_msg(1, id=tgt)
newmsg['content']'1+1'
del_msg(newmsg['id']){'status': 'success'}enable_mermaid
enable_mermaid ()
enable_mermaid()mermaid
mermaid (code, cls='mermaid', **kwargs)
A mermaid diagram
mermaid('graph LR; A[Start] --> B[Process]; B --> C[End];')toggle_header
toggle_header (id:str, dname:str='')
Toggle collapsed header state for id
| Type | Default | Details | |
|---|---|---|---|
| id | str | id of markdown header note message to toggle collapsed state | |
| dname | str | Running dialog to copy messages from; defaults to current dialog. (Note dialog must be running for this function) |
test header
hdid = read_msg()['id']test note
header end
toggle_header(hdid){'success': 'complete'}
url2note
url2note (url:str, extract_section:bool=True, selector:str=None, ai_img:bool=True, split_re:str='')
Read URL as markdown, and add note(s) below current message with the result
| Type | Default | Details | |
|---|---|---|---|
| url | str | URL to read | |
| extract_section | bool | True | If url has an anchor, return only that section |
| selector | str | None | Select section(s) using BeautifulSoup.select (overrides extract_section) |
| ai_img | bool | True | Make images visible to the AI |
| split_re | str | Regex to split content into multiple notes, set to ’’ for single note |
_id = url2note('https://www.example.org')del_msg(_id){'status': 'success'}ast_py
ast_py (code:str)
Get an SgRoot root node for python code
node = ast_py("print('hello world')")
stmt = node.find(pattern="print($A)")
res = stmt.get_match('A')
res.text(),res.range()("'hello world'",
Range(start=Pos(line=0, col=6, index=6), end=Pos(line=0, col=19, index=19)))
ast_grep
ast_grep (pattern:str, path='.', lang='python')
Use the ast-grep command to find pattern in path
| Type | Default | Details | |
|---|---|---|---|
| pattern | str | ast-grep pattern to search | |
| path | str | . | path to recursively search for files |
| lang | str | python | language to search/scan |
res = ast_grep(r"xpost($A, data=$B, $$$)", '..')
[(o['text'],o['metaVariables']['single'],o['file']) for o in res][('xpost(f\'http://localhost:{dh_settings["port"]}/{path}\', data=data, headers=headers)',
{'A': {'text': 'f\'http://localhost:{dh_settings["port"]}/{path}\'',
'range': {'byteOffset': {'start': 3767, 'end': 3815},
'start': {'line': 97, 'column': 16},
'end': {'line': 97, 'column': 64}}},
'B': {'text': 'data',
'range': {'byteOffset': {'start': 3822, 'end': 3826},
'start': {'line': 97, 'column': 71},
'end': {'line': 97, 'column': 75}}}},
'dialoghelper/core.py')]
Context
ctx_folder
ctx_folder (path:pathlib.Path='.', types:str|list='py,doc', out=False, raw=True, prefix:bool=False, include_base:bool=True, title:str=None, max_size:int=100000, max_total:int=10000000, readme_first:bool=False, files_only:bool=False, ids:bool=True, recursive:bool=True, symlinks:bool=True, file_glob:str=None, file_re:str=None, folder_re:str=None, skip_file_glob:str=None, skip_file_re:str=None, skip_folder_re:str=None, func:callable=<function join>, ret_folders:bool=False, sort:bool=True, exts:str|list=None)
Convert folder to XML context and place in a new message
| Type | Default | Details | |
|---|---|---|---|
| path | Path | . | Path to collect |
| types | str | list | py,doc | list or comma-separated str of ext types from: py, js, java, c, cpp, rb, r, ex, sh, web, doc, cfg |
| out | bool | False | Include notebook cell outputs? |
| raw | bool | True | Add raw message, or note? |
| prefix | bool | False | Include Anthropic’s suggested prose intro? |
| include_base | bool | True | Include full path in src? |
| title | str | None | Optional title attr for Documents element |
| max_size | int | 100000 | Skip files larger than this (bytes) |
| max_total | int | 10000000 | Max total output size in bytes |
| readme_first | bool | False | Prioritize README files at start of context? |
| files_only | bool | False | Return dict of {filename: size} instead of context? |
| ids | bool | True | Include cell ids in notebooks? |
| recursive | bool | True | search subfolders |
| symlinks | bool | True | follow symlinks? |
| file_glob | str | None | Only include files matching glob |
| file_re | str | None | Only include files matching regex |
| folder_re | str | None | Only enter folders matching regex |
| skip_file_glob | str | None | Skip files matching glob |
| skip_file_re | str | None | Skip files matching regex |
| skip_folder_re | str | None | Skip folders matching regex, |
| func | callable | join | function to apply to each matched file |
| ret_folders | bool | False | return folders, not just files |
| sort | bool | True | sort files by name within each folder |
| exts | str | list | None | list or comma-separated str of exts to include |
| Returns | L | Paths to matched files |
# ctx_folder(raw=False, max_total=500)<documents><document index="1"><src>
00_core.ipynb
</src><document-content>
<notebook><code>#| default_exp core</code><code>from dialoghelper import *</code><md># dialoghelper</md><code>#| export
import json,importlib,linecache,re,inspect,uuid
from typing import Dict
from tempfile import TemporaryDirectory
from ipykernel_helper import *
from dataclasses import dataclass
from fastcore.xml import to_xml
from fastcore.utils import *
from
[TRUNCATED: output size 101206 exceeded max size 500 bytes]
ctx_repo
ctx_repo (owner:str, repo:str, types:str|list='py,doc', out=False, raw=True, ref:str=None, folder:str=None, show_filters:bool=True, token:str=None, prefix:bool=False, include_base:bool=True, title:str=None, max_size:int=100000, max_total:int=10000000, readme_first:bool=False, files_only:bool=False, ids:bool=True, path:Path|str='.', recursive:bool=True, symlinks:bool=True, file_glob:str=None, file_re:str=None, folder_re:str=None, skip_file_glob:str=None, skip_file_re:str=None, skip_folder_re:str=None, func:callable=<function join>, ret_folders:bool=False, sort:bool=True, exts:str|list=None)
Convert GitHub repo to XML context and place in a new message
| Type | Default | Details | |
|---|---|---|---|
| owner | str | GitHub repo owner | |
| repo | str | GitHub repo name | |
| types | str | list | py,doc | list or comma-separated str of ext types from: py, js, java, c, cpp, rb, r, ex, sh, web, doc, cfg |
| out | bool | False | Include notebook cell outputs? |
| raw | bool | True | Add raw message, or note? |
| ref | str | None | Git ref (branch/tag/sha) (get from URL not provided); defaults to repo’s default branch |
| folder | str | None | Only include files under this path (get from URL not provided) |
| show_filters | bool | True | Include filter info in title? |
| token | str | None | GitHub token (uses GITHUB_TOKEN env var if None) |
| prefix | bool | False | Include Anthropic’s suggested prose intro? |
| include_base | bool | True | Include full path in src? |
| title | str | None | Optional title attr for Documents element |
| max_size | int | 100000 | Skip files larger than this (bytes) |
| max_total | int | 10000000 | Max total output size in bytes |
| readme_first | bool | False | Prioritize README files at start of context? |
| files_only | bool | False | Return dict of {filename: size} instead of context? |
| ids | bool | True | Include cell ids in notebooks? |
| path | pathlib.Path | str | . | path to start searching |
| recursive | bool | True | search subfolders |
| symlinks | bool | True | follow symlinks? |
| file_glob | str | None | Only include files matching glob |
| file_re | str | None | Only include files matching regex |
| folder_re | str | None | Only enter folders matching regex |
| skip_file_glob | str | None | Skip files matching glob |
| skip_file_re | str | None | Skip files matching regex |
| skip_folder_re | str | None | Skip folders matching regex, |
| func | callable | join | function to apply to each matched file |
| ret_folders | bool | False | return folders, not just files |
| sort | bool | True | sort files by name within each folder |
| exts | str | list | None | list or comma-separated str of exts to include |
| Returns | Union | XML for LM context, or dict of file sizes |
# ctx_repo('answerdotai', 'toolslm', types='py', max_total=500, raw=False)<documents title="GitHub repository contents from answerdotai/toolslm/main (filters applied -- types: py | max_total: 500)"><document index="1"><src>
00_xml.ipynb
</src><document-content>
<notebook><code>#|default_exp xml</code><md># xml source</md><code>#| export
import hashlib, inspect, xml.etree.ElementTree as ET
from collections import namedtuple
from ghapi.all import GhApi
from fastcore.utils import *
from fastcore.meta import de
[TRUNCATED: output size 102343 exceeded max size 500 bytes]
ctx_symfile
ctx_symfile (sym)
Add note with filepath and contents for a symbol’s source file
# ctx_symfile(TemporaryDirectory)ctx_symfolder
ctx_symfolder (sym, types:str|list='py', skip_file_re='^_mod', prefix:bool=False, out:bool=True, include_base:bool=True, title:str=None, max_size:int=100000, max_total:int=10000000, readme_first:bool=False, files_only:bool=False, ids:bool=True, path:Path|str='.', recursive:bool=True, symlinks:bool=True, file_glob:str=None, file_re:str=None, folder_re:str=None, skip_file_glob:str=None, skip_folder_re:str=None, func:callable=<function join>, ret_folders:bool=False, sort:bool=True, exts:str|list=None)
Add raw message with folder context for a symbol’s source file location
| Type | Default | Details | |
|---|---|---|---|
| sym | Symbol to get folder context from | ||
| types | str | list | py | list or comma-separated str of ext types from: py, js, java, c, cpp, rb, r, ex, sh, web, doc, cfg |
| skip_file_re | str | None | Skip files matching regex |
| prefix | bool | False | Include Anthropic’s suggested prose intro? |
| out | bool | True | Include notebook cell outputs? |
| include_base | bool | True | Include full path in src? |
| title | str | None | Optional title attr for Documents element |
| max_size | int | 100000 | Skip files larger than this (bytes) |
| max_total | int | 10000000 | Max total output size in bytes |
| readme_first | bool | False | Prioritize README files at start of context? |
| files_only | bool | False | Return dict of {filename: size} instead of context? |
| ids | bool | True | Include cell ids in notebooks? |
| path | pathlib.Path | str | . | path to start searching |
| recursive | bool | True | search subfolders |
| symlinks | bool | True | follow symlinks? |
| file_glob | str | None | Only include files matching glob |
| file_re | str | None | Only include files matching regex |
| folder_re | str | None | Only enter folders matching regex |
| skip_file_glob | str | None | Skip files matching glob |
| skip_folder_re | str | None | Skip folders matching regex, |
| func | callable | join | function to apply to each matched file |
| ret_folders | bool | False | return folders, not just files |
| sort | bool | True | sort files by name within each folder |
| exts | str | list | None | list or comma-separated str of exts to include |
| Returns | L | Paths to matched files |
# ctx_symfolder(folder2ctx)ctx_sympkg
ctx_sympkg (sym, types:str|list='py', skip_file_re='^_mod', prefix:bool=False, out:bool=True, include_base:bool=True, title:str=None, max_size:int=100000, max_total:int=10000000, readme_first:bool=False, files_only:bool=False, ids:bool=True, path:Path|str='.', recursive:bool=True, symlinks:bool=True, file_glob:str=None, file_re:str=None, folder_re:str=None, skip_file_glob:str=None, skip_folder_re:str=None, func:callable=<function join>, ret_folders:bool=False, sort:bool=True, exts:str|list=None)
Add raw message with repo context for a symbol’s root package
| Type | Default | Details | |
|---|---|---|---|
| sym | Symbol to get folder context from | ||
| types | str | list | py | list or comma-separated str of ext types from: py, js, java, c, cpp, rb, r, ex, sh, web, doc, cfg |
| skip_file_re | str | None | Skip files matching regex |
| prefix | bool | False | Include Anthropic’s suggested prose intro? |
| out | bool | True | Include notebook cell outputs? |
| include_base | bool | True | Include full path in src? |
| title | str | None | Optional title attr for Documents element |
| max_size | int | 100000 | Skip files larger than this (bytes) |
| max_total | int | 10000000 | Max total output size in bytes |
| readme_first | bool | False | Prioritize README files at start of context? |
| files_only | bool | False | Return dict of {filename: size} instead of context? |
| ids | bool | True | Include cell ids in notebooks? |
| path | pathlib.Path | str | . | path to start searching |
| recursive | bool | True | search subfolders |
| symlinks | bool | True | follow symlinks? |
| file_glob | str | None | Only include files matching glob |
| file_re | str | None | Only include files matching regex |
| folder_re | str | None | Only enter folders matching regex |
| skip_file_glob | str | None | Skip files matching glob |
| skip_folder_re | str | None | Skip folders matching regex, |
| func | callable | join | function to apply to each matched file |
| ret_folders | bool | False | return folders, not just files |
| sort | bool | True | sort files by name within each folder |
| exts | str | list | None | list or comma-separated str of exts to include |
| Returns | L | Paths to matched files |
# ctx_sympkg(folder2ctx)Text Edit
msg_insert_line
msg_insert_line (id:str, insert_line:int, new_str:str, dname:str='')
Insert text at a specific line number in a message. Be sure you’ve called read_msg(..., nums=True) to ensure you know the line numbers. If dname is None, the current dialog is used. If it is an open dialog, it will be updated interactively with real-time updates to the browser. If it is a closed dialog, it will be updated on disk. Dialog names must be paths relative to the solveit root directory (if starting with /) or relative to the current dialog (if not starting with /), and should not include the .ipynb extension.
| Type | Default | Details | |
|---|---|---|---|
| id | str | Message id to edit | |
| insert_line | int | The 1-based line number after which to insert the text (0: before 1st line, 1: after 1st line, 2: after 2nd, etc.) | |
| new_str | str | The text to insert | |
| dname | str | Dialog to get info for; defaults to current dialog |
msg_insert_line(_edit_id, 0, 'This should go to the first line')
msg_insert_line(_edit_id, 3, 'This should go to the 4th line')
msg_insert_line(_edit_id, 5, 'This should go to the last line'){'success': 'Inserted text after line 5 in message _16a71d7b'}
print(read_msg(n=0, id=_edit_id, nums=True)['content']) 1 │ This should go to the first line
2 │ This message should be found.
3 │
4 │ This should go to the 4th line
5 │ This is a multiline message.
6 │ This should go to the last line
msg_str_replace
msg_str_replace (id:str, old_str:str, new_str:str, dname:str='')
Replace first occurrence of old_str with new_str in a message. If dname is None, the current dialog is used. If it is an open dialog, it will be updated interactively with real-time updates to the browser. If it is a closed dialog, it will be updated on disk. Dialog names must be paths relative to the solveit root directory (if starting with /) or relative to the current dialog (if not starting with /), and should not include the .ipynb extension.
| Type | Default | Details | |
|---|---|---|---|
| id | str | Message id to edit | |
| old_str | str | Text to find and replace | |
| new_str | str | Text to replace with | |
| dname | str | Dialog to get info for; defaults to current dialog |
msg_str_replace(_edit_id, 'This should go to the first line', 'This should go to the 1st line'){'success': 'Replaced text in message _16a71d7b'}
print(read_msg(n=0, id=_edit_id, nums=True)['content']) 1 │ This should go to the 1st line
2 │ This message should be found.
3 │
4 │ This should go to the 4th line
5 │ This is a multiline message.
6 │ This should go to the last line
msg_strs_replace
msg_strs_replace (id:str, old_strs:list[str], new_strs:list[str], dname:str='')
Replace multiple strings simultaneously in a message. If dname is None, the current dialog is used. If it is an open dialog, it will be updated interactively with real-time updates to the browser. If it is a closed dialog, it will be updated on disk. Dialog names must be paths relative to the solveit root directory (if starting with /) or relative to the current dialog (if not starting with /), and should not include the .ipynb extension.
| Type | Default | Details | |
|---|---|---|---|
| id | str | Message id to edit | |
| old_strs | list | List of strings to find and replace | |
| new_strs | list | List of replacement strings (must match length of old_strs) | |
| dname | str | Dialog to get info for; defaults to current dialog |
msg_strs_replace(_edit_id, ['This is a multiline message.', 'This should go to the last line'], ['5th line', 'last line']){'success': 'Successfully replaced all the strings in message _16a71d7b'}
print(read_msg(n=0, id=_edit_id, nums=True)['content']) 1 │ This should go to the 1st line
2 │ This message should be found.
3 │
4 │ This should go to the 4th line
5 │ 5th line
6 │ last line
msg_replace_lines
msg_replace_lines (id:str, start_line:int, end_line:int=None, new_content:str='', dname:str='')
Replace a range of lines with new content in a message. Be sure you’ve called read_msg(..., nums=True) to ensure you know the line numbers. If dname is None, the current dialog is used. If it is an open dialog, it will be updated interactively with real-time updates to the browser. If it is a closed dialog, it will be updated on disk. Dialog names must be paths relative to the solveit root directory (if starting with /) or relative to the current dialog (if not starting with /), and should not include the .ipynb extension.
| Type | Default | Details | |
|---|---|---|---|
| id | str | Message id to edit | |
| start_line | int | Starting line number to replace (1-based indexing) | |
| end_line | int | None | Ending line number to replace (1-based, inclusive, negative counts from end, None for single line) |
| new_content | str | New content to replace the specified lines | |
| dname | str | Dialog to get info for; defaults to current dialog |
msg_replace_lines(_edit_id, 2, 4,'line 2\nline 3\nline 4\n'){'success': 'Replaced lines 2 to 4 in message _16a71d7b'}
print(read_msg(n=0, id=_edit_id, nums=True)['content']) 1 │ This should go to the 1st line
2 │ line 2
3 │ line 3
4 │ line 4
5 │ 5th line
6 │ last line
msg_del_lines
msg_del_lines (id:str, start_line:int, end_line:int=None, dname:str='')
Delete a range of lines from a message. Be sure you’ve called read_msg(..., nums=True) to ensure you know the line numbers. If dname is None, the current dialog is used. If it is an open dialog, it will be updated interactively with real-time updates to the browser. If it is a closed dialog, it will be updated on disk. Dialog names must be paths relative to the solveit root directory (if starting with /) or relative to the current dialog (if not starting with /), and should not include the .ipynb extension.
| Type | Default | Details | |
|---|---|---|---|
| id | str | Message id to edit | |
| start_line | int | Starting line number to delete (1-based indexing) | |
| end_line | int | None | Ending line number to delete (1-based, inclusive, negative counts from end, None for single line) |
| dname | str | Dialog to get info for; defaults to current dialog |
msg_del_lines(_edit_id, 2, 4){'success': 'Deleted lines 2 to 4 in message _16a71d7b'}
print(read_msg(n=0, id=_edit_id, nums=True)['content']) 1 │ This should go to the 1st line
2 │ 5th line
3 │ last line
del_msg(_edit_id){'status': 'success'}Gists
load_gist
load_gist (gist_id:str)
Retrieve a gist
gistid = 'jph00/e7cfd4ded593e8ef6217e78a0131960c'
gist = load_gist(gistid)
gist.html_url'https://gist.github.com/jph00/e7cfd4ded593e8ef6217e78a0131960c'
gist_file
gist_file (gist_id:str)
Get the first file from a gist
gfile = gist_file(gistid)
print(gfile.content[:100]+"…")"This is a test module which makes some simple tools available."
__all__ = ["hi","whoami"]
testfoo=…
import_string
import_string (code:str, name:str)
| Type | Details | |
|---|---|---|
| code | str | Code to import as a module |
| name | str | Name of module to create |
is_usable_tool
is_usable_tool (func:<built-infunctioncallable>)
True if the function has a docstring and all parameters have types, meaning that it can be used as an LLM tool.
def hi(who:str):
"Say hi to `who`"
return f"Hello {who}"
def hi2(who):
"Say hi to `who`"
return f"Hello {who}"
def hi3(who:str):
return f"Hello {who}"
bye = "bye"assert is_usable_tool(hi)
assert not is_usable_tool(hi2)
assert not is_usable_tool(hi3)
assert not is_usable_tool(bye)mk_toollist
mk_toollist (syms)
Markdown(mk_toollist([hi]))- &
hi: Say hi towho
import_gist
import_gist (gist_id:str, mod_name:str=None, add_global:bool=True, import_wildcard:bool=False, create_msg:bool=False)
Import gist directly from string without saving to disk
| Type | Default | Details | |
|---|---|---|---|
| gist_id | str | user/id or just id of gist to import as a module | |
| mod_name | str | None | module name to create (taken from gist filename if not passed) |
| add_global | bool | True | add module to caller’s globals? |
| import_wildcard | bool | False | import all exported symbols to caller’s globals |
| create_msg | bool | False | Add a message that lists usable tools |
import_gist(gistid)
importtest.testfoo'testbar'
import_gist.__doc__'Import gist directly from string without saving to disk'
import_gist(gistid, import_wildcard=True)
importtest.testfoo'testbar'
hi("Sarah")'Hello Sarah'
importtest.__all__['hi', 'whoami']
Tool info
from dialoghelper.core import __all__ as _allThis is how we get a superset of tools to include:
tool_info
tool_info ()
fc_tool_info
fc_tool_info ()
is_tool
is_tool (o)
Check if o is a valid tool (has name, docstring, and all params have type annotations)
# Dialoghelper tools
for o in _all:
s = globals()[o]
if is_tool(s): print(f'`{s.__name__}`', end=' ')`add_styles` `find_var` `find_msg_id` `curr_dialog` `iife` `find_msgs` `add_html` `read_msg` `read_msgid` `add_msg` `del_msg` `update_msg` `run_msg` `copy_msg` `paste_msg` `toggle_header` `url2note` `ast_py` `msg_insert_line` `msg_str_replace` `msg_strs_replace` `msg_replace_lines` `msg_del_lines` `load_gist` `gist_file` `is_usable_tool` `import_gist`
# Fastcore tools
for o in tools.__all__:
s = getattr(tools, o)
if is_tool(s): print(f'`{s.__name__}`', end=' ')`run_cmd` `rg` `sed` `view` `create` `insert` `str_replace` `strs_replace` `replace_lines`