@sylix/coworker 1.5.3 → 2.0.1
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/README.md +57 -164
- package/dist/agents/SubagentLoader.d.ts +59 -0
- package/dist/agents/SubagentLoader.d.ts.map +1 -0
- package/dist/agents/SubagentLoader.js +140 -0
- package/dist/agents/SubagentLoader.js.map +1 -0
- package/dist/agents/SubagentRunner.d.ts +15 -0
- package/dist/agents/SubagentRunner.d.ts.map +1 -0
- package/dist/agents/SubagentRunner.js +116 -0
- package/dist/agents/SubagentRunner.js.map +1 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +24 -51
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/slash/config.d.ts.map +1 -1
- package/dist/commands/slash/config.js +15 -0
- package/dist/commands/slash/config.js.map +1 -1
- package/dist/commands/slash/context.d.ts.map +1 -1
- package/dist/commands/slash/context.js +31 -0
- package/dist/commands/slash/context.js.map +1 -1
- package/dist/commands/slash/core.d.ts.map +1 -1
- package/dist/commands/slash/core.js +33 -4
- package/dist/commands/slash/core.js.map +1 -1
- package/dist/commands/slash/registry.d.ts.map +1 -1
- package/dist/commands/slash/registry.js +2 -0
- package/dist/commands/slash/registry.js.map +1 -1
- package/dist/commands/slash/session.d.ts.map +1 -1
- package/dist/commands/slash/session.js +97 -44
- package/dist/commands/slash/session.js.map +1 -1
- package/dist/commands/slash/snapshot.d.ts +3 -0
- package/dist/commands/slash/snapshot.d.ts.map +1 -0
- package/dist/commands/slash/snapshot.js +144 -0
- package/dist/commands/slash/snapshot.js.map +1 -0
- package/dist/config/SettingsManager.d.ts +2 -0
- package/dist/config/SettingsManager.d.ts.map +1 -1
- package/dist/config/SettingsManager.js +7 -0
- package/dist/config/SettingsManager.js.map +1 -1
- package/dist/core/CoWorkerAgent.d.ts +32 -0
- package/dist/core/CoWorkerAgent.d.ts.map +1 -1
- package/dist/core/CoWorkerAgent.js +414 -71
- package/dist/core/CoWorkerAgent.js.map +1 -1
- package/dist/hooks/HookEngine.d.ts +115 -0
- package/dist/hooks/HookEngine.d.ts.map +1 -0
- package/dist/hooks/HookEngine.js +220 -0
- package/dist/hooks/HookEngine.js.map +1 -0
- package/dist/memory/AutoMemory.d.ts +55 -0
- package/dist/memory/AutoMemory.d.ts.map +1 -0
- package/dist/memory/AutoMemory.js +185 -0
- package/dist/memory/AutoMemory.js.map +1 -0
- package/dist/permissions/PermissionInterceptor.d.ts +55 -7
- package/dist/permissions/PermissionInterceptor.d.ts.map +1 -1
- package/dist/permissions/PermissionInterceptor.js +170 -22
- package/dist/permissions/PermissionInterceptor.js.map +1 -1
- package/dist/session/SessionManager.d.ts +53 -10
- package/dist/session/SessionManager.d.ts.map +1 -1
- package/dist/session/SessionManager.js +127 -55
- package/dist/session/SessionManager.js.map +1 -1
- package/dist/session/db.d.ts +81 -0
- package/dist/session/db.d.ts.map +1 -0
- package/dist/session/db.js +268 -0
- package/dist/session/db.js.map +1 -0
- package/dist/skills/HookAndSkillManager.d.ts +7 -5
- package/dist/skills/HookAndSkillManager.d.ts.map +1 -1
- package/dist/skills/HookAndSkillManager.js +30 -56
- package/dist/skills/HookAndSkillManager.js.map +1 -1
- package/dist/snapshot/SnapshotManager.d.ts +94 -0
- package/dist/snapshot/SnapshotManager.d.ts.map +1 -0
- package/dist/snapshot/SnapshotManager.js +260 -0
- package/dist/snapshot/SnapshotManager.js.map +1 -0
- package/dist/tools/LSPTool.d.ts +18 -0
- package/dist/tools/LSPTool.d.ts.map +1 -0
- package/dist/tools/LSPTool.js +137 -0
- package/dist/tools/LSPTool.js.map +1 -0
- package/dist/tools/NativeTools.d.ts +4 -3
- package/dist/tools/NativeTools.d.ts.map +1 -1
- package/dist/tools/NativeTools.js +66 -19
- package/dist/tools/NativeTools.js.map +1 -1
- package/dist/tools/Schemas.d.ts +69 -0
- package/dist/tools/Schemas.d.ts.map +1 -1
- package/dist/tools/Schemas.js +32 -0
- package/dist/tools/Schemas.js.map +1 -1
- package/dist/utils/contextManager.d.ts +1 -1
- package/dist/utils/contextManager.d.ts.map +1 -1
- package/dist/utils/output.d.ts +3 -6
- package/dist/utils/output.d.ts.map +1 -1
- package/dist/utils/output.js +44 -39
- package/dist/utils/output.js.map +1 -1
- package/dist/utils/systemPrompt.d.ts.map +1 -1
- package/dist/utils/systemPrompt.js +1 -0
- package/dist/utils/systemPrompt.js.map +1 -1
- package/dist/utils/update.d.ts +9 -0
- package/dist/utils/update.d.ts.map +1 -0
- package/dist/utils/update.js +108 -0
- package/dist/utils/update.js.map +1 -0
- package/package.json +3 -1
|
@@ -34,15 +34,15 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.SessionManager = void 0;
|
|
37
|
-
const
|
|
38
|
-
const path = __importStar(require("path"));
|
|
37
|
+
const db = __importStar(require("./db"));
|
|
39
38
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
39
|
+
* SessionManager — manages conversation state backed by SQLite.
|
|
40
|
+
*
|
|
41
|
+
* Backwards-compatible API: code that calls appendMessage(), saveCheckpoint(),
|
|
42
|
+
* loadCheckpoint() still works, but now persists to ~/.coworker/coworker.db.
|
|
42
43
|
*/
|
|
43
44
|
class SessionManager {
|
|
44
45
|
constructor(sessionId) {
|
|
45
|
-
this.baseDir = '.coworker/sessions';
|
|
46
46
|
this.currentSessionId = sessionId;
|
|
47
47
|
this.state = {
|
|
48
48
|
id: sessionId,
|
|
@@ -52,81 +52,153 @@ class SessionManager {
|
|
|
52
52
|
createdAt: new Date().toISOString()
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
getCheckpointsDir() {
|
|
59
|
-
return path.join(process.cwd(), this.baseDir, this.currentSessionId, 'checkpoints');
|
|
60
|
-
}
|
|
55
|
+
/**
|
|
56
|
+
* Load session from SQLite. Creates a new session if none exists.
|
|
57
|
+
*/
|
|
61
58
|
async loadCheckpoint() {
|
|
62
59
|
try {
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
60
|
+
const session = db.getSession(this.currentSessionId);
|
|
61
|
+
if (session) {
|
|
62
|
+
// Load existing session
|
|
63
|
+
this.state.cwd = session.cwd;
|
|
64
|
+
this.state.summary = session.summary;
|
|
65
|
+
this.state.createdAt = session.created_at;
|
|
66
|
+
// Load messages
|
|
67
|
+
const rows = db.getMessages(this.currentSessionId);
|
|
68
|
+
this.state.messages = rows.map(r => ({
|
|
69
|
+
role: r.role,
|
|
70
|
+
content: r.content,
|
|
71
|
+
tool_call_id: r.tool_call_id || undefined,
|
|
72
|
+
}));
|
|
73
|
+
if (process.env.CW_VERBOSE) {
|
|
74
|
+
console.log(`[Session] Resumed: ${this.currentSessionId} (${this.state.messages.length} messages)`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
// Create new session in DB
|
|
79
|
+
db.createSession(this.currentSessionId, this.state.cwd);
|
|
80
|
+
if (process.env.CW_VERBOSE)
|
|
81
|
+
console.log(`[Session] New: ${this.currentSessionId}`);
|
|
82
|
+
}
|
|
68
83
|
}
|
|
69
|
-
catch {
|
|
84
|
+
catch (e) {
|
|
70
85
|
if (process.env.CW_VERBOSE)
|
|
71
|
-
console.
|
|
72
|
-
|
|
86
|
+
console.error(`[Session] Load error: ${e.message}`);
|
|
87
|
+
// Fallback: start fresh
|
|
73
88
|
}
|
|
74
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Persist current state to SQLite.
|
|
92
|
+
* Called after major state changes (compaction, summary update).
|
|
93
|
+
*/
|
|
75
94
|
async saveCheckpoint() {
|
|
76
95
|
try {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
96
|
+
db.updateSession(this.currentSessionId, {
|
|
97
|
+
summary: this.state.summary,
|
|
98
|
+
});
|
|
80
99
|
}
|
|
81
|
-
catch (
|
|
100
|
+
catch (e) {
|
|
82
101
|
if (process.env.CW_VERBOSE)
|
|
83
|
-
console.error(`[
|
|
102
|
+
console.error(`[Session] Save error: ${e.message}`);
|
|
84
103
|
}
|
|
85
104
|
}
|
|
86
105
|
/**
|
|
87
|
-
*
|
|
106
|
+
* Append a message and persist to SQLite.
|
|
88
107
|
*/
|
|
89
108
|
async appendMessage(message) {
|
|
90
109
|
this.state.messages.push(message);
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
* Token buffer protection. Roughly estimates 4 chars = 1 token.
|
|
96
|
-
* If > 12000 tokens (approx 48000 chars), we snip the old context and summarize.
|
|
97
|
-
*/
|
|
98
|
-
async rollupMemory() {
|
|
99
|
-
const MAX_CHAR_LIMIT = 48000;
|
|
100
|
-
// Very coarse approximation
|
|
101
|
-
const totalChars = this.state.messages.reduce((acc, curr) => acc + curr.content.length, 0);
|
|
102
|
-
if (totalChars > MAX_CHAR_LIMIT) {
|
|
110
|
+
try {
|
|
111
|
+
db.appendMessage(this.currentSessionId, message.role, message.content, undefined, message.tool_call_id);
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
103
114
|
if (process.env.CW_VERBOSE)
|
|
104
|
-
console.
|
|
105
|
-
const messagesToKeep = 20;
|
|
106
|
-
const retainedMessages = this.state.messages.slice(-messagesToKeep);
|
|
107
|
-
this.state.messages = retainedMessages;
|
|
108
|
-
this.state.summary += `\n[COMPRESSED] Context reset to last 20 turns.`;
|
|
109
|
-
await this.saveCheckpoint();
|
|
115
|
+
console.error(`[Session] Append error: ${e.message}`);
|
|
110
116
|
}
|
|
111
117
|
}
|
|
112
118
|
/**
|
|
113
|
-
*
|
|
119
|
+
* Replace all messages with a compacted summary.
|
|
120
|
+
* Used by /compact and auto-compaction.
|
|
114
121
|
*/
|
|
115
|
-
async
|
|
122
|
+
async compactMessages(summary) {
|
|
123
|
+
this.state.messages = [
|
|
124
|
+
{ role: 'assistant', content: `[conversation compressed]\n\n${summary}` }
|
|
125
|
+
];
|
|
116
126
|
try {
|
|
117
|
-
|
|
118
|
-
const content = await fs.readFile(absoluteTarget, 'utf8');
|
|
119
|
-
const checkpointsDir = this.getCheckpointsDir();
|
|
120
|
-
await fs.mkdir(checkpointsDir, { recursive: true });
|
|
121
|
-
const sanitizedName = path.basename(absoluteTarget);
|
|
122
|
-
const backupPath = path.join(checkpointsDir, `${Date.now()}_${sanitizedName}.bak`);
|
|
123
|
-
await fs.writeFile(backupPath, content, 'utf8');
|
|
124
|
-
if (process.env.CW_VERBOSE)
|
|
125
|
-
console.log(`[CoWorker Safety] Checkpointed ${targetFilePath} before mutation.`);
|
|
127
|
+
db.replaceWithCompaction(this.currentSessionId, summary);
|
|
126
128
|
}
|
|
127
129
|
catch (e) {
|
|
128
|
-
|
|
130
|
+
if (process.env.CW_VERBOSE)
|
|
131
|
+
console.error(`[Session] Compaction error: ${e.message}`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* List recent sessions for the current CWD.
|
|
136
|
+
*/
|
|
137
|
+
static listRecentSessions(cwd, limit) {
|
|
138
|
+
return db.listSessions(cwd, limit);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Search sessions by content.
|
|
142
|
+
*/
|
|
143
|
+
static searchSessions(query, limit) {
|
|
144
|
+
return db.searchSessions(query, limit);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Fork the current session into a new one.
|
|
148
|
+
*/
|
|
149
|
+
async forkSession(newId) {
|
|
150
|
+
db.forkSession(this.currentSessionId, newId);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Archive the current session.
|
|
154
|
+
*/
|
|
155
|
+
async archiveSession() {
|
|
156
|
+
db.updateSession(this.currentSessionId, { archived: 1 });
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Get message count.
|
|
160
|
+
*/
|
|
161
|
+
getMessageCount() {
|
|
162
|
+
return db.messageCount(this.currentSessionId);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* 2-PHASE COMPACTION (Vision 2.0)
|
|
166
|
+
* 1. Keeps the last 'keepRaw' messages (defaults to 10) untouched.
|
|
167
|
+
* 2. For messages older than that, it finds large tool outputs and marks them for summarization.
|
|
168
|
+
* 3. Replaces old tool outputs with concise summaries to save tokens while keeping context history.
|
|
169
|
+
*/
|
|
170
|
+
async performTwoPhaseCompaction(summarizer, keepRaw = 10) {
|
|
171
|
+
const messages = db.getMessages(this.currentSessionId);
|
|
172
|
+
if (messages.length <= keepRaw)
|
|
173
|
+
return { savedTokens: 0 };
|
|
174
|
+
const oldMessages = messages.slice(0, messages.length - keepRaw);
|
|
175
|
+
let totalSaved = 0;
|
|
176
|
+
for (const msg of oldMessages) {
|
|
177
|
+
if (msg.role === 'tool' && msg.content.length > 500) {
|
|
178
|
+
const originalTokens = Math.floor(msg.content.length / 4);
|
|
179
|
+
const summary = await summarizer(msg.content);
|
|
180
|
+
db.updateMessageContent(msg.id, `[Tool Summary]: ${summary}`);
|
|
181
|
+
totalSaved += originalTokens - Math.floor(summary.length / 4);
|
|
182
|
+
}
|
|
129
183
|
}
|
|
184
|
+
// Refresh local state
|
|
185
|
+
await this.loadCheckpoint();
|
|
186
|
+
return { savedTokens: Math.max(0, totalSaved) };
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Legacy API: Token buffer protection.
|
|
190
|
+
* Now just prunes SQLite if messages exceed threshold.
|
|
191
|
+
*/
|
|
192
|
+
async rollupMemory() {
|
|
193
|
+
// Auto-rollup is handled by compaction in CoWorkerAgent
|
|
194
|
+
// This is kept for backwards compatibility
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Legacy API: Backup file before mutation.
|
|
198
|
+
* Now handled by SnapshotManager.
|
|
199
|
+
*/
|
|
200
|
+
async backupFileBeforeMutation(targetFilePath) {
|
|
201
|
+
// No-op: SnapshotManager handles this now
|
|
130
202
|
}
|
|
131
203
|
}
|
|
132
204
|
exports.SessionManager = SessionManager;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionManager.js","sourceRoot":"","sources":["../../src/session/SessionManager.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"SessionManager.js","sourceRoot":"","sources":["../../src/session/SessionManager.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,yCAA2B;AAyB3B;;;;;GAKG;AACH,MAAa,cAAc;IAIzB,YAAY,SAAiB;QAC3B,IAAI,CAAC,gBAAgB,GAAG,SAAS,CAAC;QAClC,IAAI,CAAC,KAAK,GAAG;YACX,EAAE,EAAE,SAAS;YACb,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;YAClB,OAAO,EAAE,EAAE;YACX,QAAQ,EAAE,EAAE;YACZ,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc;QAClB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YACrD,IAAI,OAAO,EAAE,CAAC;gBACZ,wBAAwB;gBACxB,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;gBAC7B,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;gBACrC,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC;gBAE1C,gBAAgB;gBAChB,MAAM,IAAI,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;gBACnD,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;oBACnC,IAAI,EAAE,CAAC,CAAC,IAA2B;oBACnC,OAAO,EAAE,CAAC,CAAC,OAAO;oBAClB,YAAY,EAAE,CAAC,CAAC,YAAY,IAAI,SAAS;iBAC1C,CAAC,CAAC,CAAC;gBAEJ,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC;oBAC3B,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,CAAC,gBAAgB,KAAK,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,YAAY,CAAC,CAAC;gBACtG,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,2BAA2B;gBAC3B,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,gBAAgB,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBACxD,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU;oBAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;YACrF,CAAC;QACH,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU;gBAAE,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;YAChF,wBAAwB;QAC1B,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,cAAc;QAClB,IAAI,CAAC;YACH,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,gBAAgB,EAAE;gBACtC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO;aAC5B,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU;gBAAE,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QAClF,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa,CAAC,OAAoB;QACtC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAClC,IAAI,CAAC;YACH,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,gBAAgB,EACrB,OAAO,CAAC,IAAI,EACZ,OAAO,CAAC,OAAO,EACf,SAAS,EACT,OAAO,CAAC,YAAY,CACrB,CAAC;QACJ,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU;gBAAE,OAAO,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QACpF,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,eAAe,CAAC,OAAe;QACnC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG;YACpB,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,gCAAgC,OAAO,EAAE,EAAE;SAC1E,CAAC;QACF,IAAI,CAAC;YACH,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;QAC3D,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU;gBAAE,OAAO,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QACxF,CAAC;IACH,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,kBAAkB,CAAC,GAAY,EAAE,KAAc;QACpD,OAAO,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,KAAa,EAAE,KAAc;QACjD,OAAO,EAAE,CAAC,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CAAC,KAAa;QAC7B,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;IAC/C,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc;QAClB,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED;;OAEG;IACH,eAAe;QACb,OAAO,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAChD,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,yBAAyB,CAAC,UAAgD,EAAE,OAAO,GAAG,EAAE;QAC5F,MAAM,QAAQ,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QACvD,IAAI,QAAQ,CAAC,MAAM,IAAI,OAAO;YAAE,OAAO,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;QAE1D,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC;QACjE,IAAI,UAAU,GAAG,CAAC,CAAC;QAEnB,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;YAC9B,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;gBACpD,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gBAC1D,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBAE9C,EAAE,CAAC,oBAAoB,CAAC,GAAG,CAAC,EAAE,EAAE,mBAAmB,OAAO,EAAE,CAAC,CAAC;gBAC9D,UAAU,IAAI,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAChE,CAAC;QACH,CAAC;QAED,sBAAsB;QACtB,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAC5B,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE,CAAC;IAClD,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,YAAY;QAChB,wDAAwD;QACxD,2CAA2C;IAC7C,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,wBAAwB,CAAC,cAAsB;QACnD,0CAA0C;IAC5C,CAAC;CACF;AA/KD,wCA+KC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
/**
|
|
3
|
+
* Get or create the singleton database connection.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getDB(): Database.Database;
|
|
6
|
+
export interface SessionRow {
|
|
7
|
+
id: string;
|
|
8
|
+
cwd: string;
|
|
9
|
+
title: string;
|
|
10
|
+
summary: string;
|
|
11
|
+
created_at: string;
|
|
12
|
+
updated_at: string;
|
|
13
|
+
archived: number;
|
|
14
|
+
}
|
|
15
|
+
export interface MessageRow {
|
|
16
|
+
id: number;
|
|
17
|
+
session_id: string;
|
|
18
|
+
role: string;
|
|
19
|
+
content: string;
|
|
20
|
+
tool_calls: string | null;
|
|
21
|
+
tool_call_id: string | null;
|
|
22
|
+
created_at: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Create a new session.
|
|
26
|
+
*/
|
|
27
|
+
export declare function createSession(id: string, cwd: string): void;
|
|
28
|
+
/**
|
|
29
|
+
* Update session metadata.
|
|
30
|
+
*/
|
|
31
|
+
export declare function updateSession(id: string, fields: Partial<Pick<SessionRow, 'title' | 'summary' | 'archived'>>): void;
|
|
32
|
+
/**
|
|
33
|
+
* Get a session by ID.
|
|
34
|
+
*/
|
|
35
|
+
export declare function getSession(id: string): SessionRow | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* List recent sessions for a CWD.
|
|
38
|
+
*/
|
|
39
|
+
export declare function listSessions(cwd?: string, limit?: number): SessionRow[];
|
|
40
|
+
/**
|
|
41
|
+
* Search sessions by content.
|
|
42
|
+
*/
|
|
43
|
+
export declare function searchSessions(query: string, limit?: number): SessionRow[];
|
|
44
|
+
/**
|
|
45
|
+
* Fork a session — copy all messages to a new session ID.
|
|
46
|
+
*/
|
|
47
|
+
export declare function forkSession(sourceId: string, newId: string): void;
|
|
48
|
+
/**
|
|
49
|
+
* Append a message to a session.
|
|
50
|
+
*/
|
|
51
|
+
export declare function appendMessage(sessionId: string, role: string, content: string, toolCalls?: any, toolCallId?: string): void;
|
|
52
|
+
/**
|
|
53
|
+
* Update message content (for summarization).
|
|
54
|
+
*/
|
|
55
|
+
export declare function updateMessageContent(id: number, content: string): void;
|
|
56
|
+
/**
|
|
57
|
+
* Get all messages for a session.
|
|
58
|
+
*/
|
|
59
|
+
export declare function getMessages(sessionId: string): MessageRow[];
|
|
60
|
+
/**
|
|
61
|
+
* Delete old messages (for compaction).
|
|
62
|
+
* Keeps the last N messages and deletes the rest.
|
|
63
|
+
*/
|
|
64
|
+
export declare function pruneMessages(sessionId: string, keepLast: number): number;
|
|
65
|
+
/**
|
|
66
|
+
* Replace all messages with a compacted summary.
|
|
67
|
+
*/
|
|
68
|
+
export declare function replaceWithCompaction(sessionId: string, summary: string): void;
|
|
69
|
+
/**
|
|
70
|
+
* Count messages in a session.
|
|
71
|
+
*/
|
|
72
|
+
export declare function messageCount(sessionId: string): number;
|
|
73
|
+
/**
|
|
74
|
+
* Delete a session and all its messages.
|
|
75
|
+
*/
|
|
76
|
+
export declare function deleteSession(id: string): void;
|
|
77
|
+
/**
|
|
78
|
+
* Close the database connection.
|
|
79
|
+
*/
|
|
80
|
+
export declare function closeDB(): void;
|
|
81
|
+
//# sourceMappingURL=db.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/session/db.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AActC;;GAEG;AACH,wBAAgB,KAAK,IAAI,QAAQ,CAAC,QAAQ,CAmBzC;AAqCD,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAG3D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,GAAG,SAAS,GAAG,UAAU,CAAC,CAAC,GAAG,IAAI,CAWnH;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAG7D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,UAAU,EAAE,CAQ3E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,UAAU,EAAE,CAS9E;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAajE;AAMD;;GAEG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,GAAG,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAO1H;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAGtE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,EAAE,CAI3D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQzE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAU9E;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAItD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAI9C;AAED;;GAEG;AACH,wBAAgB,OAAO,IAAI,IAAI,CAG9B"}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.getDB = getDB;
|
|
40
|
+
exports.createSession = createSession;
|
|
41
|
+
exports.updateSession = updateSession;
|
|
42
|
+
exports.getSession = getSession;
|
|
43
|
+
exports.listSessions = listSessions;
|
|
44
|
+
exports.searchSessions = searchSessions;
|
|
45
|
+
exports.forkSession = forkSession;
|
|
46
|
+
exports.appendMessage = appendMessage;
|
|
47
|
+
exports.updateMessageContent = updateMessageContent;
|
|
48
|
+
exports.getMessages = getMessages;
|
|
49
|
+
exports.pruneMessages = pruneMessages;
|
|
50
|
+
exports.replaceWithCompaction = replaceWithCompaction;
|
|
51
|
+
exports.messageCount = messageCount;
|
|
52
|
+
exports.deleteSession = deleteSession;
|
|
53
|
+
exports.closeDB = closeDB;
|
|
54
|
+
const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
|
|
55
|
+
const path = __importStar(require("path"));
|
|
56
|
+
const os = __importStar(require("os"));
|
|
57
|
+
const fs = __importStar(require("fs"));
|
|
58
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
59
|
+
// SQLITE SESSION DATABASE — Replaces JSON file sessions
|
|
60
|
+
// Location: ~/.coworker/coworker.db
|
|
61
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
62
|
+
const DB_PATH = path.join(os.homedir(), '.coworker', 'coworker.db');
|
|
63
|
+
let _db = null;
|
|
64
|
+
/**
|
|
65
|
+
* Get or create the singleton database connection.
|
|
66
|
+
*/
|
|
67
|
+
function getDB() {
|
|
68
|
+
if (_db)
|
|
69
|
+
return _db;
|
|
70
|
+
// Ensure directory exists
|
|
71
|
+
const dir = path.dirname(DB_PATH);
|
|
72
|
+
if (!fs.existsSync(dir)) {
|
|
73
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
74
|
+
}
|
|
75
|
+
_db = new better_sqlite3_1.default(DB_PATH);
|
|
76
|
+
// Enable WAL mode for better concurrent read/write performance
|
|
77
|
+
_db.pragma('journal_mode = WAL');
|
|
78
|
+
_db.pragma('foreign_keys = ON');
|
|
79
|
+
// Run migrations
|
|
80
|
+
migrate(_db);
|
|
81
|
+
return _db;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Database schema and migrations.
|
|
85
|
+
*/
|
|
86
|
+
function migrate(db) {
|
|
87
|
+
db.exec(`
|
|
88
|
+
CREATE TABLE IF NOT EXISTS sessions (
|
|
89
|
+
id TEXT PRIMARY KEY,
|
|
90
|
+
cwd TEXT NOT NULL,
|
|
91
|
+
title TEXT DEFAULT '',
|
|
92
|
+
summary TEXT DEFAULT '',
|
|
93
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
94
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
95
|
+
archived INTEGER DEFAULT 0
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
CREATE TABLE IF NOT EXISTS messages (
|
|
99
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
100
|
+
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
101
|
+
role TEXT NOT NULL,
|
|
102
|
+
content TEXT NOT NULL DEFAULT '',
|
|
103
|
+
tool_calls TEXT,
|
|
104
|
+
tool_call_id TEXT,
|
|
105
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
CREATE INDEX IF NOT EXISTS idx_messages_session ON messages(session_id);
|
|
109
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_cwd ON sessions(cwd);
|
|
110
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_updated ON sessions(updated_at DESC);
|
|
111
|
+
`);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Create a new session.
|
|
115
|
+
*/
|
|
116
|
+
function createSession(id, cwd) {
|
|
117
|
+
const db = getDB();
|
|
118
|
+
db.prepare(`INSERT INTO sessions (id, cwd) VALUES (?, ?)`).run(id, cwd);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Update session metadata.
|
|
122
|
+
*/
|
|
123
|
+
function updateSession(id, fields) {
|
|
124
|
+
const db = getDB();
|
|
125
|
+
const sets = ["updated_at = datetime('now')"];
|
|
126
|
+
const params = [];
|
|
127
|
+
if (fields.title !== undefined) {
|
|
128
|
+
sets.push('title = ?');
|
|
129
|
+
params.push(fields.title);
|
|
130
|
+
}
|
|
131
|
+
if (fields.summary !== undefined) {
|
|
132
|
+
sets.push('summary = ?');
|
|
133
|
+
params.push(fields.summary);
|
|
134
|
+
}
|
|
135
|
+
if (fields.archived !== undefined) {
|
|
136
|
+
sets.push('archived = ?');
|
|
137
|
+
params.push(fields.archived);
|
|
138
|
+
}
|
|
139
|
+
params.push(id);
|
|
140
|
+
db.prepare(`UPDATE sessions SET ${sets.join(', ')} WHERE id = ?`).run(...params);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Get a session by ID.
|
|
144
|
+
*/
|
|
145
|
+
function getSession(id) {
|
|
146
|
+
const db = getDB();
|
|
147
|
+
return db.prepare(`SELECT * FROM sessions WHERE id = ?`).get(id);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* List recent sessions for a CWD.
|
|
151
|
+
*/
|
|
152
|
+
function listSessions(cwd, limit = 20) {
|
|
153
|
+
const db = getDB();
|
|
154
|
+
if (cwd) {
|
|
155
|
+
return db.prepare(`SELECT * FROM sessions WHERE cwd = ? AND archived = 0 ORDER BY updated_at DESC LIMIT ?`)
|
|
156
|
+
.all(cwd, limit);
|
|
157
|
+
}
|
|
158
|
+
return db.prepare(`SELECT * FROM sessions WHERE archived = 0 ORDER BY updated_at DESC LIMIT ?`)
|
|
159
|
+
.all(limit);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Search sessions by content.
|
|
163
|
+
*/
|
|
164
|
+
function searchSessions(query, limit = 20) {
|
|
165
|
+
const db = getDB();
|
|
166
|
+
const like = `%${query}%`;
|
|
167
|
+
return db.prepare(`
|
|
168
|
+
SELECT DISTINCT s.* FROM sessions s
|
|
169
|
+
LEFT JOIN messages m ON m.session_id = s.id
|
|
170
|
+
WHERE s.title LIKE ? OR s.summary LIKE ? OR m.content LIKE ?
|
|
171
|
+
ORDER BY s.updated_at DESC LIMIT ?
|
|
172
|
+
`).all(like, like, like, limit);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Fork a session — copy all messages to a new session ID.
|
|
176
|
+
*/
|
|
177
|
+
function forkSession(sourceId, newId) {
|
|
178
|
+
const db = getDB();
|
|
179
|
+
const source = getSession(sourceId);
|
|
180
|
+
if (!source)
|
|
181
|
+
throw new Error(`Session ${sourceId} not found`);
|
|
182
|
+
db.prepare(`INSERT INTO sessions (id, cwd, title, summary) VALUES (?, ?, ?, ?)`)
|
|
183
|
+
.run(newId, source.cwd, `Fork of ${source.title || sourceId}`, source.summary);
|
|
184
|
+
db.prepare(`
|
|
185
|
+
INSERT INTO messages (session_id, role, content, tool_calls, tool_call_id)
|
|
186
|
+
SELECT ?, role, content, tool_calls, tool_call_id
|
|
187
|
+
FROM messages WHERE session_id = ?
|
|
188
|
+
`).run(newId, sourceId);
|
|
189
|
+
}
|
|
190
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
191
|
+
// MESSAGE QUERIES
|
|
192
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
193
|
+
/**
|
|
194
|
+
* Append a message to a session.
|
|
195
|
+
*/
|
|
196
|
+
function appendMessage(sessionId, role, content, toolCalls, toolCallId) {
|
|
197
|
+
const db = getDB();
|
|
198
|
+
db.prepare(`INSERT INTO messages (session_id, role, content, tool_calls, tool_call_id) VALUES (?, ?, ?, ?, ?)`)
|
|
199
|
+
.run(sessionId, role, content, toolCalls ? JSON.stringify(toolCalls) : null, toolCallId || null);
|
|
200
|
+
// Update session timestamp
|
|
201
|
+
db.prepare(`UPDATE sessions SET updated_at = datetime('now') WHERE id = ?`).run(sessionId);
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Update message content (for summarization).
|
|
205
|
+
*/
|
|
206
|
+
function updateMessageContent(id, content) {
|
|
207
|
+
const db = getDB();
|
|
208
|
+
db.prepare(`UPDATE messages SET content = ? WHERE id = ?`).run(content, id);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Get all messages for a session.
|
|
212
|
+
*/
|
|
213
|
+
function getMessages(sessionId) {
|
|
214
|
+
const db = getDB();
|
|
215
|
+
return db.prepare(`SELECT * FROM messages WHERE session_id = ? ORDER BY id ASC`)
|
|
216
|
+
.all(sessionId);
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Delete old messages (for compaction).
|
|
220
|
+
* Keeps the last N messages and deletes the rest.
|
|
221
|
+
*/
|
|
222
|
+
function pruneMessages(sessionId, keepLast) {
|
|
223
|
+
const db = getDB();
|
|
224
|
+
const result = db.prepare(`
|
|
225
|
+
DELETE FROM messages WHERE session_id = ? AND id NOT IN (
|
|
226
|
+
SELECT id FROM messages WHERE session_id = ? ORDER BY id DESC LIMIT ?
|
|
227
|
+
)
|
|
228
|
+
`).run(sessionId, sessionId, keepLast);
|
|
229
|
+
return result.changes;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Replace all messages with a compacted summary.
|
|
233
|
+
*/
|
|
234
|
+
function replaceWithCompaction(sessionId, summary) {
|
|
235
|
+
const db = getDB();
|
|
236
|
+
const tx = db.transaction(() => {
|
|
237
|
+
db.prepare(`DELETE FROM messages WHERE session_id = ?`).run(sessionId);
|
|
238
|
+
db.prepare(`INSERT INTO messages (session_id, role, content) VALUES (?, 'assistant', ?)`)
|
|
239
|
+
.run(sessionId, `[conversation compressed]\n\n${summary}`);
|
|
240
|
+
db.prepare(`UPDATE sessions SET summary = ?, updated_at = datetime('now') WHERE id = ?`)
|
|
241
|
+
.run(summary, sessionId);
|
|
242
|
+
});
|
|
243
|
+
tx();
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Count messages in a session.
|
|
247
|
+
*/
|
|
248
|
+
function messageCount(sessionId) {
|
|
249
|
+
const db = getDB();
|
|
250
|
+
const row = db.prepare(`SELECT COUNT(*) as cnt FROM messages WHERE session_id = ?`).get(sessionId);
|
|
251
|
+
return row?.cnt || 0;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Delete a session and all its messages.
|
|
255
|
+
*/
|
|
256
|
+
function deleteSession(id) {
|
|
257
|
+
const db = getDB();
|
|
258
|
+
db.prepare(`DELETE FROM messages WHERE session_id = ?`).run(id);
|
|
259
|
+
db.prepare(`DELETE FROM sessions WHERE id = ?`).run(id);
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Close the database connection.
|
|
263
|
+
*/
|
|
264
|
+
function closeDB() {
|
|
265
|
+
_db?.close();
|
|
266
|
+
_db = null;
|
|
267
|
+
}
|
|
268
|
+
//# sourceMappingURL=db.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/session/db.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { HookEngine } from '../hooks/HookEngine';
|
|
1
2
|
export interface Skill {
|
|
2
3
|
name: string;
|
|
3
4
|
description: string;
|
|
@@ -24,14 +25,14 @@ export interface DiagnosticResult {
|
|
|
24
25
|
* This mirrors CoWorker's PostToolUse hook system.
|
|
25
26
|
*/
|
|
26
27
|
export declare class HookAndSkillManager {
|
|
27
|
-
private events;
|
|
28
28
|
loadedSkills: Map<string, Skill>;
|
|
29
|
-
preToolHooks: HookRegexCommand[];
|
|
30
|
-
postToolHooks: HookRegexCommand[];
|
|
31
29
|
lastDiagnostic: DiagnosticResult | null;
|
|
32
30
|
activeSkill: string | null;
|
|
33
31
|
constructor();
|
|
34
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Register internal CoWorker hooks (like Diagnostics) into the HookEngine.
|
|
34
|
+
*/
|
|
35
|
+
registerHooks(engine: HookEngine): void;
|
|
35
36
|
/**
|
|
36
37
|
* Runs the appropriate diagnostic/linter based on file extension.
|
|
37
38
|
* Returns errors if any are found; these get injected into the LLM context.
|
|
@@ -44,11 +45,12 @@ export declare class HookAndSkillManager {
|
|
|
44
45
|
runManualDiagnostics(filePath: string): Promise<string>;
|
|
45
46
|
/**
|
|
46
47
|
* Fired before the main CoWorker agent loop executes an LLM-requested tool.
|
|
48
|
+
* @deprecated Use hookEngine.fireBlocking('PreToolUse', ...)
|
|
47
49
|
*/
|
|
48
50
|
firePreToolHook(toolName: string, args: Record<string, any>): Promise<void>;
|
|
49
51
|
/**
|
|
50
52
|
* Fired after the tool completes execution.
|
|
51
|
-
*
|
|
53
|
+
* @deprecated Use hookEngine.fire('PostToolUse', ...)
|
|
52
54
|
*/
|
|
53
55
|
firePostToolHook(toolName: string, result: string, args?: Record<string, any>): Promise<void>;
|
|
54
56
|
/**
|