nexo-brain 7.30.15 → 7.30.16
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.
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +1 -1
- package/bin/nexo-brain.js +177 -72
- package/package.json +1 -1
- package/src/auto_update.py +21 -0
- package/src/cognitive/__init__.py +2 -0
- package/src/cognitive/_core.py +618 -48
- package/src/cognitive/_decay.py +30 -10
- package/src/cognitive/_ingest.py +133 -38
- package/src/cognitive/_memory.py +52 -11
- package/src/cognitive/_search.py +39 -15
- package/src/cognitive/_trust.py +13 -3
- package/src/hnsw_index.py +33 -5
- package/src/model_warmup.py +15 -11
- package/src/scripts/nexo-email-monitor.py +5 -71
- package/src/scripts/nexo-send-reply.py +2 -15
- package/src/server.py +8 -0
- package/templates/core-prompts/email-monitor.md +1 -6
- package/tool-enforcement-map.json +15 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexo-brain",
|
|
3
|
-
"version": "7.30.
|
|
3
|
+
"version": "7.30.16",
|
|
4
4
|
"description": "Local cognitive runtime for Claude Code \u2014 persistent memory, overnight learning, doctor diagnostics, personal scripts, recovery-aware jobs, startup preflight, and optional dashboard/power helper.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "NEXO Brain",
|
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
[Watch the overview video](https://nexo-brain.com/watch/) · [Watch on YouTube](https://www.youtube.com/watch?v=i2lkGhKyVqI) · [Open the infographic](https://nexo-brain.com/assets/nexo-brain-infographic-v5.png)
|
|
20
20
|
|
|
21
|
-
Version `7.30.
|
|
21
|
+
Version `7.30.16` is the current packaged-runtime line. Patch release over v7.30.14 - Desktop diagnostics can read embedding migration status without warming models, and the coordinated Desktop update path is covered for bundled model verification and obsolete managed model cleanup.
|
|
22
22
|
|
|
23
23
|
Previously in `7.30.14`: patch release over v7.30.13 - support tickets, provider capability discovery, task-close rearming, internal audit followups, and the memory-observation watchdog are aligned for Desktop-managed agents.
|
|
24
24
|
|
package/bin/nexo-brain.js
CHANGED
|
@@ -666,6 +666,11 @@ function shouldSkipModelWarmup() {
|
|
|
666
666
|
return ["1", "true", "yes", "on"].includes(flag);
|
|
667
667
|
}
|
|
668
668
|
|
|
669
|
+
function shouldInstallLocalClassifierWarmupDeps() {
|
|
670
|
+
const flag = String(process.env.NEXO_LOCAL_CLASSIFIER || "").trim().toLowerCase();
|
|
671
|
+
return ["1", "true", "on", "auto"].includes(flag);
|
|
672
|
+
}
|
|
673
|
+
|
|
669
674
|
function resolveSystemPython() {
|
|
670
675
|
return run("which python3") || run("which python") || "python3";
|
|
671
676
|
}
|
|
@@ -705,13 +710,15 @@ function installWarmupPythonDependencies(pythonPath, { quiet = false, installRun
|
|
|
705
710
|
}
|
|
706
711
|
}
|
|
707
712
|
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
713
|
+
if (shouldInstallLocalClassifierWarmupDeps()) {
|
|
714
|
+
const classifierResult = spawnSync(
|
|
715
|
+
pythonPath,
|
|
716
|
+
[...pipCommon, ...WARMUP_PIP_PACKAGES],
|
|
717
|
+
{ stdio, timeout: WARMUP_TIMEOUT_MS }
|
|
718
|
+
);
|
|
719
|
+
if (classifierResult.status !== 0) {
|
|
720
|
+
throw new Error("failed to install local classifier dependencies for model warmup");
|
|
721
|
+
}
|
|
715
722
|
}
|
|
716
723
|
}
|
|
717
724
|
|
|
@@ -766,6 +773,157 @@ function runDesktopAwareModelWarmup(pythonPath, nexoHome = NEXO_HOME, options =
|
|
|
766
773
|
runMandatoryModelWarmup(pythonPath, nexoHome, options);
|
|
767
774
|
}
|
|
768
775
|
|
|
776
|
+
function slugifyLocalModelName(value) {
|
|
777
|
+
return String(value || "").trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
function readManagedModelLock(dir) {
|
|
781
|
+
try {
|
|
782
|
+
const lockPath = path.join(dir, ".nexo-model-lock.json");
|
|
783
|
+
if (!fs.existsSync(lockPath)) return null;
|
|
784
|
+
const payload = JSON.parse(fs.readFileSync(lockPath, "utf8"));
|
|
785
|
+
return payload && typeof payload === "object" ? payload : null;
|
|
786
|
+
} catch (_) {
|
|
787
|
+
return null;
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
function isManagedModelRevisionDir(dir, { slug = "", revision = "" } = {}) {
|
|
792
|
+
const lock = readManagedModelLock(dir);
|
|
793
|
+
if (!lock) return false;
|
|
794
|
+
if (!lock.name || !lock.revision || (!lock.model_id && !lock.source_repo)) return false;
|
|
795
|
+
if (slug && slugifyLocalModelName(lock.name) !== slug) return false;
|
|
796
|
+
if (revision && String(lock.revision || "") !== String(revision || "")) return false;
|
|
797
|
+
return true;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
function sha256File(filePath) {
|
|
801
|
+
return crypto.createHash("sha256").update(fs.readFileSync(filePath)).digest("hex");
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
function cleanupObsoleteRuntimeLlmModels(runtimeModelsDir, manifest, { reason = "install" } = {}) {
|
|
805
|
+
if (String(process.env.NEXO_KEEP_OBSOLETE_LLM_MODELS || "").trim() === "1") {
|
|
806
|
+
log(` Keeping obsolete LLM models by NEXO_KEEP_OBSOLETE_LLM_MODELS=1 (${reason}).`);
|
|
807
|
+
return [];
|
|
808
|
+
}
|
|
809
|
+
if (!fs.existsSync(runtimeModelsDir)) return [];
|
|
810
|
+
|
|
811
|
+
const allowed = new Map();
|
|
812
|
+
for (const spec of manifest.models || []) {
|
|
813
|
+
const slug = slugifyLocalModelName(spec.name || "");
|
|
814
|
+
const revision = String(spec.revision || "").trim();
|
|
815
|
+
if (!slug || !revision) continue;
|
|
816
|
+
if (!allowed.has(slug)) allowed.set(slug, new Set());
|
|
817
|
+
allowed.get(slug).add(revision);
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
const removed = [];
|
|
821
|
+
for (const slugEntry of fs.readdirSync(runtimeModelsDir, { withFileTypes: true })) {
|
|
822
|
+
if (!slugEntry.isDirectory()) continue;
|
|
823
|
+
const slug = slugEntry.name;
|
|
824
|
+
if (slug.startsWith(".")) continue;
|
|
825
|
+
if (slug === "_hf-cache") continue;
|
|
826
|
+
const slugDir = path.join(runtimeModelsDir, slug);
|
|
827
|
+
const allowedRevisions = allowed.get(slug) || new Set();
|
|
828
|
+
for (const revisionEntry of fs.readdirSync(slugDir, { withFileTypes: true })) {
|
|
829
|
+
if (!revisionEntry.isDirectory()) continue;
|
|
830
|
+
const revision = revisionEntry.name;
|
|
831
|
+
const revisionDir = path.join(slugDir, revision);
|
|
832
|
+
if (allowedRevisions.has(revision)) continue;
|
|
833
|
+
if (!isManagedModelRevisionDir(revisionDir, { slug, revision })) continue;
|
|
834
|
+
fs.rmSync(revisionDir, { recursive: true, force: true });
|
|
835
|
+
removed.push(path.relative(runtimeModelsDir, revisionDir));
|
|
836
|
+
}
|
|
837
|
+
try {
|
|
838
|
+
if (fs.readdirSync(slugDir).length === 0) fs.rmdirSync(slugDir);
|
|
839
|
+
} catch (_) {}
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
if (removed.length > 0) {
|
|
843
|
+
log(` Removed ${removed.length} obsolete managed LLM model revision(s) (${reason}).`);
|
|
844
|
+
}
|
|
845
|
+
return removed;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
function copyBundledLlmModelsToRuntime(nexoHome = NEXO_HOME, {
|
|
849
|
+
reason = "install",
|
|
850
|
+
bundledModelsDir = path.join(__dirname, "..", "models"),
|
|
851
|
+
manifestPath = path.join(__dirname, "..", "src", "local_model_manifest.json"),
|
|
852
|
+
} = {}) {
|
|
853
|
+
// OFFLINE-FIRST: copy bundled LLM models to runtime/models BEFORE warmup,
|
|
854
|
+
// so fastembed finds them locally and skips HuggingFace downloads.
|
|
855
|
+
// Bundle layout: resources/brain-bundle/models/<source-repo-name>/<all files>.
|
|
856
|
+
// Target layout: <NEXO_HOME>/runtime/models/<spec.name slugified>/<revision>/<files>.
|
|
857
|
+
// We map by source_repo basename to match local_model_manifest.json.
|
|
858
|
+
if (!fs.existsSync(bundledModelsDir)) return 0;
|
|
859
|
+
try {
|
|
860
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
|
|
861
|
+
const runtimeModelsDir = path.join(nexoHome, "runtime", "models");
|
|
862
|
+
let modelsCopied = 0;
|
|
863
|
+
for (const spec of manifest.models || []) {
|
|
864
|
+
// Bundle layout supports either model_id basename (e.g.
|
|
865
|
+
// "bge-base-en-v1.5" from "BAAI/bge-base-en-v1.5") or source_repo
|
|
866
|
+
// basename (e.g. "bge-base-en-v1.5-onnx-q" from "qdrant/...").
|
|
867
|
+
const modelIdName = (spec.model_id || "").split("/").pop();
|
|
868
|
+
const sourceRepoName = (spec.source_repo || "").split("/").pop();
|
|
869
|
+
let sourceDir = path.join(bundledModelsDir, sourceRepoName);
|
|
870
|
+
if (!fs.existsSync(sourceDir)) {
|
|
871
|
+
sourceDir = path.join(bundledModelsDir, modelIdName);
|
|
872
|
+
}
|
|
873
|
+
if (!fs.existsSync(sourceDir)) continue;
|
|
874
|
+
const slug = slugifyLocalModelName(spec.name || "");
|
|
875
|
+
const targetDir = path.join(runtimeModelsDir, slug, spec.revision);
|
|
876
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
877
|
+
const missingFiles = [];
|
|
878
|
+
for (const f of (spec.required_files || [])) {
|
|
879
|
+
const src = path.join(sourceDir, f.path);
|
|
880
|
+
const dst = path.join(targetDir, f.path);
|
|
881
|
+
if (!fs.existsSync(src)) {
|
|
882
|
+
missingFiles.push(f.path);
|
|
883
|
+
continue;
|
|
884
|
+
}
|
|
885
|
+
fs.mkdirSync(path.dirname(dst), { recursive: true });
|
|
886
|
+
let shouldCopy = !fs.existsSync(dst) || (f.size && fs.statSync(dst).size !== f.size);
|
|
887
|
+
if (!shouldCopy && f.sha256 && sha256File(dst) !== f.sha256) {
|
|
888
|
+
shouldCopy = true;
|
|
889
|
+
}
|
|
890
|
+
if (shouldCopy) {
|
|
891
|
+
fs.copyFileSync(src, dst);
|
|
892
|
+
}
|
|
893
|
+
if (f.size && fs.statSync(dst).size !== f.size) {
|
|
894
|
+
missingFiles.push(`${f.path}:size`);
|
|
895
|
+
continue;
|
|
896
|
+
}
|
|
897
|
+
if (f.sha256) {
|
|
898
|
+
const actual = sha256File(dst);
|
|
899
|
+
if (actual !== f.sha256) {
|
|
900
|
+
missingFiles.push(`${f.path}:sha256`);
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
if (missingFiles.length) {
|
|
905
|
+
log(` WARN: bundled LLM model ${spec.name} incomplete (${missingFiles.join(", ")})`);
|
|
906
|
+
continue;
|
|
907
|
+
}
|
|
908
|
+
// Write the lock file to match revision (avoids re-download).
|
|
909
|
+
fs.writeFileSync(path.join(targetDir, ".nexo-model-lock.json"), JSON.stringify({
|
|
910
|
+
name: spec.name, kind: spec.kind, model_id: spec.model_id,
|
|
911
|
+
source_repo: spec.source_repo, revision: spec.revision, model_file: spec.model_file,
|
|
912
|
+
required_files: spec.required_files,
|
|
913
|
+
}, null, 2));
|
|
914
|
+
modelsCopied++;
|
|
915
|
+
}
|
|
916
|
+
if (modelsCopied > 0) log(` Copied ${modelsCopied} pre-bundled LLM model(s) (offline, ${reason}).`);
|
|
917
|
+
if (modelsCopied > 0 && modelsCopied === (manifest.models || []).length) {
|
|
918
|
+
cleanupObsoleteRuntimeLlmModels(runtimeModelsDir, manifest, { reason });
|
|
919
|
+
}
|
|
920
|
+
return modelsCopied;
|
|
921
|
+
} catch (err) {
|
|
922
|
+
log(` WARN: bundled models copy failed during ${reason}: ${err.message}`);
|
|
923
|
+
return 0;
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
|
|
769
927
|
async function runWarmupModelsCommand(args) {
|
|
770
928
|
const dryRun = args.includes("--dry-run");
|
|
771
929
|
const json = args.includes("--json");
|
|
@@ -3216,6 +3374,7 @@ async function runSetup() {
|
|
|
3216
3374
|
log(" Python dependencies reconciled.");
|
|
3217
3375
|
}
|
|
3218
3376
|
|
|
3377
|
+
copyBundledLlmModelsToRuntime(NEXO_HOME, { reason: "update" });
|
|
3219
3378
|
const migPythonForWarmup = findVenvPython(NEXO_HOME) || "python3";
|
|
3220
3379
|
runDesktopAwareModelWarmup(migPythonForWarmup, NEXO_HOME, { reason: "update", installRuntimeDeps: false });
|
|
3221
3380
|
|
|
@@ -3492,6 +3651,7 @@ async function runSetup() {
|
|
|
3492
3651
|
stampRuntimeRepairBaseline(NEXO_HOME, "bin.nexo-brain.same-version-repair")
|
|
3493
3652
|
);
|
|
3494
3653
|
|
|
3654
|
+
copyBundledLlmModelsToRuntime(NEXO_HOME, { reason: "repair" });
|
|
3495
3655
|
runDesktopAwareModelWarmup(syncPython, NEXO_HOME, { reason: "repair" });
|
|
3496
3656
|
logMacPermissionsNotice(NEXO_HOME, syncPython);
|
|
3497
3657
|
|
|
@@ -3935,71 +4095,7 @@ async function runSetup() {
|
|
|
3935
4095
|
}
|
|
3936
4096
|
log("Dependencies installed.");
|
|
3937
4097
|
|
|
3938
|
-
|
|
3939
|
-
// so fastembed finds them locally and skips the ~217MB HuggingFace download.
|
|
3940
|
-
// Bundle layout: resources/brain-bundle/models/<source-repo-name>/<all files>.
|
|
3941
|
-
// Target layout: <NEXO_HOME>/runtime/models/<spec.name slugified>/<revision>/<files>.
|
|
3942
|
-
// We map by source_repo basename to match local_model_manifest.json.
|
|
3943
|
-
const bundledModelsDir = path.join(__dirname, "..", "models");
|
|
3944
|
-
if (fs.existsSync(bundledModelsDir)) {
|
|
3945
|
-
try {
|
|
3946
|
-
const manifest = JSON.parse(fs.readFileSync(path.join(__dirname, "..", "src", "local_model_manifest.json"), "utf8"));
|
|
3947
|
-
const runtimeModelsDir = path.join(NEXO_HOME, "runtime", "models");
|
|
3948
|
-
let modelsCopied = 0;
|
|
3949
|
-
for (const spec of manifest.models || []) {
|
|
3950
|
-
// Bundle layout supports either model_id basename (e.g.
|
|
3951
|
-
// "bge-base-en-v1.5" from "BAAI/bge-base-en-v1.5") or source_repo
|
|
3952
|
-
// basename (e.g. "bge-base-en-v1.5-onnx-q" from "qdrant/...").
|
|
3953
|
-
const modelIdName = (spec.model_id || "").split("/").pop();
|
|
3954
|
-
const sourceRepoName = (spec.source_repo || "").split("/").pop();
|
|
3955
|
-
let sourceDir = path.join(bundledModelsDir, modelIdName);
|
|
3956
|
-
if (!fs.existsSync(sourceDir)) {
|
|
3957
|
-
sourceDir = path.join(bundledModelsDir, sourceRepoName);
|
|
3958
|
-
}
|
|
3959
|
-
if (!fs.existsSync(sourceDir)) continue;
|
|
3960
|
-
const slug = (spec.name || "").trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
3961
|
-
const targetDir = path.join(runtimeModelsDir, slug, spec.revision);
|
|
3962
|
-
fs.mkdirSync(targetDir, { recursive: true });
|
|
3963
|
-
const missingFiles = [];
|
|
3964
|
-
for (const f of (spec.required_files || [])) {
|
|
3965
|
-
const src = path.join(sourceDir, f.path);
|
|
3966
|
-
const dst = path.join(targetDir, f.path);
|
|
3967
|
-
if (!fs.existsSync(src)) {
|
|
3968
|
-
missingFiles.push(f.path);
|
|
3969
|
-
continue;
|
|
3970
|
-
}
|
|
3971
|
-
fs.mkdirSync(path.dirname(dst), { recursive: true });
|
|
3972
|
-
if (!fs.existsSync(dst) || (f.size && fs.statSync(dst).size !== f.size)) {
|
|
3973
|
-
fs.copyFileSync(src, dst);
|
|
3974
|
-
}
|
|
3975
|
-
if (f.size && fs.statSync(dst).size !== f.size) {
|
|
3976
|
-
missingFiles.push(`${f.path}:size`);
|
|
3977
|
-
continue;
|
|
3978
|
-
}
|
|
3979
|
-
if (f.sha256) {
|
|
3980
|
-
const actual = crypto.createHash("sha256").update(fs.readFileSync(dst)).digest("hex");
|
|
3981
|
-
if (actual !== f.sha256) {
|
|
3982
|
-
missingFiles.push(`${f.path}:sha256`);
|
|
3983
|
-
}
|
|
3984
|
-
}
|
|
3985
|
-
}
|
|
3986
|
-
if (missingFiles.length) {
|
|
3987
|
-
log(` WARN: bundled LLM model ${spec.name} incomplete (${missingFiles.join(", ")})`);
|
|
3988
|
-
continue;
|
|
3989
|
-
}
|
|
3990
|
-
// Write the lock file to match revision (avoids re-download).
|
|
3991
|
-
fs.writeFileSync(path.join(targetDir, ".nexo-model-lock.json"), JSON.stringify({
|
|
3992
|
-
name: spec.name, kind: spec.kind, model_id: spec.model_id,
|
|
3993
|
-
source_repo: spec.source_repo, revision: spec.revision, model_file: spec.model_file,
|
|
3994
|
-
required_files: spec.required_files,
|
|
3995
|
-
}, null, 2));
|
|
3996
|
-
modelsCopied++;
|
|
3997
|
-
}
|
|
3998
|
-
if (modelsCopied > 0) log(` Copied ${modelsCopied} pre-bundled LLM model(s) (offline).`);
|
|
3999
|
-
} catch (err) {
|
|
4000
|
-
log(` WARN: bundled models copy failed: ${err.message}`);
|
|
4001
|
-
}
|
|
4002
|
-
}
|
|
4098
|
+
copyBundledLlmModelsToRuntime(NEXO_HOME, { reason: "install" });
|
|
4003
4099
|
|
|
4004
4100
|
runDesktopAwareModelWarmup(python, NEXO_HOME, { reason: "install", installRuntimeDeps: false });
|
|
4005
4101
|
|
|
@@ -5121,4 +5217,13 @@ if (isCliEntrypoint()) {
|
|
|
5121
5217
|
console.error("Setup failed:", err.message);
|
|
5122
5218
|
process.exit(1);
|
|
5123
5219
|
});
|
|
5220
|
+
} else {
|
|
5221
|
+
module.exports = {
|
|
5222
|
+
cleanupObsoleteRuntimeLlmModels,
|
|
5223
|
+
copyBundledLlmModelsToRuntime,
|
|
5224
|
+
isManagedModelRevisionDir,
|
|
5225
|
+
readManagedModelLock,
|
|
5226
|
+
sha256File,
|
|
5227
|
+
slugifyLocalModelName,
|
|
5228
|
+
};
|
|
5124
5229
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexo-brain",
|
|
3
|
-
"version": "7.30.
|
|
3
|
+
"version": "7.30.16",
|
|
4
4
|
"mcpName": "io.github.wazionapps/nexo",
|
|
5
5
|
"description": "NEXO Brain — Shared brain for AI agents. Persistent memory, semantic RAG, natural forgetting, metacognitive guard, trust scoring, 150+ MCP tools. Works with Claude Code, Codex, Claude Desktop & any MCP client. 100% local, free.",
|
|
6
6
|
"homepage": "https://nexo-brain.com",
|
package/src/auto_update.py
CHANGED
|
@@ -1211,6 +1211,15 @@ def _local_classifier_install_command() -> list[str]:
|
|
|
1211
1211
|
return cmd
|
|
1212
1212
|
|
|
1213
1213
|
|
|
1214
|
+
def _local_classifier_auto_install_enabled() -> bool:
|
|
1215
|
+
return str(os.environ.get("NEXO_LOCAL_CLASSIFIER", "")).strip().lower() in {
|
|
1216
|
+
"1",
|
|
1217
|
+
"true",
|
|
1218
|
+
"on",
|
|
1219
|
+
"auto",
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
|
|
1214
1223
|
def _install_local_classifier_worker() -> None:
|
|
1215
1224
|
from classifier_local import MODEL_REVISION
|
|
1216
1225
|
|
|
@@ -1311,6 +1320,18 @@ def _maybe_install_local_classifier() -> None:
|
|
|
1311
1320
|
"opt_out": True,
|
|
1312
1321
|
})
|
|
1313
1322
|
return
|
|
1323
|
+
if not _local_classifier_auto_install_enabled():
|
|
1324
|
+
from classifier_local import MODEL_REVISION
|
|
1325
|
+
|
|
1326
|
+
_write_classifier_install_log("[classifier-install] deferred: model is not bundled; set NEXO_LOCAL_CLASSIFIER=auto to install")
|
|
1327
|
+
_write_classifier_install_state({
|
|
1328
|
+
"installed_at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
|
|
1329
|
+
"model_revision": MODEL_REVISION,
|
|
1330
|
+
"deps_ok": False,
|
|
1331
|
+
"deferred": True,
|
|
1332
|
+
"reason": "not_bundled",
|
|
1333
|
+
})
|
|
1334
|
+
return
|
|
1314
1335
|
try:
|
|
1315
1336
|
deps_ok, versions, _missing = _probe_local_classifier_dependencies()
|
|
1316
1337
|
if deps_ok:
|
|
@@ -17,6 +17,8 @@ from cognitive._core import (
|
|
|
17
17
|
_get_db, _init_tables, _migrate_lifecycle, _migrate_co_activation,
|
|
18
18
|
_migrate_memory_personalization,
|
|
19
19
|
_auto_migrate_embeddings,
|
|
20
|
+
embedding_migration_status,
|
|
21
|
+
_active_embedding_context, _row_embedding_array, _embedding_migration_uses_shadow,
|
|
20
22
|
_get_model, _get_reranker, rerank_results,
|
|
21
23
|
embed, cosine_similarity, _array_to_blob, _blob_to_array,
|
|
22
24
|
extract_temporal_date, redact_secrets,
|