opencode-mem 2.11.4 → 2.11.7
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/dist/services/sqlite/hnsw-index.d.ts +1 -0
- package/dist/services/sqlite/hnsw-index.d.ts.map +1 -1
- package/dist/services/sqlite/hnsw-index.js +33 -32
- package/dist/services/sqlite/vector-search.d.ts.map +1 -1
- package/dist/services/sqlite/vector-search.js +5 -0
- package/dist/services/tags.d.ts.map +1 -1
- package/dist/services/tags.js +8 -1
- package/dist/services/web-server.d.ts.map +1 -1
- package/dist/services/web-server.js +3 -0
- package/dist/web/app.js +98 -105
- package/dist/web/i18n.d.ts +2 -0
- package/dist/web/i18n.d.ts.map +1 -0
- package/dist/web/i18n.js +265 -0
- package/dist/web/index.html +76 -50
- package/dist/web/styles.css +17 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hnsw-index.d.ts","sourceRoot":"","sources":["../../../src/services/sqlite/hnsw-index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"hnsw-index.d.ts","sourceRoot":"","sources":["../../../src/services/sqlite/hnsw-index.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,KAAK,CAAkC;IAC/C,OAAO,CAAC,UAAU,CAAkC;IACpD,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAAiB;IACpC,OAAO,CAAC,WAAW,CAAkB;gBAEzB,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;YAKnC,iBAAiB;IAyBzB,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBvD,WAAW,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBlD,MAAM,CAAC,WAAW,EAAE,YAAY,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAqBzF,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYjC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAmB3B,QAAQ,IAAI,MAAM;IAIlB,WAAW,IAAI,OAAO;CAGvB;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,EAAE,MAAM;IAO3B,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS;IAWzE,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS;IAWvE,gBAAgB,CACpB,EAAE,EAAE,GAAG,EACP,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC;IAoCV,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBhF,sBAAsB,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;CA0BpE"}
|
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
import { mkdirSync, existsSync, writeFileSync,
|
|
1
|
+
import { mkdirSync, existsSync, writeFileSync, unlinkSync, readdirSync } from "node:fs";
|
|
2
2
|
import { join, dirname, basename } from "node:path";
|
|
3
3
|
import { log } from "../logger.js";
|
|
4
4
|
import { CONFIG } from "../../config.js";
|
|
5
5
|
let HNSWLib = null;
|
|
6
6
|
async function loadHNSWLib() {
|
|
7
7
|
if (!HNSWLib) {
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
// hnswlib-wasm is compiled with Emscripten -sENVIRONMENT=web and requires
|
|
9
|
+
// a browser-like global. This monkey-patch allows it to load in Node.js/Bun.
|
|
10
|
+
if (typeof globalThis.window === "undefined") {
|
|
11
|
+
globalThis.window = globalThis;
|
|
12
|
+
}
|
|
13
|
+
const { loadHnswlib } = await import("hnswlib-wasm");
|
|
14
|
+
HNSWLib = await loadHnswlib();
|
|
10
15
|
}
|
|
11
16
|
return HNSWLib;
|
|
12
17
|
}
|
|
@@ -31,32 +36,18 @@ export class HNSWIndex {
|
|
|
31
36
|
if (!existsSync(dir)) {
|
|
32
37
|
mkdirSync(dir, { recursive: true });
|
|
33
38
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
this.nextId = meta.nextId || 0;
|
|
42
|
-
this.idMap = new Map(Object.entries(meta.idMap || {}).map(([k, v]) => [Number(k), v]));
|
|
43
|
-
this.reverseMap = new Map(Object.entries(meta.reverseMap || {}));
|
|
44
|
-
}
|
|
45
|
-
log("HNSW index loaded", { path: this.indexPath, count: this.nextId });
|
|
46
|
-
}
|
|
47
|
-
catch (error) {
|
|
48
|
-
log("Failed to load HNSW index, creating new", {
|
|
49
|
-
path: this.indexPath,
|
|
50
|
-
error: String(error),
|
|
51
|
-
});
|
|
52
|
-
this.index = new hnsw.HierarchicalNSW("cosine", this.dimensions, this.maxElements);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
this.index = new hnsw.HierarchicalNSW("cosine", this.dimensions, this.maxElements);
|
|
57
|
-
log("HNSW index created", { path: this.indexPath, dimensions: this.dimensions });
|
|
58
|
-
}
|
|
39
|
+
// hnswlib-wasm uses Emscripten MEMFS (in-memory virtual FS) and has no
|
|
40
|
+
// exported FS API for bridging to real filesystem. HNSW indexes are kept
|
|
41
|
+
// purely in-memory and rebuilt from SQLite vectors on process restart.
|
|
42
|
+
// Constructor requires 3 args: (spaceName, numDimensions, autoSaveFilename)
|
|
43
|
+
this.index = new hnsw.HierarchicalNSW("cosine", this.dimensions, "");
|
|
44
|
+
// initIndex requires 4 args: (maxElements, m, efConstruction, randomSeed)
|
|
45
|
+
this.index.initIndex(this.maxElements, 16, 200, 100);
|
|
59
46
|
this.initialized = true;
|
|
47
|
+
log("HNSW index initialized (in-memory)", {
|
|
48
|
+
path: this.indexPath,
|
|
49
|
+
dimensions: this.dimensions,
|
|
50
|
+
});
|
|
60
51
|
}
|
|
61
52
|
async insert(id, vector) {
|
|
62
53
|
await this.ensureInitialized();
|
|
@@ -65,7 +56,8 @@ export class HNSWIndex {
|
|
|
65
56
|
this.index.markDelete(internalId);
|
|
66
57
|
}
|
|
67
58
|
const internalId = this.nextId++;
|
|
68
|
-
|
|
59
|
+
// hnswlib-wasm addPoint requires 3 args: (point, label, replaceDeleted)
|
|
60
|
+
this.index.addPoint(vector, internalId, false);
|
|
69
61
|
this.idMap.set(internalId, id);
|
|
70
62
|
this.reverseMap.set(id, internalId);
|
|
71
63
|
await this.save();
|
|
@@ -78,7 +70,8 @@ export class HNSWIndex {
|
|
|
78
70
|
this.index.markDelete(internalId);
|
|
79
71
|
}
|
|
80
72
|
const internalId = this.nextId++;
|
|
81
|
-
|
|
73
|
+
// hnswlib-wasm addPoint requires 3 args: (point, label, replaceDeleted)
|
|
74
|
+
this.index.addPoint(item.vector, internalId, false);
|
|
82
75
|
this.idMap.set(internalId, item.id);
|
|
83
76
|
this.reverseMap.set(item.id, internalId);
|
|
84
77
|
}
|
|
@@ -87,7 +80,11 @@ export class HNSWIndex {
|
|
|
87
80
|
async search(queryVector, k) {
|
|
88
81
|
await this.ensureInitialized();
|
|
89
82
|
try {
|
|
90
|
-
|
|
83
|
+
// hnswlib-wasm searchKnn requires 3 args: (queryPoint, numNeighbors, filter)
|
|
84
|
+
const actualK = Math.min(k, this.reverseMap.size);
|
|
85
|
+
if (actualK === 0)
|
|
86
|
+
return [];
|
|
87
|
+
const results = this.index.searchKnn(queryVector, actualK, null);
|
|
91
88
|
return results.neighbors
|
|
92
89
|
.map((internalId, idx) => ({
|
|
93
90
|
id: this.idMap.get(internalId) || "",
|
|
@@ -117,7 +114,8 @@ export class HNSWIndex {
|
|
|
117
114
|
if (!existsSync(dir)) {
|
|
118
115
|
mkdirSync(dir, { recursive: true });
|
|
119
116
|
}
|
|
120
|
-
|
|
117
|
+
// Only persist id mapping (.meta file). HNSW index data lives in-memory
|
|
118
|
+
// and is rebuilt from SQLite vectors on process restart.
|
|
121
119
|
const metaPath = this.indexPath + ".meta";
|
|
122
120
|
const meta = {
|
|
123
121
|
nextId: this.nextId,
|
|
@@ -129,6 +127,9 @@ export class HNSWIndex {
|
|
|
129
127
|
getCount() {
|
|
130
128
|
return this.reverseMap.size;
|
|
131
129
|
}
|
|
130
|
+
isPopulated() {
|
|
131
|
+
return this.reverseMap.size > 0;
|
|
132
|
+
}
|
|
132
133
|
}
|
|
133
134
|
export class HNSWIndexManager {
|
|
134
135
|
indexes = new Map();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vector-search.d.ts","sourceRoot":"","sources":["../../../src/services/sqlite/vector-search.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGnD,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAExE,QAAA,MAAM,QAAQ,sCAAgB,CAAC;AAC/B,KAAK,YAAY,GAAG,OAAO,QAAQ,CAAC,SAAS,CAAC;AAI9C,qBAAa,YAAY;IACvB,YAAY,CAAC,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI;IAqDvE,aAAa,CACjB,KAAK,EAAE,SAAS,EAChB,WAAW,EAAE,YAAY,EACzB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,YAAY,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"vector-search.d.ts","sourceRoot":"","sources":["../../../src/services/sqlite/vector-search.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGnD,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAExE,QAAA,MAAM,QAAQ,sCAAgB,CAAC;AAC/B,KAAK,YAAY,GAAG,OAAO,QAAQ,CAAC,SAAS,CAAC;AAI9C,qBAAa,YAAY;IACvB,YAAY,CAAC,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI;IAqDvE,aAAa,CACjB,KAAK,EAAE,SAAS,EAChB,WAAW,EAAE,YAAY,EACzB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,YAAY,EAAE,CAAC;IAmFpB,kBAAkB,CACtB,MAAM,EAAE,SAAS,EAAE,EACnB,WAAW,EAAE,YAAY,EACzB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,mBAAmB,EAAE,MAAM,EAC3B,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,YAAY,EAAE,CAAC;IAiBpB,YAAY,CAAC,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBlF,YAAY,CAChB,EAAE,EAAE,YAAY,EAChB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,YAAY,EACpB,KAAK,CAAC,EAAE,SAAS,EACjB,UAAU,CAAC,EAAE,YAAY,GACxB,OAAO,CAAC,IAAI,CAAC;IA4BhB,YAAY,CAAC,EAAE,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,GAAG,EAAE;IAW1E,cAAc,CAAC,EAAE,EAAE,YAAY,GAAG,GAAG,EAAE;IAKvC,aAAa,CAAC,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI;IAK7D,sBAAsB,CAAC,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,GAAG,GAAG,EAAE;IAgBlE,YAAY,CAAC,EAAE,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM;IAM5D,eAAe,CAAC,EAAE,EAAE,YAAY,GAAG,MAAM;IAMzC,eAAe,CAAC,EAAE,EAAE,YAAY,GAAG,GAAG,EAAE;IAexC,SAAS,CAAC,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKnD,WAAW,CAAC,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAK/C,gBAAgB,CACpB,EAAE,EAAE,YAAY,EAChB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC;IAIhB,eAAe,IAAI,gBAAgB;CAGpC;AAED,eAAO,MAAM,YAAY,cAAqB,CAAC"}
|
|
@@ -33,6 +33,11 @@ export class VectorSearch {
|
|
|
33
33
|
const db = connectionManager.getConnection(shard.dbPath);
|
|
34
34
|
const contentIndex = hnswIndexManager.getIndex(shard.scope, shard.scopeHash, shard.shardIndex);
|
|
35
35
|
const tagsIndex = hnswIndexManager.getTagsIndex(shard.scope, shard.scopeHash, shard.shardIndex);
|
|
36
|
+
// HNSW indexes are in-memory only (hnswlib-wasm has no real FS bridging).
|
|
37
|
+
// Auto-rebuild from SQLite vectors if indexes are empty after process restart.
|
|
38
|
+
if (!contentIndex.isPopulated()) {
|
|
39
|
+
await hnswIndexManager.rebuildFromShard(db, shard.scope, shard.scopeHash, shard.shardIndex);
|
|
40
|
+
}
|
|
36
41
|
const contentResults = await contentIndex.search(queryVector, limit * 4);
|
|
37
42
|
const tagsResults = await tagsIndex.search(queryVector, limit * 4);
|
|
38
43
|
const scoreMap = new Map();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tags.d.ts","sourceRoot":"","sources":["../../src/services/tags.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tags.d.ts","sourceRoot":"","sources":["../../src/services/tags.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,WAAW,IAAI,MAAM,GAAG,IAAI,CAU3C;AAED,wBAAgB,UAAU,IAAI,MAAM,GAAG,IAAI,CAU1C;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAW9D;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAwBhE;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAW/D;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAYxD;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAY5D;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAKxD;AAED,wBAAgB,cAAc,IAAI,OAAO,CAoBxC;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAa5D;AAED,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG;IAC1C,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CAClB,CAKA"}
|
package/dist/services/tags.js
CHANGED
|
@@ -2,6 +2,7 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
import { execSync } from "node:child_process";
|
|
3
3
|
import { CONFIG } from "../config.js";
|
|
4
4
|
import { sep, normalize, resolve, isAbsolute, basename, dirname } from "node:path";
|
|
5
|
+
import { realpathSync, existsSync } from "node:fs";
|
|
5
6
|
function sha256(input) {
|
|
6
7
|
return createHash("sha256").update(input).digest("hex").slice(0, 16);
|
|
7
8
|
}
|
|
@@ -52,7 +53,13 @@ export function getGitCommonDir(directory) {
|
|
|
52
53
|
if (!commonDir) {
|
|
53
54
|
return null;
|
|
54
55
|
}
|
|
55
|
-
|
|
56
|
+
const resolved = isAbsolute(commonDir)
|
|
57
|
+
? normalize(commonDir)
|
|
58
|
+
: normalize(resolve(directory, commonDir));
|
|
59
|
+
if (existsSync(resolved)) {
|
|
60
|
+
return realpathSync(resolved);
|
|
61
|
+
}
|
|
62
|
+
return resolved;
|
|
56
63
|
}
|
|
57
64
|
catch {
|
|
58
65
|
return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-server.d.ts","sourceRoot":"","sources":["../../src/services/web-server.ts"],"names":[],"mappings":"AAiCA,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAA6C;IAC3D,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,YAAY,CAA8B;IAClD,OAAO,CAAC,mBAAmB,CAA+B;IAC1D,OAAO,CAAC,kBAAkB,CAAsC;gBAEpD,MAAM,EAAE,eAAe;IAInC,qBAAqB,CAAC,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAIpD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YASd,MAAM;IAgCpB,OAAO,CAAC,oBAAoB;IAe5B,OAAO,CAAC,mBAAmB;YAOb,eAAe;IA+BvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAY3B,SAAS,IAAI,OAAO;IAIpB,aAAa,IAAI,OAAO;IAIxB,MAAM,IAAI,MAAM;IAIV,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC;YAchC,aAAa;
|
|
1
|
+
{"version":3,"file":"web-server.d.ts","sourceRoot":"","sources":["../../src/services/web-server.ts"],"names":[],"mappings":"AAiCA,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAA6C;IAC3D,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,YAAY,CAA8B;IAClD,OAAO,CAAC,mBAAmB,CAA+B;IAC1D,OAAO,CAAC,kBAAkB,CAAsC;gBAEpD,MAAM,EAAE,eAAe;IAInC,qBAAqB,CAAC,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAIpD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YASd,MAAM;IAgCpB,OAAO,CAAC,oBAAoB;IAe5B,OAAO,CAAC,mBAAmB;YAOb,eAAe;IA+BvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAY3B,SAAS,IAAI,OAAO;IAIpB,aAAa,IAAI,OAAO;IAIxB,MAAM,IAAI,MAAM;IAIV,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC;YAchC,aAAa;IAuN3B,OAAO,CAAC,eAAe;IA4BvB,OAAO,CAAC,YAAY;CAWrB;AAED,wBAAsB,cAAc,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,CAAC,CAIhF"}
|
|
@@ -145,6 +145,9 @@ export class WebServer {
|
|
|
145
145
|
if (path === "/app.js") {
|
|
146
146
|
return this.serveStaticFile("app.js", "application/javascript");
|
|
147
147
|
}
|
|
148
|
+
if (path === "/i18n.js") {
|
|
149
|
+
return this.serveStaticFile("i18n.js", "application/javascript");
|
|
150
|
+
}
|
|
148
151
|
if (path === "/favicon.ico") {
|
|
149
152
|
return this.serveStaticFile("favicon.ico", "image/x-icon");
|
|
150
153
|
}
|