pi-tool-discipline 0.1.9 → 0.1.10
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/extensions/search.ts +14 -9
- package/package.json +1 -1
package/extensions/search.ts
CHANGED
|
@@ -53,6 +53,7 @@ async function walk(dir: string, out: string[], state: WalkState, signal?: Abort
|
|
|
53
53
|
try {
|
|
54
54
|
entries = await readdir(dir);
|
|
55
55
|
} catch (error: any) {
|
|
56
|
+
throwIfAborted(signal); // cancellation wins over the fs error
|
|
56
57
|
if (depth === 0) state.rootError = error?.message ?? String(error);
|
|
57
58
|
return;
|
|
58
59
|
}
|
|
@@ -84,7 +85,7 @@ async function walk(dir: string, out: string[], state: WalkState, signal?: Abort
|
|
|
84
85
|
*/
|
|
85
86
|
function truncate(text: string, maxBytes = MAX_OUTPUT_BYTES, extraMarkerBytes = 0): string {
|
|
86
87
|
const buf = Buffer.from(text, "utf8");
|
|
87
|
-
if (buf.length <= maxBytes) return text;
|
|
88
|
+
if (buf.length + extraMarkerBytes <= maxBytes) return text;
|
|
88
89
|
const budget = maxBytes - Buffer.byteLength(TRUNCATE_MARKER) - extraMarkerBytes;
|
|
89
90
|
if (budget <= 0) return TRUNCATE_MARKER.trim();
|
|
90
91
|
const cut = buf.subarray(0, budget).toString("utf8");
|
|
@@ -93,12 +94,14 @@ function truncate(text: string, maxBytes = MAX_OUTPUT_BYTES, extraMarkerBytes =
|
|
|
93
94
|
return `${cut.slice(0, lastNewline)}\n${TRUNCATE_MARKER}`;
|
|
94
95
|
}
|
|
95
96
|
|
|
96
|
-
async function resolveRoot(cwd: string, sub?: string): Promise<string | null> {
|
|
97
|
+
async function resolveRoot(cwd: string, sub?: string, signal?: AbortSignal): Promise<string | null> {
|
|
97
98
|
const root = resolve(cwd, sub || ".");
|
|
98
99
|
try {
|
|
99
100
|
const st = await stat(root);
|
|
101
|
+
throwIfAborted(signal);
|
|
100
102
|
return st.isDirectory() ? root : null;
|
|
101
|
-
} catch {
|
|
103
|
+
} catch (error: any) {
|
|
104
|
+
throwIfAborted(signal);
|
|
102
105
|
return null;
|
|
103
106
|
}
|
|
104
107
|
}
|
|
@@ -118,7 +121,7 @@ export async function grepFiles(opts: {
|
|
|
118
121
|
signal?: AbortSignal;
|
|
119
122
|
}): Promise<string> {
|
|
120
123
|
throwIfAborted(opts.signal);
|
|
121
|
-
const root = await resolveRoot(opts.cwd, opts.path);
|
|
124
|
+
const root = await resolveRoot(opts.cwd, opts.path, opts.signal);
|
|
122
125
|
if (!root) return `Error: search path not found: ${resolve(opts.cwd, opts.path || ".")}`;
|
|
123
126
|
const pattern = opts.caseSensitive ? opts.pattern : opts.pattern.toLowerCase();
|
|
124
127
|
const limit = opts.maxResults ?? 100;
|
|
@@ -130,14 +133,16 @@ export async function grepFiles(opts: {
|
|
|
130
133
|
if (matches.length >= limit) break;
|
|
131
134
|
try {
|
|
132
135
|
if ((await stat(file)).size > MAX_FILE_BYTES) continue; // cap only before reading content
|
|
133
|
-
} catch {
|
|
136
|
+
} catch (error: any) {
|
|
137
|
+
throwIfAborted(opts.signal);
|
|
134
138
|
continue;
|
|
135
139
|
}
|
|
136
140
|
throwIfAborted(opts.signal);
|
|
137
141
|
let content: string;
|
|
138
142
|
try {
|
|
139
143
|
content = await readFile(file, "utf8");
|
|
140
|
-
} catch {
|
|
144
|
+
} catch (error: any) {
|
|
145
|
+
throwIfAborted(opts.signal);
|
|
141
146
|
continue;
|
|
142
147
|
}
|
|
143
148
|
throwIfAborted(opts.signal);
|
|
@@ -167,7 +172,7 @@ export async function findFiles(opts: {
|
|
|
167
172
|
signal?: AbortSignal;
|
|
168
173
|
}): Promise<string> {
|
|
169
174
|
throwIfAborted(opts.signal);
|
|
170
|
-
const root = await resolveRoot(opts.cwd, opts.path);
|
|
175
|
+
const root = await resolveRoot(opts.cwd, opts.path, opts.signal);
|
|
171
176
|
if (!root) return `Error: search path not found: ${resolve(opts.cwd, opts.path || ".")}`;
|
|
172
177
|
const { files, state } = await walkFiles(root, opts.signal);
|
|
173
178
|
if (state.rootError) return `Error: cannot read search root ${root}: ${state.rootError}`;
|
|
@@ -193,7 +198,7 @@ export async function findFiles(opts: {
|
|
|
193
198
|
|
|
194
199
|
export async function listDir(opts: { path?: string; cwd: string; signal?: AbortSignal }): Promise<string> {
|
|
195
200
|
throwIfAborted(opts.signal);
|
|
196
|
-
const root = await resolveRoot(opts.cwd, opts.path);
|
|
201
|
+
const root = await resolveRoot(opts.cwd, opts.path, opts.signal);
|
|
197
202
|
if (!root) return `Error: directory not found: ${resolve(opts.cwd, opts.path || ".")}`;
|
|
198
203
|
try {
|
|
199
204
|
const entries = await readdir(root);
|
|
@@ -201,7 +206,7 @@ export async function listDir(opts: { path?: string; cwd: string; signal?: Abort
|
|
|
201
206
|
if (entries.length === 0) return "(empty directory)";
|
|
202
207
|
return truncate(entries.join("\n"));
|
|
203
208
|
} catch (error: any) {
|
|
204
|
-
|
|
209
|
+
throwIfAborted(opts.signal);
|
|
205
210
|
return `Error listing ${root}: ${error.message}`;
|
|
206
211
|
}
|
|
207
212
|
}
|
package/package.json
CHANGED