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.
| Anyone makes an agent by describing it: one box drafts the whole agent (name, job, responsibilities, voice, skills to keep, integrations it needs, model limits and budget) as a card to change and try in a chat beside it before creating it, and an agent changes later by saying what to change, shown as a diff before it's saved. Members can make personal agents, which only they talk to and which spend from their own budget, unless owners turn that off; owners promote one to a workspace agent. The agents guide says how. | 1 | import assert from "node:assert/strict"; |
| 2 | import { test } from "node:test"; | |
| 3 | ||
| 4 | import { canArchive, canChange, canSeeAgent, creatableScope, personalRefusal } from "./access.ts"; | |
| 5 | ||
| 6 | const owner = { id: "u0", username: "olga", kind: "user" as const, workspaces: [{ slug: "acme", role: "owner" as const }] }; | |
| 7 | const ana = { id: "u1", username: "ana", kind: "user" as const, workspaces: [{ slug: "acme", role: "member" as const }] }; | |
| 8 | const bob = { id: "u2", username: "bob", kind: "user" as const, workspaces: [{ slug: "acme", role: "member" as const }] }; | |
| 9 | const token = { id: "w1", username: "acme", kind: "workspace" as const, workspaces: [] }; | |
| 10 | ||
| 11 | const anasAgent = { scope: "personal", owner_id: "u1" }; | |
| 12 | const shared = { scope: "workspace", owner_id: null }; | |
| 13 | ||
| 14 | test("members create personal agents while the workspace lets them; owners create either", () => { | |
| 15 | assert.deepEqual(creatableScope(ana, "acme", undefined, true), { ok: true, scope: "personal" }); | |
| 16 | assert.equal(creatableScope(ana, "acme", undefined, false).ok, false, "owners turned it off"); | |
| 17 | assert.equal(creatableScope(ana, "acme", "workspace", true).ok, false, "workspace agents are the owners'"); | |
| 18 | assert.deepEqual(creatableScope(owner, "acme", undefined, false), { ok: true, scope: "workspace" }); | |
| 19 | assert.deepEqual(creatableScope(owner, "acme", "personal", false), { ok: true, scope: "personal" }, "an owner may keep one for themselves"); | |
| 20 | assert.equal(creatableScope(token, "acme", "personal", true).ok, false, "a token is nobody's person"); | |
| 21 | assert.equal(creatableScope(ana, "other", undefined, true).ok, false); | |
| 22 | }); | |
| 23 | ||
| 24 | test("a personal agent is seen by its member and owners, and changed only by its member", () => { | |
| 25 | assert.equal(canSeeAgent(ana, "acme", anasAgent), true); | |
| 26 | assert.equal(canSeeAgent(owner, "acme", anasAgent), true); | |
| 27 | assert.equal(canSeeAgent(bob, "acme", anasAgent), false); | |
| 28 | assert.equal(canSeeAgent(bob, "acme", shared), true); | |
| 29 | assert.equal(canChange(ana, "acme", anasAgent), true); | |
| 30 | assert.equal(canChange(owner, "acme", anasAgent), false, "owners promote or archive it, not rewrite it"); | |
| 31 | assert.equal(canChange(ana, "acme", shared), false); | |
| 32 | assert.equal(canChange(owner, "acme", shared), true); | |
| 33 | assert.equal(canArchive(owner, "acme", anasAgent), true); | |
| 34 | assert.equal(canArchive(ana, "acme", anasAgent), true); | |
| 35 | assert.equal(canArchive(bob, "acme", anasAgent), false); | |
| 36 | }); | |
| 37 | ||
| 38 | test("a personal agent answers only its member, in the DM of the two of them", () => { | |
| 39 | assert.equal(personalRefusal(anasAgent, { asked_by: "u1", channel_kind: "dm", members: 2 }), null); | |
| 40 | assert.equal(personalRefusal(anasAgent, { asked_by: "u1", channel_kind: "dm", members: null }), null); | |
| 41 | assert.match(personalRefusal(anasAgent, { asked_by: "u2", channel_kind: "dm", members: 2 }) ?? "", /personal agent/); | |
| 42 | assert.match(personalRefusal(anasAgent, { asked_by: "u1", channel_kind: "dm", members: 3 }) ?? "", /direct message/); | |
| 43 | assert.match(personalRefusal(anasAgent, { asked_by: "u1", channel_kind: "channel", members: 5 }) ?? "", /direct message/); | |
| 44 | assert.equal(personalRefusal(shared, { asked_by: "u2", channel_kind: "channel", members: 9 }), null); | |
| 45 | }); |