@tpmjs/tools-slo-draft 0.2.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-2025 TPMJS
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,87 @@
1
+ # @tpmjs/tools-slo-draft
2
+
3
+ Draft Service Level Objective (SLO) definitions for services with comprehensive documentation, error budgets, and alerting strategies.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @tpmjs/tools-slo-draft
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import { sloDraftTool } from '@tpmjs/tools-slo-draft';
15
+
16
+ // Use with Vercel AI SDK
17
+ const result = await sloDraftTool.execute({
18
+ serviceName: 'Payment API',
19
+ metrics: [
20
+ {
21
+ name: 'Availability',
22
+ target: 99.9,
23
+ window: '30d'
24
+ },
25
+ {
26
+ name: 'API Latency P99',
27
+ target: 95.0,
28
+ window: 'rolling 7 days'
29
+ },
30
+ {
31
+ name: 'Error Rate',
32
+ target: 99.5,
33
+ window: '30d'
34
+ }
35
+ ]
36
+ });
37
+
38
+ console.log(result.slo); // Markdown formatted SLO document
39
+ console.log(result.summary); // Brief summary
40
+ console.log(result.metrics); // Processed metrics with severity
41
+ ```
42
+
43
+ ## Input
44
+
45
+ - `serviceName` (string, required): Name of the service
46
+ - `metrics` (array, required): Array of metric objects with:
47
+ - `name` (string): Metric name (e.g., "Availability", "Latency P99")
48
+ - `target` (number): Target percentage (0-100)
49
+ - `window` (string): Time window (e.g., "30d", "7 days", "rolling 30 days")
50
+
51
+ ## Output
52
+
53
+ Returns an object with:
54
+
55
+ - `slo` (string): Comprehensive SLO document in markdown format
56
+ - `metrics` (array): Processed metrics with additional metadata:
57
+ - Original name, target, window
58
+ - `windowType`: 'rolling' or 'calendar'
59
+ - `severity`: 'critical' (≥99.9%), 'high' (≥99%), or 'medium' (<99%)
60
+ - `summary` (string): Brief summary of the SLO
61
+ - `metadata` (object):
62
+ - `serviceName`: Service name
63
+ - `createdAt`: ISO timestamp
64
+ - `totalMetrics`: Total number of metrics
65
+ - `criticalMetrics`: Number of critical severity metrics
66
+
67
+ ## Features
68
+
69
+ - **Automatic Severity Classification**: Metrics are classified as critical, high, or medium based on targets
70
+ - **Error Budget Calculation**: Calculates allowed downtime for each metric
71
+ - **Alerting Strategy**: Provides burn rate-based alerting recommendations
72
+ - **Window Type Detection**: Automatically detects rolling vs calendar windows
73
+ - **Comprehensive Documentation**: Generates full SLO document with monitoring and review processes
74
+
75
+ ## Example Output
76
+
77
+ The tool generates a markdown document including:
78
+
79
+ - SLO definitions with targets and allowed downtime
80
+ - Error budget policies
81
+ - Alerting strategies based on severity
82
+ - Review processes and schedules
83
+ - Links to related documentation
84
+
85
+ ## License
86
+
87
+ MIT
@@ -0,0 +1,49 @@
1
+ import * as ai from 'ai';
2
+
3
+ /**
4
+ * SLO Draft Tool for TPMJS
5
+ * Drafts Service Level Objective (SLO) definitions for services with metrics, targets, and time windows.
6
+ */
7
+ /**
8
+ * Input metric definition
9
+ */
10
+ interface MetricInput {
11
+ name: string;
12
+ target: number;
13
+ window: string;
14
+ }
15
+ /**
16
+ * Processed metric with additional metadata
17
+ */
18
+ interface ProcessedMetric {
19
+ name: string;
20
+ target: number;
21
+ window: string;
22
+ windowType: 'rolling' | 'calendar';
23
+ severity: 'critical' | 'high' | 'medium';
24
+ }
25
+ /**
26
+ * Output interface for SLO draft
27
+ */
28
+ interface SLODraft {
29
+ slo: string;
30
+ metrics: ProcessedMetric[];
31
+ summary: string;
32
+ metadata: {
33
+ serviceName: string;
34
+ createdAt: string;
35
+ totalMetrics: number;
36
+ criticalMetrics: number;
37
+ };
38
+ }
39
+ type SLODraftInput = {
40
+ serviceName: string;
41
+ metrics: MetricInput[];
42
+ };
43
+ /**
44
+ * SLO Draft Tool
45
+ * Generates a comprehensive SLO document for a service
46
+ */
47
+ declare const sloDraftTool: ai.Tool<SLODraftInput, SLODraft>;
48
+
49
+ export { type MetricInput, type ProcessedMetric, type SLODraft, sloDraftTool as default, sloDraftTool };
package/dist/index.js ADDED
@@ -0,0 +1,264 @@
1
+ import { tool, jsonSchema } from 'ai';
2
+
3
+ // src/index.ts
4
+ function determineWindowType(window) {
5
+ const lowerWindow = window.toLowerCase();
6
+ if (lowerWindow.includes("calendar") || lowerWindow.includes("month")) {
7
+ return "calendar";
8
+ }
9
+ return "rolling";
10
+ }
11
+ function determineSeverity(target) {
12
+ if (target >= 99.9) return "critical";
13
+ if (target >= 99) return "high";
14
+ return "medium";
15
+ }
16
+ function calculateAllowedDowntime(target, window) {
17
+ const lowerWindow = window.toLowerCase();
18
+ let totalMinutes = 0;
19
+ if (lowerWindow.includes("30d") || lowerWindow.includes("30 day")) {
20
+ totalMinutes = 30 * 24 * 60;
21
+ } else if (lowerWindow.includes("7d") || lowerWindow.includes("7 day")) {
22
+ totalMinutes = 7 * 24 * 60;
23
+ } else if (lowerWindow.includes("1d") || lowerWindow.includes("1 day")) {
24
+ totalMinutes = 24 * 60;
25
+ } else if (lowerWindow.includes("month")) {
26
+ totalMinutes = 30 * 24 * 60;
27
+ } else {
28
+ totalMinutes = 30 * 24 * 60;
29
+ }
30
+ const uptimePercentage = target / 100;
31
+ const allowedDowntimeMinutes = totalMinutes * (1 - uptimePercentage);
32
+ const hours = Math.floor(allowedDowntimeMinutes / 60);
33
+ const minutes = Math.floor(allowedDowntimeMinutes % 60);
34
+ if (hours >= 24) {
35
+ const days = Math.floor(hours / 24);
36
+ const remainingHours = hours % 24;
37
+ return `${days}d ${remainingHours}h ${minutes}m`;
38
+ }
39
+ if (hours > 0) {
40
+ return `${hours}h ${minutes}m`;
41
+ }
42
+ return `${minutes}m`;
43
+ }
44
+ function generateSLOMarkdown(serviceName, metrics) {
45
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
46
+ let markdown = `# Service Level Objectives (SLO)
47
+
48
+ `;
49
+ markdown += `**Service:** ${serviceName}
50
+ `;
51
+ markdown += `**Date:** ${timestamp}
52
+ `;
53
+ markdown += `**Status:** Draft
54
+
55
+ `;
56
+ markdown += `## Overview
57
+
58
+ `;
59
+ markdown += `This document defines the Service Level Objectives (SLOs) for ${serviceName}. `;
60
+ markdown += `These objectives represent the target reliability and performance metrics that the service commits to achieving.
61
+
62
+ `;
63
+ markdown += `## SLO Definitions
64
+
65
+ `;
66
+ for (const metric of metrics) {
67
+ const downtime = calculateAllowedDowntime(metric.target, metric.window);
68
+ const icon = metric.severity === "critical" ? "\u{1F534}" : metric.severity === "high" ? "\u{1F7E1}" : "\u{1F7E2}";
69
+ markdown += `### ${icon} ${metric.name}
70
+
71
+ `;
72
+ markdown += `- **Target:** ${metric.target}%
73
+ `;
74
+ markdown += `- **Window:** ${metric.window} (${metric.windowType})
75
+ `;
76
+ markdown += `- **Severity:** ${metric.severity}
77
+ `;
78
+ markdown += `- **Allowed Downtime:** ${downtime}
79
+
80
+ `;
81
+ markdown += `**Description:** `;
82
+ const lowerName = metric.name.toLowerCase();
83
+ if (lowerName.includes("availability") || lowerName.includes("uptime")) {
84
+ markdown += `The service must be available and responding to requests ${metric.target}% of the time within the ${metric.window} window. `;
85
+ } else if (lowerName.includes("latency") || lowerName.includes("response")) {
86
+ markdown += `${metric.target}% of requests must complete within the defined latency threshold during the ${metric.window} window. `;
87
+ } else if (lowerName.includes("error") || lowerName.includes("success")) {
88
+ markdown += `The error rate must remain below ${100 - metric.target}% (success rate above ${metric.target}%) within the ${metric.window} window. `;
89
+ } else {
90
+ markdown += `This metric must achieve a ${metric.target}% target within the ${metric.window} window. `;
91
+ }
92
+ markdown += `
93
+
94
+ `;
95
+ }
96
+ markdown += `## Monitoring & Alerting
97
+
98
+ `;
99
+ markdown += `### Error Budget
100
+
101
+ `;
102
+ markdown += `Each SLO has an associated error budget based on the allowed downtime. `;
103
+ markdown += `When the error budget is exhausted:
104
+
105
+ `;
106
+ markdown += `- Halt non-critical deployments
107
+ `;
108
+ markdown += `- Focus on reliability improvements
109
+ `;
110
+ markdown += `- Conduct incident review
111
+
112
+ `;
113
+ markdown += `### Alerting Strategy
114
+
115
+ `;
116
+ const criticalMetrics = metrics.filter((m) => m.severity === "critical");
117
+ if (criticalMetrics.length > 0) {
118
+ markdown += `**Critical SLOs:** Alert immediately when burn rate indicates budget will be exhausted in <2 hours
119
+
120
+ `;
121
+ }
122
+ markdown += `**High SLOs:** Alert when burn rate indicates budget will be exhausted in <24 hours
123
+
124
+ `;
125
+ markdown += `**Medium SLOs:** Alert when burn rate indicates budget will be exhausted in <7 days
126
+
127
+ `;
128
+ markdown += `## Review Process
129
+
130
+ `;
131
+ markdown += `- **Frequency:** Quarterly
132
+ `;
133
+ markdown += `- **Participants:** Engineering team, SRE, Product
134
+ `;
135
+ markdown += `- **Review criteria:** User impact, operational cost, business requirements
136
+
137
+ `;
138
+ markdown += `## Related Documents
139
+
140
+ `;
141
+ markdown += `- Service Architecture
142
+ `;
143
+ markdown += `- Incident Response Playbook
144
+ `;
145
+ markdown += `- Monitoring Dashboard
146
+ `;
147
+ markdown += `- On-call Runbook
148
+ `;
149
+ return markdown;
150
+ }
151
+ function createSummary(serviceName, metrics) {
152
+ const criticalCount = metrics.filter((m) => m.severity === "critical").length;
153
+ const highCount = metrics.filter((m) => m.severity === "high").length;
154
+ const mediumCount = metrics.filter((m) => m.severity === "medium").length;
155
+ let summary = `SLO draft for ${serviceName} with ${metrics.length} metric${metrics.length !== 1 ? "s" : ""}`;
156
+ const parts = [];
157
+ if (criticalCount > 0) parts.push(`${criticalCount} critical`);
158
+ if (highCount > 0) parts.push(`${highCount} high`);
159
+ if (mediumCount > 0) parts.push(`${mediumCount} medium`);
160
+ if (parts.length > 0) {
161
+ summary += ` (${parts.join(", ")} severity)`;
162
+ }
163
+ summary += `. `;
164
+ const highestTarget = Math.max(...metrics.map((m) => m.target));
165
+ if (highestTarget >= 99.9) {
166
+ summary += `Includes stringent ${highestTarget}% availability targets requiring careful monitoring and error budget management.`;
167
+ } else if (highestTarget >= 99) {
168
+ summary += `Targets balanced reliability with ${highestTarget}% as the highest objective.`;
169
+ } else {
170
+ summary += `Focuses on achievable targets with ${highestTarget}% as the highest objective.`;
171
+ }
172
+ return summary;
173
+ }
174
+ var sloDraftTool = tool({
175
+ description: "Draft Service Level Objective (SLO) definitions for a service. Provide the service name and metrics (with name, target percentage, and time window) to generate a comprehensive SLO document in markdown format with error budgets, alerting strategies, and monitoring recommendations.",
176
+ inputSchema: jsonSchema({
177
+ type: "object",
178
+ properties: {
179
+ serviceName: {
180
+ type: "string",
181
+ description: 'Name of the service (e.g., "API Gateway", "Payment Service")'
182
+ },
183
+ metrics: {
184
+ type: "array",
185
+ description: 'Array of SLO metrics with name, target (percentage), and window (e.g., "30d", "7d")',
186
+ items: {
187
+ type: "object",
188
+ properties: {
189
+ name: {
190
+ type: "string",
191
+ description: 'Metric name (e.g., "Availability", "API Latency P99")'
192
+ },
193
+ target: {
194
+ type: "number",
195
+ description: "Target percentage (e.g., 99.9 for 99.9%)"
196
+ },
197
+ window: {
198
+ type: "string",
199
+ description: 'Time window for measurement (e.g., "30d", "7 days", "rolling 30 days")'
200
+ }
201
+ },
202
+ required: ["name", "target", "window"]
203
+ }
204
+ }
205
+ },
206
+ required: ["serviceName", "metrics"],
207
+ additionalProperties: false
208
+ }),
209
+ async execute({ serviceName, metrics }) {
210
+ if (!serviceName || typeof serviceName !== "string" || serviceName.trim().length === 0) {
211
+ throw new Error("Service name is required and must be a non-empty string");
212
+ }
213
+ if (!Array.isArray(metrics) || metrics.length === 0) {
214
+ throw new Error("Metrics array is required and must contain at least one metric");
215
+ }
216
+ const processedMetrics = [];
217
+ for (let i = 0; i < metrics.length; i++) {
218
+ const metric = metrics[i];
219
+ if (!metric) {
220
+ throw new Error(`Metric at index ${i}: is undefined`);
221
+ }
222
+ if (!metric.name || typeof metric.name !== "string" || metric.name.trim().length === 0) {
223
+ throw new Error(`Metric at index ${i}: name is required and must be a non-empty string`);
224
+ }
225
+ if (typeof metric.target !== "number") {
226
+ throw new Error(`Metric at index ${i}: target must be a number`);
227
+ }
228
+ if (metric.target < 0 || metric.target > 100) {
229
+ throw new Error(`Metric at index ${i}: target must be between 0 and 100`);
230
+ }
231
+ if (!metric.window || typeof metric.window !== "string" || metric.window.trim().length === 0) {
232
+ throw new Error(`Metric at index ${i}: window is required and must be a non-empty string`);
233
+ }
234
+ processedMetrics.push({
235
+ name: metric.name.trim(),
236
+ target: metric.target,
237
+ window: metric.window.trim(),
238
+ windowType: determineWindowType(metric.window),
239
+ severity: determineSeverity(metric.target)
240
+ });
241
+ }
242
+ processedMetrics.sort((a, b) => {
243
+ const severityOrder = { critical: 0, high: 1, medium: 2 };
244
+ return severityOrder[a.severity] - severityOrder[b.severity];
245
+ });
246
+ const sloMarkdown = generateSLOMarkdown(serviceName.trim(), processedMetrics);
247
+ const summary = createSummary(serviceName.trim(), processedMetrics);
248
+ const criticalMetrics = processedMetrics.filter((m) => m.severity === "critical").length;
249
+ return {
250
+ slo: sloMarkdown,
251
+ metrics: processedMetrics,
252
+ summary,
253
+ metadata: {
254
+ serviceName: serviceName.trim(),
255
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
256
+ totalMetrics: processedMetrics.length,
257
+ criticalMetrics
258
+ }
259
+ };
260
+ }
261
+ });
262
+ var index_default = sloDraftTool;
263
+
264
+ export { index_default as default, sloDraftTool };
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "@tpmjs/tools-slo-draft",
3
+ "version": "0.2.0",
4
+ "description": "Draft SLO (Service Level Objective) definitions for services",
5
+ "type": "module",
6
+ "keywords": [
7
+ "tpmjs",
8
+ "ops",
9
+ "slo",
10
+ "monitoring",
11
+ "sre"
12
+ ],
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.js"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "devDependencies": {
23
+ "tsup": "^8.3.5",
24
+ "typescript": "^5.9.3",
25
+ "@tpmjs/tsconfig": "0.0.0"
26
+ },
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/anthropics/tpmjs.git",
33
+ "directory": "packages/tools/official/slo-draft"
34
+ },
35
+ "homepage": "https://tpmjs.com",
36
+ "license": "MIT",
37
+ "tpmjs": {
38
+ "category": "ops",
39
+ "frameworks": [
40
+ "vercel-ai"
41
+ ],
42
+ "tools": [
43
+ {
44
+ "name": "sloDraftTool",
45
+ "description": "Draft SLO (Service Level Objective) definitions for services with metrics, targets, and windows",
46
+ "parameters": [
47
+ {
48
+ "name": "serviceName",
49
+ "type": "string",
50
+ "description": "Name of the service",
51
+ "required": true
52
+ },
53
+ {
54
+ "name": "metrics",
55
+ "type": "array",
56
+ "description": "Array of metrics with name, target, and window",
57
+ "required": true
58
+ }
59
+ ],
60
+ "returns": {
61
+ "type": "SLODraft",
62
+ "description": "Object with slo (markdown), metrics array, and summary"
63
+ }
64
+ }
65
+ ]
66
+ },
67
+ "dependencies": {
68
+ "ai": "6.0.0-beta.124"
69
+ },
70
+ "scripts": {
71
+ "build": "tsup",
72
+ "dev": "tsup --watch",
73
+ "type-check": "tsc --noEmit",
74
+ "clean": "rm -rf dist .turbo"
75
+ }
76
+ }