@biaoo/tiangong-wiki 0.3.0 → 0.3.2

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/core/db.js CHANGED
@@ -210,6 +210,16 @@ export function getMeta(db, key) {
210
210
  const row = db.prepare("SELECT value FROM sync_meta WHERE key = ?").get(key);
211
211
  return row?.value ?? null;
212
212
  }
213
+ export function getVectorTableDimensions(db) {
214
+ const row = db.prepare("SELECT sql FROM sqlite_master WHERE name = 'vec_pages'").get();
215
+ const sql = row?.sql ?? "";
216
+ const match = sql.match(/embedding\s+float\[(\d+)\]/i);
217
+ if (!match) {
218
+ return null;
219
+ }
220
+ const dimensions = Number.parseInt(match[1], 10);
221
+ return Number.isFinite(dimensions) && dimensions > 0 ? dimensions : null;
222
+ }
213
223
  export function setMeta(db, key, value) {
214
224
  if (value === null) {
215
225
  db.prepare("DELETE FROM sync_meta WHERE key = ?").run(key);
@@ -295,6 +305,8 @@ export function openDb(dbPath, config, embeddingDimensions) {
295
305
  sqliteVec.load(db);
296
306
  ensureBaseTables(db, embeddingDimensions);
297
307
  ensureFtsTable(db);
308
+ const vectorDimensions = getVectorTableDimensions(db);
309
+ const vectorDimensionsChanged = vectorDimensions !== null && vectorDimensions !== embeddingDimensions;
298
310
  const storedSchemaVersion = getMeta(db, "schema_version");
299
311
  if (storedSchemaVersion && storedSchemaVersion !== SCHEMA_VERSION) {
300
312
  db.close();
@@ -307,5 +319,5 @@ export function openDb(dbPath, config, embeddingDimensions) {
307
319
  schema_version: SCHEMA_VERSION,
308
320
  ...(storedConfigVersion === null ? { config_version: config.configVersion } : {}),
309
321
  });
310
- return { db, configChanged };
322
+ return { db, configChanged, vectorDimensions, vectorDimensionsChanged };
311
323
  }
@@ -15,6 +15,6 @@ export function loadRuntimeConfig(env = process.env) {
15
15
  export function openRuntimeDb(env = process.env) {
16
16
  const { paths, config } = loadRuntimeConfig(env);
17
17
  const embeddingClient = EmbeddingClient.fromEnv(env);
18
- const { db } = openDb(paths.dbPath, config, embeddingClient?.settings.dimensions ?? getEmbeddingDimensionFromEnv(env));
19
- return { db, paths, config, embeddingClient };
18
+ const { db, vectorDimensions, vectorDimensionsChanged } = openDb(paths.dbPath, config, embeddingClient?.settings.dimensions ?? getEmbeddingDimensionFromEnv(env));
19
+ return { db, paths, config, embeddingClient, vectorDimensions, vectorDimensionsChanged };
20
20
  }
package/dist/core/sync.js CHANGED
@@ -78,17 +78,18 @@ export async function syncWorkspace(options = {}) {
78
78
  }
79
79
  const config = loadConfig(runtimePaths.configPath);
80
80
  const embeddingClient = EmbeddingClient.fromEnv(env);
81
- const { db, configChanged } = openDb(runtimePaths.dbPath, config, embeddingClient?.settings.dimensions ?? getEmbeddingDimension(env));
81
+ const { db, configChanged, vectorDimensionsChanged } = openDb(runtimePaths.dbPath, config, embeddingClient?.settings.dimensions ?? getEmbeddingDimension(env));
82
82
  try {
83
83
  let mode = options.targetPaths && options.targetPaths.length > 0 && !options.force ? "path" : "full";
84
84
  let upgradedToFullSync = false;
85
85
  const storedEmbeddingProfile = embeddingClient ? getMeta(db, "embedding_profile") : null;
86
86
  const profileChanged = Boolean(embeddingClient && storedEmbeddingProfile && storedEmbeddingProfile !== embeddingClient.profileHash);
87
- if (mode === "path" && (configChanged || profileChanged)) {
87
+ const embeddingDrift = profileChanged || vectorDimensionsChanged;
88
+ if (mode === "path" && (configChanged || embeddingDrift)) {
88
89
  mode = "full";
89
90
  upgradedToFullSync = true;
90
91
  }
91
- if (profileChanged && options.skipEmbedding) {
92
+ if (embeddingDrift && options.skipEmbedding) {
92
93
  throw new AppError("Embedding profile changed, cannot skip embedding.", "config");
93
94
  }
94
95
  if (options.force) {
@@ -112,7 +113,7 @@ export async function syncWorkspace(options = {}) {
112
113
  });
113
114
  }
114
115
  let embedAll = false;
115
- if (embeddingClient && profileChanged) {
116
+ if (embeddingClient && embeddingDrift) {
116
117
  resetVectorTable(db, embeddingClient.settings.dimensions);
117
118
  db.prepare("UPDATE pages SET embedding_status = 'pending'").run();
118
119
  embedAll = true;
@@ -160,7 +161,7 @@ export async function syncWorkspace(options = {}) {
160
161
  mode,
161
162
  upgradedToFullSync,
162
163
  configChanged,
163
- profileChanged,
164
+ profileChanged: embeddingDrift,
164
165
  inserted: applyResult.inserted.length,
165
166
  updated: applyResult.updated.length,
166
167
  deleted: applyResult.deleted.length,
@@ -270,8 +270,14 @@ export async function searchPages(env = process.env, options) {
270
270
  }
271
271
  const limit = parsePositiveLimit(options.limit, "--limit", 10);
272
272
  const [queryEmbedding] = await embeddingClient.embedBatch([options.query]);
273
- const { db, config } = openRuntimeDb(env);
273
+ const { db, config, vectorDimensions, vectorDimensionsChanged } = openRuntimeDb(env);
274
274
  try {
275
+ if (vectorDimensionsChanged) {
276
+ throw new AppError("Embedding index dimensions changed, run tiangong-wiki sync to rebuild vectors.", "config", {
277
+ expectedDimensions: embeddingClient.settings.dimensions,
278
+ actualDimensions: vectorDimensions,
279
+ });
280
+ }
275
281
  const rows = db
276
282
  .prepare(`
277
283
  SELECT ${listPageColumns(config).map((column) => `pages.${column}`).join(", ")}, vec_pages.distance AS distance
@@ -2,7 +2,7 @@ import { createServer } from "node:http";
2
2
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
3
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
4
4
  import { z } from "zod";
5
- import packageJson from "../package.json" with { type: "json" };
5
+ import packageJson from "../../package.json" with { type: "json" };
6
6
  import { DaemonHttpError, requestDaemonJson } from "./daemon-client.js";
7
7
  const limitSchema = z.coerce.number().int().positive().max(1000).optional();
8
8
  const pageIdSchema = z.string().trim().min(1);
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "@biaoo/tiangong-wiki-mcp-server",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "description": "Thin MCP adapter for the Tiangong Wiki daemon.",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "bin": {
9
+ "tiangong-wiki-mcp-server": "./dist/index.js"
10
+ },
11
+ "scripts": {
12
+ "build": "node ../node_modules/typescript/bin/tsc -p tsconfig.json",
13
+ "dev": "node ../node_modules/tsx/dist/cli.mjs src/index.ts",
14
+ "start": "node dist/index.js"
15
+ },
16
+ "dependencies": {
17
+ "@modelcontextprotocol/sdk": "^1.29.0",
18
+ "zod": "^4.3.6"
19
+ }
20
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@biaoo/tiangong-wiki",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Local-first wiki index and query engine for Markdown knowledge pages (Tiangong Wiki).",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -23,6 +23,7 @@
23
23
  "files": [
24
24
  "dist",
25
25
  "mcp-server/dist",
26
+ "mcp-server/package.json",
26
27
  "assets",
27
28
  "references",
28
29
  "agents",