Sign In

@vantio/cli

Package Overview
Dependencies
Maintainers
1
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@vantio/cli - npm Package Compare versions

Comparing version
0.3.1
to
0.3.2
+122
bin/llm-hosts.cjs
// Shared Optics/Gate wrap catalog — destinations the Node interceptor may
// observe or enforce. Keep in lockstep with
// vantio-open-core/packages/vantio-agent-sdk-py/vantio/_http_observe.py
//
// Exact DNS names plus regional patterns verified against provider docs
// (2026-08-14). Do not add company NEVER_BLOCK SaaS, Cursor, or whole-cloud
// suffixes such as amazonaws.com / googleapis.com.
"use strict";
const LLM_HOSTS = [
"api.openai.com",
"api.anthropic.com",
"generativelanguage.googleapis.com",
"api.cohere.ai",
"api.cohere.com",
"api.mistral.ai",
"api.groq.com",
"api.together.xyz",
"api.perplexity.ai",
"inference.ai.azure.com",
"openai.azure.com",
"api.x.ai",
"api.deepseek.com",
"api.fireworks.ai",
"openrouter.ai",
"api.cerebras.ai",
"api.voyageai.com",
"api.sambanova.ai",
"api.deepinfra.com",
"router.huggingface.co",
"api-inference.huggingface.co",
"api.replicate.com",
"ollama.com",
"integrate.api.nvidia.com",
];
function hostListed(hostname, items) {
const h = String(hostname || "").toLowerCase();
if (!h) return false;
const arr = items && typeof items.has === "function" ? [...items] : Array.isArray(items) ? items : [];
for (const item of arr) {
const b = String(item || "").toLowerCase().trim();
if (!b) continue;
if (h === b) return true;
// Suffix match only when the listed host looks like a DNS name (has a dot)
// so a bare token like "com" cannot sweep the internet.
if (b.includes(".") && h.endsWith("." + b)) return true;
}
return false;
}
/** Regional / infix API DNS that exact+suffix matching cannot cover honestly. */
function hostMatchesRegional(hostname) {
const h = String(hostname || "").toLowerCase();
if (!h) return false;
// Amazon Bedrock Runtime + Mantle + Agents Runtime (region is a DNS label).
if (/^bedrock-runtime(-fips)?\.[a-z0-9-]+\.amazonaws\.com$/.test(h)) return true;
if (/^bedrock-mantle\.[a-z0-9-]+\.api\.aws$/.test(h)) return true;
if (/^bedrock-agent-runtime(-fips)?\.[a-z0-9-]+\.amazonaws\.com$/.test(h)) return true;
// Google Vertex AI: global, {region}-aiplatform, multi-region REP.
if (h === "aiplatform.googleapis.com") return true;
if (h.endsWith("-aiplatform.googleapis.com") && h.includes(".")) return true;
if (/^aiplatform\.(us|eu)\.rep\.googleapis\.com$/.test(h)) return true;
// Hugging Face Inference Endpoints: {name}.{region}.endpoints.huggingface.cloud
if (h === "endpoints.huggingface.cloud" || h.endsWith(".endpoints.huggingface.cloud")) return true;
return false;
}
function isOllamaLocal(hostname, port) {
const h = String(hostname || "").toLowerCase();
const p = String(port == null ? "" : port);
if (p !== "11434") return false;
return h === "localhost" || h === "127.0.0.1" || h === "::1" || h === "[::1]";
}
function catalogInScope(hostname, port, hosts) {
return (
hostListed(hostname, hosts) ||
hostMatchesRegional(hostname) ||
isOllamaLocal(hostname, port)
);
}
function guessProvider(hostname, port) {
const h = String(hostname || "").toLowerCase();
if (!h) return "unknown";
if (isOllamaLocal(hostname, port) || h === "ollama.com" || h.endsWith(".ollama.com")) return "ollama";
if (h.includes("openai") || h === "api.openai.com") return "openai";
if (h.includes("anthropic")) return "anthropic";
if (h.includes("aiplatform")) return "vertex";
if (h.includes("googleapis") || h.includes("generativelanguage")) return "google";
if (h.includes("cohere")) return "cohere";
if (h.includes("mistral")) return "mistral";
if (h.includes("groq")) return "groq";
if (h.includes("together")) return "together";
if (h.includes("perplexity")) return "perplexity";
if (h.includes("azure") || h.includes("openai.azure")) return "azure_openai";
if (h.includes("x.ai") || h.endsWith(".x.ai")) return "xai";
if (h.includes("deepseek")) return "deepseek";
if (h.includes("fireworks")) return "fireworks";
if (h.includes("openrouter")) return "openrouter";
if (h.includes("cerebras")) return "cerebras";
if (h.includes("voyageai")) return "voyage";
if (h.includes("sambanova")) return "sambanova";
if (h.includes("deepinfra")) return "deepinfra";
if (h.includes("bedrock")) return "bedrock";
if (h.includes("huggingface") || h.endsWith(".huggingface.cloud")) return "huggingface";
if (h.includes("replicate")) return "replicate";
if (h.includes("nvidia")) return "nvidia";
if (h.includes("localhost") || h.startsWith("127.")) return "local";
return "other";
}
module.exports = {
LLM_HOSTS,
hostListed,
hostMatchesRegional,
isOllamaLocal,
catalogInScope,
guessProvider,
};
+590
-47
// [ ∅ VANTIO ] Open Core Interceptor — Observe Plane
// Injected at runtime by `vantio run node agent.js` via Node --require.
// Patches globalThis.fetch to intercept outbound LLM calls — zero code changes.
// Patches globalThis.fetch and Node http/https.request|get to intercept
// outbound LLM calls — zero code changes. Raw sockets, curl, and browser
// paths stay outside this wrap.
//

@@ -22,2 +24,8 @@ // Layer identity in the Vantio suite:

const { join } = require("node:path");
const {
LLM_HOSTS: BASE_LLM_HOSTS,
hostListed,
catalogInScope,
guessProvider,
} = require("./llm-hosts.cjs");

@@ -45,2 +53,4 @@ const USE_COLOR = process.stderr.isTTY === true;

const SOAK_LOCAL = process.env.VANTIO_SOAK_LOCAL === "1";
// Local Gate control plane (Phantom-Box / dogfood) — never upsell Optics-only.
const LOCAL_GATE = SOAK_LOCAL || /:5001\/?$/.test(String(INGEST_URL || ""));

@@ -65,15 +75,6 @@ // ── Lane 1 anonymous telemetry (optional, fire-and-forget) ───────────────────

const LLM_HOSTS = new Set([
"api.openai.com",
"api.anthropic.com",
"generativelanguage.googleapis.com",
"api.cohere.ai",
"api.mistral.ai",
"api.groq.com",
"api.together.xyz",
"api.perplexity.ai",
"inference.ai.azure.com",
]);
// Local soak / self-hosted LLMs via env only — never hardcode 127.0.0.1
// (would make every out-of-scope localhost call look like LLM traffic).
const LLM_HOSTS = new Set(BASE_LLM_HOSTS);
// Local / extra LLM hosts via env only — never hardcode 127.0.0.1 as a
// blanket catalog entry (would make every localhost call look like LLM traffic).
// Ollama on localhost:11434 is matched by catalogInScope, not this set.
for (const h of String(process.env.VANTIO_EXTRA_LLM_HOSTS || "").split(",")) {

@@ -84,2 +85,58 @@ const t = h.trim();

/** Safe URL metadata — path only, never query string (may contain keys). */
function extractRequestMeta(input, init) {
let href = "";
let method = (init && init.method) || "GET";
try {
if (typeof input === "string") href = input;
else if (input instanceof URL) href = input.href;
else if (typeof Request !== "undefined" && input instanceof Request) {
href = input.url;
method = init?.method || input.method || method;
} else if (input && input.url) href = input.url;
} catch {
href = "";
}
let path = "/";
let scheme = "https";
try {
const u = new URL(href);
path = u.pathname || "/";
scheme = u.protocol.replace(":", "") || "https";
} catch {
/* keep defaults */
}
let request_bytes = null;
try {
const body = init && init.body;
if (typeof body === "string") request_bytes = Buffer.byteLength(body);
else if (Buffer.isBuffer(body)) request_bytes = body.length;
else if (body instanceof Uint8Array) request_bytes = body.byteLength;
} catch {
request_bytes = null;
}
return {
method: String(method || "GET").toUpperCase(),
path,
scheme,
request_bytes,
};
}
function responseMeta(response) {
if (!response) {
return { status: null, ok: null, content_type: null, bytes: null };
}
const cl = response.headers?.get?.("content-length");
const bytes = cl != null && cl !== "" ? parseInt(cl, 10) || 0 : null;
const ctRaw = response.headers?.get?.("content-type") || "";
const content_type = ctRaw.split(";")[0].trim() || null;
return {
status: typeof response.status === "number" ? response.status : null,
ok: typeof response.ok === "boolean" ? response.ok : null,
content_type,
bytes,
};
}
// ── Default policy (fail-open until cloud policy loads) ──────────────────────

@@ -187,5 +244,9 @@ const DEFAULT_POLICY = {

if (!cloudSyncActive) {
log(`${c.dim}[ ∅ VANTIO ] Free plan — calls observed locally only. Dashboard sync requires Pro or Enterprise (vantio.ai/pricing).${c.reset}`);
log(
LOCAL_GATE
? `${c.dim}[ ∅ VANTIO ] Local Gate — events sync to the on-box control plane (${INGEST_URL}).${c.reset}`
: `${c.dim}[ ∅ VANTIO ] Free plan — calls observed locally only. Dashboard sync requires Pro or Enterprise (vantio.ai/pricing).${c.reset}`
);
} else if (SOAK_LOCAL) {
log(`${c.dim}[ ∅ VANTIO ] Soak-local mode — syncing events to ${INGEST_URL}${c.reset}`);
log(`${c.dim}[ ∅ VANTIO ] Local Gate mode — syncing events to ${INGEST_URL}${c.reset}`);
}

@@ -272,2 +333,7 @@ }

// Maximum bytes we will buffer from a ReadableStream to scan for PII.
// Requests larger than this threshold pass through unscanned rather than being
// held in memory, preserving back-pressure for true streaming workloads.
const MAX_STREAM_SCAN_BYTES = 2 * 1024 * 1024; // 2 MB ? max Latch (2026-08-09); was 64 KB
// Redact a concrete request body value, preserving its original type.

@@ -278,5 +344,8 @@ // Returns { value, bytes, redactions, replaced, unscanned }:

// any redaction happened (so the caller knows to swap the body).
// - ReadableStream / FormData / Blob → not scanned; `unscanned` is its label.
// - ReadableStream ≤ 64 KB → tee'd, buffered, scanned; redacted copy returned
// as Uint8Array when PII found, pass-through branch returned unchanged when not.
// - ReadableStream > 64 KB / FormData / Blob → not scanned; `unscanned` is its label.
// Never throws — on any unexpected shape it returns the body unchanged.
function redactRequestBody(body) {
// This function is async because ReadableStream buffering requires awaiting reads.
async function redactRequestBody(body) {
const none = { value: body, bytes: 0, redactions: [], replaced: false, unscanned: null };

@@ -314,2 +383,50 @@ if (body == null) return none;

// ── ReadableStream: tee + buffer up to MAX_STREAM_SCAN_BYTES ─────────────
// We tee the stream so the pass-through branch (b) always carries the full
// original content. The scan branch (a) is read until we confirm the body
// fits within the scan window. If PII is found we return the redacted text as
// a Uint8Array (the stream was small enough that buffering is safe). If no PII
// is found we return the pass-through branch so the network call is unaffected.
// Streams larger than the threshold fall back to unscanned — no bytes consumed
// on the pass-through branch, preserving back-pressure.
if (typeof ReadableStream !== "undefined" && body instanceof ReadableStream) {
try {
const [scanBranch, passBranch] = body.tee();
const reader = scanBranch.getReader();
const chunks = [];
let total = 0;
let oversized = false;
for (;;) {
const { done, value } = await reader.read();
if (done) break;
const n = value ? (value.byteLength != null ? value.byteLength : value.length || 0) : 0;
total += n;
if (total > MAX_STREAM_SCAN_BYTES) { oversized = true; break; }
if (value) chunks.push(value);
}
// Release our scan reader regardless of outcome so GC can clean up.
try { reader.cancel(); } catch { /* ignore */ }
if (!oversized) {
// Full body fits — scan and optionally redact.
const all = Buffer.concat(chunks.map((c) => Buffer.from(c)));
const text = all.toString("utf8");
const r = redactBody(text);
if (r.redactions.length > 0) {
// PII found: return the redacted content as a Uint8Array so the
// caller can substitute it for the original stream.
const buf = Buffer.from(r.text, "utf8");
return { value: new Uint8Array(buf), bytes: buf.length, redactions: r.redactions, replaced: true, unscanned: null };
}
// No PII: use the pass-through branch (original content, no latency).
return { value: passBranch, bytes: total, redactions: [], replaced: false, unscanned: null };
}
// Oversized — use pass-through branch unmodified; log as unscanned.
return { value: passBranch, bytes: 0, redactions: [], replaced: false, unscanned: "ReadableStream" };
} catch {
// tee() / read failed (e.g. stream already locked) — fall through below.
}
return { value: body, bytes: 0, redactions: [], replaced: false, unscanned: "ReadableStream" };
}
const label = unscannableBodyLabel(body);

@@ -331,2 +448,10 @@ if (label) return { value: body, bytes: 0, redactions: [], replaced: false, unscanned: label };

if (FREE_MODE || !INGEST_URL || !cloudSyncActive) return;
// Additive Optics Sight Loop fields — Gate stores opaque JSON; PE joins on traceId.
const host = metadata && metadata.target_host;
const eventPayload = {
...metadata,
provider: metadata.provider || (host ? guessProvider(host) : undefined),
mediation: metadata.mediation || "sight_loop",
plane: metadata.plane || "optics_gate",
};
void _originalFetch.call(globalThis, `${INGEST_URL}/api/v1/ingest`, {

@@ -342,3 +467,3 @@ method: "POST",

auditMode: AUDIT_MODE,
eventPayload: metadata,
eventPayload,
}),

@@ -354,7 +479,7 @@ signal: AbortSignal.timeout(5000),

// (OS / package-manager / unrelated) traffic merely because a policy exists.
function inScope(hostname) {
function inScope(hostname, port) {
return (
LLM_HOSTS.has(hostname) ||
policy.blocked_hosts.includes(hostname) ||
policy.allowed_hosts.includes(hostname)
catalogInScope(hostname, port, LLM_HOSTS) ||
hostListed(hostname, policy.blocked_hosts) ||
hostListed(hostname, policy.allowed_hosts)
);

@@ -460,3 +585,3 @@ }

if (policy.enforce) {
if (policy.blocked_hosts.includes(hostname)) {
if (hostListed(hostname, policy.blocked_hosts)) {
if (policy.dry_run) {

@@ -471,3 +596,3 @@ _calls.push({ hostname, action: "DRY_RUN_BLOCKED_HOST" });

}
} else if (policy.allowed_hosts.length > 0 && !policy.allowed_hosts.includes(hostname)) {
} else if (policy.allowed_hosts.length > 0 && !hostListed(hostname, policy.allowed_hosts)) {
if (policy.dry_run) {

@@ -491,3 +616,3 @@ _calls.push({ hostname, action: "DRY_RUN_BLOCKED_HOST" });

if (init && init.body != null) {
const r = redactRequestBody(init.body);
const r = await redactRequestBody(init.body);
reqBytes = r.bytes;

@@ -561,4 +686,11 @@ redactions = r.redactions;

function destFromHref(href) {
const u = new URL(href);
const port = u.port || (u.protocol === "https:" ? "443" : "80");
return { hostname: u.hostname, port };
}
globalThis.fetch = async function vantioFetch(input, init) {
let hostname;
let port;
try {

@@ -569,3 +701,5 @@ const url = typeof input === "string" ? input

: input.url;
hostname = new URL(url).hostname;
const dest = destFromHref(url);
hostname = dest.hostname;
port = dest.port;
} catch {

@@ -586,3 +720,3 @@ return _originalFetch.call(this, input, init);

// through, untouched. We never block/redact/meter unrelated traffic.
if (!inScope(hostname)) {
if (!inScope(hostname, port)) {
return _originalFetch.call(this, input, init);

@@ -596,14 +730,73 @@ }

if (FREE_MODE) {
const response = await _originalFetch.call(this, input, init);
const bytes = parseInt(response.headers.get("content-length") || "0", 10) || null;
const reqMeta = extractRequestMeta(input, init);
const provider = guessProvider(hostname, port);
const t0 = Date.now();
let response;
try {
response = await _originalFetch.call(this, input, init);
} catch (err) {
const ts = new Date().toISOString();
const duration_ms = Date.now() - t0;
_calls.push({
hostname,
provider,
method: reqMeta.method,
path: reqMeta.path,
scheme: reqMeta.scheme,
request_bytes: reqMeta.request_bytes,
bytes: null,
status: null,
ok: false,
content_type: null,
duration_ms,
ts,
action: "OBSERVED",
error_class: err && err.name ? String(err.name) : "Error",
error: "network_error",
});
log([
"",
`${c.dim}[ ∅ VANTIO ]${c.reset} ${c.red}Outbound LLM call failed${c.reset}`,
` host: ${c.cyan}${hostname}${c.reset}`,
` provider: ${provider}`,
` method: ${reqMeta.method} ${reqMeta.path}`,
` error: ${err && err.name ? err.name : "Error"}`,
` duration: ${duration_ms}ms`,
` pid: ${process.pid}`,
` time: ${ts}`,
].join("\n"));
throw err;
}
const resp = responseMeta(response);
const duration_ms = Date.now() - t0;
const ts = new Date().toISOString();
_calls.push({ hostname, bytes, ts, action: "OBSERVED" });
_calls.push({
hostname,
provider,
method: reqMeta.method,
path: reqMeta.path,
scheme: reqMeta.scheme,
request_bytes: reqMeta.request_bytes,
bytes: resp.bytes,
status: resp.status,
ok: resp.ok,
content_type: resp.content_type,
duration_ms,
ts,
action: "OBSERVED",
});
log([
"",
`${c.dim}[ ∅ VANTIO ]${c.reset} ${c.yellow}Outbound LLM call intercepted${c.reset}`,
` host: ${c.cyan}${hostname}${c.reset}`,
` pid: ${process.pid}`,
` bytes: ${bytes != null ? bytes.toLocaleString() : "unknown"}`,
` time: ${ts}`,
` ${c.dim}→ Optics observes only. See docs/observe-only.md · upgrade to Vantio Gate (Pro) to enforce.${c.reset}`,
` host: ${c.cyan}${hostname}${c.reset}`,
` provider: ${provider}`,
` method: ${reqMeta.method} ${reqMeta.path}`,
` status: ${resp.status != null ? resp.status : "unknown"}`,
` duration: ${duration_ms}ms`,
` bytes: ${resp.bytes != null ? resp.bytes.toLocaleString() : "unknown"}`,
` pid: ${process.pid}`,
` time: ${ts}`,
LOCAL_GATE
? ` ${c.dim}→ Local Gate attached — observe now; run with VANTIO_API_KEY for Policy Latch enforce.${c.reset}`
: ` ${c.dim}→ Optics data log (your machine). See docs/sight-loop.md · Gate enforces on this path.${c.reset}`,
].join("\n"));

@@ -630,3 +823,5 @@ return response;

// network error and propagates unchanged.
const t0 = Date.now();
const response = await _originalFetch.call(this, plan.input, plan.init);
const duration_ms = Math.max(0, Date.now() - t0);

@@ -637,3 +832,20 @@ // Post-call accounting + reporting — guarded so a metering error never

const action = plan.redactions.length > 0 ? "REDACTED" : "ALLOWED";
const callRec = { hostname, bytes: 0, action, redactions: plan.redactions.length };
const reqMeta = extractRequestMeta(plan.input, plan.init);
const resp = responseMeta(response);
const callRec = {
hostname,
provider: guessProvider(hostname, port),
method: reqMeta.method,
path: reqMeta.path,
scheme: reqMeta.scheme,
request_bytes: plan.reqBytes || reqMeta.request_bytes,
bytes: 0,
status: resp.status,
ok: resp.ok,
content_type: resp.content_type,
duration_ms,
action,
redactions: plan.redactions.length,
ts: new Date().toISOString(),
};
_calls.push(callRec);

@@ -656,4 +868,17 @@

}
report({ target_host: hostname, pid: process.pid, action_taken: action,
timestamp_ns: Date.now() * 1e6, bytes_severed: callRec.bytes });
report({
target_host: hostname,
pid: process.pid,
action_taken: action,
timestamp_ns: Date.now() * 1e6,
bytes_severed: callRec.bytes,
provider: callRec.provider,
method: callRec.method,
path: callRec.path,
status: callRec.status,
content_type: callRec.content_type,
request_bytes: callRec.request_bytes,
duration_ms: callRec.duration_ms,
ok: callRec.ok,
});
} catch {

@@ -667,2 +892,268 @@ // Accounting/reporting must never break the agent's call.

// ── Run summary ─────────────────────────────────────────────────────────────
// Node http/https — same Sight Loop / Gate rules as fetch, last-known policy
// (request() is sync; fail-open until policy loads). Out-of-scope hosts and
// the ingest control plane pass through untouched. Raw sockets / curl / browsers
// stay residual.
(function patchNodeHttpHttps() {
const { EventEmitter } = require("node:events");
function isControlPlaneRequest(args) {
try {
const ingest = new URL(INGEST_URL);
const a0 = args && args[0];
let u = null;
if (typeof a0 === "string" || (typeof URL !== "undefined" && a0 instanceof URL)) {
u = new URL(String(a0));
} else if (a0 && typeof a0 === "object") {
const host = a0.hostname || (a0.host ? String(a0.host).split(":")[0] : "");
if (!host) return false;
const port = String(a0.port || (a0.protocol === "https:" ? 443 : 80));
const ingestPort = ingest.port || (ingest.protocol === "https:" ? "443" : "80");
const path = String(a0.path || a0.pathname || "");
return host.toLowerCase() === ingest.hostname.toLowerCase()
&& port === String(ingestPort)
&& path.startsWith("/api/v1/");
}
if (!u) return false;
const ingestPort = ingest.port || (ingest.protocol === "https:" ? "443" : "80");
const reqPort = u.port || (u.protocol === "https:" ? "443" : "80");
return u.hostname.toLowerCase() === ingest.hostname.toLowerCase()
&& reqPort === ingestPort
&& u.pathname.startsWith("/api/v1/");
} catch {
return false;
}
}
function destFromArgs(args) {
try {
if (!args || !args.length) return { hostname: null, port: null };
const a0 = args[0];
if (typeof a0 === "string" || (typeof URL !== "undefined" && a0 instanceof URL)) {
try {
return destFromHref(String(a0));
} catch { return { hostname: null, port: null }; }
}
if (a0 && typeof a0 === "object") {
let hostname = null;
if (typeof a0.hostname === "string") hostname = a0.hostname;
else if (typeof a0.host === "string") hostname = a0.host.split(":")[0];
else if (typeof a0.href === "string") {
try { hostname = new URL(a0.href).hostname; } catch { hostname = null; }
}
let port = a0.port;
if ((port == null || port === "") && a0.host && String(a0.host).includes(":")) {
port = String(a0.host).split(":").pop();
}
if (port == null || port === "") {
port = a0.protocol === "https:" ? 443 : 80;
}
return { hostname, port: String(port) };
}
} catch { /* ignore */ }
return { hostname: null, port: null };
}
function blockedClientRequest(err) {
const fake = new EventEmitter();
fake.end = () => fake;
fake.write = () => true;
fake.abort = () => {};
fake.destroy = () => {};
fake.setTimeout = () => fake;
fake.setHeader = () => {};
fake.getHeader = () => undefined;
fake.removeHeader = () => {};
process.nextTick(() => fake.emit("error", err));
return fake;
}
let policySettled = FREE_MODE;
if (!FREE_MODE && policyReady && typeof policyReady.then === "function") {
policyReady.then(() => { policySettled = true; }).catch(() => { policySettled = true; });
}
function decideHttp(hostname, port, args) {
if (!hostname || isControlPlaneRequest(args)) return "pass";
if (!inScope(hostname, port)) return "pass";
if (FREE_MODE) return "observe";
if (policy.enforce) {
const blocked = hostListed(hostname, policy.blocked_hosts) ||
(policy.allowed_hosts.length > 0 && !hostListed(hostname, policy.allowed_hosts));
if (blocked) return policy.dry_run ? "dry_block" : "block";
}
return "observe";
}
function wrapModule(mod, scheme) {
if (!mod || typeof mod.request !== "function") return;
if (mod.__vantioPatched) return;
const origRequest = mod.request.bind(mod);
const origGet = typeof mod.get === "function" ? mod.get.bind(mod) : null;
function pendingRequest(args, launch) {
const pending = new EventEmitter();
const buffer = [];
pending.write = (c, e, cb) => { buffer.push(["write", c, e, cb]); return true; };
pending.end = (c, e, cb) => { buffer.push(["end", c, e, cb]); return pending; };
pending.abort = () => {};
pending.destroy = () => {};
pending.setTimeout = () => pending;
pending.setHeader = () => {};
pending.getHeader = () => undefined;
pending.removeHeader = () => {};
policyReady.then(() => {
policySettled = true;
try {
const real = wrapLaunch(args, launch);
if (real && typeof real.on === "function") {
real.on("error", (err) => pending.emit("error", err));
real.on("response", (res) => pending.emit("response", res));
real.on("socket", (sock) => pending.emit("socket", sock));
real.on("timeout", () => pending.emit("timeout"));
real.on("close", () => pending.emit("close"));
}
for (const [op, c, e, cb] of buffer) {
if (op === "write" && real && real.write) real.write(c, e, cb);
if (op === "end" && real && real.end) real.end(c, e, cb);
}
} catch (err) {
pending.emit("error", err);
}
}).catch((err) => pending.emit("error", err));
return pending;
}
function wrapLaunch(args, launch) {
if (!FREE_MODE && !policySettled) {
return pendingRequest(args, launch);
}
const dest = destFromArgs(args);
const hostname = dest.hostname;
const port = dest.port;
const decision = decideHttp(hostname, port, args);
if (decision === "pass") return launch();
sendRunTelemetryOnce(hostname);
const provider = guessProvider(hostname, port);
const ts = new Date().toISOString();
const baseCall = {
hostname, provider, method: "REQUEST", path: null, scheme,
request_bytes: null, bytes: 0, status: null, ok: true,
content_type: null, duration_ms: 0, ts, optics_plane: "app_http",
};
if (decision === "block") {
_calls.push({ ...baseCall, action: "BLOCKED_HOST", ok: false });
report({
target_host: hostname, pid: process.pid, action_taken: "BLOCKED_HOST",
timestamp_ns: Date.now() * 1e6, bytes_severed: 0,
mediation: "node_http", plane: "optics_gate",
});
log(`${c.red}[ ∅ VANTIO ] BLOCKED${c.reset} ${hostname} — Node ${scheme}.request`);
const err = new Error(`Vantio Gate blocked host: ${hostname}`);
err.code = "VANTIO_GATE_BLOCKED";
return blockedClientRequest(err);
}
if (decision === "dry_block") {
_calls.push({ ...baseCall, action: "DRY_RUN_BLOCKED_HOST" });
report({
target_host: hostname, pid: process.pid, action_taken: "DRY_RUN_BLOCKED_HOST",
timestamp_ns: Date.now() * 1e6, bytes_severed: 0,
mediation: "node_http", plane: "optics_gate",
});
log(`${c.yellow}[ ∅ VANTIO ] DRY_RUN${c.reset} ${hostname} — would BLOCK Node ${scheme}.request; dry_run=true passes through`);
} else {
_calls.push({ ...baseCall, action: FREE_MODE ? "OBSERVED" : "ALLOWED" });
report({
target_host: hostname, pid: process.pid,
action_taken: FREE_MODE ? "OBSERVED" : "ALLOWED",
timestamp_ns: Date.now() * 1e6, bytes_severed: 0,
mediation: "node_http", plane: "optics_gate",
});
if (FREE_MODE) {
log(`${c.cyan}[ ∅ VANTIO ] OBSERVED${c.reset} ${hostname} — Node ${scheme}.request`);
}
}
const req = launch();
if (!req || typeof req.write !== "function") return req;
if (FREE_MODE || (!policy.redact_pii && !(policy.enforce && policy.max_request_bytes > 0))) {
return req;
}
const origWrite = req.write.bind(req);
let written = 0;
req.write = function vantioHttpWrite(chunk, encoding, cb) {
try {
const buf = chunk == null ? Buffer.alloc(0)
: Buffer.isBuffer(chunk) ? chunk
: Buffer.from(String(chunk), typeof encoding === "string" ? encoding : "utf8");
written += buf.length;
if (policy.enforce && policy.max_request_bytes > 0 && written > policy.max_request_bytes) {
if (policy.dry_run) {
report({
target_host: hostname, pid: process.pid, action_taken: "DRY_RUN_BLOCKED_SIZE",
timestamp_ns: Date.now() * 1e6, bytes_severed: written,
mediation: "node_http",
});
return origWrite(chunk, encoding, cb);
}
report({
target_host: hostname, pid: process.pid, action_taken: "BLOCKED_SIZE",
timestamp_ns: Date.now() * 1e6, bytes_severed: written,
mediation: "node_http",
});
log(`${c.red}[ ∅ VANTIO ] BLOCKED${c.reset} ${hostname} — Node ${scheme} request ${written}B exceeds cap`);
const err = new Error("Vantio Gate blocked request: request_too_large");
err.code = "VANTIO_GATE_BLOCKED";
process.nextTick(() => req.emit("error", err));
return false;
}
if (policy.redact_pii && buf.length) {
const r = redactBody(buf.toString("utf8"));
if (r.redactions.length) {
report({
target_host: hostname, pid: process.pid, action_taken: "REDACTED",
timestamp_ns: Date.now() * 1e6, bytes_severed: 0,
mediation: "node_http",
});
log(`${c.green}[ ∅ VANTIO ] REDACTED${c.reset} ${hostname} — Node ${scheme}.request stripped ${r.redactions.length} PII item(s)`);
return origWrite(Buffer.from(r.text, "utf8"), undefined, cb);
}
}
} catch {
// Fail open — never break the agent's write.
}
return origWrite(chunk, encoding, cb);
};
return req;
}
mod.request = function (...args) {
try {
return wrapLaunch(args, () => origRequest(...args));
} catch {
return origRequest(...args);
}
};
if (origGet) {
mod.get = function (...args) {
try {
return wrapLaunch(args, () => origGet(...args));
} catch {
return origGet(...args);
}
};
}
mod.__vantioPatched = true;
}
try { wrapModule(require("node:http"), "http"); } catch { try { wrapModule(require("http"), "http"); } catch { /* ignore */ } }
try { wrapModule(require("node:https"), "https"); } catch { try { wrapModule(require("https"), "https"); } catch { /* ignore */ } }
})();
process.on("exit", () => {

@@ -686,9 +1177,34 @@ if (_calls.length === 0) return;

try {
const runsDir = join(homedir(), ".vantio", "runs");
const vantioHome = process.env.VANTIO_HOME || join(homedir(), ".vantio");
const runsDir = join(vantioHome, "runs");
mkdirSync(runsDir, { recursive: true, mode: 0o700 });
const machineHost = (() => { try { return osHostname(); } catch { return "unknown"; } })();
const providers = [...new Set(_calls.map((x) => x.provider).filter(Boolean))];
const errors = _calls.filter((x) => x.error || x.ok === false).length;
const by_host = {};
const by_provider = {};
for (const call of _calls) {
const h = call.hostname || "unknown";
const p = call.provider || "unknown";
by_host[h] = by_host[h] || { calls: 0, bytes: 0, errors: 0 };
by_host[h].calls += 1;
by_host[h].bytes += call.bytes || 0;
if (call.error || call.ok === false) by_host[h].errors += 1;
by_provider[p] = by_provider[p] || { calls: 0, bytes: 0 };
by_provider[p].calls += 1;
by_provider[p].bytes += call.bytes || 0;
}
const log = {
vantio_run_log: "1",
schema_version: 2,
plane: "optics",
workflow: "sight_loop",
data_note: "Developer egress data log — metadata only; never prompts or completions.",
trace_id: RUN_TRACE_ID,
pid: process.pid,
ppid: typeof process.ppid === "number" ? process.ppid : null,
node_version: process.version,
platform: process.platform,
arch: process.arch,
cwd: (() => { try { return process.cwd(); } catch { return null; } })(),
machine: machineHost,

@@ -699,8 +1215,20 @@ started_at: new Date(_startMs).toISOString(),

cli_version: CLI_VERSION,
free_mode: FREE_MODE,
calls: _calls.map((call) => ({
hostname: call.hostname,
action: call.action,
bytes: call.bytes || 0,
ts: call.ts || null,
redactions: call.redactions || 0,
hostname: call.hostname,
provider: call.provider || guessProvider(call.hostname),
method: call.method || null,
path: call.path || null,
scheme: call.scheme || null,
request_bytes: call.request_bytes != null ? call.request_bytes : null,
bytes: call.bytes || 0,
status: call.status != null ? call.status : null,
ok: call.ok != null ? call.ok : null,
content_type: call.content_type || null,
duration_ms: call.duration_ms != null ? call.duration_ms : null,
action: call.action,
ts: call.ts || null,
redactions: call.redactions || 0,
error: call.error || null,
error_class: call.error_class || null,
})),

@@ -711,2 +1239,6 @@ summary: {

hosts: hosts,
providers,
errors,
by_host,
by_provider,
redacted: redacted,

@@ -716,2 +1248,7 @@ blocked: blocked,

},
residual: {
note: "App plane covers fetch + Node http/https. Host Sight covers host egress observe. curl/raw sockets without Host Sight still dark until PE.",
upgrade_gate: "https://vantio.ai/gate",
upgrade_enterprise: "https://vantio.ai/enterprise",
},
};

@@ -744,7 +1281,13 @@ const safeid = RUN_TRACE_ID.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 80);

? ` ${c.dim}→ Events routed to your Vantio dashboard.${c.reset}`
: ` ${c.dim}→ Free plan — observed locally only. Upgrade at vantio.ai/pricing to sync your dashboard.${c.reset}`
: (LOCAL_GATE
? ` ${c.dim}→ Local Gate — events stay on this control plane (${INGEST_URL}).${c.reset}`
: ` ${c.dim}→ Free plan — observed locally only. Upgrade at vantio.ai/pricing to sync your dashboard.${c.reset}`)
);
} else {
lines.push(` ${c.dim}→ Run \`vantio prove\` to export an auditor-ready artifact from this run.${c.reset}`);
lines.push(` ${c.dim}→ Optics observes only — upgrade to Vantio Gate (Pro) to enforce policy.${c.reset}`);
lines.push(
LOCAL_GATE
? ` ${c.dim}→ Local Gate control plane detected — set VANTIO_API_KEY=soak-pro for enforce on this box.${c.reset}`
: ` ${c.dim}→ Optics observes only — upgrade to Vantio Gate (Pro) to enforce policy.${c.reset}`
);
if (!telemetryDisabled()) {

@@ -751,0 +1294,0 @@ lines.push(` ${c.dim}Anonymous usage telemetry helps improve Vantio. Opt out with VANTIO_TELEMETRY_DISABLED=1.${c.reset}`);

+13
-9
{
"name": "@vantio/cli",
"version": "0.3.1",
"version": "0.3.2",
"description": "Vantio Optics CLI — wrap any AI agent and observe LLM egress. Blind by design, not a proxy. Sight Loop: wrap → capture → inspect.",
"license": "MIT",
"author": "Vantio AI, Inc.",
"homepage": "https://vantio.ai/platform",
"homepage": "https://vantio.ai/optics",
"repository": {

@@ -13,3 +13,5 @@ "type": "git",

},
"bugs": { "url": "https://github.com/vantioai/vantio-open-core/issues" },
"bugs": {
"url": "https://github.com/vantioai/vantio-open-core/issues"
},
"keywords": [

@@ -33,10 +35,12 @@ "vantio",

},
"files": ["bin"],
"files": [
"bin"
],
"engines": {
"node": ">=18.3.0"
},
"scripts": {
"lint": "node --check bin/vantio.js && node --check bin/interceptor.cjs && node --check bin/telemetry.cjs",
"lint": "node --check bin/vantio.js && node --check bin/interceptor.cjs && node --check bin/telemetry.cjs && node --check bin/llm-hosts.cjs",
"test": "node --test"
},
"engines": {
"node": ">=18.3.0"
}
}
}
# @vantio/cli
> Run any AI agent with full observability. Zero code changes.
> Wrap any AI agent with **Vantio Optics** — free visibility into what it sends. Zero code changes.

@@ -16,7 +16,7 @@ ```bash

```bash
vantio login <your-api-key> # validates + saves your key once
vantio run node agent.js # no env vars needed — the key is loaded for you
vantio run node agent.js # Free Observe — no key needed
vantio login <your-api-key> # optional — Gate / paid features
```
`vantio login` validates your key against `https://vantio.ai/api/v1/config` and, on success, stores it at `~/.vantio/config.json` (chmod `600`). After that, `vantio run` injects it automatically — no `VANTIO_API_KEY` juggling. Grab your key from your [dashboard](https://vantio.ai/dashboard).
`vantio login` validates your key against `https://vantio.ai/api/v1/config` and, on success, stores it at `~/.vantio/config.json` (chmod `600`). After that, `vantio run` injects it automatically — no `VANTIO_API_KEY` juggling. Free Optics needs no key. Paid Gate keys come from a trial (`hello@vantio.ai`) or Stripe once live — there is no public self-serve key dashboard yet (`/dashboard` redirects).

@@ -48,3 +48,3 @@ ---

Wrap any process with `vantio run`. The CLI automatically intercepts every outbound call to a known LLM API — OpenAI, Anthropic, Gemini, Cohere, Mistral, and more — and streams the metadata to your dashboard.
Wrap any process with `vantio run`. The CLI automatically intercepts every outbound call to a known LLM API — OpenAI, Anthropic, Gemini, Cohere, Mistral, and more — and records connection metadata locally (and to Gate when a key is configured).

@@ -109,3 +109,3 @@ Your code doesn't change. Your agent runs normally. If you've run `vantio login`, the stored key is injected into the child process; an explicit `VANTIO_API_KEY` in your environment always takes precedence.

- **Free (--local)** — reads local run logs from `~/.vantio/runs/`. No API key needed. Covers only processes started with `vantio run` on this machine.
- **Pro users** — see all SDK-monitored LLM calls with governance status (ALLOWED / REDACTED / BLOCKED / OBSERVED).
- **Pro users** — see all SDK-monitored LLM calls with governance status (`OBSERVED` / `ALLOWED` / `REDACTED` / `BLOCKED`).
- **Enterprise users (Phantom Engine)** — additionally surfaces processes that called LLM endpoints without a Vantio `trace_id` — the **Shadow AI** agents that have no governance coverage.

@@ -197,2 +197,2 @@

[vantio.ai](https://vantio.ai) · [Platform](https://vantio.ai/platform) · [Pricing](https://vantio.ai/pricing) · MIT License
[vantio.ai](https://vantio.ai) · [Optics](https://vantio.ai/optics) · [Pricing](https://vantio.ai/pricing) · MIT License