@nodetool-ai/runtime 0.8.8 → 0.8.9-beta.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/.nodetool-build-stamp +1 -1
- package/dist/context.d.ts +6 -2
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +13 -24
- package/dist/context.js.map +1 -1
- package/dist/host-binaries.d.ts +5 -5
- package/dist/host-binaries.js +5 -5
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/invocation-account.d.ts +1 -42
- package/dist/invocation-account.d.ts.map +1 -1
- package/dist/invocation-account.js +1 -59
- package/dist/invocation-account.js.map +1 -1
- package/dist/media/abort.d.ts +8 -0
- package/dist/media/abort.d.ts.map +1 -0
- package/dist/media/abort.js +18 -0
- package/dist/media/abort.js.map +1 -0
- package/dist/media/audio-encoder.d.ts +37 -0
- package/dist/media/audio-encoder.d.ts.map +1 -0
- package/dist/media/audio-encoder.js +118 -0
- package/dist/media/audio-encoder.js.map +1 -0
- package/dist/media/audio.d.ts +36 -0
- package/dist/media/audio.d.ts.map +1 -0
- package/dist/media/audio.js +84 -0
- package/dist/media/audio.js.map +1 -0
- package/dist/media/av.d.ts +51 -0
- package/dist/media/av.d.ts.map +1 -0
- package/dist/media/av.js +146 -0
- package/dist/media/av.js.map +1 -0
- package/dist/media/codecs.d.ts +9 -0
- package/dist/media/codecs.d.ts.map +1 -0
- package/dist/media/codecs.js +17 -0
- package/dist/media/codecs.js.map +1 -0
- package/dist/media/concat.d.ts +56 -0
- package/dist/media/concat.d.ts.map +1 -0
- package/dist/media/concat.js +319 -0
- package/dist/media/concat.js.map +1 -0
- package/dist/media/convert.d.ts +31 -0
- package/dist/media/convert.d.ts.map +1 -0
- package/dist/media/convert.js +114 -0
- package/dist/media/convert.js.map +1 -0
- package/dist/media/decode.d.ts +31 -0
- package/dist/media/decode.d.ts.map +1 -0
- package/dist/media/decode.js +85 -0
- package/dist/media/decode.js.map +1 -0
- package/dist/media/filter-graph.d.ts +53 -0
- package/dist/media/filter-graph.d.ts.map +1 -0
- package/dist/media/filter-graph.js +260 -0
- package/dist/media/filter-graph.js.map +1 -0
- package/dist/media/frames.d.ts +31 -0
- package/dist/media/frames.d.ts.map +1 -0
- package/dist/media/frames.js +112 -0
- package/dist/media/frames.js.map +1 -0
- package/dist/media/index.d.ts +26 -0
- package/dist/media/index.d.ts.map +1 -0
- package/dist/media/index.js +26 -0
- package/dist/media/index.js.map +1 -0
- package/dist/media/mux.d.ts +58 -0
- package/dist/media/mux.d.ts.map +1 -0
- package/dist/media/mux.js +234 -0
- package/dist/media/mux.js.map +1 -0
- package/dist/media/probe.d.ts +84 -0
- package/dist/media/probe.d.ts.map +1 -0
- package/dist/media/probe.js +133 -0
- package/dist/media/probe.js.map +1 -0
- package/dist/media/rgba.d.ts +78 -0
- package/dist/media/rgba.d.ts.map +1 -0
- package/dist/media/rgba.js +285 -0
- package/dist/media/rgba.js.map +1 -0
- package/dist/media/testing.d.ts +119 -0
- package/dist/media/testing.d.ts.map +1 -0
- package/dist/media/testing.js +343 -0
- package/dist/media/testing.js.map +1 -0
- package/dist/media/transcode.d.ts +17 -0
- package/dist/media/transcode.d.ts.map +1 -0
- package/dist/media/transcode.js +19 -0
- package/dist/media/transcode.js.map +1 -0
- package/dist/media/transform.d.ts +61 -0
- package/dist/media/transform.d.ts.map +1 -0
- package/dist/media/transform.js +371 -0
- package/dist/media/transform.js.map +1 -0
- package/dist/media/verify.d.ts +17 -0
- package/dist/media/verify.d.ts.map +1 -0
- package/dist/media/verify.js +65 -0
- package/dist/media/verify.js.map +1 -0
- package/dist/media-loader.d.ts +8 -0
- package/dist/media-loader.d.ts.map +1 -0
- package/dist/media-loader.js +10 -0
- package/dist/media-loader.js.map +1 -0
- package/dist/prefixed-storage-adapter.d.ts.map +1 -1
- package/dist/prefixed-storage-adapter.js +1 -1
- package/dist/prefixed-storage-adapter.js.map +1 -1
- package/dist/providers/anthropic-provider.d.ts.map +1 -1
- package/dist/providers/anthropic-provider.js +1 -17
- package/dist/providers/anthropic-provider.js.map +1 -1
- package/dist/providers/data-uri.d.ts +6 -0
- package/dist/providers/data-uri.d.ts.map +1 -0
- package/dist/providers/data-uri.js +19 -0
- package/dist/providers/data-uri.js.map +1 -0
- package/dist/providers/fake-provider.js +1 -1
- package/dist/providers/meta-transcription.d.ts +1 -5
- package/dist/providers/meta-transcription.d.ts.map +1 -1
- package/dist/providers/meta-transcription.js +9 -55
- package/dist/providers/meta-transcription.js.map +1 -1
- package/dist/providers/node-llama-cpp-trending.generated.js +132 -132
- package/dist/providers/node-llama-cpp-trending.generated.js.map +1 -1
- package/dist/providers/ollama-provider.d.ts.map +1 -1
- package/dist/providers/ollama-provider.js +1 -17
- package/dist/providers/ollama-provider.js.map +1 -1
- package/dist/providers/openai-provider.js +2 -2
- package/dist/providers/openai-provider.js.map +1 -1
- package/dist/providers/openrouter-provider.d.ts.map +1 -1
- package/dist/providers/openrouter-provider.js +1 -0
- package/dist/providers/openrouter-provider.js.map +1 -1
- package/dist/providers/safe-url.d.ts +1 -69
- package/dist/providers/safe-url.d.ts.map +1 -1
- package/dist/providers/safe-url.js +1 -284
- package/dist/providers/safe-url.js.map +1 -1
- package/dist/providers/topaz-provider.d.ts +1 -1
- package/dist/providers/topaz-provider.js +1 -1
- package/dist/providers/video-frame-fallback.d.ts +1 -1
- package/dist/providers/video-frame-fallback.js +4 -4
- package/dist/providers/video-frame-fallback.js.map +1 -1
- package/dist/providers/video-frames.d.ts +6 -16
- package/dist/providers/video-frames.d.ts.map +1 -1
- package/dist/providers/video-frames.js +48 -116
- package/dist/providers/video-frames.js.map +1 -1
- package/dist/storage-workspace.d.ts +1 -61
- package/dist/storage-workspace.d.ts.map +1 -1
- package/dist/storage-workspace.js +2 -430
- package/dist/storage-workspace.js.map +1 -1
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +57 -1
- package/dist/testing.js.map +1 -1
- package/dist/trim-video-window.d.ts.map +1 -1
- package/dist/trim-video-window.js +2 -32
- package/dist/trim-video-window.js.map +1 -1
- package/dist/workspace.d.ts +1 -118
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +1 -111
- package/dist/workspace.js.map +1 -1
- package/dist/yt-dlp-format.d.ts +22 -0
- package/dist/yt-dlp-format.d.ts.map +1 -0
- package/dist/yt-dlp-format.js +90 -0
- package/dist/yt-dlp-format.js.map +1 -0
- package/package.json +23 -6
|
@@ -1,285 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
* SSRF guard for outbound fetches of caller-supplied URLs, and the one address
|
|
3
|
-
* table every screening surface in the repo reads.
|
|
4
|
-
*
|
|
5
|
-
* Image/video providers (FAL, Replicate, …) return result URLs that the server
|
|
6
|
-
* then `fetch`es to download the generated bytes. Those URLs originate from the
|
|
7
|
-
* provider's response, so without validation a compromised or misbehaving
|
|
8
|
-
* provider — or a response coerced via a crafted prompt — could point the
|
|
9
|
-
* server at internal services (`http://169.254.169.254/...`,
|
|
10
|
-
* `http://localhost:6379/...`, RFC1918 hosts, …). The same is true of a media
|
|
11
|
-
* ref a workflow carries and of a URL a model hands a tool.
|
|
12
|
-
*
|
|
13
|
-
* Two things live here, and the split matters. {@link isBlockedIpLiteral} is
|
|
14
|
-
* the **address table** — which literals are internal — shared with the sandbox
|
|
15
|
-
* fetch bridge (`packages/agents/src/network-guard.ts`), which allows plain
|
|
16
|
-
* http and an opt-in private mode that this module never does.
|
|
17
|
-
* {@link isSafePublicHttpsUrl} is NodeTool's **default policy** on top of it:
|
|
18
|
-
* https only, to an apparently-public host. A predicate is not a protected
|
|
19
|
-
* fetch, though — only {@link safeFetch} validates every redirect hop, so an
|
|
20
|
-
* operation that actually goes out calls that.
|
|
21
|
-
*
|
|
22
|
-
* The check is conservative: unparseable URLs, non-https schemes, and literal
|
|
23
|
-
* IP addresses in loopback / link-local / RFC1918 / CGNAT / benchmarking ranges
|
|
24
|
-
* (including IPv4-mapped IPv6 literals and IPv4 embedded in 6to4 / NAT64
|
|
25
|
-
* transition addresses) are refused. Alternate IPv4 spellings — decimal, hex,
|
|
26
|
-
* octal, short form — are normalized by the WHATWG URL parser before the table
|
|
27
|
-
* sees them.
|
|
28
|
-
*
|
|
29
|
-
* **DNS rebinding is out of scope here, deliberately.** A public name that
|
|
30
|
-
* resolves to a private address passes: this process does not control which
|
|
31
|
-
* address `fetch` connects to, and pinning one would break TLS and virtual
|
|
32
|
-
* hosting. Two answers exist and the inventory records which each surface uses
|
|
33
|
-
* — `assertResolvedHostAllowed` (a resolve-and-check pass, for a URL handed to
|
|
34
|
-
* a separate process that opens its own sockets), and the deployment's egress
|
|
35
|
-
* control as the security boundary for everything in-process. See
|
|
36
|
-
* `docs/url-egress-inventory.md`.
|
|
37
|
-
*/
|
|
38
|
-
/**
|
|
39
|
-
* Expand an IPv6 literal (already stripped of brackets, lower-cased) into its 8
|
|
40
|
-
* 16-bit hextets, handling `::` compression and a trailing dotted-quad. Returns
|
|
41
|
-
* `null` if `host` is not a well-formed IPv6 literal.
|
|
42
|
-
*/
|
|
43
|
-
function expandIpv6(host) {
|
|
44
|
-
if (!host.includes(":"))
|
|
45
|
-
return null;
|
|
46
|
-
// Rewrite a trailing dotted-quad (`...:a.b.c.d`) into two hex hextets so the
|
|
47
|
-
// rest of the parse only deals with `:`-separated groups.
|
|
48
|
-
const body = host.replace(/((?:\d{1,3}\.){3}\d{1,3})$/, (m) => {
|
|
49
|
-
const oct = m.split(".").map((n) => parseInt(n, 10));
|
|
50
|
-
if (oct.some((n) => n > 255))
|
|
51
|
-
return "\0"; // sentinel → fails group parse
|
|
52
|
-
const hex = (n) => n.toString(16).padStart(2, "0");
|
|
53
|
-
return `${hex(oct[0])}${hex(oct[1])}:${hex(oct[2])}${hex(oct[3])}`;
|
|
54
|
-
});
|
|
55
|
-
const halves = body.split("::");
|
|
56
|
-
if (halves.length > 2)
|
|
57
|
-
return null;
|
|
58
|
-
const parseGroup = (s) => {
|
|
59
|
-
if (s === "")
|
|
60
|
-
return [];
|
|
61
|
-
const out = [];
|
|
62
|
-
for (const p of s.split(":")) {
|
|
63
|
-
if (!/^[0-9a-f]{1,4}$/.test(p))
|
|
64
|
-
return null;
|
|
65
|
-
out.push(parseInt(p, 16));
|
|
66
|
-
}
|
|
67
|
-
return out;
|
|
68
|
-
};
|
|
69
|
-
const head = parseGroup(halves[0]);
|
|
70
|
-
if (head === null)
|
|
71
|
-
return null;
|
|
72
|
-
let hextets;
|
|
73
|
-
if (halves.length === 2) {
|
|
74
|
-
const rest = parseGroup(halves[1]);
|
|
75
|
-
if (rest === null)
|
|
76
|
-
return null;
|
|
77
|
-
const middle = 8 - head.length - rest.length;
|
|
78
|
-
if (middle < 0)
|
|
79
|
-
return null;
|
|
80
|
-
hextets = [...head, ...new Array(middle).fill(0), ...rest];
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
hextets = head;
|
|
84
|
-
}
|
|
85
|
-
if (hextets.length !== 8)
|
|
86
|
-
return null;
|
|
87
|
-
return hextets;
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* True for IPv4 octet pairs in loopback / RFC1918 / link-local / CGNAT /
|
|
91
|
-
* benchmarking ranges.
|
|
92
|
-
*/
|
|
93
|
-
function isPrivateIpv4(a, b) {
|
|
94
|
-
// 0.0.0.0/8, 10.0.0.0/8, 127.0.0.0/8
|
|
95
|
-
if (a === 0 || a === 10 || a === 127)
|
|
96
|
-
return true;
|
|
97
|
-
// 169.254.0.0/16 (link-local, incl. the 169.254.169.254 metadata service)
|
|
98
|
-
if (a === 169 && b === 254)
|
|
99
|
-
return true;
|
|
100
|
-
// 172.16.0.0/12
|
|
101
|
-
if (a === 172 && b >= 16 && b <= 31)
|
|
102
|
-
return true;
|
|
103
|
-
// 192.168.0.0/16
|
|
104
|
-
if (a === 192 && b === 168)
|
|
105
|
-
return true;
|
|
106
|
-
// 100.64.0.0/10 (CGNAT)
|
|
107
|
-
if (a === 100 && b >= 64 && b <= 127)
|
|
108
|
-
return true;
|
|
109
|
-
// 198.18.0.0/15 (benchmarking)
|
|
110
|
-
if (a === 198 && (b === 18 || b === 19))
|
|
111
|
-
return true;
|
|
112
|
-
return false;
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* True when `host` is a literal IPv4/IPv6 address in a loopback, link-local,
|
|
116
|
-
* private, CGNAT or benchmarking range — including the IPv6 spellings that
|
|
117
|
-
* carry an IPv4 inside them (IPv4-mapped, IPv4-compatible, 6to4, NAT64).
|
|
118
|
-
*
|
|
119
|
-
* This is the address table, not a policy: it says nothing about schemes,
|
|
120
|
-
* hostnames or redirects, and a caller that allows private networks on purpose
|
|
121
|
-
* (the sandbox fetch bridge under `allowPrivateNetwork`) skips it rather than
|
|
122
|
-
* reimplementing it. A hostname that is not a literal is not this function's
|
|
123
|
-
* question — it answers `false`, and what the name *resolves* to is decided by
|
|
124
|
-
* the surface's DNS-rebinding policy (see the module comment).
|
|
125
|
-
*/
|
|
126
|
-
export function isBlockedIpLiteral(host) {
|
|
127
|
-
// Strip IPv6 brackets and any zone id (`fe80::1%eth0`), lower-case for the
|
|
128
|
-
// hex comparisons.
|
|
129
|
-
const h = host
|
|
130
|
-
.replace(/^\[|\]$/g, "")
|
|
131
|
-
.split("%")[0]
|
|
132
|
-
.toLowerCase();
|
|
133
|
-
// IPv4 in dotted form, standalone or as an IPv6 tail (`::ffff:127.0.0.1`).
|
|
134
|
-
const dotted = h.match(/(?:^|:)((?:\d{1,3}\.){3}\d{1,3})$/);
|
|
135
|
-
if (dotted) {
|
|
136
|
-
const [a, b] = dotted[1].split(".").map((n) => parseInt(n, 10));
|
|
137
|
-
return isPrivateIpv4(a, b);
|
|
138
|
-
}
|
|
139
|
-
if (!h.includes(":"))
|
|
140
|
-
return false;
|
|
141
|
-
if (h === "::" || h === "::1")
|
|
142
|
-
return true; // unspecified / loopback
|
|
143
|
-
if (h.startsWith("fc") || h.startsWith("fd"))
|
|
144
|
-
return true; // ULA fc00::/7
|
|
145
|
-
// link-local fe80::/10 — the first hextet spans fe80–febf, so the first three
|
|
146
|
-
// hex digits are fe8/fe9/fea/feb; "fe80" alone is too narrow.
|
|
147
|
-
if (/^fe[89ab]/.test(h))
|
|
148
|
-
return true;
|
|
149
|
-
// IPv4 embedded in a hex-serialized IPv6 literal. The WHATWG parser rewrites
|
|
150
|
-
// `::ffff:127.0.0.1` to `::ffff:7f00:1`, which the dotted regex above no
|
|
151
|
-
// longer matches, and the transition prefixes hide an IPv4 in the same way:
|
|
152
|
-
// IPv4-mapped/-compatible and NAT64 (64:ff9b::/96) in the low 32 bits, 6to4
|
|
153
|
-
// (2002:WWXX:YYZZ::/16) in the second and third hextets.
|
|
154
|
-
const hextets = expandIpv6(h);
|
|
155
|
-
if (!hextets)
|
|
156
|
-
return false;
|
|
157
|
-
const isZero = (from, to) => hextets.slice(from, to).every((n) => n === 0);
|
|
158
|
-
let embedded = null;
|
|
159
|
-
if (hextets[0] === 0x2002) {
|
|
160
|
-
embedded = hextets[1];
|
|
161
|
-
}
|
|
162
|
-
else if (isZero(0, 5) && hextets[5] === 0xffff) {
|
|
163
|
-
embedded = hextets[6]; // ::ffff:a.b.c.d
|
|
164
|
-
}
|
|
165
|
-
else if (isZero(0, 6)) {
|
|
166
|
-
embedded = hextets[6]; // ::a.b.c.d (IPv4-compatible, deprecated)
|
|
167
|
-
}
|
|
168
|
-
else if (hextets[0] === 0x64 && hextets[1] === 0xff9b && isZero(2, 6)) {
|
|
169
|
-
embedded = hextets[6]; // 64:ff9b::/96
|
|
170
|
-
}
|
|
171
|
-
if (embedded === null)
|
|
172
|
-
return false;
|
|
173
|
-
return isPrivateIpv4((embedded >> 8) & 0xff, embedded & 0xff);
|
|
174
|
-
}
|
|
175
|
-
/**
|
|
176
|
-
* Return `true` when `url` is an https URL whose host is not a loopback,
|
|
177
|
-
* link-local, or RFC1918 private address. NodeTool's default egress policy.
|
|
178
|
-
*/
|
|
179
|
-
export function isSafePublicHttpsUrl(url) {
|
|
180
|
-
let parsed;
|
|
181
|
-
try {
|
|
182
|
-
parsed = new URL(url);
|
|
183
|
-
}
|
|
184
|
-
catch {
|
|
185
|
-
return false;
|
|
186
|
-
}
|
|
187
|
-
if (parsed.protocol !== "https:") {
|
|
188
|
-
return false;
|
|
189
|
-
}
|
|
190
|
-
// Normalise: strip IPv6 brackets (WHATWG URL may include them depending on
|
|
191
|
-
// the runtime) and any trailing dot (`localhost.` resolves the same as
|
|
192
|
-
// `localhost` but would dodge the exact/suffix checks below). The dots are
|
|
193
|
-
// trimmed with a loop: `/\.+$/` backtracks quadratically on a long dot run.
|
|
194
|
-
const bare = parsed.hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
195
|
-
let end = bare.length;
|
|
196
|
-
while (end > 0 && bare[end - 1] === ".")
|
|
197
|
-
end -= 1;
|
|
198
|
-
const host = bare.slice(0, end);
|
|
199
|
-
if (!host)
|
|
200
|
-
return false;
|
|
201
|
-
if (host === "localhost" ||
|
|
202
|
-
host === "ip6-localhost" ||
|
|
203
|
-
host === "ip6-loopback" ||
|
|
204
|
-
host.endsWith(".localhost") ||
|
|
205
|
-
host.endsWith(".local") ||
|
|
206
|
-
host.endsWith(".internal")) {
|
|
207
|
-
return false;
|
|
208
|
-
}
|
|
209
|
-
return !isBlockedIpLiteral(host);
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* Throw if `url` is not a safe public https URL (see {@link isSafePublicHttpsUrl}).
|
|
213
|
-
* Use before `fetch`ing any provider-supplied download URL.
|
|
214
|
-
*/
|
|
215
|
-
export function assertSafePublicHttpsUrl(url) {
|
|
216
|
-
if (!isSafePublicHttpsUrl(url)) {
|
|
217
|
-
throw new Error(`Refusing to fetch unsafe URL (must be https to a public host): ${url}`);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
/** Request headers that must not cross an origin boundary on a redirect. */
|
|
221
|
-
const CROSS_ORIGIN_SENSITIVE_HEADERS = [
|
|
222
|
-
"authorization",
|
|
223
|
-
"cookie",
|
|
224
|
-
"proxy-authorization",
|
|
225
|
-
"x-goog-api-key"
|
|
226
|
-
];
|
|
227
|
-
/**
|
|
228
|
-
* Return a copy of `init` with credentials and body stripped, for replay
|
|
229
|
-
* against a different origin. Mirrors browser behaviour: a cross-origin
|
|
230
|
-
* redirect must not forward `Authorization`/`Cookie` headers or the request
|
|
231
|
-
* body, both of which may carry secrets meant only for the original host.
|
|
232
|
-
*/
|
|
233
|
-
function stripCrossOriginCredentials(init) {
|
|
234
|
-
const headers = new Headers(init.headers ?? undefined);
|
|
235
|
-
for (const name of CROSS_ORIGIN_SENSITIVE_HEADERS)
|
|
236
|
-
headers.delete(name);
|
|
237
|
-
const next = { ...init, headers };
|
|
238
|
-
delete next.body;
|
|
239
|
-
return next;
|
|
240
|
-
}
|
|
241
|
-
/**
|
|
242
|
-
* `fetch` a provider-supplied URL with SSRF protection. The initial URL and
|
|
243
|
-
* every redirect hop are validated with {@link assertSafePublicHttpsUrl}, so a
|
|
244
|
-
* public host cannot redirect into an internal/loopback target or downgrade to
|
|
245
|
-
* http. Redirects are followed manually up to `maxRedirects`. When a redirect
|
|
246
|
-
* crosses to a different origin, auth headers and the request body are stripped
|
|
247
|
-
* so they are never leaked to the redirect target.
|
|
248
|
-
*/
|
|
249
|
-
export async function safeFetch(url, init, maxRedirects = 5,
|
|
250
|
-
// The underlying fetch implementation. Defaults to the global fetch; callers
|
|
251
|
-
// that inject a fetch (e.g. providers with a testable `fetchFn`) can pass it
|
|
252
|
-
// here so the SSRF URL validation still runs on every hop while the actual
|
|
253
|
-
// request goes through their implementation.
|
|
254
|
-
fetchImpl = fetch) {
|
|
255
|
-
let current = url;
|
|
256
|
-
let currentInit = { ...init };
|
|
257
|
-
let currentOrigin = new URL(url).origin;
|
|
258
|
-
for (let hop = 0; hop <= maxRedirects; hop++) {
|
|
259
|
-
assertSafePublicHttpsUrl(current);
|
|
260
|
-
const res = await fetchImpl(current, { ...currentInit, redirect: "manual" });
|
|
261
|
-
// A real Response always has headers; tolerate minimal fetch mocks/polyfills
|
|
262
|
-
// that omit them (treated as no redirect).
|
|
263
|
-
const location = res.headers?.get?.("location") ?? null;
|
|
264
|
-
if (res.status >= 300 && res.status < 400 && location) {
|
|
265
|
-
const method = (currentInit.method ?? "GET").toUpperCase();
|
|
266
|
-
if (((res.status === 301 || res.status === 302) && method === "POST") ||
|
|
267
|
-
(res.status === 303 && method !== "GET" && method !== "HEAD")) {
|
|
268
|
-
const headers = new Headers(currentInit.headers);
|
|
269
|
-
for (const name of ["content-encoding", "content-language", "content-location", "content-type", "content-length"])
|
|
270
|
-
headers.delete(name);
|
|
271
|
-
currentInit = { ...currentInit, method: "GET", body: undefined, headers };
|
|
272
|
-
}
|
|
273
|
-
const next = new URL(location, current);
|
|
274
|
-
if (next.origin !== currentOrigin) {
|
|
275
|
-
currentInit = stripCrossOriginCredentials(currentInit);
|
|
276
|
-
}
|
|
277
|
-
current = next.toString();
|
|
278
|
-
currentOrigin = next.origin;
|
|
279
|
-
continue;
|
|
280
|
-
}
|
|
281
|
-
return res;
|
|
282
|
-
}
|
|
283
|
-
throw new Error(`Too many redirects while fetching: ${url}`);
|
|
284
|
-
}
|
|
1
|
+
export { isBlockedIpLiteral, isSafePublicHttpsUrl, assertSafePublicHttpsUrl, safeFetch } from "@nodetool-ai/runtime-core/safe-url";
|
|
285
2
|
//# sourceMappingURL=safe-url.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"safe-url.js","sourceRoot":"","sources":["../../src/providers/safe-url.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"safe-url.js","sourceRoot":"","sources":["../../src/providers/safe-url.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,wBAAwB,EACxB,SAAS,EACV,MAAM,oCAAoC,CAAC"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Settings → API Keys.
|
|
6
6
|
*
|
|
7
7
|
* Video enhancement is handled by the `@nodetool-ai/topaz-nodes`
|
|
8
|
-
* `topaz.video.EnhanceVideo` node (it needs local
|
|
8
|
+
* `topaz.video.EnhanceVideo` node (it needs local metadata probing and
|
|
9
9
|
* a multi-step upload pipeline), so it is intentionally not duplicated here.
|
|
10
10
|
*
|
|
11
11
|
* Topaz authenticates with the `X-API-Key` header. Image model definitions are
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Settings → API Keys.
|
|
6
6
|
*
|
|
7
7
|
* Video enhancement is handled by the `@nodetool-ai/topaz-nodes`
|
|
8
|
-
* `topaz.video.EnhanceVideo` node (it needs local
|
|
8
|
+
* `topaz.video.EnhanceVideo` node (it needs local metadata probing and
|
|
9
9
|
* a multi-step upload pipeline), so it is intentionally not duplicated here.
|
|
10
10
|
*
|
|
11
11
|
* Topaz authenticates with the `X-API-Key` header. Image model definitions are
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Most chat APIs are OpenAI-compatible and have nowhere to put a clip, so a
|
|
5
5
|
* `video` part reaching them used to be a hard refusal — even when the model
|
|
6
6
|
* behind the endpoint reads images perfectly well. This samples the clip into
|
|
7
|
-
* stills
|
|
7
|
+
* stills in process and puts them on the message as ordinary image parts,
|
|
8
8
|
* labelled with their timestamps so the model can reason about order and
|
|
9
9
|
* timing.
|
|
10
10
|
*
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Most chat APIs are OpenAI-compatible and have nowhere to put a clip, so a
|
|
5
5
|
* `video` part reaching them used to be a hard refusal — even when the model
|
|
6
6
|
* behind the endpoint reads images perfectly well. This samples the clip into
|
|
7
|
-
* stills
|
|
7
|
+
* stills in process and puts them on the message as ordinary image parts,
|
|
8
8
|
* labelled with their timestamps so the model can reason about order and
|
|
9
9
|
* timing.
|
|
10
10
|
*
|
|
@@ -42,7 +42,7 @@ function parseDataUri(uri) {
|
|
|
42
42
|
}
|
|
43
43
|
/**
|
|
44
44
|
* Source a video part's bytes: inline data first, then its URI. The container
|
|
45
|
-
* type is not read off the ref —
|
|
45
|
+
* type is not read off the ref — libav sniffs it from the file itself, which
|
|
46
46
|
* is right more often than a `mimeType` the caller guessed.
|
|
47
47
|
*/
|
|
48
48
|
async function videoContentBytes(video, options) {
|
|
@@ -134,9 +134,9 @@ export async function expandVideoContentAsFrames(messages, options = {}) {
|
|
|
134
134
|
signal: options.signal
|
|
135
135
|
});
|
|
136
136
|
if (sample.frames.length === 0) {
|
|
137
|
-
throw new Error(`
|
|
137
|
+
throw new Error(`No frames could be decoded from the attached video, so ` +
|
|
138
138
|
`${options.provider ?? "this provider"} has nothing to read. The ` +
|
|
139
|
-
`file may not be a video, or may use a codec this
|
|
139
|
+
`file may not be a video, or may use a codec this build ` +
|
|
140
140
|
`does not decode.`);
|
|
141
141
|
}
|
|
142
142
|
log.debug("Sampled a video into frames", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"video-frame-fallback.js","sourceRoot":"","sources":["../../src/providers/video-frame-fallback.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"video-frame-fallback.js","sourceRoot":"","sources":["../../src/providers/video-frame-fallback.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Sample a video into still frames
|
|
2
|
+
* Sample a video into still frames, decoded in process.
|
|
3
3
|
*
|
|
4
4
|
* This is what lets a vision model that cannot read a clip still answer
|
|
5
5
|
* questions about one: the bytes are decoded here, a bounded number of frames
|
|
6
6
|
* come back as JPEGs, and the caller sends them as ordinary image content.
|
|
7
|
-
*
|
|
8
|
-
* The argv is ours, not a model's — the only input path is a temp file this
|
|
9
|
-
* module wrote — so the containment `packages/agents/src/host-binary-guard.ts`
|
|
10
|
-
* applies to a model-supplied argv is not needed. `-protocol_whitelist file`
|
|
11
|
-
* and `-nostdin` still go in: an mp4 can name an external opener, and a child
|
|
12
|
-
* that inherits the server's stdin outlives the call.
|
|
7
|
+
* The only input is a temp file this module wrote.
|
|
13
8
|
*/
|
|
14
9
|
/** A single sampled frame, JPEG-encoded. */
|
|
15
10
|
export type SampledFrame = {
|
|
@@ -20,13 +15,13 @@ export type SampledFrame = {
|
|
|
20
15
|
};
|
|
21
16
|
export type VideoFrameSample = {
|
|
22
17
|
frames: SampledFrame[];
|
|
23
|
-
/** Clip length from
|
|
18
|
+
/** Clip length from the probe, or null when the probe did not answer. */
|
|
24
19
|
durationSec: number | null;
|
|
25
|
-
/** Frames per second
|
|
20
|
+
/** Frames per second the clip was sampled at. */
|
|
26
21
|
fps: number;
|
|
27
22
|
/**
|
|
28
23
|
* True when the frame cap stopped the sample before the end of the clip.
|
|
29
|
-
* Only reachable with an unknown duration: once
|
|
24
|
+
* Only reachable with an unknown duration: once the probe answers, the rate is
|
|
30
25
|
* chosen to fit the budget across the whole clip and the cap never bites.
|
|
31
26
|
*/
|
|
32
27
|
truncated: boolean;
|
|
@@ -40,11 +35,6 @@ export type SampleVideoFramesOptions = {
|
|
|
40
35
|
maxDimension?: number;
|
|
41
36
|
signal?: AbortSignal;
|
|
42
37
|
};
|
|
43
|
-
/** ffmpeg or ffprobe is not installed. Names the binary and the way out. */
|
|
44
|
-
export declare class FrameSamplingUnavailableError extends Error {
|
|
45
|
-
readonly binary: string;
|
|
46
|
-
constructor(binary: string);
|
|
47
|
-
}
|
|
48
38
|
/** Read a video duration from its bytes without decoding frames. */
|
|
49
39
|
export declare function probeVideoDurationSeconds(bytes: Uint8Array, signal: AbortSignal): Promise<number | null>;
|
|
50
40
|
/**
|
|
@@ -55,7 +45,7 @@ export declare function probeVideoDurationSeconds(bytes: Uint8Array, signal: Abo
|
|
|
55
45
|
export declare function frameRateFor(durationSec: number | null, maxFrames: number, maxFps: number): number;
|
|
56
46
|
/**
|
|
57
47
|
* Decode `bytes` and return up to `maxFrames` JPEG stills spread across the
|
|
58
|
-
* clip.
|
|
48
|
+
* clip.
|
|
59
49
|
*/
|
|
60
50
|
export declare function sampleVideoFrames(bytes: Uint8Array, options?: SampleVideoFramesOptions): Promise<VideoFrameSample>;
|
|
61
51
|
//# sourceMappingURL=video-frames.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"video-frames.d.ts","sourceRoot":"","sources":["../../src/providers/video-frames.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"video-frames.d.ts","sourceRoot":"","sources":["../../src/providers/video-frames.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH,4CAA4C;AAC5C,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,yEAAyE;IACzE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,iDAAiD;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,mCAAmC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AA6CF,oEAAoE;AACpE,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiBxB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,MAAM,CAMR;AAYD;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,UAAU,EACjB,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,gBAAgB,CAAC,CAsD3B"}
|