mikoshi 0.1.0 → 0.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mikoshi",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Private local code search + MCP",
5
5
  "type": "module",
6
6
  "bin": {
@@ -57,7 +57,7 @@ function reuseChunks(prevChunks, prevEmbeddings) {
57
57
  return { chunksByFile, embeddingById };
58
58
  }
59
59
 
60
- export async function indexRepo(repoPath, configOverride = null) {
60
+ export async function indexRepo(repoPath, configOverride = null, providerOverride = null) {
61
61
  const config = configOverride || loadConfig();
62
62
  const repoRoot = path.resolve(repoPath);
63
63
 
@@ -136,10 +136,10 @@ export async function indexRepo(repoPath, configOverride = null) {
136
136
  }
137
137
  }
138
138
 
139
- let provider = null;
139
+ let provider = providerOverride;
140
140
  let pendingEmbeddings = [];
141
141
  if (pendingTexts.length) {
142
- provider = getEmbeddingsProvider(config);
142
+ if (!provider) provider = getEmbeddingsProvider(config);
143
143
  pendingEmbeddings = await provider.embedTexts(pendingTexts);
144
144
  }
145
145
 
@@ -5,6 +5,7 @@ import { searchRepo } from "../retrieval/hybrid.js";
5
5
  import { loadConfig } from "../config.js";
6
6
  import { IndexStore } from "../indexing/index_store.js";
7
7
  import path from "node:path";
8
+ import { getEmbeddingsProvider } from "../retrieval/semantic.js";
8
9
 
9
10
  const TOOL_NAME = "codebase-retrieval";
10
11
  const TOOL_SCHEMA = {
@@ -54,12 +55,13 @@ async function handleToolCall(params) {
54
55
  const config = loadConfig();
55
56
  const repoRoot = path.resolve(repoPath);
56
57
  const store = new IndexStore(repoRoot, config.index_root);
58
+ const provider = getEmbeddingsProvider(config);
57
59
  if (!store.exists()) {
58
- await indexRepo(repoRoot, config);
60
+ await indexRepo(repoRoot, config, provider);
59
61
  } else {
60
- await indexRepo(repoRoot, config);
62
+ await indexRepo(repoRoot, config, provider);
61
63
  }
62
- const results = await searchRepo(repoRoot, query, k);
64
+ const results = await searchRepo(repoRoot, query, k, provider);
63
65
  return {
64
66
  isError: false,
65
67
  content: [{ type: "text", text: JSON.stringify(results) }],
@@ -67,6 +69,17 @@ async function handleToolCall(params) {
67
69
  };
68
70
  }
69
71
 
72
+ const args = new Set(process.argv.slice(2));
73
+ const quiet = args.has("--quiet");
74
+ const shouldAnnounce =
75
+ !quiet && (process.env.MIKOSHI_MCP_BANNER === "1" || process.stdin.isTTY);
76
+
77
+ if (shouldAnnounce) {
78
+ console.error("Mikoshi MCP running (stdio). Waiting for client...");
79
+ }
80
+
81
+ process.env.MIKOSHI_SILENT = "1";
82
+
70
83
  const rl = readline.createInterface({ input: process.stdin, crlfDelay: Infinity });
71
84
 
72
85
  rl.on("line", async (line) => {
@@ -88,7 +101,7 @@ rl.on("line", async (line) => {
88
101
  result: {
89
102
  protocolVersion: params?.protocolVersion || "2024-11-05",
90
103
  capabilities: { tools: {} },
91
- serverInfo: { name: "mikoshi", version: "0.1.0" },
104
+ serverInfo: { name: "mikoshi", version: "0.1.2" },
92
105
  },
93
106
  });
94
107
  return;
@@ -54,7 +54,7 @@ export async function hybridSearch(query, chunks, lexical, semantic, k = 8, alph
54
54
  return reranked.slice(0, k);
55
55
  }
56
56
 
57
- export async function searchRepo(repoPath, query, k = 8) {
57
+ export async function searchRepo(repoPath, query, k = 8, providerOverride = null) {
58
58
  const config = loadConfig();
59
59
  const repoRoot = path.resolve(repoPath);
60
60
  const store = new IndexStore(repoRoot, config.index_root);
@@ -71,7 +71,7 @@ export async function searchRepo(repoPath, query, k = 8) {
71
71
  if (!chunks.length) return [];
72
72
 
73
73
  const lexical = new LexicalIndex(chunks.map((chunk) => chunk.text));
74
- const provider = getEmbeddingsProvider(config);
74
+ const provider = providerOverride || getEmbeddingsProvider(config);
75
75
  const semantic = new SemanticSearcher(embeddingsData.embeddings, embeddingsData.dim, provider);
76
76
  const hits = await hybridSearch(query, chunks, lexical, semantic, k);
77
77
 
@@ -103,15 +103,16 @@ class TransformersEmbeddingsProvider {
103
103
 
104
104
  const offline = isOffline();
105
105
  const timeoutMs = downloadTimeoutMs();
106
+ const silent = isSilent();
106
107
 
107
- console.error("🧠 Loading embeddings model…");
108
+ if (!silent) console.error("🧠 Loading embeddings model…");
108
109
 
109
110
  env.allowRemoteModels = false;
110
111
  try {
111
112
  const extractor = await pipeline("feature-extraction", this.config.embeddings.model, {
112
113
  quantized: false,
113
114
  });
114
- console.error("✅ Embeddings model loaded");
115
+ if (!silent) console.error("✅ Embeddings model loaded");
115
116
  return extractor;
116
117
  } catch (err) {
117
118
  if (offline) {
@@ -121,14 +122,16 @@ class TransformersEmbeddingsProvider {
121
122
  }
122
123
  }
123
124
 
124
- console.error("⬇️ Downloading local model (one-time)…");
125
+ if (!silent) console.error("⬇️ Downloading local model (one-time)…");
125
126
  env.allowRemoteModels = true;
126
127
  const extractor = await withTimeout(
127
128
  pipeline("feature-extraction", this.config.embeddings.model, { quantized: false }),
128
129
  timeoutMs
129
130
  );
130
- console.error("✅ Model ready");
131
- console.error("✅ Embeddings model loaded");
131
+ if (!silent) {
132
+ console.error("✅ Model ready");
133
+ console.error("✅ Embeddings model loaded");
134
+ }
132
135
  return extractor;
133
136
  })();
134
137
  return this._pipelinePromise;
@@ -153,6 +156,11 @@ function isOffline() {
153
156
  return ["1", "true", "yes", "on"].includes(raw.toLowerCase());
154
157
  }
155
158
 
159
+ function isSilent() {
160
+ const raw = process.env.MIKOSHI_SILENT || "";
161
+ return ["1", "true", "yes", "on"].includes(raw.toLowerCase());
162
+ }
163
+
156
164
  function downloadTimeoutMs() {
157
165
  const raw = process.env.MIKOSHI_MODEL_DOWNLOAD_TIMEOUT_SEC;
158
166
  const seconds = raw ? Number.parseInt(raw, 10) : 300;