everything-gemini 1.9.0 → 2.0.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/CHANGELOG.md +24 -0
- package/README.md +14 -4
- package/agents/mlops-engineer.md +33 -0
- package/bin/everything-gemini +122 -4
- package/docs/LAUNCH_KIT_v2.0.0.md +187 -0
- package/docs/architecture/progressive-disclosure.md +3 -3
- package/docs/index.html +13 -6
- package/examples/python-sdk/README.md +4 -0
- package/examples/python-sdk/autonomous_mlops_rag_pipeline.py +254 -0
- package/mcp/README.md +1 -0
- package/mcp/mcp_config.example.json +7 -0
- package/package.json +1 -1
- package/scripts/validate.sh +1 -1
- package/skills/chromadb-vector-store/SKILL.md +188 -0
- package/skills/keda-event-autoscaling/SKILL.md +218 -0
- package/skills/opa-gatekeeper-policy/SKILL.md +200 -0
- package/skills/triton-inference-server/SKILL.md +221 -0
- package/templates/full-power/mcp_config.json +7 -0
- package/tests/cli.test.js +52 -9
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: opa-gatekeeper-policy
|
|
3
|
+
description: Authors and validates Open Policy Agent (OPA) Gatekeeper ConstraintTemplates and Rego admission policies for Kubernetes governance and security compliance.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# OPA Gatekeeper Policy
|
|
7
|
+
|
|
8
|
+
Defines declarative policy enforcement for Kubernetes clusters using Open Policy Agent (OPA) Gatekeeper ConstraintTemplates, Rego logic, and shift-left CLI testing.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 1. Admission Control Flow
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
kubectl apply -f resource.yaml
|
|
16
|
+
│
|
|
17
|
+
▼
|
|
18
|
+
┌────────────────────────┐
|
|
19
|
+
│ Kubernetes API Server │
|
|
20
|
+
└───────────┬────────────┘
|
|
21
|
+
│ ValidatingWebhookConfiguration
|
|
22
|
+
▼
|
|
23
|
+
┌────────────────────────┐ Matches Rules?
|
|
24
|
+
│ Gatekeeper Pod │────────────────────────┐
|
|
25
|
+
│ (Admission Webhook) │ │
|
|
26
|
+
└───────────┬────────────┘ ▼
|
|
27
|
+
│ Rego Evaluation ┌────────────────────┐
|
|
28
|
+
▼ │ Reject (403) │
|
|
29
|
+
┌──────────────────────┐ │ Error & Remediation│
|
|
30
|
+
│ Constraint Templates │ └────────────────────┘
|
|
31
|
+
└──────────┬───────────┘
|
|
32
|
+
│ Passed
|
|
33
|
+
▼
|
|
34
|
+
┌──────────────────────┐
|
|
35
|
+
│ Persist to etcd │
|
|
36
|
+
└──────────────────────┘
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## 2. ConstraintTemplate (Rego Engine)
|
|
42
|
+
|
|
43
|
+
Defines the reusable policy schema and Rego execution logic:
|
|
44
|
+
|
|
45
|
+
```yaml
|
|
46
|
+
apiVersion: templates.gatekeeper.sh/v1
|
|
47
|
+
kind: ConstraintTemplate
|
|
48
|
+
metadata:
|
|
49
|
+
name: k8srequiredlabels
|
|
50
|
+
annotations:
|
|
51
|
+
description: "Requires all namespaces and workloads to specify standard governance labels."
|
|
52
|
+
spec:
|
|
53
|
+
crd:
|
|
54
|
+
spec:
|
|
55
|
+
names:
|
|
56
|
+
kind: K8sRequiredLabels
|
|
57
|
+
validation:
|
|
58
|
+
openAPIV3Schema:
|
|
59
|
+
type: object
|
|
60
|
+
properties:
|
|
61
|
+
labels:
|
|
62
|
+
type: array
|
|
63
|
+
items:
|
|
64
|
+
type: string
|
|
65
|
+
targets:
|
|
66
|
+
- target: admission.k8s.gatekeeper.sh
|
|
67
|
+
rego: |
|
|
68
|
+
package k8srequiredlabels
|
|
69
|
+
|
|
70
|
+
violation[{"msg": msg, "details": {"missing_labels": missing}}] {
|
|
71
|
+
provided := {label | input.review.object.metadata.labels[label]}
|
|
72
|
+
required := {label | label := input.parameters.labels[_]}
|
|
73
|
+
missing := required - provided
|
|
74
|
+
count(missing) > 0
|
|
75
|
+
msg := sprintf("Resource %v '%v' violates policy: missing required labels: %v", [
|
|
76
|
+
input.review.object.kind,
|
|
77
|
+
input.review.object.metadata.name,
|
|
78
|
+
missing
|
|
79
|
+
])
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## 3. Instantiating the Constraint
|
|
86
|
+
|
|
87
|
+
Applies the template to specific resource kinds and namespaces:
|
|
88
|
+
|
|
89
|
+
```yaml
|
|
90
|
+
apiVersion: constraints.gatekeeper.sh/v1beta1
|
|
91
|
+
kind: K8sRequiredLabels
|
|
92
|
+
metadata:
|
|
93
|
+
name: require-team-and-cost-center
|
|
94
|
+
spec:
|
|
95
|
+
enforcementAction: deny # Options: deny, dryrun, warn
|
|
96
|
+
match:
|
|
97
|
+
kinds:
|
|
98
|
+
- apiGroups: ["apps"]
|
|
99
|
+
kinds: ["Deployment", "StatefulSet"]
|
|
100
|
+
- apiGroups: [""]
|
|
101
|
+
kinds: ["Namespace"]
|
|
102
|
+
excludedNamespaces:
|
|
103
|
+
- kube-system
|
|
104
|
+
- gatekeeper-system
|
|
105
|
+
parameters:
|
|
106
|
+
labels:
|
|
107
|
+
- "app.kubernetes.io/managed-by"
|
|
108
|
+
- "cost-center"
|
|
109
|
+
- "owner-team"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## 4. Container Security Constraint (Disallow Privileged)
|
|
115
|
+
|
|
116
|
+
Enforces zero-trust rootless containers:
|
|
117
|
+
|
|
118
|
+
```yaml
|
|
119
|
+
apiVersion: templates.gatekeeper.sh/v1
|
|
120
|
+
kind: ConstraintTemplate
|
|
121
|
+
metadata:
|
|
122
|
+
name: k8sdisallowprivileged
|
|
123
|
+
spec:
|
|
124
|
+
crd:
|
|
125
|
+
spec:
|
|
126
|
+
names:
|
|
127
|
+
kind: K8sDisallowPrivileged
|
|
128
|
+
targets:
|
|
129
|
+
- target: admission.k8s.gatekeeper.sh
|
|
130
|
+
rego: |
|
|
131
|
+
package k8sdisallowprivileged
|
|
132
|
+
|
|
133
|
+
violation[{"msg": msg}] {
|
|
134
|
+
c := input_containers[_]
|
|
135
|
+
c.securityContext.privileged == true
|
|
136
|
+
msg := sprintf("Privileged container '%v' is prohibited in namespace '%v'.", [
|
|
137
|
+
c.name,
|
|
138
|
+
input.review.object.metadata.namespace
|
|
139
|
+
])
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
input_containers[c] {
|
|
143
|
+
c := input.review.object.spec.template.spec.containers[_]
|
|
144
|
+
}
|
|
145
|
+
input_containers[c] {
|
|
146
|
+
c := input.review.object.spec.template.spec.initContainers[_]
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## 5. Shift-Left CI Validation with `gator` CLI
|
|
153
|
+
|
|
154
|
+
Validates Kubernetes manifests against Gatekeeper templates inside CI pipelines before merge:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
# Test manifests directly without a live Kubernetes cluster
|
|
158
|
+
gator test \
|
|
159
|
+
--image-template=./templates/ \
|
|
160
|
+
--constraint=./constraints/ \
|
|
161
|
+
--manifests=./deploy/production/
|
|
162
|
+
|
|
163
|
+
# Run unit tests on Rego source files
|
|
164
|
+
gator verify ./policies/...
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
```yaml
|
|
168
|
+
# Gator test suite definition (suite.yaml)
|
|
169
|
+
kind: Suite
|
|
170
|
+
apiVersion: test.gatekeeper.sh/v1alpha1
|
|
171
|
+
metadata:
|
|
172
|
+
name: deployment-label-suite
|
|
173
|
+
tests:
|
|
174
|
+
- name: test-missing-labels-denied
|
|
175
|
+
template: template.yaml
|
|
176
|
+
constraint: constraint.yaml
|
|
177
|
+
cases:
|
|
178
|
+
- name: deployment-without-cost-center
|
|
179
|
+
object: bad-deployment.yaml
|
|
180
|
+
assertions:
|
|
181
|
+
- violations: yes
|
|
182
|
+
message: "missing required labels: {\"cost-center\"}"
|
|
183
|
+
- name: compliant-deployment
|
|
184
|
+
object: good-deployment.yaml
|
|
185
|
+
assertions:
|
|
186
|
+
- violations: no
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## 6. Audit Cluster Violations
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
# Inspect non-compliant resources identified during continuous background audit
|
|
195
|
+
kubectl get constraints -A
|
|
196
|
+
|
|
197
|
+
# Detailed violation listing
|
|
198
|
+
kubectl get k8srequiredlabels.constraints.gatekeeper.sh require-team-and-cost-center -o yaml \
|
|
199
|
+
| yq '.status.violations[] | {resource: .name, kind: .kind, message: .message}'
|
|
200
|
+
```
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: triton-inference-server
|
|
3
|
+
description: Deploys, configures, and tunes NVIDIA Triton Inference Server for high-throughput, low-latency multi-model serving with dynamic batching and GPU acceleration.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Triton Inference Server
|
|
7
|
+
|
|
8
|
+
Provides production architecture and configuration patterns for serving deep learning and LLM models at enterprise scale with NVIDIA Triton Inference Server.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 1. Architecture & Execution Model
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
Client Application (gRPC / HTTP KServe v2)
|
|
16
|
+
│
|
|
17
|
+
▼
|
|
18
|
+
┌──────────────────────────────────────────────┐
|
|
19
|
+
│ NVIDIA Triton Inference Server │
|
|
20
|
+
│ │
|
|
21
|
+
│ ┌──────────────────┐ ┌──────────────────┐ │
|
|
22
|
+
│ │ Dynamic Batching │ │ Model Concurrency│ │
|
|
23
|
+
│ │ Scheduler │ │ & GPU Instances │ │
|
|
24
|
+
│ └─────────┬────────┘ └────────┬─────────┘ │
|
|
25
|
+
│ │ │ │
|
|
26
|
+
│ ▼ ▼ │
|
|
27
|
+
│ ┌────────────────────────────────────────┐ │
|
|
28
|
+
│ │ Backend Engines │ │
|
|
29
|
+
│ │ - TensorRT-LLM (High-speed generative)│ │
|
|
30
|
+
│ │ - vLLM Engine (PagedAttention serving)│ │
|
|
31
|
+
│ │ - ONNX Runtime (Embedding & classifier│ │
|
|
32
|
+
│ │ - Python Backend (Custom preprocessing│ │
|
|
33
|
+
│ └────────────────────────────────────────┘ │
|
|
34
|
+
└──────────────────────┬───────────────────────┘
|
|
35
|
+
│
|
|
36
|
+
▼
|
|
37
|
+
NVIDIA Tensor Core GPUs (H100/A100/L4)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 2. Model Repository Layout
|
|
43
|
+
|
|
44
|
+
Triton requires a strict directory layout with versioned subdirectories and `config.pbtxt`:
|
|
45
|
+
|
|
46
|
+
```text
|
|
47
|
+
model_repository/
|
|
48
|
+
├── embedding_model/
|
|
49
|
+
│ ├── 1/
|
|
50
|
+
│ │ └── model.onnx
|
|
51
|
+
│ └── config.pbtxt
|
|
52
|
+
└── llm_generator/
|
|
53
|
+
├── 1/
|
|
54
|
+
│ └── model.py
|
|
55
|
+
└── config.pbtxt
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 3. High-Throughput `config.pbtxt` Configuration
|
|
61
|
+
|
|
62
|
+
Configures dynamic batching, GPU instance groups, and TensorRT acceleration:
|
|
63
|
+
|
|
64
|
+
```protobuf
|
|
65
|
+
name: "embedding_model"
|
|
66
|
+
platform: "onnxruntime_onnx"
|
|
67
|
+
max_batch_size: 128
|
|
68
|
+
|
|
69
|
+
input [
|
|
70
|
+
{
|
|
71
|
+
name: "input_ids"
|
|
72
|
+
data_type: TYPE_INT64
|
|
73
|
+
dims: [ -1 ]
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: "attention_mask"
|
|
77
|
+
data_type: TYPE_INT64
|
|
78
|
+
dims: [ -1 ]
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
output [
|
|
83
|
+
{
|
|
84
|
+
name: "sentence_embedding"
|
|
85
|
+
data_type: TYPE_FP32
|
|
86
|
+
dims: [ 768 ]
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
# Maximize GPU utilization via dynamic queue batching
|
|
91
|
+
dynamic_batching {
|
|
92
|
+
max_queue_delay_microseconds: 5000 # 5ms SLA window
|
|
93
|
+
preferred_batch_size: [ 16, 32, 64, 128 ]
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
# Run 2 concurrent model instances on GPU 0
|
|
97
|
+
instance_group [
|
|
98
|
+
{
|
|
99
|
+
count: 2
|
|
100
|
+
kind: KIND_GPU
|
|
101
|
+
gpus: [ 0 ]
|
|
102
|
+
}
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
optimization {
|
|
106
|
+
execution_accelerators {
|
|
107
|
+
gpu_execution_accelerator : [ {
|
|
108
|
+
name : "tensorrt"
|
|
109
|
+
parameters { key: "precision_mode" value: "FP16" }
|
|
110
|
+
parameters { key: "max_workspace_size_bytes" value: "4294967296" }
|
|
111
|
+
}]
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## 4. High-Performance gRPC Client (Python)
|
|
119
|
+
|
|
120
|
+
Uses binary gRPC streaming with zero-copy serialization:
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
import numpy as np
|
|
124
|
+
import tritonclient.grpc as grpcclient
|
|
125
|
+
from tritonclient.grpc import InferInput, InferRequestedOutput
|
|
126
|
+
|
|
127
|
+
def query_triton_embeddings(
|
|
128
|
+
texts_token_ids: np.ndarray,
|
|
129
|
+
attention_masks: np.ndarray,
|
|
130
|
+
server_url: str = "localhost:8001"
|
|
131
|
+
) -> np.ndarray:
|
|
132
|
+
"""Queries Triton via low-latency gRPC channel."""
|
|
133
|
+
with grpcclient.InferenceServerClient(url=server_url) as client:
|
|
134
|
+
# Check server readiness
|
|
135
|
+
if not client.is_server_ready():
|
|
136
|
+
raise RuntimeError("Triton server is not healthy.")
|
|
137
|
+
|
|
138
|
+
inputs = [
|
|
139
|
+
InferInput("input_ids", texts_token_ids.shape, "INT64"),
|
|
140
|
+
InferInput("attention_mask", attention_masks.shape, "INT64")
|
|
141
|
+
]
|
|
142
|
+
inputs[0].set_data_from_numpy(texts_token_ids)
|
|
143
|
+
inputs[1].set_data_from_numpy(attention_masks)
|
|
144
|
+
|
|
145
|
+
outputs = [InferRequestedOutput("sentence_embedding")]
|
|
146
|
+
|
|
147
|
+
response = client.infer(
|
|
148
|
+
model_name="embedding_model",
|
|
149
|
+
inputs=inputs,
|
|
150
|
+
outputs=outputs,
|
|
151
|
+
timeout=10.0
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
return response.as_numpy("sentence_embedding")
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## 5. Production Docker & Kubernetes Deployment
|
|
160
|
+
|
|
161
|
+
```yaml
|
|
162
|
+
apiVersion: apps/v1
|
|
163
|
+
kind: Deployment
|
|
164
|
+
metadata:
|
|
165
|
+
name: triton-inference-server
|
|
166
|
+
namespace: mlops
|
|
167
|
+
spec:
|
|
168
|
+
replicas: 2
|
|
169
|
+
selector:
|
|
170
|
+
matchLabels:
|
|
171
|
+
app: triton
|
|
172
|
+
template:
|
|
173
|
+
metadata:
|
|
174
|
+
labels:
|
|
175
|
+
app: triton
|
|
176
|
+
spec:
|
|
177
|
+
containers:
|
|
178
|
+
- name: triton
|
|
179
|
+
image: nvcr.io/nvidia/tritonserver:24.08-py3
|
|
180
|
+
args: ["tritonserver", "--model-repository=/models", "--strict-model-config=true"]
|
|
181
|
+
resources:
|
|
182
|
+
limits:
|
|
183
|
+
nvidia.com/gpu: 1
|
|
184
|
+
memory: 16Gi
|
|
185
|
+
cpu: "8"
|
|
186
|
+
ports:
|
|
187
|
+
- containerPort: 8000 # HTTP
|
|
188
|
+
- containerPort: 8001 # gRPC
|
|
189
|
+
- containerPort: 8002 # Metrics (Prometheus)
|
|
190
|
+
livenessProbe:
|
|
191
|
+
httpGet:
|
|
192
|
+
path: /v2/health/live
|
|
193
|
+
port: 8000
|
|
194
|
+
initialDelaySeconds: 30
|
|
195
|
+
readinessProbe:
|
|
196
|
+
httpGet:
|
|
197
|
+
path: /v2/health/ready
|
|
198
|
+
port: 8000
|
|
199
|
+
initialDelaySeconds: 15
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## 6. Performance Benchmarking & Profiling
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
# Verify health and loaded models via v2 API
|
|
208
|
+
curl -s http://localhost:8000/v2/health/ready
|
|
209
|
+
curl -s http://localhost:8000/v2/models/embedding_model/ready
|
|
210
|
+
|
|
211
|
+
# Profile throughput and P99 latency with Perf Analyzer
|
|
212
|
+
perf_analyzer -m embedding_model \
|
|
213
|
+
-u localhost:8001 -i gRPC \
|
|
214
|
+
--concurrency-range 1:16 \
|
|
215
|
+
--shape input_ids:128 \
|
|
216
|
+
--shape attention_mask:128 \
|
|
217
|
+
--percentile 99
|
|
218
|
+
|
|
219
|
+
# Query Prometheus metrics
|
|
220
|
+
curl -s http://localhost:8002/metrics | grep nv_inference_
|
|
221
|
+
```
|
|
@@ -57,6 +57,13 @@
|
|
|
57
57
|
"puppeteer": {
|
|
58
58
|
"command": "npx",
|
|
59
59
|
"args": ["-y", "@modelcontextprotocol/server-puppeteer"]
|
|
60
|
+
},
|
|
61
|
+
"brave-search": {
|
|
62
|
+
"command": "npx",
|
|
63
|
+
"args": ["-y", "@modelcontextprotocol/server-brave-search"],
|
|
64
|
+
"env": {
|
|
65
|
+
"BRAVE_API_KEY": "${BRAVE_API_KEY}"
|
|
66
|
+
}
|
|
60
67
|
}
|
|
61
68
|
}
|
|
62
69
|
}
|
package/tests/cli.test.js
CHANGED
|
@@ -90,9 +90,9 @@ it('should benchmark ecosystem components and output valid JSON with --json', ()
|
|
|
90
90
|
const res = runCli('benchmark --json');
|
|
91
91
|
assert.strictEqual(res.status, 0);
|
|
92
92
|
const data = JSON.parse(res.stdout);
|
|
93
|
-
assert.strictEqual(data.totalComponents,
|
|
94
|
-
assert.strictEqual(data.progressiveSkillsCount,
|
|
95
|
-
assert.strictEqual(data.scopedAgentsCount,
|
|
93
|
+
assert.strictEqual(data.totalComponents, 80);
|
|
94
|
+
assert.strictEqual(data.progressiveSkillsCount, 60);
|
|
95
|
+
assert.strictEqual(data.scopedAgentsCount, 13);
|
|
96
96
|
assert.strictEqual(data.lifecycleHooksCount, 7);
|
|
97
97
|
assert(data.totalRunbookTokens > 15000, 'Expected >15,000 runbook tokens');
|
|
98
98
|
assert(data.estimatedTokensSavedPerTurn > 8000, 'Expected significant token savings');
|
|
@@ -316,7 +316,7 @@ try {
|
|
|
316
316
|
const dryRes = runCli(`bundle --output "${bundleTarget}" --dry-run`);
|
|
317
317
|
assert.strictEqual(dryRes.status, 0);
|
|
318
318
|
assert.match(dryRes.stdout, /DRY RUN MODE ACTIVATED/);
|
|
319
|
-
assert.match(dryRes.stdout, /Skills to bundle:
|
|
319
|
+
assert.match(dryRes.stdout, /Skills to bundle: 60/);
|
|
320
320
|
assert.strictEqual(fs.existsSync(bundleTarget), false, 'Dry run should not create destination directory');
|
|
321
321
|
|
|
322
322
|
// JSON Dry-run mode
|
|
@@ -324,7 +324,7 @@ try {
|
|
|
324
324
|
assert.strictEqual(jsonRes.status, 0);
|
|
325
325
|
const dryData = JSON.parse(jsonRes.stdout);
|
|
326
326
|
assert.strictEqual(dryData.dryRun, true);
|
|
327
|
-
assert.strictEqual(dryData.manifest.components.totalCount,
|
|
327
|
+
assert.strictEqual(dryData.manifest.components.totalCount, 80);
|
|
328
328
|
|
|
329
329
|
// Live mode
|
|
330
330
|
const liveRes = runCli(`bundle --output "${bundleTarget}"`);
|
|
@@ -423,14 +423,57 @@ try {
|
|
|
423
423
|
assert.match(resRate.stdout, /Distributed Rate Limiting/);
|
|
424
424
|
});
|
|
425
425
|
|
|
426
|
+
// Info for mlops-engineer and v2.0.0 skills
|
|
427
|
+
it('should display info for mlops-engineer subagent and v2.0.0 skills', () => {
|
|
428
|
+
const resMl = runCli('info mlops-engineer');
|
|
429
|
+
assert.strictEqual(resMl.status, 0);
|
|
430
|
+
assert.match(resMl.stdout, /MLOps Engineer/);
|
|
431
|
+
|
|
432
|
+
const resKeda = runCli('info keda-event-autoscaling');
|
|
433
|
+
assert.strictEqual(resKeda.status, 0);
|
|
434
|
+
assert.match(resKeda.stdout, /KEDA/);
|
|
435
|
+
|
|
436
|
+
const resChroma = runCli('info chromadb-vector-store');
|
|
437
|
+
assert.strictEqual(resChroma.status, 0);
|
|
438
|
+
assert.match(resChroma.stdout, /ChromaDB/);
|
|
439
|
+
|
|
440
|
+
const resOpa = runCli('info opa-gatekeeper-policy');
|
|
441
|
+
assert.strictEqual(resOpa.status, 0);
|
|
442
|
+
assert.match(resOpa.stdout, /Gatekeeper/);
|
|
443
|
+
|
|
444
|
+
const resTriton = runCli('info triton-inference-server');
|
|
445
|
+
assert.strictEqual(resTriton.status, 0);
|
|
446
|
+
assert.match(resTriton.stdout, /Triton/);
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
// Graph command verification
|
|
450
|
+
it('should render interaction graph in terminal, mermaid, and JSON formats', () => {
|
|
451
|
+
const resTerm = runCli('graph');
|
|
452
|
+
assert.strictEqual(resTerm.status, 0);
|
|
453
|
+
assert.match(resTerm.stdout, /Multi-Agent Topology & Dependency Graph/);
|
|
454
|
+
assert.match(resTerm.stdout, /MLOPS-ENGINEER/);
|
|
455
|
+
|
|
456
|
+
const resMermaid = runCli('graph --mermaid');
|
|
457
|
+
assert.strictEqual(resMermaid.status, 0);
|
|
458
|
+
assert.match(resMermaid.stdout, /graph TD/);
|
|
459
|
+
assert.match(resMermaid.stdout, /A_mlops_engineer/);
|
|
460
|
+
|
|
461
|
+
const resJson = runCli('graph --json');
|
|
462
|
+
assert.strictEqual(resJson.status, 0);
|
|
463
|
+
const data = JSON.parse(resJson.stdout);
|
|
464
|
+
assert.ok(data.totalNodes > 50, 'Graph should contain > 50 nodes');
|
|
465
|
+
assert.ok(data.totalEdges > 50, 'Graph should contain > 50 edges');
|
|
466
|
+
assert.ok(data.nodes.find(n => n.id === 'agent:mlops-engineer'));
|
|
467
|
+
});
|
|
468
|
+
|
|
426
469
|
// Benchmark Components Verification
|
|
427
|
-
it('should report
|
|
470
|
+
it('should report 80 components, 60 skills, and 13 subagents in benchmark --json', () => {
|
|
428
471
|
const res = runCli('benchmark --json');
|
|
429
472
|
assert.strictEqual(res.status, 0);
|
|
430
473
|
const data = JSON.parse(res.stdout);
|
|
431
|
-
assert.strictEqual(data.totalComponents,
|
|
432
|
-
assert.strictEqual(data.progressiveSkillsCount,
|
|
433
|
-
assert.strictEqual(data.scopedAgentsCount,
|
|
474
|
+
assert.strictEqual(data.totalComponents, 80, 'Total components should be 80');
|
|
475
|
+
assert.strictEqual(data.progressiveSkillsCount, 60, 'Progressive skills should be 60');
|
|
476
|
+
assert.strictEqual(data.scopedAgentsCount, 13, 'Scoped agents should be 13');
|
|
434
477
|
assert.strictEqual(data.lifecycleHooksCount, 7, 'Lifecycle hooks should be 7');
|
|
435
478
|
});
|
|
436
479
|
|