@easynet/agent-tool-buildin 0.0.1 → 0.0.2
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/CoreToolsModule.d.ts +3 -2
- package/dist/CoreToolsModule.d.ts.map +1 -1
- package/dist/exec/runCommand.d.ts.map +1 -1
- package/dist/fs/deletePath.d.ts.map +1 -1
- package/dist/fs/listDir.d.ts.map +1 -1
- package/dist/fs/readText.d.ts.map +1 -1
- package/dist/fs/searchText.d.ts.map +1 -1
- package/dist/fs/sha256.d.ts.map +1 -1
- package/dist/fs/writeText.d.ts.map +1 -1
- package/dist/http/downloadFile.d.ts.map +1 -1
- package/dist/http/duckduckgoSearch.d.ts.map +1 -1
- package/dist/http/fetchJson.d.ts.map +1 -1
- package/dist/http/fetchPageMainContent.d.ts.map +1 -1
- package/dist/http/fetchText.d.ts.map +1 -1
- package/dist/http/head.d.ts.map +1 -1
- package/dist/http/yahooFinance.d.ts +22 -0
- package/dist/http/yahooFinance.d.ts.map +1 -0
- package/dist/index.cjs +261 -86
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +259 -85
- package/dist/index.js.map +1 -1
- package/dist/util/jsonSelect.d.ts.map +1 -1
- package/dist/vitest.config.d.ts +3 -0
- package/dist/vitest.config.d.ts.map +1 -0
- package/package.json +5 -3
package/dist/index.js
CHANGED
|
@@ -150,7 +150,10 @@ function isWithinRoot(path, root) {
|
|
|
150
150
|
import { createTaggedError as createTaggedError2 } from "@easynet/agent-tool";
|
|
151
151
|
var readTextHandler = (async (args) => {
|
|
152
152
|
const ctx = getBuiltinContext();
|
|
153
|
-
const inputPath = args.path;
|
|
153
|
+
const inputPath = (args.path ?? args.filePath)?.trim();
|
|
154
|
+
if (!inputPath) {
|
|
155
|
+
throw createTaggedError2("FS_INVALID", "path is required (pass 'path' or 'filePath')", {});
|
|
156
|
+
}
|
|
154
157
|
const maxBytes = args.maxBytes ?? ctx.config.maxReadBytes;
|
|
155
158
|
const resolvedPath = await resolveSandboxedPath(inputPath, ctx.config.sandboxRoot);
|
|
156
159
|
const fileStat = await stat(resolvedPath);
|
|
@@ -185,8 +188,11 @@ import { createHash } from "crypto";
|
|
|
185
188
|
import { dirname as dirname2 } from "path";
|
|
186
189
|
var writeTextHandler = (async (args) => {
|
|
187
190
|
const ctx = getBuiltinContext();
|
|
188
|
-
const inputPath = args.path;
|
|
189
|
-
|
|
191
|
+
const inputPath = (args.path ?? args.filePath)?.trim();
|
|
192
|
+
if (!inputPath) {
|
|
193
|
+
throw new Error("path is required (pass 'path' or 'filePath')");
|
|
194
|
+
}
|
|
195
|
+
const text = args.text ?? args.content ?? "";
|
|
190
196
|
const overwrite = args.overwrite ?? false;
|
|
191
197
|
const mkdirp = args.mkdirp ?? true;
|
|
192
198
|
const resolvedPath = await resolveSandboxedPath(inputPath, ctx.config.sandboxRoot);
|
|
@@ -232,7 +238,10 @@ import { readdir, stat as stat2 } from "fs/promises";
|
|
|
232
238
|
import { resolve as resolve2, join } from "path";
|
|
233
239
|
var listDirHandler = (async (args) => {
|
|
234
240
|
const ctx = getBuiltinContext();
|
|
235
|
-
const inputPath = args.path;
|
|
241
|
+
const inputPath = (args.path ?? args.filePath ?? args.dir ?? args.directory)?.trim();
|
|
242
|
+
if (!inputPath) {
|
|
243
|
+
throw new Error("path is required (pass 'path', 'filePath', 'dir', or 'directory')");
|
|
244
|
+
}
|
|
236
245
|
const maxEntries = args.maxEntries ?? 2e3;
|
|
237
246
|
const includeHidden = args.includeHidden ?? false;
|
|
238
247
|
const recursive = args.recursive ?? false;
|
|
@@ -324,8 +333,14 @@ import { createInterface } from "readline";
|
|
|
324
333
|
import { join as join2, relative } from "path";
|
|
325
334
|
var searchTextHandler = (async (args) => {
|
|
326
335
|
const ctx = getBuiltinContext();
|
|
327
|
-
const rootPath = args.root;
|
|
328
|
-
|
|
336
|
+
const rootPath = (args.root ?? args.path ?? args.dir ?? args.directory)?.trim();
|
|
337
|
+
if (!rootPath) {
|
|
338
|
+
throw new Error("root is required (pass 'root', 'path', 'dir', or 'directory')");
|
|
339
|
+
}
|
|
340
|
+
const query = (args.query ?? args.q)?.trim();
|
|
341
|
+
if (!query) {
|
|
342
|
+
throw new Error("query is required (pass 'query' or 'q')");
|
|
343
|
+
}
|
|
329
344
|
const glob = args.glob ?? "**/*.{md,txt,log,json,ts,js,py,java,scala}";
|
|
330
345
|
const maxMatches = args.maxMatches ?? 100;
|
|
331
346
|
const maxFiles = args.maxFiles ?? 500;
|
|
@@ -444,9 +459,13 @@ function escapeRegExp(str) {
|
|
|
444
459
|
import { createReadStream as createReadStream2 } from "fs";
|
|
445
460
|
import { stat as stat4 } from "fs/promises";
|
|
446
461
|
import { createHash as createHash2 } from "crypto";
|
|
462
|
+
import { createTaggedError as createTaggedError3 } from "@easynet/agent-tool";
|
|
447
463
|
var sha256Handler = (async (args) => {
|
|
448
464
|
const ctx = getBuiltinContext();
|
|
449
|
-
const inputPath = args.path;
|
|
465
|
+
const inputPath = (args.path ?? args.filePath)?.trim();
|
|
466
|
+
if (!inputPath) {
|
|
467
|
+
throw createTaggedError3("FS_INVALID", "path is required (pass 'path' or 'filePath')", {});
|
|
468
|
+
}
|
|
450
469
|
const resolvedPath = await resolveSandboxedPath(inputPath, ctx.config.sandboxRoot);
|
|
451
470
|
const fileStat = await stat4(resolvedPath);
|
|
452
471
|
const hash = await new Promise((resolve3, reject) => {
|
|
@@ -477,7 +496,10 @@ var sha256Handler = (async (args) => {
|
|
|
477
496
|
import { rm, unlink, rmdir, stat as stat5 } from "fs/promises";
|
|
478
497
|
var deletePathHandler = (async (args) => {
|
|
479
498
|
const ctx = getBuiltinContext();
|
|
480
|
-
const inputPath = args.path;
|
|
499
|
+
const inputPath = (args.path ?? args.filePath)?.trim();
|
|
500
|
+
if (!inputPath) {
|
|
501
|
+
throw new Error("path is required (pass 'path' or 'filePath')");
|
|
502
|
+
}
|
|
481
503
|
const recursive = args.recursive ?? false;
|
|
482
504
|
const confirm = args.confirm;
|
|
483
505
|
if (!confirm) {
|
|
@@ -526,20 +548,20 @@ var deletePathHandler = (async (args) => {
|
|
|
526
548
|
|
|
527
549
|
// security/ssrf.ts
|
|
528
550
|
import { lookup } from "dns/promises";
|
|
529
|
-
import { createTaggedError as
|
|
551
|
+
import { createTaggedError as createTaggedError4 } from "@easynet/agent-tool";
|
|
530
552
|
async function validateUrl(url, allowedHosts, blockedCidrs) {
|
|
531
553
|
let parsed;
|
|
532
554
|
try {
|
|
533
555
|
parsed = new URL(url);
|
|
534
556
|
} catch {
|
|
535
|
-
throw
|
|
557
|
+
throw createTaggedError4(
|
|
536
558
|
"HTTP_DISALLOWED_HOST",
|
|
537
559
|
`Invalid URL: ${url}`,
|
|
538
560
|
{ url }
|
|
539
561
|
);
|
|
540
562
|
}
|
|
541
563
|
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
542
|
-
throw
|
|
564
|
+
throw createTaggedError4(
|
|
543
565
|
"HTTP_DISALLOWED_HOST",
|
|
544
566
|
`Protocol not allowed: ${parsed.protocol}. Only http: and https: are supported.`,
|
|
545
567
|
{ url, protocol: parsed.protocol }
|
|
@@ -547,7 +569,7 @@ async function validateUrl(url, allowedHosts, blockedCidrs) {
|
|
|
547
569
|
}
|
|
548
570
|
const hostname = parsed.hostname;
|
|
549
571
|
if (!isHostAllowed(hostname, allowedHosts)) {
|
|
550
|
-
throw
|
|
572
|
+
throw createTaggedError4(
|
|
551
573
|
"HTTP_DISALLOWED_HOST",
|
|
552
574
|
`Host "${hostname}" is not in the allowed hosts list`,
|
|
553
575
|
{ url, hostname, allowedHosts }
|
|
@@ -556,7 +578,7 @@ async function validateUrl(url, allowedHosts, blockedCidrs) {
|
|
|
556
578
|
try {
|
|
557
579
|
const { address } = await lookup(hostname);
|
|
558
580
|
if (isIpInBlockedCidrs(address, blockedCidrs)) {
|
|
559
|
-
throw
|
|
581
|
+
throw createTaggedError4(
|
|
560
582
|
"HTTP_DISALLOWED_HOST",
|
|
561
583
|
`Host "${hostname}" resolves to blocked IP: ${address}`,
|
|
562
584
|
{ url, hostname, resolvedIp: address }
|
|
@@ -566,7 +588,7 @@ async function validateUrl(url, allowedHosts, blockedCidrs) {
|
|
|
566
588
|
if (err instanceof Error && err.kind === "HTTP_DISALLOWED_HOST") {
|
|
567
589
|
throw err;
|
|
568
590
|
}
|
|
569
|
-
throw
|
|
591
|
+
throw createTaggedError4(
|
|
570
592
|
"HTTP_DISALLOWED_HOST",
|
|
571
593
|
`DNS resolution failed for host "${hostname}": ${err instanceof Error ? err.message : String(err)}`,
|
|
572
594
|
{ url, hostname }
|
|
@@ -677,10 +699,13 @@ function expandIpv6(ip) {
|
|
|
677
699
|
}
|
|
678
700
|
|
|
679
701
|
// http/fetchText.ts
|
|
680
|
-
import { createTaggedError as
|
|
702
|
+
import { createTaggedError as createTaggedError5 } from "@easynet/agent-tool";
|
|
681
703
|
var fetchTextHandler = (async (args) => {
|
|
682
704
|
const ctx = getBuiltinContext();
|
|
683
|
-
const url = args.url;
|
|
705
|
+
const url = (args.url ?? args.uri)?.trim();
|
|
706
|
+
if (!url) {
|
|
707
|
+
throw createTaggedError5("HTTP_INVALID", "url is required (pass 'url' or 'uri')", {});
|
|
708
|
+
}
|
|
684
709
|
const method = args.method ?? "GET";
|
|
685
710
|
const headers = args.headers ?? {};
|
|
686
711
|
const body = args.body ?? void 0;
|
|
@@ -702,13 +727,13 @@ var fetchTextHandler = (async (args) => {
|
|
|
702
727
|
});
|
|
703
728
|
} catch (err) {
|
|
704
729
|
if (err instanceof Error && err.name === "AbortError") {
|
|
705
|
-
throw
|
|
730
|
+
throw createTaggedError5(
|
|
706
731
|
"HTTP_TIMEOUT",
|
|
707
732
|
`Request to ${url} timed out after ${timeoutMs}ms`,
|
|
708
733
|
{ url, timeoutMs }
|
|
709
734
|
);
|
|
710
735
|
}
|
|
711
|
-
throw
|
|
736
|
+
throw createTaggedError5(
|
|
712
737
|
"UPSTREAM_ERROR",
|
|
713
738
|
`Fetch failed for ${url}: ${err instanceof Error ? err.message : String(err)}`,
|
|
714
739
|
{ url }
|
|
@@ -718,7 +743,7 @@ var fetchTextHandler = (async (args) => {
|
|
|
718
743
|
}
|
|
719
744
|
const contentLength = response.headers.get("content-length");
|
|
720
745
|
if (contentLength && parseInt(contentLength, 10) > maxBytes) {
|
|
721
|
-
throw
|
|
746
|
+
throw createTaggedError5(
|
|
722
747
|
"HTTP_TOO_LARGE",
|
|
723
748
|
`Response Content-Length ${contentLength} exceeds limit of ${maxBytes} bytes`,
|
|
724
749
|
{ url, contentLength: parseInt(contentLength, 10), limit: maxBytes }
|
|
@@ -763,7 +788,7 @@ async function readResponseWithLimit(response, maxBytes, url) {
|
|
|
763
788
|
totalBytes += value.byteLength;
|
|
764
789
|
if (totalBytes > maxBytes) {
|
|
765
790
|
reader.cancel();
|
|
766
|
-
throw
|
|
791
|
+
throw createTaggedError5(
|
|
767
792
|
"HTTP_TOO_LARGE",
|
|
768
793
|
`Response body exceeded limit of ${maxBytes} bytes while reading from ${url}`,
|
|
769
794
|
{ url, bytesRead: totalBytes, limit: maxBytes }
|
|
@@ -779,10 +804,13 @@ async function readResponseWithLimit(response, maxBytes, url) {
|
|
|
779
804
|
}
|
|
780
805
|
|
|
781
806
|
// http/fetchJson.ts
|
|
782
|
-
import { createTaggedError as
|
|
807
|
+
import { createTaggedError as createTaggedError6 } from "@easynet/agent-tool";
|
|
783
808
|
var fetchJsonHandler = (async (args) => {
|
|
784
809
|
const ctx = getBuiltinContext();
|
|
785
|
-
const url = args.url;
|
|
810
|
+
const url = (args.url ?? args.uri)?.trim();
|
|
811
|
+
if (!url) {
|
|
812
|
+
throw createTaggedError6("HTTP_INVALID", "url is required (pass 'url' or 'uri')", {});
|
|
813
|
+
}
|
|
786
814
|
const method = args.method ?? "GET";
|
|
787
815
|
const headers = args.headers ?? {};
|
|
788
816
|
const body = args.body ?? void 0;
|
|
@@ -807,13 +835,13 @@ var fetchJsonHandler = (async (args) => {
|
|
|
807
835
|
});
|
|
808
836
|
} catch (err) {
|
|
809
837
|
if (err instanceof Error && err.name === "AbortError") {
|
|
810
|
-
throw
|
|
838
|
+
throw createTaggedError6(
|
|
811
839
|
"HTTP_TIMEOUT",
|
|
812
840
|
`Request to ${url} timed out after ${timeoutMs}ms`,
|
|
813
841
|
{ url, timeoutMs }
|
|
814
842
|
);
|
|
815
843
|
}
|
|
816
|
-
throw
|
|
844
|
+
throw createTaggedError6(
|
|
817
845
|
"UPSTREAM_ERROR",
|
|
818
846
|
`Fetch failed for ${url}: ${err instanceof Error ? err.message : String(err)}`,
|
|
819
847
|
{ url }
|
|
@@ -823,7 +851,7 @@ var fetchJsonHandler = (async (args) => {
|
|
|
823
851
|
}
|
|
824
852
|
const contentLength = response.headers.get("content-length");
|
|
825
853
|
if (contentLength && parseInt(contentLength, 10) > maxBytes) {
|
|
826
|
-
throw
|
|
854
|
+
throw createTaggedError6(
|
|
827
855
|
"HTTP_TOO_LARGE",
|
|
828
856
|
`Response Content-Length ${contentLength} exceeds limit of ${maxBytes} bytes`,
|
|
829
857
|
{ url, contentLength: parseInt(contentLength, 10), limit: maxBytes }
|
|
@@ -832,7 +860,7 @@ var fetchJsonHandler = (async (args) => {
|
|
|
832
860
|
const text = await response.text();
|
|
833
861
|
const bytes = Buffer.byteLength(text, "utf-8");
|
|
834
862
|
if (bytes > maxBytes) {
|
|
835
|
-
throw
|
|
863
|
+
throw createTaggedError6(
|
|
836
864
|
"HTTP_TOO_LARGE",
|
|
837
865
|
`Response body ${bytes} bytes exceeds limit of ${maxBytes} bytes`,
|
|
838
866
|
{ url, bytes, limit: maxBytes }
|
|
@@ -842,7 +870,7 @@ var fetchJsonHandler = (async (args) => {
|
|
|
842
870
|
try {
|
|
843
871
|
json = JSON.parse(text);
|
|
844
872
|
} catch {
|
|
845
|
-
throw
|
|
873
|
+
throw createTaggedError6(
|
|
846
874
|
"UPSTREAM_ERROR",
|
|
847
875
|
`Failed to parse JSON response from ${url}: ${text.slice(0, 200)}`,
|
|
848
876
|
{ url, status: response.status, textPreview: text.slice(0, 500) }
|
|
@@ -870,11 +898,17 @@ var fetchJsonHandler = (async (args) => {
|
|
|
870
898
|
import { writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
871
899
|
import { createHash as createHash3 } from "crypto";
|
|
872
900
|
import { dirname as dirname3 } from "path";
|
|
873
|
-
import { createTaggedError as
|
|
901
|
+
import { createTaggedError as createTaggedError7 } from "@easynet/agent-tool";
|
|
874
902
|
var downloadFileHandler = (async (args) => {
|
|
875
903
|
const ctx = getBuiltinContext();
|
|
876
|
-
const url = args.url;
|
|
877
|
-
|
|
904
|
+
const url = (args.url ?? args.uri)?.trim();
|
|
905
|
+
if (!url) {
|
|
906
|
+
throw createTaggedError7("HTTP_INVALID", "url is required (pass 'url' or 'uri')", {});
|
|
907
|
+
}
|
|
908
|
+
const destPath = (args.destPath ?? args.destination ?? args.filePath)?.trim();
|
|
909
|
+
if (!destPath) {
|
|
910
|
+
throw createTaggedError7("HTTP_INVALID", "destPath is required (pass 'destPath', 'destination', or 'filePath')", {});
|
|
911
|
+
}
|
|
878
912
|
const headers = args.headers ?? {};
|
|
879
913
|
const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;
|
|
880
914
|
const maxBytes = args.maxBytes ?? ctx.config.maxDownloadBytes;
|
|
@@ -909,13 +943,13 @@ var downloadFileHandler = (async (args) => {
|
|
|
909
943
|
});
|
|
910
944
|
} catch (err) {
|
|
911
945
|
if (err instanceof Error && err.name === "AbortError") {
|
|
912
|
-
throw
|
|
946
|
+
throw createTaggedError7(
|
|
913
947
|
"HTTP_TIMEOUT",
|
|
914
948
|
`Download from ${url} timed out after ${timeoutMs}ms`,
|
|
915
949
|
{ url, timeoutMs }
|
|
916
950
|
);
|
|
917
951
|
}
|
|
918
|
-
throw
|
|
952
|
+
throw createTaggedError7(
|
|
919
953
|
"UPSTREAM_ERROR",
|
|
920
954
|
`Download failed for ${url}: ${err instanceof Error ? err.message : String(err)}`,
|
|
921
955
|
{ url }
|
|
@@ -925,14 +959,14 @@ var downloadFileHandler = (async (args) => {
|
|
|
925
959
|
}
|
|
926
960
|
const contentLength = response.headers.get("content-length");
|
|
927
961
|
if (contentLength && parseInt(contentLength, 10) > maxBytes) {
|
|
928
|
-
throw
|
|
962
|
+
throw createTaggedError7(
|
|
929
963
|
"HTTP_TOO_LARGE",
|
|
930
964
|
`Download Content-Length ${contentLength} exceeds limit of ${maxBytes} bytes`,
|
|
931
965
|
{ url, contentLength: parseInt(contentLength, 10), limit: maxBytes }
|
|
932
966
|
);
|
|
933
967
|
}
|
|
934
968
|
if (!response.body) {
|
|
935
|
-
throw
|
|
969
|
+
throw createTaggedError7("UPSTREAM_ERROR", `No response body from ${url}`, { url });
|
|
936
970
|
}
|
|
937
971
|
const reader = response.body.getReader();
|
|
938
972
|
const chunks = [];
|
|
@@ -945,7 +979,7 @@ var downloadFileHandler = (async (args) => {
|
|
|
945
979
|
totalBytes += value.byteLength;
|
|
946
980
|
if (totalBytes > maxBytes) {
|
|
947
981
|
reader.cancel();
|
|
948
|
-
throw
|
|
982
|
+
throw createTaggedError7(
|
|
949
983
|
"HTTP_TOO_LARGE",
|
|
950
984
|
`Download from ${url} exceeded limit of ${maxBytes} bytes (received ${totalBytes})`,
|
|
951
985
|
{ url, bytesRead: totalBytes, limit: maxBytes }
|
|
@@ -987,10 +1021,13 @@ var downloadFileHandler = (async (args) => {
|
|
|
987
1021
|
});
|
|
988
1022
|
|
|
989
1023
|
// http/head.ts
|
|
990
|
-
import { createTaggedError as
|
|
1024
|
+
import { createTaggedError as createTaggedError8 } from "@easynet/agent-tool";
|
|
991
1025
|
var headHandler = (async (args) => {
|
|
992
1026
|
const ctx = getBuiltinContext();
|
|
993
|
-
const url = args.url;
|
|
1027
|
+
const url = (args.url ?? args.uri)?.trim();
|
|
1028
|
+
if (!url) {
|
|
1029
|
+
throw createTaggedError8("HTTP_INVALID", "url is required (pass 'url' or 'uri')", {});
|
|
1030
|
+
}
|
|
994
1031
|
const headers = args.headers ?? {};
|
|
995
1032
|
const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;
|
|
996
1033
|
await validateUrl(url, ctx.config.allowedHosts, ctx.config.blockedCidrs);
|
|
@@ -1008,13 +1045,13 @@ var headHandler = (async (args) => {
|
|
|
1008
1045
|
});
|
|
1009
1046
|
} catch (err) {
|
|
1010
1047
|
if (err instanceof Error && err.name === "AbortError") {
|
|
1011
|
-
throw
|
|
1048
|
+
throw createTaggedError8(
|
|
1012
1049
|
"HTTP_TIMEOUT",
|
|
1013
1050
|
`HEAD request to ${url} timed out after ${timeoutMs}ms`,
|
|
1014
1051
|
{ url, timeoutMs }
|
|
1015
1052
|
);
|
|
1016
1053
|
}
|
|
1017
|
-
throw
|
|
1054
|
+
throw createTaggedError8(
|
|
1018
1055
|
"UPSTREAM_ERROR",
|
|
1019
1056
|
`HEAD request failed for ${url}: ${err instanceof Error ? err.message : String(err)}`,
|
|
1020
1057
|
{ url }
|
|
@@ -1044,13 +1081,13 @@ var headHandler = (async (args) => {
|
|
|
1044
1081
|
});
|
|
1045
1082
|
|
|
1046
1083
|
// http/duckduckgoSearch.ts
|
|
1047
|
-
import { createTaggedError as
|
|
1084
|
+
import { createTaggedError as createTaggedError9 } from "@easynet/agent-tool";
|
|
1048
1085
|
var DUCKDUCKGO_API = "https://api.duckduckgo.com/";
|
|
1049
1086
|
var duckduckgoSearchHandler = (async (args) => {
|
|
1050
1087
|
const ctx = getBuiltinContext();
|
|
1051
|
-
const query = args.query?.trim();
|
|
1088
|
+
const query = (args.query ?? args.q)?.trim();
|
|
1052
1089
|
if (!query) {
|
|
1053
|
-
throw
|
|
1090
|
+
throw createTaggedError9("DUCKDUCKGO_INVALID", "query is required (pass 'query' or 'q')", {});
|
|
1054
1091
|
}
|
|
1055
1092
|
const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;
|
|
1056
1093
|
const maxResults = args.maxResults ?? 10;
|
|
@@ -1068,13 +1105,13 @@ var duckduckgoSearchHandler = (async (args) => {
|
|
|
1068
1105
|
} catch (err) {
|
|
1069
1106
|
clearTimeout(timer);
|
|
1070
1107
|
if (err instanceof Error && err.name === "AbortError") {
|
|
1071
|
-
throw
|
|
1108
|
+
throw createTaggedError9(
|
|
1072
1109
|
"HTTP_TIMEOUT",
|
|
1073
1110
|
`DuckDuckGo search timed out after ${timeoutMs}ms`,
|
|
1074
1111
|
{ query, timeoutMs }
|
|
1075
1112
|
);
|
|
1076
1113
|
}
|
|
1077
|
-
throw
|
|
1114
|
+
throw createTaggedError9(
|
|
1078
1115
|
"UPSTREAM_ERROR",
|
|
1079
1116
|
`DuckDuckGo search failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
1080
1117
|
{ query }
|
|
@@ -1085,7 +1122,7 @@ var duckduckgoSearchHandler = (async (args) => {
|
|
|
1085
1122
|
const text = await response.text();
|
|
1086
1123
|
const bytes = Buffer.byteLength(text, "utf-8");
|
|
1087
1124
|
if (bytes > maxBytes) {
|
|
1088
|
-
throw
|
|
1125
|
+
throw createTaggedError9(
|
|
1089
1126
|
"HTTP_TOO_LARGE",
|
|
1090
1127
|
`DuckDuckGo response ${bytes} bytes exceeds limit of ${maxBytes} bytes`,
|
|
1091
1128
|
{ query, bytes, limit: maxBytes }
|
|
@@ -1095,7 +1132,7 @@ var duckduckgoSearchHandler = (async (args) => {
|
|
|
1095
1132
|
try {
|
|
1096
1133
|
raw = JSON.parse(text);
|
|
1097
1134
|
} catch {
|
|
1098
|
-
throw
|
|
1135
|
+
throw createTaggedError9(
|
|
1099
1136
|
"UPSTREAM_ERROR",
|
|
1100
1137
|
`DuckDuckGo returned invalid JSON`,
|
|
1101
1138
|
{ query, textPreview: text.slice(0, 200) }
|
|
@@ -1146,7 +1183,7 @@ var duckduckgoSearchHandler = (async (args) => {
|
|
|
1146
1183
|
|
|
1147
1184
|
// http/fetchPageMainContent.ts
|
|
1148
1185
|
import { parse } from "node-html-parser";
|
|
1149
|
-
import { createTaggedError as
|
|
1186
|
+
import { createTaggedError as createTaggedError10 } from "@easynet/agent-tool";
|
|
1150
1187
|
var MAIN_SELECTORS = [
|
|
1151
1188
|
"main",
|
|
1152
1189
|
"article",
|
|
@@ -1187,7 +1224,10 @@ function extractMainContent(html) {
|
|
|
1187
1224
|
}
|
|
1188
1225
|
var fetchPageMainContentHandler = (async (args) => {
|
|
1189
1226
|
const ctx = getBuiltinContext();
|
|
1190
|
-
const url = args.url;
|
|
1227
|
+
const url = (args.url ?? args.uri)?.trim();
|
|
1228
|
+
if (!url) {
|
|
1229
|
+
throw createTaggedError10("HTTP_INVALID", "url is required (pass 'url' or 'uri')", {});
|
|
1230
|
+
}
|
|
1191
1231
|
const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;
|
|
1192
1232
|
const maxBytes = args.maxBytes ?? ctx.config.maxHttpBytes;
|
|
1193
1233
|
await validateUrl(url, ctx.config.allowedHosts, ctx.config.blockedCidrs);
|
|
@@ -1203,13 +1243,13 @@ var fetchPageMainContentHandler = (async (args) => {
|
|
|
1203
1243
|
} catch (err) {
|
|
1204
1244
|
clearTimeout(timer);
|
|
1205
1245
|
if (err instanceof Error && err.name === "AbortError") {
|
|
1206
|
-
throw
|
|
1246
|
+
throw createTaggedError10(
|
|
1207
1247
|
"HTTP_TIMEOUT",
|
|
1208
1248
|
`Request to ${url} timed out after ${timeoutMs}ms`,
|
|
1209
1249
|
{ url, timeoutMs }
|
|
1210
1250
|
);
|
|
1211
1251
|
}
|
|
1212
|
-
throw
|
|
1252
|
+
throw createTaggedError10(
|
|
1213
1253
|
"UPSTREAM_ERROR",
|
|
1214
1254
|
`Fetch failed for ${url}: ${err instanceof Error ? err.message : String(err)}`,
|
|
1215
1255
|
{ url }
|
|
@@ -1218,7 +1258,7 @@ var fetchPageMainContentHandler = (async (args) => {
|
|
|
1218
1258
|
clearTimeout(timer);
|
|
1219
1259
|
const contentLength = response.headers.get("content-length");
|
|
1220
1260
|
if (contentLength && parseInt(contentLength, 10) > maxBytes) {
|
|
1221
|
-
throw
|
|
1261
|
+
throw createTaggedError10(
|
|
1222
1262
|
"HTTP_TOO_LARGE",
|
|
1223
1263
|
`Response Content-Length ${contentLength} exceeds limit of ${maxBytes} bytes`,
|
|
1224
1264
|
{ url, contentLength: parseInt(contentLength, 10), limit: maxBytes }
|
|
@@ -1227,7 +1267,7 @@ var fetchPageMainContentHandler = (async (args) => {
|
|
|
1227
1267
|
const rawText = await response.text();
|
|
1228
1268
|
const rawBytes = Buffer.byteLength(rawText, "utf-8");
|
|
1229
1269
|
if (rawBytes > maxBytes) {
|
|
1230
|
-
throw
|
|
1270
|
+
throw createTaggedError10(
|
|
1231
1271
|
"HTTP_TOO_LARGE",
|
|
1232
1272
|
`Response body ${rawBytes} bytes exceeds limit of ${maxBytes} bytes`,
|
|
1233
1273
|
{ url, bytes: rawBytes, limit: maxBytes }
|
|
@@ -1269,10 +1309,133 @@ var fetchPageMainContentHandler = (async (args) => {
|
|
|
1269
1309
|
};
|
|
1270
1310
|
});
|
|
1271
1311
|
|
|
1312
|
+
// http/yahooFinance.ts
|
|
1313
|
+
import { createTaggedError as createTaggedError11 } from "@easynet/agent-tool";
|
|
1314
|
+
var YAHOO_CHART_BASE = "https://query1.finance.yahoo.com/v8/finance/chart/";
|
|
1315
|
+
var yahooFinanceQuoteHandler = (async (args) => {
|
|
1316
|
+
const ctx = getBuiltinContext();
|
|
1317
|
+
const rawSymbols = args.symbols ?? args.symbol ?? args.tickers;
|
|
1318
|
+
const symbols = Array.isArray(rawSymbols) ? rawSymbols.map((s) => String(s).trim().toUpperCase()).filter(Boolean) : rawSymbols != null ? [String(rawSymbols).trim().toUpperCase()].filter(Boolean) : [];
|
|
1319
|
+
if (symbols.length === 0) {
|
|
1320
|
+
throw createTaggedError11(
|
|
1321
|
+
"YAHOO_INVALID",
|
|
1322
|
+
"At least one symbol is required",
|
|
1323
|
+
{}
|
|
1324
|
+
);
|
|
1325
|
+
}
|
|
1326
|
+
const range = args.range ?? "1d";
|
|
1327
|
+
const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;
|
|
1328
|
+
const maxBytes = ctx.config.maxHttpBytes;
|
|
1329
|
+
const quotes = [];
|
|
1330
|
+
for (const symbol of symbols) {
|
|
1331
|
+
const url2 = `${YAHOO_CHART_BASE}${encodeURIComponent(symbol)}?interval=1d&range=${range}`;
|
|
1332
|
+
await validateUrl(url2, ctx.config.allowedHosts, ctx.config.blockedCidrs);
|
|
1333
|
+
const controller = new AbortController();
|
|
1334
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
1335
|
+
let response;
|
|
1336
|
+
try {
|
|
1337
|
+
response = await fetch(url2, {
|
|
1338
|
+
method: "GET",
|
|
1339
|
+
headers: {
|
|
1340
|
+
"User-Agent": ctx.config.httpUserAgent,
|
|
1341
|
+
Accept: "application/json"
|
|
1342
|
+
},
|
|
1343
|
+
signal: controller.signal
|
|
1344
|
+
});
|
|
1345
|
+
} catch (err) {
|
|
1346
|
+
clearTimeout(timer);
|
|
1347
|
+
if (err instanceof Error && err.name === "AbortError") {
|
|
1348
|
+
throw createTaggedError11(
|
|
1349
|
+
"HTTP_TIMEOUT",
|
|
1350
|
+
`Yahoo Finance request for ${symbol} timed out after ${timeoutMs}ms`,
|
|
1351
|
+
{ symbol, timeoutMs }
|
|
1352
|
+
);
|
|
1353
|
+
}
|
|
1354
|
+
throw createTaggedError11(
|
|
1355
|
+
"UPSTREAM_ERROR",
|
|
1356
|
+
`Yahoo Finance request failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
1357
|
+
{ symbol }
|
|
1358
|
+
);
|
|
1359
|
+
}
|
|
1360
|
+
clearTimeout(timer);
|
|
1361
|
+
const text = await response.text();
|
|
1362
|
+
const bytes = Buffer.byteLength(text, "utf-8");
|
|
1363
|
+
if (bytes > maxBytes) {
|
|
1364
|
+
throw createTaggedError11(
|
|
1365
|
+
"HTTP_TOO_LARGE",
|
|
1366
|
+
`Yahoo Finance response ${bytes} bytes exceeds limit of ${maxBytes} bytes`,
|
|
1367
|
+
{ symbol, bytes, limit: maxBytes }
|
|
1368
|
+
);
|
|
1369
|
+
}
|
|
1370
|
+
let data;
|
|
1371
|
+
try {
|
|
1372
|
+
data = JSON.parse(text);
|
|
1373
|
+
} catch {
|
|
1374
|
+
throw createTaggedError11(
|
|
1375
|
+
"UPSTREAM_ERROR",
|
|
1376
|
+
"Yahoo Finance returned invalid JSON",
|
|
1377
|
+
{ symbol, textPreview: text.slice(0, 200) }
|
|
1378
|
+
);
|
|
1379
|
+
}
|
|
1380
|
+
const error = data.chart?.error;
|
|
1381
|
+
if (error?.description) {
|
|
1382
|
+
throw createTaggedError11(
|
|
1383
|
+
"YAHOO_ERROR",
|
|
1384
|
+
`Yahoo Finance error for ${symbol}: ${error.description}`,
|
|
1385
|
+
{ symbol, code: error.code }
|
|
1386
|
+
);
|
|
1387
|
+
}
|
|
1388
|
+
const result = data.chart?.result?.[0];
|
|
1389
|
+
if (!result) {
|
|
1390
|
+
quotes.push({ symbol });
|
|
1391
|
+
continue;
|
|
1392
|
+
}
|
|
1393
|
+
const meta = result.meta ?? {};
|
|
1394
|
+
const quoteArr = result.indicators?.quote?.[0];
|
|
1395
|
+
const lastIdx = (result.timestamp?.length ?? 1) - 1;
|
|
1396
|
+
const price = meta.regularMarketPrice ?? meta.previousClose ?? quoteArr?.close?.[lastIdx] ?? void 0;
|
|
1397
|
+
const previousClose = meta.previousClose ?? meta.chartPreviousClose ?? quoteArr?.close?.[Math.max(0, lastIdx - 1)] ?? void 0;
|
|
1398
|
+
const change = price != null && previousClose != null ? price - previousClose : void 0;
|
|
1399
|
+
const changePercent = change != null && previousClose != null && previousClose !== 0 ? change / previousClose * 100 : void 0;
|
|
1400
|
+
quotes.push({
|
|
1401
|
+
symbol: meta.symbol ?? symbol,
|
|
1402
|
+
currency: meta.currency,
|
|
1403
|
+
price: price ?? void 0,
|
|
1404
|
+
previousClose: previousClose ?? void 0,
|
|
1405
|
+
change,
|
|
1406
|
+
changePercent,
|
|
1407
|
+
open: quoteArr?.open?.[lastIdx] ?? void 0,
|
|
1408
|
+
high: quoteArr?.high?.[lastIdx] ?? void 0,
|
|
1409
|
+
low: quoteArr?.low?.[lastIdx] ?? void 0,
|
|
1410
|
+
volume: quoteArr?.volume?.[lastIdx] ?? void 0,
|
|
1411
|
+
timestamp: result.timestamp?.[lastIdx]
|
|
1412
|
+
});
|
|
1413
|
+
}
|
|
1414
|
+
const url = `${YAHOO_CHART_BASE}${encodeURIComponent(symbols[0])}?interval=1d&range=${range}`;
|
|
1415
|
+
return {
|
|
1416
|
+
result: {
|
|
1417
|
+
symbols: quotes.map((q) => q.symbol),
|
|
1418
|
+
quotes,
|
|
1419
|
+
range
|
|
1420
|
+
},
|
|
1421
|
+
evidence: [
|
|
1422
|
+
{
|
|
1423
|
+
type: "url",
|
|
1424
|
+
ref: url,
|
|
1425
|
+
summary: `Yahoo Finance quote: ${symbols.join(", ")} (${quotes.length} result(s))`,
|
|
1426
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1427
|
+
}
|
|
1428
|
+
]
|
|
1429
|
+
};
|
|
1430
|
+
});
|
|
1431
|
+
|
|
1272
1432
|
// util/jsonSelect.ts
|
|
1273
1433
|
var jsonSelectHandler = (async (args) => {
|
|
1274
1434
|
const json = args.json;
|
|
1275
|
-
const path = args.path;
|
|
1435
|
+
const path = (args.path ?? args.expression)?.trim();
|
|
1436
|
+
if (path === void 0 || path === "") {
|
|
1437
|
+
throw new Error("path is required (pass 'path' or 'expression')");
|
|
1438
|
+
}
|
|
1276
1439
|
let jmespath;
|
|
1277
1440
|
try {
|
|
1278
1441
|
jmespath = await import("./jmespath-6W7SK7AH.js");
|
|
@@ -1429,37 +1592,37 @@ var templateRenderHandler = (async (args) => {
|
|
|
1429
1592
|
// exec/runCommand.ts
|
|
1430
1593
|
import { spawn } from "child_process";
|
|
1431
1594
|
import { resolve as pathResolve } from "path";
|
|
1432
|
-
import { createTaggedError as
|
|
1595
|
+
import { createTaggedError as createTaggedError12 } from "@easynet/agent-tool";
|
|
1433
1596
|
var runCommandHandler = (async (args) => {
|
|
1434
1597
|
const ctx = getBuiltinContext();
|
|
1435
1598
|
const { allowedCommands, maxCommandOutputBytes, commandTimeoutMs } = ctx.config;
|
|
1436
1599
|
if (!allowedCommands.length) {
|
|
1437
|
-
throw
|
|
1600
|
+
throw createTaggedError12(
|
|
1438
1601
|
"EXEC_DISABLED",
|
|
1439
1602
|
"Exec is disabled: allowedCommands is empty",
|
|
1440
1603
|
{}
|
|
1441
1604
|
);
|
|
1442
1605
|
}
|
|
1443
|
-
const rawCommand = args.command?.trim();
|
|
1606
|
+
const rawCommand = (args.command ?? args.cmd)?.trim();
|
|
1444
1607
|
if (!rawCommand) {
|
|
1445
|
-
throw
|
|
1608
|
+
throw createTaggedError12("EXEC_INVALID", "command is required (pass 'command' or 'cmd')", {});
|
|
1446
1609
|
}
|
|
1447
1610
|
const baseName = rawCommand.replace(/^.*\//, "").trim();
|
|
1448
1611
|
if (baseName !== rawCommand || /[;&|$`\s]/.test(rawCommand)) {
|
|
1449
|
-
throw
|
|
1612
|
+
throw createTaggedError12(
|
|
1450
1613
|
"EXEC_INVALID",
|
|
1451
1614
|
"command must be a single executable name (no path, no shell chars)",
|
|
1452
1615
|
{ command: rawCommand }
|
|
1453
1616
|
);
|
|
1454
1617
|
}
|
|
1455
1618
|
if (!allowedCommands.includes(baseName)) {
|
|
1456
|
-
throw
|
|
1619
|
+
throw createTaggedError12(
|
|
1457
1620
|
"EXEC_NOT_ALLOWED",
|
|
1458
1621
|
`Command "${baseName}" is not in allowedCommands`,
|
|
1459
1622
|
{ command: baseName, allowed: allowedCommands }
|
|
1460
1623
|
);
|
|
1461
1624
|
}
|
|
1462
|
-
const cmdArgs = Array.isArray(args.args) ? args.args : [];
|
|
1625
|
+
const cmdArgs = Array.isArray(args.args) ? args.args : Array.isArray(args.arguments) ? args.arguments : [];
|
|
1463
1626
|
const timeoutMs = args.timeoutMs ?? commandTimeoutMs;
|
|
1464
1627
|
let cwd = pathResolve(ctx.config.sandboxRoot);
|
|
1465
1628
|
if (args.cwd != null && args.cwd !== "") {
|
|
@@ -1480,7 +1643,7 @@ var runCommandHandler = (async (args) => {
|
|
|
1480
1643
|
if (totalBytes + len > maxCommandOutputBytes) {
|
|
1481
1644
|
proc.kill("SIGKILL");
|
|
1482
1645
|
rejectPromise(
|
|
1483
|
-
|
|
1646
|
+
createTaggedError12(
|
|
1484
1647
|
"EXEC_OUTPUT_TOO_LARGE",
|
|
1485
1648
|
`Command output exceeded ${maxCommandOutputBytes} bytes`,
|
|
1486
1649
|
{ maxBytes: maxCommandOutputBytes }
|
|
@@ -1518,7 +1681,7 @@ var runCommandHandler = (async (args) => {
|
|
|
1518
1681
|
proc.on("error", (err) => {
|
|
1519
1682
|
clearTimeout(timeout);
|
|
1520
1683
|
rejectPromise(
|
|
1521
|
-
|
|
1684
|
+
createTaggedError12("EXEC_SPAWN_ERROR", err.message, { command: baseName })
|
|
1522
1685
|
);
|
|
1523
1686
|
});
|
|
1524
1687
|
proc.on("close", (code, signal) => {
|
|
@@ -1550,7 +1713,7 @@ var CORE_TOOL_MANIFEST = [
|
|
|
1550
1713
|
{
|
|
1551
1714
|
name: "core/fs.readText",
|
|
1552
1715
|
kind: "core",
|
|
1553
|
-
description: "Read a UTF-8 text file from the sandbox",
|
|
1716
|
+
description: "Read a UTF-8 text file from the sandbox. Input: path (or filePath), optional maxBytes.",
|
|
1554
1717
|
tags: ["filesystem", "read", "core"],
|
|
1555
1718
|
capabilities: ["read:fs"],
|
|
1556
1719
|
sideEffect: "none"
|
|
@@ -1558,7 +1721,7 @@ var CORE_TOOL_MANIFEST = [
|
|
|
1558
1721
|
{
|
|
1559
1722
|
name: "core/fs.writeText",
|
|
1560
1723
|
kind: "core",
|
|
1561
|
-
description: "Write UTF-8 text to a file in the sandbox",
|
|
1724
|
+
description: "Write UTF-8 text to a file in the sandbox. Input: path (or filePath), text (or content), optional overwrite, mkdirp.",
|
|
1562
1725
|
tags: ["filesystem", "write", "core"],
|
|
1563
1726
|
capabilities: ["write:fs"],
|
|
1564
1727
|
sideEffect: "local_write"
|
|
@@ -1566,7 +1729,7 @@ var CORE_TOOL_MANIFEST = [
|
|
|
1566
1729
|
{
|
|
1567
1730
|
name: "core/fs.listDir",
|
|
1568
1731
|
kind: "core",
|
|
1569
|
-
description: "List directory contents in the sandbox",
|
|
1732
|
+
description: "List directory contents in the sandbox. Input: path (or filePath, dir, directory), optional maxEntries, includeHidden, recursive, maxDepth.",
|
|
1570
1733
|
tags: ["filesystem", "read", "core"],
|
|
1571
1734
|
capabilities: ["read:fs"],
|
|
1572
1735
|
sideEffect: "none"
|
|
@@ -1574,7 +1737,7 @@ var CORE_TOOL_MANIFEST = [
|
|
|
1574
1737
|
{
|
|
1575
1738
|
name: "core/fs.searchText",
|
|
1576
1739
|
kind: "core",
|
|
1577
|
-
description: "Search for text patterns in files within the sandbox",
|
|
1740
|
+
description: "Search for text patterns in files within the sandbox. Input: root (or path, dir, directory), query (or q), optional glob, maxMatches, maxFiles.",
|
|
1578
1741
|
tags: ["filesystem", "search", "core"],
|
|
1579
1742
|
capabilities: ["read:fs"],
|
|
1580
1743
|
sideEffect: "none"
|
|
@@ -1582,7 +1745,7 @@ var CORE_TOOL_MANIFEST = [
|
|
|
1582
1745
|
{
|
|
1583
1746
|
name: "core/fs.sha256",
|
|
1584
1747
|
kind: "core",
|
|
1585
|
-
description: "Compute SHA-256 hash of a file in the sandbox",
|
|
1748
|
+
description: "Compute SHA-256 hash of a file in the sandbox. Input: path (or filePath).",
|
|
1586
1749
|
tags: ["filesystem", "hash", "core"],
|
|
1587
1750
|
capabilities: ["read:fs"],
|
|
1588
1751
|
sideEffect: "none"
|
|
@@ -1590,7 +1753,7 @@ var CORE_TOOL_MANIFEST = [
|
|
|
1590
1753
|
{
|
|
1591
1754
|
name: "core/fs.deletePath",
|
|
1592
1755
|
kind: "core",
|
|
1593
|
-
description: "Delete a file or directory in the sandbox (dangerous, requires explicit confirmation)",
|
|
1756
|
+
description: "Delete a file or directory in the sandbox (dangerous, requires explicit confirmation). Input: path (or filePath), confirm=true, optional recursive.",
|
|
1594
1757
|
tags: ["filesystem", "delete", "dangerous", "core"],
|
|
1595
1758
|
capabilities: ["danger:destructive", "write:fs"],
|
|
1596
1759
|
sideEffect: "destructive"
|
|
@@ -1599,7 +1762,7 @@ var CORE_TOOL_MANIFEST = [
|
|
|
1599
1762
|
{
|
|
1600
1763
|
name: "core/http.fetchText",
|
|
1601
1764
|
kind: "core",
|
|
1602
|
-
description: "Fetch a URL and return the response as text",
|
|
1765
|
+
description: "Fetch a URL and return the response as text. Input: url (or uri), optional method, headers, body, timeoutMs, maxBytes.",
|
|
1603
1766
|
tags: ["http", "network", "core"],
|
|
1604
1767
|
capabilities: ["network"],
|
|
1605
1768
|
sideEffect: "none"
|
|
@@ -1607,7 +1770,7 @@ var CORE_TOOL_MANIFEST = [
|
|
|
1607
1770
|
{
|
|
1608
1771
|
name: "core/http.fetchJson",
|
|
1609
1772
|
kind: "core",
|
|
1610
|
-
description: "Fetch a URL and return the response as parsed JSON",
|
|
1773
|
+
description: "Fetch a URL and return the response as parsed JSON. Input: url (or uri), optional method, headers, body, timeoutMs, maxBytes.",
|
|
1611
1774
|
tags: ["http", "network", "json", "core"],
|
|
1612
1775
|
capabilities: ["network"],
|
|
1613
1776
|
sideEffect: "none"
|
|
@@ -1615,7 +1778,7 @@ var CORE_TOOL_MANIFEST = [
|
|
|
1615
1778
|
{
|
|
1616
1779
|
name: "core/http.downloadFile",
|
|
1617
1780
|
kind: "core",
|
|
1618
|
-
description: "Download a file from a URL to the sandbox",
|
|
1781
|
+
description: "Download a file from a URL to the sandbox. Input: url (or uri), destPath (or destination, filePath), optional headers, timeoutMs, maxBytes, overwrite.",
|
|
1619
1782
|
tags: ["http", "network", "download", "core"],
|
|
1620
1783
|
capabilities: ["network", "write:fs"],
|
|
1621
1784
|
sideEffect: "local_write"
|
|
@@ -1623,7 +1786,7 @@ var CORE_TOOL_MANIFEST = [
|
|
|
1623
1786
|
{
|
|
1624
1787
|
name: "core/http.head",
|
|
1625
1788
|
kind: "core",
|
|
1626
|
-
description: "Send a HEAD request to get response headers without body",
|
|
1789
|
+
description: "Send a HEAD request to get response headers without body. Input: url (or uri), optional headers, timeoutMs.",
|
|
1627
1790
|
tags: ["http", "network", "core"],
|
|
1628
1791
|
capabilities: ["network"],
|
|
1629
1792
|
sideEffect: "none"
|
|
@@ -1631,7 +1794,7 @@ var CORE_TOOL_MANIFEST = [
|
|
|
1631
1794
|
{
|
|
1632
1795
|
name: "core/http.duckduckgoSearch",
|
|
1633
1796
|
kind: "core",
|
|
1634
|
-
description: "Search DuckDuckGo via Instant Answer API (no API key). Add api.duckduckgo.com to allowedHosts.",
|
|
1797
|
+
description: "Search DuckDuckGo via Instant Answer API (no API key). Add api.duckduckgo.com to allowedHosts. Input: use 'query' (or 'q') for the search string, optional 'maxResults'.",
|
|
1635
1798
|
tags: ["http", "search", "duckduckgo", "core"],
|
|
1636
1799
|
capabilities: ["network"],
|
|
1637
1800
|
sideEffect: "none"
|
|
@@ -1639,16 +1802,24 @@ var CORE_TOOL_MANIFEST = [
|
|
|
1639
1802
|
{
|
|
1640
1803
|
name: "core/http.fetchPageMainContent",
|
|
1641
1804
|
kind: "core",
|
|
1642
|
-
description: "Fetch a URL and return only the main content (main/article/body text). Strips nav, header, footer, scripts.",
|
|
1805
|
+
description: "Fetch a URL and return only the main content (main/article/body text). Strips nav, header, footer, scripts. Input: url (or uri), optional timeoutMs, maxBytes.",
|
|
1643
1806
|
tags: ["http", "network", "html", "main-content", "core"],
|
|
1644
1807
|
capabilities: ["network"],
|
|
1645
1808
|
sideEffect: "none"
|
|
1646
1809
|
},
|
|
1810
|
+
{
|
|
1811
|
+
name: "core/http.yahooFinanceQuote",
|
|
1812
|
+
kind: "core",
|
|
1813
|
+
description: "Fetch stock quote(s) from Yahoo Finance chart API (no API key). Add query1.finance.yahoo.com to allowedHosts. Input: symbols (or symbol, tickers), optional range, timeoutMs.",
|
|
1814
|
+
tags: ["http", "finance", "yahoo", "stock", "quote", "core"],
|
|
1815
|
+
capabilities: ["network"],
|
|
1816
|
+
sideEffect: "none"
|
|
1817
|
+
},
|
|
1647
1818
|
// Utils
|
|
1648
1819
|
{
|
|
1649
1820
|
name: "core/util.json.select",
|
|
1650
1821
|
kind: "core",
|
|
1651
|
-
description: "Select fields from JSON data using JMESPath expressions",
|
|
1822
|
+
description: "Select fields from JSON data using JMESPath expressions. Input: json, path (or expression).",
|
|
1652
1823
|
tags: ["util", "json", "core"],
|
|
1653
1824
|
capabilities: [],
|
|
1654
1825
|
sideEffect: "none"
|
|
@@ -1689,7 +1860,7 @@ var CORE_TOOL_MANIFEST = [
|
|
|
1689
1860
|
{
|
|
1690
1861
|
name: "core/exec.runCommand",
|
|
1691
1862
|
kind: "core",
|
|
1692
|
-
description: "Run a Linux command in the sandbox (allowlist, timeout, no shell).
|
|
1863
|
+
description: "Run a Linux command in the sandbox (allowlist, timeout, no shell). Input: command (or cmd), optional args (or arguments), cwd, timeoutMs.",
|
|
1693
1864
|
tags: ["exec", "shell", "linux", "core"],
|
|
1694
1865
|
capabilities: ["exec"],
|
|
1695
1866
|
sideEffect: "local_write"
|
|
@@ -1708,6 +1879,7 @@ var CORE_TOOL_HANDLERS = [
|
|
|
1708
1879
|
headHandler,
|
|
1709
1880
|
duckduckgoSearchHandler,
|
|
1710
1881
|
fetchPageMainContentHandler,
|
|
1882
|
+
yahooFinanceQuoteHandler,
|
|
1711
1883
|
jsonSelectHandler,
|
|
1712
1884
|
truncateHandler,
|
|
1713
1885
|
hashTextHandler,
|
|
@@ -1725,14 +1897,15 @@ var fetchTextSpec = createToolSpec(CORE_TOOL_MANIFEST[6]);
|
|
|
1725
1897
|
var fetchJsonSpec = createToolSpec(CORE_TOOL_MANIFEST[7]);
|
|
1726
1898
|
var downloadFileSpec = createToolSpec(CORE_TOOL_MANIFEST[8]);
|
|
1727
1899
|
var headSpec = createToolSpec(CORE_TOOL_MANIFEST[9]);
|
|
1728
|
-
var
|
|
1729
|
-
var
|
|
1730
|
-
var
|
|
1731
|
-
var
|
|
1732
|
-
var
|
|
1733
|
-
var
|
|
1734
|
-
var
|
|
1735
|
-
var
|
|
1900
|
+
var duckduckgoSearchSpec = createToolSpec(CORE_TOOL_MANIFEST[10]);
|
|
1901
|
+
var fetchPageMainContentSpec = createToolSpec(CORE_TOOL_MANIFEST[11]);
|
|
1902
|
+
var yahooFinanceQuoteSpec = createToolSpec(CORE_TOOL_MANIFEST[12]);
|
|
1903
|
+
var jsonSelectSpec = createToolSpec(CORE_TOOL_MANIFEST[13]);
|
|
1904
|
+
var truncateSpec = createToolSpec(CORE_TOOL_MANIFEST[14]);
|
|
1905
|
+
var hashTextSpec = createToolSpec(CORE_TOOL_MANIFEST[15]);
|
|
1906
|
+
var nowSpec = createToolSpec(CORE_TOOL_MANIFEST[16]);
|
|
1907
|
+
var templateRenderSpec = createToolSpec(CORE_TOOL_MANIFEST[17]);
|
|
1908
|
+
var runCommandSpec = createToolSpec(CORE_TOOL_MANIFEST[18]);
|
|
1736
1909
|
var CORE_GROUP_PREFIX = {
|
|
1737
1910
|
fs: "core/fs.",
|
|
1738
1911
|
http: "core/http.",
|
|
@@ -1786,6 +1959,7 @@ export {
|
|
|
1786
1959
|
templateRenderSpec,
|
|
1787
1960
|
truncateSpec,
|
|
1788
1961
|
validateUrl,
|
|
1789
|
-
writeTextSpec
|
|
1962
|
+
writeTextSpec,
|
|
1963
|
+
yahooFinanceQuoteSpec
|
|
1790
1964
|
};
|
|
1791
1965
|
//# sourceMappingURL=index.js.map
|