@takara-ai/miru-code 1.8.2 → 1.10.0
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/README.md +65 -53
- package/docs/coverage-badge.json +6 -0
- package/grammars/manifest.json +10 -2
- package/grammars/tree-sitter-astro.wasm +0 -0
- package/grammars/tree-sitter-php.wasm +0 -0
- package/grammars/tree-sitter-php_only.wasm +0 -0
- package/grammars/tree-sitter-sql.wasm +0 -0
- package/grammars/tree-sitter-svelte.wasm +0 -0
- package/grammars/tree-sitter-vue.wasm +0 -0
- package/package.json +10 -2
- package/src/agents.ts +4 -4
- package/src/auth/device.ts +26 -21
- package/src/auth/providers.ts +26 -11
- package/src/benchmark/compare.ts +3 -10
- package/src/benchmark/grep.ts +64 -37
- package/src/benchmark/locate-compare.ts +8 -1
- package/src/benchmark/rg-literal.ts +9 -4
- package/src/cache.ts +3 -3
- package/src/chunking/ast.ts +21 -3
- package/src/chunking/grammars.ts +8 -3
- package/src/chunking/structural.ts +13 -24
- package/src/cli-mode.ts +18 -0
- package/src/cli.ts +54 -98
- package/src/credentials.ts +14 -14
- package/src/embeddings/openai.ts +6 -3
- package/src/embeddings/sagemaker.ts +18 -3
- package/src/embeddings/validate.ts +10 -7
- package/src/git.ts +6 -2
- package/src/help.ts +7 -7
- package/src/index/bm25.ts +66 -6
- package/src/index/chunk-selector.ts +39 -11
- package/src/index/create.ts +5 -9
- package/src/index/files.ts +5 -1
- package/src/index/incremental.ts +48 -8
- package/src/index/sparse.ts +14 -2
- package/src/installer/agents.ts +85 -65
- package/src/installer/benchmark-mode.ts +40 -11
- package/src/installer/config.ts +105 -42
- package/src/installer/installer.ts +59 -34
- package/src/installer/legacy-hooks.ts +131 -0
- package/src/installer/prompt.ts +20 -22
- package/src/installer/search-policy.ts +10 -10
- package/src/mcp/index-cache.ts +16 -3
- package/src/mcp/server.ts +65 -46
- package/src/mcp/stdio.ts +17 -2
- package/src/miru-index.ts +90 -22
- package/src/prompt.ts +51 -14
- package/src/ranking/boosting.ts +5 -6
- package/src/ranking/location.ts +6 -10
- package/src/ranking/penalties.ts +14 -22
- package/src/search.ts +8 -12
- package/src/setup.ts +25 -13
- package/src/snippet.ts +8 -26
- package/src/spinner.ts +26 -16
- package/src/tokenizer/bert-wordpiece.ts +0 -6
- package/src/utils.ts +1 -15
- package/src/version.ts +4 -4
- package/src/installer/hooks/install.ts +0 -549
- package/src/installer/hooks/opencode-plugin.ts +0 -54
- package/src/installer/hooks/search-guard.ts +0 -272
package/src/spinner.ts
CHANGED
|
@@ -8,11 +8,14 @@ export class Spinner {
|
|
|
8
8
|
private frame = 0;
|
|
9
9
|
private belowLines = 0;
|
|
10
10
|
|
|
11
|
-
constructor(
|
|
11
|
+
constructor(
|
|
12
|
+
private readonly message: string,
|
|
13
|
+
private readonly stderr: SpinnerOutput = process.stderr,
|
|
14
|
+
) {}
|
|
12
15
|
|
|
13
16
|
start(): void {
|
|
14
|
-
if (!
|
|
15
|
-
|
|
17
|
+
if (!this.stderr.isTTY) {
|
|
18
|
+
this.stderr.write(`${this.message}...\n`);
|
|
16
19
|
return;
|
|
17
20
|
}
|
|
18
21
|
this.draw();
|
|
@@ -20,17 +23,17 @@ export class Spinner {
|
|
|
20
23
|
}
|
|
21
24
|
|
|
22
25
|
follow(line: string): void {
|
|
23
|
-
if (!
|
|
24
|
-
|
|
26
|
+
if (!this.stderr.isTTY) {
|
|
27
|
+
this.stderr.write(`${line}\n`);
|
|
25
28
|
return;
|
|
26
29
|
}
|
|
27
|
-
const cols =
|
|
30
|
+
const cols = this.stderr.columns || 80;
|
|
28
31
|
const rows = line.split("\n").reduce((count, part) => {
|
|
29
32
|
return count + Math.max(1, Math.ceil(displayWidth(part) / cols));
|
|
30
33
|
}, 0);
|
|
31
|
-
|
|
34
|
+
this.stderr.write(`\n${line}`);
|
|
32
35
|
this.belowLines += rows;
|
|
33
|
-
|
|
36
|
+
this.stderr.write(`\x1b[${this.belowLines}A`);
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
stop(finalMessage?: string): void {
|
|
@@ -38,19 +41,19 @@ export class Spinner {
|
|
|
38
41
|
clearInterval(this.timer);
|
|
39
42
|
this.timer = null;
|
|
40
43
|
}
|
|
41
|
-
if (
|
|
42
|
-
|
|
44
|
+
if (this.stderr.isTTY) {
|
|
45
|
+
this.stderr.write("\r\x1b[K");
|
|
43
46
|
if (finalMessage) {
|
|
44
|
-
|
|
47
|
+
this.stderr.write(finalMessage);
|
|
45
48
|
}
|
|
46
49
|
if (this.belowLines > 0) {
|
|
47
|
-
|
|
50
|
+
this.stderr.write(`\x1b[${this.belowLines}B`);
|
|
48
51
|
}
|
|
49
52
|
if (finalMessage || this.belowLines > 0) {
|
|
50
|
-
|
|
53
|
+
this.stderr.write("\n");
|
|
51
54
|
}
|
|
52
55
|
} else if (finalMessage) {
|
|
53
|
-
|
|
56
|
+
this.stderr.write(`${finalMessage}\n`);
|
|
54
57
|
}
|
|
55
58
|
}
|
|
56
59
|
|
|
@@ -68,16 +71,23 @@ export class Spinner {
|
|
|
68
71
|
|
|
69
72
|
private draw(): void {
|
|
70
73
|
const glyph = FRAMES[this.frame++ % FRAMES.length];
|
|
71
|
-
|
|
74
|
+
this.stderr.write(`\r${dim(glyph)} ${this.message}`);
|
|
72
75
|
}
|
|
73
76
|
}
|
|
74
77
|
|
|
78
|
+
interface SpinnerOutput {
|
|
79
|
+
isTTY?: boolean;
|
|
80
|
+
columns?: number;
|
|
81
|
+
write(text: string): unknown;
|
|
82
|
+
}
|
|
83
|
+
|
|
75
84
|
export async function withSpinner<T>(
|
|
76
85
|
message: string,
|
|
77
86
|
fn: () => Promise<T>,
|
|
78
87
|
options?: { successMessage?: string; failMessage?: string },
|
|
88
|
+
output: SpinnerOutput = process.stderr,
|
|
79
89
|
): Promise<T> {
|
|
80
|
-
const spinner = new Spinner(message);
|
|
90
|
+
const spinner = new Spinner(message, output);
|
|
81
91
|
spinner.start();
|
|
82
92
|
try {
|
|
83
93
|
const result = await fn();
|
|
@@ -99,9 +99,6 @@ function whitespaceTokenize(text: string): string[] {
|
|
|
99
99
|
|
|
100
100
|
function splitOnPunctuation(text: string): string[] {
|
|
101
101
|
const chars = [...text];
|
|
102
|
-
if (chars.length === 0) {
|
|
103
|
-
return [];
|
|
104
|
-
}
|
|
105
102
|
|
|
106
103
|
const output: string[][] = [];
|
|
107
104
|
let startNewWord = true;
|
|
@@ -138,9 +135,6 @@ function wordpieceTokenize(
|
|
|
138
135
|
prefix: string,
|
|
139
136
|
maxInputCharsPerWord: number,
|
|
140
137
|
): string[] {
|
|
141
|
-
if (token.length === 0) {
|
|
142
|
-
return [];
|
|
143
|
-
}
|
|
144
138
|
if (token.length > maxInputCharsPerWord) {
|
|
145
139
|
return [unkToken];
|
|
146
140
|
}
|
package/src/utils.ts
CHANGED
|
@@ -100,22 +100,12 @@ export type ExpandResults = {
|
|
|
100
100
|
chunks: Record<string, unknown>[];
|
|
101
101
|
};
|
|
102
102
|
|
|
103
|
-
export const
|
|
104
|
-
export const MAX_MCP_TOP_K = 10;
|
|
103
|
+
export const SEARCH_RESULT_COUNT = 5;
|
|
105
104
|
|
|
106
105
|
/** Extra chunks before/after the expand anchor — MCP `expand` tool defaults. */
|
|
107
106
|
export const DEFAULT_EXPAND_BEFORE = 1;
|
|
108
107
|
export const DEFAULT_EXPAND_AFTER = 1;
|
|
109
108
|
|
|
110
|
-
/** Clamp MCP top_k to a sane range; omit for the default. */
|
|
111
|
-
export function clampMcpTopK(topK?: number): number {
|
|
112
|
-
const value = topK ?? DEFAULT_MCP_TOP_K;
|
|
113
|
-
if (!Number.isFinite(value) || value < 1) {
|
|
114
|
-
return DEFAULT_MCP_TOP_K;
|
|
115
|
-
}
|
|
116
|
-
return Math.min(Math.floor(value), MAX_MCP_TOP_K);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
109
|
function chunkToResponseDict(chunk: Chunk, repoRoot?: string | null): Record<string, unknown> {
|
|
120
110
|
const dict = chunkToDict(chunk);
|
|
121
111
|
if (!repoRoot) {
|
|
@@ -175,10 +165,6 @@ export function expandChunksAtLine(
|
|
|
175
165
|
const anchorIndex = fileChunks.findIndex(
|
|
176
166
|
(chunk) => chunk.start_line === anchor.start_line && chunk.end_line === anchor.end_line,
|
|
177
167
|
);
|
|
178
|
-
if (anchorIndex < 0) {
|
|
179
|
-
return { anchor, chunks: [anchor] };
|
|
180
|
-
}
|
|
181
|
-
|
|
182
168
|
const start = Math.max(0, anchorIndex - before);
|
|
183
169
|
const end = Math.min(fileChunks.length, anchorIndex + after + 1);
|
|
184
170
|
return { anchor, chunks: fileChunks.slice(start, end) };
|
package/src/version.ts
CHANGED
|
@@ -26,8 +26,8 @@ export function miruVersion(): string {
|
|
|
26
26
|
* - 0.x releases: `0.{minor}` (chunking may break on minor bumps pre-1.0).
|
|
27
27
|
* - 1.x+: major version only.
|
|
28
28
|
*/
|
|
29
|
-
export function indexCacheEpoch(): string {
|
|
30
|
-
const parts =
|
|
29
|
+
export function indexCacheEpoch(version: string = packageJson.version): string {
|
|
30
|
+
const parts = version.split(".");
|
|
31
31
|
const major = parts[0] ?? "0";
|
|
32
32
|
const minor = parts[1] ?? "0";
|
|
33
33
|
if (major === "0") {
|
|
@@ -118,7 +118,7 @@ export async function fetchLatestPublishedVersion(fetchImpl: Fetcher = fetch): P
|
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
/** Print update hint to stderr when a newer package is on npm (at most once per day). */
|
|
121
|
-
export async function maybeNotifyUpdate(): Promise<void> {
|
|
121
|
+
export async function maybeNotifyUpdate(fetchImpl: Fetcher = fetch): Promise<void> {
|
|
122
122
|
if (process.env.MIRU_NO_UPDATE_CHECK === "1") {
|
|
123
123
|
return;
|
|
124
124
|
}
|
|
@@ -133,7 +133,7 @@ export async function maybeNotifyUpdate(): Promise<void> {
|
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
try {
|
|
136
|
-
const latest = await fetchLatestPublishedVersion();
|
|
136
|
+
const latest = await fetchLatestPublishedVersion(fetchImpl);
|
|
137
137
|
await writeUpdateCheckCache(latest);
|
|
138
138
|
if (isVersionNewer(latest, current)) {
|
|
139
139
|
writeUpdateNotice(latest, current);
|