pi-goosedump 0.12.28 → 0.12.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.ts +21 -7
  2. package/package.json +2 -2
package/dist/index.ts CHANGED
@@ -316,29 +316,43 @@ function isStringArray(value) {
316
316
  return Array.isArray(value) && value.every((item) => typeof item === "string");
317
317
  }
318
318
  function isMemorySource(value) {
319
- return isRecord(value) && typeof value.provider === "string" && typeof value.session_id === "string" && typeof value.entry_id === "string" && typeof value.role === "string" && typeof value.observed_at === "number" && typeof value.project === "string" && typeof value.source_path === "string" && (value.content_hash === undefined || typeof value.content_hash === "string");
319
+ return isRecord(value) && typeof value.citation_id === "string" && typeof value.provider === "string" && typeof value.session_id === "string" && typeof value.entry_id === "string" && typeof value.role === "string" && typeof value.observed_at === "number" && typeof value.project === "string" && typeof value.source_path === "string" && typeof value.snippet === "string" && (value.content_hash === undefined || typeof value.content_hash === "string");
320
+ }
321
+ function isMemoryMatchReason(value) {
322
+ return isRecord(value) && typeof value.detail === "string" && ["lexical", "entity", "relation", "vector", "history"].includes(value.kind);
323
+ }
324
+ function isMemoryRelationship(value) {
325
+ return isRecord(value) && ["outgoing", "incoming"].includes(value.direction) && ["duplicates", "supports", "revises", "contradicts"].includes(value.kind) && typeof value.claim_id === "string" && typeof value.display_id === "string" && ["fact", "decision", "preference", "procedure", "lesson"].includes(value.memory_type) && typeof value.text === "string" && ["active", "superseded"].includes(value.status) && typeof value.rationale === "string";
320
326
  }
321
327
  function parseMemoryHits(output) {
322
328
  const value = JSON.parse(output);
323
329
  if (!Array.isArray(value))
324
330
  throw new Error("goosedump memory recall returned invalid JSON");
325
- return value.filter((item) => isRecord(item) && typeof item.id === "string" && typeof item.display_id === "string" && typeof item.text === "string" && isStringArray(item.keywords) && typeof item.score === "number" && typeof item.project === "string" && (item.valid_from === null || typeof item.valid_from === "number") && (item.valid_until === null || typeof item.valid_until === "number") && (item.status === undefined || item.status === "active" || item.status === "superseded") && (item.superseded_by === undefined || item.superseded_by === null || typeof item.superseded_by === "string") && (item.related_by === undefined || Array.isArray(item.related_by) && item.related_by.every((entity) => isRecord(entity) && typeof entity.kind === "string" && typeof entity.value === "string")) && ["fact", "decision", "preference", "procedure", "lesson"].includes(item.memory_type) && Array.isArray(item.sources) && item.sources.every(isMemorySource));
331
+ return value.filter((item) => isRecord(item) && typeof item.id === "string" && typeof item.display_id === "string" && typeof item.text === "string" && isStringArray(item.keywords) && typeof item.score === "number" && typeof item.project === "string" && (item.valid_from === null || typeof item.valid_from === "number") && (item.valid_until === null || typeof item.valid_until === "number") && (item.status === undefined || item.status === "active" || item.status === "superseded") && (item.superseded_by === undefined || item.superseded_by === null || typeof item.superseded_by === "string") && (item.related_by === undefined || Array.isArray(item.related_by) && item.related_by.every((entity) => isRecord(entity) && typeof entity.kind === "string" && typeof entity.value === "string")) && Array.isArray(item.relationships) && item.relationships.every(isMemoryRelationship) && Array.isArray(item.match_reasons) && item.match_reasons.every(isMemoryMatchReason) && ["fact", "decision", "preference", "procedure", "lesson"].includes(item.memory_type) && Array.isArray(item.evidence) && item.evidence.every(isMemorySource));
326
332
  }
327
333
  function formatMemorySource(source) {
328
334
  const observed = new Date(source.observed_at).toISOString();
329
335
  const revision = source.content_hash ? `; revision ${source.content_hash.slice(0, 12)}` : "";
330
- return `${source.provider}:${source.session_id}/${source.entry_id} ` + `(${source.role}; observed ${observed}${revision}) · ${source.source_path}`;
336
+ const snippet = source.snippet.trim() ? `
337
+ ${source.snippet.trim()}` : "";
338
+ return `[${source.citation_id}] ${source.provider}:${source.session_id}/${source.entry_id} ` + `(${source.role}; observed ${observed}${revision}) · ${source.source_path}${snippet}`;
331
339
  }
332
340
  function formatMemoryHit(hit, maxBytes) {
333
341
  const keywords = hit.keywords.length > 0 ? ` · keywords: ${hit.keywords.join(", ")}` : "";
334
342
  const status = hit.status ?? "active";
335
- const sourcesText = hit.sources.map(formatMemorySource).join(`
343
+ const evidenceText = hit.evidence.map(formatMemorySource).join(`
336
344
  `);
345
+ const reasonsText = hit.match_reasons.map((reason) => `${reason.kind}: ${reason.detail}`).join("; ");
337
346
  const validSpan = hit.valid_from !== null && hit.valid_until !== null ? `${new Date(hit.valid_from).toISOString()} → ${new Date(hit.valid_until).toISOString()}` : hit.valid_from !== null ? `from ${new Date(hit.valid_from).toISOString()}` : hit.valid_until !== null ? `until ${new Date(hit.valid_until).toISOString()}` : "always valid";
338
347
  const related = hit.related_by && hit.related_by.length > 0 ? ` · related by: ${hit.related_by.map((entity) => `${entity.kind}:${entity.value}`).join(", ")}` : "";
348
+ const relationships = hit.relationships.length > 0 ? `Relationships:
349
+ ${hit.relationships.map((relationship) => `[${relationship.display_id}] ${relationship.direction} ${relationship.kind} ` + `(${relationship.status}): ${relationship.text} — ${relationship.rationale}`).join(`
350
+ `)}
351
+ ` : "";
339
352
  const provenance = `[${hit.display_id}] ${hit.memory_type} (${status}; score ${hit.score.toFixed(3)}; ${validSpan}; project ${hit.project})${keywords}${related}
340
- ` + `Sources:
341
- ${sourcesText}
353
+ ` + `Match: ${reasonsText}
354
+ ` + relationships + `Evidence:
355
+ ${evidenceText}
342
356
  `;
343
357
  const full = `${provenance}${hit.text}`;
344
358
  if (Buffer.byteLength(full) <= maxBytes)
@@ -491,7 +505,7 @@ async function goosedumpRecall(query, options = {}, signal, executablePath) {
491
505
  return { hits: parseMemoryHits(output.stdout), warning: output.stderr.trim() };
492
506
  }
493
507
  async function goosedumpMemoryRemember(target, signal, executablePath) {
494
- const output = await runGoosedumpAsync(["memory", "remember", target, "--json"], signal, executablePath);
508
+ const output = await runGoosedumpAsync(["memory", "learn", target, "--json"], signal, executablePath);
495
509
  return output.stdout.trim();
496
510
  }
497
511
  async function goosedumpMemoryForget(target, signal, executablePath) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-goosedump",
3
- "version": "0.12.28",
3
+ "version": "0.12.30",
4
4
  "description": "Pi extension for goosedump session search, durable memory, and compaction",
5
5
  "keywords": [
6
6
  "compaction",
@@ -38,7 +38,7 @@
38
38
  },
39
39
  "dependencies": {
40
40
  "@earendil-works/pi-tui": "^0.82.1",
41
- "@jarkkojs/goosedump": "^0.12.28",
41
+ "@jarkkojs/goosedump": "^0.12.30",
42
42
  "@sinclair/typebox": "^0.34.49"
43
43
  },
44
44
  "devDependencies": {