lcode-cli 0.35.1__py3-none-any.whl → 0.36.0__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/cli.py +81 -21
- lcode/repl.py +80 -31
- {lcode_cli-0.35.1.dist-info → lcode_cli-0.36.0.dist-info}/METADATA +1 -1
- {lcode_cli-0.35.1.dist-info → lcode_cli-0.36.0.dist-info}/RECORD +8 -8
- {lcode_cli-0.35.1.dist-info → lcode_cli-0.36.0.dist-info}/WHEEL +0 -0
- {lcode_cli-0.35.1.dist-info → lcode_cli-0.36.0.dist-info}/entry_points.txt +0 -0
- {lcode_cli-0.35.1.dist-info → lcode_cli-0.36.0.dist-info}/licenses/LICENSE +0 -0
lcode/__init__.py
CHANGED
lcode/cli.py
CHANGED
|
@@ -113,44 +113,96 @@ def choose_context(
|
|
|
113
113
|
# ----------------------------------------------------------------------------- lcode models
|
|
114
114
|
|
|
115
115
|
|
|
116
|
-
def print_served(
|
|
116
|
+
def print_served(
|
|
117
|
+
client: backends.OpenAICompatible, current: str | None, numbered: bool = False, out: Console | None = None
|
|
118
|
+
) -> list[str]:
|
|
119
|
+
out = out or console
|
|
117
120
|
try:
|
|
118
121
|
served = client.chat_models()
|
|
119
122
|
current = backends.pick_model(client, current) if current else None
|
|
120
123
|
except OllamaError as e:
|
|
121
124
|
if not isinstance(e, backends.BackendError) or "doesn't serve" not in str(e):
|
|
122
|
-
|
|
123
|
-
return
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
125
|
+
out.print(f"[red]{e}[/]")
|
|
126
|
+
return []
|
|
127
|
+
served = []
|
|
128
|
+
out.print(f"[bold]Models served by {escape(client.describe())}[/]")
|
|
129
|
+
for i, name in enumerate(served, 1):
|
|
130
|
+
number = f"[cyan]{i:>3}[/] " if numbered else " "
|
|
131
|
+
out.print(f"{number}{escape(name)}" + (" [bold]current[/]" if name == current else ""))
|
|
127
132
|
if not served:
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
+
out.print(" none listed")
|
|
134
|
+
if not numbered:
|
|
135
|
+
out.print(
|
|
136
|
+
"[dim]Models are downloaded and loaded in the server itself. Choose one with [/]lcode --model <id>[dim] "
|
|
137
|
+
"or [/]lcode config set model <id>[dim].[/]"
|
|
138
|
+
)
|
|
139
|
+
return served
|
|
133
140
|
|
|
134
141
|
|
|
135
|
-
def
|
|
142
|
+
def other_installed(ollama: Ollama, installed: set[str]) -> list[str]:
|
|
143
|
+
"""Installed Ollama models outside the catalog that can chat and call tools (so lcode can use them), by name.
|
|
144
|
+
Embedding models are left out: Ollama may list `tools` for them too, but not `completion`."""
|
|
145
|
+
known = {name for spec in catalog.load() for name in (spec.tag, spec.local_name)}
|
|
146
|
+
usable = []
|
|
147
|
+
for name in sorted({n.removesuffix(":latest") for n in installed} - known):
|
|
148
|
+
try:
|
|
149
|
+
capabilities = ollama.show(name).get("capabilities") or []
|
|
150
|
+
if "completion" in capabilities and "tools" in capabilities:
|
|
151
|
+
usable.append(name)
|
|
152
|
+
except OllamaError:
|
|
153
|
+
continue
|
|
154
|
+
return usable
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def model_choices(ollama: Ollama | None) -> list[str]:
|
|
158
|
+
"""What `/models` numbers, in its order: the catalog's keys, then other installed models that call tools.
|
|
159
|
+
For an OpenAI-compatible server, the models it serves."""
|
|
136
160
|
if ollama is not None and backends.is_openai(ollama):
|
|
137
|
-
|
|
138
|
-
|
|
161
|
+
try:
|
|
162
|
+
return ollama.chat_models() # type: ignore[union-attr]
|
|
163
|
+
except OllamaError:
|
|
164
|
+
return []
|
|
165
|
+
try:
|
|
166
|
+
installed = ollama.installed_names() if ollama else set()
|
|
167
|
+
except OllamaError:
|
|
168
|
+
installed = set()
|
|
169
|
+
return [spec.key for spec in catalog.load()] + (other_installed(ollama, installed) if ollama else [])
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def print_models(
|
|
173
|
+
ollama: Ollama | None,
|
|
174
|
+
hw: Hardware,
|
|
175
|
+
current: str | None = None,
|
|
176
|
+
numbered: bool = False,
|
|
177
|
+
out: Console | None = None,
|
|
178
|
+
) -> list[str]:
|
|
179
|
+
"""The models table; with `numbered`, a number on each row to pick it by. Returns the rows' names in order."""
|
|
180
|
+
out = out or console
|
|
181
|
+
if ollama is not None and backends.is_openai(ollama):
|
|
182
|
+
return print_served(ollama, current, numbered, out) # type: ignore[arg-type]
|
|
139
183
|
try:
|
|
140
184
|
installed = ollama.installed_names() if ollama else set()
|
|
141
185
|
except OllamaError:
|
|
142
186
|
installed = set()
|
|
143
187
|
rec = catalog.recommend(hw)
|
|
144
|
-
wide =
|
|
188
|
+
wide = out.width >= 130 # the descriptive columns don't fit an 80-column terminal
|
|
145
189
|
columns = ["Key", "Model", "Type", "Size", "Max ctx", "Fits here", "Speed", "Status"]
|
|
146
190
|
if not wide:
|
|
147
191
|
columns = [c for c in columns if c not in ("Model", "Type")]
|
|
192
|
+
if numbered:
|
|
193
|
+
columns.insert(0, "#")
|
|
148
194
|
table = Table(title=f"Models for this machine: {hw.describe()}", title_justify="left", header_style="bold")
|
|
149
195
|
for col in columns:
|
|
150
196
|
table.add_column(
|
|
151
|
-
col,
|
|
197
|
+
col,
|
|
198
|
+
no_wrap=col in ("#", "Key", "Size", "Max ctx", "Fits here"),
|
|
199
|
+
min_width=11 if col == "Status" else None,
|
|
200
|
+
justify="right" if col == "#" else "left",
|
|
201
|
+
style="cyan" if col == "#" else None,
|
|
152
202
|
)
|
|
203
|
+
choices: list[str] = []
|
|
153
204
|
for spec in catalog.load():
|
|
205
|
+
choices.append(spec.key)
|
|
154
206
|
ctx, speed = spec.fit(hw)
|
|
155
207
|
marks = []
|
|
156
208
|
if spec.local_name in installed or spec.tag in installed:
|
|
@@ -161,6 +213,7 @@ def print_models(ollama: Ollama | None, hw: Hardware, current: str | None = None
|
|
|
161
213
|
marks.append("[bold]current[/]")
|
|
162
214
|
marks.append("tested" if spec.tested else "[dim]untested[/]")
|
|
163
215
|
row = {
|
|
216
|
+
"#": str(len(choices)),
|
|
164
217
|
"Key": spec.key,
|
|
165
218
|
"Model": spec.name,
|
|
166
219
|
"Type": spec.params,
|
|
@@ -171,11 +224,18 @@ def print_models(ollama: Ollama | None, hw: Hardware, current: str | None = None
|
|
|
171
224
|
"Status": ", ".join(marks) if wide else "\n".join(marks),
|
|
172
225
|
}
|
|
173
226
|
table.add_row(*(row[c] for c in columns))
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
"[
|
|
177
|
-
|
|
178
|
-
|
|
227
|
+
for name in other_installed(ollama, installed) if ollama else []:
|
|
228
|
+
choices.append(name)
|
|
229
|
+
marks = ["[green]installed[/]"] + (["[bold]current[/]"] if name == current else []) + ["[dim]not in catalog[/]"]
|
|
230
|
+
row = {"#": str(len(choices)), "Key": escape(name), "Status": ", ".join(marks) if wide else "\n".join(marks)}
|
|
231
|
+
table.add_row(*(row.get(c, "") for c in columns))
|
|
232
|
+
out.print(table)
|
|
233
|
+
if not numbered:
|
|
234
|
+
out.print(
|
|
235
|
+
"[dim]Install one with [/]lcode setup <key>[dim]. 'Fits here' is the largest context that fits in memory; "
|
|
236
|
+
"choose another with --context. Any other Ollama model with tool calling also works: lcode --model <tag>[/]"
|
|
237
|
+
)
|
|
238
|
+
return choices
|
|
179
239
|
|
|
180
240
|
|
|
181
241
|
def cmd_models(args) -> None:
|
lcode/repl.py
CHANGED
|
@@ -68,8 +68,8 @@ COMMANDS = {
|
|
|
68
68
|
"/compact": "Summarize the conversation to free context (optional: what to focus on)",
|
|
69
69
|
"/context": "Show context usage and change the window size: pick from a list, or /context 128k",
|
|
70
70
|
"/ctx": "Shortcut for /context",
|
|
71
|
-
"/model": "
|
|
72
|
-
"/models": "List models and how they fit this machine",
|
|
71
|
+
"/model": "Switch model: pick a number from the list, or /model 2, /model qwen3.5-9b",
|
|
72
|
+
"/models": "List models and how they fit this machine; type a number to switch",
|
|
73
73
|
"/think": "Toggle model reasoning on/off",
|
|
74
74
|
"/verbose": "Toggle showing the model's reasoning text",
|
|
75
75
|
"/plan": "Plan before changing anything: /plan <request>, or /plan to show the approved plan",
|
|
@@ -243,14 +243,20 @@ def banner(agent: Agent) -> None:
|
|
|
243
243
|
CONTEXT_CHOICES = (16384, 32768, 65536, 131072, 262144, 524288, 1048576)
|
|
244
244
|
|
|
245
245
|
|
|
246
|
+
def model_limit(agent: Agent) -> int | None:
|
|
247
|
+
"""The largest context the model supports (what Ollama reports, else the catalog's), if known."""
|
|
248
|
+
spec = catalog.find(agent.settings.model)
|
|
249
|
+
try:
|
|
250
|
+
return agent.ollama.max_context(agent.settings.model) or (spec.max_context if spec else None)
|
|
251
|
+
except OllamaError:
|
|
252
|
+
return spec.max_context if spec else None
|
|
253
|
+
|
|
254
|
+
|
|
246
255
|
def context_options(agent: Agent, hardware: Hardware) -> list[dict]:
|
|
247
256
|
"""The context sizes this model supports, with how each one fits this machine."""
|
|
248
257
|
s = agent.settings
|
|
249
258
|
spec = catalog.find(s.model)
|
|
250
|
-
|
|
251
|
-
max_ctx = agent.ollama.max_context(s.model) or (spec.max_context if spec else None)
|
|
252
|
-
except OllamaError:
|
|
253
|
-
max_ctx = spec.max_context if spec else None
|
|
259
|
+
max_ctx = model_limit(agent)
|
|
254
260
|
sizes = {c for c in CONTEXT_CHOICES if not max_ctx or c <= max_ctx} | {s.context}
|
|
255
261
|
if max_ctx:
|
|
256
262
|
sizes.add(max_ctx)
|
|
@@ -317,6 +323,15 @@ def context_command(agent: Agent, arg: str, hardware: Hardware) -> None:
|
|
|
317
323
|
marks.append("[cyan]recommended[/]")
|
|
318
324
|
table.add_row(str(i), format_tokens(option["size"]), option["note"], ", ".join(marks))
|
|
319
325
|
c.print(table)
|
|
326
|
+
limit = model_limit(agent)
|
|
327
|
+
beyond = [size for size in CONTEXT_CHOICES if limit and size > limit]
|
|
328
|
+
if beyond:
|
|
329
|
+
sizes = " and ".join(format_tokens(size) for size in beyond[:2])
|
|
330
|
+
c.print(
|
|
331
|
+
f"[dim]Not offered: {sizes}{' and more' if len(beyond) > 2 else ''}. {s.model} was trained on up to "
|
|
332
|
+
f"{format_tokens(limit)} tokens, and Ollama caps the window there whatever the memory, so a larger "
|
|
333
|
+
"setting would only look larger.[/]"
|
|
334
|
+
)
|
|
320
335
|
try:
|
|
321
336
|
answer = input(f" Choose a number, a size like 96k, or press Enter to keep {format_tokens(s.context)}: ")
|
|
322
337
|
except EOFError:
|
|
@@ -809,6 +824,63 @@ def restore_checkpoint(agent: Agent, target: Checkpoint, rewind: bool) -> None:
|
|
|
809
824
|
agent.save()
|
|
810
825
|
|
|
811
826
|
|
|
827
|
+
def model_command(agent: Agent, arg: str, hardware: Hardware) -> None:
|
|
828
|
+
"""/models and /model: the numbered list to pick from, or straight to a number or a name (/model 2)."""
|
|
829
|
+
from lcode.cli import model_choices, print_models
|
|
830
|
+
|
|
831
|
+
c, s = agent.console, agent.settings
|
|
832
|
+
if arg and not arg.isdigit():
|
|
833
|
+
switch_model(agent, arg, hardware)
|
|
834
|
+
return
|
|
835
|
+
if arg:
|
|
836
|
+
choices = model_choices(agent.ollama)
|
|
837
|
+
else:
|
|
838
|
+
choices = print_models(agent.ollama, hardware, s.model, numbered=True, out=c)
|
|
839
|
+
if not choices:
|
|
840
|
+
return
|
|
841
|
+
try:
|
|
842
|
+
answer = input(f" Switch to which model? (number or name, Enter to keep {s.model}): ").strip()
|
|
843
|
+
except EOFError:
|
|
844
|
+
return
|
|
845
|
+
if not answer:
|
|
846
|
+
c.print(f"Keeping {s.model}.")
|
|
847
|
+
return
|
|
848
|
+
arg = answer
|
|
849
|
+
if arg.isdigit():
|
|
850
|
+
if not 1 <= int(arg) <= len(choices):
|
|
851
|
+
c.print(f"[red]There's no model {arg} in the list: choose 1 to {len(choices)}.[/]")
|
|
852
|
+
return
|
|
853
|
+
arg = choices[int(arg) - 1]
|
|
854
|
+
switch_model(agent, arg, hardware)
|
|
855
|
+
|
|
856
|
+
|
|
857
|
+
def switch_model(agent: Agent, wanted: str, hardware: Hardware) -> None:
|
|
858
|
+
"""Switch to a catalog key or an installed model, and size the context for it."""
|
|
859
|
+
from lcode.cli import NotInstalled, resolve_model
|
|
860
|
+
|
|
861
|
+
c, s = agent.console, agent.settings
|
|
862
|
+
try:
|
|
863
|
+
name, spec = resolve_model(agent.ollama, wanted)
|
|
864
|
+
except (NotInstalled, OllamaError) as e:
|
|
865
|
+
c.print(f"[red]{e}[/]")
|
|
866
|
+
return
|
|
867
|
+
if name == s.model:
|
|
868
|
+
c.print(f"Already using {name} (context {format_tokens(s.context)}).")
|
|
869
|
+
return
|
|
870
|
+
s.model = name
|
|
871
|
+
s.num_batch = spec.num_batch if spec and name == spec.local_name else None
|
|
872
|
+
if spec: # size the context for the new model: largest window that fits this machine
|
|
873
|
+
s.context = limits.cap(name, spec.fit(hardware)[0] or MIN_USEFUL_CONTEXT)
|
|
874
|
+
elif backends.is_openai(agent.ollama):
|
|
875
|
+
s.context = backends.context_for(agent.ollama, name, None)[0] # the server's window
|
|
876
|
+
agent._vision = False # the model that looks at images goes with the model: decide again
|
|
877
|
+
agent.messages[0]["content"] = agent.system_prompt()
|
|
878
|
+
c.print(f"[green]Switched to {name}[/] (context {format_tokens(s.context)}).")
|
|
879
|
+
warning = residency.dense_warning(agent.ollama, name, s.context, hardware)
|
|
880
|
+
if warning:
|
|
881
|
+
agent.say(warning, warning=True)
|
|
882
|
+
|
|
883
|
+
|
|
812
884
|
def apply_context(agent: Agent, size: int, hardware: Hardware) -> None:
|
|
813
885
|
c, s = agent.console, agent.settings
|
|
814
886
|
if size == s.context:
|
|
@@ -956,8 +1028,6 @@ def session_start(agent: Agent) -> None:
|
|
|
956
1028
|
|
|
957
1029
|
def handle_command(agent: Agent, line: str, hardware: Hardware) -> bool:
|
|
958
1030
|
"""Run a slash command. Returns False when the REPL should exit."""
|
|
959
|
-
from lcode.cli import NotInstalled, print_models, resolve_model
|
|
960
|
-
|
|
961
1031
|
cmd, _, arg = line.partition(" ")
|
|
962
1032
|
arg = arg.strip()
|
|
963
1033
|
c, s = agent.console, agent.settings
|
|
@@ -1006,29 +1076,8 @@ def handle_command(agent: Agent, line: str, hardware: Hardware) -> bool:
|
|
|
1006
1076
|
agent.compact(arg)
|
|
1007
1077
|
elif cmd in ("/context", "/ctx"):
|
|
1008
1078
|
context_command(agent, arg, hardware)
|
|
1009
|
-
elif cmd
|
|
1010
|
-
|
|
1011
|
-
elif cmd == "/model":
|
|
1012
|
-
if not arg:
|
|
1013
|
-
c.print(f"Model: {s.model}. Switch with /model <name>; list with /models.")
|
|
1014
|
-
else:
|
|
1015
|
-
try:
|
|
1016
|
-
name, spec = resolve_model(agent.ollama, arg)
|
|
1017
|
-
except (NotInstalled, OllamaError) as e:
|
|
1018
|
-
c.print(f"[red]{e}[/]")
|
|
1019
|
-
return True
|
|
1020
|
-
s.model = name
|
|
1021
|
-
s.num_batch = spec.num_batch if spec and name == spec.local_name else None
|
|
1022
|
-
if spec: # size the context for the new model: largest window that fits this machine
|
|
1023
|
-
s.context = limits.cap(name, spec.fit(hardware)[0] or MIN_USEFUL_CONTEXT)
|
|
1024
|
-
elif backends.is_openai(agent.ollama):
|
|
1025
|
-
s.context = backends.context_for(agent.ollama, name, None)[0] # the server's window
|
|
1026
|
-
agent._vision = False # the model that looks at images goes with the model: decide again
|
|
1027
|
-
agent.messages[0]["content"] = agent.system_prompt()
|
|
1028
|
-
c.print(f"[green]Switched to {name}[/] (context {format_tokens(s.context)}).")
|
|
1029
|
-
warning = residency.dense_warning(agent.ollama, name, s.context, hardware)
|
|
1030
|
-
if warning:
|
|
1031
|
-
agent.say(warning, warning=True)
|
|
1079
|
+
elif cmd in ("/models", "/model"):
|
|
1080
|
+
model_command(agent, arg, hardware)
|
|
1032
1081
|
elif cmd == "/think":
|
|
1033
1082
|
s.think = (arg == "on") if arg in ("on", "off") else not s.think
|
|
1034
1083
|
c.print(f"Reasoning {'on' if s.think else 'off'}.")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: lcode-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.36.0
|
|
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/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
lcode/__init__.py,sha256=
|
|
1
|
+
lcode/__init__.py,sha256=yGzk6CSXaFMumjYybvLVXP6ECcm-RN4YJ77pJlK1FWw,473
|
|
2
2
|
lcode/__main__.py,sha256=s5N5pryX2FAu93GGZ3FxUrIXHWGzxz66lKUoaV_h8Ws,35
|
|
3
3
|
lcode/acp.py,sha256=d97VV3sbqXdWKhPQQNbYRaDTm8WrUk0mGbDLiOyX7jE,29058
|
|
4
4
|
lcode/action.py,sha256=wuT5F9EJCdEligPeytzmEi8FpahWBhXer528tpuTj_k,16711
|
|
@@ -11,7 +11,7 @@ lcode/bench_runtime.py,sha256=EjzNgIvUkdbT8cbSy1TpmlyeIk6e-ipjlDFpM7Dnqx0,6835
|
|
|
11
11
|
lcode/catalog.py,sha256=pZ1azX9OH2r4JE2c6E5OfwywpgS39-W2oXzoCHJhmtM,4141
|
|
12
12
|
lcode/checkpoints.py,sha256=eqPtmPe44-aweWqc2H21ROogwzIt3NpvcUobsaCHoGY,18354
|
|
13
13
|
lcode/checks.py,sha256=iPaNaGOGo7zHc_mue41ELEHSNq0VIH_xVYL_bHkYLXU,9373
|
|
14
|
-
lcode/cli.py,sha256=
|
|
14
|
+
lcode/cli.py,sha256=vtrGb1A_Jnxulu-L0nac01ARdQ8dyxZI4fapb-0G2N4,44703
|
|
15
15
|
lcode/clipboard.py,sha256=nTSdJyCXPdtjH947RjvB3QvRqnL5HZsS9KB8EkC42cc,5138
|
|
16
16
|
lcode/codesearch.py,sha256=Io8leN1nb_Y-Dvlm9xaGtwUWYXX-ooswuznJV6dGU1s,10766
|
|
17
17
|
lcode/config.py,sha256=hAjuHg7plRxwFgdD4gOGnDH8-FwyT7NRV0YI5grd0qE,12604
|
|
@@ -34,7 +34,7 @@ lcode/permissions.py,sha256=q7CjDsc_Xrblw7t3_BbxA5LUjxFSswGs1RiJmtMi0po,12288
|
|
|
34
34
|
lcode/planning.py,sha256=Q2upaoZPnXDMQT2F-ETxX1lk_wDntTzhSKNVYIQSoQA,6540
|
|
35
35
|
lcode/render.py,sha256=gMvf4W3qkLUJ4Vot3az_hP_zRDAItJC9pP-68dHFkfA,1375
|
|
36
36
|
lcode/repeats.py,sha256=vpXR5pzKX9GsTzQONGS30V-rEU3gunaj_hBzJxg43Q4,5542
|
|
37
|
-
lcode/repl.py,sha256=
|
|
37
|
+
lcode/repl.py,sha256=2i_EDAsXxQ9OxXyWiuPGtIY4pLO3lQW4_SulITcThkM,56548
|
|
38
38
|
lcode/repomap.py,sha256=1GRJgEUjBl9XHSXsF7tSGXBCEgsY-3CzwMohaTudZ_M,13969
|
|
39
39
|
lcode/residency.py,sha256=bDB2J0SZULDOz6wYuMCnkjacYk7pWi5f75iY83ycAXQ,6912
|
|
40
40
|
lcode/review.py,sha256=0QBIS-R1B2b3zqx5TcC1qZptpKBbrDhYvMKSNCaDAUo,4686
|
|
@@ -65,8 +65,8 @@ lcode/servers/__init__.py,sha256=qrIhxEodEB8cjKEQ4Cicc0GsQhE2OH-9qlVHzr3-tq8,77
|
|
|
65
65
|
lcode/servers/encord.py,sha256=WSauawL1UKYZCUAG1oalcKL_An3DVof-JM6xIgFyQSE,12769
|
|
66
66
|
lcode/servers/valohai.py,sha256=e5xZGIoa4cja4f5i85q1GpL9c7cglUjV8jN2co1CFMY,14430
|
|
67
67
|
lcode/servers/xai.py,sha256=h2emAvHSnkuB9WmJInlynsDhvxJwNVD2AHFX7vqMXNc,13627
|
|
68
|
-
lcode_cli-0.
|
|
69
|
-
lcode_cli-0.
|
|
70
|
-
lcode_cli-0.
|
|
71
|
-
lcode_cli-0.
|
|
72
|
-
lcode_cli-0.
|
|
68
|
+
lcode_cli-0.36.0.dist-info/METADATA,sha256=kp6gDSBL_DtXIWYn7FRO6CpzOf8t-dQPMOwpCQ_4trU,13141
|
|
69
|
+
lcode_cli-0.36.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
70
|
+
lcode_cli-0.36.0.dist-info/entry_points.txt,sha256=Hxsn_itbnbgft3U0FwxWdmEt0yoAV2LB-nJDnL9WT20,172
|
|
71
|
+
lcode_cli-0.36.0.dist-info/licenses/LICENSE,sha256=JWjmoL7nNIC1XUa-dZm2hwLUgjUQMFo6k8APb0idNzs,1074
|
|
72
|
+
lcode_cli-0.36.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|