Skip to content
164 linesCodeBlameRaw
1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import { FOUNDATIONAL_SKILL_IDS } from "../../../packages/contracts/src/skills.ts";
5
6import {
7 BUILDER_HANDLE,
8 draftSystem,
9 freeHandle,
10 handleFrom,
11 jsonIn,
12 proposalFrom,
13 redraftFrom,
14 startingBudget,
15 trySystem,
16 tryTurns,
17 wordsOf,
18} from "./builder.ts";
19import { applyChanges } from "./definition.ts";
20import { checkHandle } from "./handle.ts";
21import { TEMPLATE_IDS } from "./templates.ts";
22
23const drafted = {
24 display_name: "Juniper",
25 name_ideas: ["Wren", "Juniper", "Basil", "!!"],
26 title: "Release Manager",
27 department: "Engineering",
28 instructions: "You cut releases.\n- Read merged pull requests since the last tag.\n- Write the notes.",
29 responsibilities: ["Cut a release every Tuesday", "Write the release notes", "Ask in #releases before tagging"],
30 personality_preset: "friendly",
31 personality: "Short sentences.",
32 skills: ["documents", "code", "made-up"],
33 integrations: [{ id: "linear", why: "Reads the issues a release closes." }, { id: "nope", why: "x" }, { id: "linear", why: "twice" }],
34 routines: [{ name: "Tuesday release", when: "Every Tuesday at 10:00", instructions: "Cut the release." }, { name: "", when: "" }],
35 floor: "frontier",
36 ceiling: "small",
37};
38
39test("a description becomes a complete definition that create takes as it is", () => {
40 const made = proposalFrom(drafted, { scope: "personal", taken: new Set(), budget: startingBudget("personal", null) });
41 assert.ok(made.ok);
42 const { definition } = made.value;
43 assert.equal(definition.handle, "juniper");
44 assert.equal(definition.display_name, "Juniper");
45 assert.equal(definition.scope, "personal");
46 assert.equal(definition.team, null, "a draft is on no team");
47 assert.deepEqual(definition.budget, { monthly_micros: 20_000_000, daily_micros: null, task_micros: 2_000_000 }, "$20 a month, $2 a session");
48 assert.deepEqual(definition.routing, { floor: null, ceiling: "small", providers: [], pinned: null }, "a floor above the ceiling is dropped");
49 assert.deepEqual(made.value.skills, ["documents", "code"], "unknown skills are left out");
50 assert.deepEqual(definition.skills_off, FOUNDATIONAL_SKILL_IDS.filter((id) => id !== "documents" && id !== "code"));
51 assert.deepEqual(made.value.integrations, [{ id: "linear", why: "Reads the issues a release closes." }], "only the catalog's, once each");
52 assert.equal(made.value.routines.length, 1);
53 assert.deepEqual(made.value.name_ideas, ["Wren", "Basil"]);
54 const { scope: _scope, ...input } = definition;
55 assert.ok(applyChanges(null, input, TEMPLATE_IDS).ok);
56});
57
58test("a draft takes a free handle, and a workspace draft the workspace's default budget", () => {
59 const made = proposalFrom(drafted, { scope: "workspace", taken: new Set(["juniper", "juniper-2"]), budget: startingBudget("workspace", 30_000_000) });
60 assert.ok(made.ok);
61 assert.equal(made.value.definition.handle, "juniper-3");
62 assert.deepEqual(made.value.definition.budget, { monthly_micros: 30_000_000, daily_micros: null, task_micros: null });
63});
64
65test("a draft with every skill unnamed keeps them all on; one with no job can't be created", () => {
66 const all = proposalFrom({ ...drafted, skills: [] }, { scope: "workspace", taken: new Set(), budget: startingBudget("workspace", null) });
67 assert.ok(all.ok);
68 assert.deepEqual(all.value.definition.skills_off, []);
69 assert.equal(proposalFrom({ ...drafted, instructions: "" }, { scope: "workspace", taken: new Set(), budget: startingBudget("workspace", null) }).ok, false);
70 assert.equal(proposalFrom(null, { scope: "workspace", taken: new Set(), budget: startingBudget("workspace", null) }).ok, false);
71});
72
73test("the model's answer is read fenced or bare, and junk is nothing", () => {
74 assert.deepEqual(jsonIn('```json\n{"a": 1}\n```'), { a: 1 });
75 assert.deepEqual(jsonIn('Here it is: {"a": {"b": 2}} done'), { a: { b: 2 } });
76 assert.equal(jsonIn("no json"), null);
77 assert.equal(jsonIn("[1, 2]"), null);
78});
79
80test("handles come from names, and are never reserved", () => {
81 assert.equal(handleFrom("Margo Lee"), "margo-lee");
82 assert.equal(handleFrom("Zoë"), "zoe");
83 assert.ok(checkHandle(freeHandle("g1t", new Set())).ok);
84 assert.ok(checkHandle(freeHandle("New", new Set())).ok);
85 assert.equal(checkHandle(BUILDER_HANDLE).ok, false, "the builder's bill name is no agent's handle");
86});
87
88const before = (() => {
89 const made = applyChanges(
90 null,
91 {
92 handle: "juniper",
93 display_name: "Juniper",
94 title: "Release Manager",
95 instructions: "You cut releases.",
96 responsibilities: ["Cut releases", "Write notes"],
97 budget: { monthly_micros: 20_000_000, task_micros: 2_000_000 },
98 },
99 TEMPLATE_IDS,
100 );
101 assert.ok(made.ok);
102 return made.value;
103})();
104
105test("a change in words keeps only what differs", () => {
106 const changed = redraftFrom(
107 { display_name: "Juniper", instructions: "You cut releases. Answer in Spanish.", monthly_dollars: 50, session_dollars: 2, summary: "Answers in Spanish; $50 a month." },
108 before,
109 false,
110 );
111 assert.ok(changed.ok);
112 assert.deepEqual(changed.value.changes, { instructions: "You cut releases. Answer in Spanish.", budget: { monthly_micros: 50_000_000 } });
113 assert.equal(changed.value.summary, "Answers in Spanish; $50 a month.");
114});
115
116test("renaming moves a handle that followed the name, and @g1t keeps who it is", () => {
117 const renamed = redraftFrom({ display_name: "Wren", summary: "Renamed." }, before, false);
118 assert.ok(renamed.ok);
119 assert.deepEqual(renamed.value.changes, { display_name: "Wren", handle: "wren" });
120 const builtin = redraftFrom({ display_name: "Boss", title: "Chief", personality: "Dry." }, before, true);
121 assert.ok(builtin.ok);
122 assert.deepEqual(builtin.value.changes, { personality: "Dry." });
123});
124
125test("a change that asks for nothing says so", () => {
126 const none = redraftFrom({ summary: "" }, before, false);
127 assert.equal(none.ok, false);
128 assert.equal(redraftFrom({ instructions: "" }, before, false).ok, false, "a job is never emptied");
129});
130
131test("Try it takes alternating turns that end with the person's", () => {
132 const turns = tryTurns([
133 { role: "assistant", content: "hi" },
134 { role: "user", content: "one" },
135 { role: "user", content: "two" },
136 { role: "assistant", content: "ok" },
137 { role: "user", content: "three" },
138 ]);
139 assert.ok(turns.ok);
140 assert.deepEqual(turns.value, [
141 { role: "user", content: "one\n\ntwo" },
142 { role: "assistant", content: "ok" },
143 { role: "user", content: "three" },
144 ]);
145 assert.equal(tryTurns([{ role: "user", content: "a" }, { role: "assistant", content: "b" }]).ok, false);
146 assert.equal(tryTurns([]).ok, false);
147 assert.equal(tryTurns(Array.from({ length: 30 }, () => ({ role: "user", content: "x" }))).ok, false);
148});
149
150test("Try it speaks with the agent's own prompt, said to be a preview with no tools", () => {
151 const prompt = trySystem({ workspace: "acme", definition: before, asker: { username: "ana" }, today: new Date("2026-10-10T00:00:00Z") });
152 assert.match(prompt, /You are Juniper \(@juniper\)/);
153 assert.match(prompt, /This is a preview/);
154 assert.match(prompt, /You can only read this conversation right now/);
155 assert.match(draftSystem("acme", "personal"), /personal agent/);
156 assert.match(draftSystem("acme", "workspace"), /linear: Linear/);
157});
158
159test("descriptions and requests are checked", () => {
160 assert.equal(wordsOf("", "description").ok, false);
161 assert.equal(wordsOf("x".repeat(2001), "description").ok, false);
162 assert.equal(wordsOf("x".repeat(1001), "request").ok, false);
163 assert.deepEqual(wordsOf(" Cut releases ", "description"), { ok: true, value: "Cut releases" });
164});