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.
- package/README.md +1 -0
- package/dist/__tests__/auto-handoff.test.d.ts +1 -0
- package/dist/__tests__/auto-handoff.test.js +72 -0
- package/dist/__tests__/auto-handoff.test.js.map +1 -0
- package/dist/__tests__/cli-review.test.d.ts +1 -0
- package/dist/__tests__/cli-review.test.js +26 -0
- package/dist/__tests__/cli-review.test.js.map +1 -0
- package/dist/__tests__/config.test.d.ts +1 -0
- package/dist/__tests__/config.test.js +54 -0
- package/dist/__tests__/config.test.js.map +1 -0
- package/dist/__tests__/hydration.test.d.ts +1 -0
- package/dist/__tests__/hydration.test.js +111 -0
- package/dist/__tests__/hydration.test.js.map +1 -0
- package/dist/__tests__/integration.test.d.ts +1 -0
- package/dist/__tests__/integration.test.js +36 -0
- package/dist/__tests__/integration.test.js.map +1 -0
- package/dist/__tests__/local-claude-source.test.d.ts +1 -0
- package/dist/__tests__/local-claude-source.test.js +97 -0
- package/dist/__tests__/local-claude-source.test.js.map +1 -0
- package/dist/__tests__/local-mirror.test.d.ts +1 -0
- package/dist/__tests__/local-mirror.test.js +95 -0
- package/dist/__tests__/local-mirror.test.js.map +1 -0
- package/dist/__tests__/pipeline-ingestion.test.d.ts +1 -0
- package/dist/__tests__/pipeline-ingestion.test.js +161 -0
- package/dist/__tests__/pipeline-ingestion.test.js.map +1 -0
- package/dist/__tests__/pipeline-scope-resolver.test.d.ts +1 -0
- package/dist/__tests__/pipeline-scope-resolver.test.js +51 -0
- package/dist/__tests__/pipeline-scope-resolver.test.js.map +1 -0
- package/dist/__tests__/pipeline-trust-tagger.test.d.ts +1 -0
- package/dist/__tests__/pipeline-trust-tagger.test.js +24 -0
- package/dist/__tests__/pipeline-trust-tagger.test.js.map +1 -0
- package/dist/__tests__/prompt-resource.test.d.ts +1 -0
- package/dist/__tests__/prompt-resource.test.js +218 -0
- package/dist/__tests__/prompt-resource.test.js.map +1 -0
- package/dist/__tests__/read-claude-memory-tree.test.d.ts +1 -0
- package/dist/__tests__/read-claude-memory-tree.test.js +37 -0
- package/dist/__tests__/read-claude-memory-tree.test.js.map +1 -0
- package/dist/__tests__/refresh.test.d.ts +1 -0
- package/dist/__tests__/refresh.test.js +73 -0
- package/dist/__tests__/refresh.test.js.map +1 -0
- package/dist/__tests__/trust-ledger.test.d.ts +1 -0
- package/dist/__tests__/trust-ledger.test.js +55 -0
- package/dist/__tests__/trust-ledger.test.js.map +1 -0
- package/dist/auto-handoff.d.ts +15 -0
- package/dist/auto-handoff.js +53 -0
- package/dist/auto-handoff.js.map +1 -0
- package/dist/cli/read-claude-memory-tree.d.ts +7 -0
- package/dist/cli/read-claude-memory-tree.js +65 -0
- package/dist/cli/read-claude-memory-tree.js.map +1 -0
- package/dist/cli/sync-memory.d.ts +2 -0
- package/dist/cli/sync-memory.js +155 -0
- package/dist/cli/sync-memory.js.map +1 -0
- package/dist/config.d.ts +11 -0
- package/dist/config.js +51 -0
- package/dist/config.js.map +1 -0
- package/dist/hydration.d.ts +2 -0
- package/dist/hydration.js +62 -0
- package/dist/hydration.js.map +1 -0
- package/dist/index.js +173 -11
- package/dist/index.js.map +1 -1
- package/dist/local-mirror.d.ts +15 -0
- package/dist/local-mirror.js +56 -0
- package/dist/local-mirror.js.map +1 -0
- package/dist/pipeline/dedupe.d.ts +11 -0
- package/dist/pipeline/dedupe.js +21 -0
- package/dist/pipeline/dedupe.js.map +1 -0
- package/dist/pipeline/ingestion.d.ts +56 -0
- package/dist/pipeline/ingestion.js +86 -0
- package/dist/pipeline/ingestion.js.map +1 -0
- package/dist/pipeline/scope-resolver.d.ts +15 -0
- package/dist/pipeline/scope-resolver.js +28 -0
- package/dist/pipeline/scope-resolver.js.map +1 -0
- package/dist/pipeline/trust-tagger.d.ts +10 -0
- package/dist/pipeline/trust-tagger.js +12 -0
- package/dist/pipeline/trust-tagger.js.map +1 -0
- package/dist/pipeline/types.d.ts +41 -0
- package/dist/pipeline/types.js +6 -0
- package/dist/pipeline/types.js.map +1 -0
- package/dist/prompt-resource.d.ts +2 -0
- package/dist/prompt-resource.js +77 -0
- package/dist/prompt-resource.js.map +1 -0
- package/dist/refresh.d.ts +3 -0
- package/dist/refresh.js +25 -0
- package/dist/refresh.js.map +1 -0
- package/dist/review/cli-review.d.ts +10 -0
- package/dist/review/cli-review.js +47 -0
- package/dist/review/cli-review.js.map +1 -0
- package/dist/sources/local-claude.d.ts +11 -0
- package/dist/sources/local-claude.js +137 -0
- package/dist/sources/local-claude.js.map +1 -0
- package/dist/sources/types.d.ts +53 -0
- package/dist/sources/types.js +9 -0
- package/dist/sources/types.js.map +1 -0
- package/dist/trust-ledger.d.ts +8 -0
- package/dist/trust-ledger.js +61 -0
- package/dist/trust-ledger.js.map +1 -0
- package/dist/types.d.ts +45 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- 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 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/pipeline/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -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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"}
|
package/dist/refresh.js
ADDED
|
@@ -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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"}
|
package/dist/types.d.ts
ADDED
|
@@ -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 @@
|
|
|
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.
|
|
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"
|