@ayoxx/kundex 2.0.7 → 2.0.8
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 +1 -1
- package/src/index.ts +1 -1
- package/src/repl.ts +16 -1
- package/src/tools.ts +42 -22
package/package.json
CHANGED
package/src/index.ts
CHANGED
package/src/repl.ts
CHANGED
|
@@ -179,7 +179,7 @@ ${c.bold}Tips:${c.reset}
|
|
|
179
179
|
|
|
180
180
|
function safeGitStatus(cwd: string): string | undefined {
|
|
181
181
|
try {
|
|
182
|
-
return execSync("git status --porcelain=v1 -b", { cwd, timeout: 5000 }).toString();
|
|
182
|
+
return execSync("git status --porcelain=v1 -b 2>/dev/null", { cwd, timeout: 5000 }).toString();
|
|
183
183
|
} catch {
|
|
184
184
|
return undefined;
|
|
185
185
|
}
|
|
@@ -187,6 +187,12 @@ function safeGitStatus(cwd: string): string | undefined {
|
|
|
187
187
|
|
|
188
188
|
function safeFileTree(cwd: string): string | undefined {
|
|
189
189
|
try {
|
|
190
|
+
// Check if this is a git repo first to avoid git errors
|
|
191
|
+
try {
|
|
192
|
+
execSync("git rev-parse --is-inside-work-tree 2>/dev/null", { cwd, timeout: 2000 });
|
|
193
|
+
} catch {
|
|
194
|
+
return undefined;
|
|
195
|
+
}
|
|
190
196
|
return execSync(
|
|
191
197
|
`find . -maxdepth 3 ! -path '*/node_modules/*' ! -path '*/.git/*' ! -path '*/dist/*' ! -path '*/build/*' -print`,
|
|
192
198
|
{ cwd, timeout: 5000 }
|
|
@@ -243,6 +249,15 @@ async function handleTurn(
|
|
|
243
249
|
},
|
|
244
250
|
signal,
|
|
245
251
|
);
|
|
252
|
+
} catch (err) {
|
|
253
|
+
sp.clear();
|
|
254
|
+
const e = err as Error;
|
|
255
|
+
if (e.name === "AbortError") {
|
|
256
|
+
process.stdout.write(`\n${c.yellow} ⚡ Stopped.${c.reset}\n\n`);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
process.stdout.write(`\n${c.red} ✗ Error after tool call: ${e.message}${c.reset}\n\n`);
|
|
260
|
+
return;
|
|
246
261
|
} finally {
|
|
247
262
|
sp.clear();
|
|
248
263
|
}
|
package/src/tools.ts
CHANGED
|
@@ -218,7 +218,7 @@ async function gitTool(cwd: string, args: { args: string[] }): Promise<string> {
|
|
|
218
218
|
}
|
|
219
219
|
|
|
220
220
|
return new Promise((resolve) => {
|
|
221
|
-
exec(cmd
|
|
221
|
+
exec(`${cmd} 2>/dev/null`, { cwd, timeout: 30_000, maxBuffer: 1024 * 1024 }, (err, stdout, stderr) => {
|
|
222
222
|
if (err) {
|
|
223
223
|
resolve(`git command failed (${err.message}):\n${stdout}\n${stderr}`);
|
|
224
224
|
} else {
|
|
@@ -291,38 +291,58 @@ async function webSearchTool(_cwd: string, args: { query: string }): Promise<str
|
|
|
291
291
|
header("web_search", args.query);
|
|
292
292
|
|
|
293
293
|
try {
|
|
294
|
-
// Use DuckDuckGo
|
|
295
|
-
const url = `https://
|
|
294
|
+
// Use DuckDuckGo lite HTML search and parse results
|
|
295
|
+
const url = `https://lite.duckduckgo.com/lite/?q=${encodeURIComponent(args.query)}`;
|
|
296
296
|
const res = await fetch(url, {
|
|
297
|
-
headers: {
|
|
298
|
-
|
|
297
|
+
headers: {
|
|
298
|
+
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
299
|
+
"Accept": "text/html",
|
|
300
|
+
},
|
|
301
|
+
signal: AbortSignal.timeout(15_000),
|
|
302
|
+
redirect: "follow",
|
|
299
303
|
});
|
|
300
|
-
const data = await res.json() as any;
|
|
301
304
|
|
|
305
|
+
if (!res.ok) {
|
|
306
|
+
return `Search failed: HTTP ${res.status}`;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const html = await res.text();
|
|
310
|
+
|
|
311
|
+
// Parse results from DuckDuckGo lite HTML
|
|
302
312
|
const results: string[] = [];
|
|
303
313
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
}
|
|
314
|
+
// Extract result links and snippets
|
|
315
|
+
const linkRegex = /<a[^>]+class="result-link"[^>]*href="([^"]*)"[^>]*>([^<]*)<\/a>/gi;
|
|
316
|
+
const snippetRegex = /<td[^>]+class="result-snippet"[^>]*>([\s\S]*?)<\/td>/gi;
|
|
308
317
|
|
|
309
|
-
|
|
310
|
-
|
|
318
|
+
const links: { url: string; title: string }[] = [];
|
|
319
|
+
const snippets: string[] = [];
|
|
320
|
+
|
|
321
|
+
let match;
|
|
322
|
+
while ((match = linkRegex.exec(html)) !== null) {
|
|
323
|
+
links.push({ url: match[1], title: match[2].trim() });
|
|
324
|
+
}
|
|
325
|
+
while ((match = snippetRegex.exec(html)) !== null) {
|
|
326
|
+
snippets.push(match[1].replace(/<[^>]+>/g, "").trim());
|
|
311
327
|
}
|
|
312
328
|
|
|
313
|
-
|
|
314
|
-
const
|
|
315
|
-
|
|
316
|
-
.slice(0, 5)
|
|
317
|
-
.map((t: any) => `- ${t.Text}${t.FirstURL ? ` (${t.FirstURL})` : ""}`);
|
|
318
|
-
if (topics.length) {
|
|
319
|
-
results.push("Related:\n" + topics.join("\n"));
|
|
320
|
-
}
|
|
329
|
+
for (let i = 0; i < Math.min(links.length, 8); i++) {
|
|
330
|
+
const snippet = snippets[i] || "";
|
|
331
|
+
results.push(`${i + 1}. **${links[i].title}**\n ${links[i].url}\n ${snippet}`);
|
|
321
332
|
}
|
|
322
333
|
|
|
323
334
|
if (results.length === 0) {
|
|
324
|
-
// Fallback:
|
|
325
|
-
|
|
335
|
+
// Fallback: try to extract any text content
|
|
336
|
+
const stripped = html
|
|
337
|
+
.replace(/<script[\s\S]*?<\/script>/gi, "")
|
|
338
|
+
.replace(/<style[\s\S]*?<\/style>/gi, "")
|
|
339
|
+
.replace(/<[^>]+>/g, " ")
|
|
340
|
+
.replace(/\s+/g, " ")
|
|
341
|
+
.trim();
|
|
342
|
+
if (stripped.length > 100) {
|
|
343
|
+
return `Search results:\n${stripped.slice(0, 4000)}`;
|
|
344
|
+
}
|
|
345
|
+
return `No results found for "${args.query}". Try different keywords.`;
|
|
326
346
|
}
|
|
327
347
|
|
|
328
348
|
return results.join("\n\n");
|