@miragon/pulse-analytics-connector 0.0.0-bootstrap.0 → 0.21.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.
- package/LICENSE +21 -0
- package/README.md +86 -3
- package/dist/bpmn-name-lookup.d.ts +72 -0
- package/dist/bpmn-name-lookup.d.ts.map +1 -0
- package/dist/bpmn-name-lookup.js +123 -0
- package/dist/bpmn-name-lookup.js.map +1 -0
- package/dist/bpmn-name-lookup.test.d.ts +2 -0
- package/dist/bpmn-name-lookup.test.d.ts.map +1 -0
- package/dist/bpmn-name-lookup.test.js +287 -0
- package/dist/bpmn-name-lookup.test.js.map +1 -0
- package/dist/bpmn-names.d.ts +38 -0
- package/dist/bpmn-names.d.ts.map +1 -0
- package/dist/bpmn-names.js +22 -0
- package/dist/bpmn-names.js.map +1 -0
- package/dist/brand-gates.test.d.ts +2 -0
- package/dist/brand-gates.test.d.ts.map +1 -0
- package/dist/brand-gates.test.js +58 -0
- package/dist/brand-gates.test.js.map +1 -0
- package/dist/builder-texts.d.ts +4 -0
- package/dist/builder-texts.d.ts.map +1 -0
- package/dist/builder-texts.js +14 -0
- package/dist/builder-texts.js.map +1 -0
- package/dist/builder-texts.test.d.ts +2 -0
- package/dist/builder-texts.test.d.ts.map +1 -0
- package/dist/builder-texts.test.js +32 -0
- package/dist/builder-texts.test.js.map +1 -0
- package/dist/definition.d.ts +3 -0
- package/dist/definition.d.ts.map +1 -0
- package/dist/definition.js +151 -0
- package/dist/definition.js.map +1 -0
- package/dist/engine-ids.d.ts +42 -0
- package/dist/engine-ids.d.ts.map +1 -0
- package/dist/engine-ids.js +50 -0
- package/dist/engine-ids.js.map +1 -0
- package/dist/engine-scope.test.d.ts +2 -0
- package/dist/engine-scope.test.d.ts.map +1 -0
- package/dist/engine-scope.test.js +260 -0
- package/dist/engine-scope.test.js.map +1 -0
- package/dist/heatmap-data.d.ts +15 -0
- package/dist/heatmap-data.d.ts.map +1 -0
- package/dist/heatmap-data.js +2 -0
- package/dist/heatmap-data.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/instructions.d.ts +8 -0
- package/dist/instructions.d.ts.map +1 -0
- package/dist/instructions.js +33 -0
- package/dist/instructions.js.map +1 -0
- package/dist/messages/de.ask-ai.d.ts +9 -0
- package/dist/messages/de.ask-ai.d.ts.map +1 -0
- package/dist/messages/de.ask-ai.js +18 -0
- package/dist/messages/de.ask-ai.js.map +1 -0
- package/dist/messages/de.builder.d.ts +12 -0
- package/dist/messages/de.builder.d.ts.map +1 -0
- package/dist/messages/de.builder.js +53 -0
- package/dist/messages/de.builder.js.map +1 -0
- package/dist/messages/de.server.d.ts +8 -0
- package/dist/messages/de.server.d.ts.map +1 -0
- package/dist/messages/de.server.js +26 -0
- package/dist/messages/de.server.js.map +1 -0
- package/dist/messages/de.sweep.d.ts +10 -0
- package/dist/messages/de.sweep.d.ts.map +1 -0
- package/dist/messages/de.sweep.js +203 -0
- package/dist/messages/de.sweep.js.map +1 -0
- package/dist/messages/en.ask-ai.d.ts +25 -0
- package/dist/messages/en.ask-ai.d.ts.map +1 -0
- package/dist/messages/en.ask-ai.js +24 -0
- package/dist/messages/en.ask-ai.js.map +1 -0
- package/dist/messages/en.builder.d.ts +12 -0
- package/dist/messages/en.builder.d.ts.map +1 -0
- package/dist/messages/en.builder.js +53 -0
- package/dist/messages/en.builder.js.map +1 -0
- package/dist/messages/en.server.d.ts +8 -0
- package/dist/messages/en.server.d.ts.map +1 -0
- package/dist/messages/en.server.js +26 -0
- package/dist/messages/en.server.js.map +1 -0
- package/dist/messages/en.sweep.d.ts +11 -0
- package/dist/messages/en.sweep.d.ts.map +1 -0
- package/dist/messages/en.sweep.js +204 -0
- package/dist/messages/en.sweep.js.map +1 -0
- package/dist/messages/glossary.d.ts +26 -0
- package/dist/messages/glossary.d.ts.map +1 -0
- package/dist/messages/glossary.js +37 -0
- package/dist/messages/glossary.js.map +1 -0
- package/dist/messages/glossary.test.d.ts +2 -0
- package/dist/messages/glossary.test.d.ts.map +1 -0
- package/dist/messages/glossary.test.js +109 -0
- package/dist/messages/glossary.test.js.map +1 -0
- package/dist/messages/index.d.ts +12 -0
- package/dist/messages/index.d.ts.map +1 -0
- package/dist/messages/index.js +23 -0
- package/dist/messages/index.js.map +1 -0
- package/dist/messages/plural.d.ts +10 -0
- package/dist/messages/plural.d.ts.map +1 -0
- package/dist/messages/plural.js +17 -0
- package/dist/messages/plural.js.map +1 -0
- package/dist/messages/use-t.d.ts +10 -0
- package/dist/messages/use-t.d.ts.map +1 -0
- package/dist/messages/use-t.js +10 -0
- package/dist/messages/use-t.js.map +1 -0
- package/dist/module.d.ts +48 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +174 -0
- package/dist/module.js.map +1 -0
- package/dist/module.test.d.ts +2 -0
- package/dist/module.test.d.ts.map +1 -0
- package/dist/module.test.js +230 -0
- package/dist/module.test.js.map +1 -0
- package/dist/named-views.d.ts +27 -0
- package/dist/named-views.d.ts.map +1 -0
- package/dist/named-views.js +73 -0
- package/dist/named-views.js.map +1 -0
- package/dist/named-views.test.d.ts +2 -0
- package/dist/named-views.test.d.ts.map +1 -0
- package/dist/named-views.test.js +110 -0
- package/dist/named-views.test.js.map +1 -0
- package/dist/plugin.d.ts +44 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +52 -0
- package/dist/plugin.js.map +1 -0
- package/dist/prometheus-wiring.test.d.ts +2 -0
- package/dist/prometheus-wiring.test.d.ts.map +1 -0
- package/dist/prometheus-wiring.test.js +142 -0
- package/dist/prometheus-wiring.test.js.map +1 -0
- package/dist/server-locale.d.ts +48 -0
- package/dist/server-locale.d.ts.map +1 -0
- package/dist/server-locale.js +33 -0
- package/dist/server-locale.js.map +1 -0
- package/dist/settings-tools.d.ts +23 -0
- package/dist/settings-tools.d.ts.map +1 -0
- package/dist/settings-tools.js +100 -0
- package/dist/settings-tools.js.map +1 -0
- package/dist/settings.d.ts +77 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +99 -0
- package/dist/settings.js.map +1 -0
- package/dist/settings.test.d.ts +2 -0
- package/dist/settings.test.d.ts.map +1 -0
- package/dist/settings.test.js +299 -0
- package/dist/settings.test.js.map +1 -0
- package/dist/steps/app-config.d.ts +30 -0
- package/dist/steps/app-config.d.ts.map +1 -0
- package/dist/steps/app-config.js +46 -0
- package/dist/steps/app-config.js.map +1 -0
- package/dist/steps/dashboard.d.ts +12 -0
- package/dist/steps/dashboard.d.ts.map +1 -0
- package/dist/steps/dashboard.js +58 -0
- package/dist/steps/dashboard.js.map +1 -0
- package/dist/steps/failure-dashboard.d.ts +10 -0
- package/dist/steps/failure-dashboard.d.ts.map +1 -0
- package/dist/steps/failure-dashboard.js +32 -0
- package/dist/steps/failure-dashboard.js.map +1 -0
- package/dist/steps/index.d.ts +3 -0
- package/dist/steps/index.d.ts.map +1 -0
- package/dist/steps/index.js +3 -0
- package/dist/steps/index.js.map +1 -0
- package/dist/steps/steps.test.d.ts +2 -0
- package/dist/steps/steps.test.d.ts.map +1 -0
- package/dist/steps/steps.test.js +153 -0
- package/dist/steps/steps.test.js.map +1 -0
- package/dist/tool-names.d.ts +13 -0
- package/dist/tool-names.d.ts.map +1 -0
- package/dist/tool-names.js +27 -0
- package/dist/tool-names.js.map +1 -0
- package/dist/tools/cluster-compare.d.ts +8 -0
- package/dist/tools/cluster-compare.d.ts.map +1 -0
- package/dist/tools/cluster-compare.js +17 -0
- package/dist/tools/cluster-compare.js.map +1 -0
- package/dist/tools/element.d.ts +8 -0
- package/dist/tools/element.d.ts.map +1 -0
- package/dist/tools/element.js +25 -0
- package/dist/tools/element.js.map +1 -0
- package/dist/tools/engine-compare.d.ts +8 -0
- package/dist/tools/engine-compare.d.ts.map +1 -0
- package/dist/tools/engine-compare.js +18 -0
- package/dist/tools/engine-compare.js.map +1 -0
- package/dist/tools/engine-compare.test.d.ts +2 -0
- package/dist/tools/engine-compare.test.d.ts.map +1 -0
- package/dist/tools/engine-compare.test.js +166 -0
- package/dist/tools/engine-compare.test.js.map +1 -0
- package/dist/tools/engine-landscape.d.ts +7 -0
- package/dist/tools/engine-landscape.d.ts.map +1 -0
- package/dist/tools/engine-landscape.js +13 -0
- package/dist/tools/engine-landscape.js.map +1 -0
- package/dist/tools/engine-landscape.test.d.ts +2 -0
- package/dist/tools/engine-landscape.test.d.ts.map +1 -0
- package/dist/tools/engine-landscape.test.js +110 -0
- package/dist/tools/engine-landscape.test.js.map +1 -0
- package/dist/tools/failures.d.ts +7 -0
- package/dist/tools/failures.d.ts.map +1 -0
- package/dist/tools/failures.js +13 -0
- package/dist/tools/failures.js.map +1 -0
- package/dist/tools/health.d.ts +7 -0
- package/dist/tools/health.d.ts.map +1 -0
- package/dist/tools/health.js +23 -0
- package/dist/tools/health.js.map +1 -0
- package/dist/tools/health.test.d.ts +2 -0
- package/dist/tools/health.test.d.ts.map +1 -0
- package/dist/tools/health.test.js +119 -0
- package/dist/tools/health.test.js.map +1 -0
- package/dist/tools/index.d.ts +18 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +35 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/performance.d.ts +8 -0
- package/dist/tools/performance.d.ts.map +1 -0
- package/dist/tools/performance.js +25 -0
- package/dist/tools/performance.js.map +1 -0
- package/dist/tools/performance.test.d.ts +2 -0
- package/dist/tools/performance.test.d.ts.map +1 -0
- package/dist/tools/performance.test.js +176 -0
- package/dist/tools/performance.test.js.map +1 -0
- package/dist/tools/version-compare.d.ts +8 -0
- package/dist/tools/version-compare.d.ts.map +1 -0
- package/dist/tools/version-compare.js +17 -0
- package/dist/tools/version-compare.js.map +1 -0
- package/dist/tools/version-compare.test.d.ts +2 -0
- package/dist/tools/version-compare.test.d.ts.map +1 -0
- package/dist/tools/version-compare.test.js +82 -0
- package/dist/tools/version-compare.test.js.map +1 -0
- package/dist/toolsets.d.ts +17 -0
- package/dist/toolsets.d.ts.map +1 -0
- package/dist/toolsets.js +47 -0
- package/dist/toolsets.js.map +1 -0
- package/dist/toolsets.test.d.ts +2 -0
- package/dist/toolsets.test.d.ts.map +1 -0
- package/dist/toolsets.test.js +91 -0
- package/dist/toolsets.test.js.map +1 -0
- package/dist/view-title.test.d.ts +2 -0
- package/dist/view-title.test.d.ts.map +1 -0
- package/dist/view-title.test.js +91 -0
- package/dist/view-title.test.js.map +1 -0
- package/dist/widget-tools/comparisons.d.ts +13 -0
- package/dist/widget-tools/comparisons.d.ts.map +1 -0
- package/dist/widget-tools/comparisons.js +177 -0
- package/dist/widget-tools/comparisons.js.map +1 -0
- package/dist/widget-tools/comparisons.test.d.ts +2 -0
- package/dist/widget-tools/comparisons.test.d.ts.map +1 -0
- package/dist/widget-tools/comparisons.test.js +123 -0
- package/dist/widget-tools/comparisons.test.js.map +1 -0
- package/dist/widget-tools/shared.d.ts +36 -0
- package/dist/widget-tools/shared.d.ts.map +1 -0
- package/dist/widget-tools/shared.js +39 -0
- package/dist/widget-tools/shared.js.map +1 -0
- package/dist/widget-tools.d.ts +25 -0
- package/dist/widget-tools.d.ts.map +1 -0
- package/dist/widget-tools.js +269 -0
- package/dist/widget-tools.js.map +1 -0
- package/dist/widget-tools.test.d.ts +2 -0
- package/dist/widget-tools.test.d.ts.map +1 -0
- package/dist/widget-tools.test.js +272 -0
- package/dist/widget-tools.test.js.map +1 -0
- package/package.json +91 -5
- package/src/bpmn-name-lookup.test.ts +333 -0
- package/src/bpmn-name-lookup.ts +197 -0
- package/src/bpmn-names.ts +51 -0
- package/src/brand-gates.test.ts +69 -0
- package/src/builder-texts.test.ts +40 -0
- package/src/builder-texts.ts +15 -0
- package/src/definition.ts +181 -0
- package/src/engine-ids.ts +85 -0
- package/src/engine-scope.test.ts +324 -0
- package/src/heatmap-data.ts +14 -0
- package/src/index.ts +4 -0
- package/src/instructions.ts +33 -0
- package/src/messages/GLOSSARY.md +88 -0
- package/src/messages/de.ask-ai.ts +28 -0
- package/src/messages/de.builder.ts +77 -0
- package/src/messages/de.server.ts +39 -0
- package/src/messages/de.sweep.ts +244 -0
- package/src/messages/en.ask-ai.ts +34 -0
- package/src/messages/en.builder.ts +76 -0
- package/src/messages/en.server.ts +39 -0
- package/src/messages/en.sweep.ts +240 -0
- package/src/messages/glossary.test.ts +122 -0
- package/src/messages/glossary.ts +62 -0
- package/src/messages/index.ts +24 -0
- package/src/messages/plural.ts +18 -0
- package/src/messages/use-t.ts +12 -0
- package/src/module.test.ts +319 -0
- package/src/module.ts +211 -0
- package/src/named-views.test.ts +141 -0
- package/src/named-views.ts +97 -0
- package/src/plugin.ts +94 -0
- package/src/prometheus-wiring.test.ts +174 -0
- package/src/server-locale.ts +59 -0
- package/src/settings-tools.ts +170 -0
- package/src/settings.test.ts +402 -0
- package/src/settings.ts +114 -0
- package/src/steps/app-config.ts +75 -0
- package/src/steps/dashboard.ts +73 -0
- package/src/steps/failure-dashboard.ts +38 -0
- package/src/steps/index.ts +2 -0
- package/src/steps/steps.test.ts +216 -0
- package/src/tool-names.ts +26 -0
- package/src/tools/cluster-compare.ts +28 -0
- package/src/tools/element.ts +35 -0
- package/src/tools/engine-compare.test.ts +210 -0
- package/src/tools/engine-compare.ts +30 -0
- package/src/tools/engine-landscape.test.ts +138 -0
- package/src/tools/engine-landscape.ts +21 -0
- package/src/tools/failures.ts +19 -0
- package/src/tools/health.test.ts +156 -0
- package/src/tools/health.ts +29 -0
- package/src/tools/index.ts +44 -0
- package/src/tools/performance.test.ts +210 -0
- package/src/tools/performance.ts +38 -0
- package/src/tools/version-compare.test.ts +97 -0
- package/src/tools/version-compare.ts +28 -0
- package/src/toolsets.test.ts +107 -0
- package/src/toolsets.ts +56 -0
- package/src/view-title.test.ts +123 -0
- package/src/widget-tools/comparisons.test.ts +170 -0
- package/src/widget-tools/comparisons.ts +229 -0
- package/src/widget-tools/shared.ts +67 -0
- package/src/widget-tools.test.ts +306 -0
- package/src/widget-tools.ts +375 -0
- package/src/widgets/analytics-dashboard/activity-bottleneck-table.tsx +179 -0
- package/src/widgets/analytics-dashboard/definition-breakdown.tsx +108 -0
- package/src/widgets/analytics-dashboard/execution-performance-kpi.tsx +94 -0
- package/src/widgets/analytics-dashboard/execution-summary-kpi.tsx +122 -0
- package/src/widgets/analytics-dashboard/lib.ts +43 -0
- package/src/widgets/bpmn-heatmap.test.tsx +75 -0
- package/src/widgets/bpmn-heatmap.tsx +127 -0
- package/src/widgets/catalogue-sync.test.ts +16 -0
- package/src/widgets/cluster-compare.tsx +148 -0
- package/src/widgets/comparison-shared.test.ts +237 -0
- package/src/widgets/comparison-shared.tsx +371 -0
- package/src/widgets/comparison-widgets.test.tsx +307 -0
- package/src/widgets/dashboard-widgets.test.tsx +397 -0
- package/src/widgets/engine-compare.tsx +87 -0
- package/src/widgets/engine-landscape.tsx +352 -0
- package/src/widgets/failure-dashboard/error-patterns-table.tsx +122 -0
- package/src/widgets/failure-dashboard/failure-rate-table.test.ts +80 -0
- package/src/widgets/failure-dashboard/failure-rate-table.tsx +170 -0
- package/src/widgets/failure-dashboard/lib.ts +32 -0
- package/src/widgets/failure-dashboard/summary-kpi.tsx +122 -0
- package/src/widgets/failure-landscape-widgets.test.tsx +393 -0
- package/src/widgets/figure.tsx +79 -0
- package/src/widgets/hand-off.test.ts +126 -0
- package/src/widgets/hand-off.ts +102 -0
- package/src/widgets/index.ts +124 -0
- package/src/widgets/model-descriptions.dashboard.test.ts +280 -0
- package/src/widgets/model-descriptions.test.ts +251 -0
- package/src/widgets/model-descriptions.ts +428 -0
- package/src/widgets/names.test.ts +32 -0
- package/src/widgets/names.ts +39 -0
- package/src/widgets/query-gate.test.tsx +57 -0
- package/src/widgets/query-gate.tsx +50 -0
- package/src/widgets/settings-section.test.tsx +174 -0
- package/src/widgets/settings-section.tsx +244 -0
- package/src/widgets/version-compare.test.ts +68 -0
- package/src/widgets/version-compare.tsx +96 -0
- package/src/widgets/view-meta.ts +18 -0
- package/src/widgets/widget-render.test-support.tsx +103 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PrometheusClient } from "@miragon/pulse-analytics-client";
|
|
2
|
+
import type { createToolRegistrar } from "@miragon/mcp-toolkit-core/tools";
|
|
3
|
+
import type { ProfileSource } from "../server-locale.js";
|
|
4
|
+
import { type AnalyticsEngineScope } from "../engine-ids.js";
|
|
5
|
+
type Register = ReturnType<typeof createToolRegistrar<PrometheusClient>>;
|
|
6
|
+
export declare function registerPerformanceTools(register: Register, engineScope: AnalyticsEngineScope, profileStore?: ProfileSource): void;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=performance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"performance.d.ts","sourceRoot":"","sources":["../../src/tools/performance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AAEvE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAA;AAC1E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAExD,OAAO,EAAmB,KAAK,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAE7E,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,gBAAgB,CAAC,CAAC,CAAA;AAExE,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,oBAAoB,EACjC,YAAY,CAAC,EAAE,aAAa,QAyB7B"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { schemas, queries } from "@miragon/pulse-analytics-client";
|
|
2
|
+
import { optionalPeriod, settingsFor } from "../settings.js";
|
|
3
|
+
import { withEngineScope } from "../engine-ids.js";
|
|
4
|
+
export function registerPerformanceTools(register, engineScope, profileStore) {
|
|
5
|
+
register({
|
|
6
|
+
name: "analytics_analyze_process_performance",
|
|
7
|
+
category: "analytics",
|
|
8
|
+
description: "Analyze process performance from metrics over a rolling window: starts, completions, incidents created (incidents, not failed instances) per 100 starts, P50/P95 duration of the instances that ENDED in the window (null when none did), and a per-activity breakdown.",
|
|
9
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
10
|
+
inputSchema: { ...schemas.analyzePerformanceInput.shape, period: optionalPeriod },
|
|
11
|
+
handler: async (ch, args, ctx) => queries.analyzePerformance(ch, {
|
|
12
|
+
...withEngineScope(engineScope, args),
|
|
13
|
+
period: args.period ?? (await settingsFor(profileStore, ctx)).defaultPeriod,
|
|
14
|
+
}),
|
|
15
|
+
});
|
|
16
|
+
register({
|
|
17
|
+
name: "analytics_compare_execution_periods",
|
|
18
|
+
category: "analytics",
|
|
19
|
+
description: "Compare process execution metrics between two explicit time windows (before/after a change, regression analysis), using PromQL historical windows. Windows are clamped to now and the 30-day retention and reported as measured (`partial` when cut short); a reversed or wholly out-of-range window is refused. Compare windows of different length by started_per_day.",
|
|
20
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
21
|
+
inputSchema: schemas.comparePeriodsInput.shape,
|
|
22
|
+
handler: async (ch, args) => queries.comparePeriods(ch, withEngineScope(engineScope, args)),
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=performance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"performance.js","sourceRoot":"","sources":["../../src/tools/performance.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAA;AAGlE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5D,OAAO,EAAE,eAAe,EAA6B,MAAM,kBAAkB,CAAA;AAI7E,MAAM,UAAU,wBAAwB,CACtC,QAAkB,EAClB,WAAiC,EACjC,YAA4B;IAE5B,QAAQ,CAAC;QACP,IAAI,EAAE,uCAAuC;QAC7C,QAAQ,EAAE,WAAW;QACrB,WAAW,EACT,yQAAyQ;QAC3Q,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;QAC9E,WAAW,EAAE,EAAE,GAAG,OAAO,CAAC,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE;QACjF,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,CAC/B,OAAO,CAAC,kBAAkB,CAAC,EAAE,EAAE;YAC7B,GAAG,eAAe,CAAC,WAAW,EAAE,IAAI,CAAC;YACrC,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,WAAW,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC,aAAa;SAC5E,CAAC;KACL,CAAC,CAAA;IAEF,QAAQ,CAAC;QACP,IAAI,EAAE,qCAAqC;QAC3C,QAAQ,EAAE,WAAW;QACrB,WAAW,EACT,0WAA0W;QAC5W,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;QAC9E,WAAW,EAAE,OAAO,CAAC,mBAAmB,CAAC,KAAK;QAC9C,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,EAAE,eAAe,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;KAC5F,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"performance.test.d.ts","sourceRoot":"","sources":["../../src/tools/performance.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { increaseIn } from "@miragon/pulse-analytics-client";
|
|
3
|
+
import { createEngineScope } from "../engine-ids.js";
|
|
4
|
+
import { registerPerformanceTools } from "./performance.js";
|
|
5
|
+
const scope = createEngineScope(["prod-a", "prod-b"]);
|
|
6
|
+
const register = (r) => registerPerformanceTools(r, scope);
|
|
7
|
+
/** Registrar stand-in that captures each tool's handler instead of an MCPServer. */
|
|
8
|
+
function captureHandlers(registerModule) {
|
|
9
|
+
const handlers = new Map();
|
|
10
|
+
const register = Object.assign((config) => {
|
|
11
|
+
handlers.set(config.name, config.handler);
|
|
12
|
+
}, { getRegisteredTools: () => [] });
|
|
13
|
+
registerModule(register);
|
|
14
|
+
return handlers;
|
|
15
|
+
}
|
|
16
|
+
/** PrometheusClient that records every instant PromQL string and returns no samples. */
|
|
17
|
+
function recordingClient() {
|
|
18
|
+
const queries = [];
|
|
19
|
+
return {
|
|
20
|
+
client: {
|
|
21
|
+
instant: (query) => {
|
|
22
|
+
queries.push(query);
|
|
23
|
+
return Promise.resolve([]);
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
queries,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
describe("analytics_analyze_process_performance PromQL", () => {
|
|
30
|
+
it("emits the exact KPI + activity-breakdown queries, scoped to key and engine", async () => {
|
|
31
|
+
const handlers = captureHandlers(register);
|
|
32
|
+
const { client, queries } = recordingClient();
|
|
33
|
+
await handlers.get("analytics_analyze_process_performance")(client, {
|
|
34
|
+
processDefinitionKey: "order",
|
|
35
|
+
period: "7d",
|
|
36
|
+
includeActivityBreakdown: true,
|
|
37
|
+
engine: "prod-a",
|
|
38
|
+
});
|
|
39
|
+
const sel = '{process_definition_key="order",engine_id="prod-a"}';
|
|
40
|
+
const completedSel = '{process_definition_key="order",engine_id="prod-a",state="COMPLETED"}';
|
|
41
|
+
const count = (series) => increaseIn(series, { range: "7d" });
|
|
42
|
+
const instance = "camunda_process_instance_duration_milliseconds";
|
|
43
|
+
const activity = "camunda_activity_duration_milliseconds";
|
|
44
|
+
expect(queries).toEqual([
|
|
45
|
+
`sum(${count(`camunda_process_instance_started_total${sel}`)})`,
|
|
46
|
+
`sum(${count(`camunda_process_instance_ended_total${completedSel}`)})`,
|
|
47
|
+
`sum(${count(`camunda_incident_created_total${sel}`)})`,
|
|
48
|
+
`sum(${count(`${instance}_sum${sel}`)}) / sum(${count(`${instance}_count${sel}`)})`,
|
|
49
|
+
`histogram_quantile(0.5, sum by (le)(${count(`${instance}_bucket${sel}`)}))`,
|
|
50
|
+
`histogram_quantile(0.95, sum by (le)(${count(`${instance}_bucket${sel}`)}))`,
|
|
51
|
+
`sum by (activity_id, activity_type)(${count(`camunda_activity_ended_total${sel}`)})`,
|
|
52
|
+
`sum by (activity_id)(${count(`${activity}_sum${sel}`)})`,
|
|
53
|
+
`histogram_quantile(0.5, sum by (activity_id, le)(${count(`${activity}_bucket${sel}`)}))`,
|
|
54
|
+
`histogram_quantile(0.95, sum by (activity_id, le)(${count(`${activity}_bucket${sel}`)}))`,
|
|
55
|
+
]);
|
|
56
|
+
});
|
|
57
|
+
it("skips the activity-breakdown queries; engine omitted reads the configured fleet", async () => {
|
|
58
|
+
const handlers = captureHandlers(register);
|
|
59
|
+
const { client, queries } = recordingClient();
|
|
60
|
+
await handlers.get("analytics_analyze_process_performance")(client, {
|
|
61
|
+
processDefinitionKey: "order",
|
|
62
|
+
period: "30d",
|
|
63
|
+
includeActivityBreakdown: false,
|
|
64
|
+
});
|
|
65
|
+
expect(queries).toHaveLength(6);
|
|
66
|
+
expect(queries.every((q) => q.includes('process_definition_key="order"'))).toBe(true);
|
|
67
|
+
expect(queries.every((q) => q.includes("[30d]"))).toBe(true);
|
|
68
|
+
// Never every engine a shared Prometheus holds (N138).
|
|
69
|
+
expect(queries.every((q) => q.includes('engine_id=~"prod-a|prod-b"'))).toBe(true);
|
|
70
|
+
expect(queries.some((q) => q.includes("camunda_activity_"))).toBe(false);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
describe("analytics_compare_execution_periods PromQL", () => {
|
|
74
|
+
// Explicit windows are clamped to [now − retention, now] — pin now.
|
|
75
|
+
beforeAll(() => {
|
|
76
|
+
vi.useFakeTimers({ toFake: ["Date"], now: Date.parse("2026-02-10T00:00:00Z") });
|
|
77
|
+
});
|
|
78
|
+
afterAll(() => {
|
|
79
|
+
vi.useRealTimers();
|
|
80
|
+
});
|
|
81
|
+
it("queries each period via `[duration] @ end` historical windows", async () => {
|
|
82
|
+
const handlers = captureHandlers(register);
|
|
83
|
+
const { client, queries } = recordingClient();
|
|
84
|
+
await handlers.get("analytics_compare_execution_periods")(client, {
|
|
85
|
+
processDefinitionKey: "order",
|
|
86
|
+
periodAFrom: "2026-01-20T00:00:00Z",
|
|
87
|
+
periodATo: "2026-01-21T00:00:00Z",
|
|
88
|
+
periodBFrom: "2026-02-01T00:00:00Z",
|
|
89
|
+
periodBTo: "2026-02-03T00:00:00Z",
|
|
90
|
+
includeActivityBreakdown: false,
|
|
91
|
+
});
|
|
92
|
+
const atA = Date.parse("2026-01-21T00:00:00Z") / 1000;
|
|
93
|
+
const atB = Date.parse("2026-02-03T00:00:00Z") / 1000;
|
|
94
|
+
const windowA = `[86400s] @ ${atA}`;
|
|
95
|
+
const windowB = `[172800s] @ ${atB}`;
|
|
96
|
+
const fleet = 'engine_id=~"prod-a|prod-b"';
|
|
97
|
+
// 6 KPI queries per period, period A first.
|
|
98
|
+
expect(queries).toHaveLength(12);
|
|
99
|
+
expect(queries.slice(0, 6).every((q) => q.includes(windowA))).toBe(true);
|
|
100
|
+
expect(queries.slice(6).every((q) => q.includes(windowB))).toBe(true);
|
|
101
|
+
const started = `camunda_process_instance_started_total{process_definition_key="order",${fleet}}`;
|
|
102
|
+
expect(queries[0]).toBe(`sum(${increaseIn(started, { range: "86400s", at: atA })})`);
|
|
103
|
+
expect(queries[6]).toBe(`sum(${increaseIn(started, { range: "172800s", at: atB })})`);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
describe("analytics_compare_execution_periods windows (N79)", () => {
|
|
107
|
+
beforeAll(() => {
|
|
108
|
+
vi.useFakeTimers({ toFake: ["Date"], now: Date.parse("2026-02-10T00:00:00Z") });
|
|
109
|
+
});
|
|
110
|
+
afterAll(() => {
|
|
111
|
+
vi.useRealTimers();
|
|
112
|
+
});
|
|
113
|
+
const base = { processDefinitionKey: "order", includeActivityBreakdown: false };
|
|
114
|
+
it("clamps a window reaching past now to now and reports what was measured", async () => {
|
|
115
|
+
const handlers = captureHandlers(register);
|
|
116
|
+
const { client, queries } = recordingClient();
|
|
117
|
+
const result = (await handlers.get("analytics_compare_execution_periods")(client, {
|
|
118
|
+
...base,
|
|
119
|
+
periodAFrom: "2026-02-01T00:00:00Z",
|
|
120
|
+
periodATo: "2026-02-05T00:00:00Z",
|
|
121
|
+
periodBFrom: "2026-02-05T00:00:00Z",
|
|
122
|
+
periodBTo: "2026-02-15T00:00:00Z",
|
|
123
|
+
}));
|
|
124
|
+
const now = Date.parse("2026-02-10T00:00:00Z") / 1000;
|
|
125
|
+
// No `@` anchor in the future: Prometheus would answer with the elapsed
|
|
126
|
+
// part while the window is reported at full length.
|
|
127
|
+
expect(queries.slice(6).every((q) => q.includes(`[432000s] @ ${now}`))).toBe(true);
|
|
128
|
+
expect(result.kpiComparison[1]).toMatchObject({
|
|
129
|
+
window_to: "2026-02-10T00:00:00.000Z",
|
|
130
|
+
window_days: 5,
|
|
131
|
+
partial: true,
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
it("refuses a reversed window instead of measuring a 1-second one", async () => {
|
|
135
|
+
const handlers = captureHandlers(register);
|
|
136
|
+
const { client, queries } = recordingClient();
|
|
137
|
+
await expect(handlers.get("analytics_compare_execution_periods")(client, {
|
|
138
|
+
...base,
|
|
139
|
+
periodAFrom: "2026-02-05T00:00:00Z",
|
|
140
|
+
periodATo: "2026-02-01T00:00:00Z",
|
|
141
|
+
periodBFrom: "2026-02-05T00:00:00Z",
|
|
142
|
+
periodBTo: "2026-02-08T00:00:00Z",
|
|
143
|
+
})).rejects.toThrow(/periodA: the window ends before it starts/);
|
|
144
|
+
expect(queries).toEqual([]);
|
|
145
|
+
});
|
|
146
|
+
it("refuses a window entirely before the retention", async () => {
|
|
147
|
+
const handlers = captureHandlers(register);
|
|
148
|
+
const { client } = recordingClient();
|
|
149
|
+
await expect(handlers.get("analytics_compare_execution_periods")(client, {
|
|
150
|
+
...base,
|
|
151
|
+
periodAFrom: "2025-10-01T00:00:00Z",
|
|
152
|
+
periodATo: "2025-10-08T00:00:00Z",
|
|
153
|
+
periodBFrom: "2026-02-01T00:00:00Z",
|
|
154
|
+
periodBTo: "2026-02-08T00:00:00Z",
|
|
155
|
+
})).rejects.toThrow(/periodA: the window lies before the 30-day Prometheus retention/);
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
describe("analytics_analyze_process_performance saved defaults", () => {
|
|
159
|
+
it("resolves the CALLER's saved period from the handler ctx the registrar hands it", async () => {
|
|
160
|
+
const store = {
|
|
161
|
+
get: (key) => Promise.resolve(key === "user-1" ? { modules: { analytics: { defaultPeriod: "30d" } } } : undefined),
|
|
162
|
+
};
|
|
163
|
+
const handlers = captureHandlers((r) => registerPerformanceTools(r, scope, store));
|
|
164
|
+
const handler = handlers.get("analytics_analyze_process_performance");
|
|
165
|
+
const firstQueryFor = async (ctx) => {
|
|
166
|
+
const { client, queries } = recordingClient();
|
|
167
|
+
await handler(client, { processDefinitionKey: "order" }, ctx);
|
|
168
|
+
return queries[0];
|
|
169
|
+
};
|
|
170
|
+
expect(await firstQueryFor({ auth: { user: { id: "user-1" } } })).toContain("[30d]");
|
|
171
|
+
// Another caller, and a request without any identity, get the schema default.
|
|
172
|
+
expect(await firstQueryFor({ auth: { user: { id: "user-2" } } })).toContain("[7d]");
|
|
173
|
+
expect(await firstQueryFor()).toContain("[7d]");
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
//# sourceMappingURL=performance.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"performance.test.js","sourceRoot":"","sources":["../../src/tools/performance.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PrometheusClient } from "@miragon/pulse-analytics-client";
|
|
2
|
+
import type { createToolRegistrar } from "@miragon/mcp-toolkit-core/tools";
|
|
3
|
+
import type { ProfileSource } from "../server-locale.js";
|
|
4
|
+
import { type AnalyticsEngineScope } from "../engine-ids.js";
|
|
5
|
+
type Register = ReturnType<typeof createToolRegistrar<PrometheusClient>>;
|
|
6
|
+
export declare function registerVersionCompareTools(register: Register, engineScope: AnalyticsEngineScope, profileStore?: ProfileSource): void;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=version-compare.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version-compare.d.ts","sourceRoot":"","sources":["../../src/tools/version-compare.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AAEvE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAA;AAC1E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAExD,OAAO,EAAmB,KAAK,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAE7E,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,gBAAgB,CAAC,CAAC,CAAA;AAExE,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,oBAAoB,EACjC,YAAY,CAAC,EAAE,aAAa,QAe7B"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { schemas, queries } from "@miragon/pulse-analytics-client";
|
|
2
|
+
import { optionalMinBucketSize, settingsFor } from "../settings.js";
|
|
3
|
+
import { withEngineScope } from "../engine-ids.js";
|
|
4
|
+
export function registerVersionCompareTools(register, engineScope, profileStore) {
|
|
5
|
+
register({
|
|
6
|
+
name: "analytics_version_compare",
|
|
7
|
+
category: "analytics",
|
|
8
|
+
description: "Compare KPIs between two deployed process definition versions of the same processDefinitionKey over a shared rolling window, from metrics. The version is an exact label on the process-instance and incident series, so instance counts, completed counts, incidents, the incident rate and durations (avg, p95) per version plus their deltas are precise. Process-wide: the element_incident_* fields stay null. Flagged `suppressed` when either version has fewer than minBucketSize started or completed instances. Pair with camunda7_list_process_definitions to discover versions.",
|
|
9
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
10
|
+
inputSchema: { ...schemas.versionCompareInput.shape, minBucketSize: optionalMinBucketSize },
|
|
11
|
+
handler: async (ch, args, ctx) => queries.versionCompare(ch, {
|
|
12
|
+
...withEngineScope(engineScope, args),
|
|
13
|
+
minBucketSize: args.minBucketSize ?? (await settingsFor(profileStore, ctx)).minBucketSize,
|
|
14
|
+
}),
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=version-compare.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version-compare.js","sourceRoot":"","sources":["../../src/tools/version-compare.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAA;AAGlE,OAAO,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACnE,OAAO,EAAE,eAAe,EAA6B,MAAM,kBAAkB,CAAA;AAI7E,MAAM,UAAU,2BAA2B,CACzC,QAAkB,EAClB,WAAiC,EACjC,YAA4B;IAE5B,QAAQ,CAAC;QACP,IAAI,EAAE,2BAA2B;QACjC,QAAQ,EAAE,WAAW;QACrB,WAAW,EACT,6jBAA6jB;QAC/jB,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;QAC9E,WAAW,EAAE,EAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE;QAC3F,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,CAC/B,OAAO,CAAC,cAAc,CAAC,EAAE,EAAE;YACzB,GAAG,eAAe,CAAC,WAAW,EAAE,IAAI,CAAC;YACrC,aAAa,EAAE,IAAI,CAAC,aAAa,IAAI,CAAC,MAAM,WAAW,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC,aAAa;SAC1F,CAAC;KACL,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version-compare.test.d.ts","sourceRoot":"","sources":["../../src/tools/version-compare.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it } from "vitest";
|
|
2
|
+
import { createEngineScope } from "../engine-ids.js";
|
|
3
|
+
import { registerVersionCompareTools } from "./version-compare.js";
|
|
4
|
+
/** Registrar stand-in that captures the tool's full config instead of an MCPServer. */
|
|
5
|
+
function captureConfig() {
|
|
6
|
+
const configs = [];
|
|
7
|
+
const register = Object.assign((config) => configs.push(config), {
|
|
8
|
+
getRegisteredTools: () => [],
|
|
9
|
+
});
|
|
10
|
+
registerVersionCompareTools(register, createEngineScope(["prod-a"]));
|
|
11
|
+
expect(configs.map((c) => c.name)).toEqual(["analytics_version_compare"]);
|
|
12
|
+
return configs[0];
|
|
13
|
+
}
|
|
14
|
+
/** PrometheusClient that records every instant PromQL string and answers 20 per query. */
|
|
15
|
+
function recordingClient() {
|
|
16
|
+
const queries = [];
|
|
17
|
+
return {
|
|
18
|
+
client: {
|
|
19
|
+
instant: (query) => {
|
|
20
|
+
queries.push(query);
|
|
21
|
+
return Promise.resolve([{ metric: {}, value: 20 }]);
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
queries,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
const args = { processDefinitionKey: "order", versionA: 1, versionB: 2, windowDays: 14 };
|
|
28
|
+
describe("analytics_version_compare", () => {
|
|
29
|
+
// Captured per test (not at collection time), so a registration that
|
|
30
|
+
// registers nothing fails a test instead of the file's collection.
|
|
31
|
+
let config;
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
config = captureConfig();
|
|
34
|
+
});
|
|
35
|
+
it("reads incidents per version, on the version label (#337)", async () => {
|
|
36
|
+
const { client, queries } = recordingClient();
|
|
37
|
+
const res = (await config.handler(client, { ...args }));
|
|
38
|
+
const incidentQueries = queries.filter((q) => q.includes("camunda_incident_created_total"));
|
|
39
|
+
expect(incidentQueries).toHaveLength(2);
|
|
40
|
+
expect(incidentQueries.map((q) => /process_definition_version="(\d+)"/.exec(q)?.[1])).toEqual([
|
|
41
|
+
"1",
|
|
42
|
+
"2",
|
|
43
|
+
]);
|
|
44
|
+
for (const kpi of res.kpis) {
|
|
45
|
+
expect(kpi).toMatchObject({
|
|
46
|
+
instance_count: 20,
|
|
47
|
+
incident_count: 20,
|
|
48
|
+
incident_rate_pct: 100,
|
|
49
|
+
element_incident_count: null,
|
|
50
|
+
element_incident_rate_pct: null,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
expect(res.delta.incident_rate_delta_pp).toBe(0);
|
|
54
|
+
});
|
|
55
|
+
it("tells the model the incident figures are per version and the comparison process-wide", () => {
|
|
56
|
+
expect(config.description).toContain("process-instance and incident series");
|
|
57
|
+
expect(config.description).toContain("element_incident_* fields stay null");
|
|
58
|
+
});
|
|
59
|
+
it("accepts the version-compare input plus the optional minBucketSize override", () => {
|
|
60
|
+
expect(Object.keys(config.inputSchema ?? {})).toEqual(expect.arrayContaining(["processDefinitionKey", "versionA", "versionB", "minBucketSize"]));
|
|
61
|
+
});
|
|
62
|
+
it("registers as a read-only external read under the analytics category", () => {
|
|
63
|
+
expect(config.category).toBe("analytics");
|
|
64
|
+
expect(config.annotations).toEqual({
|
|
65
|
+
readOnlyHint: true,
|
|
66
|
+
idempotentHint: true,
|
|
67
|
+
openWorldHint: true,
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
it("prefers an explicit minBucketSize over the resolved setting", async () => {
|
|
71
|
+
const { client } = recordingClient();
|
|
72
|
+
const explicit = (await config.handler(client, {
|
|
73
|
+
...args,
|
|
74
|
+
minBucketSize: 3,
|
|
75
|
+
}));
|
|
76
|
+
const fallback = (await config.handler(client, { ...args }));
|
|
77
|
+
expect(explicit.minBucketSize).toBe(3);
|
|
78
|
+
// Without a store the registrar path lands on the schema default.
|
|
79
|
+
expect(fallback.minBucketSize).toBe(10);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
//# sourceMappingURL=version-compare.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version-compare.test.js","sourceRoot":"","sources":["../../src/tools/version-compare.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const ANALYTICS_TOOLSETS: readonly ["read-only", "standard"];
|
|
2
|
+
export type AnalyticsToolset = (typeof ANALYTICS_TOOLSETS)[number];
|
|
3
|
+
/** The vocabulary the module declares to the composition root (`analyticsModule.toolsets`). */
|
|
4
|
+
export declare const analyticsToolsets: import("@miragon/pulse-widget-shell/server").ToolsetVocabulary<"read-only" | "standard">;
|
|
5
|
+
export declare function isAnalyticsToolset(value: string): value is AnalyticsToolset;
|
|
6
|
+
/**
|
|
7
|
+
* Whether the toolset permits the module's durable writes
|
|
8
|
+
* (`analytics_save_settings`). Registered outside the tool registrar, that save
|
|
9
|
+
* has to gate itself — no registrar filter ever sees it.
|
|
10
|
+
*
|
|
11
|
+
* Decided by the vocabulary, never by an ad-hoc `toolset === "read-only"`
|
|
12
|
+
* compare (which fails open for every other name): a missing toolset resolves
|
|
13
|
+
* to the read-only floor, an unknown one warns and degrades to it, and only a
|
|
14
|
+
* toolset above the floor (`standard`) writes.
|
|
15
|
+
*/
|
|
16
|
+
export declare function allowsDurableWrites(toolset?: string): boolean;
|
|
17
|
+
//# sourceMappingURL=toolsets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolsets.d.ts","sourceRoot":"","sources":["../src/toolsets.ts"],"names":[],"mappings":"AA0BA,eAAO,MAAM,kBAAkB,oCAAqC,CAAA;AACpE,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAA;AAElE,+FAA+F;AAC/F,eAAO,MAAM,iBAAiB,0FAO7B,CAAA;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,gBAAgB,CAE3E;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAE7D"}
|
package/dist/toolsets.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The analytics module's toolset vocabulary. Module peers own their toolset
|
|
3
|
+
* NAMES; the fail-closed SEMANTICS are shared (`createToolsetVocabulary` from
|
|
4
|
+
* `@miragon/pulse-widget-shell/server`):
|
|
5
|
+
*
|
|
6
|
+
* - `read-only` — the floor: every analytics read, no durable write (the
|
|
7
|
+
* settings save tool is not registered);
|
|
8
|
+
* - `standard` — the full analytics surface, including the caller's own
|
|
9
|
+
* settings save. Analytics has no admin tier: it reads Prometheus and never
|
|
10
|
+
* writes to an engine, so there is nothing wider to name.
|
|
11
|
+
*
|
|
12
|
+
* Which one a boot runs with (`MCP_ACTIVE_MODULES=analytics:<toolset>`):
|
|
13
|
+
*
|
|
14
|
+
* - no suffix → `read-only` on an unauthenticated boot, `standard` when the
|
|
15
|
+
* root installed OAuth;
|
|
16
|
+
* - an empty or unknown suffix → warns and degrades to `read-only` — a suffix
|
|
17
|
+
* always meant to restrict, so a typo never grants the write it tried to
|
|
18
|
+
* take away;
|
|
19
|
+
* - nothing ever resolves to "everything".
|
|
20
|
+
*
|
|
21
|
+
* The composition root resolves the suffix once per boot and hands the module
|
|
22
|
+
* a concrete name; a direct `createPlugin` caller that passes none gets the
|
|
23
|
+
* floor.
|
|
24
|
+
*/
|
|
25
|
+
import { createToolsetVocabulary } from "@miragon/pulse-widget-shell/server";
|
|
26
|
+
export const ANALYTICS_TOOLSETS = ["read-only", "standard"];
|
|
27
|
+
/** The vocabulary the module declares to the composition root (`analyticsModule.toolsets`). */
|
|
28
|
+
export const analyticsToolsets = createToolsetVocabulary("analytics", ANALYTICS_TOOLSETS, "read-only", {
|
|
29
|
+
authenticatedDefault: "standard",
|
|
30
|
+
});
|
|
31
|
+
export function isAnalyticsToolset(value) {
|
|
32
|
+
return analyticsToolsets.isKnown(value);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Whether the toolset permits the module's durable writes
|
|
36
|
+
* (`analytics_save_settings`). Registered outside the tool registrar, that save
|
|
37
|
+
* has to gate itself — no registrar filter ever sees it.
|
|
38
|
+
*
|
|
39
|
+
* Decided by the vocabulary, never by an ad-hoc `toolset === "read-only"`
|
|
40
|
+
* compare (which fails open for every other name): a missing toolset resolves
|
|
41
|
+
* to the read-only floor, an unknown one warns and degrades to it, and only a
|
|
42
|
+
* toolset above the floor (`standard`) writes.
|
|
43
|
+
*/
|
|
44
|
+
export function allowsDurableWrites(toolset) {
|
|
45
|
+
return analyticsToolsets.allowsDurableWrites(analyticsToolsets.resolve(toolset));
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=toolsets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolsets.js","sourceRoot":"","sources":["../src/toolsets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAA;AAE5E,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,WAAW,EAAE,UAAU,CAAU,CAAA;AAGpE,+FAA+F;AAC/F,MAAM,CAAC,MAAM,iBAAiB,GAAG,uBAAuB,CACtD,WAAW,EACX,kBAAkB,EAClB,WAAW,EACX;IACE,oBAAoB,EAAE,UAAU;CACjC,CACF,CAAA;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC9C,OAAO,iBAAiB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;AACzC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,OAAO,iBAAiB,CAAC,mBAAmB,CAAC,iBAAiB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;AAClF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolsets.test.d.ts","sourceRoot":"","sources":["../src/toolsets.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { allowsDurableWrites, ANALYTICS_TOOLSETS, analyticsToolsets, isAnalyticsToolset, } from "./toolsets.js";
|
|
3
|
+
afterEach(() => {
|
|
4
|
+
vi.restoreAllMocks();
|
|
5
|
+
});
|
|
6
|
+
describe("analyticsToolsets (the vocabulary the module declares)", () => {
|
|
7
|
+
it("declares exactly read-only and standard — analytics has no admin tier", () => {
|
|
8
|
+
expect(ANALYTICS_TOOLSETS).toEqual(["read-only", "standard"]);
|
|
9
|
+
expect(analyticsToolsets.module).toBe("analytics");
|
|
10
|
+
expect(analyticsToolsets.names).toEqual(["read-only", "standard"]);
|
|
11
|
+
});
|
|
12
|
+
it("floors at read-only and defaults to standard under OAuth", () => {
|
|
13
|
+
expect(analyticsToolsets.fallback).toBe("read-only");
|
|
14
|
+
expect(analyticsToolsets.authenticatedDefault).toBe("standard");
|
|
15
|
+
});
|
|
16
|
+
it("no suffix: read-only without OAuth, standard with it — never 'everything'", () => {
|
|
17
|
+
expect(analyticsToolsets.effective(undefined, { authenticated: false })).toEqual({
|
|
18
|
+
toolset: "read-only",
|
|
19
|
+
source: "default",
|
|
20
|
+
});
|
|
21
|
+
expect(analyticsToolsets.effective(undefined, { authenticated: true })).toEqual({
|
|
22
|
+
toolset: "standard",
|
|
23
|
+
source: "default",
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
it("a named suffix wins over the auth-dependent default, in both directions", () => {
|
|
27
|
+
expect(analyticsToolsets.effective("standard", { authenticated: false })).toEqual({
|
|
28
|
+
toolset: "standard",
|
|
29
|
+
source: "suffix",
|
|
30
|
+
});
|
|
31
|
+
expect(analyticsToolsets.effective("read-only", { authenticated: true })).toEqual({
|
|
32
|
+
toolset: "read-only",
|
|
33
|
+
source: "suffix",
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
it("an empty or unknown suffix (incl. camunda7's 'admin') falls back to the floor, with a warning", () => {
|
|
37
|
+
const warn = vi.spyOn(console, "warn").mockImplementation(() => { });
|
|
38
|
+
for (const suffix of ["", "admin"]) {
|
|
39
|
+
expect(analyticsToolsets.effective(suffix, { authenticated: true })).toEqual({
|
|
40
|
+
toolset: "read-only",
|
|
41
|
+
source: "fallback",
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
expect(warn).toHaveBeenCalledTimes(2);
|
|
45
|
+
expect(warn).toHaveBeenCalledWith(expect.stringContaining("[analytics]"));
|
|
46
|
+
expect(warn).toHaveBeenCalledWith(expect.stringContaining('Unknown toolset "admin"'));
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
describe("isAnalyticsToolset", () => {
|
|
50
|
+
it("accepts every declared name and nothing else", () => {
|
|
51
|
+
for (const toolset of ANALYTICS_TOOLSETS) {
|
|
52
|
+
expect(isAnalyticsToolset(toolset)).toBe(true);
|
|
53
|
+
}
|
|
54
|
+
expect(isAnalyticsToolset("admin")).toBe(false);
|
|
55
|
+
expect(isAnalyticsToolset("")).toBe(false);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
describe("allowsDurableWrites", () => {
|
|
59
|
+
it("forbids writes when no toolset is configured — a missing toolset is the read-only floor", () => {
|
|
60
|
+
// Fail-closed: a direct `createPlugin` caller that passes no toolset gets
|
|
61
|
+
// the floor, never the full surface.
|
|
62
|
+
const warn = vi.spyOn(console, "warn").mockImplementation(() => { });
|
|
63
|
+
expect(allowsDurableWrites(undefined)).toBe(false);
|
|
64
|
+
expect(allowsDurableWrites()).toBe(false);
|
|
65
|
+
expect(warn).not.toHaveBeenCalled();
|
|
66
|
+
});
|
|
67
|
+
it("forbids writes in the module's read-only toolset", () => {
|
|
68
|
+
expect(allowsDurableWrites("read-only")).toBe(false);
|
|
69
|
+
});
|
|
70
|
+
it("permits writes in the standard toolset (the user's own settings save)", () => {
|
|
71
|
+
expect(allowsDurableWrites("standard")).toBe(true);
|
|
72
|
+
});
|
|
73
|
+
it("fails CLOSED on an unknown toolset name, with a warning", () => {
|
|
74
|
+
// A typo'd `analytics:standrad`, or camunda7's `operations`, must not
|
|
75
|
+
// grant the one write — unknown names degrade to `read-only`.
|
|
76
|
+
const warn = vi.spyOn(console, "warn").mockImplementation(() => { });
|
|
77
|
+
expect(allowsDurableWrites("operations")).toBe(false);
|
|
78
|
+
expect(warn).toHaveBeenCalledOnce();
|
|
79
|
+
expect(warn).toHaveBeenCalledWith(expect.stringContaining('Unknown toolset "operations"'));
|
|
80
|
+
});
|
|
81
|
+
it("decides by declared name, not by an ad-hoc string compare", () => {
|
|
82
|
+
// The regression this guards: a `toolset === "read-only"` check silently
|
|
83
|
+
// fails open for every name that is NOT that literal. Every declared
|
|
84
|
+
// toolset is a deliberate decision: only the floor forbids the write.
|
|
85
|
+
expect(ANALYTICS_TOOLSETS.map((toolset) => [toolset, allowsDurableWrites(toolset)])).toEqual([
|
|
86
|
+
["read-only", false],
|
|
87
|
+
["standard", true],
|
|
88
|
+
]);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
//# sourceMappingURL=toolsets.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolsets.test.js","sourceRoot":"","sources":["../src/toolsets.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view-title.test.d.ts","sourceRoot":"","sources":["../src/view-title.test.ts"],"names":[],"mappings":""}
|