@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,743 @@
|
|
|
1
|
+
import { logger } from '../utils';
|
|
2
|
+
import type { AgentTask, AgentPlan } from './planner';
|
|
3
|
+
|
|
4
|
+
// ==========================================
|
|
5
|
+
// Safety Check Types (inline — no HTTP)
|
|
6
|
+
// ==========================================
|
|
7
|
+
|
|
8
|
+
export interface SafetyCheckResult {
|
|
9
|
+
passed: boolean;
|
|
10
|
+
severity: 'low' | 'medium' | 'high' | 'critical';
|
|
11
|
+
message: string;
|
|
12
|
+
details?: Record<string, unknown>;
|
|
13
|
+
can_proceed: boolean;
|
|
14
|
+
requires_approval: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface SafetyCheck {
|
|
18
|
+
id: string;
|
|
19
|
+
type: 'pre_execution' | 'during_execution' | 'post_execution';
|
|
20
|
+
category: 'security' | 'cost' | 'availability' | 'compliance';
|
|
21
|
+
name: string;
|
|
22
|
+
description: string;
|
|
23
|
+
severity: 'low' | 'medium' | 'high' | 'critical';
|
|
24
|
+
check: (context: Record<string, unknown>) => Promise<SafetyCheckResult>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// ==========================================
|
|
28
|
+
// SafetyManager
|
|
29
|
+
// ==========================================
|
|
30
|
+
|
|
31
|
+
export class SafetyManager {
|
|
32
|
+
private checks: Map<string, SafetyCheck>;
|
|
33
|
+
|
|
34
|
+
constructor() {
|
|
35
|
+
this.checks = new Map();
|
|
36
|
+
this.initializeDefaultChecks();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Run pre-execution safety checks
|
|
41
|
+
*/
|
|
42
|
+
async runPreExecutionChecks(
|
|
43
|
+
task: AgentTask,
|
|
44
|
+
plan: AgentPlan
|
|
45
|
+
): Promise<{ passed: boolean; results: SafetyCheckResult[]; blockers: SafetyCheckResult[] }> {
|
|
46
|
+
logger.info(`Running pre-execution safety checks for task: ${task.id}`);
|
|
47
|
+
|
|
48
|
+
const preExecutionChecks = Array.from(this.checks.values()).filter(
|
|
49
|
+
check => check.type === 'pre_execution'
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const results: SafetyCheckResult[] = [];
|
|
53
|
+
const context = {
|
|
54
|
+
task,
|
|
55
|
+
plan,
|
|
56
|
+
environment: task.context.environment,
|
|
57
|
+
provider: task.context.provider,
|
|
58
|
+
components: task.context.components,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
for (const check of preExecutionChecks) {
|
|
62
|
+
try {
|
|
63
|
+
const result = await check.check(context);
|
|
64
|
+
results.push(result);
|
|
65
|
+
|
|
66
|
+
logger.info(
|
|
67
|
+
`Safety check ${check.id}: ${result.passed ? 'PASSED' : 'FAILED'} (${check.name})`
|
|
68
|
+
);
|
|
69
|
+
} catch (error) {
|
|
70
|
+
logger.error(`Error running safety check ${check.id}`, error);
|
|
71
|
+
results.push({
|
|
72
|
+
passed: false,
|
|
73
|
+
severity: 'high',
|
|
74
|
+
message: `Check failed with error: ${(error as Error).message}`,
|
|
75
|
+
can_proceed: false,
|
|
76
|
+
requires_approval: true,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Identify blockers (failed checks that prevent execution)
|
|
82
|
+
const blockers = results.filter(r => !r.passed && !r.can_proceed);
|
|
83
|
+
|
|
84
|
+
const passed = blockers.length === 0;
|
|
85
|
+
|
|
86
|
+
logger.info(
|
|
87
|
+
`Pre-execution checks: ${results.length} total, ${results.filter(r => r.passed).length} passed, ${blockers.length} blockers`
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
return { passed, results, blockers };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Run during-execution safety checks
|
|
95
|
+
*/
|
|
96
|
+
async runDuringExecutionChecks(
|
|
97
|
+
context: Record<string, unknown>
|
|
98
|
+
): Promise<{ passed: boolean; results: SafetyCheckResult[] }> {
|
|
99
|
+
logger.info('Running during-execution safety checks');
|
|
100
|
+
|
|
101
|
+
const duringExecutionChecks = Array.from(this.checks.values()).filter(
|
|
102
|
+
check => check.type === 'during_execution'
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
const results: SafetyCheckResult[] = [];
|
|
106
|
+
|
|
107
|
+
for (const check of duringExecutionChecks) {
|
|
108
|
+
try {
|
|
109
|
+
const result = await check.check(context);
|
|
110
|
+
results.push(result);
|
|
111
|
+
} catch (error) {
|
|
112
|
+
logger.error(`Error running safety check ${check.id}`, error);
|
|
113
|
+
results.push({
|
|
114
|
+
passed: false,
|
|
115
|
+
severity: 'high',
|
|
116
|
+
message: `Check failed with error: ${(error as Error).message}`,
|
|
117
|
+
can_proceed: false,
|
|
118
|
+
requires_approval: true,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const passed = results.every(r => r.passed || r.can_proceed);
|
|
124
|
+
|
|
125
|
+
return { passed, results };
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Run post-execution safety checks
|
|
130
|
+
*/
|
|
131
|
+
async runPostExecutionChecks(
|
|
132
|
+
context: Record<string, unknown>
|
|
133
|
+
): Promise<{ passed: boolean; results: SafetyCheckResult[] }> {
|
|
134
|
+
logger.info('Running post-execution safety checks');
|
|
135
|
+
|
|
136
|
+
const postExecutionChecks = Array.from(this.checks.values()).filter(
|
|
137
|
+
check => check.type === 'post_execution'
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
const results: SafetyCheckResult[] = [];
|
|
141
|
+
|
|
142
|
+
for (const check of postExecutionChecks) {
|
|
143
|
+
try {
|
|
144
|
+
const result = await check.check(context);
|
|
145
|
+
results.push(result);
|
|
146
|
+
} catch (error) {
|
|
147
|
+
logger.error(`Error running safety check ${check.id}`, error);
|
|
148
|
+
results.push({
|
|
149
|
+
passed: false,
|
|
150
|
+
severity: 'high',
|
|
151
|
+
message: `Check failed with error: ${(error as Error).message}`,
|
|
152
|
+
can_proceed: true, // Post-execution failures don't block
|
|
153
|
+
requires_approval: false,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const passed = results.every(r => r.passed);
|
|
159
|
+
|
|
160
|
+
return { passed, results };
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Register custom safety check
|
|
165
|
+
*/
|
|
166
|
+
registerCheck(check: SafetyCheck): void {
|
|
167
|
+
this.checks.set(check.id, check);
|
|
168
|
+
logger.info(`Registered safety check: ${check.id}`);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Remove safety check
|
|
173
|
+
*/
|
|
174
|
+
removeCheck(checkId: string): void {
|
|
175
|
+
this.checks.delete(checkId);
|
|
176
|
+
logger.info(`Removed safety check: ${checkId}`);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Get all checks
|
|
181
|
+
*/
|
|
182
|
+
getAllChecks(): SafetyCheck[] {
|
|
183
|
+
return Array.from(this.checks.values());
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Initialize default safety checks
|
|
188
|
+
*/
|
|
189
|
+
private initializeDefaultChecks(): void {
|
|
190
|
+
// ===== Pre-Execution Checks =====
|
|
191
|
+
|
|
192
|
+
// Check: Production environment safeguards
|
|
193
|
+
this.registerCheck({
|
|
194
|
+
id: 'pre_prod_safeguard',
|
|
195
|
+
type: 'pre_execution',
|
|
196
|
+
category: 'security',
|
|
197
|
+
name: 'Production Environment Safeguards',
|
|
198
|
+
description: 'Verify additional safeguards for production deployments',
|
|
199
|
+
severity: 'critical',
|
|
200
|
+
check: async context => {
|
|
201
|
+
const task = context.task as AgentTask;
|
|
202
|
+
const plan = context.plan as AgentPlan;
|
|
203
|
+
|
|
204
|
+
if (task.context.environment === 'production') {
|
|
205
|
+
// Production requires approval
|
|
206
|
+
if (!plan.requires_approval || !plan.approved_by) {
|
|
207
|
+
return {
|
|
208
|
+
passed: false,
|
|
209
|
+
severity: 'critical',
|
|
210
|
+
message: 'Production deployment requires explicit approval',
|
|
211
|
+
can_proceed: false,
|
|
212
|
+
requires_approval: true,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Check for high-risk operations
|
|
217
|
+
if (plan.risk_level === 'high' || plan.risk_level === 'critical') {
|
|
218
|
+
return {
|
|
219
|
+
passed: true,
|
|
220
|
+
severity: 'high',
|
|
221
|
+
message: 'High-risk production deployment approved',
|
|
222
|
+
details: {
|
|
223
|
+
risk_level: plan.risk_level,
|
|
224
|
+
approved_by: plan.approved_by,
|
|
225
|
+
},
|
|
226
|
+
can_proceed: true,
|
|
227
|
+
requires_approval: false,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return {
|
|
233
|
+
passed: true,
|
|
234
|
+
severity: 'low',
|
|
235
|
+
message: 'Environment safeguards satisfied',
|
|
236
|
+
can_proceed: true,
|
|
237
|
+
requires_approval: false,
|
|
238
|
+
};
|
|
239
|
+
},
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
// Check: Cost limits
|
|
243
|
+
this.registerCheck({
|
|
244
|
+
id: 'pre_cost_limit',
|
|
245
|
+
type: 'pre_execution',
|
|
246
|
+
category: 'cost',
|
|
247
|
+
name: 'Cost Limit Check',
|
|
248
|
+
description: 'Verify estimated cost is within acceptable limits',
|
|
249
|
+
severity: 'high',
|
|
250
|
+
check: async context => {
|
|
251
|
+
const plan = context.plan as AgentPlan;
|
|
252
|
+
const estimatedCost = plan.estimated_cost || 0;
|
|
253
|
+
const maxCost = 5000; // $5000 per month limit
|
|
254
|
+
|
|
255
|
+
if (estimatedCost > maxCost) {
|
|
256
|
+
return {
|
|
257
|
+
passed: false,
|
|
258
|
+
severity: 'high',
|
|
259
|
+
message: `Estimated cost $${estimatedCost} exceeds limit $${maxCost}`,
|
|
260
|
+
details: {
|
|
261
|
+
estimated: estimatedCost,
|
|
262
|
+
limit: maxCost,
|
|
263
|
+
},
|
|
264
|
+
can_proceed: false,
|
|
265
|
+
requires_approval: true,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return {
|
|
270
|
+
passed: true,
|
|
271
|
+
severity: 'low',
|
|
272
|
+
message: `Estimated cost $${estimatedCost} within limit`,
|
|
273
|
+
can_proceed: true,
|
|
274
|
+
requires_approval: false,
|
|
275
|
+
};
|
|
276
|
+
},
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
// Check: Security best practices
|
|
280
|
+
this.registerCheck({
|
|
281
|
+
id: 'pre_security_practices',
|
|
282
|
+
type: 'pre_execution',
|
|
283
|
+
category: 'security',
|
|
284
|
+
name: 'Security Best Practices',
|
|
285
|
+
description: 'Verify security best practices are applied',
|
|
286
|
+
severity: 'critical',
|
|
287
|
+
check: async context => {
|
|
288
|
+
const plan = context.plan as AgentPlan;
|
|
289
|
+
|
|
290
|
+
// Check if security validation steps are included
|
|
291
|
+
const hasSecurityValidation = plan.steps.some(
|
|
292
|
+
step => step.action === 'apply_best_practices'
|
|
293
|
+
);
|
|
294
|
+
|
|
295
|
+
if (!hasSecurityValidation) {
|
|
296
|
+
return {
|
|
297
|
+
passed: false,
|
|
298
|
+
severity: 'critical',
|
|
299
|
+
message: 'Plan missing security best practices validation',
|
|
300
|
+
can_proceed: false,
|
|
301
|
+
requires_approval: true,
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
return {
|
|
306
|
+
passed: true,
|
|
307
|
+
severity: 'low',
|
|
308
|
+
message: 'Security best practices validation included',
|
|
309
|
+
can_proceed: true,
|
|
310
|
+
requires_approval: false,
|
|
311
|
+
};
|
|
312
|
+
},
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
// Check: Backup strategy
|
|
316
|
+
this.registerCheck({
|
|
317
|
+
id: 'pre_backup_strategy',
|
|
318
|
+
type: 'pre_execution',
|
|
319
|
+
category: 'availability',
|
|
320
|
+
name: 'Backup Strategy',
|
|
321
|
+
description: 'Verify backup strategy is defined for stateful components',
|
|
322
|
+
severity: 'high',
|
|
323
|
+
check: async context => {
|
|
324
|
+
const task = context.task as AgentTask;
|
|
325
|
+
const hasStatefulComponents = task.context.components.some(c =>
|
|
326
|
+
['rds', 's3', 'efs'].includes(c)
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
if (hasStatefulComponents) {
|
|
330
|
+
// Check if backup is configured
|
|
331
|
+
const hasBackup = task.context.requirements?.backup_enabled === true;
|
|
332
|
+
|
|
333
|
+
if (!hasBackup && task.context.environment === 'production') {
|
|
334
|
+
return {
|
|
335
|
+
passed: false,
|
|
336
|
+
severity: 'high',
|
|
337
|
+
message: 'Production stateful components require backup strategy',
|
|
338
|
+
can_proceed: false,
|
|
339
|
+
requires_approval: true,
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (!hasBackup) {
|
|
344
|
+
return {
|
|
345
|
+
passed: true,
|
|
346
|
+
severity: 'medium',
|
|
347
|
+
message: 'Backup recommended for stateful components',
|
|
348
|
+
can_proceed: true,
|
|
349
|
+
requires_approval: false,
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
return {
|
|
355
|
+
passed: true,
|
|
356
|
+
severity: 'low',
|
|
357
|
+
message: 'Backup strategy validated',
|
|
358
|
+
can_proceed: true,
|
|
359
|
+
requires_approval: false,
|
|
360
|
+
};
|
|
361
|
+
},
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
// Check: Destructive operations
|
|
365
|
+
this.registerCheck({
|
|
366
|
+
id: 'pre_destructive_ops',
|
|
367
|
+
type: 'pre_execution',
|
|
368
|
+
category: 'availability',
|
|
369
|
+
name: 'Destructive Operations',
|
|
370
|
+
description: 'Verify destructive operations are intentional',
|
|
371
|
+
severity: 'critical',
|
|
372
|
+
check: async context => {
|
|
373
|
+
const plan = context.plan as AgentPlan;
|
|
374
|
+
|
|
375
|
+
// Check for deployment steps that could be destructive
|
|
376
|
+
const hasDeployment = plan.steps.some(step => step.action === 'apply_deployment');
|
|
377
|
+
|
|
378
|
+
if (hasDeployment) {
|
|
379
|
+
// Ensure plan has rollback capability
|
|
380
|
+
const hasRollback = plan.steps.some(step => step.rollback_action);
|
|
381
|
+
|
|
382
|
+
if (!hasRollback) {
|
|
383
|
+
return {
|
|
384
|
+
passed: false,
|
|
385
|
+
severity: 'high',
|
|
386
|
+
message: 'Deployment steps should have rollback capability',
|
|
387
|
+
can_proceed: true, // Can proceed but warned
|
|
388
|
+
requires_approval: true,
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
return {
|
|
394
|
+
passed: true,
|
|
395
|
+
severity: 'low',
|
|
396
|
+
message: 'Destructive operations validated',
|
|
397
|
+
can_proceed: true,
|
|
398
|
+
requires_approval: false,
|
|
399
|
+
};
|
|
400
|
+
},
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
// ===== During-Execution Checks =====
|
|
404
|
+
|
|
405
|
+
// Check: Resource creation rate
|
|
406
|
+
this.registerCheck({
|
|
407
|
+
id: 'during_resource_rate',
|
|
408
|
+
type: 'during_execution',
|
|
409
|
+
category: 'cost',
|
|
410
|
+
name: 'Resource Creation Rate',
|
|
411
|
+
description: 'Monitor resource creation rate for anomalies',
|
|
412
|
+
severity: 'medium',
|
|
413
|
+
check: async context => {
|
|
414
|
+
// In production, this would monitor actual resource creation
|
|
415
|
+
const resourcesCreated = (context.resources_created as number) || 0;
|
|
416
|
+
const maxRate = 50; // Max 50 resources per execution
|
|
417
|
+
|
|
418
|
+
if (resourcesCreated > maxRate) {
|
|
419
|
+
return {
|
|
420
|
+
passed: false,
|
|
421
|
+
severity: 'high',
|
|
422
|
+
message: `Unusual resource creation rate: ${resourcesCreated} resources`,
|
|
423
|
+
details: { count: resourcesCreated, threshold: maxRate },
|
|
424
|
+
can_proceed: false,
|
|
425
|
+
requires_approval: true,
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
return {
|
|
430
|
+
passed: true,
|
|
431
|
+
severity: 'low',
|
|
432
|
+
message: 'Resource creation rate normal',
|
|
433
|
+
can_proceed: true,
|
|
434
|
+
requires_approval: false,
|
|
435
|
+
};
|
|
436
|
+
},
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
// Check: Execution timeout
|
|
440
|
+
this.registerCheck({
|
|
441
|
+
id: 'during_execution_timeout',
|
|
442
|
+
type: 'during_execution',
|
|
443
|
+
category: 'availability',
|
|
444
|
+
name: 'Execution Timeout',
|
|
445
|
+
description: 'Ensure execution does not exceed time limits',
|
|
446
|
+
severity: 'medium',
|
|
447
|
+
check: async context => {
|
|
448
|
+
const startTime = context.start_time as Date;
|
|
449
|
+
const maxDuration = 3600000; // 1 hour
|
|
450
|
+
|
|
451
|
+
if (startTime) {
|
|
452
|
+
const elapsed = Date.now() - startTime.getTime();
|
|
453
|
+
|
|
454
|
+
if (elapsed > maxDuration) {
|
|
455
|
+
return {
|
|
456
|
+
passed: false,
|
|
457
|
+
severity: 'high',
|
|
458
|
+
message: 'Execution exceeding time limit',
|
|
459
|
+
details: { elapsed, limit: maxDuration },
|
|
460
|
+
can_proceed: false,
|
|
461
|
+
requires_approval: false,
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
return {
|
|
467
|
+
passed: true,
|
|
468
|
+
severity: 'low',
|
|
469
|
+
message: 'Execution within time limits',
|
|
470
|
+
can_proceed: true,
|
|
471
|
+
requires_approval: false,
|
|
472
|
+
};
|
|
473
|
+
},
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
// ===== Post-Execution Checks =====
|
|
477
|
+
|
|
478
|
+
// Check: Deployment verification
|
|
479
|
+
this.registerCheck({
|
|
480
|
+
id: 'post_deployment_verify',
|
|
481
|
+
type: 'post_execution',
|
|
482
|
+
category: 'availability',
|
|
483
|
+
name: 'Deployment Verification',
|
|
484
|
+
description: 'Verify deployed resources are healthy',
|
|
485
|
+
severity: 'high',
|
|
486
|
+
check: async context => {
|
|
487
|
+
const deploymentSuccess = context.deployment_success as boolean;
|
|
488
|
+
|
|
489
|
+
if (deploymentSuccess === false) {
|
|
490
|
+
return {
|
|
491
|
+
passed: false,
|
|
492
|
+
severity: 'critical',
|
|
493
|
+
message: 'Deployment verification failed',
|
|
494
|
+
can_proceed: true, // Already deployed
|
|
495
|
+
requires_approval: false,
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
return {
|
|
500
|
+
passed: true,
|
|
501
|
+
severity: 'low',
|
|
502
|
+
message: 'Deployment verified successfully',
|
|
503
|
+
can_proceed: true,
|
|
504
|
+
requires_approval: false,
|
|
505
|
+
};
|
|
506
|
+
},
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
// Check: Cost anomaly detection
|
|
510
|
+
this.registerCheck({
|
|
511
|
+
id: 'post_cost_anomaly',
|
|
512
|
+
type: 'post_execution',
|
|
513
|
+
category: 'cost',
|
|
514
|
+
name: 'Cost Anomaly Detection',
|
|
515
|
+
description: 'Check for unexpected cost increases',
|
|
516
|
+
severity: 'medium',
|
|
517
|
+
check: async context => {
|
|
518
|
+
const estimatedCost = (context.estimated_cost as number) || 0;
|
|
519
|
+
const actualCost = (context.actual_cost as number) || estimatedCost;
|
|
520
|
+
|
|
521
|
+
// Allow 20% variance
|
|
522
|
+
const variance = Math.abs(actualCost - estimatedCost) / estimatedCost;
|
|
523
|
+
|
|
524
|
+
if (variance > 0.2) {
|
|
525
|
+
return {
|
|
526
|
+
passed: false,
|
|
527
|
+
severity: 'high',
|
|
528
|
+
message: `Actual cost differs significantly from estimate`,
|
|
529
|
+
details: {
|
|
530
|
+
estimated: estimatedCost,
|
|
531
|
+
actual: actualCost,
|
|
532
|
+
variance: `${(variance * 100).toFixed(1)}%`,
|
|
533
|
+
},
|
|
534
|
+
can_proceed: true,
|
|
535
|
+
requires_approval: false,
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
return {
|
|
540
|
+
passed: true,
|
|
541
|
+
severity: 'low',
|
|
542
|
+
message: 'Cost within expected range',
|
|
543
|
+
can_proceed: true,
|
|
544
|
+
requires_approval: false,
|
|
545
|
+
};
|
|
546
|
+
},
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
// Check: Security posture
|
|
550
|
+
this.registerCheck({
|
|
551
|
+
id: 'post_security_posture',
|
|
552
|
+
type: 'post_execution',
|
|
553
|
+
category: 'security',
|
|
554
|
+
name: 'Security Posture Assessment',
|
|
555
|
+
description: 'Assess final security configuration',
|
|
556
|
+
severity: 'critical',
|
|
557
|
+
check: async context => {
|
|
558
|
+
const securityScore = (context.security_score as number) || 0;
|
|
559
|
+
const minScore = 80;
|
|
560
|
+
|
|
561
|
+
if (securityScore < minScore) {
|
|
562
|
+
return {
|
|
563
|
+
passed: false,
|
|
564
|
+
severity: 'critical',
|
|
565
|
+
message: `Security score ${securityScore} below threshold ${minScore}`,
|
|
566
|
+
details: { score: securityScore, threshold: minScore },
|
|
567
|
+
can_proceed: true,
|
|
568
|
+
requires_approval: false,
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
return {
|
|
573
|
+
passed: true,
|
|
574
|
+
severity: 'low',
|
|
575
|
+
message: `Security score ${securityScore} meets requirements`,
|
|
576
|
+
can_proceed: true,
|
|
577
|
+
requires_approval: false,
|
|
578
|
+
};
|
|
579
|
+
},
|
|
580
|
+
});
|
|
581
|
+
|
|
582
|
+
// Check: No production delete without backup
|
|
583
|
+
this.registerCheck({
|
|
584
|
+
id: 'no_production_delete_without_backup',
|
|
585
|
+
type: 'pre_execution',
|
|
586
|
+
category: 'availability',
|
|
587
|
+
name: 'No Production Delete Without Backup',
|
|
588
|
+
description: 'Blocks destroy/delete operations in production when backup is not enabled',
|
|
589
|
+
severity: 'critical',
|
|
590
|
+
check: async context => {
|
|
591
|
+
const task = context.task as AgentTask;
|
|
592
|
+
const plan = context.plan as AgentPlan;
|
|
593
|
+
|
|
594
|
+
if (task.context.environment !== 'production') {
|
|
595
|
+
return {
|
|
596
|
+
passed: true,
|
|
597
|
+
severity: 'low',
|
|
598
|
+
message: 'Non-production environment, policy not applicable',
|
|
599
|
+
can_proceed: true,
|
|
600
|
+
requires_approval: false,
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
const hasDestructiveAction = plan.steps.some(
|
|
605
|
+
step =>
|
|
606
|
+
(step.action === 'apply_deployment' && step.parameters?.destroy) ||
|
|
607
|
+
(step.action === 'apply_deployment' &&
|
|
608
|
+
step.description?.toLowerCase().includes('delete')) ||
|
|
609
|
+
step.description?.toLowerCase().includes('destroy')
|
|
610
|
+
);
|
|
611
|
+
|
|
612
|
+
if (!hasDestructiveAction) {
|
|
613
|
+
return {
|
|
614
|
+
passed: true,
|
|
615
|
+
severity: 'low',
|
|
616
|
+
message: 'No destructive actions found in plan',
|
|
617
|
+
can_proceed: true,
|
|
618
|
+
requires_approval: false,
|
|
619
|
+
};
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
const backupEnabled = task.context.requirements?.backup_enabled === true;
|
|
623
|
+
|
|
624
|
+
if (!backupEnabled) {
|
|
625
|
+
return {
|
|
626
|
+
passed: false,
|
|
627
|
+
severity: 'critical',
|
|
628
|
+
message:
|
|
629
|
+
'Production destroy/delete operations require backup_enabled in requirements. ' +
|
|
630
|
+
'Create a backup first or use a staging environment.',
|
|
631
|
+
can_proceed: false,
|
|
632
|
+
requires_approval: true,
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
return {
|
|
637
|
+
passed: true,
|
|
638
|
+
severity: 'low',
|
|
639
|
+
message: 'Backup enabled for production destructive operation',
|
|
640
|
+
can_proceed: true,
|
|
641
|
+
requires_approval: false,
|
|
642
|
+
};
|
|
643
|
+
},
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
// Check: Require dry-run before apply
|
|
647
|
+
this.registerCheck({
|
|
648
|
+
id: 'require_dry_run_first',
|
|
649
|
+
type: 'pre_execution',
|
|
650
|
+
category: 'compliance',
|
|
651
|
+
name: 'Require Dry Run First',
|
|
652
|
+
description: 'Blocks apply_deployment if no plan_deployment step precedes it',
|
|
653
|
+
severity: 'high',
|
|
654
|
+
check: async context => {
|
|
655
|
+
const plan = context.plan as AgentPlan;
|
|
656
|
+
|
|
657
|
+
const hasApply = plan.steps.some(step => step.action === 'apply_deployment');
|
|
658
|
+
|
|
659
|
+
if (!hasApply) {
|
|
660
|
+
return {
|
|
661
|
+
passed: true,
|
|
662
|
+
severity: 'low',
|
|
663
|
+
message: 'No apply_deployment steps in plan',
|
|
664
|
+
can_proceed: true,
|
|
665
|
+
requires_approval: false,
|
|
666
|
+
};
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
const hasPlan = plan.steps.some(step => step.action === 'plan_deployment');
|
|
670
|
+
|
|
671
|
+
if (!hasPlan) {
|
|
672
|
+
return {
|
|
673
|
+
passed: false,
|
|
674
|
+
severity: 'high',
|
|
675
|
+
message:
|
|
676
|
+
'Plan contains apply_deployment without a preceding plan_deployment step. ' +
|
|
677
|
+
'Run with --dry-run first to preview changes.',
|
|
678
|
+
can_proceed: false,
|
|
679
|
+
requires_approval: true,
|
|
680
|
+
};
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
return {
|
|
684
|
+
passed: true,
|
|
685
|
+
severity: 'low',
|
|
686
|
+
message: 'Dry-run (plan_deployment) step precedes apply',
|
|
687
|
+
can_proceed: true,
|
|
688
|
+
requires_approval: false,
|
|
689
|
+
};
|
|
690
|
+
},
|
|
691
|
+
});
|
|
692
|
+
|
|
693
|
+
// Check: Token budget guardrail
|
|
694
|
+
this.registerCheck({
|
|
695
|
+
id: 'pre_token_budget',
|
|
696
|
+
type: 'pre_execution',
|
|
697
|
+
category: 'cost',
|
|
698
|
+
name: 'Token Budget Check',
|
|
699
|
+
description: 'Verify estimated token usage does not exceed budget',
|
|
700
|
+
severity: 'high',
|
|
701
|
+
check: async context => {
|
|
702
|
+
const plan = context.plan as AgentPlan & { estimated_tokens?: number };
|
|
703
|
+
const maxTokensPerTask = parseInt(process.env.MAX_TOKENS_PER_TASK || '0', 10);
|
|
704
|
+
|
|
705
|
+
if (!maxTokensPerTask || maxTokensPerTask <= 0) {
|
|
706
|
+
return {
|
|
707
|
+
passed: true,
|
|
708
|
+
severity: 'low',
|
|
709
|
+
message: 'No token budget configured',
|
|
710
|
+
can_proceed: true,
|
|
711
|
+
requires_approval: false,
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
const estimatedTokens = plan.estimated_tokens ?? plan.estimated_cost ?? 0;
|
|
716
|
+
|
|
717
|
+
if (estimatedTokens > maxTokensPerTask) {
|
|
718
|
+
return {
|
|
719
|
+
passed: false,
|
|
720
|
+
severity: 'high',
|
|
721
|
+
message: `Estimated token usage (${estimatedTokens}) exceeds budget (${maxTokensPerTask})`,
|
|
722
|
+
details: {
|
|
723
|
+
estimated: estimatedTokens,
|
|
724
|
+
budget: maxTokensPerTask,
|
|
725
|
+
},
|
|
726
|
+
can_proceed: false,
|
|
727
|
+
requires_approval: true,
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
return {
|
|
732
|
+
passed: true,
|
|
733
|
+
severity: 'low',
|
|
734
|
+
message: `Estimated tokens (${estimatedTokens}) within budget (${maxTokensPerTask})`,
|
|
735
|
+
can_proceed: true,
|
|
736
|
+
requires_approval: false,
|
|
737
|
+
};
|
|
738
|
+
},
|
|
739
|
+
});
|
|
740
|
+
|
|
741
|
+
logger.info(`Initialized ${this.checks.size} default safety checks`);
|
|
742
|
+
}
|
|
743
|
+
}
|