Fresh history cut from cynarAI/evoo antigravity-handoff/project-timeline (Voice First + project timeline). Brand docs/titles as evOo; keep @rakazo/* packages as tech debt. Excludes node_modules, caches, secrets, voice blobs.
210 lines
7.3 KiB
TypeScript
210 lines
7.3 KiB
TypeScript
import { createCipheriv, createHash } from "node:crypto";
|
|
import { describe, expect, it } from "vitest";
|
|
import { FakeSandboxProvider } from "./fake-sandbox.js";
|
|
import { inferScript, ScriptedAgentRuntime } from "./scripted-runtime.js";
|
|
import { EncryptedSecretStore } from "./secrets.js";
|
|
|
|
describe("secret store", () => {
|
|
it("round-trips and never stores plaintext in ciphertext", async () => {
|
|
const store = new EncryptedSecretStore("test-key");
|
|
const record = await store.put("sk-or-v1-secretvalue", {
|
|
operationId: "1",
|
|
traceId: "1",
|
|
spaceId: "w",
|
|
userId: "u",
|
|
signal: new AbortController().signal,
|
|
});
|
|
expect(record.ciphertext).not.toContain("sk-or-v1-secretvalue");
|
|
expect(record.ciphertext).toMatch(/^v2:/);
|
|
expect(store.load(record.ciphertext, record.id)).toBe("sk-or-v1-secretvalue");
|
|
expect(() => store.load(record.ciphertext, "another-row")).toThrow();
|
|
});
|
|
|
|
it("keeps legacy ciphertext readable without rewriting it at startup", () => {
|
|
const key = "legacy-test-key";
|
|
const iv = Buffer.alloc(12, 7);
|
|
const cipher = createCipheriv("aes-256-gcm", createHash("sha256").update(key).digest(), iv);
|
|
const encrypted = Buffer.concat([cipher.update("legacy-secret", "utf8"), cipher.final()]);
|
|
const legacy = Buffer.concat([iv, cipher.getAuthTag(), encrypted]).toString("base64");
|
|
const store = new EncryptedSecretStore(key);
|
|
expect(store.load(legacy, "secret-row")).toBe("legacy-secret");
|
|
});
|
|
});
|
|
|
|
describe("scripted runtime", () => {
|
|
it("requests takeover for login work", () => {
|
|
const script = inferScript("install the cli and sign in");
|
|
expect(script?.some((t) => t.takeover)).toBe(true);
|
|
});
|
|
|
|
it("resumes after takeover without asking again", () => {
|
|
const script = inferScript("install the cli and sign in", "takeover");
|
|
expect(script?.some((t) => t.takeover)).toBe(false);
|
|
expect(script?.some((t) => t.complete)).toBe(true);
|
|
});
|
|
|
|
it("resumes a skipped takeover without treating login as done", () => {
|
|
const script = inferScript("install the cli and sign in", "takeover-skipped");
|
|
expect(script?.some((t) => t.takeover)).toBe(false);
|
|
expect(script?.some((t) => t.assistant?.includes("login was skipped"))).toBe(true);
|
|
});
|
|
|
|
it("does not infer a takeover checkpoint from ordinary task text", () => {
|
|
const script = inferScript("ask me whether to record 'skipped the login'");
|
|
expect(script?.some((t) => t.assistant?.includes("decision"))).toBe(true);
|
|
expect(script?.some((t) => t.assistant?.includes("login was skipped"))).toBe(false);
|
|
});
|
|
|
|
it("routes destination/crm work through the connector", () => {
|
|
const script = inferScript("write this to the destination crm as a note");
|
|
expect(script?.some((t) => t.toolCalls?.some((c) => c.name === "destination.write"))).toBe(
|
|
true,
|
|
);
|
|
});
|
|
|
|
it("spawns a named bot", () => {
|
|
const script = inferScript("spawn a bot named Scout to research venues");
|
|
expect(script?.some((t) => t.toolCalls?.some((c) => c.name === "spawn_bot"))).toBe(true);
|
|
expect(script?.some((t) => t.toolCalls?.some((c) => c.args.name === "Scout"))).toBe(true);
|
|
});
|
|
|
|
it("proposes a named space", () => {
|
|
const script = inferScript("create a space named Customer support");
|
|
expect(
|
|
script?.some((turn) =>
|
|
turn.toolCalls?.some(
|
|
(call) => call.name === "create_space" && call.args.name === "Customer support",
|
|
),
|
|
),
|
|
).toBe(true);
|
|
});
|
|
|
|
it("runs an in-thread subagent", () => {
|
|
const script = inferScript("run a subagent to summarize the notes");
|
|
expect(script?.some((t) => t.toolCalls?.some((c) => c.name === "run_subagent"))).toBe(true);
|
|
});
|
|
|
|
it("asks when it needs a decision", () => {
|
|
const script = inferScript("ask me which city to use");
|
|
expect(script?.some((t) => t.ask?.text.toLowerCase().includes("city"))).toBe(true);
|
|
});
|
|
|
|
it("stops hang work when aborted", async () => {
|
|
const runtime = new ScriptedAgentRuntime();
|
|
const ctx = {
|
|
operationId: "1",
|
|
traceId: "1",
|
|
spaceId: "w",
|
|
userId: "u",
|
|
signal: new AbortController().signal,
|
|
};
|
|
const types: string[] = [];
|
|
const iterating = (async () => {
|
|
for await (const event of runtime.run(
|
|
{
|
|
botId: "b",
|
|
threadId: "t",
|
|
runId: "hang-1",
|
|
prompt: "keep working until I stop you",
|
|
instructions: "",
|
|
history: [],
|
|
tools: [],
|
|
model: { provider: "scripted", id: "scripted" },
|
|
},
|
|
ctx,
|
|
)) {
|
|
types.push(event.type);
|
|
if (event.type === "progress") await runtime.abort("hang-1");
|
|
}
|
|
})();
|
|
await iterating;
|
|
expect(types).toContain("progress");
|
|
expect(types.at(-1)).toBe("done");
|
|
});
|
|
|
|
it("attaches a workspace file into the thread", () => {
|
|
const script = inferScript("write notes/result.txt and attach it to the thread");
|
|
expect(script?.some((t) => t.toolCalls?.some((c) => c.name === "write_file"))).toBe(true);
|
|
expect(script?.some((t) => t.toolCalls?.some((c) => c.name === "attach_file"))).toBe(true);
|
|
});
|
|
|
|
it("observes the screen when asked", () => {
|
|
const script = inferScript("observe your screen and type writer-desk");
|
|
expect(script?.some((t) => t.toolCalls?.some((c) => c.name === "computer_observe"))).toBe(true);
|
|
expect(
|
|
script?.some((t) =>
|
|
t.toolCalls?.some(
|
|
(c) =>
|
|
c.name === "computer_act" &&
|
|
Array.isArray(c.args.actions) &&
|
|
c.args.actions.some(
|
|
(action) =>
|
|
action &&
|
|
typeof action === "object" &&
|
|
"kind" in action &&
|
|
"text" in action &&
|
|
action.kind === "type" &&
|
|
action.text === "writer-desk",
|
|
),
|
|
),
|
|
),
|
|
).toBe(true);
|
|
});
|
|
|
|
it("archives a spawned bot by exact name", () => {
|
|
const script = inferScript("delete the bot named Scout");
|
|
expect(
|
|
script?.some((t) =>
|
|
t.toolCalls?.some((c) => c.name === "archive_bot" && c.args.confirm_name === "Scout"),
|
|
),
|
|
).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe("builtin tools", () => {
|
|
it("exposes the tools the executor actually applies", async () => {
|
|
const { builtinAgentTools } = await import("./builtin-tools.js");
|
|
expect(builtinAgentTools.map((t) => t.name)).toEqual(
|
|
expect.arrayContaining([
|
|
"write_file",
|
|
"attach_file",
|
|
"shell",
|
|
"remember",
|
|
"request_takeover",
|
|
"ask_user",
|
|
"message_user",
|
|
"request_secret",
|
|
"run_subagent",
|
|
"create_space",
|
|
"spawn_bot",
|
|
"archive_bot",
|
|
"skill_read",
|
|
"skill_create",
|
|
"skill_update",
|
|
"skill_delete",
|
|
"web_search",
|
|
"web_fetch",
|
|
"browser_navigate",
|
|
"browser_snapshot",
|
|
"browser_act",
|
|
]),
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("fake sandbox", () => {
|
|
it("provisions isolated computers", async () => {
|
|
const sandbox = new FakeSandboxProvider();
|
|
const ctx = {
|
|
operationId: "1",
|
|
traceId: "1",
|
|
spaceId: "w",
|
|
userId: "u",
|
|
signal: new AbortController().signal,
|
|
};
|
|
const a = await sandbox.provision({ botId: "a", homePath: "/tmp/a" }, ctx);
|
|
const b = await sandbox.provision({ botId: "b", homePath: "/tmp/b" }, ctx);
|
|
expect(a.id).not.toBe(b.id);
|
|
});
|
|
});
|