mirror of
https://github.com/garrytan/gbrain.git
synced 2026-08-14 08:53:22 +00:00
fix(import): quote frontmatter values and omit absent conversation id (#3600)
Review follow-up to #3549. An envelope is a third-party file, so interpolating source_provider raw let a provider string carrying a newline close the scalar and inject arbitrary frontmatter keys. title: on the line above was already quoted; source: now matches it. memvelope_conversation_id emitted the literal string undefined when a conversation carried no id, which asserts a value rather than reporting absence: every id-less conversation claims the same id, so anything grouping or deduping on that key merges unrelated pages. The key is now omitted. Filename and frontmatter read one hasId predicate so they cannot disagree about whether an id exists. Tests add both cases; the injection case parses emitted frontmatter with js-yaml rather than substring-matching it.
This commit is contained in:
@@ -64,7 +64,11 @@ for (const [i, c] of conversations.entries()) {
|
||||
// other. The date only leads as a human/chronological sort prefix; the id
|
||||
// carries uniqueness. Positional fallback keeps names unique and deterministic
|
||||
// when an envelope omits an id.
|
||||
const convId = (typeof c.id === 'string' && c.id.trim()) ? c.id.trim() : `conv-${i + 1}`;
|
||||
// One predicate for "this conversation carries its own id", shared by the
|
||||
// filename and the frontmatter below. Keeping it in a single place is what
|
||||
// stops the two from disagreeing about whether an id exists.
|
||||
const hasId = typeof c.id === 'string' && c.id.trim() !== '';
|
||||
const convId = hasId ? c.id.trim() : `conv-${i + 1}`;
|
||||
const name = `${date || '0000-00-00'}-${slug(convId, `conv-${i + 1}`)}.md`;
|
||||
// gbrain reads YAML frontmatter + markdown body; keep provenance in frontmatter.
|
||||
// Emit `type: conversation` so gbrain stores these as conversation pages rather
|
||||
@@ -77,8 +81,15 @@ for (const [i, c] of conversations.entries()) {
|
||||
'type: conversation',
|
||||
`title: ${JSON.stringify(c.title || 'Untitled conversation')}`,
|
||||
`date: ${date || 'null'}`,
|
||||
`source: ${env.meta?.source_provider || 'unknown'}`,
|
||||
`memvelope_conversation_id: ${JSON.stringify(c.id)}`,
|
||||
// Every interpolated value is quoted. An envelope is a third-party file, so
|
||||
// a provider string carrying a newline would otherwise close this scalar and
|
||||
// inject arbitrary frontmatter keys into the page gbrain ingests.
|
||||
`source: ${JSON.stringify(env.meta?.source_provider || 'unknown')}`,
|
||||
// Omit the key entirely when the envelope carries no id, rather than
|
||||
// emitting the literal `undefined` or a synthesized `conv-N` — the positional
|
||||
// fallback names the file, but it is not a memvelope conversation id and
|
||||
// must not be recorded as one.
|
||||
...(hasId ? [`memvelope_conversation_id: ${JSON.stringify(convId)}`] : []),
|
||||
'origin: memvelope/envelope-v0',
|
||||
'---',
|
||||
'',
|
||||
|
||||
Reference in New Issue
Block a user