mirror of
https://github.com/unslothai/unsloth.git
synced 2026-10-19 08:54:21 +00:00
Fix main CI: rewind and Skills strings, token count harness, deep research contract, zoo 2026.10.5 scan baseline (#13701)
* Studio i18n: move the Italian rewind filesNotRestored string into rewind #13676 added it under settings.data.library, so the overlay parity check in Frontend CI fails with an overlay key missing from en. * Tests: lift arrow-function consts like functions in the node harness resolver #13687 added const skillsForTools = () => ..., which reads the zustand Skills switch store. The resolver treated it as an eagerly evaluated const and dropped it because the store cannot be lifted, so the token count parity harness failed with ReferenceError: skillsForTools is not defined. An arrow or function expression reads its references only when called. The parity harness also gets a stand-in Skills switch store. * Baseline the unsloth-zoo 2026.10.5 findings after review Five pinned zoo sites moved digest in 2026.10.5. Four have the same matched code; speculative.py adds two mx.eval calls (MLX array evaluation). The rest of each file's 2026.10.4 to 2026.10.5 diff adds no network, exec or process code. * Studio i18n: translate skills.turnOff in every overlay #13687 added the Skills switch's Turn off skills label in en only, so the strict overlay check in Frontend CI fails with it missing from all 13. * Tests: follow the keyed + menu in the deep research contract #13679 builds the chat + menu from a keyed list, so the one-shot gate is now deepResearch: researchAvailable ? ( ... ) : null. * Tests: shorten the deep research contract comment
This commit is contained in:
parent
3822d7046e
commit
eb49b6f8b8
18 changed files with 90 additions and 4 deletions
|
|
@ -2562,6 +2562,51 @@
|
|||
"evidence": "Obfusc: L338: exec(compile(cached_bytes, cache_file, \"exec\"), module.__dict__)\nExec: L338: exec(compile(cached_bytes, cache_file, \"exec\"), module.__dict__)",
|
||||
"evidence_hash": "ef22a4fe0d8ec7e2b0e4afc6e6a3d997cd94c981bf59790562217d4f9dd70732",
|
||||
"file_sha256": "24bcbf0d36a0850fde3f5cddf303c31e24d93394ff0f6d71494370d41533e50e"
|
||||
},
|
||||
{
|
||||
"package": "unsloth-zoo",
|
||||
"file": "unsloth_zoo/vllm_utils.py",
|
||||
"check": "Advanced obfuscation (marshal/compile/zlib) + exec/eval",
|
||||
"severity": "HIGH",
|
||||
"evidence": "Obfusc: L4472: lora_types.append(getattr(__import__(module_path, fromlist = [class_name]), class_name))\nExec: L1357: cross_attn_layer = eval(f'vllm_internals.{name}') | L1402: layernorm = eval(vllm_name).state_dict()[\"weight\"] | L1924: parent = eval(f\"new_model.{parent_path}\") if parent_path else new_model | L1930: exec(f\"new_model.{layer_name_br} = layer\") | L2001: exec(f\"new_model.{layer_name_br}.weight = None\") | L2002: exec(f\"new_model.{layer_name_br}.weight = weight_param\") | L2004: exec(f\"new_model.{layer_name_br}.bias = None\") | L2005: exec(f\"new_model.{layer_name_br}.bias = bias\") | L2011: exec(f\"new_model.{layer_name} = layer\") | L2043: new_model.eval() | L4279: exec(f\"module.to({dtype})\") | L4302: exec(f\"module.to({dtype})\") | L5961: model.eval() | L6001: new_model.eval()",
|
||||
"evidence_hash": "4928e730b84a3fa71dcc50cfe185c77c2028be09ad908706710ab864786b4659",
|
||||
"file_sha256": "88134b230d81ec499927d5355b90a32315cf94cb282021f462251ee44578fcd3"
|
||||
},
|
||||
{
|
||||
"package": "unsloth-zoo",
|
||||
"file": "unsloth_zoo/mlx/decision.py",
|
||||
"check": "Advanced obfuscation (marshal/compile/zlib) + exec/eval",
|
||||
"severity": "HIGH",
|
||||
"evidence": "Obfusc: L382: with av.open(io.BytesIO(base64.b64decode(url.partition(\",\")[2], validate = True))) as container: sha256:946796d261fb90a0f7ad5f482b39026735f161d8d6877aa38112583f98acf957\nExec: L248: mx.eval(out) | L283: model.eval() | L284: mx.eval(model.parameters()) | L799: model.eval() | L800: mx.eval(model.parameters()) | L831: mx.eval(decoder.parameters()) | L1023: self.model.eval() | L1032: mx.eval(self.model.parameters()) | L1090: mx.eval(head, [entry.state for entry in cache]) | L1489: head.eval() | L1490: mx.eval(head.parameters()) | L1589: mx.eval(self.head.parameters()) | L1590: self.head.eval() | L2230: mx.eval(x) | L2242: mx.eval(loss, grads, cotangent) | L2250: mx.eval(stage_grads, cotangent) | L2340: mx.eval(model.parameters()) | L2381: mx.eval(self.parameters()) | L2407: mx.eval(logits) | L2547: mx.eval(total, grads) | L2574: network.eval() | L2651: model.eval()",
|
||||
"evidence_hash": "e247443dfea5b48389857add89110a17e97c5226b7b8cd3c6bce68309d6e2c9d",
|
||||
"file_sha256": "d83445bf7066c573bc8fa568a9fbafee4d5bf8a0aa3eaf6cac6bfdeeb40f95df"
|
||||
},
|
||||
{
|
||||
"package": "unsloth-zoo",
|
||||
"file": "unsloth_zoo/mlx/loader.py",
|
||||
"check": "Advanced obfuscation (marshal/compile/zlib) + exec/eval",
|
||||
"severity": "HIGH",
|
||||
"evidence": "Obfusc: L5297: _mod = __import__(module_name, fromlist=[\"_\"])\nExec: L163: mx.eval(model.parameters()) | L197: mx.eval([v for k, v in tree_flatten(casted) if is_mlx_norm_parameter_path(k)]) | L1491: mx.eval(model.parameters()) | L1492: mx.eval(mx.distributed.all_sum(mx.array(1.0), stream=mx.cpu)) | L1559: mx.eval(model.parameters()) | L1562: mx.eval(mx.distributed.all_sum(mx.array(1.0), stream=mx.cpu)) | L2991: mx.eval(altup.correct(predictions, activated)) | L3463: model.eval() | L3540: mx.eval(baseline, perturbed) | L4945: model.eval() | L5702: mx.eval(model.parameters()) | L5818: mx.eval(module.weight) | L8423: mx.eval(model.parameters()) | L8440: mx.eval(target.parameters()) | L9440: lambda: mx.eval(model.parameters()), | L9504: lambda: mx.eval(model.parameters()), | L9667: mx.eval(model.parameters())",
|
||||
"evidence_hash": "d1c32d6d0a0f4625af70ef11ce765a893c07f48e54c21fb8ff5ef43381daf18e",
|
||||
"file_sha256": "171e445ef608e624f86b538b0fac15628d9f35338c8424f79988b24354009aec"
|
||||
},
|
||||
{
|
||||
"package": "unsloth-zoo",
|
||||
"file": "unsloth_zoo/mlx/speculative.py",
|
||||
"check": "Advanced obfuscation (marshal/compile/zlib) + exec/eval",
|
||||
"severity": "HIGH",
|
||||
"evidence": "Obfusc: L835: module = __import__(f\"mlx_vlm.models.{family}.language\", fromlist = [\"LanguageModel\"])\nExec: L1044: mx.eval(drafts) | L1068: mx.eval([array for pair in drawn for array in pair if array is not None] + ([] if drafts is None else [drafts])) | L1343: mx.eval(parts[-1]) | L1345: mx.eval(self._scan) | L1838: mx.eval(model.parameters())",
|
||||
"evidence_hash": "64b95579c569b39eddc493ac6b808258094d9b1d62154c55ae9c224c80577e45",
|
||||
"file_sha256": "29edc582762bcde4f88e36af0f04a0c652c6e0c1c0e3a06f3d354d211d7ae51c"
|
||||
},
|
||||
{
|
||||
"package": "unsloth-zoo",
|
||||
"file": "unsloth_zoo/temporary_patches/moe_utils.py",
|
||||
"check": "Advanced obfuscation (marshal/compile/zlib) + exec/eval",
|
||||
"severity": "HIGH",
|
||||
"evidence": "Obfusc: L338: exec(compile(cached_bytes, cache_file, \"exec\"), module.__dict__)\nExec: L338: exec(compile(cached_bytes, cache_file, \"exec\"), module.__dict__)",
|
||||
"evidence_hash": "ef22a4fe0d8ec7e2b0e4afc6e6a3d997cd94c981bf59790562217d4f9dd70732",
|
||||
"file_sha256": "86f4fe7b9a8e5973951eaa5ce70e2c0b4823c1e6bf9e54487f8be41c6fa2ee2d"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3984,6 +3984,7 @@ export const ar = {
|
|||
discard: "تجاهل",
|
||||
mentions: "المهارات",
|
||||
manage: "إدارة المهارات",
|
||||
turnOff: "إيقاف المهارات",
|
||||
bulkActions: "إجراءات المهارات",
|
||||
enableAll: "تفعيل الكل",
|
||||
disableAll: "تعطيل الكل",
|
||||
|
|
|
|||
|
|
@ -4057,6 +4057,7 @@ export const de = {
|
|||
discard: "Verwerfen",
|
||||
mentions: "Fähigkeiten",
|
||||
manage: "Fähigkeiten verwalten",
|
||||
turnOff: "Fähigkeiten ausschalten",
|
||||
bulkActions: "Fähigkeiten-Aktionen",
|
||||
enableAll: "Alle aktivieren",
|
||||
disableAll: "Alle deaktivieren",
|
||||
|
|
|
|||
|
|
@ -4056,6 +4056,7 @@ export const es = {
|
|||
discard: "Descartar",
|
||||
mentions: "Habilidades",
|
||||
manage: "Gestionar habilidades",
|
||||
turnOff: "Desactivar habilidades",
|
||||
bulkActions: "Acciones de habilidades",
|
||||
enableAll: "Activar todas",
|
||||
disableAll: "Desactivar todas",
|
||||
|
|
|
|||
|
|
@ -4068,6 +4068,7 @@ export const fr = {
|
|||
discard: "Abandonner",
|
||||
mentions: "Compétences",
|
||||
manage: "Gérer les compétences",
|
||||
turnOff: "Désactiver les compétences",
|
||||
bulkActions: "Actions sur les compétences",
|
||||
enableAll: "Tout activer",
|
||||
disableAll: "Tout désactiver",
|
||||
|
|
|
|||
|
|
@ -4098,6 +4098,7 @@ export const he = {
|
|||
discard: "ביטול שינויים",
|
||||
mentions: "מיומנויות",
|
||||
manage: "ניהול מיומנויות",
|
||||
turnOff: "כיבוי מיומנויות",
|
||||
bulkActions: "פעולות מיומנויות",
|
||||
enableAll: "הפעל הכול",
|
||||
disableAll: "השבת הכול",
|
||||
|
|
|
|||
|
|
@ -3993,6 +3993,7 @@ export const hi = {
|
|||
discard: "छोड़ें",
|
||||
mentions: "कौशल",
|
||||
manage: "कौशल प्रबंधित करें",
|
||||
turnOff: "कौशल बंद करें",
|
||||
bulkActions: "कौशल क्रियाएँ",
|
||||
enableAll: "सभी चालू करें",
|
||||
disableAll: "सभी बंद करें",
|
||||
|
|
|
|||
|
|
@ -2782,7 +2782,6 @@ export const it = {
|
|||
working: "Elaborazione...",
|
||||
loadFailed: "Impossibile caricare gli elementi archiviati",
|
||||
loadMoreFailed: "Impossibile caricare altri elementi archiviati",
|
||||
filesNotRestored: "{count} file modificati non possono essere ripristinati e restano come sono.",
|
||||
restoreFailed: "Impossibile ripristinare gli elementi selezionati",
|
||||
deleteFailed: "Impossibile eliminare gli elementi selezionati",
|
||||
projectsFailed: "Impossibile caricare i progetti archiviati",
|
||||
|
|
@ -3155,6 +3154,7 @@ export const it = {
|
|||
restoredMany: "{count} file ripristinati",
|
||||
nothingRestored: "Nessun file da ripristinare",
|
||||
skippedCount: "{count} saltati",
|
||||
filesNotRestored: "{count} file modificati non possono essere ripristinati e restano come sono.",
|
||||
restoreFailed: "Impossibile ripristinare i file",
|
||||
undo: "Annulla",
|
||||
undone: "Ripristino dei file annullato",
|
||||
|
|
@ -4058,6 +4058,7 @@ export const it = {
|
|||
discard: "Scarta",
|
||||
mentions: "Competenze",
|
||||
manage: "Gestisci competenze",
|
||||
turnOff: "Disattiva competenze",
|
||||
bulkActions: "Azioni sulle competenze",
|
||||
enableAll: "Attiva tutte",
|
||||
disableAll: "Disattiva tutte",
|
||||
|
|
|
|||
|
|
@ -3932,6 +3932,7 @@ export const ja = {
|
|||
discard: "破棄",
|
||||
mentions: "スキル",
|
||||
manage: "スキルを管理",
|
||||
turnOff: "スキルをオフにする",
|
||||
bulkActions: "スキルの操作",
|
||||
enableAll: "すべて有効にする",
|
||||
disableAll: "すべて無効にする",
|
||||
|
|
|
|||
|
|
@ -3975,6 +3975,7 @@ export const ko = {
|
|||
discard: "버리기",
|
||||
mentions: "스킬",
|
||||
manage: "스킬 관리",
|
||||
turnOff: "스킬 끄기",
|
||||
bulkActions: "스킬 작업",
|
||||
enableAll: "모두 사용",
|
||||
disableAll: "모두 사용 안 함",
|
||||
|
|
|
|||
|
|
@ -4016,6 +4016,7 @@ export const ptBR = {
|
|||
discard: "Descartar",
|
||||
mentions: "Habilidades",
|
||||
manage: "Gerenciar habilidades",
|
||||
turnOff: "Desativar habilidades",
|
||||
bulkActions: "Ações de habilidades",
|
||||
enableAll: "Ativar todas",
|
||||
disableAll: "Desativar todas",
|
||||
|
|
|
|||
|
|
@ -4012,6 +4012,7 @@ export const ru = {
|
|||
discard: "Отменить",
|
||||
mentions: "Навыки",
|
||||
manage: "Управлять навыками",
|
||||
turnOff: "Отключить навыки",
|
||||
bulkActions: "Действия с навыками",
|
||||
enableAll: "Включить все",
|
||||
disableAll: "Отключить все",
|
||||
|
|
|
|||
|
|
@ -4233,6 +4233,7 @@ export const sv = {
|
|||
discard: "Ignorera",
|
||||
mentions: "Färdigheter",
|
||||
manage: "Hantera färdigheter",
|
||||
turnOff: "Stäng av färdigheter",
|
||||
bulkActions: "Färdighetsåtgärder",
|
||||
enableAll: "Aktivera alla",
|
||||
disableAll: "Inaktivera alla",
|
||||
|
|
|
|||
|
|
@ -3889,6 +3889,7 @@ export const zhCN = {
|
|||
discard: "放弃",
|
||||
mentions: "技能",
|
||||
manage: "管理技能",
|
||||
turnOff: "关闭技能",
|
||||
bulkActions: "技能操作",
|
||||
enableAll: "全部启用",
|
||||
disableAll: "全部停用",
|
||||
|
|
|
|||
|
|
@ -45,6 +45,11 @@ _REEXPORT_RE = re.compile(
|
|||
# Initialisers a `const` may carry and still be safe to lift: literals and callables.
|
||||
# Anything else (a store built by `create(...)`, a client instantiated at import time) is
|
||||
# module setup rather than a helper, so it is refused instead of executed in the harness.
|
||||
# A `const` bound to a function expression runs nothing until it is called, like a `function`.
|
||||
_FUNCTION_DECL_RE = re.compile(
|
||||
r"^(?:export\s+)?(?:const|let|var)\s+[A-Za-z_$][\w$]*\s*=\s*"
|
||||
r"(?:async\s+function\b|function\b|(?:async\s*)?(?:\([^()]*\)|[A-Za-z_$][\w$]*)\s*=>)"
|
||||
)
|
||||
_SAFE_INIT_RE = re.compile(
|
||||
r"^(?:/|[\"'`]|\d|\[|\{|!|new\s+(?:Set|Map|RegExp|Date)\b"
|
||||
r"|async\s+function\b|function\b|async\s*\(|\(|[A-Za-z_$][\w$]*\s*(?:=>|;))"
|
||||
|
|
@ -516,8 +521,11 @@ def resolve_dependencies(
|
|||
# A name this module really does resolve, so failing to follow it matters.
|
||||
wanted.add(reference)
|
||||
pull(reference, origin)
|
||||
kind = home.kind(name) or "const"
|
||||
if _FUNCTION_DECL_RE.match(text.lstrip()):
|
||||
kind = "function"
|
||||
pulled[name] = (
|
||||
home.kind(name) or "const",
|
||||
kind,
|
||||
f"// sliced from {home.path.name}\n" + re.sub(r"^export\s+", "", text, count = 1),
|
||||
wanted,
|
||||
)
|
||||
|
|
@ -531,7 +539,8 @@ def resolve_dependencies(
|
|||
# A declaration evaluated at import time cannot be left half-resolved: `const A = [B]` with `B` refused crashes the
|
||||
# whole harness on load, which is worse than the lazy ReferenceError it replaced. Drop those to a fixed point
|
||||
# instead. Functions and types are lazy or erased, so an unfollowed reference in one costs nothing until it is
|
||||
# called. A fixture the harness defines does not rescue one either: the fixtures sit BELOW this block, so reading
|
||||
# called, and so is a `const` bound to an arrow or function expression. A fixture the harness defines does not
|
||||
# rescue one either: the fixtures sit BELOW this block, so reading
|
||||
# one from here is a TDZ error rather than a resolution.
|
||||
eager = {"const", "let", "var", "class"}
|
||||
while True:
|
||||
|
|
|
|||
|
|
@ -347,7 +347,8 @@ def test_research_is_one_shot_per_thread_without_disabling_normal_chat() -> None
|
|||
assert "runtime.setDeepResearchEnabled(false)" in adapter
|
||||
assert "effectiveDeepResearchEnabled" in thread
|
||||
assert "researchAvailable={!researchUsed}" in thread
|
||||
assert "{researchAvailable ? (" in thread
|
||||
# #13679: the + menu is a keyed list.
|
||||
assert "deepResearch: researchAvailable ? (" in thread
|
||||
assert "setToolsEnabled" in thread
|
||||
assert "Web search" in thread
|
||||
|
||||
|
|
|
|||
|
|
@ -134,6 +134,21 @@ def test_a_pulled_const_that_needs_a_fixture_is_dropped_not_emitted(tmp_path):
|
|||
assert "const HEADERS" not in resolved.replace("const used = HEADERS;", "")
|
||||
|
||||
|
||||
def test_a_pulled_arrow_const_is_kept_like_a_function(tmp_path):
|
||||
"""An arrow const reads its references only when called, so one it cannot follow is fine."""
|
||||
module = tmp_path / "src" / "m.ts"
|
||||
module.parent.mkdir(parents = True)
|
||||
module.write_text(
|
||||
'import { store } from "./store";\n'
|
||||
"const pick = () =>\n store.getState().on === false ? [] : [1];\n"
|
||||
"export function count() {\n return pick().length;\n}\n"
|
||||
)
|
||||
(module.parent / "store.ts").write_text("export const store = create(() => ({ on: null }));\n")
|
||||
resolved = resolve_dependencies("const used = count();\n", (module,), root = tmp_path / "src")
|
||||
assert "const pick = () =>" in resolved
|
||||
assert "create(" not in resolved
|
||||
|
||||
|
||||
def test_a_destructured_fixture_is_not_declared_twice(tmp_path):
|
||||
"""``const { only, ...rest } = ...`` is a binding a declaration regex does not see."""
|
||||
module = tmp_path / "src" / "m.ts"
|
||||
|
|
|
|||
|
|
@ -123,6 +123,9 @@ const state: any = {
|
|||
|
||||
const useChatRuntimeStore: any = { getState: () => state };
|
||||
const useBrowserAgentStore: any = { getState: () => state.browserAgent };
|
||||
// The composer's Skills switch (#13687), unset as on a fresh install: skillsForTools() then
|
||||
// offers the skill snapshot, the same list the request reads.
|
||||
const useSkillsSwitchStore: any = { getState: () => ({ on: null }) };
|
||||
|
||||
// Browser use off: the count must match a turn that offers no browser tools.
|
||||
function browserAgentToolsForTurn(): string[] {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue