Ctrl K
ComunidadGuías…

test/clay-vendor-usage.test.js

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
var test = require("node:test");
var assert = require("node:assert/strict");
var fs = require("node:fs");
var path = require("node:path");
var control = require("../lib/clay-vendor-usage");
var tools = require("../lib/clay-product-control-tools");
var attachVendorUsageOverview = require("../lib/vendor-usage-overview").attachVendorUsageOverview;
var usageService = require("../lib/vendor-usage-service");
var metrics = require("../lib/vendor-usage-metrics");

function fixture(options) {
  options = options || {};
  var calls = [];
  var overviewCtx = {
    slug: "alpha", sm: { sessions: new Map(), installedVendors: ["codex", "kimi", "antigravity"] }, clients: new Set(),
    usersModule: { isMultiUser: function () { return options.multiUser === true; }, findUserById: function (id) { return { id: id }; }, canAccessProject: function () { return true; } },
    getProjectAccess: function () { return {}; }, sendTo: function () {},
    usageService: usageService.createUsageService({
      multiUser: function () { return options.multiUser === true; }, osUsersEnabled: function () { return !!options.osUsers; },
      getAdapter: function () { return {}; },
      readers: {
        codex: function (context) { calls.push({ vendor: "codex", linuxUser: context.linuxUser }); return Promise.resolve({ metrics: [metrics.metric("percent", "p", "P", { usedPercent: 12 })] }); },
        kimi: function () { calls.push({ vendor: "kimi" }); return Promise.resolve({ metrics: [metrics.metric("count", "k", "K", { used: 1, limit: 5, remaining: 4 })] }); },
      },
    }),
    getLinuxUserForWs: function () { return null; }, osUsers: options.osUsers,
  };
  var overview = attachVendorUsageOverview(overviewCtx);
  var state = { principal: { userId: "alice" }, project: { readVendorUsage: null }, authorized: true, resolveSlug: "target" };
  var project = {
    readVendorUsage: function (request) {
      calls.push({ request: request });
      return overview.readForOwner({ owner: request.owner, linuxUser: options.linuxUser || null, installed: { codex: true, kimi: true, antigravity: true }, isCurrent: request.isCurrent });
    },
  };
  state.project = project;
  var bound = control.attachClayVendorUsage({
    authorize: function () { if (!state.authorized) throw new Error("Source no longer authorized."); },
    multiUser: function () { return options.multiUser === true; },
    resolve: function (slug) { if (slug !== "target") throw new Error("Selected records require an owned ordinary project with live access."); return { principal: state.principal, project: state.project, status: {} }; },
  });
  return { bound: bound, state: state, calls: calls, project: project };
}

test("the tool reads the owner's own usage through the shared service and keeps units and reasons", async function () {
  var f = fixture({ multiUser: true, osUsers: true, linuxUser: "u_alice" });
  var result = await f.bound.readVendorUsage({ projectSlug: "target" });
  assert.equal(result.status, "completed");
  var byVendor = {};
  result.vendors.forEach(function (v) { byVendor[v.vendor] = v; });
  assert.equal(f.calls.filter(function (c) { return c.request; })[0].request.owner, "alice", "the owner is derived from the live principal, not an argument");
  assert.equal(byVendor.codex.account.metrics[0].unit, "percent");
  assert.equal(byVendor.codex.capability.mode, "query");
  assert.equal(byVendor.kimi.account.status, "refused", "a server-user credential is not read for an account-mode owner");
  assert.equal(byVendor.kimi.account.failureKind, "identity_unprovable");
  assert.equal(byVendor.antigravity.account.status, "unintegrated");
  assert.match(byVendor.antigravity.capability.reason, /^Not integrated:/);
  assert.equal(f.calls.filter(function (c) { return c.vendor === "kimi"; }).length, 0, "no reader ran for a refused vendor");
  assert.equal(f.calls.find(function (c) { return c.vendor === "codex"; }).linuxUser, "u_alice");
  assert.doesNotMatch(JSON.stringify(result), /Bearer|access_token|SECRET/);
});

test("single-user canonical reads use the single local owner", async function () {
  var f = fixture({ multiUser: false });
  var result = await f.bound.readVendorUsage({ projectSlug: "target" });
  assert.equal(f.calls.filter(function (c) { return c.request; })[0].request.owner, "default");
  assert.equal(result.vendors.filter(function (v) { return v.vendor === "kimi"; })[0].account.status, "ok");
});

test("only an exact projectSlug is accepted: no user, credential, URL, command, refresh or settings argument", async function () {
  var f = fixture();
  for (var args of [undefined, {}, { projectSlug: "" }, { projectSlug: "target", owner: "bob" }, { projectSlug: "target", force: true }, { projectSlug: "target", url: "https://x" }, { projectSlug: "target", vendor: "kimi" }, { projectSlug: 5 }]) {
    await assert.rejects(f.bound.readVendorUsage(args), /Choose an exact owned ordinary project/);
  }
  assert.equal(f.calls.length, 0);
});

test("an unowned, foreign or private project is refused by the shared project resolver, and a revoked source reads nothing", async function () {
  var f = fixture();
  await assert.rejects(f.bound.readVendorUsage({ projectSlug: "someone-elses" }), /owned ordinary project/);
  f.state.authorized = false;
  await assert.rejects(f.bound.readVendorUsage({ projectSlug: "target" }), /no longer authorized/);
  assert.equal(f.calls.length, 0);
});

test("the result is withheld when the project or access changes while usage is read", async function () {
  var f = fixture({ multiUser: true });
  var pending = f.bound.readVendorUsage({ projectSlug: "target" });
  f.state.project = { readVendorUsage: f.project.readVendorUsage };
  await assert.rejects(pending, /changed while usage was read/);
  var g = fixture({ multiUser: true });
  var second = g.bound.readVendorUsage({ projectSlug: "target" });
  g.state.principal = { userId: "mallory" };
  await assert.rejects(second, /changed while usage was read/);
  var h = fixture();
  var third = h.bound.readVendorUsage({ projectSlug: "target" });
  h.state.authorized = false;
  await assert.rejects(third, /changed while usage was read/);
});

test("a project without the service reports it unavailable rather than guessing", async function () {
  var f = fixture();
  f.state.project = {};
  await assert.rejects(f.bound.readVendorUsage({ projectSlug: "target" }), /unavailable for this project/);
});

test("the tool is in the typed catalog, both SDK and hook allowlists and the friendly presentation, and is read-only", function () {
  var defs = tools.getToolDefs(null);
  var tool = defs.filter(function (t) { return t.name === "read_vendor_usage"; })[0];
  assert.ok(tool);
  assert.deepEqual(Object.keys(tool.inputSchema), ["projectSlug"]);
  assert.equal(defs.filter(function (t) { return /vendor_usage/.test(t.name); }).length, 1, "no inspect or control twin exists: nothing here mutates");
  var root = path.join(__dirname, "..", "lib");
  assert.match(fs.readFileSync(path.join(root, "sdk-bridge.js"), "utf8"), /"mcp__clay-workspace__read_vendor_usage": true/);
  assert.match(fs.readFileSync(path.join(root, "yoke", "claude-hook-installer.js"), "utf8"), /"mcp__clay-workspace__read_vendor_usage"/);
  assert.match(fs.readFileSync(path.join(root, "public", "modules", "clay-tool-presentation.js"), "utf8"), /\['read_vendor_usage', 'Reading vendor usage'/);
  var source = fs.readFileSync(path.join(root, "clay-vendor-usage.js"), "utf8");
  assert.doesNotMatch(source, /fetch\(|child_process|readFile|WebSocket|ws\.send|force:/);
});

test("an unbound tool call fails closed", async function () {
  var tool = tools.getToolDefs(null).filter(function (t) { return t.name === "read_vendor_usage"; })[0];
  var out = await tool.handler({ projectSlug: "target" });
  assert.equal(out.isError, true);
});