antri_cli 1.50.0 → 1.52.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/shortcuts.d.ts.map +1 -1
- package/dist/cli/shortcuts.js +57 -0
- package/dist/cli/shortcuts.js.map +1 -1
- package/dist/cloud/firestore.d.ts +7 -0
- package/dist/cloud/firestore.d.ts.map +1 -1
- package/dist/cloud/firestore.js +17 -0
- package/dist/cloud/firestore.js.map +1 -1
- package/dist/core/agent.d.ts +1 -0
- package/dist/core/agent.d.ts.map +1 -1
- package/dist/core/agent.js +19 -6
- package/dist/core/agent.js.map +1 -1
- package/dist/core/config.js +1 -1
- package/dist/core/history.d.ts +1 -0
- package/dist/core/history.d.ts.map +1 -1
- package/dist/core/history.js +3 -0
- package/dist/core/history.js.map +1 -1
- package/dist/core/sessionManager.d.ts +23 -0
- package/dist/core/sessionManager.d.ts.map +1 -0
- package/dist/core/sessionManager.js +188 -0
- package/dist/core/sessionManager.js.map +1 -0
- package/dist/core/updater.d.ts +1 -1
- package/dist/core/updater.js +1 -1
- package/dist/desktop/public/app.js +150 -2
- package/dist/desktop/public/index.html +16 -2
- package/dist/desktop/public/style.css +79 -0
- package/dist/desktop/server.d.ts.map +1 -1
- package/dist/desktop/server.js +48 -0
- package/dist/desktop/server.js.map +1 -1
- package/dist/profiles/profileManager.d.ts.map +1 -1
- package/dist/profiles/profileManager.js +48 -32
- package/dist/profiles/profileManager.js.map +1 -1
- package/dist/types.d.ts +16 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
const CHATS_DIR = path.join(os.homedir(), '.antri', 'chats');
|
|
5
|
+
const ACTIVE_SESSION_FILE = path.join(CHATS_DIR, '.active_session');
|
|
6
|
+
export class SessionManager {
|
|
7
|
+
chatsDir;
|
|
8
|
+
activeSessionId = '';
|
|
9
|
+
constructor(customDir) {
|
|
10
|
+
this.chatsDir = customDir || CHATS_DIR;
|
|
11
|
+
this.ensureDirectory();
|
|
12
|
+
this.initActiveSession();
|
|
13
|
+
}
|
|
14
|
+
ensureDirectory() {
|
|
15
|
+
if (!fs.existsSync(this.chatsDir)) {
|
|
16
|
+
fs.mkdirSync(this.chatsDir, { recursive: true });
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
initActiveSession() {
|
|
20
|
+
try {
|
|
21
|
+
if (fs.existsSync(ACTIVE_SESSION_FILE)) {
|
|
22
|
+
const id = fs.readFileSync(ACTIVE_SESSION_FILE, 'utf-8').trim();
|
|
23
|
+
if (id && fs.existsSync(this.getSessionFilePath(id))) {
|
|
24
|
+
this.activeSessionId = id;
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
catch { }
|
|
30
|
+
// Pick first existing session or create a default session
|
|
31
|
+
const sessions = this.listSessions();
|
|
32
|
+
if (sessions.length > 0) {
|
|
33
|
+
this.activeSessionId = sessions[0].id;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
const newSession = this.createSession('New Chat');
|
|
37
|
+
this.activeSessionId = newSession.id;
|
|
38
|
+
}
|
|
39
|
+
this.saveActiveSessionId();
|
|
40
|
+
}
|
|
41
|
+
getSessionFilePath(id) {
|
|
42
|
+
const cleanId = id.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
43
|
+
return path.join(this.chatsDir, `${cleanId}.json`);
|
|
44
|
+
}
|
|
45
|
+
saveActiveSessionId() {
|
|
46
|
+
try {
|
|
47
|
+
this.ensureDirectory();
|
|
48
|
+
fs.writeFileSync(ACTIVE_SESSION_FILE, this.activeSessionId, 'utf-8');
|
|
49
|
+
}
|
|
50
|
+
catch { }
|
|
51
|
+
}
|
|
52
|
+
getActiveSessionId() {
|
|
53
|
+
return this.activeSessionId;
|
|
54
|
+
}
|
|
55
|
+
setActiveSessionId(id) {
|
|
56
|
+
const session = this.getSession(id);
|
|
57
|
+
if (session) {
|
|
58
|
+
this.activeSessionId = id;
|
|
59
|
+
this.saveActiveSessionId();
|
|
60
|
+
return session;
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
createSession(title = 'New Chat') {
|
|
65
|
+
this.ensureDirectory();
|
|
66
|
+
const id = `chat_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;
|
|
67
|
+
const session = {
|
|
68
|
+
id,
|
|
69
|
+
title,
|
|
70
|
+
createdAt: Date.now(),
|
|
71
|
+
updatedAt: Date.now(),
|
|
72
|
+
messages: [],
|
|
73
|
+
};
|
|
74
|
+
this.saveSession(session);
|
|
75
|
+
this.activeSessionId = id;
|
|
76
|
+
this.saveActiveSessionId();
|
|
77
|
+
return session;
|
|
78
|
+
}
|
|
79
|
+
getSession(id) {
|
|
80
|
+
const filePath = this.getSessionFilePath(id);
|
|
81
|
+
if (fs.existsSync(filePath)) {
|
|
82
|
+
try {
|
|
83
|
+
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
84
|
+
return JSON.parse(raw);
|
|
85
|
+
}
|
|
86
|
+
catch { }
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
getActiveSession() {
|
|
91
|
+
const session = this.getSession(this.activeSessionId);
|
|
92
|
+
if (session)
|
|
93
|
+
return session;
|
|
94
|
+
return this.createSession('New Chat');
|
|
95
|
+
}
|
|
96
|
+
saveSession(session) {
|
|
97
|
+
this.ensureDirectory();
|
|
98
|
+
session.updatedAt = Date.now();
|
|
99
|
+
const filePath = this.getSessionFilePath(session.id);
|
|
100
|
+
fs.writeFileSync(filePath, JSON.stringify(session, null, 2), 'utf-8');
|
|
101
|
+
}
|
|
102
|
+
addMessageToActiveSession(message) {
|
|
103
|
+
const session = this.getActiveSession();
|
|
104
|
+
session.messages.push({
|
|
105
|
+
...message,
|
|
106
|
+
timestamp: message.timestamp || Date.now(),
|
|
107
|
+
});
|
|
108
|
+
// Auto-generate title on first user message if title is "New Chat"
|
|
109
|
+
if (session.title === 'New Chat' && message.role === 'user') {
|
|
110
|
+
const cleanPrompt = message.content.replace(/\[Attached File:[^\]]+\]/g, '').trim();
|
|
111
|
+
if (cleanPrompt) {
|
|
112
|
+
session.title = cleanPrompt.length > 35 ? `${cleanPrompt.slice(0, 32)}...` : cleanPrompt;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
this.saveSession(session);
|
|
116
|
+
return session;
|
|
117
|
+
}
|
|
118
|
+
listSessions() {
|
|
119
|
+
this.ensureDirectory();
|
|
120
|
+
try {
|
|
121
|
+
const files = fs.readdirSync(this.chatsDir).filter((f) => f.endsWith('.json') && !f.startsWith('.'));
|
|
122
|
+
const summaries = [];
|
|
123
|
+
for (const file of files) {
|
|
124
|
+
try {
|
|
125
|
+
const filePath = path.join(this.chatsDir, file);
|
|
126
|
+
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
127
|
+
const data = JSON.parse(raw);
|
|
128
|
+
if (data && data.id) {
|
|
129
|
+
const lastUserMsg = data.messages?.filter((m) => m.role === 'user').pop();
|
|
130
|
+
summaries.push({
|
|
131
|
+
id: data.id,
|
|
132
|
+
title: data.title || 'Untitled Chat',
|
|
133
|
+
createdAt: data.createdAt || 0,
|
|
134
|
+
updatedAt: data.updatedAt || 0,
|
|
135
|
+
messageCount: data.messages?.length || 0,
|
|
136
|
+
preview: lastUserMsg?.content?.slice(0, 80) || '',
|
|
137
|
+
isActive: data.id === this.activeSessionId,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
catch { }
|
|
142
|
+
}
|
|
143
|
+
return summaries.sort((a, b) => b.updatedAt - a.updatedAt);
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
return [];
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
deleteSession(id) {
|
|
150
|
+
const filePath = this.getSessionFilePath(id);
|
|
151
|
+
try {
|
|
152
|
+
if (fs.existsSync(filePath)) {
|
|
153
|
+
fs.unlinkSync(filePath);
|
|
154
|
+
}
|
|
155
|
+
if (this.activeSessionId === id) {
|
|
156
|
+
const remaining = this.listSessions();
|
|
157
|
+
if (remaining.length > 0) {
|
|
158
|
+
this.activeSessionId = remaining[0].id;
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
const fresh = this.createSession('New Chat');
|
|
162
|
+
this.activeSessionId = fresh.id;
|
|
163
|
+
}
|
|
164
|
+
this.saveActiveSessionId();
|
|
165
|
+
}
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
renameSession(id, newTitle) {
|
|
173
|
+
const session = this.getSession(id);
|
|
174
|
+
if (session) {
|
|
175
|
+
session.title = newTitle.trim() || 'Untitled Chat';
|
|
176
|
+
this.saveSession(session);
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
clearActiveSessionMessages() {
|
|
182
|
+
const session = this.getActiveSession();
|
|
183
|
+
session.messages = [];
|
|
184
|
+
this.saveSession(session);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
export const sessionManager = new SessionManager();
|
|
188
|
+
//# sourceMappingURL=sessionManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionManager.js","sourceRoot":"","sources":["../../src/core/sessionManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AAGpB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;AAC7D,MAAM,mBAAmB,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;AAEpE,MAAM,OAAO,cAAc;IACjB,QAAQ,CAAS;IACjB,eAAe,GAAW,EAAE,CAAC;IAErC,YAAY,SAAkB;QAC5B,IAAI,CAAC,QAAQ,GAAG,SAAS,IAAI,SAAS,CAAC;QACvC,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,IAAI,CAAC,iBAAiB,EAAE,CAAC;IAC3B,CAAC;IAEO,eAAe;QACrB,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAEO,iBAAiB;QACvB,IAAI,CAAC;YACH,IAAI,EAAE,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAE,CAAC;gBACvC,MAAM,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,mBAAmB,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;gBAChE,IAAI,EAAE,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;oBACrD,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC;oBAC1B,OAAO;gBACT,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QAEV,0DAA0D;QAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACrC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC,eAAe,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACxC,CAAC;aAAM,CAAC;YACN,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;YAClD,IAAI,CAAC,eAAe,GAAG,UAAU,CAAC,EAAE,CAAC;QACvC,CAAC;QACD,IAAI,CAAC,mBAAmB,EAAE,CAAC;IAC7B,CAAC;IAEO,kBAAkB,CAAC,EAAU;QACnC,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,OAAO,OAAO,CAAC,CAAC;IACrD,CAAC;IAEO,mBAAmB;QACzB,IAAI,CAAC;YACH,IAAI,CAAC,eAAe,EAAE,CAAC;YACvB,EAAE,CAAC,aAAa,CAAC,mBAAmB,EAAE,IAAI,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;QACvE,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACZ,CAAC;IAEM,kBAAkB;QACvB,OAAO,IAAI,CAAC,eAAe,CAAC;IAC9B,CAAC;IAEM,kBAAkB,CAAC,EAAU;QAClC,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QACpC,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC;YAC1B,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC3B,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,aAAa,CAAC,KAAK,GAAG,UAAU;QACrC,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,MAAM,EAAE,GAAG,QAAQ,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QAC1E,MAAM,OAAO,GAAgB;YAC3B,EAAE;YACF,KAAK;YACL,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,QAAQ,EAAE,EAAE;SACb,CAAC;QAEF,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAC1B,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC;QAC1B,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC3B,OAAO,OAAO,CAAC;IACjB,CAAC;IAEM,UAAU,CAAC,EAAU;QAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC;QAC7C,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5B,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAC/C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;QACZ,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,gBAAgB;QACrB,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QACtD,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC;QAC5B,OAAO,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;IAEM,WAAW,CAAC,OAAoB;QACrC,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACrD,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACxE,CAAC;IAEM,yBAAyB,CAAC,OAAoB;QACnD,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACxC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;YACpB,GAAG,OAAO;YACV,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE;SAC3C,CAAC,CAAC;QAEH,mEAAmE;QACnE,IAAI,OAAO,CAAC,KAAK,KAAK,UAAU,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC5D,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,2BAA2B,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YACpF,IAAI,WAAW,EAAE,CAAC;gBAChB,OAAO,CAAC,KAAK,GAAG,WAAW,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC;YAC3F,CAAC;QACH,CAAC;QAED,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAC1B,OAAO,OAAO,CAAC;IACjB,CAAC;IAEM,YAAY;QACjB,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;YACrG,MAAM,SAAS,GAAyB,EAAE,CAAC;YAE3C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,CAAC;oBACH,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;oBAChD,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;oBAC/C,MAAM,IAAI,GAAgB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;oBAC1C,IAAI,IAAI,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;wBACpB,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC;wBAC1E,SAAS,CAAC,IAAI,CAAC;4BACb,EAAE,EAAE,IAAI,CAAC,EAAE;4BACX,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,eAAe;4BACpC,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,CAAC;4BAC9B,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,CAAC;4BAC9B,YAAY,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC;4BACxC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE;4BACjD,QAAQ,EAAE,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,eAAe;yBAC3C,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC,CAAA,CAAC;YACZ,CAAC;YAED,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;QAC7D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAEM,aAAa,CAAC,EAAU;QAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC;QAC7C,IAAI,CAAC;YACH,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC5B,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;YAC1B,CAAC;YACD,IAAI,IAAI,CAAC,eAAe,KAAK,EAAE,EAAE,CAAC;gBAChC,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;gBACtC,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACzB,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBACzC,CAAC;qBAAM,CAAC;oBACN,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;oBAC7C,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC,EAAE,CAAC;gBAClC,CAAC;gBACD,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC7B,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAEM,aAAa,CAAC,EAAU,EAAE,QAAgB;QAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QACpC,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,IAAI,eAAe,CAAC;YACnD,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;YAC1B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAEM,0BAA0B;QAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACxC,OAAO,CAAC,QAAQ,GAAG,EAAE,CAAC;QACtB,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;CACF;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,cAAc,EAAE,CAAC"}
|
package/dist/core/updater.d.ts
CHANGED
package/dist/core/updater.js
CHANGED
|
@@ -5,7 +5,7 @@ import ora from 'ora';
|
|
|
5
5
|
const execPromise = util.promisify(exec);
|
|
6
6
|
export class Updater {
|
|
7
7
|
static PACKAGE_NAME = 'antri_cli';
|
|
8
|
-
static CURRENT_VERSION = '1.
|
|
8
|
+
static CURRENT_VERSION = '1.52.0';
|
|
9
9
|
/**
|
|
10
10
|
* Fetches latest release version directly from registry.npmjs.org (cache-free)
|
|
11
11
|
*/
|
|
@@ -19,6 +19,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|
|
19
19
|
await checkAuthStatus();
|
|
20
20
|
await loadStatus();
|
|
21
21
|
await loadCommands();
|
|
22
|
+
await loadChatSessions();
|
|
22
23
|
await loadProfiles();
|
|
23
24
|
await loadSkills();
|
|
24
25
|
await loadMemory();
|
|
@@ -401,6 +402,146 @@ function handleInputKey(event) {
|
|
|
401
402
|
}
|
|
402
403
|
}
|
|
403
404
|
|
|
405
|
+
// ==========================================
|
|
406
|
+
// Multi-Chat Session Management
|
|
407
|
+
// ==========================================
|
|
408
|
+
let currentActiveChatId = '';
|
|
409
|
+
let allChatSessions = [];
|
|
410
|
+
|
|
411
|
+
async function loadChatSessions(renderMessages = true) {
|
|
412
|
+
try {
|
|
413
|
+
const res = await fetch('/api/chats');
|
|
414
|
+
const data = await res.json();
|
|
415
|
+
allChatSessions = data.sessions || [];
|
|
416
|
+
currentActiveChatId = data.activeId || (allChatSessions[0]?.id || '');
|
|
417
|
+
|
|
418
|
+
const select = document.getElementById('select-chat-session');
|
|
419
|
+
if (select) {
|
|
420
|
+
select.innerHTML = '';
|
|
421
|
+
allChatSessions.forEach((s) => {
|
|
422
|
+
const opt = document.createElement('option');
|
|
423
|
+
opt.value = s.id;
|
|
424
|
+
opt.textContent = `${s.title} (${s.messageCount || 0})`;
|
|
425
|
+
if (s.id === currentActiveChatId) opt.selected = true;
|
|
426
|
+
select.appendChild(opt);
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
if (renderMessages && data.activeSession) {
|
|
431
|
+
renderActiveSessionMessages(data.activeSession.messages || []);
|
|
432
|
+
}
|
|
433
|
+
} catch (err) {
|
|
434
|
+
console.error('Failed to load chat sessions:', err);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
function renderActiveSessionMessages(messages) {
|
|
439
|
+
const container = document.getElementById('chat-messages');
|
|
440
|
+
if (!container) return;
|
|
441
|
+
container.innerHTML = '';
|
|
442
|
+
|
|
443
|
+
if (!messages || messages.length === 0) {
|
|
444
|
+
container.innerHTML = `
|
|
445
|
+
<div class="welcome-card" id="chat-welcome-card">
|
|
446
|
+
<h2>ANTRI Control Plane</h2>
|
|
447
|
+
<p>Minimalist environment for autonomous coding, architectural planning, and self-refinement. State, memory, profiles, and skills are synchronized across CLI and Desktop.</p>
|
|
448
|
+
<div class="quick-action-pills">
|
|
449
|
+
<button onclick="setPrompt('Plan the architecture for a real-time collaborative code editor')">Plan Editor Architecture</button>
|
|
450
|
+
<button onclick="setPrompt('/debate What are the trade-offs between WebSockets vs Server-Sent Events?')">Start Dialectic Debate</button>
|
|
451
|
+
<button onclick="setPrompt('/goal Implement a zero-dependency LRU cache with TTL in TypeScript')">Run Goal Loop</button>
|
|
452
|
+
</div>
|
|
453
|
+
</div>
|
|
454
|
+
`;
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
messages.forEach((msg) => {
|
|
459
|
+
if (msg.role === 'user' || msg.role === 'assistant') {
|
|
460
|
+
appendMessage(msg.role, msg.content);
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
async function createNewChatSession() {
|
|
466
|
+
try {
|
|
467
|
+
const res = await fetch('/api/chats/new', {
|
|
468
|
+
method: 'POST',
|
|
469
|
+
headers: { 'Content-Type': 'application/json' },
|
|
470
|
+
body: JSON.stringify({ title: 'New Chat' }),
|
|
471
|
+
});
|
|
472
|
+
const data = await res.json();
|
|
473
|
+
if (data.success && data.session) {
|
|
474
|
+
currentActiveChatId = data.session.id;
|
|
475
|
+
await loadChatSessions(true);
|
|
476
|
+
showToast('Started new chat session.');
|
|
477
|
+
}
|
|
478
|
+
} catch (err) {
|
|
479
|
+
console.error('Failed to create new chat session:', err);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
async function onChatSessionSelect(id) {
|
|
484
|
+
try {
|
|
485
|
+
const res = await fetch('/api/chats/select', {
|
|
486
|
+
method: 'POST',
|
|
487
|
+
headers: { 'Content-Type': 'application/json' },
|
|
488
|
+
body: JSON.stringify({ id }),
|
|
489
|
+
});
|
|
490
|
+
const data = await res.json();
|
|
491
|
+
if (data.success && data.session) {
|
|
492
|
+
currentActiveChatId = data.session.id;
|
|
493
|
+
renderActiveSessionMessages(data.session.messages || []);
|
|
494
|
+
await loadChatSessions(false);
|
|
495
|
+
}
|
|
496
|
+
} catch (err) {
|
|
497
|
+
console.error('Failed to select chat session:', err);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
async function clearCurrentChatContext() {
|
|
502
|
+
if (!confirm('Clear all conversation messages in this chat session?')) return;
|
|
503
|
+
const container = document.getElementById('chat-messages');
|
|
504
|
+
if (container) {
|
|
505
|
+
container.innerHTML = `
|
|
506
|
+
<div class="welcome-card" id="chat-welcome-card">
|
|
507
|
+
<h2>ANTRI Control Plane</h2>
|
|
508
|
+
<p>Minimalist environment for autonomous coding, architectural planning, and self-refinement. State, memory, profiles, and skills are synchronized across CLI and Desktop.</p>
|
|
509
|
+
<div class="quick-action-pills">
|
|
510
|
+
<button onclick="setPrompt('Plan the architecture for a real-time collaborative code editor')">Plan Editor Architecture</button>
|
|
511
|
+
<button onclick="setPrompt('/debate What are the trade-offs between WebSockets vs Server-Sent Events?')">Start Dialectic Debate</button>
|
|
512
|
+
<button onclick="setPrompt('/goal Implement a zero-dependency LRU cache with TTL in TypeScript')">Run Goal Loop</button>
|
|
513
|
+
</div>
|
|
514
|
+
</div>
|
|
515
|
+
`;
|
|
516
|
+
}
|
|
517
|
+
await fetch('/api/chat', {
|
|
518
|
+
method: 'POST',
|
|
519
|
+
headers: { 'Content-Type': 'application/json' },
|
|
520
|
+
body: JSON.stringify({ prompt: '/clear' }),
|
|
521
|
+
}).catch(() => {});
|
|
522
|
+
await loadChatSessions(false);
|
|
523
|
+
showToast('Chat context cleared.');
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
async function deleteCurrentChatSession() {
|
|
527
|
+
if (!currentActiveChatId) return;
|
|
528
|
+
if (!confirm('Are you sure you want to delete this chat session?')) return;
|
|
529
|
+
try {
|
|
530
|
+
const res = await fetch('/api/chats/delete', {
|
|
531
|
+
method: 'POST',
|
|
532
|
+
headers: { 'Content-Type': 'application/json' },
|
|
533
|
+
body: JSON.stringify({ id: currentActiveChatId }),
|
|
534
|
+
});
|
|
535
|
+
const data = await res.json();
|
|
536
|
+
if (data.success) {
|
|
537
|
+
await loadChatSessions(true);
|
|
538
|
+
showToast('Chat session deleted.');
|
|
539
|
+
}
|
|
540
|
+
} catch (err) {
|
|
541
|
+
console.error('Failed to delete chat session:', err);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
404
545
|
// Chat Prompt Submission with Real-Time Word-by-Word Side-by-Side Streaming
|
|
405
546
|
async function submitPrompt() {
|
|
406
547
|
const input = document.getElementById('prompt-input');
|
|
@@ -419,6 +560,12 @@ async function submitPrompt() {
|
|
|
419
560
|
input.value = '';
|
|
420
561
|
hidePalette();
|
|
421
562
|
|
|
563
|
+
// Remove welcome card if present
|
|
564
|
+
const welcomeCard = document.getElementById('chat-welcome-card');
|
|
565
|
+
if (welcomeCard) {
|
|
566
|
+
welcomeCard.remove();
|
|
567
|
+
}
|
|
568
|
+
|
|
422
569
|
// Intercept /debate or /goal inside chat
|
|
423
570
|
if (prompt.startsWith('/debate')) {
|
|
424
571
|
showTab('dialectic');
|
|
@@ -502,6 +649,7 @@ async function submitPrompt() {
|
|
|
502
649
|
} finally {
|
|
503
650
|
sendBtn.disabled = false;
|
|
504
651
|
sendBtn.innerHTML = '<span>Send</span>';
|
|
652
|
+
await loadChatSessions(false);
|
|
505
653
|
}
|
|
506
654
|
}
|
|
507
655
|
|
|
@@ -920,7 +1068,7 @@ async function deleteActiveProfile() {
|
|
|
920
1068
|
alert('Cannot delete default profile_1.');
|
|
921
1069
|
return;
|
|
922
1070
|
}
|
|
923
|
-
if (!confirm(`Are you sure you want to delete profile '${target}.md'
|
|
1071
|
+
if (!confirm(`Are you sure you want to delete profile '${target}.md' from both your device and the cloud? It will not be pulled again.`)) return;
|
|
924
1072
|
|
|
925
1073
|
const res = await fetch('/api/profile/delete', {
|
|
926
1074
|
method: 'POST',
|
|
@@ -931,7 +1079,7 @@ async function deleteActiveProfile() {
|
|
|
931
1079
|
if (data.success) {
|
|
932
1080
|
currentViewedProfile = 'profile_1';
|
|
933
1081
|
await loadProfiles();
|
|
934
|
-
showToast(`Profile '${target}' deleted.`);
|
|
1082
|
+
showToast(`Profile '${target}.md' deleted from device and cloud.`);
|
|
935
1083
|
}
|
|
936
1084
|
}
|
|
937
1085
|
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
<header class="app-header">
|
|
16
16
|
<div class="brand-zone">
|
|
17
17
|
<span class="logo-mark">ANTRI</span>
|
|
18
|
-
<span class="version-tag">v1.
|
|
18
|
+
<span class="version-tag">v1.52.0</span>
|
|
19
19
|
</div>
|
|
20
20
|
|
|
21
21
|
<!-- Mode Toggle -->
|
|
@@ -109,8 +109,22 @@
|
|
|
109
109
|
<!-- TAB 1: Chat & Agent Studio -->
|
|
110
110
|
<section id="tab-chat" class="tab-panel active">
|
|
111
111
|
<div class="chat-container">
|
|
112
|
+
<!-- Chat Session Switcher Header -->
|
|
113
|
+
<div class="chat-session-header">
|
|
114
|
+
<div class="chat-session-selector-group">
|
|
115
|
+
<button class="new-chat-btn" onclick="createNewChatSession()">+ New Chat</button>
|
|
116
|
+
<select id="select-chat-session" class="chat-session-select" onchange="onChatSessionSelect(this.value)">
|
|
117
|
+
<!-- Populated dynamically -->
|
|
118
|
+
</select>
|
|
119
|
+
</div>
|
|
120
|
+
<div class="chat-session-actions">
|
|
121
|
+
<button class="chat-session-action-btn" title="Clear conversation context" onclick="clearCurrentChatContext()">🧹 Clear</button>
|
|
122
|
+
<button class="chat-session-action-btn btn-danger" title="Delete this chat" onclick="deleteCurrentChatSession()">🗑️</button>
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
125
|
+
|
|
112
126
|
<div id="chat-messages" class="chat-messages">
|
|
113
|
-
<div class="welcome-card">
|
|
127
|
+
<div class="welcome-card" id="chat-welcome-card">
|
|
114
128
|
<h2>ANTRI Control Plane</h2>
|
|
115
129
|
<p>Minimalist environment for autonomous coding, architectural planning, and self-refinement. State, memory, profiles, and skills are synchronized across CLI and Desktop.</p>
|
|
116
130
|
<div class="quick-action-pills">
|
|
@@ -286,6 +286,85 @@ body.antri-app {
|
|
|
286
286
|
position: relative;
|
|
287
287
|
}
|
|
288
288
|
|
|
289
|
+
.chat-session-header {
|
|
290
|
+
display: flex;
|
|
291
|
+
align-items: center;
|
|
292
|
+
justify-content: space-between;
|
|
293
|
+
padding: 0.6rem 1rem;
|
|
294
|
+
background: var(--bg-card);
|
|
295
|
+
border: 1px solid var(--border-main);
|
|
296
|
+
border-radius: var(--radius-sm);
|
|
297
|
+
margin-bottom: 1rem;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
.chat-session-selector-group {
|
|
301
|
+
display: flex;
|
|
302
|
+
align-items: center;
|
|
303
|
+
gap: 0.75rem;
|
|
304
|
+
flex: 1;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
.new-chat-btn {
|
|
308
|
+
background: var(--accent-primary);
|
|
309
|
+
color: var(--text-inverted);
|
|
310
|
+
border: none;
|
|
311
|
+
padding: 0.45rem 0.9rem;
|
|
312
|
+
border-radius: var(--radius-xs);
|
|
313
|
+
font-family: var(--font-sans);
|
|
314
|
+
font-size: 0.8rem;
|
|
315
|
+
font-weight: 700;
|
|
316
|
+
cursor: pointer;
|
|
317
|
+
white-space: nowrap;
|
|
318
|
+
transition: all 0.15s ease;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.new-chat-btn:hover {
|
|
322
|
+
opacity: 0.9;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.chat-session-select {
|
|
326
|
+
background: var(--bg-subtle);
|
|
327
|
+
border: 1px solid var(--border-main);
|
|
328
|
+
color: var(--text-primary);
|
|
329
|
+
font-family: var(--font-sans);
|
|
330
|
+
font-size: 0.82rem;
|
|
331
|
+
font-weight: 600;
|
|
332
|
+
padding: 0.4rem 0.75rem;
|
|
333
|
+
border-radius: var(--radius-xs);
|
|
334
|
+
cursor: pointer;
|
|
335
|
+
max-width: 320px;
|
|
336
|
+
width: 100%;
|
|
337
|
+
outline: none;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
.chat-session-actions {
|
|
341
|
+
display: flex;
|
|
342
|
+
align-items: center;
|
|
343
|
+
gap: 0.4rem;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.chat-session-action-btn {
|
|
347
|
+
background: transparent;
|
|
348
|
+
border: 1px solid var(--border-main);
|
|
349
|
+
padding: 0.35rem 0.65rem;
|
|
350
|
+
border-radius: var(--radius-xs);
|
|
351
|
+
font-size: 0.78rem;
|
|
352
|
+
color: var(--text-secondary);
|
|
353
|
+
cursor: pointer;
|
|
354
|
+
transition: all 0.15s ease;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.chat-session-action-btn:hover {
|
|
358
|
+
background: var(--bg-hover);
|
|
359
|
+
color: var(--text-primary);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
.chat-session-action-btn.btn-danger:hover {
|
|
363
|
+
background: #fee2e2;
|
|
364
|
+
border-color: #fca5a5;
|
|
365
|
+
color: #dc2626;
|
|
366
|
+
}
|
|
367
|
+
|
|
289
368
|
.chat-messages {
|
|
290
369
|
flex: 1;
|
|
291
370
|
overflow-y: auto;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/desktop/server.ts"],"names":[],"mappings":"AAqCA,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,IAAI,CAAQ;IACpB,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,kBAAkB,CAAiD;IAC3E,OAAO,CAAC,gBAAgB,CAAqD;;IAO7E,OAAO,CAAC,sBAAsB;IA2BjB,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAqExB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAUpB,SAAS;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/desktop/server.ts"],"names":[],"mappings":"AAqCA,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,IAAI,CAAQ;IACpB,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,kBAAkB,CAAiD;IAC3E,OAAO,CAAC,gBAAgB,CAAqD;;IAO7E,OAAO,CAAC,sBAAsB;IA2BjB,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAqExB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAUpB,SAAS;WAsgBH,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;CAyBnD"}
|
package/dist/desktop/server.js
CHANGED
|
@@ -227,6 +227,16 @@ export class DesktopServer {
|
|
|
227
227
|
res.end(JSON.stringify(memoryStatus));
|
|
228
228
|
return;
|
|
229
229
|
}
|
|
230
|
+
// GET /api/chats (List multi-chat sessions)
|
|
231
|
+
if (pathname === '/api/chats' && req.method === 'GET') {
|
|
232
|
+
const { sessionManager } = await import('../core/sessionManager.js');
|
|
233
|
+
const sessions = sessionManager.listSessions();
|
|
234
|
+
const activeId = sessionManager.getActiveSessionId();
|
|
235
|
+
const activeSession = sessionManager.getActiveSession();
|
|
236
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
237
|
+
res.end(JSON.stringify({ sessions, activeId, activeSession }));
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
230
240
|
// Read Body for POST requests
|
|
231
241
|
let body = '';
|
|
232
242
|
req.on('data', (chunk) => {
|
|
@@ -477,6 +487,8 @@ export class DesktopServer {
|
|
|
477
487
|
// POST /api/profile/delete
|
|
478
488
|
if (pathname === '/api/profile/delete' && req.method === 'POST') {
|
|
479
489
|
const ok = profileManager.deleteProfile(payload.name);
|
|
490
|
+
const { FirestoreSyncManager } = await import('../cloud/firestore.js');
|
|
491
|
+
FirestoreSyncManager.deleteFromFirestore(payload.name).catch(() => { });
|
|
480
492
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
481
493
|
res.end(JSON.stringify({ success: ok }));
|
|
482
494
|
return;
|
|
@@ -504,6 +516,42 @@ export class DesktopServer {
|
|
|
504
516
|
res.end(JSON.stringify({ success: true, skill }));
|
|
505
517
|
return;
|
|
506
518
|
}
|
|
519
|
+
// POST /api/chats/new (Create new chat session)
|
|
520
|
+
if (pathname === '/api/chats/new' && req.method === 'POST') {
|
|
521
|
+
const { sessionManager } = await import('../core/sessionManager.js');
|
|
522
|
+
const session = sessionManager.createSession(payload.title || 'New Chat');
|
|
523
|
+
this.activeAgent.syncHistoryFromActiveSession();
|
|
524
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
525
|
+
res.end(JSON.stringify({ success: true, session }));
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
// POST /api/chats/select (Switch active chat session)
|
|
529
|
+
if (pathname === '/api/chats/select' && req.method === 'POST') {
|
|
530
|
+
const { sessionManager } = await import('../core/sessionManager.js');
|
|
531
|
+
const session = sessionManager.setActiveSessionId(payload.id);
|
|
532
|
+
this.activeAgent.syncHistoryFromActiveSession();
|
|
533
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
534
|
+
res.end(JSON.stringify({ success: !!session, session }));
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
// POST /api/chats/delete (Delete chat session)
|
|
538
|
+
if (pathname === '/api/chats/delete' && req.method === 'POST') {
|
|
539
|
+
const { sessionManager } = await import('../core/sessionManager.js');
|
|
540
|
+
const ok = sessionManager.deleteSession(payload.id);
|
|
541
|
+
this.activeAgent.syncHistoryFromActiveSession();
|
|
542
|
+
const activeSession = sessionManager.getActiveSession();
|
|
543
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
544
|
+
res.end(JSON.stringify({ success: ok, activeSession }));
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
// POST /api/chats/rename (Rename chat session)
|
|
548
|
+
if (pathname === '/api/chats/rename' && req.method === 'POST') {
|
|
549
|
+
const { sessionManager } = await import('../core/sessionManager.js');
|
|
550
|
+
const ok = sessionManager.renameSession(payload.id, payload.title);
|
|
551
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
552
|
+
res.end(JSON.stringify({ success: ok }));
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
507
555
|
// POST /api/skill/save
|
|
508
556
|
if (pathname === '/api/skill/save' && req.method === 'POST') {
|
|
509
557
|
const ok = skillManager.saveSkill(payload.id, payload.content);
|