@takara-ai/miru-code 1.3.0 → 1.3.1

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": "@takara-ai/miru-code",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "Miru (見る) — hybrid code search for agents. Bun, TypeScript, Takara embeddings.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -47,8 +47,13 @@ export async function benchmarkLocateComparison(options: {
47
47
  const miruTok = countTokens(JSON.stringify(payload));
48
48
 
49
49
  // Unbounded agent-style Grep dump (±context) — the costlier path without locate.
50
- const grep = await rgLiteralOutput(options.repoPath, options.literal, {
51
- context: GREP_CONTEXT,
50
+ // Never use less context than the caller actually requested via context_lines,
51
+ // or a locate call that returns inline context looks artificially expensive
52
+ // against a baseline that didn't have to fetch that context at all. Likewise,
53
+ // grep every variant `match_variants`/an array `literal` actually matched —
54
+ // one grep pattern isn't equivalent recall, so it isn't a fair baseline.
55
+ const grep = await rgLiteralOutput(options.repoPath, result.literals ?? [options.literal], {
56
+ context: Math.max(GREP_CONTEXT, locateOpts.context_lines ?? 0),
52
57
  maxCount: 0,
53
58
  ignoreCase: locateOpts.ignore_case,
54
59
  });
@@ -61,13 +61,14 @@ function parsePathLinePrefix(line: string): { path: string; line: number } | nul
61
61
 
62
62
  export async function rgLiteralOutput(
63
63
  repoRoot: string,
64
- literal: string,
64
+ literal: string | readonly string[],
65
65
  options: {
66
66
  context?: number;
67
67
  maxCount?: number;
68
68
  ignoreCase?: boolean;
69
69
  } = {},
70
70
  ): Promise<RgLiteralOutput> {
71
+ const literals = Array.isArray(literal) ? literal : [literal as string];
71
72
  const context = options.context ?? 0;
72
73
  const maxCount = options.maxCount ?? 20;
73
74
  const tool = selectBenchmarkSearchTool();
@@ -76,7 +77,7 @@ export async function rgLiteralOutput(
76
77
  }
77
78
  const start = performance.now();
78
79
  const proc = Bun.spawn(
79
- buildLiteralArgs(tool, repoRoot, literal, context, maxCount, !!options.ignoreCase),
80
+ buildLiteralArgs(tool, repoRoot, literals, context, maxCount, !!options.ignoreCase),
80
81
  {
81
82
  stdout: "pipe",
82
83
  stderr: "pipe",
@@ -90,10 +91,14 @@ export async function rgLiteralOutput(
90
91
  return { text, tokens: countTokens(text), latency_ms, ...stats };
91
92
  }
92
93
 
94
+ /**
95
+ * OR-matches every literal, mirroring what an agent without `locate` would have to run
96
+ * to get the same recall as `literals`/`match_variants` (one pattern isn't equivalent).
97
+ */
93
98
  function buildLiteralArgs(
94
99
  tool: "rg" | "grep" | "findstr",
95
100
  repoRoot: string,
96
- literal: string,
101
+ literals: readonly string[],
97
102
  context: number,
98
103
  maxCount: number,
99
104
  ignoreCase: boolean,
@@ -109,7 +114,10 @@ function buildLiteralArgs(
109
114
  if (maxCount > 0) {
110
115
  args.push("-m", String(maxCount));
111
116
  }
112
- args.push(literal, repoRoot);
117
+ for (const l of literals) {
118
+ args.push("-e", l);
119
+ }
120
+ args.push(repoRoot);
113
121
  return args;
114
122
  }
115
123
  if (tool === "grep") {
@@ -132,10 +140,17 @@ function buildLiteralArgs(
132
140
  if (maxCount > 0) {
133
141
  args.push("-m", String(maxCount));
134
142
  }
135
- args.push(literal, repoRoot);
143
+ for (const l of literals) {
144
+ args.push("-e", l);
145
+ }
146
+ args.push(repoRoot);
136
147
  return args;
137
148
  }
138
- const args = ["findstr", "/S", "/N", "/P", `/C:${literal}`, "*"];
149
+ const args = ["findstr", "/S", "/N", "/P"];
150
+ for (const l of literals) {
151
+ args.push(`/C:${l}`);
152
+ }
153
+ args.push("*");
139
154
  if (ignoreCase) {
140
155
  args.splice(4, 0, "/I");
141
156
  }