btca-server 2.0.2 → 2.0.3
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/package.json +1 -1
- package/src/agent/agent.test.ts +25 -16
- package/src/agent/service.ts +100 -110
- package/src/collections/service.test.ts +119 -0
- package/src/collections/service.ts +73 -14
- package/src/config/config.test.ts +21 -16
- package/src/config/index.ts +179 -200
- package/src/effect/services.ts +15 -23
- package/src/resources/service.ts +45 -44
- package/src/vfs/virtual-fs.ts +73 -0
|
@@ -2,6 +2,7 @@ import { describe, it, expect, beforeEach, afterEach } from 'bun:test';
|
|
|
2
2
|
import { promises as fs } from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import os from 'node:os';
|
|
5
|
+
import { Effect } from 'effect';
|
|
5
6
|
|
|
6
7
|
import {
|
|
7
8
|
load as loadConfig,
|
|
@@ -380,12 +381,14 @@ describe('Config', () => {
|
|
|
380
381
|
expect(config.resources.length).toBe(3);
|
|
381
382
|
|
|
382
383
|
// Add a new resource
|
|
383
|
-
await
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
384
|
+
await Effect.runPromise(
|
|
385
|
+
config.addResource({
|
|
386
|
+
name: 'new-resource',
|
|
387
|
+
type: 'git',
|
|
388
|
+
url: 'https://github.com/test/new-resource',
|
|
389
|
+
branch: 'main'
|
|
390
|
+
})
|
|
391
|
+
);
|
|
389
392
|
|
|
390
393
|
// Verify merged state shows 4 resources
|
|
391
394
|
expect(config.resources.length).toBe(4);
|
|
@@ -459,7 +462,7 @@ describe('Config', () => {
|
|
|
459
462
|
expect(config.resources.length).toBe(3);
|
|
460
463
|
|
|
461
464
|
// Remove the project resource
|
|
462
|
-
await config.removeResource('myproject');
|
|
465
|
+
await Effect.runPromise(config.removeResource('myproject'));
|
|
463
466
|
|
|
464
467
|
// Verify merged state shows 2 resources (only global)
|
|
465
468
|
expect(config.resources.length).toBe(2);
|
|
@@ -477,7 +480,7 @@ describe('Config', () => {
|
|
|
477
480
|
).toBeUndefined();
|
|
478
481
|
|
|
479
482
|
// Trying to remove a global resource should throw an error
|
|
480
|
-
expect(config.removeResource('svelte')).rejects.toThrow(
|
|
483
|
+
expect(Effect.runPromise(config.removeResource('svelte'))).rejects.toThrow(
|
|
481
484
|
'Resource "svelte" is defined in the global config'
|
|
482
485
|
);
|
|
483
486
|
|
|
@@ -528,7 +531,7 @@ describe('Config', () => {
|
|
|
528
531
|
// Update the model
|
|
529
532
|
const nextProvider = 'openrouter';
|
|
530
533
|
const nextModel = 'openai/gpt-4o-mini';
|
|
531
|
-
await config.updateModel(nextProvider, nextModel);
|
|
534
|
+
await Effect.runPromise(config.updateModel(nextProvider, nextModel));
|
|
532
535
|
|
|
533
536
|
expect(config.provider).toBe(nextProvider);
|
|
534
537
|
expect(config.model).toBe(nextModel);
|
|
@@ -574,12 +577,14 @@ describe('Config', () => {
|
|
|
574
577
|
const config = await Config.load();
|
|
575
578
|
|
|
576
579
|
// Add a resource (should go to global)
|
|
577
|
-
await
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
580
|
+
await Effect.runPromise(
|
|
581
|
+
config.addResource({
|
|
582
|
+
name: 'new-resource',
|
|
583
|
+
type: 'git',
|
|
584
|
+
url: 'https://github.com/test/new-resource',
|
|
585
|
+
branch: 'main'
|
|
586
|
+
})
|
|
587
|
+
);
|
|
583
588
|
|
|
584
589
|
expect(config.resources.length).toBe(2);
|
|
585
590
|
|
|
@@ -592,7 +597,7 @@ describe('Config', () => {
|
|
|
592
597
|
]);
|
|
593
598
|
|
|
594
599
|
// Remove a resource (should work since we're in global-only mode)
|
|
595
|
-
await config.removeResource('svelte');
|
|
600
|
+
await Effect.runPromise(config.removeResource('svelte'));
|
|
596
601
|
expect(config.resources.length).toBe(1);
|
|
597
602
|
|
|
598
603
|
const savedGlobalConfig2 = JSON.parse(await fs.readFile(globalConfigPath, 'utf-8'));
|
package/src/config/index.ts
CHANGED
|
@@ -141,20 +141,11 @@ export type ConfigService = {
|
|
|
141
141
|
provider: string,
|
|
142
142
|
model: string,
|
|
143
143
|
providerOptions?: ProviderOptionsConfig
|
|
144
|
-
) => Promise<{ provider: string; model: string; savedTo: ConfigScope }>;
|
|
145
|
-
updateModelEffect: (
|
|
146
|
-
provider: string,
|
|
147
|
-
model: string,
|
|
148
|
-
providerOptions?: ProviderOptionsConfig
|
|
149
144
|
) => Effect.Effect<{ provider: string; model: string; savedTo: ConfigScope }, unknown>;
|
|
150
|
-
addResource: (resource: ResourceDefinition) =>
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
clearResources: () => Promise<{ cleared: number }>;
|
|
155
|
-
clearResourcesEffect: () => Effect.Effect<{ cleared: number }, unknown>;
|
|
156
|
-
reload: () => Promise<void>;
|
|
157
|
-
reloadEffect: () => Effect.Effect<void, unknown>;
|
|
145
|
+
addResource: (resource: ResourceDefinition) => Effect.Effect<ResourceDefinition, unknown>;
|
|
146
|
+
removeResource: (name: string) => Effect.Effect<void, unknown>;
|
|
147
|
+
clearResources: () => Effect.Effect<{ cleared: number }, unknown>;
|
|
148
|
+
reload: () => Effect.Effect<void, unknown>;
|
|
158
149
|
};
|
|
159
150
|
|
|
160
151
|
export type Service = ConfigService;
|
|
@@ -495,234 +486,222 @@ const makeService = (
|
|
|
495
486
|
}
|
|
496
487
|
};
|
|
497
488
|
|
|
498
|
-
const
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
489
|
+
const updateModelPromise = async (
|
|
490
|
+
provider: string,
|
|
491
|
+
model: string,
|
|
492
|
+
providerOptions?: ProviderOptionsConfig
|
|
493
|
+
): Promise<{ provider: string; model: string; savedTo: ConfigScope }> => {
|
|
494
|
+
if (!isProviderSupported(provider)) {
|
|
495
|
+
const available = getSupportedProviders();
|
|
496
|
+
throw new ConfigError({
|
|
497
|
+
message: `Provider "${provider}" is not supported`,
|
|
498
|
+
hint: `Available providers: ${available.join(', ')}. Open an issue to request this provider: https://github.com/davis7dotsh/better-context/issues.`
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
const mutableConfig = getMutableConfig();
|
|
502
|
+
const existingProviderOptions = mutableConfig.providerOptions ?? {};
|
|
503
|
+
const nextProviderOptions = providerOptions
|
|
504
|
+
? {
|
|
505
|
+
...existingProviderOptions,
|
|
506
|
+
[provider]: {
|
|
507
|
+
...(existingProviderOptions[provider] ?? {}),
|
|
508
|
+
...providerOptions
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
: existingProviderOptions;
|
|
512
|
+
const updated = {
|
|
513
|
+
...mutableConfig,
|
|
514
|
+
provider,
|
|
515
|
+
model,
|
|
516
|
+
...(providerOptions ? { providerOptions: nextProviderOptions } : {})
|
|
517
|
+
};
|
|
518
518
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
519
|
+
if (provider === 'openai-compat') {
|
|
520
|
+
const merged = currentProjectConfig
|
|
521
|
+
? mergeProviderOptions(currentGlobalConfig, updated)
|
|
522
|
+
: mergeProviderOptions(updated, null);
|
|
523
|
+
const compat = merged['openai-compat'];
|
|
524
|
+
const baseURL = compat?.baseURL?.trim();
|
|
525
|
+
const name = compat?.name?.trim();
|
|
526
|
+
if (!baseURL || !name) {
|
|
526
527
|
throw new ConfigError({
|
|
527
|
-
message:
|
|
528
|
-
hint:
|
|
528
|
+
message: 'openai-compat requires baseURL and name',
|
|
529
|
+
hint: 'Run "btca connect -p openai-compat" to configure baseURL and name.'
|
|
529
530
|
});
|
|
530
531
|
}
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
: existingProviderOptions;
|
|
542
|
-
const updated = {
|
|
543
|
-
...mutableConfig,
|
|
544
|
-
provider,
|
|
545
|
-
model,
|
|
546
|
-
...(providerOptions ? { providerOptions: nextProviderOptions } : {})
|
|
547
|
-
};
|
|
532
|
+
}
|
|
533
|
+
setMutableConfig(updated);
|
|
534
|
+
await saveConfig(configPath, updated);
|
|
535
|
+
metricsInfo('config.model.updated', { provider, model });
|
|
536
|
+
return {
|
|
537
|
+
provider,
|
|
538
|
+
model,
|
|
539
|
+
savedTo: currentProjectConfig ? 'project' : 'global'
|
|
540
|
+
};
|
|
541
|
+
};
|
|
548
542
|
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
model,
|
|
569
|
-
savedTo: currentProjectConfig ? 'project' : 'global'
|
|
570
|
-
};
|
|
571
|
-
},
|
|
543
|
+
const addResourcePromise = async (resource: ResourceDefinition): Promise<ResourceDefinition> => {
|
|
544
|
+
const mergedResources = getMergedResources();
|
|
545
|
+
if (mergedResources.some((r) => r.name === resource.name)) {
|
|
546
|
+
throw new ConfigError({
|
|
547
|
+
message: `Resource "${resource.name}" already exists`,
|
|
548
|
+
hint: `Choose a different name or remove the existing resource first with "btca remove ${resource.name}".`
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
const mutableConfig = getMutableConfig();
|
|
553
|
+
const updated = {
|
|
554
|
+
...mutableConfig,
|
|
555
|
+
resources: [...mutableConfig.resources, resource]
|
|
556
|
+
};
|
|
557
|
+
setMutableConfig(updated);
|
|
558
|
+
await saveConfig(configPath, updated);
|
|
559
|
+
metricsInfo('config.resource.added', { name: resource.name, type: resource.type });
|
|
560
|
+
return resource;
|
|
561
|
+
};
|
|
572
562
|
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
563
|
+
const removeResourcePromise = async (name: string): Promise<void> => {
|
|
564
|
+
const mergedResources = getMergedResources();
|
|
565
|
+
const exists = mergedResources.some((r) => r.name === name);
|
|
566
|
+
if (!exists) {
|
|
567
|
+
const available = mergedResources.map((r) => r.name);
|
|
568
|
+
throw new ConfigError({
|
|
569
|
+
message: `Resource "${name}" not found`,
|
|
570
|
+
hint:
|
|
571
|
+
available.length > 0
|
|
572
|
+
? `Available resources: ${available.join(', ')}. ${CommonHints.LIST_RESOURCES}`
|
|
573
|
+
: `No resources configured. ${CommonHints.ADD_RESOURCE}`
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
const mutableConfig = getMutableConfig();
|
|
578
|
+
const isInMutableConfig = mutableConfig.resources.some((r) => r.name === name);
|
|
579
|
+
|
|
580
|
+
if (currentProjectConfig) {
|
|
581
|
+
const isInGlobal = currentGlobalConfig.resources.some((r) => r.name === name);
|
|
582
|
+
const isInProject = currentProjectConfig.resources.some((r) => r.name === name);
|
|
583
|
+
|
|
584
|
+
if (isInProject) {
|
|
585
|
+
const updated = {
|
|
586
|
+
...currentProjectConfig,
|
|
587
|
+
resources: currentProjectConfig.resources.filter((r) => r.name !== name)
|
|
588
|
+
};
|
|
589
|
+
currentProjectConfig = updated;
|
|
590
|
+
await saveConfig(configPath, updated);
|
|
591
|
+
metricsInfo('config.resource.removed', { name, from: 'project' });
|
|
592
|
+
} else if (isInGlobal) {
|
|
577
593
|
throw new ConfigError({
|
|
578
|
-
message: `Resource "${
|
|
579
|
-
hint: `
|
|
594
|
+
message: `Resource "${name}" is defined in the global config`,
|
|
595
|
+
hint: `To remove this resource globally, edit the global config at "${expandHome(GLOBAL_CONFIG_DIR)}/${GLOBAL_CONFIG_FILENAME}" or run the command without a project config present.`
|
|
596
|
+
});
|
|
597
|
+
}
|
|
598
|
+
} else {
|
|
599
|
+
if (!isInMutableConfig) {
|
|
600
|
+
throw new ConfigError({
|
|
601
|
+
message: `Resource "${name}" not found in config`,
|
|
602
|
+
hint: CommonHints.LIST_RESOURCES
|
|
580
603
|
});
|
|
581
604
|
}
|
|
582
|
-
|
|
583
|
-
// Add only to the mutable config (project if exists, else global)
|
|
584
|
-
const mutableConfig = getMutableConfig();
|
|
585
605
|
const updated = {
|
|
586
606
|
...mutableConfig,
|
|
587
|
-
resources:
|
|
607
|
+
resources: mutableConfig.resources.filter((r) => r.name !== name)
|
|
588
608
|
};
|
|
589
609
|
setMutableConfig(updated);
|
|
590
610
|
await saveConfig(configPath, updated);
|
|
591
|
-
metricsInfo('config.resource.
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
removeResource: async (name: string) => {
|
|
596
|
-
const mergedResources = getMergedResources();
|
|
597
|
-
const exists = mergedResources.some((r) => r.name === name);
|
|
598
|
-
if (!exists) {
|
|
599
|
-
const available = mergedResources.map((r) => r.name);
|
|
600
|
-
throw new ConfigError({
|
|
601
|
-
message: `Resource "${name}" not found`,
|
|
602
|
-
hint:
|
|
603
|
-
available.length > 0
|
|
604
|
-
? `Available resources: ${available.join(', ')}. ${CommonHints.LIST_RESOURCES}`
|
|
605
|
-
: `No resources configured. ${CommonHints.ADD_RESOURCE}`
|
|
606
|
-
});
|
|
607
|
-
}
|
|
611
|
+
metricsInfo('config.resource.removed', { name, from: 'global' });
|
|
612
|
+
}
|
|
613
|
+
};
|
|
608
614
|
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
if (currentProjectConfig) {
|
|
613
|
-
// We have a project config
|
|
614
|
-
const isInGlobal = currentGlobalConfig.resources.some((r) => r.name === name);
|
|
615
|
-
const isInProject = currentProjectConfig.resources.some((r) => r.name === name);
|
|
616
|
-
|
|
617
|
-
if (isInProject) {
|
|
618
|
-
// Resource is in project config - just remove it
|
|
619
|
-
const updated = {
|
|
620
|
-
...currentProjectConfig,
|
|
621
|
-
resources: currentProjectConfig.resources.filter((r) => r.name !== name)
|
|
622
|
-
};
|
|
623
|
-
currentProjectConfig = updated;
|
|
624
|
-
await saveConfig(configPath, updated);
|
|
625
|
-
metricsInfo('config.resource.removed', { name, from: 'project' });
|
|
626
|
-
} else if (isInGlobal) {
|
|
627
|
-
// Resource is only in global config
|
|
628
|
-
// User wants to remove a global resource from project context
|
|
629
|
-
// We can't modify global config from project context, so throw an error
|
|
630
|
-
throw new ConfigError({
|
|
631
|
-
message: `Resource "${name}" is defined in the global config`,
|
|
632
|
-
hint: `To remove this resource globally, edit the global config at "${expandHome(GLOBAL_CONFIG_DIR)}/${GLOBAL_CONFIG_FILENAME}" or run the command without a project config present.`
|
|
633
|
-
});
|
|
634
|
-
}
|
|
635
|
-
} else {
|
|
636
|
-
// No project config, modify global directly
|
|
637
|
-
if (!isInMutableConfig) {
|
|
638
|
-
// This shouldn't happen given the exists check above, but be safe
|
|
639
|
-
throw new ConfigError({
|
|
640
|
-
message: `Resource "${name}" not found in config`,
|
|
641
|
-
hint: CommonHints.LIST_RESOURCES
|
|
642
|
-
});
|
|
643
|
-
}
|
|
644
|
-
const updated = {
|
|
645
|
-
...mutableConfig,
|
|
646
|
-
resources: mutableConfig.resources.filter((r) => r.name !== name)
|
|
647
|
-
};
|
|
648
|
-
setMutableConfig(updated);
|
|
649
|
-
await saveConfig(configPath, updated);
|
|
650
|
-
metricsInfo('config.resource.removed', { name, from: 'global' });
|
|
651
|
-
}
|
|
652
|
-
},
|
|
615
|
+
const clearResourcesPromise = async (): Promise<{ cleared: number }> => {
|
|
616
|
+
let clearedCount = 0;
|
|
653
617
|
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
618
|
+
let resourcesDir: string[] = [];
|
|
619
|
+
try {
|
|
620
|
+
resourcesDir = await fs.readdir(resourcesDirectory);
|
|
621
|
+
} catch {
|
|
622
|
+
resourcesDir = [];
|
|
623
|
+
}
|
|
657
624
|
|
|
658
|
-
|
|
625
|
+
for (const item of resourcesDir) {
|
|
659
626
|
try {
|
|
660
|
-
|
|
627
|
+
await fs.rm(`${resourcesDirectory}/${item}`, { recursive: true, force: true });
|
|
628
|
+
clearedCount++;
|
|
661
629
|
} catch {
|
|
662
|
-
|
|
630
|
+
break;
|
|
663
631
|
}
|
|
632
|
+
}
|
|
664
633
|
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
clearedCount++;
|
|
669
|
-
} catch {
|
|
670
|
-
break;
|
|
671
|
-
}
|
|
672
|
-
}
|
|
634
|
+
metricsInfo('config.resources.cleared', { count: clearedCount });
|
|
635
|
+
return { cleared: clearedCount };
|
|
636
|
+
};
|
|
673
637
|
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
},
|
|
638
|
+
const reloadPromise = async (): Promise<void> => {
|
|
639
|
+
metricsInfo('config.reload.start', { configPath });
|
|
677
640
|
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
641
|
+
const configExists = await Bun.file(configPath).exists();
|
|
642
|
+
if (!configExists) {
|
|
643
|
+
metricsInfo('config.reload.skipped', { reason: 'file not found', configPath });
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
682
646
|
|
|
683
|
-
|
|
684
|
-
if (!configExists) {
|
|
685
|
-
metricsInfo('config.reload.skipped', { reason: 'file not found', configPath });
|
|
686
|
-
return;
|
|
687
|
-
}
|
|
647
|
+
const reloaded = await loadConfigFromPath(configPath);
|
|
688
648
|
|
|
689
|
-
|
|
649
|
+
if (currentProjectConfig !== null) {
|
|
650
|
+
currentProjectConfig = reloaded;
|
|
651
|
+
} else {
|
|
652
|
+
currentGlobalConfig = reloaded;
|
|
653
|
+
}
|
|
690
654
|
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
}
|
|
655
|
+
metricsInfo('config.reload.done', {
|
|
656
|
+
resources: reloaded.resources.length,
|
|
657
|
+
configPath
|
|
658
|
+
});
|
|
659
|
+
};
|
|
697
660
|
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
661
|
+
const service: ConfigService = {
|
|
662
|
+
resourcesDirectory,
|
|
663
|
+
configPath,
|
|
664
|
+
get resources() {
|
|
665
|
+
return getMergedResources();
|
|
702
666
|
},
|
|
703
|
-
|
|
667
|
+
get model() {
|
|
668
|
+
return getActiveConfig().model ?? DEFAULT_MODEL;
|
|
669
|
+
},
|
|
670
|
+
get provider() {
|
|
671
|
+
return getActiveConfig().provider ?? DEFAULT_PROVIDER;
|
|
672
|
+
},
|
|
673
|
+
get providerTimeoutMs() {
|
|
674
|
+
return getActiveConfig().providerTimeoutMs;
|
|
675
|
+
},
|
|
676
|
+
get maxSteps() {
|
|
677
|
+
return getActiveConfig().maxSteps ?? DEFAULT_MAX_STEPS;
|
|
678
|
+
},
|
|
679
|
+
getProviderOptions: (providerId: string) => getMergedProviderOptions()[providerId],
|
|
680
|
+
getResource: (name: string) => getMergedResources().find((r) => r.name === name),
|
|
681
|
+
|
|
682
|
+
updateModel: (provider, model, providerOptions) =>
|
|
704
683
|
Effect.tryPromise({
|
|
705
|
-
try: () =>
|
|
684
|
+
try: () => updateModelPromise(provider, model, providerOptions),
|
|
706
685
|
catch: (cause) => cause
|
|
707
686
|
}),
|
|
708
|
-
|
|
687
|
+
addResource: (resource) =>
|
|
709
688
|
Effect.tryPromise({
|
|
710
|
-
try: () =>
|
|
689
|
+
try: () => addResourcePromise(resource),
|
|
711
690
|
catch: (cause) => cause
|
|
712
691
|
}),
|
|
713
|
-
|
|
692
|
+
removeResource: (name) =>
|
|
714
693
|
Effect.tryPromise({
|
|
715
|
-
try: () =>
|
|
694
|
+
try: () => removeResourcePromise(name),
|
|
716
695
|
catch: (cause) => cause
|
|
717
696
|
}),
|
|
718
|
-
|
|
697
|
+
clearResources: () =>
|
|
719
698
|
Effect.tryPromise({
|
|
720
|
-
try: () =>
|
|
699
|
+
try: () => clearResourcesPromise(),
|
|
721
700
|
catch: (cause) => cause
|
|
722
701
|
}),
|
|
723
|
-
|
|
702
|
+
reload: () =>
|
|
724
703
|
Effect.tryPromise({
|
|
725
|
-
try: () =>
|
|
704
|
+
try: () => reloadPromise(),
|
|
726
705
|
catch: (cause) => cause
|
|
727
706
|
})
|
|
728
707
|
};
|
package/src/effect/services.ts
CHANGED
|
@@ -97,58 +97,50 @@ export const getDefaultResourceNames: Effect.Effect<string[], never, ConfigServi
|
|
|
97
97
|
|
|
98
98
|
export const reloadConfig: Effect.Effect<void, unknown, ConfigService> = Effect.flatMap(
|
|
99
99
|
configService,
|
|
100
|
-
(config) => config.
|
|
100
|
+
(config) => config.reload()
|
|
101
101
|
);
|
|
102
102
|
|
|
103
|
-
export const listProviders
|
|
104
|
-
Awaited<ReturnType<AgentServiceShape['listProviders']>>,
|
|
105
|
-
unknown,
|
|
106
|
-
AgentService
|
|
107
|
-
> = Effect.flatMap(agentService, (agent) => agent.listProvidersEffect());
|
|
103
|
+
export const listProviders = Effect.flatMap(agentService, (agent) => agent.listProviders());
|
|
108
104
|
|
|
109
105
|
export const loadCollection = (args: {
|
|
110
106
|
resourceNames: readonly string[];
|
|
111
107
|
quiet?: boolean;
|
|
112
108
|
}): Effect.Effect<
|
|
113
|
-
Awaited<ReturnType<CollectionsServiceShape['
|
|
109
|
+
Awaited<ReturnType<CollectionsServiceShape['loadPromise']>>,
|
|
114
110
|
unknown,
|
|
115
111
|
CollectionsService
|
|
116
|
-
> => Effect.flatMap(collectionsService, (collections) => collections.
|
|
112
|
+
> => Effect.flatMap(collectionsService, (collections) => collections.load(args));
|
|
117
113
|
|
|
118
114
|
export const askQuestion = (args: {
|
|
119
|
-
collection: Awaited<ReturnType<CollectionsServiceShape['
|
|
115
|
+
collection: Awaited<ReturnType<CollectionsServiceShape['loadPromise']>>;
|
|
120
116
|
question: string;
|
|
121
|
-
})
|
|
122
|
-
Effect.flatMap(agentService, (agent) => agent.askEffect(args));
|
|
117
|
+
}) => Effect.flatMap(agentService, (agent) => agent.ask(args));
|
|
123
118
|
|
|
124
119
|
export const askQuestionStream = (args: {
|
|
125
|
-
collection: Awaited<ReturnType<CollectionsServiceShape['
|
|
120
|
+
collection: Awaited<ReturnType<CollectionsServiceShape['loadPromise']>>;
|
|
126
121
|
question: string;
|
|
127
|
-
})
|
|
128
|
-
Effect.flatMap(agentService, (agent) => agent.askStreamEffect(args));
|
|
122
|
+
}) => Effect.flatMap(agentService, (agent) => agent.askStream(args));
|
|
129
123
|
|
|
130
124
|
export const updateModelConfig = (args: {
|
|
131
125
|
provider: string;
|
|
132
126
|
model: string;
|
|
133
127
|
providerOptions?: Parameters<ConfigServiceShape['updateModel']>[2];
|
|
134
|
-
})
|
|
128
|
+
}) =>
|
|
135
129
|
Effect.flatMap(configService, (config) =>
|
|
136
|
-
config.
|
|
130
|
+
config.updateModel(args.provider, args.model, args.providerOptions)
|
|
137
131
|
);
|
|
138
132
|
|
|
139
133
|
export const addConfigResource = (
|
|
140
134
|
resource: ResourceDefinition
|
|
141
135
|
): Effect.Effect<ResourceDefinition, unknown, ConfigService> =>
|
|
142
|
-
Effect.flatMap(configService, (config) => config.
|
|
136
|
+
Effect.flatMap(configService, (config) => config.addResource(resource));
|
|
143
137
|
|
|
144
138
|
export const removeConfigResource = (name: string): Effect.Effect<void, unknown, ConfigService> =>
|
|
145
|
-
Effect.flatMap(configService, (config) => config.
|
|
139
|
+
Effect.flatMap(configService, (config) => config.removeResource(name));
|
|
146
140
|
|
|
147
|
-
export const clearConfigResources
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
ConfigService
|
|
151
|
-
> = Effect.flatMap(configService, (config) => config.clearResourcesEffect());
|
|
141
|
+
export const clearConfigResources = Effect.flatMap(configService, (config) =>
|
|
142
|
+
config.clearResources()
|
|
143
|
+
);
|
|
152
144
|
|
|
153
145
|
export const loadedResourceCollectionKey = (resourceNames: readonly string[]) =>
|
|
154
146
|
getCollectionKey(resourceNames);
|