@xynogen/pix-find 0.1.20 → 0.1.24
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/README.md +1 -1
- package/package.json +4 -4
- package/src/find.test.ts +67 -1
- package/src/find.ts +40 -15
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ After a configurable delay (default 10 seconds), completed output collapses to a
|
|
|
20
20
|
}
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
Set `collapse.tools.find: false` to disable for this tool only. See `@xynogen/pix-
|
|
23
|
+
Set `collapse.tools.find: false` to disable for this tool only. See `@xynogen/pix-runtime/collapse` for the full API.
|
|
24
24
|
|
|
25
25
|
## Install
|
|
26
26
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xynogen/pix-find",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.24",
|
|
4
4
|
"description": "Pi tool — glob file search",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -34,9 +34,9 @@
|
|
|
34
34
|
"access": "public"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@xynogen/pix-data": "^0.4.
|
|
38
|
-
"@xynogen/pix-pretty": "^1.
|
|
39
|
-
"@xynogen/pix-runtime": "^0.
|
|
37
|
+
"@xynogen/pix-data": "^0.4.3",
|
|
38
|
+
"@xynogen/pix-pretty": "^1.11.2",
|
|
39
|
+
"@xynogen/pix-runtime": "^0.5.3"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"@earendil-works/pi-coding-agent": "*"
|
package/src/find.test.ts
CHANGED
|
@@ -110,9 +110,75 @@ describe("registerFindTool", () => {
|
|
|
110
110
|
|
|
111
111
|
expect(result?.getText()).toContain("src/one.ts");
|
|
112
112
|
expect(result?.getText()).toContain("src/two.ts");
|
|
113
|
+
// No floating count header in the framed view — the collapsed row carries it.
|
|
113
114
|
expect(result?.getText()).not.toContain("2 files");
|
|
114
115
|
});
|
|
115
116
|
|
|
117
|
+
it("frames single-file output like multi-file (no inline row)", () => {
|
|
118
|
+
const registered: { renderResult?: (...args: unknown[]) => MockTextComponent } = {};
|
|
119
|
+
const mockPi: PiPrettyApi = {
|
|
120
|
+
registerTool(tool: unknown) {
|
|
121
|
+
Object.assign(registered, tool);
|
|
122
|
+
},
|
|
123
|
+
registerCommand() {},
|
|
124
|
+
on() {},
|
|
125
|
+
};
|
|
126
|
+
registerFindTool(
|
|
127
|
+
mockPi,
|
|
128
|
+
() => ({ execute: async () => ({ content: [], details: undefined }) }),
|
|
129
|
+
{
|
|
130
|
+
cwd: process.cwd(),
|
|
131
|
+
sp: (p: string) => p,
|
|
132
|
+
TextComponent: MockTextComponent as unknown as TextComponentCtor,
|
|
133
|
+
fffState: {
|
|
134
|
+
module: null,
|
|
135
|
+
finder: null,
|
|
136
|
+
partialIndex: false,
|
|
137
|
+
dbDir: null,
|
|
138
|
+
} satisfies FffState,
|
|
139
|
+
cursorStore: { store: () => "", get: () => undefined } as unknown as CursorStore,
|
|
140
|
+
},
|
|
141
|
+
);
|
|
142
|
+
const theme: ThemeLike = { fg: (_k: string, v: string) => v, bold: (v: string) => v };
|
|
143
|
+
const strip = (s: string) => s.replace(/\u001b\[[0-9;]*m/g, "");
|
|
144
|
+
const result = {
|
|
145
|
+
content: [{ type: "text", text: "src/a.ts" }],
|
|
146
|
+
details: { _type: "findResult", text: "src/a.ts", pattern: "*.ts", matchCount: 1 } as never,
|
|
147
|
+
};
|
|
148
|
+
const out =
|
|
149
|
+
registered
|
|
150
|
+
.renderResult?.(result, { isPartial: false }, theme, {
|
|
151
|
+
expanded: false,
|
|
152
|
+
isError: false,
|
|
153
|
+
invalidate: () => {},
|
|
154
|
+
state: {},
|
|
155
|
+
} as unknown as RenderContextLike)
|
|
156
|
+
?.getText() ?? "";
|
|
157
|
+
// Single result is framed just like multi — one shape, no inline row.
|
|
158
|
+
expect(out).toContain("─");
|
|
159
|
+
expect(out).toContain("src/a.ts");
|
|
160
|
+
expect(strip(out)).not.toContain("file");
|
|
161
|
+
const multi = {
|
|
162
|
+
content: [{ type: "text", text: "a.ts\nb.ts\nc.ts" }],
|
|
163
|
+
details: {
|
|
164
|
+
_type: "findResult",
|
|
165
|
+
text: "a.ts\nb.ts\nc.ts",
|
|
166
|
+
pattern: "*.ts",
|
|
167
|
+
matchCount: 3,
|
|
168
|
+
} as never,
|
|
169
|
+
};
|
|
170
|
+
const multiOut =
|
|
171
|
+
registered
|
|
172
|
+
.renderResult?.(multi, { isPartial: false }, theme, {
|
|
173
|
+
expanded: false,
|
|
174
|
+
isError: false,
|
|
175
|
+
invalidate: () => {},
|
|
176
|
+
state: {},
|
|
177
|
+
} as unknown as RenderContextLike)
|
|
178
|
+
?.getText() ?? "";
|
|
179
|
+
expect(multiOut).toContain("─");
|
|
180
|
+
});
|
|
181
|
+
|
|
116
182
|
it("collapses structured errors and restores the exact diagnostic on expansion", () => {
|
|
117
183
|
const registered: { renderResult?: (...args: unknown[]) => MockTextComponent } = {};
|
|
118
184
|
const mockPi: PiPrettyApi = {
|
|
@@ -159,7 +225,7 @@ describe("registerFindTool", () => {
|
|
|
159
225
|
?.getText() ?? "";
|
|
160
226
|
|
|
161
227
|
expect(render({ timer: 1 })).toContain(diagnostic);
|
|
162
|
-
expect(render({ collapsed: true })).toContain("✗
|
|
228
|
+
expect(render({ collapsed: true })).toContain("✗ find [ in src · failed");
|
|
163
229
|
expect(render({ collapsed: true }, true)).toContain(diagnostic);
|
|
164
230
|
});
|
|
165
231
|
});
|
package/src/find.ts
CHANGED
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
getTextContent,
|
|
21
21
|
hideCollapsedToolCall,
|
|
22
22
|
makeTextResult,
|
|
23
|
+
pluralize,
|
|
23
24
|
renderCollapsedToolRow,
|
|
24
25
|
renderDimPreview,
|
|
25
26
|
renderToolError,
|
|
@@ -93,19 +94,35 @@ export function registerFindTool(
|
|
|
93
94
|
}
|
|
94
95
|
|
|
95
96
|
// SDK fallback
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
97
|
+
try {
|
|
98
|
+
const result = await origFind.execute(tid, effectiveParams, sig, upd as never, toolCtx);
|
|
99
|
+
const textContent = getTextContent(result);
|
|
100
|
+
const matchCount = textContent ? textContent.trim().split("\n").filter(Boolean).length : 0;
|
|
101
|
+
|
|
102
|
+
setResultDetails<FindResultDetails>(result, {
|
|
103
|
+
_type: "findResult",
|
|
104
|
+
text: textContent,
|
|
105
|
+
pattern: params.pattern,
|
|
106
|
+
path: params.path,
|
|
107
|
+
matchCount,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
return result;
|
|
111
|
+
} catch (error) {
|
|
112
|
+
const text = error instanceof Error ? error.message : String(error);
|
|
113
|
+
if (sig?.aborted || /aborted/i.test(text)) throw error;
|
|
114
|
+
return {
|
|
115
|
+
content: [{ type: "text" as const, text }],
|
|
116
|
+
details: {
|
|
117
|
+
_type: "findResult" as const,
|
|
118
|
+
text,
|
|
119
|
+
pattern: params.pattern,
|
|
120
|
+
path: params.path,
|
|
121
|
+
matchCount: 0,
|
|
122
|
+
},
|
|
123
|
+
isError: true,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
109
126
|
},
|
|
110
127
|
|
|
111
128
|
renderCall(args: FindParams, theme: ThemeLike, renderCtx: RenderContextLike) {
|
|
@@ -148,7 +165,9 @@ export function registerFindTool(
|
|
|
148
165
|
const cs = renderCtx.state as CollapseState;
|
|
149
166
|
if (!isPartial && tickCollapse("find", cs, renderCtx.invalidate, renderCtx.expanded)) {
|
|
150
167
|
const summary =
|
|
151
|
-
d?._type === "findResult" && d.matchCount != null
|
|
168
|
+
d?._type === "findResult" && d.matchCount != null
|
|
169
|
+
? pluralize(d.matchCount, "file")
|
|
170
|
+
: "found";
|
|
152
171
|
const target = d?._type === "findResult" ? d.pattern : "";
|
|
153
172
|
const scope = d?._type === "findResult" && d.path ? ` in ${sp(d.path)}` : "";
|
|
154
173
|
text.setText(
|
|
@@ -169,7 +188,13 @@ export function registerFindTool(
|
|
|
169
188
|
}
|
|
170
189
|
|
|
171
190
|
const output = getTextContent(result) || "found";
|
|
172
|
-
|
|
191
|
+
// One framed shape; rules follow status color. Count lives in the collapsed row.
|
|
192
|
+
text.setText(
|
|
193
|
+
renderDimPreview(output, theme, {
|
|
194
|
+
frame: true,
|
|
195
|
+
paint: (s: string) => theme.fg(renderCtx.isError ? "error" : "success", s),
|
|
196
|
+
}),
|
|
197
|
+
);
|
|
173
198
|
return text;
|
|
174
199
|
},
|
|
175
200
|
});
|