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.
@@ -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 config.addResource({
384
- name: 'new-resource',
385
- type: 'git',
386
- url: 'https://github.com/test/new-resource',
387
- branch: 'main'
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 config.addResource({
578
- name: 'new-resource',
579
- type: 'git',
580
- url: 'https://github.com/test/new-resource',
581
- branch: 'main'
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'));
@@ -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) => Promise<ResourceDefinition>;
151
- addResourceEffect: (resource: ResourceDefinition) => Effect.Effect<ResourceDefinition, unknown>;
152
- removeResource: (name: string) => Promise<void>;
153
- removeResourceEffect: (name: string) => Effect.Effect<void, unknown>;
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 service: ConfigService = {
499
- resourcesDirectory,
500
- configPath,
501
- get resources() {
502
- return getMergedResources();
503
- },
504
- get model() {
505
- return getActiveConfig().model ?? DEFAULT_MODEL;
506
- },
507
- get provider() {
508
- return getActiveConfig().provider ?? DEFAULT_PROVIDER;
509
- },
510
- get providerTimeoutMs() {
511
- return getActiveConfig().providerTimeoutMs;
512
- },
513
- get maxSteps() {
514
- return getActiveConfig().maxSteps ?? DEFAULT_MAX_STEPS;
515
- },
516
- getProviderOptions: (providerId: string) => getMergedProviderOptions()[providerId],
517
- getResource: (name: string) => getMergedResources().find((r) => r.name === name),
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
- updateModel: async (
520
- provider: string,
521
- model: string,
522
- providerOptions?: ProviderOptionsConfig
523
- ) => {
524
- if (!isProviderSupported(provider)) {
525
- const available = getSupportedProviders();
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: `Provider "${provider}" is not supported`,
528
- hint: `Available providers: ${available.join(', ')}. Open an issue to request this provider: https://github.com/davis7dotsh/better-context/issues.`
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
- const mutableConfig = getMutableConfig();
532
- const existingProviderOptions = mutableConfig.providerOptions ?? {};
533
- const nextProviderOptions = providerOptions
534
- ? {
535
- ...existingProviderOptions,
536
- [provider]: {
537
- ...(existingProviderOptions[provider] ?? {}),
538
- ...providerOptions
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
- if (provider === 'openai-compat') {
550
- const merged = currentProjectConfig
551
- ? mergeProviderOptions(currentGlobalConfig, updated)
552
- : mergeProviderOptions(updated, null);
553
- const compat = merged['openai-compat'];
554
- const baseURL = compat?.baseURL?.trim();
555
- const name = compat?.name?.trim();
556
- if (!baseURL || !name) {
557
- throw new ConfigError({
558
- message: 'openai-compat requires baseURL and name',
559
- hint: 'Run "btca connect -p openai-compat" to configure baseURL and name.'
560
- });
561
- }
562
- }
563
- setMutableConfig(updated);
564
- await saveConfig(configPath, updated);
565
- metricsInfo('config.model.updated', { provider, model });
566
- return {
567
- provider,
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
- addResource: async (resource: ResourceDefinition) => {
574
- // Check for duplicate name in merged resources
575
- const mergedResources = getMergedResources();
576
- if (mergedResources.some((r) => r.name === resource.name)) {
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 "${resource.name}" already exists`,
579
- hint: `Choose a different name or remove the existing resource first with "btca remove ${resource.name}".`
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: [...mutableConfig.resources, resource]
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.added', { name: resource.name, type: resource.type });
592
- return resource;
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
- const mutableConfig = getMutableConfig();
610
- const isInMutableConfig = mutableConfig.resources.some((r) => r.name === name);
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
- clearResources: async () => {
655
- // Clear the resources directory
656
- let clearedCount = 0;
618
+ let resourcesDir: string[] = [];
619
+ try {
620
+ resourcesDir = await fs.readdir(resourcesDirectory);
621
+ } catch {
622
+ resourcesDir = [];
623
+ }
657
624
 
658
- let resourcesDir: string[] = [];
625
+ for (const item of resourcesDir) {
659
626
  try {
660
- resourcesDir = await fs.readdir(resourcesDirectory);
627
+ await fs.rm(`${resourcesDirectory}/${item}`, { recursive: true, force: true });
628
+ clearedCount++;
661
629
  } catch {
662
- resourcesDir = [];
630
+ break;
663
631
  }
632
+ }
664
633
 
665
- for (const item of resourcesDir) {
666
- try {
667
- await fs.rm(`${resourcesDirectory}/${item}`, { recursive: true, force: true });
668
- clearedCount++;
669
- } catch {
670
- break;
671
- }
672
- }
634
+ metricsInfo('config.resources.cleared', { count: clearedCount });
635
+ return { cleared: clearedCount };
636
+ };
673
637
 
674
- metricsInfo('config.resources.cleared', { count: clearedCount });
675
- return { cleared: clearedCount };
676
- },
638
+ const reloadPromise = async (): Promise<void> => {
639
+ metricsInfo('config.reload.start', { configPath });
677
640
 
678
- reload: async () => {
679
- // Reload the config file from disk
680
- // configPath points to either project config (if it existed at startup) or global config
681
- metricsInfo('config.reload.start', { configPath });
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
- const configExists = await Bun.file(configPath).exists();
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
- const reloaded = await loadConfigFromPath(configPath);
649
+ if (currentProjectConfig !== null) {
650
+ currentProjectConfig = reloaded;
651
+ } else {
652
+ currentGlobalConfig = reloaded;
653
+ }
690
654
 
691
- // Update the appropriate config based on what we had at startup
692
- if (currentProjectConfig !== null) {
693
- currentProjectConfig = reloaded;
694
- } else {
695
- currentGlobalConfig = reloaded;
696
- }
655
+ metricsInfo('config.reload.done', {
656
+ resources: reloaded.resources.length,
657
+ configPath
658
+ });
659
+ };
697
660
 
698
- metricsInfo('config.reload.done', {
699
- resources: reloaded.resources.length,
700
- configPath
701
- });
661
+ const service: ConfigService = {
662
+ resourcesDirectory,
663
+ configPath,
664
+ get resources() {
665
+ return getMergedResources();
702
666
  },
703
- updateModelEffect: (provider, model, providerOptions) =>
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: () => service.updateModel(provider, model, providerOptions),
684
+ try: () => updateModelPromise(provider, model, providerOptions),
706
685
  catch: (cause) => cause
707
686
  }),
708
- addResourceEffect: (resource) =>
687
+ addResource: (resource) =>
709
688
  Effect.tryPromise({
710
- try: () => service.addResource(resource),
689
+ try: () => addResourcePromise(resource),
711
690
  catch: (cause) => cause
712
691
  }),
713
- removeResourceEffect: (name) =>
692
+ removeResource: (name) =>
714
693
  Effect.tryPromise({
715
- try: () => service.removeResource(name),
694
+ try: () => removeResourcePromise(name),
716
695
  catch: (cause) => cause
717
696
  }),
718
- clearResourcesEffect: () =>
697
+ clearResources: () =>
719
698
  Effect.tryPromise({
720
- try: () => service.clearResources(),
699
+ try: () => clearResourcesPromise(),
721
700
  catch: (cause) => cause
722
701
  }),
723
- reloadEffect: () =>
702
+ reload: () =>
724
703
  Effect.tryPromise({
725
- try: () => service.reload(),
704
+ try: () => reloadPromise(),
726
705
  catch: (cause) => cause
727
706
  })
728
707
  };
@@ -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.reloadEffect()
100
+ (config) => config.reload()
101
101
  );
102
102
 
103
- export const listProviders: Effect.Effect<
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['load']>>,
109
+ Awaited<ReturnType<CollectionsServiceShape['loadPromise']>>,
114
110
  unknown,
115
111
  CollectionsService
116
- > => Effect.flatMap(collectionsService, (collections) => collections.loadEffect(args));
112
+ > => Effect.flatMap(collectionsService, (collections) => collections.load(args));
117
113
 
118
114
  export const askQuestion = (args: {
119
- collection: Awaited<ReturnType<CollectionsServiceShape['load']>>;
115
+ collection: Awaited<ReturnType<CollectionsServiceShape['loadPromise']>>;
120
116
  question: string;
121
- }): Effect.Effect<Awaited<ReturnType<AgentServiceShape['ask']>>, unknown, AgentService> =>
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['load']>>;
120
+ collection: Awaited<ReturnType<CollectionsServiceShape['loadPromise']>>;
126
121
  question: string;
127
- }): Effect.Effect<Awaited<ReturnType<AgentServiceShape['askStream']>>, unknown, AgentService> =>
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
- }): Effect.Effect<Awaited<ReturnType<ConfigServiceShape['updateModel']>>, unknown, ConfigService> =>
128
+ }) =>
135
129
  Effect.flatMap(configService, (config) =>
136
- config.updateModelEffect(args.provider, args.model, args.providerOptions)
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.addResourceEffect(resource));
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.removeResourceEffect(name));
139
+ Effect.flatMap(configService, (config) => config.removeResource(name));
146
140
 
147
- export const clearConfigResources: Effect.Effect<
148
- Awaited<ReturnType<ConfigServiceShape['clearResources']>>,
149
- unknown,
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);