@artemis-studio/plugin-sdk 2026.9.43 → 2026.9.44
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/index.js +3 -0
- package/package.json +1 -1
- package/types/kernel/api/schema.d.ts +91 -0
- package/types/kernel/metrics/ChartPanel.d.ts +28 -0
- package/types/kernel/metrics/MetricChart.d.ts +13 -0
- package/types/kernel/metrics/axis.d.ts +71 -0
- package/types/kernel/metrics/pluginSeries.d.ts +17 -0
- package/types/sdk/index.d.ts +3 -0
package/index.js
CHANGED
|
@@ -9,6 +9,8 @@ export const ApiError = outsideStudio('ApiError');
|
|
|
9
9
|
export const CONTRACT = outsideStudio('CONTRACT');
|
|
10
10
|
export const CapabilityGate = outsideStudio('CapabilityGate');
|
|
11
11
|
export const ConfirmByTyping = outsideStudio('ConfirmByTyping');
|
|
12
|
+
export const METRIC_RANGES = outsideStudio('METRIC_RANGES');
|
|
13
|
+
export const MetricChart = outsideStudio('MetricChart');
|
|
12
14
|
export const NAV_GROUPS = outsideStudio('NAV_GROUPS');
|
|
13
15
|
export const NodeOutcomeSummary = outsideStudio('NodeOutcomeSummary');
|
|
14
16
|
export const OutcomeSummary = outsideStudio('OutcomeSummary');
|
|
@@ -27,3 +29,4 @@ export const request = outsideStudio('request');
|
|
|
27
29
|
export const rootRoute = outsideStudio('rootRoute');
|
|
28
30
|
export const useCan = outsideStudio('useCan');
|
|
29
31
|
export const useMe = outsideStudio('useMe');
|
|
32
|
+
export const usePluginSeries = outsideStudio('usePluginSeries');
|
package/package.json
CHANGED
|
@@ -1700,6 +1700,22 @@ export interface paths {
|
|
|
1700
1700
|
patch?: never;
|
|
1701
1701
|
trace?: never;
|
|
1702
1702
|
};
|
|
1703
|
+
"/api/v1/clusters/{clusterId}/metrics/plugin": {
|
|
1704
|
+
parameters: {
|
|
1705
|
+
query?: never;
|
|
1706
|
+
header?: never;
|
|
1707
|
+
path?: never;
|
|
1708
|
+
cookie?: never;
|
|
1709
|
+
};
|
|
1710
|
+
get: operations["plugin"];
|
|
1711
|
+
put?: never;
|
|
1712
|
+
post?: never;
|
|
1713
|
+
delete?: never;
|
|
1714
|
+
options?: never;
|
|
1715
|
+
head?: never;
|
|
1716
|
+
patch?: never;
|
|
1717
|
+
trace?: never;
|
|
1718
|
+
};
|
|
1703
1719
|
"/api/v1/clusters/{clusterId}/health": {
|
|
1704
1720
|
parameters: {
|
|
1705
1721
|
query?: never;
|
|
@@ -2068,6 +2084,22 @@ export interface paths {
|
|
|
2068
2084
|
patch?: never;
|
|
2069
2085
|
trace?: never;
|
|
2070
2086
|
};
|
|
2087
|
+
"/api/v1/clusters/{clusterId}/alerts/plugin-metrics": {
|
|
2088
|
+
parameters: {
|
|
2089
|
+
query?: never;
|
|
2090
|
+
header?: never;
|
|
2091
|
+
path?: never;
|
|
2092
|
+
cookie?: never;
|
|
2093
|
+
};
|
|
2094
|
+
get: operations["pluginMetrics"];
|
|
2095
|
+
put?: never;
|
|
2096
|
+
post?: never;
|
|
2097
|
+
delete?: never;
|
|
2098
|
+
options?: never;
|
|
2099
|
+
head?: never;
|
|
2100
|
+
patch?: never;
|
|
2101
|
+
trace?: never;
|
|
2102
|
+
};
|
|
2071
2103
|
"/api/v1/clusters/{clusterId}/alerts/history": {
|
|
2072
2104
|
parameters: {
|
|
2073
2105
|
query?: never;
|
|
@@ -2686,6 +2718,8 @@ export interface components {
|
|
|
2686
2718
|
scope?: string | null;
|
|
2687
2719
|
enabled: boolean;
|
|
2688
2720
|
channelIds: string[];
|
|
2721
|
+
/** @description False when the rule watches a plugin metric whose plugin is not running */
|
|
2722
|
+
sourceAvailable: boolean;
|
|
2689
2723
|
/** Format: date-time */
|
|
2690
2724
|
createdAt: string;
|
|
2691
2725
|
/** Format: date-time */
|
|
@@ -5168,6 +5202,13 @@ export interface components {
|
|
|
5168
5202
|
/** Format: int32 */
|
|
5169
5203
|
pageSize: number;
|
|
5170
5204
|
};
|
|
5205
|
+
PluginMetricView: {
|
|
5206
|
+
metric: string;
|
|
5207
|
+
plugin: string;
|
|
5208
|
+
description: string;
|
|
5209
|
+
unit: string;
|
|
5210
|
+
subject: string;
|
|
5211
|
+
};
|
|
5171
5212
|
AlertFiringPageView: {
|
|
5172
5213
|
items: components["schemas"]["AlertFiringView"][];
|
|
5173
5214
|
/** Format: int64 */
|
|
@@ -8542,6 +8583,34 @@ export interface operations {
|
|
|
8542
8583
|
};
|
|
8543
8584
|
};
|
|
8544
8585
|
};
|
|
8586
|
+
plugin: {
|
|
8587
|
+
parameters: {
|
|
8588
|
+
query?: {
|
|
8589
|
+
metric?: string;
|
|
8590
|
+
subject?: string;
|
|
8591
|
+
from?: string;
|
|
8592
|
+
to?: string;
|
|
8593
|
+
step?: string;
|
|
8594
|
+
};
|
|
8595
|
+
header?: never;
|
|
8596
|
+
path: {
|
|
8597
|
+
clusterId: string;
|
|
8598
|
+
};
|
|
8599
|
+
cookie?: never;
|
|
8600
|
+
};
|
|
8601
|
+
requestBody?: never;
|
|
8602
|
+
responses: {
|
|
8603
|
+
/** @description OK */
|
|
8604
|
+
200: {
|
|
8605
|
+
headers: {
|
|
8606
|
+
[name: string]: unknown;
|
|
8607
|
+
};
|
|
8608
|
+
content: {
|
|
8609
|
+
"*/*": components["schemas"]["MetricSeriesResponse"];
|
|
8610
|
+
};
|
|
8611
|
+
};
|
|
8612
|
+
};
|
|
8613
|
+
};
|
|
8545
8614
|
health: {
|
|
8546
8615
|
parameters: {
|
|
8547
8616
|
query?: never;
|
|
@@ -9095,6 +9164,28 @@ export interface operations {
|
|
|
9095
9164
|
};
|
|
9096
9165
|
};
|
|
9097
9166
|
};
|
|
9167
|
+
pluginMetrics: {
|
|
9168
|
+
parameters: {
|
|
9169
|
+
query?: never;
|
|
9170
|
+
header?: never;
|
|
9171
|
+
path: {
|
|
9172
|
+
clusterId: string;
|
|
9173
|
+
};
|
|
9174
|
+
cookie?: never;
|
|
9175
|
+
};
|
|
9176
|
+
requestBody?: never;
|
|
9177
|
+
responses: {
|
|
9178
|
+
/** @description OK */
|
|
9179
|
+
200: {
|
|
9180
|
+
headers: {
|
|
9181
|
+
[name: string]: unknown;
|
|
9182
|
+
};
|
|
9183
|
+
content: {
|
|
9184
|
+
"*/*": components["schemas"]["PluginMetricView"][];
|
|
9185
|
+
};
|
|
9186
|
+
};
|
|
9187
|
+
};
|
|
9188
|
+
};
|
|
9098
9189
|
history_2: {
|
|
9099
9190
|
parameters: {
|
|
9100
9191
|
query?: {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ApiError } from '../api/request.ts';
|
|
2
|
+
/** Every metric plot is this tall, whatever it is currently able to show. */
|
|
3
|
+
export declare const CHART_HEIGHT = 220;
|
|
4
|
+
/**
|
|
5
|
+
* A titled panel around one metric plot, and the three states it can be in.
|
|
6
|
+
*
|
|
7
|
+
* Failure, emptiness and loading are rendered as three different things at one
|
|
8
|
+
* fixed height (ADR-0055). Both halves of that matter:
|
|
9
|
+
*
|
|
10
|
+
* - a metrics read that returned 500 used to render "No samples in this window
|
|
11
|
+
* yet", which presents an outage as a fact about the cluster — and a flat empty
|
|
12
|
+
* chart during an incident reads as "quiet", the most expensive possible
|
|
13
|
+
* misreading;
|
|
14
|
+
* - a panel that collapses while loading and expands when data arrives moves the
|
|
15
|
+
* page under a pointer already travelling towards something else.
|
|
16
|
+
*/
|
|
17
|
+
export declare function ChartPanel({ title, unit, isPending, error, isEmpty, emptyLabel, note, children, }: {
|
|
18
|
+
title: string;
|
|
19
|
+
unit: string;
|
|
20
|
+
isPending: boolean;
|
|
21
|
+
error: ApiError | null;
|
|
22
|
+
/** True when the read succeeded and carried nothing for this window. */
|
|
23
|
+
isEmpty: boolean;
|
|
24
|
+
emptyLabel: string;
|
|
25
|
+
/** A coverage caveat that belongs beside the title, not inside a tooltip. */
|
|
26
|
+
note?: React.ReactNode;
|
|
27
|
+
children: React.ReactNode;
|
|
28
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { MetricRange } from '../time/ranges.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Studio's time-proportional chart of one plugin metric for one subject (ADR-0055, ADR-0113):
|
|
4
|
+
* a titled panel that tells loading, failure and an empty window apart, over a live range.
|
|
5
|
+
*/
|
|
6
|
+
export declare function MetricChart({ clusterId, metric, subject, title, range, emptyLabel, }: {
|
|
7
|
+
clusterId: string;
|
|
8
|
+
metric: string;
|
|
9
|
+
subject: string;
|
|
10
|
+
title: string;
|
|
11
|
+
range?: MetricRange;
|
|
12
|
+
emptyLabel?: string;
|
|
13
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { components } from '../api/schema.d.ts';
|
|
2
|
+
import { type MetricRange } from '../time/ranges.ts';
|
|
3
|
+
type MetricSeries = components['schemas']['MetricSeries'];
|
|
4
|
+
/**
|
|
5
|
+
* Format an instant in the operator's chosen zone.
|
|
6
|
+
*
|
|
7
|
+
* Bare `dayjs(ms).format(...)` renders in the browser's zone, which used to leave
|
|
8
|
+
* the charts and the tables disagreeing on every deployment where the two differed
|
|
9
|
+
* — the axis in local time, every table in UTC, and nothing saying so. Everything
|
|
10
|
+
* that renders a metric timestamp goes through here.
|
|
11
|
+
*/
|
|
12
|
+
export declare function formatInZone(ms: number, pattern: string): string;
|
|
13
|
+
export declare function tickFormatter(range: MetricRange): (ms: number) => string;
|
|
14
|
+
export declare function labelFormatter(range: MetricRange): (ms: number) => string;
|
|
15
|
+
/**
|
|
16
|
+
* Props for the recharts `XAxis` behind every metric chart.
|
|
17
|
+
*
|
|
18
|
+
* `type: 'number'` with `scale: 'time'` is the whole decision. The explicit
|
|
19
|
+
* `[from, to]` domain — rather than `['dataMin', 'dataMax']` — keeps the plotted
|
|
20
|
+
* width equal to the *requested* window, so a series that stops halfway through
|
|
21
|
+
* the range renders as a chart that is half empty rather than one that silently
|
|
22
|
+
* rescales to whatever data survived.
|
|
23
|
+
*/
|
|
24
|
+
export declare function timeAxisProps(range: MetricRange, from: number, to: number): {
|
|
25
|
+
type: "number";
|
|
26
|
+
scale: "time";
|
|
27
|
+
domain: [number, number];
|
|
28
|
+
tickFormatter: (ms: number) => string;
|
|
29
|
+
minTickGap: number;
|
|
30
|
+
stroke: string;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* `integral` is for a metric that only ever takes whole values — a consumer
|
|
34
|
+
* count. Without it recharts picks fractional ticks for a small domain, and the
|
|
35
|
+
* integer formatter renders every one of them as the same "0": an axis of five
|
|
36
|
+
* identical labels beside bars of visibly different heights.
|
|
37
|
+
*/
|
|
38
|
+
export declare function yAxisProps(options?: {
|
|
39
|
+
integral?: boolean;
|
|
40
|
+
}): {
|
|
41
|
+
allowDecimals?: boolean | undefined;
|
|
42
|
+
stroke: string;
|
|
43
|
+
width: number;
|
|
44
|
+
};
|
|
45
|
+
export declare function gridProps(): {
|
|
46
|
+
stroke: string;
|
|
47
|
+
};
|
|
48
|
+
/** Bucket boundaries a series is expected to cover, used to size the empty case. */
|
|
49
|
+
export declare function bucketCount(range: MetricRange): number;
|
|
50
|
+
/**
|
|
51
|
+
* Merge any number of series onto one row per timestamp, keyed by epoch ms.
|
|
52
|
+
*
|
|
53
|
+
* Series are merged by timestamp rather than by index because a metric with no
|
|
54
|
+
* samples in a bucket is simply omitted from its series, so two series over the
|
|
55
|
+
* same window can carry different bucket sets. Zipping them by position would
|
|
56
|
+
* silently pair a value with the wrong instant.
|
|
57
|
+
*/
|
|
58
|
+
export declare function mergeByTimestamp(named: Array<{
|
|
59
|
+
name: string;
|
|
60
|
+
series: MetricSeries | undefined;
|
|
61
|
+
field?: 'value' | 'peak';
|
|
62
|
+
}>): Array<Record<string, number>>;
|
|
63
|
+
/** The last point of a series, or `null` when there is none to state. */
|
|
64
|
+
export declare function latest(series: MetricSeries | undefined): number | null;
|
|
65
|
+
/** The first point of a series, for stating movement across the window. */
|
|
66
|
+
export declare function earliest(series: MetricSeries | undefined): number | null;
|
|
67
|
+
/** Depth runs to millions on a real cluster; an axis tick cannot carry the digits. */
|
|
68
|
+
export declare function formatCount(value: number): string;
|
|
69
|
+
export declare function formatExact(value: number): string;
|
|
70
|
+
export declare function formatRate(value: number): string;
|
|
71
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type UseQueryResult } from '@tanstack/react-query';
|
|
2
|
+
import { ApiError } from '../api/request.ts';
|
|
3
|
+
import type { components } from '../api/schema.d.ts';
|
|
4
|
+
import { type MetricRange } from '../time/ranges.ts';
|
|
5
|
+
type MetricSeriesResponse = components['schemas']['MetricSeriesResponse'];
|
|
6
|
+
/**
|
|
7
|
+
* A plugin metric's series for one subject over a live range (ADR-0113). Needs the permission the
|
|
8
|
+
* plugin declared for the metric; without it the read fails like any cluster read the user may
|
|
9
|
+
* not make.
|
|
10
|
+
*/
|
|
11
|
+
export declare function usePluginSeries(clusterId: string, metric: string, subject: string, range?: MetricRange): UseQueryResult<MetricSeriesResponse, ApiError> & {
|
|
12
|
+
window: {
|
|
13
|
+
from: string;
|
|
14
|
+
to: string;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
export {};
|
package/types/sdk/index.d.ts
CHANGED
|
@@ -22,6 +22,9 @@ export { ConfirmByTyping } from '../ui/ConfirmByTyping.tsx';
|
|
|
22
22
|
export { NodeOutcomeSummary, OutcomeSummary, type OutcomeRow } from '../ui/NodeOutcomeSummary.tsx';
|
|
23
23
|
export { Pager } from '../ui/Pager.tsx';
|
|
24
24
|
export { VirtualTable, type GridColumn } from '../ui/VirtualTable.tsx';
|
|
25
|
+
export { MetricChart } from '../kernel/metrics/MetricChart.tsx';
|
|
26
|
+
export { usePluginSeries } from '../kernel/metrics/pluginSeries.ts';
|
|
27
|
+
export { METRIC_RANGES, type MetricRange } from '../kernel/time/ranges.ts';
|
|
25
28
|
/**
|
|
26
29
|
* Shows a notification in Studio's own notification area. Import this, never
|
|
27
30
|
* `@mantine/notifications` directly: that is not shared, so a plugin's own copy would show nothing.
|