@elinpf/dsh-ops-tool-environment 0.1.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/lib/tool.d.ts ADDED
@@ -0,0 +1,159 @@
1
+ /**
2
+ * The `environment` model tool — the preset-plane face of the inventory.
3
+ *
4
+ * Three working actions plus help:
5
+ *
6
+ * - `overview` — compact all-cluster summary (middleware counts by type,
7
+ * unknown count, stale flag, scan time).
8
+ * - `show` — one cluster in detail: middleware instances, the unknown
9
+ * bucket, relation edges.
10
+ * - `refresh` — re-scan every k8s profile in the ops-access registry.
11
+ *
12
+ * Freshness: overview/show call ensureFresh first — when the inventory is
13
+ * missing or its oldest section is older than the configured TTL, a refresh
14
+ * runs before answering. Nothing scans at session start; apply() only
15
+ * registers the tool.
16
+ *
17
+ * Refresh resolves each k8s profile WITHOUT an agent identity: the access
18
+ * gate's broker falls back to the ro tier for agent-less resolves, which is
19
+ * exactly the read-only discipline the scanner wants. kubeconfig paths are
20
+ * used to spawn kubectl and never surface in results — every error string
21
+ * crossing into tool output is scrubbed.
22
+ *
23
+ * @module @elinpf/dsh-ops-tool-environment
24
+ */
25
+ import type { Context } from '@deepseek-ai/cordis';
26
+ import { readInventory, refreshInventory } from './inventory.js';
27
+ import type { InventorySection } from './inventory.js';
28
+ import type { CephHints, MonitoringStatus, RelationEdge, ResourceRef } from './types.js';
29
+ export interface EnvironmentToolConfig {
30
+ /** Inventory file path (default ~/.dsh-ops/environment.yaml). */
31
+ inventoryFile: string;
32
+ /** User classification rules file (default ~/.dsh-ops/environment-rules.yaml). */
33
+ rulesFile: string;
34
+ /** Sections older than this are re-scanned on the next read (default 60). */
35
+ ttlMinutes: number;
36
+ /** Per-kubectl-call scan timeout (ms, default 30000). Slow clusters may need more. */
37
+ scanTimeoutMs: number;
38
+ /** Prometheus scrape timeout (ms, default 15000). */
39
+ prometheusTimeoutMs: number;
40
+ }
41
+ export interface ClusterSummary {
42
+ name: string;
43
+ scannedAt: string;
44
+ stale: boolean;
45
+ /** Middleware instance count. */
46
+ middleware: number;
47
+ /** Unknown-bucket workload count. */
48
+ unknown: number;
49
+ /** Prometheus-down target count across workloads (0 when unmonitored/healthy). */
50
+ down: number;
51
+ /** Detected anomaly count. */
52
+ anomalies: number;
53
+ /** Middleware type → instance count. */
54
+ byType: Array<{
55
+ type: string;
56
+ count: number;
57
+ }>;
58
+ /** CephBlockPool count when the scan found rook-ceph hints (ticket 15). */
59
+ cephPools?: number;
60
+ lastError?: string;
61
+ }
62
+ export interface UnknownWorkload {
63
+ name: string;
64
+ namespace: string;
65
+ kind: string;
66
+ images: string[];
67
+ monitoring?: MonitoringStatus;
68
+ }
69
+ /**
70
+ * Edge as shown to the model: same shape as RelationEdge but with a plain
71
+ * string kind — the output schema cannot express the literal union, and
72
+ * RelationEdge is assignable to it.
73
+ */
74
+ export interface DisplayEdge {
75
+ kind: string;
76
+ from: RelationEdge['from'];
77
+ to: RelationEdge['to'];
78
+ via: string;
79
+ targetType?: string;
80
+ }
81
+ export interface ClusterDetail {
82
+ name: string;
83
+ scannedAt: string;
84
+ stale: boolean;
85
+ lastError?: string;
86
+ /** The Prometheus service monitoring data came from, when discovered. */
87
+ prometheusService?: string;
88
+ /** rook-ceph footprint hints (pools / cluster / tools pod), when found. */
89
+ ceph?: CephHints;
90
+ middleware: InventorySection['middleware'];
91
+ unknown: UnknownWorkload[];
92
+ edges: DisplayEdge[];
93
+ anomalies: DisplayAnomaly[];
94
+ counts: {
95
+ services: number;
96
+ ingresses: number;
97
+ workloads: number;
98
+ };
99
+ }
100
+ /** Anomaly as shown to the model: Anomaly with plain-string kind/severity. */
101
+ export interface DisplayAnomaly {
102
+ kind: string;
103
+ severity: string;
104
+ message: string;
105
+ ref: ResourceRef;
106
+ related?: ResourceRef;
107
+ }
108
+ /** One anomaly line in overview output. */
109
+ export interface OverviewAnomaly {
110
+ cluster: string;
111
+ kind: string;
112
+ severity: string;
113
+ message: string;
114
+ }
115
+ export interface RefreshResultEntry {
116
+ cluster: string;
117
+ status: 'ok' | 'stale' | 'skipped';
118
+ middleware?: number;
119
+ unknown?: number;
120
+ /** Sanitized — never carries a credential path. */
121
+ error?: string;
122
+ }
123
+ export interface EnvironmentToolResult {
124
+ action: string;
125
+ help?: string;
126
+ /** overview */
127
+ totalClusters?: number;
128
+ clusters?: ClusterSummary[];
129
+ /** overview: every detected anomaly across clusters, one line each. */
130
+ anomalies?: OverviewAnomaly[];
131
+ /** show */
132
+ cluster?: ClusterDetail;
133
+ /** refresh */
134
+ results?: RefreshResultEntry[];
135
+ refreshedAt?: string;
136
+ /** Non-fatal note, e.g. auto-refresh skipped because ops-access is absent. */
137
+ note?: string;
138
+ error?: string;
139
+ }
140
+ export interface EnvironmentToolDeps {
141
+ readInventory?: typeof readInventory;
142
+ refreshInventory?: typeof refreshInventory;
143
+ now?: () => number;
144
+ }
145
+ export interface ShowFilter {
146
+ namespace?: string;
147
+ name?: string;
148
+ }
149
+ /**
150
+ * Apply show's optional filters to a cluster detail. Both filters narrow the
151
+ * middleware list and the unknown bucket; when a filter is given, edges are
152
+ * kept only when their WORKLOAD endpoint survives the filter — that endpoint
153
+ * is `from` for uses-service/uses-middleware/references-secret edges and `to`
154
+ * for fronts edges (whose from is a Service). An investigation starts from a
155
+ * workload and follows its outgoing edges, so edges whose workload fell out
156
+ * of the filtered set are noise.
157
+ */
158
+ export declare function filterDetail(detail: ClusterDetail, filter: ShowFilter): ClusterDetail;
159
+ export declare function createEnvironmentTool(ctx: Context, config: EnvironmentToolConfig, deps?: EnvironmentToolDeps): import("@deepseek-ai/dsh-tools").ToolDefinition;