lcode-cli 0.2.2__py3-none-any.whl → 0.3.1__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.
- lcode/__init__.py +1 -1
- lcode/agent.py +23 -0
- lcode/bench.py +1082 -0
- lcode/checkpoints.py +449 -0
- lcode/cli.py +92 -2
- lcode/config.py +1 -0
- lcode/ollama.py +4 -0
- lcode/repl.py +163 -1
- lcode/tools.py +3 -0
- {lcode_cli-0.2.2.dist-info → lcode_cli-0.3.1.dist-info}/METADATA +7 -4
- lcode_cli-0.3.1.dist-info/RECORD +23 -0
- lcode_cli-0.2.2.dist-info/RECORD +0 -21
- {lcode_cli-0.2.2.dist-info → lcode_cli-0.3.1.dist-info}/WHEEL +0 -0
- {lcode_cli-0.2.2.dist-info → lcode_cli-0.3.1.dist-info}/entry_points.txt +0 -0
- {lcode_cli-0.2.2.dist-info → lcode_cli-0.3.1.dist-info}/licenses/LICENSE +0 -0
lcode/repl.py
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import html
|
|
6
|
+
import json
|
|
6
7
|
import os
|
|
7
8
|
import re
|
|
8
9
|
import threading
|
|
@@ -23,6 +24,7 @@ from rich.text import Text
|
|
|
23
24
|
from lcode import __version__, catalog, limits, sessions, web
|
|
24
25
|
from lcode.agent import AUTO_COMPACT_RATIO, INIT_PROMPT, Agent
|
|
25
26
|
from lcode.catalog import MIN_USEFUL_CONTEXT
|
|
27
|
+
from lcode.checkpoints import Checkpoint, CheckpointError, Restore
|
|
26
28
|
from lcode.config import PERMISSION_MODES, STATE_DIR, ConfigError, format_tokens, parse_context
|
|
27
29
|
from lcode.hardware import Hardware
|
|
28
30
|
from lcode.ollama import OllamaError
|
|
@@ -34,6 +36,9 @@ COMMANDS = {
|
|
|
34
36
|
"/clear": "Start a fresh conversation",
|
|
35
37
|
"/rename": "Name this session so you can find it later, e.g. /rename auth refactor",
|
|
36
38
|
"/resume": "Resume a saved session: pick from a list, or /resume <number|name> (/resume all: every folder)",
|
|
39
|
+
"/undo": "Undo the file changes of the last request (lcode saves a checkpoint before changing files)",
|
|
40
|
+
"/rewind": "Go back to before an earlier request: its files, and optionally the conversation",
|
|
41
|
+
"/checkpoints": "List the requests that changed files, and which files",
|
|
37
42
|
"/compact": "Summarize the conversation to free context (optional: what to focus on)",
|
|
38
43
|
"/context": "Show context usage and change the window size: pick from a list, or /context 128k",
|
|
39
44
|
"/ctx": "Shortcut for /context",
|
|
@@ -229,6 +234,157 @@ def context_command(agent: Agent, arg: str, hardware: Hardware) -> None:
|
|
|
229
234
|
apply_context(agent, size, hardware)
|
|
230
235
|
|
|
231
236
|
|
|
237
|
+
def ask_yes(question: str) -> bool:
|
|
238
|
+
try:
|
|
239
|
+
return input(f" {question} [y/N] ").strip().lower() in ("y", "yes")
|
|
240
|
+
except EOFError:
|
|
241
|
+
return False
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def checkpoints_off(agent: Agent) -> bool:
|
|
245
|
+
if agent.checkpoints.enabled:
|
|
246
|
+
return False
|
|
247
|
+
agent.console.print("Checkpoints are off. Turn them on with: lcode config set checkpoints true")
|
|
248
|
+
return True
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def print_checkpoints(agent: Agent) -> None:
|
|
252
|
+
c = agent.console
|
|
253
|
+
if checkpoints_off(agent):
|
|
254
|
+
return
|
|
255
|
+
items = agent.checkpoints.items
|
|
256
|
+
if not items:
|
|
257
|
+
c.print(
|
|
258
|
+
"No checkpoints yet. Before the model first changes files in a request, lcode saves a checkpoint; "
|
|
259
|
+
"/undo restores it."
|
|
260
|
+
)
|
|
261
|
+
return
|
|
262
|
+
table = Table(title="Checkpoints", title_justify="left", header_style="bold")
|
|
263
|
+
table.add_column("#", justify="right", style="cyan")
|
|
264
|
+
table.add_column("When")
|
|
265
|
+
table.add_column("Request")
|
|
266
|
+
table.add_column("Files changed")
|
|
267
|
+
for cp in items:
|
|
268
|
+
files = ", ".join(escape(p) for p in cp.paths[:3]) + (f", +{len(cp.paths) - 3}" if len(cp.paths) > 3 else "")
|
|
269
|
+
style = "dim strike" if cp.undone else ""
|
|
270
|
+
table.add_row(
|
|
271
|
+
str(cp.n),
|
|
272
|
+
sessions.age(cp.created),
|
|
273
|
+
escape(cp.title),
|
|
274
|
+
files + (" [dim](undone)[/]" if cp.undone else ""),
|
|
275
|
+
style=style,
|
|
276
|
+
)
|
|
277
|
+
c.print(table)
|
|
278
|
+
c.print("[dim]/undo reverts the latest request; /rewind <number> goes back to before that request.[/]")
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def undo_command(agent: Agent) -> None:
|
|
282
|
+
if checkpoints_off(agent):
|
|
283
|
+
return
|
|
284
|
+
active = agent.checkpoints.active()
|
|
285
|
+
if not active:
|
|
286
|
+
agent.console.print("Nothing to undo: no request in this session has changed files (or they're all undone).")
|
|
287
|
+
return
|
|
288
|
+
restore_checkpoint(agent, active[-1], rewind=False)
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def rewind_command(agent: Agent, arg: str) -> None:
|
|
292
|
+
c = agent.console
|
|
293
|
+
if checkpoints_off(agent):
|
|
294
|
+
return
|
|
295
|
+
if not arg:
|
|
296
|
+
print_checkpoints(agent)
|
|
297
|
+
if not agent.checkpoints.active():
|
|
298
|
+
return
|
|
299
|
+
try:
|
|
300
|
+
arg = input(" Go back to before which request? (number, Enter to cancel): ").strip()
|
|
301
|
+
except EOFError:
|
|
302
|
+
return
|
|
303
|
+
if not arg:
|
|
304
|
+
return
|
|
305
|
+
target = agent.checkpoints.find(int(arg)) if arg.isdigit() else None
|
|
306
|
+
if target is None:
|
|
307
|
+
c.print(f"[yellow]No checkpoint {escape(arg)}. /checkpoints lists them.[/]")
|
|
308
|
+
elif target.undone:
|
|
309
|
+
c.print(f"Checkpoint {target.n} is already undone.")
|
|
310
|
+
else:
|
|
311
|
+
restore_checkpoint(agent, target, rewind=True)
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
def file_summary(plan: Restore, limit: int = 30) -> str:
|
|
315
|
+
parts = []
|
|
316
|
+
for verb, paths in (("restored", plan.restore), ("removed", plan.remove)):
|
|
317
|
+
if paths:
|
|
318
|
+
shown = ", ".join(paths[:limit]) + (f" and {len(paths) - limit} more" if len(paths) > limit else "")
|
|
319
|
+
parts.append(f"{verb} {shown}")
|
|
320
|
+
return "; ".join(parts)
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
def restore_checkpoint(agent: Agent, target: Checkpoint, rewind: bool) -> None:
|
|
324
|
+
"""Put the files back to how they were before `target`'s request (and every later one)."""
|
|
325
|
+
c, cps = agent.console, agent.checkpoints
|
|
326
|
+
try:
|
|
327
|
+
plan = cps.plan(target)
|
|
328
|
+
except CheckpointError as e:
|
|
329
|
+
c.print(f"[red]Can't read checkpoint {target.n}: {escape(str(e))}[/]")
|
|
330
|
+
return
|
|
331
|
+
later = len(plan.undoing) - 1
|
|
332
|
+
also = f" and {later} later request{'' if later == 1 else 's'}" if later > 0 else ""
|
|
333
|
+
action = "Going back to before" if rewind else "Undoing"
|
|
334
|
+
c.print(f"{action} request {target.n}{also}: [bold]{escape(target.title)}[/]")
|
|
335
|
+
for path in plan.restore[:20]:
|
|
336
|
+
c.print(f" [green]restore[/] {escape(path)}")
|
|
337
|
+
for path in plan.remove[:20]:
|
|
338
|
+
c.print(f" [red]remove[/] {escape(path)}")
|
|
339
|
+
hidden = max(0, len(plan.restore) - 20) + max(0, len(plan.remove) - 20)
|
|
340
|
+
if hidden:
|
|
341
|
+
c.print(f" … and {hidden} more")
|
|
342
|
+
if plan.conflicts:
|
|
343
|
+
c.print("[yellow]These files changed again after lcode changed them; going back loses those later edits:[/]")
|
|
344
|
+
for path in plan.conflicts[:20]:
|
|
345
|
+
c.print(f" [yellow]{escape(path)}[/]")
|
|
346
|
+
if not ask_yes("Go back anyway?"):
|
|
347
|
+
c.print("Nothing changed.")
|
|
348
|
+
return
|
|
349
|
+
elif rewind and (plan.restore or plan.remove) and not ask_yes("Restore these files?"):
|
|
350
|
+
c.print("Nothing changed.")
|
|
351
|
+
return
|
|
352
|
+
index = target.message_index
|
|
353
|
+
truncate = (
|
|
354
|
+
rewind
|
|
355
|
+
and 0 < index < len(agent.messages)
|
|
356
|
+
and agent.messages[index].get("role") == "user"
|
|
357
|
+
and agent.messages[index].get("content", "").startswith(target.request)
|
|
358
|
+
and ask_yes("Also remove those requests and answers from the conversation?")
|
|
359
|
+
)
|
|
360
|
+
try:
|
|
361
|
+
cps.apply(plan)
|
|
362
|
+
except CheckpointError as e:
|
|
363
|
+
c.print(f"[red]Couldn't restore the files: {escape(str(e))}[/]")
|
|
364
|
+
return
|
|
365
|
+
for path in cps.absolute_paths(plan):
|
|
366
|
+
agent.tools.read_mtimes.pop(path, None) # the model must read restored files again before editing
|
|
367
|
+
if not (plan.restore or plan.remove):
|
|
368
|
+
c.print("The files were already back to how they were before that request.")
|
|
369
|
+
else:
|
|
370
|
+
c.print(f"[green]Done:[/] {escape(file_summary(plan, limit=8))}.")
|
|
371
|
+
if truncate:
|
|
372
|
+
agent.messages = agent.messages[:index]
|
|
373
|
+
agent.ctx_used = sum(len(json.dumps(m)) for m in agent.messages) // 3
|
|
374
|
+
c.print(f"The conversation is back to before request {target.n} as well.")
|
|
375
|
+
elif plan.restore or plan.remove:
|
|
376
|
+
what = "undid the file changes from" if not rewind else "rolled the files back to before"
|
|
377
|
+
agent.messages.append(
|
|
378
|
+
{
|
|
379
|
+
"role": "user",
|
|
380
|
+
"content": f'[lcode] The user {what} their request "{target.title}": {file_summary(plan)}. '
|
|
381
|
+
"Those files are back to how they were before that request, so read them again before "
|
|
382
|
+
"changing them.",
|
|
383
|
+
}
|
|
384
|
+
)
|
|
385
|
+
agent.save()
|
|
386
|
+
|
|
387
|
+
|
|
232
388
|
def apply_context(agent: Agent, size: int, hardware: Hardware) -> None:
|
|
233
389
|
c, s = agent.console, agent.settings
|
|
234
390
|
if size == s.context:
|
|
@@ -282,7 +438,7 @@ def handle_command(agent: Agent, line: str, hardware: Hardware) -> bool:
|
|
|
282
438
|
if cmd in ("/exit", "/quit", "/q"):
|
|
283
439
|
return False
|
|
284
440
|
if cmd == "/help":
|
|
285
|
-
rows = "\n".join(f" [cyan]{k:<
|
|
441
|
+
rows = "\n".join(f" [cyan]{k:<13}[/] {v}" for k, v in COMMANDS.items())
|
|
286
442
|
keys = (
|
|
287
443
|
"Enter = send · Esc+Enter or trailing \\ = newline · Ctrl+C = interrupt · Ctrl+D = quit · "
|
|
288
444
|
"@path = attach a file · Shift+Tab = cycle permission mode"
|
|
@@ -302,6 +458,12 @@ def handle_command(agent: Agent, line: str, hardware: Hardware) -> bool:
|
|
|
302
458
|
info = choose_session(agent, arg)
|
|
303
459
|
if info:
|
|
304
460
|
resume_session(agent, info)
|
|
461
|
+
elif cmd == "/undo":
|
|
462
|
+
undo_command(agent)
|
|
463
|
+
elif cmd == "/rewind":
|
|
464
|
+
rewind_command(agent, arg)
|
|
465
|
+
elif cmd == "/checkpoints":
|
|
466
|
+
print_checkpoints(agent)
|
|
305
467
|
elif cmd == "/compact":
|
|
306
468
|
agent.compact(arg)
|
|
307
469
|
elif cmd in ("/context", "/ctx"):
|
lcode/tools.py
CHANGED
|
@@ -438,6 +438,7 @@ class Toolbox:
|
|
|
438
438
|
ok, feedback = self.agent.perms.request("edit", "edit", f"{verb} {self.rel(p)}", body)
|
|
439
439
|
if not ok:
|
|
440
440
|
return feedback
|
|
441
|
+
self.agent.checkpoint()
|
|
441
442
|
self._write(p, content)
|
|
442
443
|
n = len(content.splitlines())
|
|
443
444
|
self.console.print(f" [green]✓[/] {'Updated' if exists else 'Created'} {self.rel(p)} ({n} lines)")
|
|
@@ -472,6 +473,7 @@ class Toolbox:
|
|
|
472
473
|
ok, feedback = self.agent.perms.request("edit", "edit", f"Edit {self.rel(p)}", self._diff(p, text, new_text))
|
|
473
474
|
if not ok:
|
|
474
475
|
return feedback
|
|
476
|
+
self.agent.checkpoint()
|
|
475
477
|
self._write(p, new_text)
|
|
476
478
|
self.console.print(f" [green]✓[/] Edited {self.rel(p)}")
|
|
477
479
|
idx = new_text.find(new_string) if new_string else -1
|
|
@@ -493,6 +495,7 @@ class Toolbox:
|
|
|
493
495
|
)
|
|
494
496
|
if not ok:
|
|
495
497
|
return feedback
|
|
498
|
+
self.agent.checkpoint()
|
|
496
499
|
self.console.print(Text(f" $ {command}", style="bold cyan"))
|
|
497
500
|
fd, cwd_file = tempfile.mkstemp(prefix="lcode_cwd_")
|
|
498
501
|
os.close(fd)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: lcode-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: A local-first terminal coding agent powered by open-weight models on your own GPU or Mac, via Ollama.
|
|
5
5
|
Project-URL: Homepage, https://nasser1941.github.io/lcode/
|
|
6
6
|
Project-URL: Documentation, https://nasser1941.github.io/lcode/
|
|
@@ -73,9 +73,12 @@ through [Ollama](https://ollama.com), and when it needs current information it c
|
|
|
73
73
|
plans multi-step tasks with a visible todo list.
|
|
74
74
|
- **Long context.** 256K tokens with the default model (1M with Nemotron). You choose the window.
|
|
75
75
|
- **Hardware-aware.** Detects your NVIDIA GPU or Apple Silicon Mac and picks the best model and the
|
|
76
|
-
largest context that fits: `lcode setup` does it in one step.
|
|
76
|
+
largest context that fits: `lcode setup` does it in one step. `lcode bench` compares models on
|
|
77
|
+
real coding tasks on your machine.
|
|
77
78
|
- **Safe by default.** Every edit is shown as a diff and every command that isn't read-only needs
|
|
78
79
|
your approval. `auto-edit` and `yolo` modes when you want speed.
|
|
80
|
+
- **Undo.** lcode saves a checkpoint before the model changes files; `/undo` takes back the last
|
|
81
|
+
request's edits, new files and shell-command changes, without touching your git history.
|
|
79
82
|
- **Bring your own model.** Eight curated open-weight models, all tested end to end, or any Ollama model
|
|
80
83
|
with tool calling.
|
|
81
84
|
- **Web search when needed.** Looks up the latest versions, docs and error messages with Ollama web
|
|
@@ -123,6 +126,8 @@ lcode
|
|
|
123
126
|
| `lcode -c` / `lcode --resume` | continue the last session here / pick a saved session from a list |
|
|
124
127
|
| `lcode --model qwen3.5-9b --context 128k` | pick a model and context window for this session |
|
|
125
128
|
| `lcode models` / `lcode doctor` | what fits this machine / check the installation |
|
|
129
|
+
| `lcode bench qwen3.6-35b qwen3.5-9b` | compare models on small coding tasks on this machine |
|
|
130
|
+
| `/undo`, `/rewind` | take back the last request's file changes, or go back further |
|
|
126
131
|
| `/rename`, `/resume` | name the current session, resume a saved one |
|
|
127
132
|
| `/model`, `/context`, `/compact`, `/help` | switch model, resize the context window (pick from a list), summarize, list commands |
|
|
128
133
|
|
|
@@ -167,8 +172,6 @@ fills up. Details: [How it works](https://nasser1941.github.io/lcode/how-it-work
|
|
|
167
172
|
|
|
168
173
|
See the pinned [Roadmap issue](https://github.com/nasser1941/lcode/issues/10). Next up:
|
|
169
174
|
|
|
170
|
-
- [`/undo` and automatic checkpoints](https://github.com/nasser1941/lcode/issues/4)
|
|
171
|
-
- [`lcode bench`: score models on your own hardware](https://github.com/nasser1941/lcode/issues/5)
|
|
172
175
|
- [MCP tool servers](https://github.com/nasser1941/lcode/issues/6)
|
|
173
176
|
- [Homebrew formula](https://github.com/nasser1941/lcode/issues/8) and an [optional sandbox for shell commands](https://github.com/nasser1941/lcode/issues/9)
|
|
174
177
|
- More models in the catalog, and test reports from your hardware ([report one](https://github.com/nasser1941/lcode/issues/new?template=model_request.yml))
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
lcode/__init__.py,sha256=7co3jkJP_ri78Ap0JVyQJkT8sWh6fKXdJUCuT5A5Ab4,117
|
|
2
|
+
lcode/__main__.py,sha256=s5N5pryX2FAu93GGZ3FxUrIXHWGzxz66lKUoaV_h8Ws,35
|
|
3
|
+
lcode/agent.py,sha256=VYYGmkQi8CnP7mXgA2n_tjXnYn44uwK00j4Ow7vGKmg,25776
|
|
4
|
+
lcode/bench.py,sha256=72TSBit063ERFlzgsq2xuCSzWaCLGoZKhB3G_E5HlBM,37751
|
|
5
|
+
lcode/catalog.py,sha256=pZ1azX9OH2r4JE2c6E5OfwywpgS39-W2oXzoCHJhmtM,4141
|
|
6
|
+
lcode/checkpoints.py,sha256=eqPtmPe44-aweWqc2H21ROogwzIt3NpvcUobsaCHoGY,18354
|
|
7
|
+
lcode/cli.py,sha256=h830l_4BTgQCZULcKbMvKMV57v5g6Va0livr83vAF1E,24295
|
|
8
|
+
lcode/config.py,sha256=xkD7L5gSrHbgnXt7C8SYktNXO62BqNIXtuGyCY-y4FY,6002
|
|
9
|
+
lcode/hardware.py,sha256=2VbknZCxTZJwJUD8YWdQ7ryEQo_LcjtoOBOHOU9Y0fw,3085
|
|
10
|
+
lcode/limits.py,sha256=oJzVQoMyTZ0_Fkpu5t3qxrf9v7Hv9S8U8BRQR5M1aKA,1237
|
|
11
|
+
lcode/models.toml,sha256=lt2G64zzo_Ryxv2ISRSNZoVD_JqCqYqsM01n8WoXGs8,4098
|
|
12
|
+
lcode/ollama.py,sha256=-EB_8DKh87larG7iV0neyndPRom1Hxh4y8AAfI1Ebq8,6690
|
|
13
|
+
lcode/permissions.py,sha256=wJKwhJQx44AzjOFZCWwM4M2oUlPFUNYI2cIVfoBGGgc,3898
|
|
14
|
+
lcode/render.py,sha256=gMvf4W3qkLUJ4Vot3az_hP_zRDAItJC9pP-68dHFkfA,1375
|
|
15
|
+
lcode/repl.py,sha256=F5DsLYya5UmJt2LvJf-N_3CdBKxiK8sr7B0zNSS7gKI,26525
|
|
16
|
+
lcode/sessions.py,sha256=wOR-J0EHgJxLSPboKPHnvBcp5VTUYTj3tZWgpsa6-K4,4013
|
|
17
|
+
lcode/tools.py,sha256=0JFM-owT3K243tvMhHlcfWKSMyHSa44GY4A2GebKU0k,25935
|
|
18
|
+
lcode/web.py,sha256=vyxKbSRJTl1Lj3hj7Yd_NwTgbv0Xi6dup2YfUXjqp-Y,14579
|
|
19
|
+
lcode_cli-0.3.1.dist-info/METADATA,sha256=8sici8niZzAGQwTLMDDsOckVIbZmYB3lXZ8Cqpn7F2o,9490
|
|
20
|
+
lcode_cli-0.3.1.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
21
|
+
lcode_cli-0.3.1.dist-info/entry_points.txt,sha256=pZ_uDQ98UzVAHUQeXn5HeyQWKGSH3r3T5aPHuSB89eI,41
|
|
22
|
+
lcode_cli-0.3.1.dist-info/licenses/LICENSE,sha256=JWjmoL7nNIC1XUa-dZm2hwLUgjUQMFo6k8APb0idNzs,1074
|
|
23
|
+
lcode_cli-0.3.1.dist-info/RECORD,,
|
lcode_cli-0.2.2.dist-info/RECORD
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
lcode/__init__.py,sha256=f69CJWRNbXrayd_uWS82hWDQJcvsIH6fRtjvpXj-I8s,117
|
|
2
|
-
lcode/__main__.py,sha256=s5N5pryX2FAu93GGZ3FxUrIXHWGzxz66lKUoaV_h8Ws,35
|
|
3
|
-
lcode/agent.py,sha256=ppO9sMxymIVvFPeHS-5hqTyryQYBOK_0OAucaX6SeWU,24535
|
|
4
|
-
lcode/catalog.py,sha256=pZ1azX9OH2r4JE2c6E5OfwywpgS39-W2oXzoCHJhmtM,4141
|
|
5
|
-
lcode/cli.py,sha256=bvKv_5SGJgy8bkY-zFpXwyNACiGa6nu_n16ems_Vmq8,20103
|
|
6
|
-
lcode/config.py,sha256=ZyddgIZ9TaHAcJSW_A8o7qFQbp1s2RHmsbFzOzEjV4o,5894
|
|
7
|
-
lcode/hardware.py,sha256=2VbknZCxTZJwJUD8YWdQ7ryEQo_LcjtoOBOHOU9Y0fw,3085
|
|
8
|
-
lcode/limits.py,sha256=oJzVQoMyTZ0_Fkpu5t3qxrf9v7Hv9S8U8BRQR5M1aKA,1237
|
|
9
|
-
lcode/models.toml,sha256=lt2G64zzo_Ryxv2ISRSNZoVD_JqCqYqsM01n8WoXGs8,4098
|
|
10
|
-
lcode/ollama.py,sha256=fELwqw7xqLH9TM7XvdI1pxqYZFeIRJBv-VSz9REdvwA,6516
|
|
11
|
-
lcode/permissions.py,sha256=wJKwhJQx44AzjOFZCWwM4M2oUlPFUNYI2cIVfoBGGgc,3898
|
|
12
|
-
lcode/render.py,sha256=gMvf4W3qkLUJ4Vot3az_hP_zRDAItJC9pP-68dHFkfA,1375
|
|
13
|
-
lcode/repl.py,sha256=1InDmkMz286vuCOwRHNCTdBih_KekYkM4Ol52_g7C4s,20001
|
|
14
|
-
lcode/sessions.py,sha256=wOR-J0EHgJxLSPboKPHnvBcp5VTUYTj3tZWgpsa6-K4,4013
|
|
15
|
-
lcode/tools.py,sha256=97wPiabQuztMr4qsMgf_beNAFfraxSlU2195QJffFkg,25835
|
|
16
|
-
lcode/web.py,sha256=vyxKbSRJTl1Lj3hj7Yd_NwTgbv0Xi6dup2YfUXjqp-Y,14579
|
|
17
|
-
lcode_cli-0.2.2.dist-info/METADATA,sha256=XQ3SNVJtZ6MAxIM90xpJVSLQ17uCvulOJ00kyhSNbco,9232
|
|
18
|
-
lcode_cli-0.2.2.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
19
|
-
lcode_cli-0.2.2.dist-info/entry_points.txt,sha256=pZ_uDQ98UzVAHUQeXn5HeyQWKGSH3r3T5aPHuSB89eI,41
|
|
20
|
-
lcode_cli-0.2.2.dist-info/licenses/LICENSE,sha256=JWjmoL7nNIC1XUa-dZm2hwLUgjUQMFo6k8APb0idNzs,1074
|
|
21
|
-
lcode_cli-0.2.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|