@hasna/oldpal 0.1.7 → 0.1.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/dist/index.js +261 -8
- package/dist/index.js.map +8 -7
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -29187,6 +29187,194 @@ class FilesystemTools {
|
|
|
29187
29187
|
};
|
|
29188
29188
|
}
|
|
29189
29189
|
|
|
29190
|
+
// packages/core/src/tools/web.ts
|
|
29191
|
+
class WebFetchTool {
|
|
29192
|
+
static tool = {
|
|
29193
|
+
name: "web_fetch",
|
|
29194
|
+
description: "Fetch content from a URL and return the text content. Useful for reading web pages, documentation, API responses, etc.",
|
|
29195
|
+
parameters: {
|
|
29196
|
+
type: "object",
|
|
29197
|
+
properties: {
|
|
29198
|
+
url: {
|
|
29199
|
+
type: "string",
|
|
29200
|
+
description: "The URL to fetch content from"
|
|
29201
|
+
},
|
|
29202
|
+
extract_type: {
|
|
29203
|
+
type: "string",
|
|
29204
|
+
description: 'What to extract: "text" for readable text, "html" for raw HTML, "json" for JSON response',
|
|
29205
|
+
enum: ["text", "html", "json"],
|
|
29206
|
+
default: "text"
|
|
29207
|
+
},
|
|
29208
|
+
timeout: {
|
|
29209
|
+
type: "number",
|
|
29210
|
+
description: "Timeout in milliseconds (default: 30000)"
|
|
29211
|
+
}
|
|
29212
|
+
},
|
|
29213
|
+
required: ["url"]
|
|
29214
|
+
}
|
|
29215
|
+
};
|
|
29216
|
+
static executor = async (input) => {
|
|
29217
|
+
const url = input.url;
|
|
29218
|
+
const extractType = input.extract_type || "text";
|
|
29219
|
+
const timeout = input.timeout || 30000;
|
|
29220
|
+
try {
|
|
29221
|
+
const parsedUrl = new URL(url);
|
|
29222
|
+
const hostname = parsedUrl.hostname;
|
|
29223
|
+
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname.startsWith("192.168.") || hostname.startsWith("10.") || hostname.startsWith("172.")) {
|
|
29224
|
+
return "Error: Cannot fetch from local/private network addresses for security reasons";
|
|
29225
|
+
}
|
|
29226
|
+
const controller = new AbortController;
|
|
29227
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
29228
|
+
const response = await fetch(url, {
|
|
29229
|
+
signal: controller.signal,
|
|
29230
|
+
headers: {
|
|
29231
|
+
"User-Agent": "oldpal/1.0 (AI Assistant)",
|
|
29232
|
+
Accept: extractType === "json" ? "application/json" : "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
|
|
29233
|
+
}
|
|
29234
|
+
});
|
|
29235
|
+
clearTimeout(timeoutId);
|
|
29236
|
+
if (!response.ok) {
|
|
29237
|
+
return `Error: HTTP ${response.status} ${response.statusText}`;
|
|
29238
|
+
}
|
|
29239
|
+
const contentType = response.headers.get("content-type") || "";
|
|
29240
|
+
if (extractType === "json") {
|
|
29241
|
+
try {
|
|
29242
|
+
const json = await response.json();
|
|
29243
|
+
return JSON.stringify(json, null, 2);
|
|
29244
|
+
} catch {
|
|
29245
|
+
return "Error: Response is not valid JSON";
|
|
29246
|
+
}
|
|
29247
|
+
}
|
|
29248
|
+
const html = await response.text();
|
|
29249
|
+
if (extractType === "html") {
|
|
29250
|
+
const maxLength2 = 50000;
|
|
29251
|
+
if (html.length > maxLength2) {
|
|
29252
|
+
return html.slice(0, maxLength2) + `
|
|
29253
|
+
|
|
29254
|
+
[Content truncated...]`;
|
|
29255
|
+
}
|
|
29256
|
+
return html;
|
|
29257
|
+
}
|
|
29258
|
+
const text = extractReadableText(html);
|
|
29259
|
+
const maxLength = 30000;
|
|
29260
|
+
if (text.length > maxLength) {
|
|
29261
|
+
return text.slice(0, maxLength) + `
|
|
29262
|
+
|
|
29263
|
+
[Content truncated...]`;
|
|
29264
|
+
}
|
|
29265
|
+
return text || "No readable content found on page";
|
|
29266
|
+
} catch (error) {
|
|
29267
|
+
if (error instanceof Error) {
|
|
29268
|
+
if (error.name === "AbortError") {
|
|
29269
|
+
return `Error: Request timed out after ${timeout}ms`;
|
|
29270
|
+
}
|
|
29271
|
+
return `Error: ${error.message}`;
|
|
29272
|
+
}
|
|
29273
|
+
return `Error: ${String(error)}`;
|
|
29274
|
+
}
|
|
29275
|
+
};
|
|
29276
|
+
}
|
|
29277
|
+
|
|
29278
|
+
class WebSearchTool {
|
|
29279
|
+
static tool = {
|
|
29280
|
+
name: "web_search",
|
|
29281
|
+
description: "Search the web using DuckDuckGo and return results. Useful for finding current information, documentation, news, etc.",
|
|
29282
|
+
parameters: {
|
|
29283
|
+
type: "object",
|
|
29284
|
+
properties: {
|
|
29285
|
+
query: {
|
|
29286
|
+
type: "string",
|
|
29287
|
+
description: "The search query"
|
|
29288
|
+
},
|
|
29289
|
+
max_results: {
|
|
29290
|
+
type: "number",
|
|
29291
|
+
description: "Maximum number of results to return (default: 5, max: 10)"
|
|
29292
|
+
}
|
|
29293
|
+
},
|
|
29294
|
+
required: ["query"]
|
|
29295
|
+
}
|
|
29296
|
+
};
|
|
29297
|
+
static executor = async (input) => {
|
|
29298
|
+
const query = input.query;
|
|
29299
|
+
const maxResults = Math.min(input.max_results || 5, 10);
|
|
29300
|
+
try {
|
|
29301
|
+
const searchUrl = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(query)}`;
|
|
29302
|
+
const response = await fetch(searchUrl, {
|
|
29303
|
+
headers: {
|
|
29304
|
+
"User-Agent": "oldpal/1.0 (AI Assistant)",
|
|
29305
|
+
Accept: "text/html"
|
|
29306
|
+
}
|
|
29307
|
+
});
|
|
29308
|
+
if (!response.ok) {
|
|
29309
|
+
return `Error: Search request failed with HTTP ${response.status}`;
|
|
29310
|
+
}
|
|
29311
|
+
const html = await response.text();
|
|
29312
|
+
const results = parseDuckDuckGoResults(html, maxResults);
|
|
29313
|
+
if (results.length === 0) {
|
|
29314
|
+
return `No results found for "${query}"`;
|
|
29315
|
+
}
|
|
29316
|
+
let output = `Search results for "${query}":
|
|
29317
|
+
|
|
29318
|
+
`;
|
|
29319
|
+
for (let i = 0;i < results.length; i++) {
|
|
29320
|
+
const r = results[i];
|
|
29321
|
+
output += `${i + 1}. ${r.title}
|
|
29322
|
+
`;
|
|
29323
|
+
output += ` ${r.url}
|
|
29324
|
+
`;
|
|
29325
|
+
if (r.snippet) {
|
|
29326
|
+
output += ` ${r.snippet}
|
|
29327
|
+
`;
|
|
29328
|
+
}
|
|
29329
|
+
output += `
|
|
29330
|
+
`;
|
|
29331
|
+
}
|
|
29332
|
+
return output.trim();
|
|
29333
|
+
} catch (error) {
|
|
29334
|
+
return `Error: ${error instanceof Error ? error.message : String(error)}`;
|
|
29335
|
+
}
|
|
29336
|
+
};
|
|
29337
|
+
}
|
|
29338
|
+
function extractReadableText(html) {
|
|
29339
|
+
let text = html.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, "").replace(/<style[^>]*>[\s\S]*?<\/style>/gi, "").replace(/<noscript[^>]*>[\s\S]*?<\/noscript>/gi, "").replace(/<nav[^>]*>[\s\S]*?<\/nav>/gi, "").replace(/<footer[^>]*>[\s\S]*?<\/footer>/gi, "").replace(/<header[^>]*>[\s\S]*?<\/header>/gi, "");
|
|
29340
|
+
text = text.replace(/<\/?(p|div|br|h[1-6]|li|tr|blockquote)[^>]*>/gi, `
|
|
29341
|
+
`).replace(/<\/?[^>]+>/g, " ").replace(/ /gi, " ").replace(/&/gi, "&").replace(/</gi, "<").replace(/>/gi, ">").replace(/"/gi, '"').replace(/'/gi, "'").replace(/\s+/g, " ").replace(/\n\s*\n/g, `
|
|
29342
|
+
|
|
29343
|
+
`).trim();
|
|
29344
|
+
return text;
|
|
29345
|
+
}
|
|
29346
|
+
function parseDuckDuckGoResults(html, maxResults) {
|
|
29347
|
+
const results = [];
|
|
29348
|
+
const resultRegex = /<a[^>]*class="result__a"[^>]*href="([^"]*)"[^>]*>([^<]*)<\/a>[\s\S]*?<a[^>]*class="result__snippet"[^>]*>([^<]*)/gi;
|
|
29349
|
+
let match;
|
|
29350
|
+
while ((match = resultRegex.exec(html)) !== null && results.length < maxResults) {
|
|
29351
|
+
const url = decodeURIComponent(match[1].replace(/\/l\/\?uddg=/, "").split("&")[0]);
|
|
29352
|
+
const title = match[2].trim();
|
|
29353
|
+
const snippet = match[3].trim().replace(/&[^;]+;/g, " ");
|
|
29354
|
+
if (url && title && !url.startsWith("//duckduckgo.com")) {
|
|
29355
|
+
results.push({ title, url, snippet });
|
|
29356
|
+
}
|
|
29357
|
+
}
|
|
29358
|
+
if (results.length === 0) {
|
|
29359
|
+
const simpleRegex = /<a[^>]*href="(https?:\/\/[^"]+)"[^>]*class="[^"]*result[^"]*"[^>]*>([^<]+)/gi;
|
|
29360
|
+
while ((match = simpleRegex.exec(html)) !== null && results.length < maxResults) {
|
|
29361
|
+
const url = match[1];
|
|
29362
|
+
const title = match[2].trim();
|
|
29363
|
+
if (url && title) {
|
|
29364
|
+
results.push({ title, url, snippet: "" });
|
|
29365
|
+
}
|
|
29366
|
+
}
|
|
29367
|
+
}
|
|
29368
|
+
return results;
|
|
29369
|
+
}
|
|
29370
|
+
|
|
29371
|
+
class WebTools {
|
|
29372
|
+
static registerAll(registry) {
|
|
29373
|
+
registry.register(WebFetchTool.tool, WebFetchTool.executor);
|
|
29374
|
+
registry.register(WebSearchTool.tool, WebSearchTool.executor);
|
|
29375
|
+
}
|
|
29376
|
+
}
|
|
29377
|
+
|
|
29190
29378
|
// packages/core/src/skills/loader.ts
|
|
29191
29379
|
import { join as join3 } from "path";
|
|
29192
29380
|
import { homedir as homedir2 } from "os";
|
|
@@ -29605,6 +29793,7 @@ class AgentLoop {
|
|
|
29605
29793
|
this.llmClient = await createLLMClient(this.config.llm);
|
|
29606
29794
|
this.toolRegistry.register(BashTool.tool, BashTool.executor);
|
|
29607
29795
|
FilesystemTools.registerAll(this.toolRegistry);
|
|
29796
|
+
WebTools.registerAll(this.toolRegistry);
|
|
29608
29797
|
await this.connectorBridge.discover(this.config.connectors);
|
|
29609
29798
|
this.connectorBridge.registerAll(this.toolRegistry);
|
|
29610
29799
|
await this.skillLoader.loadAll(this.cwd);
|
|
@@ -30158,7 +30347,7 @@ function parseMarkdown(text) {
|
|
|
30158
30347
|
|
|
30159
30348
|
// packages/terminal/src/components/Messages.tsx
|
|
30160
30349
|
var jsx_dev_runtime3 = __toESM(require_jsx_dev_runtime(), 1);
|
|
30161
|
-
function Messages4({ messages, currentResponse, currentToolCall, lastToolResult }) {
|
|
30350
|
+
function Messages4({ messages, currentResponse, currentToolCall, lastToolResult, activityLog = [] }) {
|
|
30162
30351
|
const visibleMessages = messages.slice(-15);
|
|
30163
30352
|
return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
30164
30353
|
flexDirection: "column",
|
|
@@ -30166,7 +30355,37 @@ function Messages4({ messages, currentResponse, currentToolCall, lastToolResult
|
|
|
30166
30355
|
visibleMessages.map((message) => /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(MessageBubble, {
|
|
30167
30356
|
message
|
|
30168
30357
|
}, message.id, false, undefined, this)),
|
|
30169
|
-
|
|
30358
|
+
activityLog.map((entry) => {
|
|
30359
|
+
if (entry.type === "tool_call" && entry.toolCall) {
|
|
30360
|
+
return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
30361
|
+
marginY: 1,
|
|
30362
|
+
children: [
|
|
30363
|
+
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
30364
|
+
dimColor: true,
|
|
30365
|
+
children: "\u25D0 "
|
|
30366
|
+
}, undefined, false, undefined, this),
|
|
30367
|
+
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
30368
|
+
dimColor: true,
|
|
30369
|
+
children: formatToolCall(entry.toolCall)
|
|
30370
|
+
}, undefined, false, undefined, this)
|
|
30371
|
+
]
|
|
30372
|
+
}, entry.id, true, undefined, this);
|
|
30373
|
+
}
|
|
30374
|
+
if (entry.type === "tool_result" && entry.toolResult) {
|
|
30375
|
+
return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
30376
|
+
marginLeft: 2,
|
|
30377
|
+
children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
30378
|
+
dimColor: true,
|
|
30379
|
+
children: [
|
|
30380
|
+
"\u2192 ",
|
|
30381
|
+
truncate(entry.toolResult.content, 100)
|
|
30382
|
+
]
|
|
30383
|
+
}, undefined, true, undefined, this)
|
|
30384
|
+
}, entry.id, false, undefined, this);
|
|
30385
|
+
}
|
|
30386
|
+
return null;
|
|
30387
|
+
}),
|
|
30388
|
+
currentToolCall && !activityLog.some((e) => e.toolCall?.id === currentToolCall.id) && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
30170
30389
|
marginY: 1,
|
|
30171
30390
|
children: [
|
|
30172
30391
|
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
@@ -30179,7 +30398,7 @@ function Messages4({ messages, currentResponse, currentToolCall, lastToolResult
|
|
|
30179
30398
|
}, undefined, false, undefined, this)
|
|
30180
30399
|
]
|
|
30181
30400
|
}, undefined, true, undefined, this),
|
|
30182
|
-
lastToolResult && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
30401
|
+
lastToolResult && !activityLog.some((e) => e.toolResult?.toolCallId === lastToolResult.toolCallId) && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
30183
30402
|
marginY: 1,
|
|
30184
30403
|
marginLeft: 2,
|
|
30185
30404
|
children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
@@ -30391,8 +30610,11 @@ function App2({ cwd: cwd2 }) {
|
|
|
30391
30610
|
const [isInitializing, setIsInitializing] = import_react25.useState(true);
|
|
30392
30611
|
const [error, setError] = import_react25.useState(null);
|
|
30393
30612
|
const [messageQueue, setMessageQueue] = import_react25.useState([]);
|
|
30613
|
+
const [activityLog, setActivityLog] = import_react25.useState([]);
|
|
30394
30614
|
const responseRef = import_react25.useRef("");
|
|
30395
30615
|
const clientRef = import_react25.useRef(null);
|
|
30616
|
+
const toolCallsRef = import_react25.useRef([]);
|
|
30617
|
+
const toolResultsRef = import_react25.useRef([]);
|
|
30396
30618
|
const processQueue = import_react25.useCallback(async () => {
|
|
30397
30619
|
if (!clientRef.current || messageQueue.length === 0)
|
|
30398
30620
|
return;
|
|
@@ -30407,9 +30629,12 @@ function App2({ cwd: cwd2 }) {
|
|
|
30407
30629
|
setMessages((prev) => [...prev, userMessage]);
|
|
30408
30630
|
setCurrentResponse("");
|
|
30409
30631
|
responseRef.current = "";
|
|
30632
|
+
toolCallsRef.current = [];
|
|
30633
|
+
toolResultsRef.current = [];
|
|
30410
30634
|
setError(null);
|
|
30411
30635
|
setCurrentToolCall(undefined);
|
|
30412
30636
|
setLastToolResult(undefined);
|
|
30637
|
+
setActivityLog([]);
|
|
30413
30638
|
setIsProcessing(true);
|
|
30414
30639
|
await clientRef.current.send(nextMessage);
|
|
30415
30640
|
}, [messageQueue]);
|
|
@@ -30423,27 +30648,51 @@ function App2({ cwd: cwd2 }) {
|
|
|
30423
30648
|
responseRef.current += chunk.content;
|
|
30424
30649
|
setCurrentResponse(responseRef.current);
|
|
30425
30650
|
} else if (chunk.type === "tool_use" && chunk.toolCall) {
|
|
30651
|
+
toolCallsRef.current.push(chunk.toolCall);
|
|
30652
|
+
setActivityLog((prev) => [
|
|
30653
|
+
...prev,
|
|
30654
|
+
{
|
|
30655
|
+
id: generateId(),
|
|
30656
|
+
type: "tool_call",
|
|
30657
|
+
toolCall: chunk.toolCall,
|
|
30658
|
+
timestamp: now()
|
|
30659
|
+
}
|
|
30660
|
+
]);
|
|
30426
30661
|
setCurrentToolCall(chunk.toolCall);
|
|
30427
30662
|
setLastToolResult(undefined);
|
|
30428
30663
|
} else if (chunk.type === "tool_result" && chunk.toolResult) {
|
|
30664
|
+
toolResultsRef.current.push(chunk.toolResult);
|
|
30665
|
+
setActivityLog((prev) => [
|
|
30666
|
+
...prev,
|
|
30667
|
+
{
|
|
30668
|
+
id: generateId(),
|
|
30669
|
+
type: "tool_result",
|
|
30670
|
+
toolResult: chunk.toolResult,
|
|
30671
|
+
timestamp: now()
|
|
30672
|
+
}
|
|
30673
|
+
]);
|
|
30429
30674
|
setLastToolResult(chunk.toolResult);
|
|
30430
30675
|
setCurrentToolCall(undefined);
|
|
30431
30676
|
} else if (chunk.type === "error" && chunk.error) {
|
|
30432
30677
|
setError(chunk.error);
|
|
30433
30678
|
setIsProcessing(false);
|
|
30434
30679
|
} else if (chunk.type === "done") {
|
|
30435
|
-
if (responseRef.current) {
|
|
30680
|
+
if (responseRef.current || toolCallsRef.current.length > 0) {
|
|
30436
30681
|
setMessages((prev) => [
|
|
30437
30682
|
...prev,
|
|
30438
30683
|
{
|
|
30439
30684
|
id: generateId(),
|
|
30440
30685
|
role: "assistant",
|
|
30441
30686
|
content: responseRef.current,
|
|
30442
|
-
timestamp: now()
|
|
30687
|
+
timestamp: now(),
|
|
30688
|
+
toolCalls: toolCallsRef.current.length > 0 ? [...toolCallsRef.current] : undefined,
|
|
30689
|
+
toolResults: toolResultsRef.current.length > 0 ? [...toolResultsRef.current] : undefined
|
|
30443
30690
|
}
|
|
30444
30691
|
]);
|
|
30445
30692
|
setCurrentResponse("");
|
|
30446
30693
|
responseRef.current = "";
|
|
30694
|
+
toolCallsRef.current = [];
|
|
30695
|
+
toolResultsRef.current = [];
|
|
30447
30696
|
}
|
|
30448
30697
|
setCurrentToolCall(undefined);
|
|
30449
30698
|
setLastToolResult(undefined);
|
|
@@ -30550,9 +30799,12 @@ function App2({ cwd: cwd2 }) {
|
|
|
30550
30799
|
setMessages((prev) => [...prev, userMessage]);
|
|
30551
30800
|
setCurrentResponse("");
|
|
30552
30801
|
responseRef.current = "";
|
|
30802
|
+
toolCallsRef.current = [];
|
|
30803
|
+
toolResultsRef.current = [];
|
|
30553
30804
|
setError(null);
|
|
30554
30805
|
setCurrentToolCall(undefined);
|
|
30555
30806
|
setLastToolResult(undefined);
|
|
30807
|
+
setActivityLog([]);
|
|
30556
30808
|
setIsProcessing(true);
|
|
30557
30809
|
await client.send(trimmedInput);
|
|
30558
30810
|
}, [client, isProcessing]);
|
|
@@ -30573,7 +30825,8 @@ function App2({ cwd: cwd2 }) {
|
|
|
30573
30825
|
messages,
|
|
30574
30826
|
currentResponse: isProcessing ? currentResponse : undefined,
|
|
30575
30827
|
currentToolCall,
|
|
30576
|
-
lastToolResult
|
|
30828
|
+
lastToolResult,
|
|
30829
|
+
activityLog: isProcessing ? activityLog : []
|
|
30577
30830
|
}, undefined, false, undefined, this),
|
|
30578
30831
|
messageQueue.length > 0 && /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
|
|
30579
30832
|
marginY: 1,
|
|
@@ -30626,7 +30879,7 @@ var options = {
|
|
|
30626
30879
|
help: args.includes("--help") || args.includes("-h")
|
|
30627
30880
|
};
|
|
30628
30881
|
if (options.version) {
|
|
30629
|
-
console.log("oldpal v0.1.
|
|
30882
|
+
console.log("oldpal v0.1.8");
|
|
30630
30883
|
process.exit(0);
|
|
30631
30884
|
}
|
|
30632
30885
|
if (options.help) {
|
|
@@ -30657,4 +30910,4 @@ waitUntilExit().then(() => {
|
|
|
30657
30910
|
process.exit(0);
|
|
30658
30911
|
});
|
|
30659
30912
|
|
|
30660
|
-
//# debugId=
|
|
30913
|
+
//# debugId=43BB59ABD8BF8C1564756E2164756E21
|