@build-astron-co/nimbus 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 +21 -0
- package/README.md +628 -0
- package/bin/nimbus +38 -0
- package/package.json +80 -0
- package/src/__tests__/app.test.ts +76 -0
- package/src/__tests__/audit.test.ts +877 -0
- package/src/__tests__/circuit-breaker.test.ts +116 -0
- package/src/__tests__/cli-run.test.ts +115 -0
- package/src/__tests__/context-manager.test.ts +502 -0
- package/src/__tests__/context.test.ts +242 -0
- package/src/__tests__/enterprise.test.ts +401 -0
- package/src/__tests__/generator.test.ts +433 -0
- package/src/__tests__/hooks.test.ts +582 -0
- package/src/__tests__/init.test.ts +436 -0
- package/src/__tests__/intent-parser.test.ts +229 -0
- package/src/__tests__/llm-router.test.ts +209 -0
- package/src/__tests__/lsp.test.ts +293 -0
- package/src/__tests__/modes.test.ts +336 -0
- package/src/__tests__/permissions.test.ts +338 -0
- package/src/__tests__/serve.test.ts +275 -0
- package/src/__tests__/sessions.test.ts +227 -0
- package/src/__tests__/sharing.test.ts +288 -0
- package/src/__tests__/snapshots.test.ts +581 -0
- package/src/__tests__/state-db.test.ts +334 -0
- package/src/__tests__/stream-with-tools.test.ts +732 -0
- package/src/__tests__/subagents.test.ts +176 -0
- package/src/__tests__/system-prompt.test.ts +169 -0
- package/src/__tests__/tool-converter.test.ts +256 -0
- package/src/__tests__/tool-schemas.test.ts +397 -0
- package/src/__tests__/tools.test.ts +143 -0
- package/src/__tests__/version.test.ts +49 -0
- package/src/agent/compaction-agent.ts +227 -0
- package/src/agent/context-manager.ts +435 -0
- package/src/agent/context.ts +427 -0
- package/src/agent/deploy-preview.ts +426 -0
- package/src/agent/index.ts +68 -0
- package/src/agent/loop.ts +717 -0
- package/src/agent/modes.ts +429 -0
- package/src/agent/permissions.ts +466 -0
- package/src/agent/subagents/base.ts +116 -0
- package/src/agent/subagents/cost.ts +51 -0
- package/src/agent/subagents/explore.ts +42 -0
- package/src/agent/subagents/general.ts +54 -0
- package/src/agent/subagents/index.ts +102 -0
- package/src/agent/subagents/infra.ts +59 -0
- package/src/agent/subagents/security.ts +69 -0
- package/src/agent/system-prompt.ts +436 -0
- package/src/app.ts +122 -0
- package/src/audit/activity-log.ts +290 -0
- package/src/audit/compliance-checker.ts +540 -0
- package/src/audit/cost-tracker.ts +318 -0
- package/src/audit/index.ts +23 -0
- package/src/audit/security-scanner.ts +596 -0
- package/src/auth/guard.ts +75 -0
- package/src/auth/index.ts +56 -0
- package/src/auth/oauth.ts +455 -0
- package/src/auth/providers.ts +470 -0
- package/src/auth/sso.ts +113 -0
- package/src/auth/store.ts +505 -0
- package/src/auth/types.ts +187 -0
- package/src/build.ts +141 -0
- package/src/cli/index.ts +16 -0
- package/src/cli/init.ts +854 -0
- package/src/cli/openapi-spec.ts +356 -0
- package/src/cli/run.ts +237 -0
- package/src/cli/serve-auth.ts +80 -0
- package/src/cli/serve.ts +462 -0
- package/src/cli/web.ts +67 -0
- package/src/cli.ts +1417 -0
- package/src/clients/core-engine-client.ts +227 -0
- package/src/clients/enterprise-client.ts +334 -0
- package/src/clients/generator-client.ts +351 -0
- package/src/clients/git-client.ts +627 -0
- package/src/clients/github-client.ts +410 -0
- package/src/clients/helm-client.ts +504 -0
- package/src/clients/index.ts +80 -0
- package/src/clients/k8s-client.ts +497 -0
- package/src/clients/llm-client.ts +161 -0
- package/src/clients/rest-client.ts +130 -0
- package/src/clients/service-discovery.ts +33 -0
- package/src/clients/terraform-client.ts +482 -0
- package/src/clients/tools-client.ts +1843 -0
- package/src/clients/ws-client.ts +115 -0
- package/src/commands/analyze/index.ts +352 -0
- package/src/commands/apply/helm.ts +473 -0
- package/src/commands/apply/index.ts +213 -0
- package/src/commands/apply/k8s.ts +454 -0
- package/src/commands/apply/terraform.ts +582 -0
- package/src/commands/ask.ts +167 -0
- package/src/commands/audit/index.ts +238 -0
- package/src/commands/auth-cloud.ts +294 -0
- package/src/commands/auth-list.ts +134 -0
- package/src/commands/auth-profile.ts +121 -0
- package/src/commands/auth-status.ts +141 -0
- package/src/commands/aws/ec2.ts +501 -0
- package/src/commands/aws/iam.ts +397 -0
- package/src/commands/aws/index.ts +133 -0
- package/src/commands/aws/lambda.ts +396 -0
- package/src/commands/aws/rds.ts +439 -0
- package/src/commands/aws/s3.ts +439 -0
- package/src/commands/aws/vpc.ts +393 -0
- package/src/commands/aws-discover.ts +649 -0
- package/src/commands/aws-terraform.ts +805 -0
- package/src/commands/azure/aks.ts +376 -0
- package/src/commands/azure/functions.ts +253 -0
- package/src/commands/azure/index.ts +116 -0
- package/src/commands/azure/storage.ts +478 -0
- package/src/commands/azure/vm.ts +355 -0
- package/src/commands/billing/index.ts +256 -0
- package/src/commands/chat.ts +314 -0
- package/src/commands/config.ts +346 -0
- package/src/commands/cost/cloud-cost-estimator.ts +266 -0
- package/src/commands/cost/estimator.ts +79 -0
- package/src/commands/cost/index.ts +594 -0
- package/src/commands/cost/parsers/terraform.ts +273 -0
- package/src/commands/cost/parsers/types.ts +25 -0
- package/src/commands/cost/pricing/aws.ts +544 -0
- package/src/commands/cost/pricing/azure.ts +499 -0
- package/src/commands/cost/pricing/gcp.ts +396 -0
- package/src/commands/cost/pricing/index.ts +40 -0
- package/src/commands/demo.ts +250 -0
- package/src/commands/doctor.ts +794 -0
- package/src/commands/drift/index.ts +439 -0
- package/src/commands/explain.ts +277 -0
- package/src/commands/feedback.ts +389 -0
- package/src/commands/fix.ts +324 -0
- package/src/commands/fs/index.ts +402 -0
- package/src/commands/gcp/compute.ts +325 -0
- package/src/commands/gcp/functions.ts +271 -0
- package/src/commands/gcp/gke.ts +438 -0
- package/src/commands/gcp/iam.ts +344 -0
- package/src/commands/gcp/index.ts +129 -0
- package/src/commands/gcp/storage.ts +284 -0
- package/src/commands/generate-helm.ts +1249 -0
- package/src/commands/generate-k8s.ts +1560 -0
- package/src/commands/generate-terraform.ts +1460 -0
- package/src/commands/gh/index.ts +863 -0
- package/src/commands/git/index.ts +1343 -0
- package/src/commands/helm/index.ts +1126 -0
- package/src/commands/help.ts +539 -0
- package/src/commands/history.ts +142 -0
- package/src/commands/import.ts +868 -0
- package/src/commands/index.ts +367 -0
- package/src/commands/init.ts +1046 -0
- package/src/commands/k8s/index.ts +1137 -0
- package/src/commands/login.ts +631 -0
- package/src/commands/logout.ts +83 -0
- package/src/commands/onboarding.ts +228 -0
- package/src/commands/plan/display.ts +279 -0
- package/src/commands/plan/index.ts +599 -0
- package/src/commands/preview.ts +452 -0
- package/src/commands/questionnaire.ts +1270 -0
- package/src/commands/resume.ts +55 -0
- package/src/commands/team/index.ts +346 -0
- package/src/commands/template.ts +232 -0
- package/src/commands/tf/index.ts +1034 -0
- package/src/commands/upgrade.ts +550 -0
- package/src/commands/usage/index.ts +134 -0
- package/src/commands/version.ts +170 -0
- package/src/compat/index.ts +2 -0
- package/src/compat/runtime.ts +12 -0
- package/src/compat/sqlite.ts +107 -0
- package/src/config/index.ts +17 -0
- package/src/config/manager.ts +530 -0
- package/src/config/safety-policy.ts +358 -0
- package/src/config/schema.ts +125 -0
- package/src/config/types.ts +527 -0
- package/src/context/context-db.ts +199 -0
- package/src/demo/index.ts +349 -0
- package/src/demo/scenarios/full-journey.ts +229 -0
- package/src/demo/scenarios/getting-started.ts +127 -0
- package/src/demo/scenarios/helm-release.ts +341 -0
- package/src/demo/scenarios/k8s-deployment.ts +194 -0
- package/src/demo/scenarios/terraform-vpc.ts +170 -0
- package/src/demo/types.ts +92 -0
- package/src/engine/cost-estimator.ts +438 -0
- package/src/engine/diagram-generator.ts +256 -0
- package/src/engine/drift-detector.ts +902 -0
- package/src/engine/executor.ts +1035 -0
- package/src/engine/index.ts +76 -0
- package/src/engine/orchestrator.ts +636 -0
- package/src/engine/planner.ts +720 -0
- package/src/engine/safety.ts +743 -0
- package/src/engine/verifier.ts +770 -0
- package/src/enterprise/audit.ts +348 -0
- package/src/enterprise/auth.ts +270 -0
- package/src/enterprise/billing.ts +822 -0
- package/src/enterprise/index.ts +17 -0
- package/src/enterprise/teams.ts +443 -0
- package/src/generator/best-practices.ts +1608 -0
- package/src/generator/helm.ts +630 -0
- package/src/generator/index.ts +37 -0
- package/src/generator/intent-parser.ts +514 -0
- package/src/generator/kubernetes.ts +976 -0
- package/src/generator/terraform.ts +1867 -0
- package/src/history/index.ts +8 -0
- package/src/history/manager.ts +322 -0
- package/src/history/types.ts +34 -0
- package/src/hooks/config.ts +432 -0
- package/src/hooks/engine.ts +391 -0
- package/src/hooks/index.ts +4 -0
- package/src/llm/auth-bridge.ts +198 -0
- package/src/llm/circuit-breaker.ts +140 -0
- package/src/llm/config-loader.ts +201 -0
- package/src/llm/cost-calculator.ts +171 -0
- package/src/llm/index.ts +8 -0
- package/src/llm/model-aliases.ts +115 -0
- package/src/llm/provider-registry.ts +63 -0
- package/src/llm/providers/anthropic.ts +433 -0
- package/src/llm/providers/bedrock.ts +477 -0
- package/src/llm/providers/google.ts +405 -0
- package/src/llm/providers/ollama.ts +767 -0
- package/src/llm/providers/openai-compatible.ts +340 -0
- package/src/llm/providers/openai.ts +328 -0
- package/src/llm/providers/openrouter.ts +338 -0
- package/src/llm/router.ts +1035 -0
- package/src/llm/types.ts +232 -0
- package/src/lsp/client.ts +298 -0
- package/src/lsp/languages.ts +116 -0
- package/src/lsp/manager.ts +278 -0
- package/src/mcp/client.ts +402 -0
- package/src/mcp/index.ts +5 -0
- package/src/mcp/manager.ts +133 -0
- package/src/nimbus.ts +214 -0
- package/src/plugins/index.ts +27 -0
- package/src/plugins/loader.ts +334 -0
- package/src/plugins/manager.ts +376 -0
- package/src/plugins/types.ts +284 -0
- package/src/scanners/cicd-scanner.ts +258 -0
- package/src/scanners/cloud-scanner.ts +466 -0
- package/src/scanners/framework-scanner.ts +469 -0
- package/src/scanners/iac-scanner.ts +388 -0
- package/src/scanners/index.ts +539 -0
- package/src/scanners/language-scanner.ts +276 -0
- package/src/scanners/package-manager-scanner.ts +277 -0
- package/src/scanners/types.ts +172 -0
- package/src/sessions/manager.ts +365 -0
- package/src/sessions/types.ts +44 -0
- package/src/sharing/sync.ts +296 -0
- package/src/sharing/viewer.ts +97 -0
- package/src/snapshots/index.ts +2 -0
- package/src/snapshots/manager.ts +530 -0
- package/src/state/artifacts.ts +147 -0
- package/src/state/audit.ts +137 -0
- package/src/state/billing.ts +240 -0
- package/src/state/checkpoints.ts +117 -0
- package/src/state/config.ts +67 -0
- package/src/state/conversations.ts +14 -0
- package/src/state/credentials.ts +154 -0
- package/src/state/db.ts +58 -0
- package/src/state/index.ts +26 -0
- package/src/state/messages.ts +115 -0
- package/src/state/projects.ts +123 -0
- package/src/state/schema.ts +236 -0
- package/src/state/sessions.ts +147 -0
- package/src/state/teams.ts +200 -0
- package/src/telemetry.ts +108 -0
- package/src/tools/aws-ops.ts +952 -0
- package/src/tools/azure-ops.ts +579 -0
- package/src/tools/file-ops.ts +593 -0
- package/src/tools/gcp-ops.ts +625 -0
- package/src/tools/git-ops.ts +773 -0
- package/src/tools/github-ops.ts +799 -0
- package/src/tools/helm-ops.ts +943 -0
- package/src/tools/index.ts +17 -0
- package/src/tools/k8s-ops.ts +819 -0
- package/src/tools/schemas/converter.ts +184 -0
- package/src/tools/schemas/devops.ts +612 -0
- package/src/tools/schemas/index.ts +73 -0
- package/src/tools/schemas/standard.ts +1144 -0
- package/src/tools/schemas/types.ts +705 -0
- package/src/tools/terraform-ops.ts +862 -0
- package/src/types/ambient.d.ts +193 -0
- package/src/types/config.ts +83 -0
- package/src/types/drift.ts +116 -0
- package/src/types/enterprise.ts +335 -0
- package/src/types/index.ts +20 -0
- package/src/types/plan.ts +44 -0
- package/src/types/request.ts +65 -0
- package/src/types/response.ts +54 -0
- package/src/types/service.ts +51 -0
- package/src/ui/App.tsx +997 -0
- package/src/ui/DeployPreview.tsx +169 -0
- package/src/ui/Header.tsx +68 -0
- package/src/ui/InputBox.tsx +350 -0
- package/src/ui/MessageList.tsx +585 -0
- package/src/ui/PermissionPrompt.tsx +151 -0
- package/src/ui/StatusBar.tsx +158 -0
- package/src/ui/ToolCallDisplay.tsx +409 -0
- package/src/ui/chat-ui.ts +853 -0
- package/src/ui/index.ts +33 -0
- package/src/ui/ink/index.ts +711 -0
- package/src/ui/streaming.ts +176 -0
- package/src/ui/types.ts +57 -0
- package/src/utils/analytics.ts +72 -0
- package/src/utils/cost-warning.ts +27 -0
- package/src/utils/env.ts +46 -0
- package/src/utils/errors.ts +69 -0
- package/src/utils/event-bus.ts +38 -0
- package/src/utils/index.ts +24 -0
- package/src/utils/logger.ts +171 -0
- package/src/utils/rate-limiter.ts +121 -0
- package/src/utils/service-auth.ts +49 -0
- package/src/utils/validation.ts +53 -0
- package/src/version.ts +4 -0
- package/src/watcher/index.ts +163 -0
- package/src/wizard/approval.ts +383 -0
- package/src/wizard/index.ts +25 -0
- package/src/wizard/prompts.ts +338 -0
- package/src/wizard/types.ts +171 -0
- package/src/wizard/ui.ts +556 -0
- package/src/wizard/wizard.ts +304 -0
- package/tsconfig.json +24 -0
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kubernetes Tools Client
|
|
3
|
+
*
|
|
4
|
+
* REST client for communicating with the K8s Tools Service
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { RestClient, ServiceURLs } from '.';
|
|
8
|
+
|
|
9
|
+
export interface K8sResource {
|
|
10
|
+
apiVersion: string;
|
|
11
|
+
kind: string;
|
|
12
|
+
metadata: {
|
|
13
|
+
name: string;
|
|
14
|
+
namespace?: string;
|
|
15
|
+
labels?: Record<string, string>;
|
|
16
|
+
};
|
|
17
|
+
[key: string]: any;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface K8sGetResult {
|
|
21
|
+
success: boolean;
|
|
22
|
+
items: K8sResource[];
|
|
23
|
+
error?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface K8sApplyResult {
|
|
27
|
+
success: boolean;
|
|
28
|
+
output: string;
|
|
29
|
+
created?: string[];
|
|
30
|
+
configured?: string[];
|
|
31
|
+
error?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface K8sDeleteResult {
|
|
35
|
+
success: boolean;
|
|
36
|
+
output: string;
|
|
37
|
+
deleted?: string[];
|
|
38
|
+
error?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface K8sLogsResult {
|
|
42
|
+
success: boolean;
|
|
43
|
+
logs: string;
|
|
44
|
+
error?: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Client for Kubernetes Tools Service
|
|
49
|
+
*/
|
|
50
|
+
export class K8sClient {
|
|
51
|
+
private client: RestClient;
|
|
52
|
+
|
|
53
|
+
constructor(baseUrl?: string) {
|
|
54
|
+
this.client = new RestClient(baseUrl || ServiceURLs.K8S_TOOLS);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Get Kubernetes resources
|
|
59
|
+
*/
|
|
60
|
+
async get(
|
|
61
|
+
resource: string,
|
|
62
|
+
options?: {
|
|
63
|
+
namespace?: string;
|
|
64
|
+
name?: string;
|
|
65
|
+
labels?: Record<string, string>;
|
|
66
|
+
output?: 'json' | 'yaml' | 'wide';
|
|
67
|
+
}
|
|
68
|
+
): Promise<K8sGetResult> {
|
|
69
|
+
const params = new URLSearchParams();
|
|
70
|
+
params.set('resource', resource);
|
|
71
|
+
if (options?.namespace) {
|
|
72
|
+
params.set('namespace', options.namespace);
|
|
73
|
+
}
|
|
74
|
+
if (options?.name) {
|
|
75
|
+
params.set('name', options.name);
|
|
76
|
+
}
|
|
77
|
+
if (options?.output) {
|
|
78
|
+
params.set('output', options.output);
|
|
79
|
+
}
|
|
80
|
+
if (options?.labels) {
|
|
81
|
+
params.set('labels', JSON.stringify(options.labels));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const response = await this.client.get<K8sGetResult>(`/api/k8s/get?${params.toString()}`);
|
|
85
|
+
if (response.success && response.data) {
|
|
86
|
+
return response.data;
|
|
87
|
+
}
|
|
88
|
+
return { success: false, items: [], error: response.error?.message || 'Unknown error' };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Apply Kubernetes manifests
|
|
93
|
+
*/
|
|
94
|
+
async apply(
|
|
95
|
+
manifests: string | K8sResource[],
|
|
96
|
+
options?: {
|
|
97
|
+
namespace?: string;
|
|
98
|
+
dryRun?: boolean;
|
|
99
|
+
}
|
|
100
|
+
): Promise<K8sApplyResult> {
|
|
101
|
+
const response = await this.client.post<K8sApplyResult>('/api/k8s/apply', {
|
|
102
|
+
manifests,
|
|
103
|
+
...options,
|
|
104
|
+
});
|
|
105
|
+
if (response.success && response.data) {
|
|
106
|
+
return response.data;
|
|
107
|
+
}
|
|
108
|
+
return { success: false, output: '', error: response.error?.message || 'Unknown error' };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Delete Kubernetes resources
|
|
113
|
+
*/
|
|
114
|
+
async delete(
|
|
115
|
+
resource: string,
|
|
116
|
+
name: string,
|
|
117
|
+
options?: {
|
|
118
|
+
namespace?: string;
|
|
119
|
+
force?: boolean;
|
|
120
|
+
}
|
|
121
|
+
): Promise<K8sDeleteResult> {
|
|
122
|
+
const response = await this.client.post<K8sDeleteResult>('/api/k8s/delete', {
|
|
123
|
+
resource,
|
|
124
|
+
name,
|
|
125
|
+
...options,
|
|
126
|
+
});
|
|
127
|
+
if (response.success && response.data) {
|
|
128
|
+
return response.data;
|
|
129
|
+
}
|
|
130
|
+
return { success: false, output: '', error: response.error?.message || 'Unknown error' };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Get logs from a pod
|
|
135
|
+
*/
|
|
136
|
+
async logs(
|
|
137
|
+
podName: string,
|
|
138
|
+
options?: {
|
|
139
|
+
namespace?: string;
|
|
140
|
+
container?: string;
|
|
141
|
+
tail?: number;
|
|
142
|
+
since?: string;
|
|
143
|
+
follow?: boolean;
|
|
144
|
+
}
|
|
145
|
+
): Promise<K8sLogsResult> {
|
|
146
|
+
const params = new URLSearchParams();
|
|
147
|
+
params.set('pod', podName);
|
|
148
|
+
if (options?.namespace) {
|
|
149
|
+
params.set('namespace', options.namespace);
|
|
150
|
+
}
|
|
151
|
+
if (options?.container) {
|
|
152
|
+
params.set('container', options.container);
|
|
153
|
+
}
|
|
154
|
+
if (options?.tail) {
|
|
155
|
+
params.set('tail', String(options.tail));
|
|
156
|
+
}
|
|
157
|
+
if (options?.since) {
|
|
158
|
+
params.set('since', options.since);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const response = await this.client.get<K8sLogsResult>(`/api/k8s/logs?${params.toString()}`);
|
|
162
|
+
if (response.success && response.data) {
|
|
163
|
+
return response.data;
|
|
164
|
+
}
|
|
165
|
+
return { success: false, logs: '', error: response.error?.message || 'Unknown error' };
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Describe a Kubernetes resource
|
|
170
|
+
*/
|
|
171
|
+
async describe(
|
|
172
|
+
resource: string,
|
|
173
|
+
name: string,
|
|
174
|
+
options?: { namespace?: string }
|
|
175
|
+
): Promise<{ success: boolean; output: string; error?: string }> {
|
|
176
|
+
const params = new URLSearchParams();
|
|
177
|
+
params.set('resource', resource);
|
|
178
|
+
params.set('name', name);
|
|
179
|
+
if (options?.namespace) {
|
|
180
|
+
params.set('namespace', options.namespace);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const response = await this.client.get<{ success: boolean; output: string; error?: string }>(
|
|
184
|
+
`/api/k8s/describe?${params.toString()}`
|
|
185
|
+
);
|
|
186
|
+
if (response.success && response.data) {
|
|
187
|
+
return response.data;
|
|
188
|
+
}
|
|
189
|
+
return { success: false, output: '', error: response.error?.message || 'Unknown error' };
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Scale a deployment/replicaset
|
|
194
|
+
*/
|
|
195
|
+
async scale(
|
|
196
|
+
resource: string,
|
|
197
|
+
name: string,
|
|
198
|
+
replicas: number,
|
|
199
|
+
options?: { namespace?: string }
|
|
200
|
+
): Promise<{ success: boolean; output: string; error?: string }> {
|
|
201
|
+
const response = await this.client.post<{ success: boolean; output: string; error?: string }>(
|
|
202
|
+
'/api/k8s/scale',
|
|
203
|
+
{ resource, name, replicas, ...options }
|
|
204
|
+
);
|
|
205
|
+
if (response.success && response.data) {
|
|
206
|
+
return response.data;
|
|
207
|
+
}
|
|
208
|
+
return { success: false, output: '', error: response.error?.message || 'Unknown error' };
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Execute a command in a pod
|
|
213
|
+
*/
|
|
214
|
+
async exec(
|
|
215
|
+
pod: string,
|
|
216
|
+
command: string[],
|
|
217
|
+
options?: {
|
|
218
|
+
namespace?: string;
|
|
219
|
+
container?: string;
|
|
220
|
+
}
|
|
221
|
+
): Promise<{ success: boolean; output: string; error?: string }> {
|
|
222
|
+
const response = await this.client.post<{ success: boolean; output: string; error?: string }>(
|
|
223
|
+
'/api/k8s/exec',
|
|
224
|
+
{ pod, command, ...options }
|
|
225
|
+
);
|
|
226
|
+
if (response.success && response.data) {
|
|
227
|
+
return response.data;
|
|
228
|
+
}
|
|
229
|
+
return { success: false, output: '', error: response.error?.message || 'Unknown error' };
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Manage rollouts
|
|
234
|
+
*/
|
|
235
|
+
async rollout(
|
|
236
|
+
resource: string,
|
|
237
|
+
name: string,
|
|
238
|
+
action: string,
|
|
239
|
+
options?: {
|
|
240
|
+
namespace?: string;
|
|
241
|
+
revision?: number;
|
|
242
|
+
}
|
|
243
|
+
): Promise<{ success: boolean; output: string; error?: string }> {
|
|
244
|
+
const response = await this.client.post<{ success: boolean; output: string; error?: string }>(
|
|
245
|
+
'/api/k8s/rollout',
|
|
246
|
+
{ action, resource, name, ...options }
|
|
247
|
+
);
|
|
248
|
+
if (response.success && response.data) {
|
|
249
|
+
return response.data;
|
|
250
|
+
}
|
|
251
|
+
return { success: false, output: '', error: response.error?.message || 'Unknown error' };
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Get events from a namespace
|
|
256
|
+
*/
|
|
257
|
+
async events(options?: {
|
|
258
|
+
namespace?: string;
|
|
259
|
+
fieldSelector?: string;
|
|
260
|
+
}): Promise<{ success: boolean; events: Array<Record<string, string>>; error?: string }> {
|
|
261
|
+
const params = new URLSearchParams();
|
|
262
|
+
if (options?.namespace) {
|
|
263
|
+
params.set('namespace', options.namespace);
|
|
264
|
+
}
|
|
265
|
+
if (options?.fieldSelector) {
|
|
266
|
+
params.set('fieldSelector', options.fieldSelector);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const response = await this.client.get<{
|
|
270
|
+
success: boolean;
|
|
271
|
+
events: Array<Record<string, string>>;
|
|
272
|
+
error?: string;
|
|
273
|
+
}>(`/api/k8s/events?${params.toString()}`);
|
|
274
|
+
if (response.success && response.data) {
|
|
275
|
+
return response.data;
|
|
276
|
+
}
|
|
277
|
+
return { success: false, events: [], error: response.error?.message || 'Unknown error' };
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Forward local ports to a pod
|
|
282
|
+
*/
|
|
283
|
+
async portForward(
|
|
284
|
+
pod: string,
|
|
285
|
+
ports: string,
|
|
286
|
+
options?: {
|
|
287
|
+
namespace?: string;
|
|
288
|
+
kubeconfig?: string;
|
|
289
|
+
context?: string;
|
|
290
|
+
}
|
|
291
|
+
): Promise<{ success: boolean; output: string; error?: string }> {
|
|
292
|
+
const response = await this.client.post<{ success: boolean; output: string; error?: string }>(
|
|
293
|
+
'/api/k8s/port-forward',
|
|
294
|
+
{ pod, ports, ...options }
|
|
295
|
+
);
|
|
296
|
+
if (response.success && response.data) {
|
|
297
|
+
return response.data;
|
|
298
|
+
}
|
|
299
|
+
return { success: false, output: '', error: response.error?.message || 'Unknown error' };
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* List namespaces
|
|
304
|
+
*/
|
|
305
|
+
async listNamespaces(options?: {
|
|
306
|
+
kubeconfig?: string;
|
|
307
|
+
context?: string;
|
|
308
|
+
}): Promise<{ success: boolean; namespaces: string[]; error?: string }> {
|
|
309
|
+
const params = new URLSearchParams();
|
|
310
|
+
if (options?.kubeconfig) {
|
|
311
|
+
params.set('kubeconfig', options.kubeconfig);
|
|
312
|
+
}
|
|
313
|
+
if (options?.context) {
|
|
314
|
+
params.set('context', options.context);
|
|
315
|
+
}
|
|
316
|
+
const query = params.toString() ? `?${params.toString()}` : '';
|
|
317
|
+
const response = await this.client.get<{
|
|
318
|
+
success: boolean;
|
|
319
|
+
namespaces: string[];
|
|
320
|
+
error?: string;
|
|
321
|
+
}>(`/api/k8s/namespaces${query}`);
|
|
322
|
+
if (response.success && response.data) {
|
|
323
|
+
return response.data;
|
|
324
|
+
}
|
|
325
|
+
return { success: false, namespaces: [], error: response.error?.message || 'Unknown error' };
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Create a namespace
|
|
330
|
+
*/
|
|
331
|
+
async createNamespace(
|
|
332
|
+
name: string,
|
|
333
|
+
options?: {
|
|
334
|
+
kubeconfig?: string;
|
|
335
|
+
context?: string;
|
|
336
|
+
}
|
|
337
|
+
): Promise<{ success: boolean; output: string; error?: string }> {
|
|
338
|
+
const response = await this.client.post<{ success: boolean; output: string; error?: string }>(
|
|
339
|
+
'/api/k8s/namespace',
|
|
340
|
+
{ name, ...options }
|
|
341
|
+
);
|
|
342
|
+
if (response.success && response.data) {
|
|
343
|
+
return response.data;
|
|
344
|
+
}
|
|
345
|
+
return { success: false, output: '', error: response.error?.message || 'Unknown error' };
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Delete a namespace
|
|
350
|
+
*/
|
|
351
|
+
async deleteNamespace(
|
|
352
|
+
name: string,
|
|
353
|
+
options?: {
|
|
354
|
+
kubeconfig?: string;
|
|
355
|
+
context?: string;
|
|
356
|
+
}
|
|
357
|
+
): Promise<{ success: boolean; output: string; error?: string }> {
|
|
358
|
+
const response = await this.client.post<{ success: boolean; output: string; error?: string }>(
|
|
359
|
+
'/api/k8s/namespace/delete',
|
|
360
|
+
{ name, ...options }
|
|
361
|
+
);
|
|
362
|
+
if (response.success && response.data) {
|
|
363
|
+
return response.data;
|
|
364
|
+
}
|
|
365
|
+
return { success: false, output: '', error: response.error?.message || 'Unknown error' };
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Get top resource usage for pods or nodes
|
|
370
|
+
*/
|
|
371
|
+
async top(
|
|
372
|
+
resourceType: 'pods' | 'nodes',
|
|
373
|
+
options?: {
|
|
374
|
+
namespace?: string;
|
|
375
|
+
kubeconfig?: string;
|
|
376
|
+
context?: string;
|
|
377
|
+
}
|
|
378
|
+
): Promise<{
|
|
379
|
+
success: boolean;
|
|
380
|
+
output: string;
|
|
381
|
+
items: Array<Record<string, string>>;
|
|
382
|
+
error?: string;
|
|
383
|
+
}> {
|
|
384
|
+
const params = new URLSearchParams();
|
|
385
|
+
if (options?.namespace) {
|
|
386
|
+
params.set('namespace', options.namespace);
|
|
387
|
+
}
|
|
388
|
+
if (options?.kubeconfig) {
|
|
389
|
+
params.set('kubeconfig', options.kubeconfig);
|
|
390
|
+
}
|
|
391
|
+
if (options?.context) {
|
|
392
|
+
params.set('context', options.context);
|
|
393
|
+
}
|
|
394
|
+
const query = params.toString() ? `?${params.toString()}` : '';
|
|
395
|
+
const response = await this.client.get<{
|
|
396
|
+
success: boolean;
|
|
397
|
+
output: string;
|
|
398
|
+
items: Array<Record<string, string>>;
|
|
399
|
+
error?: string;
|
|
400
|
+
}>(`/api/k8s/top/${resourceType}${query}`);
|
|
401
|
+
if (response.success && response.data) {
|
|
402
|
+
return response.data;
|
|
403
|
+
}
|
|
404
|
+
return {
|
|
405
|
+
success: false,
|
|
406
|
+
output: '',
|
|
407
|
+
items: [],
|
|
408
|
+
error: response.error?.message || 'Unknown error',
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Patch a Kubernetes resource
|
|
414
|
+
*/
|
|
415
|
+
async patch(
|
|
416
|
+
resource: string,
|
|
417
|
+
name: string,
|
|
418
|
+
patch: string,
|
|
419
|
+
options?: {
|
|
420
|
+
namespace?: string;
|
|
421
|
+
type?: 'strategic' | 'merge' | 'json';
|
|
422
|
+
kubeconfig?: string;
|
|
423
|
+
context?: string;
|
|
424
|
+
}
|
|
425
|
+
): Promise<{ success: boolean; output: string; error?: string }> {
|
|
426
|
+
const response = await this.client.post<{ success: boolean; output: string; error?: string }>(
|
|
427
|
+
'/api/k8s/patch',
|
|
428
|
+
{ resource, name, patch, ...options }
|
|
429
|
+
);
|
|
430
|
+
if (response.success && response.data) {
|
|
431
|
+
return response.data;
|
|
432
|
+
}
|
|
433
|
+
return { success: false, output: '', error: response.error?.message || 'Unknown error' };
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Label a Kubernetes resource
|
|
438
|
+
*/
|
|
439
|
+
async label(
|
|
440
|
+
resource: string,
|
|
441
|
+
name: string,
|
|
442
|
+
labels: Record<string, string>,
|
|
443
|
+
options?: {
|
|
444
|
+
namespace?: string;
|
|
445
|
+
overwrite?: boolean;
|
|
446
|
+
kubeconfig?: string;
|
|
447
|
+
context?: string;
|
|
448
|
+
}
|
|
449
|
+
): Promise<{ success: boolean; output: string; error?: string }> {
|
|
450
|
+
const response = await this.client.post<{ success: boolean; output: string; error?: string }>(
|
|
451
|
+
'/api/k8s/label',
|
|
452
|
+
{ resource, name, labels, ...options }
|
|
453
|
+
);
|
|
454
|
+
if (response.success && response.data) {
|
|
455
|
+
return response.data;
|
|
456
|
+
}
|
|
457
|
+
return { success: false, output: '', error: response.error?.message || 'Unknown error' };
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Annotate a Kubernetes resource
|
|
462
|
+
*/
|
|
463
|
+
async annotate(
|
|
464
|
+
resource: string,
|
|
465
|
+
name: string,
|
|
466
|
+
annotations: Record<string, string>,
|
|
467
|
+
options?: {
|
|
468
|
+
namespace?: string;
|
|
469
|
+
overwrite?: boolean;
|
|
470
|
+
kubeconfig?: string;
|
|
471
|
+
context?: string;
|
|
472
|
+
}
|
|
473
|
+
): Promise<{ success: boolean; output: string; error?: string }> {
|
|
474
|
+
const response = await this.client.post<{ success: boolean; output: string; error?: string }>(
|
|
475
|
+
'/api/k8s/annotate',
|
|
476
|
+
{ resource, name, annotations, ...options }
|
|
477
|
+
);
|
|
478
|
+
if (response.success && response.data) {
|
|
479
|
+
return response.data;
|
|
480
|
+
}
|
|
481
|
+
return { success: false, output: '', error: response.error?.message || 'Unknown error' };
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* Check if service is available
|
|
486
|
+
*/
|
|
487
|
+
async isAvailable(): Promise<boolean> {
|
|
488
|
+
try {
|
|
489
|
+
const response = await this.client.get<{ status: string }>('/health');
|
|
490
|
+
return response.success && response.data?.status === 'healthy';
|
|
491
|
+
} catch {
|
|
492
|
+
return false;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
export const k8sClient = new K8sClient();
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM Client
|
|
3
|
+
*
|
|
4
|
+
* WebSocket client for streaming LLM responses from the LLM Service
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { WebSocketClient, WebSocketURLs } from '.';
|
|
8
|
+
|
|
9
|
+
export interface ChatMessage {
|
|
10
|
+
role: 'user' | 'assistant' | 'system';
|
|
11
|
+
content: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface StreamingChunk {
|
|
15
|
+
type: 'content' | 'tool_calls' | 'done' | 'error';
|
|
16
|
+
content?: string;
|
|
17
|
+
toolCalls?: any[];
|
|
18
|
+
done?: boolean;
|
|
19
|
+
tokenCount?: number;
|
|
20
|
+
error?: string;
|
|
21
|
+
message?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface ChatOptions {
|
|
25
|
+
model?: string;
|
|
26
|
+
taskType?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* LLM Client for streaming chat completions
|
|
31
|
+
*/
|
|
32
|
+
export class LLMClient {
|
|
33
|
+
private wsUrl: string;
|
|
34
|
+
|
|
35
|
+
constructor(wsUrl?: string) {
|
|
36
|
+
this.wsUrl = wsUrl || WebSocketURLs.LLM;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Stream a chat completion
|
|
41
|
+
* @param messages - Array of chat messages
|
|
42
|
+
* @param options - Chat options (model, taskType)
|
|
43
|
+
* @returns AsyncGenerator yielding StreamingChunk objects
|
|
44
|
+
*/
|
|
45
|
+
async *streamChat(
|
|
46
|
+
messages: ChatMessage[],
|
|
47
|
+
options: ChatOptions = {}
|
|
48
|
+
): AsyncGenerator<StreamingChunk> {
|
|
49
|
+
const ws = new WebSocketClient(this.wsUrl, {
|
|
50
|
+
reconnect: false, // Don't reconnect for single requests
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const messageQueue: StreamingChunk[] = [];
|
|
54
|
+
let done = false;
|
|
55
|
+
let error: Error | null = null;
|
|
56
|
+
let resolveWaiting: (() => void) | null = null;
|
|
57
|
+
|
|
58
|
+
// Set up message handler
|
|
59
|
+
const removeMessageHandler = ws.onMessage((data: StreamingChunk) => {
|
|
60
|
+
messageQueue.push(data);
|
|
61
|
+
|
|
62
|
+
if (data.type === 'done' || data.type === 'error') {
|
|
63
|
+
done = true;
|
|
64
|
+
if (data.type === 'error') {
|
|
65
|
+
error = new Error(data.message || data.error || 'Unknown error');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Wake up the generator if it's waiting
|
|
70
|
+
if (resolveWaiting) {
|
|
71
|
+
resolveWaiting();
|
|
72
|
+
resolveWaiting = null;
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const removeErrorHandler = ws.onError(() => {
|
|
77
|
+
error = new Error('WebSocket connection failed');
|
|
78
|
+
done = true;
|
|
79
|
+
if (resolveWaiting) {
|
|
80
|
+
resolveWaiting();
|
|
81
|
+
resolveWaiting = null;
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const removeCloseHandler = ws.onClose(() => {
|
|
86
|
+
done = true;
|
|
87
|
+
if (resolveWaiting) {
|
|
88
|
+
resolveWaiting();
|
|
89
|
+
resolveWaiting = null;
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
// Connect to WebSocket
|
|
95
|
+
await ws.connect();
|
|
96
|
+
|
|
97
|
+
// Send the chat request
|
|
98
|
+
ws.send({
|
|
99
|
+
messages,
|
|
100
|
+
model: options.model,
|
|
101
|
+
taskType: options.taskType,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// Yield chunks as they arrive
|
|
105
|
+
while (!done || messageQueue.length > 0) {
|
|
106
|
+
if (messageQueue.length > 0) {
|
|
107
|
+
const chunk = messageQueue.shift()!;
|
|
108
|
+
yield chunk;
|
|
109
|
+
} else if (!done) {
|
|
110
|
+
// Wait for more messages
|
|
111
|
+
await new Promise<void>(resolve => {
|
|
112
|
+
resolveWaiting = resolve;
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (error) {
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
} finally {
|
|
121
|
+
// Clean up
|
|
122
|
+
removeMessageHandler();
|
|
123
|
+
removeErrorHandler();
|
|
124
|
+
removeCloseHandler();
|
|
125
|
+
ws.close();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Send a single chat message and get streaming response
|
|
131
|
+
* Convenience method that builds the messages array
|
|
132
|
+
*/
|
|
133
|
+
async *chat(
|
|
134
|
+
userMessage: string,
|
|
135
|
+
history: ChatMessage[] = [],
|
|
136
|
+
options: ChatOptions = {}
|
|
137
|
+
): AsyncGenerator<StreamingChunk> {
|
|
138
|
+
const messages: ChatMessage[] = [...history, { role: 'user', content: userMessage }];
|
|
139
|
+
|
|
140
|
+
yield* this.streamChat(messages, options);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Check if LLM service is available
|
|
145
|
+
*/
|
|
146
|
+
async isAvailable(): Promise<boolean> {
|
|
147
|
+
try {
|
|
148
|
+
// Use HTTP health check endpoint
|
|
149
|
+
const httpUrl = this.wsUrl.replace('ws://', 'http://').replace('wss://', 'https://');
|
|
150
|
+
const response = await fetch(`${httpUrl}/health`, {
|
|
151
|
+
signal: AbortSignal.timeout(5000),
|
|
152
|
+
});
|
|
153
|
+
return response.ok;
|
|
154
|
+
} catch {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Export singleton instance
|
|
161
|
+
export const llmClient = new LLMClient();
|