The owner's zero-configuration ruling (2026-09-23): nothing configures the graph beyond chat models. The prior-knowledge injection — its budget dial, its runner, its marker part, its dock/dispatch entries — is removed across all bands; the prober now reads the learner's persistent knowledge map on demand through two gated tools instead: - list_sessions: every birth session, names + kinds + counts + dates (graphSessionIndex, Platform's core seam) - list_propositions(session): what was born there + the session's own latest understanding level + that evaluation's date (graphSessionPropositions) — names/levels/dating ONLY, no statement text (owner ruling: the map's organization is the prober's business, its prose is not) Registered via createProberTools when chat-handler passes graphStore (the graphToolsEnabled gate decided server-side, per-turn fresh); the prober doctrine gains the map-review nudge at session start. Also: runner's JobKind special-casing collapses (KIND_ROLE/KIND_RUNNERS are plain records again), semantic-clusters.ts dies with its test, the embedder dep's doc tells the wave-7 stub story, and ports.ts's readClusterLabels/readNamingRuns surface stays untouched for Platform's ledger-port interlude. 848/848 tests, typecheck/lint/build green.
55 lines
1.9 KiB
TypeScript
55 lines
1.9 KiB
TypeScript
/**
|
|
* Tests for the shared settings-body parser, chat-section flavor
|
|
* (default-settings wave, 2026-09-18; record-backed 2026-09-19): the seam
|
|
* behind BOTH chat-settings routes — per-chat and the defaults alias.
|
|
*
|
|
* The record store, the legacy-file migration, and the record-backed
|
|
* default-settings facade are covered in tests/settings-store.test.ts
|
|
* (one fs owner per file — the test runner executes files in parallel).
|
|
*/
|
|
|
|
import assert from "node:assert/strict";
|
|
import { describe, it } from "node:test";
|
|
import { parseSettingsBody } from "../src/server/settings-body.ts";
|
|
|
|
describe("parseSettingsBody (shared by both settings routes)", () => {
|
|
it("an empty object parses to {} — the clear-overrides write", () => {
|
|
const r = parseSettingsBody({});
|
|
assert.ok(r.ok);
|
|
assert.deepEqual(r.ok ? r.settings : null, {});
|
|
});
|
|
|
|
it("a full valid body parses field-for-field", () => {
|
|
const r = parseSettingsBody({
|
|
model: { provider: "openrouter", id: "z-ai/glm-5.3-flash" },
|
|
thinkingLevel: "high",
|
|
});
|
|
assert.ok(r.ok);
|
|
assert.deepEqual(r.settings, {
|
|
model: { provider: "openrouter", id: "z-ai/glm-5.3-flash" },
|
|
thinkingLevel: "high",
|
|
});
|
|
});
|
|
|
|
it("partial bodies keep only the present overrides (replace-whole)", () => {
|
|
const r = parseSettingsBody({ thinkingLevel: "low" });
|
|
assert.ok(r.ok);
|
|
assert.deepEqual(r.settings, { thinkingLevel: "low" });
|
|
});
|
|
|
|
it("rejects non-object bodies", () => {
|
|
for (const body of ["junk", 42, [{}]]) {
|
|
const r = parseSettingsBody(body);
|
|
assert.equal(r.ok, false, JSON.stringify(body));
|
|
if (!r.ok) assert.match(r.error, /Invalid JSON body/);
|
|
}
|
|
});
|
|
|
|
it("rejects malformed model and non-string thinkingLevel", () => {
|
|
assert.equal(parseSettingsBody({ model: "nope" }).ok, false);
|
|
assert.equal(parseSettingsBody({ model: { provider: 1, id: "x" } }).ok, false);
|
|
assert.equal(parseSettingsBody({ thinkingLevel: 7 }).ok, false);
|
|
});
|
|
|
|
});
|