@praveencs/agent 0.1.0 → 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.
- package/dist/src/cli/commands/goal.d.ts +7 -0
- package/dist/src/cli/commands/goal.d.ts.map +1 -0
- package/dist/src/cli/commands/goal.js +246 -0
- package/dist/src/cli/commands/goal.js.map +1 -0
- package/dist/src/cli/commands/memory.d.ts +3 -0
- package/dist/src/cli/commands/memory.d.ts.map +1 -0
- package/dist/src/cli/commands/memory.js +108 -0
- package/dist/src/cli/commands/memory.js.map +1 -0
- package/dist/src/cli/commands/skills.d.ts.map +1 -1
- package/dist/src/cli/commands/skills.js +254 -15
- package/dist/src/cli/commands/skills.js.map +1 -1
- package/dist/src/cli/index.d.ts.map +1 -1
- package/dist/src/cli/index.js +7 -2
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/config/defaults.js +1 -1
- package/dist/src/config/defaults.js.map +1 -1
- package/dist/src/config/schema.js +1 -1
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/goals/store.d.ts +128 -0
- package/dist/src/goals/store.d.ts.map +1 -0
- package/dist/src/goals/store.js +234 -0
- package/dist/src/goals/store.js.map +1 -0
- package/dist/src/memory/store.d.ts +69 -0
- package/dist/src/memory/store.d.ts.map +1 -0
- package/dist/src/memory/store.js +255 -0
- package/dist/src/memory/store.js.map +1 -0
- package/dist/src/plans/types.d.ts +6 -6
- package/package.json +3 -1
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
export class GoalStore {
|
|
2
|
+
db;
|
|
3
|
+
constructor(memoryStore) {
|
|
4
|
+
// Reuse the same database from MemoryStore
|
|
5
|
+
this.db = memoryStore.db;
|
|
6
|
+
}
|
|
7
|
+
// ─── Goal Operations ──────────────────────────────────────
|
|
8
|
+
/**
|
|
9
|
+
* Create a new goal
|
|
10
|
+
*/
|
|
11
|
+
addGoal(title, options = {}) {
|
|
12
|
+
const stmt = this.db.prepare(`
|
|
13
|
+
INSERT INTO goals (title, description, priority, deadline, parent_goal_id)
|
|
14
|
+
VALUES (?, ?, ?, ?, ?)
|
|
15
|
+
`);
|
|
16
|
+
const result = stmt.run(title, options.description ?? null, options.priority ?? 5, options.deadline ?? null, options.parentGoalId ?? null);
|
|
17
|
+
this.logAudit('goal.created', 'goal', result.lastInsertRowid, title);
|
|
18
|
+
return this.getGoal(result.lastInsertRowid);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Get a goal by ID
|
|
22
|
+
*/
|
|
23
|
+
getGoal(id) {
|
|
24
|
+
const row = this.db.prepare('SELECT * FROM goals WHERE id = ?').get(id);
|
|
25
|
+
if (!row)
|
|
26
|
+
return null;
|
|
27
|
+
return { ...row, metadata: JSON.parse(row.metadata || '{}') };
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* List goals by status
|
|
31
|
+
*/
|
|
32
|
+
listGoals(status) {
|
|
33
|
+
let rows;
|
|
34
|
+
if (status) {
|
|
35
|
+
rows = this.db.prepare('SELECT * FROM goals WHERE status = ? ORDER BY priority ASC, created_at DESC').all(status);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
rows = this.db.prepare('SELECT * FROM goals ORDER BY status ASC, priority ASC, created_at DESC').all();
|
|
39
|
+
}
|
|
40
|
+
return rows.map(r => ({ ...r, metadata: JSON.parse(r.metadata || '{}') }));
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Update goal status
|
|
44
|
+
*/
|
|
45
|
+
updateGoalStatus(id, status) {
|
|
46
|
+
this.db.prepare(`
|
|
47
|
+
UPDATE goals SET status = ?, updated_at = datetime('now') WHERE id = ?
|
|
48
|
+
`).run(status, id);
|
|
49
|
+
this.logAudit(`goal.${status}`, 'goal', id, `Goal #${id} → ${status}`);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Update goal progress (0.0 to 1.0)
|
|
53
|
+
*/
|
|
54
|
+
updateGoalProgress(id) {
|
|
55
|
+
const tasks = this.listTasks(id);
|
|
56
|
+
if (tasks.length === 0)
|
|
57
|
+
return;
|
|
58
|
+
const completed = tasks.filter(t => t.status === 'completed').length;
|
|
59
|
+
const progress = completed / tasks.length;
|
|
60
|
+
this.db.prepare(`
|
|
61
|
+
UPDATE goals SET progress = ?, updated_at = datetime('now') WHERE id = ?
|
|
62
|
+
`).run(progress, id);
|
|
63
|
+
// Auto-complete goal if all tasks done
|
|
64
|
+
if (progress >= 1.0) {
|
|
65
|
+
this.updateGoalStatus(id, 'completed');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Delete a goal and its tasks
|
|
70
|
+
*/
|
|
71
|
+
removeGoal(id) {
|
|
72
|
+
const result = this.db.prepare('DELETE FROM goals WHERE id = ?').run(id);
|
|
73
|
+
return result.changes > 0;
|
|
74
|
+
}
|
|
75
|
+
// ─── Task Operations ──────────────────────────────────────
|
|
76
|
+
/**
|
|
77
|
+
* Add a task to a goal
|
|
78
|
+
*/
|
|
79
|
+
addTask(goalId, title, options = {}) {
|
|
80
|
+
const stmt = this.db.prepare(`
|
|
81
|
+
INSERT INTO tasks (goal_id, title, description, skill, input, depends_on, requires_approval, scheduled_at)
|
|
82
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
83
|
+
`);
|
|
84
|
+
const result = stmt.run(goalId, title, options.description ?? null, options.skill ?? null, JSON.stringify(options.input ?? {}), JSON.stringify(options.dependsOn ?? []), options.requiresApproval ? 1 : 0, options.scheduledAt ?? null);
|
|
85
|
+
this.logAudit('task.created', 'task', result.lastInsertRowid, title);
|
|
86
|
+
return this.getTask(result.lastInsertRowid);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Get a task by ID
|
|
90
|
+
*/
|
|
91
|
+
getTask(id) {
|
|
92
|
+
const row = this.db.prepare('SELECT * FROM tasks WHERE id = ?').get(id);
|
|
93
|
+
if (!row)
|
|
94
|
+
return null;
|
|
95
|
+
return this.parseTask(row);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* List tasks for a goal
|
|
99
|
+
*/
|
|
100
|
+
listTasks(goalId) {
|
|
101
|
+
const rows = this.db.prepare('SELECT * FROM tasks WHERE goal_id = ? ORDER BY id ASC').all(goalId);
|
|
102
|
+
return rows.map(r => this.parseTask(r));
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Get the next executable task (respects dependencies)
|
|
106
|
+
*/
|
|
107
|
+
getNextTask() {
|
|
108
|
+
// Get all pending/queued tasks ordered by goal priority
|
|
109
|
+
const candidates = this.db.prepare(`
|
|
110
|
+
SELECT t.* FROM tasks t
|
|
111
|
+
JOIN goals g ON t.goal_id = g.id
|
|
112
|
+
WHERE t.status IN ('pending', 'queued')
|
|
113
|
+
AND g.status = 'active'
|
|
114
|
+
ORDER BY g.priority ASC, t.id ASC
|
|
115
|
+
`).all();
|
|
116
|
+
for (const row of candidates) {
|
|
117
|
+
const task = this.parseTask(row);
|
|
118
|
+
// Check dependencies
|
|
119
|
+
if (task.depends_on.length > 0) {
|
|
120
|
+
const deps = task.depends_on.map(id => this.getTask(id));
|
|
121
|
+
const allMet = deps.every(d => d?.status === 'completed');
|
|
122
|
+
if (!allMet)
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
// Check if approval is needed and granted
|
|
126
|
+
if (task.requires_approval && !task.approved_at)
|
|
127
|
+
continue;
|
|
128
|
+
return task;
|
|
129
|
+
}
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Mark task as running
|
|
134
|
+
*/
|
|
135
|
+
startTask(id) {
|
|
136
|
+
this.db.prepare(`
|
|
137
|
+
UPDATE tasks SET status = 'running', started_at = datetime('now') WHERE id = ?
|
|
138
|
+
`).run(id);
|
|
139
|
+
this.logAudit('task.started', 'task', id, `Task #${id} started`);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Mark task as completed
|
|
143
|
+
*/
|
|
144
|
+
completeTask(id, output) {
|
|
145
|
+
this.db.prepare(`
|
|
146
|
+
UPDATE tasks SET status = 'completed', output = ?, completed_at = datetime('now')
|
|
147
|
+
WHERE id = ?
|
|
148
|
+
`).run(output, id);
|
|
149
|
+
this.logAudit('task.completed', 'task', id, `Task #${id} completed`);
|
|
150
|
+
// Update goal progress
|
|
151
|
+
const task = this.getTask(id);
|
|
152
|
+
if (task)
|
|
153
|
+
this.updateGoalProgress(task.goal_id);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Mark task as failed
|
|
157
|
+
*/
|
|
158
|
+
failTask(id, error) {
|
|
159
|
+
const task = this.getTask(id);
|
|
160
|
+
if (!task)
|
|
161
|
+
return;
|
|
162
|
+
if (task.retry_count < task.max_retries) {
|
|
163
|
+
// Retry
|
|
164
|
+
this.db.prepare(`
|
|
165
|
+
UPDATE tasks SET status = 'pending', retry_count = retry_count + 1, error = ?
|
|
166
|
+
WHERE id = ?
|
|
167
|
+
`).run(error, id);
|
|
168
|
+
this.logAudit('task.retry', 'task', id, `Task #${id} retry ${task.retry_count + 1}/${task.max_retries}: ${error}`);
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
// Final failure
|
|
172
|
+
this.db.prepare(`
|
|
173
|
+
UPDATE tasks SET status = 'failed', error = ?, completed_at = datetime('now')
|
|
174
|
+
WHERE id = ?
|
|
175
|
+
`).run(error, id);
|
|
176
|
+
this.logAudit('task.failed', 'task', id, `Task #${id} failed: ${error}`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Approve a task that requires human approval
|
|
181
|
+
*/
|
|
182
|
+
approveTask(id) {
|
|
183
|
+
const result = this.db.prepare(`
|
|
184
|
+
UPDATE tasks SET approved_at = datetime('now'), status = 'queued'
|
|
185
|
+
WHERE id = ? AND requires_approval = 1
|
|
186
|
+
`).run(id);
|
|
187
|
+
if (result.changes > 0) {
|
|
188
|
+
this.logAudit('task.approved', 'task', id, `Task #${id} approved`);
|
|
189
|
+
}
|
|
190
|
+
return result.changes > 0;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Get tasks waiting for approval
|
|
194
|
+
*/
|
|
195
|
+
getPendingApprovals() {
|
|
196
|
+
const rows = this.db.prepare(`
|
|
197
|
+
SELECT * FROM tasks
|
|
198
|
+
WHERE requires_approval = 1 AND approved_at IS NULL
|
|
199
|
+
AND status NOT IN ('cancelled', 'completed', 'failed')
|
|
200
|
+
ORDER BY id ASC
|
|
201
|
+
`).all();
|
|
202
|
+
return rows.map(r => this.parseTask(r));
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Get summary stats
|
|
206
|
+
*/
|
|
207
|
+
stats() {
|
|
208
|
+
return {
|
|
209
|
+
activeGoals: this.db.prepare("SELECT COUNT(*) as c FROM goals WHERE status = 'active'").get().c,
|
|
210
|
+
completedGoals: this.db.prepare("SELECT COUNT(*) as c FROM goals WHERE status = 'completed'").get().c,
|
|
211
|
+
pendingTasks: this.db.prepare("SELECT COUNT(*) as c FROM tasks WHERE status IN ('pending','queued')").get().c,
|
|
212
|
+
runningTasks: this.db.prepare("SELECT COUNT(*) as c FROM tasks WHERE status = 'running'").get().c,
|
|
213
|
+
completedTasks: this.db.prepare("SELECT COUNT(*) as c FROM tasks WHERE status = 'completed'").get().c,
|
|
214
|
+
failedTasks: this.db.prepare("SELECT COUNT(*) as c FROM tasks WHERE status = 'failed'").get().c,
|
|
215
|
+
awaitingApproval: this.db.prepare("SELECT COUNT(*) as c FROM tasks WHERE requires_approval = 1 AND approved_at IS NULL AND status NOT IN ('cancelled','completed','failed')").get().c,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
// ─── Helpers ──────────────────────────────────────────────
|
|
219
|
+
parseTask(row) {
|
|
220
|
+
return {
|
|
221
|
+
...row,
|
|
222
|
+
input: JSON.parse(row.input || '{}'),
|
|
223
|
+
depends_on: JSON.parse(row.depends_on || '[]'),
|
|
224
|
+
requires_approval: !!row.requires_approval,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
logAudit(eventType, entityType, entityId, details) {
|
|
228
|
+
this.db.prepare(`
|
|
229
|
+
INSERT INTO audit_events (event_type, entity_type, entity_id, action, details)
|
|
230
|
+
VALUES (?, ?, ?, ?, ?)
|
|
231
|
+
`).run(eventType, entityType, entityId, eventType, details);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/goals/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Store — Persistent agent memory backed by SQLite + FTS5
|
|
3
|
+
*
|
|
4
|
+
* Stores facts, project context, and learned information
|
|
5
|
+
* that persists across sessions.
|
|
6
|
+
*/
|
|
7
|
+
export interface Memory {
|
|
8
|
+
id: number;
|
|
9
|
+
content: string;
|
|
10
|
+
category: 'project' | 'preference' | 'fact' | 'learned' | 'general';
|
|
11
|
+
source: 'user' | 'agent' | 'auto';
|
|
12
|
+
tags: string[];
|
|
13
|
+
created_at: string;
|
|
14
|
+
accessed_at: string | null;
|
|
15
|
+
relevance_score: number;
|
|
16
|
+
}
|
|
17
|
+
export interface MemorySearchResult extends Memory {
|
|
18
|
+
rank: number;
|
|
19
|
+
}
|
|
20
|
+
export declare class MemoryStore {
|
|
21
|
+
private db;
|
|
22
|
+
private static instance;
|
|
23
|
+
constructor(dbPath: string);
|
|
24
|
+
/**
|
|
25
|
+
* Get singleton instance scoped to a working directory
|
|
26
|
+
*/
|
|
27
|
+
static open(workDir: string): MemoryStore;
|
|
28
|
+
/**
|
|
29
|
+
* Run database migrations
|
|
30
|
+
*/
|
|
31
|
+
private migrate;
|
|
32
|
+
/**
|
|
33
|
+
* Save a new memory
|
|
34
|
+
*/
|
|
35
|
+
save(content: string, category?: Memory['category'], source?: Memory['source'], tags?: string[]): Memory;
|
|
36
|
+
/**
|
|
37
|
+
* Search memories using full-text search
|
|
38
|
+
*/
|
|
39
|
+
search(query: string, limit?: number): MemorySearchResult[];
|
|
40
|
+
/**
|
|
41
|
+
* Get all memories, optionally filtered by category
|
|
42
|
+
*/
|
|
43
|
+
list(category?: Memory['category'], limit?: number): Memory[];
|
|
44
|
+
/**
|
|
45
|
+
* Get a specific memory by ID
|
|
46
|
+
*/
|
|
47
|
+
getMemory(id: number): Memory | null;
|
|
48
|
+
/**
|
|
49
|
+
* Delete a memory
|
|
50
|
+
*/
|
|
51
|
+
forget(id: number): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Get relevant context for an LLM prompt
|
|
54
|
+
* Searches memories and returns formatted context
|
|
55
|
+
*/
|
|
56
|
+
getContext(query: string, maxTokens?: number): string;
|
|
57
|
+
/**
|
|
58
|
+
* Get memory count and stats
|
|
59
|
+
*/
|
|
60
|
+
stats(): {
|
|
61
|
+
total: number;
|
|
62
|
+
byCategory: Record<string, number>;
|
|
63
|
+
bySource: Record<string, number>;
|
|
64
|
+
};
|
|
65
|
+
private logAudit;
|
|
66
|
+
getAuditLog(limit?: number): any[];
|
|
67
|
+
close(): void;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/memory/store.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AAEH,MAAM,WAAW,MAAM;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,SAAS,GAAG,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;IACpE,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;IAClC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAmB,SAAQ,MAAM;IAC9C,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,WAAW;IACpB,OAAO,CAAC,EAAE,CAAoB;IAC9B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA4B;gBAEvC,MAAM,EAAE,MAAM;IAY1B;;OAEG;IACH,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW;IASzC;;OAEG;IACH,OAAO,CAAC,OAAO;IAsGf;;OAEG;IACH,IAAI,CACA,OAAO,EAAE,MAAM,EACf,QAAQ,GAAE,MAAM,CAAC,UAAU,CAAa,EACxC,MAAM,GAAE,MAAM,CAAC,QAAQ,CAAU,EACjC,IAAI,GAAE,MAAM,EAAO,GACpB,MAAM;IAYT;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,kBAAkB,EAAE;IA0BvD;;OAEG;IACH,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC,EAAE,KAAK,SAAK,GAAG,MAAM,EAAE;IAqBzD;;OAEG;IACH,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAOpC;;OAEG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAS3B;;;OAGG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAM,GAAG,MAAM;IAkBlD;;OAEG;IACH,KAAK,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE;IAoBhG,OAAO,CAAC,QAAQ;IAOhB,WAAW,CAAC,KAAK,SAAK,GAAG,GAAG,EAAE;IAQ9B,KAAK,IAAI,IAAI;CAIhB"}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { mkdirSync } from 'node:fs';
|
|
4
|
+
export class MemoryStore {
|
|
5
|
+
db;
|
|
6
|
+
static instance = null;
|
|
7
|
+
constructor(dbPath) {
|
|
8
|
+
// Ensure directory exists
|
|
9
|
+
mkdirSync(path.dirname(dbPath), { recursive: true });
|
|
10
|
+
this.db = new Database(dbPath);
|
|
11
|
+
// Enable WAL mode for better concurrent performance
|
|
12
|
+
this.db.pragma('journal_mode = WAL');
|
|
13
|
+
this.migrate();
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Get singleton instance scoped to a working directory
|
|
17
|
+
*/
|
|
18
|
+
static open(workDir) {
|
|
19
|
+
const dbPath = path.join(workDir, '.agent', 'memory.db');
|
|
20
|
+
if (!MemoryStore.instance || MemoryStore.instance._path !== dbPath) {
|
|
21
|
+
MemoryStore.instance = new MemoryStore(dbPath);
|
|
22
|
+
MemoryStore.instance._path = dbPath;
|
|
23
|
+
}
|
|
24
|
+
return MemoryStore.instance;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Run database migrations
|
|
28
|
+
*/
|
|
29
|
+
migrate() {
|
|
30
|
+
this.db.exec(`
|
|
31
|
+
-- Memories table
|
|
32
|
+
CREATE TABLE IF NOT EXISTS memories (
|
|
33
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
34
|
+
content TEXT NOT NULL,
|
|
35
|
+
category TEXT DEFAULT 'general'
|
|
36
|
+
CHECK(category IN ('project','preference','fact','learned','general')),
|
|
37
|
+
source TEXT DEFAULT 'user'
|
|
38
|
+
CHECK(source IN ('user','agent','auto')),
|
|
39
|
+
tags TEXT DEFAULT '[]',
|
|
40
|
+
created_at DATETIME DEFAULT (datetime('now')),
|
|
41
|
+
accessed_at DATETIME,
|
|
42
|
+
relevance_score REAL DEFAULT 1.0
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
-- Full-text search index
|
|
46
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS memories_fts USING fts5(
|
|
47
|
+
content, category, tags,
|
|
48
|
+
content='memories',
|
|
49
|
+
content_rowid='id'
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
-- Triggers to keep FTS in sync
|
|
53
|
+
CREATE TRIGGER IF NOT EXISTS memories_ai AFTER INSERT ON memories BEGIN
|
|
54
|
+
INSERT INTO memories_fts(rowid, content, category, tags)
|
|
55
|
+
VALUES (new.id, new.content, new.category, new.tags);
|
|
56
|
+
END;
|
|
57
|
+
|
|
58
|
+
CREATE TRIGGER IF NOT EXISTS memories_ad AFTER DELETE ON memories BEGIN
|
|
59
|
+
INSERT INTO memories_fts(memories_fts, rowid, content, category, tags)
|
|
60
|
+
VALUES ('delete', old.id, old.content, old.category, old.tags);
|
|
61
|
+
END;
|
|
62
|
+
|
|
63
|
+
CREATE TRIGGER IF NOT EXISTS memories_au AFTER UPDATE ON memories BEGIN
|
|
64
|
+
INSERT INTO memories_fts(memories_fts, rowid, content, category, tags)
|
|
65
|
+
VALUES ('delete', old.id, old.content, old.category, old.tags);
|
|
66
|
+
INSERT INTO memories_fts(rowid, content, category, tags)
|
|
67
|
+
VALUES (new.id, new.content, new.category, new.tags);
|
|
68
|
+
END;
|
|
69
|
+
|
|
70
|
+
-- Goals table
|
|
71
|
+
CREATE TABLE IF NOT EXISTS goals (
|
|
72
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
73
|
+
title TEXT NOT NULL,
|
|
74
|
+
description TEXT,
|
|
75
|
+
status TEXT DEFAULT 'active'
|
|
76
|
+
CHECK(status IN ('active','paused','completed','failed','cancelled')),
|
|
77
|
+
priority INTEGER DEFAULT 5
|
|
78
|
+
CHECK(priority BETWEEN 1 AND 10),
|
|
79
|
+
created_at DATETIME DEFAULT (datetime('now')),
|
|
80
|
+
updated_at DATETIME DEFAULT (datetime('now')),
|
|
81
|
+
deadline DATETIME,
|
|
82
|
+
parent_goal_id INTEGER REFERENCES goals(id),
|
|
83
|
+
progress REAL DEFAULT 0.0,
|
|
84
|
+
metadata TEXT DEFAULT '{}'
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
-- Tasks table
|
|
88
|
+
CREATE TABLE IF NOT EXISTS tasks (
|
|
89
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
90
|
+
goal_id INTEGER REFERENCES goals(id) ON DELETE CASCADE,
|
|
91
|
+
title TEXT NOT NULL,
|
|
92
|
+
description TEXT,
|
|
93
|
+
status TEXT DEFAULT 'pending'
|
|
94
|
+
CHECK(status IN ('pending','queued','running','completed','failed','blocked','cancelled')),
|
|
95
|
+
skill TEXT,
|
|
96
|
+
input TEXT DEFAULT '{}',
|
|
97
|
+
output TEXT,
|
|
98
|
+
depends_on TEXT DEFAULT '[]',
|
|
99
|
+
scheduled_at DATETIME,
|
|
100
|
+
started_at DATETIME,
|
|
101
|
+
completed_at DATETIME,
|
|
102
|
+
retry_count INTEGER DEFAULT 0,
|
|
103
|
+
max_retries INTEGER DEFAULT 3,
|
|
104
|
+
error TEXT,
|
|
105
|
+
requires_approval BOOLEAN DEFAULT 0,
|
|
106
|
+
approved_at DATETIME,
|
|
107
|
+
created_at DATETIME DEFAULT (datetime('now'))
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
-- Audit events table
|
|
111
|
+
CREATE TABLE IF NOT EXISTS audit_events (
|
|
112
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
113
|
+
event_type TEXT NOT NULL,
|
|
114
|
+
entity_type TEXT,
|
|
115
|
+
entity_id INTEGER,
|
|
116
|
+
action TEXT NOT NULL,
|
|
117
|
+
details TEXT,
|
|
118
|
+
created_at DATETIME DEFAULT (datetime('now'))
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
-- Indexes
|
|
122
|
+
CREATE INDEX IF NOT EXISTS idx_goals_status ON goals(status);
|
|
123
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_goal ON tasks(goal_id);
|
|
124
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);
|
|
125
|
+
CREATE INDEX IF NOT EXISTS idx_audit_entity ON audit_events(entity_type, entity_id);
|
|
126
|
+
`);
|
|
127
|
+
}
|
|
128
|
+
// ─── Memory Operations ─────────────────────────────────────
|
|
129
|
+
/**
|
|
130
|
+
* Save a new memory
|
|
131
|
+
*/
|
|
132
|
+
save(content, category = 'general', source = 'user', tags = []) {
|
|
133
|
+
const stmt = this.db.prepare(`
|
|
134
|
+
INSERT INTO memories (content, category, source, tags)
|
|
135
|
+
VALUES (?, ?, ?, ?)
|
|
136
|
+
`);
|
|
137
|
+
const result = stmt.run(content, category, source, JSON.stringify(tags));
|
|
138
|
+
this.logAudit('memory.save', 'memory', result.lastInsertRowid, content);
|
|
139
|
+
return this.getMemory(result.lastInsertRowid);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Search memories using full-text search
|
|
143
|
+
*/
|
|
144
|
+
search(query, limit = 10) {
|
|
145
|
+
const stmt = this.db.prepare(`
|
|
146
|
+
SELECT m.*, fts.rank
|
|
147
|
+
FROM memories_fts fts
|
|
148
|
+
JOIN memories m ON m.id = fts.rowid
|
|
149
|
+
WHERE memories_fts MATCH ?
|
|
150
|
+
ORDER BY fts.rank
|
|
151
|
+
LIMIT ?
|
|
152
|
+
`);
|
|
153
|
+
const results = stmt.all(query, limit);
|
|
154
|
+
// Update accessed_at for returned memories
|
|
155
|
+
const updateStmt = this.db.prepare(`
|
|
156
|
+
UPDATE memories SET accessed_at = datetime('now') WHERE id = ?
|
|
157
|
+
`);
|
|
158
|
+
for (const r of results) {
|
|
159
|
+
updateStmt.run(r.id);
|
|
160
|
+
}
|
|
161
|
+
return results.map(r => ({
|
|
162
|
+
...r,
|
|
163
|
+
tags: JSON.parse(r.tags || '[]'),
|
|
164
|
+
}));
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Get all memories, optionally filtered by category
|
|
168
|
+
*/
|
|
169
|
+
list(category, limit = 50) {
|
|
170
|
+
let stmt;
|
|
171
|
+
if (category) {
|
|
172
|
+
stmt = this.db.prepare(`
|
|
173
|
+
SELECT * FROM memories WHERE category = ?
|
|
174
|
+
ORDER BY created_at DESC LIMIT ?
|
|
175
|
+
`);
|
|
176
|
+
return stmt.all(category, limit).map(r => ({
|
|
177
|
+
...r,
|
|
178
|
+
tags: JSON.parse(r.tags || '[]'),
|
|
179
|
+
}));
|
|
180
|
+
}
|
|
181
|
+
stmt = this.db.prepare(`
|
|
182
|
+
SELECT * FROM memories ORDER BY created_at DESC LIMIT ?
|
|
183
|
+
`);
|
|
184
|
+
return stmt.all(limit).map(r => ({
|
|
185
|
+
...r,
|
|
186
|
+
tags: JSON.parse(r.tags || '[]'),
|
|
187
|
+
}));
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Get a specific memory by ID
|
|
191
|
+
*/
|
|
192
|
+
getMemory(id) {
|
|
193
|
+
const stmt = this.db.prepare('SELECT * FROM memories WHERE id = ?');
|
|
194
|
+
const row = stmt.get(id);
|
|
195
|
+
if (!row)
|
|
196
|
+
return null;
|
|
197
|
+
return { ...row, tags: JSON.parse(row.tags || '[]') };
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Delete a memory
|
|
201
|
+
*/
|
|
202
|
+
forget(id) {
|
|
203
|
+
const stmt = this.db.prepare('DELETE FROM memories WHERE id = ?');
|
|
204
|
+
const result = stmt.run(id);
|
|
205
|
+
if (result.changes > 0) {
|
|
206
|
+
this.logAudit('memory.forget', 'memory', id, `Deleted memory #${id}`);
|
|
207
|
+
}
|
|
208
|
+
return result.changes > 0;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Get relevant context for an LLM prompt
|
|
212
|
+
* Searches memories and returns formatted context
|
|
213
|
+
*/
|
|
214
|
+
getContext(query, maxTokens = 500) {
|
|
215
|
+
const results = this.search(query, 5);
|
|
216
|
+
if (results.length === 0)
|
|
217
|
+
return '';
|
|
218
|
+
const lines = results.map(r => `- [${r.category}] ${r.content}`);
|
|
219
|
+
const context = lines.join('\n');
|
|
220
|
+
// Rough token estimate (4 chars ≈ 1 token)
|
|
221
|
+
if (context.length > maxTokens * 4) {
|
|
222
|
+
return context.slice(0, maxTokens * 4) + '\n...';
|
|
223
|
+
}
|
|
224
|
+
return context;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Get memory count and stats
|
|
228
|
+
*/
|
|
229
|
+
stats() {
|
|
230
|
+
const total = this.db.prepare('SELECT COUNT(*) as c FROM memories').get().c;
|
|
231
|
+
const byCat = this.db.prepare('SELECT category, COUNT(*) as c FROM memories GROUP BY category').all();
|
|
232
|
+
const bySrc = this.db.prepare('SELECT source, COUNT(*) as c FROM memories GROUP BY source').all();
|
|
233
|
+
return {
|
|
234
|
+
total,
|
|
235
|
+
byCategory: Object.fromEntries(byCat.map(r => [r.category, r.c])),
|
|
236
|
+
bySource: Object.fromEntries(bySrc.map(r => [r.source, r.c])),
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
// ─── Audit Operations ─────────────────────────────────────
|
|
240
|
+
logAudit(eventType, entityType, entityId, details) {
|
|
241
|
+
this.db.prepare(`
|
|
242
|
+
INSERT INTO audit_events (event_type, entity_type, entity_id, action, details)
|
|
243
|
+
VALUES (?, ?, ?, ?, ?)
|
|
244
|
+
`).run(eventType, entityType, entityId, eventType, details);
|
|
245
|
+
}
|
|
246
|
+
getAuditLog(limit = 20) {
|
|
247
|
+
return this.db.prepare('SELECT * FROM audit_events ORDER BY created_at DESC LIMIT ?').all(limit);
|
|
248
|
+
}
|
|
249
|
+
// ─── Cleanup ─────────────────────────────────────────────
|
|
250
|
+
close() {
|
|
251
|
+
this.db.close();
|
|
252
|
+
MemoryStore.instance = null;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/memory/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -135,7 +135,7 @@ export declare const StepSchema: z.ZodObject<{
|
|
|
135
135
|
}, "strip", z.ZodTypeAny, {
|
|
136
136
|
name: string;
|
|
137
137
|
id: string;
|
|
138
|
-
onFailure: "
|
|
138
|
+
onFailure: "abort" | "retry" | "skip";
|
|
139
139
|
retries: number;
|
|
140
140
|
args?: Record<string, unknown> | undefined;
|
|
141
141
|
description?: string | undefined;
|
|
@@ -161,7 +161,7 @@ export declare const StepSchema: z.ZodObject<{
|
|
|
161
161
|
fileExists?: string | undefined;
|
|
162
162
|
contains?: string | undefined;
|
|
163
163
|
} | undefined;
|
|
164
|
-
onFailure?: "
|
|
164
|
+
onFailure?: "abort" | "retry" | "skip" | undefined;
|
|
165
165
|
retries?: number | undefined;
|
|
166
166
|
dependsOn?: string[] | undefined;
|
|
167
167
|
}>;
|
|
@@ -271,7 +271,7 @@ export declare const PlanSchema: z.ZodObject<{
|
|
|
271
271
|
}, "strip", z.ZodTypeAny, {
|
|
272
272
|
name: string;
|
|
273
273
|
id: string;
|
|
274
|
-
onFailure: "
|
|
274
|
+
onFailure: "abort" | "retry" | "skip";
|
|
275
275
|
retries: number;
|
|
276
276
|
args?: Record<string, unknown> | undefined;
|
|
277
277
|
description?: string | undefined;
|
|
@@ -297,7 +297,7 @@ export declare const PlanSchema: z.ZodObject<{
|
|
|
297
297
|
fileExists?: string | undefined;
|
|
298
298
|
contains?: string | undefined;
|
|
299
299
|
} | undefined;
|
|
300
|
-
onFailure?: "
|
|
300
|
+
onFailure?: "abort" | "retry" | "skip" | undefined;
|
|
301
301
|
retries?: number | undefined;
|
|
302
302
|
dependsOn?: string[] | undefined;
|
|
303
303
|
}>, "many">;
|
|
@@ -378,7 +378,7 @@ export declare const PlanSchema: z.ZodObject<{
|
|
|
378
378
|
steps: {
|
|
379
379
|
name: string;
|
|
380
380
|
id: string;
|
|
381
|
-
onFailure: "
|
|
381
|
+
onFailure: "abort" | "retry" | "skip";
|
|
382
382
|
retries: number;
|
|
383
383
|
args?: Record<string, unknown> | undefined;
|
|
384
384
|
description?: string | undefined;
|
|
@@ -426,7 +426,7 @@ export declare const PlanSchema: z.ZodObject<{
|
|
|
426
426
|
fileExists?: string | undefined;
|
|
427
427
|
contains?: string | undefined;
|
|
428
428
|
} | undefined;
|
|
429
|
-
onFailure?: "
|
|
429
|
+
onFailure?: "abort" | "retry" | "skip" | undefined;
|
|
430
430
|
retries?: number | undefined;
|
|
431
431
|
dependsOn?: string[] | undefined;
|
|
432
432
|
}[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praveencs/agent",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"files": [
|
|
5
5
|
"dist",
|
|
6
6
|
"bin",
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@anthropic-ai/sdk": "^0.39.0",
|
|
49
49
|
"@modelcontextprotocol/sdk": "^1.5.0",
|
|
50
|
+
"better-sqlite3": "^12.6.2",
|
|
50
51
|
"chalk": "^5.4.1",
|
|
51
52
|
"chokidar": "^4.0.3",
|
|
52
53
|
"commander": "^13.1.0",
|
|
@@ -64,6 +65,7 @@
|
|
|
64
65
|
"zod": "^3.24.2"
|
|
65
66
|
},
|
|
66
67
|
"devDependencies": {
|
|
68
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
67
69
|
"@types/diff": "^7.0.0",
|
|
68
70
|
"@types/inquirer": "^9.0.7",
|
|
69
71
|
"@types/node": "^22.13.0",
|