@sema-agent/core
Version:
Stateless, task-oriented AI agent core
85 lines (84 loc) • 6.27 kB
JavaScript
import { strict as assert } from "node:assert";
import { beginContract } from "./contract-harness.js";
export async function toolResultStoreContract(make, runAssertion, onOptionalMember) {
const { run, settle } = beginContract(runAssertion);
run("put/get full + sliced; write-once no-op; unknown → undefined", async () => {
const store = make();
const ref = "tr_s_c";
await store.put(ref, "0123456789");
assert.deepEqual(await store.get(ref), { content: "0123456789", offset: 0, totalChars: 10 });
assert.deepEqual(await store.get(ref, { offset: 2, limit: 3 }), { content: "234", offset: 2, totalChars: 10 });
await store.put(ref, "IGNORED");
assert.equal((await store.get(ref)).content, "0123456789");
assert.equal(await store.get("tr_unknown"), undefined);
});
run("RB-266 unsafe refs are rejected at the WRITE by every backend; the read face degrades instead", async () => {
const store = make();
const NUL = String.fromCharCode(0);
const unsafe = ["", ".", "..", "a/b", "../escape", "dir\\ref", `tr_x${NUL}y`];
for (const ref of unsafe) {
await assert.rejects((async () => store.put(ref, "payload"))(), `put(${JSON.stringify(ref)}) must reject — a durable backend cannot key it`);
assert.equal(await store.get(ref), undefined, "get of an unsafe ref degrades to undefined");
}
await store.put("tr_sess-1_call.7", "ok");
assert.equal((await store.get("tr_sess-1_call.7")).content, "ok");
});
run("RB-273 a ref the contract ACCEPTS round-trips on every backend (no backend is stricter than the rule)", async () => {
const store = make();
for (const ref of ["tr_sess_call:1", "tr_sess_call%2F1", "tr_sess_call 1", "tr_sess_日本語"]) {
await store.put(ref, `payload-${ref}`);
assert.equal((await store.get(ref))?.content, `payload-${ref}`, `put(${JSON.stringify(ref)}) must round-trip here`);
}
assert.equal((await store.get("tr_sess_call:1")).content, "payload-tr_sess_call:1");
});
run("#119 provenance: content+owner are one write; ownerOf answers; a different owner is a TYPED refusal; unowned rows stay unowned", async () => {
const store = make();
assert.equal(typeof store.ownerOf, "function", "a backend must implement ownerOf — a store that cannot say who owns a ref cannot back a host read face");
const ownerOf = (ref) => Promise.resolve(store.ownerOf(ref));
const ref = "tr_s1~c1";
await store.put(ref, "0123456789", { sessionId: "sess-A", taskId: "task-1" });
assert.deepEqual(await ownerOf(ref), { sessionId: "sess-A", taskId: "task-1" }, "the winning write's owner round-trips");
await store.put(ref, "IGNORED", { sessionId: "sess-A", taskId: "task-1" });
assert.equal((await store.get(ref)).content, "0123456789");
assert.deepEqual(await ownerOf(ref), { sessionId: "sess-A", taskId: "task-1" });
await store.put(ref, "IGNORED");
assert.deepEqual(await ownerOf(ref), { sessionId: "sess-A", taskId: "task-1" }, "an ownerless put must not clear the owner");
for (const other of [{ sessionId: "sess-B" }, { sessionId: "sess-A", taskId: "task-2" }]) {
await assert.rejects((async () => store.put(ref, "other tenant's bytes", other))(), (err) => err.code === "tool_result.ref_conflict", `put(${JSON.stringify(other)}) on an occupied ref must reject with code tool_result.ref_conflict`);
}
assert.equal((await store.get(ref)).content, "0123456789", "a refused put must not have overwritten anything");
const unowned = "tr_no_owner~c";
await store.put(unowned, "bytes from a write site that stated no owner");
assert.equal(await ownerOf(unowned), undefined, "a row stored without provenance is UNOWNED");
await store.put(unowned, "bytes from a write site that stated no owner", { sessionId: "sess-A" });
assert.equal(await ownerOf(unowned), undefined, "put must not back-fill an owner onto an unowned row");
assert.equal((await store.get(unowned)).content, "bytes from a write site that stated no owner");
assert.equal(await ownerOf("tr_never~written"), undefined);
});
run("#196 deleteBySession (optional): four-state semantics when present; absence is REPORTED, not silently green", async () => {
const probe = make();
if (probe.deleteBySession === undefined) {
onOptionalMember?.({ member: "deleteBySession", status: "absent" });
return;
}
assert.equal(typeof probe.deleteBySession, "function", `deleteBySession is present but not callable (got ${typeof probe.deleteBySession}) — a garbage member is a DEFECT, not an optional-member absence`);
const store = make();
const del = (sessionId) => Promise.resolve(store.deleteBySession(sessionId));
await store.put("tr_sweep~a", "A-bytes", { sessionId: "sess-X", taskId: "t1" });
await store.put("tr_sweep~b", "B-bytes", { sessionId: "sess-X" });
await store.put("tr_sweep~other", "OTHER-bytes", { sessionId: "sess-Y" });
await store.put("tr_sweep~unowned", "UNOWNED-bytes");
const first = await del("sess-X");
assert.equal(first.deleted, 2, "both rows recorded for the session are deleted (taskId presence does not split the key)");
assert.equal(await store.get("tr_sweep~a"), undefined, "a swept row is gone");
assert.equal(await store.get("tr_sweep~b"), undefined);
assert.equal((await store.get("tr_sweep~other")).content, "OTHER-bytes", "another session's row survives the sweep");
assert.equal(first.unattributable >= 1, true, "an unowned row is counted unattributable");
assert.equal((await store.get("tr_sweep~unowned")).content, "UNOWNED-bytes", "an unowned row is never deleted by a session sweep");
const second = await del("sess-X");
assert.equal(second.deleted, 0, "a repeated sweep deletes nothing");
assert.equal((await store.get("tr_sweep~other")).content, "OTHER-bytes");
onOptionalMember?.({ member: "deleteBySession", status: "verified" });
});
await settle();
}