Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| Chat and workspace agents: channels, DMs and named agents you talk to | 1 | import assert from "node:assert/strict"; |
| 2 | import { test } from "node:test"; | |
| 3 | ||
| 4 | import type { User } from "@g1t/contracts"; | |
| 5 | ||
| 6 | import { canManage, canSee } from "./access.ts"; | |
| 7 | import { DEFAULT_AUTONOMY, DEFAULT_CAPACITY, applyChanges, readJson } from "./definition.ts"; | |
| 8 | import { TEMPLATES, TEMPLATE_IDS } from "./templates.ts"; | |
| 9 | ||
| 10 | const input = { handle: "Ship", display_name: " Ship ", role: "Release manager", instructions: "Cut releases." }; | |
| 11 | ||
| 12 | test("a new agent gets safe defaults", () => { | |
| 13 | const made = applyChanges(null, input, TEMPLATE_IDS); | |
| 14 | assert.ok(made.ok); | |
| 15 | if (!made.ok) return; | |
| 16 | assert.equal(made.value.handle, "ship"); | |
| 17 | assert.equal(made.value.display_name, "Ship"); | |
| 18 | assert.equal(made.value.personality_preset, "crisp"); | |
| 19 | assert.equal(made.value.capacity, DEFAULT_CAPACITY); | |
| 20 | assert.deepEqual(made.value.autonomy, DEFAULT_AUTONOMY); | |
| 21 | assert.equal(made.value.autonomy.merge, "approval"); | |
| 22 | assert.deepEqual(made.value.routing, { floor: null, ceiling: null, providers: [], pinned: null }); | |
| 23 | }); | |
| 24 | ||
| 25 | test("a new agent needs a handle, a name, a role and instructions", () => { | |
| 26 | for (const missing of ["handle", "display_name", "role", "instructions"] as const) { | |
| 27 | const made = applyChanges(null, { ...input, [missing]: "" }, TEMPLATE_IDS); | |
| 28 | assert.equal(made.ok, false, missing); | |
| 29 | } | |
| 30 | assert.equal(applyChanges(null, { ...input, handle: "g1t" }, TEMPLATE_IDS).ok, false); | |
| 31 | }); | |
| 32 | ||
| 33 | test("a change merges onto the definition, and is checked", () => { | |
| 34 | const made = applyChanges(null, input, TEMPLATE_IDS); | |
| 35 | assert.ok(made.ok); | |
| 36 | if (!made.ok) return; | |
| 37 | const changed = applyChanges(made.value, { routing: { floor: "large" }, budget: { monthly_micros: 5_000_000 }, autonomy: { merge: "never" } }, TEMPLATE_IDS); | |
| 38 | assert.ok(changed.ok); | |
| 39 | if (!changed.ok) return; | |
| 40 | assert.equal(changed.value.handle, "ship", "untouched fields stay"); | |
| 41 | assert.equal(changed.value.routing.floor, "large"); | |
| 42 | assert.equal(changed.value.routing.ceiling, null); | |
| 43 | assert.equal(changed.value.budget.monthly_micros, 5_000_000); | |
| 44 | assert.equal(changed.value.budget.daily_micros, null); | |
| 45 | assert.equal(changed.value.autonomy.merge, "never"); | |
| 46 | assert.equal(changed.value.autonomy.open_pull_requests, "alone"); | |
| 47 | ||
| 48 | const bad = (changes: object) => applyChanges(made.value, changes, TEMPLATE_IDS).ok; | |
| 49 | assert.equal(bad({ routing: { floor: "frontier", ceiling: "small" } }), false, "floor above ceiling"); | |
| 50 | assert.equal(bad({ routing: { floor: "huge" } }), false); | |
| 51 | assert.equal(bad({ routing: { pinned: "no-slash" } }), false); | |
| 52 | assert.equal(bad({ budget: { monthly_micros: -1 } }), false); | |
| 53 | assert.equal(bad({ budget: { daily_micros: 1.5 } }), false); | |
| 54 | assert.equal(bad({ autonomy: { deploy_production: "alone" } }), false, "production deploys always ask"); | |
| 55 | assert.equal(bad({ capacity: 0 }), false); | |
| 56 | assert.equal(bad({ capacity: 11 }), false); | |
| 57 | assert.equal(bad({ personality_preset: "pirate" }), false); | |
| 58 | assert.equal(bad({ template: "nope" }), false); | |
| 59 | assert.equal(bad({ template: "reviewer" }), true); | |
| 60 | for (const providers of [[], ["g1t"], ["workspace"], ["int_1"], ["g1t", "workspace"]]) assert.equal(bad({ routing: { providers } }), true, JSON.stringify(providers)); | |
| 61 | assert.equal(bad({ routing: { providers: [""] } }), false); | |
| 62 | assert.equal(bad({ instructions: "x".repeat(8001) }), false); | |
| 63 | }); | |
| 64 | ||
| 65 | test("a stored JSON column that cannot be read is the default", () => { | |
| 66 | assert.deepEqual(readJson("{bad", { a: 1 }), { a: 1 }); | |
| 67 | assert.deepEqual(readJson('{"b":2}', { a: 1 }), { a: 1, b: 2 }); | |
| 68 | assert.deepEqual(readJson(null, { a: 1 }), { a: 1 }); | |
| 69 | }); | |
| 70 | ||
| 71 | test("every template is a valid definition with the routing its job needs", () => { | |
| 72 | assert.deepEqual(TEMPLATE_IDS, ["planner", "implementer", "reviewer", "triage", "documenter", "release-manager", "on-call"]); | |
| 73 | for (const template of TEMPLATES) { | |
| 74 | const made = applyChanges(null, { ...template, template: template.id }, TEMPLATE_IDS); | |
| 75 | assert.ok(made.ok, template.id); | |
| 76 | } | |
| 77 | const byId = Object.fromEntries(TEMPLATES.map((t) => [t.id, t])); | |
| 78 | assert.equal(byId.reviewer.routing.floor, "large"); | |
| 79 | assert.equal(byId.triage.routing.ceiling, "large"); | |
| 80 | assert.equal(new Set(TEMPLATES.map((t) => t.handle)).size, TEMPLATES.length, "handles are distinct"); | |
| 81 | }); | |
| 82 | ||
| 83 | test("members see a workspace's agents; owners change them", () => { | |
| 84 | const person = (role: "owner" | "member"): User => ({ id: "u", username: "u", workspaces: [{ slug: "acme", role }] }) as User; | |
| 85 | assert.ok(canSee(person("member"), "ACME")); | |
| 86 | assert.ok(!canManage(person("member"), "acme")); | |
| 87 | assert.ok(canManage(person("owner"), "acme")); | |
| 88 | assert.ok(!canSee(person("owner"), "other")); | |
| 89 | assert.ok(!canSee(null, "acme")); | |
| 90 | const token = { id: "w", username: "acme", kind: "workspace" } as User; | |
| 91 | assert.ok(canManage(token, "acme"), "the workspace's own token"); | |
| 92 | assert.ok(!canSee(token, "other")); | |
| 93 | }); |