coderouter-cli 2.7.5__py3-none-any.whl → 2.7.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.
- coderouter/adapters/agent_cli.py +591 -0
- coderouter/adapters/registry.py +6 -0
- coderouter/config/schemas.py +162 -3
- coderouter/gguf_introspect.py +19 -0
- coderouter/ingress/launcher_routes.py +215 -20
- coderouter/launcher_speculative.py +333 -0
- {coderouter_cli-2.7.5.dist-info → coderouter_cli-2.7.7.dist-info}/METADATA +1 -1
- {coderouter_cli-2.7.5.dist-info → coderouter_cli-2.7.7.dist-info}/RECORD +11 -9
- {coderouter_cli-2.7.5.dist-info → coderouter_cli-2.7.7.dist-info}/WHEEL +1 -1
- {coderouter_cli-2.7.5.dist-info → coderouter_cli-2.7.7.dist-info}/entry_points.txt +0 -0
- {coderouter_cli-2.7.5.dist-info → coderouter_cli-2.7.7.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
"""Speculative-decoding / MTP flag resolution for the llama.cpp launcher.
|
|
2
|
+
|
|
3
|
+
Why this module exists
|
|
4
|
+
======================
|
|
5
|
+
|
|
6
|
+
llama.cpp's ``llama-server`` (2026) folds Multi-Token Prediction (MTP) into
|
|
7
|
+
its speculative-decoding framework. Instead of asking the operator to hand-
|
|
8
|
+
assemble the right ``--spec-type`` / ``--model-draft`` incantation, the
|
|
9
|
+
launcher exposes two high-level knobs — ``draft_model_path`` and
|
|
10
|
+
``mtp_mode`` — and derives the concrete CLI tokens here.
|
|
11
|
+
|
|
12
|
+
Both launchers (the FastAPI web UI in
|
|
13
|
+
:mod:`coderouter.ingress.launcher_routes` and the tkinter desktop app in
|
|
14
|
+
``launcher_gui.py``) call :func:`resolve_speculative` so the decision logic
|
|
15
|
+
lives in exactly one place.
|
|
16
|
+
|
|
17
|
+
Decision summary (llama.cpp only)
|
|
18
|
+
---------------------------------
|
|
19
|
+
|
|
20
|
+
* ``mtp_mode="off"`` — never emit speculative flags (reproduces the historical
|
|
21
|
+
command exactly). Combining it with ``draft_model_path`` is a conflict.
|
|
22
|
+
* Explicit ``draft_model_path`` — validate it, then pick ``draft-mtp`` when the
|
|
23
|
+
filename looks MTP-ish (``/mtp/i``) or ``draft-simple`` otherwise.
|
|
24
|
+
* ``mtp_mode="auto"`` (the default) — inspect the main GGUF: if it embeds nextn
|
|
25
|
+
layers (``{arch}.nextn_predict_layers > 0``) use ``--spec-type draft-mtp``
|
|
26
|
+
with no separate draft model; otherwise scan the *same directory* for a
|
|
27
|
+
small companion draft/MTP gguf and wire it up if one is found.
|
|
28
|
+
|
|
29
|
+
The functions here are pure stdlib + :mod:`coderouter.gguf_introspect`; they
|
|
30
|
+
perform filesystem reads but never spawn processes and hold no FastAPI
|
|
31
|
+
dependency, which keeps them trivially unit-testable.
|
|
32
|
+
|
|
33
|
+
Security
|
|
34
|
+
--------
|
|
35
|
+
|
|
36
|
+
Every resolved path is placed into an argv list by the caller (never a shell
|
|
37
|
+
string), and ``draft_model_path`` must resolve to an existing regular file —
|
|
38
|
+
so this module adds no new shell-interpolation or path-probing surface beyond
|
|
39
|
+
reading GGUF headers the operator already pointed us at.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
from __future__ import annotations
|
|
43
|
+
|
|
44
|
+
import re
|
|
45
|
+
from pathlib import Path
|
|
46
|
+
|
|
47
|
+
from coderouter.gguf_introspect import try_read_gguf_metadata
|
|
48
|
+
|
|
49
|
+
__all__ = ["find_draft_companion", "resolve_speculative"]
|
|
50
|
+
|
|
51
|
+
_LLAMA_CPP = "llama.cpp"
|
|
52
|
+
|
|
53
|
+
# Companion candidates must be meaningfully smaller than the main model — a
|
|
54
|
+
# draft / MTP head is a fraction of the target's weights. Guards against
|
|
55
|
+
# mistaking a second full model in the same folder for a draft.
|
|
56
|
+
_COMPANION_MAX_SIZE_RATIO = 0.5
|
|
57
|
+
|
|
58
|
+
# Minimum stripped-prefix length before a shared-prefix match is trusted
|
|
59
|
+
# (avoids matching two unrelated models that merely share a short token).
|
|
60
|
+
_MIN_PREFIX_LEN = 3
|
|
61
|
+
|
|
62
|
+
# Trailing GGUF shard marker, e.g. "-00001-of-00003".
|
|
63
|
+
_SHARD_RE = re.compile(r"[-._]\d{5}-of-\d{5}$", re.IGNORECASE)
|
|
64
|
+
|
|
65
|
+
# Trailing quantisation token, e.g. "-Q4_K_M", ".IQ3_XXS", "-F16", "-BF16".
|
|
66
|
+
_QUANT_RE = re.compile(
|
|
67
|
+
r"[-._]?(i?q\d[_a-z0-9]*|bf16|fp?16|fp?32)$",
|
|
68
|
+
re.IGNORECASE,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
# Filename hint that the companion carries MTP tensors (→ draft-mtp).
|
|
72
|
+
_MTP_NAME_RE = re.compile(r"mtp", re.IGNORECASE)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _strip_quant_suffix(stem: str) -> str:
|
|
76
|
+
"""Return ``stem`` with a trailing shard marker and quant token removed.
|
|
77
|
+
|
|
78
|
+
Used to derive a model's "family prefix" so a companion sitting next to
|
|
79
|
+
``Foo-7B-Q4_K_M.gguf`` (prefix ``Foo-7B``) can be matched even though its
|
|
80
|
+
own quant/shape suffix differs.
|
|
81
|
+
"""
|
|
82
|
+
s = _SHARD_RE.sub("", stem)
|
|
83
|
+
s = _QUANT_RE.sub("", s)
|
|
84
|
+
return s
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _has_spec_type(user_tokens: list[str]) -> bool:
|
|
88
|
+
"""True if the operator already supplied ``--spec-type`` in extra args."""
|
|
89
|
+
return any(
|
|
90
|
+
tok == "--spec-type" or tok.startswith("--spec-type=")
|
|
91
|
+
for tok in user_tokens
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _has_split_mode_tensor(user_tokens: list[str]) -> bool:
|
|
96
|
+
"""True if the tokens request ``--split-mode tensor`` (either form).
|
|
97
|
+
|
|
98
|
+
llama.cpp issue #24309: a nextn-embedded model combined with tensor split
|
|
99
|
+
crashes, so callers warn (but do not block) when this pairs with emitted
|
|
100
|
+
speculative flags.
|
|
101
|
+
"""
|
|
102
|
+
for i, tok in enumerate(user_tokens):
|
|
103
|
+
if tok == "--split-mode=tensor":
|
|
104
|
+
return True
|
|
105
|
+
if (
|
|
106
|
+
tok == "--split-mode"
|
|
107
|
+
and i + 1 < len(user_tokens)
|
|
108
|
+
and user_tokens[i + 1] == "tensor"
|
|
109
|
+
):
|
|
110
|
+
return True
|
|
111
|
+
return False
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _spec_type_for_name(path: Path) -> str:
|
|
115
|
+
"""Pick ``draft-mtp`` for MTP-named files, ``draft-simple`` otherwise."""
|
|
116
|
+
return "draft-mtp" if _MTP_NAME_RE.search(path.name) else "draft-simple"
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def find_draft_companion(main_path: str | Path) -> Path | None:
|
|
120
|
+
"""Scan the directory of ``main_path`` for a companion draft/MTP gguf.
|
|
121
|
+
|
|
122
|
+
A candidate qualifies when it is a ``*.gguf`` other than the main file,
|
|
123
|
+
is smaller than :data:`_COMPANION_MAX_SIZE_RATIO` of the main file, and
|
|
124
|
+
either:
|
|
125
|
+
|
|
126
|
+
* has an ``mtp`` or ``draft`` hint in its filename, or
|
|
127
|
+
* shares the main file's family prefix (main filename with its shard /
|
|
128
|
+
quant suffix stripped).
|
|
129
|
+
|
|
130
|
+
If a candidate's GGUF ``architecture`` is readable and differs from the
|
|
131
|
+
main model's, it is dropped (tokenizer/vocab must match for speculation);
|
|
132
|
+
unreadable metadata is kept on a best-effort basis.
|
|
133
|
+
|
|
134
|
+
Candidates are ranked by name hint (``mtp`` > ``draft`` > none), then by
|
|
135
|
+
whether they share the prefix, then by smallest size. Returns the best
|
|
136
|
+
match, or ``None`` when the directory holds no suitable companion.
|
|
137
|
+
"""
|
|
138
|
+
main = Path(main_path).expanduser()
|
|
139
|
+
directory = main.parent
|
|
140
|
+
try:
|
|
141
|
+
main_size = main.stat().st_size
|
|
142
|
+
except OSError:
|
|
143
|
+
return None
|
|
144
|
+
if main_size <= 0:
|
|
145
|
+
return None
|
|
146
|
+
|
|
147
|
+
main_prefix = _strip_quant_suffix(main.stem)
|
|
148
|
+
main_meta = try_read_gguf_metadata(main)
|
|
149
|
+
main_arch = main_meta.architecture if main_meta else None
|
|
150
|
+
|
|
151
|
+
try:
|
|
152
|
+
entries = list(directory.iterdir())
|
|
153
|
+
except OSError:
|
|
154
|
+
return None
|
|
155
|
+
|
|
156
|
+
# Each ranked candidate: (name_hint, shares_prefix, -size) sorted so that
|
|
157
|
+
# the strongest hint / prefix / smallest file sorts first.
|
|
158
|
+
ranked: list[tuple[int, int, int, Path]] = []
|
|
159
|
+
for cand in entries:
|
|
160
|
+
if cand == main:
|
|
161
|
+
continue
|
|
162
|
+
if cand.suffix.lower() != ".gguf":
|
|
163
|
+
continue
|
|
164
|
+
try:
|
|
165
|
+
if not cand.is_file():
|
|
166
|
+
continue
|
|
167
|
+
size = cand.stat().st_size
|
|
168
|
+
except OSError:
|
|
169
|
+
continue
|
|
170
|
+
if size <= 0 or size >= main_size * _COMPANION_MAX_SIZE_RATIO:
|
|
171
|
+
continue
|
|
172
|
+
|
|
173
|
+
name_lower = cand.name.lower()
|
|
174
|
+
has_mtp = "mtp" in name_lower
|
|
175
|
+
has_draft = "draft" in name_lower
|
|
176
|
+
shares_prefix = (
|
|
177
|
+
len(main_prefix) >= _MIN_PREFIX_LEN
|
|
178
|
+
and cand.stem.lower().startswith(main_prefix.lower())
|
|
179
|
+
)
|
|
180
|
+
if not (has_mtp or has_draft or shares_prefix):
|
|
181
|
+
continue
|
|
182
|
+
|
|
183
|
+
# Reject a candidate whose architecture is readable and mismatches the
|
|
184
|
+
# main model — a speculator must share the target's vocabulary.
|
|
185
|
+
cand_meta = try_read_gguf_metadata(cand)
|
|
186
|
+
if (
|
|
187
|
+
cand_meta is not None
|
|
188
|
+
and cand_meta.architecture is not None
|
|
189
|
+
and main_arch is not None
|
|
190
|
+
and cand_meta.architecture != main_arch
|
|
191
|
+
):
|
|
192
|
+
continue
|
|
193
|
+
|
|
194
|
+
name_hint = 2 if has_mtp else (1 if has_draft else 0)
|
|
195
|
+
ranked.append((name_hint, int(shares_prefix), size, cand))
|
|
196
|
+
|
|
197
|
+
if not ranked:
|
|
198
|
+
return None
|
|
199
|
+
# Highest hint, then prefix match, then smallest size.
|
|
200
|
+
ranked.sort(key=lambda t: (-t[0], -t[1], t[2]))
|
|
201
|
+
return ranked[0][3]
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def resolve_speculative(
|
|
205
|
+
backend: str,
|
|
206
|
+
model_path: str,
|
|
207
|
+
draft_model_path: str | None,
|
|
208
|
+
mtp_mode: str,
|
|
209
|
+
user_tokens: list[str],
|
|
210
|
+
) -> tuple[list[str], list[str]]:
|
|
211
|
+
"""Resolve speculative-decoding / MTP CLI tokens for a launch.
|
|
212
|
+
|
|
213
|
+
Parameters
|
|
214
|
+
----------
|
|
215
|
+
backend:
|
|
216
|
+
Target backend id. Only ``"llama.cpp"`` supports speculation; other
|
|
217
|
+
backends must not receive ``draft_model_path`` / ``mtp_mode="off"``.
|
|
218
|
+
model_path:
|
|
219
|
+
The vetted main model path (already set via the launcher's dedicated
|
|
220
|
+
field). Inspected for embedded nextn layers / same-folder companions.
|
|
221
|
+
draft_model_path:
|
|
222
|
+
Optional explicit companion draft or MTP gguf. ``None`` means "not
|
|
223
|
+
supplied".
|
|
224
|
+
mtp_mode:
|
|
225
|
+
``"auto"`` (default behaviour — detect) or ``"off"`` (never emit
|
|
226
|
+
speculative flags).
|
|
227
|
+
user_tokens:
|
|
228
|
+
The flat list of option/extra-args tokens already destined for the
|
|
229
|
+
command line. Used to defer to an operator-supplied ``--spec-type``
|
|
230
|
+
and to warn about the tensor-split crash.
|
|
231
|
+
|
|
232
|
+
Returns
|
|
233
|
+
-------
|
|
234
|
+
``(spec_tokens, notes)`` where ``spec_tokens`` is the list of CLI tokens to
|
|
235
|
+
append (empty when none apply) and ``notes`` is a list of human-readable
|
|
236
|
+
strings describing what was decided (surfaced in the process log).
|
|
237
|
+
|
|
238
|
+
Raises
|
|
239
|
+
------
|
|
240
|
+
ValueError
|
|
241
|
+
On misuse — the web API maps this to HTTP 400:
|
|
242
|
+
|
|
243
|
+
* ``draft_model_path`` / ``mtp_mode="off"`` on a non-llama.cpp backend,
|
|
244
|
+
* ``mtp_mode="off"`` combined with an explicit ``draft_model_path``,
|
|
245
|
+
* an explicit ``draft_model_path`` that does not resolve to a file.
|
|
246
|
+
"""
|
|
247
|
+
notes: list[str] = []
|
|
248
|
+
|
|
249
|
+
# 1. Non-llama.cpp backends do not support speculation. Reject explicit
|
|
250
|
+
# use; otherwise (auto default, no draft) stay a silent no-op.
|
|
251
|
+
if backend != _LLAMA_CPP:
|
|
252
|
+
if draft_model_path or mtp_mode == "off":
|
|
253
|
+
raise ValueError(
|
|
254
|
+
"draft_model_path / mtp_mode are only supported for llama.cpp"
|
|
255
|
+
)
|
|
256
|
+
return [], notes
|
|
257
|
+
|
|
258
|
+
# 2. Explicit opt-out. Never emit flags; conflicting draft path is an error.
|
|
259
|
+
if mtp_mode == "off":
|
|
260
|
+
if draft_model_path:
|
|
261
|
+
raise ValueError(
|
|
262
|
+
"mtp_mode='off' conflicts with an explicit draft_model_path"
|
|
263
|
+
)
|
|
264
|
+
return [], notes
|
|
265
|
+
|
|
266
|
+
# 3. Operator already drives speculation via extra args → defer entirely.
|
|
267
|
+
if _has_spec_type(user_tokens):
|
|
268
|
+
notes.append(
|
|
269
|
+
"spec flags supplied via extra args; auto MTP detection skipped"
|
|
270
|
+
)
|
|
271
|
+
return [], notes
|
|
272
|
+
|
|
273
|
+
spec_tokens: list[str] = []
|
|
274
|
+
|
|
275
|
+
# 4. Explicit companion draft / MTP gguf.
|
|
276
|
+
if draft_model_path:
|
|
277
|
+
draft = Path(draft_model_path).expanduser()
|
|
278
|
+
if not draft.is_file():
|
|
279
|
+
raise ValueError(
|
|
280
|
+
f"draft_model_path does not exist or is not a file: {draft}"
|
|
281
|
+
)
|
|
282
|
+
spec_type = _spec_type_for_name(draft)
|
|
283
|
+
spec_tokens = ["--spec-type", spec_type, "--model-draft", str(draft)]
|
|
284
|
+
notes.append(
|
|
285
|
+
f"MTP: explicit draft model {draft.name} → --spec-type {spec_type}"
|
|
286
|
+
)
|
|
287
|
+
# 5. Auto detection (only when the main path is an existing .gguf).
|
|
288
|
+
else:
|
|
289
|
+
main = Path(model_path).expanduser()
|
|
290
|
+
if main.suffix.lower() != ".gguf" or not main.is_file():
|
|
291
|
+
notes.append(
|
|
292
|
+
"MTP auto: main model is not an existing .gguf; "
|
|
293
|
+
"skipping speculative detection"
|
|
294
|
+
)
|
|
295
|
+
else:
|
|
296
|
+
info = try_read_gguf_metadata(main)
|
|
297
|
+
if info is not None and info.n_nextn and info.n_nextn > 0:
|
|
298
|
+
# 5a. Main gguf embeds nextn/MTP tensors — no draft model needed.
|
|
299
|
+
spec_tokens = ["--spec-type", "draft-mtp"]
|
|
300
|
+
notes.append(
|
|
301
|
+
f"MTP: nextn layers ({info.n_nextn}) detected in main "
|
|
302
|
+
"gguf → --spec-type draft-mtp"
|
|
303
|
+
)
|
|
304
|
+
else:
|
|
305
|
+
# 5b. Look for a companion gguf next to the main model.
|
|
306
|
+
companion = find_draft_companion(main)
|
|
307
|
+
if companion is not None:
|
|
308
|
+
spec_type = _spec_type_for_name(companion)
|
|
309
|
+
spec_tokens = [
|
|
310
|
+
"--spec-type",
|
|
311
|
+
spec_type,
|
|
312
|
+
"--model-draft",
|
|
313
|
+
str(companion),
|
|
314
|
+
]
|
|
315
|
+
notes.append(
|
|
316
|
+
f"MTP: companion gguf {companion.name} found next to "
|
|
317
|
+
f"main → --spec-type {spec_type}"
|
|
318
|
+
)
|
|
319
|
+
else:
|
|
320
|
+
# 5c. Nothing found — start without speculative decoding.
|
|
321
|
+
notes.append(
|
|
322
|
+
f"MTP/draft gguf not found next to {main.name}; "
|
|
323
|
+
"starting without speculative decoding"
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
# 6. Warn (do not block) about the nextn + tensor-split crash.
|
|
327
|
+
if spec_tokens and _has_split_mode_tensor(user_tokens):
|
|
328
|
+
notes.append(
|
|
329
|
+
"WARNING: --split-mode tensor with speculative/nextn is known to "
|
|
330
|
+
"crash llama.cpp (issue #24309); consider --split-mode layer"
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
return spec_tokens, notes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: coderouter-cli
|
|
3
|
-
Version: 2.7.
|
|
3
|
+
Version: 2.7.7
|
|
4
4
|
Summary: Local-first, free-first, fallback-built-in LLM router. Claude Code / OpenAI compatible.
|
|
5
5
|
Project-URL: Homepage, https://github.com/zephel01/CodeRouter
|
|
6
6
|
Project-URL: Repository, https://github.com/zephel01/CodeRouter
|
|
@@ -7,23 +7,25 @@ coderouter/doctor.py,sha256=2luNk6BHSRvpQStJnHcqzNvNi-SKdOuKV0WZdorZhVk,82854
|
|
|
7
7
|
coderouter/doctor_apply.py,sha256=r_J6xbu5-HivofPNriw4_vjNYs_VRs7GsGTS0oMEX10,24209
|
|
8
8
|
coderouter/env_security.py,sha256=FEBZnXfJ0xE39kmMMn39zk0W_DRRnmcB_REmP9f4xWo,14796
|
|
9
9
|
coderouter/errors.py,sha256=Xmq67lheyw8iv3Ox39jh2c4tvNI5RcUR4QkoxVDN6l4,1130
|
|
10
|
-
coderouter/gguf_introspect.py,sha256=
|
|
10
|
+
coderouter/gguf_introspect.py,sha256=KeE00CfbYRa4gSTrzuwC6zVuHi20IzLC4nUQa98BEXI,10387
|
|
11
11
|
coderouter/hardware.py,sha256=gn3_9qbVcGRR81yKMn1lJE_8-YDRau0LxIH_M-f7pxE,8356
|
|
12
12
|
coderouter/language_tax.py,sha256=LTbE3tIfoJuV2O3T0NixRKhzq_dEOTUuPEerJv2q9uk,9360
|
|
13
|
+
coderouter/launcher_speculative.py,sha256=kWaHNmhzBsbWuM_lRGDlbWkgJ1suuxBWQNTKhJOC-yg,12644
|
|
13
14
|
coderouter/logging.py,sha256=91cveN8SCJEMNz9DGi6TrFSlc8cx0wdUkOdSLWLA-z8,56144
|
|
14
15
|
coderouter/output_filters.py,sha256=0ry_rPiS_kC-FnHgaNVP6v7e6Al2djxzu9vBzZ8kEkE,25314
|
|
15
16
|
coderouter/token_estimation.py,sha256=iz22vZEEW2P7uKLB2pYvPNpIbZGbgXRO5MtfkS_-9Sk,7531
|
|
16
17
|
coderouter/token_estimation_accurate.py,sha256=GTfzrBVnvAGjeVzmzAeUdOYZvWZKLAxcxPpFiJGlzjk,4609
|
|
17
18
|
coderouter/adapters/__init__.py,sha256=7dIDSZ-FE_0iSqLSDc_lK1idRdLTKcM2hP9tCJipgPI,463
|
|
19
|
+
coderouter/adapters/agent_cli.py,sha256=jy8u5aNacQmKMH698P_4aZYNIhjGA6xFgynGquNOzOM,24335
|
|
18
20
|
coderouter/adapters/anthropic_native.py,sha256=CT9Hitun-c3z83YHT2zZXgwZpY3_t6eRnOfAmNud2aw,23610
|
|
19
21
|
coderouter/adapters/base.py,sha256=ykKMaiIVVGr23oFFXilK2iP_YhI8-CtsEiJyFXaC9bE,10396
|
|
20
22
|
coderouter/adapters/openai_compat.py,sha256=wcrd_UpV7N6ISpUyKvdFPGU-YjCrX5oMqGpjAFEeWfg,20356
|
|
21
|
-
coderouter/adapters/registry.py,sha256=
|
|
23
|
+
coderouter/adapters/registry.py,sha256=A2LNhp70LOSNodM_iKO6EL-MBadB3kli-YPWRe1U7pQ,979
|
|
22
24
|
coderouter/config/__init__.py,sha256=FODEn74fN-qZnt4INPSHswqhOlEgpL6-_onxsitSx8g,274
|
|
23
25
|
coderouter/config/capability_registry.py,sha256=RZgzHF54dXy0CCDocRCz2ee21qXGbbgTSKTkRI9iLL4,16936
|
|
24
26
|
coderouter/config/env_file.py,sha256=CoMK27fuAXm-NtoLzXb8yN2E-wDFjHQuFwiIlmgTBQw,10356
|
|
25
27
|
coderouter/config/loader.py,sha256=FUEe8m4Tnmj_aul0vSctD8vKvNW-oLRoMRbTpSKqSmc,4077
|
|
26
|
-
coderouter/config/schemas.py,sha256
|
|
28
|
+
coderouter/config/schemas.py,sha256=-HrlEN1BkfO_Euo0m-mszQIaLupg3en6vHkqpPKTvAw,84538
|
|
27
29
|
coderouter/data/__init__.py,sha256=uNyfD9jaCvTWsBAWtaw1Fr25OSxzv3psGMfBjT1z0Cc,328
|
|
28
30
|
coderouter/data/model-capabilities.yaml,sha256=S9jt6SC6-3s2-icZ_n-a14iEMnc2yB1C2R6q-N_tZWQ,19309
|
|
29
31
|
coderouter/guards/__init__.py,sha256=5qliYBqygvVPneej7nx0uSjxDKsz7t8VzvrDgVBJlvU,1170
|
|
@@ -41,7 +43,7 @@ coderouter/ingress/__init__.py,sha256=WQsCH2CGJCAhy0mS6GSEdeYZRkkQu2OHDsP4CJWTLu
|
|
|
41
43
|
coderouter/ingress/anthropic_routes.py,sha256=1ThXzx8VgxRV7UCi3NF5ey7kbr0ADPKTXyQuYS5gK1w,27063
|
|
42
44
|
coderouter/ingress/app.py,sha256=h6s-UWsbGP22rku4pPVlvRdrtbMj4KoEEUZoQQOrTTw,19370
|
|
43
45
|
coderouter/ingress/dashboard_routes.py,sha256=1SqNNrVTfQiZcx5n2MvjAzWirittX0e61tCt-MKp4Ag,25617
|
|
44
|
-
coderouter/ingress/launcher_routes.py,sha256=
|
|
46
|
+
coderouter/ingress/launcher_routes.py,sha256=8EY3a6O_vbA45h2uhp_wc37bP_DJFqVVjsd68d_bwtk,66179
|
|
45
47
|
coderouter/ingress/metrics_routes.py,sha256=M22dwOGn24P05Ge4W3c7d7mYytSGWjIR-pPSPOAiHJY,3965
|
|
46
48
|
coderouter/ingress/openai_routes.py,sha256=TrugsQNJfNPgKKLzfT1aXzrs4emWYGE4XebEBuaZoWk,12505
|
|
47
49
|
coderouter/metrics/__init__.py,sha256=7Es351DPS7yLM0yVF_F0eesmiD83n7Zzhie44chht38,1465
|
|
@@ -67,8 +69,8 @@ coderouter/translation/__init__.py,sha256=PYXN7XVEwpG1uC8RLy6fvnGbzEZhhrEuUapH8I
|
|
|
67
69
|
coderouter/translation/anthropic.py,sha256=aZkcYH4x82b0x7efJgJb9RWn9Hbyc9pEOthXe4vjUdU,11113
|
|
68
70
|
coderouter/translation/convert.py,sha256=VV4kpu4dvLmGBmJfQnCLY5ryy_AnQcV2NuwjqRtaR8Q,52633
|
|
69
71
|
coderouter/translation/tool_repair.py,sha256=DGOKArM53yfVbIfiAveoul1vGq9NEKmjagf43Qh4IkM,57630
|
|
70
|
-
coderouter_cli-2.7.
|
|
71
|
-
coderouter_cli-2.7.
|
|
72
|
-
coderouter_cli-2.7.
|
|
73
|
-
coderouter_cli-2.7.
|
|
74
|
-
coderouter_cli-2.7.
|
|
72
|
+
coderouter_cli-2.7.7.dist-info/METADATA,sha256=BfuchYkkpXZtvCOcok0FISgazhd7eSFKD9f8qID58dI,15546
|
|
73
|
+
coderouter_cli-2.7.7.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
|
|
74
|
+
coderouter_cli-2.7.7.dist-info/entry_points.txt,sha256=-dnLfD1YZ2WjH2zSdNCvlO65wYltM9bsHt9Fhg3yGss,51
|
|
75
|
+
coderouter_cli-2.7.7.dist-info/licenses/LICENSE,sha256=wkEzoR86jFw33jvfOHjULqmkGEfxTFMgMaJnpR8mPRw,1065
|
|
76
|
+
coderouter_cli-2.7.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|