@guckdev/core 0.1.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.
Files changed (62) hide show
  1. package/dist/config.d.ts +19 -0
  2. package/dist/config.d.ts.map +1 -0
  3. package/dist/config.js +178 -0
  4. package/dist/config.js.map +1 -0
  5. package/dist/index.d.ts +7 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +7 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/redact.d.ts +3 -0
  10. package/dist/redact.d.ts.map +1 -0
  11. package/dist/redact.js +68 -0
  12. package/dist/redact.js.map +1 -0
  13. package/dist/schema.d.ts +113 -0
  14. package/dist/schema.d.ts.map +1 -0
  15. package/dist/schema.js +2 -0
  16. package/dist/schema.js.map +1 -0
  17. package/dist/store/backends/cloudwatch.d.ts +4 -0
  18. package/dist/store/backends/cloudwatch.d.ts.map +1 -0
  19. package/dist/store/backends/cloudwatch.js +302 -0
  20. package/dist/store/backends/cloudwatch.js.map +1 -0
  21. package/dist/store/backends/k8s.d.ts +4 -0
  22. package/dist/store/backends/k8s.d.ts.map +1 -0
  23. package/dist/store/backends/k8s.js +307 -0
  24. package/dist/store/backends/k8s.js.map +1 -0
  25. package/dist/store/backends/local.d.ts +10 -0
  26. package/dist/store/backends/local.d.ts.map +1 -0
  27. package/dist/store/backends/local.js +31 -0
  28. package/dist/store/backends/local.js.map +1 -0
  29. package/dist/store/backends/types.d.ts +25 -0
  30. package/dist/store/backends/types.d.ts.map +1 -0
  31. package/dist/store/backends/types.js +2 -0
  32. package/dist/store/backends/types.js.map +1 -0
  33. package/dist/store/file-store.d.ts +21 -0
  34. package/dist/store/file-store.d.ts.map +1 -0
  35. package/dist/store/file-store.js +169 -0
  36. package/dist/store/file-store.js.map +1 -0
  37. package/dist/store/filters.d.ts +4 -0
  38. package/dist/store/filters.d.ts.map +1 -0
  39. package/dist/store/filters.js +73 -0
  40. package/dist/store/filters.js.map +1 -0
  41. package/dist/store/read-store.d.ts +35 -0
  42. package/dist/store/read-store.d.ts.map +1 -0
  43. package/dist/store/read-store.js +256 -0
  44. package/dist/store/read-store.js.map +1 -0
  45. package/dist/store/time.d.ts +4 -0
  46. package/dist/store/time.d.ts.map +1 -0
  47. package/dist/store/time.js +47 -0
  48. package/dist/store/time.js.map +1 -0
  49. package/package.json +38 -0
  50. package/src/config.ts +210 -0
  51. package/src/index.ts +6 -0
  52. package/src/redact.ts +83 -0
  53. package/src/schema.ts +130 -0
  54. package/src/store/backends/cloudwatch.ts +373 -0
  55. package/src/store/backends/k8s.ts +400 -0
  56. package/src/store/backends/local.ts +47 -0
  57. package/src/store/backends/types.ts +18 -0
  58. package/src/store/file-store.ts +217 -0
  59. package/src/store/filters.ts +83 -0
  60. package/src/store/read-store.ts +340 -0
  61. package/src/store/time.ts +54 -0
  62. package/tsconfig.json +19 -0
@@ -0,0 +1,31 @@
1
+ import { listSessions, searchEvents, statsEvents } from "../file-store.js";
2
+ const tagLocalSource = (event, backendId) => {
3
+ const source = event.source ?? { kind: "mcp" };
4
+ return {
5
+ ...event,
6
+ source: {
7
+ ...source,
8
+ backend: "local",
9
+ backend_id: backendId ?? source.backend_id,
10
+ },
11
+ };
12
+ };
13
+ export const createLocalBackend = (options) => {
14
+ const { storeDir, config, backendId } = options;
15
+ return {
16
+ search: async (params) => {
17
+ const result = await searchEvents(storeDir, config, params);
18
+ return {
19
+ ...result,
20
+ events: result.events.map((event) => tagLocalSource(event, backendId)),
21
+ };
22
+ },
23
+ stats: async (params) => {
24
+ return statsEvents(storeDir, config, params);
25
+ },
26
+ sessions: async (params) => {
27
+ return listSessions(storeDir, config, params);
28
+ },
29
+ };
30
+ };
31
+ //# sourceMappingURL=local.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local.js","sourceRoot":"","sources":["../../../src/store/backends/local.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAS3E,MAAM,cAAc,GAAG,CAAC,KAAgB,EAAE,SAAkB,EAAa,EAAE;IACzE,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,EAAE,IAAI,EAAE,KAAc,EAAE,CAAC;IACxD,OAAO;QACL,GAAG,KAAK;QACR,MAAM,EAAE;YACN,GAAG,MAAM;YACT,OAAO,EAAE,OAAO;YAChB,UAAU,EAAE,SAAS,IAAI,MAAM,CAAC,UAAU;SAC3C;KACF,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,OAA4B,EAAe,EAAE;IAC9E,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAEhD,OAAO;QACL,MAAM,EAAE,KAAK,EAAE,MAAwB,EAAyB,EAAE;YAChE,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YAC5D,OAAO;gBACL,GAAG,MAAM;gBACT,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;aACvE,CAAC;QACJ,CAAC;QACD,KAAK,EAAE,KAAK,EAAE,MAAuB,EAAwB,EAAE;YAC7D,OAAO,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QAC/C,CAAC;QACD,QAAQ,EAAE,KAAK,EAAE,MAA0B,EAA2B,EAAE;YACtE,OAAO,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QAChD,CAAC;KACF,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { GuckEvent, GuckSearchParams, GuckStatsParams, GuckSessionsParams } from "../../schema.js";
2
+ export type SearchResult = {
3
+ events: GuckEvent[];
4
+ truncated: boolean;
5
+ };
6
+ export type StatsResult = {
7
+ buckets: Array<{
8
+ key: string;
9
+ count: number;
10
+ }>;
11
+ };
12
+ export type SessionsResult = {
13
+ sessions: Array<{
14
+ session_id: string;
15
+ last_ts: string;
16
+ event_count: number;
17
+ error_count: number;
18
+ }>;
19
+ };
20
+ export type ReadBackend = {
21
+ search: (params: GuckSearchParams) => Promise<SearchResult>;
22
+ stats: (params: GuckStatsParams) => Promise<StatsResult>;
23
+ sessions: (params: GuckSessionsParams) => Promise<SessionsResult>;
24
+ };
25
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/store/backends/types.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EACnB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,MAAM,YAAY,GAAG;IAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC;AACvE,MAAM,MAAM,WAAW,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC;AAC7E,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,EAAE,KAAK,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpG,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IAC5D,KAAK,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IACzD,QAAQ,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;CACnE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/store/backends/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,21 @@
1
+ import { GuckConfig, GuckEvent, GuckSearchParams, GuckSessionsParams, GuckStatsParams } from "../schema.js";
2
+ export declare const appendEvent: (storeDir: string, event: GuckEvent) => Promise<string>;
3
+ export declare const searchEvents: (storeDir: string, config: GuckConfig, params: GuckSearchParams) => Promise<{
4
+ events: GuckEvent[];
5
+ truncated: boolean;
6
+ }>;
7
+ export declare const statsEvents: (storeDir: string, config: GuckConfig, params: GuckStatsParams) => Promise<{
8
+ buckets: Array<{
9
+ key: string;
10
+ count: number;
11
+ }>;
12
+ }>;
13
+ export declare const listSessions: (storeDir: string, config: GuckConfig, params: GuckSessionsParams) => Promise<{
14
+ sessions: Array<{
15
+ session_id: string;
16
+ last_ts: string;
17
+ event_count: number;
18
+ error_count: number;
19
+ }>;
20
+ }>;
21
+ //# sourceMappingURL=file-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-store.d.ts","sourceRoot":"","sources":["../../src/store/file-store.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EAChB,MAAM,cAAc,CAAC;AA+DtB,eAAO,MAAM,WAAW,aACZ,MAAM,SACT,SAAS,KACf,QAAQ,MAAM,CAOhB,CAAC;AAEF,eAAO,MAAM,YAAY,aACb,MAAM,UACR,UAAU,UACV,gBAAgB;YACL,SAAS,EAAE;eAAa,OAAO;EA0BnD,CAAC;AAEF,eAAO,MAAM,WAAW,aACZ,MAAM,UACR,UAAU,UACV,eAAe;aACH,MAAM;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;EA2C1D,CAAC;AAEF,eAAO,MAAM,YAAY,aACb,MAAM,UACR,UAAU,UACV,kBAAkB;cAEhB,MAAM;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;EA8CnG,CAAC"}
@@ -0,0 +1,169 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import readline from "node:readline";
4
+ import { parseTimeInput, normalizeTimestamp, formatDateSegment } from "./time.js";
5
+ import { eventMatches } from "./filters.js";
6
+ const ensureDir = async (dir) => {
7
+ await fs.promises.mkdir(dir, { recursive: true });
8
+ };
9
+ const getEventTimestamp = (event) => {
10
+ return normalizeTimestamp(event.ts);
11
+ };
12
+ const collectFiles = async (root, service) => {
13
+ const storeRoot = service ? path.join(root, service) : root;
14
+ const result = [];
15
+ if (!fs.existsSync(storeRoot)) {
16
+ return result;
17
+ }
18
+ const stack = [storeRoot];
19
+ while (stack.length > 0) {
20
+ const current = stack.pop();
21
+ if (!current) {
22
+ continue;
23
+ }
24
+ const entries = await fs.promises.readdir(current, { withFileTypes: true });
25
+ for (const entry of entries) {
26
+ const fullPath = path.join(current, entry.name);
27
+ if (entry.isDirectory()) {
28
+ stack.push(fullPath);
29
+ }
30
+ else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
31
+ result.push(fullPath);
32
+ }
33
+ }
34
+ }
35
+ return result;
36
+ };
37
+ const readJsonLines = async (filePath, onEvent) => {
38
+ const stream = fs.createReadStream(filePath, { encoding: "utf8" });
39
+ const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });
40
+ for await (const line of rl) {
41
+ const trimmed = line.trim();
42
+ if (!trimmed) {
43
+ continue;
44
+ }
45
+ try {
46
+ const parsed = JSON.parse(trimmed);
47
+ const shouldContinue = onEvent(parsed);
48
+ if (shouldContinue === false) {
49
+ rl.close();
50
+ break;
51
+ }
52
+ }
53
+ catch {
54
+ // ignore malformed line
55
+ }
56
+ }
57
+ };
58
+ export const appendEvent = async (storeDir, event) => {
59
+ const dateSegment = formatDateSegment(new Date(event.ts));
60
+ const fileDir = path.join(storeDir, event.service, dateSegment);
61
+ await ensureDir(fileDir);
62
+ const filePath = path.join(fileDir, `${event.run_id}.jsonl`);
63
+ await fs.promises.appendFile(filePath, `${JSON.stringify(event)}\n`, "utf8");
64
+ return filePath;
65
+ };
66
+ export const searchEvents = async (storeDir, config, params) => {
67
+ const limit = params.limit ?? config.mcp.max_results;
68
+ const sinceMs = params.since ? parseTimeInput(params.since) : undefined;
69
+ const untilMs = params.until ? parseTimeInput(params.until) : undefined;
70
+ const events = [];
71
+ let truncated = false;
72
+ const files = await collectFiles(storeDir, params.service);
73
+ for (const filePath of files) {
74
+ await readJsonLines(filePath, (event) => {
75
+ if (!eventMatches(event, params, sinceMs, untilMs)) {
76
+ return true;
77
+ }
78
+ events.push(event);
79
+ if (events.length >= limit) {
80
+ truncated = true;
81
+ return false;
82
+ }
83
+ return true;
84
+ });
85
+ if (truncated) {
86
+ break;
87
+ }
88
+ }
89
+ return { events, truncated };
90
+ };
91
+ export const statsEvents = async (storeDir, config, params) => {
92
+ const limit = params.limit ?? config.mcp.max_results;
93
+ const sinceMs = params.since ? parseTimeInput(params.since) : undefined;
94
+ const untilMs = params.until ? parseTimeInput(params.until) : undefined;
95
+ const buckets = new Map();
96
+ const files = await collectFiles(storeDir, params.service);
97
+ for (const filePath of files) {
98
+ await readJsonLines(filePath, (event) => {
99
+ const match = eventMatches(event, {
100
+ service: params.service,
101
+ session_id: params.session_id,
102
+ types: undefined,
103
+ levels: undefined,
104
+ }, sinceMs, untilMs);
105
+ if (!match) {
106
+ return true;
107
+ }
108
+ let key = "unknown";
109
+ if (params.group_by === "type") {
110
+ key = event.type;
111
+ }
112
+ else if (params.group_by === "level") {
113
+ key = event.level;
114
+ }
115
+ else if (params.group_by === "stage") {
116
+ const stage = event.data?.stage;
117
+ key = typeof stage === "string" ? stage : "unknown";
118
+ }
119
+ buckets.set(key, (buckets.get(key) ?? 0) + 1);
120
+ return true;
121
+ });
122
+ }
123
+ const sorted = [...buckets.entries()]
124
+ .sort((a, b) => b[1] - a[1])
125
+ .slice(0, limit)
126
+ .map(([key, count]) => ({ key, count }));
127
+ return { buckets: sorted };
128
+ };
129
+ export const listSessions = async (storeDir, config, params) => {
130
+ const limit = params.limit ?? config.mcp.max_results;
131
+ const sinceMs = params.since ? parseTimeInput(params.since) : undefined;
132
+ const sessions = new Map();
133
+ const files = await collectFiles(storeDir, params.service);
134
+ for (const filePath of files) {
135
+ await readJsonLines(filePath, (event) => {
136
+ if (params.service && event.service !== params.service) {
137
+ return true;
138
+ }
139
+ if (!event.session_id) {
140
+ return true;
141
+ }
142
+ const ts = getEventTimestamp(event);
143
+ if (sinceMs !== undefined && ts !== undefined && ts < sinceMs) {
144
+ return true;
145
+ }
146
+ const existing = sessions.get(event.session_id) ?? {
147
+ session_id: event.session_id,
148
+ last_ts: event.ts,
149
+ event_count: 0,
150
+ error_count: 0,
151
+ };
152
+ existing.event_count += 1;
153
+ if (event.level === "error" || event.level === "fatal") {
154
+ existing.error_count += 1;
155
+ }
156
+ const existingTs = normalizeTimestamp(existing.last_ts) ?? 0;
157
+ if (ts !== undefined && ts > existingTs) {
158
+ existing.last_ts = event.ts;
159
+ }
160
+ sessions.set(event.session_id, existing);
161
+ return true;
162
+ });
163
+ }
164
+ const sorted = [...sessions.values()]
165
+ .sort((a, b) => (normalizeTimestamp(b.last_ts) ?? 0) - (normalizeTimestamp(a.last_ts) ?? 0))
166
+ .slice(0, limit);
167
+ return { sessions: sorted };
168
+ };
169
+ //# sourceMappingURL=file-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-store.js","sourceRoot":"","sources":["../../src/store/file-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,QAAQ,MAAM,eAAe,CAAC;AAQrC,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAClF,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,SAAS,GAAG,KAAK,EAAE,GAAW,EAAiB,EAAE;IACrD,MAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AACpD,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,KAAgB,EAAsB,EAAE;IACjE,OAAO,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AACtC,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,KAAK,EAAE,IAAY,EAAE,OAAgB,EAAqB,EAAE;IAC/E,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5D,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,KAAK,GAAa,CAAC,SAAS,CAAC,CAAC;IACpC,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,SAAS;QACX,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5E,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAChD,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACvB,CAAC;iBAAM,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC3D,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,KAAK,EACzB,QAAgB,EAChB,OAA6C,EAC9B,EAAE;IACjB,MAAM,MAAM,GAAG,EAAE,CAAC,gBAAgB,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IACnE,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC5E,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,EAAE,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,SAAS;QACX,CAAC;QACD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAc,CAAC;YAChD,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;YACvC,IAAI,cAAc,KAAK,KAAK,EAAE,CAAC;gBAC7B,EAAE,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM;YACR,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,wBAAwB;QAC1B,CAAC;IACH,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAC9B,QAAgB,EAChB,KAAgB,EACC,EAAE;IACnB,MAAM,WAAW,GAAG,iBAAiB,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAChE,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC;IACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,MAAM,QAAQ,CAAC,CAAC;IAC7D,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC7E,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAC/B,QAAgB,EAChB,MAAkB,EAClB,MAAwB,EAC8B,EAAE;IACxD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC;IACrD,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACxE,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACxE,MAAM,MAAM,GAAgB,EAAE,CAAC;IAC/B,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3D,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;QAC7B,MAAM,aAAa,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;YACtC,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC;gBACnD,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,IAAI,MAAM,CAAC,MAAM,IAAI,KAAK,EAAE,CAAC;gBAC3B,SAAS,GAAG,IAAI,CAAC;gBACjB,OAAO,KAAK,CAAC;YACf,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAC;QACH,IAAI,SAAS,EAAE,CAAC;YACd,MAAM;QACR,CAAC;IACH,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;AAC/B,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAC9B,QAAgB,EAChB,MAAkB,EAClB,MAAuB,EACsC,EAAE;IAC/D,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC;IACrD,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACxE,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACxE,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAE1C,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3D,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;QAC7B,MAAM,aAAa,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;YACtC,MAAM,KAAK,GAAG,YAAY,CACxB,KAAK,EACL;gBACE,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,KAAK,EAAE,SAAS;gBAChB,MAAM,EAAE,SAAS;aAClB,EACD,OAAO,EACP,OAAO,CACR,CAAC;YACF,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO,IAAI,CAAC;YACd,CAAC;YACD,IAAI,GAAG,GAAG,SAAS,CAAC;YACpB,IAAI,MAAM,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;gBAC/B,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC;YACnB,CAAC;iBAAM,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;gBACvC,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC;YACpB,CAAC;iBAAM,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;gBACvC,MAAM,KAAK,GAAI,KAAK,CAAC,IAA4C,EAAE,KAAK,CAAC;gBACzE,GAAG,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;YACtD,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC9C,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;SAClC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;SAC3B,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC;SACf,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IAE3C,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AAC7B,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAC/B,QAAgB,EAChB,MAAkB,EAClB,MAA0B,EAGzB,EAAE;IACH,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC;IACrD,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACxE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAGrB,CAAC;IAEJ,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3D,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;QAC7B,MAAM,aAAa,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;YACtC,IAAI,MAAM,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC;gBACvD,OAAO,IAAI,CAAC;YACd,CAAC;YACD,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;gBACtB,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,EAAE,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;YACpC,IAAI,OAAO,KAAK,SAAS,IAAI,EAAE,KAAK,SAAS,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC;gBAC9D,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI;gBACjD,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,OAAO,EAAE,KAAK,CAAC,EAAE;gBACjB,WAAW,EAAE,CAAC;gBACd,WAAW,EAAE,CAAC;aACf,CAAC;YACF,QAAQ,CAAC,WAAW,IAAI,CAAC,CAAC;YAC1B,IAAI,KAAK,CAAC,KAAK,KAAK,OAAO,IAAI,KAAK,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC;gBACvD,QAAQ,CAAC,WAAW,IAAI,CAAC,CAAC;YAC5B,CAAC;YACD,MAAM,UAAU,GAAG,kBAAkB,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC7D,IAAI,EAAE,KAAK,SAAS,IAAI,EAAE,GAAG,UAAU,EAAE,CAAC;gBACxC,QAAQ,CAAC,OAAO,GAAG,KAAK,CAAC,EAAE,CAAC;YAC9B,CAAC;YACD,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YACzC,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;SAClC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;SAC3F,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAEnB,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;AAC9B,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { GuckEvent, GuckLevel, GuckSearchParams } from "../schema.js";
2
+ export declare const eventMatches: (event: GuckEvent, params: GuckSearchParams, sinceMs?: number, untilMs?: number) => boolean;
3
+ export declare const normalizeLevel: (level?: string) => GuckLevel | undefined;
4
+ //# sourceMappingURL=filters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filters.d.ts","sourceRoot":"","sources":["../../src/store/filters.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAgCtE,eAAO,MAAM,YAAY,UAChB,SAAS,UACR,gBAAgB,YACd,MAAM,YACN,MAAM,KACf,OA2BF,CAAC;AAEF,eAAO,MAAM,cAAc,WAAY,MAAM,KAAG,SAAS,GAAG,SAgB3D,CAAC"}
@@ -0,0 +1,73 @@
1
+ import { normalizeTimestamp } from "./time.js";
2
+ const matchesContains = (event, needle) => {
3
+ const lower = needle.toLowerCase();
4
+ const message = event.message?.toLowerCase() ?? "";
5
+ if (message.includes(lower)) {
6
+ return true;
7
+ }
8
+ if (event.type.toLowerCase().includes(lower)) {
9
+ return true;
10
+ }
11
+ if (event.session_id?.toLowerCase().includes(lower)) {
12
+ return true;
13
+ }
14
+ if (event.data) {
15
+ try {
16
+ const serialized = JSON.stringify(event.data).toLowerCase();
17
+ if (serialized.includes(lower)) {
18
+ return true;
19
+ }
20
+ }
21
+ catch {
22
+ return false;
23
+ }
24
+ }
25
+ return false;
26
+ };
27
+ const getEventTimestamp = (event) => {
28
+ return normalizeTimestamp(event.ts);
29
+ };
30
+ export const eventMatches = (event, params, sinceMs, untilMs) => {
31
+ if (params.service && event.service !== params.service) {
32
+ return false;
33
+ }
34
+ if (params.session_id && event.session_id !== params.session_id) {
35
+ return false;
36
+ }
37
+ if (params.run_id && event.run_id !== params.run_id) {
38
+ return false;
39
+ }
40
+ if (params.types && params.types.length > 0 && !params.types.includes(event.type)) {
41
+ return false;
42
+ }
43
+ if (params.levels && params.levels.length > 0 && !params.levels.includes(event.level)) {
44
+ return false;
45
+ }
46
+ if (params.contains && !matchesContains(event, params.contains)) {
47
+ return false;
48
+ }
49
+ const ts = getEventTimestamp(event);
50
+ if (sinceMs !== undefined && ts !== undefined && ts < sinceMs) {
51
+ return false;
52
+ }
53
+ if (untilMs !== undefined && ts !== undefined && ts > untilMs) {
54
+ return false;
55
+ }
56
+ return true;
57
+ };
58
+ export const normalizeLevel = (level) => {
59
+ if (!level) {
60
+ return undefined;
61
+ }
62
+ const value = level.toLowerCase();
63
+ if (value === "trace" ||
64
+ value === "debug" ||
65
+ value === "info" ||
66
+ value === "warn" ||
67
+ value === "error" ||
68
+ value === "fatal") {
69
+ return value;
70
+ }
71
+ return undefined;
72
+ };
73
+ //# sourceMappingURL=filters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filters.js","sourceRoot":"","sources":["../../src/store/filters.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import { GuckConfig, GuckEvent, GuckSearchParams, GuckSessionsParams, GuckStatsParams, GuckTailParams } from "../schema.js";
2
+ export type BackendError = {
3
+ backend: string;
4
+ backend_id?: string;
5
+ message: string;
6
+ };
7
+ export declare const readSearch: (config: GuckConfig, rootDir: string, params: GuckSearchParams) => Promise<{
8
+ events: GuckEvent[];
9
+ truncated: boolean;
10
+ errors?: BackendError[] | undefined;
11
+ }>;
12
+ export declare const readStats: (config: GuckConfig, rootDir: string, params: GuckStatsParams) => Promise<{
13
+ buckets: Array<{
14
+ key: string;
15
+ count: number;
16
+ }>;
17
+ errors?: BackendError[] | undefined;
18
+ }>;
19
+ export declare const readSessions: (config: GuckConfig, rootDir: string, params: GuckSessionsParams) => Promise<{
20
+ sessions: Array<{
21
+ session_id: string;
22
+ last_ts: string;
23
+ event_count: number;
24
+ error_count: number;
25
+ }>;
26
+ errors?: BackendError[] | undefined;
27
+ }>;
28
+ export declare const readTail: (config: GuckConfig, rootDir: string, params: GuckTailParams & {
29
+ since?: string;
30
+ }) => Promise<{
31
+ events: GuckEvent[];
32
+ truncated: boolean;
33
+ errors?: BackendError[] | undefined;
34
+ }>;
35
+ //# sourceMappingURL=read-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-store.d.ts","sourceRoot":"","sources":["../../src/store/read-store.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,UAAU,EACV,SAAS,EAET,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,cAAc,EACf,MAAM,cAAc,CAAC;AAatB,MAAM,MAAM,YAAY,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAyGrF,eAAO,MAAM,UAAU,WACb,UAAU,WACT,MAAM,UACP,gBAAgB;YACL,SAAS,EAAE;eAAa,OAAO;;EAsDnD,CAAC;AAEF,eAAO,MAAM,SAAS,WACZ,UAAU,WACT,MAAM,UACP,eAAe;aACH,MAAM;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;;EAgD1D,CAAC;AAEF,eAAO,MAAM,YAAY,WACf,UAAU,WACT,MAAM,UACP,kBAAkB;cAEhB,MAAM;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;;EAiEnG,CAAC;AAEF,eAAO,MAAM,QAAQ,WACX,UAAU,WACT,MAAM,UACP,cAAc,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE;YACxB,SAAS,EAAE;eAAa,OAAO;;EAqBnD,CAAC"}
@@ -0,0 +1,256 @@
1
+ import path from "node:path";
2
+ import { resolveStoreDir } from "../config.js";
3
+ import { normalizeTimestamp } from "./time.js";
4
+ import { createCloudWatchBackend } from "./backends/cloudwatch.js";
5
+ import { createK8sBackend } from "./backends/k8s.js";
6
+ import { createLocalBackend } from "./backends/local.js";
7
+ const resolveLocalDir = (rootDir, storeDir, dir) => {
8
+ if (!dir) {
9
+ return storeDir;
10
+ }
11
+ if (path.isAbsolute(dir)) {
12
+ return dir;
13
+ }
14
+ return path.join(rootDir, dir);
15
+ };
16
+ const resolveBackends = (config, rootDir) => {
17
+ const errors = [];
18
+ const backends = [];
19
+ const storeDir = resolveStoreDir(config, rootDir);
20
+ const readConfig = config.read ?? { backend: "local" };
21
+ const addBackend = (backendConfig) => {
22
+ if (backendConfig.type === "local") {
23
+ const dir = resolveLocalDir(rootDir, storeDir, backendConfig.dir);
24
+ backends.push({
25
+ type: "local",
26
+ id: backendConfig.id,
27
+ backend: createLocalBackend({ storeDir: dir, config, backendId: backendConfig.id }),
28
+ });
29
+ return;
30
+ }
31
+ if (backendConfig.type === "cloudwatch") {
32
+ backends.push({
33
+ type: "cloudwatch",
34
+ id: backendConfig.id,
35
+ backend: createCloudWatchBackend(backendConfig),
36
+ });
37
+ return;
38
+ }
39
+ if (backendConfig.type === "k8s") {
40
+ backends.push({
41
+ type: "k8s",
42
+ id: backendConfig.id,
43
+ backend: createK8sBackend(backendConfig),
44
+ });
45
+ return;
46
+ }
47
+ const unknown = backendConfig;
48
+ errors.push({
49
+ backend: unknown.type,
50
+ backend_id: unknown.id,
51
+ message: `Unknown backend type: ${unknown.type}`,
52
+ });
53
+ };
54
+ if (readConfig.backend !== "multi") {
55
+ addBackend({ type: "local" });
56
+ return { backends, errors };
57
+ }
58
+ const configured = readConfig.backends ?? [];
59
+ if (configured.length === 0) {
60
+ addBackend({ type: "local" });
61
+ return { backends, errors };
62
+ }
63
+ for (const backendConfig of configured) {
64
+ addBackend(backendConfig);
65
+ }
66
+ return { backends, errors };
67
+ };
68
+ const filterBackends = (entries, filters) => {
69
+ if (!filters || filters.length === 0) {
70
+ return entries;
71
+ }
72
+ const filterSet = new Set(filters);
73
+ return entries.filter((entry) => {
74
+ if (entry.id && filterSet.has(entry.id)) {
75
+ return true;
76
+ }
77
+ if (filterSet.has(entry.type)) {
78
+ return true;
79
+ }
80
+ return false;
81
+ });
82
+ };
83
+ const sortEventsDesc = (events) => {
84
+ return [...events].sort((a, b) => {
85
+ const aTs = normalizeTimestamp(a.ts) ?? 0;
86
+ const bTs = normalizeTimestamp(b.ts) ?? 0;
87
+ return bTs - aTs;
88
+ });
89
+ };
90
+ export const readSearch = async (config, rootDir, params) => {
91
+ const { backends, errors: resolveErrors } = resolveBackends(config, rootDir);
92
+ const selected = filterBackends(backends, params.backends);
93
+ const errors = [...resolveErrors];
94
+ if (params.backends && params.backends.length > 0 && selected.length === 0) {
95
+ errors.push({
96
+ backend: "multi",
97
+ message: `No backends matched filter: ${params.backends.join(", ")}`,
98
+ });
99
+ }
100
+ const results = await Promise.all(selected.map(async (entry) => {
101
+ try {
102
+ const result = await entry.backend.search(params);
103
+ return { entry, result };
104
+ }
105
+ catch (error) {
106
+ errors.push({
107
+ backend: entry.type,
108
+ backend_id: entry.id,
109
+ message: error instanceof Error ? error.message : String(error),
110
+ });
111
+ return null;
112
+ }
113
+ }));
114
+ const limit = params.limit ?? config.mcp.max_results;
115
+ const events = [];
116
+ let truncated = false;
117
+ for (const item of results) {
118
+ if (!item) {
119
+ continue;
120
+ }
121
+ events.push(...item.result.events);
122
+ if (item.result.truncated) {
123
+ truncated = true;
124
+ }
125
+ }
126
+ const sorted = sortEventsDesc(events);
127
+ const mergedCount = sorted.length;
128
+ const sliced = sorted.slice(0, limit);
129
+ if (mergedCount > limit) {
130
+ truncated = true;
131
+ }
132
+ return {
133
+ events: sliced,
134
+ truncated,
135
+ errors: errors.length > 0 ? errors : undefined,
136
+ };
137
+ };
138
+ export const readStats = async (config, rootDir, params) => {
139
+ const { backends, errors: resolveErrors } = resolveBackends(config, rootDir);
140
+ const selected = filterBackends(backends, params.backends);
141
+ const errors = [...resolveErrors];
142
+ if (params.backends && params.backends.length > 0 && selected.length === 0) {
143
+ errors.push({
144
+ backend: "multi",
145
+ message: `No backends matched filter: ${params.backends.join(", ")}`,
146
+ });
147
+ }
148
+ const results = await Promise.all(selected.map(async (entry) => {
149
+ try {
150
+ const result = await entry.backend.stats(params);
151
+ return { entry, result };
152
+ }
153
+ catch (error) {
154
+ errors.push({
155
+ backend: entry.type,
156
+ backend_id: entry.id,
157
+ message: error instanceof Error ? error.message : String(error),
158
+ });
159
+ return null;
160
+ }
161
+ }));
162
+ const buckets = new Map();
163
+ for (const item of results) {
164
+ if (!item) {
165
+ continue;
166
+ }
167
+ for (const bucket of item.result.buckets) {
168
+ buckets.set(bucket.key, (buckets.get(bucket.key) ?? 0) + bucket.count);
169
+ }
170
+ }
171
+ const limit = params.limit ?? config.mcp.max_results;
172
+ const merged = [...buckets.entries()]
173
+ .sort((a, b) => b[1] - a[1])
174
+ .slice(0, limit)
175
+ .map(([key, count]) => ({ key, count }));
176
+ return {
177
+ buckets: merged,
178
+ errors: errors.length > 0 ? errors : undefined,
179
+ };
180
+ };
181
+ export const readSessions = async (config, rootDir, params) => {
182
+ const { backends, errors: resolveErrors } = resolveBackends(config, rootDir);
183
+ const selected = filterBackends(backends, params.backends);
184
+ const errors = [...resolveErrors];
185
+ if (params.backends && params.backends.length > 0 && selected.length === 0) {
186
+ errors.push({
187
+ backend: "multi",
188
+ message: `No backends matched filter: ${params.backends.join(", ")}`,
189
+ });
190
+ }
191
+ const results = await Promise.all(selected.map(async (entry) => {
192
+ try {
193
+ const result = await entry.backend.sessions(params);
194
+ return { entry, result };
195
+ }
196
+ catch (error) {
197
+ errors.push({
198
+ backend: entry.type,
199
+ backend_id: entry.id,
200
+ message: error instanceof Error ? error.message : String(error),
201
+ });
202
+ return null;
203
+ }
204
+ }));
205
+ const sessions = new Map();
206
+ for (const item of results) {
207
+ if (!item) {
208
+ continue;
209
+ }
210
+ for (const session of item.result.sessions) {
211
+ const existing = sessions.get(session.session_id) ?? {
212
+ session_id: session.session_id,
213
+ last_ts: session.last_ts,
214
+ event_count: 0,
215
+ error_count: 0,
216
+ };
217
+ existing.event_count += session.event_count;
218
+ existing.error_count += session.error_count;
219
+ const existingTs = normalizeTimestamp(existing.last_ts) ?? 0;
220
+ const sessionTs = normalizeTimestamp(session.last_ts) ?? 0;
221
+ if (sessionTs > existingTs) {
222
+ existing.last_ts = session.last_ts;
223
+ }
224
+ sessions.set(session.session_id, existing);
225
+ }
226
+ }
227
+ const limit = params.limit ?? config.mcp.max_results;
228
+ const merged = [...sessions.values()]
229
+ .sort((a, b) => (normalizeTimestamp(b.last_ts) ?? 0) - (normalizeTimestamp(a.last_ts) ?? 0))
230
+ .slice(0, limit);
231
+ return {
232
+ sessions: merged,
233
+ errors: errors.length > 0 ? errors : undefined,
234
+ };
235
+ };
236
+ export const readTail = async (config, rootDir, params) => {
237
+ const limit = params.limit ?? Math.min(config.mcp.max_results, 50);
238
+ const searchParams = {
239
+ service: params.service,
240
+ session_id: params.session_id,
241
+ run_id: params.run_id,
242
+ since: params.since,
243
+ limit: config.mcp.max_results,
244
+ backends: params.backends,
245
+ };
246
+ const result = await readSearch(config, rootDir, searchParams);
247
+ const sorted = sortEventsDesc(result.events);
248
+ const sliced = sorted.slice(0, limit);
249
+ const truncated = result.truncated || sorted.length > limit;
250
+ return {
251
+ events: sliced,
252
+ truncated,
253
+ errors: result.errors,
254
+ };
255
+ };
256
+ //# sourceMappingURL=read-store.js.map