* Build the markdown body with YAML frontmatter (title/type/tags) injected. * * Two cases: * - Page body already starts with `---\n` (transcripts) — inject into the * existing frontmatter block before its close fence so gbrain's frontmatter * parser picks up the fields alongside any sess
(page: PageRecord)
| 843 | * source of truth and gbrain rejects mismatches. |
| 844 | */ |
| 845 | function renderPageBody(page: PageRecord): string { |
| 846 | let body = page.body; |
| 847 | if (body.startsWith("---\n")) { |
| 848 | const end = body.indexOf("\n---", 4); |
| 849 | if (end > 0) { |
| 850 | const inject = [ |
| 851 | `title: ${JSON.stringify(page.title)}`, |
| 852 | `type: ${page.type}`, |
| 853 | `tags:`, |
| 854 | ...page.tags.map((t) => ` - ${t}`), |
| 855 | ].join("\n"); |
| 856 | body = body.slice(0, end) + "\n" + inject + body.slice(end); |
| 857 | } |
| 858 | } else { |
| 859 | body = [ |
| 860 | "---", |
| 861 | `title: ${JSON.stringify(page.title)}`, |
| 862 | `type: ${page.type}`, |
| 863 | `tags: [${page.tags.map((t) => JSON.stringify(t)).join(", ")}]`, |
| 864 | "---", |
| 865 | "", |
| 866 | body, |
| 867 | ].join("\n"); |
| 868 | } |
| 869 | // Strip NUL bytes — Postgres rejects 0x00 in UTF-8 text columns. Some Claude |
| 870 | // Code transcripts contain NUL inside user-pasted content or tool output, and |
| 871 | // surfacing those as `internal_error: invalid byte sequence` from the brain |
| 872 | // is unhelpful when we can sanitize at write time. Originally landed in v1.32.0.0 |
| 873 | // (PR #1411) on the per-file `gbrain put` path; moved here so all staged |
| 874 | // pages still get the same sanitization. |
| 875 | body = body.replace(/\x00/g, ""); |
| 876 | return body; |
| 877 | } |
| 878 | |
| 879 | interface PreparedPage { |
| 880 | /** Page slug (path-shaped, e.g. "transcripts/claude-code/foo"). */ |