ghagga-core 2.1.0 → 2.2.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/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/memory/engram-client.d.ts +38 -0
- package/dist/memory/engram-client.d.ts.map +1 -0
- package/dist/memory/engram-client.js +153 -0
- package/dist/memory/engram-client.js.map +1 -0
- package/dist/memory/engram-mapping.d.ts +83 -0
- package/dist/memory/engram-mapping.d.ts.map +1 -0
- package/dist/memory/engram-mapping.js +159 -0
- package/dist/memory/engram-mapping.js.map +1 -0
- package/dist/memory/engram-types.d.ts +51 -0
- package/dist/memory/engram-types.d.ts.map +1 -0
- package/dist/memory/engram-types.js +12 -0
- package/dist/memory/engram-types.js.map +1 -0
- package/dist/memory/engram.d.ts +76 -0
- package/dist/memory/engram.d.ts.map +1 -0
- package/dist/memory/engram.js +194 -0
- package/dist/memory/engram.js.map +1 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -17,5 +17,6 @@ export type { FallbackProvider, FallbackOptions, FallbackResult } from './provid
|
|
|
17
17
|
export { formatMemoryContext } from './memory/context.js';
|
|
18
18
|
export { stripPrivateData } from './memory/privacy.js';
|
|
19
19
|
export { SqliteMemoryStorage } from './memory/sqlite.js';
|
|
20
|
+
export { EngramMemoryStorage } from './memory/engram.js';
|
|
20
21
|
export { formatReviewComment, STATUS_EMOJI, SEVERITY_EMOJI } from './format.js';
|
|
21
22
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAI/C,YAAY,EAEV,WAAW,EACX,cAAc,EACd,aAAa,EACb,UAAU,EACV,WAAW,EACX,YAAY,EACZ,kBAAkB,EAClB,WAAW,EAGX,YAAY,EACZ,aAAa,EACb,cAAc,EACd,YAAY,EACZ,eAAe,EACf,aAAa,EAGb,oBAAoB,EACpB,UAAU,EACV,UAAU,EAGV,kBAAkB,EAClB,eAAe,EACf,aAAa,EAGb,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,oBAAoB,EACpB,uBAAuB,EACvB,WAAW,EACX,uBAAuB,EAGvB,gBAAgB,EAChB,aAAa,GACd,MAAM,YAAY,CAAC;AAIpB,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAI9D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACnF,YAAY,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAIjF,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAIjG,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAIzD,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAI/C,YAAY,EAEV,WAAW,EACX,cAAc,EACd,aAAa,EACb,UAAU,EACV,WAAW,EACX,YAAY,EACZ,kBAAkB,EAClB,WAAW,EAGX,YAAY,EACZ,aAAa,EACb,cAAc,EACd,YAAY,EACZ,eAAe,EACf,aAAa,EAGb,oBAAoB,EACpB,UAAU,EACV,UAAU,EAGV,kBAAkB,EAClB,eAAe,EACf,aAAa,EAGb,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,oBAAoB,EACpB,uBAAuB,EACvB,WAAW,EACX,uBAAuB,EAGvB,gBAAgB,EAChB,aAAa,GACd,MAAM,YAAY,CAAC;AAIpB,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAI9D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACnF,YAAY,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAIjF,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAIjG,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAIzD,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -19,6 +19,7 @@ export { generateWithFallback } from './providers/fallback.js';
|
|
|
19
19
|
export { formatMemoryContext } from './memory/context.js';
|
|
20
20
|
export { stripPrivateData } from './memory/privacy.js';
|
|
21
21
|
export { SqliteMemoryStorage } from './memory/sqlite.js';
|
|
22
|
+
export { EngramMemoryStorage } from './memory/engram.js';
|
|
22
23
|
// ─── Formatting ─────────────────────────────────────────────────
|
|
23
24
|
export { formatReviewComment, STATUS_EMOJI, SEVERITY_EMOJI } from './format.js';
|
|
24
25
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,mEAAmE;AAEnE,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AA+C/C,mEAAmE;AAEnE,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE9D,mEAAmE;AAEnE,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEnF,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAEjF,mEAAmE;AAEnE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAG/D,mEAAmE;AAEnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,mEAAmE;AAEnE,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,mEAAmE;AAEnE,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AA+C/C,mEAAmE;AAEnE,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE9D,mEAAmE;AAEnE,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEnF,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAEjF,mEAAmE;AAEnE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAG/D,mEAAmE;AAEnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,mEAAmE;AAEnE,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thin HTTP client wrapping native fetch() for the Engram REST API.
|
|
3
|
+
*
|
|
4
|
+
* Uses Node 18+ built-in fetch — no external dependencies.
|
|
5
|
+
* All methods are wrapped in try/catch and return safe fallback values
|
|
6
|
+
* (null, false, []) on failure. Errors are logged via console.warn
|
|
7
|
+
* for graceful degradation — the review never fails because of Engram.
|
|
8
|
+
*/
|
|
9
|
+
import type { EngramConfig, EngramObservation, EngramStats } from './engram-types.js';
|
|
10
|
+
export declare class EngramClient {
|
|
11
|
+
private baseUrl;
|
|
12
|
+
private timeout;
|
|
13
|
+
constructor(config: EngramConfig);
|
|
14
|
+
/** Health check: GET /api/stats. Returns true if Engram is reachable. */
|
|
15
|
+
healthCheck(): Promise<boolean>;
|
|
16
|
+
/** Search observations. GET /api/search?q=...&project=...&limit=... */
|
|
17
|
+
search(query: string, project?: string, limit?: number): Promise<EngramObservation[]>;
|
|
18
|
+
/** Save an observation. POST /api/save */
|
|
19
|
+
save(data: {
|
|
20
|
+
type: string;
|
|
21
|
+
title: string;
|
|
22
|
+
content: string;
|
|
23
|
+
project?: string;
|
|
24
|
+
topic_key?: string;
|
|
25
|
+
scope?: string;
|
|
26
|
+
}): Promise<EngramObservation | null>;
|
|
27
|
+
/** Get a single observation by ID. GET /api/observations/:id */
|
|
28
|
+
getObservation(id: string | number): Promise<EngramObservation | null>;
|
|
29
|
+
/** Delete an observation by ID. DELETE /api/observations/:id */
|
|
30
|
+
deleteObservation(id: string | number): Promise<boolean>;
|
|
31
|
+
/** Get aggregate stats. GET /api/stats */
|
|
32
|
+
getStats(): Promise<EngramStats | null>;
|
|
33
|
+
/** Create a new session. POST /api/sessions */
|
|
34
|
+
createSession(project: string): Promise<number | null>;
|
|
35
|
+
/** End a session with a summary. POST /api/sessions/:id/summary */
|
|
36
|
+
endSession(id: number, summary: string): Promise<void>;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=engram-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engram-client.d.ts","sourceRoot":"","sources":["../../src/memory/engram-client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEtF,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,YAAY;IAQhC,yEAAyE;IACnE,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAWrC,uEAAuE;IACjE,MAAM,CACV,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,iBAAiB,EAAE,CAAC;IA2B/B,0CAA0C;IACpC,IAAI,CAAC,IAAI,EAAE;QACf,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAkBrC,gEAAgE;IAC1D,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAe5E,gEAAgE;IAC1D,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAc9D,0CAA0C;IACpC,QAAQ,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAe7C,+CAA+C;IACzC,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAmB5D,mEAAmE;IAC7D,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAY7D"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thin HTTP client wrapping native fetch() for the Engram REST API.
|
|
3
|
+
*
|
|
4
|
+
* Uses Node 18+ built-in fetch — no external dependencies.
|
|
5
|
+
* All methods are wrapped in try/catch and return safe fallback values
|
|
6
|
+
* (null, false, []) on failure. Errors are logged via console.warn
|
|
7
|
+
* for graceful degradation — the review never fails because of Engram.
|
|
8
|
+
*/
|
|
9
|
+
export class EngramClient {
|
|
10
|
+
baseUrl;
|
|
11
|
+
timeout;
|
|
12
|
+
constructor(config) {
|
|
13
|
+
// Strip trailing slash for consistent URL construction
|
|
14
|
+
this.baseUrl = config.host.replace(/\/+$/, '');
|
|
15
|
+
this.timeout = config.timeout;
|
|
16
|
+
}
|
|
17
|
+
// ─── Public API ─────────────────────────────────────────────────
|
|
18
|
+
/** Health check: GET /api/stats. Returns true if Engram is reachable. */
|
|
19
|
+
async healthCheck() {
|
|
20
|
+
try {
|
|
21
|
+
const response = await fetch(`${this.baseUrl}/api/stats`, {
|
|
22
|
+
signal: AbortSignal.timeout(this.timeout),
|
|
23
|
+
});
|
|
24
|
+
return response.ok;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** Search observations. GET /api/search?q=...&project=...&limit=... */
|
|
31
|
+
async search(query, project, limit) {
|
|
32
|
+
try {
|
|
33
|
+
const params = new URLSearchParams({ q: query });
|
|
34
|
+
if (project)
|
|
35
|
+
params.set('project', project);
|
|
36
|
+
if (limit != null)
|
|
37
|
+
params.set('limit', String(limit));
|
|
38
|
+
const response = await fetch(`${this.baseUrl}/api/search?${params}`, {
|
|
39
|
+
signal: AbortSignal.timeout(this.timeout),
|
|
40
|
+
});
|
|
41
|
+
if (!response.ok)
|
|
42
|
+
return [];
|
|
43
|
+
const data = await response.json();
|
|
44
|
+
// Handle both array response and { observations: [...] } envelope
|
|
45
|
+
if (Array.isArray(data))
|
|
46
|
+
return data;
|
|
47
|
+
if (data != null && typeof data === 'object' && 'observations' in data && Array.isArray(data.observations)) {
|
|
48
|
+
return data.observations;
|
|
49
|
+
}
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
console.warn('[ghagga:engram] search failed:', error.message);
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** Save an observation. POST /api/save */
|
|
58
|
+
async save(data) {
|
|
59
|
+
try {
|
|
60
|
+
const response = await fetch(`${this.baseUrl}/api/save`, {
|
|
61
|
+
method: 'POST',
|
|
62
|
+
headers: { 'Content-Type': 'application/json' },
|
|
63
|
+
body: JSON.stringify(data),
|
|
64
|
+
signal: AbortSignal.timeout(this.timeout),
|
|
65
|
+
});
|
|
66
|
+
if (!response.ok)
|
|
67
|
+
return null;
|
|
68
|
+
return (await response.json());
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
console.warn('[ghagga:engram] save failed:', error.message);
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/** Get a single observation by ID. GET /api/observations/:id */
|
|
76
|
+
async getObservation(id) {
|
|
77
|
+
try {
|
|
78
|
+
const response = await fetch(`${this.baseUrl}/api/observations/${id}`, {
|
|
79
|
+
signal: AbortSignal.timeout(this.timeout),
|
|
80
|
+
});
|
|
81
|
+
if (!response.ok)
|
|
82
|
+
return null;
|
|
83
|
+
return (await response.json());
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
console.warn('[ghagga:engram] getObservation failed:', error.message);
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/** Delete an observation by ID. DELETE /api/observations/:id */
|
|
91
|
+
async deleteObservation(id) {
|
|
92
|
+
try {
|
|
93
|
+
const response = await fetch(`${this.baseUrl}/api/observations/${id}`, {
|
|
94
|
+
method: 'DELETE',
|
|
95
|
+
signal: AbortSignal.timeout(this.timeout),
|
|
96
|
+
});
|
|
97
|
+
return response.ok;
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
console.warn('[ghagga:engram] deleteObservation failed:', error.message);
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/** Get aggregate stats. GET /api/stats */
|
|
105
|
+
async getStats() {
|
|
106
|
+
try {
|
|
107
|
+
const response = await fetch(`${this.baseUrl}/api/stats`, {
|
|
108
|
+
signal: AbortSignal.timeout(this.timeout),
|
|
109
|
+
});
|
|
110
|
+
if (!response.ok)
|
|
111
|
+
return null;
|
|
112
|
+
return (await response.json());
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
console.warn('[ghagga:engram] getStats failed:', error.message);
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/** Create a new session. POST /api/sessions */
|
|
120
|
+
async createSession(project) {
|
|
121
|
+
try {
|
|
122
|
+
const response = await fetch(`${this.baseUrl}/api/sessions`, {
|
|
123
|
+
method: 'POST',
|
|
124
|
+
headers: { 'Content-Type': 'application/json' },
|
|
125
|
+
body: JSON.stringify({ project }),
|
|
126
|
+
signal: AbortSignal.timeout(this.timeout),
|
|
127
|
+
});
|
|
128
|
+
if (!response.ok)
|
|
129
|
+
return null;
|
|
130
|
+
const data = (await response.json());
|
|
131
|
+
return data.id ?? null;
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
console.warn('[ghagga:engram] createSession failed:', error.message);
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/** End a session with a summary. POST /api/sessions/:id/summary */
|
|
139
|
+
async endSession(id, summary) {
|
|
140
|
+
try {
|
|
141
|
+
await fetch(`${this.baseUrl}/api/sessions/${id}/summary`, {
|
|
142
|
+
method: 'POST',
|
|
143
|
+
headers: { 'Content-Type': 'application/json' },
|
|
144
|
+
body: JSON.stringify({ summary }),
|
|
145
|
+
signal: AbortSignal.timeout(this.timeout),
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
console.warn('[ghagga:engram] endSession failed:', error.message);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=engram-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engram-client.js","sourceRoot":"","sources":["../../src/memory/engram-client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,OAAO,YAAY;IACf,OAAO,CAAS;IAChB,OAAO,CAAS;IAExB,YAAY,MAAoB;QAC9B,uDAAuD;QACvD,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;IAChC,CAAC;IAED,mEAAmE;IAEnE,yEAAyE;IACzE,KAAK,CAAC,WAAW;QACf,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,YAAY,EAAE;gBACxD,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;aAC1C,CAAC,CAAC;YACH,OAAO,QAAQ,CAAC,EAAE,CAAC;QACrB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,uEAAuE;IACvE,KAAK,CAAC,MAAM,CACV,KAAa,EACb,OAAgB,EAChB,KAAc;QAEd,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;YACjD,IAAI,OAAO;gBAAE,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAC5C,IAAI,KAAK,IAAI,IAAI;gBAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAEtD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,eAAe,MAAM,EAAE,EAAE;gBACnE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;aAC1C,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE;gBAAE,OAAO,EAAE,CAAC;YAE5B,MAAM,IAAI,GAAY,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YAE5C,kEAAkE;YAClE,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;gBAAE,OAAO,IAA2B,CAAC;YAC5D,IAAI,IAAI,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,cAAc,IAAI,IAAI,IAAI,KAAK,CAAC,OAAO,CAAE,IAAgC,CAAC,YAAY,CAAC,EAAE,CAAC;gBACxI,OAAQ,IAAgC,CAAC,YAAmC,CAAC;YAC/E,CAAC;YAED,OAAO,EAAE,CAAC;QACZ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,gCAAgC,EAAG,KAAe,CAAC,OAAO,CAAC,CAAC;YACzE,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED,0CAA0C;IAC1C,KAAK,CAAC,IAAI,CAAC,IAOV;QACC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,WAAW,EAAE;gBACvD,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;gBAC1B,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;aAC1C,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE;gBAAE,OAAO,IAAI,CAAC;YAE9B,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAsB,CAAC;QACtD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,8BAA8B,EAAG,KAAe,CAAC,OAAO,CAAC,CAAC;YACvE,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,gEAAgE;IAChE,KAAK,CAAC,cAAc,CAAC,EAAmB;QACtC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,qBAAqB,EAAE,EAAE,EAAE;gBACrE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;aAC1C,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE;gBAAE,OAAO,IAAI,CAAC;YAE9B,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAsB,CAAC;QACtD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,wCAAwC,EAAG,KAAe,CAAC,OAAO,CAAC,CAAC;YACjF,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,gEAAgE;IAChE,KAAK,CAAC,iBAAiB,CAAC,EAAmB;QACzC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,qBAAqB,EAAE,EAAE,EAAE;gBACrE,MAAM,EAAE,QAAQ;gBAChB,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;aAC1C,CAAC,CAAC;YAEH,OAAO,QAAQ,CAAC,EAAE,CAAC;QACrB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,2CAA2C,EAAG,KAAe,CAAC,OAAO,CAAC,CAAC;YACpF,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,0CAA0C;IAC1C,KAAK,CAAC,QAAQ;QACZ,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,YAAY,EAAE;gBACxD,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;aAC1C,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE;gBAAE,OAAO,IAAI,CAAC;YAE9B,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAgB,CAAC;QAChD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,kCAAkC,EAAG,KAAe,CAAC,OAAO,CAAC,CAAC;YAC3E,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,+CAA+C;IAC/C,KAAK,CAAC,aAAa,CAAC,OAAe;QACjC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,eAAe,EAAE;gBAC3D,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC;gBACjC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;aAC1C,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE;gBAAE,OAAO,IAAI,CAAC;YAE9B,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAoB,CAAC;YACxD,OAAO,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC;QACzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,uCAAuC,EAAG,KAAe,CAAC,OAAO,CAAC,CAAC;YAChF,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,mEAAmE;IACnE,KAAK,CAAC,UAAU,CAAC,EAAU,EAAE,OAAe;QAC1C,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,iBAAiB,EAAE,UAAU,EAAE;gBACxD,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC;gBACjC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;aAC1C,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,oCAAoC,EAAG,KAAe,CAAC,OAAO,CAAC,CAAC;QAC/E,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema mapping between GHAGGA observation types and Engram API shapes.
|
|
3
|
+
*
|
|
4
|
+
* GHAGGA stores severity, filePaths, and a source marker as structured
|
|
5
|
+
* text within Engram's `content` field:
|
|
6
|
+
*
|
|
7
|
+
* [severity:high]
|
|
8
|
+
* <actual content>
|
|
9
|
+
* ---
|
|
10
|
+
* Files: path/a.ts, path/b.ts
|
|
11
|
+
* ---
|
|
12
|
+
* Source: ghagga
|
|
13
|
+
*
|
|
14
|
+
* On read, the mapping functions parse this structure back out.
|
|
15
|
+
* If the content doesn't match (e.g., an observation created by another tool),
|
|
16
|
+
* sensible defaults are used.
|
|
17
|
+
*/
|
|
18
|
+
import type { MemoryObservationRow, MemoryObservationDetail } from '../types.js';
|
|
19
|
+
import type { EngramObservation } from './engram-types.js';
|
|
20
|
+
export interface EngramSavePayload {
|
|
21
|
+
type: string;
|
|
22
|
+
title: string;
|
|
23
|
+
content: string;
|
|
24
|
+
project?: string;
|
|
25
|
+
topic_key?: string;
|
|
26
|
+
scope?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Encode GHAGGA-specific fields into a single Engram `content` string.
|
|
30
|
+
*
|
|
31
|
+
* - Prepends `[severity:xxx]` if severity is provided
|
|
32
|
+
* - Appends `\n---\nFiles: path1, path2` if filePaths are provided
|
|
33
|
+
* - Always appends `\n---\nSource: ghagga` as a footer
|
|
34
|
+
*/
|
|
35
|
+
export declare function toEngramContent(data: {
|
|
36
|
+
content: string;
|
|
37
|
+
severity?: string | null;
|
|
38
|
+
filePaths?: string[] | null;
|
|
39
|
+
}): string;
|
|
40
|
+
/**
|
|
41
|
+
* Parse GHAGGA-structured content back into its component fields.
|
|
42
|
+
*
|
|
43
|
+
* Extracts `[severity:xxx]` from the first line, `Files: ...` from the
|
|
44
|
+
* footer section, and returns the clean content without metadata.
|
|
45
|
+
*
|
|
46
|
+
* If the content doesn't match the expected structure, returns it
|
|
47
|
+
* as-is with null severity and filePaths.
|
|
48
|
+
*/
|
|
49
|
+
export declare function fromEngramContent(content: string): {
|
|
50
|
+
content: string;
|
|
51
|
+
severity: string | null;
|
|
52
|
+
filePaths: string[] | null;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Map an Engram observation to GHAGGA's MemoryObservationRow.
|
|
56
|
+
*
|
|
57
|
+
* Uses `fromEngramContent()` to extract severity/filePaths from the
|
|
58
|
+
* content field. The Engram ID (string | number) is converted to a
|
|
59
|
+
* stable numeric ID via parseInt or a simple hash.
|
|
60
|
+
*/
|
|
61
|
+
export declare function toMemoryObservationRow(obs: EngramObservation): MemoryObservationRow;
|
|
62
|
+
/**
|
|
63
|
+
* Map an Engram observation to GHAGGA's MemoryObservationDetail.
|
|
64
|
+
*
|
|
65
|
+
* Full mapping including metadata fields (project, topicKey, timestamps, etc.).
|
|
66
|
+
*/
|
|
67
|
+
export declare function toMemoryObservationDetail(obs: EngramObservation): MemoryObservationDetail;
|
|
68
|
+
/**
|
|
69
|
+
* Map GHAGGA save data to the Engram save request payload.
|
|
70
|
+
*
|
|
71
|
+
* Uses `toEngramContent()` to embed severity/filePaths in the content field.
|
|
72
|
+
*/
|
|
73
|
+
export declare function toEngramSaveData(data: {
|
|
74
|
+
sessionId?: number;
|
|
75
|
+
project: string;
|
|
76
|
+
type: string;
|
|
77
|
+
title: string;
|
|
78
|
+
content: string;
|
|
79
|
+
topicKey?: string;
|
|
80
|
+
filePaths?: string[];
|
|
81
|
+
severity?: string;
|
|
82
|
+
}): EngramSavePayload;
|
|
83
|
+
//# sourceMappingURL=engram-mapping.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engram-mapping.d.ts","sourceRoot":"","sources":["../../src/memory/engram-mapping.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AACjF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAI3D,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAID;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;CAC7B,GAAG,MAAM,CAkBT;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;CAC5B,CAiCA;AAID;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,iBAAiB,GAAG,oBAAoB,CAWnF;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,iBAAiB,GAAG,uBAAuB,CAgBzF;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,iBAAiB,CAYpB"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema mapping between GHAGGA observation types and Engram API shapes.
|
|
3
|
+
*
|
|
4
|
+
* GHAGGA stores severity, filePaths, and a source marker as structured
|
|
5
|
+
* text within Engram's `content` field:
|
|
6
|
+
*
|
|
7
|
+
* [severity:high]
|
|
8
|
+
* <actual content>
|
|
9
|
+
* ---
|
|
10
|
+
* Files: path/a.ts, path/b.ts
|
|
11
|
+
* ---
|
|
12
|
+
* Source: ghagga
|
|
13
|
+
*
|
|
14
|
+
* On read, the mapping functions parse this structure back out.
|
|
15
|
+
* If the content doesn't match (e.g., an observation created by another tool),
|
|
16
|
+
* sensible defaults are used.
|
|
17
|
+
*/
|
|
18
|
+
// ─── GHAGGA → Engram ────────────────────────────────────────────
|
|
19
|
+
/**
|
|
20
|
+
* Encode GHAGGA-specific fields into a single Engram `content` string.
|
|
21
|
+
*
|
|
22
|
+
* - Prepends `[severity:xxx]` if severity is provided
|
|
23
|
+
* - Appends `\n---\nFiles: path1, path2` if filePaths are provided
|
|
24
|
+
* - Always appends `\n---\nSource: ghagga` as a footer
|
|
25
|
+
*/
|
|
26
|
+
export function toEngramContent(data) {
|
|
27
|
+
const parts = [];
|
|
28
|
+
if (data.severity) {
|
|
29
|
+
parts.push(`[severity:${data.severity}]`);
|
|
30
|
+
}
|
|
31
|
+
parts.push(data.content);
|
|
32
|
+
if (data.filePaths && data.filePaths.length > 0) {
|
|
33
|
+
parts.push('---');
|
|
34
|
+
parts.push(`Files: ${data.filePaths.join(', ')}`);
|
|
35
|
+
}
|
|
36
|
+
parts.push('---');
|
|
37
|
+
parts.push('Source: ghagga');
|
|
38
|
+
return parts.join('\n');
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Parse GHAGGA-structured content back into its component fields.
|
|
42
|
+
*
|
|
43
|
+
* Extracts `[severity:xxx]` from the first line, `Files: ...` from the
|
|
44
|
+
* footer section, and returns the clean content without metadata.
|
|
45
|
+
*
|
|
46
|
+
* If the content doesn't match the expected structure, returns it
|
|
47
|
+
* as-is with null severity and filePaths.
|
|
48
|
+
*/
|
|
49
|
+
export function fromEngramContent(content) {
|
|
50
|
+
let severity = null;
|
|
51
|
+
let filePaths = null;
|
|
52
|
+
let body = content;
|
|
53
|
+
// Extract [severity:xxx] from the first line
|
|
54
|
+
const severityMatch = body.match(/^\[severity:(\w+)\]\n?/);
|
|
55
|
+
if (severityMatch) {
|
|
56
|
+
severity = severityMatch[1];
|
|
57
|
+
body = body.slice(severityMatch[0].length);
|
|
58
|
+
}
|
|
59
|
+
// Extract footer sections (delimited by ---) from the end
|
|
60
|
+
// Look for "Source: ghagga" footer to confirm this is GHAGGA-structured
|
|
61
|
+
const sourceFooterIdx = body.lastIndexOf('\n---\nSource: ghagga');
|
|
62
|
+
if (sourceFooterIdx !== -1) {
|
|
63
|
+
const beforeSource = body.slice(0, sourceFooterIdx);
|
|
64
|
+
// Look for "Files: ..." section before the Source footer
|
|
65
|
+
const filesFooterIdx = beforeSource.lastIndexOf('\n---\nFiles: ');
|
|
66
|
+
if (filesFooterIdx !== -1) {
|
|
67
|
+
const filesLine = beforeSource.slice(filesFooterIdx + '\n---\nFiles: '.length);
|
|
68
|
+
filePaths = filesLine
|
|
69
|
+
.split(',')
|
|
70
|
+
.map((f) => f.trim())
|
|
71
|
+
.filter((f) => f.length > 0);
|
|
72
|
+
body = beforeSource.slice(0, filesFooterIdx);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
body = beforeSource;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return { content: body, severity, filePaths };
|
|
79
|
+
}
|
|
80
|
+
// ─── Engram → GHAGGA ────────────────────────────────────────────
|
|
81
|
+
/**
|
|
82
|
+
* Map an Engram observation to GHAGGA's MemoryObservationRow.
|
|
83
|
+
*
|
|
84
|
+
* Uses `fromEngramContent()` to extract severity/filePaths from the
|
|
85
|
+
* content field. The Engram ID (string | number) is converted to a
|
|
86
|
+
* stable numeric ID via parseInt or a simple hash.
|
|
87
|
+
*/
|
|
88
|
+
export function toMemoryObservationRow(obs) {
|
|
89
|
+
const parsed = fromEngramContent(obs.content);
|
|
90
|
+
return {
|
|
91
|
+
id: toNumericId(obs.id),
|
|
92
|
+
type: obs.type ?? 'observation',
|
|
93
|
+
title: obs.title ?? '',
|
|
94
|
+
content: parsed.content,
|
|
95
|
+
filePaths: parsed.filePaths,
|
|
96
|
+
severity: parsed.severity,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Map an Engram observation to GHAGGA's MemoryObservationDetail.
|
|
101
|
+
*
|
|
102
|
+
* Full mapping including metadata fields (project, topicKey, timestamps, etc.).
|
|
103
|
+
*/
|
|
104
|
+
export function toMemoryObservationDetail(obs) {
|
|
105
|
+
const parsed = fromEngramContent(obs.content);
|
|
106
|
+
return {
|
|
107
|
+
id: toNumericId(obs.id),
|
|
108
|
+
type: obs.type ?? 'observation',
|
|
109
|
+
title: obs.title ?? '',
|
|
110
|
+
content: parsed.content,
|
|
111
|
+
filePaths: parsed.filePaths,
|
|
112
|
+
severity: parsed.severity,
|
|
113
|
+
project: obs.project ?? '',
|
|
114
|
+
topicKey: obs.topic_key ?? null,
|
|
115
|
+
revisionCount: obs.revision_count ?? 1,
|
|
116
|
+
createdAt: obs.created_at ?? new Date().toISOString(),
|
|
117
|
+
updatedAt: obs.updated_at ?? obs.created_at ?? new Date().toISOString(),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Map GHAGGA save data to the Engram save request payload.
|
|
122
|
+
*
|
|
123
|
+
* Uses `toEngramContent()` to embed severity/filePaths in the content field.
|
|
124
|
+
*/
|
|
125
|
+
export function toEngramSaveData(data) {
|
|
126
|
+
return {
|
|
127
|
+
type: data.type,
|
|
128
|
+
title: data.title,
|
|
129
|
+
content: toEngramContent({
|
|
130
|
+
content: data.content,
|
|
131
|
+
severity: data.severity,
|
|
132
|
+
filePaths: data.filePaths,
|
|
133
|
+
}),
|
|
134
|
+
project: data.project,
|
|
135
|
+
topic_key: data.topicKey,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
// ─── Helpers ────────────────────────────────────────────────────
|
|
139
|
+
/**
|
|
140
|
+
* Convert an Engram ID (string or number) to a stable numeric ID.
|
|
141
|
+
*
|
|
142
|
+
* - If the ID is already a number, return it directly.
|
|
143
|
+
* - If the ID is a numeric string, parse it.
|
|
144
|
+
* - Otherwise, hash the string to a positive 32-bit integer.
|
|
145
|
+
*/
|
|
146
|
+
function toNumericId(id) {
|
|
147
|
+
if (typeof id === 'number')
|
|
148
|
+
return id;
|
|
149
|
+
const parsed = parseInt(id, 10);
|
|
150
|
+
if (!isNaN(parsed))
|
|
151
|
+
return parsed;
|
|
152
|
+
// Simple hash for UUID/string IDs → positive 32-bit integer
|
|
153
|
+
let hash = 0;
|
|
154
|
+
for (let i = 0; i < id.length; i++) {
|
|
155
|
+
hash = ((hash << 5) - hash + id.charCodeAt(i)) | 0;
|
|
156
|
+
}
|
|
157
|
+
return Math.abs(hash);
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=engram-mapping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engram-mapping.js","sourceRoot":"","sources":["../../src/memory/engram-mapping.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engram adapter types.
|
|
3
|
+
*
|
|
4
|
+
* Defines configuration and API response shapes for the Engram REST API.
|
|
5
|
+
* These types are internal to the Engram adapter — not exported from @ghagga/core.
|
|
6
|
+
*/
|
|
7
|
+
/** Configuration for connecting to an Engram server. */
|
|
8
|
+
export interface EngramConfig {
|
|
9
|
+
/** Engram server base URL (default: 'http://localhost:7437') */
|
|
10
|
+
host: string;
|
|
11
|
+
/** HTTP request timeout in milliseconds (default: 5000) */
|
|
12
|
+
timeout: number;
|
|
13
|
+
}
|
|
14
|
+
/** Default Engram configuration values. */
|
|
15
|
+
export declare const ENGRAM_DEFAULTS: EngramConfig;
|
|
16
|
+
/** Shape of an observation returned by Engram's REST API. */
|
|
17
|
+
export interface EngramObservation {
|
|
18
|
+
id: string | number;
|
|
19
|
+
type: string;
|
|
20
|
+
title: string;
|
|
21
|
+
content: string;
|
|
22
|
+
project?: string;
|
|
23
|
+
topic_key?: string;
|
|
24
|
+
revision_count?: number;
|
|
25
|
+
created_at?: string;
|
|
26
|
+
updated_at?: string;
|
|
27
|
+
deleted_at?: string | null;
|
|
28
|
+
duplicate_count?: number;
|
|
29
|
+
last_seen_at?: string;
|
|
30
|
+
scope?: string;
|
|
31
|
+
}
|
|
32
|
+
/** Shape of Engram's session response. */
|
|
33
|
+
export interface EngramSession {
|
|
34
|
+
id: number;
|
|
35
|
+
project: string;
|
|
36
|
+
started_at?: string;
|
|
37
|
+
ended_at?: string | null;
|
|
38
|
+
summary?: string | null;
|
|
39
|
+
}
|
|
40
|
+
/** Shape of Engram's GET /api/stats response. */
|
|
41
|
+
export interface EngramStats {
|
|
42
|
+
total_observations: number;
|
|
43
|
+
total_sessions: number;
|
|
44
|
+
projects?: string[];
|
|
45
|
+
}
|
|
46
|
+
/** Shape of Engram's search response. */
|
|
47
|
+
export interface EngramSearchResult {
|
|
48
|
+
observations: EngramObservation[];
|
|
49
|
+
total?: number;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=engram-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engram-types.d.ts","sourceRoot":"","sources":["../../src/memory/engram-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,wDAAwD;AACxD,MAAM,WAAW,YAAY;IAC3B,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAC;IAEb,2DAA2D;IAC3D,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,2CAA2C;AAC3C,eAAO,MAAM,eAAe,EAAE,YAG7B,CAAC;AAIF,6DAA6D;AAC7D,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,0CAA0C;AAC1C,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,iDAAiD;AACjD,MAAM,WAAW,WAAW;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,yCAAyC;AACzC,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,iBAAiB,EAAE,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engram adapter types.
|
|
3
|
+
*
|
|
4
|
+
* Defines configuration and API response shapes for the Engram REST API.
|
|
5
|
+
* These types are internal to the Engram adapter — not exported from @ghagga/core.
|
|
6
|
+
*/
|
|
7
|
+
/** Default Engram configuration values. */
|
|
8
|
+
export const ENGRAM_DEFAULTS = {
|
|
9
|
+
host: 'http://localhost:7437',
|
|
10
|
+
timeout: 5000,
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=engram-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engram-types.js","sourceRoot":"","sources":["../../src/memory/engram-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAaH,2CAA2C;AAC3C,MAAM,CAAC,MAAM,eAAe,GAAiB;IAC3C,IAAI,EAAE,uBAAuB;IAC7B,OAAO,EAAE,IAAI;CACd,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engram-backed memory storage.
|
|
3
|
+
*
|
|
4
|
+
* Implements the MemoryStorage interface by mapping each method to HTTP
|
|
5
|
+
* calls against Engram's REST API (localhost:7437). Uses native fetch()
|
|
6
|
+
* with no external dependencies.
|
|
7
|
+
*
|
|
8
|
+
* Graceful degradation: the async factory performs a health check. If
|
|
9
|
+
* Engram is unreachable it returns null so the caller can fall back to
|
|
10
|
+
* SQLite. During operation, individual method calls catch HTTP errors
|
|
11
|
+
* and return safe defaults — the review never fails because of Engram.
|
|
12
|
+
*/
|
|
13
|
+
import type { MemoryStorage, MemoryObservationRow, MemoryObservationDetail, MemoryStats, ListObservationsOptions } from '../types.js';
|
|
14
|
+
import type { EngramConfig } from './engram-types.js';
|
|
15
|
+
export declare class EngramMemoryStorage implements MemoryStorage {
|
|
16
|
+
private client;
|
|
17
|
+
/**
|
|
18
|
+
* Maps GHAGGA numeric IDs → Engram original IDs (string | number).
|
|
19
|
+
* Populated by searchObservations(), listObservations(), and saveObservation().
|
|
20
|
+
* Used by getObservation() and deleteObservation() to resolve the real Engram ID.
|
|
21
|
+
*/
|
|
22
|
+
private idMap;
|
|
23
|
+
private nextId;
|
|
24
|
+
private constructor();
|
|
25
|
+
/**
|
|
26
|
+
* Async factory — creates an instance after verifying Engram is reachable.
|
|
27
|
+
*
|
|
28
|
+
* Config resolution order:
|
|
29
|
+
* 1. Explicit `config` parameter
|
|
30
|
+
* 2. Environment variables (GHAGGA_ENGRAM_HOST, GHAGGA_ENGRAM_TIMEOUT)
|
|
31
|
+
* 3. Defaults (http://localhost:7437, 5000ms)
|
|
32
|
+
*
|
|
33
|
+
* Returns null if Engram is not reachable (caller should fall back to SQLite).
|
|
34
|
+
*/
|
|
35
|
+
static create(config?: Partial<EngramConfig>): Promise<EngramMemoryStorage | null>;
|
|
36
|
+
searchObservations(project: string, query: string, options?: {
|
|
37
|
+
limit?: number;
|
|
38
|
+
type?: string;
|
|
39
|
+
}): Promise<MemoryObservationRow[]>;
|
|
40
|
+
saveObservation(data: {
|
|
41
|
+
sessionId?: number;
|
|
42
|
+
project: string;
|
|
43
|
+
type: string;
|
|
44
|
+
title: string;
|
|
45
|
+
content: string;
|
|
46
|
+
topicKey?: string;
|
|
47
|
+
filePaths?: string[];
|
|
48
|
+
severity?: string;
|
|
49
|
+
}): Promise<MemoryObservationRow>;
|
|
50
|
+
createSession(data: {
|
|
51
|
+
project: string;
|
|
52
|
+
prNumber?: number;
|
|
53
|
+
}): Promise<{
|
|
54
|
+
id: number;
|
|
55
|
+
}>;
|
|
56
|
+
endSession(sessionId: number, summary: string): Promise<void>;
|
|
57
|
+
/** No-op — HTTP connections don't need explicit cleanup. */
|
|
58
|
+
close(): Promise<void>;
|
|
59
|
+
listObservations(options?: ListObservationsOptions): Promise<MemoryObservationDetail[]>;
|
|
60
|
+
getObservation(id: number): Promise<MemoryObservationDetail | null>;
|
|
61
|
+
deleteObservation(id: number): Promise<boolean>;
|
|
62
|
+
getStats(): Promise<MemoryStats>;
|
|
63
|
+
/**
|
|
64
|
+
* Not supported by the Engram HTTP API.
|
|
65
|
+
* Use the `engram` CLI directly for bulk operations.
|
|
66
|
+
*/
|
|
67
|
+
clearObservations(_options?: {
|
|
68
|
+
project?: string;
|
|
69
|
+
}): Promise<number>;
|
|
70
|
+
/**
|
|
71
|
+
* Track the mapping between a GHAGGA numeric ID and the original Engram ID.
|
|
72
|
+
* This allows getObservation() and deleteObservation() to resolve the real ID.
|
|
73
|
+
*/
|
|
74
|
+
private trackId;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=engram.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engram.d.ts","sourceRoot":"","sources":["../../src/memory/engram.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,oBAAoB,EACpB,uBAAuB,EACvB,WAAW,EACX,uBAAuB,EACxB,MAAM,aAAa,CAAC;AAOrB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,qBAAa,mBAAoB,YAAW,aAAa;IACvD,OAAO,CAAC,MAAM,CAAe;IAE7B;;;;OAIG;IACH,OAAO,CAAC,KAAK,CAAsC;IACnD,OAAO,CAAC,MAAM,CAAK;IAEnB,OAAO;IAMP;;;;;;;;;OASG;WACU,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAsBlF,kBAAkB,CACtB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAO,GAC9C,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAmB5B,eAAe,CAAC,IAAI,EAAE;QAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAwB3B,aAAa,CAAC,IAAI,EAAE;QACxB,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IAWrB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOnE,4DAA4D;IACtD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAMtB,gBAAgB,CAAC,OAAO,GAAE,uBAA4B,GAAG,OAAO,CAAC,uBAAuB,EAAE,CAAC;IAyB3F,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC;IAkBnE,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAkB/C,QAAQ,IAAI,OAAO,CAAC,WAAW,CAAC;IA8BtC;;;OAGG;IACG,iBAAiB,CAAC,QAAQ,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAUzE;;;OAGG;IACH,OAAO,CAAC,OAAO;CAKhB"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engram-backed memory storage.
|
|
3
|
+
*
|
|
4
|
+
* Implements the MemoryStorage interface by mapping each method to HTTP
|
|
5
|
+
* calls against Engram's REST API (localhost:7437). Uses native fetch()
|
|
6
|
+
* with no external dependencies.
|
|
7
|
+
*
|
|
8
|
+
* Graceful degradation: the async factory performs a health check. If
|
|
9
|
+
* Engram is unreachable it returns null so the caller can fall back to
|
|
10
|
+
* SQLite. During operation, individual method calls catch HTTP errors
|
|
11
|
+
* and return safe defaults — the review never fails because of Engram.
|
|
12
|
+
*/
|
|
13
|
+
import { EngramClient } from './engram-client.js';
|
|
14
|
+
import { toMemoryObservationRow, toMemoryObservationDetail, toEngramSaveData, } from './engram-mapping.js';
|
|
15
|
+
export class EngramMemoryStorage {
|
|
16
|
+
client;
|
|
17
|
+
/**
|
|
18
|
+
* Maps GHAGGA numeric IDs → Engram original IDs (string | number).
|
|
19
|
+
* Populated by searchObservations(), listObservations(), and saveObservation().
|
|
20
|
+
* Used by getObservation() and deleteObservation() to resolve the real Engram ID.
|
|
21
|
+
*/
|
|
22
|
+
idMap = new Map();
|
|
23
|
+
nextId = 1;
|
|
24
|
+
constructor(client) {
|
|
25
|
+
this.client = client;
|
|
26
|
+
}
|
|
27
|
+
// ─── Factory ────────────────────────────────────────────────────
|
|
28
|
+
/**
|
|
29
|
+
* Async factory — creates an instance after verifying Engram is reachable.
|
|
30
|
+
*
|
|
31
|
+
* Config resolution order:
|
|
32
|
+
* 1. Explicit `config` parameter
|
|
33
|
+
* 2. Environment variables (GHAGGA_ENGRAM_HOST, GHAGGA_ENGRAM_TIMEOUT)
|
|
34
|
+
* 3. Defaults (http://localhost:7437, 5000ms)
|
|
35
|
+
*
|
|
36
|
+
* Returns null if Engram is not reachable (caller should fall back to SQLite).
|
|
37
|
+
*/
|
|
38
|
+
static async create(config) {
|
|
39
|
+
const fullConfig = {
|
|
40
|
+
host: config?.host ?? process.env.GHAGGA_ENGRAM_HOST ?? 'http://localhost:7437',
|
|
41
|
+
timeout: config?.timeout ?? Number(process.env.GHAGGA_ENGRAM_TIMEOUT ?? '5') * 1000,
|
|
42
|
+
};
|
|
43
|
+
const client = new EngramClient(fullConfig);
|
|
44
|
+
const healthy = await client.healthCheck();
|
|
45
|
+
if (!healthy) {
|
|
46
|
+
console.warn('[ghagga:engram] Engram server not reachable at %s — falling back to SQLite', fullConfig.host);
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
return new EngramMemoryStorage(client);
|
|
50
|
+
}
|
|
51
|
+
// ─── Hot-path methods ───────────────────────────────────────────
|
|
52
|
+
async searchObservations(project, query, options = {}) {
|
|
53
|
+
const { limit = 10, type } = options;
|
|
54
|
+
const results = await this.client.search(query, project, limit);
|
|
55
|
+
let mapped = results.map((obs) => {
|
|
56
|
+
const row = toMemoryObservationRow(obs);
|
|
57
|
+
this.trackId(row.id, obs.id);
|
|
58
|
+
return row;
|
|
59
|
+
});
|
|
60
|
+
// Client-side type filter (Engram may not support it natively)
|
|
61
|
+
if (type) {
|
|
62
|
+
mapped = mapped.filter((r) => r.type === type);
|
|
63
|
+
}
|
|
64
|
+
return mapped;
|
|
65
|
+
}
|
|
66
|
+
async saveObservation(data) {
|
|
67
|
+
const payload = toEngramSaveData(data);
|
|
68
|
+
const result = await this.client.save(payload);
|
|
69
|
+
if (!result) {
|
|
70
|
+
// Graceful degradation: return a synthetic row so the pipeline continues
|
|
71
|
+
console.warn('[ghagga:engram] saveObservation: Engram save failed, returning synthetic row');
|
|
72
|
+
return {
|
|
73
|
+
id: -1,
|
|
74
|
+
type: data.type,
|
|
75
|
+
title: data.title,
|
|
76
|
+
content: data.content,
|
|
77
|
+
filePaths: data.filePaths ?? null,
|
|
78
|
+
severity: data.severity ?? null,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
const row = toMemoryObservationRow(result);
|
|
82
|
+
this.trackId(row.id, result.id);
|
|
83
|
+
return row;
|
|
84
|
+
}
|
|
85
|
+
// ─── Session methods ────────────────────────────────────────────
|
|
86
|
+
async createSession(data) {
|
|
87
|
+
const sessionId = await this.client.createSession(data.project);
|
|
88
|
+
if (sessionId == null) {
|
|
89
|
+
console.warn('[ghagga:engram] createSession failed, returning synthetic id');
|
|
90
|
+
return { id: -1 };
|
|
91
|
+
}
|
|
92
|
+
return { id: sessionId };
|
|
93
|
+
}
|
|
94
|
+
async endSession(sessionId, summary) {
|
|
95
|
+
// Skip if session was never properly created
|
|
96
|
+
if (sessionId === -1)
|
|
97
|
+
return;
|
|
98
|
+
await this.client.endSession(sessionId, summary);
|
|
99
|
+
}
|
|
100
|
+
/** No-op — HTTP connections don't need explicit cleanup. */
|
|
101
|
+
async close() {
|
|
102
|
+
// Nothing to clean up for HTTP-based storage
|
|
103
|
+
}
|
|
104
|
+
// ─── Management methods ─────────────────────────────────────────
|
|
105
|
+
async listObservations(options = {}) {
|
|
106
|
+
const { project, type, limit = 20 } = options;
|
|
107
|
+
// Use search with empty query to list all observations
|
|
108
|
+
const results = await this.client.search('', project, limit);
|
|
109
|
+
let mapped = results.map((obs) => {
|
|
110
|
+
const detail = toMemoryObservationDetail(obs);
|
|
111
|
+
this.trackId(detail.id, obs.id);
|
|
112
|
+
return detail;
|
|
113
|
+
});
|
|
114
|
+
// Client-side type filter
|
|
115
|
+
if (type) {
|
|
116
|
+
mapped = mapped.filter((r) => r.type === type);
|
|
117
|
+
}
|
|
118
|
+
// Client-side offset (Engram may not support it natively)
|
|
119
|
+
if (options.offset && options.offset > 0) {
|
|
120
|
+
mapped = mapped.slice(options.offset);
|
|
121
|
+
}
|
|
122
|
+
return mapped;
|
|
123
|
+
}
|
|
124
|
+
async getObservation(id) {
|
|
125
|
+
const realId = this.idMap.get(id);
|
|
126
|
+
if (realId == null) {
|
|
127
|
+
console.warn('[ghagga:engram] getObservation: ID %d not found in local map. ' +
|
|
128
|
+
'Run searchObservations or listObservations first.', id);
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
const obs = await this.client.getObservation(realId);
|
|
132
|
+
if (!obs)
|
|
133
|
+
return null;
|
|
134
|
+
return toMemoryObservationDetail(obs);
|
|
135
|
+
}
|
|
136
|
+
async deleteObservation(id) {
|
|
137
|
+
const realId = this.idMap.get(id);
|
|
138
|
+
if (realId == null) {
|
|
139
|
+
console.warn('[ghagga:engram] deleteObservation: ID %d not found in local map.', id);
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
const deleted = await this.client.deleteObservation(realId);
|
|
143
|
+
if (deleted) {
|
|
144
|
+
this.idMap.delete(id);
|
|
145
|
+
}
|
|
146
|
+
return deleted;
|
|
147
|
+
}
|
|
148
|
+
async getStats() {
|
|
149
|
+
const stats = await this.client.getStats();
|
|
150
|
+
if (!stats) {
|
|
151
|
+
return {
|
|
152
|
+
totalObservations: 0,
|
|
153
|
+
byType: {},
|
|
154
|
+
byProject: {},
|
|
155
|
+
oldestObservation: null,
|
|
156
|
+
newestObservation: null,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
// Map Engram stats to GHAGGA's MemoryStats shape
|
|
160
|
+
const byProject = {};
|
|
161
|
+
if (stats.projects) {
|
|
162
|
+
for (const p of stats.projects) {
|
|
163
|
+
byProject[p] = 0; // Engram doesn't provide per-project counts in stats
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
totalObservations: stats.total_observations,
|
|
168
|
+
byType: {}, // Engram stats endpoint doesn't break down by type
|
|
169
|
+
byProject,
|
|
170
|
+
oldestObservation: null, // Not provided by Engram stats
|
|
171
|
+
newestObservation: null, // Not provided by Engram stats
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Not supported by the Engram HTTP API.
|
|
176
|
+
* Use the `engram` CLI directly for bulk operations.
|
|
177
|
+
*/
|
|
178
|
+
async clearObservations(_options) {
|
|
179
|
+
console.warn('[ghagga:engram] clearObservations is not supported with the Engram backend. ' +
|
|
180
|
+
'Use the "engram" CLI directly for bulk deletion.');
|
|
181
|
+
return 0;
|
|
182
|
+
}
|
|
183
|
+
// ─── Internal helpers ───────────────────────────────────────────
|
|
184
|
+
/**
|
|
185
|
+
* Track the mapping between a GHAGGA numeric ID and the original Engram ID.
|
|
186
|
+
* This allows getObservation() and deleteObservation() to resolve the real ID.
|
|
187
|
+
*/
|
|
188
|
+
trackId(numericId, engramId) {
|
|
189
|
+
if (!this.idMap.has(numericId)) {
|
|
190
|
+
this.idMap.set(numericId, engramId);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=engram.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engram.js","sourceRoot":"","sources":["../../src/memory/engram.ts"],"names":[],"mappings":"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"}
|