proofscan 0.10.52 → 0.10.53

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.
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Filter DSL v0.1 Evaluator
3
+ *
4
+ * Evaluates parsed FilterAst against a FilterContext record.
5
+ * All conditions are ANDed together.
6
+ *
7
+ * No DOM dependencies - can be reused in CLI/Ledger.
8
+ */
9
+ import type { FilterAst, FilterContext } from './types.js';
10
+ /**
11
+ * Evaluate a filter AST against a context record
12
+ * @param ast - Parsed filter AST
13
+ * @param ctx - Context record to evaluate
14
+ * @returns true if record matches all conditions (implicit AND)
15
+ */
16
+ export declare function evaluateFilter(ast: FilterAst, ctx: FilterContext): boolean;
17
+ //# sourceMappingURL=evaluator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluator.d.ts","sourceRoot":"","sources":["../../src/filter/evaluator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAmB,aAAa,EAAE,MAAM,YAAY,CAAC;AAE5E;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,aAAa,GAAG,OAAO,CAQ1E"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Filter DSL v0.1 Evaluator
3
+ *
4
+ * Evaluates parsed FilterAst against a FilterContext record.
5
+ * All conditions are ANDed together.
6
+ *
7
+ * No DOM dependencies - can be reused in CLI/Ledger.
8
+ */
9
+ /**
10
+ * Evaluate a filter AST against a context record
11
+ * @param ast - Parsed filter AST
12
+ * @param ctx - Context record to evaluate
13
+ * @returns true if record matches all conditions (implicit AND)
14
+ */
15
+ export function evaluateFilter(ast, ctx) {
16
+ // Empty filter matches everything
17
+ if (ast.conditions.length === 0) {
18
+ return true;
19
+ }
20
+ // All conditions must match (implicit AND)
21
+ return ast.conditions.every((cond) => evaluateCondition(cond, ctx));
22
+ }
23
+ /**
24
+ * Evaluate a single condition against a context
25
+ */
26
+ function evaluateCondition(cond, ctx) {
27
+ const val = ctx[cond.field];
28
+ // null/undefined handling:
29
+ // - != returns true (field doesn't equal anything if it doesn't exist)
30
+ // - all other operators return false
31
+ if (val === null || val === undefined) {
32
+ return cond.operator === '!=';
33
+ }
34
+ switch (cond.operator) {
35
+ case '==':
36
+ return compareEqual(val, cond.value);
37
+ case '!=':
38
+ return !compareEqual(val, cond.value);
39
+ case '~=':
40
+ return compareSubstring(val, cond.value);
41
+ case '>':
42
+ return compareNumeric(val, cond.value, (a, b) => a > b);
43
+ case '<':
44
+ return compareNumeric(val, cond.value, (a, b) => a < b);
45
+ default:
46
+ return false;
47
+ }
48
+ }
49
+ /**
50
+ * Case-insensitive equality comparison
51
+ */
52
+ function compareEqual(fieldValue, condValue) {
53
+ return String(fieldValue).toLowerCase() === String(condValue).toLowerCase();
54
+ }
55
+ /**
56
+ * Case-insensitive substring match
57
+ */
58
+ function compareSubstring(fieldValue, condValue) {
59
+ return String(fieldValue).toLowerCase().includes(String(condValue).toLowerCase());
60
+ }
61
+ /**
62
+ * Numeric comparison with NaN guard
63
+ * Returns false if either value is not a valid number
64
+ */
65
+ function compareNumeric(fieldValue, condValue, compareFn) {
66
+ const numField = typeof fieldValue === 'number' ? fieldValue : Number(fieldValue);
67
+ const numCond = typeof condValue === 'number' ? condValue : Number(condValue);
68
+ if (isNaN(numField) || isNaN(numCond)) {
69
+ return false;
70
+ }
71
+ return compareFn(numField, numCond);
72
+ }
73
+ //# sourceMappingURL=evaluator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluator.js","sourceRoot":"","sources":["../../src/filter/evaluator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,GAAc,EAAE,GAAkB;IAC/D,kCAAkC;IAClC,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,2CAA2C;IAC3C,OAAO,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;AACtE,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB,CAAC,IAAqB,EAAE,GAAkB;IAClE,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAE5B,2BAA2B;IAC3B,uEAAuE;IACvE,qCAAqC;IACrC,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtC,OAAO,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC;IAChC,CAAC;IAED,QAAQ,IAAI,CAAC,QAAQ,EAAE,CAAC;QACtB,KAAK,IAAI;YACP,OAAO,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACvC,KAAK,IAAI;YACP,OAAO,CAAC,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACxC,KAAK,IAAI;YACP,OAAO,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3C,KAAK,GAAG;YACN,OAAO,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1D,KAAK,GAAG;YACN,OAAO,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1D;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,UAA2B,EAAE,SAA0B;IAC3E,OAAO,MAAM,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;AAC9E,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CAAC,UAA2B,EAAE,SAA0B;IAC/E,OAAO,MAAM,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AACpF,CAAC;AAED;;;GAGG;AACH,SAAS,cAAc,CACrB,UAA2B,EAC3B,SAA0B,EAC1B,SAA4C;IAE5C,MAAM,QAAQ,GAAG,OAAO,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAClF,MAAM,OAAO,GAAG,OAAO,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAE9E,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QACtC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AACtC,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Filter Field Definitions
3
+ *
4
+ * Provides metadata for autocomplete and validation.
5
+ * No DOM dependencies - can be reused in CLI/Ledger.
6
+ */
7
+ import type { FilterField } from './types.js';
8
+ /** Field definition for autocomplete and validation */
9
+ export interface FieldDefinition {
10
+ name: FilterField;
11
+ description: string;
12
+ type: 'string' | 'number';
13
+ examples?: string[];
14
+ }
15
+ /** All supported filter fields with metadata */
16
+ export declare const FILTER_FIELDS: FieldDefinition[];
17
+ /** Set of valid field names for fast lookup */
18
+ export declare const VALID_FIELDS: Set<string>;
19
+ /**
20
+ * Suggest fields matching a prefix (for autocomplete)
21
+ * @param prefix - The prefix to match (case-insensitive)
22
+ * @returns Array of matching field definitions
23
+ */
24
+ export declare function suggestFields(prefix: string): FieldDefinition[];
25
+ /**
26
+ * Check if a field name is valid
27
+ * @param field - Field name to check
28
+ * @returns true if valid
29
+ */
30
+ export declare function isValidField(field: string): field is FilterField;
31
+ //# sourceMappingURL=fields.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fields.d.ts","sourceRoot":"","sources":["../../src/filter/fields.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,uDAAuD;AACvD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,WAAW,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,gDAAgD;AAChD,eAAO,MAAM,aAAa,EAAE,eAAe,EA6D1C,CAAC;AAEF,+CAA+C;AAC/C,eAAO,MAAM,YAAY,EAAE,GAAG,CAAC,MAAM,CAA6C,CAAC;AAEnF;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe,EAAE,CAG/D;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,WAAW,CAEhE"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Filter Field Definitions
3
+ *
4
+ * Provides metadata for autocomplete and validation.
5
+ * No DOM dependencies - can be reused in CLI/Ledger.
6
+ */
7
+ /** All supported filter fields with metadata */
8
+ export const FILTER_FIELDS = [
9
+ {
10
+ name: 'session.id',
11
+ description: 'Session ID (ULID)',
12
+ type: 'string',
13
+ },
14
+ {
15
+ name: 'session.latency',
16
+ description: 'Total session latency (ms)',
17
+ type: 'number',
18
+ },
19
+ {
20
+ name: 'rpc.id',
21
+ description: 'RPC call ID',
22
+ type: 'string',
23
+ },
24
+ {
25
+ name: 'rpc.method',
26
+ description: 'RPC method name',
27
+ type: 'string',
28
+ examples: ['initialize', 'tools/call', 'tools/list', 'resources/list', 'prompts/list'],
29
+ },
30
+ {
31
+ name: 'rpc.status',
32
+ description: 'RPC status',
33
+ type: 'string',
34
+ examples: ['ok', 'err', 'pending'],
35
+ },
36
+ {
37
+ name: 'rpc.latency',
38
+ description: 'RPC latency (ms)',
39
+ type: 'number',
40
+ },
41
+ {
42
+ name: 'tools.method',
43
+ description: 'Tool method (alias of tools.name)',
44
+ type: 'string',
45
+ },
46
+ {
47
+ name: 'tools.name',
48
+ description: 'Called tool name',
49
+ type: 'string',
50
+ },
51
+ {
52
+ name: 'event.kind',
53
+ description: 'Event kind',
54
+ type: 'string',
55
+ examples: ['request', 'response', 'notification', 'transport_event'],
56
+ },
57
+ {
58
+ name: 'event.type',
59
+ description: 'Transport event type',
60
+ type: 'string',
61
+ examples: ['connected', 'disconnected'],
62
+ },
63
+ {
64
+ name: 'direction',
65
+ description: 'Message direction',
66
+ type: 'string',
67
+ examples: ['req', 'res', 'trans'],
68
+ },
69
+ ];
70
+ /** Set of valid field names for fast lookup */
71
+ export const VALID_FIELDS = new Set(FILTER_FIELDS.map((f) => f.name));
72
+ /**
73
+ * Suggest fields matching a prefix (for autocomplete)
74
+ * @param prefix - The prefix to match (case-insensitive)
75
+ * @returns Array of matching field definitions
76
+ */
77
+ export function suggestFields(prefix) {
78
+ const lower = prefix.toLowerCase();
79
+ return FILTER_FIELDS.filter((f) => f.name.startsWith(lower));
80
+ }
81
+ /**
82
+ * Check if a field name is valid
83
+ * @param field - Field name to check
84
+ * @returns true if valid
85
+ */
86
+ export function isValidField(field) {
87
+ return VALID_FIELDS.has(field);
88
+ }
89
+ //# sourceMappingURL=fields.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fields.js","sourceRoot":"","sources":["../../src/filter/fields.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,gDAAgD;AAChD,MAAM,CAAC,MAAM,aAAa,GAAsB;IAC9C;QACE,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,mBAAmB;QAChC,IAAI,EAAE,QAAQ;KACf;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,WAAW,EAAE,4BAA4B;QACzC,IAAI,EAAE,QAAQ;KACf;IACD;QACE,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,aAAa;QAC1B,IAAI,EAAE,QAAQ;KACf;IACD;QACE,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,iBAAiB;QAC9B,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,cAAc,CAAC;KACvF;IACD;QACE,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,YAAY;QACzB,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,CAAC;KACnC;IACD;QACE,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,kBAAkB;QAC/B,IAAI,EAAE,QAAQ;KACf;IACD;QACE,IAAI,EAAE,cAAc;QACpB,WAAW,EAAE,mCAAmC;QAChD,IAAI,EAAE,QAAQ;KACf;IACD;QACE,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,kBAAkB;QAC/B,IAAI,EAAE,QAAQ;KACf;IACD;QACE,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,YAAY;QACzB,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,cAAc,EAAE,iBAAiB,CAAC;KACrE;IACD;QACE,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,sBAAsB;QACnC,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,CAAC,WAAW,EAAE,cAAc,CAAC;KACxC;IACD;QACE,IAAI,EAAE,WAAW;QACjB,WAAW,EAAE,mBAAmB;QAChC,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC;KAClC;CACF,CAAC;AAEF,+CAA+C;AAC/C,MAAM,CAAC,MAAM,YAAY,GAAgB,IAAI,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAEnF;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IACnC,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,OAAO,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACjC,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Filter DSL v0.1
3
+ *
4
+ * Public API for filter parsing and evaluation.
5
+ * No DOM dependencies - can be reused in CLI/Ledger.
6
+ */
7
+ export type { FilterAst, FilterCondition, FilterContext, FilterField, FilterOperator, ParseResult, } from './types.js';
8
+ export type { FieldDefinition } from './fields.js';
9
+ export { FILTER_FIELDS, VALID_FIELDS, isValidField, suggestFields } from './fields.js';
10
+ export { parseFilter } from './parser.js';
11
+ export { evaluateFilter } from './evaluator.js';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/filter/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,YAAY,EACV,SAAS,EACT,eAAe,EACf,aAAa,EACb,WAAW,EACX,cAAc,EACd,WAAW,GACZ,MAAM,YAAY,CAAC;AAGpB,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGvF,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Filter DSL v0.1
3
+ *
4
+ * Public API for filter parsing and evaluation.
5
+ * No DOM dependencies - can be reused in CLI/Ledger.
6
+ */
7
+ export { FILTER_FIELDS, VALID_FIELDS, isValidField, suggestFields } from './fields.js';
8
+ // Parser
9
+ export { parseFilter } from './parser.js';
10
+ // Evaluator
11
+ export { evaluateFilter } from './evaluator.js';
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/filter/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAcH,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEvF,SAAS;AACT,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,YAAY;AACZ,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Filter DSL v0.1 Parser
3
+ *
4
+ * Grammar:
5
+ * filter = condition ( condition )*
6
+ * condition = field operator value
7
+ * field = identifier ( '.' identifier )?
8
+ * operator = '==' | '!=' | '~=' | '>' | '<'
9
+ * value = string_literal | number_literal
10
+ *
11
+ * String literals: "value" or 'value'
12
+ * Numbers: 123 or 123.45 or -123
13
+ *
14
+ * No DOM dependencies - can be reused in CLI/Ledger.
15
+ */
16
+ import type { ParseResult } from './types.js';
17
+ /**
18
+ * Parse a filter expression into an AST
19
+ * @param input - The filter expression (optionally prefixed with "filter:")
20
+ * @returns ParseResult with AST or error
21
+ */
22
+ export declare function parseFilter(input: string): ParseResult;
23
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/filter/parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAA2D,WAAW,EAAE,MAAM,YAAY,CAAC;AAMvG;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAuDtD"}
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Filter DSL v0.1 Parser
3
+ *
4
+ * Grammar:
5
+ * filter = condition ( condition )*
6
+ * condition = field operator value
7
+ * field = identifier ( '.' identifier )?
8
+ * operator = '==' | '!=' | '~=' | '>' | '<'
9
+ * value = string_literal | number_literal
10
+ *
11
+ * String literals: "value" or 'value'
12
+ * Numbers: 123 or 123.45 or -123
13
+ *
14
+ * No DOM dependencies - can be reused in CLI/Ledger.
15
+ */
16
+ import { isValidField } from './fields.js';
17
+ /** Valid operators in order of length (longest first for matching) */
18
+ const OPERATORS = ['==', '!=', '~=', '>', '<'];
19
+ /**
20
+ * Parse a filter expression into an AST
21
+ * @param input - The filter expression (optionally prefixed with "filter:")
22
+ * @returns ParseResult with AST or error
23
+ */
24
+ export function parseFilter(input) {
25
+ // Strip optional "filter:" prefix for copy/paste compatibility
26
+ let trimmed = input.trim();
27
+ if (trimmed.toLowerCase().startsWith('filter:')) {
28
+ trimmed = trimmed.slice(7).trim();
29
+ }
30
+ // Empty filter matches everything
31
+ if (!trimmed) {
32
+ return { ok: true, ast: { conditions: [] } };
33
+ }
34
+ const conditions = [];
35
+ let pos = 0;
36
+ while (pos < trimmed.length) {
37
+ // Skip whitespace
38
+ pos = skipWhitespace(trimmed, pos);
39
+ if (pos >= trimmed.length)
40
+ break;
41
+ // Parse field
42
+ const fieldResult = parseField(trimmed, pos);
43
+ if (!fieldResult.ok) {
44
+ return { ok: false, error: fieldResult.error, position: fieldResult.position };
45
+ }
46
+ pos = fieldResult.pos;
47
+ // Skip whitespace
48
+ pos = skipWhitespace(trimmed, pos);
49
+ // Parse operator
50
+ const opResult = parseOperator(trimmed, pos);
51
+ if (!opResult.ok) {
52
+ return { ok: false, error: opResult.error, position: opResult.position };
53
+ }
54
+ pos = opResult.pos;
55
+ // Skip whitespace
56
+ pos = skipWhitespace(trimmed, pos);
57
+ // Parse value
58
+ const valResult = parseValue(trimmed, pos);
59
+ if (!valResult.ok) {
60
+ return { ok: false, error: valResult.error, position: valResult.position };
61
+ }
62
+ pos = valResult.pos;
63
+ conditions.push({
64
+ field: fieldResult.field,
65
+ operator: opResult.operator,
66
+ value: valResult.value,
67
+ });
68
+ }
69
+ return { ok: true, ast: { conditions } };
70
+ }
71
+ /** Skip whitespace characters */
72
+ function skipWhitespace(input, pos) {
73
+ while (pos < input.length && /\s/.test(input[pos])) {
74
+ pos++;
75
+ }
76
+ return pos;
77
+ }
78
+ /** Parse a field name (e.g., "rpc.method") */
79
+ function parseField(input, pos) {
80
+ const start = pos;
81
+ // Read identifier characters (letters, digits, dots, underscores)
82
+ while (pos < input.length && /[a-zA-Z0-9_.]/.test(input[pos])) {
83
+ pos++;
84
+ }
85
+ if (pos === start) {
86
+ return { ok: false, error: `Expected field name at char ${start + 1}`, position: start };
87
+ }
88
+ const field = input.slice(start, pos);
89
+ if (!isValidField(field)) {
90
+ return { ok: false, error: `Unknown field '${field}' at char ${start + 1}`, position: start };
91
+ }
92
+ return { ok: true, field, pos };
93
+ }
94
+ /** Parse an operator (==, !=, ~=, >, <) */
95
+ function parseOperator(input, pos) {
96
+ for (const op of OPERATORS) {
97
+ if (input.slice(pos, pos + op.length) === op) {
98
+ return { ok: true, operator: op, pos: pos + op.length };
99
+ }
100
+ }
101
+ return {
102
+ ok: false,
103
+ error: `Expected operator (==, !=, ~=, >, <) at char ${pos + 1}`,
104
+ position: pos,
105
+ };
106
+ }
107
+ /** Parse a value (string literal or number) */
108
+ function parseValue(input, pos) {
109
+ if (pos >= input.length) {
110
+ return { ok: false, error: `Expected value at char ${pos + 1}`, position: pos };
111
+ }
112
+ const char = input[pos];
113
+ // String literal with double quotes
114
+ if (char === '"') {
115
+ return parseStringLiteral(input, pos, '"');
116
+ }
117
+ // String literal with single quotes
118
+ if (char === "'") {
119
+ return parseStringLiteral(input, pos, "'");
120
+ }
121
+ // Number (including negative)
122
+ if (/[0-9\-]/.test(char)) {
123
+ return parseNumber(input, pos);
124
+ }
125
+ // Unquoted identifier (for convenience)
126
+ if (/[a-zA-Z_]/.test(char)) {
127
+ return parseUnquotedValue(input, pos);
128
+ }
129
+ return { ok: false, error: `Unexpected character '${char}' at char ${pos + 1}`, position: pos };
130
+ }
131
+ /** Parse a quoted string literal */
132
+ function parseStringLiteral(input, pos, quote) {
133
+ const start = pos;
134
+ pos++; // Skip opening quote
135
+ let value = '';
136
+ while (pos < input.length) {
137
+ const char = input[pos];
138
+ if (char === quote) {
139
+ return { ok: true, value, pos: pos + 1 };
140
+ }
141
+ if (char === '\\' && pos + 1 < input.length) {
142
+ // Handle escape sequences
143
+ const next = input[pos + 1];
144
+ if (next === quote || next === '\\') {
145
+ value += next;
146
+ pos += 2;
147
+ continue;
148
+ }
149
+ }
150
+ value += char;
151
+ pos++;
152
+ }
153
+ return { ok: false, error: `Unterminated string starting at char ${start + 1}`, position: start };
154
+ }
155
+ /** Parse a number (integer or decimal) */
156
+ function parseNumber(input, pos) {
157
+ const start = pos;
158
+ // Optional negative sign
159
+ if (input[pos] === '-') {
160
+ pos++;
161
+ }
162
+ // Must have at least one digit
163
+ if (pos >= input.length || !/[0-9]/.test(input[pos])) {
164
+ return { ok: false, error: `Expected number at char ${start + 1}`, position: start };
165
+ }
166
+ // Integer part
167
+ while (pos < input.length && /[0-9]/.test(input[pos])) {
168
+ pos++;
169
+ }
170
+ // Optional decimal part
171
+ if (pos < input.length && input[pos] === '.') {
172
+ pos++;
173
+ while (pos < input.length && /[0-9]/.test(input[pos])) {
174
+ pos++;
175
+ }
176
+ }
177
+ const numStr = input.slice(start, pos);
178
+ const value = Number(numStr);
179
+ if (isNaN(value)) {
180
+ return { ok: false, error: `Invalid number '${numStr}' at char ${start + 1}`, position: start };
181
+ }
182
+ return { ok: true, value, pos };
183
+ }
184
+ /** Parse an unquoted value (for convenience, e.g., ok instead of "ok") */
185
+ function parseUnquotedValue(input, pos) {
186
+ const start = pos;
187
+ while (pos < input.length && /[a-zA-Z0-9_/\-]/.test(input[pos])) {
188
+ pos++;
189
+ }
190
+ if (pos === start) {
191
+ return { ok: false, error: `Expected value at char ${start + 1}`, position: start };
192
+ }
193
+ return { ok: true, value: input.slice(start, pos), pos };
194
+ }
195
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/filter/parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,sEAAsE;AACtE,MAAM,SAAS,GAAqB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAEjE;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,+DAA+D;IAC/D,IAAI,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC3B,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAChD,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACpC,CAAC;IAED,kCAAkC;IAClC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,CAAC;IAC/C,CAAC;IAED,MAAM,UAAU,GAAsB,EAAE,CAAC;IACzC,IAAI,GAAG,GAAG,CAAC,CAAC;IAEZ,OAAO,GAAG,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;QAC5B,kBAAkB;QAClB,GAAG,GAAG,cAAc,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QACnC,IAAI,GAAG,IAAI,OAAO,CAAC,MAAM;YAAE,MAAM;QAEjC,cAAc;QACd,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAC7C,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC;YACpB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,EAAE,QAAQ,EAAE,WAAW,CAAC,QAAQ,EAAE,CAAC;QACjF,CAAC;QACD,GAAG,GAAG,WAAW,CAAC,GAAG,CAAC;QAEtB,kBAAkB;QAClB,GAAG,GAAG,cAAc,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAEnC,iBAAiB;QACjB,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAC7C,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC;QAC3E,CAAC;QACD,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC;QAEnB,kBAAkB;QAClB,GAAG,GAAG,cAAc,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAEnC,cAAc;QACd,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAC3C,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC;YAClB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC;QAC7E,CAAC;QACD,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC;QAEpB,UAAU,CAAC,IAAI,CAAC;YACd,KAAK,EAAE,WAAW,CAAC,KAAK;YACxB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,KAAK,EAAE,SAAS,CAAC,KAAK;SACvB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,UAAU,EAAE,EAAE,CAAC;AAC3C,CAAC;AAED,iCAAiC;AACjC,SAAS,cAAc,CAAC,KAAa,EAAE,GAAW;IAChD,OAAO,GAAG,GAAG,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QACnD,GAAG,EAAE,CAAC;IACR,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,8CAA8C;AAC9C,SAAS,UAAU,CACjB,KAAa,EACb,GAAW;IAEX,MAAM,KAAK,GAAG,GAAG,CAAC;IAElB,kEAAkE;IAClE,OAAO,GAAG,GAAG,KAAK,CAAC,MAAM,IAAI,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QAC9D,GAAG,EAAE,CAAC;IACR,CAAC;IAED,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;QAClB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,+BAA+B,KAAK,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAC3F,CAAC;IAED,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAEtC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,kBAAkB,KAAK,aAAa,KAAK,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAChG,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;AAClC,CAAC;AAED,2CAA2C;AAC3C,SAAS,aAAa,CACpB,KAAa,EACb,GAAW;IAEX,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC;YAC7C,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC;QAC1D,CAAC;IACH,CAAC;IAED,OAAO;QACL,EAAE,EAAE,KAAK;QACT,KAAK,EAAE,gDAAgD,GAAG,GAAG,CAAC,EAAE;QAChE,QAAQ,EAAE,GAAG;KACd,CAAC;AACJ,CAAC;AAED,+CAA+C;AAC/C,SAAS,UAAU,CACjB,KAAa,EACb,GAAW;IAEX,IAAI,GAAG,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACxB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,0BAA0B,GAAG,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;IAClF,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;IAExB,oCAAoC;IACpC,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;QACjB,OAAO,kBAAkB,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAC7C,CAAC;IAED,oCAAoC;IACpC,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;QACjB,OAAO,kBAAkB,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAC7C,CAAC;IAED,8BAA8B;IAC9B,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,OAAO,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACjC,CAAC;IAED,wCAAwC;IACxC,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,OAAO,kBAAkB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACxC,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,yBAAyB,IAAI,aAAa,GAAG,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;AAClG,CAAC;AAED,oCAAoC;AACpC,SAAS,kBAAkB,CACzB,KAAa,EACb,GAAW,EACX,KAAgB;IAEhB,MAAM,KAAK,GAAG,GAAG,CAAC;IAClB,GAAG,EAAE,CAAC,CAAC,qBAAqB;IAE5B,IAAI,KAAK,GAAG,EAAE,CAAC;IACf,OAAO,GAAG,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;QAExB,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;YACnB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC,EAAE,CAAC;QAC3C,CAAC;QAED,IAAI,IAAI,KAAK,IAAI,IAAI,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YAC5C,0BAA0B;YAC1B,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;YAC5B,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBACpC,KAAK,IAAI,IAAI,CAAC;gBACd,GAAG,IAAI,CAAC,CAAC;gBACT,SAAS;YACX,CAAC;QACH,CAAC;QAED,KAAK,IAAI,IAAI,CAAC;QACd,GAAG,EAAE,CAAC;IACR,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,wCAAwC,KAAK,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AACpG,CAAC;AAED,0CAA0C;AAC1C,SAAS,WAAW,CAClB,KAAa,EACb,GAAW;IAEX,MAAM,KAAK,GAAG,GAAG,CAAC;IAElB,yBAAyB;IACzB,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC;QACvB,GAAG,EAAE,CAAC;IACR,CAAC;IAED,+BAA+B;IAC/B,IAAI,GAAG,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QACrD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,2BAA2B,KAAK,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IACvF,CAAC;IAED,eAAe;IACf,OAAO,GAAG,GAAG,KAAK,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QACtD,GAAG,EAAE,CAAC;IACR,CAAC;IAED,wBAAwB;IACxB,IAAI,GAAG,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC;QAC7C,GAAG,EAAE,CAAC;QACN,OAAO,GAAG,GAAG,KAAK,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YACtD,GAAG,EAAE,CAAC;QACR,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAE7B,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACjB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,mBAAmB,MAAM,aAAa,KAAK,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAClG,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;AAClC,CAAC;AAED,0EAA0E;AAC1E,SAAS,kBAAkB,CACzB,KAAa,EACb,GAAW;IAEX,MAAM,KAAK,GAAG,GAAG,CAAC;IAElB,OAAO,GAAG,GAAG,KAAK,CAAC,MAAM,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QAChE,GAAG,EAAE,CAAC;IACR,CAAC;IAED,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;QAClB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,0BAA0B,KAAK,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IACtF,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Filter DSL v0.1 Types
3
+ *
4
+ * Single-line expression: `rpc.method == "tools/call" rpc.status == "ok"`
5
+ * Conditions are space-separated (implicit AND).
6
+ */
7
+ /** Supported comparison operators */
8
+ export type FilterOperator = '==' | '!=' | '~=' | '>' | '<';
9
+ /** Supported field paths */
10
+ export type FilterField = 'session.id' | 'session.latency' | 'rpc.id' | 'rpc.method' | 'rpc.status' | 'rpc.latency' | 'tools.method' | 'tools.name' | 'event.kind' | 'event.type' | 'direction';
11
+ /** Single condition in the filter expression */
12
+ export interface FilterCondition {
13
+ field: FilterField;
14
+ operator: FilterOperator;
15
+ value: string | number;
16
+ }
17
+ /** Parsed filter AST (implicit AND of all conditions) */
18
+ export interface FilterAst {
19
+ conditions: FilterCondition[];
20
+ }
21
+ /** Parser result with success/error status */
22
+ export type ParseResult = {
23
+ ok: true;
24
+ ast: FilterAst;
25
+ } | {
26
+ ok: false;
27
+ error: string;
28
+ position?: number;
29
+ };
30
+ /**
31
+ * Evaluation context - the data record to evaluate.
32
+ * Uses FilterField as keys for direct access in evaluator.
33
+ */
34
+ export type FilterContext = Partial<Record<FilterField, string | number | null>>;
35
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/filter/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,qCAAqC;AACrC,MAAM,MAAM,cAAc,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC;AAE5D,4BAA4B;AAC5B,MAAM,MAAM,WAAW,GACnB,YAAY,GACZ,iBAAiB,GACjB,QAAQ,GACR,YAAY,GACZ,YAAY,GACZ,aAAa,GACb,cAAc,GACd,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,WAAW,CAAC;AAEhB,gDAAgD;AAChD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,EAAE,cAAc,CAAC;IACzB,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;CACxB;AAED,yDAAyD;AACzD,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,eAAe,EAAE,CAAC;CAC/B;AAED,8CAA8C;AAC9C,MAAM,MAAM,WAAW,GACnB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,SAAS,CAAA;CAAE,GAC5B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpD;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Filter DSL v0.1 Types
3
+ *
4
+ * Single-line expression: `rpc.method == "tools/call" rpc.status == "ok"`
5
+ * Conditions are space-separated (implicit AND).
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/filter/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -2572,7 +2572,7 @@ function renderTopTools(topTools) {
2572
2572
  const rows = topTools.items
2573
2573
  .map((tool, idx) => {
2574
2574
  return `
2575
- <div class="top-tool-row">
2575
+ <div class="top-tool-row" data-tool-name="${escapeHtml(tool.name)}">
2576
2576
  <span class="top-tool-rank">${idx + 1}.</span>
2577
2577
  <span class="top-tool-name" title="${escapeHtml(tool.name)}">${escapeHtml(tool.name)}</span>
2578
2578
  <div class="top-tool-bar-container">