mirror of
https://github.com/Patiun/com.gregkilmer.www.git
synced 2026-11-07 19:58:24 +00:00
Add the content service and MCP server (phase 2)
services/content watches the vault's Site folder, runs every change through fixed rules, keeps the last accepted version of each note with its history, and serves one write API. The HTTP API, the MCP server for agents, and the admin page and editing tools to come all write through it. - SQLite store with history, review queue, redirects, links and full-text search - Rules: invalid, misplaced, duplicate name or slug, text loss, secrets, agent contact details, agent edits, agent publishing, agent batches - Watcher with debounce and a periodic full scan - HTTP API with reader, agent, editor and admin tokens - MCP tools: search, get_note, get_schema, list_held, set_status, add_library_item, update_fields, draft_post - Tests, including taking in all 545 migrated notes with nothing held Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012aSbo2D1qP8cMFQCykf7kx
This commit is contained in:
@@ -87,6 +87,19 @@ function orderKeys(def: NoteTypeDef, data: Record<string, unknown>): Record<stri
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a note's text without checking it, so a caller can run checkNote on
|
||||
* the result and report problems field by field.
|
||||
*/
|
||||
export function formatNote(data: Record<string, unknown>, body = ""): string {
|
||||
const def = typeDef(String(data.type));
|
||||
const ordered = def ? orderKeys(def, data) : data;
|
||||
// Write what was given (not schema defaults), so notes stay short.
|
||||
const yaml = stringifyYaml(ordered, { lineWidth: 0 }).trimEnd();
|
||||
const text = body.trim() ? `\n${body.trim()}\n` : "";
|
||||
return `---\n${yaml}\n---\n${text}`;
|
||||
}
|
||||
|
||||
/** Write a note's text. The data is checked first; this throws when it fails. */
|
||||
export function writeNote(data: Record<string, unknown>, body = ""): string {
|
||||
const def = typeDef(String(data.type));
|
||||
@@ -96,10 +109,7 @@ export function writeNote(data: Record<string, unknown>, body = ""): string {
|
||||
const problems = result.error.issues.map((i) => `${i.path.join(".") || "note"}: ${i.message}`).join("; ");
|
||||
throw new Error(`"${String(data.title)}" is not a valid ${def.label}: ${problems}`);
|
||||
}
|
||||
// Write what was given (not schema defaults), so notes stay short.
|
||||
const yaml = stringifyYaml(orderKeys(def, data), { lineWidth: 0 }).trimEnd();
|
||||
const text = body.trim() ? `\n${body.trim()}\n` : "";
|
||||
return `---\n${yaml}\n---\n${text}`;
|
||||
return formatNote(data, body);
|
||||
}
|
||||
|
||||
/** Where a note of this type lives, relative to the Site folder, with `.md`. */
|
||||
|
||||
Reference in New Issue
Block a user