Ctrl K
ComunidadGuías…

electron/cloud-send-team.node-test.mjs

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

Archivo original ↗Preguntar a KiBot
import assert from "node:assert/strict";
import test from "node:test";

import { EMPTY, itemKey } from "./cloud-send-parts.mjs";
import { createCloudSend } from "./cloud-send.mjs";

const TEAM = "https://omb-u-acme.fly.dev";
const OWNER = "p_mycloudownerkeyxxxxxxx";
const json = (value, status = 200) => new Response(JSON.stringify(value), { status });
const reply = (status, body) => ({ status, ok: status < 400, body });
const summary = (items) => ({ v: 1, appVersion: "0.1.121", items, chats: 1 });
const scout = { key: itemKey.bot("scout"), kind: "bot", label: "Scout", id: "scout", parts: { soul: "s1", name: "n1" } };

/** My Cloud as the source of one bot's move (every read it got), and a team that keeps what it is sent (every call). */
function sides() {
  const reads = [], calls = [];
  const there = new Map();
  const local = async (route) => {
    reads.push(route);
    const bare = route.replace(/[?&]bot=scout$/u, "");
    if (bare === "/api/cloud-send?move=1") return json(summary(route.includes("bot=scout") ? [scout] : [scout, { key: "login:x|y", kind: "login", label: "x", parts: { saved: "1" } }]));
    if (bare === "/api/bots?messages=0") return json({ bots: [{ id: "scout", name: "Scout", threadId: "scout-main", soul: "Plans trips." }] });
    if (/^\/api\/bots\/scout\/skills$/u.test(bare)) return json({ skills: [] });
    if (bare === "/api/cloud-send/files") return json({ v: 1, files: [] });
    if (bare === "/api/cloud-send/chats?attachments=1") return json({ v: 1, attachments: [] });
    if (bare === "/api/cloud-send/chats") return json({ v: 1, dataDir: "/mycloud", owner: OWNER, conversations: [{ bot: "scout", threadId: "scout-main", last: 1, lastId: "r1", busy: false, settings: {} }] });
    if (bare.startsWith("/api/cloud-send/chats/rows?thread=scout-main")) return json({ rows: [{ id: "r1", at: 1, role: "user", text: "hi", sender: { id: OWNER, name: "Ada" } }], leaf: "r1", task: null, last: 1, lastId: "r1", more: false, attachments: [] });
    if (bare.startsWith("/api/cloud-send/chats/ids?thread=scout-main")) return json({ v: 1, ids: ["r1"], path: ["r1"], leaf: "r1", more: false });
    if (bare === "/api/cloud-send/manifest") return json({ v: 1, items: [scout], conversations: [{ threadId: "scout-main", bot: "scout", rows: 1, newest: "r1", settings: {} }], attachments: [], files: [], automations: [], runs: [] });
    return json({}, 404);
  };
  const session = {
    call: async (method, route, body) => {
      calls.push([method, route, body]);
      if (route === "/.well-known/openmausbot/environment") return reply(200, { capabilities: { cloudHome: true, move: 1 } });
      if (route.startsWith("/api/cloud-send?")) return reply(200, summary([...there.values()]));
      if (method === "POST" && route === "/api/bots") { there.set(itemKey.bot(body.id), { ...scout, parts: { soul: EMPTY, name: "n2" } }); return reply(201, { bot: { id: body.id } }); }
      if (method === "PATCH" && route === "/api/bots/scout") { if (body.soul) there.get(scout.key).parts.soul = "s1"; return reply(200, {}); }
      if (route.startsWith("/api/cloud-send/files")) return reply(200, { v: 1, files: [], space: { freeBytes: 1e12, volumeBytes: 1e12 } });
      if (method === "GET" && route.startsWith("/api/cloud-send/chats")) return reply(200, { v: 1, conversations: [{ threadId: "scout-main", settings: {} }] });
      if (route === "/api/cloud-send/chats") return reply(200, { conversations: 1, messages: 1, accepted: body.conversations.map((entry) => entry.threadId), waiting: [], removed: [] });
      if (route === "/api/cloud-send/chats/verify") return reply(200, { v: 1, conversations: [{ threadId: "scout-main", missing: [], unstamped: 0, path: { holds: true, at: "r1", leaf: "r1", length: 1 } }] });
      if (route.startsWith("/api/cloud-send/manifest")) return reply(200, { v: 1, items: [...there.values()], conversations: [{ threadId: "scout-main", bot: "scout", settings: {} }], attachments: [], files: [], automations: [], runs: [] });
      return reply(200, {});
    },
    upload: async () => reply(201, {}),
    close: async () => {},
  };
  let state = null;
  const send = createCloudSend({
    local,
    cloud: { origin: () => TEAM, asleep: () => false, read: async () => json({}, 404), open: async () => session },
    handoff: async (what) => { calls.push(["HANDOFF", what.kind]); throw new Error("nothing personal moves into a team"); },
    store: { read: () => state, write: (value) => { state = structuredClone(value); } },
    team: { bot: "scout", name: "Scout (Ada)", label: "Ada" },
  });
  return { send, reads, calls };
}

test("a bot moving into a team carries its own things only: no apps, keys, logins, settings or notes, every read kept to it", async () => {
  const { send, reads, calls } = sides();
  await send.send({ reason: "move" });
  const routes = calls.map(([method, route]) => `${method} ${route}`);
  for (const personal of ["/api/cloud-connections", "/api/cloud-send/memory", "/api/logins", "/api/config", "/api/cloud-send/verify-secrets"]) {
    assert.ok(!routes.some((route) => route.includes(personal)), personal);
    assert.ok(!reads.some((route) => route.includes(personal)), personal);
  }
  assert.ok(!calls.some(([kind]) => kind === "HANDOFF"), "no secret is asked for");
  for (const route of reads.filter((read) => /^\/api\/cloud-send(?:\?|\/manifest|\/files$|\/files\?|\/chats$|\/chats\?)/u.test(read))) assert.match(route, /[?&]bot=scout$/u, route);
  assert.ok(routes.includes("GET /api/cloud-send?move=1&bot=scout"), "the team's side is read kept to it too");
  const made = calls.find(([method, route]) => method === "POST" && route === "/api/bots")[2];
  assert.equal(made.threadId, undefined, "its main chat stays the team's own");
  assert.equal(made.name, "Scout (Ada)");
  const sent = calls.find(([method, route]) => method === "POST" && route === "/api/cloud-send/chats")[2];
  assert.equal(sent.owner, OWNER, "the team learns whose lines become the mover's");
  const report = await send.check();
  assert.deepEqual(report.secrets, { equal: [], differs: [], missing: [] });
  assert.ok(calls.some(([method, route]) => method === "GET" && /^\/api\/cloud-send\/manifest\?(?:[\w=&]+&)?bot=scout$/u.test(route)));
});