btca-server 1.0.961 → 2.0.0
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 +3 -3
- package/src/agent/agent.test.ts +31 -24
- package/src/agent/index.ts +8 -2
- package/src/agent/loop.ts +303 -346
- package/src/agent/service.ts +252 -233
- package/src/agent/types.ts +2 -2
- package/src/collections/index.ts +2 -1
- package/src/collections/service.ts +352 -345
- package/src/config/config.test.ts +3 -1
- package/src/config/index.ts +615 -727
- package/src/config/remote.ts +214 -369
- package/src/context/index.ts +6 -12
- package/src/context/transaction.ts +23 -30
- package/src/effect/errors.ts +45 -0
- package/src/effect/layers.ts +26 -0
- package/src/effect/runtime.ts +19 -0
- package/src/effect/services.ts +154 -0
- package/src/index.ts +291 -369
- package/src/metrics/index.ts +46 -46
- package/src/pricing/models-dev.ts +104 -106
- package/src/providers/auth.ts +159 -200
- package/src/providers/index.ts +19 -2
- package/src/providers/model.ts +115 -135
- package/src/providers/openai.ts +3 -3
- package/src/resources/impls/git.ts +123 -146
- package/src/resources/impls/npm.test.ts +16 -5
- package/src/resources/impls/npm.ts +66 -75
- package/src/resources/index.ts +6 -1
- package/src/resources/schema.ts +7 -6
- package/src/resources/service.test.ts +13 -12
- package/src/resources/service.ts +153 -112
- package/src/stream/index.ts +1 -1
- package/src/stream/service.test.ts +5 -5
- package/src/stream/service.ts +282 -293
- package/src/tools/glob.ts +126 -141
- package/src/tools/grep.ts +205 -210
- package/src/tools/index.ts +8 -4
- package/src/tools/list.ts +118 -140
- package/src/tools/read.ts +209 -235
- package/src/tools/virtual-sandbox.ts +91 -83
- package/src/validation/index.ts +18 -22
- package/src/vfs/virtual-fs.test.ts +37 -25
- package/src/vfs/virtual-fs.ts +218 -216
package/src/tools/glob.ts
CHANGED
|
@@ -4,164 +4,149 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import * as path from 'node:path';
|
|
6
6
|
import { z } from 'zod';
|
|
7
|
-
import { Result } from 'better-result';
|
|
8
7
|
|
|
9
8
|
import type { ToolContext } from './context.ts';
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
output: string;
|
|
34
|
-
metadata: {
|
|
35
|
-
count: number;
|
|
36
|
-
truncated: boolean;
|
|
37
|
-
};
|
|
9
|
+
import { resolveSandboxPath } from './virtual-sandbox.ts';
|
|
10
|
+
import { listVirtualFsFilesRecursive, statVirtualFs } from '../vfs/virtual-fs.ts';
|
|
11
|
+
|
|
12
|
+
const MAX_RESULTS = 100;
|
|
13
|
+
|
|
14
|
+
export const GlobToolParameters = z.object({
|
|
15
|
+
pattern: z
|
|
16
|
+
.string()
|
|
17
|
+
.describe('The glob pattern to match files against (e.g. "**/*.ts", "src/**/*.js")'),
|
|
18
|
+
path: z
|
|
19
|
+
.string()
|
|
20
|
+
.optional()
|
|
21
|
+
.describe('The directory to search in. Defaults to the collection root.')
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
export type GlobToolParametersType = z.infer<typeof GlobToolParameters>;
|
|
25
|
+
|
|
26
|
+
export type GlobToolResult = {
|
|
27
|
+
title: string;
|
|
28
|
+
output: string;
|
|
29
|
+
metadata: {
|
|
30
|
+
count: number;
|
|
31
|
+
truncated: boolean;
|
|
38
32
|
};
|
|
33
|
+
};
|
|
39
34
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
return
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
output: `Directory not found: ${params.path || '.'}`,
|
|
63
|
-
metadata: {
|
|
64
|
-
count: 0,
|
|
65
|
-
truncated: false
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
if (!stats.isDirectory) {
|
|
70
|
-
return {
|
|
71
|
-
title: params.pattern,
|
|
72
|
-
output: `Path is not a directory: ${params.path || '.'}`,
|
|
73
|
-
metadata: {
|
|
74
|
-
count: 0,
|
|
75
|
-
truncated: false
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Collect files matching the pattern
|
|
81
|
-
const files: Array<{ path: string; mtime: number }> = [];
|
|
82
|
-
let truncated = false;
|
|
83
|
-
|
|
84
|
-
const patternRegex = globToRegExp(params.pattern);
|
|
85
|
-
const allFiles = await VirtualFs.listFilesRecursive(searchPath, vfsId);
|
|
86
|
-
for (const file of allFiles) {
|
|
87
|
-
if (files.length >= MAX_RESULTS) {
|
|
88
|
-
truncated = true;
|
|
89
|
-
break;
|
|
35
|
+
const safeStat = async (filePath: string, vfsId?: string) => {
|
|
36
|
+
try {
|
|
37
|
+
return await statVirtualFs(filePath, vfsId);
|
|
38
|
+
} catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const executeGlobTool = async (
|
|
44
|
+
params: GlobToolParametersType,
|
|
45
|
+
context: ToolContext
|
|
46
|
+
): Promise<GlobToolResult> => {
|
|
47
|
+
const { basePath, vfsId } = context;
|
|
48
|
+
const searchPath = params.path ? resolveSandboxPath(basePath, params.path) : basePath;
|
|
49
|
+
const stats = await safeStat(searchPath, vfsId);
|
|
50
|
+
if (!stats) {
|
|
51
|
+
return {
|
|
52
|
+
title: params.pattern,
|
|
53
|
+
output: `Directory not found: ${params.path || '.'}`,
|
|
54
|
+
metadata: {
|
|
55
|
+
count: 0,
|
|
56
|
+
truncated: false
|
|
90
57
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
truncated: false
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Sort by modification time (most recent first)
|
|
109
|
-
files.sort((a, b) => b.mtime - a.mtime);
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
if (!stats.isDirectory) {
|
|
61
|
+
return {
|
|
62
|
+
title: params.pattern,
|
|
63
|
+
output: `Path is not a directory: ${params.path || '.'}`,
|
|
64
|
+
metadata: {
|
|
65
|
+
count: 0,
|
|
66
|
+
truncated: false
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
110
70
|
|
|
111
|
-
|
|
112
|
-
|
|
71
|
+
const files: Array<{ path: string; mtime: number }> = [];
|
|
72
|
+
let truncated = false;
|
|
73
|
+
const patternRegex = globToRegExp(params.pattern);
|
|
74
|
+
const allFiles = await listVirtualFsFilesRecursive(searchPath, vfsId);
|
|
113
75
|
|
|
114
|
-
|
|
115
|
-
if (
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
`[Truncated: Results limited to ${MAX_RESULTS} files. Use a more specific pattern for more targeted results.]`
|
|
119
|
-
);
|
|
76
|
+
for (const file of allFiles) {
|
|
77
|
+
if (files.length >= MAX_RESULTS) {
|
|
78
|
+
truncated = true;
|
|
79
|
+
break;
|
|
120
80
|
}
|
|
81
|
+
const relative = path.posix.relative(searchPath, file);
|
|
82
|
+
if (!patternRegex.test(relative)) continue;
|
|
83
|
+
const fileStats = await safeStat(file, vfsId);
|
|
84
|
+
files.push({ path: file, mtime: fileStats?.mtimeMs ?? 0 });
|
|
85
|
+
}
|
|
121
86
|
|
|
87
|
+
if (files.length === 0) {
|
|
122
88
|
return {
|
|
123
89
|
title: params.pattern,
|
|
124
|
-
output:
|
|
90
|
+
output: 'No files found matching pattern.',
|
|
125
91
|
metadata: {
|
|
126
|
-
count:
|
|
127
|
-
truncated
|
|
92
|
+
count: 0,
|
|
93
|
+
truncated: false
|
|
128
94
|
}
|
|
129
95
|
};
|
|
130
96
|
}
|
|
131
97
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
98
|
+
files.sort((a, b) => b.mtime - a.mtime);
|
|
99
|
+
const outputLines = files.map((f) => path.posix.relative(basePath, f.path));
|
|
100
|
+
|
|
101
|
+
if (truncated) {
|
|
102
|
+
outputLines.push('');
|
|
103
|
+
outputLines.push(
|
|
104
|
+
`[Truncated: Results limited to ${MAX_RESULTS} files. Use a more specific pattern for more targeted results.]`
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return {
|
|
109
|
+
title: params.pattern,
|
|
110
|
+
output: outputLines.join('\n'),
|
|
111
|
+
metadata: {
|
|
112
|
+
count: files.length,
|
|
113
|
+
truncated
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const globToRegExp = (pattern: string): RegExp => {
|
|
119
|
+
let regex = '^';
|
|
120
|
+
let i = 0;
|
|
121
|
+
while (i < pattern.length) {
|
|
122
|
+
const char = pattern[i] ?? '';
|
|
123
|
+
const next = pattern[i + 1] ?? '';
|
|
124
|
+
if (char === '*' && next === '*') {
|
|
125
|
+
regexAdd('.*');
|
|
126
|
+
i += 2;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (char === '*') {
|
|
130
|
+
regexAdd('[^/]*');
|
|
158
131
|
i += 1;
|
|
132
|
+
continue;
|
|
159
133
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
134
|
+
if (char === '?') {
|
|
135
|
+
regexAdd('[^/]');
|
|
136
|
+
i += 1;
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if ('\\.^$+{}()|[]'.includes(char)) {
|
|
140
|
+
regexAdd('\\' + char);
|
|
141
|
+
} else {
|
|
142
|
+
regexAdd(char);
|
|
165
143
|
}
|
|
144
|
+
i += 1;
|
|
145
|
+
}
|
|
146
|
+
regex += '$';
|
|
147
|
+
return new RegExp(regex);
|
|
148
|
+
|
|
149
|
+
function regexAdd(value: string) {
|
|
150
|
+
regex += value;
|
|
166
151
|
}
|
|
167
|
-
}
|
|
152
|
+
};
|