@loom-framework/backend 0.1.0-alpha.1 → 0.1.0-alpha.10
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/ai/button-resolver.d.ts +17 -0
- package/dist/ai/button-resolver.d.ts.map +1 -0
- package/dist/ai/button-resolver.js +40 -0
- package/dist/ai/button-resolver.js.map +1 -0
- package/dist/ai/engine.d.ts +14 -0
- package/dist/ai/engine.d.ts.map +1 -1
- package/dist/ai/engine.js +74 -23
- package/dist/ai/engine.js.map +1 -1
- package/dist/ai/index.d.ts +3 -1
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/index.js +1 -0
- package/dist/ai/index.js.map +1 -1
- package/dist/ai/output-parser.d.ts +14 -7
- package/dist/ai/output-parser.d.ts.map +1 -1
- package/dist/ai/output-parser.js +126 -117
- package/dist/ai/output-parser.js.map +1 -1
- package/dist/ai/session-manager.d.ts +11 -2
- package/dist/ai/session-manager.d.ts.map +1 -1
- package/dist/ai/session-manager.js +88 -12
- package/dist/ai/session-manager.js.map +1 -1
- package/dist/bin.js +0 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -7
- package/dist/index.js.map +1 -1
- package/dist/routes/chat.d.ts +31 -0
- package/dist/routes/chat.d.ts.map +1 -0
- package/dist/routes/chat.js +216 -0
- package/dist/routes/chat.js.map +1 -0
- package/dist/routes/index.d.ts +3 -0
- package/dist/routes/index.d.ts.map +1 -1
- package/dist/routes/index.js +2 -0
- package/dist/routes/index.js.map +1 -1
- package/dist/routes/upload.d.ts +24 -0
- package/dist/routes/upload.d.ts.map +1 -0
- package/dist/routes/upload.js +67 -0
- package/dist/routes/upload.js.map +1 -0
- package/package.json +12 -13
- package/dist/websocket/index.d.ts +0 -32
- package/dist/websocket/index.d.ts.map +0 -1
- package/dist/websocket/index.js +0 -320
- package/dist/websocket/index.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output-parser.js","sourceRoot":"","sources":["../../src/ai/output-parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"output-parser.js","sourceRoot":"","sources":["../../src/ai/output-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -33,10 +33,12 @@ export declare class SessionManager {
|
|
|
33
33
|
private sessionsDir;
|
|
34
34
|
/** In-memory index of active sessions for stale detection */
|
|
35
35
|
private activeIndex;
|
|
36
|
+
/** In-memory session index for fast listing */
|
|
37
|
+
private sessionIndex;
|
|
36
38
|
private cleanupTimer?;
|
|
37
39
|
constructor(projectRoot: string);
|
|
38
40
|
/**
|
|
39
|
-
* Ensure sessions directory exists
|
|
41
|
+
* Ensure sessions directory exists and load index
|
|
40
42
|
*/
|
|
41
43
|
initialize(): Promise<void>;
|
|
42
44
|
/**
|
|
@@ -60,9 +62,13 @@ export declare class SessionManager {
|
|
|
60
62
|
*/
|
|
61
63
|
addMessages(id: string, messages: SessionMessage[], claudeSessionId?: string, usage?: AIUsage): Promise<SessionRecord>;
|
|
62
64
|
/**
|
|
63
|
-
* List all sessions sorted by most recent first
|
|
65
|
+
* List all sessions sorted by most recent first (from index, O(1))
|
|
64
66
|
*/
|
|
65
67
|
listSessions(): Promise<SessionRecord[]>;
|
|
68
|
+
/**
|
|
69
|
+
* List full session records from files (fallback, used during initialization)
|
|
70
|
+
*/
|
|
71
|
+
private listSessionsFromFiles;
|
|
66
72
|
/**
|
|
67
73
|
* Delete a session
|
|
68
74
|
*/
|
|
@@ -77,5 +83,8 @@ export declare class SessionManager {
|
|
|
77
83
|
private cleanStaleSessions;
|
|
78
84
|
private getSessionPath;
|
|
79
85
|
private writeSessionFile;
|
|
86
|
+
private getIndexFilePath;
|
|
87
|
+
private loadIndex;
|
|
88
|
+
private saveIndex;
|
|
80
89
|
}
|
|
81
90
|
//# sourceMappingURL=session-manager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../../src/ai/session-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAiB,OAAO,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../../src/ai/session-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAiB,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAmBnE,6BAA6B;AAC7B,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,WAAW,CAAS;IAC5B,6DAA6D;IAC7D,OAAO,CAAC,WAAW,CAAyC;IAC5D,+CAA+C;IAC/C,OAAO,CAAC,YAAY,CAAmD;IACvE,OAAO,CAAC,YAAY,CAAC,CAAiC;gBAE1C,WAAW,EAAE,MAAM;IAI/B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA+BjC;;OAEG;IACH,YAAY,CAAC,UAAU,GAAE,MAAe,GAAG,IAAI;IAM/C;;OAEG;IACH,WAAW,IAAI,IAAI;IAOnB;;OAEG;IACG,aAAa,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAgCxD;;OAEG;IACG,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAU5D;;OAEG;IACG,WAAW,CACf,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,cAAc,EAAE,EAC1B,eAAe,CAAC,EAAE,MAAM,EACxB,KAAK,CAAC,EAAE,OAAO,GACd,OAAO,CAAC,aAAa,CAAC;IA8CzB;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;IAiB9C;;OAEG;YACW,qBAAqB;IA2BnC;;OAEG;IACG,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAiBjD;;OAEG;IACG,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAMrD;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAS1B,OAAO,CAAC,cAAc;YAIR,gBAAgB;IAM9B,OAAO,CAAC,gBAAgB;YAIV,SAAS;YAUT,SAAS;CAYxB"}
|
|
@@ -12,24 +12,39 @@ export class SessionManager {
|
|
|
12
12
|
sessionsDir;
|
|
13
13
|
/** In-memory index of active sessions for stale detection */
|
|
14
14
|
activeIndex = new Map();
|
|
15
|
+
/** In-memory session index for fast listing */
|
|
16
|
+
sessionIndex = { sessions: [], lastUpdated: '' };
|
|
15
17
|
cleanupTimer;
|
|
16
18
|
constructor(projectRoot) {
|
|
17
19
|
this.sessionsDir = path.join(projectRoot, '.loom', 'sessions');
|
|
18
20
|
}
|
|
19
21
|
/**
|
|
20
|
-
* Ensure sessions directory exists
|
|
22
|
+
* Ensure sessions directory exists and load index
|
|
21
23
|
*/
|
|
22
24
|
async initialize() {
|
|
23
25
|
await fs.mkdir(this.sessionsDir, { recursive: true });
|
|
24
|
-
//
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
this.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
// Try to load index from disk
|
|
27
|
+
const indexLoaded = await this.loadIndex();
|
|
28
|
+
if (!indexLoaded) {
|
|
29
|
+
// Fallback: rebuild index from session files
|
|
30
|
+
const sessions = await this.listSessionsFromFiles();
|
|
31
|
+
this.sessionIndex = {
|
|
32
|
+
sessions: sessions.map((s) => ({
|
|
33
|
+
id: s.id,
|
|
34
|
+
title: s.title,
|
|
35
|
+
updatedAt: s.updatedAt,
|
|
36
|
+
createdAt: s.createdAt,
|
|
37
|
+
})),
|
|
38
|
+
lastUpdated: new Date().toISOString(),
|
|
39
|
+
};
|
|
40
|
+
await this.saveIndex();
|
|
41
|
+
}
|
|
42
|
+
// Load into active index for stale detection
|
|
43
|
+
for (const entry of this.sessionIndex.sessions) {
|
|
44
|
+
this.activeIndex.set(entry.id, {
|
|
45
|
+
id: entry.id,
|
|
46
|
+
lastActivity: new Date(entry.updatedAt).getTime(),
|
|
47
|
+
createdAt: new Date(entry.createdAt).getTime(),
|
|
33
48
|
});
|
|
34
49
|
}
|
|
35
50
|
}
|
|
@@ -69,6 +84,15 @@ export class SessionManager {
|
|
|
69
84
|
lastActivity: Date.now(),
|
|
70
85
|
createdAt: Date.now(),
|
|
71
86
|
});
|
|
87
|
+
// Update index
|
|
88
|
+
this.sessionIndex.sessions.push({
|
|
89
|
+
id: sessionId,
|
|
90
|
+
title: session.title,
|
|
91
|
+
updatedAt: session.updatedAt,
|
|
92
|
+
createdAt: session.createdAt,
|
|
93
|
+
});
|
|
94
|
+
this.sessionIndex.lastUpdated = new Date().toISOString();
|
|
95
|
+
await this.saveIndex();
|
|
72
96
|
return session;
|
|
73
97
|
}
|
|
74
98
|
/**
|
|
@@ -115,16 +139,43 @@ export class SessionManager {
|
|
|
115
139
|
lastActivity: Date.now(),
|
|
116
140
|
createdAt: new Date(session.createdAt).getTime(),
|
|
117
141
|
});
|
|
142
|
+
// Sync index entry (title may have changed)
|
|
143
|
+
const idxEntry = this.sessionIndex.sessions.find((e) => e.id === id);
|
|
144
|
+
if (idxEntry) {
|
|
145
|
+
idxEntry.title = session.title;
|
|
146
|
+
idxEntry.updatedAt = session.updatedAt;
|
|
147
|
+
}
|
|
148
|
+
this.sessionIndex.lastUpdated = new Date().toISOString();
|
|
149
|
+
await this.saveIndex();
|
|
118
150
|
return session;
|
|
119
151
|
}
|
|
120
152
|
/**
|
|
121
|
-
* List all sessions sorted by most recent first
|
|
153
|
+
* List all sessions sorted by most recent first (from index, O(1))
|
|
122
154
|
*/
|
|
123
155
|
async listSessions() {
|
|
156
|
+
// Use index for fast path: only return summary data
|
|
157
|
+
// For full records, callers should use readSession(id)
|
|
158
|
+
const entries = [...this.sessionIndex.sessions];
|
|
159
|
+
entries.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());
|
|
160
|
+
// Map index entries to minimal SessionRecord shape
|
|
161
|
+
return entries.map((e) => ({
|
|
162
|
+
id: e.id,
|
|
163
|
+
title: e.title,
|
|
164
|
+
createdAt: e.createdAt,
|
|
165
|
+
updatedAt: e.updatedAt,
|
|
166
|
+
messages: [],
|
|
167
|
+
}));
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* List full session records from files (fallback, used during initialization)
|
|
171
|
+
*/
|
|
172
|
+
async listSessionsFromFiles() {
|
|
124
173
|
try {
|
|
125
174
|
const files = await fs.readdir(this.sessionsDir);
|
|
126
175
|
const sessions = [];
|
|
127
176
|
for (const file of files) {
|
|
177
|
+
if (file === 'index.json')
|
|
178
|
+
continue;
|
|
128
179
|
if (!file.endsWith('.json'))
|
|
129
180
|
continue;
|
|
130
181
|
const filePath = path.join(this.sessionsDir, file);
|
|
@@ -136,7 +187,6 @@ export class SessionManager {
|
|
|
136
187
|
// Skip malformed files
|
|
137
188
|
}
|
|
138
189
|
}
|
|
139
|
-
// Sort by updatedAt descending
|
|
140
190
|
sessions.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());
|
|
141
191
|
return sessions;
|
|
142
192
|
}
|
|
@@ -152,6 +202,10 @@ export class SessionManager {
|
|
|
152
202
|
try {
|
|
153
203
|
await fs.unlink(filePath);
|
|
154
204
|
this.activeIndex.delete(id);
|
|
205
|
+
// Sync index
|
|
206
|
+
this.sessionIndex.sessions = this.sessionIndex.sessions.filter((e) => e.id !== id);
|
|
207
|
+
this.sessionIndex.lastUpdated = new Date().toISOString();
|
|
208
|
+
await this.saveIndex();
|
|
155
209
|
return true;
|
|
156
210
|
}
|
|
157
211
|
catch {
|
|
@@ -186,6 +240,28 @@ export class SessionManager {
|
|
|
186
240
|
await fs.mkdir(this.sessionsDir, { recursive: true });
|
|
187
241
|
await fs.writeFile(filePath, JSON.stringify(session, null, 2), 'utf-8');
|
|
188
242
|
}
|
|
243
|
+
getIndexFilePath() {
|
|
244
|
+
return path.join(this.sessionsDir, 'index.json');
|
|
245
|
+
}
|
|
246
|
+
async loadIndex() {
|
|
247
|
+
try {
|
|
248
|
+
const content = await fs.readFile(this.getIndexFilePath(), 'utf-8');
|
|
249
|
+
this.sessionIndex = JSON.parse(content);
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
catch {
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
async saveIndex() {
|
|
257
|
+
try {
|
|
258
|
+
await fs.mkdir(this.sessionsDir, { recursive: true });
|
|
259
|
+
await fs.writeFile(this.getIndexFilePath(), JSON.stringify(this.sessionIndex, null, 2), 'utf-8');
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
// Non-critical: index is in-memory, will rebuild on next init
|
|
263
|
+
}
|
|
264
|
+
}
|
|
189
265
|
}
|
|
190
266
|
function generateSessionId() {
|
|
191
267
|
return `session_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-manager.js","sourceRoot":"","sources":["../../src/ai/session-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,IAAI,MAAM,MAAM,CAAC;AAGxB,0CAA0C;AAC1C,MAAM,gBAAgB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"session-manager.js","sourceRoot":"","sources":["../../src/ai/session-manager.ts"],"names":[],"mappings":"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"}
|
package/dist/bin.js
CHANGED
|
File without changes
|
package/dist/index.d.ts
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* @loom-framework/backend - Main Server
|
|
3
3
|
*
|
|
4
4
|
* Assembles Fastify server with:
|
|
5
|
-
* -
|
|
6
|
-
* - REST routes for DataAdapter CRUD + health check
|
|
5
|
+
* - HTTP SSE chat route (Ant Design X compatible)
|
|
6
|
+
* - REST routes for DataAdapter CRUD + health check + sessions
|
|
7
7
|
* - Static file serving for production mode
|
|
8
8
|
* - Configuration from loom.config.ts
|
|
9
9
|
*/
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,OAAO,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,OAAO,MAAM,SAAS,CAAC;AAK9B,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAS5F,MAAM,WAAW,iBAAiB;IAChC,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,YAAY,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IACrC,kEAAkE;IAClE,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,qEAAqE;IACrE,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,mBAAmB;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,iBAAiB,CAAuB;IAChD,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,OAAO,CAAoB;gBAEvB,OAAO,EAAE,iBAAiB;IAKtC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA2EjC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B,0CAA0C;IAC1C,UAAU,IAAI,UAAU,CAAC,OAAO,OAAO,CAAC;IAIxC,gCAAgC;IAChC,SAAS,IAAI,UAAU;IAIvB,iCAAiC;IACjC,UAAU,IAAI,WAAW;IAIzB;;OAEG;IACH,OAAO,CAAC,aAAa;CAUtB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAK1E"}
|
package/dist/index.js
CHANGED
|
@@ -2,14 +2,13 @@
|
|
|
2
2
|
* @loom-framework/backend - Main Server
|
|
3
3
|
*
|
|
4
4
|
* Assembles Fastify server with:
|
|
5
|
-
* -
|
|
6
|
-
* - REST routes for DataAdapter CRUD + health check
|
|
5
|
+
* - HTTP SSE chat route (Ant Design X compatible)
|
|
6
|
+
* - REST routes for DataAdapter CRUD + health check + sessions
|
|
7
7
|
* - Static file serving for production mode
|
|
8
8
|
* - Configuration from loom.config.ts
|
|
9
9
|
*/
|
|
10
10
|
import Fastify from 'fastify';
|
|
11
11
|
import cors from '@fastify/cors';
|
|
12
|
-
import websocket from '@fastify/websocket';
|
|
13
12
|
import staticPlugin from '@fastify/static';
|
|
14
13
|
import path from 'path';
|
|
15
14
|
import { FileSystemAdapter, loadConfig } from '@loom-framework/core';
|
|
@@ -17,8 +16,7 @@ import { SQLiteAdapter } from '@loom-framework/core';
|
|
|
17
16
|
import { ClaudeCodeEngine } from './ai/engine.js';
|
|
18
17
|
import { SessionManager } from './ai/session-manager.js';
|
|
19
18
|
import { AIInteractionLogger } from './observe/index.js';
|
|
20
|
-
import {
|
|
21
|
-
import { registerDataRoutes, registerHealthRoute } from './routes/index.js';
|
|
19
|
+
import { registerDataRoutes, registerHealthRoute, registerUploadRoutes, registerChatRoutes } from './routes/index.js';
|
|
22
20
|
export class LoomServer {
|
|
23
21
|
config;
|
|
24
22
|
engine;
|
|
@@ -67,7 +65,6 @@ export class LoomServer {
|
|
|
67
65
|
if (serverConfig.cors !== false) {
|
|
68
66
|
await this.fastify.register(cors, { origin: true });
|
|
69
67
|
}
|
|
70
|
-
await this.fastify.register(websocket);
|
|
71
68
|
// Static file serving in production
|
|
72
69
|
if (serverConfig.staticDir) {
|
|
73
70
|
const staticDir = path.resolve(this.projectRoot, serverConfig.staticDir);
|
|
@@ -80,11 +77,13 @@ export class LoomServer {
|
|
|
80
77
|
// Register routes
|
|
81
78
|
registerHealthRoute(this.fastify, this.adapter);
|
|
82
79
|
registerDataRoutes(this.fastify, this.adapter);
|
|
83
|
-
|
|
80
|
+
registerUploadRoutes(this.fastify, { projectRoot: this.projectRoot });
|
|
81
|
+
registerChatRoutes(this.fastify, {
|
|
84
82
|
engine: this.engine,
|
|
85
83
|
sessionManager: this.sessionManager,
|
|
86
84
|
config: this.config,
|
|
87
85
|
logger: this.interactionLogger,
|
|
86
|
+
projectRoot: this.projectRoot,
|
|
88
87
|
});
|
|
89
88
|
// Graceful shutdown handlers
|
|
90
89
|
const cleanup = async () => {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,IAAI,MAAM,eAAe,CAAC;AACjC,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chat SSE Route - HTTP Server-Sent Events streaming for AI chat
|
|
3
|
+
*
|
|
4
|
+
* Replaces WebSocket with HTTP SSE for AI conversation streaming.
|
|
5
|
+
* Ant Design X (useXChat + XRequest) natively consumes this format.
|
|
6
|
+
*
|
|
7
|
+
* POST /api/v1/chat
|
|
8
|
+
* Body: { content, session_id, button_id?, context?, files? }
|
|
9
|
+
* Response: SSE stream with data lines containing JSON chunks
|
|
10
|
+
*
|
|
11
|
+
* GET /api/v1/sessions - List sessions
|
|
12
|
+
* POST /api/v1/sessions - Create session
|
|
13
|
+
* GET /api/v1/sessions/:id - Load session
|
|
14
|
+
* DELETE /api/v1/sessions/:id - Delete session
|
|
15
|
+
*/
|
|
16
|
+
import type { FastifyInstance } from 'fastify';
|
|
17
|
+
import type { AIEngine, LoomConfig } from '@loom-framework/core';
|
|
18
|
+
import { SessionManager } from '../ai/session-manager.js';
|
|
19
|
+
import { AIInteractionLogger } from '../observe/index.js';
|
|
20
|
+
export interface ChatRouteOptions {
|
|
21
|
+
engine: AIEngine;
|
|
22
|
+
sessionManager: SessionManager;
|
|
23
|
+
config: LoomConfig;
|
|
24
|
+
logger?: AIInteractionLogger;
|
|
25
|
+
projectRoot: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Register chat SSE route and session REST routes
|
|
29
|
+
*/
|
|
30
|
+
export declare function registerChatRoutes(fastify: FastifyInstance, options: ChatRouteOptions): void;
|
|
31
|
+
//# sourceMappingURL=chat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/routes/chat.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAgC,MAAM,SAAS,CAAC;AAC7E,OAAO,KAAK,EACV,QAAQ,EACR,UAAU,EAEX,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAuB,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EAAE,mBAAmB,EAAyB,MAAM,qBAAqB,CAAC;AAIjF,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,QAAQ,CAAC;IACjB,cAAc,EAAE,cAAc,CAAC;IAC/B,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;CACrB;AAqDD;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,gBAAgB,GACxB,IAAI,CAgKN"}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chat SSE Route - HTTP Server-Sent Events streaming for AI chat
|
|
3
|
+
*
|
|
4
|
+
* Replaces WebSocket with HTTP SSE for AI conversation streaming.
|
|
5
|
+
* Ant Design X (useXChat + XRequest) natively consumes this format.
|
|
6
|
+
*
|
|
7
|
+
* POST /api/v1/chat
|
|
8
|
+
* Body: { content, session_id, button_id?, context?, files? }
|
|
9
|
+
* Response: SSE stream with data lines containing JSON chunks
|
|
10
|
+
*
|
|
11
|
+
* GET /api/v1/sessions - List sessions
|
|
12
|
+
* POST /api/v1/sessions - Create session
|
|
13
|
+
* GET /api/v1/sessions/:id - Load session
|
|
14
|
+
* DELETE /api/v1/sessions/:id - Delete session
|
|
15
|
+
*/
|
|
16
|
+
import { saveUploadedFile } from './upload.js';
|
|
17
|
+
import { resolveButtonPrompt } from '../ai/button-resolver.js';
|
|
18
|
+
// ── Route Registration ──
|
|
19
|
+
/**
|
|
20
|
+
* Register chat SSE route and session REST routes
|
|
21
|
+
*/
|
|
22
|
+
export function registerChatRoutes(fastify, options) {
|
|
23
|
+
const { engine, sessionManager, config, logger, projectRoot } = options;
|
|
24
|
+
// POST /api/v1/chat — SSE streaming AI response
|
|
25
|
+
fastify.post('/api/v1/chat', async (request, reply) => {
|
|
26
|
+
const body = request.body;
|
|
27
|
+
const { content, session_id, button_id, context, files } = body;
|
|
28
|
+
if (!content && !button_id) {
|
|
29
|
+
return reply.status(400).send({ error: 'content or button_id is required' });
|
|
30
|
+
}
|
|
31
|
+
if (!session_id) {
|
|
32
|
+
return reply.status(400).send({ error: 'session_id is required' });
|
|
33
|
+
}
|
|
34
|
+
// Set SSE headers
|
|
35
|
+
reply.raw.writeHead(200, {
|
|
36
|
+
'Content-Type': 'text/event-stream',
|
|
37
|
+
'Cache-Control': 'no-cache',
|
|
38
|
+
Connection: 'keep-alive',
|
|
39
|
+
'X-Accel-Buffering': 'no', // Disable nginx buffering
|
|
40
|
+
});
|
|
41
|
+
const messageId = generateMessageId();
|
|
42
|
+
const startTime = Date.now();
|
|
43
|
+
// Handle file uploads
|
|
44
|
+
const uploadedFiles = [];
|
|
45
|
+
if (files && files.length > 0 && projectRoot) {
|
|
46
|
+
for (const file of files) {
|
|
47
|
+
if (file.content) {
|
|
48
|
+
try {
|
|
49
|
+
const result = await saveUploadedFile(projectRoot, session_id, file.name, file.content);
|
|
50
|
+
uploadedFiles.push({ name: file.name, path: result.path });
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
fastify.log.warn('Failed to save uploaded file %s: %s', file.name, err);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Resolve prompt: AI button or direct content
|
|
59
|
+
let prompt;
|
|
60
|
+
if (button_id) {
|
|
61
|
+
const resolved = resolveButtonPrompt(button_id, context, config);
|
|
62
|
+
if (!resolved) {
|
|
63
|
+
sendSSE(reply, { type: 'error', error: `AI button "${button_id}" not found`, message_id: messageId, session_id });
|
|
64
|
+
endSSE(reply);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (resolved.error) {
|
|
68
|
+
sendSSE(reply, { type: 'error', error: resolved.error, message_id: messageId, session_id });
|
|
69
|
+
endSSE(reply);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
prompt = resolved.prompt;
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
prompt = content;
|
|
76
|
+
}
|
|
77
|
+
// Get or create session
|
|
78
|
+
const session = await sessionManager.getOrCreate(session_id);
|
|
79
|
+
// Add user message to session
|
|
80
|
+
const userMsg = {
|
|
81
|
+
id: messageId,
|
|
82
|
+
role: 'user',
|
|
83
|
+
content: prompt,
|
|
84
|
+
timestamp: new Date().toISOString(),
|
|
85
|
+
files: files?.map((f) => ({ uid: f.uid, name: f.name, size: f.size, type: f.type })),
|
|
86
|
+
};
|
|
87
|
+
await sessionManager.addMessages(session_id, [userMsg]);
|
|
88
|
+
// Call AI engine and stream chunks
|
|
89
|
+
let aiContent = '';
|
|
90
|
+
let claudeSessionId;
|
|
91
|
+
let usage;
|
|
92
|
+
try {
|
|
93
|
+
for await (const chunk of engine.call(prompt, {
|
|
94
|
+
sessionId: session_id,
|
|
95
|
+
resumeSessionId: session.claudeSessionId,
|
|
96
|
+
files: uploadedFiles.length > 0 ? uploadedFiles : undefined,
|
|
97
|
+
})) {
|
|
98
|
+
if (chunk.type === 'content' && chunk.content) {
|
|
99
|
+
aiContent += chunk.content;
|
|
100
|
+
sendSSE(reply, { type: 'chunk', content: chunk.content, message_id: messageId, session_id });
|
|
101
|
+
}
|
|
102
|
+
else if (chunk.type === 'session_info') {
|
|
103
|
+
claudeSessionId = chunk.sessionId;
|
|
104
|
+
if (chunk.usage)
|
|
105
|
+
usage = chunk.usage;
|
|
106
|
+
}
|
|
107
|
+
else if (chunk.type === 'error' && chunk.error) {
|
|
108
|
+
sendSSE(reply, { type: 'error', error: chunk.error, message_id: messageId, session_id });
|
|
109
|
+
}
|
|
110
|
+
else if (chunk.type === 'tool_call') {
|
|
111
|
+
sendSSE(reply, { type: 'tool_call', tool: chunk.toolName || 'unknown', status: 'started' });
|
|
112
|
+
}
|
|
113
|
+
else if (chunk.type === 'tool_result') {
|
|
114
|
+
sendSSE(reply, { type: 'tool_call', tool: chunk.toolName || 'unknown', status: 'completed', result: chunk.toolResult });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
fastify.log.error('AI engine exception: %s', error);
|
|
120
|
+
recordLog(logger, session_id, messageId, prompt, '', startTime, [], [], error instanceof Error ? error.message : String(error), fastify);
|
|
121
|
+
sendSSE(reply, { type: 'error', error: `Processing error: ${error}`, message_id: messageId, session_id });
|
|
122
|
+
endSSE(reply);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
// Send completion
|
|
126
|
+
const completePayload = {
|
|
127
|
+
type: 'done',
|
|
128
|
+
content: aiContent || '(empty response)',
|
|
129
|
+
message_id: messageId,
|
|
130
|
+
session_id,
|
|
131
|
+
};
|
|
132
|
+
if (claudeSessionId)
|
|
133
|
+
completePayload.claude_session_id = claudeSessionId;
|
|
134
|
+
if (usage)
|
|
135
|
+
completePayload.usage = usage;
|
|
136
|
+
sendSSE(reply, completePayload);
|
|
137
|
+
// Persist assistant message
|
|
138
|
+
const assistantMsg = {
|
|
139
|
+
id: messageId,
|
|
140
|
+
role: 'assistant',
|
|
141
|
+
content: aiContent || '(empty response)',
|
|
142
|
+
timestamp: new Date().toISOString(),
|
|
143
|
+
};
|
|
144
|
+
await sessionManager.addMessages(session_id, [assistantMsg], claudeSessionId, usage);
|
|
145
|
+
// Record log
|
|
146
|
+
recordLog(logger, session_id, messageId, prompt, aiContent || '(empty response)', startTime, [], [], undefined, fastify, usage);
|
|
147
|
+
endSSE(reply);
|
|
148
|
+
});
|
|
149
|
+
// GET /api/v1/sessions — List sessions
|
|
150
|
+
fastify.get('/api/v1/sessions', async (_request, reply) => {
|
|
151
|
+
const sessions = await sessionManager.listSessions();
|
|
152
|
+
return reply.send(sessions);
|
|
153
|
+
});
|
|
154
|
+
// POST /api/v1/sessions — Create session
|
|
155
|
+
fastify.post('/api/v1/sessions', async (request, reply) => {
|
|
156
|
+
const body = request.body;
|
|
157
|
+
const session = await sessionManager.createSession(body?.id);
|
|
158
|
+
return reply.code(201).send(session);
|
|
159
|
+
});
|
|
160
|
+
// GET /api/v1/sessions/:id — Load session
|
|
161
|
+
fastify.get('/api/v1/sessions/:id', async (request, reply) => {
|
|
162
|
+
const { id } = request.params;
|
|
163
|
+
const session = await sessionManager.readSession(id);
|
|
164
|
+
if (!session)
|
|
165
|
+
return reply.status(404).send({ error: 'Session not found' });
|
|
166
|
+
return reply.send(session);
|
|
167
|
+
});
|
|
168
|
+
// DELETE /api/v1/sessions/:id — Delete session
|
|
169
|
+
fastify.delete('/api/v1/sessions/:id', async (request, reply) => {
|
|
170
|
+
const { id } = request.params;
|
|
171
|
+
const success = await sessionManager.deleteSession(id);
|
|
172
|
+
if (!success)
|
|
173
|
+
return reply.status(404).send({ error: 'Session not found' });
|
|
174
|
+
return reply.send({ success: true });
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
// ── SSE Helpers ──
|
|
178
|
+
function sendSSE(reply, event) {
|
|
179
|
+
try {
|
|
180
|
+
reply.raw.write(`data: ${JSON.stringify(event)}\n\n`);
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
// Client may have disconnected
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
function endSSE(reply) {
|
|
187
|
+
try {
|
|
188
|
+
reply.raw.end();
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
// Already closed
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
function generateMessageId() {
|
|
195
|
+
return `msg_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
|
|
196
|
+
}
|
|
197
|
+
function recordLog(logger, sessionId, messageId, prompt, response, startTime, mcpCalls, cliCalls, error, fastify, usage) {
|
|
198
|
+
if (!logger)
|
|
199
|
+
return;
|
|
200
|
+
const logEntry = {
|
|
201
|
+
sessionId,
|
|
202
|
+
messageId,
|
|
203
|
+
timestamp: new Date().toISOString(),
|
|
204
|
+
prompt,
|
|
205
|
+
response,
|
|
206
|
+
duration: Date.now() - startTime,
|
|
207
|
+
usage: usage ? { inputTokens: usage.inputTokens, outputTokens: usage.outputTokens } : undefined,
|
|
208
|
+
mcpCalls,
|
|
209
|
+
cliCalls,
|
|
210
|
+
error,
|
|
211
|
+
};
|
|
212
|
+
logger.log(logEntry).catch((err) => {
|
|
213
|
+
fastify.log.warn('Failed to write interaction log: %s', err);
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=chat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat.js","sourceRoot":"","sources":["../../src/routes/chat.ts"],"names":[],"mappings":"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"}
|