Skip to content

Commit 0f4e4ce

Browse files
betegonclaude
andcommitted
fix(search-events): rejoin IN-list env filters split by the tokenizer
Bugbot: tokenizeSearchQuery splits `environment:[a, b]` on the internal space, so the bracket-list parser saw a truncated token (garbage env + dropped names). Rejoin following tokens until the list closes before parsing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 48fe1a8 commit 0f4e4ce

2 files changed

Lines changed: 19 additions & 4 deletions

File tree

‎packages/mcp-core/src/tools/catalog/search-events-environment-note.test.ts‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ describe("collectRequestedEnvironments", () => {
2626
expect(
2727
collectRequestedEnvironments(null, "environment:[prod,dev]"),
2828
).toEqual(["prod", "dev"]);
29+
// IN-list with spaces after commas (official syntax) — tokenizer splits it,
30+
// so it must be rejoined rather than parsed as garbage.
31+
expect(
32+
collectRequestedEnvironments(null, "environment:[prod, dev] level:error"),
33+
).toEqual(["prod", "dev"]);
2934
expect(collectRequestedEnvironments(null, 'environment:"qa eu"')).toEqual([
3035
"qa eu",
3136
]);

‎packages/mcp-core/src/tools/catalog/search-events.ts‎

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,14 +191,24 @@ export function collectRequestedEnvironments(
191191
// Tokenize (quote/escape-aware) and only take tokens that ARE an `environment:`
192192
// filter, so dotted keys like `deployment.environment:` and `environment:`
193193
// inside quoted text (e.g. a message value) aren't mistaken for a filter.
194-
for (const token of tokenizeSearchQuery(query)) {
195-
const match = /^environment:(.*)$/is.exec(token);
194+
const tokens = tokenizeSearchQuery(query);
195+
for (let i = 0; i < tokens.length; i++) {
196+
const match = /^environment:(.*)$/is.exec(tokens[i]);
196197
if (!match) {
197198
continue;
198199
}
199-
const raw = match[1];
200+
let value = match[1];
201+
// An IN-list (`environment:[a, b]`) can be split across tokens on its
202+
// internal spaces; rejoin following tokens until the list is closed.
203+
while (
204+
value.startsWith("[") &&
205+
!value.includes("]") &&
206+
i + 1 < tokens.length
207+
) {
208+
value += ` ${tokens[++i]}`;
209+
}
200210
const inner =
201-
raw.startsWith("[") && raw.endsWith("]") ? raw.slice(1, -1) : raw;
211+
value.startsWith("[") && value.endsWith("]") ? value.slice(1, -1) : value;
202212
for (const part of inner.split(",")) {
203213
const cleaned = part.trim().replace(/^["']|["']$/g, "");
204214
if (cleaned) {

0 commit comments

Comments
 (0)