claw-dashboard 1.9.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.c8rc.json +38 -0
- package/.dockerignore +68 -0
- package/.github/dependabot.yml +45 -0
- package/.github/pull_request_template.md +39 -0
- package/.github/workflows/ci.yml +147 -0
- package/.github/workflows/release.yml +40 -0
- package/.github/workflows/security.yml +84 -0
- package/.husky/pre-commit +1 -0
- package/.planning/codebase/ARCHITECTURE.md +206 -0
- package/.planning/codebase/INTEGRATIONS.md +150 -0
- package/.planning/codebase/STACK.md +122 -0
- package/.planning/codebase/STRUCTURE.md +201 -0
- package/CHANGELOG.md +293 -0
- package/CONTRIBUTING.md +378 -0
- package/Dockerfile +54 -0
- package/FEATURES.md +195 -21
- package/README.md +83 -6
- package/TODO.md +28 -0
- package/build-cjs.js +127 -0
- package/cjs-shim.js +13 -0
- package/dist/clawdash +1729 -0
- package/dist/clawdash.meta.json +2236 -0
- package/dist/widgets.cjs +6511 -0
- package/docker-compose.yml +67 -0
- package/docs/API.md +1050 -0
- package/docs/PLUGINS.md +1504 -0
- package/esbuild.config.js +158 -0
- package/eslint.config.js +56 -0
- package/examples/plugins/README.md +122 -0
- package/examples/plugins/api-status/index.js +294 -0
- package/examples/plugins/api-status/plugin.json +19 -0
- package/examples/plugins/hello-world/index.js +104 -0
- package/examples/plugins/hello-world/plugin.json +15 -0
- package/examples/plugins/system-metrics-chart/index.js +339 -0
- package/examples/plugins/system-metrics-chart/plugin.json +18 -0
- package/examples/plugins/weather-widget/index.js +136 -0
- package/examples/plugins/weather-widget/plugin.json +19 -0
- package/index.cjs +23005 -0
- package/index.js +5285 -566
- package/jest.config.js +11 -0
- package/man/clawdash.1 +276 -0
- package/package.json +54 -6
- package/schemas/plugin-manifest.json +128 -0
- package/scripts/release.js +595 -0
- package/src/alerts.js +693 -0
- package/src/auto-save.js +584 -0
- package/src/cache.js +390 -0
- package/src/checksum.js +146 -0
- package/src/cli/args.js +110 -0
- package/src/cli/export-schedule.js +423 -0
- package/src/cli/export-snapshot.js +138 -0
- package/src/cli/help.js +69 -0
- package/src/cli/import-snapshot.js +230 -0
- package/src/cli/index.js +14 -0
- package/src/cli/list-templates.js +69 -0
- package/src/cli/validate-config.js +76 -0
- package/src/cli/validate-plugin.js +187 -0
- package/src/cli/version.js +15 -0
- package/src/config-validator.js +586 -0
- package/src/config-watcher.js +401 -0
- package/src/config.js +684 -0
- package/src/container-detector.js +499 -0
- package/src/database.js +734 -0
- package/src/differential-render.js +327 -0
- package/src/errors.js +169 -0
- package/src/export-scheduler.js +581 -0
- package/src/gateway-manager.js +685 -0
- package/src/hints.js +371 -0
- package/src/loading-states.js +509 -0
- package/src/logger.js +185 -0
- package/src/memory-pressure.js +467 -0
- package/src/performance-monitor.js +374 -0
- package/src/plugin-errors.js +586 -0
- package/src/plugin-manifest-validator.js +219 -0
- package/src/plugin-reload.js +481 -0
- package/src/plugin-scaffold.js +1934 -0
- package/src/plugin-validator.js +284 -0
- package/src/retry.js +218 -0
- package/src/security.js +860 -0
- package/src/snapshot.js +372 -0
- package/src/splash.js +115 -0
- package/src/theme-selector.js +411 -0
- package/src/themes.js +874 -0
- package/src/transitions.js +534 -0
- package/src/types.d.ts +174 -0
- package/src/validation.js +926 -0
- package/src/web-server.js +885 -0
- package/src/widgets/builtin-widgets.js +1056 -0
- package/src/widgets/config-processor.js +401 -0
- package/src/widgets/dependency-resolver.js +596 -0
- package/src/widgets/index.js +79 -0
- package/src/widgets/plugin-api.js +845 -0
- package/src/widgets/widget-error-boundary.js +773 -0
- package/src/widgets/widget-error-isolation.js +551 -0
- package/src/widgets/widget-loader.js +1437 -0
- package/src/workers/system-worker.js +130 -0
- package/src/workers/worker-pool.js +633 -0
- package/tests/alerts.test.js +437 -0
- package/tests/auto-save.test.js +529 -0
- package/tests/cache.test.js +317 -0
- package/tests/cli.test.js +351 -0
- package/tests/command-palette.test.js +320 -0
- package/tests/config-processor.test.js +452 -0
- package/tests/config-validator.test.js +710 -0
- package/tests/config-watcher.test.js +594 -0
- package/tests/config.test.js +755 -0
- package/tests/database.test.js +438 -0
- package/tests/errors.test.js +189 -0
- package/tests/example-plugins.test.js +624 -0
- package/tests/integration.test.js +1321 -0
- package/tests/loading-states.test.js +300 -0
- package/tests/manifest-validation-on-load.test.js +671 -0
- package/tests/performance-monitor.test.js +190 -0
- package/tests/plugin-api-rate-limit.test.js +302 -0
- package/tests/plugin-errors.test.js +311 -0
- package/tests/plugin-lifecycle-e2e.test.js +1036 -0
- package/tests/plugin-reload.test.js +764 -0
- package/tests/rate-limiter.test.js +539 -0
- package/tests/retry.test.js +308 -0
- package/tests/security.test.js +411 -0
- package/tests/settings-modal.test.js +226 -0
- package/tests/theme-selector.test.js +57 -0
- package/tests/utils.js +242 -0
- package/tests/utils.test.js +317 -0
- package/tests/validate-plugin-cli.test.js +359 -0
- package/tests/validation.test.js +837 -0
- package/tests/web-server.test.js +646 -0
- package/tests/widget-arrange-mode.test.js +183 -0
- package/tests/widget-config-hot-reload.test.js +465 -0
- package/tests/widget-dependency.test.js +591 -0
- package/tests/widget-error-boundary.test.js +749 -0
- package/tests/widget-error-isolation.test.js +469 -0
- package/tests/widget-integration.test.js +1147 -0
- package/tests/widget-refresh-intervals.test.js +284 -0
- package/tests/worker-pool.test.js +522 -0
package/src/config.js
ADDED
|
@@ -0,0 +1,684 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized configuration file for Claw Dashboard
|
|
3
|
+
* Contains all magic numbers, constants, and configurable values
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import os from 'os';
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
9
|
+
import { dirname, join } from 'path';
|
|
10
|
+
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
+
const __dirname = dirname(__filename);
|
|
13
|
+
|
|
14
|
+
// Load dashboard version from package.json
|
|
15
|
+
let DASHBOARD_VERSION = 'unknown';
|
|
16
|
+
try {
|
|
17
|
+
const pkg = JSON.parse(fs.readFileSync(join(__dirname, '../package.json'), 'utf8'));
|
|
18
|
+
DASHBOARD_VERSION = pkg.version || 'unknown';
|
|
19
|
+
} catch {}
|
|
20
|
+
|
|
21
|
+
export { DASHBOARD_VERSION };
|
|
22
|
+
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// REFRESH & TIMING SETTINGS
|
|
25
|
+
// ============================================================================
|
|
26
|
+
|
|
27
|
+
export const REFRESH_INTERVALS = {
|
|
28
|
+
DEFAULT: 2000,
|
|
29
|
+
ACTIVE: 2000, // 2 seconds when agents active
|
|
30
|
+
IDLE: 10000, // 10 seconds when idle (no active agents)
|
|
31
|
+
OPTIONS: [1000, 2000, 5000, 10000], // Available refresh interval options
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const IDLE_THRESHOLD_MS = 5 * 60 * 1000; // 5 minutes to consider session idle
|
|
35
|
+
|
|
36
|
+
// ============================================================================
|
|
37
|
+
// HISTORY & DISPLAY LIMITS
|
|
38
|
+
// ============================================================================
|
|
39
|
+
|
|
40
|
+
export const HISTORY = {
|
|
41
|
+
LENGTH: 60, // Default history length for charts
|
|
42
|
+
NETWORK_LENGTH: 30, // Network history length
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// ============================================================================
|
|
46
|
+
// GATEWAY CONFIGURATION
|
|
47
|
+
// ============================================================================
|
|
48
|
+
|
|
49
|
+
export const GATEWAY = {
|
|
50
|
+
DEFAULT_PORT: 18789,
|
|
51
|
+
TIMEOUT_MS: 3000,
|
|
52
|
+
MAX_ENDPOINTS: 10, // Maximum number of gateway endpoints
|
|
53
|
+
DEFAULT_ENDPOINT_NAME: 'local', // Default name for local gateway
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// Default gateway endpoint configuration
|
|
57
|
+
export const DEFAULT_GATEWAY_ENDPOINT = {
|
|
58
|
+
name: 'local',
|
|
59
|
+
host: 'localhost',
|
|
60
|
+
port: 18789,
|
|
61
|
+
token: null,
|
|
62
|
+
enabled: true,
|
|
63
|
+
type: 'local', // 'local', 'remote', 'cloud'
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// ============================================================================
|
|
67
|
+
// UI DIMENSIONS & DEFAULTS
|
|
68
|
+
// ============================================================================
|
|
69
|
+
|
|
70
|
+
export const UI = {
|
|
71
|
+
GAUGE_WIDTH: 15,
|
|
72
|
+
SPARKLINE_WIDTH: 15,
|
|
73
|
+
LOG_BOX_MIN_HEIGHT: 10,
|
|
74
|
+
DEFAULT_WIDTH: 80,
|
|
75
|
+
DEFAULT_HEIGHT: 24,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// ============================================================================
|
|
79
|
+
// CACHE TTL SETTINGS (in milliseconds)
|
|
80
|
+
// ============================================================================
|
|
81
|
+
|
|
82
|
+
export const CACHE_TTL = {
|
|
83
|
+
CPU: 1000, // 1 second TTL for CPU
|
|
84
|
+
MEMORY: 1000, // 1 second TTL for memory
|
|
85
|
+
GPU: 5000, // 5 second TTL for GPU (expensive)
|
|
86
|
+
NETWORK: 5000, // 5 second TTL for network (was 1s, causes timeouts)
|
|
87
|
+
DISK: 60000, // 60 second TTL for disk (rarely changes)
|
|
88
|
+
SYSTEM: 3600000, // 1 HOUR TTL for system info (OS version rarely changes!)
|
|
89
|
+
CONTAINER: 300000, // 5 minute TTL for container detection
|
|
90
|
+
DEFAULT: 2000, // Default TTL fallback
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// Cache configuration object (for direct use)
|
|
94
|
+
export const CACHE_CONFIG = {
|
|
95
|
+
cpu: { ttl: CACHE_TTL.CPU },
|
|
96
|
+
memory: { ttl: CACHE_TTL.MEMORY },
|
|
97
|
+
gpu: { ttl: CACHE_TTL.GPU },
|
|
98
|
+
network: { ttl: CACHE_TTL.NETWORK },
|
|
99
|
+
disk: { ttl: CACHE_TTL.DISK },
|
|
100
|
+
system: { ttl: CACHE_TTL.SYSTEM },
|
|
101
|
+
container: { ttl: CACHE_TTL.CONTAINER },
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
// ============================================================================
|
|
105
|
+
// DATABASE SETTINGS
|
|
106
|
+
// ============================================================================
|
|
107
|
+
|
|
108
|
+
export const DATABASE = {
|
|
109
|
+
PATH: os.homedir() + '/.openclaw/dashboard-history.db',
|
|
110
|
+
SAVE_INTERVAL_MS: 30000, // Save every 30 seconds
|
|
111
|
+
CLEANUP_INTERVAL_MS: 60 * 60 * 1000, // Cleanup every hour
|
|
112
|
+
DEFAULT_RETENTION_DAYS: 30,
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// ============================================================================
|
|
116
|
+
// CHECKSUM VERIFICATION SETTINGS
|
|
117
|
+
// ============================================================================
|
|
118
|
+
|
|
119
|
+
export const CHECKSUM = {
|
|
120
|
+
ENABLED: true, // Enable checksum verification by default
|
|
121
|
+
ALGORITHM: 'sha256', // Hash algorithm: sha256, sha512, md5
|
|
122
|
+
HEADER_NAME: 'x-response-checksum', // HTTP header containing the checksum
|
|
123
|
+
STRICT_MODE: false, // If true, reject responses without checksums
|
|
124
|
+
MAX_AGE_MS: 300000, // Maximum age of checksum (5 minutes)
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
// ============================================================================
|
|
128
|
+
// RETRY SETTINGS
|
|
129
|
+
// ============================================================================
|
|
130
|
+
|
|
131
|
+
export const RETRY = {
|
|
132
|
+
DEFAULT_MAX_RETRIES: 3,
|
|
133
|
+
DEFAULT_INITIAL_DELAY: 1000, // 1 second
|
|
134
|
+
DEFAULT_MAX_DELAY: 10000, // 10 seconds
|
|
135
|
+
DEFAULT_BACKOFF_MULTIPLIER: 2,
|
|
136
|
+
TIMEOUT: 30000, // Max time to keep retrying
|
|
137
|
+
INTERVAL: 1000, // Time between retries
|
|
138
|
+
JITTER_FACTOR: 0.1, // ±10% jitter
|
|
139
|
+
RETRYABLE_STATUSES: [408, 429, 500, 502, 503, 504],
|
|
140
|
+
RETRYABLE_ERRORS: [
|
|
141
|
+
'ECONNREFUSED',
|
|
142
|
+
'ETIMEDOUT',
|
|
143
|
+
'ENOTFOUND',
|
|
144
|
+
'EAI_AGAIN',
|
|
145
|
+
'ECONNRESET',
|
|
146
|
+
'EPIPE'
|
|
147
|
+
],
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
// Retry configuration object (for direct use)
|
|
151
|
+
export const DEFAULT_RETRY_OPTIONS = {
|
|
152
|
+
maxRetries: RETRY.DEFAULT_MAX_RETRIES,
|
|
153
|
+
initialDelay: RETRY.DEFAULT_INITIAL_DELAY,
|
|
154
|
+
maxDelay: RETRY.DEFAULT_MAX_DELAY,
|
|
155
|
+
backoffMultiplier: RETRY.DEFAULT_BACKOFF_MULTIPLIER,
|
|
156
|
+
retryableStatuses: RETRY.RETRYABLE_STATUSES,
|
|
157
|
+
retryableErrors: RETRY.RETRYABLE_ERRORS,
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
// ============================================================================
|
|
161
|
+
// AUTO-RETRY SETTINGS (Gateway connectivity)
|
|
162
|
+
// ============================================================================
|
|
163
|
+
|
|
164
|
+
export const AUTO_RETRY = {
|
|
165
|
+
ENABLED: true, // Enable auto-retry by default
|
|
166
|
+
DEFAULT_INTERVAL_MS: 30000, // Default: 30 seconds between auto-retries
|
|
167
|
+
MIN_INTERVAL_MS: 5000, // Minimum: 5 seconds (prevent hammering)
|
|
168
|
+
MAX_INTERVAL_MS: 300000, // Maximum: 5 minutes
|
|
169
|
+
EXPONENTIAL_BACKOFF: true, // Enable exponential backoff for consecutive failures
|
|
170
|
+
BACKOFF_MULTIPLIER: 2, // Multiply interval by this after each failure
|
|
171
|
+
MAX_BACKOFF_INTERVAL_MS: 300000, // Cap backoff at 5 minutes
|
|
172
|
+
RESET_AFTER_SUCCESS: true, // Reset backoff after successful connection
|
|
173
|
+
CONSECUTIVE_FAILURE_THRESHOLD: 3, // Number of failures before applying backoff
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
// ============================================================================
|
|
177
|
+
// ALERT THRESHOLDS
|
|
178
|
+
// ============================================================================
|
|
179
|
+
|
|
180
|
+
export const ALERT_THRESHOLDS = {
|
|
181
|
+
CPU: { warning: 70, critical: 90 },
|
|
182
|
+
MEMORY: { warning: 75, critical: 90 },
|
|
183
|
+
DISK: { warning: 80, critical: 95 },
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
// Alert rate limiting
|
|
187
|
+
export const ALERT_RATE_LIMIT = {
|
|
188
|
+
ENABLED: true,
|
|
189
|
+
WINDOW_MS: 60000, // 1 minute window
|
|
190
|
+
MAX_ALERTS: 5, // Max alerts per window per type
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
// Alert history limit
|
|
194
|
+
export const MAX_ALERT_HISTORY = 100;
|
|
195
|
+
|
|
196
|
+
// ============================================================================
|
|
197
|
+
// MEMORY PRESSURE DETECTION SETTINGS
|
|
198
|
+
// ============================================================================
|
|
199
|
+
|
|
200
|
+
export const MEMORY_PRESSURE = {
|
|
201
|
+
// Thresholds for memory pressure detection (applies to dashboard process itself)
|
|
202
|
+
THRESHOLDS: {
|
|
203
|
+
WARNING_MB: 512, // Warning when heap reaches 512MB
|
|
204
|
+
CRITICAL_MB: 1024, // Critical when heap reaches 1GB
|
|
205
|
+
EMERGENCY_MB: 1536, // Emergency when heap reaches 1.5GB
|
|
206
|
+
},
|
|
207
|
+
// Trend detection settings
|
|
208
|
+
TREND: {
|
|
209
|
+
SAMPLE_COUNT: 10, // Number of samples to analyze for trend
|
|
210
|
+
GROWTH_THRESHOLD_MB: 50, // Minimum MB growth to consider a trend
|
|
211
|
+
TIME_WINDOW_MS: 60000, // 1 minute window for trend analysis
|
|
212
|
+
},
|
|
213
|
+
// Sustained pressure detection
|
|
214
|
+
SUSTAINED: {
|
|
215
|
+
DURATION_MS: 120000, // 2 minutes of high memory to trigger sustained alert
|
|
216
|
+
CHECK_INTERVAL_MS: 10000, // Check every 10 seconds
|
|
217
|
+
},
|
|
218
|
+
// Actions
|
|
219
|
+
ACTIONS: {
|
|
220
|
+
// Automatically clear old performance history when memory is high
|
|
221
|
+
AUTO_CLEAR_HISTORY: true,
|
|
222
|
+
// Request garbage collection hint (if available)
|
|
223
|
+
REQUEST_GC: true,
|
|
224
|
+
},
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
// ============================================================================
|
|
228
|
+
// VALIDATION CONSTRAINTS
|
|
229
|
+
// ============================================================================
|
|
230
|
+
|
|
231
|
+
export const VALIDATION = {
|
|
232
|
+
REFRESH_INTERVAL: {
|
|
233
|
+
MIN: 500,
|
|
234
|
+
MAX: 60000,
|
|
235
|
+
},
|
|
236
|
+
VALID_THEMES: ['default', 'dark', 'high-contrast', 'ocean', 'auto'],
|
|
237
|
+
VALID_SORT_MODES: ['time', 'tokens', 'idle', 'name'],
|
|
238
|
+
VALID_LOG_LEVELS: ['all', 'error', 'warn', 'info', 'debug'],
|
|
239
|
+
VALID_EXPORT_FORMATS: ['json', 'csv'],
|
|
240
|
+
VALID_ENDPOINT_TYPES: ['local', 'remote', 'cloud'],
|
|
241
|
+
ENDPOINT_NAME: {
|
|
242
|
+
MIN_LENGTH: 1,
|
|
243
|
+
MAX_LENGTH: 32,
|
|
244
|
+
PATTERN: /^[a-zA-Z0-9_-]+$/,
|
|
245
|
+
},
|
|
246
|
+
AUTO_RETRY: {
|
|
247
|
+
INTERVAL_MS: {
|
|
248
|
+
MIN: 5000, // Minimum 5 seconds
|
|
249
|
+
MAX: 300000, // Maximum 5 minutes
|
|
250
|
+
},
|
|
251
|
+
BACKOFF_MULTIPLIER: {
|
|
252
|
+
MIN: 1,
|
|
253
|
+
MAX: 10,
|
|
254
|
+
},
|
|
255
|
+
MAX_BACKOFF_INTERVAL_MS: {
|
|
256
|
+
MIN: 10000, // Minimum 10 seconds
|
|
257
|
+
MAX: 600000, // Maximum 10 minutes
|
|
258
|
+
},
|
|
259
|
+
CONSECUTIVE_FAILURE_THRESHOLD: {
|
|
260
|
+
MIN: 1,
|
|
261
|
+
MAX: 10,
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
// ============================================================================
|
|
267
|
+
// COMMAND TIMEOUTS (in milliseconds)
|
|
268
|
+
// ============================================================================
|
|
269
|
+
|
|
270
|
+
export const COMMAND_TIMEOUTS = {
|
|
271
|
+
LAUNCHCTL: 2000,
|
|
272
|
+
PS: 2000,
|
|
273
|
+
SYSTEM_PROFILER: 5000,
|
|
274
|
+
IOREG: 3000,
|
|
275
|
+
POWERMETRICS: 3000,
|
|
276
|
+
OPENCLAW_VERSION: 3000,
|
|
277
|
+
OPENCLAW_LOGS: 5000,
|
|
278
|
+
NVIDIA_SMI: 3000,
|
|
279
|
+
LSPCI: 3000,
|
|
280
|
+
RADEONTOP: 3000,
|
|
281
|
+
POWERSHELL: 5000, // Windows PowerShell WMI queries
|
|
282
|
+
WSL_SMI: 5000, // WSL2 nvidia-smi.exe via Windows host
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
// ============================================================================
|
|
286
|
+
// WORKER THREAD SETTINGS
|
|
287
|
+
// ============================================================================
|
|
288
|
+
|
|
289
|
+
export const WORKERS = {
|
|
290
|
+
ENABLED: true, // Enable worker threads for heavy operations
|
|
291
|
+
MAX_WORKERS: 2, // Number of worker threads to spawn
|
|
292
|
+
TASK_TIMEOUT: 10000, // Task timeout in milliseconds (10 seconds)
|
|
293
|
+
FALLBACK_ON_ERROR: true, // Fall back to direct execution if workers fail
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
// ============================================================================
|
|
297
|
+
// GRACEFUL DEGRADATION SETTINGS (Worker Pool Overload Handling)
|
|
298
|
+
// ============================================================================
|
|
299
|
+
|
|
300
|
+
export const WORKER_DEGRADATION = {
|
|
301
|
+
// Queue size thresholds
|
|
302
|
+
QUEUE: {
|
|
303
|
+
WARNING_SIZE: 10, // Warn when queue reaches this size
|
|
304
|
+
CRITICAL_SIZE: 25, // Critical when queue reaches this size
|
|
305
|
+
MAX_SIZE: 50, // Max queue size before rejecting tasks
|
|
306
|
+
},
|
|
307
|
+
// Worker utilization thresholds (percentage)
|
|
308
|
+
UTILIZATION: {
|
|
309
|
+
WARNING_PCT: 75, // Warning when utilization exceeds this
|
|
310
|
+
CRITICAL_PCT: 90, // Critical when utilization exceeds this
|
|
311
|
+
},
|
|
312
|
+
// Degradation strategies
|
|
313
|
+
STRATEGIES: {
|
|
314
|
+
// Increase timeout during overload (multiplier)
|
|
315
|
+
ADAPTIVE_TIMEOUT: {
|
|
316
|
+
ENABLED: true,
|
|
317
|
+
WARNING_MULTIPLIER: 1.5, // 1.5x timeout at warning level
|
|
318
|
+
CRITICAL_MULTIPLIER: 2.0, // 2x timeout at critical level
|
|
319
|
+
},
|
|
320
|
+
// Shed load by rejecting non-critical tasks
|
|
321
|
+
SHED_LOAD: {
|
|
322
|
+
ENABLED: true,
|
|
323
|
+
SHED_NON_CRITICAL: true, // Reject non-critical tasks when overloaded
|
|
324
|
+
},
|
|
325
|
+
// Circuit breaker for repeated failures
|
|
326
|
+
CIRCUIT_BREAKER: {
|
|
327
|
+
ENABLED: true,
|
|
328
|
+
FAILURE_THRESHOLD: 5, // Open circuit after N consecutive failures
|
|
329
|
+
RESET_TIMEOUT_MS: 30000, // Try to close circuit after 30s
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
// Recovery settings
|
|
333
|
+
RECOVERY: {
|
|
334
|
+
COOLDOWN_MS: 5000, // Time before lowering degradation level
|
|
335
|
+
MIN_NORMAL_OPERATIONS: 5, // Successful ops before marking healthy
|
|
336
|
+
},
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
// ============================================================================
|
|
340
|
+
// WORKER POOL OVERLOAD SETTINGS
|
|
341
|
+
// ============================================================================
|
|
342
|
+
|
|
343
|
+
export const WORKER_OVERLOAD = {
|
|
344
|
+
// Queue size thresholds
|
|
345
|
+
QUEUE: {
|
|
346
|
+
WARNING_SIZE: 10, // Warning when queue reaches this size
|
|
347
|
+
CRITICAL_SIZE: 25, // Critical when queue reaches this size
|
|
348
|
+
MAX_SIZE: 50, // Maximum queue size (reject new tasks when exceeded)
|
|
349
|
+
},
|
|
350
|
+
// Degradation levels
|
|
351
|
+
DEGRADATION: {
|
|
352
|
+
NONE: 'none',
|
|
353
|
+
PARTIAL: 'partial', // Queue warning threshold exceeded
|
|
354
|
+
SEVERE: 'severe', // Queue critical threshold exceeded
|
|
355
|
+
CRITICAL: 'critical', // Queue max threshold exceeded
|
|
356
|
+
},
|
|
357
|
+
// Adaptive timeout settings
|
|
358
|
+
TIMEOUTS: {
|
|
359
|
+
// Extend timeouts as degradation increases
|
|
360
|
+
PARTIAL_MULTIPLIER: 1.2, // 20% longer timeouts
|
|
361
|
+
SEVERE_MULTIPLIER: 1.5, // 50% longer timeouts
|
|
362
|
+
CRITICAL_MULTIPLIER: 2.0, // 100% longer timeouts (double)
|
|
363
|
+
},
|
|
364
|
+
// Recovery settings
|
|
365
|
+
RECOVERY: {
|
|
366
|
+
COOL_DOWN_MS: 5000, // Time before attempting to recover from overload
|
|
367
|
+
CHECK_INTERVAL_MS: 1000, // How often to check for recovery
|
|
368
|
+
MIN_HEALTHY_CHECKS: 3, // Number of healthy checks before full recovery
|
|
369
|
+
},
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
// ============================================================================
|
|
373
|
+
// WEB INTERFACE SETTINGS
|
|
374
|
+
// ============================================================================
|
|
375
|
+
|
|
376
|
+
export const WEB = {
|
|
377
|
+
DEFAULT_PORT: 18790, // Default port for web interface
|
|
378
|
+
HOST: '0.0.0.0', // Bind to all interfaces by default
|
|
379
|
+
CORS_ORIGIN: '*', // CORS origin (restrict in production)
|
|
380
|
+
REQUEST_TIMEOUT: 30000, // Request timeout in milliseconds
|
|
381
|
+
REFRESH_CACHE_MS: 2000, // Cache data for 2 seconds
|
|
382
|
+
ENDPOINTS: {
|
|
383
|
+
HEALTH: '/health', // Health check endpoint
|
|
384
|
+
METRICS: '/metrics', // System metrics endpoint
|
|
385
|
+
SESSIONS: '/sessions', // Sessions list endpoint
|
|
386
|
+
AGENTS: '/agents', // Agents list endpoint
|
|
387
|
+
LOGS: '/logs', // Logs endpoint
|
|
388
|
+
STATUS: '/status', // Full dashboard status endpoint
|
|
389
|
+
},
|
|
390
|
+
// Rate limiting configuration
|
|
391
|
+
RATE_LIMIT: {
|
|
392
|
+
ENABLED: true, // Enable rate limiting by default
|
|
393
|
+
WINDOW_MS: 60000, // Time window in milliseconds (1 minute)
|
|
394
|
+
MAX_REQUESTS: 100, // Max requests per IP per window
|
|
395
|
+
TRUST_PROXY: false, // Trust X-Forwarded-For header (set true behind reverse proxy)
|
|
396
|
+
},
|
|
397
|
+
// CORS configuration
|
|
398
|
+
CORS: {
|
|
399
|
+
// Production: specify allowed origins as array (e.g., ['https://example.com'])
|
|
400
|
+
// Development: use '*' to allow all origins
|
|
401
|
+
ALLOWED_ORIGINS: '*', // Default to allow all (restrict in production)
|
|
402
|
+
ALLOWED_METHODS: ['GET', 'POST', 'OPTIONS'],
|
|
403
|
+
ALLOWED_HEADERS: ['Content-Type', 'Authorization'],
|
|
404
|
+
CREDENTIALS: false, // Allow cookies/credentials
|
|
405
|
+
MAX_AGE: 86400, // Preflight cache duration (24 hours)
|
|
406
|
+
},
|
|
407
|
+
// Authentication configuration
|
|
408
|
+
AUTH: {
|
|
409
|
+
ENABLED: false, // Disabled by default (enable explicitly)
|
|
410
|
+
HEADER_NAME: 'Authorization', // HTTP header for API key
|
|
411
|
+
SCHEME: 'Bearer', // Auth scheme (Bearer, ApiKey, etc.)
|
|
412
|
+
KEY_PREFIX: 'cd_', // Prefix for auto-generated API keys
|
|
413
|
+
KEY_LENGTH: 32, // Length of random API key
|
|
414
|
+
KEY_PATTERN: /^cd_[a-zA-Z0-9]{32}$/, // Pattern for valid keys
|
|
415
|
+
MAX_KEYS: 10, // Maximum number of API keys allowed
|
|
416
|
+
KEY_NAME_MIN_LENGTH: 1, // Minimum length for key name
|
|
417
|
+
KEY_NAME_MAX_LENGTH: 64, // Maximum length for key name
|
|
418
|
+
},
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
// ============================================================================
|
|
422
|
+
// WIDGET SETTINGS
|
|
423
|
+
// ============================================================================
|
|
424
|
+
|
|
425
|
+
export const WIDGETS = {
|
|
426
|
+
ENABLED: true, // Enable widget lazy loading
|
|
427
|
+
AUTO_DISCOVER: true, // Auto-discover plugins in plugins directory
|
|
428
|
+
PRELOAD_PRIORITY: ['cpu', 'memory', 'gpu'], // Widgets to preload immediately
|
|
429
|
+
LAZY_LOAD_DELAY: 500, // Delay before loading non-priority widgets (ms)
|
|
430
|
+
MAX_CONCURRENT_LOADS: 3, // Maximum concurrent widget loads
|
|
431
|
+
FALLBACK_ON_ERROR: true, // Fall back to default widgets if loading fails
|
|
432
|
+
CACHE_TTL: 60000, // Widget data cache TTL (ms)
|
|
433
|
+
BUILTIN: {
|
|
434
|
+
cpu: { priority: 10, lazyLoad: false },
|
|
435
|
+
memory: { priority: 20, lazyLoad: false },
|
|
436
|
+
gpu: { priority: 30, lazyLoad: false },
|
|
437
|
+
network: { priority: 40, lazyLoad: true },
|
|
438
|
+
disk: { priority: 50, lazyLoad: true },
|
|
439
|
+
system: { priority: 60, lazyLoad: true },
|
|
440
|
+
uptime: { priority: 70, lazyLoad: true },
|
|
441
|
+
dataHealth: { priority: 80, lazyLoad: true },
|
|
442
|
+
},
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
// ============================================================================
|
|
446
|
+
// WIDGET REFRESH INTERVAL SETTINGS
|
|
447
|
+
// ============================================================================
|
|
448
|
+
|
|
449
|
+
export const WIDGET_REFRESH_INTERVALS = {
|
|
450
|
+
// Per-widget refresh intervals (in milliseconds)
|
|
451
|
+
// null = use global refresh interval
|
|
452
|
+
DEFAULT: null, // Default: use global interval
|
|
453
|
+
CPU: 1000, // CPU updates frequently (1 second)
|
|
454
|
+
MEMORY: 1000, // Memory updates frequently (1 second)
|
|
455
|
+
GPU: 5000, // GPU is expensive to query (5 seconds)
|
|
456
|
+
NETWORK: 1000, // Network updates frequently (1 second)
|
|
457
|
+
DISK: 30000, // Disk rarely changes (30 seconds)
|
|
458
|
+
SYSTEM: 5000, // System info changes occasionally (5 seconds)
|
|
459
|
+
UPTIME: 60000, // Uptime only changes every minute (60 seconds)
|
|
460
|
+
DATA_HEALTH: 10000, // Data health checks every 10 seconds
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
// Widget size presets
|
|
464
|
+
export const WIDGET_SIZE_PRESETS = {
|
|
465
|
+
SMALL: 'small',
|
|
466
|
+
MEDIUM: 'medium',
|
|
467
|
+
LARGE: 'large',
|
|
468
|
+
WIDE: 'wide',
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
// Default widget sizes by type (in rows)
|
|
472
|
+
export const WIDGET_SIZES = {
|
|
473
|
+
[WIDGET_SIZE_PRESETS.SMALL]: 3,
|
|
474
|
+
[WIDGET_SIZE_PRESETS.MEDIUM]: 5,
|
|
475
|
+
[WIDGET_SIZE_PRESETS.LARGE]: 8,
|
|
476
|
+
[WIDGET_SIZE_PRESETS.WIDE]: 5, // Wide uses medium height by default
|
|
477
|
+
};
|
|
478
|
+
|
|
479
|
+
// Default widget size for each built-in widget
|
|
480
|
+
export const WIDGET_DEFAULT_SIZES = {
|
|
481
|
+
cpu: WIDGET_SIZE_PRESETS.MEDIUM,
|
|
482
|
+
mem: WIDGET_SIZE_PRESETS.MEDIUM,
|
|
483
|
+
gpu: WIDGET_SIZE_PRESETS.MEDIUM,
|
|
484
|
+
net: WIDGET_SIZE_PRESETS.MEDIUM,
|
|
485
|
+
disk: WIDGET_SIZE_PRESETS.MEDIUM,
|
|
486
|
+
sys: WIDGET_SIZE_PRESETS.MEDIUM,
|
|
487
|
+
uptime: WIDGET_SIZE_PRESETS.MEDIUM,
|
|
488
|
+
health: WIDGET_SIZE_PRESETS.MEDIUM,
|
|
489
|
+
gateway: WIDGET_SIZE_PRESETS.MEDIUM,
|
|
490
|
+
};
|
|
491
|
+
|
|
492
|
+
// Widget refresh validation constraints
|
|
493
|
+
export const WIDGET_REFRESH_VALIDATION = {
|
|
494
|
+
MIN_INTERVAL: 500, // Minimum 500ms between refreshes
|
|
495
|
+
MAX_INTERVAL: 60000, // Maximum 60 seconds between refreshes
|
|
496
|
+
ALLOWED_CUSTOM_INTERVALS: [500, 1000, 2000, 5000, 10000, 30000, 60000],
|
|
497
|
+
};
|
|
498
|
+
|
|
499
|
+
// Graceful degradation settings for widgets under worker pool overload
|
|
500
|
+
export const WIDGET_DEGRADATION = {
|
|
501
|
+
// When degradation level is WARNING
|
|
502
|
+
WARNING: {
|
|
503
|
+
SKIP_NON_CRITICAL: false, // Don't skip updates, just extend intervals
|
|
504
|
+
EXTEND_INTERVAL_MULTIPLIER: 1.5, // 1.5x refresh intervals
|
|
505
|
+
PRIORITY_THRESHOLD: 50, // Only update widgets with priority <= 50
|
|
506
|
+
},
|
|
507
|
+
// When degradation level is CRITICAL
|
|
508
|
+
CRITICAL: {
|
|
509
|
+
SKIP_NON_CRITICAL: true, // Skip non-critical widgets
|
|
510
|
+
EXTEND_INTERVAL_MULTIPLIER: 2.0, // 2x refresh intervals
|
|
511
|
+
PRIORITY_THRESHOLD: 30, // Only update widgets with priority <= 30
|
|
512
|
+
},
|
|
513
|
+
// Widget categories for degradation decisions
|
|
514
|
+
CRITICAL_WIDGETS: ['cpu', 'memory'], // Always update these if possible
|
|
515
|
+
NON_CRITICAL_WIDGETS: ['disk', 'system', 'uptime', 'dataHealth'], // Can be skipped
|
|
516
|
+
};
|
|
517
|
+
|
|
518
|
+
// ============================================================================
|
|
519
|
+
// PATH SETTINGS
|
|
520
|
+
// ============================================================================
|
|
521
|
+
|
|
522
|
+
export const PATHS = {
|
|
523
|
+
SETTINGS: os.homedir() + '/.openclaw/dashboard-settings.json',
|
|
524
|
+
STATE: os.homedir() + '/.openclaw/dashboard-state.json',
|
|
525
|
+
EXPORTS: os.homedir() + '/.openclaw/exports',
|
|
526
|
+
OPENCLAW_CONFIG: os.homedir() + '/.openclaw/openclaw.json',
|
|
527
|
+
LOG: os.homedir() + '/.openclaw/claw-dashboard.log',
|
|
528
|
+
HOME_DIR: os.homedir(),
|
|
529
|
+
OPENCLAW_DIR: os.homedir() + '/.openclaw',
|
|
530
|
+
AGENTS_DIR: os.homedir() + '/.openclaw/agents',
|
|
531
|
+
WIDGETS_DIR: os.homedir() + '/.openclaw/widgets',
|
|
532
|
+
PLUGINS_DIR: os.homedir() + '/.openclaw/plugins',
|
|
533
|
+
};
|
|
534
|
+
|
|
535
|
+
// ============================================================================
|
|
536
|
+
// AUTO-SAVE SETTINGS
|
|
537
|
+
// ============================================================================
|
|
538
|
+
|
|
539
|
+
export const AUTO_SAVE = {
|
|
540
|
+
ENABLED: true, // Enable auto-save by default
|
|
541
|
+
INTERVAL_MS: 30000, // Auto-save every 30 seconds
|
|
542
|
+
SAVE_ON_EXIT: true, // Save on graceful shutdown
|
|
543
|
+
MAX_CONSECUTIVE_FAILURES: 3, // Disable auto-save after N failures
|
|
544
|
+
BACKUP_COUNT: 3, // Keep N backup state files
|
|
545
|
+
};
|
|
546
|
+
|
|
547
|
+
// ============================================================================
|
|
548
|
+
// EXPORT SCHEDULER SETTINGS
|
|
549
|
+
// ============================================================================
|
|
550
|
+
|
|
551
|
+
export const EXPORT_SCHEDULE = {
|
|
552
|
+
ENABLED: false, // Disabled by default (must explicitly enable)
|
|
553
|
+
DEFAULT_FORMAT: 'json', // Default export format: 'json' or 'csv'
|
|
554
|
+
DEFAULT_SCHEDULE: '0 * * * *', // Default: every hour at minute 0
|
|
555
|
+
MIN_RETENTION_DAYS: 0, // Minimum retention (0 = forever)
|
|
556
|
+
MAX_RETENTION_DAYS: 365, // Maximum retention days
|
|
557
|
+
DEFAULT_RETENTION_DAYS: 30, // Default: keep 30 days of exports
|
|
558
|
+
MAX_SCHEDULED_EXPORTS_PER_DAY: 1440, // Max exports per day (once per minute)
|
|
559
|
+
};
|
|
560
|
+
|
|
561
|
+
// ============================================================================
|
|
562
|
+
// DEFAULT SETTINGS
|
|
563
|
+
// ============================================================================
|
|
564
|
+
|
|
565
|
+
export const DEFAULT_SETTINGS = {
|
|
566
|
+
refreshInterval: REFRESH_INTERVALS.DEFAULT,
|
|
567
|
+
logLevelFilter: 'all',
|
|
568
|
+
sessionSortMode: 'time',
|
|
569
|
+
showWidget1: true, // CPU
|
|
570
|
+
showWidget2: true, // Memory
|
|
571
|
+
showWidget3: true, // GPU
|
|
572
|
+
showWidget4: true, // Network
|
|
573
|
+
showWidget5: true, // Disk
|
|
574
|
+
showWidget6: true, // System
|
|
575
|
+
showWidget7: true, // Uptime
|
|
576
|
+
showWidget8: true, // Data Health
|
|
577
|
+
showWidget9: true, // Gateway Status
|
|
578
|
+
showPerformanceMetrics: false, // Show performance metrics in footer
|
|
579
|
+
theme: 'auto',
|
|
580
|
+
exportFormat: 'json',
|
|
581
|
+
exportDirectory: PATHS.EXPORTS,
|
|
582
|
+
sessionSearchQuery: '',
|
|
583
|
+
favorites: {}, // Map of sessionId -> true
|
|
584
|
+
showFavoritesOnly: false,
|
|
585
|
+
pinnedWidgets: [], // Array of widget IDs (1-9) pinned to favorites row (max 4)
|
|
586
|
+
firstRun: true, // Show tooltip hints on first run
|
|
587
|
+
gatewayEndpoints: [ // Support for multiple gateway endpoints
|
|
588
|
+
{ ...DEFAULT_GATEWAY_ENDPOINT }
|
|
589
|
+
],
|
|
590
|
+
activeGatewayEndpoint: 'local', // Currently selected/active endpoint
|
|
591
|
+
webInterface: {
|
|
592
|
+
enabled: false, // Web interface disabled by default
|
|
593
|
+
port: WEB.DEFAULT_PORT,
|
|
594
|
+
host: WEB.HOST,
|
|
595
|
+
cors: true, // Enable CORS by default
|
|
596
|
+
// CORS origins - set to specific origins in production (e.g., ['https://example.com'])
|
|
597
|
+
// Use '*' for development to allow all origins
|
|
598
|
+
corsOrigins: WEB.CORS.ALLOWED_ORIGINS,
|
|
599
|
+
// Rate limiting configuration
|
|
600
|
+
rateLimit: {
|
|
601
|
+
enabled: WEB.RATE_LIMIT.ENABLED,
|
|
602
|
+
windowMs: WEB.RATE_LIMIT.WINDOW_MS,
|
|
603
|
+
maxRequests: WEB.RATE_LIMIT.MAX_REQUESTS,
|
|
604
|
+
trustProxy: WEB.RATE_LIMIT.TRUST_PROXY,
|
|
605
|
+
},
|
|
606
|
+
// Authentication configuration
|
|
607
|
+
auth: {
|
|
608
|
+
enabled: WEB.AUTH.ENABLED, // Disabled by default - must explicitly enable
|
|
609
|
+
keys: [], // Array of { id, name, createdAt, keyHash } - keys are not stored in plain text
|
|
610
|
+
},
|
|
611
|
+
},
|
|
612
|
+
widgetLoading: {
|
|
613
|
+
enabled: true, // Enable lazy loading
|
|
614
|
+
preloadPriority: ['cpu', 'memory', 'gpu'], // Widgets to load immediately
|
|
615
|
+
lazyLoadDelay: 500, // Delay before loading other widgets
|
|
616
|
+
maxConcurrent: 3, // Max concurrent widget loads
|
|
617
|
+
autoDiscover: true, // Auto-discover plugins
|
|
618
|
+
},
|
|
619
|
+
widgetSizes: {}, // Map of widget name -> size preset (small, medium, large, wide)
|
|
620
|
+
plugins: {}, // Plugin-specific configurations
|
|
621
|
+
autoRetry: { // Auto-retry configuration for gateway connectivity
|
|
622
|
+
enabled: AUTO_RETRY.ENABLED,
|
|
623
|
+
intervalMs: AUTO_RETRY.DEFAULT_INTERVAL_MS,
|
|
624
|
+
exponentialBackoff: AUTO_RETRY.EXPONENTIAL_BACKOFF,
|
|
625
|
+
backoffMultiplier: AUTO_RETRY.BACKOFF_MULTIPLIER,
|
|
626
|
+
maxBackoffIntervalMs: AUTO_RETRY.MAX_BACKOFF_INTERVAL_MS,
|
|
627
|
+
resetAfterSuccess: AUTO_RETRY.RESET_AFTER_SUCCESS,
|
|
628
|
+
consecutiveFailureThreshold: AUTO_RETRY.CONSECUTIVE_FAILURE_THRESHOLD,
|
|
629
|
+
},
|
|
630
|
+
autoSave: { // Dashboard auto-save configuration
|
|
631
|
+
enabled: AUTO_SAVE.ENABLED,
|
|
632
|
+
intervalMs: AUTO_SAVE.INTERVAL_MS,
|
|
633
|
+
saveOnExit: AUTO_SAVE.SAVE_ON_EXIT,
|
|
634
|
+
},
|
|
635
|
+
exportSchedule: { // Scheduled metric exports configuration
|
|
636
|
+
enabled: EXPORT_SCHEDULE.ENABLED,
|
|
637
|
+
format: EXPORT_SCHEDULE.DEFAULT_FORMAT,
|
|
638
|
+
schedule: EXPORT_SCHEDULE.DEFAULT_SCHEDULE,
|
|
639
|
+
retentionDays: EXPORT_SCHEDULE.DEFAULT_RETENTION_DAYS,
|
|
640
|
+
directory: null, // null = use default snapshots directory
|
|
641
|
+
includeMetrics: true,
|
|
642
|
+
},
|
|
643
|
+
};
|
|
644
|
+
|
|
645
|
+
// ============================================================================
|
|
646
|
+
// EXPORT DEFAULT OBJECT (for backward compatibility)
|
|
647
|
+
// ============================================================================
|
|
648
|
+
|
|
649
|
+
export default {
|
|
650
|
+
REFRESH_INTERVALS,
|
|
651
|
+
IDLE_THRESHOLD_MS,
|
|
652
|
+
HISTORY,
|
|
653
|
+
GATEWAY,
|
|
654
|
+
DEFAULT_GATEWAY_ENDPOINT,
|
|
655
|
+
CHECKSUM,
|
|
656
|
+
UI,
|
|
657
|
+
CACHE_TTL,
|
|
658
|
+
CACHE_CONFIG,
|
|
659
|
+
DATABASE,
|
|
660
|
+
RETRY,
|
|
661
|
+
DEFAULT_RETRY_OPTIONS,
|
|
662
|
+
AUTO_RETRY,
|
|
663
|
+
AUTO_SAVE,
|
|
664
|
+
EXPORT_SCHEDULE,
|
|
665
|
+
ALERT_THRESHOLDS,
|
|
666
|
+
ALERT_RATE_LIMIT,
|
|
667
|
+
MAX_ALERT_HISTORY,
|
|
668
|
+
MEMORY_PRESSURE,
|
|
669
|
+
VALIDATION,
|
|
670
|
+
COMMAND_TIMEOUTS,
|
|
671
|
+
PATHS,
|
|
672
|
+
DEFAULT_SETTINGS,
|
|
673
|
+
WORKERS,
|
|
674
|
+
WORKER_DEGRADATION,
|
|
675
|
+
WEB,
|
|
676
|
+
WIDGETS,
|
|
677
|
+
WIDGET_REFRESH_INTERVALS,
|
|
678
|
+
WIDGET_REFRESH_VALIDATION,
|
|
679
|
+
WIDGET_DEGRADATION,
|
|
680
|
+
WIDGET_SIZE_PRESETS,
|
|
681
|
+
WIDGET_SIZES,
|
|
682
|
+
WIDGET_DEFAULT_SIZES,
|
|
683
|
+
DASHBOARD_VERSION,
|
|
684
|
+
};
|