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.
- package/README.md +334 -153
- package/dist/enhanced-mcp-server.d.ts +35 -0
- package/dist/enhanced-mcp-server.d.ts.map +1 -0
- package/dist/enhanced-mcp-server.js +425 -0
- package/dist/enhanced-mcp-server.js.map +1 -0
- package/dist/error-recovery.d.ts +66 -0
- package/dist/error-recovery.d.ts.map +1 -0
- package/dist/error-recovery.js +210 -0
- package/dist/error-recovery.js.map +1 -0
- package/dist/file-tracker.d.ts +81 -0
- package/dist/file-tracker.d.ts.map +1 -0
- package/dist/file-tracker.js +252 -0
- package/dist/file-tracker.js.map +1 -0
- package/dist/git-integration.d.ts +95 -0
- package/dist/git-integration.d.ts.map +1 -0
- package/dist/git-integration.js +219 -0
- package/dist/git-integration.js.map +1 -0
- package/dist/index-enhanced.d.ts +12 -0
- package/dist/index-enhanced.d.ts.map +1 -0
- package/dist/index-enhanced.js +27 -0
- package/dist/index-enhanced.js.map +1 -0
- package/dist/session-memory.d.ts +85 -0
- package/dist/session-memory.d.ts.map +1 -0
- package/dist/session-memory.js +325 -0
- package/dist/session-memory.js.map +1 -0
- package/dist/types.d.ts +11 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +3 -2
|
@@ -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
|