@remit/backend 0.0.23 → 0.0.24

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remit/backend",
3
- "version": "0.0.23",
3
+ "version": "0.0.24",
4
4
  "description": "Remit Mail Inspector API backend",
5
5
  "license": "MIT",
6
6
  "author": "",
@@ -14,6 +14,14 @@ const moduleNotFound = (): Error => {
14
14
  return error;
15
15
  };
16
16
 
17
+ const modelUnavailable = (): Error => {
18
+ const error = new Error(
19
+ 'Embedding model "Xenova/paraphrase-multilingual-MiniLM-L12-v2" could not be loaded',
20
+ );
21
+ (error as Error & { code: string }).code = "ERR_EMBEDDING_MODEL_UNAVAILABLE";
22
+ return error;
23
+ };
24
+
17
25
  describe("noteSemanticCapabilityAbsence", () => {
18
26
  const ORIGINAL = process.env.DATA_BACKEND;
19
27
  beforeEach(() => {
@@ -44,6 +52,16 @@ describe("noteSemanticCapabilityAbsence", () => {
44
52
  assert.equal(noteSemanticCapabilityAbsence(error), true);
45
53
  });
46
54
 
55
+ it("absorbs an embedding-model load failure (e2e-dev from source, HuggingFace fetch failed) and remembers it", () => {
56
+ for (const backend of ["sqlite", "postgres"]) {
57
+ _resetSemanticCapabilityForTest();
58
+ process.env.DATA_BACKEND = backend;
59
+ assert.equal(isSemanticSearchUnavailable(), false);
60
+ assert.equal(noteSemanticCapabilityAbsence(modelUnavailable()), true);
61
+ assert.equal(isSemanticSearchUnavailable(), true);
62
+ }
63
+ });
64
+
47
65
  it("rethrows genuine query errors on the self-host SQL backends", () => {
48
66
  process.env.DATA_BACKEND = "sqlite";
49
67
  assert.equal(
@@ -57,8 +75,10 @@ describe("noteSemanticCapabilityAbsence", () => {
57
75
  it("never engages on the AWS DynamoDB path — a missing module there is a broken deploy", () => {
58
76
  delete process.env.DATA_BACKEND;
59
77
  assert.equal(noteSemanticCapabilityAbsence(moduleNotFound()), false);
78
+ assert.equal(noteSemanticCapabilityAbsence(modelUnavailable()), false);
60
79
  process.env.DATA_BACKEND = "dynamodb";
61
80
  assert.equal(noteSemanticCapabilityAbsence(moduleNotFound()), false);
81
+ assert.equal(noteSemanticCapabilityAbsence(modelUnavailable()), false);
62
82
  assert.equal(isSemanticSearchUnavailable(), false);
63
83
  });
64
84
  });
@@ -13,6 +13,15 @@ import { isSelfHostSqlBackend } from "../data-backend.js";
13
13
  * fetches semantic hits alongside every literal search), retried by the client
14
14
  * on top.
15
15
  *
16
+ * The e2e-dev lane runs this backend from source rather than the container, so
17
+ * `@huggingface/transformers` IS present and the local embedder instead tries to
18
+ * lazily download the model from HuggingFace; a transient `fetch failed` there
19
+ * surfaces the same way. The search-service raises it as a typed
20
+ * `EmbeddingModelUnavailableError` (code ERR_EMBEDDING_MODEL_UNAVAILABLE), which
21
+ * this gate treats as the same capability absence — the model is not available,
22
+ * empty semantic results are the truthful answer, and the lane never depends on
23
+ * a live external download.
24
+ *
16
25
  * When the pipeline is genuinely absent, empty hits are the truthful answer:
17
26
  * the FTS/literal engine is the primary search surface on these profiles and is
18
27
  * unaffected. The absence is remembered so subsequent requests short-circuit.
@@ -29,6 +38,7 @@ const CAPABILITY_ABSENCE_CODES = new Set([
29
38
  "ERR_MODULE_NOT_FOUND",
30
39
  "MODULE_NOT_FOUND",
31
40
  "ERR_DLOPEN_FAILED",
41
+ "ERR_EMBEDDING_MODEL_UNAVAILABLE",
32
42
  ]);
33
43
 
34
44
  let semanticUnavailable = false;