clavix 2.3.0 → 2.4.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/cli/commands/init.js +1 -1
- package/dist/core 2/adapters/agents-md-generator.d.ts +26 -0
- package/dist/core 2/adapters/agents-md-generator.js +102 -0
- package/dist/core 2/adapters/amp-adapter.d.ts +27 -0
- package/dist/core 2/adapters/amp-adapter.js +42 -0
- package/dist/core 2/adapters/augment-adapter.d.ts +22 -0
- package/dist/core 2/adapters/augment-adapter.js +77 -0
- package/dist/core 2/adapters/base-adapter.d.ts +45 -0
- package/dist/core 2/adapters/base-adapter.js +142 -0
- package/dist/core 2/adapters/claude-code-adapter.d.ts +32 -0
- package/dist/core 2/adapters/claude-code-adapter.js +116 -0
- package/dist/core 2/adapters/cline-adapter.d.ts +34 -0
- package/dist/core 2/adapters/cline-adapter.js +52 -0
- package/dist/core 2/adapters/codebuddy-adapter.d.ts +24 -0
- package/dist/core 2/adapters/codebuddy-adapter.js +82 -0
- package/dist/core 2/adapters/codex-adapter.d.ts +24 -0
- package/dist/core 2/adapters/codex-adapter.js +79 -0
- package/dist/core 2/adapters/copilot-instructions-generator.d.ts +26 -0
- package/dist/core 2/adapters/copilot-instructions-generator.js +104 -0
- package/dist/core 2/adapters/crush-adapter.d.ts +35 -0
- package/dist/core 2/adapters/crush-adapter.js +49 -0
- package/dist/core 2/adapters/cursor-adapter.d.ts +25 -0
- package/dist/core 2/adapters/cursor-adapter.js +40 -0
- package/dist/core 2/adapters/droid-adapter.d.ts +33 -0
- package/dist/core 2/adapters/droid-adapter.js +57 -0
- package/dist/core 2/adapters/gemini-adapter.d.ts +27 -0
- package/dist/core 2/adapters/gemini-adapter.js +90 -0
- package/dist/core 2/adapters/kilocode-adapter.d.ts +34 -0
- package/dist/core 2/adapters/kilocode-adapter.js +49 -0
- package/dist/core 2/adapters/octo-md-generator.d.ts +26 -0
- package/dist/core 2/adapters/octo-md-generator.js +102 -0
- package/dist/core 2/adapters/opencode-adapter.d.ts +33 -0
- package/dist/core 2/adapters/opencode-adapter.js +56 -0
- package/dist/core 2/adapters/qwen-adapter.d.ts +27 -0
- package/dist/core 2/adapters/qwen-adapter.js +90 -0
- package/dist/core 2/adapters/roocode-adapter.d.ts +40 -0
- package/dist/core 2/adapters/roocode-adapter.js +68 -0
- package/dist/core 2/adapters/warp-md-generator.d.ts +17 -0
- package/dist/core 2/adapters/warp-md-generator.js +88 -0
- package/dist/core 2/adapters/windsurf-adapter.d.ts +34 -0
- package/dist/core 2/adapters/windsurf-adapter.js +49 -0
- package/dist/core 2/agent-manager.d.ts +51 -0
- package/dist/core 2/agent-manager.js +126 -0
- package/dist/core 2/archive-manager.d.ts +100 -0
- package/dist/core 2/archive-manager.js +338 -0
- package/dist/core 2/conversation-analyzer.d.ts +86 -0
- package/dist/core 2/doc-injector.d.ts +51 -0
- package/dist/core 2/doc-injector.js +236 -0
- package/dist/core 2/git-manager.d.ts +100 -0
- package/dist/core 2/git-manager.js +214 -0
- package/dist/core 2/prompt-optimizer.d.ts +268 -0
- package/dist/core 2/prompt-optimizer.js +963 -0
- package/dist/core 2/question-engine.d.ts +167 -0
- package/dist/core 2/question-engine.js +395 -0
- package/dist/core 2/session-manager.d.ts +139 -0
- package/dist/core 2/session-manager.js +403 -0
- package/dist/core 2/task-manager.d.ts +155 -0
- package/dist/core 2/task-manager.js +689 -0
- package/dist/utils/template-loader.js +24 -22
- package/package.json +1 -1
- package/dist/templates/slash-commands/augment/archive.md +0 -291
- package/dist/templates/slash-commands/augment/deep.md +0 -207
- package/dist/templates/slash-commands/augment/fast.md +0 -183
- package/dist/templates/slash-commands/augment/implement.md +0 -267
- package/dist/templates/slash-commands/augment/plan.md +0 -173
- package/dist/templates/slash-commands/augment/prd.md +0 -178
- package/dist/templates/slash-commands/augment/start.md +0 -142
- package/dist/templates/slash-commands/augment/summarize.md +0 -179
- package/dist/templates/slash-commands/claude-code/archive.md +0 -291
- package/dist/templates/slash-commands/claude-code/deep.md +0 -207
- package/dist/templates/slash-commands/claude-code/fast.md +0 -183
- package/dist/templates/slash-commands/claude-code/implement.md +0 -267
- package/dist/templates/slash-commands/claude-code/plan.md +0 -173
- package/dist/templates/slash-commands/claude-code/prd.md +0 -178
- package/dist/templates/slash-commands/claude-code/start.md +0 -142
- package/dist/templates/slash-commands/claude-code/summarize.md +0 -179
- package/dist/templates/slash-commands/cline/archive.md +0 -291
- package/dist/templates/slash-commands/cline/deep.md +0 -207
- package/dist/templates/slash-commands/cline/fast.md +0 -183
- package/dist/templates/slash-commands/cline/implement.md +0 -267
- package/dist/templates/slash-commands/cline/plan.md +0 -173
- package/dist/templates/slash-commands/cline/prd.md +0 -178
- package/dist/templates/slash-commands/cline/start.md +0 -142
- package/dist/templates/slash-commands/cline/summarize.md +0 -179
- package/dist/templates/slash-commands/codebuddy/archive.md +0 -291
- package/dist/templates/slash-commands/codebuddy/deep.md +0 -207
- package/dist/templates/slash-commands/codebuddy/fast.md +0 -183
- package/dist/templates/slash-commands/codebuddy/implement.md +0 -267
- package/dist/templates/slash-commands/codebuddy/plan.md +0 -173
- package/dist/templates/slash-commands/codebuddy/prd.md +0 -178
- package/dist/templates/slash-commands/codebuddy/start.md +0 -142
- package/dist/templates/slash-commands/codebuddy/summarize.md +0 -179
- package/dist/templates/slash-commands/codex/archive.md +0 -291
- package/dist/templates/slash-commands/codex/deep.md +0 -207
- package/dist/templates/slash-commands/codex/fast.md +0 -183
- package/dist/templates/slash-commands/codex/implement.md +0 -267
- package/dist/templates/slash-commands/codex/plan.md +0 -173
- package/dist/templates/slash-commands/codex/prd.md +0 -178
- package/dist/templates/slash-commands/codex/start.md +0 -142
- package/dist/templates/slash-commands/codex/summarize.md +0 -179
- package/dist/templates/slash-commands/crush/archive.md +0 -291
- package/dist/templates/slash-commands/crush/deep.md +0 -207
- package/dist/templates/slash-commands/crush/fast.md +0 -183
- package/dist/templates/slash-commands/crush/implement.md +0 -267
- package/dist/templates/slash-commands/crush/plan.md +0 -173
- package/dist/templates/slash-commands/crush/prd.md +0 -178
- package/dist/templates/slash-commands/crush/start.md +0 -142
- package/dist/templates/slash-commands/crush/summarize.md +0 -179
- package/dist/templates/slash-commands/cursor/archive.md +0 -291
- package/dist/templates/slash-commands/cursor/deep.md +0 -207
- package/dist/templates/slash-commands/cursor/fast.md +0 -183
- package/dist/templates/slash-commands/cursor/implement.md +0 -267
- package/dist/templates/slash-commands/cursor/plan.md +0 -173
- package/dist/templates/slash-commands/cursor/prd.md +0 -178
- package/dist/templates/slash-commands/cursor/start.md +0 -142
- package/dist/templates/slash-commands/cursor/summarize.md +0 -179
- package/dist/templates/slash-commands/droid/archive.md +0 -291
- package/dist/templates/slash-commands/droid/deep.md +0 -207
- package/dist/templates/slash-commands/droid/fast.md +0 -183
- package/dist/templates/slash-commands/droid/implement.md +0 -267
- package/dist/templates/slash-commands/droid/plan.md +0 -173
- package/dist/templates/slash-commands/droid/prd.md +0 -178
- package/dist/templates/slash-commands/droid/start.md +0 -142
- package/dist/templates/slash-commands/droid/summarize.md +0 -179
- package/dist/templates/slash-commands/gemini/archive.toml +0 -290
- package/dist/templates/slash-commands/gemini/deep.toml +0 -206
- package/dist/templates/slash-commands/gemini/fast.toml +0 -182
- package/dist/templates/slash-commands/gemini/implement.toml +0 -266
- package/dist/templates/slash-commands/gemini/plan.toml +0 -170
- package/dist/templates/slash-commands/gemini/prd.toml +0 -177
- package/dist/templates/slash-commands/gemini/start.toml +0 -141
- package/dist/templates/slash-commands/gemini/summarize.toml +0 -178
- package/dist/templates/slash-commands/kilocode/archive.md +0 -291
- package/dist/templates/slash-commands/kilocode/deep.md +0 -207
- package/dist/templates/slash-commands/kilocode/fast.md +0 -183
- package/dist/templates/slash-commands/kilocode/implement.md +0 -267
- package/dist/templates/slash-commands/kilocode/plan.md +0 -173
- package/dist/templates/slash-commands/kilocode/prd.md +0 -178
- package/dist/templates/slash-commands/kilocode/start.md +0 -142
- package/dist/templates/slash-commands/kilocode/summarize.md +0 -179
- package/dist/templates/slash-commands/opencode/archive.md +0 -291
- package/dist/templates/slash-commands/opencode/deep.md +0 -207
- package/dist/templates/slash-commands/opencode/fast.md +0 -183
- package/dist/templates/slash-commands/opencode/implement.md +0 -267
- package/dist/templates/slash-commands/opencode/plan.md +0 -173
- package/dist/templates/slash-commands/opencode/prd.md +0 -178
- package/dist/templates/slash-commands/opencode/start.md +0 -142
- package/dist/templates/slash-commands/opencode/summarize.md +0 -179
- package/dist/templates/slash-commands/qwen/archive.toml +0 -290
- package/dist/templates/slash-commands/qwen/deep.toml +0 -206
- package/dist/templates/slash-commands/qwen/fast.toml +0 -182
- package/dist/templates/slash-commands/qwen/implement.toml +0 -266
- package/dist/templates/slash-commands/qwen/plan.toml +0 -170
- package/dist/templates/slash-commands/qwen/prd.toml +0 -177
- package/dist/templates/slash-commands/qwen/start.toml +0 -141
- package/dist/templates/slash-commands/qwen/summarize.toml +0 -178
- package/dist/templates/slash-commands/roocode/archive.md +0 -291
- package/dist/templates/slash-commands/roocode/deep.md +0 -207
- package/dist/templates/slash-commands/roocode/fast.md +0 -183
- package/dist/templates/slash-commands/roocode/implement.md +0 -267
- package/dist/templates/slash-commands/roocode/plan.md +0 -173
- package/dist/templates/slash-commands/roocode/prd.md +0 -178
- package/dist/templates/slash-commands/roocode/start.md +0 -142
- package/dist/templates/slash-commands/roocode/summarize.md +0 -179
- package/dist/templates/slash-commands/windsurf/archive.md +0 -291
- package/dist/templates/slash-commands/windsurf/deep.md +0 -207
- package/dist/templates/slash-commands/windsurf/fast.md +0 -183
- package/dist/templates/slash-commands/windsurf/implement.md +0 -267
- package/dist/templates/slash-commands/windsurf/plan.md +0 -173
- package/dist/templates/slash-commands/windsurf/prd.md +0 -178
- package/dist/templates/slash-commands/windsurf/start.md +0 -142
- package/dist/templates/slash-commands/windsurf/summarize.md +0 -179
- /package/dist/templates/slash-commands/{amp → _canonical}/archive.md +0 -0
- /package/dist/templates/slash-commands/{amp → _canonical}/deep.md +0 -0
- /package/dist/templates/slash-commands/{amp → _canonical}/fast.md +0 -0
- /package/dist/templates/slash-commands/{amp → _canonical}/implement.md +0 -0
- /package/dist/templates/slash-commands/{amp → _canonical}/plan.md +0 -0
- /package/dist/templates/slash-commands/{amp → _canonical}/prd.md +0 -0
- /package/dist/templates/slash-commands/{amp → _canonical}/start.md +0 -0
- /package/dist/templates/slash-commands/{amp → _canonical}/summarize.md +0 -0
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SessionManager - Manages conversational sessions for clavix start/summarize
|
|
4
|
+
*
|
|
5
|
+
* This class handles:
|
|
6
|
+
* - Session creation with unique IDs
|
|
7
|
+
* - Message tracking and storage
|
|
8
|
+
* - Session file persistence (JSON format)
|
|
9
|
+
* - Session listing, filtering, and search
|
|
10
|
+
* - CRUD operations for sessions
|
|
11
|
+
*
|
|
12
|
+
* Sessions are stored in `.clavix/sessions/` as JSON files:
|
|
13
|
+
* `.clavix/sessions/{session-id}.json`
|
|
14
|
+
*/
|
|
15
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
18
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
19
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
20
|
+
}
|
|
21
|
+
Object.defineProperty(o, k2, desc);
|
|
22
|
+
}) : (function(o, m, k, k2) {
|
|
23
|
+
if (k2 === undefined) k2 = k;
|
|
24
|
+
o[k2] = m[k];
|
|
25
|
+
}));
|
|
26
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
27
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
28
|
+
}) : function(o, v) {
|
|
29
|
+
o["default"] = v;
|
|
30
|
+
});
|
|
31
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
32
|
+
var ownKeys = function(o) {
|
|
33
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
34
|
+
var ar = [];
|
|
35
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
36
|
+
return ar;
|
|
37
|
+
};
|
|
38
|
+
return ownKeys(o);
|
|
39
|
+
};
|
|
40
|
+
return function (mod) {
|
|
41
|
+
if (mod && mod.__esModule) return mod;
|
|
42
|
+
var result = {};
|
|
43
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
44
|
+
__setModuleDefault(result, mod);
|
|
45
|
+
return result;
|
|
46
|
+
};
|
|
47
|
+
})();
|
|
48
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
+
exports.SessionManager = void 0;
|
|
50
|
+
const fs = __importStar(require("fs-extra"));
|
|
51
|
+
const path = __importStar(require("path"));
|
|
52
|
+
const file_system_1 = require("../utils/file-system");
|
|
53
|
+
// Use require for uuid to avoid Jest ESM issues
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
55
|
+
const { v4: uuidv4 } = require('uuid');
|
|
56
|
+
/**
|
|
57
|
+
* SessionManager class
|
|
58
|
+
*
|
|
59
|
+
* Manages all session-related operations including creation, storage,
|
|
60
|
+
* retrieval, listing, and search functionality.
|
|
61
|
+
*/
|
|
62
|
+
class SessionManager {
|
|
63
|
+
constructor(sessionsDir) {
|
|
64
|
+
this.defaultSessionsDir = '.clavix/sessions';
|
|
65
|
+
this.sessionsDir = sessionsDir || this.defaultSessionsDir;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Create a new session
|
|
69
|
+
*
|
|
70
|
+
* @param options - Session creation options
|
|
71
|
+
* @returns The created session
|
|
72
|
+
*/
|
|
73
|
+
async createSession(options = {}) {
|
|
74
|
+
const now = new Date();
|
|
75
|
+
const session = {
|
|
76
|
+
id: uuidv4(),
|
|
77
|
+
projectName: options.projectName || this.generateDefaultProjectName(),
|
|
78
|
+
agent: options.agent || 'Claude Code',
|
|
79
|
+
created: now,
|
|
80
|
+
updated: now,
|
|
81
|
+
status: 'active',
|
|
82
|
+
messages: [],
|
|
83
|
+
tags: options.tags,
|
|
84
|
+
description: options.description,
|
|
85
|
+
};
|
|
86
|
+
await this.saveSession(session);
|
|
87
|
+
return session;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Get a session by ID
|
|
91
|
+
*
|
|
92
|
+
* @param sessionId - The session ID
|
|
93
|
+
* @returns The session, or null if not found
|
|
94
|
+
*/
|
|
95
|
+
async getSession(sessionId) {
|
|
96
|
+
try {
|
|
97
|
+
const sessionPath = this.getSessionPath(sessionId);
|
|
98
|
+
const exists = await fs.pathExists(sessionPath);
|
|
99
|
+
if (!exists) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
const serialized = await fs.readJSON(sessionPath);
|
|
103
|
+
return this.deserializeSession(serialized);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Save a session to disk
|
|
111
|
+
*
|
|
112
|
+
* @param session - The session to save
|
|
113
|
+
*/
|
|
114
|
+
async saveSession(session) {
|
|
115
|
+
await file_system_1.FileSystem.ensureDir(this.sessionsDir);
|
|
116
|
+
const sessionPath = this.getSessionPath(session.id);
|
|
117
|
+
const serialized = this.serializeSession(session);
|
|
118
|
+
// Use atomic write to prevent corruption
|
|
119
|
+
await file_system_1.FileSystem.writeFileAtomic(sessionPath, JSON.stringify(serialized, null, 2));
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Update a session
|
|
123
|
+
*
|
|
124
|
+
* @param sessionId - The session ID
|
|
125
|
+
* @param updates - Partial session updates
|
|
126
|
+
* @returns The updated session, or null if not found
|
|
127
|
+
*/
|
|
128
|
+
async updateSession(sessionId, updates) {
|
|
129
|
+
const session = await this.getSession(sessionId);
|
|
130
|
+
if (!session) {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
const updatedSession = {
|
|
134
|
+
...session,
|
|
135
|
+
...updates,
|
|
136
|
+
id: session.id,
|
|
137
|
+
created: session.created,
|
|
138
|
+
updated: new Date(),
|
|
139
|
+
};
|
|
140
|
+
await this.saveSession(updatedSession);
|
|
141
|
+
return updatedSession;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Delete a session
|
|
145
|
+
*
|
|
146
|
+
* @param sessionId - The session ID
|
|
147
|
+
* @returns True if deleted, false if not found
|
|
148
|
+
*/
|
|
149
|
+
async deleteSession(sessionId) {
|
|
150
|
+
const sessionPath = this.getSessionPath(sessionId);
|
|
151
|
+
const exists = await fs.pathExists(sessionPath);
|
|
152
|
+
if (!exists) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
await fs.remove(sessionPath);
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Add a message to a session
|
|
160
|
+
*
|
|
161
|
+
* @param sessionId - The session ID
|
|
162
|
+
* @param role - Message role (user or assistant)
|
|
163
|
+
* @param content - Message content
|
|
164
|
+
* @returns The updated session, or null if session not found
|
|
165
|
+
*/
|
|
166
|
+
async addMessage(sessionId, role, content) {
|
|
167
|
+
const session = await this.getSession(sessionId);
|
|
168
|
+
if (!session) {
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
const message = {
|
|
172
|
+
role,
|
|
173
|
+
content,
|
|
174
|
+
timestamp: new Date(),
|
|
175
|
+
};
|
|
176
|
+
session.messages.push(message);
|
|
177
|
+
session.updated = new Date();
|
|
178
|
+
await this.saveSession(session);
|
|
179
|
+
return session;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* List all sessions with optional filtering
|
|
183
|
+
*
|
|
184
|
+
* @param filter - Optional filter criteria
|
|
185
|
+
* @returns Array of session metadata
|
|
186
|
+
*/
|
|
187
|
+
async listSessions(filter) {
|
|
188
|
+
await file_system_1.FileSystem.ensureDir(this.sessionsDir);
|
|
189
|
+
const files = await fs.readdir(this.sessionsDir);
|
|
190
|
+
const sessionFiles = files.filter((f) => f.endsWith('.json'));
|
|
191
|
+
const sessions = [];
|
|
192
|
+
for (const file of sessionFiles) {
|
|
193
|
+
try {
|
|
194
|
+
const sessionPath = path.join(this.sessionsDir, file);
|
|
195
|
+
const serialized = await fs.readJSON(sessionPath);
|
|
196
|
+
const metadata = this.extractMetadata(serialized);
|
|
197
|
+
// Apply filters
|
|
198
|
+
if (filter && !this.matchesFilter(metadata, filter)) {
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
sessions.push(metadata);
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
// Skip corrupted session files
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
// Sort by updated date (most recent first)
|
|
209
|
+
sessions.sort((a, b) => {
|
|
210
|
+
return new Date(b.updated).getTime() - new Date(a.updated).getTime();
|
|
211
|
+
});
|
|
212
|
+
return sessions;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Search sessions by keyword
|
|
216
|
+
*
|
|
217
|
+
* Searches in project name, description, tags, and message content
|
|
218
|
+
*
|
|
219
|
+
* @param keyword - Search keyword
|
|
220
|
+
* @returns Array of matching session metadata
|
|
221
|
+
*/
|
|
222
|
+
async searchSessions(keyword) {
|
|
223
|
+
await file_system_1.FileSystem.ensureDir(this.sessionsDir);
|
|
224
|
+
const files = await fs.readdir(this.sessionsDir);
|
|
225
|
+
const sessionFiles = files.filter((f) => f.endsWith('.json'));
|
|
226
|
+
const matches = [];
|
|
227
|
+
const lowerKeyword = keyword.toLowerCase();
|
|
228
|
+
for (const file of sessionFiles) {
|
|
229
|
+
try {
|
|
230
|
+
const sessionPath = path.join(this.sessionsDir, file);
|
|
231
|
+
const serialized = await fs.readJSON(sessionPath);
|
|
232
|
+
// Search in project name
|
|
233
|
+
if (serialized.projectName.toLowerCase().includes(lowerKeyword)) {
|
|
234
|
+
matches.push(this.extractMetadata(serialized));
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
// Search in description
|
|
238
|
+
if (serialized.description?.toLowerCase().includes(lowerKeyword)) {
|
|
239
|
+
matches.push(this.extractMetadata(serialized));
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
// Search in tags
|
|
243
|
+
if (serialized.tags?.some((tag) => tag.toLowerCase().includes(lowerKeyword))) {
|
|
244
|
+
matches.push(this.extractMetadata(serialized));
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
// Search in message content
|
|
248
|
+
const hasMessageMatch = serialized.messages.some((msg) => msg.content.toLowerCase().includes(lowerKeyword));
|
|
249
|
+
if (hasMessageMatch) {
|
|
250
|
+
matches.push(this.extractMetadata(serialized));
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
// Skip corrupted session files
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
// Sort by updated date (most recent first)
|
|
259
|
+
matches.sort((a, b) => {
|
|
260
|
+
return new Date(b.updated).getTime() - new Date(a.updated).getTime();
|
|
261
|
+
});
|
|
262
|
+
return matches;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Get the most recent active session
|
|
266
|
+
*
|
|
267
|
+
* @returns The active session, or null if none exists
|
|
268
|
+
*/
|
|
269
|
+
async getActiveSession() {
|
|
270
|
+
const activeSessions = await this.listSessions({ status: 'active' });
|
|
271
|
+
if (activeSessions.length === 0) {
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
// Return the most recently updated active session
|
|
275
|
+
return this.getSession(activeSessions[0].id);
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Mark a session as completed
|
|
279
|
+
*
|
|
280
|
+
* @param sessionId - The session ID
|
|
281
|
+
* @returns The updated session, or null if not found
|
|
282
|
+
*/
|
|
283
|
+
async completeSession(sessionId) {
|
|
284
|
+
return this.updateSession(sessionId, { status: 'completed' });
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Mark a session as archived
|
|
288
|
+
*
|
|
289
|
+
* @param sessionId - The session ID
|
|
290
|
+
* @returns The updated session, or null if not found
|
|
291
|
+
*/
|
|
292
|
+
async archiveSession(sessionId) {
|
|
293
|
+
return this.updateSession(sessionId, { status: 'archived' });
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Get the path to a session file
|
|
297
|
+
*/
|
|
298
|
+
getSessionPath(sessionId) {
|
|
299
|
+
return path.join(this.sessionsDir, `${sessionId}.json`);
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Generate a default project name based on timestamp
|
|
303
|
+
*/
|
|
304
|
+
generateDefaultProjectName() {
|
|
305
|
+
const date = new Date();
|
|
306
|
+
const timestamp = date.toISOString().split('T')[0]; // YYYY-MM-DD
|
|
307
|
+
return `session-${timestamp}`;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Serialize a session for file storage
|
|
311
|
+
*/
|
|
312
|
+
serializeSession(session) {
|
|
313
|
+
return {
|
|
314
|
+
id: session.id,
|
|
315
|
+
projectName: session.projectName,
|
|
316
|
+
agent: session.agent,
|
|
317
|
+
created: session.created.toISOString(),
|
|
318
|
+
updated: session.updated.toISOString(),
|
|
319
|
+
status: session.status,
|
|
320
|
+
messages: session.messages.map((msg) => ({
|
|
321
|
+
role: msg.role,
|
|
322
|
+
content: msg.content,
|
|
323
|
+
timestamp: msg.timestamp.toISOString(),
|
|
324
|
+
})),
|
|
325
|
+
tags: session.tags,
|
|
326
|
+
description: session.description,
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Deserialize a session from file storage
|
|
331
|
+
*/
|
|
332
|
+
deserializeSession(serialized) {
|
|
333
|
+
return {
|
|
334
|
+
id: serialized.id,
|
|
335
|
+
projectName: serialized.projectName,
|
|
336
|
+
agent: serialized.agent,
|
|
337
|
+
created: new Date(serialized.created),
|
|
338
|
+
updated: new Date(serialized.updated),
|
|
339
|
+
status: serialized.status,
|
|
340
|
+
messages: serialized.messages.map((msg) => ({
|
|
341
|
+
role: msg.role,
|
|
342
|
+
content: msg.content,
|
|
343
|
+
timestamp: new Date(msg.timestamp),
|
|
344
|
+
})),
|
|
345
|
+
tags: serialized.tags,
|
|
346
|
+
description: serialized.description,
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Extract metadata from a serialized session
|
|
351
|
+
*/
|
|
352
|
+
extractMetadata(serialized) {
|
|
353
|
+
return {
|
|
354
|
+
id: serialized.id,
|
|
355
|
+
projectName: serialized.projectName,
|
|
356
|
+
agent: serialized.agent,
|
|
357
|
+
created: serialized.created,
|
|
358
|
+
updated: serialized.updated,
|
|
359
|
+
status: serialized.status,
|
|
360
|
+
messageCount: serialized.messages.length,
|
|
361
|
+
tags: serialized.tags,
|
|
362
|
+
description: serialized.description,
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Check if session metadata matches filter criteria
|
|
367
|
+
*/
|
|
368
|
+
matchesFilter(metadata, filter) {
|
|
369
|
+
// Status filter
|
|
370
|
+
if (filter.status && metadata.status !== filter.status) {
|
|
371
|
+
return false;
|
|
372
|
+
}
|
|
373
|
+
// Project name filter
|
|
374
|
+
if (filter.projectName && metadata.projectName !== filter.projectName) {
|
|
375
|
+
return false;
|
|
376
|
+
}
|
|
377
|
+
// Agent filter
|
|
378
|
+
if (filter.agent && metadata.agent !== filter.agent) {
|
|
379
|
+
return false;
|
|
380
|
+
}
|
|
381
|
+
// Tags filter (session must have ALL specified tags)
|
|
382
|
+
if (filter.tags && filter.tags.length > 0) {
|
|
383
|
+
if (!metadata.tags || metadata.tags.length === 0) {
|
|
384
|
+
return false;
|
|
385
|
+
}
|
|
386
|
+
const hasAllTags = filter.tags.every((tag) => metadata.tags.includes(tag));
|
|
387
|
+
if (!hasAllTags) {
|
|
388
|
+
return false;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
// Date range filters
|
|
392
|
+
const updatedDate = new Date(metadata.updated);
|
|
393
|
+
if (filter.startDate && updatedDate < filter.startDate) {
|
|
394
|
+
return false;
|
|
395
|
+
}
|
|
396
|
+
if (filter.endDate && updatedDate > filter.endDate) {
|
|
397
|
+
return false;
|
|
398
|
+
}
|
|
399
|
+
return true;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
exports.SessionManager = SessionManager;
|
|
403
|
+
//# sourceMappingURL=session-manager.js.map
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TaskManager - Manages PRD-based task generation and execution
|
|
3
|
+
*
|
|
4
|
+
* This class handles:
|
|
5
|
+
* - Analyzing PRD documents
|
|
6
|
+
* - Generating CLEAR-optimized task breakdowns
|
|
7
|
+
* - Reading/writing tasks.md with checkbox format
|
|
8
|
+
* - Tracking task completion state
|
|
9
|
+
* - Managing session resume capability
|
|
10
|
+
*/
|
|
11
|
+
export type PrdSourceType = 'auto' | 'full' | 'quick' | 'mini' | 'prompt';
|
|
12
|
+
/**
|
|
13
|
+
* Represents a single task in the implementation plan
|
|
14
|
+
*/
|
|
15
|
+
export interface Task {
|
|
16
|
+
id: string;
|
|
17
|
+
description: string;
|
|
18
|
+
phase: string;
|
|
19
|
+
completed: boolean;
|
|
20
|
+
prdReference?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Represents a phase/section of tasks
|
|
24
|
+
*/
|
|
25
|
+
export interface TaskPhase {
|
|
26
|
+
name: string;
|
|
27
|
+
tasks: Task[];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Options for task generation
|
|
31
|
+
*/
|
|
32
|
+
export interface TaskGenerationOptions {
|
|
33
|
+
maxTasksPerPhase?: number;
|
|
34
|
+
includeReferences?: boolean;
|
|
35
|
+
clearMode?: 'fast' | 'deep';
|
|
36
|
+
source?: PrdSourceType;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Result of task generation
|
|
40
|
+
*/
|
|
41
|
+
export interface TaskGenerationResult {
|
|
42
|
+
phases: TaskPhase[];
|
|
43
|
+
totalTasks: number;
|
|
44
|
+
outputPath: string;
|
|
45
|
+
sourcePath: string;
|
|
46
|
+
sourceType: Exclude<PrdSourceType, 'auto'>;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* TaskManager class
|
|
50
|
+
*
|
|
51
|
+
* Generates and manages implementation tasks from PRD documents
|
|
52
|
+
*/
|
|
53
|
+
export declare class TaskManager {
|
|
54
|
+
private readonly optimizer;
|
|
55
|
+
constructor();
|
|
56
|
+
/**
|
|
57
|
+
* Generate tasks.md from PRD
|
|
58
|
+
*
|
|
59
|
+
* @param prdPath - Path to the PRD directory
|
|
60
|
+
* @param options - Generation options
|
|
61
|
+
* @returns Task generation result
|
|
62
|
+
*/
|
|
63
|
+
generateTasksFromPrd(prdPath: string, options?: TaskGenerationOptions): Promise<TaskGenerationResult>;
|
|
64
|
+
/**
|
|
65
|
+
* Find the PRD file in a directory
|
|
66
|
+
*/
|
|
67
|
+
private resolvePrdFile;
|
|
68
|
+
/**
|
|
69
|
+
* Analyze PRD content and generate task breakdown
|
|
70
|
+
*/
|
|
71
|
+
private analyzePrdAndGenerateTasks;
|
|
72
|
+
private getSectionByAliases;
|
|
73
|
+
private generatePhasesFromCoreFeatures;
|
|
74
|
+
private extractListItems;
|
|
75
|
+
private buildFeatureTaskDescriptions;
|
|
76
|
+
private formatInlineText;
|
|
77
|
+
private toTitleCase;
|
|
78
|
+
private injectTechnicalConstraintsTask;
|
|
79
|
+
private appendSuccessCriteriaPhase;
|
|
80
|
+
/**
|
|
81
|
+
* Parse PRD into sections
|
|
82
|
+
*/
|
|
83
|
+
private parsePrdSections;
|
|
84
|
+
/**
|
|
85
|
+
* Normalize section name for consistent lookup
|
|
86
|
+
*/
|
|
87
|
+
private normalizeSectionName;
|
|
88
|
+
/**
|
|
89
|
+
* Generate tasks from requirements section
|
|
90
|
+
*/
|
|
91
|
+
private generateTasksFromRequirements;
|
|
92
|
+
/**
|
|
93
|
+
* Generate a phase from a feature description
|
|
94
|
+
*/
|
|
95
|
+
private generatePhaseFromFeature;
|
|
96
|
+
/**
|
|
97
|
+
* Convert behavior description to task description
|
|
98
|
+
*/
|
|
99
|
+
private convertBehaviorToTask;
|
|
100
|
+
/**
|
|
101
|
+
* Generate default phases when no structure found
|
|
102
|
+
*/
|
|
103
|
+
private generateDefaultPhases;
|
|
104
|
+
/**
|
|
105
|
+
* Sanitize ID for use in task IDs
|
|
106
|
+
*/
|
|
107
|
+
private sanitizeId;
|
|
108
|
+
/**
|
|
109
|
+
* Optimize task description using CLEAR principles
|
|
110
|
+
*/
|
|
111
|
+
private optimizeTaskDescription;
|
|
112
|
+
/**
|
|
113
|
+
* Write tasks to tasks.md file
|
|
114
|
+
*/
|
|
115
|
+
private writeTasksFile;
|
|
116
|
+
/**
|
|
117
|
+
* Read tasks from tasks.md file
|
|
118
|
+
*/
|
|
119
|
+
readTasksFile(tasksPath: string): Promise<TaskPhase[]>;
|
|
120
|
+
/**
|
|
121
|
+
* Parse tasks.md content into TaskPhase objects
|
|
122
|
+
*/
|
|
123
|
+
private parseTasksFile;
|
|
124
|
+
/**
|
|
125
|
+
* Find the first incomplete task
|
|
126
|
+
*/
|
|
127
|
+
findFirstIncompleteTask(phases: TaskPhase[]): Task | null;
|
|
128
|
+
/**
|
|
129
|
+
* Mark a task as completed in the tasks.md file
|
|
130
|
+
*/
|
|
131
|
+
markTaskCompleted(tasksPath: string, taskId: string): Promise<void>;
|
|
132
|
+
/**
|
|
133
|
+
* Escape special regex characters
|
|
134
|
+
*/
|
|
135
|
+
private escapeRegex;
|
|
136
|
+
/**
|
|
137
|
+
* Get task completion statistics
|
|
138
|
+
*/
|
|
139
|
+
getTaskStats(phases: TaskPhase[]): {
|
|
140
|
+
total: number;
|
|
141
|
+
completed: number;
|
|
142
|
+
remaining: number;
|
|
143
|
+
percentage: number;
|
|
144
|
+
};
|
|
145
|
+
/**
|
|
146
|
+
* Find PRD directory from current working directory
|
|
147
|
+
*/
|
|
148
|
+
findPrdDirectory(projectName?: string): Promise<string>;
|
|
149
|
+
/**
|
|
150
|
+
* Check if directory has a PRD file
|
|
151
|
+
*/
|
|
152
|
+
hasPrdFile(dirPath: string): Promise<boolean>;
|
|
153
|
+
detectAvailableSources(dirPath: string): Promise<Array<Exclude<PrdSourceType, 'auto'>>>;
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=task-manager.d.ts.map
|