btca-server 2.0.1 → 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "btca-server",
3
- "version": "2.0.1",
3
+ "version": "2.0.3",
4
4
  "description": "BTCA server for answering questions about your codebase using OpenCode AI",
5
5
  "author": "Ben Davis",
6
6
  "license": "MIT",
@@ -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 { createAgentService } from './service.ts';
7
8
  import { load as loadConfig } from '../config/index.ts';
@@ -71,10 +72,12 @@ describe('Agent', () => {
71
72
  vfsId
72
73
  };
73
74
 
74
- const result = await agent.ask({
75
- collection,
76
- question: 'What number is the answer to life according to the README?'
77
- });
75
+ const result = await Effect.runPromise(
76
+ agent.ask({
77
+ collection,
78
+ question: 'What number is the answer to life according to the README?'
79
+ })
80
+ );
78
81
 
79
82
  expect(result).toBeDefined();
80
83
  expect(result.answer).toBeDefined();
@@ -102,10 +105,12 @@ describe('Agent', () => {
102
105
  vfsId
103
106
  };
104
107
 
105
- const { stream, model } = await agent.askStream({
106
- collection,
107
- question: 'What is the capital of France according to the data file?'
108
- });
108
+ const { stream, model } = await Effect.runPromise(
109
+ agent.askStream({
110
+ collection,
111
+ question: 'What is the capital of France according to the data file?'
112
+ })
113
+ );
109
114
 
110
115
  expect(model).toBeDefined();
111
116
  expect(model.provider).toBeDefined();
@@ -154,10 +159,12 @@ describe('Agent', () => {
154
159
  vfsId
155
160
  };
156
161
 
157
- const result = await agent.ask({
158
- collection,
159
- question: 'What number is the answer according to the README?'
160
- });
162
+ const result = await Effect.runPromise(
163
+ agent.ask({
164
+ collection,
165
+ question: 'What number is the answer according to the README?'
166
+ })
167
+ );
161
168
 
162
169
  expect(result).toBeDefined();
163
170
  expect(hasVirtualFs(vfsId)).toBe(false);
@@ -200,10 +207,12 @@ describe('Agent', () => {
200
207
  vfsId
201
208
  };
202
209
 
203
- const { stream } = await agent.askStream({
204
- collection,
205
- question: 'What is the capital of France according to the README?'
206
- });
210
+ const { stream } = await Effect.runPromise(
211
+ agent.askStream({
212
+ collection,
213
+ question: 'What is the capital of France according to the README?'
214
+ })
215
+ );
207
216
 
208
217
  for await (const _event of stream) {
209
218
  // drain stream to trigger cleanup
@@ -87,11 +87,7 @@ export class ProviderNotConnectedError extends Error {
87
87
  }
88
88
 
89
89
  export type AgentService = {
90
- askStream: (args: { collection: CollectionResult; question: string }) => Promise<{
91
- stream: AsyncIterable<AgentEvent>;
92
- model: { provider: string; model: string };
93
- }>;
94
- askStreamEffect: (args: { collection: CollectionResult; question: string }) => Effect.Effect<
90
+ askStream: (args: { collection: CollectionResult; question: string }) => Effect.Effect<
95
91
  {
96
92
  stream: AsyncIterable<AgentEvent>;
97
93
  model: { provider: string; model: string };
@@ -99,17 +95,12 @@ export type AgentService = {
99
95
  unknown
100
96
  >;
101
97
 
102
- ask: (args: { collection: CollectionResult; question: string }) => Promise<AgentResult>;
103
- askEffect: (args: {
98
+ ask: (args: {
104
99
  collection: CollectionResult;
105
100
  question: string;
106
101
  }) => Effect.Effect<AgentResult, unknown>;
107
102
 
108
- listProviders: () => Promise<{
109
- all: { id: string; models: Record<string, unknown> }[];
110
- connected: string[];
111
- }>;
112
- listProvidersEffect: () => Effect.Effect<
103
+ listProviders: () => Effect.Effect<
113
104
  {
114
105
  all: { id: string; models: Record<string, unknown> }[];
115
106
  connected: string[];
@@ -121,36 +112,39 @@ export type AgentService = {
121
112
  export type Service = AgentService;
122
113
 
123
114
  export const createAgentService = (config: ConfigServiceShape): AgentService => {
124
- const cleanupCollection = (collection: CollectionResult) =>
125
- Effect.promise(async () => {
126
- if (collection.vfsId) {
127
- disposeVirtualFs(collection.vfsId);
128
- clearVirtualCollectionMetadata(collection.vfsId);
129
- }
130
- try {
131
- await collection.cleanup?.();
132
- } catch {
133
- return;
134
- }
135
- });
115
+ const cleanupCollection = async (collection: CollectionResult) => {
116
+ if (collection.vfsId) {
117
+ disposeVirtualFs(collection.vfsId);
118
+ clearVirtualCollectionMetadata(collection.vfsId);
119
+ }
120
+ try {
121
+ await collection.cleanup?.();
122
+ } catch {
123
+ return;
124
+ }
125
+ };
136
126
 
137
- const ensureProviderConnected = Effect.fn(function* () {
138
- const isAuthed = yield* Effect.tryPromise(() => isAuthenticated(config.provider));
127
+ const ensureProviderConnected = async () => {
128
+ const isAuthed = await isAuthenticated(config.provider);
139
129
  const requiresAuth = config.provider !== 'opencode' && config.provider !== 'openai-compat';
140
130
  if (isAuthed || !requiresAuth) return;
141
- const authenticated = yield* Effect.tryPromise(() => getAuthenticatedProviders());
142
- yield* Effect.fail(
143
- new ProviderNotConnectedError({
144
- providerId: config.provider,
145
- connectedProviders: authenticated
146
- })
147
- );
148
- });
131
+ const authenticated = await getAuthenticatedProviders();
132
+ throw new ProviderNotConnectedError({
133
+ providerId: config.provider,
134
+ connectedProviders: authenticated
135
+ });
136
+ };
149
137
 
150
138
  /**
151
139
  * Ask a question and stream the response using the new AI SDK loop
152
140
  */
153
- const askStream: AgentService['askStream'] = async ({ collection, question }) => {
141
+ const askStreamImpl = async ({
142
+ collection,
143
+ question
144
+ }: {
145
+ collection: CollectionResult;
146
+ question: string;
147
+ }) => {
154
148
  metricsInfo('agent.ask.start', {
155
149
  provider: config.provider,
156
150
  model: config.model,
@@ -158,9 +152,9 @@ export const createAgentService = (config: ConfigServiceShape): AgentService =>
158
152
  });
159
153
 
160
154
  try {
161
- await Effect.runPromise(ensureProviderConnected());
155
+ await ensureProviderConnected();
162
156
  } catch (error) {
163
- await Effect.runPromise(cleanupCollection(collection));
157
+ await cleanupCollection(collection);
164
158
  throw error;
165
159
  }
166
160
 
@@ -181,7 +175,7 @@ export const createAgentService = (config: ConfigServiceShape): AgentService =>
181
175
  yield event;
182
176
  }
183
177
  } finally {
184
- await Effect.runPromise(cleanupCollection(collection));
178
+ await cleanupCollection(collection);
185
179
  }
186
180
  })();
187
181
 
@@ -194,103 +188,99 @@ export const createAgentService = (config: ConfigServiceShape): AgentService =>
194
188
  /**
195
189
  * Ask a question and return the complete response
196
190
  */
197
- const ask: AgentService['ask'] = async ({ collection, question }) => {
198
- return Effect.runPromise(
199
- Effect.gen(function* () {
200
- metricsInfo('agent.ask.start', {
201
- provider: config.provider,
202
- model: config.model,
203
- questionLength: question.length
204
- });
191
+ const askImpl = async ({
192
+ collection,
193
+ question
194
+ }: {
195
+ collection: CollectionResult;
196
+ question: string;
197
+ }) => {
198
+ try {
199
+ metricsInfo('agent.ask.start', {
200
+ provider: config.provider,
201
+ model: config.model,
202
+ questionLength: question.length
203
+ });
205
204
 
206
- yield* ensureProviderConnected();
205
+ await ensureProviderConnected();
207
206
 
208
- const result = yield* Effect.tryPromise({
209
- try: () =>
210
- runAgentLoop({
211
- providerId: config.provider,
212
- modelId: config.model,
213
- maxSteps: config.maxSteps,
214
- collectionPath: collection.path,
215
- vfsId: collection.vfsId,
216
- agentInstructions: collection.agentInstructions,
217
- question,
218
- providerOptions: config.getProviderOptions(config.provider)
219
- }),
220
- catch: (cause) =>
221
- new AgentError({
222
- message: getErrorMessage(cause),
223
- hint:
224
- getErrorHint(cause) ??
225
- 'This may be a temporary issue. Try running the command again.',
226
- cause
227
- })
207
+ let result: Awaited<ReturnType<typeof runAgentLoop>>;
208
+ try {
209
+ result = await runAgentLoop({
210
+ providerId: config.provider,
211
+ modelId: config.model,
212
+ maxSteps: config.maxSteps,
213
+ collectionPath: collection.path,
214
+ vfsId: collection.vfsId,
215
+ agentInstructions: collection.agentInstructions,
216
+ question,
217
+ providerOptions: config.getProviderOptions(config.provider)
228
218
  });
229
-
230
- metricsInfo('agent.ask.complete', {
231
- provider: config.provider,
232
- model: config.model,
233
- answerLength: result.answer.length,
234
- eventCount: result.events.length
219
+ } catch (cause) {
220
+ throw new AgentError({
221
+ message: getErrorMessage(cause),
222
+ hint:
223
+ getErrorHint(cause) ?? 'This may be a temporary issue. Try running the command again.',
224
+ cause
235
225
  });
226
+ }
236
227
 
237
- return {
238
- answer: result.answer,
239
- model: result.model,
240
- events: result.events
241
- };
242
- }).pipe(
243
- Effect.tapError((error) =>
244
- Effect.sync(() => metricsError('agent.ask.error', { error: metricsErrorInfo(error) }))
245
- ),
246
- Effect.ensuring(cleanupCollection(collection))
247
- )
248
- );
228
+ metricsInfo('agent.ask.complete', {
229
+ provider: config.provider,
230
+ model: config.model,
231
+ answerLength: result.answer.length,
232
+ eventCount: result.events.length
233
+ });
234
+
235
+ return {
236
+ answer: result.answer,
237
+ model: result.model,
238
+ events: result.events
239
+ };
240
+ } catch (error) {
241
+ metricsError('agent.ask.error', { error: metricsErrorInfo(error) });
242
+ throw error;
243
+ } finally {
244
+ await cleanupCollection(collection);
245
+ }
249
246
  };
250
247
 
251
248
  /**
252
249
  * List available providers using local auth data
253
250
  */
254
- const listProviders: AgentService['listProviders'] = async () => {
255
- return Effect.runPromise(
256
- Effect.gen(function* () {
257
- const supportedProviders = getSupportedProviders();
258
- const authenticatedProviders = yield* Effect.tryPromise(() => getAuthenticatedProviders());
259
- const all = supportedProviders.map((id) => ({
260
- id,
261
- models: {} as Record<string, unknown>
262
- }));
251
+ const listProvidersImpl = async () => {
252
+ const supportedProviders = getSupportedProviders();
253
+ const authenticatedProviders = await getAuthenticatedProviders();
254
+ const all = supportedProviders.map((id) => ({
255
+ id,
256
+ models: {} as Record<string, unknown>
257
+ }));
263
258
 
264
- return {
265
- all,
266
- connected: authenticatedProviders
267
- };
268
- })
269
- );
259
+ return {
260
+ all,
261
+ connected: authenticatedProviders
262
+ };
270
263
  };
271
264
 
272
- const askStreamEffect: AgentService['askStreamEffect'] = (args) =>
265
+ const askStream: AgentService['askStream'] = (args) =>
273
266
  Effect.tryPromise({
274
- try: () => askStream(args),
267
+ try: () => askStreamImpl(args),
275
268
  catch: (cause) => cause
276
269
  });
277
- const askEffect: AgentService['askEffect'] = (args) =>
270
+ const ask: AgentService['ask'] = (args) =>
278
271
  Effect.tryPromise({
279
- try: () => ask(args),
272
+ try: () => askImpl(args),
280
273
  catch: (cause) => cause
281
274
  });
282
- const listProvidersEffect: AgentService['listProvidersEffect'] = () =>
275
+ const listProviders: AgentService['listProviders'] = () =>
283
276
  Effect.tryPromise({
284
- try: () => listProviders(),
277
+ try: () => listProvidersImpl(),
285
278
  catch: (cause) => cause
286
279
  });
287
280
 
288
281
  return {
289
282
  askStream,
290
283
  ask,
291
- listProviders,
292
- askStreamEffect,
293
- askEffect,
294
- listProvidersEffect
284
+ listProviders
295
285
  };
296
286
  };
@@ -0,0 +1,119 @@
1
+ import { describe, expect, it } from 'bun:test';
2
+ import { promises as fs } from 'node:fs';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+
6
+ import type { ConfigService } from '../config/index.ts';
7
+ import type { ResourcesService } from '../resources/service.ts';
8
+ import { createCollectionsService } from './service.ts';
9
+ import { disposeVirtualFs, existsInVirtualFs } from '../vfs/virtual-fs.ts';
10
+
11
+ const createLocalResource = (name: string, resourcePath: string) => ({
12
+ _tag: 'fs-based' as const,
13
+ name,
14
+ fsName: name,
15
+ type: 'local' as const,
16
+ repoSubPaths: [],
17
+ specialAgentInstructions: '',
18
+ getAbsoluteDirectoryPath: async () => resourcePath
19
+ });
20
+
21
+ const createConfigMock = () =>
22
+ ({
23
+ getResource: () => undefined
24
+ }) as unknown as ConfigService;
25
+
26
+ const createResourcesMock = (resourcePath: string) =>
27
+ ({
28
+ load: () => {
29
+ throw new Error('Not implemented in test');
30
+ },
31
+ loadPromise: async () => createLocalResource('repo', resourcePath)
32
+ }) as unknown as ResourcesService;
33
+
34
+ const runGit = (cwd: string, args: string[]) => {
35
+ const result = Bun.spawnSync({
36
+ cmd: ['git', ...args],
37
+ cwd,
38
+ stdout: 'pipe',
39
+ stderr: 'pipe'
40
+ });
41
+ if (result.exitCode !== 0) {
42
+ throw new Error(
43
+ `git ${args.join(' ')} failed: ${new TextDecoder().decode(result.stderr).trim()}`
44
+ );
45
+ }
46
+ };
47
+
48
+ const cleanupCollection = async (collection: { vfsId?: string; cleanup?: () => Promise<void> }) => {
49
+ await collection.cleanup?.();
50
+ if (collection.vfsId) disposeVirtualFs(collection.vfsId);
51
+ };
52
+
53
+ describe('createCollectionsService', () => {
54
+ it('imports git-backed local resources from tracked and unignored files only', async () => {
55
+ const resourcePath = await fs.mkdtemp(path.join(os.tmpdir(), 'btca-collections-git-'));
56
+ const collections = createCollectionsService({
57
+ config: createConfigMock(),
58
+ resources: createResourcesMock(resourcePath)
59
+ });
60
+
61
+ try {
62
+ await fs.mkdir(path.join(resourcePath, 'node_modules', 'pkg'), { recursive: true });
63
+ await fs.writeFile(path.join(resourcePath, '.gitignore'), 'node_modules\n');
64
+ await fs.writeFile(path.join(resourcePath, 'package.json'), '{"name":"repo"}\n');
65
+ await fs.writeFile(path.join(resourcePath, 'README.md'), 'local notes\n');
66
+ await fs.writeFile(path.join(resourcePath, 'node_modules', 'pkg', 'index.js'), 'ignored\n');
67
+
68
+ runGit(resourcePath, ['init', '-q']);
69
+ runGit(resourcePath, ['add', '.gitignore', 'package.json']);
70
+
71
+ const collection = await collections.loadPromise({ resourceNames: ['repo'] });
72
+
73
+ try {
74
+ expect(await existsInVirtualFs('/repo/package.json', collection.vfsId)).toBe(true);
75
+ expect(await existsInVirtualFs('/repo/README.md', collection.vfsId)).toBe(true);
76
+ expect(await existsInVirtualFs('/repo/node_modules/pkg/index.js', collection.vfsId)).toBe(
77
+ false
78
+ );
79
+ expect(await existsInVirtualFs('/repo/.git/config', collection.vfsId)).toBe(false);
80
+ } finally {
81
+ await cleanupCollection(collection);
82
+ }
83
+ } finally {
84
+ await fs.rm(resourcePath, { recursive: true, force: true });
85
+ }
86
+ });
87
+
88
+ it('falls back to directory import and still skips heavy local build directories', async () => {
89
+ const resourcePath = await fs.mkdtemp(path.join(os.tmpdir(), 'btca-collections-local-'));
90
+ const collections = createCollectionsService({
91
+ config: createConfigMock(),
92
+ resources: createResourcesMock(resourcePath)
93
+ });
94
+
95
+ try {
96
+ await fs.mkdir(path.join(resourcePath, 'node_modules', 'pkg'), { recursive: true });
97
+ await fs.mkdir(path.join(resourcePath, 'dist'), { recursive: true });
98
+ await fs.writeFile(path.join(resourcePath, 'package.json'), '{"name":"repo"}\n');
99
+ await fs.writeFile(path.join(resourcePath, 'README.md'), 'hello\n');
100
+ await fs.writeFile(path.join(resourcePath, 'node_modules', 'pkg', 'index.js'), 'ignored\n');
101
+ await fs.writeFile(path.join(resourcePath, 'dist', 'bundle.js'), 'ignored\n');
102
+
103
+ const collection = await collections.loadPromise({ resourceNames: ['repo'] });
104
+
105
+ try {
106
+ expect(await existsInVirtualFs('/repo/package.json', collection.vfsId)).toBe(true);
107
+ expect(await existsInVirtualFs('/repo/README.md', collection.vfsId)).toBe(true);
108
+ expect(await existsInVirtualFs('/repo/node_modules/pkg/index.js', collection.vfsId)).toBe(
109
+ false
110
+ );
111
+ expect(await existsInVirtualFs('/repo/dist/bundle.js', collection.vfsId)).toBe(false);
112
+ } finally {
113
+ await cleanupCollection(collection);
114
+ }
115
+ } finally {
116
+ await fs.rm(resourcePath, { recursive: true, force: true });
117
+ }
118
+ });
119
+ });
@@ -15,6 +15,7 @@ import {
15
15
  createVirtualFs,
16
16
  disposeVirtualFs,
17
17
  importDirectoryIntoVirtualFs,
18
+ importPathsIntoVirtualFs,
18
19
  mkdirVirtualFs,
19
20
  rmVirtualFs
20
21
  } from '../vfs/virtual-fs.ts';
@@ -25,11 +26,14 @@ import {
25
26
  } from './virtual-metadata.ts';
26
27
 
27
28
  export type CollectionsService = {
28
- load: (args: { resourceNames: readonly string[]; quiet?: boolean }) => Promise<CollectionResult>;
29
- loadEffect: (args: {
29
+ load: (args: {
30
30
  resourceNames: readonly string[];
31
31
  quiet?: boolean;
32
- }) => Effect.Effect<CollectionResult, CollectionError>;
32
+ }) => Effect.Effect<CollectionResult, CollectionError, never>;
33
+ loadPromise: (args: {
34
+ resourceNames: readonly string[];
35
+ quiet?: boolean;
36
+ }) => Promise<CollectionResult>;
33
37
  };
34
38
 
35
39
  const encodePathSegments = (value: string) => value.split('/').map(encodeURIComponent).join('/');
@@ -92,6 +96,53 @@ const ignoreErrors = async (action: () => Promise<unknown>) => {
92
96
  }
93
97
  };
94
98
 
99
+ const LOCAL_RESOURCE_IGNORED_DIRECTORIES = new Set([
100
+ '.git',
101
+ '.turbo',
102
+ '.next',
103
+ '.svelte-kit',
104
+ '.vercel',
105
+ '.cache',
106
+ 'coverage',
107
+ 'dist',
108
+ 'build',
109
+ 'out',
110
+ 'node_modules'
111
+ ]);
112
+
113
+ const normalizeRelativePath = (value: string) => value.split(path.sep).join('/');
114
+
115
+ const shouldIgnoreImportedPath = (resource: BtcaFsResource, relativePath: string) => {
116
+ const normalized = normalizeRelativePath(relativePath);
117
+ if (!normalized || normalized === '.') return false;
118
+ const segments = normalized.split('/');
119
+ if (segments.includes('.git')) return true;
120
+ if (resource.type !== 'local') return false;
121
+ return segments.some((segment) => LOCAL_RESOURCE_IGNORED_DIRECTORIES.has(segment));
122
+ };
123
+
124
+ const listGitVisiblePaths = async (resourcePath: string) => {
125
+ try {
126
+ const proc = Bun.spawn(
127
+ ['git', 'ls-files', '-z', '--cached', '--others', '--exclude-standard'],
128
+ {
129
+ cwd: resourcePath,
130
+ stdout: 'pipe',
131
+ stderr: 'ignore'
132
+ }
133
+ );
134
+ const stdout = await new Response(proc.stdout).text();
135
+ const exitCode = await proc.exited;
136
+ if (exitCode !== 0) return null;
137
+ return stdout
138
+ .split('\0')
139
+ .map((entry) => entry.trim())
140
+ .filter((entry) => entry.length > 0);
141
+ } catch {
142
+ return null;
143
+ }
144
+ };
145
+
95
146
  const initVirtualRoot = async (collectionPath: string, vfsId: string) => {
96
147
  try {
97
148
  await mkdirVirtualFs(collectionPath, { recursive: true }, vfsId);
@@ -106,7 +157,7 @@ const initVirtualRoot = async (collectionPath: string, vfsId: string) => {
106
157
 
107
158
  const loadResource = async (resources: ResourcesService, name: string, quiet: boolean) => {
108
159
  try {
109
- return await resources.load(name, { quiet });
160
+ return await resources.loadPromise(name, { quiet });
110
161
  } catch (cause) {
111
162
  const underlyingHint = getErrorHint(cause);
112
163
  const underlyingMessage = getErrorMessage(cause);
@@ -139,16 +190,24 @@ const virtualizeResource = async (args: {
139
190
  vfsId: string;
140
191
  }) => {
141
192
  try {
193
+ if (args.resource.type === 'local') {
194
+ const gitVisiblePaths = await listGitVisiblePaths(args.resourcePath);
195
+ if (gitVisiblePaths) {
196
+ await importPathsIntoVirtualFs({
197
+ sourcePath: args.resourcePath,
198
+ destinationPath: args.virtualResourcePath,
199
+ relativePaths: gitVisiblePaths,
200
+ vfsId: args.vfsId
201
+ });
202
+ return;
203
+ }
204
+ }
205
+
142
206
  await importDirectoryIntoVirtualFs({
143
207
  sourcePath: args.resourcePath,
144
208
  destinationPath: args.virtualResourcePath,
145
209
  vfsId: args.vfsId,
146
- ignore: (relativePath) => {
147
- const normalized = relativePath.split(path.sep).join('/');
148
- return (
149
- normalized === '.git' || normalized.startsWith('.git/') || normalized.includes('/.git/')
150
- );
151
- }
210
+ ignore: (relativePath) => shouldIgnoreImportedPath(args.resource, relativePath)
152
211
  });
153
212
  } catch (cause) {
154
213
  throw new CollectionError({
@@ -270,7 +329,7 @@ export const createCollectionsService = (args: {
270
329
  config: ConfigServiceShape;
271
330
  resources: ResourcesService;
272
331
  }): CollectionsService => {
273
- const load: CollectionsService['load'] = ({ resourceNames, quiet = false }) =>
332
+ const loadPromise: CollectionsService['loadPromise'] = ({ resourceNames, quiet = false }) =>
274
333
  runTransaction('collections.load', async () => {
275
334
  const uniqueNames = Array.from(new Set(resourceNames));
276
335
  if (uniqueNames.length === 0)
@@ -368,9 +427,9 @@ export const createCollectionsService = (args: {
368
427
  }
369
428
  });
370
429
 
371
- const loadEffect: CollectionsService['loadEffect'] = ({ resourceNames, quiet }) =>
430
+ const load: CollectionsService['load'] = ({ resourceNames, quiet }) =>
372
431
  Effect.tryPromise({
373
- try: () => load({ resourceNames, quiet }),
432
+ try: () => loadPromise({ resourceNames, quiet }),
374
433
  catch: (cause) =>
375
434
  cause instanceof CollectionError
376
435
  ? cause
@@ -383,6 +442,6 @@ export const createCollectionsService = (args: {
383
442
 
384
443
  return {
385
444
  load,
386
- loadEffect
445
+ loadPromise
387
446
  };
388
447
  };