openclaw-engram 0.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.
Files changed (90) hide show
  1. package/dist/availability.d.ts +34 -0
  2. package/dist/availability.d.ts.map +1 -0
  3. package/dist/availability.js +70 -0
  4. package/dist/availability.js.map +1 -0
  5. package/dist/client.d.ts +147 -0
  6. package/dist/client.d.ts.map +1 -0
  7. package/dist/client.js +199 -0
  8. package/dist/client.js.map +1 -0
  9. package/dist/commands/memory.d.ts +11 -0
  10. package/dist/commands/memory.d.ts.map +1 -0
  11. package/dist/commands/memory.js +49 -0
  12. package/dist/commands/memory.js.map +1 -0
  13. package/dist/commands/remember.d.ts +15 -0
  14. package/dist/commands/remember.d.ts.map +1 -0
  15. package/dist/commands/remember.js +61 -0
  16. package/dist/commands/remember.js.map +1 -0
  17. package/dist/config.d.ts +73 -0
  18. package/dist/config.d.ts.map +1 -0
  19. package/dist/config.js +81 -0
  20. package/dist/config.js.map +1 -0
  21. package/dist/context/formatter.d.ts +33 -0
  22. package/dist/context/formatter.d.ts.map +1 -0
  23. package/dist/context/formatter.js +193 -0
  24. package/dist/context/formatter.js.map +1 -0
  25. package/dist/hooks/after-tool-call.d.ts +19 -0
  26. package/dist/hooks/after-tool-call.d.ts.map +1 -0
  27. package/dist/hooks/after-tool-call.js +53 -0
  28. package/dist/hooks/after-tool-call.js.map +1 -0
  29. package/dist/hooks/before-compaction.d.ts +19 -0
  30. package/dist/hooks/before-compaction.d.ts.map +1 -0
  31. package/dist/hooks/before-compaction.js +60 -0
  32. package/dist/hooks/before-compaction.js.map +1 -0
  33. package/dist/hooks/before-prompt-build.d.ts +20 -0
  34. package/dist/hooks/before-prompt-build.d.ts.map +1 -0
  35. package/dist/hooks/before-prompt-build.js +76 -0
  36. package/dist/hooks/before-prompt-build.js.map +1 -0
  37. package/dist/hooks/session-end.d.ts +18 -0
  38. package/dist/hooks/session-end.d.ts.map +1 -0
  39. package/dist/hooks/session-end.js +57 -0
  40. package/dist/hooks/session-end.js.map +1 -0
  41. package/dist/hooks/session-start.d.ts +17 -0
  42. package/dist/hooks/session-start.d.ts.map +1 -0
  43. package/dist/hooks/session-start.js +77 -0
  44. package/dist/hooks/session-start.js.map +1 -0
  45. package/dist/identity.d.ts +36 -0
  46. package/dist/identity.d.ts.map +1 -0
  47. package/dist/identity.js +106 -0
  48. package/dist/identity.js.map +1 -0
  49. package/dist/index.d.ts +24 -0
  50. package/dist/index.d.ts.map +1 -0
  51. package/dist/index.js +208 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/services/file-watcher.d.ts +11 -0
  54. package/dist/services/file-watcher.d.ts.map +1 -0
  55. package/dist/services/file-watcher.js +139 -0
  56. package/dist/services/file-watcher.js.map +1 -0
  57. package/dist/tools/engram-decisions.d.ts +8 -0
  58. package/dist/tools/engram-decisions.d.ts.map +1 -0
  59. package/dist/tools/engram-decisions.js +70 -0
  60. package/dist/tools/engram-decisions.js.map +1 -0
  61. package/dist/tools/engram-remember.d.ts +9 -0
  62. package/dist/tools/engram-remember.d.ts.map +1 -0
  63. package/dist/tools/engram-remember.js +116 -0
  64. package/dist/tools/engram-remember.js.map +1 -0
  65. package/dist/tools/engram-search.d.ts +9 -0
  66. package/dist/tools/engram-search.d.ts.map +1 -0
  67. package/dist/tools/engram-search.js +62 -0
  68. package/dist/tools/engram-search.js.map +1 -0
  69. package/dist/tools/memory-forget.d.ts +10 -0
  70. package/dist/tools/memory-forget.d.ts.map +1 -0
  71. package/dist/tools/memory-forget.js +41 -0
  72. package/dist/tools/memory-forget.js.map +1 -0
  73. package/dist/tools/memory-get.d.ts +11 -0
  74. package/dist/tools/memory-get.d.ts.map +1 -0
  75. package/dist/tools/memory-get.js +86 -0
  76. package/dist/tools/memory-get.js.map +1 -0
  77. package/dist/tools/memory-migrate.d.ts +11 -0
  78. package/dist/tools/memory-migrate.d.ts.map +1 -0
  79. package/dist/tools/memory-migrate.js +180 -0
  80. package/dist/tools/memory-migrate.js.map +1 -0
  81. package/dist/types/openclaw.d.ts +212 -0
  82. package/dist/types/openclaw.d.ts.map +1 -0
  83. package/dist/types/openclaw.js +9 -0
  84. package/dist/types/openclaw.js.map +1 -0
  85. package/dist/utils/memory-files.d.ts +25 -0
  86. package/dist/utils/memory-files.d.ts.map +1 -0
  87. package/dist/utils/memory-files.js +187 -0
  88. package/dist/utils/memory-files.js.map +1 -0
  89. package/openclaw.plugin.json +86 -0
  90. package/package.json +45 -0
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Passive availability detection with 3-strike circuit breaker.
3
+ *
4
+ * The tracker never polls engram — it only records outcomes of calls
5
+ * that the client already makes. After 3 consecutive failures the server
6
+ * is marked unavailable for a 60-second cooldown period, after which the
7
+ * next call is allowed through as a probe.
8
+ */
9
+ export declare class AvailabilityTracker {
10
+ private consecutiveFailures;
11
+ private unavailableSince;
12
+ /**
13
+ * Record a successful call. Resets the failure counter and restores
14
+ * availability if the server was in cooldown.
15
+ */
16
+ recordSuccess(): void;
17
+ /**
18
+ * Record a failed call. After STRIKE_THRESHOLD consecutive failures
19
+ * the server enters a cooldown period.
20
+ */
21
+ recordFailure(): void;
22
+ /**
23
+ * Returns true if the server is considered available.
24
+ *
25
+ * After the cooldown period expires the server is tentatively considered
26
+ * available again so that the next call can act as a probe. If that call
27
+ * succeeds, `recordSuccess()` completes the recovery. If it fails,
28
+ * `recordFailure()` restarts the cooldown immediately.
29
+ */
30
+ isAvailable(): boolean;
31
+ /** Remaining cooldown in milliseconds, or 0 if available. */
32
+ remainingCooldownMs(): number;
33
+ }
34
+ //# sourceMappingURL=availability.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"availability.d.ts","sourceRoot":"","sources":["../src/availability.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,mBAAmB,CAAK;IAChC,OAAO,CAAC,gBAAgB,CAAuB;IAE/C;;;OAGG;IACH,aAAa,IAAI,IAAI;IASrB;;;OAGG;IACH,aAAa,IAAI,IAAI;IAWrB;;;;;;;OAOG;IACH,WAAW,IAAI,OAAO;IAYtB,6DAA6D;IAC7D,mBAAmB,IAAI,MAAM;CAK9B"}
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ /**
3
+ * Passive availability detection with 3-strike circuit breaker.
4
+ *
5
+ * The tracker never polls engram — it only records outcomes of calls
6
+ * that the client already makes. After 3 consecutive failures the server
7
+ * is marked unavailable for a 60-second cooldown period, after which the
8
+ * next call is allowed through as a probe.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.AvailabilityTracker = void 0;
12
+ const STRIKE_THRESHOLD = 3;
13
+ const COOLDOWN_MS = 60_000;
14
+ class AvailabilityTracker {
15
+ consecutiveFailures = 0;
16
+ unavailableSince = null;
17
+ /**
18
+ * Record a successful call. Resets the failure counter and restores
19
+ * availability if the server was in cooldown.
20
+ */
21
+ recordSuccess() {
22
+ const wasUnavailable = this.unavailableSince !== null;
23
+ this.consecutiveFailures = 0;
24
+ this.unavailableSince = null;
25
+ if (wasUnavailable) {
26
+ console.warn('[engram] server is back online');
27
+ }
28
+ }
29
+ /**
30
+ * Record a failed call. After STRIKE_THRESHOLD consecutive failures
31
+ * the server enters a cooldown period.
32
+ */
33
+ recordFailure() {
34
+ this.consecutiveFailures += 1;
35
+ if (this.consecutiveFailures >= STRIKE_THRESHOLD) {
36
+ this.unavailableSince = Date.now();
37
+ console.warn(`[engram] server marked unavailable after ${STRIKE_THRESHOLD} consecutive failures — ` +
38
+ `cooldown for ${COOLDOWN_MS / 1000}s`);
39
+ }
40
+ }
41
+ /**
42
+ * Returns true if the server is considered available.
43
+ *
44
+ * After the cooldown period expires the server is tentatively considered
45
+ * available again so that the next call can act as a probe. If that call
46
+ * succeeds, `recordSuccess()` completes the recovery. If it fails,
47
+ * `recordFailure()` restarts the cooldown immediately.
48
+ */
49
+ isAvailable() {
50
+ if (this.unavailableSince === null)
51
+ return true;
52
+ const elapsed = Date.now() - this.unavailableSince;
53
+ if (elapsed >= COOLDOWN_MS) {
54
+ // Cooldown expired — reset to allow one probe
55
+ this.consecutiveFailures = 0;
56
+ this.unavailableSince = null;
57
+ return true;
58
+ }
59
+ return false;
60
+ }
61
+ /** Remaining cooldown in milliseconds, or 0 if available. */
62
+ remainingCooldownMs() {
63
+ if (this.unavailableSince === null)
64
+ return 0;
65
+ const elapsed = Date.now() - this.unavailableSince;
66
+ return Math.max(0, COOLDOWN_MS - elapsed);
67
+ }
68
+ }
69
+ exports.AvailabilityTracker = AvailabilityTracker;
70
+ //# sourceMappingURL=availability.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"availability.js","sourceRoot":"","sources":["../src/availability.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;AAEH,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAC3B,MAAM,WAAW,GAAG,MAAM,CAAC;AAE3B,MAAa,mBAAmB;IACtB,mBAAmB,GAAG,CAAC,CAAC;IACxB,gBAAgB,GAAkB,IAAI,CAAC;IAE/C;;;OAGG;IACH,aAAa;QACX,MAAM,cAAc,GAAG,IAAI,CAAC,gBAAgB,KAAK,IAAI,CAAC;QACtD,IAAI,CAAC,mBAAmB,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC7B,IAAI,cAAc,EAAE,CAAC;YACnB,OAAO,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,aAAa;QACX,IAAI,CAAC,mBAAmB,IAAI,CAAC,CAAC;QAC9B,IAAI,IAAI,CAAC,mBAAmB,IAAI,gBAAgB,EAAE,CAAC;YACjD,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACnC,OAAO,CAAC,IAAI,CACV,4CAA4C,gBAAgB,0BAA0B;gBACpF,gBAAgB,WAAW,GAAG,IAAI,GAAG,CACxC,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACH,WAAW;QACT,IAAI,IAAI,CAAC,gBAAgB,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAChD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC;QACnD,IAAI,OAAO,IAAI,WAAW,EAAE,CAAC;YAC3B,8CAA8C;YAC9C,IAAI,CAAC,mBAAmB,GAAG,CAAC,CAAC;YAC7B,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;YAC7B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,6DAA6D;IAC7D,mBAAmB;QACjB,IAAI,IAAI,CAAC,gBAAgB,KAAK,IAAI;YAAE,OAAO,CAAC,CAAC;QAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC;QACnD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC;IAC5C,CAAC;CACF;AA1DD,kDA0DC"}
@@ -0,0 +1,147 @@
1
+ /**
2
+ * EngramRestClient — typed REST client for the engram HTTP API.
3
+ *
4
+ * All methods return null on error and update the availability tracker.
5
+ * No method ever throws to its caller — engram failures must not block agent operation.
6
+ */
7
+ import { AvailabilityTracker } from './availability.js';
8
+ import type { PluginConfig } from './config.js';
9
+ export interface Observation {
10
+ id: number;
11
+ title: string;
12
+ type: string;
13
+ scope?: string;
14
+ narrative?: string;
15
+ facts?: string[];
16
+ tags?: string[];
17
+ similarity?: number;
18
+ project?: string;
19
+ }
20
+ export interface ContextInjectResponse {
21
+ observations: Observation[];
22
+ sessionId?: number;
23
+ }
24
+ export interface ContextSearchResponse {
25
+ observations: Observation[];
26
+ }
27
+ export interface SessionInitResponse {
28
+ sessionDbId: number;
29
+ promptNumber: number;
30
+ skipped?: boolean;
31
+ }
32
+ export interface HealthResponse {
33
+ status: string;
34
+ version?: string;
35
+ }
36
+ export interface SelfCheckResponse {
37
+ components: Record<string, {
38
+ status: string;
39
+ message?: string;
40
+ }>;
41
+ }
42
+ export interface BulkObservationInput {
43
+ title: string;
44
+ content: string;
45
+ type: string;
46
+ project: string;
47
+ scope?: string;
48
+ tags?: string[];
49
+ }
50
+ /** @deprecated Use BulkObservationInput instead. */
51
+ export type BulkImportRequest = BulkObservationInput;
52
+ export interface BulkImportResponse {
53
+ imported: number;
54
+ skipped_duplicates: number;
55
+ errors?: string[];
56
+ }
57
+ export interface BulkDeleteResponse {
58
+ deleted: number;
59
+ }
60
+ export declare class EngramRestClient {
61
+ private readonly baseUrl;
62
+ private readonly token;
63
+ private readonly defaultTimeoutMs;
64
+ readonly availability: AvailabilityTracker;
65
+ constructor(config: PluginConfig);
66
+ /**
67
+ * Fetch session context for injection (static session-level context).
68
+ * GET /api/context/inject?agent_id={id}&cwd={cwd}
69
+ */
70
+ getContextInject(agentId: string, cwd?: string): Promise<ContextInjectResponse | null>;
71
+ /**
72
+ * Per-turn context search.
73
+ * POST /api/context/search
74
+ */
75
+ searchContext(body: {
76
+ project: string;
77
+ query: string;
78
+ cwd?: string;
79
+ agent_id?: string;
80
+ }): Promise<ContextSearchResponse | null>;
81
+ /**
82
+ * Ingest a tool event for self-learning.
83
+ * POST /api/events/ingest (fire-and-forget — returns void)
84
+ */
85
+ ingestEvent(body: {
86
+ session_id: string;
87
+ project: string;
88
+ tool_name: string;
89
+ tool_input: string;
90
+ tool_result: string;
91
+ }): Promise<void>;
92
+ /**
93
+ * Submit a transcript for session backfill/extraction.
94
+ * POST /api/backfill/session (fire-and-forget — returns void)
95
+ */
96
+ backfillSession(body: {
97
+ session_id: string;
98
+ project: string;
99
+ content: string;
100
+ }): Promise<void>;
101
+ /**
102
+ * Initialize a new engram session for this agent interaction.
103
+ * POST /api/sessions/init
104
+ */
105
+ initSession(body: {
106
+ claudeSessionId: string;
107
+ project: string;
108
+ prompt?: string;
109
+ }): Promise<SessionInitResponse | null>;
110
+ /**
111
+ * Mark observation IDs as injected into this session.
112
+ * POST /api/sessions/{id}/mark-injected (fire-and-forget)
113
+ */
114
+ markInjected(sessionDbId: number, ids: number[]): Promise<void>;
115
+ /**
116
+ * Health check.
117
+ * GET /api/health
118
+ */
119
+ health(): Promise<HealthResponse | null>;
120
+ /**
121
+ * Component-level health check.
122
+ * GET /api/selfcheck
123
+ */
124
+ selfCheck(): Promise<SelfCheckResponse | null>;
125
+ /**
126
+ * Bulk-import observations.
127
+ * POST /api/observations/bulk-import
128
+ *
129
+ * Server expects: { project, observations: [{ type, title, narrative, scope, concepts }] }
130
+ * Client uses: { content → narrative, tags → concepts }
131
+ */
132
+ bulkImport(observations: BulkObservationInput[]): Promise<BulkImportResponse | null>;
133
+ /**
134
+ * Bulk-delete (archive) observations by ID.
135
+ * POST /api/observations/bulk-status { action: "archive", ids, reason }
136
+ *
137
+ * The server has no dedicated bulk-delete endpoint. Archiving is the closest
138
+ * equivalent — it removes observations from search results and context injection.
139
+ */
140
+ bulkDelete(ids: string[]): Promise<BulkDeleteResponse | null>;
141
+ /** Returns true if the server is currently considered reachable. */
142
+ isAvailable(): boolean;
143
+ private get;
144
+ private post;
145
+ private request;
146
+ }
147
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/client.js ADDED
@@ -0,0 +1,199 @@
1
+ "use strict";
2
+ /**
3
+ * EngramRestClient — typed REST client for the engram HTTP API.
4
+ *
5
+ * All methods return null on error and update the availability tracker.
6
+ * No method ever throws to its caller — engram failures must not block agent operation.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.EngramRestClient = void 0;
10
+ const availability_js_1 = require("./availability.js");
11
+ // ---------------------------------------------------------------------------
12
+ // Client
13
+ // ---------------------------------------------------------------------------
14
+ class EngramRestClient {
15
+ baseUrl;
16
+ token;
17
+ defaultTimeoutMs;
18
+ availability;
19
+ constructor(config) {
20
+ // Extract origin from potentially path-bearing URL
21
+ this.baseUrl = extractOrigin(config.url);
22
+ this.token = config.token;
23
+ this.defaultTimeoutMs = config.timeoutMs;
24
+ this.availability = new availability_js_1.AvailabilityTracker();
25
+ }
26
+ // ---------------------------------------------------------------------------
27
+ // Endpoints
28
+ // ---------------------------------------------------------------------------
29
+ /**
30
+ * Fetch session context for injection (static session-level context).
31
+ * GET /api/context/inject?agent_id={id}&cwd={cwd}
32
+ */
33
+ async getContextInject(agentId, cwd) {
34
+ const params = new URLSearchParams({ agent_id: agentId });
35
+ if (cwd)
36
+ params.set('cwd', cwd);
37
+ return this.get(`/api/context/inject?${params.toString()}`);
38
+ }
39
+ /**
40
+ * Per-turn context search.
41
+ * POST /api/context/search
42
+ */
43
+ async searchContext(body) {
44
+ return this.post('/api/context/search', body);
45
+ }
46
+ /**
47
+ * Ingest a tool event for self-learning.
48
+ * POST /api/events/ingest (fire-and-forget — returns void)
49
+ */
50
+ async ingestEvent(body) {
51
+ void this.post('/api/events/ingest', body, 3000);
52
+ }
53
+ /**
54
+ * Submit a transcript for session backfill/extraction.
55
+ * POST /api/backfill/session (fire-and-forget — returns void)
56
+ */
57
+ async backfillSession(body) {
58
+ void this.post('/api/backfill/session', body, 5000);
59
+ }
60
+ /**
61
+ * Initialize a new engram session for this agent interaction.
62
+ * POST /api/sessions/init
63
+ */
64
+ async initSession(body) {
65
+ return this.post('/api/sessions/init', body);
66
+ }
67
+ /**
68
+ * Mark observation IDs as injected into this session.
69
+ * POST /api/sessions/{id}/mark-injected (fire-and-forget)
70
+ */
71
+ async markInjected(sessionDbId, ids) {
72
+ void this.post(`/api/sessions/${sessionDbId}/mark-injected`, { ids }, 3000);
73
+ }
74
+ /**
75
+ * Health check.
76
+ * GET /api/health
77
+ */
78
+ async health() {
79
+ return this.get('/api/health', 3000);
80
+ }
81
+ /**
82
+ * Component-level health check.
83
+ * GET /api/selfcheck
84
+ */
85
+ async selfCheck() {
86
+ return this.get('/api/selfcheck', 5000);
87
+ }
88
+ /**
89
+ * Bulk-import observations.
90
+ * POST /api/observations/bulk-import
91
+ *
92
+ * Server expects: { project, observations: [{ type, title, narrative, scope, concepts }] }
93
+ * Client uses: { content → narrative, tags → concepts }
94
+ */
95
+ async bulkImport(observations) {
96
+ if (observations.length === 0)
97
+ return { imported: 0, skipped_duplicates: 0 };
98
+ // All observations in a batch must share the same project.
99
+ const project = observations[0].project;
100
+ const mapped = observations.map((o) => ({
101
+ type: o.type,
102
+ title: o.title,
103
+ narrative: o.content,
104
+ scope: o.scope,
105
+ concepts: o.tags,
106
+ }));
107
+ return this.post('/api/observations/bulk-import', {
108
+ project,
109
+ observations: mapped,
110
+ });
111
+ }
112
+ /**
113
+ * Bulk-delete (archive) observations by ID.
114
+ * POST /api/observations/bulk-status { action: "archive", ids, reason }
115
+ *
116
+ * The server has no dedicated bulk-delete endpoint. Archiving is the closest
117
+ * equivalent — it removes observations from search results and context injection.
118
+ */
119
+ async bulkDelete(ids) {
120
+ const numericIds = ids.map((id) => Number(id)).filter((n) => !Number.isNaN(n));
121
+ if (numericIds.length === 0)
122
+ return { deleted: 0 };
123
+ const resp = await this.post('/api/observations/bulk-status', { action: 'archive', ids: numericIds, reason: 'Deleted via memory_forget' });
124
+ if (!resp)
125
+ return null;
126
+ return { deleted: resp.updated };
127
+ }
128
+ /** Returns true if the server is currently considered reachable. */
129
+ isAvailable() {
130
+ return this.availability.isAvailable();
131
+ }
132
+ // ---------------------------------------------------------------------------
133
+ // Internal HTTP helpers
134
+ // ---------------------------------------------------------------------------
135
+ async get(path, timeoutMs) {
136
+ return this.request('GET', path, undefined, timeoutMs);
137
+ }
138
+ async post(path, body, timeoutMs) {
139
+ return this.request('POST', path, body, timeoutMs);
140
+ }
141
+ async request(method, path, body, timeoutMs) {
142
+ if (!this.availability.isAvailable())
143
+ return null;
144
+ const url = this.baseUrl + path;
145
+ const timeout = timeoutMs ?? this.defaultTimeoutMs;
146
+ const controller = new AbortController();
147
+ const timer = setTimeout(() => controller.abort(), timeout);
148
+ try {
149
+ const headers = {
150
+ 'Authorization': `Bearer ${this.token}`,
151
+ };
152
+ if (body !== undefined) {
153
+ headers['Content-Type'] = 'application/json';
154
+ }
155
+ const response = await fetch(url, {
156
+ method,
157
+ headers,
158
+ body: body !== undefined ? JSON.stringify(body) : undefined,
159
+ signal: controller.signal,
160
+ });
161
+ const text = await response.text();
162
+ if (!response.ok) {
163
+ throw new Error(`HTTP ${response.status} ${response.statusText}: ${text}`);
164
+ }
165
+ this.availability.recordSuccess();
166
+ if (!text)
167
+ return null;
168
+ return JSON.parse(text);
169
+ }
170
+ catch (err) {
171
+ this.availability.recordFailure();
172
+ const msg = err instanceof Error ? err.message : String(err);
173
+ console.error(`[engram] ${method} ${path} failed: ${msg}`);
174
+ return null;
175
+ }
176
+ finally {
177
+ clearTimeout(timer);
178
+ }
179
+ }
180
+ }
181
+ exports.EngramRestClient = EngramRestClient;
182
+ // ---------------------------------------------------------------------------
183
+ // Helpers
184
+ // ---------------------------------------------------------------------------
185
+ /**
186
+ * Extract the origin (protocol + host) from a URL that may include a path.
187
+ * Falls back to trimming the trailing segment on parse failure.
188
+ */
189
+ function extractOrigin(rawUrl) {
190
+ const trimmed = rawUrl.trim();
191
+ try {
192
+ const parsed = new URL(trimmed);
193
+ return `${parsed.protocol}//${parsed.host}${parsed.pathname.replace(/\/+$/, '')}`;
194
+ }
195
+ catch {
196
+ return trimmed.replace(/\/$/, '');
197
+ }
198
+ }
199
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEH,uDAAwD;AAiExD,8EAA8E;AAC9E,SAAS;AACT,8EAA8E;AAE9E,MAAa,gBAAgB;IACV,OAAO,CAAS;IAChB,KAAK,CAAS;IACd,gBAAgB,CAAS;IACjC,YAAY,CAAsB;IAE3C,YAAY,MAAoB;QAC9B,mDAAmD;QACnD,IAAI,CAAC,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACzC,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAC1B,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC,SAAS,CAAC;QACzC,IAAI,CAAC,YAAY,GAAG,IAAI,qCAAmB,EAAE,CAAC;IAChD,CAAC;IAED,8EAA8E;IAC9E,YAAY;IACZ,8EAA8E;IAE9E;;;OAGG;IACH,KAAK,CAAC,gBAAgB,CACpB,OAAe,EACf,GAAY;QAEZ,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;QAC1D,IAAI,GAAG;YAAE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAChC,OAAO,IAAI,CAAC,GAAG,CAAwB,uBAAuB,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACrF,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,aAAa,CAAC,IAKnB;QACC,OAAO,IAAI,CAAC,IAAI,CAAwB,qBAAqB,EAAE,IAAI,CAAC,CAAC;IACvE,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,WAAW,CAAC,IAMjB;QACC,KAAK,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACnD,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,eAAe,CAAC,IAIrB;QACC,KAAK,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACtD,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,WAAW,CAAC,IAIjB;QACC,OAAO,IAAI,CAAC,IAAI,CAAsB,oBAAoB,EAAE,IAAI,CAAC,CAAC;IACpE,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,YAAY,CAAC,WAAmB,EAAE,GAAa;QACnD,KAAK,IAAI,CAAC,IAAI,CACZ,iBAAiB,WAAW,gBAAgB,EAC5C,EAAE,GAAG,EAAE,EACP,IAAI,CACL,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,MAAM;QACV,OAAO,IAAI,CAAC,GAAG,CAAiB,aAAa,EAAE,IAAI,CAAC,CAAC;IACvD,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,SAAS;QACb,OAAO,IAAI,CAAC,GAAG,CAAoB,gBAAgB,EAAE,IAAI,CAAC,CAAC;IAC7D,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,UAAU,CACd,YAAoC;QAEpC,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,EAAE,CAAC;QAE7E,2DAA2D;QAC3D,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QAExC,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACtC,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,SAAS,EAAE,CAAC,CAAC,OAAO;YACpB,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,QAAQ,EAAE,CAAC,CAAC,IAAI;SACjB,CAAC,CAAC,CAAC;QAEJ,OAAO,IAAI,CAAC,IAAI,CAAqB,+BAA+B,EAAE;YACpE,OAAO;YACP,YAAY,EAAE,MAAM;SACrB,CAAC,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,UAAU,CAAC,GAAa;QAC5B,MAAM,UAAU,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/E,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;QAEnD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAC1B,+BAA+B,EAC/B,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,2BAA2B,EAAE,CAC5E,CAAC;QACF,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QACvB,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;IACnC,CAAC;IAED,oEAAoE;IACpE,WAAW;QACT,OAAO,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC;IACzC,CAAC;IAED,8EAA8E;IAC9E,wBAAwB;IACxB,8EAA8E;IAEtE,KAAK,CAAC,GAAG,CACf,IAAY,EACZ,SAAkB;QAElB,OAAO,IAAI,CAAC,OAAO,CAAI,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;IAC5D,CAAC;IAEO,KAAK,CAAC,IAAI,CAChB,IAAY,EACZ,IAAa,EACb,SAAkB;QAElB,OAAO,IAAI,CAAC,OAAO,CAAI,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IACxD,CAAC;IAEO,KAAK,CAAC,OAAO,CACnB,MAAc,EACd,IAAY,EACZ,IAAa,EACb,SAAkB;QAElB,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE;YAAE,OAAO,IAAI,CAAC;QAElD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QAChC,MAAM,OAAO,GAAG,SAAS,IAAI,IAAI,CAAC,gBAAgB,CAAC;QACnD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;QAE5D,IAAI,CAAC;YACH,MAAM,OAAO,GAA2B;gBACtC,eAAe,EAAE,UAAU,IAAI,CAAC,KAAK,EAAE;aACxC,CAAC;YACF,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACvB,OAAO,CAAC,cAAc,CAAC,GAAG,kBAAkB,CAAC;YAC/C,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAChC,MAAM;gBACN,OAAO;gBACP,IAAI,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;gBAC3D,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YAEH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CAAC,QAAQ,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC,CAAC;YAC7E,CAAC;YAED,IAAI,CAAC,YAAY,CAAC,aAAa,EAAE,CAAC;YAElC,IAAI,CAAC,IAAI;gBAAE,OAAO,IAAI,CAAC;YACvB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAM,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,IAAI,CAAC,YAAY,CAAC,aAAa,EAAE,CAAC;YAClC,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC7D,OAAO,CAAC,KAAK,CAAC,YAAY,MAAM,IAAI,IAAI,YAAY,GAAG,EAAE,CAAC,CAAC;YAC3D,OAAO,IAAI,CAAC;QACd,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;CACF;AApOD,4CAoOC;AAED,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E;;;GAGG;AACH,SAAS,aAAa,CAAC,MAAc;IACnC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;QAChC,OAAO,GAAG,MAAM,CAAC,QAAQ,KAAK,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC;IACpF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACpC,CAAC;AACH,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * /memory command — shows engram server status and recent context overview.
3
+ */
4
+ import type { EngramRestClient } from '../client.js';
5
+ import type { PluginConfig } from '../config.js';
6
+ import type { OpenClawPluginCommandDefinition } from '../types/openclaw.js';
7
+ /**
8
+ * Build the /memory command definition.
9
+ */
10
+ export declare function buildMemoryCommand(client: EngramRestClient, config: PluginConfig): OpenClawPluginCommandDefinition;
11
+ //# sourceMappingURL=memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/commands/memory.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,+BAA+B,EAAwB,MAAM,sBAAsB,CAAC;AAElG;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,YAAY,GACnB,+BAA+B,CA4CjC"}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ /**
3
+ * /memory command — shows engram server status and recent context overview.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.buildMemoryCommand = buildMemoryCommand;
7
+ /**
8
+ * Build the /memory command definition.
9
+ */
10
+ function buildMemoryCommand(client, config) {
11
+ return {
12
+ name: 'memory',
13
+ description: 'Show engram memory server status and recent observations',
14
+ acceptsArgs: false,
15
+ async handler(_ctx) {
16
+ if (!client.isAvailable()) {
17
+ const cooldown = client.availability.remainingCooldownMs();
18
+ return {
19
+ text: `engram status: UNAVAILABLE\n` +
20
+ `Server: ${config.url}\n` +
21
+ (cooldown > 0 ? `Retry in: ${Math.ceil(cooldown / 1000)}s\n` : ''),
22
+ };
23
+ }
24
+ const [health, selfCheck] = await Promise.all([
25
+ client.health(),
26
+ client.selfCheck(),
27
+ ]);
28
+ const lines = [];
29
+ lines.push(`engram status: ${health?.status ?? 'UNKNOWN'}`);
30
+ lines.push(`Server: ${config.url}`);
31
+ if (health?.version)
32
+ lines.push(`Version: ${health.version}`);
33
+ if (selfCheck?.components) {
34
+ lines.push('\nComponents:');
35
+ for (const [name, comp] of Object.entries(selfCheck.components)) {
36
+ const icon = comp.status === 'ok' ? 'OK' : 'WARN';
37
+ lines.push(` [${icon}] ${name}${comp.message ? ': ' + comp.message : ''}`);
38
+ }
39
+ }
40
+ lines.push(`\nConfig:`);
41
+ lines.push(` Token budget: ${config.tokenBudget} tokens`);
42
+ lines.push(` Context limit: ${config.contextLimit} observations/turn`);
43
+ lines.push(` Session context limit: ${config.sessionContextLimit} observations`);
44
+ lines.push(` Auto-extract: ${config.autoExtract ? 'enabled' : 'disabled'}`);
45
+ return { text: lines.join('\n') };
46
+ },
47
+ };
48
+ }
49
+ //# sourceMappingURL=memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/commands/memory.ts"],"names":[],"mappings":";AAAA;;GAEG;;AASH,gDA+CC;AAlDD;;GAEG;AACH,SAAgB,kBAAkB,CAChC,MAAwB,EACxB,MAAoB;IAEpB,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,0DAA0D;QACvE,WAAW,EAAE,KAAK;QAElB,KAAK,CAAC,OAAO,CAAC,IAA0B;YACtC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC;gBAC1B,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,mBAAmB,EAAE,CAAC;gBAC3D,OAAO;oBACL,IAAI,EACF,8BAA8B;wBAC9B,WAAW,MAAM,CAAC,GAAG,IAAI;wBACzB,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,IAAI,CAAC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;iBACrE,CAAC;YACJ,CAAC;YAED,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;gBAC5C,MAAM,CAAC,MAAM,EAAE;gBACf,MAAM,CAAC,SAAS,EAAE;aACnB,CAAC,CAAC;YAEH,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,kBAAkB,MAAM,EAAE,MAAM,IAAI,SAAS,EAAE,CAAC,CAAC;YAC5D,KAAK,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;YACpC,IAAI,MAAM,EAAE,OAAO;gBAAE,KAAK,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;YAE9D,IAAI,SAAS,EAAE,UAAU,EAAE,CAAC;gBAC1B,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;gBAC5B,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC;oBAChE,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;oBAClD,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,KAAK,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC9E,CAAC;YACH,CAAC;YAED,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACxB,KAAK,CAAC,IAAI,CAAC,mBAAmB,MAAM,CAAC,WAAW,SAAS,CAAC,CAAC;YAC3D,KAAK,CAAC,IAAI,CAAC,oBAAoB,MAAM,CAAC,YAAY,oBAAoB,CAAC,CAAC;YACxE,KAAK,CAAC,IAAI,CAAC,4BAA4B,MAAM,CAAC,mBAAmB,eAAe,CAAC,CAAC;YAClF,KAAK,CAAC,IAAI,CAAC,mBAAmB,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC;YAE7E,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * /remember command — quick observation storage shortcut.
3
+ *
4
+ * Usage: /remember <text>
5
+ *
6
+ * Stores the provided text as a "change" type observation in the current project.
7
+ */
8
+ import type { EngramRestClient } from '../client.js';
9
+ import type { PluginConfig } from '../config.js';
10
+ import type { OpenClawPluginCommandDefinition } from '../types/openclaw.js';
11
+ /**
12
+ * Build the /remember command definition.
13
+ */
14
+ export declare function buildRememberCommand(client: EngramRestClient, config: PluginConfig): OpenClawPluginCommandDefinition;
15
+ //# sourceMappingURL=remember.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remember.d.ts","sourceRoot":"","sources":["../../src/commands/remember.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAqB,MAAM,cAAc,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,OAAO,KAAK,EAAE,+BAA+B,EAAwB,MAAM,sBAAsB,CAAC;AAIlG;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,YAAY,GACnB,+BAA+B,CAsDjC"}
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ /**
3
+ * /remember command — quick observation storage shortcut.
4
+ *
5
+ * Usage: /remember <text>
6
+ *
7
+ * Stores the provided text as a "change" type observation in the current project.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.buildRememberCommand = buildRememberCommand;
11
+ const identity_js_1 = require("../identity.js");
12
+ const CONTENT_MAX_CHARS = 900;
13
+ /**
14
+ * Build the /remember command definition.
15
+ */
16
+ function buildRememberCommand(client, config) {
17
+ return {
18
+ name: 'remember',
19
+ description: 'Quickly store a note in engram memory',
20
+ acceptsArgs: true,
21
+ async handler(ctx) {
22
+ const text = (ctx.args ?? '').trim();
23
+ if (!text) {
24
+ return { text: 'Usage: /remember <text to remember>' };
25
+ }
26
+ if (!client.isAvailable()) {
27
+ return { text: 'engram is currently unreachable — cannot store memory' };
28
+ }
29
+ const identity = (0, identity_js_1.resolveIdentity)('', config.workspaceDir ?? process.cwd());
30
+ const project = config.project ?? identity.projectId;
31
+ // Use the first sentence (up to 80 chars) as the title
32
+ const firstSentence = text.split(/[.!?]/)[0]?.trim() ?? text;
33
+ const title = firstSentence.length > 80
34
+ ? firstSentence.slice(0, 77) + '...'
35
+ : firstSentence;
36
+ const content = text.length > CONTENT_MAX_CHARS
37
+ ? text.slice(0, CONTENT_MAX_CHARS)
38
+ : text;
39
+ const observation = {
40
+ title,
41
+ content,
42
+ type: 'change',
43
+ project,
44
+ scope: 'project',
45
+ };
46
+ const response = await client.bulkImport([observation]);
47
+ if (!response) {
48
+ return { text: 'Failed to store memory — engram returned no response' };
49
+ }
50
+ if (response.imported > 0) {
51
+ return { text: `Stored: "${title}"` };
52
+ }
53
+ if (response.skipped_duplicates > 0) {
54
+ return { text: `Skipped (likely a near-duplicate): "${title}"` };
55
+ }
56
+ const errMsg = response.errors?.join(', ') ?? 'unknown error';
57
+ return { text: `Failed to store memory: ${errMsg}` };
58
+ },
59
+ };
60
+ }
61
+ //# sourceMappingURL=remember.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remember.js","sourceRoot":"","sources":["../../src/commands/remember.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAYH,oDAyDC;AAjED,gDAAiD;AAGjD,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAE9B;;GAEG;AACH,SAAgB,oBAAoB,CAClC,MAAwB,EACxB,MAAoB;IAEpB,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,uCAAuC;QACpD,WAAW,EAAE,IAAI;QAEjB,KAAK,CAAC,OAAO,CAAC,GAAyB;YACrC,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YACrC,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,EAAE,IAAI,EAAE,qCAAqC,EAAE,CAAC;YACzD,CAAC;YAED,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC;gBAC1B,OAAO,EAAE,IAAI,EAAE,uDAAuD,EAAE,CAAC;YAC3E,CAAC;YAED,MAAM,QAAQ,GAAG,IAAA,6BAAe,EAAC,EAAE,EAAE,MAAM,CAAC,YAAY,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;YAC3E,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,QAAQ,CAAC,SAAS,CAAC;YAErD,uDAAuD;YACvD,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC;YAC7D,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,GAAG,EAAE;gBACrC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK;gBACpC,CAAC,CAAC,aAAa,CAAC;YAElB,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,iBAAiB;gBAC7C,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,iBAAiB,CAAC;gBAClC,CAAC,CAAC,IAAI,CAAC;YAET,MAAM,WAAW,GAAsB;gBACrC,KAAK;gBACL,OAAO;gBACP,IAAI,EAAE,QAAQ;gBACd,OAAO;gBACP,KAAK,EAAE,SAAS;aACjB,CAAC;YAEF,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;YACxD,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO,EAAE,IAAI,EAAE,sDAAsD,EAAE,CAAC;YAC1E,CAAC;YAED,IAAI,QAAQ,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC;gBAC1B,OAAO,EAAE,IAAI,EAAE,YAAY,KAAK,GAAG,EAAE,CAAC;YACxC,CAAC;YAED,IAAI,QAAQ,CAAC,kBAAkB,GAAG,CAAC,EAAE,CAAC;gBACpC,OAAO,EAAE,IAAI,EAAE,uCAAuC,KAAK,GAAG,EAAE,CAAC;YACnE,CAAC;YAED,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,eAAe,CAAC;YAC9D,OAAO,EAAE,IAAI,EAAE,2BAA2B,MAAM,EAAE,EAAE,CAAC;QACvD,CAAC;KACF,CAAC;AACJ,CAAC"}