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.
Files changed (43) hide show
  1. package/package.json +3 -3
  2. package/src/agent/agent.test.ts +31 -24
  3. package/src/agent/index.ts +8 -2
  4. package/src/agent/loop.ts +303 -346
  5. package/src/agent/service.ts +252 -233
  6. package/src/agent/types.ts +2 -2
  7. package/src/collections/index.ts +2 -1
  8. package/src/collections/service.ts +352 -345
  9. package/src/config/config.test.ts +3 -1
  10. package/src/config/index.ts +615 -727
  11. package/src/config/remote.ts +214 -369
  12. package/src/context/index.ts +6 -12
  13. package/src/context/transaction.ts +23 -30
  14. package/src/effect/errors.ts +45 -0
  15. package/src/effect/layers.ts +26 -0
  16. package/src/effect/runtime.ts +19 -0
  17. package/src/effect/services.ts +154 -0
  18. package/src/index.ts +291 -369
  19. package/src/metrics/index.ts +46 -46
  20. package/src/pricing/models-dev.ts +104 -106
  21. package/src/providers/auth.ts +159 -200
  22. package/src/providers/index.ts +19 -2
  23. package/src/providers/model.ts +115 -135
  24. package/src/providers/openai.ts +3 -3
  25. package/src/resources/impls/git.ts +123 -146
  26. package/src/resources/impls/npm.test.ts +16 -5
  27. package/src/resources/impls/npm.ts +66 -75
  28. package/src/resources/index.ts +6 -1
  29. package/src/resources/schema.ts +7 -6
  30. package/src/resources/service.test.ts +13 -12
  31. package/src/resources/service.ts +153 -112
  32. package/src/stream/index.ts +1 -1
  33. package/src/stream/service.test.ts +5 -5
  34. package/src/stream/service.ts +282 -293
  35. package/src/tools/glob.ts +126 -141
  36. package/src/tools/grep.ts +205 -210
  37. package/src/tools/index.ts +8 -4
  38. package/src/tools/list.ts +118 -140
  39. package/src/tools/read.ts +209 -235
  40. package/src/tools/virtual-sandbox.ts +91 -83
  41. package/src/validation/index.ts +18 -22
  42. package/src/vfs/virtual-fs.test.ts +37 -25
  43. 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 { VirtualSandbox } from './virtual-sandbox.ts';
11
- import { VirtualFs } from '../vfs/virtual-fs.ts';
12
-
13
- export namespace GlobTool {
14
- // Configuration
15
- const MAX_RESULTS = 100;
16
-
17
- // Schema for tool parameters
18
- export const Parameters = z.object({
19
- pattern: z
20
- .string()
21
- .describe('The glob pattern to match files against (e.g. "**/*.ts", "src/**/*.js")'),
22
- path: z
23
- .string()
24
- .optional()
25
- .describe('The directory to search in. Defaults to the collection root.')
26
- });
27
-
28
- export type ParametersType = z.infer<typeof Parameters>;
29
-
30
- // Result type
31
- export type Result = {
32
- title: string;
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
- const safeStat = async (filePath: string, vfsId?: string) => {
41
- const result = await Result.tryPromise(() => VirtualFs.stat(filePath, vfsId));
42
- return result.match({
43
- ok: (value) => value,
44
- err: () => null
45
- });
46
- };
47
-
48
- /**
49
- * Execute the glob tool
50
- */
51
- export async function execute(params: ParametersType, context: ToolContext): Promise<Result> {
52
- const { basePath, vfsId } = context;
53
-
54
- // Resolve search path within sandbox
55
- const searchPath = params.path ? VirtualSandbox.resolvePath(basePath, params.path) : basePath;
56
-
57
- // Validate the search path exists and is a directory
58
- const stats = await safeStat(searchPath, vfsId);
59
- if (!stats) {
60
- return {
61
- title: params.pattern,
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
- const relative = path.posix.relative(searchPath, file);
92
- if (!patternRegex.test(relative)) continue;
93
- const fileStats = await safeStat(file, vfsId);
94
- files.push({ path: file, mtime: fileStats?.mtimeMs ?? 0 });
95
- }
96
-
97
- if (files.length === 0) {
98
- return {
99
- title: params.pattern,
100
- output: 'No files found matching pattern.',
101
- metadata: {
102
- count: 0,
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
- // Format output with relative paths
112
- const outputLines = files.map((f) => path.posix.relative(basePath, f.path));
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
- // Add truncation notice
115
- if (truncated) {
116
- outputLines.push('');
117
- outputLines.push(
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: outputLines.join('\n'),
90
+ output: 'No files found matching pattern.',
125
91
  metadata: {
126
- count: files.length,
127
- truncated
92
+ count: 0,
93
+ truncated: false
128
94
  }
129
95
  };
130
96
  }
131
97
 
132
- function globToRegExp(pattern: string): RegExp {
133
- let regex = '^';
134
- let i = 0;
135
- while (i < pattern.length) {
136
- const char = pattern[i] ?? '';
137
- const next = pattern[i + 1] ?? '';
138
- if (char === '*' && next === '*') {
139
- regexAdd('.*');
140
- i += 2;
141
- continue;
142
- }
143
- if (char === '*') {
144
- regexAdd('[^/]*');
145
- i += 1;
146
- continue;
147
- }
148
- if (char === '?') {
149
- regexAdd('[^/]');
150
- i += 1;
151
- continue;
152
- }
153
- if ('\\.^$+{}()|[]'.includes(char)) {
154
- regexAdd('\\' + char);
155
- } else {
156
- regexAdd(char);
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
- regex += '$';
161
- return new RegExp(regex);
162
-
163
- function regexAdd(value: string) {
164
- regex += value;
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
+ };