@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,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core Engine Client
|
|
3
|
+
*
|
|
4
|
+
* Client for interacting with the Core Engine Service
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { DriftReport, DriftRemediationResult, DriftProvider } from '../types';
|
|
8
|
+
|
|
9
|
+
export interface DriftDetectParams {
|
|
10
|
+
provider: DriftProvider;
|
|
11
|
+
directory: string;
|
|
12
|
+
namespace?: string;
|
|
13
|
+
release?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface DriftFixParams {
|
|
17
|
+
provider: DriftProvider;
|
|
18
|
+
directory: string;
|
|
19
|
+
dryRun?: boolean;
|
|
20
|
+
namespace?: string;
|
|
21
|
+
release?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface RollbackParams {
|
|
25
|
+
taskId: string;
|
|
26
|
+
force?: boolean;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface RollbackResult {
|
|
30
|
+
success: boolean;
|
|
31
|
+
message: string;
|
|
32
|
+
details?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface ResumeResult {
|
|
36
|
+
success: boolean;
|
|
37
|
+
data?: any;
|
|
38
|
+
error?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export class CoreEngineClient {
|
|
42
|
+
private baseUrl: string;
|
|
43
|
+
|
|
44
|
+
constructor(baseUrl?: string) {
|
|
45
|
+
this.baseUrl = baseUrl || process.env.CORE_ENGINE_URL || 'http://localhost:3010';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Detect drift in infrastructure
|
|
50
|
+
*/
|
|
51
|
+
async detectDrift(params: DriftDetectParams): Promise<DriftReport> {
|
|
52
|
+
const response = await fetch(`${this.baseUrl}/api/drift/detect`, {
|
|
53
|
+
method: 'POST',
|
|
54
|
+
headers: {
|
|
55
|
+
'Content-Type': 'application/json',
|
|
56
|
+
},
|
|
57
|
+
body: JSON.stringify(params),
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
if (!response.ok) {
|
|
61
|
+
const error = (await response.json().catch(() => ({ message: 'Unknown error' }))) as {
|
|
62
|
+
message?: string;
|
|
63
|
+
};
|
|
64
|
+
throw new Error(error.message || `Failed to detect drift: ${response.status}`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const data = (await response.json()) as { report: DriftReport };
|
|
68
|
+
return data.report;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Create a remediation plan for detected drift
|
|
73
|
+
*/
|
|
74
|
+
async createRemediationPlan(params: DriftDetectParams): Promise<any> {
|
|
75
|
+
const response = await fetch(`${this.baseUrl}/api/drift/plan`, {
|
|
76
|
+
method: 'POST',
|
|
77
|
+
headers: {
|
|
78
|
+
'Content-Type': 'application/json',
|
|
79
|
+
},
|
|
80
|
+
body: JSON.stringify(params),
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
if (!response.ok) {
|
|
84
|
+
const error = (await response.json().catch(() => ({ message: 'Unknown error' }))) as {
|
|
85
|
+
message?: string;
|
|
86
|
+
};
|
|
87
|
+
throw new Error(error.message || `Failed to create remediation plan: ${response.status}`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return response.json() as Promise<any>;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Fix detected drift
|
|
95
|
+
*/
|
|
96
|
+
async fixDrift(params: DriftFixParams): Promise<DriftRemediationResult> {
|
|
97
|
+
const response = await fetch(`${this.baseUrl}/api/drift/fix`, {
|
|
98
|
+
method: 'POST',
|
|
99
|
+
headers: {
|
|
100
|
+
'Content-Type': 'application/json',
|
|
101
|
+
},
|
|
102
|
+
body: JSON.stringify(params),
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
if (!response.ok) {
|
|
106
|
+
const error = (await response.json().catch(() => ({ message: 'Unknown error' }))) as {
|
|
107
|
+
message?: string;
|
|
108
|
+
};
|
|
109
|
+
throw new Error(error.message || `Failed to fix drift: ${response.status}`);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const data = (await response.json()) as { result: DriftRemediationResult };
|
|
113
|
+
return data.result;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Check if a task can be rolled back
|
|
118
|
+
*/
|
|
119
|
+
async canRollback(taskId: string): Promise<boolean> {
|
|
120
|
+
const response = await fetch(`${this.baseUrl}/api/tasks/${taskId}/rollback/check`, {
|
|
121
|
+
method: 'GET',
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
if (!response.ok) {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const data = (await response.json()) as { canRollback: boolean };
|
|
129
|
+
return data.canRollback;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Rollback a task
|
|
134
|
+
*/
|
|
135
|
+
async rollback(params: RollbackParams): Promise<RollbackResult> {
|
|
136
|
+
const response = await fetch(`${this.baseUrl}/api/tasks/${params.taskId}/rollback`, {
|
|
137
|
+
method: 'POST',
|
|
138
|
+
headers: {
|
|
139
|
+
'Content-Type': 'application/json',
|
|
140
|
+
},
|
|
141
|
+
body: JSON.stringify({ force: params.force }),
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
if (!response.ok) {
|
|
145
|
+
const error = (await response.json().catch(() => ({ message: 'Unknown error' }))) as {
|
|
146
|
+
message?: string;
|
|
147
|
+
};
|
|
148
|
+
throw new Error(error.message || `Failed to rollback: ${response.status}`);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return response.json() as Promise<RollbackResult>;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Resume a task from its last checkpoint
|
|
156
|
+
*/
|
|
157
|
+
async resumeTask(taskId: string): Promise<ResumeResult> {
|
|
158
|
+
const response = await fetch(`${this.baseUrl}/api/tasks/${taskId}/resume`, {
|
|
159
|
+
method: 'POST',
|
|
160
|
+
headers: {
|
|
161
|
+
'Content-Type': 'application/json',
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
if (!response.ok) {
|
|
166
|
+
const error = (await response.json().catch(() => ({ message: 'Unknown error' }))) as {
|
|
167
|
+
error?: string;
|
|
168
|
+
message?: string;
|
|
169
|
+
};
|
|
170
|
+
return {
|
|
171
|
+
success: false,
|
|
172
|
+
error: error.error || error.message || `Failed to resume task: ${response.status}`,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const data = (await response.json()) as { success: boolean; data?: any; error?: string };
|
|
177
|
+
return {
|
|
178
|
+
success: data.success,
|
|
179
|
+
data: data.data,
|
|
180
|
+
error: data.error,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Get compliance report
|
|
186
|
+
*/
|
|
187
|
+
async getComplianceReport(params: DriftDetectParams): Promise<any> {
|
|
188
|
+
const response = await fetch(`${this.baseUrl}/api/drift/compliance`, {
|
|
189
|
+
method: 'POST',
|
|
190
|
+
headers: {
|
|
191
|
+
'Content-Type': 'application/json',
|
|
192
|
+
},
|
|
193
|
+
body: JSON.stringify(params),
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
if (!response.ok) {
|
|
197
|
+
const error = (await response.json().catch(() => ({ message: 'Unknown error' }))) as {
|
|
198
|
+
message?: string;
|
|
199
|
+
};
|
|
200
|
+
throw new Error(error.message || `Failed to get compliance report: ${response.status}`);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return response.json() as Promise<any>;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Check if the Core Engine service is available
|
|
208
|
+
*/
|
|
209
|
+
async isAvailable(): Promise<boolean> {
|
|
210
|
+
try {
|
|
211
|
+
const response = await fetch(`${this.baseUrl}/health`, {
|
|
212
|
+
method: 'GET',
|
|
213
|
+
signal: AbortSignal.timeout(5000),
|
|
214
|
+
});
|
|
215
|
+
return response.ok;
|
|
216
|
+
} catch {
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Health check (alias for isAvailable)
|
|
223
|
+
*/
|
|
224
|
+
async healthCheck(): Promise<boolean> {
|
|
225
|
+
return this.isAvailable();
|
|
226
|
+
}
|
|
227
|
+
}
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enterprise API Clients
|
|
3
|
+
* Clients for auth, team, billing, and audit services
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { RestClient, ServiceURLs } from '.';
|
|
7
|
+
import { logger } from '../utils';
|
|
8
|
+
import type {
|
|
9
|
+
DeviceCodeResponse,
|
|
10
|
+
DevicePollResponse,
|
|
11
|
+
TokenValidateResponse,
|
|
12
|
+
Team,
|
|
13
|
+
TeamMember,
|
|
14
|
+
CreateTeamRequest,
|
|
15
|
+
InviteMemberRequest,
|
|
16
|
+
BillingStatus,
|
|
17
|
+
SubscribeRequest,
|
|
18
|
+
Invoice,
|
|
19
|
+
UsageSummary,
|
|
20
|
+
AuditLog,
|
|
21
|
+
AuditLogQuery,
|
|
22
|
+
CreateAuditLogRequest,
|
|
23
|
+
} from '../types';
|
|
24
|
+
|
|
25
|
+
// ==================== Auth Client ====================
|
|
26
|
+
|
|
27
|
+
export class AuthClient {
|
|
28
|
+
private client: RestClient;
|
|
29
|
+
|
|
30
|
+
constructor() {
|
|
31
|
+
this.client = new RestClient(ServiceURLs.AUTH);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async initiateDeviceFlow(): Promise<DeviceCodeResponse> {
|
|
35
|
+
const response = await this.client.post<DeviceCodeResponse>('/api/auth/device/initiate');
|
|
36
|
+
if (!response.success || !response.data) {
|
|
37
|
+
throw new Error(response.error?.message || 'Failed to initiate device flow');
|
|
38
|
+
}
|
|
39
|
+
return response.data;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async pollDeviceCode(deviceCode: string): Promise<DevicePollResponse> {
|
|
43
|
+
const response = await this.client.get<DevicePollResponse>(
|
|
44
|
+
`/api/auth/device/poll/${deviceCode}`
|
|
45
|
+
);
|
|
46
|
+
if (!response.success || !response.data) {
|
|
47
|
+
throw new Error(response.error?.message || 'Failed to poll device code');
|
|
48
|
+
}
|
|
49
|
+
return response.data;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async verifyDeviceCode(userCode: string, userId: string): Promise<boolean> {
|
|
53
|
+
const response = await this.client.post<{ verified: boolean }>('/api/auth/device/verify', {
|
|
54
|
+
userCode,
|
|
55
|
+
userId,
|
|
56
|
+
});
|
|
57
|
+
return response.success && response.data?.verified === true;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async validateToken(accessToken: string): Promise<TokenValidateResponse> {
|
|
61
|
+
const response = await this.client.post<TokenValidateResponse>('/api/auth/token/validate', {
|
|
62
|
+
accessToken,
|
|
63
|
+
});
|
|
64
|
+
if (!response.success || !response.data) {
|
|
65
|
+
return { valid: false };
|
|
66
|
+
}
|
|
67
|
+
return response.data;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// ==================== Team Client ====================
|
|
72
|
+
|
|
73
|
+
export class TeamClient {
|
|
74
|
+
private client: RestClient;
|
|
75
|
+
|
|
76
|
+
constructor() {
|
|
77
|
+
this.client = new RestClient(ServiceURLs.TEAM);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async createTeam(request: CreateTeamRequest): Promise<Team> {
|
|
81
|
+
const response = await this.client.post<Team>('/api/team/teams', request);
|
|
82
|
+
if (!response.success || !response.data) {
|
|
83
|
+
throw new Error(response.error?.message || 'Failed to create team');
|
|
84
|
+
}
|
|
85
|
+
return response.data;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async getTeam(teamId: string): Promise<Team | null> {
|
|
89
|
+
const response = await this.client.get<Team>(`/api/team/teams/${teamId}`);
|
|
90
|
+
if (!response.success) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
return response.data || null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async listTeams(userId: string): Promise<Team[]> {
|
|
97
|
+
const response = await this.client.get<Team[]>(`/api/team/teams?userId=${userId}`);
|
|
98
|
+
if (!response.success || !response.data) {
|
|
99
|
+
logger.warn('Failed to list teams; returning empty list', {
|
|
100
|
+
userId,
|
|
101
|
+
error: response.error?.message,
|
|
102
|
+
});
|
|
103
|
+
return [];
|
|
104
|
+
}
|
|
105
|
+
return response.data;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async deleteTeam(teamId: string): Promise<void> {
|
|
109
|
+
const response = await this.client.delete(`/api/team/teams/${teamId}`);
|
|
110
|
+
if (!response.success) {
|
|
111
|
+
throw new Error(response.error?.message || 'Failed to delete team');
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async inviteMember(teamId: string, request: InviteMemberRequest): Promise<TeamMember> {
|
|
116
|
+
const response = await this.client.post<TeamMember>(
|
|
117
|
+
`/api/team/teams/${teamId}/members`,
|
|
118
|
+
request
|
|
119
|
+
);
|
|
120
|
+
if (!response.success || !response.data) {
|
|
121
|
+
throw new Error(response.error?.message || 'Failed to invite member');
|
|
122
|
+
}
|
|
123
|
+
return response.data;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async listMembers(teamId: string): Promise<TeamMember[]> {
|
|
127
|
+
const response = await this.client.get<TeamMember[]>(`/api/team/teams/${teamId}/members`);
|
|
128
|
+
if (!response.success || !response.data) {
|
|
129
|
+
logger.warn('Failed to list team members; returning empty list', {
|
|
130
|
+
teamId,
|
|
131
|
+
error: response.error?.message,
|
|
132
|
+
});
|
|
133
|
+
return [];
|
|
134
|
+
}
|
|
135
|
+
return response.data;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async removeMember(teamId: string, userId: string): Promise<void> {
|
|
139
|
+
const response = await this.client.delete(`/api/team/teams/${teamId}/members/${userId}`);
|
|
140
|
+
if (!response.success) {
|
|
141
|
+
throw new Error(response.error?.message || 'Failed to remove member');
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async updateMemberRole(teamId: string, userId: string, role: string): Promise<TeamMember> {
|
|
146
|
+
const response = await this.client.put<TeamMember>(
|
|
147
|
+
`/api/team/teams/${teamId}/members/${userId}`,
|
|
148
|
+
{ role }
|
|
149
|
+
);
|
|
150
|
+
if (!response.success || !response.data) {
|
|
151
|
+
throw new Error(response.error?.message || 'Failed to update member role');
|
|
152
|
+
}
|
|
153
|
+
return response.data;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// ==================== Billing Client ====================
|
|
158
|
+
|
|
159
|
+
export class BillingClient {
|
|
160
|
+
private client: RestClient;
|
|
161
|
+
|
|
162
|
+
constructor() {
|
|
163
|
+
this.client = new RestClient(ServiceURLs.BILLING);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
async getStatus(teamId: string): Promise<BillingStatus> {
|
|
167
|
+
const response = await this.client.get<BillingStatus>(`/api/billing/status?teamId=${teamId}`);
|
|
168
|
+
if (!response.success || !response.data) {
|
|
169
|
+
throw new Error(response.error?.message || 'Failed to get billing status');
|
|
170
|
+
}
|
|
171
|
+
return response.data;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
async subscribe(teamId: string, request: SubscribeRequest): Promise<BillingStatus> {
|
|
175
|
+
const response = await this.client.post<BillingStatus>('/api/billing/subscribe', {
|
|
176
|
+
...request,
|
|
177
|
+
teamId,
|
|
178
|
+
});
|
|
179
|
+
if (!response.success || !response.data) {
|
|
180
|
+
throw new Error(response.error?.message || 'Failed to subscribe');
|
|
181
|
+
}
|
|
182
|
+
return response.data;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async cancel(teamId: string): Promise<BillingStatus> {
|
|
186
|
+
const response = await this.client.post<BillingStatus>('/api/billing/cancel', { teamId });
|
|
187
|
+
if (!response.success || !response.data) {
|
|
188
|
+
throw new Error(response.error?.message || 'Failed to cancel subscription');
|
|
189
|
+
}
|
|
190
|
+
return response.data;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async getUsage(
|
|
194
|
+
teamId: string,
|
|
195
|
+
period: 'day' | 'week' | 'month' = 'month'
|
|
196
|
+
): Promise<UsageSummary> {
|
|
197
|
+
const response = await this.client.get<UsageSummary>(
|
|
198
|
+
`/api/billing/usage?teamId=${teamId}&period=${period}`
|
|
199
|
+
);
|
|
200
|
+
if (!response.success || !response.data) {
|
|
201
|
+
throw new Error(response.error?.message || 'Failed to get usage');
|
|
202
|
+
}
|
|
203
|
+
return response.data;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
async getInvoices(teamId: string, limit: number = 10): Promise<Invoice[]> {
|
|
207
|
+
const response = await this.client.get<Invoice[]>(
|
|
208
|
+
`/api/billing/invoices?teamId=${teamId}&limit=${limit}`
|
|
209
|
+
);
|
|
210
|
+
if (!response.success || !response.data) {
|
|
211
|
+
logger.warn('Failed to fetch invoices; returning empty list', {
|
|
212
|
+
teamId,
|
|
213
|
+
error: response.error?.message,
|
|
214
|
+
});
|
|
215
|
+
return [];
|
|
216
|
+
}
|
|
217
|
+
return response.data;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
async recordUsage(
|
|
221
|
+
teamId: string,
|
|
222
|
+
operationType: string,
|
|
223
|
+
tokensUsed: number,
|
|
224
|
+
costUsd: number,
|
|
225
|
+
userId?: string
|
|
226
|
+
): Promise<void> {
|
|
227
|
+
await this.client.post('/api/billing/usage', {
|
|
228
|
+
teamId,
|
|
229
|
+
userId,
|
|
230
|
+
operationType,
|
|
231
|
+
tokensUsed,
|
|
232
|
+
costUsd,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// ==================== Audit Client ====================
|
|
238
|
+
|
|
239
|
+
export class AuditClient {
|
|
240
|
+
private client: RestClient;
|
|
241
|
+
|
|
242
|
+
constructor() {
|
|
243
|
+
this.client = new RestClient(ServiceURLs.AUDIT);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
async createLog(request: CreateAuditLogRequest): Promise<AuditLog> {
|
|
247
|
+
const response = await this.client.post<AuditLog>('/api/audit/logs', request);
|
|
248
|
+
if (!response.success || !response.data) {
|
|
249
|
+
throw new Error(response.error?.message || 'Failed to create audit log');
|
|
250
|
+
}
|
|
251
|
+
return response.data;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
async queryLogs(query: AuditLogQuery = {}): Promise<{
|
|
255
|
+
logs: AuditLog[];
|
|
256
|
+
total: number;
|
|
257
|
+
limit: number;
|
|
258
|
+
offset: number;
|
|
259
|
+
}> {
|
|
260
|
+
const params = new URLSearchParams();
|
|
261
|
+
if (query.teamId) {
|
|
262
|
+
params.set('teamId', query.teamId);
|
|
263
|
+
}
|
|
264
|
+
if (query.userId) {
|
|
265
|
+
params.set('userId', query.userId);
|
|
266
|
+
}
|
|
267
|
+
if (query.action) {
|
|
268
|
+
params.set('action', query.action);
|
|
269
|
+
}
|
|
270
|
+
if (query.status) {
|
|
271
|
+
params.set('status', query.status);
|
|
272
|
+
}
|
|
273
|
+
if (query.since) {
|
|
274
|
+
params.set('since', query.since);
|
|
275
|
+
}
|
|
276
|
+
if (query.until) {
|
|
277
|
+
params.set('until', query.until);
|
|
278
|
+
}
|
|
279
|
+
if (query.limit) {
|
|
280
|
+
params.set('limit', query.limit.toString());
|
|
281
|
+
}
|
|
282
|
+
if (query.offset) {
|
|
283
|
+
params.set('offset', query.offset.toString());
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const response = await this.client.get<{
|
|
287
|
+
logs: AuditLog[];
|
|
288
|
+
total: number;
|
|
289
|
+
limit: number;
|
|
290
|
+
offset: number;
|
|
291
|
+
}>(`/api/audit/logs?${params}`);
|
|
292
|
+
|
|
293
|
+
if (!response.success || !response.data) {
|
|
294
|
+
return { logs: [], total: 0, limit: 100, offset: 0 };
|
|
295
|
+
}
|
|
296
|
+
return response.data;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
async exportLogs(format: 'csv' | 'json', query: Partial<AuditLogQuery> = {}): Promise<string> {
|
|
300
|
+
const params = new URLSearchParams();
|
|
301
|
+
params.set('format', format);
|
|
302
|
+
if (query.teamId) {
|
|
303
|
+
params.set('teamId', query.teamId);
|
|
304
|
+
}
|
|
305
|
+
if (query.userId) {
|
|
306
|
+
params.set('userId', query.userId);
|
|
307
|
+
}
|
|
308
|
+
if (query.action) {
|
|
309
|
+
params.set('action', query.action);
|
|
310
|
+
}
|
|
311
|
+
if (query.since) {
|
|
312
|
+
params.set('since', query.since);
|
|
313
|
+
}
|
|
314
|
+
if (query.until) {
|
|
315
|
+
params.set('until', query.until);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const url = `${ServiceURLs.AUDIT}/api/audit/export?${params}`;
|
|
319
|
+
const response = await fetch(url);
|
|
320
|
+
|
|
321
|
+
if (!response.ok) {
|
|
322
|
+
throw new Error('Failed to export audit logs');
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
return response.text();
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// ==================== Singleton Instances ====================
|
|
330
|
+
|
|
331
|
+
export const authClient = new AuthClient();
|
|
332
|
+
export const teamClient = new TeamClient();
|
|
333
|
+
export const billingClient = new BillingClient();
|
|
334
|
+
export const auditClient = new AuditClient();
|