toolslm 0.3.2__py3-none-any.whl → 0.3.7__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.
- toolslm/__init__.py +1 -1
- toolslm/_modidx.py +12 -3
- toolslm/funccall.py +59 -13
- toolslm/md_hier.py +35 -6
- toolslm/xml.py +86 -14
- {toolslm-0.3.2.dist-info → toolslm-0.3.7.dist-info}/METADATA +2 -2
- toolslm-0.3.7.dist-info/RECORD +13 -0
- toolslm-0.3.2.dist-info/RECORD +0 -13
- {toolslm-0.3.2.dist-info → toolslm-0.3.7.dist-info}/WHEEL +0 -0
- {toolslm-0.3.2.dist-info → toolslm-0.3.7.dist-info}/entry_points.txt +0 -0
- {toolslm-0.3.2.dist-info → toolslm-0.3.7.dist-info}/licenses/LICENSE +0 -0
- {toolslm-0.3.2.dist-info → toolslm-0.3.7.dist-info}/top_level.txt +0 -0
toolslm/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.3.
|
|
1
|
+
__version__ = "0.3.7"
|
toolslm/_modidx.py
CHANGED
|
@@ -14,7 +14,7 @@ d = { 'settings': { 'branch': 'main',
|
|
|
14
14
|
'toolslm.download.read_html': ('download.html#read_html', 'toolslm/download.py'),
|
|
15
15
|
'toolslm.download.read_md': ('download.html#read_md', 'toolslm/download.py'),
|
|
16
16
|
'toolslm.download.split_url': ('download.html#split_url', 'toolslm/download.py')},
|
|
17
|
-
'toolslm.funccall': { 'toolslm.funccall.
|
|
17
|
+
'toolslm.funccall': { 'toolslm.funccall._coerce_inputs': ('funccall.html#_coerce_inputs', 'toolslm/funccall.py'),
|
|
18
18
|
'toolslm.funccall._copy_loc': ('funccall.html#_copy_loc', 'toolslm/funccall.py'),
|
|
19
19
|
'toolslm.funccall._get_nested_schema': ('funccall.html#_get_nested_schema', 'toolslm/funccall.py'),
|
|
20
20
|
'toolslm.funccall._handle_container': ('funccall.html#_handle_container', 'toolslm/funccall.py'),
|
|
@@ -29,16 +29,25 @@ d = { 'settings': { 'branch': 'main',
|
|
|
29
29
|
'toolslm.funccall.call_func_async': ('funccall.html#call_func_async', 'toolslm/funccall.py'),
|
|
30
30
|
'toolslm.funccall.get_schema': ('funccall.html#get_schema', 'toolslm/funccall.py'),
|
|
31
31
|
'toolslm.funccall.mk_ns': ('funccall.html#mk_ns', 'toolslm/funccall.py'),
|
|
32
|
-
'toolslm.funccall.
|
|
32
|
+
'toolslm.funccall.mk_param': ('funccall.html#mk_param', 'toolslm/funccall.py'),
|
|
33
|
+
'toolslm.funccall.mk_tool': ('funccall.html#mk_tool', 'toolslm/funccall.py'),
|
|
34
|
+
'toolslm.funccall.python': ('funccall.html#python', 'toolslm/funccall.py'),
|
|
35
|
+
'toolslm.funccall.schema2sig': ('funccall.html#schema2sig', 'toolslm/funccall.py')},
|
|
33
36
|
'toolslm.md_hier': {},
|
|
34
37
|
'toolslm.shell': { 'toolslm.shell.TerminalInteractiveShell.run_cell': ( 'shell.html#terminalinteractiveshell.run_cell',
|
|
35
38
|
'toolslm/shell.py'),
|
|
36
39
|
'toolslm.shell.get_shell': ('shell.html#get_shell', 'toolslm/shell.py')},
|
|
37
40
|
'toolslm.xml': { 'toolslm.xml._add_nls': ('xml.html#_add_nls', 'toolslm/xml.py'),
|
|
41
|
+
'toolslm.xml.cell2out': ('xml.html#cell2out', 'toolslm/xml.py'),
|
|
42
|
+
'toolslm.xml.cell2xml': ('xml.html#cell2xml', 'toolslm/xml.py'),
|
|
38
43
|
'toolslm.xml.docs_xml': ('xml.html#docs_xml', 'toolslm/xml.py'),
|
|
39
44
|
'toolslm.xml.files2ctx': ('xml.html#files2ctx', 'toolslm/xml.py'),
|
|
40
45
|
'toolslm.xml.folder2ctx': ('xml.html#folder2ctx', 'toolslm/xml.py'),
|
|
41
46
|
'toolslm.xml.folder2ctx_cli': ('xml.html#folder2ctx_cli', 'toolslm/xml.py'),
|
|
47
|
+
'toolslm.xml.get_mime_text': ('xml.html#get_mime_text', 'toolslm/xml.py'),
|
|
42
48
|
'toolslm.xml.json_to_xml': ('xml.html#json_to_xml', 'toolslm/xml.py'),
|
|
43
49
|
'toolslm.xml.mk_doc': ('xml.html#mk_doc', 'toolslm/xml.py'),
|
|
44
|
-
'toolslm.xml.mk_doctype': ('xml.html#mk_doctype', 'toolslm/xml.py')
|
|
50
|
+
'toolslm.xml.mk_doctype': ('xml.html#mk_doctype', 'toolslm/xml.py'),
|
|
51
|
+
'toolslm.xml.nb2xml': ('xml.html#nb2xml', 'toolslm/xml.py'),
|
|
52
|
+
'toolslm.xml.read_file': ('xml.html#read_file', 'toolslm/xml.py'),
|
|
53
|
+
'toolslm.xml.repo2ctx': ('xml.html#repo2ctx', 'toolslm/xml.py')}}}
|
toolslm/funccall.py
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
# AUTOGENERATED! DO NOT EDIT! File to edit: ../01_funccall.ipynb.
|
|
2
2
|
|
|
3
3
|
# %% auto 0
|
|
4
|
-
__all__ = ['empty', 'custom_types', 'get_schema', '
|
|
4
|
+
__all__ = ['empty', 'custom_types', 'get_schema', 'python', 'mk_ns', 'call_func', 'call_func_async', 'mk_param', 'schema2sig',
|
|
5
|
+
'mk_tool']
|
|
5
6
|
|
|
6
7
|
# %% ../01_funccall.ipynb
|
|
7
|
-
import inspect
|
|
8
|
+
import inspect, json
|
|
8
9
|
from collections import abc
|
|
9
10
|
from fastcore.utils import *
|
|
10
11
|
from fastcore.docments import docments
|
|
11
|
-
from typing import get_origin, get_args, Dict, List, Optional, Tuple, Union
|
|
12
|
+
from typing import get_origin, get_args, Dict, List, Optional, Tuple, Union, Any
|
|
12
13
|
from types import UnionType
|
|
14
|
+
from typing import get_type_hints
|
|
15
|
+
from inspect import Parameter, Signature
|
|
16
|
+
from decimal import Decimal
|
|
17
|
+
from uuid import UUID
|
|
13
18
|
|
|
14
19
|
# %% ../01_funccall.ipynb
|
|
15
20
|
empty = inspect.Parameter.empty
|
|
@@ -41,7 +46,7 @@ def _param(name, info):
|
|
|
41
46
|
return pschema
|
|
42
47
|
|
|
43
48
|
# %% ../01_funccall.ipynb
|
|
44
|
-
custom_types = {Path}
|
|
49
|
+
custom_types = {Path, bytes, Decimal, UUID}
|
|
45
50
|
|
|
46
51
|
def _handle_type(t, defs):
|
|
47
52
|
"Handle a single type, creating nested schemas if necessary"
|
|
@@ -107,7 +112,9 @@ def _get_nested_schema(obj):
|
|
|
107
112
|
if n != 'return' and n != 'self':
|
|
108
113
|
_process_property(n, o, props, req, defs)
|
|
109
114
|
|
|
110
|
-
|
|
115
|
+
tkw = {}
|
|
116
|
+
if isinstance(obj, type): tkw['title']=obj.__name__
|
|
117
|
+
schema = dict(type='object', properties=props, **tkw)
|
|
111
118
|
if req: schema['required'] = list(req)
|
|
112
119
|
if defs: schema['$defs'] = defs
|
|
113
120
|
return schema
|
|
@@ -121,14 +128,9 @@ def get_schema(f:Union[callable,dict], pname='input_schema')->dict:
|
|
|
121
128
|
assert desc, "Docstring missing!"
|
|
122
129
|
d = docments(f, full=True)
|
|
123
130
|
ret = d.pop('return')
|
|
124
|
-
if ret.anno is not empty: desc += f'\n\nReturns:\n- type: {_types(ret.anno)[0]}'
|
|
131
|
+
if (ret.anno is not empty) and (ret.anno is not None): desc += f'\n\nReturns:\n- type: {_types(ret.anno)[0]}'
|
|
125
132
|
return {"name": f.__name__, "description": desc, pname: schema}
|
|
126
133
|
|
|
127
|
-
# %% ../01_funccall.ipynb
|
|
128
|
-
def PathArg(
|
|
129
|
-
path: str # A filesystem path
|
|
130
|
-
): return Path(path)
|
|
131
|
-
|
|
132
134
|
# %% ../01_funccall.ipynb
|
|
133
135
|
import ast, time, signal, traceback
|
|
134
136
|
from fastcore.utils import *
|
|
@@ -191,14 +193,26 @@ def mk_ns(fs):
|
|
|
191
193
|
elif callable(o) and hasattr(o, '__name__'): merged |= {o.__name__: o}
|
|
192
194
|
return merged
|
|
193
195
|
|
|
196
|
+
# %% ../01_funccall.ipynb
|
|
197
|
+
def _coerce_inputs(func, inputs):
|
|
198
|
+
"Coerce inputs based on function type annotations"
|
|
199
|
+
hints = get_type_hints(func) if hasattr(func, '__annotations__') else {}
|
|
200
|
+
res = {}
|
|
201
|
+
for k,v in inputs.items():
|
|
202
|
+
ann = hints.get(k)
|
|
203
|
+
if ann in custom_types: res[k] = ann(v)
|
|
204
|
+
elif isinstance(v, dict) and callable(ann): res[k] = ann(**v)
|
|
205
|
+
else: res[k] = v
|
|
206
|
+
return res
|
|
207
|
+
|
|
194
208
|
# %% ../01_funccall.ipynb
|
|
195
209
|
def call_func(fc_name, fc_inputs, ns, raise_on_err=True):
|
|
196
210
|
"Call the function `fc_name` with the given `fc_inputs` using namespace `ns`."
|
|
197
211
|
if not isinstance(ns, abc.Mapping): ns = mk_ns(ns)
|
|
198
212
|
func = ns[fc_name]
|
|
199
|
-
# Clean up bad param names
|
|
200
213
|
inps = {re.sub(r'\W', '', k):v for k,v in fc_inputs.items()}
|
|
201
|
-
|
|
214
|
+
inps = _coerce_inputs(func, inps)
|
|
215
|
+
try: return func(**inps)
|
|
202
216
|
except Exception as e:
|
|
203
217
|
if raise_on_err: raise e from None
|
|
204
218
|
else: return traceback.format_exc()
|
|
@@ -213,3 +227,35 @@ async def call_func_async(fc_name, fc_inputs, ns, raise_on_err=True):
|
|
|
213
227
|
if raise_on_err: raise e from None
|
|
214
228
|
else: return traceback.format_exc()
|
|
215
229
|
return res
|
|
230
|
+
|
|
231
|
+
# %% ../01_funccall.ipynb
|
|
232
|
+
def mk_param(nm, props, req):
|
|
233
|
+
"Create a `Parameter` for `nm` with schema `props`"
|
|
234
|
+
kind = Parameter.POSITIONAL_OR_KEYWORD if nm in req else Parameter.KEYWORD_ONLY
|
|
235
|
+
default = Parameter.empty if nm in req else props.get('default')
|
|
236
|
+
if props.get('type') == 'array' and 'items' in props:
|
|
237
|
+
item_type = type_map.get(props['items'].get('type'), Any)
|
|
238
|
+
anno = list[item_type]
|
|
239
|
+
else: anno = type_map.get(props.get('type'), Any)
|
|
240
|
+
return Parameter(nm, kind, default=default, annotation=anno)
|
|
241
|
+
|
|
242
|
+
# %% ../01_funccall.ipynb
|
|
243
|
+
def schema2sig(tool):
|
|
244
|
+
"Convert json schema `tool` to a `Signature`"
|
|
245
|
+
props, req = tool.inputSchema['properties'], tool.inputSchema.get('required', [])
|
|
246
|
+
params = sorted([mk_param(k, v, req) for k, v in props.items()], key=lambda p: p.kind)
|
|
247
|
+
return Signature(params)
|
|
248
|
+
|
|
249
|
+
# %% ../01_funccall.ipynb
|
|
250
|
+
def mk_tool(dispfn, tool):
|
|
251
|
+
"Create a callable function from a JSON schema tool definition"
|
|
252
|
+
sig = schema2sig(tool)
|
|
253
|
+
props = tool.inputSchema['properties']
|
|
254
|
+
def fn(*args, **kwargs):
|
|
255
|
+
bound = sig.bind(*args, **kwargs)
|
|
256
|
+
return dispfn(tool.name, **bound.arguments)
|
|
257
|
+
fn.__doc__ = tool.description
|
|
258
|
+
fn.__signature__ = sig
|
|
259
|
+
fn.__name__ = fn.__qualname__ = tool.name
|
|
260
|
+
fn.__annotations__ = {k: p.annotation for k, p in sig.parameters.items()}
|
|
261
|
+
return fn
|
toolslm/md_hier.py
CHANGED
|
@@ -14,20 +14,32 @@ def create_heading_dict(text, rm_fenced=True):
|
|
|
14
14
|
original_text = text
|
|
15
15
|
original_lines = text.splitlines()
|
|
16
16
|
|
|
17
|
-
#
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
# Build line mapping when removing fenced blocks
|
|
18
|
+
if rm_fenced:
|
|
19
|
+
filtered_lines,original_line_map,in_fenced = [],{},False
|
|
20
|
+
for i, line in enumerate(original_lines):
|
|
21
|
+
if line.strip().startswith('```'):
|
|
22
|
+
in_fenced = not in_fenced
|
|
23
|
+
continue
|
|
24
|
+
if not in_fenced:
|
|
25
|
+
original_line_map[len(filtered_lines)] = i
|
|
26
|
+
filtered_lines.append(line)
|
|
27
|
+
|
|
28
|
+
lines_for_headings = filtered_lines
|
|
29
|
+
else:
|
|
30
|
+
lines_for_headings = original_lines
|
|
31
|
+
original_line_map = {i: i for i in range(len(original_lines))}
|
|
20
32
|
|
|
21
|
-
lines_for_headings = text_for_headings.splitlines()
|
|
22
33
|
headings = []
|
|
23
34
|
|
|
24
|
-
# Parse headings with their levels and line numbers
|
|
35
|
+
# Parse headings with their levels and original line numbers
|
|
25
36
|
for idx, line in enumerate(lines_for_headings):
|
|
26
37
|
match = re.match(r'^(#{1,6})\s+\S.*', line)
|
|
27
38
|
if match:
|
|
28
39
|
level = len(match.group(1))
|
|
29
40
|
title = line.strip('#').strip()
|
|
30
|
-
|
|
41
|
+
original_line_idx = original_line_map[idx]
|
|
42
|
+
headings.append({'level': level, 'title': title, 'line': original_line_idx})
|
|
31
43
|
|
|
32
44
|
# Assign text content to each heading using original lines
|
|
33
45
|
for i, h in enumerate(headings):
|
|
@@ -270,9 +282,26 @@ More content after code."""
|
|
|
270
282
|
assert '💻 Computer' in result['🚀 Rocket Heading']
|
|
271
283
|
assert result.text == md_content
|
|
272
284
|
|
|
285
|
+
def test_fenced_blocks_between_headings():
|
|
286
|
+
md_content = """# First Header
|
|
287
|
+
Content here.
|
|
288
|
+
|
|
289
|
+
```python
|
|
290
|
+
# A comment that should be ignored for structure
|
|
291
|
+
def example():
|
|
292
|
+
pass
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
# Second Header
|
|
296
|
+
This content belongs to Second Header."""
|
|
297
|
+
result = create_heading_dict(md_content)
|
|
298
|
+
assert "def example():" not in result['Second Header'].text
|
|
299
|
+
assert result['Second Header'].text == "# Second Header\nThis content belongs to Second Header."
|
|
300
|
+
|
|
273
301
|
test_empty_input()
|
|
274
302
|
test_whitespace_only()
|
|
275
303
|
test_malformed_headings()
|
|
276
304
|
test_unicode_and_emojis()
|
|
305
|
+
test_fenced_blocks_between_headings()
|
|
277
306
|
print('tests passed')
|
|
278
307
|
|
toolslm/xml.py
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
# AUTOGENERATED! DO NOT EDIT! File to edit: ../00_xml.ipynb.
|
|
2
2
|
|
|
3
3
|
# %% auto 0
|
|
4
|
-
__all__ = ['doctype', 'json_to_xml', '
|
|
4
|
+
__all__ = ['doctype', 'json_to_xml', 'get_mime_text', 'cell2out', 'cell2xml', 'nb2xml', 'mk_doctype', 'mk_doc', 'docs_xml',
|
|
5
|
+
'read_file', 'files2ctx', 'folder2ctx', 'repo2ctx', 'folder2ctx_cli']
|
|
5
6
|
|
|
6
7
|
# %% ../00_xml.ipynb
|
|
7
8
|
import hashlib,xml.etree.ElementTree as ET
|
|
8
9
|
from collections import namedtuple
|
|
10
|
+
from ghapi.all import GhApi
|
|
9
11
|
|
|
10
12
|
from fastcore.utils import *
|
|
11
13
|
from fastcore.meta import delegates
|
|
12
14
|
from fastcore.xtras import hl_md
|
|
13
|
-
from fastcore.xml import to_xml, Document, Documents, Document_content, Src
|
|
15
|
+
from fastcore.xml import to_xml, Document, Documents, Document_content, Src, Source,Out,Outs,Cell,Notebook,Md,Code
|
|
14
16
|
from fastcore.script import call_parse
|
|
15
|
-
try: from IPython import display
|
|
16
|
-
except: display=None
|
|
17
17
|
|
|
18
18
|
# %% ../00_xml.ipynb
|
|
19
19
|
def json_to_xml(d:dict, # JSON dictionary to convert
|
|
@@ -31,6 +31,42 @@ def json_to_xml(d:dict, # JSON dictionary to convert
|
|
|
31
31
|
ET.indent(root)
|
|
32
32
|
return ET.tostring(root, encoding='unicode')
|
|
33
33
|
|
|
34
|
+
# %% ../00_xml.ipynb
|
|
35
|
+
def get_mime_text(data):
|
|
36
|
+
"Get text from MIME bundle, preferring markdown over plain"
|
|
37
|
+
if 'text/markdown' in data: return ''.join(list(data['text/markdown']))
|
|
38
|
+
if 'text/plain' in data: return ''.join(list(data['text/plain']))
|
|
39
|
+
|
|
40
|
+
# %% ../00_xml.ipynb
|
|
41
|
+
def cell2out(o):
|
|
42
|
+
"Convert single notebook output to XML format"
|
|
43
|
+
if hasattr(o, 'data'):
|
|
44
|
+
txt = get_mime_text(o.data)
|
|
45
|
+
if txt: return Out(txt, mime='markdown' if 'text/markdown' in o.data else 'plain')
|
|
46
|
+
if hasattr(o, 'text'):
|
|
47
|
+
txt = o.text if isinstance(o.text, str) else ''.join(o.text)
|
|
48
|
+
return Out(txt, type='stream', name=o.get('name', 'stdout'))
|
|
49
|
+
if hasattr(o, 'ename'): return Out(f"{o.ename}: {o.evalue}", type='error')
|
|
50
|
+
|
|
51
|
+
# %% ../00_xml.ipynb
|
|
52
|
+
def cell2xml(cell, out=True):
|
|
53
|
+
"Convert notebook cell to concise XML format"
|
|
54
|
+
src = ''.join(getattr(cell, 'source', ''))
|
|
55
|
+
f = Code if cell.cell_type=='code' else Md
|
|
56
|
+
if not out: return f(src)
|
|
57
|
+
parts = [Source(src)]
|
|
58
|
+
out_items = L(getattr(cell,'outputs',[])).map(cell2out).filter()
|
|
59
|
+
if out_items: parts.append(Outs(*out_items))
|
|
60
|
+
return f(*parts)
|
|
61
|
+
|
|
62
|
+
# %% ../00_xml.ipynb
|
|
63
|
+
def nb2xml(fname=None, nb=None, out=True):
|
|
64
|
+
"Convert notebook to XML format"
|
|
65
|
+
assert bool(fname)^bool(nb), "Pass either `fname` or `nb`"
|
|
66
|
+
if not nb: nb = dict2obj(fname.read_json())
|
|
67
|
+
cells_xml = [to_xml(cell2xml(c, out=out), do_escape=False) for c in nb.cells if c.cell_type in ('code','markdown')]
|
|
68
|
+
return to_xml(Notebook(*cells_xml), do_escape=False)
|
|
69
|
+
|
|
34
70
|
# %% ../00_xml.ipynb
|
|
35
71
|
doctype = namedtuple('doctype', ['src', 'content'])
|
|
36
72
|
|
|
@@ -73,32 +109,68 @@ def docs_xml(docs:list[str], # The content of each document
|
|
|
73
109
|
if srcs is None: srcs = [None]*len(docs)
|
|
74
110
|
if details is None: details = [{}]*len(docs)
|
|
75
111
|
docs = (mk_doc(i+1, d, s, **kw) for i,(d,s,kw) in enumerate(zip(docs,srcs,details)))
|
|
76
|
-
return pre + to_xml(Documents(docs))
|
|
112
|
+
return pre + to_xml(Documents(docs), do_escape=False)
|
|
113
|
+
|
|
114
|
+
# %% ../00_xml.ipynb
|
|
115
|
+
def read_file(fname, out=True):
|
|
116
|
+
"Read file content, converting notebooks to XML if needed"
|
|
117
|
+
fname = Path(fname)
|
|
118
|
+
if fname.suffix == '.ipynb': return nb2xml(fname, out=out)
|
|
119
|
+
return fname.read_text()
|
|
77
120
|
|
|
78
121
|
# %% ../00_xml.ipynb
|
|
79
122
|
def files2ctx(
|
|
80
123
|
fnames:list[Union[str,Path]], # List of file names to add to context
|
|
81
|
-
prefix:bool=True # Include Anthropic's suggested prose intro?
|
|
124
|
+
prefix:bool=True, # Include Anthropic's suggested prose intro?
|
|
125
|
+
out:bool=True, # Include notebook cell outputs?
|
|
126
|
+
srcs:Optional[list]=None # Use the labels instead of `fnames`
|
|
82
127
|
)->str: # XML for LM context
|
|
128
|
+
"Convert files to XML context, handling notebooks"
|
|
83
129
|
fnames = [Path(o) for o in fnames]
|
|
84
|
-
contents = [o
|
|
85
|
-
return docs_xml(contents, fnames, prefix=prefix)
|
|
130
|
+
contents = [read_file(o, out=out) for o in fnames]
|
|
131
|
+
return docs_xml(contents, srcs or fnames, prefix=prefix)
|
|
86
132
|
|
|
87
133
|
# %% ../00_xml.ipynb
|
|
88
134
|
@delegates(globtastic)
|
|
89
135
|
def folder2ctx(
|
|
90
|
-
folder:Union[str,Path],
|
|
91
|
-
prefix:bool=True,
|
|
92
|
-
|
|
93
|
-
|
|
136
|
+
folder:Union[str,Path],
|
|
137
|
+
prefix:bool=True,
|
|
138
|
+
out:bool=True,
|
|
139
|
+
include_base:bool=True,
|
|
140
|
+
**kwargs
|
|
141
|
+
)->str:
|
|
142
|
+
"Convert folder contents to XML context, handling notebooks"
|
|
143
|
+
folder = Path(folder)
|
|
94
144
|
fnames = globtastic(folder, **kwargs)
|
|
95
|
-
|
|
145
|
+
srcs = fnames if include_base else [Path(f).relative_to(folder) for f in fnames]
|
|
146
|
+
return files2ctx(fnames, prefix=prefix, out=out, srcs=srcs)
|
|
147
|
+
|
|
148
|
+
# %% ../00_xml.ipynb
|
|
149
|
+
@delegates(folder2ctx)
|
|
150
|
+
def repo2ctx(
|
|
151
|
+
owner:str, # GitHub repo owner
|
|
152
|
+
repo:str, # GitHub repo name
|
|
153
|
+
ref:str=None, # Git ref (branch/tag/sha); defaults to repo's default branch
|
|
154
|
+
**kwargs # Passed to `folder2ctx`
|
|
155
|
+
)->str: # XML for LM context
|
|
156
|
+
"Convert GitHub repo to XML context without cloning"
|
|
157
|
+
import tempfile, tarfile, io
|
|
158
|
+
api = GhApi()
|
|
159
|
+
if ref is None: ref = api.repos.get(owner, repo).default_branch
|
|
160
|
+
data = api.repos.download_tarball_archive(owner, repo, ref)
|
|
161
|
+
tf = tarfile.open(fileobj=io.BytesIO(data))
|
|
162
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
163
|
+
tf.extractall(tmp, filter='data')
|
|
164
|
+
subdir = Path(tmp) / tf.getmembers()[0].name.split('/')[0]
|
|
165
|
+
return folder2ctx(subdir, include_base=False, **kwargs)
|
|
96
166
|
|
|
97
167
|
# %% ../00_xml.ipynb
|
|
98
168
|
@call_parse
|
|
99
169
|
@delegates(folder2ctx)
|
|
100
170
|
def folder2ctx_cli(
|
|
101
171
|
folder:str, # Folder name containing files to add to context
|
|
172
|
+
out:bool=True, # Include notebook cell outputs?
|
|
102
173
|
**kwargs # Passed to `folder2ctx`
|
|
103
174
|
)->str: # XML for Claude context
|
|
104
|
-
|
|
175
|
+
"CLI to convert folder contents to XML context, handling notebooks"
|
|
176
|
+
print(folder2ctx(folder, out=out, **kwargs))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: toolslm
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.7
|
|
4
4
|
Summary: Tools to make language models a bit easier to use
|
|
5
5
|
Home-page: https://github.com/AnswerDotAI/toolslm
|
|
6
6
|
Author: Jeremy Howard
|
|
@@ -16,7 +16,7 @@ Classifier: License :: OSI Approved :: Apache Software License
|
|
|
16
16
|
Requires-Python: >=3.9
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
18
|
License-File: LICENSE
|
|
19
|
-
Requires-Dist: fastcore>=1.
|
|
19
|
+
Requires-Dist: fastcore>=1.9.6
|
|
20
20
|
Requires-Dist: httpx
|
|
21
21
|
Provides-Extra: dev
|
|
22
22
|
Dynamic: author
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
toolslm/__init__.py,sha256=J0I0c7-a50EOnWXMryTu_E6xhXSYFBPjVpeYP_a3vRI,22
|
|
2
|
+
toolslm/_modidx.py,sha256=kpgsDpj-Tvn90wezrHaMttyzhNcyNVgw_dQgK10qotI,5308
|
|
3
|
+
toolslm/download.py,sha256=g3BxUSxylC_575M7RFSJ1GI3Co3EwPDdEeWzxaf2Czk,4451
|
|
4
|
+
toolslm/funccall.py,sha256=0OBrx6KzI0KK13L-5Hn69yah9oZhgTsKchmMenCoT0A,10421
|
|
5
|
+
toolslm/md_hier.py,sha256=r_NPezhgfxjRmSYFlu_ND42hXt1qSbaPWHTcjbviOn4,11010
|
|
6
|
+
toolslm/shell.py,sha256=dGInuRKvexu21VmtZkw_0S3BGiTsbAongUG-yG4YHpc,1566
|
|
7
|
+
toolslm/xml.py,sha256=TO3i6QD1g_ya8B7Wxwib2ZWv7pwVpfyaAalw1qrKb74,7148
|
|
8
|
+
toolslm-0.3.7.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
9
|
+
toolslm-0.3.7.dist-info/METADATA,sha256=IaRtHzIR_YzPP-XOAcO5EdSKWChZwgpSOz5HCdgGqGc,2403
|
|
10
|
+
toolslm-0.3.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
11
|
+
toolslm-0.3.7.dist-info/entry_points.txt,sha256=xFz0Eymlo5X7BGpaO6DI9gMxvN5A7faebzrlr8ctp5I,95
|
|
12
|
+
toolslm-0.3.7.dist-info/top_level.txt,sha256=4hRTrFWayz_Kz5221XjvlpCwVFrW3WPi1P0fllkTq9s,8
|
|
13
|
+
toolslm-0.3.7.dist-info/RECORD,,
|
toolslm-0.3.2.dist-info/RECORD
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
toolslm/__init__.py,sha256=vNiWJ14r_cw5t_7UDqDQIVZvladKFGyHH2avsLpN7Vg,22
|
|
2
|
-
toolslm/_modidx.py,sha256=-D-B5o30VGs11gBKf96lpADVXnZhdiVEshJpLzmUnDs,4378
|
|
3
|
-
toolslm/download.py,sha256=g3BxUSxylC_575M7RFSJ1GI3Co3EwPDdEeWzxaf2Czk,4451
|
|
4
|
-
toolslm/funccall.py,sha256=7nPfbcvDRMWiVKBKMLlCOMInoUJgDs5e38ef2T7QBHY,8485
|
|
5
|
-
toolslm/md_hier.py,sha256=Havk9Hf0t2Xt67n_r7ZxCsS0pciR85iLcE5quShvkTg,10032
|
|
6
|
-
toolslm/shell.py,sha256=dGInuRKvexu21VmtZkw_0S3BGiTsbAongUG-yG4YHpc,1566
|
|
7
|
-
toolslm/xml.py,sha256=D665Nk7NzyZlXyXrpnIRqfK2xQ-6Gf0bCSgocjF7zik,4061
|
|
8
|
-
toolslm-0.3.2.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
9
|
-
toolslm-0.3.2.dist-info/METADATA,sha256=5lWEv7BWTwdd5cvXgGsQXqr0j6tk8UIcGpRTlcjV3V4,2404
|
|
10
|
-
toolslm-0.3.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
11
|
-
toolslm-0.3.2.dist-info/entry_points.txt,sha256=xFz0Eymlo5X7BGpaO6DI9gMxvN5A7faebzrlr8ctp5I,95
|
|
12
|
-
toolslm-0.3.2.dist-info/top_level.txt,sha256=4hRTrFWayz_Kz5221XjvlpCwVFrW3WPi1P0fllkTq9s,8
|
|
13
|
-
toolslm-0.3.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|