log10x-mcp 1.0.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 (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +148 -0
  3. package/build/index.d.ts +8 -0
  4. package/build/index.js +150 -0
  5. package/build/index.js.map +1 -0
  6. package/build/lib/api.d.ts +31 -0
  7. package/build/lib/api.js +89 -0
  8. package/build/lib/api.js.map +1 -0
  9. package/build/lib/cost.d.ts +14 -0
  10. package/build/lib/cost.js +23 -0
  11. package/build/lib/cost.js.map +1 -0
  12. package/build/lib/environments.d.ts +24 -0
  13. package/build/lib/environments.js +51 -0
  14. package/build/lib/environments.js.map +1 -0
  15. package/build/lib/format.d.ts +29 -0
  16. package/build/lib/format.js +90 -0
  17. package/build/lib/format.js.map +1 -0
  18. package/build/lib/gates.d.ts +23 -0
  19. package/build/lib/gates.js +29 -0
  20. package/build/lib/gates.js.map +1 -0
  21. package/build/lib/promql.d.ts +43 -0
  22. package/build/lib/promql.js +99 -0
  23. package/build/lib/promql.js.map +1 -0
  24. package/build/lib/resolve-env.d.ts +11 -0
  25. package/build/lib/resolve-env.js +35 -0
  26. package/build/lib/resolve-env.js.map +1 -0
  27. package/build/resources/status.d.ts +7 -0
  28. package/build/resources/status.js +37 -0
  29. package/build/resources/status.js.map +1 -0
  30. package/build/tools/cost-drivers.d.ts +28 -0
  31. package/build/tools/cost-drivers.js +142 -0
  32. package/build/tools/cost-drivers.js.map +1 -0
  33. package/build/tools/dependency-check.d.ts +22 -0
  34. package/build/tools/dependency-check.js +80 -0
  35. package/build/tools/dependency-check.js.map +1 -0
  36. package/build/tools/event-lookup.d.ts +23 -0
  37. package/build/tools/event-lookup.js +131 -0
  38. package/build/tools/event-lookup.js.map +1 -0
  39. package/build/tools/exclusion-filter.d.ts +21 -0
  40. package/build/tools/exclusion-filter.js +246 -0
  41. package/build/tools/exclusion-filter.js.map +1 -0
  42. package/build/tools/savings.d.ts +17 -0
  43. package/build/tools/savings.js +75 -0
  44. package/build/tools/savings.js.map +1 -0
  45. package/build/tools/services.d.ts +14 -0
  46. package/build/tools/services.js +53 -0
  47. package/build/tools/services.js.map +1 -0
  48. package/build/tools/trend.d.ts +20 -0
  49. package/build/tools/trend.js +122 -0
  50. package/build/tools/trend.js.map +1 -0
  51. package/package.json +56 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Log10x
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,148 @@
1
+ # Log10x MCP Server
2
+
3
+ Per-pattern log cost attribution for AI assistants. Ask Claude (or any MCP-compatible AI) "why did our log costs spike this week?" and get an instant, dollar-ranked answer powered by pre-aggregated Prometheus metrics.
4
+
5
+ ## What it does
6
+
7
+ Log10x pre-aggregates per-pattern byte metrics inline, before logs hit any SIEM. This MCP server exposes that data to AI assistants as a set of tools:
8
+
9
+ | Tool | Answers |
10
+ |---|---|
11
+ | `log10x_cost_drivers` | "Why did our log costs spike?" — dollar-ranked patterns with before→after deltas |
12
+ | `log10x_event_lookup` | "What is this Payment Gateway pattern?" — cost breakdown + AI classification |
13
+ | `log10x_savings` | "How much are we saving?" — per-app savings with annual projection |
14
+ | `log10x_pattern_trend` | "When did this pattern start spiking?" — time series + sparkline |
15
+ | `log10x_services` | "What services are we monitoring?" — volume + cost by service |
16
+ | `log10x_exclusion_filter` | "How do I drop this in Datadog?" — config snippets for 14 vendors |
17
+ | `log10x_dependency_check` | "Anything depending on this before I drop it?" — SIEM dependency scan |
18
+
19
+ The server queries `prometheus.log10x.com` over HTTPS. No log scanning, sub-second at any scale.
20
+
21
+ ## Install
22
+
23
+ ### Claude Desktop
24
+
25
+ Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
26
+
27
+ ```json
28
+ {
29
+ "mcpServers": {
30
+ "log10x": {
31
+ "command": "npx",
32
+ "args": ["-y", "log10x-mcp"],
33
+ "env": {
34
+ "LOG10X_API_KEY": "your-api-key",
35
+ "LOG10X_ENV_ID": "your-env-id"
36
+ }
37
+ }
38
+ }
39
+ }
40
+ ```
41
+
42
+ Restart Claude Desktop.
43
+
44
+ ### Claude Code
45
+
46
+ ```bash
47
+ claude mcp add --transport stdio \
48
+ --env LOG10X_API_KEY=your-api-key \
49
+ --env LOG10X_ENV_ID=your-env-id \
50
+ log10x -- npx -y log10x-mcp
51
+ ```
52
+
53
+ Verify with `/mcp`.
54
+
55
+ ### Cursor / Windsurf / other MCP clients
56
+
57
+ Same pattern — add an `mcpServers` entry with `"command": "npx"`, `"args": ["-y", "log10x-mcp"]`, and the two env vars.
58
+
59
+ ## Get your credentials
60
+
61
+ 1. Log into [console.log10x.com](https://console.log10x.com)
62
+ 2. Open Profile → API Settings
63
+ 3. Copy your **API Key** and **Environment ID**
64
+ 4. (Optional) Set your **Analyzer Cost** ($/GB for your SIEM) — the server reads this automatically
65
+
66
+ ## Multi-environment setup
67
+
68
+ To query multiple Log10x environments from a single MCP client, use `LOG10X_ENVS` instead of the single-env variables:
69
+
70
+ ```json
71
+ {
72
+ "mcpServers": {
73
+ "log10x": {
74
+ "command": "npx",
75
+ "args": ["-y", "log10x-mcp"],
76
+ "env": {
77
+ "LOG10X_ENVS": "[{\"nickname\":\"prod\",\"apiKey\":\"...\",\"envId\":\"...\"},{\"nickname\":\"staging\",\"apiKey\":\"...\",\"envId\":\"...\"}]"
78
+ }
79
+ }
80
+ }
81
+ }
82
+ ```
83
+
84
+ Then ask "check prod costs" or "what's spiking in staging?" — the AI routes to the right environment via the `environment` parameter.
85
+
86
+ ## Usage
87
+
88
+ You never call tools directly. Just ask your AI assistant a question in plain English:
89
+
90
+ | You say | The AI calls |
91
+ |---|---|
92
+ | "Why did our log costs spike this week?" | `log10x_cost_drivers` |
93
+ | "What is this Payment Gateway Timeout pattern?" | `log10x_event_lookup` |
94
+ | "How much are we saving with the pipeline?" | `log10x_savings` |
95
+ | "When did the checkout service start spiking?" | `log10x_pattern_trend` |
96
+ | "What services are we monitoring?" | `log10x_services` |
97
+ | "How do I drop this in Datadog?" | `log10x_exclusion_filter` |
98
+ | "Anything depending on this before I drop it?" | `log10x_dependency_check` |
99
+
100
+ ## Cost driver algorithm
101
+
102
+ When you ask about cost spikes, the server runs the same algorithm as the Log10x Slack bot:
103
+
104
+ 1. **Query current window** — bytes per pattern for the selected timeframe
105
+ 2. **Query baseline** — average of the 3 prior windows of the same size
106
+ 3. **Compute delta** — `cost_this_period - cost_baseline` per pattern
107
+ 4. **Apply gates** — a pattern is a cost driver when it passes both:
108
+ - Dollar floor: delta exceeds `$500/period`
109
+ - Contribution floor: delta is at least `5%` of the total service increase
110
+ 5. **Sort by delta** descending
111
+
112
+ Example output:
113
+
114
+ ```
115
+ cart — $103 → $13K/wk (3 cost drivers)
116
+
117
+ #1 cart cartstore ValkeyCartStore $51 → $6.4K/wk INFO 6.6B events
118
+ #2 GetCartAsync called with userId $34 → $4.3K/wk 4.2B events
119
+ #3 AddItemAsync called with userId $18 → $2.2K/wk 2.1B events
120
+
121
+ 3 drivers = 98% of increase · 11 other patterns
122
+ ```
123
+
124
+ ## Environment variables
125
+
126
+ | Variable | Required | Description |
127
+ |---|---|---|
128
+ | `LOG10X_API_KEY` | Yes (single-env) | Your Log10x API key |
129
+ | `LOG10X_ENV_ID` | Yes (single-env) | Your Log10x environment ID |
130
+ | `LOG10X_ENVS` | Yes (multi-env) | JSON array of `{nickname, apiKey, envId}` |
131
+ | `LOG10X_API_BASE` | No | API base URL (default: `https://prometheus.log10x.com`) |
132
+
133
+ The server fetches your analyzer cost ($/GB) from your Console profile at startup and refreshes it hourly. To change it, update the cost in your profile — the server picks up the new value within an hour.
134
+
135
+ ## Security
136
+
137
+ - All API calls use your personal API key (never exposed in tool output)
138
+ - The server runs locally — no data leaves your machine except Prometheus queries
139
+ - Dependency check scripts run locally with your own SIEM credentials (read-only)
140
+ - No caching of log content — all data comes from pre-aggregated metrics
141
+
142
+ ## Documentation
143
+
144
+ Full documentation: [doc.log10x.com/manage/mcp-server](https://doc.log10x.com/manage/mcp-server/)
145
+
146
+ ## License
147
+
148
+ MIT
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Log10x MCP Server
4
+ *
5
+ * Gives AI assistants real-time access to per-pattern log cost attribution data.
6
+ * Queries pre-aggregated Prometheus metrics — no log scanning, sub-second at any scale.
7
+ */
8
+ export {};
package/build/index.js ADDED
@@ -0,0 +1,150 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Log10x MCP Server
4
+ *
5
+ * Gives AI assistants real-time access to per-pattern log cost attribution data.
6
+ * Queries pre-aggregated Prometheus metrics — no log scanning, sub-second at any scale.
7
+ */
8
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
9
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
10
+ import { loadEnvironments, resolveEnv } from './lib/environments.js';
11
+ import { fetchAnalyzerCost } from './lib/api.js';
12
+ import { costDriversSchema, executeCostDrivers } from './tools/cost-drivers.js';
13
+ import { eventLookupSchema, executeEventLookup } from './tools/event-lookup.js';
14
+ import { savingsSchema, executeSavings } from './tools/savings.js';
15
+ import { trendSchema, executeTrend } from './tools/trend.js';
16
+ import { servicesSchema, executeServices } from './tools/services.js';
17
+ import { exclusionFilterSchema, executeExclusionFilter } from './tools/exclusion-filter.js';
18
+ import { dependencyCheckSchema, executeDependencyCheck } from './tools/dependency-check.js';
19
+ import { getStatus } from './resources/status.js';
20
+ // ── Environment + cost cache ──
21
+ const envs = loadEnvironments();
22
+ const costCache = new Map();
23
+ const COST_REFRESH_MS = 3_600_000; // 1 hour
24
+ async function getAnalyzerCost(env, override) {
25
+ if (override !== undefined)
26
+ return override;
27
+ const key = env.envId;
28
+ const cached = costCache.get(key);
29
+ const now = Date.now();
30
+ if (cached && (now - cached.fetchedAt) < COST_REFRESH_MS) {
31
+ return cached.cost;
32
+ }
33
+ const cost = await fetchAnalyzerCost(env);
34
+ costCache.set(key, { cost, fetchedAt: now });
35
+ return cost;
36
+ }
37
+ // ── Server ──
38
+ const server = new McpServer({ name: 'log10x', version: '1.0.0' }, {
39
+ instructions: `Log10x provides per-pattern log cost attribution. Use these tools when users ask about:
40
+ - Log costs, billing spikes, cost drivers → use log10x_cost_drivers
41
+ - Specific log patterns, errors, events → use log10x_event_lookup
42
+ - Pipeline savings, ROI, optimization → use log10x_savings
43
+ - Cost trends over time → use log10x_pattern_trend
44
+ - What services are being monitored → use log10x_services
45
+ - How to drop/filter a log pattern → use log10x_exclusion_filter
46
+ - Whether dashboards/alerts depend on a pattern → use log10x_dependency_check
47
+
48
+ Always show dollar amounts prominently. The value is attribution: which specific patterns
49
+ drive costs, not just "costs went up." When showing cost drivers, emphasize the before→after
50
+ delta and flag new patterns.
51
+
52
+ Analyzer cost is auto-detected from the user's profile. If unclear which SIEM they use:
53
+ Splunk=$6/GB, Datadog=$2.50/GB, CloudWatch=$0.50/GB, Elasticsearch=$1/GB.`,
54
+ });
55
+ // ── Tool: log10x_cost_drivers ──
56
+ server.tool('log10x_cost_drivers', 'Find log patterns driving cost increases. Shows dollar-ranked attribution with before→after deltas. The core tool — start here when costs spike.', costDriversSchema, async (args) => {
57
+ try {
58
+ const env = resolveEnv(envs, args.environment);
59
+ const cost = await getAnalyzerCost(env, args.analyzerCost);
60
+ const result = await executeCostDrivers({ ...args, analyzerCost: cost }, env);
61
+ return { content: [{ type: 'text', text: result }] };
62
+ }
63
+ catch (e) {
64
+ return { content: [{ type: 'text', text: `Error: ${e.message}` }], isError: true };
65
+ }
66
+ });
67
+ // ── Tool: log10x_event_lookup ──
68
+ server.tool('log10x_event_lookup', 'Analyze a specific log pattern — cost breakdown by service, before→after delta, and AI classification with recommended action.', eventLookupSchema, async (args) => {
69
+ try {
70
+ const env = resolveEnv(envs, args.environment);
71
+ const cost = await getAnalyzerCost(env, args.analyzerCost);
72
+ const result = await executeEventLookup({ ...args, analyzerCost: cost }, env);
73
+ return { content: [{ type: 'text', text: result }] };
74
+ }
75
+ catch (e) {
76
+ return { content: [{ type: 'text', text: `Error: ${e.message}` }], isError: true };
77
+ }
78
+ });
79
+ // ── Tool: log10x_savings ──
80
+ server.tool('log10x_savings', 'Show pipeline savings — how much the regulator (filtering), optimizer (compaction), and streamer (indexing) are saving in dollars.', savingsSchema, async (args) => {
81
+ try {
82
+ const env = resolveEnv(envs, args.environment);
83
+ const cost = await getAnalyzerCost(env, args.analyzerCost);
84
+ const result = await executeSavings({ ...args, analyzerCost: cost }, env);
85
+ return { content: [{ type: 'text', text: result }] };
86
+ }
87
+ catch (e) {
88
+ return { content: [{ type: 'text', text: `Error: ${e.message}` }], isError: true };
89
+ }
90
+ });
91
+ // ── Tool: log10x_pattern_trend ──
92
+ server.tool('log10x_pattern_trend', 'Show volume trend for a pattern over time — detects spikes, shows before/after cost, includes sparkline.', trendSchema, async (args) => {
93
+ try {
94
+ const env = resolveEnv(envs, args.environment);
95
+ const cost = await getAnalyzerCost(env, args.analyzerCost);
96
+ const result = await executeTrend({ ...args, analyzerCost: cost }, env);
97
+ return { content: [{ type: 'text', text: result }] };
98
+ }
99
+ catch (e) {
100
+ return { content: [{ type: 'text', text: `Error: ${e.message}` }], isError: true };
101
+ }
102
+ });
103
+ // ── Tool: log10x_services ──
104
+ server.tool('log10x_services', 'List all monitored services with volume and cost breakdown.', servicesSchema, async (args) => {
105
+ try {
106
+ const env = resolveEnv(envs, args.environment);
107
+ const cost = await getAnalyzerCost(env, args.analyzerCost);
108
+ const result = await executeServices({ ...args, analyzerCost: cost }, env);
109
+ return { content: [{ type: 'text', text: result }] };
110
+ }
111
+ catch (e) {
112
+ return { content: [{ type: 'text', text: `Error: ${e.message}` }], isError: true };
113
+ }
114
+ });
115
+ // ── Tool: log10x_exclusion_filter ──
116
+ server.tool('log10x_exclusion_filter', 'Generate a SIEM or forwarder config snippet to drop a log pattern. Supports 14 vendors (Datadog, Splunk, Elasticsearch, CloudWatch, Fluent Bit, OTel Collector, Vector, etc.).', exclusionFilterSchema, async (args) => {
117
+ try {
118
+ const result = executeExclusionFilter(args);
119
+ return { content: [{ type: 'text', text: result }] };
120
+ }
121
+ catch (e) {
122
+ return { content: [{ type: 'text', text: `Error: ${e.message}` }], isError: true };
123
+ }
124
+ });
125
+ // ── Tool: log10x_dependency_check ──
126
+ server.tool('log10x_dependency_check', 'Generate a command to scan your SIEM for dashboards, alerts, or saved searches that depend on a pattern. Run before dropping.', dependencyCheckSchema, async (args) => {
127
+ try {
128
+ const result = executeDependencyCheck(args);
129
+ return { content: [{ type: 'text', text: result }] };
130
+ }
131
+ catch (e) {
132
+ return { content: [{ type: 'text', text: `Error: ${e.message}` }], isError: true };
133
+ }
134
+ });
135
+ // ── Resource: log10x://status ──
136
+ server.resource('pipeline-status', 'log10x://status', { description: 'Current pipeline health and volume summary', mimeType: 'text/plain' }, async () => {
137
+ const env = envs.default;
138
+ const text = await getStatus(env);
139
+ return { contents: [{ uri: 'log10x://status', text, mimeType: 'text/plain' }] };
140
+ });
141
+ // ── Start ──
142
+ async function main() {
143
+ const transport = new StdioServerTransport();
144
+ await server.connect(transport);
145
+ }
146
+ main().catch((error) => {
147
+ console.error('Fatal:', error);
148
+ process.exit(1);
149
+ });
150
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Log10x API client.
3
+ *
4
+ * Handles authentication, Prometheus queries, user settings,
5
+ * and AI analysis via the Log10x REST API.
6
+ */
7
+ import type { EnvConfig } from './environments.js';
8
+ /** Raw Prometheus instant query. Returns parsed JSON response. */
9
+ export declare function queryInstant(env: EnvConfig, promql: string): Promise<PrometheusResponse>;
10
+ /** Prometheus range query. Returns parsed JSON response. */
11
+ export declare function queryRange(env: EnvConfig, promql: string, start: number, end: number, step: number): Promise<PrometheusResponse>;
12
+ /** AI analysis query. Returns the AI text response. */
13
+ export declare function queryAi(env: EnvConfig, queryResult: string, prompt: string, ingestionCost: number): Promise<string>;
14
+ /**
15
+ * Fetches the user's analyzer cost ($/GB) from the Log10x REST API.
16
+ * Stored in Auth0 user_metadata.analyzer_cost, returned by GET /api/v1/user.
17
+ * Falls back to DEFAULT_COST_PER_GB on failure.
18
+ */
19
+ export declare function fetchAnalyzerCost(env: EnvConfig): Promise<number>;
20
+ export interface PrometheusResult {
21
+ metric: Record<string, string>;
22
+ value?: [number, string];
23
+ values?: [number, string][];
24
+ }
25
+ export interface PrometheusResponse {
26
+ status: string;
27
+ data: {
28
+ resultType: string;
29
+ result: PrometheusResult[];
30
+ };
31
+ }
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Log10x API client.
3
+ *
4
+ * Handles authentication, Prometheus queries, user settings,
5
+ * and AI analysis via the Log10x REST API.
6
+ */
7
+ const DEFAULT_BASE = 'https://prometheus.log10x.com';
8
+ const DEFAULT_COST_PER_GB = 2.50;
9
+ function getBase() {
10
+ return process.env.LOG10X_API_BASE || DEFAULT_BASE;
11
+ }
12
+ function authHeader(env) {
13
+ return `${env.apiKey}/${env.envId}`;
14
+ }
15
+ /** Raw Prometheus instant query. Returns parsed JSON response. */
16
+ export async function queryInstant(env, promql) {
17
+ const url = new URL('/api/v1/query', getBase());
18
+ url.searchParams.set('query', promql);
19
+ url.searchParams.set('stats', 'all');
20
+ const res = await fetch(url.toString(), {
21
+ headers: { 'X-10X-Auth': authHeader(env) },
22
+ });
23
+ if (!res.ok) {
24
+ const body = await res.text();
25
+ throw new Error(`Prometheus HTTP ${res.status}: ${body}`);
26
+ }
27
+ return res.json();
28
+ }
29
+ /** Prometheus range query. Returns parsed JSON response. */
30
+ export async function queryRange(env, promql, start, end, step) {
31
+ const url = new URL('/api/v1/query_range', getBase());
32
+ url.searchParams.set('query', promql);
33
+ url.searchParams.set('start', start.toString());
34
+ url.searchParams.set('end', end.toString());
35
+ url.searchParams.set('step', step.toString());
36
+ const res = await fetch(url.toString(), {
37
+ headers: { 'X-10X-Auth': authHeader(env) },
38
+ });
39
+ if (!res.ok) {
40
+ const body = await res.text();
41
+ throw new Error(`Prometheus HTTP ${res.status}: ${body}`);
42
+ }
43
+ return res.json();
44
+ }
45
+ /** AI analysis query. Returns the AI text response. */
46
+ export async function queryAi(env, queryResult, prompt, ingestionCost) {
47
+ const url = new URL('/api/v1/query_ai', getBase());
48
+ url.searchParams.set('query', 'vector(0)');
49
+ url.searchParams.set('query_result', queryResult);
50
+ url.searchParams.set('prompt', prompt);
51
+ url.searchParams.set('ingestion_cost', ingestionCost.toString());
52
+ url.searchParams.set('total_volume', '0');
53
+ url.searchParams.set('output_table', 'false');
54
+ url.searchParams.set('prompt_timeout', '15000');
55
+ const res = await fetch(url.toString(), {
56
+ headers: { 'X-10X-Auth': authHeader(env) },
57
+ });
58
+ if (!res.ok) {
59
+ const body = await res.text();
60
+ throw new Error(`AI query HTTP ${res.status}: ${body}`);
61
+ }
62
+ const data = await res.json();
63
+ return data.data?.ai || '';
64
+ }
65
+ /**
66
+ * Fetches the user's analyzer cost ($/GB) from the Log10x REST API.
67
+ * Stored in Auth0 user_metadata.analyzer_cost, returned by GET /api/v1/user.
68
+ * Falls back to DEFAULT_COST_PER_GB on failure.
69
+ */
70
+ export async function fetchAnalyzerCost(env) {
71
+ try {
72
+ const url = new URL('/api/v1/user', getBase());
73
+ const res = await fetch(url.toString(), {
74
+ headers: { 'X-10X-Auth': authHeader(env) },
75
+ });
76
+ if (!res.ok)
77
+ return DEFAULT_COST_PER_GB;
78
+ const data = await res.json();
79
+ const raw = data.user?.metadata?.analyzer_cost;
80
+ if (raw === undefined || raw === null)
81
+ return DEFAULT_COST_PER_GB;
82
+ const cost = typeof raw === 'number' ? raw : parseFloat(raw);
83
+ return cost > 0 ? cost : DEFAULT_COST_PER_GB;
84
+ }
85
+ catch {
86
+ return DEFAULT_COST_PER_GB;
87
+ }
88
+ }
89
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Cost calculation helpers.
3
+ *
4
+ * Converts bytes to dollars using the analyzer cost per GB.
5
+ * Matches the formula in SlackPatternService.java.
6
+ */
7
+ /** Convert bytes to cost in dollars at the given $/GB rate. */
8
+ export declare function bytesToCost(bytes: number, costPerGb: number): number;
9
+ /** Convert bytes to GB. */
10
+ export declare function bytesToGb(bytes: number): number;
11
+ /** Parse a Prometheus value (always a string) to a number. */
12
+ export declare function parsePrometheusValue(result: {
13
+ value?: [number, string];
14
+ }): number;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Cost calculation helpers.
3
+ *
4
+ * Converts bytes to dollars using the analyzer cost per GB.
5
+ * Matches the formula in SlackPatternService.java.
6
+ */
7
+ const GB = 1024 * 1024 * 1024;
8
+ /** Convert bytes to cost in dollars at the given $/GB rate. */
9
+ export function bytesToCost(bytes, costPerGb) {
10
+ return (bytes / GB) * costPerGb;
11
+ }
12
+ /** Convert bytes to GB. */
13
+ export function bytesToGb(bytes) {
14
+ return bytes / GB;
15
+ }
16
+ /** Parse a Prometheus value (always a string) to a number. */
17
+ export function parsePrometheusValue(result) {
18
+ if (!result.value || result.value.length < 2)
19
+ return 0;
20
+ const val = parseFloat(result.value[1]);
21
+ return isNaN(val) ? 0 : val;
22
+ }
23
+ //# sourceMappingURL=cost.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost.js","sourceRoot":"","sources":["../../src/lib/cost.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,EAAE,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE9B,+DAA+D;AAC/D,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,SAAiB;IAC1D,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC,GAAG,SAAS,CAAC;AAClC,CAAC;AAED,2BAA2B;AAC3B,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,OAAO,KAAK,GAAG,EAAE,CAAC;AACpB,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,oBAAoB,CAAC,MAAoC;IACvE,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC;IACvD,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACxC,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Multi-environment configuration.
3
+ *
4
+ * Supports single-env (LOG10X_API_KEY + LOG10X_ENV_ID) or multi-env
5
+ * (LOG10X_ENVS JSON array with nicknames), matching the Slack bot pattern.
6
+ */
7
+ export interface EnvConfig {
8
+ nickname: string;
9
+ apiKey: string;
10
+ envId: string;
11
+ }
12
+ /** Parsed environment list + default. */
13
+ export interface Environments {
14
+ all: EnvConfig[];
15
+ byNickname: Map<string, EnvConfig>;
16
+ default: EnvConfig;
17
+ }
18
+ /**
19
+ * Parses environment configuration from process.env.
20
+ * Throws if no environments are configured.
21
+ */
22
+ export declare function loadEnvironments(): Environments;
23
+ /** Resolves an environment by nickname, or returns the default. */
24
+ export declare function resolveEnv(envs: Environments, nickname?: string): EnvConfig;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Multi-environment configuration.
3
+ *
4
+ * Supports single-env (LOG10X_API_KEY + LOG10X_ENV_ID) or multi-env
5
+ * (LOG10X_ENVS JSON array with nicknames), matching the Slack bot pattern.
6
+ */
7
+ /**
8
+ * Parses environment configuration from process.env.
9
+ * Throws if no environments are configured.
10
+ */
11
+ export function loadEnvironments() {
12
+ const envsJson = process.env.LOG10X_ENVS;
13
+ let envs;
14
+ if (envsJson) {
15
+ const parsed = JSON.parse(envsJson);
16
+ if (!Array.isArray(parsed) || parsed.length === 0) {
17
+ throw new Error('LOG10X_ENVS must be a non-empty JSON array');
18
+ }
19
+ envs = parsed.map((e) => {
20
+ if (!e.nickname || !e.apiKey || !e.envId) {
21
+ throw new Error(`Each env entry requires nickname, apiKey, envId. Got: ${JSON.stringify(e)}`);
22
+ }
23
+ return { nickname: e.nickname, apiKey: e.apiKey, envId: e.envId };
24
+ });
25
+ }
26
+ else {
27
+ const apiKey = process.env.LOG10X_API_KEY;
28
+ const envId = process.env.LOG10X_ENV_ID;
29
+ if (!apiKey || !envId) {
30
+ throw new Error('Set LOG10X_API_KEY + LOG10X_ENV_ID, or LOG10X_ENVS for multi-env');
31
+ }
32
+ envs = [{ nickname: 'default', apiKey, envId }];
33
+ }
34
+ const byNickname = new Map();
35
+ for (const env of envs) {
36
+ byNickname.set(env.nickname.toLowerCase(), env);
37
+ }
38
+ return { all: envs, byNickname, default: envs[0] };
39
+ }
40
+ /** Resolves an environment by nickname, or returns the default. */
41
+ export function resolveEnv(envs, nickname) {
42
+ if (!nickname)
43
+ return envs.default;
44
+ const env = envs.byNickname.get(nickname.toLowerCase());
45
+ if (!env) {
46
+ const available = envs.all.map(e => e.nickname).join(', ');
47
+ throw new Error(`Unknown environment "${nickname}". Available: ${available}`);
48
+ }
49
+ return env;
50
+ }
51
+ //# sourceMappingURL=environments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"environments.js","sourceRoot":"","sources":["../../src/lib/environments.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAeH;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;IAEzC,IAAI,IAAiB,CAAC;IAEtB,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACpC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAClD,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAChE,CAAC;QACD,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAyB,EAAE,EAAE;YAC9C,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;gBACzC,MAAM,IAAI,KAAK,CAAC,yDAAyD,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAChG,CAAC;YACD,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;QACpE,CAAC,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;QAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;QACxC,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC;QACtF,CAAC;QACD,IAAI,GAAG,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAClD,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,GAAG,EAAqB,CAAC;IAChD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,GAAG,CAAC,CAAC;IAClD,CAAC;IAED,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;AACrD,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,UAAU,CAAC,IAAkB,EAAE,QAAiB;IAC9D,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC,OAAO,CAAC;IACnC,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;IACxD,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,wBAAwB,QAAQ,iBAAiB,SAAS,EAAE,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Output formatting helpers.
3
+ *
4
+ * Plain text, not markdown. Dollar amounts are prominent.
5
+ * Designed for AI consumption — concise, structured, parseable.
6
+ */
7
+ /** Format a dollar amount: $1.2K, $14K, $1.2M, etc. */
8
+ export declare function fmtDollar(amount: number): string;
9
+ /** Format bytes as human-readable: 1.2 GB, 450 MB, etc. */
10
+ export declare function fmtBytes(bytes: number): string;
11
+ /** Format event count: 1.2B, 450M, 12K, etc. */
12
+ export declare function fmtCount(count: number): string;
13
+ /** Format a pattern name for display: replace underscores with spaces. */
14
+ export declare function fmtPattern(pattern: string): string;
15
+ /** Format severity: first 4 chars uppercase. */
16
+ export declare function fmtSeverity(sev: string): string;
17
+ /** Format a percentage. */
18
+ export declare function fmtPct(value: number): string;
19
+ /** Timeframe config matching SlackTimeframe.java. */
20
+ export interface Timeframe {
21
+ days: number;
22
+ range: string;
23
+ label: string;
24
+ baselineOffsets: number[];
25
+ }
26
+ /** Parse a timeframe string (1d, 7d, 30d) into a Timeframe config. */
27
+ export declare function parseTimeframe(input: string): Timeframe;
28
+ /** Cost period label for output. */
29
+ export declare function costPeriodLabel(days: number): string;