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,161 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { readFileSync, readdirSync, statSync, rmSync, mkdtempSync } from 'node:fs';
3
+ import { tmpdir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import { runIngestion } from '../pipeline/ingestion.js';
6
+ import { LocalClaudeSource } from '../sources/local-claude.js';
7
+ import { SyncConfig } from '../config.js';
8
+ import { TrustLedger } from '../trust-ledger.js';
9
+ import { LocalMirror } from '../local-mirror.js';
10
+ function readFixtureFs(root) {
11
+ const files = [];
12
+ function walk(dir) {
13
+ for (const name of readdirSync(dir)) {
14
+ const full = join(dir, name);
15
+ const st = statSync(full);
16
+ if (st.isDirectory())
17
+ walk(full);
18
+ else if (name.endsWith('.md'))
19
+ files.push({ path: full, content: readFileSync(full, 'utf8') });
20
+ }
21
+ }
22
+ walk(root);
23
+ return { rootPath: root, files };
24
+ }
25
+ const FIXTURE_PATH = join(__dirname, 'fixtures', 'local-claude', 'project-a');
26
+ describe('runIngestion', () => {
27
+ it('returns success with warning when mirror.append throws', async () => {
28
+ const fs = readFixtureFs(FIXTURE_PATH);
29
+ const tmpHome = mkdtempSync(join(tmpdir(), 'aismem-mirrorfail-'));
30
+ try {
31
+ const config = new SyncConfig(tmpHome);
32
+ const ledger = new TrustLedger(tmpHome);
33
+ // Stub mirror whose append throws
34
+ const brokenMirror = {
35
+ append: () => { throw new Error('disk full'); },
36
+ cleanup: () => { },
37
+ scrub: () => { },
38
+ };
39
+ const result = await runIngestion({
40
+ adapter: new LocalClaudeSource(),
41
+ rawSourceData: fs,
42
+ scope: { kind: 'project', label: 'mirrorfail', projectPath: FIXTURE_PATH },
43
+ agentId: 'agent1',
44
+ config,
45
+ ledger,
46
+ mirror: brokenMirror,
47
+ existingHashes: new Set(),
48
+ bulkStore: async (drafts) => ({
49
+ created: drafts.map((_, i) => ({ index: i, id: `m-${i}` })),
50
+ failed: [],
51
+ }),
52
+ review: async (d) => d,
53
+ });
54
+ expect(result.imported).toBeGreaterThan(0);
55
+ expect(result.warnings.some((w) => /local mirror append failed/.test(w))).toBe(true);
56
+ // Ledger must have been advanced despite mirror failure (syncCount=1, not yet trusted)
57
+ expect(ledger.isTrusted('agent1', 'claude-local', `project||${FIXTURE_PATH}|mirrorfail`)).toBe(false);
58
+ }
59
+ finally {
60
+ rmSync(tmpHome, { recursive: true, force: true });
61
+ }
62
+ });
63
+ it('treats scopes with same kind but different labels as distinct for trust-ledger', async () => {
64
+ const fs = readFixtureFs(FIXTURE_PATH);
65
+ const tmpHome = mkdtempSync(join(tmpdir(), 'aismem-scopekey-'));
66
+ try {
67
+ const config = new SyncConfig(tmpHome);
68
+ const ledger = new TrustLedger(tmpHome);
69
+ const mirror = new LocalMirror(tmpHome, 30);
70
+ const adapter = new LocalClaudeSource();
71
+ const bulkStore = async (drafts) => ({
72
+ created: drafts.map((_, i) => ({ index: i, id: `m-${i}` })),
73
+ failed: [],
74
+ });
75
+ const review = async (d) => d;
76
+ // First sync: label 'alpha'
77
+ await runIngestion({
78
+ adapter, rawSourceData: fs,
79
+ scope: { kind: 'project', label: 'alpha', projectPath: '/shared/path' },
80
+ agentId: 'agent1', config, ledger, mirror, existingHashes: new Set(),
81
+ bulkStore, review,
82
+ });
83
+ // Second sync: label 'beta' (same projectPath)
84
+ await runIngestion({
85
+ adapter, rawSourceData: fs,
86
+ scope: { kind: 'project', label: 'beta', projectPath: '/shared/path' },
87
+ agentId: 'agent1', config, ledger, mirror, existingHashes: new Set(),
88
+ bulkStore, review,
89
+ });
90
+ // Each label has its own trust-ledger row; neither should be trusted yet (syncCount=1 each).
91
+ expect(ledger.isTrusted('agent1', 'claude-local', 'project||/shared/path|alpha')).toBe(false);
92
+ expect(ledger.isTrusted('agent1', 'claude-local', 'project||/shared/path|beta')).toBe(false);
93
+ }
94
+ finally {
95
+ rmSync(tmpHome, { recursive: true, force: true });
96
+ }
97
+ });
98
+ it('end-to-end: fixture dir → filtered → bulk-stored → mirrored', async () => {
99
+ const fs = readFixtureFs(FIXTURE_PATH);
100
+ const tmpHome = mkdtempSync(join(tmpdir(), 'aismem-ingest-'));
101
+ try {
102
+ const config = new SyncConfig(tmpHome);
103
+ const ledger = new TrustLedger(tmpHome);
104
+ const mirror = new LocalMirror(tmpHome, 30);
105
+ const bulkStore = vi.fn(async (drafts) => ({
106
+ created: drafts.map((_, i) => ({ index: i, id: `mem-${i}` })),
107
+ failed: [],
108
+ }));
109
+ const reviewApprover = vi.fn(async (drafts) => drafts);
110
+ const result = await runIngestion({
111
+ adapter: new LocalClaudeSource(),
112
+ rawSourceData: fs,
113
+ scope: { kind: 'project', label: 'fixture', projectPath: FIXTURE_PATH },
114
+ agentId: 'agent1',
115
+ config,
116
+ ledger,
117
+ mirror,
118
+ existingHashes: new Set(),
119
+ bulkStore,
120
+ review: reviewApprover,
121
+ });
122
+ expect(result.imported).toBeGreaterThan(0);
123
+ expect(result.failed).toHaveLength(0);
124
+ expect(bulkStore).toHaveBeenCalledTimes(1);
125
+ expect(reviewApprover).toHaveBeenCalledTimes(1);
126
+ }
127
+ finally {
128
+ rmSync(tmpHome, { recursive: true, force: true });
129
+ }
130
+ });
131
+ it('dedupes against existingHashes', async () => {
132
+ const fs = readFixtureFs(FIXTURE_PATH);
133
+ const source = new LocalClaudeSource();
134
+ const parsed = source.parseResponse(fs);
135
+ const firstDraft = source.mapToAis(parsed.memories[0], { kind: 'project', label: 'x' }, 'agent1');
136
+ const existingHashes = new Set([firstDraft.provenance.sourceHash]);
137
+ const tmpHome = mkdtempSync(join(tmpdir(), 'aismem-dedupe-'));
138
+ try {
139
+ const result = await runIngestion({
140
+ adapter: source,
141
+ rawSourceData: fs,
142
+ scope: { kind: 'project', label: 'x' },
143
+ agentId: 'agent1',
144
+ config: new SyncConfig(tmpHome),
145
+ ledger: new TrustLedger(tmpHome),
146
+ mirror: new LocalMirror(tmpHome, 30),
147
+ existingHashes,
148
+ bulkStore: async (drafts) => ({
149
+ created: drafts.map((_, i) => ({ index: i, id: `m-${i}` })),
150
+ failed: [],
151
+ }),
152
+ review: async (drafts) => drafts,
153
+ });
154
+ expect(result.skippedExactDupes).toBeGreaterThanOrEqual(1);
155
+ }
156
+ finally {
157
+ rmSync(tmpHome, { recursive: true, force: true });
158
+ }
159
+ });
160
+ });
161
+ //# sourceMappingURL=pipeline-ingestion.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline-ingestion.test.js","sourceRoot":"","sources":["../../src/__tests__/pipeline-ingestion.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,51 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import { mkdtempSync, rmSync } from 'node:fs';
3
+ import { tmpdir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import { resolveScope } from '../pipeline/scope-resolver.js';
6
+ import { SyncConfig } from '../config.js';
7
+ describe('resolveScope', () => {
8
+ let tmpHome;
9
+ beforeEach(() => {
10
+ tmpHome = mkdtempSync(join(tmpdir(), 'aismem-resolve-'));
11
+ });
12
+ afterEach(() => rmSync(tmpHome, { recursive: true, force: true }));
13
+ it('returns saved preference when present', async () => {
14
+ const cfg = new SyncConfig(tmpHome);
15
+ cfg.saveScopePreference('/tmp/myproj', { kind: 'project', label: 'myproj', projectPath: '/tmp/myproj' });
16
+ const scope = await resolveScope({
17
+ config: cfg,
18
+ projectPath: '/tmp/myproj',
19
+ activeGoal: null,
20
+ sessionTopic: null,
21
+ confirmer: async () => { throw new Error('should not prompt'); },
22
+ });
23
+ expect(scope.kind).toBe('project');
24
+ expect(scope.label).toBe('myproj');
25
+ });
26
+ it('proposes project scope when no preference but projectPath set', async () => {
27
+ const cfg = new SyncConfig(tmpHome);
28
+ const scope = await resolveScope({
29
+ config: cfg,
30
+ projectPath: '/tmp/newproj',
31
+ activeGoal: null,
32
+ sessionTopic: null,
33
+ confirmer: async (proposed) => proposed,
34
+ });
35
+ expect(scope.kind).toBe('project');
36
+ expect(scope.projectPath).toBe('/tmp/newproj');
37
+ });
38
+ it('prefers active goal over project', async () => {
39
+ const cfg = new SyncConfig(tmpHome);
40
+ const scope = await resolveScope({
41
+ config: cfg,
42
+ projectPath: '/tmp/proj',
43
+ activeGoal: { id: 'g1', description: 'ship sync' },
44
+ sessionTopic: null,
45
+ confirmer: async (proposed) => proposed,
46
+ });
47
+ expect(scope.kind).toBe('goal');
48
+ expect(scope.goalId).toBe('g1');
49
+ });
50
+ });
51
+ //# sourceMappingURL=pipeline-scope-resolver.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline-scope-resolver.test.js","sourceRoot":"","sources":["../../src/__tests__/pipeline-scope-resolver.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,24 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { applyTrustTags } from '../pipeline/trust-tagger.js';
3
+ function draft(trustScore) {
4
+ const prov = {
5
+ source: 'claude-local',
6
+ sourceHash: 'h',
7
+ importedAt: new Date().toISOString(),
8
+ importedBy: 'a1',
9
+ sourceScope: { kind: 'project', label: 'p' },
10
+ sourcePrompt: '',
11
+ };
12
+ return { content: 'c', type: 'fact', importance: 0.5, trustScore, provenance: prov };
13
+ }
14
+ describe('applyTrustTags', () => {
15
+ it('sets default trustScore=0.5 for drafts that came in at 0', () => {
16
+ const result = applyTrustTags([draft(0)], { defaultTrustScore: 0.5 });
17
+ expect(result[0]?.trustScore).toBe(0.5);
18
+ });
19
+ it('preserves non-zero trustScore from adapter', () => {
20
+ const result = applyTrustTags([draft(0.8)], { defaultTrustScore: 0.5 });
21
+ expect(result[0]?.trustScore).toBe(0.8);
22
+ });
23
+ });
24
+ //# sourceMappingURL=pipeline-trust-tagger.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline-trust-tagger.test.js","sourceRoot":"","sources":["../../src/__tests__/pipeline-trust-tagger.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAG7D,SAAS,KAAK,CAAC,UAAkB;IAC/B,MAAM,IAAI,GAAqB;QAC7B,MAAM,EAAE,cAAc;QACtB,UAAU,EAAE,GAAG;QACf,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACpC,UAAU,EAAE,IAAI;QAChB,WAAW,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAe;QACzD,YAAY,EAAE,EAAE;KACjB,CAAC;IACF,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;AACvF,CAAC;AAED,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,MAAM,GAAG,cAAc,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,iBAAiB,EAAE,GAAG,EAAE,CAAC,CAAC;QACtE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,MAAM,GAAG,cAAc,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,iBAAiB,EAAE,GAAG,EAAE,CAAC,CAAC;QACxE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,218 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { assemblePrompt } from '../prompt-resource.js';
3
+ const baseContext = {
4
+ identity: {
5
+ id: 'agent-001',
6
+ did: 'did:key:z6MkAgent001',
7
+ name: 'Atlas',
8
+ description: 'A general-purpose agent',
9
+ status: 'active',
10
+ },
11
+ personality: {
12
+ traits: [
13
+ { name: 'curious', value: 0.9 },
14
+ { name: 'methodical', value: 0.8 },
15
+ { name: 'concise', value: 0.7 },
16
+ ],
17
+ communicationStyle: 'direct',
18
+ tonePreferences: ['professional', 'friendly'],
19
+ },
20
+ goals: [
21
+ { title: 'Implement feature X', progress: 60, status: 'IN_PROGRESS' },
22
+ { title: 'Write tests', progress: 20, status: 'IN_PROGRESS' },
23
+ ],
24
+ recentMemories: [
25
+ {
26
+ id: 'mem-1',
27
+ content: 'The API uses bearer tokens for auth',
28
+ type: 'semantic',
29
+ importance: 0.9,
30
+ createdAt: '2026-04-03T00:00:00Z',
31
+ },
32
+ {
33
+ id: 'mem-2',
34
+ content: 'Deployed to Railway last Tuesday',
35
+ type: 'episodic',
36
+ importance: 0.5,
37
+ createdAt: '2026-04-02T00:00:00Z',
38
+ },
39
+ ],
40
+ skills: [{ name: 'TypeScript' }],
41
+ lastHandoff: {
42
+ summary: 'Completed authentication module',
43
+ keyLearnings: ['JWT expiry is 1h', 'Rate limiting is per IP'],
44
+ taskContext: 'Working on auth',
45
+ createdAt: '2026-04-02T23:00:00Z',
46
+ },
47
+ assembledAt: '2026-04-03T01:00:00Z',
48
+ totalTokens: 500,
49
+ };
50
+ describe('assemblePrompt', () => {
51
+ it('returns empty string when context is null', () => {
52
+ expect(assemblePrompt(null)).toBe('');
53
+ });
54
+ it('includes identity name and DID', () => {
55
+ const result = assemblePrompt(baseContext);
56
+ expect(result).toContain('Atlas');
57
+ expect(result).toContain('did:key:z6MkAgent001');
58
+ });
59
+ it('includes identity status and description', () => {
60
+ const result = assemblePrompt(baseContext);
61
+ expect(result).toContain('active');
62
+ expect(result).toContain('A general-purpose agent');
63
+ });
64
+ it('includes personality traits and communication style', () => {
65
+ const result = assemblePrompt(baseContext);
66
+ expect(result).toContain('direct');
67
+ expect(result).toContain('curious');
68
+ expect(result).toContain('0.9');
69
+ });
70
+ it('includes personality tone preferences', () => {
71
+ const result = assemblePrompt(baseContext);
72
+ expect(result).toContain('professional');
73
+ expect(result).toContain('friendly');
74
+ });
75
+ it('includes goals with progress percentage', () => {
76
+ const result = assemblePrompt(baseContext);
77
+ expect(result).toContain('Implement feature X');
78
+ expect(result).toContain('60%');
79
+ expect(result).toContain('Write tests');
80
+ expect(result).toContain('20%');
81
+ });
82
+ it('includes memories with type labels', () => {
83
+ const result = assemblePrompt(baseContext);
84
+ expect(result).toContain('[semantic]');
85
+ expect(result).toContain('The API uses bearer tokens for auth');
86
+ expect(result).toContain('[episodic]');
87
+ expect(result).toContain('Deployed to Railway last Tuesday');
88
+ });
89
+ it('includes memory importance values', () => {
90
+ const result = assemblePrompt(baseContext);
91
+ expect(result).toContain('importance: 0.9');
92
+ expect(result).toContain('importance: 0.5');
93
+ });
94
+ it('includes last handoff summary and key learnings', () => {
95
+ const result = assemblePrompt(baseContext);
96
+ expect(result).toContain('Completed authentication module');
97
+ expect(result).toContain('JWT expiry is 1h');
98
+ expect(result).toContain('Rate limiting is per IP');
99
+ });
100
+ it('includes behavioral instructions with "continuous entity" and "handoff"', () => {
101
+ const result = assemblePrompt(baseContext);
102
+ expect(result).toContain('continuous entity');
103
+ expect(result).toContain('handoff');
104
+ });
105
+ it('includes persistent knowledge instruction', () => {
106
+ const result = assemblePrompt(baseContext);
107
+ expect(result).toContain('persistent knowledge');
108
+ });
109
+ it('handles missing personality gracefully — no Communication style section', () => {
110
+ const ctx = { ...baseContext, personality: null };
111
+ const result = assemblePrompt(ctx);
112
+ expect(result).not.toContain('Communication style');
113
+ expect(result).not.toContain('Personality');
114
+ // Identity still present
115
+ expect(result).toContain('Atlas');
116
+ });
117
+ it('handles missing lastHandoff gracefully — no Last Handoff section', () => {
118
+ const ctx = { ...baseContext, lastHandoff: null };
119
+ const result = assemblePrompt(ctx);
120
+ expect(result).not.toContain('Last Handoff');
121
+ expect(result).not.toContain('Completed authentication module');
122
+ // Behavioral instructions still present
123
+ expect(result).toContain('continuous entity');
124
+ });
125
+ it('trims memories when total chars exceed budget (30 memories → fewer in output)', () => {
126
+ // Build 30 large memories — each ~600 chars content
127
+ const manyMemories = Array.from({ length: 30 }, (_, i) => ({
128
+ id: `mem-${i}`,
129
+ content: `Memory content ${i}: ${'x'.repeat(550)}`,
130
+ type: 'semantic',
131
+ importance: (30 - i) / 30, // descending importance
132
+ createdAt: '2026-04-03T00:00:00Z',
133
+ }));
134
+ const ctx = { ...baseContext, recentMemories: manyMemories };
135
+ const result = assemblePrompt(ctx);
136
+ // Count how many memory lines appear (lines starting with "- [")
137
+ const memoryLineCount = result
138
+ .split('\n')
139
+ .filter((line) => line.startsWith('- [')).length;
140
+ expect(memoryLineCount).toBeGreaterThan(0);
141
+ expect(memoryLineCount).toBeLessThan(30);
142
+ // Total output should be within or near the budget
143
+ expect(result.length).toBeLessThanOrEqual(16_000 + 700); // small buffer for last line
144
+ });
145
+ it('sorts memories by importance descending when trimming', () => {
146
+ // High importance memory should survive trimming; low importance should be dropped
147
+ const mixedMemories = [
148
+ {
149
+ id: 'low',
150
+ content: `Low importance memory: ${'z'.repeat(400)}`,
151
+ type: 'episodic',
152
+ importance: 0.1,
153
+ createdAt: '2026-04-03T00:00:00Z',
154
+ },
155
+ ...Array.from({ length: 25 }, (_, i) => ({
156
+ id: `filler-${i}`,
157
+ content: `Filler memory ${i}: ${'x'.repeat(500)}`,
158
+ type: 'semantic',
159
+ importance: 0.5,
160
+ createdAt: '2026-04-03T00:00:00Z',
161
+ })),
162
+ {
163
+ id: 'high',
164
+ content: 'High importance unique marker KEEP_THIS',
165
+ type: 'semantic',
166
+ importance: 0.99,
167
+ createdAt: '2026-04-03T00:00:00Z',
168
+ },
169
+ ];
170
+ const ctx = { ...baseContext, recentMemories: mixedMemories };
171
+ const result = assemblePrompt(ctx);
172
+ // The high-importance memory should be in the output
173
+ expect(result).toContain('KEEP_THIS');
174
+ });
175
+ it('handles empty goals array gracefully', () => {
176
+ const ctx = { ...baseContext, goals: [] };
177
+ const result = assemblePrompt(ctx);
178
+ // No goals section or empty — just shouldn't throw
179
+ expect(result).toContain('Atlas');
180
+ });
181
+ it('handles empty memories array gracefully', () => {
182
+ const ctx = { ...baseContext, recentMemories: [] };
183
+ const result = assemblePrompt(ctx);
184
+ expect(result).toContain('Atlas');
185
+ expect(result).toContain('Recent Memories');
186
+ expect(result).toContain('(none)');
187
+ });
188
+ it('limits personality traits to top 5 by value', () => {
189
+ const ctx = {
190
+ ...baseContext,
191
+ personality: {
192
+ ...baseContext.personality,
193
+ traits: [
194
+ { name: 'trait-a', value: 0.1 },
195
+ { name: 'trait-b', value: 0.2 },
196
+ { name: 'trait-c', value: 0.3 },
197
+ { name: 'trait-d', value: 0.4 },
198
+ { name: 'trait-e', value: 0.5 },
199
+ { name: 'trait-f', value: 0.6 }, // top 5 cutoff
200
+ { name: 'trait-g', value: 0.7 },
201
+ { name: 'trait-h', value: 0.8 },
202
+ ],
203
+ },
204
+ };
205
+ const result = assemblePrompt(ctx);
206
+ // Top 5: trait-h, trait-g, trait-f, trait-e, trait-d
207
+ expect(result).toContain('trait-h');
208
+ expect(result).toContain('trait-g');
209
+ expect(result).toContain('trait-f');
210
+ expect(result).toContain('trait-e');
211
+ expect(result).toContain('trait-d');
212
+ // Bottom 3 should NOT appear
213
+ expect(result).not.toContain('trait-a');
214
+ expect(result).not.toContain('trait-b');
215
+ expect(result).not.toContain('trait-c');
216
+ });
217
+ });
218
+ //# sourceMappingURL=prompt-resource.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-resource.test.js","sourceRoot":"","sources":["../../src/__tests__/prompt-resource.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,37 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'node:fs';
3
+ import { tmpdir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import { readClaudeMemoryTree } from '../cli/read-claude-memory-tree.js';
6
+ describe('readClaudeMemoryTree', () => {
7
+ let tmpRoot;
8
+ beforeEach(() => {
9
+ tmpRoot = mkdtempSync(join(tmpdir(), 'aismem-walker-'));
10
+ });
11
+ afterEach(() => rmSync(tmpRoot, { recursive: true, force: true }));
12
+ it('only reads .md files from project/memory subtrees', () => {
13
+ // Project A with memory/ dir and .md files
14
+ const projectA = join(tmpRoot, 'projectA');
15
+ const memA = join(projectA, 'memory');
16
+ mkdirSync(memA, { recursive: true });
17
+ writeFileSync(join(memA, 'MEMORY.md'), '# A');
18
+ writeFileSync(join(memA, 'feedback_x.md'), '# fx');
19
+ // Also a .md OUTSIDE memory/ — should NOT be included
20
+ writeFileSync(join(projectA, 'README.md'), '# readme');
21
+ // Project B without memory/ dir — should be skipped entirely
22
+ const projectB = join(tmpRoot, 'projectB');
23
+ mkdirSync(projectB, { recursive: true });
24
+ writeFileSync(join(projectB, 'CLAUDE.md'), '# claude');
25
+ const result = readClaudeMemoryTree(tmpRoot);
26
+ const paths = result.files.map((f) => f.path);
27
+ expect(paths).toContain(join(memA, 'MEMORY.md'));
28
+ expect(paths).toContain(join(memA, 'feedback_x.md'));
29
+ expect(paths).not.toContain(join(projectA, 'README.md'));
30
+ expect(paths).not.toContain(join(projectB, 'CLAUDE.md'));
31
+ });
32
+ it('returns empty when root does not exist or is not a directory', () => {
33
+ const result = readClaudeMemoryTree(join(tmpRoot, 'does-not-exist'));
34
+ expect(result.files).toEqual([]);
35
+ });
36
+ });
37
+ //# sourceMappingURL=read-claude-memory-tree.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-claude-memory-tree.test.js","sourceRoot":"","sources":["../../src/__tests__/read-claude-memory-tree.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACxE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAEzE,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,IAAI,OAAe,CAAC;IAEpB,UAAU,CAAC,GAAG,EAAE;QACd,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAEnE,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,2CAA2C;QAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACtC,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,KAAK,CAAC,CAAC;QAC9C,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,EAAE,MAAM,CAAC,CAAC;QACnD,sDAAsD;QACtD,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,EAAE,UAAU,CAAC,CAAC;QAEvD,6DAA6D;QAC7D,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAC3C,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,EAAE,UAAU,CAAC,CAAC;QAEvD,MAAM,MAAM,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC9C,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC;QACjD,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC;QACrD,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC;QACzD,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;QACtE,MAAM,MAAM,GAAG,oBAAoB,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC;QACrE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,73 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
+ import { startRefreshTimer, stopRefreshTimer } from '../refresh.js';
3
+ const MOCK_AIS_URL = 'https://ais.example.com';
4
+ const MOCK_AGENT_ID = 'agent-123';
5
+ const MOCK_TOKEN = 'test-token';
6
+ const INTERVAL_MS = 1000;
7
+ const mockMemories = [
8
+ { id: 'm1', content: 'Test memory', type: 'episodic', importance: 0.8, createdAt: '2026-01-01T00:00:00Z' },
9
+ ];
10
+ function makeFetchMock(ok, body) {
11
+ return vi.fn().mockResolvedValue({
12
+ ok,
13
+ json: vi.fn().mockResolvedValue(body),
14
+ });
15
+ }
16
+ describe('startRefreshTimer', () => {
17
+ beforeEach(() => {
18
+ vi.useFakeTimers();
19
+ });
20
+ afterEach(() => {
21
+ stopRefreshTimer();
22
+ vi.restoreAllMocks();
23
+ vi.useRealTimers();
24
+ });
25
+ it('fetches memories on tick and calls the update callback', async () => {
26
+ const mockFetch = makeFetchMock(true, {
27
+ success: true,
28
+ data: { memories: mockMemories },
29
+ });
30
+ vi.stubGlobal('fetch', mockFetch);
31
+ const onUpdate = vi.fn();
32
+ startRefreshTimer(MOCK_AIS_URL, MOCK_AGENT_ID, MOCK_TOKEN, onUpdate, INTERVAL_MS);
33
+ // Advance time to trigger the first tick
34
+ await vi.advanceTimersByTimeAsync(INTERVAL_MS);
35
+ expect(mockFetch).toHaveBeenCalledOnce();
36
+ expect(mockFetch).toHaveBeenCalledWith(`${MOCK_AIS_URL}/v1/agents/${MOCK_AGENT_ID}/memory?limit=20&minImportance=0.5`, { headers: { Authorization: `Bearer ${MOCK_TOKEN}` } });
37
+ expect(onUpdate).toHaveBeenCalledOnce();
38
+ expect(onUpdate).toHaveBeenCalledWith(mockMemories);
39
+ });
40
+ it('does not crash when fetch fails and timer continues', async () => {
41
+ const mockFetch = vi.fn().mockRejectedValue(new Error('Network error'));
42
+ vi.stubGlobal('fetch', mockFetch);
43
+ const onUpdate = vi.fn();
44
+ startRefreshTimer(MOCK_AIS_URL, MOCK_AGENT_ID, MOCK_TOKEN, onUpdate, INTERVAL_MS);
45
+ // First tick — fetch throws, should not crash
46
+ await vi.advanceTimersByTimeAsync(INTERVAL_MS);
47
+ expect(mockFetch).toHaveBeenCalledOnce();
48
+ expect(onUpdate).not.toHaveBeenCalled();
49
+ // Second tick — timer is still running
50
+ await vi.advanceTimersByTimeAsync(INTERVAL_MS);
51
+ expect(mockFetch).toHaveBeenCalledTimes(2);
52
+ expect(onUpdate).not.toHaveBeenCalled();
53
+ });
54
+ it('stopRefreshTimer clears the interval so no more callbacks fire', async () => {
55
+ const mockFetch = makeFetchMock(true, {
56
+ success: true,
57
+ data: { memories: mockMemories },
58
+ });
59
+ vi.stubGlobal('fetch', mockFetch);
60
+ const onUpdate = vi.fn();
61
+ startRefreshTimer(MOCK_AIS_URL, MOCK_AGENT_ID, MOCK_TOKEN, onUpdate, INTERVAL_MS);
62
+ // First tick fires
63
+ await vi.advanceTimersByTimeAsync(INTERVAL_MS);
64
+ expect(onUpdate).toHaveBeenCalledOnce();
65
+ // Stop the timer
66
+ stopRefreshTimer();
67
+ // Advance time again — no additional calls should occur
68
+ await vi.advanceTimersByTimeAsync(INTERVAL_MS * 3);
69
+ expect(onUpdate).toHaveBeenCalledOnce(); // still only 1
70
+ expect(mockFetch).toHaveBeenCalledOnce(); // still only 1
71
+ });
72
+ });
73
+ //# sourceMappingURL=refresh.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refresh.test.js","sourceRoot":"","sources":["../../src/__tests__/refresh.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};