diff --git a/dialoghelper/_modidx.py b/dialoghelper/_modidx.py index 9f3fdae..ba2a68a 100644 --- a/dialoghelper/_modidx.py +++ b/dialoghelper/_modidx.py @@ -26,6 +26,10 @@ 'dialoghelper.core.load_gist': ('core.html#load_gist', 'dialoghelper/core.py'), 'dialoghelper.core.mk_toollist': ('core.html#mk_toollist', 'dialoghelper/core.py'), 'dialoghelper.core.msg_idx': ('core.html#msg_idx', 'dialoghelper/core.py'), + 'dialoghelper.core.msg_insert_line': ('core.html#msg_insert_line', 'dialoghelper/core.py'), + 'dialoghelper.core.msg_replace_lines': ('core.html#msg_replace_lines', 'dialoghelper/core.py'), + 'dialoghelper.core.msg_str_replace': ('core.html#msg_str_replace', 'dialoghelper/core.py'), + 'dialoghelper.core.msg_strs_replace': ('core.html#msg_strs_replace', 'dialoghelper/core.py'), 'dialoghelper.core.read_msg': ('core.html#read_msg', 'dialoghelper/core.py'), 'dialoghelper.core.run_msg': ('core.html#run_msg', 'dialoghelper/core.py'), 'dialoghelper.core.tool_info': ('core.html#tool_info', 'dialoghelper/core.py'), diff --git a/dialoghelper/core.py b/dialoghelper/core.py index 18850de..7ad4aaa 100644 --- a/dialoghelper/core.py +++ b/dialoghelper/core.py @@ -2,9 +2,9 @@ # %% auto 0 __all__ = ['Placements', 'empty', 'find_var', 'call_endp', 'find_dname', 'find_msg_id', 'curr_dialog', 'find_msgs', 'msg_idx', - 'read_msg', 'add_html', 'run_msg', 'add_msg', 'del_msg', 'update_msg', 'url2note', 'ast_py', 'ast_grep', - 'load_gist', 'gist_file', 'import_string', 'is_usable_tool', 'mk_toollist', 'import_gist', 'tool_info', - 'fc_tool_info', 'asdict'] + 'add_html', 'add_msg', 'del_msg', 'update_msg', 'url2note', 'ast_py', 'ast_grep', 'read_msg', 'run_msg', + 'msg_insert_line', 'msg_str_replace', 'msg_strs_replace', 'msg_replace_lines', 'load_gist', 'gist_file', + 'import_string', 'is_usable_tool', 'mk_toollist', 'import_gist', 'tool_info', 'fc_tool_info', 'asdict'] # %% ../nbs/00_core.ipynb import json, importlib, linecache @@ -88,17 +88,6 @@ def msg_idx( if not msgid: msgid = find_msg_id() return call_endp('msg_idx_', dname, json=True, msgid=msgid)['msgid'] -# %% ../nbs/00_core.ipynb -def read_msg( - n:int=-1, # Message index (if relative, +ve is downwards) - msgid=None, # Message id to find (defaults to current message) - relative:bool=True, # Is `n` relative to current message (True) or absolute (False)? - dname:str='' # Running dialog to get info for; defaults to current dialog - ): - "Get the `Message` object indexed in the current dialog." - if not msgid: msgid = find_msg_id() - return call_endp('read_msg_', dname, json=True, msgid=msgid, n=n, relative=relative)['msg'] - # %% ../nbs/00_core.ipynb def add_html( content:str, # The HTML to send to the client (generally should include hx-swap-oob) @@ -107,14 +96,6 @@ def add_html( "Send HTML to the browser to be swapped into the DOM" call_endp('add_html_', dname, content=to_xml(content)) -# %% ../nbs/00_core.ipynb -def run_msg( - msgid:str=None, # id of message to execute - dname:str='' # Running dialog to get info for; defaults to current dialog -): - "Adds a message to the run queue. Use read_msg to see the output once it runs." - return call_endp('add_runq_', dname, msgid=msgid, api=True) - # %% ../nbs/00_core.ipynb Placements = str_enum('Placements', 'add_after', 'add_before', 'at_start', 'at_end') @@ -221,6 +202,71 @@ def ast_grep( res = subprocess.run(cmd, shell=True, capture_output=True, text=True) return json.loads(res.stdout) if res.stdout else res.stderr +# %% ../nbs/00_core.ipynb +def read_msg( + n:int=-1, # Message index (if relative, +ve is downwards) + relative:bool=True, # Is `n` relative to current message (True) or absolute (False)? + msgid:str=None, # Message id to find (defaults to current message) + view_range:list[int,int]=None, # Optional 1-indexed (start, end) line range for files, end=-1 for EOF + nums:bool=False, # Whether to show line numbers + dname:str='' # Running dialog to get info for; defaults to current dialog + ): + "Get the `Message` object indexed in the current dialog." + if not msgid: msgid = find_msg_id() + data = dict(n=n, relative=relative, msgid=msgid) + if view_range: data['view_range'] = view_range # None gets converted to '' so we avoid passing it to use the p.default + if nums: data['nums'] = nums + return call_endp('read_msg_', dname, json=True, **data) + +# %% ../nbs/00_core.ipynb +def run_msg( + msgid:str=None, # id of message to execute + dname:str='' # Running dialog to get info for; defaults to current dialog +): + "Adds a message to the run queue. Use read_msg to see the output once it runs." + return call_endp('add_runq_', dname, msgid=msgid, api=True) + +# %% ../nbs/00_core.ipynb +def msg_insert_line( + msgid:str, # Message id to edit + insert_line: int, # The line number after which to insert the text (0 for beginning of file) + new_str: str, # The text to insert + dname:str='' # Running dialog to get info for; defaults to current dialog + ): + "Insert text at a specific line number in a message" + return call_endp('msg_insert_line_', dname, json=True, msgid=msgid, insert_line=insert_line, new_str=new_str) + +# %% ../nbs/00_core.ipynb +def msg_str_replace( + msgid:str, # Message id to edit + old_str: str, # Text to find and replace + new_str: str, # Text to replace with + dname:str='' # Running dialog to get info for; defaults to current dialog +): + "Replace first occurrence of old_str with new_str in a message" + return call_endp('msg_str_replace_', dname, json=True, msgid=msgid, old_str=old_str, new_str=new_str) + +# %% ../nbs/00_core.ipynb +def msg_strs_replace( + msgid:str, # Message id to edit + old_strs:list[str], # List of strings to find and replace + new_strs:list[str], # List of replacement strings (must match length of old_strs) + dname:str='' # Running dialog to get info for; defaults to current dialog +): + "Replace multiple strings simultaneously in a message" + return call_endp('msg_strs_replace_', dname, json=True, msgid=msgid, old_strs=old_strs, new_strs=new_strs) + +# %% ../nbs/00_core.ipynb +def msg_replace_lines( + msgid:str, # Message id to edit + start_line:int, # Starting line number to replace (1-based indexing) + end_line:int, # Ending line number to replace (1-based indexing, inclusive) + new_content:str, # New content to replace the specified lines + dname:str='' # Running dialog to get info for; defaults to current dialog +): + "Replace a range of lines with new content in a message" + return call_endp('msg_replace_lines_', dname, json=True, msgid=msgid, start_line=start_line, end_line=end_line, new_content=new_content) + # %% ../nbs/00_core.ipynb def load_gist(gist_id:str): "Retrieve a gist" @@ -298,10 +344,18 @@ def tool_info(): - &`find_msgs`: Find messages in current specific dialog that contain the given information. - (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.) - &`read_msg`: Get the message indexed in the current dialog. + - To get the exact message use `n=0` and `relative=True` together with `msgid`. + - 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. - &`del_msg`: Delete a message from the dialog. - &`add_msg`: Add/update a message to the queue to show after code execution completes. - &`update_msg`: Update an existing message. -- &`url2note`: Read URL as markdown, and add a note below current message with the result''' +- &`url2note`: Read URL as markdown, and add a note below current message with the result +- &`msg_insert_line`: Insert text at a specific location in a message. +- &`msg_str_replace`: Find and replace text in a message. +- &`msg_strs_replace`: Find and replace multiple strings in a message. +- &`msg_replace_lines`: Replace a range of lines in a message with new content. + - Always first use `read_msg( msgid=msgid, n=0, relative=True, nums=True)` to view the content with line numbers.''' add_msg(cts) # %% ../nbs/00_core.ipynb diff --git a/nbs/00_core.ipynb b/nbs/00_core.ipynb index 8752246..3599812 100644 --- a/nbs/00_core.ipynb +++ b/nbs/00_core.ipynb @@ -4,7 +4,9 @@ "cell_type": "code", "execution_count": null, "id": "955b9784", - "metadata": {}, + "metadata": { + "time_run": "10:22:16a" + }, "outputs": [], "source": [ "#| default_exp core" @@ -22,7 +24,9 @@ "cell_type": "code", "execution_count": null, "id": "e881cda4", - "metadata": {}, + "metadata": { + "time_run": "10:22:17a" + }, "outputs": [], "source": [ "#| export\n", @@ -48,7 +52,9 @@ "cell_type": "code", "execution_count": null, "id": "0eac27d1", - "metadata": {}, + "metadata": { + "time_run": "10:22:17a" + }, "outputs": [], "source": [ "from fastcore import tools" @@ -66,7 +72,9 @@ "cell_type": "code", "execution_count": null, "id": "82476a28", - "metadata": {}, + "metadata": { + "time_run": "10:22:17a" + }, "outputs": [], "source": [ "#| export\n", @@ -77,7 +85,9 @@ "cell_type": "code", "execution_count": null, "id": "1fd907bb", - "metadata": {}, + "metadata": { + "time_run": "10:22:17a" + }, "outputs": [], "source": [ "#| export\n", @@ -95,7 +105,9 @@ "cell_type": "code", "execution_count": null, "id": "bb0489a1", - "metadata": {}, + "metadata": { + "time_run": "10:22:17a" + }, "outputs": [ { "data": { @@ -103,7 +115,7 @@ "1" ] }, - "execution_count": null, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } @@ -117,7 +129,9 @@ "cell_type": "code", "execution_count": null, "id": "dbffb51c", - "metadata": {}, + "metadata": { + "time_run": "10:22:17a" + }, "outputs": [], "source": [ "#| export\n", @@ -134,7 +148,9 @@ "cell_type": "code", "execution_count": null, "id": "a01ad161", - "metadata": {}, + "metadata": { + "time_run": "10:22:17a" + }, "outputs": [], "source": [ "#| export\n", @@ -147,7 +163,9 @@ "cell_type": "code", "execution_count": null, "id": "3d93b27c", - "metadata": {}, + "metadata": { + "time_run": "10:22:17a" + }, "outputs": [], "source": [ "#| export\n", @@ -160,7 +178,9 @@ "cell_type": "code", "execution_count": null, "id": "9cbd170d", - "metadata": {}, + "metadata": { + "time_run": "10:22:17a" + }, "outputs": [ { "data": { @@ -168,7 +188,7 @@ "'_9cbd170d'" ] }, - "execution_count": null, + "execution_count": 23, "metadata": {}, "output_type": "execute_result" } @@ -181,7 +201,9 @@ "cell_type": "code", "execution_count": null, "id": "a9cb5512", - "metadata": {}, + "metadata": { + "time_run": "10:22:17a" + }, "outputs": [], "source": [ "#| export\n", @@ -198,7 +220,9 @@ "cell_type": "code", "execution_count": null, "id": "6a4aa03b", - "metadata": {}, + "metadata": { + "time_run": "10:22:17a" + }, "outputs": [], "source": [ "#| export\n", @@ -220,7 +244,9 @@ "cell_type": "code", "execution_count": null, "id": "aa444dff", - "metadata": {}, + "metadata": { + "time_run": "10:22:17a" + }, "outputs": [ { "data": { @@ -228,7 +254,7 @@ "'from fastcore import tools'" ] }, - "execution_count": null, + "execution_count": 29, "metadata": {}, "output_type": "execute_result" } @@ -244,7 +270,9 @@ "cell_type": "code", "execution_count": null, "id": "19d00175", - "metadata": {}, + "metadata": { + "time_run": "10:22:17a" + }, "outputs": [], "source": [ "#| export\n", @@ -261,7 +289,9 @@ "cell_type": "code", "execution_count": null, "id": "97cf9c42", - "metadata": {}, + "metadata": { + "time_run": "10:22:17a" + }, "outputs": [ { "data": { @@ -269,7 +299,7 @@ "16" ] }, - "execution_count": null, + "execution_count": 33, "metadata": {}, "output_type": "execute_result" } @@ -278,79 +308,13 @@ "msg_idx()" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "fd350235", - "metadata": {}, - "outputs": [], - "source": [ - "#| export\n", - "def read_msg(\n", - " n:int=-1, # Message index (if relative, +ve is downwards)\n", - " msgid=None, # Message id to find (defaults to current message)\n", - " relative:bool=True, # Is `n` relative to current message (True) or absolute (False)?\n", - " dname:str='' # Running dialog to get info for; defaults to current dialog\n", - " ):\n", - " \"Get the `Message` object indexed in the current dialog.\"\n", - " if not msgid: msgid = find_msg_id()\n", - " return call_endp('read_msg_', dname, json=True, msgid=msgid, n=n, relative=relative)['msg']" - ] - }, - { - "cell_type": "markdown", - "id": "8e203f85", - "metadata": {}, - "source": [ - "This message should be found." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "287bda51", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "This message should be found.\n" - ] - } - ], - "source": [ - "# Previous message relative to current\n", - "print(read_msg(-1)['content'])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7e3a864f", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'#| hide\\nfrom nbdev import nbdev_export\\nnbdev_export()'" - ] - }, - "execution_count": null, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Last message in dialog\n", - "read_msg(-1, relative=False)['content']" - ] - }, { "cell_type": "code", "execution_count": null, "id": "2489a94d", - "metadata": {}, + "metadata": { + "time_run": "10:22:17a" + }, "outputs": [], "source": [ "#| export\n", @@ -366,7 +330,9 @@ "cell_type": "code", "execution_count": null, "id": "0657b2ca", - "metadata": {}, + "metadata": { + "time_run": "10:22:17a" + }, "outputs": [], "source": [ "from fasthtml.common import *" @@ -376,85 +342,21 @@ "cell_type": "code", "execution_count": null, "id": "788a9150", - "metadata": {}, + "metadata": { + "time_run": "10:22:17a" + }, "outputs": [], "source": [ "add_html(Div(P('Hi'), hx_swap_oob='beforeend:#dialog-container'))" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "5760ca4d", - "metadata": {}, - "outputs": [], - "source": [ - "#| export\n", - "def run_msg(\n", - " msgid:str=None, # id of message to execute\n", - " dname:str='' # Running dialog to get info for; defaults to current dialog\n", - "):\n", - " \"Adds a message to the run queue. Use read_msg to see the output once it runs.\"\n", - " return call_endp('add_runq_', dname, msgid=msgid, api=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1c87c586", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "2" - ] - }, - "execution_count": null, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "1+1" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "0235d3a4", - "metadata": {}, - "outputs": [], - "source": [ - "codeid = read_msg()['id']" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "58418e15", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'{\"status\":\"queued\"}'" - ] - }, - "execution_count": null, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "run_msg(codeid)" - ] - }, { "cell_type": "code", "execution_count": null, "id": "fdc5a465", - "metadata": {}, + "metadata": { + "time_run": "10:22:17a" + }, "outputs": [], "source": [ "#| export\n", @@ -465,7 +367,9 @@ "cell_type": "code", "execution_count": null, "id": "3ad14786", - "metadata": {}, + "metadata": { + "time_run": "10:22:17a" + }, "outputs": [], "source": [ "#| export\n", @@ -496,7 +400,9 @@ "cell_type": "code", "execution_count": null, "id": "9c544573", - "metadata": {}, + "metadata": { + "time_run": "10:22:17a" + }, "outputs": [], "source": [ "_id = add_msg('testing')" @@ -506,7 +412,9 @@ "cell_type": "code", "execution_count": null, "id": "f1ee1903", - "metadata": {}, + "metadata": { + "time_run": "10:22:17a" + }, "outputs": [], "source": [ "#| export\n", @@ -522,7 +430,9 @@ "cell_type": "code", "execution_count": null, "id": "9c6c959b", - "metadata": {}, + "metadata": { + "time_run": "10:22:17a" + }, "outputs": [], "source": [ "del_msg(_id)" @@ -532,7 +442,9 @@ "cell_type": "code", "execution_count": null, "id": "a9614fcc", - "metadata": {}, + "metadata": { + "time_run": "10:22:17a" + }, "outputs": [], "source": [ "#| export\n", @@ -556,7 +468,9 @@ "cell_type": "code", "execution_count": null, "id": "44cb1b2a", - "metadata": {}, + "metadata": { + "time_run": "10:22:18a" + }, "outputs": [], "source": [ "_id = _add_msg_unsafe('1+1', run=True, msg_type='code')" @@ -566,7 +480,9 @@ "cell_type": "code", "execution_count": null, "id": "8f1e0ee6", - "metadata": {}, + "metadata": { + "time_run": "10:22:18a" + }, "outputs": [], "source": [ "del_msg(_id)" @@ -576,7 +492,9 @@ "cell_type": "code", "execution_count": null, "id": "da3525d7", - "metadata": {}, + "metadata": { + "time_run": "10:22:18a" + }, "outputs": [], "source": [ "_id = _add_msg_unsafe('Hi', run=True, msg_type='prompt')" @@ -586,7 +504,9 @@ "cell_type": "code", "execution_count": null, "id": "4b0077ef", - "metadata": {}, + "metadata": { + "time_run": "10:22:18a" + }, "outputs": [], "source": [ "del_msg(_id)" @@ -596,7 +516,9 @@ "cell_type": "code", "execution_count": null, "id": "023dcb74", - "metadata": {}, + "metadata": { + "time_run": "10:22:18a" + }, "outputs": [], "source": [ "#| export\n", @@ -618,7 +540,9 @@ "cell_type": "code", "execution_count": null, "id": "76ea5418", - "metadata": {}, + "metadata": { + "time_run": "10:22:18a" + }, "outputs": [], "source": [ "#| export\n", @@ -639,71 +563,45 @@ "cell_type": "code", "execution_count": null, "id": "4df69d72", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'_766c3c49'" - ] - }, - "execution_count": null, - "metadata": {}, - "output_type": "execute_result" - } - ], + "metadata": { + "time_run": "10:22:18a" + }, + "outputs": [], "source": [ - "_id = add_msg('testing')\n", - "_id" + "_id = add_msg('testing')" ] }, { "cell_type": "code", "execution_count": null, "id": "05b509a7", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'_766c3c49'" - ] - }, - "execution_count": null, - "metadata": {}, - "output_type": "execute_result" - } - ], + "metadata": { + "time_run": "10:22:18a" + }, + "outputs": [], "source": [ - "update_msg(_id, content='toasting')" + "_id = update_msg(_id, content='toasting')" ] }, { "cell_type": "code", "execution_count": null, "id": "8eaf1438", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'_766c3c49'" - ] - }, - "execution_count": null, - "metadata": {}, - "output_type": "execute_result" - } - ], + "metadata": { + "time_run": "10:22:18a" + }, + "outputs": [], "source": [ - "update_msg(_id, skipped=1)" + "_id = update_msg(_id, skipped=1)" ] }, { "cell_type": "code", "execution_count": null, "id": "ae95747a", - "metadata": {}, + "metadata": { + "time_run": "10:22:18a" + }, "outputs": [], "source": [ "del_msg(_id)" @@ -713,7 +611,9 @@ "cell_type": "code", "execution_count": null, "id": "1b6f96c7", - "metadata": {}, + "metadata": { + "time_run": "10:22:18a" + }, "outputs": [], "source": [ "#| export\n", @@ -731,7 +631,9 @@ "cell_type": "code", "execution_count": null, "id": "fff18bc3", - "metadata": {}, + "metadata": { + "time_run": "10:22:19a" + }, "outputs": [], "source": [ "_id = url2note('https://www.example.org')" @@ -741,7 +643,9 @@ "cell_type": "code", "execution_count": null, "id": "eef90eee", - "metadata": {}, + "metadata": { + "time_run": "10:22:19a" + }, "outputs": [], "source": [ "del_msg(_id)" @@ -751,7 +655,9 @@ "cell_type": "code", "execution_count": null, "id": "7fd95bdf", - "metadata": {}, + "metadata": { + "time_run": "10:22:19a" + }, "outputs": [], "source": [ "#| export\n", @@ -765,7 +671,9 @@ "cell_type": "code", "execution_count": null, "id": "af5a9dfe", - "metadata": {}, + "metadata": { + "time_run": "10:22:19a" + }, "outputs": [ { "data": { @@ -774,7 +682,7 @@ " Range(start=Pos(line=0, col=6, index=6), end=Pos(line=0, col=19, index=19)))" ] }, - "execution_count": null, + "execution_count": 81, "metadata": {}, "output_type": "execute_result" } @@ -790,7 +698,9 @@ "cell_type": "code", "execution_count": null, "id": "013f0d0b", - "metadata": {}, + "metadata": { + "time_run": "10:22:19a" + }, "outputs": [], "source": [ "#| export\n", @@ -811,24 +721,26 @@ "cell_type": "code", "execution_count": null, "id": "1998094e", - "metadata": {}, + "metadata": { + "time_run": "10:22:19a" + }, "outputs": [ { "data": { "text/plain": [ "[(\"xpost(f'http://localhost:5001/{path}', data=data)\",\n", " {'A': {'text': \"f'http://localhost:5001/{path}'\",\n", - " 'range': {'byteOffset': {'start': 1556, 'end': 1587},\n", + " 'range': {'byteOffset': {'start': 1651, 'end': 1682},\n", " 'start': {'line': 43, 'column': 16},\n", " 'end': {'line': 43, 'column': 47}}},\n", " 'B': {'text': 'data',\n", - " 'range': {'byteOffset': {'start': 1594, 'end': 1598},\n", + " 'range': {'byteOffset': {'start': 1689, 'end': 1693},\n", " 'start': {'line': 43, 'column': 54},\n", " 'end': {'line': 43, 'column': 58}}}},\n", " 'dialoghelper/core.py')]" ] }, - "execution_count": null, + "execution_count": 85, "metadata": {}, "output_type": "execute_result" } @@ -839,100 +751,552 @@ ] }, { - "cell_type": "markdown", - "id": "db2c0e1c", - "metadata": {}, + "cell_type": "code", + "execution_count": null, + "id": "9da19150", + "metadata": { + "time_run": "10:22:19a" + }, + "outputs": [], "source": [ - "## Gists" + "#| export\n", + "def read_msg(\n", + " n:int=-1, # Message index (if relative, +ve is downwards)\n", + " relative:bool=True, # Is `n` relative to current message (True) or absolute (False)?\n", + " msgid:str=None, # Message id to find (defaults to current message)\n", + " view_range:list[int,int]=None, # Optional 1-indexed (start, end) line range for files, end=-1 for EOF\n", + " nums:bool=False, # Whether to show line numbers\n", + " dname:str='' # Running dialog to get info for; defaults to current dialog\n", + " ):\n", + " \"Get the `Message` object indexed in the current dialog.\"\n", + " if not msgid: msgid = find_msg_id()\n", + " data = dict(n=n, relative=relative, msgid=msgid)\n", + " if view_range: data['view_range'] = view_range # None gets converted to '' so we avoid passing it to use the p.default\n", + " if nums: data['nums'] = nums\n", + " return call_endp('read_msg_', dname, json=True, **data)" ] }, { "cell_type": "code", "execution_count": null, - "id": "eb4c6bf4", - "metadata": {}, + "id": "ab9d75ec", + "metadata": { + "time_run": "10:23:27a" + }, "outputs": [], "source": [ - "#| export\n", - "def load_gist(gist_id:str):\n", - " \"Retrieve a gist\"\n", - " api = GhApi()\n", - " if '/' in gist_id: *_,user,gist_id = gist_id.split('/')\n", - " else: user = None\n", - " return api.gists.get(gist_id, user=user)" + "_edit_id = add_msg('This message should be found.\\n\\nThis is a multiline message.')" ] }, { "cell_type": "code", "execution_count": null, - "id": "3ab7586f", - "metadata": {}, + "id": "885957eb", + "metadata": { + "time_run": "10:23:29a" + }, "outputs": [ { - "data": { - "text/plain": [ - "'https://gist.github.com/jph00/e7cfd4ded593e8ef6217e78a0131960c'" - ] - }, - "execution_count": null, - "metadata": {}, - "output_type": "execute_result" + "name": "stdout", + "output_type": "stream", + "text": [ + "This message should be found.\n", + "\n", + "This is a multiline message.\n" + ] } ], "source": [ - "gistid = 'jph00/e7cfd4ded593e8ef6217e78a0131960c'\n", - "gist = load_gist(gistid)\n", - "gist.html_url" + "print(read_msg()['msg']['content'])" ] }, { "cell_type": "code", "execution_count": null, - "id": "3b151f8f", - "metadata": {}, - "outputs": [], + "id": "6d53e2dd", + "metadata": { + "time_run": "10:23:30a" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 1 │ This message should be found.\n", + " 2 │ \n", + " 3 │ This is a multiline message.\n" + ] + } + ], "source": [ - "#| export\n", - "def gist_file(gist_id:str):\n", - " \"Get the first file from a gist\"\n", - " gist = load_gist(gist_id)\n", - " return first(gist.files.values())" + "print(read_msg(n=0, msgid=_edit_id, nums=True)['msg']['content'])" ] }, { "cell_type": "code", "execution_count": null, - "id": "ea33969d", - "metadata": {}, + "id": "eda5f04b", + "metadata": { + "time_run": "10:23:31a" + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "\"This is a test module which makes some simple tools available.\"\n", - "__all__ = [\"hi\",\"whoami\"]\n", - "\n", - "testfoo=…\n" + " 2 │ \n", + " 3 │ This is a multiline message.\n" ] } ], "source": [ - "gfile = gist_file(gistid)\n", - "print(gfile.content[:100]+\"…\")" + "print(read_msg(n=0, msgid=_edit_id, nums=True, view_range=[2,3])['msg']['content'])" ] }, { "cell_type": "code", "execution_count": null, - "id": "1ccfc95a", - "metadata": {}, + "id": "316bd7a0", + "metadata": { + "time_run": "10:22:19a" + }, "outputs": [], "source": [ "#| export\n", - "def import_string(\n", - " code:str, # Code to import as a module\n", - " name:str # Name of module to create\n", - "):\n", + "def run_msg(\n", + " msgid:str=None, # id of message to execute\n", + " dname:str='' # Running dialog to get info for; defaults to current dialog\n", + "):\n", + " \"Adds a message to the run queue. Use read_msg to see the output once it runs.\"\n", + " return call_endp('add_runq_', dname, msgid=msgid, api=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6e354677", + "metadata": { + "time_run": "10:22:20a" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 105, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "1+1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6e1c440e", + "metadata": { + "time_run": "10:22:19a" + }, + "outputs": [], + "source": [ + "codeid = read_msg()['msg']['id']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7084f544", + "metadata": { + "time_run": "10:22:19a" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'{\"status\":\"queued\"}'" + ] + }, + "execution_count": 103, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "run_msg(codeid)" + ] + }, + { + "cell_type": "markdown", + "id": "4cfd0bc5", + "metadata": {}, + "source": [ + "## Text Edit" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "63fa73fc", + "metadata": { + "time_run": "10:23:36a" + }, + "outputs": [], + "source": [ + "#| export\n", + "def msg_insert_line(\n", + " msgid:str, # Message id to edit\n", + " insert_line: int, # The line number after which to insert the text (0 for beginning of file)\n", + " new_str: str, # The text to insert\n", + " dname:str='' # Running dialog to get info for; defaults to current dialog\n", + " ):\n", + " \"Insert text at a specific line number in a message\"\n", + " return call_endp('msg_insert_line_', dname, json=True, msgid=msgid, insert_line=insert_line, new_str=new_str)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e97e962f", + "metadata": { + "time_run": "10:23:36a" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'success': 'Inserted text after line 5 in message _c3e8e7f8'}" + ] + }, + "execution_count": 121, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "msg_insert_line(_edit_id, 0, 'This should go to the first line')\n", + "msg_insert_line(_edit_id, 3, 'This should go to the 4th line')\n", + "msg_insert_line(_edit_id, 5, 'This should go to the last line')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1bc29396", + "metadata": { + "time_run": "10:23:39a" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 1 │ This should go to the first line\n", + " 2 │ This message should be found.\n", + " 3 │ \n", + " 4 │ This should go to the 4th line\n", + " 5 │ This is a multiline message.\n", + " 6 │ This should go to the last line\n" + ] + } + ], + "source": [ + "print(read_msg(n=0, msgid=_edit_id, nums=True)['msg']['content'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a2aca58c", + "metadata": { + "time_run": "10:23:46a" + }, + "outputs": [], + "source": [ + "#| export\n", + "def msg_str_replace(\n", + " msgid:str, # Message id to edit\n", + " old_str: str, # Text to find and replace\n", + " new_str: str, # Text to replace with\n", + " dname:str='' # Running dialog to get info for; defaults to current dialog\n", + "):\n", + " \"Replace first occurrence of old_str with new_str in a message\"\n", + " return call_endp('msg_str_replace_', dname, json=True, msgid=msgid, old_str=old_str, new_str=new_str)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "429ad7d4", + "metadata": { + "time_run": "10:23:46a" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'success': 'Replaced text in message _c3e8e7f8'}" + ] + }, + "execution_count": 127, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "msg_str_replace(_edit_id, 'This should go to the first line', 'This should go to the 1st line')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ea4948ca", + "metadata": { + "time_run": "10:23:48a" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 1 │ This should go to the 1st line\n", + " 2 │ This message should be found.\n", + " 3 │ \n", + " 4 │ This should go to the 4th line\n", + " 5 │ This is a multiline message.\n", + " 6 │ This should go to the last line\n" + ] + } + ], + "source": [ + "print(read_msg(n=0, msgid=_edit_id, nums=True)['msg']['content'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "085723cd", + "metadata": { + "time_run": "10:23:51a" + }, + "outputs": [], + "source": [ + "#| export\n", + "def msg_strs_replace(\n", + " msgid:str, # Message id to edit\n", + " old_strs:list[str], # List of strings to find and replace\n", + " new_strs:list[str], # List of replacement strings (must match length of old_strs)\n", + " dname:str='' # Running dialog to get info for; defaults to current dialog\n", + "):\n", + " \"Replace multiple strings simultaneously in a message\"\n", + " return call_endp('msg_strs_replace_', dname, json=True, msgid=msgid, old_strs=old_strs, new_strs=new_strs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e962e660", + "metadata": { + "time_run": "10:23:52a" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'success': 'Successfully replaced all the strings in message _c3e8e7f8'}" + ] + }, + "execution_count": 133, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "msg_strs_replace(_edit_id, ['This is a multiline message.', 'This should go to the last line'], ['5th line', 'last line'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "83897f47", + "metadata": { + "time_run": "10:23:52a" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 1 │ This should go to the 1st line\n", + " 2 │ This message should be found.\n", + " 3 │ \n", + " 4 │ This should go to the 4th line\n", + " 5 │ 5th line\n", + " 6 │ last line\n" + ] + } + ], + "source": [ + "print(read_msg(n=0, msgid=_edit_id, nums=True)['msg']['content'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ebb9dd09", + "metadata": { + "time_run": "10:23:57a" + }, + "outputs": [], + "source": [ + "#| export\n", + "def msg_replace_lines(\n", + " msgid:str, # Message id to edit\n", + " start_line:int, # Starting line number to replace (1-based indexing)\n", + " end_line:int, # Ending line number to replace (1-based indexing, inclusive)\n", + " new_content:str, # New content to replace the specified lines\n", + " dname:str='' # Running dialog to get info for; defaults to current dialog\n", + "):\n", + " \"Replace a range of lines with new content in a message\"\n", + " return call_endp('msg_replace_lines_', dname, json=True, msgid=msgid, start_line=start_line, end_line=end_line, new_content=new_content)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cf50ad90", + "metadata": { + "time_run": "10:23:58a" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'success': 'Replaced lines 2 to 4 in message _c3e8e7f8'}" + ] + }, + "execution_count": 139, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "msg_replace_lines(_edit_id, 2, 4,'line 2\\nline 3\\nline 4\\n')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "816ca38e", + "metadata": { + "time_run": "10:24:00a" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 1 │ This should go to the 1st line\n", + " 2 │ line 2\n", + " 3 │ line 3\n", + " 4 │ line 4\n", + " 5 │ 5th line\n", + " 6 │ last line\n" + ] + } + ], + "source": [ + "print(read_msg(n=0, msgid=_edit_id, nums=True)['msg']['content'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "89487ddb", + "metadata": { + "time_run": "10:24:07a" + }, + "outputs": [], + "source": [ + "del_msg(_edit_id)" + ] + }, + { + "cell_type": "markdown", + "id": "db2c0e1c", + "metadata": {}, + "source": [ + "## Gists" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eb4c6bf4", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def load_gist(gist_id:str):\n", + " \"Retrieve a gist\"\n", + " api = GhApi()\n", + " if '/' in gist_id: *_,user,gist_id = gist_id.split('/')\n", + " else: user = None\n", + " return api.gists.get(gist_id, user=user)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3ab7586f", + "metadata": {}, + "outputs": [], + "source": [ + "gistid = 'jph00/e7cfd4ded593e8ef6217e78a0131960c'\n", + "gist = load_gist(gistid)\n", + "gist.html_url" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3b151f8f", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def gist_file(gist_id:str):\n", + " \"Get the first file from a gist\"\n", + " gist = load_gist(gist_id)\n", + " return first(gist.files.values())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ea33969d", + "metadata": {}, + "outputs": [], + "source": [ + "gfile = gist_file(gistid)\n", + "print(gfile.content[:100]+\"…\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1ccfc95a", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def import_string(\n", + " code:str, # Code to import as a module\n", + " name:str # Name of module to create\n", + "):\n", " with TemporaryDirectory() as tmpdir:\n", " path = Path(tmpdir) / f\"{name}.py\"\n", " path.write_text(code)\n", @@ -1012,21 +1376,7 @@ "execution_count": null, "id": "a952258c", "metadata": {}, - "outputs": [ - { - "data": { - "text/markdown": [ - "- &`hi`: Say hi to `who`" - ], - "text/plain": [ - "" - ] - }, - "execution_count": null, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "Markdown(mk_toollist([hi]))" ] @@ -1068,18 +1418,7 @@ "execution_count": null, "id": "aefee238", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'testbar'" - ] - }, - "execution_count": null, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "import_gist(gistid)\n", "importtest.testfoo" @@ -1090,18 +1429,7 @@ "execution_count": null, "id": "4a4f7f89", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'Import gist directly from string without saving to disk'" - ] - }, - "execution_count": null, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "import_gist.__doc__" ] @@ -1111,18 +1439,7 @@ "execution_count": null, "id": "e80a7944", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'testbar'" - ] - }, - "execution_count": null, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "import_gist(gistid, import_wildcard=True)\n", "importtest.testfoo" @@ -1133,18 +1450,7 @@ "execution_count": null, "id": "573abb48", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'Hello Sarah'" - ] - }, - "execution_count": null, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "hi(\"Sarah\")" ] @@ -1154,18 +1460,7 @@ "execution_count": null, "id": "392dc090", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['hi', 'whoami']" - ] - }, - "execution_count": null, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "importtest.__all__" ] @@ -1189,8 +1484,10 @@ { "cell_type": "code", "execution_count": null, - "id": "694240b8", - "metadata": {}, + "id": "c304279a", + "metadata": { + "time_run": "10:24:27a" + }, "outputs": [], "source": [ "#| export\n", @@ -1204,10 +1501,18 @@ "- &`find_msgs`: Find messages in current specific dialog that contain the given information.\n", " - (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.)\n", "- &`read_msg`: Get the message indexed in the current dialog.\n", + " - To get the exact message use `n=0` and `relative=True` together with `msgid`.\n", + " - To get a relative message use `n` (relative position index).\n", + " - To get the nth message use `n` with `relative=False`, e.g `n=0` first message, `n=-1` last message.\n", "- &`del_msg`: Delete a message from the dialog.\n", "- &`add_msg`: Add/update a message to the queue to show after code execution completes.\n", "- &`update_msg`: Update an existing message.\n", - "- &`url2note`: Read URL as markdown, and add a note below current message with the result'''\n", + "- &`url2note`: Read URL as markdown, and add a note below current message with the result\n", + "- &`msg_insert_line`: Insert text at a specific location in a message.\n", + "- &`msg_str_replace`: Find and replace text in a message.\n", + "- &`msg_strs_replace`: Find and replace multiple strings in a message.\n", + "- &`msg_replace_lines`: Replace a range of lines in a message with new content.\n", + " - Always first use `read_msg( msgid=msgid, n=0, relative=True, nums=True)` to view the content with line numbers.'''\n", " add_msg(cts)" ] }, @@ -1216,36 +1521,7 @@ "execution_count": null, "id": "ccc6ffd1", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "- &`find_var`: Search for var in all frames of the call stack\n", - "- &`find_dname`: Get the message id by searching the call stack for __dialog_id.\n", - "- &`find_msg_id`: Get the message id by searching the call stack for __dialog_id.\n", - "- &`curr_dialog`: Get the current dialog info.\n", - "- &`find_msgs`: 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.\n", - "- &`msg_idx`: Get absolute index of message in dialog.\n", - "- &`read_msg`: Get the `Message` object indexed in the current dialog.\n", - "- &`add_html`: Send HTML to the browser to be swapped into the DOM\n", - "- &`run_msg`: Adds a message to the run queue. Use read_msg to see the output once it runs.\n", - "- &`add_msg`: Add/update a message to the queue to show after code execution completes.\n", - "- &`del_msg`: Delete a message from the dialog.\n", - "- &`update_msg`: Update an existing message. Provide either `msg` OR field key/values to update.\n", - " Use `content` param to update contents.\n", - " Only include parameters to update--missing ones will be left unchanged.\n", - "- &`url2note`: Read URL as markdown, and add a note below current message with the result\n", - "- &`ast_py`: Get an SgRoot root node for python `code`\n", - "- &`ast_grep`: Use the `ast-grep` command to find `pattern` in `path`\n", - "- &`load_gist`: Retrieve a gist\n", - "- &`gist_file`: Get the first file from a gist\n", - "- &`is_usable_tool`: True if the function has a docstring and all parameters have types, meaning that it can be used as an LLM tool.\n", - "- &`import_gist`: Import gist directly from string without saving to disk\n", - "- &`asdict`: Convert `o` to a `dict`, supporting dataclasses, namedtuples, iterables, and `__dict__` attrs.\n" - ] - } - ], + "outputs": [], "source": [ "for o in _all:\n", " s = globals()[o]\n", @@ -1281,23 +1557,7 @@ "execution_count": null, "id": "694429ca", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "- &`run_cmd`: Run `cmd` passing split `argstr`, optionally checking for allowed argstr\n", - "- &`rg`: Run the `rg` command with the args in `argstr` (no need to backslash escape)\n", - "- &`sed`: Run the `sed` command with the args in `argstr` (e.g for reading a section of a file)\n", - "- &`view`: View directory or file contents with optional line range and numbers\n", - "- &`create`: Creates a new file with the given content at the specified path\n", - "- &`insert`: Insert new_str at specified line number\n", - "- &`str_replace`: Replace first occurrence of old_str with new_str in file\n", - "- &`strs_replace`: Replace for each str pair in old_strs,new_strs call `str_replace\n", - "- &`replace_lines`: Replace lines in file using start and end line-numbers (index starting at 1)\n" - ] - } - ], + "outputs": [], "source": [ "for o in tools.__all__:\n", " s = getattr(tools, o)\n", @@ -1316,7 +1576,9 @@ "cell_type": "code", "execution_count": null, "id": "379099ac", - "metadata": {}, + "metadata": { + "time_run": "11:09:00a" + }, "outputs": [], "source": [ "#| hide\n",