aismemory 0.2.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 (69) hide show
  1. package/dist/__tests__/cli-review.test.d.ts +1 -0
  2. package/dist/__tests__/cli-review.test.js +26 -0
  3. package/dist/__tests__/cli-review.test.js.map +1 -0
  4. package/dist/__tests__/config.test.d.ts +1 -0
  5. package/dist/__tests__/config.test.js +54 -0
  6. package/dist/__tests__/config.test.js.map +1 -0
  7. package/dist/__tests__/local-claude-source.test.d.ts +1 -0
  8. package/dist/__tests__/local-claude-source.test.js +97 -0
  9. package/dist/__tests__/local-claude-source.test.js.map +1 -0
  10. package/dist/__tests__/local-mirror.test.d.ts +1 -0
  11. package/dist/__tests__/local-mirror.test.js +95 -0
  12. package/dist/__tests__/local-mirror.test.js.map +1 -0
  13. package/dist/__tests__/pipeline-ingestion.test.d.ts +1 -0
  14. package/dist/__tests__/pipeline-ingestion.test.js +161 -0
  15. package/dist/__tests__/pipeline-ingestion.test.js.map +1 -0
  16. package/dist/__tests__/pipeline-scope-resolver.test.d.ts +1 -0
  17. package/dist/__tests__/pipeline-scope-resolver.test.js +51 -0
  18. package/dist/__tests__/pipeline-scope-resolver.test.js.map +1 -0
  19. package/dist/__tests__/pipeline-trust-tagger.test.d.ts +1 -0
  20. package/dist/__tests__/pipeline-trust-tagger.test.js +24 -0
  21. package/dist/__tests__/pipeline-trust-tagger.test.js.map +1 -0
  22. package/dist/__tests__/read-claude-memory-tree.test.d.ts +1 -0
  23. package/dist/__tests__/read-claude-memory-tree.test.js +37 -0
  24. package/dist/__tests__/read-claude-memory-tree.test.js.map +1 -0
  25. package/dist/__tests__/trust-ledger.test.d.ts +1 -0
  26. package/dist/__tests__/trust-ledger.test.js +55 -0
  27. package/dist/__tests__/trust-ledger.test.js.map +1 -0
  28. package/dist/cli/read-claude-memory-tree.d.ts +7 -0
  29. package/dist/cli/read-claude-memory-tree.js +65 -0
  30. package/dist/cli/read-claude-memory-tree.js.map +1 -0
  31. package/dist/cli/sync-memory.d.ts +2 -0
  32. package/dist/cli/sync-memory.js +155 -0
  33. package/dist/cli/sync-memory.js.map +1 -0
  34. package/dist/config.d.ts +11 -0
  35. package/dist/config.js +51 -0
  36. package/dist/config.js.map +1 -0
  37. package/dist/index.js +46 -18
  38. package/dist/index.js.map +1 -1
  39. package/dist/local-mirror.d.ts +15 -0
  40. package/dist/local-mirror.js +56 -0
  41. package/dist/local-mirror.js.map +1 -0
  42. package/dist/pipeline/dedupe.d.ts +11 -0
  43. package/dist/pipeline/dedupe.js +21 -0
  44. package/dist/pipeline/dedupe.js.map +1 -0
  45. package/dist/pipeline/ingestion.d.ts +56 -0
  46. package/dist/pipeline/ingestion.js +86 -0
  47. package/dist/pipeline/ingestion.js.map +1 -0
  48. package/dist/pipeline/scope-resolver.d.ts +15 -0
  49. package/dist/pipeline/scope-resolver.js +28 -0
  50. package/dist/pipeline/scope-resolver.js.map +1 -0
  51. package/dist/pipeline/trust-tagger.d.ts +10 -0
  52. package/dist/pipeline/trust-tagger.js +12 -0
  53. package/dist/pipeline/trust-tagger.js.map +1 -0
  54. package/dist/pipeline/types.d.ts +41 -0
  55. package/dist/pipeline/types.js +6 -0
  56. package/dist/pipeline/types.js.map +1 -0
  57. package/dist/review/cli-review.d.ts +10 -0
  58. package/dist/review/cli-review.js +47 -0
  59. package/dist/review/cli-review.js.map +1 -0
  60. package/dist/sources/local-claude.d.ts +11 -0
  61. package/dist/sources/local-claude.js +137 -0
  62. package/dist/sources/local-claude.js.map +1 -0
  63. package/dist/sources/types.d.ts +53 -0
  64. package/dist/sources/types.js +9 -0
  65. package/dist/sources/types.js.map +1 -0
  66. package/dist/trust-ledger.d.ts +8 -0
  67. package/dist/trust-ledger.js +61 -0
  68. package/dist/trust-ledger.js.map +1 -0
  69. package/package.json +1 -1
@@ -0,0 +1,56 @@
1
+ import { existsSync, mkdirSync, appendFileSync, readFileSync, writeFileSync, renameSync, unlinkSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { homedir } from 'node:os';
4
+ export class LocalMirror {
5
+ home;
6
+ retentionDays;
7
+ cacheDir;
8
+ constructor(home = homedir(), retentionDays = 30) {
9
+ this.home = home;
10
+ this.retentionDays = retentionDays;
11
+ this.cacheDir = join(home, '.aismemory', 'cache');
12
+ if (!existsSync(this.cacheDir)) {
13
+ mkdirSync(this.cacheDir, { recursive: true, mode: 0o700 });
14
+ }
15
+ }
16
+ append(agentId, entries) {
17
+ const filePath = this.pathFor(agentId);
18
+ const lines = entries
19
+ .map((e) => {
20
+ const stored = { ...e, importedAt: e.memory.provenance.importedAt };
21
+ return JSON.stringify(stored);
22
+ })
23
+ .join('\n') + '\n';
24
+ appendFileSync(filePath, lines, { mode: 0o600 });
25
+ }
26
+ cleanup(agentId) {
27
+ const filePath = this.pathFor(agentId);
28
+ if (!existsSync(filePath))
29
+ return;
30
+ const cutoff = Date.now() - this.retentionDays * 24 * 60 * 60 * 1000;
31
+ const lines = readFileSync(filePath, 'utf8')
32
+ .split('\n')
33
+ .filter((l) => l.length > 0);
34
+ const surviving = lines.filter((line) => {
35
+ try {
36
+ const parsed = JSON.parse(line);
37
+ return new Date(parsed.importedAt).getTime() >= cutoff;
38
+ }
39
+ catch {
40
+ return false;
41
+ }
42
+ });
43
+ const tmp = `${filePath}.tmp`;
44
+ writeFileSync(tmp, surviving.join('\n') + (surviving.length > 0 ? '\n' : ''), { mode: 0o600 });
45
+ renameSync(tmp, filePath);
46
+ }
47
+ scrub(agentId) {
48
+ const filePath = this.pathFor(agentId);
49
+ if (existsSync(filePath))
50
+ unlinkSync(filePath);
51
+ }
52
+ pathFor(agentId) {
53
+ return join(this.cacheDir, `${agentId}.jsonl`);
54
+ }
55
+ }
56
+ //# sourceMappingURL=local-mirror.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-mirror.js","sourceRoot":"","sources":["../src/local-mirror.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { AisMemoryDraft } from './types.js';
2
+ export interface DedupeResult {
3
+ keep: AisMemoryDraft[];
4
+ skippedExactDupes: number;
5
+ }
6
+ /**
7
+ * Exact-dupe filtering by provenance.sourceHash. Near-dupe detection via
8
+ * embeddings happens in the review UI layer, not here — this stage only
9
+ * prevents identical re-imports.
10
+ */
11
+ export declare function preCommitDedupe(drafts: AisMemoryDraft[], existingHashes: ReadonlySet<string>): DedupeResult;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Exact-dupe filtering by provenance.sourceHash. Near-dupe detection via
3
+ * embeddings happens in the review UI layer, not here — this stage only
4
+ * prevents identical re-imports.
5
+ */
6
+ export function preCommitDedupe(drafts, existingHashes) {
7
+ const seenHashes = new Set();
8
+ const keep = [];
9
+ let skipped = 0;
10
+ for (const draft of drafts) {
11
+ const hash = draft.provenance.sourceHash;
12
+ if (existingHashes.has(hash) || seenHashes.has(hash)) {
13
+ skipped += 1;
14
+ continue;
15
+ }
16
+ seenHashes.add(hash);
17
+ keep.push(draft);
18
+ }
19
+ return { keep, skippedExactDupes: skipped };
20
+ }
21
+ //# sourceMappingURL=dedupe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dedupe.js","sourceRoot":"","sources":["../../src/pipeline/dedupe.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAwB,EACxB,cAAmC;IAEnC,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;IACrC,MAAM,IAAI,GAAqB,EAAE,CAAC;IAClC,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC;QACzC,IAAI,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACrD,OAAO,IAAI,CAAC,CAAC;YACb,SAAS;QACX,CAAC;QACD,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACrB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnB,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,56 @@
1
+ import type { SourceAdapter, FilesystemResult } from '../sources/types.js';
2
+ import type { SyncScope, AisMemoryDraft, SyncResult } from './types.js';
3
+ import type { SyncConfig } from '../config.js';
4
+ import type { TrustLedger } from '../trust-ledger.js';
5
+ import type { LocalMirror } from '../local-mirror.js';
6
+ export interface BulkStoreResult {
7
+ created: Array<{
8
+ index: number;
9
+ id: string;
10
+ }>;
11
+ failed: Array<{
12
+ index: number;
13
+ error: string;
14
+ }>;
15
+ }
16
+ export type BulkStoreFn = (drafts: AisMemoryDraft[]) => Promise<BulkStoreResult>;
17
+ export type ReviewFn = (drafts: AisMemoryDraft[]) => Promise<AisMemoryDraft[]>;
18
+ export interface IngestionOptions {
19
+ adapter: SourceAdapter;
20
+ rawSourceData: string | FilesystemResult;
21
+ scope: SyncScope;
22
+ agentId: string;
23
+ config: SyncConfig;
24
+ ledger: TrustLedger;
25
+ mirror: LocalMirror;
26
+ existingHashes: ReadonlySet<string>;
27
+ bulkStore: BulkStoreFn;
28
+ review: ReviewFn;
29
+ defaultTrustScore?: number;
30
+ }
31
+ /**
32
+ * Run the full ingestion pipeline for a single source adapter + scope pair.
33
+ *
34
+ * Pipeline order:
35
+ * 1. Parse raw source data via `adapter.parseResponse`.
36
+ * 2. Map to AIS drafts and apply trust tags.
37
+ * 3. Pre-commit deduplicate against `existingHashes`.
38
+ * 4. Offer non-auto-commit batches to `review` for user approval.
39
+ * 5. Bulk-store approved drafts in AIS via `bulkStore`.
40
+ * 6. Advance the trust ledger (`ledger.recordSync`).
41
+ * 7. Append entries to the local mirror.
42
+ *
43
+ * Failure semantics:
44
+ * - If `bulkStore` throws, neither ledger nor mirror is updated — the caller
45
+ * may safely retry the entire run without double-counting.
46
+ * - If `mirror.append` throws after a successful `bulkStore`, the ledger has
47
+ * already been advanced (AIS accepted the memories) and the failure is
48
+ * surfaced as a `warnings` entry rather than an exception so the caller
49
+ * receives a valid `SyncResult`.
50
+ *
51
+ * Zero-import path:
52
+ * - When all candidates are dedupe-skipped or rejected by `review`,
53
+ * `ledger.recordSync` is still called so the `syncCount` advances and the
54
+ * trust ladder progresses toward auto-commit on future syncs.
55
+ */
56
+ export declare function runIngestion(options: IngestionOptions): Promise<SyncResult>;
@@ -0,0 +1,86 @@
1
+ import { preCommitDedupe } from './dedupe.js';
2
+ import { applyTrustTags } from './trust-tagger.js';
3
+ /**
4
+ * Run the full ingestion pipeline for a single source adapter + scope pair.
5
+ *
6
+ * Pipeline order:
7
+ * 1. Parse raw source data via `adapter.parseResponse`.
8
+ * 2. Map to AIS drafts and apply trust tags.
9
+ * 3. Pre-commit deduplicate against `existingHashes`.
10
+ * 4. Offer non-auto-commit batches to `review` for user approval.
11
+ * 5. Bulk-store approved drafts in AIS via `bulkStore`.
12
+ * 6. Advance the trust ledger (`ledger.recordSync`).
13
+ * 7. Append entries to the local mirror.
14
+ *
15
+ * Failure semantics:
16
+ * - If `bulkStore` throws, neither ledger nor mirror is updated — the caller
17
+ * may safely retry the entire run without double-counting.
18
+ * - If `mirror.append` throws after a successful `bulkStore`, the ledger has
19
+ * already been advanced (AIS accepted the memories) and the failure is
20
+ * surfaced as a `warnings` entry rather than an exception so the caller
21
+ * receives a valid `SyncResult`.
22
+ *
23
+ * Zero-import path:
24
+ * - When all candidates are dedupe-skipped or rejected by `review`,
25
+ * `ledger.recordSync` is still called so the `syncCount` advances and the
26
+ * trust ladder progresses toward auto-commit on future syncs.
27
+ */
28
+ export async function runIngestion(options) {
29
+ const { adapter, rawSourceData, scope, agentId, config, ledger, mirror, existingHashes, bulkStore, review, } = options;
30
+ const defaultTrustScore = options.defaultTrustScore ?? 0.5;
31
+ const parsed = adapter.parseResponse(rawSourceData);
32
+ const candidateDrafts = parsed.memories.map((src) => adapter.mapToAis(src, scope, agentId));
33
+ const taggedDrafts = applyTrustTags(candidateDrafts, { defaultTrustScore });
34
+ const { keep: afterDedupe, skippedExactDupes } = preCommitDedupe(taggedDrafts, existingHashes);
35
+ const scopeKey = scopeToKey(scope);
36
+ const shouldAutoCommit = config.autoCommit(adapter.id) || ledger.isTrusted(agentId, adapter.id, scopeKey);
37
+ const approved = shouldAutoCommit ? afterDedupe : await review(afterDedupe);
38
+ const skippedByUser = afterDedupe.length - approved.length;
39
+ if (approved.length === 0) {
40
+ ledger.recordSync(agentId, adapter.id, scopeKey);
41
+ return {
42
+ imported: 0,
43
+ skippedExactDupes,
44
+ skippedByUser,
45
+ warnings: parsed.warnings,
46
+ memoryIds: [],
47
+ failed: [],
48
+ };
49
+ }
50
+ const storeResult = await bulkStore(approved);
51
+ // Advance the trust ledger FIRST — if AIS accepted the memories, the
52
+ // trust ladder must reflect that regardless of local-mirror success.
53
+ ledger.recordSync(agentId, adapter.id, scopeKey);
54
+ const mirrorEntries = storeResult.created.map((c) => ({
55
+ aisMemoryId: c.id,
56
+ memory: approved[c.index],
57
+ }));
58
+ const mirrorWarnings = [];
59
+ try {
60
+ mirror.append(agentId, mirrorEntries);
61
+ }
62
+ catch (err) {
63
+ const msg = err instanceof Error ? err.message : String(err);
64
+ mirrorWarnings.push(`local mirror append failed: ${msg}`);
65
+ }
66
+ return {
67
+ imported: storeResult.created.length,
68
+ skippedExactDupes,
69
+ skippedByUser,
70
+ warnings: [...parsed.warnings, ...mirrorWarnings],
71
+ memoryIds: storeResult.created.map((c) => c.id),
72
+ failed: storeResult.failed,
73
+ };
74
+ }
75
+ function scopeToKey(scope) {
76
+ // Stable multi-field encoding prevents collisions when optional fields
77
+ // are absent. Pipe separator is safe because none of the component
78
+ // values may contain it in practice (enforced by call sites).
79
+ return [
80
+ scope.kind,
81
+ scope.goalId ?? '',
82
+ scope.projectPath ?? '',
83
+ scope.label,
84
+ ].join('|');
85
+ }
86
+ //# sourceMappingURL=ingestion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ingestion.js","sourceRoot":"","sources":["../../src/pipeline/ingestion.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { SyncConfig } from '../config.js';
2
+ import type { SyncScope } from './types.js';
3
+ export interface ActiveGoal {
4
+ id: string;
5
+ description: string;
6
+ }
7
+ export interface ScopeResolverOptions {
8
+ config: SyncConfig;
9
+ projectPath: string | null;
10
+ activeGoal: ActiveGoal | null;
11
+ sessionTopic: string | null;
12
+ confirmer: (proposed: SyncScope) => Promise<SyncScope>;
13
+ saveAsDefault?: boolean;
14
+ }
15
+ export declare function resolveScope(options: ScopeResolverOptions): Promise<SyncScope>;
@@ -0,0 +1,28 @@
1
+ export async function resolveScope(options) {
2
+ const { config, projectPath, activeGoal, sessionTopic, confirmer, saveAsDefault = false } = options;
3
+ if (projectPath) {
4
+ const saved = config.scopePreference(projectPath);
5
+ if (saved)
6
+ return saved;
7
+ }
8
+ let proposed;
9
+ if (activeGoal) {
10
+ proposed = { kind: 'goal', label: activeGoal.description, goalId: activeGoal.id };
11
+ }
12
+ else if (projectPath) {
13
+ const label = projectPath.split('/').filter(Boolean).pop() ?? 'project';
14
+ proposed = { kind: 'project', label, projectPath };
15
+ }
16
+ else if (sessionTopic) {
17
+ proposed = { kind: 'session', label: sessionTopic, topicSummary: sessionTopic };
18
+ }
19
+ else {
20
+ proposed = { kind: 'user-named', label: 'untitled' };
21
+ }
22
+ const confirmed = await confirmer(proposed);
23
+ if (saveAsDefault && projectPath) {
24
+ config.saveScopePreference(projectPath, confirmed);
25
+ }
26
+ return confirmed;
27
+ }
28
+ //# sourceMappingURL=scope-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope-resolver.js","sourceRoot":"","sources":["../../src/pipeline/scope-resolver.ts"],"names":[],"mappings":"AAiBA,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAA6B;IAC9D,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IAEpG,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,KAAK,GAAG,MAAM,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;QAClD,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;IAC1B,CAAC;IAED,IAAI,QAAmB,CAAC;IACxB,IAAI,UAAU,EAAE,CAAC;QACf,QAAQ,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC;IACpF,CAAC;SAAM,IAAI,WAAW,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,IAAI,SAAS,CAAC;QACxE,QAAQ,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;IACrD,CAAC;SAAM,IAAI,YAAY,EAAE,CAAC;QACxB,QAAQ,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC;IAClF,CAAC;SAAM,CAAC;QACN,QAAQ,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;IACvD,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,CAAC;IAE5C,IAAI,aAAa,IAAI,WAAW,EAAE,CAAC;QACjC,MAAM,CAAC,mBAAmB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IACrD,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { AisMemoryDraft } from './types.js';
2
+ export interface TrustTagOptions {
3
+ defaultTrustScore: number;
4
+ }
5
+ /**
6
+ * Fills in default trust scores for drafts left at 0 by the adapter.
7
+ * Adapters may optionally pre-set trust (e.g., if they have provider-level
8
+ * confidence signals). This stage is a safety net, not a mandatory rewrite.
9
+ */
10
+ export declare function applyTrustTags(drafts: AisMemoryDraft[], options: TrustTagOptions): AisMemoryDraft[];
@@ -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,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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"}