btca-server 1.0.932 → 1.0.950
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/service.ts +2 -0
- package/src/config/config.test.ts +54 -1
- package/src/config/index.ts +8 -1
- package/src/index.ts +2 -0
package/package.json
CHANGED
package/src/agent/service.ts
CHANGED
|
@@ -149,6 +149,7 @@ export namespace Agent {
|
|
|
149
149
|
const stream = AgentLoop.stream({
|
|
150
150
|
providerId: config.provider,
|
|
151
151
|
modelId: config.model,
|
|
152
|
+
maxSteps: config.maxSteps,
|
|
152
153
|
collectionPath: collection.path,
|
|
153
154
|
vfsId: collection.vfsId,
|
|
154
155
|
agentInstructions: collection.agentInstructions,
|
|
@@ -207,6 +208,7 @@ export namespace Agent {
|
|
|
207
208
|
AgentLoop.run({
|
|
208
209
|
providerId: config.provider,
|
|
209
210
|
modelId: config.model,
|
|
211
|
+
maxSteps: config.maxSteps,
|
|
210
212
|
collectionPath: collection.path,
|
|
211
213
|
vfsId: collection.vfsId,
|
|
212
214
|
agentInstructions: collection.agentInstructions,
|
|
@@ -3,7 +3,13 @@ import { promises as fs } from 'node:fs';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import os from 'node:os';
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
Config,
|
|
8
|
+
DEFAULT_MAX_STEPS,
|
|
9
|
+
DEFAULT_MODEL,
|
|
10
|
+
DEFAULT_PROVIDER,
|
|
11
|
+
DEFAULT_RESOURCES
|
|
12
|
+
} from './index.ts';
|
|
7
13
|
|
|
8
14
|
describe('Config', () => {
|
|
9
15
|
let testDir: string;
|
|
@@ -32,6 +38,7 @@ describe('Config', () => {
|
|
|
32
38
|
|
|
33
39
|
expect(config.provider).toBe(DEFAULT_PROVIDER);
|
|
34
40
|
expect(config.model).toBe(DEFAULT_MODEL);
|
|
41
|
+
expect(config.maxSteps).toBe(DEFAULT_MAX_STEPS);
|
|
35
42
|
expect(config.resources.length).toBe(DEFAULT_RESOURCES.length);
|
|
36
43
|
expect(config.getResource('svelte')).toBeDefined();
|
|
37
44
|
});
|
|
@@ -121,6 +128,30 @@ describe('Config', () => {
|
|
|
121
128
|
expect(config.model).toBe('commented-model');
|
|
122
129
|
});
|
|
123
130
|
|
|
131
|
+
it('loads maxSteps when provided in config', async () => {
|
|
132
|
+
const projectConfig = {
|
|
133
|
+
$schema: 'https://btca.dev/btca.schema.json',
|
|
134
|
+
provider: 'test-provider',
|
|
135
|
+
model: 'test-model',
|
|
136
|
+
maxSteps: 80,
|
|
137
|
+
resources: [
|
|
138
|
+
{
|
|
139
|
+
name: 'test-resource',
|
|
140
|
+
type: 'git',
|
|
141
|
+
url: 'https://github.com/test/repo',
|
|
142
|
+
branch: 'main'
|
|
143
|
+
}
|
|
144
|
+
]
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
await fs.writeFile(path.join(testDir, 'btca.config.jsonc'), JSON.stringify(projectConfig));
|
|
148
|
+
process.chdir(testDir);
|
|
149
|
+
|
|
150
|
+
const config = await Config.load();
|
|
151
|
+
|
|
152
|
+
expect(config.maxSteps).toBe(80);
|
|
153
|
+
});
|
|
154
|
+
|
|
124
155
|
it('getResource returns undefined for unknown resource', async () => {
|
|
125
156
|
process.chdir(testDir);
|
|
126
157
|
|
|
@@ -148,6 +179,28 @@ describe('Config', () => {
|
|
|
148
179
|
expect(Config.load()).rejects.toThrow('Invalid config');
|
|
149
180
|
});
|
|
150
181
|
|
|
182
|
+
it('throws ConfigError for invalid maxSteps', async () => {
|
|
183
|
+
const invalidConfig = {
|
|
184
|
+
$schema: 'https://btca.dev/btca.schema.json',
|
|
185
|
+
provider: 'test-provider',
|
|
186
|
+
model: 'test-model',
|
|
187
|
+
maxSteps: 0,
|
|
188
|
+
resources: [
|
|
189
|
+
{
|
|
190
|
+
name: 'test-resource',
|
|
191
|
+
type: 'git',
|
|
192
|
+
url: 'https://github.com/test/repo',
|
|
193
|
+
branch: 'main'
|
|
194
|
+
}
|
|
195
|
+
]
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
await fs.writeFile(path.join(testDir, 'btca.config.jsonc'), JSON.stringify(invalidConfig));
|
|
199
|
+
process.chdir(testDir);
|
|
200
|
+
|
|
201
|
+
expect(Config.load()).rejects.toThrow('Invalid config');
|
|
202
|
+
});
|
|
203
|
+
|
|
151
204
|
it('merges project config with global config (project takes priority)', async () => {
|
|
152
205
|
// Create global config with some resources
|
|
153
206
|
const globalConfigDir = path.join(testDir, '.config', 'btca');
|
package/src/config/index.ts
CHANGED
|
@@ -19,6 +19,7 @@ export const CONFIG_SCHEMA_URL = 'https://btca.dev/btca.schema.json';
|
|
|
19
19
|
export const DEFAULT_MODEL = 'claude-haiku-4-5';
|
|
20
20
|
export const DEFAULT_PROVIDER = 'opencode';
|
|
21
21
|
export const DEFAULT_PROVIDER_TIMEOUT_MS = 300_000;
|
|
22
|
+
export const DEFAULT_MAX_STEPS = 40;
|
|
22
23
|
|
|
23
24
|
export const DEFAULT_RESOURCES: ResourceDefinition[] = [
|
|
24
25
|
{
|
|
@@ -61,6 +62,7 @@ const StoredConfigSchema = z.object({
|
|
|
61
62
|
$schema: z.string().optional(),
|
|
62
63
|
dataDirectory: z.string().optional(),
|
|
63
64
|
providerTimeoutMs: z.number().int().positive().optional(),
|
|
65
|
+
maxSteps: z.number().int().positive().optional(),
|
|
64
66
|
resources: z.array(ResourceDefinitionSchema),
|
|
65
67
|
// Provider and model are optional - defaults are applied when loading
|
|
66
68
|
model: z.string().optional(),
|
|
@@ -131,6 +133,7 @@ export namespace Config {
|
|
|
131
133
|
model: string;
|
|
132
134
|
provider: string;
|
|
133
135
|
providerTimeoutMs?: number;
|
|
136
|
+
maxSteps: number;
|
|
134
137
|
configPath: string;
|
|
135
138
|
getProviderOptions: (providerId: string) => ProviderOptionsConfig | undefined;
|
|
136
139
|
getResource: (name: string) => ResourceDefinition | undefined;
|
|
@@ -507,7 +510,8 @@ export namespace Config {
|
|
|
507
510
|
resources: DEFAULT_RESOURCES,
|
|
508
511
|
model: DEFAULT_MODEL,
|
|
509
512
|
provider: DEFAULT_PROVIDER,
|
|
510
|
-
providerTimeoutMs: DEFAULT_PROVIDER_TIMEOUT_MS
|
|
513
|
+
providerTimeoutMs: DEFAULT_PROVIDER_TIMEOUT_MS,
|
|
514
|
+
maxSteps: DEFAULT_MAX_STEPS
|
|
511
515
|
};
|
|
512
516
|
|
|
513
517
|
const result = await Result.gen(async function* () {
|
|
@@ -640,6 +644,9 @@ export namespace Config {
|
|
|
640
644
|
get providerTimeoutMs() {
|
|
641
645
|
return getActiveConfig().providerTimeoutMs;
|
|
642
646
|
},
|
|
647
|
+
get maxSteps() {
|
|
648
|
+
return getActiveConfig().maxSteps ?? DEFAULT_MAX_STEPS;
|
|
649
|
+
},
|
|
643
650
|
getProviderOptions: (providerId: string) => getMergedProviderOptions()[providerId],
|
|
644
651
|
getResource: (name: string) => getMergedResources().find((r) => r.name === name),
|
|
645
652
|
|
package/src/index.ts
CHANGED
|
@@ -283,6 +283,7 @@ const createApp = (deps: {
|
|
|
283
283
|
provider: config.provider,
|
|
284
284
|
model: config.model,
|
|
285
285
|
providerTimeoutMs: config.providerTimeoutMs ?? null,
|
|
286
|
+
maxSteps: config.maxSteps,
|
|
286
287
|
resourcesDirectory: config.resourcesDirectory,
|
|
287
288
|
resourceCount: config.resources.length
|
|
288
289
|
});
|
|
@@ -534,6 +535,7 @@ export const startServer = async (options: StartServerOptions = {}): Promise<Ser
|
|
|
534
535
|
Metrics.info('config.ready', {
|
|
535
536
|
provider: config.provider,
|
|
536
537
|
model: config.model,
|
|
538
|
+
maxSteps: config.maxSteps,
|
|
537
539
|
resources: config.resources.map((r) => r.name),
|
|
538
540
|
resourcesDirectory: config.resourcesDirectory
|
|
539
541
|
});
|