gemini-helper-friend 2.0.0 → 2.0.2
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/config/templates/manual.mdx +499 -0
- package/dist/config/yaml/subagents.yaml +737 -33
- package/dist/index.js +83 -7
- package/dist/index.js.map +1 -1
- package/dist/tools/cleanup.d.ts +13 -0
- package/dist/tools/cleanup.d.ts.map +1 -0
- package/dist/tools/cleanup.js +55 -0
- package/dist/tools/cleanup.js.map +1 -0
- package/dist/tools/constants.d.ts +46 -0
- package/dist/tools/constants.d.ts.map +1 -0
- package/dist/tools/constants.js +73 -0
- package/dist/tools/constants.js.map +1 -0
- package/dist/tools/index.d.ts +3 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +1 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/subagent.tool.d.ts +6 -26
- package/dist/tools/subagent.tool.d.ts.map +1 -1
- package/dist/tools/subagent.tool.js +295 -110
- package/dist/tools/subagent.tool.js.map +1 -1
- package/dist/tools/task-store.d.ts +49 -0
- package/dist/tools/task-store.d.ts.map +1 -0
- package/dist/tools/task-store.js +191 -0
- package/dist/tools/task-store.js.map +1 -0
- package/package.json +3 -1
- package/src/config/templates/manual.mdx +499 -0
- package/src/config/yaml/subagents.yaml +737 -33
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite-based persistent task store
|
|
3
|
+
* Replaces in-memory Map to support async task persistence across MCP sessions
|
|
4
|
+
*/
|
|
5
|
+
import Database from 'better-sqlite3';
|
|
6
|
+
import { join } from 'path';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
import { dirname } from 'path';
|
|
9
|
+
import { existsSync, mkdirSync } from 'fs';
|
|
10
|
+
import { TASK_ID_MIN, TASK_ID_MAX, TASK_EXPIRY_MS, CLEANUP_INTERVAL_MS, DATA_DIR_NAME, DB_FILE_NAME, } from './constants.js';
|
|
11
|
+
import { cleanupOrphanedTempFiles } from './cleanup.js';
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
const __dirname = dirname(__filename);
|
|
14
|
+
// Database path - store in project root/.mcp-data directory
|
|
15
|
+
const DATA_DIR = join(__dirname, '../..', DATA_DIR_NAME);
|
|
16
|
+
const DB_PATH = join(DATA_DIR, DB_FILE_NAME);
|
|
17
|
+
// Ensure data directory exists
|
|
18
|
+
if (!existsSync(DATA_DIR)) {
|
|
19
|
+
mkdirSync(DATA_DIR, { recursive: true });
|
|
20
|
+
}
|
|
21
|
+
// Initialize database
|
|
22
|
+
const db = new Database(DB_PATH);
|
|
23
|
+
// Enable WAL mode for better concurrency
|
|
24
|
+
db.pragma('journal_mode = WAL');
|
|
25
|
+
// Create tasks table
|
|
26
|
+
db.exec(`
|
|
27
|
+
CREATE TABLE IF NOT EXISTS tasks (
|
|
28
|
+
id INTEGER PRIMARY KEY,
|
|
29
|
+
status TEXT NOT NULL,
|
|
30
|
+
task_type TEXT NOT NULL,
|
|
31
|
+
progress INTEGER NOT NULL DEFAULT 0,
|
|
32
|
+
result TEXT,
|
|
33
|
+
error TEXT,
|
|
34
|
+
started_at TEXT NOT NULL,
|
|
35
|
+
completed_at TEXT,
|
|
36
|
+
updated_at TEXT NOT NULL,
|
|
37
|
+
pid INTEGER
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);
|
|
41
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_started_at ON tasks(started_at);
|
|
42
|
+
`);
|
|
43
|
+
// Migration: Add pid column if it doesn't exist (for existing databases)
|
|
44
|
+
try {
|
|
45
|
+
db.exec(`ALTER TABLE tasks ADD COLUMN pid INTEGER;`);
|
|
46
|
+
console.error('[TaskStore] Migration: Added pid column to existing database');
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
// Column already exists or other error - safe to ignore
|
|
50
|
+
if (!error.message?.includes('duplicate column')) {
|
|
51
|
+
console.error('[TaskStore] Migration note:', error.message);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// Prepared statements for better performance
|
|
55
|
+
const insertTaskStmt = db.prepare(`
|
|
56
|
+
INSERT INTO tasks (id, status, task_type, progress, started_at, updated_at)
|
|
57
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
58
|
+
`);
|
|
59
|
+
const updateTaskStmt = db.prepare(`
|
|
60
|
+
UPDATE tasks
|
|
61
|
+
SET status = ?, progress = ?, result = ?, error = ?, completed_at = ?, updated_at = ?, pid = ?
|
|
62
|
+
WHERE id = ?
|
|
63
|
+
`);
|
|
64
|
+
const getTaskStmt = db.prepare(`
|
|
65
|
+
SELECT * FROM tasks WHERE id = ?
|
|
66
|
+
`);
|
|
67
|
+
const getCompletedTasksStmt = db.prepare(`
|
|
68
|
+
SELECT * FROM tasks WHERE status IN ('completed', 'failed')
|
|
69
|
+
ORDER BY completed_at DESC
|
|
70
|
+
`);
|
|
71
|
+
const deleteTaskStmt = db.prepare(`
|
|
72
|
+
DELETE FROM tasks WHERE id = ?
|
|
73
|
+
`);
|
|
74
|
+
const deleteExpiredTasksStmt = db.prepare(`
|
|
75
|
+
DELETE FROM tasks
|
|
76
|
+
WHERE datetime(started_at, '+1 hour') < datetime('now')
|
|
77
|
+
`);
|
|
78
|
+
// ID counter - get max ID from database on startup
|
|
79
|
+
let taskIdCounter = TASK_ID_MIN;
|
|
80
|
+
const maxIdRow = db.prepare('SELECT MAX(id) as max_id FROM tasks').get();
|
|
81
|
+
if (maxIdRow.max_id && maxIdRow.max_id >= taskIdCounter) {
|
|
82
|
+
taskIdCounter = maxIdRow.max_id + 1;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Generate unique 5-digit task ID
|
|
86
|
+
* Wraps around from TASK_ID_MAX back to TASK_ID_MIN
|
|
87
|
+
*/
|
|
88
|
+
export function generateTaskId() {
|
|
89
|
+
const id = taskIdCounter;
|
|
90
|
+
taskIdCounter++;
|
|
91
|
+
if (taskIdCounter > TASK_ID_MAX) {
|
|
92
|
+
taskIdCounter = TASK_ID_MIN;
|
|
93
|
+
}
|
|
94
|
+
return id;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Create a new task in pending state
|
|
98
|
+
*/
|
|
99
|
+
export function createTask(taskType) {
|
|
100
|
+
const id = generateTaskId();
|
|
101
|
+
const now = new Date().toISOString();
|
|
102
|
+
const task = {
|
|
103
|
+
id,
|
|
104
|
+
status: 'pending',
|
|
105
|
+
task_type: taskType,
|
|
106
|
+
progress: 0,
|
|
107
|
+
started_at: now,
|
|
108
|
+
updated_at: now,
|
|
109
|
+
};
|
|
110
|
+
insertTaskStmt.run(id, task.status, task.task_type, task.progress, task.started_at, task.updated_at);
|
|
111
|
+
// Schedule cleanup after expiry (note: this only works if process stays alive)
|
|
112
|
+
setTimeout(() => {
|
|
113
|
+
deleteTaskStmt.run(id);
|
|
114
|
+
}, TASK_EXPIRY_MS);
|
|
115
|
+
return task;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Update task status
|
|
119
|
+
*/
|
|
120
|
+
export function updateTask(id, updates) {
|
|
121
|
+
const task = getTask(id);
|
|
122
|
+
if (!task)
|
|
123
|
+
return null;
|
|
124
|
+
// Merge updates
|
|
125
|
+
const updatedTask = { ...task, ...updates, updated_at: new Date().toISOString() };
|
|
126
|
+
updateTaskStmt.run(updatedTask.status, updatedTask.progress, updatedTask.result || null, updatedTask.error || null, updatedTask.completed_at || null, updatedTask.updated_at, updatedTask.pid || null, id);
|
|
127
|
+
return updatedTask;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Get task by ID
|
|
131
|
+
*/
|
|
132
|
+
export function getTask(id) {
|
|
133
|
+
const row = getTaskStmt.get(id);
|
|
134
|
+
if (!row)
|
|
135
|
+
return null;
|
|
136
|
+
return {
|
|
137
|
+
id: row.id,
|
|
138
|
+
status: row.status,
|
|
139
|
+
task_type: row.task_type,
|
|
140
|
+
progress: row.progress,
|
|
141
|
+
result: row.result || undefined,
|
|
142
|
+
error: row.error || undefined,
|
|
143
|
+
started_at: row.started_at,
|
|
144
|
+
completed_at: row.completed_at || undefined,
|
|
145
|
+
updated_at: row.updated_at,
|
|
146
|
+
pid: row.pid || undefined,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Get all completed or failed tasks
|
|
151
|
+
*/
|
|
152
|
+
export function getCompletedTasks() {
|
|
153
|
+
const rows = getCompletedTasksStmt.all();
|
|
154
|
+
return rows.map(row => ({
|
|
155
|
+
id: row.id,
|
|
156
|
+
status: row.status,
|
|
157
|
+
task_type: row.task_type,
|
|
158
|
+
progress: row.progress,
|
|
159
|
+
result: row.result || undefined,
|
|
160
|
+
error: row.error || undefined,
|
|
161
|
+
started_at: row.started_at,
|
|
162
|
+
completed_at: row.completed_at || undefined,
|
|
163
|
+
updated_at: row.updated_at,
|
|
164
|
+
pid: row.pid || undefined,
|
|
165
|
+
}));
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Delete expired tasks (older than 1 hour)
|
|
169
|
+
* Call this periodically to clean up old tasks
|
|
170
|
+
*/
|
|
171
|
+
export function cleanupExpiredTasks() {
|
|
172
|
+
const result = deleteExpiredTasksStmt.run();
|
|
173
|
+
return result.changes;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Close database connection (call on shutdown)
|
|
177
|
+
*/
|
|
178
|
+
export function closeDatabase() {
|
|
179
|
+
db.close();
|
|
180
|
+
}
|
|
181
|
+
// Cleanup expired tasks and orphaned temp files on startup
|
|
182
|
+
cleanupExpiredTasks();
|
|
183
|
+
cleanupOrphanedTempFiles();
|
|
184
|
+
// Periodic cleanup at configured interval
|
|
185
|
+
setInterval(() => {
|
|
186
|
+
const deleted = cleanupExpiredTasks();
|
|
187
|
+
if (deleted > 0) {
|
|
188
|
+
console.error(`[TaskStore] Cleaned up ${deleted} expired tasks`);
|
|
189
|
+
}
|
|
190
|
+
}, CLEANUP_INTERVAL_MS);
|
|
191
|
+
//# sourceMappingURL=task-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-store.js","sourceRoot":"","sources":["../../src/tools/task-store.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gemini-helper-friend",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"description": "Your autonomous AI helper that works on your codebase using Gemini CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -48,6 +48,8 @@
|
|
|
48
48
|
],
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@modelcontextprotocol/sdk": "^0.5.0",
|
|
51
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
52
|
+
"better-sqlite3": "^12.5.0",
|
|
51
53
|
"yaml": "^2.3.4",
|
|
52
54
|
"zod": "^3.25.76",
|
|
53
55
|
"zod-to-json-schema": "^3.24.6"
|