CLI loads harness spec 3.0.0-draft; the show tool over the link

The spec's version may be a pre-release (3.0.0-draft). Every tool file is
loaded, with the new fields `sessions`, `requires`, `unavailable` and
`confirm`; the CLI's tools are those not the server's alone and offered in an
agent session (forCli) — a chat's own tools over the server's tree (mkdir, mv,
rm, search, python, the forge verbs) are not built in. blocks/context.md is
known; blocks/workspace.md is the server's alone.

show is built in with `requires: display`: offered only in a session a client
opened over the link when that client said `show: true` (capability `show`);
the device reads the file (at most 1 MB) and sends it with `_lembas/show`.
The harness tests now say 3.0.0's split of tools instead of "the execution
tools are the CLI's alone".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
HomerandClaude Opus 5.5 committed 2026-10-27 20:00:02 +00:00
1 parent 9f536d8345
commit bc78aec424
10 files changed
+200 -24

No files matched your search

+22 -2
View File
@@ -64,7 +64,7 @@ const limitsFor = (root: string, extra: Partial<Limits> = {}): Limits => ({ root
/** A fake LLeMbas on one side of the agent. `lembas: false`: an editor that is not LLeMbas. */
/** `protocol`: what the client says it speaks (2 by default; 1 is an older client). */
async function client(limits?: Limits, o: { lembas?: boolean; protocol?: number; instance?: string; hub?: Hub; handlers?: Record<string, (p: any) => unknown> } = {}) {
async function client(limits?: Limits, o: { lembas?: boolean; protocol?: number; instance?: string; hub?: Hub; show?: boolean; handlers?: Record<string, (p: any) => unknown> } = {}) {
const [ta, tb] = pair()
new AcpAgent(new Peer(ta), limits, o.instance, o.hub)
const c = new Peer(tb)
@@ -76,7 +76,7 @@ async function client(limits?: Limits, o: { lembas?: boolean; protocol?: number;
c.on("_lembas/permission/settled", (p) => void notes.push({ method: "settled", params: p }))
c.handle("session/request_permission", () => ({ outcome: { outcome: "selected", optionId: "once" } }))
for (const [m, fn] of Object.entries(o.handlers ?? {})) c.handle(m, fn)
const init: any = await c.request("initialize", { protocolVersion: 1, clientCapabilities: o.lembas === false ? {} : { _meta: { lembas: o.protocol === 1 ? true : { protocol: o.protocol ?? 2 } } } })
const init: any = await c.request("initialize", { protocolVersion: 1, clientCapabilities: o.lembas === false ? {} : { _meta: { lembas: o.protocol === 1 ? true : { protocol: o.protocol ?? 2, ...(o.show ? { show: true } : {}) } } } })
return { c, updates, events, notes, init }
}
@@ -312,6 +312,26 @@ test("initialize lists the 1.1.0 capabilities", async () => {
for (const cap of ["context", "library", "prototypes", "plan_state", "rewind"]) expect(init._meta.lembas.capabilities).toContain(cap)
})
test("show (spec 3.0.0): offered only to a client that shows files; the file goes over _lembas/show", async () => {
const page = "<!doctype html><h1>Hi</h1>"
fake = fakeProvider([{ chunks: [toolCall(0, "s1", "show", JSON.stringify({ path: "out/page.html", line: 1 }))] }, { chunks: [delta({ content: "there" })] }, { chunks: [delta({ content: "plain" })] }])
config(fake.url)
const root = project({ "out/page.html": page })
let shown: any
const { c, init } = await client(limitsFor(root), { show: true, handlers: { "_lembas/show": (p) => ((shown = p), { shown: true }) } })
expect(init._meta.lembas.capabilities).toContain("show")
const s: any = await c.request("session/new", { cwd: root })
await c.request("session/prompt", { sessionId: s.sessionId, prompt: [{ type: "text", text: "make a page" }] })
expect(fake.requests[0].tools.map((t: any) => t.function.name)).toContain("show")
expect(shown).toEqual({ sessionId: s.sessionId, toolCallId: "s1", path: "out/page.html", kind: "html", line: 1, text: page })
expect(fake.requests[1].messages.find((m: any) => m.role === "tool").content).toContain("Shown to the user: out/page.html")
// A client that did not say it shows files: no show tool.
const other = await client(limitsFor(root))
const s2: any = await other.c.request("session/new", { cwd: root })
await other.c.request("session/prompt", { sessionId: s2.sessionId, prompt: [{ type: "text", text: "hi" }] })
expect(fake.requests[2].tools.map((t: any) => t.function.name)).not.toContain("show")
})
test("the context reaches the prompt: the instance's instructions, its personalization, the library's scope, prototypes", async () => {
fake = fakeProvider([{ chunks: [delta({ content: "one" })] }, { chunks: [delta({ content: "two" })] }, { chunks: [delta({ content: "three" })] }])
config(fake.url, "personality: concise\ninstructions: local words\n")