@marcopeg/hal 1.0.22 → 1.0.25
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/README.md +9 -12
- package/dist/bot/commands/engine-callback.d.ts +4 -0
- package/dist/bot/commands/engine-callback.d.ts.map +1 -0
- package/dist/bot/commands/engine-callback.js +39 -0
- package/dist/bot/commands/engine-callback.js.map +1 -0
- package/dist/bot/commands/engine.d.ts +4 -0
- package/dist/bot/commands/engine.d.ts.map +1 -0
- package/dist/bot/commands/engine.js +65 -0
- package/dist/bot/commands/engine.js.map +1 -0
- package/dist/bot/commands/loader.d.ts +18 -1
- package/dist/bot/commands/loader.d.ts.map +1 -1
- package/dist/bot/commands/loader.js +39 -7
- package/dist/bot/commands/loader.js.map +1 -1
- package/dist/bot/commands/message.d.ts.map +1 -1
- package/dist/bot/commands/message.js +2 -1
- package/dist/bot/commands/message.js.map +1 -1
- package/dist/bot/commands/model-callback.d.ts.map +1 -1
- package/dist/bot/commands/model-callback.js +6 -1
- package/dist/bot/commands/model-callback.js.map +1 -1
- package/dist/bot/commands/model.d.ts.map +1 -1
- package/dist/bot/commands/model.js +15 -2
- package/dist/bot/commands/model.js.map +1 -1
- package/dist/bot/commands/watcher.d.ts.map +1 -1
- package/dist/bot/commands/watcher.js +13 -4
- package/dist/bot/commands/watcher.js.map +1 -1
- package/dist/bot.d.ts.map +1 -1
- package/dist/bot.js +22 -4
- package/dist/bot.js.map +1 -1
- package/dist/cli.js +19 -16
- package/dist/cli.js.map +1 -1
- package/dist/config-writer.d.ts +2 -6
- package/dist/config-writer.d.ts.map +1 -1
- package/dist/config-writer.js +32 -28
- package/dist/config-writer.js.map +1 -1
- package/dist/config.d.ts +103 -56
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +141 -46
- package/dist/config.js.map +1 -1
- package/dist/engine/adapters/codex.d.ts.map +1 -1
- package/dist/engine/adapters/codex.js +4 -2
- package/dist/engine/adapters/codex.js.map +1 -1
- package/dist/engine/adapters/copilot.d.ts.map +1 -1
- package/dist/engine/adapters/copilot.js +8 -5
- package/dist/engine/adapters/copilot.js.map +1 -1
- package/dist/engine/adapters/cursor.d.ts.map +1 -1
- package/dist/engine/adapters/cursor.js +8 -3
- package/dist/engine/adapters/cursor.js.map +1 -1
- package/dist/engine/adapters/opencode.d.ts.map +1 -1
- package/dist/engine/adapters/opencode.js +4 -2
- package/dist/engine/adapters/opencode.js.map +1 -1
- package/dist/logger.d.ts +2 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +54 -3
- package/dist/logger.js.map +1 -1
- package/dist/user/setup.d.ts.map +1 -1
- package/dist/user/setup.js +5 -1
- package/dist/user/setup.js.map +1 -1
- package/package.json +1 -1
package/dist/config.d.ts
CHANGED
|
@@ -7,6 +7,38 @@ declare const EngineNameSchema: z.ZodEnum<{
|
|
|
7
7
|
cursor: "cursor";
|
|
8
8
|
antigravity: "antigravity";
|
|
9
9
|
}>;
|
|
10
|
+
declare const ProvidersConfigSchema: z.ZodOptional<z.ZodObject<{
|
|
11
|
+
claude: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
12
|
+
name: z.ZodString;
|
|
13
|
+
description: z.ZodOptional<z.ZodString>;
|
|
14
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
15
|
+
}, z.core.$strip>>>;
|
|
16
|
+
copilot: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
17
|
+
name: z.ZodString;
|
|
18
|
+
description: z.ZodOptional<z.ZodString>;
|
|
19
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
20
|
+
}, z.core.$strip>>>;
|
|
21
|
+
codex: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
22
|
+
name: z.ZodString;
|
|
23
|
+
description: z.ZodOptional<z.ZodString>;
|
|
24
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
25
|
+
}, z.core.$strip>>>;
|
|
26
|
+
opencode: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
27
|
+
name: z.ZodString;
|
|
28
|
+
description: z.ZodOptional<z.ZodString>;
|
|
29
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
30
|
+
}, z.core.$strip>>>;
|
|
31
|
+
cursor: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
32
|
+
name: z.ZodString;
|
|
33
|
+
description: z.ZodOptional<z.ZodString>;
|
|
34
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
35
|
+
}, z.core.$strip>>>;
|
|
36
|
+
antigravity: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
37
|
+
name: z.ZodString;
|
|
38
|
+
description: z.ZodOptional<z.ZodString>;
|
|
39
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
40
|
+
}, z.core.$strip>>>;
|
|
41
|
+
}, z.core.$strip>>;
|
|
10
42
|
declare const GlobalsFileSchema: z.ZodOptional<z.ZodObject<{
|
|
11
43
|
access: z.ZodOptional<z.ZodObject<{
|
|
12
44
|
allowedUserIds: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>>;
|
|
@@ -39,32 +71,6 @@ declare const GlobalsFileSchema: z.ZodOptional<z.ZodObject<{
|
|
|
39
71
|
sandbox: z.ZodOptional<z.ZodBoolean>;
|
|
40
72
|
}, z.core.$strip>>>;
|
|
41
73
|
}, z.core.$strip>>;
|
|
42
|
-
providers: z.ZodOptional<z.ZodObject<{
|
|
43
|
-
claude: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
44
|
-
name: z.ZodString;
|
|
45
|
-
description: z.ZodOptional<z.ZodString>;
|
|
46
|
-
}, z.core.$strip>>>;
|
|
47
|
-
copilot: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
48
|
-
name: z.ZodString;
|
|
49
|
-
description: z.ZodOptional<z.ZodString>;
|
|
50
|
-
}, z.core.$strip>>>;
|
|
51
|
-
codex: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
52
|
-
name: z.ZodString;
|
|
53
|
-
description: z.ZodOptional<z.ZodString>;
|
|
54
|
-
}, z.core.$strip>>>;
|
|
55
|
-
opencode: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
56
|
-
name: z.ZodString;
|
|
57
|
-
description: z.ZodOptional<z.ZodString>;
|
|
58
|
-
}, z.core.$strip>>>;
|
|
59
|
-
cursor: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
60
|
-
name: z.ZodString;
|
|
61
|
-
description: z.ZodOptional<z.ZodString>;
|
|
62
|
-
}, z.core.$strip>>>;
|
|
63
|
-
antigravity: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
64
|
-
name: z.ZodString;
|
|
65
|
-
description: z.ZodOptional<z.ZodString>;
|
|
66
|
-
}, z.core.$strip>>>;
|
|
67
|
-
}, z.core.$strip>>;
|
|
68
74
|
logging: z.ZodOptional<z.ZodObject<{
|
|
69
75
|
level: z.ZodOptional<z.ZodEnum<{
|
|
70
76
|
debug: "debug";
|
|
@@ -138,12 +144,15 @@ declare const GlobalsFileSchema: z.ZodOptional<z.ZodObject<{
|
|
|
138
144
|
model: z.ZodOptional<z.ZodObject<{
|
|
139
145
|
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
140
146
|
}, z.core.$strip>>;
|
|
147
|
+
engine: z.ZodOptional<z.ZodObject<{
|
|
148
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
149
|
+
}, z.core.$strip>>;
|
|
141
150
|
}, z.core.$strip>>;
|
|
142
151
|
}, z.core.$strip>>;
|
|
143
152
|
declare const ProjectFileSchema: z.ZodObject<{
|
|
144
153
|
name: z.ZodOptional<z.ZodString>;
|
|
145
154
|
active: z.ZodOptional<z.ZodBoolean>;
|
|
146
|
-
cwd: z.ZodString
|
|
155
|
+
cwd: z.ZodOptional<z.ZodString>;
|
|
147
156
|
telegram: z.ZodObject<{
|
|
148
157
|
botToken: z.ZodString;
|
|
149
158
|
}, z.core.$strip>;
|
|
@@ -182,26 +191,32 @@ declare const ProjectFileSchema: z.ZodObject<{
|
|
|
182
191
|
claude: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
183
192
|
name: z.ZodString;
|
|
184
193
|
description: z.ZodOptional<z.ZodString>;
|
|
194
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
185
195
|
}, z.core.$strip>>>;
|
|
186
196
|
copilot: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
187
197
|
name: z.ZodString;
|
|
188
198
|
description: z.ZodOptional<z.ZodString>;
|
|
199
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
189
200
|
}, z.core.$strip>>>;
|
|
190
201
|
codex: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
191
202
|
name: z.ZodString;
|
|
192
203
|
description: z.ZodOptional<z.ZodString>;
|
|
204
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
193
205
|
}, z.core.$strip>>>;
|
|
194
206
|
opencode: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
195
207
|
name: z.ZodString;
|
|
196
208
|
description: z.ZodOptional<z.ZodString>;
|
|
209
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
197
210
|
}, z.core.$strip>>>;
|
|
198
211
|
cursor: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
199
212
|
name: z.ZodString;
|
|
200
213
|
description: z.ZodOptional<z.ZodString>;
|
|
214
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
201
215
|
}, z.core.$strip>>>;
|
|
202
216
|
antigravity: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
203
217
|
name: z.ZodString;
|
|
204
218
|
description: z.ZodOptional<z.ZodString>;
|
|
219
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
205
220
|
}, z.core.$strip>>>;
|
|
206
221
|
}, z.core.$strip>>;
|
|
207
222
|
logging: z.ZodOptional<z.ZodObject<{
|
|
@@ -278,6 +293,9 @@ declare const ProjectFileSchema: z.ZodObject<{
|
|
|
278
293
|
model: z.ZodOptional<z.ZodObject<{
|
|
279
294
|
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
280
295
|
}, z.core.$strip>>;
|
|
296
|
+
engine: z.ZodOptional<z.ZodObject<{
|
|
297
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
298
|
+
}, z.core.$strip>>;
|
|
281
299
|
}, z.core.$strip>>;
|
|
282
300
|
}, z.core.$strip>;
|
|
283
301
|
declare const MultiConfigFileSchema: z.ZodObject<{
|
|
@@ -313,32 +331,6 @@ declare const MultiConfigFileSchema: z.ZodObject<{
|
|
|
313
331
|
sandbox: z.ZodOptional<z.ZodBoolean>;
|
|
314
332
|
}, z.core.$strip>>>;
|
|
315
333
|
}, z.core.$strip>>;
|
|
316
|
-
providers: z.ZodOptional<z.ZodObject<{
|
|
317
|
-
claude: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
318
|
-
name: z.ZodString;
|
|
319
|
-
description: z.ZodOptional<z.ZodString>;
|
|
320
|
-
}, z.core.$strip>>>;
|
|
321
|
-
copilot: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
322
|
-
name: z.ZodString;
|
|
323
|
-
description: z.ZodOptional<z.ZodString>;
|
|
324
|
-
}, z.core.$strip>>>;
|
|
325
|
-
codex: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
326
|
-
name: z.ZodString;
|
|
327
|
-
description: z.ZodOptional<z.ZodString>;
|
|
328
|
-
}, z.core.$strip>>>;
|
|
329
|
-
opencode: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
330
|
-
name: z.ZodString;
|
|
331
|
-
description: z.ZodOptional<z.ZodString>;
|
|
332
|
-
}, z.core.$strip>>>;
|
|
333
|
-
cursor: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
334
|
-
name: z.ZodString;
|
|
335
|
-
description: z.ZodOptional<z.ZodString>;
|
|
336
|
-
}, z.core.$strip>>>;
|
|
337
|
-
antigravity: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
338
|
-
name: z.ZodString;
|
|
339
|
-
description: z.ZodOptional<z.ZodString>;
|
|
340
|
-
}, z.core.$strip>>>;
|
|
341
|
-
}, z.core.$strip>>;
|
|
342
334
|
logging: z.ZodOptional<z.ZodObject<{
|
|
343
335
|
level: z.ZodOptional<z.ZodEnum<{
|
|
344
336
|
debug: "debug";
|
|
@@ -412,13 +404,48 @@ declare const MultiConfigFileSchema: z.ZodObject<{
|
|
|
412
404
|
model: z.ZodOptional<z.ZodObject<{
|
|
413
405
|
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
414
406
|
}, z.core.$strip>>;
|
|
407
|
+
engine: z.ZodOptional<z.ZodObject<{
|
|
408
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
409
|
+
}, z.core.$strip>>;
|
|
415
410
|
}, z.core.$strip>>;
|
|
416
411
|
}, z.core.$strip>>;
|
|
412
|
+
providers: z.ZodOptional<z.ZodObject<{
|
|
413
|
+
claude: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
414
|
+
name: z.ZodString;
|
|
415
|
+
description: z.ZodOptional<z.ZodString>;
|
|
416
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
417
|
+
}, z.core.$strip>>>;
|
|
418
|
+
copilot: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
419
|
+
name: z.ZodString;
|
|
420
|
+
description: z.ZodOptional<z.ZodString>;
|
|
421
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
422
|
+
}, z.core.$strip>>>;
|
|
423
|
+
codex: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
424
|
+
name: z.ZodString;
|
|
425
|
+
description: z.ZodOptional<z.ZodString>;
|
|
426
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
427
|
+
}, z.core.$strip>>>;
|
|
428
|
+
opencode: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
429
|
+
name: z.ZodString;
|
|
430
|
+
description: z.ZodOptional<z.ZodString>;
|
|
431
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
432
|
+
}, z.core.$strip>>>;
|
|
433
|
+
cursor: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
434
|
+
name: z.ZodString;
|
|
435
|
+
description: z.ZodOptional<z.ZodString>;
|
|
436
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
437
|
+
}, z.core.$strip>>>;
|
|
438
|
+
antigravity: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
439
|
+
name: z.ZodString;
|
|
440
|
+
description: z.ZodOptional<z.ZodString>;
|
|
441
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
442
|
+
}, z.core.$strip>>>;
|
|
443
|
+
}, z.core.$strip>>;
|
|
417
444
|
context: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
418
|
-
projects: z.
|
|
445
|
+
projects: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
419
446
|
name: z.ZodOptional<z.ZodString>;
|
|
420
447
|
active: z.ZodOptional<z.ZodBoolean>;
|
|
421
|
-
cwd: z.ZodString
|
|
448
|
+
cwd: z.ZodOptional<z.ZodString>;
|
|
422
449
|
telegram: z.ZodObject<{
|
|
423
450
|
botToken: z.ZodString;
|
|
424
451
|
}, z.core.$strip>;
|
|
@@ -457,26 +484,32 @@ declare const MultiConfigFileSchema: z.ZodObject<{
|
|
|
457
484
|
claude: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
458
485
|
name: z.ZodString;
|
|
459
486
|
description: z.ZodOptional<z.ZodString>;
|
|
487
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
460
488
|
}, z.core.$strip>>>;
|
|
461
489
|
copilot: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
462
490
|
name: z.ZodString;
|
|
463
491
|
description: z.ZodOptional<z.ZodString>;
|
|
492
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
464
493
|
}, z.core.$strip>>>;
|
|
465
494
|
codex: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
466
495
|
name: z.ZodString;
|
|
467
496
|
description: z.ZodOptional<z.ZodString>;
|
|
497
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
468
498
|
}, z.core.$strip>>>;
|
|
469
499
|
opencode: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
470
500
|
name: z.ZodString;
|
|
471
501
|
description: z.ZodOptional<z.ZodString>;
|
|
502
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
472
503
|
}, z.core.$strip>>>;
|
|
473
504
|
cursor: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
474
505
|
name: z.ZodString;
|
|
475
506
|
description: z.ZodOptional<z.ZodString>;
|
|
507
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
476
508
|
}, z.core.$strip>>>;
|
|
477
509
|
antigravity: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
478
510
|
name: z.ZodString;
|
|
479
511
|
description: z.ZodOptional<z.ZodString>;
|
|
512
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
480
513
|
}, z.core.$strip>>>;
|
|
481
514
|
}, z.core.$strip>>;
|
|
482
515
|
logging: z.ZodOptional<z.ZodObject<{
|
|
@@ -553,6 +586,9 @@ declare const MultiConfigFileSchema: z.ZodObject<{
|
|
|
553
586
|
model: z.ZodOptional<z.ZodObject<{
|
|
554
587
|
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
555
588
|
}, z.core.$strip>>;
|
|
589
|
+
engine: z.ZodOptional<z.ZodObject<{
|
|
590
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
591
|
+
}, z.core.$strip>>;
|
|
556
592
|
}, z.core.$strip>>;
|
|
557
593
|
}, z.core.$strip>>;
|
|
558
594
|
}, z.core.$strip>;
|
|
@@ -563,6 +599,7 @@ export type EngineName = z.infer<typeof EngineNameSchema>;
|
|
|
563
599
|
export interface ProviderModel {
|
|
564
600
|
name: string;
|
|
565
601
|
description?: string;
|
|
602
|
+
default?: boolean;
|
|
566
603
|
}
|
|
567
604
|
export interface ResolvedProjectConfig {
|
|
568
605
|
slug: string;
|
|
@@ -607,6 +644,8 @@ export interface ResolvedProjectConfig {
|
|
|
607
644
|
} | undefined;
|
|
608
645
|
context: Record<string, string> | undefined;
|
|
609
646
|
providerModels: ProviderModel[];
|
|
647
|
+
providerDefaultModel: string | undefined;
|
|
648
|
+
availableEngines: EngineName[];
|
|
610
649
|
commands: {
|
|
611
650
|
start: {
|
|
612
651
|
enabled: boolean;
|
|
@@ -636,6 +675,9 @@ export interface ResolvedProjectConfig {
|
|
|
636
675
|
model: {
|
|
637
676
|
enabled: boolean;
|
|
638
677
|
};
|
|
678
|
+
engine: {
|
|
679
|
+
enabled: boolean;
|
|
680
|
+
};
|
|
639
681
|
};
|
|
640
682
|
}
|
|
641
683
|
export declare class ConfigLoadError extends Error {
|
|
@@ -646,9 +688,14 @@ export interface LoadedConfigResult {
|
|
|
646
688
|
loadedFiles: string[];
|
|
647
689
|
}
|
|
648
690
|
export declare function deriveSlug(name: string | undefined, cwd: string): string;
|
|
649
|
-
export declare function resolveProjectConfig(project: ProjectFileEntry, globals: GlobalsFile, configDir: string, rootContext?: Record<string, string>): ResolvedProjectConfig;
|
|
691
|
+
export declare function resolveProjectConfig(key: string, project: ProjectFileEntry, globals: GlobalsFile, configDir: string, rootContext?: Record<string, string>, providers?: z.infer<typeof ProvidersConfigSchema>): ResolvedProjectConfig;
|
|
650
692
|
export declare function validateProjects(projects: ResolvedProjectConfig[]): void;
|
|
651
693
|
export declare function validateAccessPolicies(projects: ResolvedProjectConfig[]): void;
|
|
694
|
+
/**
|
|
695
|
+
* Validates that at most one model per providers.<engine> list has default: true.
|
|
696
|
+
* Call after config load and env substitution, before resolving project configs.
|
|
697
|
+
*/
|
|
698
|
+
export declare function validateProviderDefaultUniqueness(config: MultiConfigFile): void;
|
|
652
699
|
export type ConfigFormat = "json" | "jsonc" | "yaml";
|
|
653
700
|
interface ResolvedConfigFile {
|
|
654
701
|
path: string;
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAsBxB,QAAA,MAAM,gBAAgB;;;;;;;EAOpB,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/config.js
CHANGED
|
@@ -102,11 +102,13 @@ const CommandsConfigSchema = z
|
|
|
102
102
|
clean: SimpleCommandConfigSchema,
|
|
103
103
|
git: GitConfigSchema,
|
|
104
104
|
model: GitConfigSchema,
|
|
105
|
+
engine: GitConfigSchema,
|
|
105
106
|
})
|
|
106
107
|
.optional();
|
|
107
108
|
const ProviderModelSchema = z.object({
|
|
108
109
|
name: z.string().min(1),
|
|
109
110
|
description: z.string().optional(),
|
|
111
|
+
default: z.boolean().optional(),
|
|
110
112
|
});
|
|
111
113
|
const ProvidersConfigSchema = z
|
|
112
114
|
.object({
|
|
@@ -130,7 +132,6 @@ const GlobalsFileSchema = z
|
|
|
130
132
|
.object({
|
|
131
133
|
access: AccessSchema,
|
|
132
134
|
engine: EngineConfigSchema,
|
|
133
|
-
providers: ProvidersConfigSchema,
|
|
134
135
|
logging: z
|
|
135
136
|
.object({
|
|
136
137
|
level: LogLevelSchema,
|
|
@@ -154,11 +155,17 @@ const GlobalsFileSchema = z
|
|
|
154
155
|
commands: CommandsConfigSchema,
|
|
155
156
|
})
|
|
156
157
|
.optional();
|
|
158
|
+
// ─── Project map key (slug-like: safe for default cwd path segment) ─────────────
|
|
159
|
+
const PROJECT_KEY_REGEX = /^[a-zA-Z0-9_-]+$/;
|
|
160
|
+
/** Project map keys must be slug-like so default cwd is a safe path segment. */
|
|
161
|
+
const ProjectKeySchema = z
|
|
162
|
+
.string()
|
|
163
|
+
.regex(PROJECT_KEY_REGEX, "project key must be slug-like (letters, numbers, dashes, underscores only)");
|
|
157
164
|
// ─── Per-project schema ────────────────────────────────────────────────────────
|
|
158
165
|
const ProjectFileSchema = z.object({
|
|
159
166
|
name: z.string().optional(),
|
|
160
167
|
active: z.boolean().optional(),
|
|
161
|
-
cwd: z.string().min(1, "project.cwd
|
|
168
|
+
cwd: z.string().min(1, "project.cwd must be non-empty when set").optional(),
|
|
162
169
|
telegram: z.object({
|
|
163
170
|
botToken: z.string().min(1, "project.telegram.botToken is required"),
|
|
164
171
|
}),
|
|
@@ -189,12 +196,16 @@ const ProjectFileSchema = z.object({
|
|
|
189
196
|
commands: CommandsConfigSchema,
|
|
190
197
|
});
|
|
191
198
|
// ─── Multi-project config file schema ─────────────────────────────────────────
|
|
199
|
+
const ProjectsMapSchema = z
|
|
200
|
+
.record(ProjectKeySchema, ProjectFileSchema)
|
|
201
|
+
.refine((rec) => Object.keys(rec).length >= 1, {
|
|
202
|
+
message: "At least one project is required",
|
|
203
|
+
});
|
|
192
204
|
const MultiConfigFileSchema = z.object({
|
|
193
205
|
globals: GlobalsFileSchema,
|
|
206
|
+
providers: ProvidersConfigSchema,
|
|
194
207
|
context: z.record(z.string(), z.string()).optional(),
|
|
195
|
-
projects:
|
|
196
|
-
.array(ProjectFileSchema)
|
|
197
|
-
.min(1, "At least one project is required"),
|
|
208
|
+
projects: ProjectsMapSchema,
|
|
198
209
|
});
|
|
199
210
|
// ─── Local config partial schema ──────────────────────────────────────────────
|
|
200
211
|
const LocalProjectSchema = ProjectFileSchema.partial().extend({
|
|
@@ -204,8 +215,9 @@ const LocalProjectSchema = ProjectFileSchema.partial().extend({
|
|
|
204
215
|
const LocalConfigFileSchema = z
|
|
205
216
|
.object({
|
|
206
217
|
globals: GlobalsFileSchema,
|
|
218
|
+
providers: ProvidersConfigSchema,
|
|
207
219
|
context: z.record(z.string(), z.string()).optional(),
|
|
208
|
-
projects: z.
|
|
220
|
+
projects: z.record(ProjectKeySchema, LocalProjectSchema).optional(),
|
|
209
221
|
})
|
|
210
222
|
.optional();
|
|
211
223
|
// ─── Config load result & errors ───────────────────────────────────────────────
|
|
@@ -231,6 +243,13 @@ function parseTelegramUserId(value, path) {
|
|
|
231
243
|
}
|
|
232
244
|
return num;
|
|
233
245
|
}
|
|
246
|
+
/** Set name/cwd from map key when omitted. Mutates entries in place. */
|
|
247
|
+
function normalizeProjectMap(projects) {
|
|
248
|
+
for (const [key, entry] of Object.entries(projects)) {
|
|
249
|
+
entry.name = entry.name ?? key;
|
|
250
|
+
entry.cwd = entry.cwd ?? key;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
234
253
|
function normalizeAllowedUserIdsInConfig(config) {
|
|
235
254
|
const globalsAccess = config.globals?.access;
|
|
236
255
|
if (globalsAccess?.allowedUserIds != null) {
|
|
@@ -241,15 +260,14 @@ function normalizeAllowedUserIdsInConfig(config) {
|
|
|
241
260
|
}
|
|
242
261
|
globalsAccess.allowedUserIds = normalized;
|
|
243
262
|
}
|
|
244
|
-
for (
|
|
245
|
-
const project = config.projects[j];
|
|
263
|
+
for (const [key, project] of Object.entries(config.projects)) {
|
|
246
264
|
const access = project.access;
|
|
247
265
|
if (access?.allowedUserIds == null)
|
|
248
266
|
continue;
|
|
249
267
|
const raw = access.allowedUserIds;
|
|
250
268
|
const normalized = [];
|
|
251
269
|
for (let i = 0; i < raw.length; i++) {
|
|
252
|
-
normalized.push(parseTelegramUserId(raw[i], `projects
|
|
270
|
+
normalized.push(parseTelegramUserId(raw[i], `projects.${key}.access.allowedUserIds[${i}]`));
|
|
253
271
|
}
|
|
254
272
|
access.allowedUserIds = normalized;
|
|
255
273
|
}
|
|
@@ -280,11 +298,11 @@ function resolveDataDir(dataDirRaw, projectCwd, configDir, slug) {
|
|
|
280
298
|
return resolve(projectCwd, dataDirRaw);
|
|
281
299
|
}
|
|
282
300
|
// ─── Merge: project over globals over defaults ─────────────────────────────────
|
|
283
|
-
export function resolveProjectConfig(project, globals, configDir, rootContext) {
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
const
|
|
301
|
+
export function resolveProjectConfig(key, project, globals, configDir, rootContext, providers) {
|
|
302
|
+
const slug = key;
|
|
303
|
+
const name = project.name ?? key;
|
|
304
|
+
const cwd = project.cwd ?? key;
|
|
305
|
+
const resolvedCwd = isAbsolute(cwd) ? cwd : resolve(configDir, cwd);
|
|
288
306
|
const logDir = resolve(configDir, ".hal", "logs", slug);
|
|
289
307
|
const dataDir = resolveDataDir(project.dataDir ?? globals.dataDir, resolvedCwd, configDir, slug);
|
|
290
308
|
const hasTranscription = project.transcription !== undefined || globals.transcription !== undefined;
|
|
@@ -304,11 +322,42 @@ export function resolveProjectConfig(project, globals, configDir, rootContext) {
|
|
|
304
322
|
}
|
|
305
323
|
return msg.text;
|
|
306
324
|
}
|
|
325
|
+
// Resolve engine and provider models early (needed for command enabled flags)
|
|
326
|
+
const rawEngineName = project.engine?.name ?? globals.engine?.name;
|
|
327
|
+
if (!rawEngineName) {
|
|
328
|
+
throw new ConfigLoadError(`Configuration error: project "${key}" has no engine configured. ` +
|
|
329
|
+
"Set engine.name in the project or in globals.");
|
|
330
|
+
}
|
|
331
|
+
const engineName = rawEngineName;
|
|
332
|
+
const mergedProviders = {
|
|
333
|
+
...(providers ?? {}),
|
|
334
|
+
...(project.providers ?? {}),
|
|
335
|
+
};
|
|
336
|
+
const availableEngines = Object.keys(mergedProviders).filter((k) => {
|
|
337
|
+
const list = mergedProviders[k];
|
|
338
|
+
return Array.isArray(list) && list.length > 0;
|
|
339
|
+
});
|
|
340
|
+
const rawProviderModels = project.providers?.[engineName] ?? providers?.[engineName] ?? [];
|
|
341
|
+
const providerModels = rawProviderModels.map((m) => ({
|
|
342
|
+
name: m.name,
|
|
343
|
+
description: m.description,
|
|
344
|
+
default: m.default,
|
|
345
|
+
}));
|
|
346
|
+
const defaultEntries = providerModels.filter((m) => m.default === true);
|
|
347
|
+
const providerDefaultModel = defaultEntries.length === 1 ? defaultEntries[0].name : undefined;
|
|
307
348
|
// Resolve command enabled flags (project > globals > default)
|
|
308
349
|
const rawStart = project.commands?.start ?? globals.commands?.start;
|
|
309
350
|
const rawHelp = project.commands?.help ?? globals.commands?.help;
|
|
310
351
|
const rawReset = project.commands?.reset ?? globals.commands?.reset;
|
|
311
352
|
const rawClean = project.commands?.clean ?? globals.commands?.clean;
|
|
353
|
+
const modelEnabled = (project.commands?.model?.enabled ??
|
|
354
|
+
globals.commands?.model?.enabled ??
|
|
355
|
+
true) &&
|
|
356
|
+
providerModels.length > 1;
|
|
357
|
+
const engineEnabled = (project.commands?.engine?.enabled ??
|
|
358
|
+
globals.commands?.engine?.enabled ??
|
|
359
|
+
true) &&
|
|
360
|
+
availableEngines.length > 1;
|
|
312
361
|
const resolvedCommands = {
|
|
313
362
|
start: {
|
|
314
363
|
enabled: project.commands?.start?.enabled ??
|
|
@@ -351,23 +400,12 @@ export function resolveProjectConfig(project, globals, configDir, rootContext) {
|
|
|
351
400
|
globals.commands?.git?.enabled ??
|
|
352
401
|
false,
|
|
353
402
|
},
|
|
354
|
-
model: {
|
|
355
|
-
|
|
356
|
-
globals.commands?.model?.enabled ??
|
|
357
|
-
true,
|
|
358
|
-
},
|
|
403
|
+
model: { enabled: modelEnabled },
|
|
404
|
+
engine: { enabled: engineEnabled },
|
|
359
405
|
};
|
|
360
|
-
const engineName = (project.engine?.name ??
|
|
361
|
-
globals.engine?.name ??
|
|
362
|
-
"claude");
|
|
363
|
-
const rawProviderModels = project.providers?.[engineName] ?? globals.providers?.[engineName] ?? [];
|
|
364
|
-
const providerModels = rawProviderModels.map((m) => ({
|
|
365
|
-
name: m.name,
|
|
366
|
-
description: m.description,
|
|
367
|
-
}));
|
|
368
406
|
return {
|
|
369
407
|
slug,
|
|
370
|
-
name
|
|
408
|
+
name,
|
|
371
409
|
cwd: resolvedCwd,
|
|
372
410
|
configDir,
|
|
373
411
|
dataDir,
|
|
@@ -425,6 +463,8 @@ export function resolveProjectConfig(project, globals, configDir, rootContext) {
|
|
|
425
463
|
}
|
|
426
464
|
: undefined,
|
|
427
465
|
providerModels,
|
|
466
|
+
providerDefaultModel,
|
|
467
|
+
availableEngines,
|
|
428
468
|
context: hasContext ? { ...rootContext, ...project.context } : undefined,
|
|
429
469
|
commands: resolvedCommands,
|
|
430
470
|
};
|
|
@@ -467,6 +507,49 @@ export function validateAccessPolicies(projects) {
|
|
|
467
507
|
throw new ConfigLoadError(`Configuration error: invalid access policy\n${errors.map((e) => ` - ${e}`).join("\n")}`);
|
|
468
508
|
}
|
|
469
509
|
}
|
|
510
|
+
// ─── Boot-time provider default uniqueness ────────────────────────────────────
|
|
511
|
+
const PROVIDER_ENGINE_KEYS = [
|
|
512
|
+
"claude",
|
|
513
|
+
"copilot",
|
|
514
|
+
"codex",
|
|
515
|
+
"opencode",
|
|
516
|
+
"cursor",
|
|
517
|
+
"antigravity",
|
|
518
|
+
];
|
|
519
|
+
function countProviderDefaults(list) {
|
|
520
|
+
if (!Array.isArray(list))
|
|
521
|
+
return 0;
|
|
522
|
+
return list.filter((m) => m.default === true).length;
|
|
523
|
+
}
|
|
524
|
+
/**
|
|
525
|
+
* Validates that at most one model per providers.<engine> list has default: true.
|
|
526
|
+
* Call after config load and env substitution, before resolving project configs.
|
|
527
|
+
*/
|
|
528
|
+
export function validateProviderDefaultUniqueness(config) {
|
|
529
|
+
const topProviders = config.providers;
|
|
530
|
+
if (topProviders) {
|
|
531
|
+
for (const engine of PROVIDER_ENGINE_KEYS) {
|
|
532
|
+
const list = topProviders[engine];
|
|
533
|
+
const n = countProviderDefaults(list);
|
|
534
|
+
if (n > 1) {
|
|
535
|
+
throw new ConfigLoadError(`Configuration error: at most one model in providers.${engine} may have default: true (found ${n}).`);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
for (const [key, project] of Object.entries(config.projects)) {
|
|
540
|
+
const projectProviders = project.providers;
|
|
541
|
+
if (!projectProviders)
|
|
542
|
+
continue;
|
|
543
|
+
const projectLabel = project.name ?? key;
|
|
544
|
+
for (const engine of PROVIDER_ENGINE_KEYS) {
|
|
545
|
+
const list = projectProviders[engine];
|
|
546
|
+
const n = countProviderDefaults(list);
|
|
547
|
+
if (n > 1) {
|
|
548
|
+
throw new ConfigLoadError(`Configuration error: at most one model in projects["${key}"].providers.${engine} may have default: true (found ${n}). Project: ${projectLabel}.`);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
}
|
|
470
553
|
function loadEnvFiles(configDir, projectCwds) {
|
|
471
554
|
const loadedFiles = [];
|
|
472
555
|
const vars = {};
|
|
@@ -619,32 +702,36 @@ function mergeLocalIntoBase(base, local, baseFileName, localFileName) {
|
|
|
619
702
|
const mergedGlobals = local.globals !== undefined
|
|
620
703
|
? deepMerge(base.globals ?? {}, local.globals)
|
|
621
704
|
: base.globals;
|
|
705
|
+
const mergedProviders = local.providers !== undefined
|
|
706
|
+
? base.providers
|
|
707
|
+
? deepMerge(base.providers, local.providers)
|
|
708
|
+
: local.providers
|
|
709
|
+
: base.providers;
|
|
622
710
|
const mergedContext = local.context !== undefined
|
|
623
711
|
? base.context
|
|
624
712
|
? { ...base.context, ...local.context }
|
|
625
713
|
: local.context
|
|
626
714
|
: base.context;
|
|
627
|
-
if (!local.projects || local.projects.length === 0) {
|
|
628
|
-
return {
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
if (idx === -1) {
|
|
641
|
-
throw new ConfigLoadError(`Configuration error: local project "${matchKey}" not found in ${baseFileName}.\n` +
|
|
642
|
-
` Every entry in ${localFileName} projects must match a base project by name or cwd.`);
|
|
715
|
+
if (!local.projects || Object.keys(local.projects).length === 0) {
|
|
716
|
+
return {
|
|
717
|
+
...base,
|
|
718
|
+
globals: mergedGlobals,
|
|
719
|
+
providers: mergedProviders,
|
|
720
|
+
context: mergedContext,
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
const mergedProjects = { ...base.projects };
|
|
724
|
+
for (const [localKey, localProject] of Object.entries(local.projects)) {
|
|
725
|
+
if (!(localKey in mergedProjects)) {
|
|
726
|
+
throw new ConfigLoadError(`Configuration error: local project key "${localKey}" not found in ${baseFileName}.\n` +
|
|
727
|
+
` Every key in ${localFileName} projects must exist in the base config.`);
|
|
643
728
|
}
|
|
644
|
-
mergedProjects[
|
|
729
|
+
mergedProjects[localKey] = deepMerge(mergedProjects[localKey], localProject);
|
|
645
730
|
}
|
|
731
|
+
normalizeProjectMap(mergedProjects);
|
|
646
732
|
return {
|
|
647
733
|
globals: mergedGlobals,
|
|
734
|
+
providers: mergedProviders,
|
|
648
735
|
context: mergedContext,
|
|
649
736
|
projects: mergedProjects,
|
|
650
737
|
};
|
|
@@ -681,6 +768,7 @@ function loadMultiConfigInternal(configDir) {
|
|
|
681
768
|
throw new ConfigLoadError(`Configuration error in ${baseFileName}:\n${issues}`);
|
|
682
769
|
}
|
|
683
770
|
let merged = baseResult.data;
|
|
771
|
+
normalizeProjectMap(merged.projects);
|
|
684
772
|
// 3. Load and merge local config
|
|
685
773
|
const localResult = loadLocalConfig(configDir);
|
|
686
774
|
if (localResult !== null) {
|
|
@@ -689,7 +777,13 @@ function loadMultiConfigInternal(configDir) {
|
|
|
689
777
|
merged = mergeLocalIntoBase(merged, localResult.config, baseFileName, localFileName);
|
|
690
778
|
}
|
|
691
779
|
// 4. Load .env files (using raw cwds from merged config for path resolution)
|
|
692
|
-
|
|
780
|
+
// Stable order: sort project keys so iteration is deterministic.
|
|
781
|
+
const projectKeys = Object.keys(merged.projects).sort();
|
|
782
|
+
const rawCwds = projectKeys.map((key) => {
|
|
783
|
+
const p = merged.projects[key];
|
|
784
|
+
const cwd = p.cwd ?? key;
|
|
785
|
+
return isAbsolute(cwd) ? cwd : resolve(configDir, cwd);
|
|
786
|
+
});
|
|
693
787
|
const envSources = loadEnvFiles(configDir, rawCwds);
|
|
694
788
|
// 5. Substitute env vars in the merged raw object (before final Zod pass)
|
|
695
789
|
const substituted = substituteEnvVars(merged, envSources.vars);
|
|
@@ -701,6 +795,7 @@ function loadMultiConfigInternal(configDir) {
|
|
|
701
795
|
.join("\n");
|
|
702
796
|
throw new ConfigLoadError(`Configuration error after environment variable substitution:\n${issues}`);
|
|
703
797
|
}
|
|
798
|
+
normalizeProjectMap(finalResult.data.projects);
|
|
704
799
|
// 7. Normalize allowedUserIds (string | number)[] → number[] with validation
|
|
705
800
|
normalizeAllowedUserIdsInConfig(finalResult.data);
|
|
706
801
|
return {
|