@jango-blockchained/hoox-cli 0.5.2 → 0.5.7

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