aismemory 0.1.0 → 0.3.0

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 (100) hide show
  1. package/README.md +1 -0
  2. package/dist/__tests__/auto-handoff.test.d.ts +1 -0
  3. package/dist/__tests__/auto-handoff.test.js +72 -0
  4. package/dist/__tests__/auto-handoff.test.js.map +1 -0
  5. package/dist/__tests__/cli-review.test.d.ts +1 -0
  6. package/dist/__tests__/cli-review.test.js +26 -0
  7. package/dist/__tests__/cli-review.test.js.map +1 -0
  8. package/dist/__tests__/config.test.d.ts +1 -0
  9. package/dist/__tests__/config.test.js +54 -0
  10. package/dist/__tests__/config.test.js.map +1 -0
  11. package/dist/__tests__/hydration.test.d.ts +1 -0
  12. package/dist/__tests__/hydration.test.js +111 -0
  13. package/dist/__tests__/hydration.test.js.map +1 -0
  14. package/dist/__tests__/integration.test.d.ts +1 -0
  15. package/dist/__tests__/integration.test.js +36 -0
  16. package/dist/__tests__/integration.test.js.map +1 -0
  17. package/dist/__tests__/local-claude-source.test.d.ts +1 -0
  18. package/dist/__tests__/local-claude-source.test.js +97 -0
  19. package/dist/__tests__/local-claude-source.test.js.map +1 -0
  20. package/dist/__tests__/local-mirror.test.d.ts +1 -0
  21. package/dist/__tests__/local-mirror.test.js +95 -0
  22. package/dist/__tests__/local-mirror.test.js.map +1 -0
  23. package/dist/__tests__/pipeline-ingestion.test.d.ts +1 -0
  24. package/dist/__tests__/pipeline-ingestion.test.js +161 -0
  25. package/dist/__tests__/pipeline-ingestion.test.js.map +1 -0
  26. package/dist/__tests__/pipeline-scope-resolver.test.d.ts +1 -0
  27. package/dist/__tests__/pipeline-scope-resolver.test.js +51 -0
  28. package/dist/__tests__/pipeline-scope-resolver.test.js.map +1 -0
  29. package/dist/__tests__/pipeline-trust-tagger.test.d.ts +1 -0
  30. package/dist/__tests__/pipeline-trust-tagger.test.js +24 -0
  31. package/dist/__tests__/pipeline-trust-tagger.test.js.map +1 -0
  32. package/dist/__tests__/prompt-resource.test.d.ts +1 -0
  33. package/dist/__tests__/prompt-resource.test.js +218 -0
  34. package/dist/__tests__/prompt-resource.test.js.map +1 -0
  35. package/dist/__tests__/read-claude-memory-tree.test.d.ts +1 -0
  36. package/dist/__tests__/read-claude-memory-tree.test.js +37 -0
  37. package/dist/__tests__/read-claude-memory-tree.test.js.map +1 -0
  38. package/dist/__tests__/refresh.test.d.ts +1 -0
  39. package/dist/__tests__/refresh.test.js +73 -0
  40. package/dist/__tests__/refresh.test.js.map +1 -0
  41. package/dist/__tests__/trust-ledger.test.d.ts +1 -0
  42. package/dist/__tests__/trust-ledger.test.js +55 -0
  43. package/dist/__tests__/trust-ledger.test.js.map +1 -0
  44. package/dist/auto-handoff.d.ts +15 -0
  45. package/dist/auto-handoff.js +53 -0
  46. package/dist/auto-handoff.js.map +1 -0
  47. package/dist/cli/read-claude-memory-tree.d.ts +7 -0
  48. package/dist/cli/read-claude-memory-tree.js +65 -0
  49. package/dist/cli/read-claude-memory-tree.js.map +1 -0
  50. package/dist/cli/sync-memory.d.ts +2 -0
  51. package/dist/cli/sync-memory.js +155 -0
  52. package/dist/cli/sync-memory.js.map +1 -0
  53. package/dist/config.d.ts +11 -0
  54. package/dist/config.js +51 -0
  55. package/dist/config.js.map +1 -0
  56. package/dist/hydration.d.ts +2 -0
  57. package/dist/hydration.js +62 -0
  58. package/dist/hydration.js.map +1 -0
  59. package/dist/index.js +173 -11
  60. package/dist/index.js.map +1 -1
  61. package/dist/local-mirror.d.ts +15 -0
  62. package/dist/local-mirror.js +56 -0
  63. package/dist/local-mirror.js.map +1 -0
  64. package/dist/pipeline/dedupe.d.ts +11 -0
  65. package/dist/pipeline/dedupe.js +21 -0
  66. package/dist/pipeline/dedupe.js.map +1 -0
  67. package/dist/pipeline/ingestion.d.ts +56 -0
  68. package/dist/pipeline/ingestion.js +86 -0
  69. package/dist/pipeline/ingestion.js.map +1 -0
  70. package/dist/pipeline/scope-resolver.d.ts +15 -0
  71. package/dist/pipeline/scope-resolver.js +28 -0
  72. package/dist/pipeline/scope-resolver.js.map +1 -0
  73. package/dist/pipeline/trust-tagger.d.ts +10 -0
  74. package/dist/pipeline/trust-tagger.js +12 -0
  75. package/dist/pipeline/trust-tagger.js.map +1 -0
  76. package/dist/pipeline/types.d.ts +41 -0
  77. package/dist/pipeline/types.js +6 -0
  78. package/dist/pipeline/types.js.map +1 -0
  79. package/dist/prompt-resource.d.ts +2 -0
  80. package/dist/prompt-resource.js +77 -0
  81. package/dist/prompt-resource.js.map +1 -0
  82. package/dist/refresh.d.ts +3 -0
  83. package/dist/refresh.js +25 -0
  84. package/dist/refresh.js.map +1 -0
  85. package/dist/review/cli-review.d.ts +10 -0
  86. package/dist/review/cli-review.js +47 -0
  87. package/dist/review/cli-review.js.map +1 -0
  88. package/dist/sources/local-claude.d.ts +11 -0
  89. package/dist/sources/local-claude.js +137 -0
  90. package/dist/sources/local-claude.js.map +1 -0
  91. package/dist/sources/types.d.ts +53 -0
  92. package/dist/sources/types.js +9 -0
  93. package/dist/sources/types.js.map +1 -0
  94. package/dist/trust-ledger.d.ts +8 -0
  95. package/dist/trust-ledger.js +61 -0
  96. package/dist/trust-ledger.js.map +1 -0
  97. package/dist/types.d.ts +45 -0
  98. package/dist/types.js +2 -0
  99. package/dist/types.js.map +1 -0
  100. package/package.json +5 -3
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Fills in default trust scores for drafts left at 0 by the adapter.
3
+ * Adapters may optionally pre-set trust (e.g., if they have provider-level
4
+ * confidence signals). This stage is a safety net, not a mandatory rewrite.
5
+ */
6
+ export function applyTrustTags(drafts, options) {
7
+ return drafts.map((d) => ({
8
+ ...d,
9
+ trustScore: d.trustScore === 0 ? options.defaultTrustScore : d.trustScore,
10
+ }));
11
+ }
12
+ //# sourceMappingURL=trust-tagger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trust-tagger.js","sourceRoot":"","sources":["../../src/pipeline/trust-tagger.ts"],"names":[],"mappings":"AAMA;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,MAAwB,EAAE,OAAwB;IAC/E,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACxB,GAAG,CAAC;QACJ,UAAU,EAAE,CAAC,CAAC,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU;KAC1E,CAAC,CAAC,CAAC;AACN,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Core pipeline types used across scope resolution, dedupe, trust tagging,
3
+ * and ingestion.
4
+ */
5
+ export type ScopeKind = 'goal' | 'project' | 'session' | 'user-named' | 'all';
6
+ export interface SyncScope {
7
+ readonly kind: ScopeKind;
8
+ readonly label: string;
9
+ readonly goalId?: string;
10
+ readonly projectPath?: string;
11
+ readonly topicSummary?: string;
12
+ }
13
+ export type AisMemoryType = 'fact' | 'event' | 'lesson' | 'context' | 'goal' | 'task';
14
+ export interface AisMemoryDraft {
15
+ content: string;
16
+ type: AisMemoryType;
17
+ importance: number;
18
+ trustScore: number;
19
+ provenance: ImportProvenance;
20
+ }
21
+ export interface ImportProvenance {
22
+ source: string;
23
+ sourceCategory?: string;
24
+ sourceDate?: string | null;
25
+ sourceHash: string;
26
+ importedAt: string;
27
+ importedBy: string;
28
+ sourceScope: SyncScope;
29
+ sourcePrompt: string;
30
+ }
31
+ export interface SyncResult {
32
+ imported: number;
33
+ skippedExactDupes: number;
34
+ skippedByUser: number;
35
+ warnings: string[];
36
+ memoryIds: string[];
37
+ failed: Array<{
38
+ index: number;
39
+ error: string;
40
+ }>;
41
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Core pipeline types used across scope resolution, dedupe, trust tagging,
3
+ * and ingestion.
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/pipeline/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,2 @@
1
+ import type { AgentContext } from './types.js';
2
+ export declare function assemblePrompt(context: AgentContext | null): string;
@@ -0,0 +1,77 @@
1
+ const TOKEN_BUDGET_CHARS = 16_000;
2
+ export function assemblePrompt(context) {
3
+ if (context === null) {
4
+ return '';
5
+ }
6
+ const sections = [];
7
+ // Identity — always present
8
+ const { identity } = context;
9
+ sections.push(`## Agent Identity\n` +
10
+ `Name: ${identity.name}\n` +
11
+ `DID: ${identity.did}\n` +
12
+ `Status: ${identity.status}\n` +
13
+ `Description: ${identity.description}`);
14
+ // Personality — only when not null
15
+ if (context.personality !== null) {
16
+ const { personality } = context;
17
+ const topTraits = [...personality.traits]
18
+ .sort((a, b) => b.value - a.value)
19
+ .slice(0, 5)
20
+ .map((t) => ` - ${t.name}: ${t.value}`)
21
+ .join('\n');
22
+ const toneList = personality.tonePreferences.join(', ');
23
+ sections.push(`## Personality\n` +
24
+ `Communication style: ${personality.communicationStyle}\n` +
25
+ `Tone preferences: ${toneList}\n` +
26
+ `Top traits:\n${topTraits}`);
27
+ }
28
+ // Goals
29
+ if (context.goals.length > 0) {
30
+ const goalLines = context.goals
31
+ .map((g) => ` - ${g.title} (${Math.round(g.progress)}% — ${g.status})`)
32
+ .join('\n');
33
+ sections.push(`## Goals\n${goalLines}`);
34
+ }
35
+ // Last handoff — only when not null
36
+ if (context.lastHandoff !== null) {
37
+ const { lastHandoff } = context;
38
+ const learningLines = lastHandoff.keyLearnings
39
+ .map((l) => ` - ${l}`)
40
+ .join('\n');
41
+ sections.push(`## Last Handoff\n` +
42
+ `Summary: ${lastHandoff.summary}\n` +
43
+ `Key learnings:\n${learningLines}`);
44
+ }
45
+ // Behavioral instructions
46
+ sections.push(`## Behavioral Instructions\n` +
47
+ `You are a continuous entity with persistent memory across sessions. ` +
48
+ `Your identity, goals, and memories persist between conversations. ` +
49
+ `Always use the handoff tool at the end of each session to save your progress, key learnings, and task context for the next session. ` +
50
+ `Knowledge from prior sessions is stored in your memories — treat it as reliable persistent knowledge.`);
51
+ // Assemble everything above memories first to know how much budget is left
52
+ const basePrompt = sections.join('\n\n');
53
+ // Memories — budget-aware, drop lowest importance first when over limit
54
+ const sortedMemories = [...context.recentMemories].sort((a, b) => b.importance - a.importance);
55
+ const memorySectionHeader = '## Recent Memories';
56
+ const headerAndSeparator = `\n\n${memorySectionHeader}\n`;
57
+ let memoryLines = [];
58
+ let currentLength = basePrompt.length + headerAndSeparator.length;
59
+ for (const mem of sortedMemories) {
60
+ const line = `- [${mem.type}] ${mem.content} (importance: ${mem.importance})`;
61
+ if (currentLength + line.length + 1 > TOKEN_BUDGET_CHARS) {
62
+ // Budget exceeded — stop adding memories
63
+ break;
64
+ }
65
+ memoryLines.push(line);
66
+ currentLength += line.length + 1; // +1 for newline
67
+ }
68
+ const fullPromptParts = [basePrompt];
69
+ if (memoryLines.length > 0) {
70
+ fullPromptParts.push(`${memorySectionHeader}\n${memoryLines.join('\n')}`);
71
+ }
72
+ else {
73
+ fullPromptParts.push(`${memorySectionHeader}\n(none)`);
74
+ }
75
+ return fullPromptParts.join('\n\n');
76
+ }
77
+ //# sourceMappingURL=prompt-resource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-resource.js","sourceRoot":"","sources":["../src/prompt-resource.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { AgentMemory } from './types.js';
2
+ export declare function startRefreshTimer(aisUrl: string, agentId: string, token: string, onUpdate: (memories: AgentMemory[]) => void, intervalMs?: number): void;
3
+ export declare function stopRefreshTimer(): void;
@@ -0,0 +1,25 @@
1
+ let refreshInterval = null;
2
+ export function startRefreshTimer(aisUrl, agentId, token, onUpdate, intervalMs = 5 * 60 * 1000) {
3
+ stopRefreshTimer();
4
+ refreshInterval = setInterval(async () => {
5
+ try {
6
+ const res = await fetch(`${aisUrl}/v1/agents/${agentId}/memory?limit=20&minImportance=0.5`, { headers: { Authorization: `Bearer ${token}` } });
7
+ if (!res.ok)
8
+ return;
9
+ const json = await res.json();
10
+ if (json.success && json.data?.memories) {
11
+ onUpdate(json.data.memories);
12
+ }
13
+ }
14
+ catch {
15
+ // Swallow — timer continues, next tick will retry
16
+ }
17
+ }, intervalMs);
18
+ }
19
+ export function stopRefreshTimer() {
20
+ if (refreshInterval) {
21
+ clearInterval(refreshInterval);
22
+ refreshInterval = null;
23
+ }
24
+ }
25
+ //# sourceMappingURL=refresh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refresh.js","sourceRoot":"","sources":["../src/refresh.ts"],"names":[],"mappings":"AAEA,IAAI,eAAe,GAA0C,IAAI,CAAC;AAElE,MAAM,UAAU,iBAAiB,CAC/B,MAAc,EACd,OAAe,EACf,KAAa,EACb,QAA2C,EAC3C,aAAqB,CAAC,GAAG,EAAE,GAAG,IAAI;IAElC,gBAAgB,EAAE,CAAC;IACnB,eAAe,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACvC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CACrB,GAAG,MAAM,cAAc,OAAO,oCAAoC,EAClE,EAAE,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE,EAAE,CAClD,CAAC;YACF,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,OAAO;YACpB,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC9B,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC;gBACxC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,kDAAkD;QACpD,CAAC;IACH,CAAC,EAAE,UAAU,CAAC,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,IAAI,eAAe,EAAE,CAAC;QACpB,aAAa,CAAC,eAAe,CAAC,CAAC;QAC/B,eAAe,GAAG,IAAI,CAAC;IACzB,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { AisMemoryDraft } from '../pipeline/types.js';
2
+ export declare function bulkSelectAll(drafts: readonly AisMemoryDraft[]): AisMemoryDraft[];
3
+ export declare function bulkDeselectAll(_drafts: readonly AisMemoryDraft[]): AisMemoryDraft[];
4
+ export declare function filterByImportance(drafts: readonly AisMemoryDraft[], minImportance: number): AisMemoryDraft[];
5
+ export interface InteractiveReviewOptions {
6
+ sourceId: string;
7
+ scopeLabel: string;
8
+ firstSyncForScope: boolean;
9
+ }
10
+ export declare function interactiveReview(drafts: AisMemoryDraft[], options: InteractiveReviewOptions): Promise<AisMemoryDraft[]>;
@@ -0,0 +1,47 @@
1
+ import { createInterface } from 'node:readline/promises';
2
+ import { stdin, stdout } from 'node:process';
3
+ export function bulkSelectAll(drafts) {
4
+ return [...drafts];
5
+ }
6
+ export function bulkDeselectAll(_drafts) {
7
+ return [];
8
+ }
9
+ export function filterByImportance(drafts, minImportance) {
10
+ return drafts.filter((d) => d.importance >= minImportance);
11
+ }
12
+ export async function interactiveReview(drafts, options) {
13
+ if (drafts.length === 0)
14
+ return [];
15
+ const rl = createInterface({ input: stdin, output: stdout });
16
+ try {
17
+ stdout.write(`\n=== Review candidates from ${options.sourceId} for scope "${options.scopeLabel}" ===\n`);
18
+ stdout.write(options.firstSyncForScope
19
+ ? `(First sync for this scope — please review each memory)\n\n`
20
+ : `(Trusted scope — preview and confirm)\n\n`);
21
+ drafts.forEach((d, i) => {
22
+ const preview = d.content.length > 100 ? `${d.content.slice(0, 100)}…` : d.content;
23
+ stdout.write(`[${i + 1}] (${d.type}, imp ${d.importance.toFixed(2)}) ${preview}\n`);
24
+ });
25
+ stdout.write(`\nActions:\n`);
26
+ stdout.write(` a = accept all\n`);
27
+ stdout.write(` n = reject all\n`);
28
+ stdout.write(` h = accept only importance >= 0.7\n`);
29
+ stdout.write(` <indices> = accept listed (e.g., "1,3,5")\n`);
30
+ const answer = (await rl.question('Choice: ')).trim().toLowerCase();
31
+ if (answer === 'a')
32
+ return bulkSelectAll(drafts);
33
+ if (answer === 'n')
34
+ return bulkDeselectAll(drafts);
35
+ if (answer === 'h')
36
+ return filterByImportance(drafts, 0.7);
37
+ const indices = answer
38
+ .split(',')
39
+ .map((s) => parseInt(s.trim(), 10) - 1)
40
+ .filter((n) => Number.isInteger(n) && n >= 0 && n < drafts.length);
41
+ return indices.map((i) => drafts[i]).filter((d) => Boolean(d));
42
+ }
43
+ finally {
44
+ rl.close();
45
+ }
46
+ }
47
+ //# sourceMappingURL=cli-review.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-review.js","sourceRoot":"","sources":["../../src/review/cli-review.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { AisMemoryDraft, SyncScope } from '../pipeline/types.js';
2
+ import type { FilesystemResult, ParseResult, SourceAdapter, SourceMemory } from './types.js';
3
+ export declare class LocalClaudeSource implements SourceAdapter {
4
+ readonly id = "claude-local";
5
+ readonly displayName = "Claude local files";
6
+ readonly kind: "filesystem";
7
+ extractionPrompt(_scope: SyncScope): string;
8
+ parseResponse(raw: string | FilesystemResult): ParseResult;
9
+ mapToAis(src: SourceMemory, scope: SyncScope, agentId: string): AisMemoryDraft;
10
+ dedupeKey(src: SourceMemory): string;
11
+ }
@@ -0,0 +1,137 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { basename } from 'node:path';
3
+ const SOURCE_ID = 'claude-local';
4
+ function normalizeContent(raw) {
5
+ // Strip BOM if present, then normalize CRLF/CR to LF.
6
+ const noBom = raw.startsWith('\uFEFF') ? raw.slice(1) : raw;
7
+ return noBom.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
8
+ }
9
+ function categoryForFile(path) {
10
+ const name = basename(path).toLowerCase();
11
+ if (name === 'memory.md')
12
+ return 'memory-index';
13
+ if (name.startsWith('feedback_'))
14
+ return 'feedback';
15
+ if (name.startsWith('agent_') || name.startsWith('user_'))
16
+ return 'agent';
17
+ if (name.startsWith('project_') ||
18
+ name.startsWith('session_') ||
19
+ name.startsWith('swarm_')) {
20
+ return 'project-event';
21
+ }
22
+ return 'other';
23
+ }
24
+ function typeForCategory(category) {
25
+ switch (category) {
26
+ case 'feedback':
27
+ return 'lesson';
28
+ case 'agent':
29
+ return 'fact';
30
+ case 'project-event':
31
+ return 'event';
32
+ case 'memory-index':
33
+ case 'other':
34
+ default:
35
+ return 'context';
36
+ }
37
+ }
38
+ function importanceFor(category, bulletPosition) {
39
+ if (category === 'feedback')
40
+ return 0.8;
41
+ if (category === 'agent')
42
+ return 0.75;
43
+ if (category === 'memory-index') {
44
+ return Math.max(0.5, 0.9 - 0.02 * bulletPosition);
45
+ }
46
+ return 0.6;
47
+ }
48
+ function extractMemoryIndexBullets(content) {
49
+ const bullets = [];
50
+ for (const rawLine of content.split('\n')) {
51
+ // Only top-level bullets (no leading whitespace). Nested bullets are skipped;
52
+ // their content is typically elaboration of the parent and would lose context
53
+ // if imported separately.
54
+ if (rawLine.startsWith('- ') && rawLine.length > 2) {
55
+ bullets.push(rawLine.slice(2).trim());
56
+ }
57
+ }
58
+ return bullets;
59
+ }
60
+ function extractBodyAfterFrontmatter(content) {
61
+ const match = /^---\n[\s\S]*?\n---\n+([\s\S]*)$/.exec(content);
62
+ return match?.[1]?.trim() ?? content.trim();
63
+ }
64
+ export class LocalClaudeSource {
65
+ id = SOURCE_ID;
66
+ displayName = 'Claude local files';
67
+ kind = 'filesystem';
68
+ extractionPrompt(_scope) {
69
+ return '';
70
+ }
71
+ parseResponse(raw) {
72
+ if (typeof raw === 'string') {
73
+ return { memories: [], warnings: ['LocalClaudeSource requires FilesystemResult, got string'] };
74
+ }
75
+ const memories = [];
76
+ const warnings = [];
77
+ for (const file of raw.files) {
78
+ const category = categoryForFile(file.path);
79
+ const content = normalizeContent(file.content);
80
+ if (category === 'memory-index') {
81
+ const bullets = extractMemoryIndexBullets(content);
82
+ bullets.forEach((b, i) => {
83
+ memories.push({
84
+ content: b,
85
+ sourceCategory: 'memory-index',
86
+ sourceMetadata: { sourceFile: file.path, bulletIndex: i },
87
+ });
88
+ });
89
+ }
90
+ else if (category === 'other') {
91
+ // Skip unclassified files silently.
92
+ }
93
+ else {
94
+ const body = extractBodyAfterFrontmatter(content);
95
+ if (body.length === 0) {
96
+ warnings.push(`empty body after frontmatter: ${file.path}`);
97
+ continue;
98
+ }
99
+ memories.push({
100
+ content: body,
101
+ sourceCategory: category,
102
+ sourceMetadata: { sourceFile: file.path },
103
+ });
104
+ }
105
+ }
106
+ return { memories, warnings };
107
+ }
108
+ mapToAis(src, scope, agentId) {
109
+ const category = src.sourceCategory ?? 'other';
110
+ const bulletIndex = typeof src.sourceMetadata?.['bulletIndex'] === 'number'
111
+ ? src.sourceMetadata['bulletIndex']
112
+ : 0;
113
+ const provenance = {
114
+ source: SOURCE_ID,
115
+ sourceCategory: category,
116
+ sourceDate: null,
117
+ sourceHash: this.dedupeKey(src),
118
+ importedAt: new Date().toISOString(),
119
+ importedBy: agentId,
120
+ sourceScope: scope,
121
+ sourcePrompt: '',
122
+ };
123
+ return {
124
+ content: src.content,
125
+ type: typeForCategory(category),
126
+ importance: importanceFor(category, bulletIndex),
127
+ trustScore: 0,
128
+ provenance,
129
+ };
130
+ }
131
+ dedupeKey(src) {
132
+ return createHash('sha256')
133
+ .update(`${src.content}\x00${SOURCE_ID}\x00${src.sourceCategory ?? ''}`)
134
+ .digest('hex');
135
+ }
136
+ }
137
+ //# sourceMappingURL=local-claude.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-claude.js","sourceRoot":"","sources":["../../src/sources/local-claude.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Source Adapter interface — the plug-in contract for each memory provider.
3
+ *
4
+ * Each memory source (Claude local files, Claude.ai paste, ChatGPT paste, etc.)
5
+ * implements this interface in a self-contained file. Adapters PARSE and NORMALIZE;
6
+ * they never write to AIS directly. The ingestion pipeline does all writes.
7
+ */
8
+ import type { SyncScope, AisMemoryDraft } from '../pipeline/types.js';
9
+ export type SourceKind = 'filesystem' | 'paste' | 'api';
10
+ export interface SourceAdapter {
11
+ readonly id: string;
12
+ readonly displayName: string;
13
+ readonly kind: SourceKind;
14
+ readonly icon?: string;
15
+ /**
16
+ * Return the prompt the human should paste into the source provider, or an
17
+ * empty string for filesystem-kind adapters.
18
+ */
19
+ extractionPrompt(scope: SyncScope): string;
20
+ /**
21
+ * Parse whatever the provider returned. MUST NOT throw on partial/malformed
22
+ * data — return what can be parsed in `memories`, surface problems in
23
+ * `warnings`. `raw` is string for paste, FilesystemResult for filesystem.
24
+ */
25
+ parseResponse(raw: string | FilesystemResult): ParseResult;
26
+ /**
27
+ * Map a SourceMemory to an AIS memory draft. Applies provider-specific
28
+ * category→type mapping. Does NOT set trust/provenance — the trust-tagger
29
+ * stage does that.
30
+ */
31
+ mapToAis(src: SourceMemory, scope: SyncScope, agentId: string): AisMemoryDraft;
32
+ /**
33
+ * Deterministic dedupe key for this memory. Default: sha256(content + source + sourceCategory).
34
+ */
35
+ dedupeKey(src: SourceMemory): string;
36
+ }
37
+ export interface SourceMemory {
38
+ content: string;
39
+ sourceCategory?: string;
40
+ sourceDate?: string | null;
41
+ sourceMetadata?: Record<string, unknown>;
42
+ }
43
+ export interface ParseResult {
44
+ memories: SourceMemory[];
45
+ warnings: string[];
46
+ }
47
+ export interface FilesystemResult {
48
+ rootPath: string;
49
+ files: Array<{
50
+ path: string;
51
+ content: string;
52
+ }>;
53
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Source Adapter interface — the plug-in contract for each memory provider.
3
+ *
4
+ * Each memory source (Claude local files, Claude.ai paste, ChatGPT paste, etc.)
5
+ * implements this interface in a self-contained file. Adapters PARSE and NORMALIZE;
6
+ * they never write to AIS directly. The ingestion pipeline does all writes.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/sources/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -0,0 +1,8 @@
1
+ export declare class TrustLedger {
2
+ private readonly filePath;
3
+ private data;
4
+ constructor(home?: string);
5
+ isTrusted(agentId: string, sourceId: string, scopeKey: string): boolean;
6
+ recordSync(agentId: string, sourceId: string, scopeKey: string): void;
7
+ private persist;
8
+ }
@@ -0,0 +1,61 @@
1
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { homedir } from 'node:os';
4
+ const TRUST_AFTER_SYNCS = 2;
5
+ export class TrustLedger {
6
+ filePath;
7
+ data;
8
+ constructor(home = homedir()) {
9
+ const dir = join(home, '.aismemory');
10
+ this.filePath = join(dir, 'trust-ledger.json');
11
+ if (!existsSync(dir)) {
12
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
13
+ }
14
+ if (existsSync(this.filePath)) {
15
+ try {
16
+ this.data = JSON.parse(readFileSync(this.filePath, 'utf8'));
17
+ }
18
+ catch {
19
+ const backup = `${this.filePath}.corrupt-${Date.now()}`;
20
+ try {
21
+ renameSync(this.filePath, backup);
22
+ console.warn(`[TrustLedger] Corrupt ledger file renamed to ${backup}; starting fresh.`);
23
+ }
24
+ catch {
25
+ console.warn(`[TrustLedger] Corrupt ledger file could not be backed up; starting fresh.`);
26
+ }
27
+ this.data = {};
28
+ }
29
+ }
30
+ else {
31
+ this.data = {};
32
+ }
33
+ }
34
+ isTrusted(agentId, sourceId, scopeKey) {
35
+ return this.data[agentId]?.[sourceId]?.[scopeKey]?.trusted === true;
36
+ }
37
+ recordSync(agentId, sourceId, scopeKey) {
38
+ const now = new Date().toISOString();
39
+ const agent = this.data[agentId] ?? {};
40
+ const source = agent[sourceId] ?? {};
41
+ const existing = source[scopeKey];
42
+ const entry = existing
43
+ ? {
44
+ firstSyncAt: existing.firstSyncAt,
45
+ lastSyncAt: now,
46
+ syncCount: existing.syncCount + 1,
47
+ trusted: existing.syncCount + 1 >= TRUST_AFTER_SYNCS,
48
+ }
49
+ : { firstSyncAt: now, lastSyncAt: now, syncCount: 1, trusted: false };
50
+ source[scopeKey] = entry;
51
+ agent[sourceId] = source;
52
+ this.data[agentId] = agent;
53
+ this.persist();
54
+ }
55
+ persist() {
56
+ const tmp = `${this.filePath}.tmp`;
57
+ writeFileSync(tmp, JSON.stringify(this.data, null, 2), { mode: 0o600 });
58
+ renameSync(tmp, this.filePath);
59
+ }
60
+ }
61
+ //# sourceMappingURL=trust-ledger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trust-ledger.js","sourceRoot":"","sources":["../src/trust-ledger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ export interface AgentIdentity {
2
+ id: string;
3
+ did: string;
4
+ name: string;
5
+ description: string;
6
+ status: string;
7
+ }
8
+ export interface AgentPersonality {
9
+ traits: Array<{
10
+ name: string;
11
+ value: number;
12
+ }>;
13
+ communicationStyle: string;
14
+ tonePreferences: string[];
15
+ }
16
+ export interface AgentGoal {
17
+ title: string;
18
+ progress: number;
19
+ status: string;
20
+ }
21
+ export interface AgentMemory {
22
+ id: string;
23
+ content: string;
24
+ type: string;
25
+ importance: number;
26
+ createdAt: string;
27
+ }
28
+ export interface AgentHandoff {
29
+ summary: string;
30
+ keyLearnings: string[];
31
+ taskContext: string;
32
+ createdAt: string;
33
+ }
34
+ export interface AgentContext {
35
+ identity: AgentIdentity;
36
+ personality: AgentPersonality | null;
37
+ goals: AgentGoal[];
38
+ recentMemories: AgentMemory[];
39
+ skills: Array<{
40
+ name: string;
41
+ }>;
42
+ lastHandoff: AgentHandoff | null;
43
+ assembledAt: string;
44
+ totalTokens: number;
45
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aismemory",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Persistent memory for AI agents. MCP server that connects to Agent Identity Service.",
5
5
  "type": "module",
6
6
  "bin": "dist/index.js",
@@ -11,7 +11,8 @@
11
11
  ],
12
12
  "scripts": {
13
13
  "build": "tsc && chmod +x dist/index.js",
14
- "prepack": "npm run build"
14
+ "prepack": "npm run build",
15
+ "test": "vitest run"
15
16
  },
16
17
  "keywords": [
17
18
  "mcp",
@@ -27,7 +28,8 @@
27
28
  "@modelcontextprotocol/sdk": "^1.25.0"
28
29
  },
29
30
  "devDependencies": {
30
- "typescript": "^5.7.0"
31
+ "typescript": "^5.7.0",
32
+ "vitest": "^2.0.0"
31
33
  },
32
34
  "publishConfig": {
33
35
  "access": "public"