vet-skills 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +57 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7616,7 +7616,7 @@ import { parseArgs } from "node:util";
|
|
|
7616
7616
|
import { spawnSync } from "node:child_process";
|
|
7617
7617
|
import { readFileSync as readFileSync3, existsSync as existsSync4 } from "node:fs";
|
|
7618
7618
|
import { resolve, join as join4, dirname, basename } from "node:path";
|
|
7619
|
-
import { hostname, platform, userInfo } from "node:os";
|
|
7619
|
+
import { hostname, platform as platform2, userInfo } from "node:os";
|
|
7620
7620
|
import { createHash } from "node:crypto";
|
|
7621
7621
|
import { createInterface } from "node:readline";
|
|
7622
7622
|
|
|
@@ -7629,7 +7629,7 @@ import { mkdirSync, readFileSync, writeFileSync, existsSync, appendFileSync, chm
|
|
|
7629
7629
|
import { homedir } from "node:os";
|
|
7630
7630
|
import { join } from "node:path";
|
|
7631
7631
|
import { randomUUID } from "node:crypto";
|
|
7632
|
-
var VERSION = "0.5.
|
|
7632
|
+
var VERSION = "0.5.1";
|
|
7633
7633
|
var HOME = process.env.VET_SKILLS_HOME ?? join(homedir(), ".vet-skills");
|
|
7634
7634
|
var API = (process.env.KILLERSKILLS_API ?? "https://killerskills.ai").replace(/\/$/, "");
|
|
7635
7635
|
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -7735,6 +7735,33 @@ function stateSummary() {
|
|
|
7735
7735
|
const sz = (f) => existsSync(join(HOME, f)) ? statSync(join(HOME, f)).size : 0;
|
|
7736
7736
|
return { home: HOME, cacheEntries: cacheSize(), cacheBytes: sz("cache.json"), logBytes: sz("log.jsonl") };
|
|
7737
7737
|
}
|
|
7738
|
+
function telemetryEnabled() {
|
|
7739
|
+
const env = (process.env.VET_SKILLS_TELEMETRY ?? "").toLowerCase();
|
|
7740
|
+
if (["0", "false", "off", "no"].includes(env)) return false;
|
|
7741
|
+
if (process.env.DO_NOT_TRACK === "1") return false;
|
|
7742
|
+
const p = join(HOME, "telemetry");
|
|
7743
|
+
if (existsSync(p)) return readFileSync(p, "utf8").trim() !== "off";
|
|
7744
|
+
return true;
|
|
7745
|
+
}
|
|
7746
|
+
function setTelemetry(on2) {
|
|
7747
|
+
ensureHome();
|
|
7748
|
+
writeFileSync(join(HOME, "telemetry"), on2 ? "on\n" : "off\n", { mode: 384 });
|
|
7749
|
+
}
|
|
7750
|
+
function telemetryNoticePending() {
|
|
7751
|
+
ensureHome();
|
|
7752
|
+
const p = join(HOME, "telemetry-notice");
|
|
7753
|
+
if (existsSync(p)) return false;
|
|
7754
|
+
writeFileSync(p, (/* @__PURE__ */ new Date()).toISOString() + "\n", { mode: 384 });
|
|
7755
|
+
return true;
|
|
7756
|
+
}
|
|
7757
|
+
function hintOncePerDay(key) {
|
|
7758
|
+
ensureHome();
|
|
7759
|
+
const p = join(HOME, `hint-${key.replace(/[^\w-]/g, "_")}`);
|
|
7760
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
7761
|
+
if (existsSync(p) && readFileSync(p, "utf8").trim() === today) return false;
|
|
7762
|
+
writeFileSync(p, today + "\n", { mode: 384 });
|
|
7763
|
+
return true;
|
|
7764
|
+
}
|
|
7738
7765
|
|
|
7739
7766
|
// src/api.ts
|
|
7740
7767
|
async function call(path, init = {}, timeoutMs = 8e3) {
|
|
@@ -7792,6 +7819,12 @@ function detonate(tgz, opts = {}) {
|
|
|
7792
7819
|
const q = new URLSearchParams();
|
|
7793
7820
|
return call(`/api/v1/detonate?${q}`, { method: "POST", body: new Blob([tgz]), headers: { "content-type": "application/gzip", ...opts.publisher ? { "x-vs-publisher": opts.publisher } : {} } }, 18e4);
|
|
7794
7821
|
}
|
|
7822
|
+
function sendTelemetry(body) {
|
|
7823
|
+
return call("/api/v1/telemetry", { method: "POST", body: JSON.stringify(body) }, 1500);
|
|
7824
|
+
}
|
|
7825
|
+
|
|
7826
|
+
// src/check.ts
|
|
7827
|
+
import { platform } from "node:os";
|
|
7795
7828
|
|
|
7796
7829
|
// src/render.ts
|
|
7797
7830
|
var on = !!process.stdout.isTTY && !process.env.NO_COLOR;
|
|
@@ -7908,6 +7941,10 @@ async function check(q, opts = {}) {
|
|
|
7908
7941
|
offline,
|
|
7909
7942
|
requestId: remote?.approvalRequestId
|
|
7910
7943
|
});
|
|
7944
|
+
if (!org && telemetryEnabled()) {
|
|
7945
|
+
if (telemetryNoticePending()) process.stderr.write(c.muted("vet-skills sends anonymous usage (skill name, version, decision, agent type; never code, prompts or paths). Opt out: vet-skills telemetry off") + "\n");
|
|
7946
|
+
await sendTelemetry({ skill: resolved?.skill.name ?? q, semver: resolved?.version.semver ?? null, registry: resolved?.skill.registry ?? null, decision: decision.decision, would_be: decision.wouldBe ?? null, agent_kind: opts.agentKind ?? "other", hook_version: VERSION, os: platform(), offline }).catch(() => null);
|
|
7947
|
+
}
|
|
7911
7948
|
return { resolved, decision, source, cacheAge, remote, offline, policyLabel };
|
|
7912
7949
|
}
|
|
7913
7950
|
function renderCheck(r) {
|
|
@@ -8153,10 +8190,11 @@ ${out}
|
|
|
8153
8190
|
`);
|
|
8154
8191
|
return 2;
|
|
8155
8192
|
case "block":
|
|
8156
|
-
process.stderr.write(`vet-skills blocked this install by org policy.
|
|
8193
|
+
process.stderr.write(`vet-skills blocked this install by ${readOrg() ? "org" : "your"} policy.
|
|
8157
8194
|
${renderCheck(r)}
|
|
8158
8195
|
${out}
|
|
8159
8196
|
`);
|
|
8197
|
+
if (!readOrg() && hintOncePerDay("teams")) process.stderr.write("Running this for a team? One policy across every developer's agents, approvals and inventory: https://killerskills.ai/pricing\n");
|
|
8160
8198
|
return 2;
|
|
8161
8199
|
}
|
|
8162
8200
|
return 0;
|
|
@@ -8211,6 +8249,11 @@ async function ask(question, choices) {
|
|
|
8211
8249
|
}
|
|
8212
8250
|
var USAGE = `vet-skills ${VERSION} \u2014 check agent skills and MCP servers before they run.
|
|
8213
8251
|
|
|
8252
|
+
Get started:
|
|
8253
|
+
vet-skills hook install claude-code check every install Claude Code makes (one time)
|
|
8254
|
+
vet-skills check <skill> see the verdict for anything before installing it
|
|
8255
|
+
vet-skills join <org> --token <t> enroll this machine in your team's policy (token from the dashboard)
|
|
8256
|
+
|
|
8214
8257
|
vet-skills check <skill> dry-run the decision
|
|
8215
8258
|
vet-skills install <skill> check, then \`npx skills add\`
|
|
8216
8259
|
vet-skills detonate <path> [--publisher h] upload a local bundle to the sandbox and print its verdict
|
|
@@ -8396,7 +8439,7 @@ async function main() {
|
|
|
8396
8439
|
machine_label: hostname(),
|
|
8397
8440
|
agent_kind: values.agent ?? "other",
|
|
8398
8441
|
hook_version: VERSION,
|
|
8399
|
-
os:
|
|
8442
|
+
os: platform2(),
|
|
8400
8443
|
installed: [],
|
|
8401
8444
|
ci: values.ci === true
|
|
8402
8445
|
});
|
|
@@ -8463,6 +8506,16 @@ async function main() {
|
|
|
8463
8506
|
console.log(`${c.verified("\u2713")} ${handle} added to the personal block list${values.reason ? ` (${values.reason})` : ""}.`);
|
|
8464
8507
|
return 0;
|
|
8465
8508
|
}
|
|
8509
|
+
case "telemetry": {
|
|
8510
|
+
const sub = rest[0] ?? "status";
|
|
8511
|
+
if (sub === "on" || sub === "off") {
|
|
8512
|
+
setTelemetry(sub === "on");
|
|
8513
|
+
console.log(`${c.verified("\u2713")} telemetry ${sub}`);
|
|
8514
|
+
return 0;
|
|
8515
|
+
}
|
|
8516
|
+
console.log(`telemetry ${telemetryEnabled() ? "on" : "off"} ${c.muted(readOrg() ? "(enrolled: decisions report to the org, not here)" : "(anonymous: skill, version, decision, agent type; never code, prompts or paths)")}`);
|
|
8517
|
+
return 0;
|
|
8518
|
+
}
|
|
8466
8519
|
case "status": {
|
|
8467
8520
|
const org = readOrg();
|
|
8468
8521
|
const { policy, source } = readPolicy();
|