@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.
Files changed (93) hide show
  1. package/README.md +57 -164
  2. package/dist/agents/SubagentLoader.d.ts +59 -0
  3. package/dist/agents/SubagentLoader.d.ts.map +1 -0
  4. package/dist/agents/SubagentLoader.js +140 -0
  5. package/dist/agents/SubagentLoader.js.map +1 -0
  6. package/dist/agents/SubagentRunner.d.ts +15 -0
  7. package/dist/agents/SubagentRunner.d.ts.map +1 -0
  8. package/dist/agents/SubagentRunner.js +116 -0
  9. package/dist/agents/SubagentRunner.js.map +1 -0
  10. package/dist/cli/index.d.ts.map +1 -1
  11. package/dist/cli/index.js +24 -51
  12. package/dist/cli/index.js.map +1 -1
  13. package/dist/commands/slash/config.d.ts.map +1 -1
  14. package/dist/commands/slash/config.js +15 -0
  15. package/dist/commands/slash/config.js.map +1 -1
  16. package/dist/commands/slash/context.d.ts.map +1 -1
  17. package/dist/commands/slash/context.js +31 -0
  18. package/dist/commands/slash/context.js.map +1 -1
  19. package/dist/commands/slash/core.d.ts.map +1 -1
  20. package/dist/commands/slash/core.js +33 -4
  21. package/dist/commands/slash/core.js.map +1 -1
  22. package/dist/commands/slash/registry.d.ts.map +1 -1
  23. package/dist/commands/slash/registry.js +2 -0
  24. package/dist/commands/slash/registry.js.map +1 -1
  25. package/dist/commands/slash/session.d.ts.map +1 -1
  26. package/dist/commands/slash/session.js +97 -44
  27. package/dist/commands/slash/session.js.map +1 -1
  28. package/dist/commands/slash/snapshot.d.ts +3 -0
  29. package/dist/commands/slash/snapshot.d.ts.map +1 -0
  30. package/dist/commands/slash/snapshot.js +144 -0
  31. package/dist/commands/slash/snapshot.js.map +1 -0
  32. package/dist/config/SettingsManager.d.ts +2 -0
  33. package/dist/config/SettingsManager.d.ts.map +1 -1
  34. package/dist/config/SettingsManager.js +7 -0
  35. package/dist/config/SettingsManager.js.map +1 -1
  36. package/dist/core/CoWorkerAgent.d.ts +32 -0
  37. package/dist/core/CoWorkerAgent.d.ts.map +1 -1
  38. package/dist/core/CoWorkerAgent.js +414 -71
  39. package/dist/core/CoWorkerAgent.js.map +1 -1
  40. package/dist/hooks/HookEngine.d.ts +115 -0
  41. package/dist/hooks/HookEngine.d.ts.map +1 -0
  42. package/dist/hooks/HookEngine.js +220 -0
  43. package/dist/hooks/HookEngine.js.map +1 -0
  44. package/dist/memory/AutoMemory.d.ts +55 -0
  45. package/dist/memory/AutoMemory.d.ts.map +1 -0
  46. package/dist/memory/AutoMemory.js +185 -0
  47. package/dist/memory/AutoMemory.js.map +1 -0
  48. package/dist/permissions/PermissionInterceptor.d.ts +55 -7
  49. package/dist/permissions/PermissionInterceptor.d.ts.map +1 -1
  50. package/dist/permissions/PermissionInterceptor.js +170 -22
  51. package/dist/permissions/PermissionInterceptor.js.map +1 -1
  52. package/dist/session/SessionManager.d.ts +53 -10
  53. package/dist/session/SessionManager.d.ts.map +1 -1
  54. package/dist/session/SessionManager.js +127 -55
  55. package/dist/session/SessionManager.js.map +1 -1
  56. package/dist/session/db.d.ts +81 -0
  57. package/dist/session/db.d.ts.map +1 -0
  58. package/dist/session/db.js +268 -0
  59. package/dist/session/db.js.map +1 -0
  60. package/dist/skills/HookAndSkillManager.d.ts +7 -5
  61. package/dist/skills/HookAndSkillManager.d.ts.map +1 -1
  62. package/dist/skills/HookAndSkillManager.js +30 -56
  63. package/dist/skills/HookAndSkillManager.js.map +1 -1
  64. package/dist/snapshot/SnapshotManager.d.ts +94 -0
  65. package/dist/snapshot/SnapshotManager.d.ts.map +1 -0
  66. package/dist/snapshot/SnapshotManager.js +260 -0
  67. package/dist/snapshot/SnapshotManager.js.map +1 -0
  68. package/dist/tools/LSPTool.d.ts +18 -0
  69. package/dist/tools/LSPTool.d.ts.map +1 -0
  70. package/dist/tools/LSPTool.js +137 -0
  71. package/dist/tools/LSPTool.js.map +1 -0
  72. package/dist/tools/NativeTools.d.ts +4 -3
  73. package/dist/tools/NativeTools.d.ts.map +1 -1
  74. package/dist/tools/NativeTools.js +66 -19
  75. package/dist/tools/NativeTools.js.map +1 -1
  76. package/dist/tools/Schemas.d.ts +69 -0
  77. package/dist/tools/Schemas.d.ts.map +1 -1
  78. package/dist/tools/Schemas.js +32 -0
  79. package/dist/tools/Schemas.js.map +1 -1
  80. package/dist/utils/contextManager.d.ts +1 -1
  81. package/dist/utils/contextManager.d.ts.map +1 -1
  82. package/dist/utils/output.d.ts +3 -6
  83. package/dist/utils/output.d.ts.map +1 -1
  84. package/dist/utils/output.js +44 -39
  85. package/dist/utils/output.js.map +1 -1
  86. package/dist/utils/systemPrompt.d.ts.map +1 -1
  87. package/dist/utils/systemPrompt.js +1 -0
  88. package/dist/utils/systemPrompt.js.map +1 -1
  89. package/dist/utils/update.d.ts +9 -0
  90. package/dist/utils/update.d.ts.map +1 -0
  91. package/dist/utils/update.js +108 -0
  92. package/dist/utils/update.js.map +1 -0
  93. 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 fs = __importStar(require("fs/promises"));
38
- const path = __importStar(require("path"));
37
+ const db = __importStar(require("./db"));
39
38
  /**
40
- * Phase 2 & 4: Session Checkpointing and Token Resuming
41
- * Fully implemented to write memory snapshots mapped by session ID.
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
- getSessionFilePath() {
56
- return path.join(process.cwd(), this.baseDir, `${this.currentSessionId}.json`);
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 dbPath = this.getSessionFilePath();
64
- const content = await fs.readFile(dbPath, 'utf8');
65
- this.state = JSON.parse(content);
66
- if (process.env.CW_VERBOSE)
67
- console.log(`[CoWorker Session] Resumed session: ${this.currentSessionId}`);
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.log(`[CoWorker Session] Started new session: ${this.currentSessionId}`);
72
- await this.saveCheckpoint();
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
- const dbPath = this.getSessionFilePath();
78
- await fs.mkdir(path.dirname(dbPath), { recursive: true });
79
- await fs.writeFile(dbPath, JSON.stringify(this.state, null, 2), 'utf8');
96
+ db.updateSession(this.currentSessionId, {
97
+ summary: this.state.summary,
98
+ });
80
99
  }
81
- catch (err) {
100
+ catch (e) {
82
101
  if (process.env.CW_VERBOSE)
83
- console.error(`[CoWorker Session] Failed to save DB: ${err.message}`);
102
+ console.error(`[Session] Save error: ${e.message}`);
84
103
  }
85
104
  }
86
105
  /**
87
- * Pushes a new turn into the context window and automatically triggers token rollup if needed.
106
+ * Append a message and persist to SQLite.
88
107
  */
89
108
  async appendMessage(message) {
90
109
  this.state.messages.push(message);
91
- await this.rollupMemory();
92
- await this.saveCheckpoint();
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.log(`[CoWorker Memory] Context threshold exceeded (${totalChars} chars). Triggering rollup compression.`);
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
- * Used for 'Edit' and 'Write' tools to backup a file before mutating it.
119
+ * Replace all messages with a compacted summary.
120
+ * Used by /compact and auto-compaction.
114
121
  */
115
- async backupFileBeforeMutation(targetFilePath) {
122
+ async compactMessages(summary) {
123
+ this.state.messages = [
124
+ { role: 'assistant', content: `[conversation compressed]\n\n${summary}` }
125
+ ];
116
126
  try {
117
- const absoluteTarget = path.resolve(process.cwd(), targetFilePath);
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
- // Silently ignore if file doesn't exist yet (e.g. for creating new files)
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":"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"}
1
+ {"version":3,"file":"SessionManager.js","sourceRoot":"","sources":["../../src/session/SessionManager.ts"],"names":[],"mappings":"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"}
@@ -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
- private registerInternalHooks;
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
- * NOW: also runs inline error detection for file-mutation tools.
53
+ * @deprecated Use hookEngine.fire('PostToolUse', ...)
52
54
  */
53
55
  firePostToolHook(toolName: string, result: string, args?: Record<string, any>): Promise<void>;
54
56
  /**