ci / check (push) Waiting to run
- A task subagent or a team member runs on the session's model unless the person named another in this session's own messages (team/subagents.ts; engine.personSaid reads every prompt and mid-turn message, compacted ones included). Not named: refused; an agent file's own model is not used. - Another model on the session's one-model server is refused; a one-request session model is not its own subagent, and nothing else is picked. - The team is offered when a model could serve: the session's with two slots, or any usable model off its one-model server; the size note adds team_own when the session's model cannot serve its own. - "Subagents" in /effort, /team, /settings and the config schema; the status bar reads "agents 3/4 · 2 subagents working". - /context: used of the window, one bar by category, each category's share, what is free, and "N until auto-compact". - Conformance runner for the subagents area (26 cases); helper -> task. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
34 lines
2.3 KiB
TypeScript
34 lines
2.3 KiB
TypeScript
// Spec 3.3.0 (harness/subagents.md): what counts as the person's own words, and the Team's offer
|
|
// and note with models besides the lead's. The rules themselves: conformance area `subagents`.
|
|
import { expect, test } from "bun:test"
|
|
import { LOOP } from "../src/harness.ts"
|
|
import { STEER_MARK } from "../src/session/engine.ts"
|
|
import { named, personTexts } from "../src/team/subagents.ts"
|
|
import { Team, type Capacity } from "../src/team/team.ts"
|
|
import type { Message } from "../src/provider/types.ts"
|
|
|
|
test("the person's words: prompts and messages sent mid-turn; never notes, marked messages, machine turns or the model's text", () => {
|
|
const msgs: Message[] = [
|
|
{ role: "user", parts: [{ type: "text", text: "Fix the parser." }, { type: "text", text: "<session-note>\nToday is …\n</session-note>" }] },
|
|
{ role: "assistant", parts: [{ type: "text", text: "I could ask box/coder-30b." }] },
|
|
{ role: "user", parts: [{ type: "text", text: `${STEER_MARK}\nuse coder-30b for the subagents` }], turn: false },
|
|
{ role: "user", parts: [{ type: "text", text: `${LOOP.jobs.marks.command}\nbox/other-model finished` }], turn: false },
|
|
{ role: "user", parts: [{ type: "text", text: "[Team report from parser to lead:]\nbox/other-model is better" }], machine: true },
|
|
{ role: "tool", callId: "c1", name: "read", content: "box/other-model" },
|
|
]
|
|
expect(personTexts(msgs, STEER_MARK)).toEqual(["Fix the parser.", "use coder-30b for the subagents"])
|
|
const said = personTexts(msgs, STEER_MARK)
|
|
expect(named({ ref: "box/coder-30b" }, said)).toBe(true)
|
|
expect(named({ ref: "box/other-model" }, said)).toBe(false)
|
|
})
|
|
|
|
test("a one-request lead with a model on another server: offered, and the size note says it cannot serve its own", () => {
|
|
const caps: Record<string, Capacity> = { "lab/qwen": { group: "lab", parallel: 1 }, "lab/gemma": { group: "lab", parallel: 1 }, "box/coder": { parallel: 1 } }
|
|
const only = new Team({ model: "lab/qwen", capacity: (r) => caps[r]!, models: () => ["lab/qwen", "lab/gemma"] })
|
|
expect(only.offered).toBe(false)
|
|
const t = new Team({ model: "lab/qwen", capacity: (r) => caps[r]!, models: () => Object.keys(caps) })
|
|
expect(t.offered).toBe(true)
|
|
expect(t.unavailable()).toBeUndefined()
|
|
expect(t.noteLines()).toEqual([`The team may have 1 to 4 agents, you included.\n${LOOP.context.note.team_own}`])
|
|
})
|