@baitong-dev/mcp-helpers 0.0.1 → 0.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/dist/config.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  #!/usr/bin/env bun
2
2
  export declare const MCP_HOME_DIR: string;
3
+ export declare const MCP_WORKSPACE_DIR: string;
package/dist/config.js CHANGED
@@ -4,7 +4,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  return (mod && mod.__esModule) ? mod : { "default": mod };
5
5
  };
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.MCP_HOME_DIR = void 0;
7
+ exports.MCP_WORKSPACE_DIR = exports.MCP_HOME_DIR = void 0;
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const os_1 = __importDefault(require("os"));
10
- exports.MCP_HOME_DIR = process.env.MCP_HOME_DIR || path_1.default.join(os_1.default.homedir(), '\.baitong');
10
+ exports.MCP_HOME_DIR = process.env.MCP_HOME_DIR || path_1.default.join(os_1.default.homedir(), '.baitong');
11
+ exports.MCP_WORKSPACE_DIR = process.env.MCP_WORKSPACE_DIR || path_1.default.resolve(path_1.default.join(exports.MCP_HOME_DIR, 'workspace'));
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env bun
1
+ export * as Ripgrep from './ripgrep';
2
2
  /**
3
3
  * Check if a path is a directory.
4
4
  * @param path The path to check
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.Ripgrep = void 0;
40
+ exports.isDir = isDir;
41
+ exports.isSubdirectory = isSubdirectory;
42
+ const path_1 = __importDefault(require("path"));
43
+ exports.Ripgrep = __importStar(require("./ripgrep"));
44
+ /**
45
+ * Check if a path is a directory.
46
+ * @param path The path to check
47
+ * @returns Whether the path is a directory
48
+ */
49
+ async function isDir(path) {
50
+ try {
51
+ const stat = await Bun.file(path).stat();
52
+ return stat.isDirectory();
53
+ }
54
+ catch {
55
+ return false;
56
+ }
57
+ }
58
+ /**
59
+ * 检查一个目录是否是另一个目录的子目录
60
+ * @param parent - 父目录路径
61
+ * @param child - 要检查的子目录路径
62
+ * @param options - 配置选项
63
+ * @param options.includeSelf - 是否将自身视为子目录
64
+ * @returns - 同步返回 boolean,异步返回 Promise
65
+ */
66
+ function isSubdirectory(parent, child, { includeSelf = false }) {
67
+ const parentPath = path_1.default.resolve(parent);
68
+ const childPath = path_1.default.isAbsolute(child) ? child : path_1.default.join(parentPath, child);
69
+ const relative = path_1.default.relative(parentPath, childPath);
70
+ if (includeSelf && childPath === parentPath) {
71
+ return true;
72
+ }
73
+ return (relative && !relative.startsWith('..') && !path_1.default.isAbsolute(relative)) || false;
74
+ }
@@ -0,0 +1,187 @@
1
+ import z from 'zod';
2
+ declare const Begin: z.ZodObject<{
3
+ type: z.ZodLiteral<"begin">;
4
+ data: z.ZodObject<{
5
+ path: z.ZodObject<{
6
+ text: z.ZodString;
7
+ }, z.core.$strip>;
8
+ }, z.core.$strip>;
9
+ }, z.core.$strip>;
10
+ export declare const Match: z.ZodObject<{
11
+ type: z.ZodLiteral<"match">;
12
+ data: z.ZodObject<{
13
+ path: z.ZodObject<{
14
+ text: z.ZodString;
15
+ }, z.core.$strip>;
16
+ lines: z.ZodObject<{
17
+ text: z.ZodString;
18
+ }, z.core.$strip>;
19
+ line_number: z.ZodNumber;
20
+ absolute_offset: z.ZodNumber;
21
+ submatches: z.ZodArray<z.ZodObject<{
22
+ match: z.ZodObject<{
23
+ text: z.ZodString;
24
+ }, z.core.$strip>;
25
+ start: z.ZodNumber;
26
+ end: z.ZodNumber;
27
+ }, z.core.$strip>>;
28
+ }, z.core.$strip>;
29
+ }, z.core.$strip>;
30
+ declare const End: z.ZodObject<{
31
+ type: z.ZodLiteral<"end">;
32
+ data: z.ZodObject<{
33
+ path: z.ZodObject<{
34
+ text: z.ZodString;
35
+ }, z.core.$strip>;
36
+ binary_offset: z.ZodNullable<z.ZodNumber>;
37
+ stats: z.ZodObject<{
38
+ elapsed: z.ZodObject<{
39
+ secs: z.ZodNumber;
40
+ nanos: z.ZodNumber;
41
+ human: z.ZodString;
42
+ }, z.core.$strip>;
43
+ searches: z.ZodNumber;
44
+ searches_with_match: z.ZodNumber;
45
+ bytes_searched: z.ZodNumber;
46
+ bytes_printed: z.ZodNumber;
47
+ matched_lines: z.ZodNumber;
48
+ matches: z.ZodNumber;
49
+ }, z.core.$strip>;
50
+ }, z.core.$strip>;
51
+ }, z.core.$strip>;
52
+ declare const Summary: z.ZodObject<{
53
+ type: z.ZodLiteral<"summary">;
54
+ data: z.ZodObject<{
55
+ elapsed_total: z.ZodObject<{
56
+ human: z.ZodString;
57
+ nanos: z.ZodNumber;
58
+ secs: z.ZodNumber;
59
+ }, z.core.$strip>;
60
+ stats: z.ZodObject<{
61
+ elapsed: z.ZodObject<{
62
+ secs: z.ZodNumber;
63
+ nanos: z.ZodNumber;
64
+ human: z.ZodString;
65
+ }, z.core.$strip>;
66
+ searches: z.ZodNumber;
67
+ searches_with_match: z.ZodNumber;
68
+ bytes_searched: z.ZodNumber;
69
+ bytes_printed: z.ZodNumber;
70
+ matched_lines: z.ZodNumber;
71
+ matches: z.ZodNumber;
72
+ }, z.core.$strip>;
73
+ }, z.core.$strip>;
74
+ }, z.core.$strip>;
75
+ declare const Result: z.ZodUnion<readonly [z.ZodObject<{
76
+ type: z.ZodLiteral<"begin">;
77
+ data: z.ZodObject<{
78
+ path: z.ZodObject<{
79
+ text: z.ZodString;
80
+ }, z.core.$strip>;
81
+ }, z.core.$strip>;
82
+ }, z.core.$strip>, z.ZodObject<{
83
+ type: z.ZodLiteral<"match">;
84
+ data: z.ZodObject<{
85
+ path: z.ZodObject<{
86
+ text: z.ZodString;
87
+ }, z.core.$strip>;
88
+ lines: z.ZodObject<{
89
+ text: z.ZodString;
90
+ }, z.core.$strip>;
91
+ line_number: z.ZodNumber;
92
+ absolute_offset: z.ZodNumber;
93
+ submatches: z.ZodArray<z.ZodObject<{
94
+ match: z.ZodObject<{
95
+ text: z.ZodString;
96
+ }, z.core.$strip>;
97
+ start: z.ZodNumber;
98
+ end: z.ZodNumber;
99
+ }, z.core.$strip>>;
100
+ }, z.core.$strip>;
101
+ }, z.core.$strip>, z.ZodObject<{
102
+ type: z.ZodLiteral<"end">;
103
+ data: z.ZodObject<{
104
+ path: z.ZodObject<{
105
+ text: z.ZodString;
106
+ }, z.core.$strip>;
107
+ binary_offset: z.ZodNullable<z.ZodNumber>;
108
+ stats: z.ZodObject<{
109
+ elapsed: z.ZodObject<{
110
+ secs: z.ZodNumber;
111
+ nanos: z.ZodNumber;
112
+ human: z.ZodString;
113
+ }, z.core.$strip>;
114
+ searches: z.ZodNumber;
115
+ searches_with_match: z.ZodNumber;
116
+ bytes_searched: z.ZodNumber;
117
+ bytes_printed: z.ZodNumber;
118
+ matched_lines: z.ZodNumber;
119
+ matches: z.ZodNumber;
120
+ }, z.core.$strip>;
121
+ }, z.core.$strip>;
122
+ }, z.core.$strip>, z.ZodObject<{
123
+ type: z.ZodLiteral<"summary">;
124
+ data: z.ZodObject<{
125
+ elapsed_total: z.ZodObject<{
126
+ human: z.ZodString;
127
+ nanos: z.ZodNumber;
128
+ secs: z.ZodNumber;
129
+ }, z.core.$strip>;
130
+ stats: z.ZodObject<{
131
+ elapsed: z.ZodObject<{
132
+ secs: z.ZodNumber;
133
+ nanos: z.ZodNumber;
134
+ human: z.ZodString;
135
+ }, z.core.$strip>;
136
+ searches: z.ZodNumber;
137
+ searches_with_match: z.ZodNumber;
138
+ bytes_searched: z.ZodNumber;
139
+ bytes_printed: z.ZodNumber;
140
+ matched_lines: z.ZodNumber;
141
+ matches: z.ZodNumber;
142
+ }, z.core.$strip>;
143
+ }, z.core.$strip>;
144
+ }, z.core.$strip>]>;
145
+ export type Result = z.infer<typeof Result>;
146
+ export type Match = z.infer<typeof Match>;
147
+ export type Begin = z.infer<typeof Begin>;
148
+ export type End = z.infer<typeof End>;
149
+ export type Summary = z.infer<typeof Summary>;
150
+ export declare function filepath(): Promise<string>;
151
+ export declare function files(input: {
152
+ cwd: string;
153
+ glob?: string[];
154
+ hidden?: boolean;
155
+ follow?: boolean;
156
+ maxDepth?: number;
157
+ signal?: AbortSignal;
158
+ }): Promise<string[]>;
159
+ export declare function tree(input: {
160
+ cwd: string;
161
+ limit?: number;
162
+ signal?: AbortSignal;
163
+ }): Promise<string>;
164
+ export declare function search(input: {
165
+ cwd: string;
166
+ pattern: string;
167
+ glob?: string[];
168
+ limit?: number;
169
+ follow?: boolean;
170
+ }): Promise<{
171
+ path: {
172
+ text: string;
173
+ };
174
+ lines: {
175
+ text: string;
176
+ };
177
+ line_number: number;
178
+ absolute_offset: number;
179
+ submatches: {
180
+ match: {
181
+ text: string;
182
+ };
183
+ start: number;
184
+ end: number;
185
+ }[];
186
+ }[]>;
187
+ export {};
@@ -0,0 +1,229 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Match = void 0;
7
+ exports.filepath = filepath;
8
+ exports.files = files;
9
+ exports.tree = tree;
10
+ exports.search = search;
11
+ const path_1 = __importDefault(require("path"));
12
+ const promises_1 = __importDefault(require("fs/promises"));
13
+ const zod_1 = __importDefault(require("zod"));
14
+ const bun_1 = require("bun");
15
+ const util_1 = require("../util");
16
+ const process_1 = require("../process");
17
+ const logger_1 = require("../logger");
18
+ const simple_process_1 = require("../process/simple-process");
19
+ const logger = new logger_1.Logger('ripgrep');
20
+ const Stats = zod_1.default.object({
21
+ elapsed: zod_1.default.object({
22
+ secs: zod_1.default.number(),
23
+ nanos: zod_1.default.number(),
24
+ human: zod_1.default.string()
25
+ }),
26
+ searches: zod_1.default.number(),
27
+ searches_with_match: zod_1.default.number(),
28
+ bytes_searched: zod_1.default.number(),
29
+ bytes_printed: zod_1.default.number(),
30
+ matched_lines: zod_1.default.number(),
31
+ matches: zod_1.default.number()
32
+ });
33
+ const Begin = zod_1.default.object({
34
+ type: zod_1.default.literal('begin'),
35
+ data: zod_1.default.object({
36
+ path: zod_1.default.object({
37
+ text: zod_1.default.string()
38
+ })
39
+ })
40
+ });
41
+ exports.Match = zod_1.default.object({
42
+ type: zod_1.default.literal('match'),
43
+ data: zod_1.default.object({
44
+ path: zod_1.default.object({
45
+ text: zod_1.default.string()
46
+ }),
47
+ lines: zod_1.default.object({
48
+ text: zod_1.default.string()
49
+ }),
50
+ line_number: zod_1.default.number(),
51
+ absolute_offset: zod_1.default.number(),
52
+ submatches: zod_1.default.array(zod_1.default.object({
53
+ match: zod_1.default.object({
54
+ text: zod_1.default.string()
55
+ }),
56
+ start: zod_1.default.number(),
57
+ end: zod_1.default.number()
58
+ }))
59
+ })
60
+ });
61
+ const End = zod_1.default.object({
62
+ type: zod_1.default.literal('end'),
63
+ data: zod_1.default.object({
64
+ path: zod_1.default.object({
65
+ text: zod_1.default.string()
66
+ }),
67
+ binary_offset: zod_1.default.number().nullable(),
68
+ stats: Stats
69
+ })
70
+ });
71
+ const Summary = zod_1.default.object({
72
+ type: zod_1.default.literal('summary'),
73
+ data: zod_1.default.object({
74
+ elapsed_total: zod_1.default.object({
75
+ human: zod_1.default.string(),
76
+ nanos: zod_1.default.number(),
77
+ secs: zod_1.default.number()
78
+ }),
79
+ stats: Stats
80
+ })
81
+ });
82
+ const Result = zod_1.default.union([Begin, exports.Match, End, Summary]);
83
+ const state = (0, util_1.lazy)(async () => {
84
+ if ((0, process_1.isBundledBinaryExists)('rg')) {
85
+ return { filepath: (0, process_1.getBundledBinaryPath)('rg') };
86
+ }
87
+ const system = Bun.which('rg');
88
+ if (system) {
89
+ const stat = await promises_1.default.stat(system).catch(() => undefined);
90
+ if (stat?.isFile())
91
+ return { filepath: system };
92
+ logger.warn('bun.which returned invalid rg path', { filepath: system });
93
+ }
94
+ throw new Error('rg not found');
95
+ });
96
+ async function filepath() {
97
+ const { filepath } = await state();
98
+ return filepath;
99
+ }
100
+ async function files(input) {
101
+ input.signal?.throwIfAborted();
102
+ const command = await filepath();
103
+ const args = ['--files', '--glob=!.git/*'];
104
+ if (input.follow)
105
+ args.push('--follow');
106
+ if (input.hidden !== false)
107
+ args.push('--hidden');
108
+ if (input.maxDepth !== undefined)
109
+ args.push(`--max-depth=${input.maxDepth}`);
110
+ if (input.glob) {
111
+ for (const g of input.glob) {
112
+ args.push(`--glob=${g}`);
113
+ }
114
+ }
115
+ // Guard against invalid cwd to provide a consistent ENOENT error.
116
+ if (!(await promises_1.default.stat(input.cwd).catch(() => undefined))?.isDirectory()) {
117
+ throw Object.assign(new Error(`No such file or directory: '${input.cwd}'`), {
118
+ code: 'ENOENT',
119
+ errno: -2,
120
+ path: input.cwd
121
+ });
122
+ }
123
+ const proc = (0, simple_process_1.spawn)(command, args, {
124
+ cwd: input.cwd,
125
+ stdout: 'pipe',
126
+ stderr: 'ignore',
127
+ abort: input.signal
128
+ });
129
+ if (!proc.stdout) {
130
+ throw new Error('Process output not available');
131
+ }
132
+ const results = [];
133
+ let buffer = '';
134
+ const stream = proc.stdout;
135
+ for await (const chunk of stream) {
136
+ input.signal?.throwIfAborted();
137
+ buffer += typeof chunk === 'string' ? chunk : chunk.toString();
138
+ // Handle both Unix (\n) and Windows (\r\n) line endings
139
+ const lines = buffer.split(/\r?\n/);
140
+ buffer = lines.pop() || '';
141
+ for (const line of lines) {
142
+ if (line)
143
+ results.push(line);
144
+ }
145
+ }
146
+ if (buffer)
147
+ results.push(buffer);
148
+ await proc.exited;
149
+ input.signal?.throwIfAborted();
150
+ return results;
151
+ }
152
+ async function tree(input) {
153
+ logger.info('tree', input);
154
+ const _files = await files({ cwd: input.cwd, signal: input.signal });
155
+ function dir(node, name) {
156
+ const existing = node.children.get(name);
157
+ if (existing)
158
+ return existing;
159
+ const next = { name, children: new Map() };
160
+ node.children.set(name, next);
161
+ return next;
162
+ }
163
+ const root = { name: '', children: new Map() };
164
+ for (const file of _files) {
165
+ if (file.includes('.baitong'))
166
+ continue;
167
+ const parts = file.split(path_1.default.sep);
168
+ if (parts.length < 2)
169
+ continue;
170
+ let node = root;
171
+ for (const part of parts.slice(0, -1)) {
172
+ node = dir(node, part);
173
+ }
174
+ }
175
+ function count(node) {
176
+ let total = 0;
177
+ for (const child of node.children.values()) {
178
+ total += 1 + count(child);
179
+ }
180
+ return total;
181
+ }
182
+ const total = count(root);
183
+ const limit = input.limit ?? total;
184
+ const lines = [];
185
+ const queue = [];
186
+ for (const child of Array.from(root.children.values()).sort((a, b) => a.name.localeCompare(b.name))) {
187
+ queue.push({ node: child, path: child.name });
188
+ }
189
+ let used = 0;
190
+ for (let i = 0; i < queue.length && used < limit; i++) {
191
+ const { node, path } = queue[i];
192
+ lines.push(path);
193
+ used++;
194
+ for (const child of Array.from(node.children.values()).sort((a, b) => a.name.localeCompare(b.name))) {
195
+ queue.push({ node: child, path: `${path}/${child.name}` });
196
+ }
197
+ }
198
+ if (total > used)
199
+ lines.push(`[${total - used} truncated]`);
200
+ return lines.join('\n');
201
+ }
202
+ async function search(input) {
203
+ const args = [`${await filepath()}`, '--json', '--hidden', "--glob='!.git/*'"];
204
+ if (input.follow)
205
+ args.push('--follow');
206
+ if (input.glob) {
207
+ for (const g of input.glob) {
208
+ args.push(`--glob=${g}`);
209
+ }
210
+ }
211
+ if (input.limit) {
212
+ args.push(`--max-count=${input.limit}`);
213
+ }
214
+ args.push('--');
215
+ args.push(input.pattern);
216
+ const command = args.join(' ');
217
+ const result = await (0, bun_1.$) `${{ raw: command }}`.cwd(input.cwd).quiet().nothrow();
218
+ if (result.exitCode !== 0) {
219
+ return [];
220
+ }
221
+ // Handle both Unix (\n) and Windows (\r\n) line endings
222
+ const lines = result.text().trim().split(/\r?\n/).filter(Boolean);
223
+ // Parse JSON lines from ripgrep output
224
+ return lines
225
+ .map(line => JSON.parse(line))
226
+ .map(parsed => Result.parse(parsed))
227
+ .filter(r => r.type === 'match')
228
+ .map(r => r.data);
229
+ }
@@ -0,0 +1,12 @@
1
+ export declare class Logger {
2
+ private name;
3
+ private isProduction;
4
+ constructor(name: string);
5
+ setProductionMode(isProduction: boolean): void;
6
+ info(...data: any[]): void;
7
+ error(...data: any[]): void;
8
+ warn(...data: any[]): void;
9
+ log(...data: any[]): void;
10
+ debug(...data: any[]): void;
11
+ verbose(...data: any[]): void;
12
+ }
package/dist/logger.js ADDED
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Logger = void 0;
4
+ class Logger {
5
+ constructor(name) {
6
+ this.isProduction = false;
7
+ this.name = name;
8
+ }
9
+ setProductionMode(isProduction) {
10
+ this.isProduction = isProduction;
11
+ }
12
+ info(...data) {
13
+ console.info(`[${this.name}][INFO]`, ...data);
14
+ }
15
+ error(...data) {
16
+ console.error(`[${this.name}][ERROR]`, ...data);
17
+ }
18
+ warn(...data) {
19
+ console.warn(`[${this.name}][WARN]`, ...data);
20
+ }
21
+ log(...data) {
22
+ if (this.isProduction) {
23
+ return;
24
+ }
25
+ console.log(`[${this.name}][LOG]`, ...data);
26
+ }
27
+ debug(...data) {
28
+ if (this.isProduction) {
29
+ return;
30
+ }
31
+ console.debug(`[${this.name}][DEBUG]`, ...data);
32
+ }
33
+ verbose(...data) {
34
+ if (this.isProduction) {
35
+ return;
36
+ }
37
+ console.log(`[${this.name}][VERBOSE]`, ...data);
38
+ }
39
+ }
40
+ exports.Logger = Logger;
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env bun
1
+ export * as SimpleProcess from './simple-process';
2
2
  /**
3
3
  * 将 Windows 文件路径转换为 Git Bash 路径格式
4
4
  * @param path - Windows 格式的文件路径 (如 "C:\\Users")
@@ -17,18 +17,11 @@ export declare function findGitBash(customPath?: string | null): string | null;
17
17
  * @param name Binary Name
18
18
  * @returns Whether the binary exists
19
19
  */
20
- export declare function isBinaryExists(name: string): boolean;
20
+ export declare function isBundledBinaryExists(name: string): boolean;
21
21
  /**
22
22
  * Get full path to a bundled binary
23
23
  * @param name Binary Name
24
24
  * @returns Full path to the binary
25
25
  */
26
26
  export declare function getBundledBinaryPath(name?: string): string;
27
- export declare function getBinaryEnvs(): {
28
- PATH: string;
29
- NODE: string;
30
- npm_config_globalconfig: string;
31
- npm_config_global_prefix: string;
32
- npm_config_prefix: string;
33
- npm_node_execpath: string;
34
- };
27
+ export declare function getBundledBinaryEnvs(): Record<string, string>;
@@ -1,18 +1,52 @@
1
- #!/usr/bin/env bun
2
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
3
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
4
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
5
37
  };
6
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.SimpleProcess = void 0;
7
40
  exports.windowsToGitBashPath = windowsToGitBashPath;
8
41
  exports.gitBashToWindowsPath = gitBashToWindowsPath;
9
42
  exports.findGitBash = findGitBash;
10
- exports.isBinaryExists = isBinaryExists;
43
+ exports.isBundledBinaryExists = isBundledBinaryExists;
11
44
  exports.getBundledBinaryPath = getBundledBinaryPath;
12
- exports.getBinaryEnvs = getBinaryEnvs;
45
+ exports.getBundledBinaryEnvs = getBundledBinaryEnvs;
13
46
  const path_1 = __importDefault(require("path"));
14
- const config_1 = require("./config");
47
+ const config_1 = require("../config");
15
48
  const fs_1 = __importDefault(require("fs"));
49
+ exports.SimpleProcess = __importStar(require("./simple-process"));
16
50
  /**
17
51
  * 将 Windows 文件路径转换为 Git Bash 路径格式
18
52
  * @param path - Windows 格式的文件路径 (如 "C:\\Users")
@@ -127,7 +161,10 @@ function findGitBash(customPath) {
127
161
  * @param name Binary Name
128
162
  * @returns Binary Name with .exe extension on Windows
129
163
  */
130
- function getBinaryName(name) {
164
+ function getBundledBinaryName(name) {
165
+ if (name === 'ripgrep') {
166
+ name = 'rg';
167
+ }
131
168
  if (process.platform == 'win32') {
132
169
  if (['npm', 'npx'].includes(name)) {
133
170
  return name;
@@ -141,7 +178,7 @@ function getBinaryName(name) {
141
178
  * @param name Binary Name
142
179
  * @returns Whether the binary exists
143
180
  */
144
- function isBinaryExists(name) {
181
+ function isBundledBinaryExists(name) {
145
182
  const cmd = getBundledBinaryPath(name);
146
183
  return Bun.file(cmd).size > 0;
147
184
  }
@@ -155,7 +192,7 @@ function getBundledBinaryPath(name) {
155
192
  if (!name) {
156
193
  return binariesDir;
157
194
  }
158
- const binaryName = getBinaryName(name);
195
+ const binaryName = getBundledBinaryName(name);
159
196
  const binariesDirExists = fs_1.default.existsSync(binariesDir);
160
197
  if (binariesDirExists) {
161
198
  if (['git', 'bash', 'sh'].includes(name)) {
@@ -166,28 +203,32 @@ function getBundledBinaryPath(name) {
166
203
  // Node.js binaries are in a subdirectory
167
204
  return path_1.default.join(binariesDir, 'node', binaryName);
168
205
  }
169
- if (['python', 'python3'].includes(name)) {
206
+ if (['python'].includes(name)) {
170
207
  // Python binaries are in a subdirectory
171
208
  return path_1.default.join(binariesDir, 'python', binaryName);
172
209
  }
173
210
  if (['pip', 'pip3'].includes(name)) {
174
- // pip binaries are in a subdirectory
211
+ // Python binaries are in a subdirectory
175
212
  return path_1.default.join(binariesDir, 'python/Scripts', binaryName);
176
213
  }
214
+ if (['rg', 'ripgrep'].includes(name)) {
215
+ // ripgrep binaries are in a subdirectory
216
+ return path_1.default.join(binariesDir, 'ripgrep', binaryName);
217
+ }
177
218
  return path_1.default.join(binariesDir, binaryName);
178
219
  }
179
220
  return binaryName;
180
221
  }
181
- function getBinaryEnvs() {
222
+ function getBundledBinaryEnvs() {
182
223
  const binariesDir = getBundledBinaryPath();
183
- const envPaths = process.env?.path?.split(';') || [];
224
+ const envPaths = process.env?.PATH?.split(';') || [];
184
225
  envPaths.unshift(binariesDir); // bun uv uvx
185
226
  envPaths.unshift(path_1.default.join(binariesDir, 'node')); // node
186
227
  envPaths.unshift(path_1.default.join(binariesDir, 'python')); // python
187
228
  envPaths.unshift(path_1.default.join(binariesDir, 'python/Scripts')); // pip
188
229
  const nodePath = getBundledBinaryPath('node');
189
230
  const nodeDir = path_1.default.join(nodePath, '..');
190
- return {
231
+ const envs = {
191
232
  PATH: envPaths.join(';'),
192
233
  NODE: nodePath,
193
234
  npm_config_globalconfig: path_1.default.join(nodeDir, 'etc', 'npmrc'),
@@ -195,4 +236,20 @@ function getBinaryEnvs() {
195
236
  npm_config_prefix: nodeDir,
196
237
  npm_node_execpath: nodePath
197
238
  };
239
+ const MORE_ENV_VARS = [
240
+ 'BUN_TMPDIR',
241
+ 'BUN_INSTALL',
242
+ 'NPM_CONFIG_REGISTRY',
243
+ 'UV_PYTHON_INSTALL_MIRROR',
244
+ 'UV_DEFAULT_INDEX',
245
+ 'PIP_INDEX_URL'
246
+ ];
247
+ for (const key of MORE_ENV_VARS) {
248
+ const value = process.env[key];
249
+ if (value === undefined) {
250
+ continue;
251
+ }
252
+ envs[key] = value;
253
+ }
254
+ return envs;
198
255
  }
@@ -0,0 +1,16 @@
1
+ import { ChildProcess } from 'child_process';
2
+ export type Stdio = 'inherit' | 'pipe' | 'ignore';
3
+ export interface Options {
4
+ cwd?: string;
5
+ env?: NodeJS.ProcessEnv | null;
6
+ stdin?: Stdio;
7
+ stdout?: Stdio;
8
+ stderr?: Stdio;
9
+ abort?: AbortSignal;
10
+ kill?: NodeJS.Signals | number;
11
+ timeout?: number;
12
+ }
13
+ export type Child = ChildProcess & {
14
+ exited: Promise<number>;
15
+ };
16
+ export declare function spawn(command: string, args: readonly string[], options?: Options): Child;
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.spawn = spawn;
4
+ const child_process_1 = require("child_process");
5
+ function spawn(command, args, options = {}) {
6
+ options.abort?.throwIfAborted();
7
+ const proc = (0, child_process_1.spawn)(command, args, {
8
+ cwd: options.cwd,
9
+ env: options.env === null ? {} : options.env ? { ...process.env, ...options.env } : undefined,
10
+ stdio: [options.stdin ?? 'ignore', options.stdout ?? 'ignore', options.stderr ?? 'ignore']
11
+ });
12
+ let aborted = false;
13
+ let timer;
14
+ const abort = () => {
15
+ if (aborted)
16
+ return;
17
+ if (proc.exitCode !== null || proc.signalCode !== null)
18
+ return;
19
+ aborted = true;
20
+ proc.kill(options.kill ?? 'SIGTERM');
21
+ const timeout = options.timeout ?? 5_000;
22
+ if (timeout <= 0)
23
+ return;
24
+ timer = setTimeout(() => {
25
+ proc.kill('SIGKILL');
26
+ }, timeout);
27
+ };
28
+ const exited = new Promise((resolve, reject) => {
29
+ const done = () => {
30
+ options.abort?.removeEventListener('abort', abort);
31
+ if (timer)
32
+ clearTimeout(timer);
33
+ };
34
+ proc.once('exit', (exitCode, signal) => {
35
+ done();
36
+ resolve(exitCode ?? (signal ? 1 : 0));
37
+ });
38
+ proc.once('error', error => {
39
+ done();
40
+ reject(error);
41
+ });
42
+ });
43
+ if (options.abort) {
44
+ options.abort.addEventListener('abort', abort, { once: true });
45
+ if (options.abort.aborted)
46
+ abort();
47
+ }
48
+ const child = proc;
49
+ child.exited = exited;
50
+ return child;
51
+ }
package/dist/util.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/env bun
2
1
  /**
3
2
  * Lazily initialize a value.
4
3
  * @param fn A function that returns the value to be lazily initialized
package/dist/util.js CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/env bun
2
1
  "use strict";
3
2
  Object.defineProperty(exports, "__esModule", { value: true });
4
3
  exports.lazy = lazy;
@@ -13,15 +12,9 @@ function lazy(fn) {
13
12
  const result = () => {
14
13
  if (loaded)
15
14
  return value;
16
- try {
17
- value = fn();
18
- loaded = true;
19
- return value;
20
- }
21
- catch (e) {
22
- // Don't mark as loaded if initialization failed
23
- throw e;
24
- }
15
+ value = fn();
16
+ loaded = true;
17
+ return value;
25
18
  };
26
19
  result.reset = () => {
27
20
  loaded = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@baitong-dev/mcp-helpers",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "main": "./dist/index.js",
5
5
  "files": [
6
6
  "dist",
package/dist/file.js DELETED
@@ -1,40 +0,0 @@
1
- #!/usr/bin/env bun
2
- "use strict";
3
- var __importDefault = (this && this.__importDefault) || function (mod) {
4
- return (mod && mod.__esModule) ? mod : { "default": mod };
5
- };
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.isDir = isDir;
8
- exports.isSubdirectory = isSubdirectory;
9
- const path_1 = __importDefault(require("path"));
10
- /**
11
- * Check if a path is a directory.
12
- * @param path The path to check
13
- * @returns Whether the path is a directory
14
- */
15
- async function isDir(path) {
16
- try {
17
- const stat = await Bun.file(path).stat();
18
- return stat.isDirectory();
19
- }
20
- catch {
21
- return false;
22
- }
23
- }
24
- /**
25
- * 检查一个目录是否是另一个目录的子目录
26
- * @param parent - 父目录路径
27
- * @param child - 要检查的子目录路径
28
- * @param options - 配置选项
29
- * @param options.includeSelf - 是否将自身视为子目录
30
- * @returns - 同步返回 boolean,异步返回 Promise
31
- */
32
- function isSubdirectory(parent, child, { includeSelf = false }) {
33
- const parentPath = path_1.default.resolve(parent);
34
- const childPath = path_1.default.isAbsolute(child) ? child : path_1.default.join(parentPath, child);
35
- const relative = path_1.default.relative(parentPath, childPath);
36
- if (includeSelf && childPath === parentPath) {
37
- return true;
38
- }
39
- return (relative && !relative.startsWith('..') && !path_1.default.isAbsolute(relative)) || false;
40
- }