@stackfactor/agent-utils 1.8.0 → 1.9.0
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 +15 -0
- package/dist/cjs/index.d.ts +2 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/tavily.d.ts +31 -0
- package/dist/cjs/tavily.d.ts.map +1 -1
- package/dist/cjs/tavily.js +88 -1
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/tavily.d.ts +31 -0
- package/dist/esm/tavily.d.ts.map +1 -1
- package/dist/esm/tavily.js +86 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -419,6 +419,21 @@ A model that cannot tell it received half a regulation will reason over the half
|
|
|
419
419
|
- Per-URL failures are surfaced in the tool result instead of being dropped, so a fetch failure is not mistaken for an absence of content.
|
|
420
420
|
- Tool calls honour the caller's abort signal, so a cancelled run stops paying for in-flight crawls.
|
|
421
421
|
|
|
422
|
+
### Checking that cited links resolve
|
|
423
|
+
|
|
424
|
+
`checkUrlsReachable(urls, config, usageTracker?)` returns the URLs, exactly as passed, that Tavily could fetch. Use it in place of requesting a link yourself. Cited links come from web pages anyone can publish, so a link, its redirects or its DNS can point inside StackFactor's network; a request this process sends would go there through StackFactor's own egress addresses. Tavily fetches from its own infrastructure.
|
|
425
|
+
|
|
426
|
+
```js
|
|
427
|
+
const { checkUrlsReachable } = require("@stackfactor/agent-utils");
|
|
428
|
+
|
|
429
|
+
const live = await checkUrlsReachable(references.map((r) => r.url), config, usageTracker);
|
|
430
|
+
const kept = references.filter((r) => !r.url || live.has(r.url));
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
- Only `http:` and `https:` URLs are sent, 20 per call (Tavily's limit), at basic depth: 1 credit per 5 URLs fetched, failed ones free. Credits are billed like any Tavily call; the URLs are not added to `webSearchSources`.
|
|
434
|
+
- A URL Tavily lists under `failed_results` is unreachable. A batch whose call fails, or a config without `tavilyAPIKey`, confirms none of its URLs. It never throws.
|
|
435
|
+
- No `config.tavily` or `agentic` is needed: it calls Tavily directly, not through the model.
|
|
436
|
+
|
|
422
437
|
---
|
|
423
438
|
|
|
424
439
|
## Supported Models
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -7,11 +7,13 @@ import { callAgent, checkAgent } from "./client.js";
|
|
|
7
7
|
import * as runtimeContext from "./runtimeContext.js";
|
|
8
8
|
import { recordUsage, USAGE_UNITS } from "./usage.js";
|
|
9
9
|
import stackfactorKnowledge from "./stackfactorKnowledge.js";
|
|
10
|
+
import { checkUrlsReachable } from "./tavily.js";
|
|
10
11
|
export { constants };
|
|
11
12
|
export { errorHandling, AppError };
|
|
12
13
|
export type { ParsedError } from "./errorHandling.js";
|
|
13
14
|
export { langChain };
|
|
14
15
|
export type { UsageTracker } from "./langChain.js";
|
|
16
|
+
export { checkUrlsReachable };
|
|
15
17
|
export type { TavilyConfig, TavilyToolName } from "./tavily.js";
|
|
16
18
|
export { logger };
|
|
17
19
|
export { serve, runOnce, isRunOnceExecution, EXECUTION_ENV };
|
package/dist/cjs/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,aAAa,EAAE,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,SAAS,MAAM,gBAAgB,CAAC;AACvC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,oBAAoB,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,aAAa,EAAE,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,SAAS,MAAM,gBAAgB,CAAC;AACvC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,oBAAoB,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EAAE,SAAS,EAAE,CAAC;AAErB,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC;AAEnC,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,SAAS,EAAE,CAAC;AAErB,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAE9B,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,EAAE,MAAM,EAAE,CAAC;AAElB,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,CAAC;AAE7D,OAAO,EAAE,SAAS,EAAE,CAAC;AAErB,OAAO,EAAE,UAAU,EAAE,CAAC;AAEtB,YAAY,EACV,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,WAAW,GACZ,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC;AAEpC,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAExD,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAEhC,YAAY,EACV,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,eAAe,EACf,aAAa,EACb,oBAAoB,GACrB,MAAM,2BAA2B,CAAC"}
|
package/dist/cjs/index.js
CHANGED
|
@@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.stackfactorKnowledge = exports.USAGE_UNITS = exports.recordUsage = exports.runtimeContext = exports.checkAgent = exports.callAgent = exports.EXECUTION_ENV = exports.isRunOnceExecution = exports.runOnce = exports.serve = exports.logger = exports.langChain = exports.AppError = exports.errorHandling = exports.constants = void 0;
|
|
39
|
+
exports.stackfactorKnowledge = exports.USAGE_UNITS = exports.recordUsage = exports.runtimeContext = exports.checkAgent = exports.callAgent = exports.EXECUTION_ENV = exports.isRunOnceExecution = exports.runOnce = exports.serve = exports.logger = exports.checkUrlsReachable = exports.langChain = exports.AppError = exports.errorHandling = exports.constants = void 0;
|
|
40
40
|
const const_js_1 = __importDefault(require("./const.js"));
|
|
41
41
|
exports.constants = const_js_1.default;
|
|
42
42
|
const errorHandling_js_1 = __importStar(require("./errorHandling.js"));
|
|
@@ -61,3 +61,5 @@ Object.defineProperty(exports, "recordUsage", { enumerable: true, get: function
|
|
|
61
61
|
Object.defineProperty(exports, "USAGE_UNITS", { enumerable: true, get: function () { return usage_js_1.USAGE_UNITS; } });
|
|
62
62
|
const stackfactorKnowledge_js_1 = __importDefault(require("./stackfactorKnowledge.js"));
|
|
63
63
|
exports.stackfactorKnowledge = stackfactorKnowledge_js_1.default;
|
|
64
|
+
const tavily_js_1 = require("./tavily.js");
|
|
65
|
+
Object.defineProperty(exports, "checkUrlsReachable", { enumerable: true, get: function () { return tavily_js_1.checkUrlsReachable; } });
|
package/dist/cjs/tavily.d.ts
CHANGED
|
@@ -82,9 +82,40 @@ export declare const assertTavilyUsable: (config: any, options: TavilyConfig) =>
|
|
|
82
82
|
* @returns LangChain tool instances to append to the agent's tool list
|
|
83
83
|
*/
|
|
84
84
|
export declare const buildTavilyTools: (config: any, options: TavilyConfig, usageTracker?: UsageTracker | null) => any[];
|
|
85
|
+
/**
|
|
86
|
+
* Which of these URLs resolve, judged by Tavily fetching them rather than by
|
|
87
|
+
* this process connecting to them.
|
|
88
|
+
*
|
|
89
|
+
* An agent that confirms a cited link by requesting it itself sends that
|
|
90
|
+
* request from inside StackFactor's network, through its fixed egress
|
|
91
|
+
* addresses, to wherever the link, a redirect or its DNS points — and cited
|
|
92
|
+
* links come from web pages anyone can publish, so that is a request to an
|
|
93
|
+
* address an outsider chose (server-side request forgery). Tavily fetches from
|
|
94
|
+
* its own infrastructure, so nothing here ever connects to such a host.
|
|
95
|
+
*
|
|
96
|
+
* Only `http:` and `https:` URLs are sent; any other is unreachable by
|
|
97
|
+
* definition. They go in batches of 20, Tavily's limit, at basic depth: 1
|
|
98
|
+
* credit per 5 URLs Tavily fetched, failed ones free. The credits are billed
|
|
99
|
+
* like every other Tavily call, but the URLs are not added to the tracker's
|
|
100
|
+
* sources: a link worth checking was found there in the first place.
|
|
101
|
+
*
|
|
102
|
+
* Tavily accounts for every URL it is given, listing the ones it could not
|
|
103
|
+
* fetch under `failed_results`. So a URL listed there is unreachable, and every
|
|
104
|
+
* other URL of a batch Tavily answered is reachable (the results may name a
|
|
105
|
+
* URL by its address after a redirect, which is why they are not matched). A
|
|
106
|
+
* batch whose call fails outright, or a config without `tavilyAPIKey`,
|
|
107
|
+
* confirms none of its URLs: a link that could not be checked is not trusted.
|
|
108
|
+
*
|
|
109
|
+
* @param urls - The URLs to check; a URL given twice is checked once
|
|
110
|
+
* @param config - The integration config; supplies `tavilyAPIKey`
|
|
111
|
+
* @param usageTracker - Optional accumulator the credits are counted into
|
|
112
|
+
* @returns The given URLs, exactly as passed, that resolve
|
|
113
|
+
*/
|
|
114
|
+
export declare const checkUrlsReachable: (urls: readonly string[], config: any, usageTracker?: UsageTracker | null) => Promise<Set<string>>;
|
|
85
115
|
declare const _default: {
|
|
86
116
|
assertTavilyUsable: (config: any, options: TavilyConfig) => void;
|
|
87
117
|
buildTavilyTools: (config: any, options: TavilyConfig, usageTracker?: UsageTracker | null) => any[];
|
|
118
|
+
checkUrlsReachable: (urls: readonly string[], config: any, usageTracker?: UsageTracker | null) => Promise<Set<string>>;
|
|
88
119
|
getTavilyOptions: (config: any) => TavilyConfig | null;
|
|
89
120
|
recordTavilyUsage: (tracker: UsageTracker | null | undefined, _config: any, credits: number, sources: {
|
|
90
121
|
url: string;
|
package/dist/cjs/tavily.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tavily.d.ts","sourceRoot":"","sources":["../../src/tavily.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AA0BnD,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,KAAK,CAAC;AAEpE;;;;;;;;;GASG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IACzB,iEAAiE;IACjE,WAAW,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,YAAY,CAAC;IAC3D,kFAAkF;IAClF,YAAY,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IACpC,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oEAAoE;IACpE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4CAA4C;IAC5C,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,6CAA6C;IAC7C,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;CAC9B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,GAAI,QAAQ,GAAG,KAAG,YAAY,GAAG,IAI7D,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,GAAI,QAAQ,GAAG,EAAE,SAAS,YAAY,KAAG,IAsBvE,CAAC;AAsLF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,GAAG,EACX,SAAS,YAAY,EACrB,eAAc,YAAY,GAAG,IAAW,KACvC,GAAG,EA2PL,CAAC;;
|
|
1
|
+
{"version":3,"file":"tavily.d.ts","sourceRoot":"","sources":["../../src/tavily.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AA0BnD,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,KAAK,CAAC;AAEpE;;;;;;;;;GASG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IACzB,iEAAiE;IACjE,WAAW,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,YAAY,CAAC;IAC3D,kFAAkF;IAClF,YAAY,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IACpC,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oEAAoE;IACpE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4CAA4C;IAC5C,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,6CAA6C;IAC7C,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;CAC9B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,GAAI,QAAQ,GAAG,KAAG,YAAY,GAAG,IAI7D,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,GAAI,QAAQ,GAAG,EAAE,SAAS,YAAY,KAAG,IAsBvE,CAAC;AAsLF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,GAAG,EACX,SAAS,YAAY,EACrB,eAAc,YAAY,GAAG,IAAW,KACvC,GAAG,EA2PL,CAAC;AAqBF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,kBAAkB,GAC7B,MAAM,SAAS,MAAM,EAAE,EACvB,QAAQ,GAAG,EACX,eAAc,YAAY,GAAG,IAAW,KACvC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CA6DrB,CAAC;;iCA/kByC,GAAG,WAAW,YAAY,KAAG,IAAI;+BA8NlE,GAAG,WACF,YAAY,iBACP,YAAY,GAAG,IAAI,KAChC,GAAG,EAAE;+BA8SA,SAAS,MAAM,EAAE,UACf,GAAG,iBACG,YAAY,GAAG,IAAI,KAChC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;+BAjiBkB,GAAG,KAAG,YAAY,GAAG,IAAI;iCAsIvD,YAAY,GAAG,IAAI,GAAG,SAAS,WAC/B,GAAG,WACH,MAAM,WACN;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,KACzC,IAAI;;AAsdP,wBAME"}
|
package/dist/cjs/tavily.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.buildTavilyTools = exports.assertTavilyUsable = exports.getTavilyOptions = void 0;
|
|
6
|
+
exports.checkUrlsReachable = exports.buildTavilyTools = exports.assertTavilyUsable = exports.getTavilyOptions = void 0;
|
|
7
7
|
const langchain_1 = require("langchain");
|
|
8
8
|
const zod_1 = require("zod");
|
|
9
9
|
const const_js_1 = __importDefault(require("./const.js"));
|
|
@@ -395,9 +395,96 @@ const buildTavilyTools = (config, options, usageTracker = null) => {
|
|
|
395
395
|
return tools;
|
|
396
396
|
};
|
|
397
397
|
exports.buildTavilyTools = buildTavilyTools;
|
|
398
|
+
/** Tavily's own limit on URLs per `/extract` request. */
|
|
399
|
+
const EXTRACT_MAX_URLS = 20;
|
|
400
|
+
/** Seconds. A reachability check needs the page fetched, not rendered at length. */
|
|
401
|
+
const REACHABILITY_TIMEOUT_SECONDS = 20;
|
|
402
|
+
/** How a URL is matched against Tavily's answer: trimmed, lowercased, no trailing slash. */
|
|
403
|
+
const urlMatchKey = (url) => url.trim().replace(/\/+$/, "").toLowerCase();
|
|
404
|
+
/** True for an `http:` or `https:` URL; false for anything else, unparsable included. */
|
|
405
|
+
const isWebUrl = (url) => {
|
|
406
|
+
try {
|
|
407
|
+
const { protocol } = new URL(url);
|
|
408
|
+
return protocol === "http:" || protocol === "https:";
|
|
409
|
+
}
|
|
410
|
+
catch {
|
|
411
|
+
return false;
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
/**
|
|
415
|
+
* Which of these URLs resolve, judged by Tavily fetching them rather than by
|
|
416
|
+
* this process connecting to them.
|
|
417
|
+
*
|
|
418
|
+
* An agent that confirms a cited link by requesting it itself sends that
|
|
419
|
+
* request from inside StackFactor's network, through its fixed egress
|
|
420
|
+
* addresses, to wherever the link, a redirect or its DNS points — and cited
|
|
421
|
+
* links come from web pages anyone can publish, so that is a request to an
|
|
422
|
+
* address an outsider chose (server-side request forgery). Tavily fetches from
|
|
423
|
+
* its own infrastructure, so nothing here ever connects to such a host.
|
|
424
|
+
*
|
|
425
|
+
* Only `http:` and `https:` URLs are sent; any other is unreachable by
|
|
426
|
+
* definition. They go in batches of 20, Tavily's limit, at basic depth: 1
|
|
427
|
+
* credit per 5 URLs Tavily fetched, failed ones free. The credits are billed
|
|
428
|
+
* like every other Tavily call, but the URLs are not added to the tracker's
|
|
429
|
+
* sources: a link worth checking was found there in the first place.
|
|
430
|
+
*
|
|
431
|
+
* Tavily accounts for every URL it is given, listing the ones it could not
|
|
432
|
+
* fetch under `failed_results`. So a URL listed there is unreachable, and every
|
|
433
|
+
* other URL of a batch Tavily answered is reachable (the results may name a
|
|
434
|
+
* URL by its address after a redirect, which is why they are not matched). A
|
|
435
|
+
* batch whose call fails outright, or a config without `tavilyAPIKey`,
|
|
436
|
+
* confirms none of its URLs: a link that could not be checked is not trusted.
|
|
437
|
+
*
|
|
438
|
+
* @param urls - The URLs to check; a URL given twice is checked once
|
|
439
|
+
* @param config - The integration config; supplies `tavilyAPIKey`
|
|
440
|
+
* @param usageTracker - Optional accumulator the credits are counted into
|
|
441
|
+
* @returns The given URLs, exactly as passed, that resolve
|
|
442
|
+
*/
|
|
443
|
+
const checkUrlsReachable = async (urls, config, usageTracker = null) => {
|
|
444
|
+
const reachable = new Set();
|
|
445
|
+
const candidates = [
|
|
446
|
+
...new Set(urls.filter((url) => typeof url === "string" && isWebUrl(url.trim()))),
|
|
447
|
+
];
|
|
448
|
+
if (candidates.length === 0)
|
|
449
|
+
return reachable;
|
|
450
|
+
const apiKey = config?.tavilyAPIKey;
|
|
451
|
+
if (!apiKey) {
|
|
452
|
+
logger_js_1.default.log(null, logger_js_1.default.levels.warn, `Tavily reachability: no tavilyAPIKey, so none of ${candidates.length} URL(s) is confirmed`);
|
|
453
|
+
return reachable;
|
|
454
|
+
}
|
|
455
|
+
const batches = [];
|
|
456
|
+
for (let start = 0; start < candidates.length; start += EXTRACT_MAX_URLS) {
|
|
457
|
+
batches.push(candidates.slice(start, start + EXTRACT_MAX_URLS));
|
|
458
|
+
}
|
|
459
|
+
await Promise.all(batches.map(async (batch) => {
|
|
460
|
+
let data;
|
|
461
|
+
try {
|
|
462
|
+
data = await callTavily("extract", {
|
|
463
|
+
urls: batch.map((url) => url.trim()),
|
|
464
|
+
extract_depth: "basic",
|
|
465
|
+
format: "text",
|
|
466
|
+
}, apiKey, REACHABILITY_TIMEOUT_SECONDS);
|
|
467
|
+
}
|
|
468
|
+
catch (err) {
|
|
469
|
+
logger_js_1.default.log(null, logger_js_1.default.levels.warn, `Tavily reachability: the check of ${batch.length} URL(s) failed (${err?.message || String(err)}), so none of them is confirmed`);
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
recordTavilyUsage(usageTracker, config, data?.usage?.credits || 0, []);
|
|
473
|
+
const failed = new Set((data?.failed_results || [])
|
|
474
|
+
.map((entry) => typeof entry?.url === "string" ? urlMatchKey(entry.url) : "")
|
|
475
|
+
.filter(Boolean));
|
|
476
|
+
for (const url of batch) {
|
|
477
|
+
if (!failed.has(urlMatchKey(url)))
|
|
478
|
+
reachable.add(url);
|
|
479
|
+
}
|
|
480
|
+
}));
|
|
481
|
+
return reachable;
|
|
482
|
+
};
|
|
483
|
+
exports.checkUrlsReachable = checkUrlsReachable;
|
|
398
484
|
exports.default = {
|
|
399
485
|
assertTavilyUsable: exports.assertTavilyUsable,
|
|
400
486
|
buildTavilyTools: exports.buildTavilyTools,
|
|
487
|
+
checkUrlsReachable: exports.checkUrlsReachable,
|
|
401
488
|
getTavilyOptions: exports.getTavilyOptions,
|
|
402
489
|
recordTavilyUsage,
|
|
403
490
|
};
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -7,11 +7,13 @@ import { callAgent, checkAgent } from "./client.js";
|
|
|
7
7
|
import * as runtimeContext from "./runtimeContext.js";
|
|
8
8
|
import { recordUsage, USAGE_UNITS } from "./usage.js";
|
|
9
9
|
import stackfactorKnowledge from "./stackfactorKnowledge.js";
|
|
10
|
+
import { checkUrlsReachable } from "./tavily.js";
|
|
10
11
|
export { constants };
|
|
11
12
|
export { errorHandling, AppError };
|
|
12
13
|
export type { ParsedError } from "./errorHandling.js";
|
|
13
14
|
export { langChain };
|
|
14
15
|
export type { UsageTracker } from "./langChain.js";
|
|
16
|
+
export { checkUrlsReachable };
|
|
15
17
|
export type { TavilyConfig, TavilyToolName } from "./tavily.js";
|
|
16
18
|
export { logger };
|
|
17
19
|
export { serve, runOnce, isRunOnceExecution, EXECUTION_ENV };
|
package/dist/esm/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,aAAa,EAAE,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,SAAS,MAAM,gBAAgB,CAAC;AACvC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,oBAAoB,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,aAAa,EAAE,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,SAAS,MAAM,gBAAgB,CAAC;AACvC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,oBAAoB,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EAAE,SAAS,EAAE,CAAC;AAErB,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC;AAEnC,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,SAAS,EAAE,CAAC;AAErB,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAE9B,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,EAAE,MAAM,EAAE,CAAC;AAElB,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,CAAC;AAE7D,OAAO,EAAE,SAAS,EAAE,CAAC;AAErB,OAAO,EAAE,UAAU,EAAE,CAAC;AAEtB,YAAY,EACV,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,WAAW,GACZ,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC;AAEpC,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAExD,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAEhC,YAAY,EACV,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,eAAe,EACf,aAAa,EACb,oBAAoB,GACrB,MAAM,2BAA2B,CAAC"}
|
package/dist/esm/index.js
CHANGED
|
@@ -7,9 +7,11 @@ import { callAgent, checkAgent } from "./client.js";
|
|
|
7
7
|
import * as runtimeContext from "./runtimeContext.js";
|
|
8
8
|
import { recordUsage, USAGE_UNITS } from "./usage.js";
|
|
9
9
|
import stackfactorKnowledge from "./stackfactorKnowledge.js";
|
|
10
|
+
import { checkUrlsReachable } from "./tavily.js";
|
|
10
11
|
export { constants };
|
|
11
12
|
export { errorHandling, AppError };
|
|
12
13
|
export { langChain };
|
|
14
|
+
export { checkUrlsReachable };
|
|
13
15
|
export { logger };
|
|
14
16
|
export { serve, runOnce, isRunOnceExecution, EXECUTION_ENV };
|
|
15
17
|
export { callAgent };
|
package/dist/esm/tavily.d.ts
CHANGED
|
@@ -82,9 +82,40 @@ export declare const assertTavilyUsable: (config: any, options: TavilyConfig) =>
|
|
|
82
82
|
* @returns LangChain tool instances to append to the agent's tool list
|
|
83
83
|
*/
|
|
84
84
|
export declare const buildTavilyTools: (config: any, options: TavilyConfig, usageTracker?: UsageTracker | null) => any[];
|
|
85
|
+
/**
|
|
86
|
+
* Which of these URLs resolve, judged by Tavily fetching them rather than by
|
|
87
|
+
* this process connecting to them.
|
|
88
|
+
*
|
|
89
|
+
* An agent that confirms a cited link by requesting it itself sends that
|
|
90
|
+
* request from inside StackFactor's network, through its fixed egress
|
|
91
|
+
* addresses, to wherever the link, a redirect or its DNS points — and cited
|
|
92
|
+
* links come from web pages anyone can publish, so that is a request to an
|
|
93
|
+
* address an outsider chose (server-side request forgery). Tavily fetches from
|
|
94
|
+
* its own infrastructure, so nothing here ever connects to such a host.
|
|
95
|
+
*
|
|
96
|
+
* Only `http:` and `https:` URLs are sent; any other is unreachable by
|
|
97
|
+
* definition. They go in batches of 20, Tavily's limit, at basic depth: 1
|
|
98
|
+
* credit per 5 URLs Tavily fetched, failed ones free. The credits are billed
|
|
99
|
+
* like every other Tavily call, but the URLs are not added to the tracker's
|
|
100
|
+
* sources: a link worth checking was found there in the first place.
|
|
101
|
+
*
|
|
102
|
+
* Tavily accounts for every URL it is given, listing the ones it could not
|
|
103
|
+
* fetch under `failed_results`. So a URL listed there is unreachable, and every
|
|
104
|
+
* other URL of a batch Tavily answered is reachable (the results may name a
|
|
105
|
+
* URL by its address after a redirect, which is why they are not matched). A
|
|
106
|
+
* batch whose call fails outright, or a config without `tavilyAPIKey`,
|
|
107
|
+
* confirms none of its URLs: a link that could not be checked is not trusted.
|
|
108
|
+
*
|
|
109
|
+
* @param urls - The URLs to check; a URL given twice is checked once
|
|
110
|
+
* @param config - The integration config; supplies `tavilyAPIKey`
|
|
111
|
+
* @param usageTracker - Optional accumulator the credits are counted into
|
|
112
|
+
* @returns The given URLs, exactly as passed, that resolve
|
|
113
|
+
*/
|
|
114
|
+
export declare const checkUrlsReachable: (urls: readonly string[], config: any, usageTracker?: UsageTracker | null) => Promise<Set<string>>;
|
|
85
115
|
declare const _default: {
|
|
86
116
|
assertTavilyUsable: (config: any, options: TavilyConfig) => void;
|
|
87
117
|
buildTavilyTools: (config: any, options: TavilyConfig, usageTracker?: UsageTracker | null) => any[];
|
|
118
|
+
checkUrlsReachable: (urls: readonly string[], config: any, usageTracker?: UsageTracker | null) => Promise<Set<string>>;
|
|
88
119
|
getTavilyOptions: (config: any) => TavilyConfig | null;
|
|
89
120
|
recordTavilyUsage: (tracker: UsageTracker | null | undefined, _config: any, credits: number, sources: {
|
|
90
121
|
url: string;
|
package/dist/esm/tavily.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tavily.d.ts","sourceRoot":"","sources":["../../src/tavily.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AA0BnD,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,KAAK,CAAC;AAEpE;;;;;;;;;GASG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IACzB,iEAAiE;IACjE,WAAW,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,YAAY,CAAC;IAC3D,kFAAkF;IAClF,YAAY,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IACpC,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oEAAoE;IACpE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4CAA4C;IAC5C,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,6CAA6C;IAC7C,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;CAC9B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,GAAI,QAAQ,GAAG,KAAG,YAAY,GAAG,IAI7D,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,GAAI,QAAQ,GAAG,EAAE,SAAS,YAAY,KAAG,IAsBvE,CAAC;AAsLF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,GAAG,EACX,SAAS,YAAY,EACrB,eAAc,YAAY,GAAG,IAAW,KACvC,GAAG,EA2PL,CAAC;;
|
|
1
|
+
{"version":3,"file":"tavily.d.ts","sourceRoot":"","sources":["../../src/tavily.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AA0BnD,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,KAAK,CAAC;AAEpE;;;;;;;;;GASG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IACzB,iEAAiE;IACjE,WAAW,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,YAAY,CAAC;IAC3D,kFAAkF;IAClF,YAAY,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IACpC,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oEAAoE;IACpE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4CAA4C;IAC5C,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,6CAA6C;IAC7C,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;CAC9B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,GAAI,QAAQ,GAAG,KAAG,YAAY,GAAG,IAI7D,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,GAAI,QAAQ,GAAG,EAAE,SAAS,YAAY,KAAG,IAsBvE,CAAC;AAsLF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,GAAG,EACX,SAAS,YAAY,EACrB,eAAc,YAAY,GAAG,IAAW,KACvC,GAAG,EA2PL,CAAC;AAqBF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,kBAAkB,GAC7B,MAAM,SAAS,MAAM,EAAE,EACvB,QAAQ,GAAG,EACX,eAAc,YAAY,GAAG,IAAW,KACvC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CA6DrB,CAAC;;iCA/kByC,GAAG,WAAW,YAAY,KAAG,IAAI;+BA8NlE,GAAG,WACF,YAAY,iBACP,YAAY,GAAG,IAAI,KAChC,GAAG,EAAE;+BA8SA,SAAS,MAAM,EAAE,UACf,GAAG,iBACG,YAAY,GAAG,IAAI,KAChC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;+BAjiBkB,GAAG,KAAG,YAAY,GAAG,IAAI;iCAsIvD,YAAY,GAAG,IAAI,GAAG,SAAS,WAC/B,GAAG,WACH,MAAM,WACN;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,KACzC,IAAI;;AAsdP,wBAME"}
|
package/dist/esm/tavily.js
CHANGED
|
@@ -386,9 +386,95 @@ export const buildTavilyTools = (config, options, usageTracker = null) => {
|
|
|
386
386
|
logger.log(null, logger.levels.info, `Tavily tools enabled: ${tools.map((entry) => entry.name).join(", ")}`);
|
|
387
387
|
return tools;
|
|
388
388
|
};
|
|
389
|
+
/** Tavily's own limit on URLs per `/extract` request. */
|
|
390
|
+
const EXTRACT_MAX_URLS = 20;
|
|
391
|
+
/** Seconds. A reachability check needs the page fetched, not rendered at length. */
|
|
392
|
+
const REACHABILITY_TIMEOUT_SECONDS = 20;
|
|
393
|
+
/** How a URL is matched against Tavily's answer: trimmed, lowercased, no trailing slash. */
|
|
394
|
+
const urlMatchKey = (url) => url.trim().replace(/\/+$/, "").toLowerCase();
|
|
395
|
+
/** True for an `http:` or `https:` URL; false for anything else, unparsable included. */
|
|
396
|
+
const isWebUrl = (url) => {
|
|
397
|
+
try {
|
|
398
|
+
const { protocol } = new URL(url);
|
|
399
|
+
return protocol === "http:" || protocol === "https:";
|
|
400
|
+
}
|
|
401
|
+
catch {
|
|
402
|
+
return false;
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
/**
|
|
406
|
+
* Which of these URLs resolve, judged by Tavily fetching them rather than by
|
|
407
|
+
* this process connecting to them.
|
|
408
|
+
*
|
|
409
|
+
* An agent that confirms a cited link by requesting it itself sends that
|
|
410
|
+
* request from inside StackFactor's network, through its fixed egress
|
|
411
|
+
* addresses, to wherever the link, a redirect or its DNS points — and cited
|
|
412
|
+
* links come from web pages anyone can publish, so that is a request to an
|
|
413
|
+
* address an outsider chose (server-side request forgery). Tavily fetches from
|
|
414
|
+
* its own infrastructure, so nothing here ever connects to such a host.
|
|
415
|
+
*
|
|
416
|
+
* Only `http:` and `https:` URLs are sent; any other is unreachable by
|
|
417
|
+
* definition. They go in batches of 20, Tavily's limit, at basic depth: 1
|
|
418
|
+
* credit per 5 URLs Tavily fetched, failed ones free. The credits are billed
|
|
419
|
+
* like every other Tavily call, but the URLs are not added to the tracker's
|
|
420
|
+
* sources: a link worth checking was found there in the first place.
|
|
421
|
+
*
|
|
422
|
+
* Tavily accounts for every URL it is given, listing the ones it could not
|
|
423
|
+
* fetch under `failed_results`. So a URL listed there is unreachable, and every
|
|
424
|
+
* other URL of a batch Tavily answered is reachable (the results may name a
|
|
425
|
+
* URL by its address after a redirect, which is why they are not matched). A
|
|
426
|
+
* batch whose call fails outright, or a config without `tavilyAPIKey`,
|
|
427
|
+
* confirms none of its URLs: a link that could not be checked is not trusted.
|
|
428
|
+
*
|
|
429
|
+
* @param urls - The URLs to check; a URL given twice is checked once
|
|
430
|
+
* @param config - The integration config; supplies `tavilyAPIKey`
|
|
431
|
+
* @param usageTracker - Optional accumulator the credits are counted into
|
|
432
|
+
* @returns The given URLs, exactly as passed, that resolve
|
|
433
|
+
*/
|
|
434
|
+
export const checkUrlsReachable = async (urls, config, usageTracker = null) => {
|
|
435
|
+
const reachable = new Set();
|
|
436
|
+
const candidates = [
|
|
437
|
+
...new Set(urls.filter((url) => typeof url === "string" && isWebUrl(url.trim()))),
|
|
438
|
+
];
|
|
439
|
+
if (candidates.length === 0)
|
|
440
|
+
return reachable;
|
|
441
|
+
const apiKey = config?.tavilyAPIKey;
|
|
442
|
+
if (!apiKey) {
|
|
443
|
+
logger.log(null, logger.levels.warn, `Tavily reachability: no tavilyAPIKey, so none of ${candidates.length} URL(s) is confirmed`);
|
|
444
|
+
return reachable;
|
|
445
|
+
}
|
|
446
|
+
const batches = [];
|
|
447
|
+
for (let start = 0; start < candidates.length; start += EXTRACT_MAX_URLS) {
|
|
448
|
+
batches.push(candidates.slice(start, start + EXTRACT_MAX_URLS));
|
|
449
|
+
}
|
|
450
|
+
await Promise.all(batches.map(async (batch) => {
|
|
451
|
+
let data;
|
|
452
|
+
try {
|
|
453
|
+
data = await callTavily("extract", {
|
|
454
|
+
urls: batch.map((url) => url.trim()),
|
|
455
|
+
extract_depth: "basic",
|
|
456
|
+
format: "text",
|
|
457
|
+
}, apiKey, REACHABILITY_TIMEOUT_SECONDS);
|
|
458
|
+
}
|
|
459
|
+
catch (err) {
|
|
460
|
+
logger.log(null, logger.levels.warn, `Tavily reachability: the check of ${batch.length} URL(s) failed (${err?.message || String(err)}), so none of them is confirmed`);
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
recordTavilyUsage(usageTracker, config, data?.usage?.credits || 0, []);
|
|
464
|
+
const failed = new Set((data?.failed_results || [])
|
|
465
|
+
.map((entry) => typeof entry?.url === "string" ? urlMatchKey(entry.url) : "")
|
|
466
|
+
.filter(Boolean));
|
|
467
|
+
for (const url of batch) {
|
|
468
|
+
if (!failed.has(urlMatchKey(url)))
|
|
469
|
+
reachable.add(url);
|
|
470
|
+
}
|
|
471
|
+
}));
|
|
472
|
+
return reachable;
|
|
473
|
+
};
|
|
389
474
|
export default {
|
|
390
475
|
assertTavilyUsable,
|
|
391
476
|
buildTavilyTools,
|
|
477
|
+
checkUrlsReachable,
|
|
392
478
|
getTavilyOptions,
|
|
393
479
|
recordTavilyUsage,
|
|
394
480
|
};
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.
|
|
6
|
+
"version": "1.9.0",
|
|
7
7
|
"description": "",
|
|
8
8
|
"main": "dist/cjs/index.js",
|
|
9
9
|
"module": "dist/esm/index.js",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"work:release": "bash scripts/release.sh",
|
|
21
21
|
"release": "bash scripts/release.sh",
|
|
22
22
|
"release:fanout": "bash scripts/release-fanout.sh",
|
|
23
|
-
"ar-auth": "npm config set @stackfactor:registry https://us-central1-npm.pkg.dev/virtual-development-team/sf-devenv-npm-private/; TOKEN=$(gcloud auth print-access-token 2>/dev/null || curl -sfH 'Metadata-Flavor: Google' http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token | sed -n 's/.*\"access_token\":\"\\([^\"]*\\)\".*/\\1/p'); test -n \"$TOKEN\" || { echo 'ar-auth: no credential
|
|
23
|
+
"ar-auth": "npm config set @stackfactor:registry https://us-central1-npm.pkg.dev/virtual-development-team/sf-devenv-npm-private/; TOKEN=$(gcloud auth print-access-token 2>/dev/null || curl -sfH 'Metadata-Flavor: Google' http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token | sed -n 's/.*\"access_token\":\"\\([^\"]*\\)\".*/\\1/p'); test -n \"$TOKEN\" || { echo 'ar-auth: no credential — run: gcloud auth login' >&2; exit 1; }; npm config set //us-central1-npm.pkg.dev/virtual-development-team/sf-devenv-npm-private/:_authToken \"$TOKEN\"; npm config set //us-central1-npm.pkg.dev/virtual-development-team/:_authToken \"$TOKEN\"; echo 'ar-auth: Artifact Registry scope + token configured'",
|
|
24
24
|
"reinstall": "npm run ar-auth && npm ci",
|
|
25
25
|
"test:coverage": "npm run build && node --experimental-test-coverage --test --test-reporter=tap test/*.test.js"
|
|
26
26
|
},
|