statecli-mcp-server 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,219 @@
1
+ "use strict";
2
+ /**
3
+ * Git Integration - Track changes between commits
4
+ *
5
+ * Integrates with git to provide commit-level state tracking
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.GitIntegration = void 0;
42
+ const child_process_1 = require("child_process");
43
+ const path = __importStar(require("path"));
44
+ class GitIntegration {
45
+ statecli;
46
+ repoPath;
47
+ constructor(statecli, repoPath = '.') {
48
+ this.statecli = statecli;
49
+ this.repoPath = path.resolve(repoPath);
50
+ }
51
+ /**
52
+ * Check if current directory is a git repository
53
+ */
54
+ isGitRepo() {
55
+ try {
56
+ this.execGit('rev-parse --git-dir');
57
+ return true;
58
+ }
59
+ catch {
60
+ return false;
61
+ }
62
+ }
63
+ /**
64
+ * Get current branch name
65
+ */
66
+ getCurrentBranch() {
67
+ return this.execGit('rev-parse --abbrev-ref HEAD').trim();
68
+ }
69
+ /**
70
+ * Get current commit hash
71
+ */
72
+ getCurrentCommit() {
73
+ return this.execGit('rev-parse HEAD').trim();
74
+ }
75
+ /**
76
+ * Get recent commits
77
+ */
78
+ getRecentCommits(count = 10) {
79
+ const format = '%H|%h|%s|%an|%ai';
80
+ const log = this.execGit(`log -${count} --pretty=format:"${format}"`);
81
+ return log.split('\n').filter(line => line.trim()).map(line => {
82
+ const [hash, shortHash, message, author, date] = line.split('|');
83
+ const files = this.getCommitFiles(hash);
84
+ return { hash, shortHash, message, author, date, files };
85
+ });
86
+ }
87
+ /**
88
+ * Get files changed in a commit
89
+ */
90
+ getCommitFiles(commitHash) {
91
+ try {
92
+ const output = this.execGit(`diff-tree --no-commit-id --name-only -r ${commitHash}`);
93
+ return output.split('\n').filter(f => f.trim());
94
+ }
95
+ catch {
96
+ return [];
97
+ }
98
+ }
99
+ /**
100
+ * Compare two commits
101
+ */
102
+ compareCommits(fromCommit, toCommit) {
103
+ const diffOutput = this.execGit(`diff --stat ${fromCommit}..${toCommit}`);
104
+ const files = [];
105
+ // Parse diff stat output
106
+ const lines = diffOutput.split('\n');
107
+ for (const line of lines) {
108
+ const match = line.match(/^\s*(.+?)\s+\|\s+(\d+)\s+(\++)?(-+)?/);
109
+ if (match) {
110
+ const [, file, total, additions, deletions] = match;
111
+ files.push({
112
+ file: file.trim(),
113
+ additions: (additions || '').length,
114
+ deletions: (deletions || '').length,
115
+ changes: this.getFileDiff(fromCommit, toCommit, file.trim())
116
+ });
117
+ }
118
+ }
119
+ const summary = `Comparing ${fromCommit.substring(0, 7)} to ${toCommit.substring(0, 7)}: ${files.length} files changed`;
120
+ return { fromCommit, toCommit, files, summary };
121
+ }
122
+ /**
123
+ * Get diff for a specific file between commits
124
+ */
125
+ getFileDiff(fromCommit, toCommit, filePath) {
126
+ try {
127
+ const diff = this.execGit(`diff ${fromCommit}..${toCommit} -- "${filePath}"`);
128
+ return diff.split('\n').slice(0, 100); // Limit to 100 lines
129
+ }
130
+ catch {
131
+ return [];
132
+ }
133
+ }
134
+ /**
135
+ * Track current git state in StateCLI
136
+ */
137
+ trackGitState(actor = 'git-integration') {
138
+ const branch = this.getCurrentBranch();
139
+ const commit = this.getCurrentCommit();
140
+ const recentCommits = this.getRecentCommits(5);
141
+ this.statecli.track('git', 'state', {
142
+ branch,
143
+ commit,
144
+ shortCommit: commit.substring(0, 7),
145
+ recentCommits: recentCommits.map(c => ({
146
+ hash: c.shortHash,
147
+ message: c.message
148
+ })),
149
+ timestamp: new Date().toISOString()
150
+ }, actor);
151
+ }
152
+ /**
153
+ * Create a checkpoint at current git state
154
+ */
155
+ createGitCheckpoint(name) {
156
+ const commit = this.getCurrentCommit();
157
+ const checkpointName = name || `git-${commit.substring(0, 7)}`;
158
+ const result = this.statecli.checkpoint('git:state', checkpointName);
159
+ return {
160
+ checkpointId: result.id,
161
+ commit
162
+ };
163
+ }
164
+ /**
165
+ * Get what happened between two commits in StateCLI format
166
+ */
167
+ getCommitHistory(fromCommit, toCommit) {
168
+ // Get commits between the two
169
+ const commits = this.getCommitsBetween(fromCommit, toCommit);
170
+ // Get comparison
171
+ const comparison = this.compareCommits(fromCommit, toCommit);
172
+ // Get StateCLI state changes during this period
173
+ const stateChanges = this.statecli.replay('git:state');
174
+ return { commits, comparison, stateChanges };
175
+ }
176
+ /**
177
+ * Get commits between two commit hashes
178
+ */
179
+ getCommitsBetween(fromCommit, toCommit) {
180
+ const format = '%H|%h|%s|%an|%ai';
181
+ try {
182
+ const log = this.execGit(`log ${fromCommit}..${toCommit} --pretty=format:"${format}"`);
183
+ return log.split('\n').filter(line => line.trim()).map(line => {
184
+ const [hash, shortHash, message, author, date] = line.split('|');
185
+ const files = this.getCommitFiles(hash);
186
+ return { hash, shortHash, message, author, date, files };
187
+ });
188
+ }
189
+ catch {
190
+ return [];
191
+ }
192
+ }
193
+ /**
194
+ * Get uncommitted changes
195
+ */
196
+ getUncommittedChanges() {
197
+ const staged = this.execGit('diff --cached --name-only').split('\n').filter(f => f.trim());
198
+ const unstaged = this.execGit('diff --name-only').split('\n').filter(f => f.trim());
199
+ const untracked = this.execGit('ls-files --others --exclude-standard').split('\n').filter(f => f.trim());
200
+ return { staged, unstaged, untracked };
201
+ }
202
+ /**
203
+ * Execute a git command
204
+ */
205
+ execGit(command) {
206
+ try {
207
+ return (0, child_process_1.execSync)(`git ${command}`, {
208
+ cwd: this.repoPath,
209
+ encoding: 'utf-8',
210
+ stdio: ['pipe', 'pipe', 'pipe']
211
+ });
212
+ }
213
+ catch (error) {
214
+ throw new Error(`Git command failed: ${error.message}`);
215
+ }
216
+ }
217
+ }
218
+ exports.GitIntegration = GitIntegration;
219
+ //# sourceMappingURL=git-integration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-integration.js","sourceRoot":"","sources":["../src/git-integration.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * StateCLI Enhanced MCP Server Entry Point
4
+ *
5
+ * Includes all advanced features:
6
+ * - File tracking with diffs
7
+ * - Error recovery and auto-rollback
8
+ * - Session memory and cross-session queries
9
+ * - Git integration
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=index-enhanced.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-enhanced.d.ts","sourceRoot":"","sources":["../src/index-enhanced.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG"}
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * StateCLI Enhanced MCP Server Entry Point
5
+ *
6
+ * Includes all advanced features:
7
+ * - File tracking with diffs
8
+ * - Error recovery and auto-rollback
9
+ * - Session memory and cross-session queries
10
+ * - Git integration
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ const enhanced_mcp_server_1 = require("./enhanced-mcp-server");
14
+ const server = new enhanced_mcp_server_1.EnhancedStateCLIMCPServer();
15
+ process.on('SIGINT', () => {
16
+ server.close();
17
+ process.exit(0);
18
+ });
19
+ process.on('SIGTERM', () => {
20
+ server.close();
21
+ process.exit(0);
22
+ });
23
+ server.run().catch((error) => {
24
+ console.error('Failed to start enhanced server:', error);
25
+ process.exit(1);
26
+ });
27
+ //# sourceMappingURL=index-enhanced.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-enhanced.js","sourceRoot":"","sources":["../src/index-enhanced.ts"],"names":[],"mappings":";;AACA;;;;;;;;GAQG;;AAEH,+DAAkE;AAElE,MAAM,MAAM,GAAG,IAAI,+CAAyB,EAAE,CAAC;AAE/C,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;IACxB,MAAM,CAAC,KAAK,EAAE,CAAC;IACf,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;IACzB,MAAM,CAAC,KAAK,EAAE,CAAC;IACf,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IAC3B,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,KAAK,CAAC,CAAC;IACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Session Memory - Cross-session persistence and memory
3
+ *
4
+ * Remembers what happened across sessions and provides memory queries
5
+ */
6
+ import { StateCLI } from './statecli';
7
+ import { StateChange } from './types';
8
+ export interface SessionInfo {
9
+ id: string;
10
+ startTime: string;
11
+ endTime?: string;
12
+ summary: string;
13
+ changesCount: number;
14
+ entities: string[];
15
+ }
16
+ export interface MemoryQuery {
17
+ entity?: string;
18
+ entityPattern?: string;
19
+ timeRange?: {
20
+ start: string;
21
+ end: string;
22
+ };
23
+ actor?: string;
24
+ keyword?: string;
25
+ }
26
+ export interface MemoryResult {
27
+ query: MemoryQuery;
28
+ sessions: SessionInfo[];
29
+ changes: StateChange[];
30
+ summary: string;
31
+ }
32
+ export declare class SessionMemory {
33
+ private statecli;
34
+ private sessionId;
35
+ private sessionStartTime;
36
+ private memoryDir;
37
+ constructor(statecli: StateCLI, memoryDir?: string);
38
+ /**
39
+ * Get current session ID
40
+ */
41
+ getSessionId(): string;
42
+ /**
43
+ * Query memory across sessions
44
+ */
45
+ queryMemory(query: MemoryQuery): MemoryResult;
46
+ /**
47
+ * Ask a natural language question about past actions
48
+ */
49
+ ask(question: string): MemoryResult;
50
+ /**
51
+ * Get all recorded sessions
52
+ */
53
+ getSessions(): SessionInfo[];
54
+ /**
55
+ * Get session data by ID
56
+ */
57
+ getSession(sessionId: string): {
58
+ info: SessionInfo;
59
+ changes: StateChange[];
60
+ } | null;
61
+ /**
62
+ * Save current session data
63
+ */
64
+ saveSession(): void;
65
+ /**
66
+ * End current session
67
+ */
68
+ endSession(): SessionInfo;
69
+ /**
70
+ * Get recent activity summary
71
+ */
72
+ getRecentActivity(hours?: number): MemoryResult;
73
+ /**
74
+ * Get activity for a specific entity across all sessions
75
+ */
76
+ getEntityHistory(entityPattern: string): MemoryResult;
77
+ private generateSessionId;
78
+ private ensureMemoryDir;
79
+ private recordSessionStart;
80
+ private loadSessionData;
81
+ private changeMatchesQuery;
82
+ private parseQuestion;
83
+ private createQuerySummary;
84
+ }
85
+ //# sourceMappingURL=session-memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-memory.d.ts","sourceRoot":"","sources":["../src/session-memory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,WAAW,EAAgB,MAAM,SAAS,CAAC;AAEpD,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE;QACV,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,SAAS,CAAS;gBAEd,QAAQ,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,MAAM;IAUlD;;OAEG;IACH,YAAY,IAAI,MAAM;IAItB;;OAEG;IACH,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,YAAY;IAkC7C;;OAEG;IACH,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY;IAMnC;;OAEG;IACH,WAAW,IAAI,WAAW,EAAE;IAqB5B;;OAEG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE,WAAW,CAAC;QAAC,OAAO,EAAE,WAAW,EAAE,CAAA;KAAE,GAAG,IAAI;IAInF;;OAEG;IACH,WAAW,IAAI,IAAI;IA0CnB;;OAEG;IACH,UAAU,IAAI,WAAW;IAczB;;OAEG;IACH,iBAAiB,CAAC,KAAK,GAAE,MAAW,GAAG,YAAY;IAWnD;;OAEG;IACH,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,YAAY;IAIrD,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,eAAe;IAcvB,OAAO,CAAC,kBAAkB;IA0C1B,OAAO,CAAC,aAAa;IA0CrB,OAAO,CAAC,kBAAkB;CA6B3B"}
@@ -0,0 +1,325 @@
1
+ "use strict";
2
+ /**
3
+ * Session Memory - Cross-session persistence and memory
4
+ *
5
+ * Remembers what happened across sessions and provides memory queries
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.SessionMemory = void 0;
42
+ const fs = __importStar(require("fs"));
43
+ const path = __importStar(require("path"));
44
+ class SessionMemory {
45
+ statecli;
46
+ sessionId;
47
+ sessionStartTime;
48
+ memoryDir;
49
+ constructor(statecli, memoryDir) {
50
+ this.statecli = statecli;
51
+ this.sessionId = this.generateSessionId();
52
+ this.sessionStartTime = new Date().toISOString();
53
+ this.memoryDir = memoryDir || path.join(process.cwd(), '.statecli', 'memory');
54
+ this.ensureMemoryDir();
55
+ this.recordSessionStart();
56
+ }
57
+ /**
58
+ * Get current session ID
59
+ */
60
+ getSessionId() {
61
+ return this.sessionId;
62
+ }
63
+ /**
64
+ * Query memory across sessions
65
+ */
66
+ queryMemory(query) {
67
+ const sessions = this.getSessions();
68
+ const matchingSessions = [];
69
+ const matchingChanges = [];
70
+ for (const session of sessions) {
71
+ // Load session data
72
+ const sessionData = this.loadSessionData(session.id);
73
+ if (!sessionData)
74
+ continue;
75
+ let sessionMatches = false;
76
+ for (const change of sessionData.changes) {
77
+ if (this.changeMatchesQuery(change, query)) {
78
+ matchingChanges.push(change);
79
+ sessionMatches = true;
80
+ }
81
+ }
82
+ if (sessionMatches) {
83
+ matchingSessions.push(session);
84
+ }
85
+ }
86
+ const summary = this.createQuerySummary(query, matchingSessions, matchingChanges);
87
+ return {
88
+ query,
89
+ sessions: matchingSessions,
90
+ changes: matchingChanges,
91
+ summary
92
+ };
93
+ }
94
+ /**
95
+ * Ask a natural language question about past actions
96
+ */
97
+ ask(question) {
98
+ // Parse question into query
99
+ const query = this.parseQuestion(question);
100
+ return this.queryMemory(query);
101
+ }
102
+ /**
103
+ * Get all recorded sessions
104
+ */
105
+ getSessions() {
106
+ const sessions = [];
107
+ try {
108
+ const files = fs.readdirSync(this.memoryDir);
109
+ for (const file of files) {
110
+ if (file.endsWith('.session.json')) {
111
+ const sessionPath = path.join(this.memoryDir, file);
112
+ const data = JSON.parse(fs.readFileSync(sessionPath, 'utf-8'));
113
+ sessions.push(data.info);
114
+ }
115
+ }
116
+ }
117
+ catch {
118
+ // Memory dir might not exist yet
119
+ }
120
+ return sessions.sort((a, b) => new Date(b.startTime).getTime() - new Date(a.startTime).getTime());
121
+ }
122
+ /**
123
+ * Get session data by ID
124
+ */
125
+ getSession(sessionId) {
126
+ return this.loadSessionData(sessionId);
127
+ }
128
+ /**
129
+ * Save current session data
130
+ */
131
+ saveSession() {
132
+ // Get all changes from current session
133
+ const allEntities = this.statecli.listEntities();
134
+ const allChanges = [];
135
+ for (const entity of allEntities) {
136
+ const replay = this.statecli.replay(entity);
137
+ for (const change of replay.changes) {
138
+ // Only include changes from current session
139
+ if (change.timestamp >= this.sessionStartTime) {
140
+ allChanges.push({
141
+ id: change.id || `${entity}-${change.step}`,
142
+ entity,
143
+ entityType: entity.split(':')[0],
144
+ entityId: entity.split(':')[1] || '',
145
+ timestamp: change.timestamp,
146
+ before: change.before,
147
+ after: change.after,
148
+ actor: change.actor
149
+ });
150
+ }
151
+ }
152
+ }
153
+ const sessionInfo = {
154
+ id: this.sessionId,
155
+ startTime: this.sessionStartTime,
156
+ endTime: new Date().toISOString(),
157
+ summary: `Session with ${allChanges.length} changes across ${allEntities.length} entities`,
158
+ changesCount: allChanges.length,
159
+ entities: allEntities
160
+ };
161
+ const sessionData = {
162
+ info: sessionInfo,
163
+ changes: allChanges
164
+ };
165
+ const sessionPath = path.join(this.memoryDir, `${this.sessionId}.session.json`);
166
+ fs.writeFileSync(sessionPath, JSON.stringify(sessionData, null, 2));
167
+ }
168
+ /**
169
+ * End current session
170
+ */
171
+ endSession() {
172
+ this.saveSession();
173
+ const sessions = this.getSessions();
174
+ return sessions.find(s => s.id === this.sessionId) || {
175
+ id: this.sessionId,
176
+ startTime: this.sessionStartTime,
177
+ endTime: new Date().toISOString(),
178
+ summary: 'Session ended',
179
+ changesCount: 0,
180
+ entities: []
181
+ };
182
+ }
183
+ /**
184
+ * Get recent activity summary
185
+ */
186
+ getRecentActivity(hours = 24) {
187
+ const cutoff = new Date(Date.now() - hours * 60 * 60 * 1000).toISOString();
188
+ return this.queryMemory({
189
+ timeRange: {
190
+ start: cutoff,
191
+ end: new Date().toISOString()
192
+ }
193
+ });
194
+ }
195
+ /**
196
+ * Get activity for a specific entity across all sessions
197
+ */
198
+ getEntityHistory(entityPattern) {
199
+ return this.queryMemory({ entityPattern });
200
+ }
201
+ generateSessionId() {
202
+ const timestamp = Date.now().toString(36);
203
+ const random = Math.random().toString(36).substring(2, 8);
204
+ return `session-${timestamp}-${random}`;
205
+ }
206
+ ensureMemoryDir() {
207
+ if (!fs.existsSync(this.memoryDir)) {
208
+ fs.mkdirSync(this.memoryDir, { recursive: true });
209
+ }
210
+ }
211
+ recordSessionStart() {
212
+ this.statecli.track('session', this.sessionId, {
213
+ event: 'start',
214
+ startTime: this.sessionStartTime
215
+ }, 'session-memory');
216
+ }
217
+ loadSessionData(sessionId) {
218
+ const sessionPath = path.join(this.memoryDir, `${sessionId}.session.json`);
219
+ try {
220
+ if (fs.existsSync(sessionPath)) {
221
+ return JSON.parse(fs.readFileSync(sessionPath, 'utf-8'));
222
+ }
223
+ }
224
+ catch {
225
+ // File might be corrupted
226
+ }
227
+ return null;
228
+ }
229
+ changeMatchesQuery(change, query) {
230
+ // Entity filter
231
+ if (query.entity && change.entity !== query.entity) {
232
+ return false;
233
+ }
234
+ // Entity pattern filter
235
+ if (query.entityPattern) {
236
+ const pattern = query.entityPattern.replace('*', '.*');
237
+ const regex = new RegExp(pattern);
238
+ if (!regex.test(change.entity)) {
239
+ return false;
240
+ }
241
+ }
242
+ // Time range filter
243
+ if (query.timeRange) {
244
+ const changeTime = new Date(change.timestamp).getTime();
245
+ const startTime = new Date(query.timeRange.start).getTime();
246
+ const endTime = new Date(query.timeRange.end).getTime();
247
+ if (changeTime < startTime || changeTime > endTime) {
248
+ return false;
249
+ }
250
+ }
251
+ // Actor filter
252
+ if (query.actor && change.actor !== query.actor) {
253
+ return false;
254
+ }
255
+ // Keyword filter (search in state values)
256
+ if (query.keyword) {
257
+ const stateStr = JSON.stringify(change.after).toLowerCase();
258
+ if (!stateStr.includes(query.keyword.toLowerCase())) {
259
+ return false;
260
+ }
261
+ }
262
+ return true;
263
+ }
264
+ parseQuestion(question) {
265
+ const query = {};
266
+ const lowerQ = question.toLowerCase();
267
+ // Parse time references
268
+ if (lowerQ.includes('yesterday')) {
269
+ const yesterday = new Date(Date.now() - 24 * 60 * 60 * 1000);
270
+ query.timeRange = {
271
+ start: yesterday.toISOString(),
272
+ end: new Date().toISOString()
273
+ };
274
+ }
275
+ else if (lowerQ.includes('last week')) {
276
+ const lastWeek = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
277
+ query.timeRange = {
278
+ start: lastWeek.toISOString(),
279
+ end: new Date().toISOString()
280
+ };
281
+ }
282
+ else if (lowerQ.includes('today')) {
283
+ const today = new Date();
284
+ today.setHours(0, 0, 0, 0);
285
+ query.timeRange = {
286
+ start: today.toISOString(),
287
+ end: new Date().toISOString()
288
+ };
289
+ }
290
+ // Parse entity references
291
+ const entityMatch = question.match(/(?:to|on|for|in)\s+(\w+[:\w]*)/i);
292
+ if (entityMatch) {
293
+ query.entityPattern = entityMatch[1].includes(':')
294
+ ? entityMatch[1]
295
+ : `${entityMatch[1]}:*`;
296
+ }
297
+ // Parse actor references
298
+ if (lowerQ.includes('i did') || lowerQ.includes('my ')) {
299
+ query.actor = 'ai-agent';
300
+ }
301
+ return query;
302
+ }
303
+ createQuerySummary(query, sessions, changes) {
304
+ const lines = [];
305
+ lines.push(`Memory Query Results`);
306
+ lines.push(`====================`);
307
+ lines.push(`Found ${changes.length} changes across ${sessions.length} sessions`);
308
+ if (query.timeRange) {
309
+ lines.push(`Time range: ${query.timeRange.start} to ${query.timeRange.end}`);
310
+ }
311
+ if (query.entityPattern) {
312
+ lines.push(`Entity pattern: ${query.entityPattern}`);
313
+ }
314
+ if (changes.length > 0) {
315
+ lines.push(``);
316
+ lines.push(`Recent changes:`);
317
+ for (const change of changes.slice(-5)) {
318
+ lines.push(` - ${change.timestamp}: ${change.entity} (${change.actor})`);
319
+ }
320
+ }
321
+ return lines.join('\n');
322
+ }
323
+ }
324
+ exports.SessionMemory = SessionMemory;
325
+ //# sourceMappingURL=session-memory.js.map