@jango-blockchained/hoox-cli 0.5.1 → 0.5.6

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.
Files changed (106) hide show
  1. package/bin/hoox.js +3 -4
  2. package/dist/index.js +32545 -0
  3. package/package.json +10 -15
  4. package/src/commands/check/check-command.test.ts +0 -476
  5. package/src/commands/check/check-command.ts +0 -1144
  6. package/src/commands/check/index.ts +0 -10
  7. package/src/commands/check/prerequisites-command.test.ts +0 -19
  8. package/src/commands/check/prerequisites-command.ts +0 -96
  9. package/src/commands/check/types.ts +0 -103
  10. package/src/commands/clone/clone-command.test.ts +0 -442
  11. package/src/commands/clone/clone-command.ts +0 -431
  12. package/src/commands/clone/index.ts +0 -1
  13. package/src/commands/config/config-command.test.ts +0 -583
  14. package/src/commands/config/config-command.ts +0 -897
  15. package/src/commands/config/env-command.test.ts +0 -43
  16. package/src/commands/config/env-command.ts +0 -295
  17. package/src/commands/config/index.ts +0 -3
  18. package/src/commands/config/kv-command.test.ts +0 -14
  19. package/src/commands/config/kv-command.ts +0 -290
  20. package/src/commands/dashboard/dashboard-command.test.ts +0 -47
  21. package/src/commands/dashboard/dashboard-command.ts +0 -128
  22. package/src/commands/dashboard/index.ts +0 -1
  23. package/src/commands/db/db-command.test.ts +0 -21
  24. package/src/commands/db/db-command.ts +0 -312
  25. package/src/commands/db/index.ts +0 -1
  26. package/src/commands/deploy/deploy-command.test.ts +0 -304
  27. package/src/commands/deploy/deploy-command.ts +0 -1135
  28. package/src/commands/deploy/index.ts +0 -2
  29. package/src/commands/deploy/telegram-service.ts +0 -76
  30. package/src/commands/deploy/types.ts +0 -34
  31. package/src/commands/dev/dev-command.test.ts +0 -383
  32. package/src/commands/dev/dev-command.ts +0 -398
  33. package/src/commands/dev/index.ts +0 -1
  34. package/src/commands/infra/index.ts +0 -5
  35. package/src/commands/infra/infra-command.test.ts +0 -719
  36. package/src/commands/infra/infra-command.ts +0 -974
  37. package/src/commands/infra/types.ts +0 -23
  38. package/src/commands/init/__tests__/cli-provisioner.test.ts +0 -17
  39. package/src/commands/init/cli-provisioner.ts +0 -71
  40. package/src/commands/init/index.ts +0 -1
  41. package/src/commands/init/init-command.test.ts +0 -876
  42. package/src/commands/init/init-command.ts +0 -593
  43. package/src/commands/init/types.ts +0 -23
  44. package/src/commands/logs/index.ts +0 -1
  45. package/src/commands/logs/logs-command.test.ts +0 -294
  46. package/src/commands/logs/logs-command.ts +0 -452
  47. package/src/commands/monitor/index.ts +0 -2
  48. package/src/commands/monitor/monitor-command.test.ts +0 -263
  49. package/src/commands/monitor/monitor-command.ts +0 -269
  50. package/src/commands/monitor/monitor-service.ts +0 -65
  51. package/src/commands/monitor/types.ts +0 -13
  52. package/src/commands/repair/index.ts +0 -2
  53. package/src/commands/repair/repair-command.test.ts +0 -224
  54. package/src/commands/repair/repair-command.ts +0 -220
  55. package/src/commands/repair/repair-service.ts +0 -138
  56. package/src/commands/repair/types.ts +0 -13
  57. package/src/commands/test/index.ts +0 -2
  58. package/src/commands/test/test-command.test.ts +0 -319
  59. package/src/commands/test/test-command.ts +0 -406
  60. package/src/commands/tui/index.ts +0 -1
  61. package/src/commands/tui/tui-command.ts +0 -87
  62. package/src/commands/update/index.ts +0 -1
  63. package/src/commands/update/update-command.ts +0 -168
  64. package/src/commands/waf/index.ts +0 -2
  65. package/src/commands/waf/types.ts +0 -48
  66. package/src/commands/waf/waf-command.test.ts +0 -506
  67. package/src/commands/waf/waf-command.ts +0 -548
  68. package/src/index.ts +0 -269
  69. package/src/services/cloudflare/cloudflare-service.test.ts +0 -658
  70. package/src/services/cloudflare/cloudflare-service.ts +0 -433
  71. package/src/services/cloudflare/index.ts +0 -2
  72. package/src/services/cloudflare/types.ts +0 -30
  73. package/src/services/config/config-service.test.ts +0 -395
  74. package/src/services/config/config-service.ts +0 -207
  75. package/src/services/config/index.ts +0 -9
  76. package/src/services/config/types.ts +0 -66
  77. package/src/services/db/db-service.test.ts +0 -51
  78. package/src/services/db/db-service.ts +0 -131
  79. package/src/services/db/index.ts +0 -1
  80. package/src/services/docker/docker-service.ts +0 -155
  81. package/src/services/docker/index.ts +0 -1
  82. package/src/services/env/env-service.test.ts +0 -236
  83. package/src/services/env/env-service.ts +0 -386
  84. package/src/services/env/index.ts +0 -1
  85. package/src/services/kv/index.ts +0 -1
  86. package/src/services/kv/kv-sync-service.test.ts +0 -38
  87. package/src/services/kv/kv-sync-service.ts +0 -234
  88. package/src/services/prerequisites/index.ts +0 -1
  89. package/src/services/prerequisites/prerequisites-service.test.ts +0 -89
  90. package/src/services/prerequisites/prerequisites-service.ts +0 -377
  91. package/src/services/prerequisites/types.ts +0 -48
  92. package/src/services/secrets/index.ts +0 -11
  93. package/src/services/secrets/secrets-service.test.ts +0 -495
  94. package/src/services/secrets/secrets-service.ts +0 -287
  95. package/src/services/secrets/types.ts +0 -50
  96. package/src/services/update/index.ts +0 -2
  97. package/src/services/update/update-service.test.ts +0 -76
  98. package/src/services/update/update-service.ts +0 -193
  99. package/src/ui/banner.ts +0 -141
  100. package/src/ui/index.ts +0 -8
  101. package/src/ui/menu.ts +0 -490
  102. package/src/utils/errors.test.ts +0 -69
  103. package/src/utils/errors.ts +0 -23
  104. package/src/utils/formatters.test.ts +0 -180
  105. package/src/utils/formatters.ts +0 -269
  106. package/src/utils/theme.ts +0 -94
@@ -1,386 +0,0 @@
1
- export interface EnvVarDefinition {
2
- name: string;
3
- required: boolean;
4
- secret: boolean;
5
- section: string;
6
- default?: string;
7
- hint?: string;
8
- }
9
-
10
- /** A .env file with its path and parsed variables. */
11
- export interface EnvFile {
12
- path: string;
13
- vars: Record<string, string>;
14
- }
15
-
16
- export interface EnvValidationResult {
17
- missing: string[];
18
- warnings: string[];
19
- }
20
-
21
- export class EnvService {
22
- static getDefinitions(): EnvVarDefinition[] {
23
- return [
24
- {
25
- name: "CLOUDFLARE_API_TOKEN",
26
- required: true,
27
- secret: true,
28
- section: "Cloudflare Account",
29
- hint: "API token with Workers/KV/D1/R2 permissions",
30
- },
31
- {
32
- name: "CLOUDFLARE_ACCOUNT_ID",
33
- required: true,
34
- secret: false,
35
- section: "Cloudflare Account",
36
- hint: "From Cloudflare dashboard URL",
37
- },
38
- {
39
- name: "CLOUDFLARE_SECRET_STORE_ID",
40
- required: false,
41
- secret: false,
42
- section: "Cloudflare Account",
43
- default: "",
44
- hint: "Optional",
45
- },
46
- {
47
- name: "SUBDOMAIN_PREFIX",
48
- required: true,
49
- secret: false,
50
- section: "Cloudflare Account",
51
- default: "cryptolinx",
52
- hint: "Prefix for worker URLs",
53
- },
54
- {
55
- name: "D1_INTERNAL_KEY",
56
- required: true,
57
- secret: true,
58
- section: "Internal Auth",
59
- hint: "Internal key for D1 worker auth",
60
- },
61
- {
62
- name: "TRADE_INTERNAL_KEY",
63
- required: true,
64
- secret: true,
65
- section: "Internal Auth",
66
- hint: "Internal key for trade worker auth",
67
- },
68
- {
69
- name: "AGENT_INTERNAL_KEY",
70
- required: true,
71
- secret: true,
72
- section: "Internal Auth",
73
- hint: "Internal key for agent worker auth",
74
- },
75
- {
76
- name: "WEBHOOK_API_KEY_BINDING",
77
- required: true,
78
- secret: true,
79
- section: "Internal Auth",
80
- hint: "Webhook auth key for hoox gateway",
81
- },
82
- {
83
- name: "INTERNAL_KEY_BINDING",
84
- required: true,
85
- secret: true,
86
- section: "Internal Auth",
87
- hint: "Shared internal auth key for inter-worker communication",
88
- },
89
- {
90
- name: "API_SERVICE_KEY",
91
- required: true,
92
- secret: true,
93
- section: "Internal Auth",
94
- hint: "API service key for trade-worker",
95
- },
96
- {
97
- name: "HA_TOKEN_BINDING",
98
- required: false,
99
- secret: true,
100
- section: "Internal Auth",
101
- hint: "Home Assistant token for hoox",
102
- },
103
- {
104
- name: "TELEGRAM_BOT_TOKEN",
105
- required: false,
106
- secret: true,
107
- section: "Telegram",
108
- hint: "From @BotFather",
109
- },
110
- {
111
- name: "TELEGRAM_SECRET_TOKEN",
112
- required: false,
113
- secret: true,
114
- section: "Telegram",
115
- hint: "Telegram webhook secret token",
116
- },
117
- {
118
- name: "AGENT_OPENAI_KEY",
119
- required: false,
120
- secret: true,
121
- section: "AI Providers",
122
- hint: "OpenAI API key",
123
- },
124
- {
125
- name: "AGENT_ANTHROPIC_KEY",
126
- required: false,
127
- secret: true,
128
- section: "AI Providers",
129
- hint: "Anthropic API key",
130
- },
131
- {
132
- name: "AGENT_GOOGLE_KEY",
133
- required: false,
134
- secret: true,
135
- section: "AI Providers",
136
- hint: "Google AI API key",
137
- },
138
- {
139
- name: "BINANCE_API_KEY",
140
- required: false,
141
- secret: true,
142
- section: "Exchanges",
143
- hint: "Binance API key",
144
- },
145
- {
146
- name: "BINANCE_API_SECRET",
147
- required: false,
148
- secret: true,
149
- section: "Exchanges",
150
- hint: "Binance API secret",
151
- },
152
- {
153
- name: "MEXC_API_KEY",
154
- required: false,
155
- secret: true,
156
- section: "Exchanges",
157
- hint: "MEXC API key",
158
- },
159
- {
160
- name: "MEXC_API_SECRET",
161
- required: false,
162
- secret: true,
163
- section: "Exchanges",
164
- hint: "MEXC API secret",
165
- },
166
- {
167
- name: "BYBIT_API_KEY",
168
- required: false,
169
- secret: true,
170
- section: "Exchanges",
171
- hint: "Bybit API key",
172
- },
173
- {
174
- name: "BYBIT_API_SECRET",
175
- required: false,
176
- secret: true,
177
- section: "Exchanges",
178
- hint: "Bybit API secret",
179
- },
180
- // Email
181
- {
182
- name: "EMAIL_HOST",
183
- required: false,
184
- secret: true,
185
- section: "Email",
186
- hint: "Email IMAP server host",
187
- },
188
- {
189
- name: "EMAIL_USER",
190
- required: false,
191
- secret: true,
192
- section: "Email",
193
- hint: "Email IMAP username",
194
- },
195
- {
196
- name: "EMAIL_PASS",
197
- required: false,
198
- secret: true,
199
- section: "Email",
200
- hint: "Email IMAP password",
201
- },
202
- {
203
- name: "INTERNAL_KEY",
204
- required: false,
205
- secret: true,
206
- section: "Email",
207
- hint: "Internal auth key for email-worker",
208
- },
209
- // Wallet
210
- {
211
- name: "WALLET_MNEMONIC_SECRET",
212
- required: false,
213
- secret: true,
214
- section: "Wallet",
215
- hint: "Wallet mnemonic phrase for web3-wallet-worker",
216
- },
217
- {
218
- name: "WALLET_PK_SECRET",
219
- required: false,
220
- secret: true,
221
- section: "Wallet",
222
- hint: "Wallet private key for web3-wallet-worker",
223
- },
224
- {
225
- name: "DASHBOARD_USER",
226
- required: true,
227
- secret: false,
228
- section: "Dashboard",
229
- default: "admin",
230
- hint: "Dashboard login username",
231
- },
232
- {
233
- name: "DASHBOARD_PASS",
234
- required: true,
235
- secret: true,
236
- section: "Dashboard",
237
- hint: "Dashboard login password",
238
- },
239
- {
240
- name: "SESSION_SECRET",
241
- required: true,
242
- secret: true,
243
- section: "Dashboard",
244
- hint: "32+ char random string for session signing",
245
- },
246
- ];
247
- }
248
-
249
- static getSections(): string[] {
250
- return [...new Set(EnvService.getDefinitions().map((d) => d.section))];
251
- }
252
-
253
- static async loadDotEnvAsync(
254
- filePath: string
255
- ): Promise<Record<string, string>> {
256
- const file = Bun.file(filePath);
257
- if (!(await file.exists())) return {};
258
- const text = await file.text();
259
- const vars: Record<string, string> = {};
260
- for (const line of text.split("\n")) {
261
- const trimmed = line.trim();
262
- if (trimmed === "" || trimmed.startsWith("#")) continue;
263
- const eqIdx = trimmed.indexOf("=");
264
- if (eqIdx < 1) continue;
265
- const key = trimmed.substring(0, eqIdx).trim();
266
- let value = trimmed.substring(eqIdx + 1).trim();
267
- if (
268
- (value.startsWith('"') && value.endsWith('"')) ||
269
- (value.startsWith("'") && value.endsWith("'"))
270
- ) {
271
- value = value.slice(1, -1);
272
- }
273
- vars[key] = value;
274
- }
275
- return vars;
276
- }
277
-
278
- static validate(vars: Record<string, string>): EnvValidationResult {
279
- const missing: string[] = [];
280
- const warnings: string[] = [];
281
- for (const def of EnvService.getDefinitions()) {
282
- if (def.required) {
283
- const val = vars[def.name];
284
- if (!val || val.startsWith("your_") || val.startsWith("generate_")) {
285
- missing.push(def.name);
286
- }
287
- }
288
- }
289
- if (vars.SESSION_SECRET && vars.SESSION_SECRET.length < 32) {
290
- warnings.push("SESSION_SECRET should be at least 32 characters");
291
- }
292
- return { missing, warnings };
293
- }
294
-
295
- static generateEnvLocal(vars?: Record<string, string>): string {
296
- const v = vars ?? {};
297
- const defs = EnvService.getDefinitions();
298
- const sections = EnvService.getSections();
299
- let output =
300
- "# Hoox Local Environment Configuration\n# Generated by `hoox config env init`.\n# NEVER commit this file.\n\n";
301
- for (const section of sections) {
302
- output += `# --- ${section.toUpperCase()} ---\n`;
303
- for (const def of defs.filter((d) => d.section === section)) {
304
- const val =
305
- v[def.name] !== undefined
306
- ? v[def.name]
307
- : (def.default ?? `your_${def.name.toLowerCase()}`);
308
- output += `${def.name}="${val}"\n`;
309
- }
310
- output += "\n";
311
- }
312
- return output;
313
- }
314
-
315
- static getWorkerDevVars(
316
- vars: Record<string, string>
317
- ): Record<string, Record<string, string>> {
318
- const workerMap: Record<string, string[]> = {
319
- "workers/hoox": [
320
- "WEBHOOK_API_KEY_BINDING",
321
- "INTERNAL_KEY_BINDING",
322
- "HA_TOKEN_BINDING",
323
- ],
324
- "workers/trade-worker": [
325
- "API_SERVICE_KEY",
326
- "INTERNAL_KEY_BINDING",
327
- "BINANCE_API_KEY",
328
- "BINANCE_API_SECRET",
329
- "MEXC_API_KEY",
330
- "MEXC_API_SECRET",
331
- "BYBIT_API_KEY",
332
- "BYBIT_API_SECRET",
333
- ],
334
- "workers/agent-worker": [
335
- "AGENT_INTERNAL_KEY",
336
- "AGENT_OPENAI_KEY",
337
- "AGENT_ANTHROPIC_KEY",
338
- "AGENT_GOOGLE_KEY",
339
- ],
340
- "workers/d1-worker": ["D1_INTERNAL_KEY"],
341
- "workers/telegram-worker": [
342
- "TELEGRAM_BOT_TOKEN",
343
- "TELEGRAM_SECRET_TOKEN",
344
- ],
345
- "workers/web3-wallet-worker": [
346
- "WALLET_MNEMONIC_SECRET",
347
- "WALLET_PK_SECRET",
348
- ],
349
- "workers/email-worker": [
350
- "EMAIL_HOST",
351
- "EMAIL_USER",
352
- "EMAIL_PASS",
353
- "INTERNAL_KEY",
354
- ],
355
- "workers/analytics-worker": ["CLOUDFLARE_API_TOKEN"],
356
- };
357
- const result: Record<string, Record<string, string>> = {};
358
- for (const [workerPath, varNames] of Object.entries(workerMap)) {
359
- const workerVars: Record<string, string> = {};
360
- for (const name of varNames) {
361
- if (vars[name] !== undefined && vars[name] !== "") {
362
- workerVars[name] = vars[name];
363
- }
364
- }
365
- if (Object.keys(workerVars).length > 0) result[workerPath] = workerVars;
366
- }
367
- return result;
368
- }
369
-
370
- static show(vars: Record<string, string>): string {
371
- const defs = EnvService.getDefinitions();
372
- const sections = EnvService.getSections();
373
- let output = "";
374
- for (const section of sections) {
375
- output += `\n${section}:\n`;
376
- for (const def of defs.filter((d) => d.section === section)) {
377
- const val = vars[def.name];
378
- const displayVal =
379
- def.secret && val ? "********" : (val ?? "(not set)");
380
- const status = val ? " [set]" : " [missing]";
381
- output += ` ${def.name}=${displayVal}${def.secret ? " (secret)" : ""}${status}\n`;
382
- }
383
- }
384
- return output;
385
- }
386
- }
@@ -1 +0,0 @@
1
- export { EnvService } from "./env-service.js";
@@ -1 +0,0 @@
1
- export { KvSyncService } from "./kv-sync-service.js";
@@ -1,38 +0,0 @@
1
- import { describe, expect, it } from "bun:test";
2
- import { KvSyncService } from "./kv-sync-service.js";
3
-
4
- describe("KvSyncService", () => {
5
- describe("getManifest", () => {
6
- it("returns manifest with CONFIG_KV namespace", () => {
7
- const manifest = KvSyncService.getManifest();
8
- expect(manifest.namespace).toBe("CONFIG_KV");
9
- expect(manifest.keys.length).toBeGreaterThan(10);
10
- });
11
-
12
- it("each key has required fields", () => {
13
- for (const key of KvSyncService.getManifestKeys()) {
14
- expect(key.key).toBeTruthy();
15
- expect(["boolean", "number", "string"]).toContain(key.type);
16
- expect(key.description).toBeTruthy();
17
- expect(typeof key.default).toBe("string");
18
- }
19
- });
20
-
21
- it("includes known critical keys", () => {
22
- const keys = KvSyncService.getManifestKeys().map((k) => k.key);
23
- expect(keys).toContain("trade:kill_switch");
24
- expect(keys).toContain("trade:max_daily_drawdown_percent");
25
- expect(keys).toContain("agent:openai_key");
26
- expect(keys).toContain("email:use_imap");
27
- });
28
-
29
- it("returns exactly 16 manifest keys", () => {
30
- expect(KvSyncService.getManifestKeys().length).toBe(16);
31
- });
32
-
33
- it("has no duplicates", () => {
34
- const keys = KvSyncService.getManifestKeys().map((k) => k.key);
35
- expect(new Set(keys).size).toBe(keys.length);
36
- });
37
- });
38
- });
@@ -1,234 +0,0 @@
1
- export interface KvManifestKey {
2
- key: string;
3
- type: "boolean" | "number" | "string";
4
- default: string;
5
- description: string;
6
- secret?: boolean;
7
- }
8
-
9
- export interface KvManifest {
10
- namespace: string;
11
- keys: KvManifestKey[];
12
- }
13
-
14
- export class KvSyncService {
15
- async resolveNamespaceId(namespaceId?: string): Promise<string> {
16
- if (namespaceId) return namespaceId;
17
-
18
- try {
19
- const proc = Bun.spawn(["wrangler", "kv:namespace", "list"], {
20
- stdout: "pipe",
21
- stderr: "pipe",
22
- });
23
- const stdout = await new Response(proc.stdout).text();
24
- const exitCode = await proc.exited;
25
-
26
- if (exitCode === 0) {
27
- try {
28
- const namespaces = JSON.parse(stdout) as Array<{
29
- id: string;
30
- title: string;
31
- }>;
32
- const configKv = namespaces.find((n) => n.title === "CONFIG_KV");
33
- if (configKv) return configKv.id;
34
- } catch {
35
- // Not JSON — skip
36
- }
37
- }
38
- } catch {
39
- // wrangler not available
40
- }
41
-
42
- throw new Error(
43
- "Could not resolve CONFIG_KV namespace ID. Provide --namespace-id flag."
44
- );
45
- }
46
-
47
- async list(namespaceId: string): Promise<Array<{ name: string }>> {
48
- const proc = Bun.spawn(
49
- ["wrangler", "kv:key", "list", "--namespace-id", namespaceId],
50
- { stdout: "pipe", stderr: "pipe" }
51
- );
52
- const stdout = await new Response(proc.stdout).text();
53
- const exitCode = await proc.exited;
54
-
55
- if (exitCode !== 0) {
56
- throw new Error(
57
- `Failed to list KV keys: ${stdout.trim() || `exit ${exitCode}`}`
58
- );
59
- }
60
-
61
- try {
62
- const parsed = JSON.parse(stdout) as Array<{ name: string }>;
63
- return parsed;
64
- } catch {
65
- return stdout
66
- .split("\n")
67
- .filter(Boolean)
68
- .map((name) => ({ name: name.trim() }));
69
- }
70
- }
71
-
72
- async get(namespaceId: string, key: string): Promise<string | null> {
73
- const proc = Bun.spawn(
74
- ["wrangler", "kv:key", "get", "--namespace-id", namespaceId, key],
75
- { stdout: "pipe", stderr: "pipe" }
76
- );
77
- const stdout = await new Response(proc.stdout).text();
78
- const stderr = await new Response(proc.stderr).text();
79
- const exitCode = await proc.exited;
80
-
81
- if (exitCode !== 0) {
82
- if (stderr.includes("not found")) return null;
83
- throw new Error(
84
- `Failed to get key "${key}": ${stderr.trim() || `exit ${exitCode}`}`
85
- );
86
- }
87
-
88
- return stdout.trim() || null;
89
- }
90
-
91
- async set(namespaceId: string, key: string, value: string): Promise<void> {
92
- const proc = Bun.spawn(
93
- ["wrangler", "kv:key", "put", "--namespace-id", namespaceId, key, value],
94
- { stdout: "pipe", stderr: "pipe" }
95
- );
96
- const exitCode = await proc.exited;
97
- const stderr = await new Response(proc.stderr).text();
98
-
99
- if (exitCode !== 0) {
100
- throw new Error(
101
- `Failed to set key "${key}": ${stderr.trim() || `exit ${exitCode}`}`
102
- );
103
- }
104
- }
105
-
106
- async delete(namespaceId: string, key: string): Promise<void> {
107
- const proc = Bun.spawn(
108
- ["wrangler", "kv:key", "delete", "--namespace-id", namespaceId, key],
109
- { stdout: "pipe", stderr: "pipe" }
110
- );
111
- const exitCode = await proc.exited;
112
- const stderr = await new Response(proc.stderr).text();
113
-
114
- if (exitCode !== 0) {
115
- throw new Error(
116
- `Failed to delete key "${key}": ${stderr.trim() || `exit ${exitCode}`}`
117
- );
118
- }
119
- }
120
-
121
- static getManifest(): KvManifest {
122
- return {
123
- namespace: "CONFIG_KV",
124
- keys: [
125
- {
126
- key: "webhook:tradingview:ip_check_enabled",
127
- type: "boolean",
128
- default: "false",
129
- description: "Enable TradingView IP allowlist check",
130
- },
131
- {
132
- key: "webhook:allowed_ips",
133
- type: "string",
134
- default: "",
135
- description: "Comma-separated allowed IPs for webhook",
136
- },
137
- {
138
- key: "routing:dynamic:enabled",
139
- type: "boolean",
140
- default: "false",
141
- description: "Enable dynamic routing",
142
- },
143
- {
144
- key: "trade:max_daily_drawdown_percent",
145
- type: "number",
146
- default: "10",
147
- description: "Max daily loss percentage before halt",
148
- },
149
- {
150
- key: "trade:kill_switch",
151
- type: "boolean",
152
- default: "false",
153
- description: "Emergency stop all trading",
154
- },
155
- {
156
- key: "trade:watermark:{exchange}:{symbol}:{side}",
157
- type: "number",
158
- default: "",
159
- description: "Per-market watermark (template key)",
160
- secret: true,
161
- },
162
- {
163
- key: "agent:openai_key",
164
- type: "string",
165
- default: "",
166
- description: "OpenAI API key for AI agent",
167
- secret: true,
168
- },
169
- {
170
- key: "agent:anthropic_key",
171
- type: "string",
172
- default: "",
173
- description: "Anthropic API key for AI agent",
174
- secret: true,
175
- },
176
- {
177
- key: "agent:google_key",
178
- type: "string",
179
- default: "",
180
- description: "Google AI API key for agent",
181
- secret: true,
182
- },
183
- {
184
- key: "agent:azure_api_key",
185
- type: "string",
186
- default: "",
187
- description: "Azure OpenAI API key",
188
- secret: true,
189
- },
190
- {
191
- key: "agent:azure_endpoint",
192
- type: "string",
193
- default: "",
194
- description: "Azure OpenAI endpoint",
195
- secret: true,
196
- },
197
- {
198
- key: "email:scan_subject",
199
- type: "string",
200
- default: "",
201
- description: "Email subject filter for signal scanning",
202
- },
203
- {
204
- key: "email:coin_pattern",
205
- type: "string",
206
- default: "",
207
- description: "Regex pattern to extract coin from email",
208
- },
209
- {
210
- key: "email:action_pattern",
211
- type: "string",
212
- default: "",
213
- description: "Regex pattern to extract action from email",
214
- },
215
- {
216
- key: "email:quantity_multiplier",
217
- type: "number",
218
- default: "1",
219
- description: "Multiplier for email signal quantity",
220
- },
221
- {
222
- key: "email:use_imap",
223
- type: "boolean",
224
- default: "false",
225
- description: "Use IMAP for email scanning",
226
- },
227
- ],
228
- };
229
- }
230
-
231
- static getManifestKeys(): KvManifestKey[] {
232
- return KvSyncService.getManifest().keys;
233
- }
234
- }
@@ -1 +0,0 @@
1
- export { PrerequisitesService } from "./prerequisites-service.js";