log10x-mcp 1.12.2 → 1.12.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/index.js +239 -79
- package/build/index.js.map +1 -1
- package/build/lib/action-intent-parser.d.ts +1 -1
- package/build/lib/action-intent-parser.js +1 -1
- package/build/lib/advisor/reporter-forwarders.js +4 -4
- package/build/lib/advisor/reporter-forwarders.js.map +1 -1
- package/build/lib/anchor-dispersion.d.ts +7 -7
- package/build/lib/anchor-dispersion.js +7 -7
- package/build/lib/anchor-promql.d.ts +35 -0
- package/build/lib/anchor-promql.js +44 -0
- package/build/lib/anchor-promql.js.map +1 -0
- package/build/lib/anchor-suggestions.d.ts +58 -0
- package/build/lib/anchor-suggestions.js +87 -0
- package/build/lib/anchor-suggestions.js.map +1 -0
- package/build/lib/anti-jargon-prose.d.ts +92 -0
- package/build/lib/anti-jargon-prose.js +243 -0
- package/build/lib/anti-jargon-prose.js.map +1 -0
- package/build/lib/api.d.ts +0 -6
- package/build/lib/api.js +11 -29
- package/build/lib/api.js.map +1 -1
- package/build/lib/cap-csv-fetch.d.ts +27 -0
- package/build/lib/cap-csv-fetch.js +93 -1
- package/build/lib/cap-csv-fetch.js.map +1 -1
- package/build/lib/chassis-envelope.d.ts +178 -53
- package/build/lib/chassis-envelope.js +131 -11
- package/build/lib/chassis-envelope.js.map +1 -1
- package/build/lib/cli-output-parser.js +4 -4
- package/build/lib/cli-output-parser.js.map +1 -1
- package/build/lib/correlate.js +3 -3
- package/build/lib/correlate.js.map +1 -1
- package/build/lib/cost.d.ts +3 -3
- package/build/lib/cost.js +11 -6
- package/build/lib/cost.js.map +1 -1
- package/build/lib/customer-metrics.d.ts +24 -2
- package/build/lib/customer-metrics.js +23 -13
- package/build/lib/customer-metrics.js.map +1 -1
- package/build/lib/dev-cli.d.ts +1 -1
- package/build/lib/dev-cli.js +1 -1
- package/build/lib/drift.js +30 -11
- package/build/lib/drift.js.map +1 -1
- package/build/lib/env-alias-bridge.d.ts +55 -0
- package/build/lib/env-alias-bridge.js +133 -0
- package/build/lib/env-alias-bridge.js.map +1 -0
- package/build/lib/env-config/env-var-bridge.d.ts +53 -0
- package/build/lib/env-config/env-var-bridge.js +180 -0
- package/build/lib/env-config/env-var-bridge.js.map +1 -0
- package/build/lib/env-config/resolve-cluster-config.d.ts +158 -0
- package/build/lib/env-config/resolve-cluster-config.js +239 -0
- package/build/lib/env-config/resolve-cluster-config.js.map +1 -0
- package/build/lib/env-config/resolver.d.ts +62 -0
- package/build/lib/env-config/resolver.js +184 -0
- package/build/lib/env-config/resolver.js.map +1 -0
- package/build/lib/env-config/store-aws-ssm.d.ts +90 -0
- package/build/lib/env-config/store-aws-ssm.js +267 -0
- package/build/lib/env-config/store-aws-ssm.js.map +1 -0
- package/build/lib/env-config/store-azure-ac.d.ts +62 -0
- package/build/lib/env-config/store-azure-ac.js +214 -0
- package/build/lib/env-config/store-azure-ac.js.map +1 -0
- package/build/lib/env-config/store-gcp-sm.d.ts +54 -0
- package/build/lib/env-config/store-gcp-sm.js +306 -0
- package/build/lib/env-config/store-gcp-sm.js.map +1 -0
- package/build/lib/env-config/store-interface.d.ts +50 -0
- package/build/lib/env-config/store-interface.js +16 -0
- package/build/lib/env-config/store-interface.js.map +1 -0
- package/build/lib/env-config/store-k8s.d.ts +144 -0
- package/build/lib/env-config/store-k8s.js +483 -0
- package/build/lib/env-config/store-k8s.js.map +1 -0
- package/build/lib/env-config/store-local-file.d.ts +52 -0
- package/build/lib/env-config/store-local-file.js +124 -0
- package/build/lib/env-config/store-local-file.js.map +1 -0
- package/build/lib/env-config/stores.d.ts +14 -0
- package/build/lib/env-config/stores.js +40 -0
- package/build/lib/env-config/stores.js.map +1 -0
- package/build/lib/env-config/types.d.ts +551 -0
- package/build/lib/env-config/types.js +119 -0
- package/build/lib/env-config/types.js.map +1 -0
- package/build/lib/environments.d.ts +9 -0
- package/build/lib/environments.js +55 -4
- package/build/lib/environments.js.map +1 -1
- package/build/lib/format.d.ts +8 -7
- package/build/lib/format.js +23 -16
- package/build/lib/format.js.map +1 -1
- package/build/lib/investigation-templates.d.ts +1 -1
- package/build/lib/investigation-templates.js +24 -4
- package/build/lib/investigation-templates.js.map +1 -1
- package/build/lib/line-chart.js +3 -3
- package/build/lib/line-chart.js.map +1 -1
- package/build/lib/mode-detect.js +8 -0
- package/build/lib/mode-detect.js.map +1 -1
- package/build/lib/not-configured.d.ts +2 -2
- package/build/lib/not-configured.js +2 -2
- package/build/lib/offload-status.d.ts +2 -2
- package/build/lib/offload-status.js +3 -3
- package/build/lib/offload-status.js.map +1 -1
- package/build/lib/output-types.d.ts +126 -40
- package/build/lib/output-types.js +12 -2
- package/build/lib/output-types.js.map +1 -1
- package/build/lib/pattern-label.d.ts +58 -0
- package/build/lib/pattern-label.js +67 -0
- package/build/lib/pattern-label.js.map +1 -0
- package/build/lib/pattern-reference-resolver.d.ts +82 -0
- package/build/lib/pattern-reference-resolver.js +99 -0
- package/build/lib/pattern-reference-resolver.js.map +1 -0
- package/build/lib/poc-envelope-v2.js +1 -1
- package/build/lib/policy-loader.js +37 -22
- package/build/lib/policy-loader.js.map +1 -1
- package/build/lib/primitive-errors.d.ts +5 -6
- package/build/lib/primitive-errors.js +15 -5
- package/build/lib/primitive-errors.js.map +1 -1
- package/build/lib/product-kb/chunker.d.ts +47 -0
- package/build/lib/product-kb/chunker.js +196 -0
- package/build/lib/product-kb/chunker.js.map +1 -0
- package/build/lib/product-kb/index.d.ts +56 -0
- package/build/lib/product-kb/index.js +88 -0
- package/build/lib/product-kb/index.js.map +1 -0
- package/build/lib/product-kb/loader.d.ts +54 -0
- package/build/lib/product-kb/loader.js +249 -0
- package/build/lib/product-kb/loader.js.map +1 -0
- package/build/lib/product-kb/search.d.ts +149 -0
- package/build/lib/product-kb/search.js +373 -0
- package/build/lib/product-kb/search.js.map +1 -0
- package/build/lib/product-kb/types.d.ts +69 -0
- package/build/lib/product-kb/types.js +10 -0
- package/build/lib/product-kb/types.js.map +1 -0
- package/build/lib/promql.d.ts +45 -7
- package/build/lib/promql.js +89 -22
- package/build/lib/promql.js.map +1 -1
- package/build/lib/rate-resolution.d.ts +86 -0
- package/build/lib/rate-resolution.js +176 -0
- package/build/lib/rate-resolution.js.map +1 -0
- package/build/lib/read-only-guard.d.ts +64 -0
- package/build/lib/read-only-guard.js +80 -0
- package/build/lib/read-only-guard.js.map +1 -0
- package/build/lib/recurring-tick.d.ts +16 -0
- package/build/lib/recurring-tick.js +18 -3
- package/build/lib/recurring-tick.js.map +1 -1
- package/build/lib/resolve-pattern-hash.d.ts +46 -0
- package/build/lib/resolve-pattern-hash.js +72 -0
- package/build/lib/resolve-pattern-hash.js.map +1 -1
- package/build/lib/retriever-api.d.ts +4 -4
- package/build/lib/retriever-api.js +16 -18
- package/build/lib/retriever-api.js.map +1 -1
- package/build/lib/retriever-fidelity.js +7 -3
- package/build/lib/retriever-fidelity.js.map +1 -1
- package/build/lib/retriever-probe.d.ts +125 -0
- package/build/lib/retriever-probe.js +658 -0
- package/build/lib/retriever-probe.js.map +1 -0
- package/build/lib/retriever-state.d.ts +1 -1
- package/build/lib/source-disclosure.d.ts +89 -0
- package/build/lib/source-disclosure.js +135 -0
- package/build/lib/source-disclosure.js.map +1 -0
- package/build/lib/strict-args.d.ts +48 -0
- package/build/lib/strict-args.js +83 -0
- package/build/lib/strict-args.js.map +1 -0
- package/build/lib/tool-errors.js +1 -1
- package/build/lib/tool-errors.js.map +1 -1
- package/build/lib/top-patterns-extras.d.ts +7 -7
- package/build/lib/top-patterns-extras.js +8 -9
- package/build/lib/top-patterns-extras.js.map +1 -1
- package/build/lib/trend-delta.d.ts +1 -1
- package/build/lib/trend-delta.js +1 -1
- package/build/tools/advise-install.d.ts +2 -2
- package/build/tools/advise-retriever.d.ts +6 -2
- package/build/tools/advise-retriever.js +119 -13
- package/build/tools/advise-retriever.js.map +1 -1
- package/build/tools/backfill-metric.d.ts +11 -10
- package/build/tools/backfill-metric.js +25 -17
- package/build/tools/backfill-metric.js.map +1 -1
- package/build/tools/baseline.d.ts +50 -0
- package/build/tools/baseline.js +111 -14
- package/build/tools/baseline.js.map +1 -1
- package/build/tools/commitment-report.d.ts +99 -11
- package/build/tools/commitment-report.js +326 -34
- package/build/tools/commitment-report.js.map +1 -1
- package/build/tools/configure-engine.d.ts +26 -5
- package/build/tools/configure-engine.js +949 -91
- package/build/tools/configure-engine.js.map +1 -1
- package/build/tools/configure-env.d.ts +8 -8
- package/build/tools/configure-env.js +2 -0
- package/build/tools/configure-env.js.map +1 -1
- package/build/tools/cost-options.d.ts +5 -2
- package/build/tools/cost-options.js +83 -42
- package/build/tools/cost-options.js.map +1 -1
- package/build/tools/create-env.js +2 -0
- package/build/tools/create-env.js.map +1 -1
- package/build/tools/delete-env.js +2 -0
- package/build/tools/delete-env.js.map +1 -1
- package/build/tools/dependency-check.js +31 -6
- package/build/tools/dependency-check.js.map +1 -1
- package/build/tools/dev-restart.js +2 -0
- package/build/tools/dev-restart.js.map +1 -1
- package/build/tools/discover-join.d.ts +6 -0
- package/build/tools/discover-join.js +61 -10
- package/build/tools/discover-join.js.map +1 -1
- package/build/tools/doctor.js +156 -36
- package/build/tools/doctor.js.map +1 -1
- package/build/tools/env-config-manage.d.ts +69 -0
- package/build/tools/env-config-manage.js +696 -0
- package/build/tools/env-config-manage.js.map +1 -0
- package/build/tools/env-register.d.ts +245 -0
- package/build/tools/env-register.js +223 -0
- package/build/tools/env-register.js.map +1 -0
- package/build/tools/estimate-savings.d.ts +70 -21
- package/build/tools/estimate-savings.js +322 -72
- package/build/tools/estimate-savings.js.map +1 -1
- package/build/tools/event-lookup.js +105 -40
- package/build/tools/event-lookup.js.map +1 -1
- package/build/tools/explain-mode.d.ts +2 -0
- package/build/tools/explain-mode.js +63 -36
- package/build/tools/explain-mode.js.map +1 -1
- package/build/tools/extract-templates.js +1 -1
- package/build/tools/extract-templates.js.map +1 -1
- package/build/tools/find-skew.d.ts +21 -0
- package/build/tools/find-skew.js +37 -29
- package/build/tools/find-skew.js.map +1 -1
- package/build/tools/investigate.d.ts +8 -2
- package/build/tools/investigate.js +299 -64
- package/build/tools/investigate.js.map +1 -1
- package/build/tools/log10x-start.d.ts +1 -1
- package/build/tools/log10x-start.js +3 -3
- package/build/tools/log10x-start.js.map +1 -1
- package/build/tools/measure-compaction.d.ts +2 -2
- package/build/tools/measure-compaction.js +67 -21
- package/build/tools/measure-compaction.js.map +1 -1
- package/build/tools/metric-overlay.d.ts +6 -0
- package/build/tools/metric-overlay.js +175 -29
- package/build/tools/metric-overlay.js.map +1 -1
- package/build/tools/metrics-that-moved.d.ts +19 -0
- package/build/tools/metrics-that-moved.js +220 -37
- package/build/tools/metrics-that-moved.js.map +1 -1
- package/build/tools/offload-manage.d.ts +95 -0
- package/build/tools/offload-manage.js +430 -0
- package/build/tools/offload-manage.js.map +1 -0
- package/build/tools/overflow-contents.d.ts +3 -4
- package/build/tools/overflow-contents.js +118 -81
- package/build/tools/overflow-contents.js.map +1 -1
- package/build/tools/pattern-detail.d.ts +3 -3
- package/build/tools/pattern-detail.js +61 -25
- package/build/tools/pattern-detail.js.map +1 -1
- package/build/tools/pattern-diff.d.ts +55 -0
- package/build/tools/pattern-diff.js +652 -0
- package/build/tools/pattern-diff.js.map +1 -0
- package/build/tools/pattern-examples.d.ts +29 -15
- package/build/tools/pattern-examples.js +413 -58
- package/build/tools/pattern-examples.js.map +1 -1
- package/build/tools/pattern-mitigate.js +69 -29
- package/build/tools/pattern-mitigate.js.map +1 -1
- package/build/tools/poc-from-local.js +6 -6
- package/build/tools/poc-from-local.js.map +1 -1
- package/build/tools/poc-from-siem.js +1 -1
- package/build/tools/poc-from-siem.js.map +1 -1
- package/build/tools/preview-filter.d.ts +10 -0
- package/build/tools/preview-filter.js +45 -19
- package/build/tools/preview-filter.js.map +1 -1
- package/build/tools/product-qa.d.ts +111 -0
- package/build/tools/product-qa.js +358 -0
- package/build/tools/product-qa.js.map +1 -0
- package/build/tools/rank-by-shape-similarity.d.ts +6 -0
- package/build/tools/rank-by-shape-similarity.js +179 -26
- package/build/tools/rank-by-shape-similarity.js.map +1 -1
- package/build/tools/resolve-batch.js +16 -15
- package/build/tools/resolve-batch.js.map +1 -1
- package/build/tools/retriever-probe.d.ts +30 -0
- package/build/tools/retriever-probe.js +247 -0
- package/build/tools/retriever-probe.js.map +1 -0
- package/build/tools/retriever-query-status.js +157 -47
- package/build/tools/retriever-query-status.js.map +1 -1
- package/build/tools/retriever-query.d.ts +7 -6
- package/build/tools/retriever-query.js +183 -27
- package/build/tools/retriever-query.js.map +1 -1
- package/build/tools/retriever-register.d.ts +88 -0
- package/build/tools/retriever-register.js +239 -0
- package/build/tools/retriever-register.js.map +1 -0
- package/build/tools/retriever-series.js +177 -15
- package/build/tools/retriever-series.js.map +1 -1
- package/build/tools/rotate-api-key.js +2 -0
- package/build/tools/rotate-api-key.js.map +1 -1
- package/build/tools/savings.js +57 -21
- package/build/tools/savings.js.map +1 -1
- package/build/tools/services.d.ts +10 -1
- package/build/tools/services.js +108 -29
- package/build/tools/services.js.map +1 -1
- package/build/tools/set-gitops-repo.js +2 -0
- package/build/tools/set-gitops-repo.js.map +1 -1
- package/build/tools/setup-recurring.d.ts +2 -2
- package/build/tools/signin.js +3 -0
- package/build/tools/signin.js.map +1 -1
- package/build/tools/signout.js +2 -0
- package/build/tools/signout.js.map +1 -1
- package/build/tools/top-patterns.js +193 -41
- package/build/tools/top-patterns.js.map +1 -1
- package/build/tools/trend.d.ts +1 -1
- package/build/tools/trend.js +124 -10
- package/build/tools/trend.js.map +1 -1
- package/build/tools/update-env.d.ts +1 -1
- package/build/tools/update-env.js +5 -3
- package/build/tools/update-env.js.map +1 -1
- package/build/tools/update-settings.js +3 -1
- package/build/tools/update-settings.js.map +1 -1
- package/build/tools/whats-changing.d.ts +45 -0
- package/build/tools/whats-changing.js +613 -0
- package/build/tools/whats-changing.js.map +1 -0
- package/build/tools/whats-new.d.ts +44 -0
- package/build/tools/whats-new.js +408 -0
- package/build/tools/whats-new.js.map +1 -0
- package/default-manifest.json +133 -1
- package/package.json +6 -4
package/build/index.js
CHANGED
|
@@ -17,7 +17,6 @@ import { StructuredOutputSchema, buildEnvelope, } from './lib/output-types.js';
|
|
|
17
17
|
import { detectMode, shouldRegisterTool, formatModeResolution, } from './lib/mode-detect.js';
|
|
18
18
|
import { makeShapeCoercive } from './lib/input-coerce.js';
|
|
19
19
|
import { loadEnvironments, resolveEnv, revalidateEnvironments, EnvironmentValidationError } from './lib/environments.js';
|
|
20
|
-
import { fetchAnalyzerCost } from './lib/api.js';
|
|
21
20
|
import { eventLookupSchema, executeEventLookup } from './tools/event-lookup.js';
|
|
22
21
|
import { savingsSchema, executeSavings } from './tools/savings.js';
|
|
23
22
|
import { trendSchema, executeTrend } from './tools/trend.js';
|
|
@@ -34,9 +33,16 @@ import { investigateSchema, executeInvestigate, } from './tools/investigate.js';
|
|
|
34
33
|
import { doctorSchema, executeDoctor, runDoctorChecks, renderDoctorReport } from './tools/doctor.js';
|
|
35
34
|
import { log } from './lib/log.js';
|
|
36
35
|
import { describeToolError } from './lib/tool-errors.js';
|
|
37
|
-
import {
|
|
36
|
+
import { DemoReadOnlyError, isReadOnlyMode } from './lib/read-only-guard.js';
|
|
37
|
+
import { buildDemoReadOnlyEnvelope } from './lib/chassis-envelope.js';
|
|
38
|
+
import { retrieverQuerySchema, executeRetrieverQuery, retrieverNotConfiguredMessage } from './tools/retriever-query.js';
|
|
38
39
|
import { retrieverSeriesSchema, executeRetrieverSeries } from './tools/retriever-series.js';
|
|
39
40
|
import { retrieverQueryStatusSchema, executeRetrieverQueryStatus } from './tools/retriever-query-status.js';
|
|
41
|
+
import { retrieverProbeSchema, executeRetrieverProbe } from './tools/retriever-probe.js';
|
|
42
|
+
import { retrieverRegisterSchema, executeRetrieverRegister } from './tools/retriever-register.js';
|
|
43
|
+
import { patternDiffSchema, executePatternDiff } from './tools/pattern-diff.js';
|
|
44
|
+
import { whatsChangingSchema, executeWhatsChanging } from './tools/whats-changing.js';
|
|
45
|
+
import { whatsNewSchema, executeWhatsNew } from './tools/whats-new.js';
|
|
40
46
|
import { backfillMetricSchema, executeBackfillMetric } from './tools/backfill-metric.js';
|
|
41
47
|
import { customerMetricsQuerySchema, executeCustomerMetricsQuery, } from './tools/customer-metrics-query.js';
|
|
42
48
|
import { discoverJoinSchema, executeDiscoverJoin } from './tools/discover-join.js';
|
|
@@ -60,14 +66,17 @@ import { updateSettingsSchema, executeUpdateSettings } from './tools/update-sett
|
|
|
60
66
|
import { createEnvSchema, executeCreateEnv } from './tools/create-env.js';
|
|
61
67
|
import { updateEnvSchema, executeUpdateEnv } from './tools/update-env.js';
|
|
62
68
|
import { deleteEnvSchema, executeDeleteEnv } from './tools/delete-env.js';
|
|
69
|
+
import { envRegisterSchema, executeEnvRegister } from './tools/env-register.js';
|
|
63
70
|
import { setGitopsRepoSchema, executeSetGitopsRepo } from './tools/set-gitops-repo.js';
|
|
71
|
+
import { destSetSchema, executeDestSet, envValidateSchema, executeEnvValidate, envDiffVsEnvvarsSchema, executeEnvDiffVsEnvvars, } from './tools/env-config-manage.js';
|
|
72
|
+
import { offloadAddSchema, executeOffloadAdd, offloadArchiveSchema, executeOffloadArchive, } from './tools/offload-manage.js';
|
|
64
73
|
import { rotateApiKeySchema, executeRotateApiKey } from './tools/rotate-api-key.js';
|
|
65
74
|
import { servicesSchema, executeServices } from './tools/services.js';
|
|
66
75
|
import { overflowContentsSchema, executeOverflowContents } from './tools/overflow-contents.js';
|
|
67
|
-
import { fetchCapCsvForEnv, fetchActionIntentForEnv } from './lib/cap-csv-fetch.js';
|
|
76
|
+
import { fetchCapCsvForEnv, fetchActionIntentForEnv, fetchCapCsvFromConfigMap, fetchActionIntentFromConfigMap, } from './lib/cap-csv-fetch.js';
|
|
68
77
|
import { findSkewSchema, executeFindSkew } from './tools/find-skew.js';
|
|
69
78
|
// find_constant_slots, find_uuid_in_body, find_incident_cluster removed
|
|
70
|
-
//
|
|
79
|
+
// because they produced findings the agent could not act on
|
|
71
80
|
// (engine-tokenization config changes need a human + redeploy) OR
|
|
72
81
|
// overlapped with log10x_investigate's trajectory + chain analysis.
|
|
73
82
|
import { discoverLabelsSchema, executeDiscoverLabels } from './tools/discover-labels.js';
|
|
@@ -76,6 +85,7 @@ import { log10xStartSchema, executeLog10xStart } from './tools/log10x-start.js';
|
|
|
76
85
|
import { costOptionsSchema, executeCostOptions } from './tools/cost-options.js';
|
|
77
86
|
import { explainModeSchema, executeExplainMode } from './tools/explain-mode.js';
|
|
78
87
|
import { previewFilterSchema, executePreviewFilter } from './tools/preview-filter.js';
|
|
88
|
+
import { productQaSchema, executeProductQa } from './tools/product-qa.js';
|
|
79
89
|
import { patternDetailSchema, executePatternDetail } from './tools/pattern-detail.js';
|
|
80
90
|
import { measureCompactionSchema, executeMeasureCompaction } from './tools/measure-compaction.js';
|
|
81
91
|
import { setupRecurringSchema, executeSetupRecurring } from './tools/setup-recurring.js';
|
|
@@ -92,6 +102,10 @@ import { getStatus } from './resources/status.js';
|
|
|
92
102
|
let envs;
|
|
93
103
|
let bootMode;
|
|
94
104
|
async function initEnvs() {
|
|
105
|
+
// loadEnvironments() now applies the SaaS↔on-prem alias bridge
|
|
106
|
+
// internally so every caller (including tools like doctor that
|
|
107
|
+
// re-load envs on each call) sees the same enriched byNickname map.
|
|
108
|
+
// See src/lib/env-alias-bridge.ts.
|
|
95
109
|
envs = await loadEnvironments();
|
|
96
110
|
}
|
|
97
111
|
/**
|
|
@@ -118,8 +132,6 @@ function getEnvs() {
|
|
|
118
132
|
}
|
|
119
133
|
return envs;
|
|
120
134
|
}
|
|
121
|
-
const costCache = new Map();
|
|
122
|
-
const COST_REFRESH_MS = 3_600_000; // 1 hour
|
|
123
135
|
/**
|
|
124
136
|
* Wrap a tool implementation in a try/catch that produces actionable error
|
|
125
137
|
* suggestions via `describeToolError(toolName, e)`. Every tool callback
|
|
@@ -137,9 +149,9 @@ const COST_REFRESH_MS = 3_600_000; // 1 hour
|
|
|
137
149
|
* etc.). When the MCP is in pure-demo mode (no user configuration,
|
|
138
150
|
* silently landed on the demo backend), these tools short-circuit
|
|
139
151
|
* with a structured `not_configured` response instead of returning
|
|
140
|
-
* demo data the user didn't ask for.
|
|
141
|
-
* the
|
|
142
|
-
*
|
|
152
|
+
* demo data the user didn't ask for. We surface the conversation
|
|
153
|
+
* starter without breaking the demo-mode walkthrough; the silent-demo
|
|
154
|
+
* path will be removed in a later release.
|
|
143
155
|
*
|
|
144
156
|
* Tools NOT in this set bypass the gate: configure_env (the
|
|
145
157
|
* onboarding tool itself), doctor (status reporting works in any
|
|
@@ -174,9 +186,9 @@ const METRIC_REQUIRING_TOOLS = new Set([
|
|
|
174
186
|
const DEMO_PLAYGROUND = /^(1|true|yes)$/i.test(process.env.LOG10X_MCP_DEMO_PLAYGROUND ?? '');
|
|
175
187
|
async function wrap(toolName, fn) {
|
|
176
188
|
const started = Date.now();
|
|
177
|
-
//
|
|
189
|
+
// Demo-mode gate: if this is a metric-requiring tool and the MCP is
|
|
178
190
|
// in pure-demo state, redirect to the conversational onboarding flow
|
|
179
|
-
// instead of returning silent-demo data
|
|
191
|
+
// instead of returning silent-demo data, UNLESS this is an intentional
|
|
180
192
|
// demo playground (LOG10X_MCP_DEMO_PLAYGROUND), which wants the demo data
|
|
181
193
|
// served (the gated tools are exactly the demo's headline surface).
|
|
182
194
|
if (METRIC_REQUIRING_TOOLS.has(toolName) &&
|
|
@@ -189,11 +201,19 @@ async function wrap(toolName, fn) {
|
|
|
189
201
|
// not a bare text blob; the agent branches on data.status and the MCP
|
|
190
202
|
// SDK requires structuredContent for tools that declare an outputSchema
|
|
191
203
|
// (a text-only return here is rejected as "no structured content").
|
|
204
|
+
// rq-1: retriever_query / retriever_series read the offload bucket (the
|
|
205
|
+
// held-back cohort), not the metrics backend. This wrap gate pre-empts their
|
|
206
|
+
// own correct kind:'retriever' gate, so branch the remediation here: a
|
|
207
|
+
// metrics-backend nag points the agent at the wrong subsystem entirely.
|
|
208
|
+
const isRetrieverTool = toolName === 'log10x_retriever_query' || toolName === 'log10x_retriever_series';
|
|
209
|
+
const ncKind = isRetrieverTool ? 'retriever' : 'metrics_backend';
|
|
192
210
|
return notConfiguredToolResult(buildNotConfiguredEnvelope({
|
|
193
211
|
tool: toolName,
|
|
194
|
-
kind:
|
|
195
|
-
remediation:
|
|
196
|
-
|
|
212
|
+
kind: ncKind,
|
|
213
|
+
remediation: isRetrieverTool
|
|
214
|
+
? retrieverNotConfiguredMessage()
|
|
215
|
+
: notConfiguredMessageForTool(toolName),
|
|
216
|
+
actions: defaultActionsForKind(ncKind),
|
|
197
217
|
}));
|
|
198
218
|
}
|
|
199
219
|
// Mode gate: if the boot-time mode-detect determined this tool is
|
|
@@ -325,6 +345,30 @@ async function wrap(toolName, fn) {
|
|
|
325
345
|
catch (e) {
|
|
326
346
|
const raw = e instanceof Error ? e.message : String(e);
|
|
327
347
|
log.debug(`tool.${toolName}.raw_err`, { msg: raw });
|
|
348
|
+
// Demo read-only gate: a writer tool called `requireWriteAccess()` while
|
|
349
|
+
// the MCP is running with LOG10X_MCP_READ_ONLY=true. Return the canonical
|
|
350
|
+
// demo_read_only envelope (status='error', data.status='demo_read_only',
|
|
351
|
+
// data.error.error_type='demo_read_only') so the agent can branch on the
|
|
352
|
+
// typed discriminant without parsing prose. structuredContent is populated
|
|
353
|
+
// so MCP hosts that honor the 2025-03-26 revision see typed JSON directly.
|
|
354
|
+
if (e instanceof DemoReadOnlyError) {
|
|
355
|
+
log.info(`tool.${toolName}.demo_read_only`, {
|
|
356
|
+
ms: Date.now() - started,
|
|
357
|
+
would_have: e.would_have.slice(0, 200),
|
|
358
|
+
});
|
|
359
|
+
const envelope = buildDemoReadOnlyEnvelope({
|
|
360
|
+
tool: toolName,
|
|
361
|
+
would_have: e.would_have,
|
|
362
|
+
hint: e.hint,
|
|
363
|
+
});
|
|
364
|
+
const structuredContent = envelope;
|
|
365
|
+
return {
|
|
366
|
+
content: [
|
|
367
|
+
{ type: 'text', text: JSON.stringify(envelope, null, 2) },
|
|
368
|
+
],
|
|
369
|
+
structuredContent,
|
|
370
|
+
};
|
|
371
|
+
}
|
|
328
372
|
// A deliberate "not configured" throw (the loud human-escape-hatch
|
|
329
373
|
// path, e.g. customer_metrics_query) must not abort the agent's chain
|
|
330
374
|
// as an opaque error. Convert it to a structured, branchable
|
|
@@ -468,19 +512,6 @@ function applyDemoBanner(text) {
|
|
|
468
512
|
// Pure demo: lighter footer; the user opted in by not setting a key.
|
|
469
513
|
return text + `\n\n_(Demo mode — account-scoped tools query the read-only Log10x demo env. Call \`log10x_login_status\` to use your own data.)_`;
|
|
470
514
|
}
|
|
471
|
-
async function getAnalyzerCost(env, override) {
|
|
472
|
-
if (override !== undefined)
|
|
473
|
-
return override;
|
|
474
|
-
const key = env.envId;
|
|
475
|
-
const cached = costCache.get(key);
|
|
476
|
-
const now = Date.now();
|
|
477
|
-
if (cached && (now - cached.fetchedAt) < COST_REFRESH_MS) {
|
|
478
|
-
return cached.cost;
|
|
479
|
-
}
|
|
480
|
-
const cost = await fetchAnalyzerCost(env);
|
|
481
|
-
costCache.set(key, { cost, fetchedAt: now });
|
|
482
|
-
return cost;
|
|
483
|
-
}
|
|
484
515
|
// ── Server ──
|
|
485
516
|
const SERVER_INFO = { name: 'log10x', version: readClientVersion() };
|
|
486
517
|
// Build/version provenance, surfaced on GET /health and in the mcp.boot log so
|
|
@@ -526,10 +557,10 @@ CUSTOMER TIER LADDER (determines which tools are available)
|
|
|
526
557
|
filebeat / logstash / otel-collector / vector). Filters, samples, and optionally
|
|
527
558
|
losslessly compacts events in-flight. Replaces the legacy Regulator + Optimizer apps.
|
|
528
559
|
Same tools as Reporter, plus event modification on the forwarder's path.
|
|
529
|
-
4. Retriever (deployable with or without Reporter/Receiver)
|
|
530
|
-
|
|
531
|
-
Adds: log10x_retriever_query (
|
|
532
|
-
|
|
560
|
+
4. Retriever (deployable with or without Reporter/Receiver). Reads the customer-owned
|
|
561
|
+
overflow S3 bucket the Receiver's offload action writes to, indexed by Bloom filter.
|
|
562
|
+
Adds: log10x_retriever_query (read the offloaded cohort for a pattern, the events the
|
|
563
|
+
Receiver held back from the SIEM). log10x_backfill_metric is deprecated and dark.
|
|
533
564
|
|
|
534
565
|
TOOL ROUTING BY USER INTENT
|
|
535
566
|
|
|
@@ -572,17 +603,16 @@ Cost investigation:
|
|
|
572
603
|
since last week" framing.)
|
|
573
604
|
- "pipeline savings / ROI" → log10x_savings
|
|
574
605
|
|
|
575
|
-
|
|
576
|
-
- "
|
|
577
|
-
"
|
|
578
|
-
"I need the events themselves, not aggregates"
|
|
579
|
-
- "
|
|
580
|
-
- "
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
lines. "Post-mortem needs the actual log events" = retriever_query, not investigate.)
|
|
606
|
+
Offloaded cohort: RAW EVENTS the Receiver held back from the SIEM (the overflow bucket):
|
|
607
|
+
- "show me what's being offloaded for <pattern>", "sample the held-back events",
|
|
608
|
+
"pull the raw events the Receiver kept out of Datadog/Splunk",
|
|
609
|
+
"I need the offloaded events themselves, not aggregates" → log10x_retriever_query
|
|
610
|
+
- "sample the offloaded <pattern> events" → log10x_retriever_query
|
|
611
|
+
- "verify the offload decision for customer X filtered by Y" → log10x_retriever_query
|
|
612
|
+
(Critical: retriever_query reads the offload bucket, the cohort the SIEM never received.
|
|
613
|
+
It is not a mirror of indexed history. For events the SIEM still holds, the SIEM is the
|
|
614
|
+
source. investigate returns aggregate pattern analysis; retriever_query returns the
|
|
615
|
+
actual offloaded log lines. Re-ingest from the bucket is customer-driven, not an MCP action.)
|
|
586
616
|
|
|
587
617
|
Root-cause across services (the investigate wedge):
|
|
588
618
|
- user pastes an error, asks "what's causing the upstream" → log10x_investigate
|
|
@@ -627,12 +657,9 @@ NATURAL TOOL CHAINS
|
|
|
627
657
|
At reporter/dev tier log10x_cost_options returns 2 modes (observe_only + install_receiver);
|
|
628
658
|
at receiver/retriever tier it returns 6 modes (drop/sample/compact/tier_down/offload/observe_only).
|
|
629
659
|
|
|
630
|
-
|
|
660
|
+
Inspect the offloaded cohort for a pattern:
|
|
631
661
|
log10x_event_lookup → log10x_retriever_query
|
|
632
662
|
|
|
633
|
-
New metric from historical archive:
|
|
634
|
-
log10x_top_patterns or log10x_investigate → log10x_backfill_metric
|
|
635
|
-
|
|
636
663
|
RESPONSE STYLE
|
|
637
664
|
|
|
638
665
|
- For cost questions: show dollar amounts prominently, emphasize before→after deltas, flag new
|
|
@@ -696,7 +723,7 @@ Tool responses carry rich label context per series (message_pattern, severity_le
|
|
|
696
723
|
|
|
697
724
|
3. **Two tiers when the user asks for verification or audit.** A "**Facts:**" / "**Interpretation:**" split is appropriate when the user is auditing or debugging your synthesis. For a normal "show me X" request, write the decoded answer inline — facts and interpretation woven together — and skip the tiering. Default to terse, single-pass prose; reach for the two-tier layout only when warranted.
|
|
698
725
|
|
|
699
|
-
4. **Refusal beats guess.** If you don't recognize a \`message_pattern\` token, severity, or label value with high confidence, say "symbol unknown" or "context unclear" and
|
|
726
|
+
4. **Refusal beats guess.** If you don't recognize a \`message_pattern\` token, severity, or label value with high confidence, say "symbol unknown" or "context unclear" and run \`log10x_event_lookup\` for a known sample. When the pattern is under an active offload action, \`log10x_retriever_query\` can sample the held-back events. Do not invent a plausible-sounding identity.
|
|
700
727
|
|
|
701
728
|
5. **No reference to patterns/services/severities outside the response.** The label set in the tool result is the universe. Phrases like "you probably also have…" or "I'd expect to see…" are forbidden — they invite the user to look for problems that aren't in the data.
|
|
702
729
|
|
|
@@ -841,8 +868,7 @@ function applyToolRegistrations(target, registry) {
|
|
|
841
868
|
// ── Tool: log10x_event_lookup ──
|
|
842
869
|
registerLog10xTool('log10x_event_lookup', eventLookupSchema, (args) => wrap('log10x_event_lookup', async () => {
|
|
843
870
|
const env = resolveEnv(getEnvs(), args.environment);
|
|
844
|
-
|
|
845
|
-
return executeEventLookup({ ...args, analyzerCost: cost }, env);
|
|
871
|
+
return executeEventLookup(args, env);
|
|
846
872
|
}));
|
|
847
873
|
// ── Tool: log10x_pattern_examples ──
|
|
848
874
|
//
|
|
@@ -855,17 +881,22 @@ registerLog10xTool('log10x_pattern_examples', patternExamplesSchema, (args) => w
|
|
|
855
881
|
const env = resolveEnv(getEnvs(), args.environment);
|
|
856
882
|
return executePatternExamples(args, env);
|
|
857
883
|
}));
|
|
884
|
+
// ── Tool: log10x_product_qa ──
|
|
885
|
+
//
|
|
886
|
+
// Local docs-corpus lookup. No env / TSDB / SIEM dependency — the
|
|
887
|
+
// corpus is shipped inside the build at build/product-kb/docs (the
|
|
888
|
+
// build script copies it from config/mksite/docs). See
|
|
889
|
+
// src/lib/product-kb/index.ts for path resolution + override env.
|
|
890
|
+
registerLog10xTool('log10x_product_qa', productQaSchema, (args) => wrap('log10x_product_qa', async () => executeProductQa(args)));
|
|
858
891
|
// ── Tool: log10x_savings ──
|
|
859
892
|
registerLog10xTool('log10x_savings', savingsSchema, (args) => wrap('log10x_savings', async () => {
|
|
860
893
|
const env = resolveEnv(getEnvs(), args.environment);
|
|
861
|
-
|
|
862
|
-
return executeSavings({ ...args, analyzerCost: cost }, env);
|
|
894
|
+
return executeSavings(args, env);
|
|
863
895
|
}));
|
|
864
896
|
// ── Tool: log10x_pattern_trend ──
|
|
865
897
|
registerLog10xTool('log10x_pattern_trend', trendSchema, (args) => wrap('log10x_pattern_trend', async () => {
|
|
866
898
|
const env = resolveEnv(getEnvs(), args.environment);
|
|
867
|
-
|
|
868
|
-
return executeTrend({ ...args, analyzerCost: cost }, env);
|
|
899
|
+
return executeTrend(args, env);
|
|
869
900
|
}));
|
|
870
901
|
// ── Tool: log10x_dependency_check ──
|
|
871
902
|
registerLog10xTool('log10x_dependency_check', dependencyCheckSchema, (args) => wrap('log10x_dependency_check', async () => executeDependencyCheck(args)));
|
|
@@ -886,24 +917,89 @@ registerLog10xTool('log10x_configure_env', configureEnvSchema, (args) => wrap('l
|
|
|
886
917
|
registerLog10xTool('log10x_set_gitops_repo', setGitopsRepoSchema, (args) => wrap('log10x_set_gitops_repo', async () => {
|
|
887
918
|
return executeSetGitopsRepo(args);
|
|
888
919
|
}));
|
|
920
|
+
// ── Tool: log10x_dest_set ──
|
|
921
|
+
// Edit the SIEM destination block on an env-config document. Separate
|
|
922
|
+
// from configure_env (which validates the live metrics backend before
|
|
923
|
+
// writing) so the agent can change destination fields without re-supplying
|
|
924
|
+
// backend credentials.
|
|
925
|
+
registerLog10xTool('log10x_dest_set', destSetSchema, (args) => wrap('log10x_dest_set', async () => {
|
|
926
|
+
return executeDestSet(args);
|
|
927
|
+
}));
|
|
928
|
+
// ── Tool: log10x_env_validate ──
|
|
929
|
+
// Schema + cross-field sanity over a stored env-config document. Catches
|
|
930
|
+
// destination/region mismatches, ingest_url shape issues, cluster-vs-offload
|
|
931
|
+
// type misalignments before downstream tools fail with vendor errors.
|
|
932
|
+
registerLog10xTool('log10x_env_validate', envValidateSchema, (args) => wrap('log10x_env_validate', async () => {
|
|
933
|
+
return executeEnvValidate(args);
|
|
934
|
+
}));
|
|
935
|
+
// ── Tool: log10x_env_diff_vs_envvars ──
|
|
936
|
+
// Compare the stored env doc against the LOG10X_* env vars the bridge
|
|
937
|
+
// would have produced. Surfaces "I set the env var but it's being ignored"
|
|
938
|
+
// drift with per-field recommendations.
|
|
939
|
+
registerLog10xTool('log10x_env_diff_vs_envvars', envDiffVsEnvvarsSchema, (args) => wrap('log10x_env_diff_vs_envvars', async () => {
|
|
940
|
+
return executeEnvDiffVsEnvvars(args);
|
|
941
|
+
}));
|
|
942
|
+
// ── Tool: log10x_offload_add ──
|
|
943
|
+
// Append a new entry to the env-config document's offload_destinations[].
|
|
944
|
+
// Multi-target is the documented use case (drain a legacy bucket while a
|
|
945
|
+
// new one is primary); the schema array stays non-empty by default.
|
|
946
|
+
registerLog10xTool('log10x_offload_add', offloadAddSchema, (args) => wrap('log10x_offload_add', async () => {
|
|
947
|
+
return executeOffloadAdd(args);
|
|
948
|
+
}));
|
|
949
|
+
// ── Tool: log10x_offload_archive ──
|
|
950
|
+
// Flip one destination's status to `archived` (kept in the list as a
|
|
951
|
+
// historical reference). Refuses when the target is the last active
|
|
952
|
+
// destination — the Receiver needs at least one active destination to
|
|
953
|
+
// route the dropped slice to.
|
|
954
|
+
registerLog10xTool('log10x_offload_archive', offloadArchiveSchema, (args) => wrap('log10x_offload_archive', async () => {
|
|
955
|
+
return executeOffloadArchive(args);
|
|
956
|
+
}));
|
|
889
957
|
// ── Tool: log10x_top_patterns ──
|
|
890
958
|
registerLog10xTool('log10x_top_patterns', topPatternsSchema, (args) => wrap('log10x_top_patterns', async () => {
|
|
891
959
|
const env = resolveEnv(getEnvs(), args.environment);
|
|
892
|
-
|
|
893
|
-
|
|
960
|
+
return executeTopPatterns(args, env);
|
|
961
|
+
}));
|
|
962
|
+
// ── Tool: log10x_pattern_diff ──
|
|
963
|
+
//
|
|
964
|
+
// Set diff of patterns across a time boundary. Compares pattern presence in
|
|
965
|
+
// two windows and returns new / retired / persistent / re_emerged sets plus
|
|
966
|
+
// co_emergence_clusters (deploy fingerprint via first_seen clustering).
|
|
967
|
+
// Coherent only because log10x pattern_hash is stable across queries;
|
|
968
|
+
// competitors that re-cluster per query can't answer this.
|
|
969
|
+
registerLog10xTool('log10x_pattern_diff', patternDiffSchema, (args) => wrap('log10x_pattern_diff', async () => {
|
|
970
|
+
const env = resolveEnv(getEnvs(), args.environment);
|
|
971
|
+
return executePatternDiff(args, env);
|
|
972
|
+
}));
|
|
973
|
+
// ── Tool: log10x_whats_changing ──
|
|
974
|
+
//
|
|
975
|
+
// Patterns ranked by delta vs a baseline window (not current cost). Restores
|
|
976
|
+
// the capability of the removed log10x_cost_drivers tool
|
|
977
|
+
// using the modern StructuredOutput envelope. Brand-new patterns (no
|
|
978
|
+
// baseline) are excluded — they go to log10x_whats_new.
|
|
979
|
+
registerLog10xTool('log10x_whats_changing', whatsChangingSchema, (args) => wrap('log10x_whats_changing', async () => {
|
|
980
|
+
const env = resolveEnv(getEnvs(), args.environment);
|
|
981
|
+
return executeWhatsChanging(args, env);
|
|
982
|
+
}));
|
|
983
|
+
// ── Tool: log10x_whats_new ──
|
|
984
|
+
//
|
|
985
|
+
// Patterns whose first_seen timestamp falls inside a recency window. Sister
|
|
986
|
+
// tool to whats_changing — new patterns have no baseline, so they get a
|
|
987
|
+
// clean home that doesn't pollute the delta-vs-baseline surface.
|
|
988
|
+
registerLog10xTool('log10x_whats_new', whatsNewSchema, (args) => wrap('log10x_whats_new', async () => {
|
|
989
|
+
const env = resolveEnv(getEnvs(), args.environment);
|
|
990
|
+
return executeWhatsNew(args, env);
|
|
894
991
|
}));
|
|
895
992
|
// ── Tool: log10x_services ──
|
|
896
993
|
registerLog10xTool('log10x_services', servicesSchema, (args) => wrap('log10x_services', async () => {
|
|
897
994
|
const env = resolveEnv(getEnvs(), args.environment);
|
|
898
|
-
|
|
899
|
-
return executeServices({ ...args, analyzerCost: cost }, env);
|
|
995
|
+
return executeServices(args, env);
|
|
900
996
|
}));
|
|
901
997
|
// ── Tool: log10x_overflow_contents ──
|
|
902
998
|
//
|
|
903
|
-
//
|
|
999
|
+
// The contents view of the
|
|
904
1000
|
// customer-owned offload bucket. Queries dropped-by-pattern from the
|
|
905
1001
|
// TSDB, joins to the cap-CSV to filter to action=offload only, and
|
|
906
|
-
// routes the agent to log10x_retriever_query
|
|
1002
|
+
// routes the agent to log10x_retriever_query to inspect the offloaded cohort. See
|
|
907
1003
|
// the long docstring on src/tools/overflow-contents.ts for the
|
|
908
1004
|
// design rationale + cap-CSV degraded-mode semantics.
|
|
909
1005
|
registerLog10xTool('log10x_overflow_contents', overflowContentsSchema, (args) => wrap('log10x_overflow_contents', async () => {
|
|
@@ -940,6 +1036,21 @@ registerLog10xTool('log10x_retriever_series', retrieverSeriesSchema, (args) => w
|
|
|
940
1036
|
}));
|
|
941
1037
|
// ── Tool: log10x_retriever_query_status ──
|
|
942
1038
|
registerLog10xTool('log10x_retriever_query_status', retrieverQueryStatusSchema, (args) => wrap('log10x_retriever_query_status', async () => executeRetrieverQueryStatus(args)));
|
|
1039
|
+
// ── Tool: log10x_retriever_probe ──
|
|
1040
|
+
//
|
|
1041
|
+
// End-to-end probe of the deployed retriever chain. Fires a synthetic query
|
|
1042
|
+
// and asserts every stage (offload bucket freshness, indexer pipeline running,
|
|
1043
|
+
// SQS depths, pod ready, CloudWatch scan/stream events, S3 qr/*.jsonl, MCP
|
|
1044
|
+
// events returned). Returns a structured verdict (green / broken / unknown)
|
|
1045
|
+
// with per-stage asserts and a remedy on the first failure.
|
|
1046
|
+
registerLog10xTool('log10x_retriever_probe', retrieverProbeSchema, (args) => wrap('log10x_retriever_probe', async () => executeRetrieverProbe(args)));
|
|
1047
|
+
// ── Tool: log10x_retriever_register ──
|
|
1048
|
+
//
|
|
1049
|
+
// Write the Retriever endpoint + queue coordinates onto an existing
|
|
1050
|
+
// environment-config document. Requires `log10x_env_register` to have
|
|
1051
|
+
// created the env first — refuses on env_not_found rather than
|
|
1052
|
+
// stamping a partial document the rest of the schema can't satisfy.
|
|
1053
|
+
registerLog10xTool('log10x_retriever_register', retrieverRegisterSchema, (args) => wrap('log10x_retriever_register', async () => executeRetrieverRegister(args)));
|
|
943
1054
|
// ── Tool: log10x_backfill_metric ──
|
|
944
1055
|
registerLog10xTool('log10x_backfill_metric', backfillMetricSchema, (args) => wrap('log10x_backfill_metric', async () => {
|
|
945
1056
|
const env = resolveEnv(getEnvs(), args.environment);
|
|
@@ -1028,6 +1139,14 @@ registerLog10xTool('log10x_create_env', createEnvSchema, (args) => wrap('log10x_
|
|
|
1028
1139
|
registerLog10xTool('log10x_update_env', updateEnvSchema, (args) => wrap('log10x_update_env', async () => executeUpdateEnv(args, getEnvs())));
|
|
1029
1140
|
// ── Tool: log10x_delete_env ──
|
|
1030
1141
|
registerLog10xTool('log10x_delete_env', deleteEnvSchema, (args) => wrap('log10x_delete_env', async () => executeDeleteEnv(args, getEnvs())));
|
|
1142
|
+
// ── Tool: log10x_env_register ──
|
|
1143
|
+
//
|
|
1144
|
+
// Writes a full EnvironmentConfig document (cluster identity, SIEM
|
|
1145
|
+
// destination, offload destinations, streamer + retriever endpoints)
|
|
1146
|
+
// to whichever on-prem store the customer's cloud uses. Distinct from
|
|
1147
|
+
// create_env: that mints account-level identity on the SaaS backend;
|
|
1148
|
+
// this writes the cluster-side descriptor every tool resolves against.
|
|
1149
|
+
registerLog10xTool('log10x_env_register', envRegisterSchema, (args) => wrap('log10x_env_register', async () => executeEnvRegister(args)));
|
|
1031
1150
|
// ── Tool: log10x_rotate_api_key ──
|
|
1032
1151
|
registerLog10xTool('log10x_rotate_api_key', rotateApiKeySchema, (args) => wrap('log10x_rotate_api_key', async () => executeRotateApiKey(args, getEnvs())));
|
|
1033
1152
|
// ── Tool: log10x_customer_metrics_query (v1.4) ──
|
|
@@ -1122,7 +1241,10 @@ registerLog10xTool('log10x_advise_retriever', adviseRetrieverSchema, (args) => w
|
|
|
1122
1241
|
// ── Tool: log10x_advise_install (install wizard for Reporter / Receiver) ──
|
|
1123
1242
|
registerLog10xTool('log10x_advise_install', adviseInstallSchema, (args) => wrap('log10x_advise_install', () => executeAdviseInstall(args, getEnvs(), server)));
|
|
1124
1243
|
// ── Tool: log10x_configure_engine (unified per-pattern action-plan PR author) ──
|
|
1125
|
-
registerLog10xTool('log10x_configure_engine', configureEngineSchema, (args) => wrap('log10x_configure_engine', () =>
|
|
1244
|
+
registerLog10xTool('log10x_configure_engine', configureEngineSchema, (args) => wrap('log10x_configure_engine', () => {
|
|
1245
|
+
const env = resolveEnv(getEnvs(), args.environment);
|
|
1246
|
+
return executeConfigureEngine(args, env);
|
|
1247
|
+
}));
|
|
1126
1248
|
// ── Tool: log10x_estimate_savings (forecast + verify modes) ──
|
|
1127
1249
|
registerLog10xTool('log10x_estimate_savings', estimateSavingsSchema, (args) => wrap('log10x_estimate_savings', () => {
|
|
1128
1250
|
const env = resolveEnv(getEnvs(), args.environment);
|
|
@@ -1147,11 +1269,10 @@ registerLog10xTool('log10x_baseline', baselineSchema, (args) => wrap('log10x_bas
|
|
|
1147
1269
|
// baseline_window is the pre-policy reference.
|
|
1148
1270
|
// 3. Adapts VerifyResult → WeeklyVerifyResult.
|
|
1149
1271
|
//
|
|
1150
|
-
//
|
|
1151
|
-
//
|
|
1152
|
-
//
|
|
1153
|
-
//
|
|
1154
|
-
// cap-CSV join land. Item 1 only unblocks the not_ready hard-return.
|
|
1272
|
+
// Limitation: runEstimateVerify queries `[range]` ending at "now", so
|
|
1273
|
+
// every weekly loop hits the same live snapshot. Week-specific windows
|
|
1274
|
+
// and the per_pattern_breakdown cap-CSV join are not yet implemented;
|
|
1275
|
+
// this path only unblocks the not_ready hard-return.
|
|
1155
1276
|
_setVerifyRunner(async ({ commitment, week_start, week_end }) => {
|
|
1156
1277
|
const env = resolveEnv(getEnvs(), commitment.env);
|
|
1157
1278
|
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
@@ -1159,13 +1280,33 @@ _setVerifyRunner(async ({ commitment, week_start, week_end }) => {
|
|
|
1159
1280
|
// Best-effort fetch of action-intent.json (canonical action source) and
|
|
1160
1281
|
// cap CSV (byte-cap context + legacy action suffix fallback). Both are
|
|
1161
1282
|
// passed to runEstimateVerify for action-split attribution. On any
|
|
1162
|
-
// failure
|
|
1163
|
-
//
|
|
1164
|
-
//
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1283
|
+
// failure the respective field is undefined and the verify run falls
|
|
1284
|
+
// back to single-bucket attribution in commitment-report.
|
|
1285
|
+
//
|
|
1286
|
+
// Delivery channel comes from commitment.delivery_target captured at
|
|
1287
|
+
// apply time:
|
|
1288
|
+
// - kind='configmap' → kubectl get configmap (the kubectl_configmap
|
|
1289
|
+
// delivery path; otel-demo and other k8s-native deploys)
|
|
1290
|
+
// - kind='gitops' or absent → gh api (the original PR-merge path;
|
|
1291
|
+
// also the back-compat path for commitments persisted before
|
|
1292
|
+
// delivery_target was added)
|
|
1293
|
+
// When both channels are wired, gitops wins (PR is the durable source
|
|
1294
|
+
// of truth and matches the source_disclosure label).
|
|
1295
|
+
const target = commitment.delivery_target;
|
|
1296
|
+
let capCsv;
|
|
1297
|
+
let actionIntent;
|
|
1298
|
+
if (target?.kind === 'configmap') {
|
|
1299
|
+
[capCsv, actionIntent] = await Promise.all([
|
|
1300
|
+
fetchCapCsvFromConfigMap(target.name, target.namespace).catch(() => undefined),
|
|
1301
|
+
fetchActionIntentFromConfigMap(target.name, target.namespace).catch(() => undefined),
|
|
1302
|
+
]);
|
|
1303
|
+
}
|
|
1304
|
+
else {
|
|
1305
|
+
[capCsv, actionIntent] = await Promise.all([
|
|
1306
|
+
fetchCapCsvForEnv(env).catch(() => undefined),
|
|
1307
|
+
fetchActionIntentForEnv(env).catch(() => undefined),
|
|
1308
|
+
]);
|
|
1309
|
+
}
|
|
1169
1310
|
const vr = await runEstimateVerify({
|
|
1170
1311
|
destination: commitment.destination,
|
|
1171
1312
|
baseline_window: commitment.baseline_window || '7d',
|
|
@@ -1204,16 +1345,20 @@ if (process.env.LOG10X_DEV_MODE === 'true') {
|
|
|
1204
1345
|
const REGISTERED_TOOLS = [
|
|
1205
1346
|
{ name: 'log10x_start', intent: 'CALL FIRST on any cost / orient / "where do I start" question — returns tier + action menu + must_ask_user question; agent must surface verbatim and wait for user pick before any other tool' },
|
|
1206
1347
|
{ name: 'log10x_event_lookup', intent: 'What is this single log line — resolve to stable identity + cost + AI classification' },
|
|
1207
|
-
{ name: 'log10x_pattern_examples', intent: 'Recent live events for a pattern from the log analyzer with template-parsed slot values
|
|
1348
|
+
{ name: 'log10x_pattern_examples', intent: 'Recent live events for a pattern from the log analyzer with template-parsed slot values, bounded to 24h. When the pattern is offloaded, retriever_query samples the held-back cohort.' },
|
|
1208
1349
|
{ name: 'log10x_savings', intent: 'Pipeline ROI — how much receiver / retriever are saving in dollars' },
|
|
1209
1350
|
{ name: 'log10x_pattern_trend', intent: 'Time series for a pattern — volume + cost history, spike detection, sparkline' },
|
|
1210
1351
|
{ name: 'log10x_dependency_check', intent: 'Scan SIEM + dashboards + alerts for refs to a pattern before muting / deleting it' },
|
|
1211
1352
|
{ name: 'log10x_top_patterns', intent: 'Top N patterns by current cost, with per-row delta vs comparison_window and newly-emerged section' },
|
|
1353
|
+
{ name: 'log10x_pattern_diff', intent: 'Set diff of patterns across a time boundary — new/retired/persistent/re_emerged + co_emergence_clusters (deploy fingerprint). Coherent across boundaries because pattern_hash is stable across queries.' },
|
|
1354
|
+
{ name: 'log10x_whats_changing', intent: 'Patterns ranked by delta vs baseline (growth/shrinkage). Brand-new patterns excluded — see log10x_whats_new for those. Restores the deleted log10x_cost_drivers capability.' },
|
|
1355
|
+
{ name: 'log10x_whats_new', intent: 'Patterns whose first_seen falls inside a recency window. Separate from delta-vs-baseline because new patterns have no baseline.' },
|
|
1212
1356
|
{ name: 'log10x_investigate', intent: 'Single-call root-cause — causal chain for acute spikes or cohort for drift' },
|
|
1213
1357
|
{ name: 'log10x_resolve_batch', intent: 'Pasted-batch triage — per-pattern variable concentration + next actions' },
|
|
1214
|
-
{ name: 'log10x_retriever_query', intent: '
|
|
1215
|
-
{ name: 'log10x_retriever_series', intent: '
|
|
1216
|
-
{ name: '
|
|
1358
|
+
{ name: 'log10x_retriever_query', intent: 'Read the offloaded cohort for a pattern (tenx_user_pattern) from the customer-owned overflow bucket with JS filter expressions: the events the Receiver held back from the SIEM' },
|
|
1359
|
+
{ name: 'log10x_retriever_series', intent: 'Time series over the offloaded cohort in the overflow bucket: auto-selects exact aggregation vs sampled parallel sub-window queries' },
|
|
1360
|
+
{ name: 'log10x_retriever_probe', intent: 'End-to-end retriever chain probe — fires a synthetic query and asserts every stage (offload bucket, indexer pipeline, SQS, pod ready, CW scan/stream, S3 jsonl, MCP events). Returns green/broken/unknown with per-stage asserts and remedies.' },
|
|
1361
|
+
{ name: 'log10x_backfill_metric', intent: 'Deprecated, kept dark. The live isDropped metric surface answers overflow-volume questions as a TSDB query.' },
|
|
1217
1362
|
{ name: 'log10x_doctor', intent: 'Startup health check — env config, gateway, tier, freshness, Retriever, paste endpoint, cross-pillar enrichment floor' },
|
|
1218
1363
|
{ name: 'log10x_login_status', intent: 'Report credential / env state — identity, env list with permissions, demo-mode upgrade guide if applicable' },
|
|
1219
1364
|
{ name: 'log10x_signin_start', intent: 'Step 1 of Auth0 Device Flow signup/signin: opens browser, returns the user_code + device_code so the model can surface them and chain to log10x_signin_complete' },
|
|
@@ -1221,9 +1366,13 @@ const REGISTERED_TOOLS = [
|
|
|
1221
1366
|
{ name: 'log10x_signout', intent: 'Wipe ~/.log10x/credentials and fall back to demo mode (or lower-priority config); does not revoke the key on the backend' },
|
|
1222
1367
|
{ name: 'log10x_update_settings', intent: 'Update user metadata (analyzer cost, AI provider, etc.) via POST /api/v1/user' },
|
|
1223
1368
|
{ name: 'log10x_create_env', intent: 'Create a new Log10x environment on the account; pairs with log10x_advise_install for end-to-end provision-and-install' },
|
|
1224
|
-
{ name: 'log10x_update_env', intent: 'Rename an env or change the default
|
|
1369
|
+
{ name: 'log10x_update_env', intent: 'Rename an env or change the default; requires the backend PUT route' },
|
|
1225
1370
|
{ name: 'log10x_delete_env', intent: 'Delete an env (destructive, irrecoverable) — requires confirm_name matching the env\'s name' },
|
|
1226
1371
|
{ name: 'log10x_set_gitops_repo', intent: 'Write gitops.repo to ~/.log10x/envs.json so configure_engine can author cap-CSV PRs; confirm="set-now" required' },
|
|
1372
|
+
{ name: 'log10x_dest_set', intent: 'Update the SIEM destination block (siem_vendor / region / log_group_prefix / ingest_url) on an env-config document; idempotent, validates new doc against schema before write' },
|
|
1373
|
+
{ name: 'log10x_env_validate', intent: 'Schema parse + cross-field sanity check on a stored env-config document — region/vendor pairing, ingest_url shape, cluster vs offload type alignment, active-offload presence' },
|
|
1374
|
+
{ name: 'log10x_env_diff_vs_envvars', intent: 'Diff stored env-config doc against LOG10X_* env vars — surfaces silent-ignored env vars with per-field remediation; pure-on-prem-store configs return empty diff' },
|
|
1375
|
+
{ name: 'log10x_retriever_register', intent: 'Attach the Retriever endpoint + queue coordinates to an existing env-config document. Requires log10x_env_register to have created the env first.' },
|
|
1227
1376
|
{ name: 'log10x_rotate_api_key', intent: 'Rotate the Log10x API key (destructive) — old key invalidated immediately, new one persisted to ~/.log10x/credentials' },
|
|
1228
1377
|
{ name: 'log10x_customer_metrics_query', intent: 'Direct PromQL passthrough to the customer metric backend (escape hatch for cross-pillar investigations)' },
|
|
1229
1378
|
{ name: 'log10x_discover_join', intent: 'Auto-discover the join label between Log10x pattern metrics and the customer metric backend via Jaccard similarity' },
|
|
@@ -1235,14 +1384,16 @@ const REGISTERED_TOOLS = [
|
|
|
1235
1384
|
{ name: 'log10x_poc_from_local', intent: 'Run the POC from local kubectl logs (no SIEM credentials needed); industry-pricing matrix instead of bill prediction' },
|
|
1236
1385
|
{ name: 'log10x_discover_env', intent: 'Read-only probe of k8s + AWS — returns a snapshot_id the advise_* tools consume' },
|
|
1237
1386
|
{ name: 'log10x_advise_install', intent: 'Install wizard for Reporter / Receiver — walks the user through app / forwarder / backends / airgapped / license, then emits a concrete helm plan' },
|
|
1238
|
-
{ name: 'log10x_advise_retriever', intent: 'Retriever install/verify/teardown plan
|
|
1387
|
+
{ name: 'log10x_advise_retriever', intent: 'Retriever install/verify/teardown plan: standalone reader over the customer-owned offload S3 bucket (S3 + SQS indexer + query)' },
|
|
1239
1388
|
{ name: 'log10x_configure_engine', intent: 'Unified per-pattern action-plan PR author — resolves a budget to a per-pattern plan (pass | sample | compact | drop | tier_down) under a per-destination cost model and emits a gitops PR.' },
|
|
1240
1389
|
{ name: 'log10x_estimate_savings', intent: 'Two-mode savings estimator — forecast mode projects bytes_out + $/mo for a proposed plan under the per-destination cost model; verify mode counts realized savings from the engine `isDropped` label with cap-hit / drift / new-patterns / leakage attribution.' },
|
|
1241
1390
|
{ name: 'log10x_baseline', intent: 'Pre-flight readiness gate for cost-reduction tools — verifies Reporter age (default 7d), pattern-coverage stability, and absence of acute anomalies; returns structured `not_ready` with the specific gate(s) that failed.' },
|
|
1242
1391
|
{ name: 'log10x_commitment_report', intent: 'CFO-facing weekly aggregate against a commitment record — Bayesian Beta(2,2) confidence prior on realized savings, markdown report suitable for sharing.' },
|
|
1243
1392
|
{ name: 'log10x_pattern_mitigate', intent: 'Return the env-gated mitigation options + exact configs for a pattern (drop @ analyzer, drop @ forwarder, mute @ 10x, compact @ 10x) in user terms with env-capability gating' },
|
|
1244
|
-
{ name: 'log10x_overflow_contents', intent: 'Contents view of the customer-owned offload S3 bucket
|
|
1393
|
+
{ name: 'log10x_overflow_contents', intent: 'Contents view of the customer-owned offload S3 bucket: per-pattern bytes, event count, time-first/last-seen, growth-rate; filtered to action=offload via the cap-CSV. Routes the agent to retriever_query to inspect the offloaded cohort.' },
|
|
1245
1394
|
{ name: 'log10x_setup_recurring', intent: 'Progressive wizard to configure a recurring cost-reduction agent — target services, savings %, schedule, scheduler (k8s/GHA/crontab), gitops repo — emits policy.yaml + scheduler manifest' },
|
|
1395
|
+
{ name: 'log10x_offload_add', intent: 'Append a new offload destination (s3 / gcs / azure_blob / file) to an env-config document\'s offload_destinations[]. Multi-target offload is allowed; nickname must be unique within the list.' },
|
|
1396
|
+
{ name: 'log10x_offload_archive', intent: 'Flip an offload destination\'s status to `archived` and stamp archived_at. Kept in the list as a historical reference. Refuses when the target is the only active destination — the Receiver requires at least one.' },
|
|
1246
1397
|
];
|
|
1247
1398
|
async function handleCliFlags() {
|
|
1248
1399
|
const args = process.argv.slice(2);
|
|
@@ -1487,11 +1638,20 @@ async function main() {
|
|
|
1487
1638
|
default_env: loaded.default.nickname,
|
|
1488
1639
|
demo_mode: loaded.isDemoMode,
|
|
1489
1640
|
demo_playground: DEMO_PLAYGROUND,
|
|
1641
|
+
read_only_mode: isReadOnlyMode(),
|
|
1490
1642
|
manifest_loaded: manifest !== null,
|
|
1491
1643
|
boot_mode: bootMode?.mode,
|
|
1492
1644
|
boot_mode_backend: bootMode?.detectionPath,
|
|
1493
1645
|
boot_mode_probe_ms: bootMode?.probeDurationMs,
|
|
1494
1646
|
});
|
|
1647
|
+
// Read-only playground banner. The structured `mcp.boot` line is
|
|
1648
|
+
// gated behind LOG10X_MCP_LOG_LEVEL (silent by default), so operators
|
|
1649
|
+
// would not see read-only state in stock installs. Force a stderr
|
|
1650
|
+
// banner when the gate is on, regardless of log level.
|
|
1651
|
+
if (isReadOnlyMode()) {
|
|
1652
|
+
// eslint-disable-next-line no-console
|
|
1653
|
+
console.error(`[log10x-mcp] Running in read-only mode (LOG10X_MCP_READ_ONLY=${process.env.LOG10X_MCP_READ_ONLY}). Writer tools will return demo_read_only envelopes instead of executing.`);
|
|
1654
|
+
}
|
|
1495
1655
|
// Surface mode-detect resolution to stderr at boot so it shows up
|
|
1496
1656
|
// in MCP-client logs without needing to call `log10x_doctor`.
|
|
1497
1657
|
if (bootMode) {
|