xiaozuoassistant 0.1.95 → 0.1.97
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/bin/cli.js +4 -1
- package/package.json +1 -1
- package/dist/client/assets/browser-ponyfill-Do7nqjGM.js +0 -2
- package/dist/client/assets/index-BtPLguA3.css +0 -1
- package/dist/client/assets/index-yLtVOGjh.js +0 -196
- package/dist/client/favicon.svg +0 -4
- package/dist/client/index.html +0 -14
- package/dist/client/locales/en/translation.json +0 -110
- package/dist/client/locales/zh/translation.json +0 -112
- package/dist/server/agents/office.js +0 -23
- package/dist/server/app.js +0 -50
- package/dist/server/channels/base-channel.js +0 -23
- package/dist/server/channels/create-channels.js +0 -18
- package/dist/server/channels/dingtalk.js +0 -83
- package/dist/server/channels/feishu.js +0 -108
- package/dist/server/channels/telegram.js +0 -53
- package/dist/server/channels/terminal.js +0 -49
- package/dist/server/channels/web.js +0 -66
- package/dist/server/channels/wechat.js +0 -107
- package/dist/server/config/loader.js +0 -96
- package/dist/server/config/paths.js +0 -24
- package/dist/server/config/prompts.js +0 -12
- package/dist/server/core/agents/manager.js +0 -27
- package/dist/server/core/agents/runtime.js +0 -92
- package/dist/server/core/brain.js +0 -235
- package/dist/server/core/event-bus.js +0 -24
- package/dist/server/core/logger.js +0 -71
- package/dist/server/core/memories/manager.js +0 -238
- package/dist/server/core/memories/short-term.js +0 -512
- package/dist/server/core/memories/structured.js +0 -357
- package/dist/server/core/memories/vector.js +0 -137
- package/dist/server/core/memory.js +0 -2
- package/dist/server/core/plugin-manager.js +0 -128
- package/dist/server/core/plugin.js +0 -1
- package/dist/server/core/scheduler.js +0 -85
- package/dist/server/core/task-queue.js +0 -104
- package/dist/server/core/types.js +0 -1
- package/dist/server/index.js +0 -866
- package/dist/server/llm/openai.js +0 -23
- package/dist/server/plugins/core-skills/src/create-agent.js +0 -58
- package/dist/server/plugins/core-skills/src/delegate.js +0 -39
- package/dist/server/plugins/core-skills/src/file-system.js +0 -142
- package/dist/server/plugins/core-skills/src/index.js +0 -26
- package/dist/server/plugins/core-skills/src/list-agents.js +0 -24
- package/dist/server/plugins/core-skills/src/search.js +0 -31
- package/dist/server/plugins/core-skills/src/system-time.js +0 -27
- package/dist/server/plugins/office-skills/src/index.js +0 -19
- package/dist/server/plugins/office-skills/src/office-excel.js +0 -84
- package/dist/server/plugins/office-skills/src/office-ppt.js +0 -58
- package/dist/server/plugins/office-skills/src/office-word.js +0 -90
- package/dist/server/routes/auth.js +0 -28
- package/dist/server/server/create-http.js +0 -22
- package/dist/server/server.js +0 -29
- package/dist/server/skills/base-skill.js +0 -20
- package/dist/server/skills/registry.js +0 -52
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { EventEmitter } from 'events';
|
|
2
|
-
class EventBus extends EventEmitter {
|
|
3
|
-
constructor() {
|
|
4
|
-
super();
|
|
5
|
-
}
|
|
6
|
-
static getInstance() {
|
|
7
|
-
if (!EventBus.instance) {
|
|
8
|
-
EventBus.instance = new EventBus();
|
|
9
|
-
}
|
|
10
|
-
return EventBus.instance;
|
|
11
|
-
}
|
|
12
|
-
emitEvent(event) {
|
|
13
|
-
this.emit(event.type, event);
|
|
14
|
-
// 同时也触发一个通用的 '*' 事件,方便日志记录
|
|
15
|
-
this.emit('*', event);
|
|
16
|
-
}
|
|
17
|
-
onEvent(eventType, handler) {
|
|
18
|
-
this.on(eventType, handler);
|
|
19
|
-
}
|
|
20
|
-
offEvent(eventType, handler) {
|
|
21
|
-
this.off(eventType, handler);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
export const eventBus = EventBus.getInstance();
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import winston from 'winston';
|
|
2
|
-
import 'winston-daily-rotate-file';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import fs from 'fs';
|
|
5
|
-
// Determine log directory
|
|
6
|
-
// In production, logs should be in the directory where the user runs the app (process.cwd()/logs)
|
|
7
|
-
// In development, it might be the project root.
|
|
8
|
-
const logDir = path.join(process.cwd(), 'logs');
|
|
9
|
-
// Ensure log directory exists
|
|
10
|
-
if (!fs.existsSync(logDir)) {
|
|
11
|
-
try {
|
|
12
|
-
fs.mkdirSync(logDir, { recursive: true });
|
|
13
|
-
}
|
|
14
|
-
catch (e) {
|
|
15
|
-
console.error('Failed to create log directory:', e);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
// Define the custom format
|
|
19
|
-
const logFormat = winston.format.combine(winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), winston.format.errors({ stack: true }), // Print stack trace for errors
|
|
20
|
-
winston.format.splat(), winston.format.printf(({ timestamp, level, message, stack }) => {
|
|
21
|
-
return `[${timestamp}] ${level.toUpperCase()}: ${message} ${stack || ''}`;
|
|
22
|
-
}));
|
|
23
|
-
// Create the rotating file transport
|
|
24
|
-
const fileTransport = new winston.transports.DailyRotateFile({
|
|
25
|
-
filename: path.join(logDir, 'app-%DATE%.log'),
|
|
26
|
-
datePattern: 'YYYY-MM-DD',
|
|
27
|
-
zippedArchive: true, // Archive old logs (gzip)
|
|
28
|
-
maxSize: '20m', // Rotate if size exceeds 20MB (optional safety)
|
|
29
|
-
maxFiles: '30d', // Keep logs for 30 days
|
|
30
|
-
createSymlink: true, // Create a symlink 'app.log' pointing to current log
|
|
31
|
-
symlinkName: 'app.log',
|
|
32
|
-
level: 'info'
|
|
33
|
-
});
|
|
34
|
-
const transports = [
|
|
35
|
-
fileTransport,
|
|
36
|
-
new winston.transports.Console({
|
|
37
|
-
format: winston.format.combine(winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), winston.format.colorize(), winston.format.printf(({ timestamp, level, message, stack }) => {
|
|
38
|
-
return `[${timestamp}] ${level}: ${message} ${stack || ''}`;
|
|
39
|
-
}))
|
|
40
|
-
})
|
|
41
|
-
];
|
|
42
|
-
export const logger = winston.createLogger({
|
|
43
|
-
level: 'info',
|
|
44
|
-
format: logFormat,
|
|
45
|
-
transports: transports,
|
|
46
|
-
exceptionHandlers: [
|
|
47
|
-
new winston.transports.File({ filename: path.join(logDir, 'exceptions.log') })
|
|
48
|
-
],
|
|
49
|
-
rejectionHandlers: [
|
|
50
|
-
new winston.transports.File({ filename: path.join(logDir, 'rejections.log') })
|
|
51
|
-
]
|
|
52
|
-
});
|
|
53
|
-
// Helper to integrate with existing console.log usage
|
|
54
|
-
export const overrideConsole = () => {
|
|
55
|
-
const originalLog = console.log;
|
|
56
|
-
const originalError = console.error;
|
|
57
|
-
const originalWarn = console.warn;
|
|
58
|
-
const originalInfo = console.info;
|
|
59
|
-
console.log = (...args) => {
|
|
60
|
-
logger.info(args.map(arg => typeof arg === 'object' ? JSON.stringify(arg, null, 2) : arg).join(' '));
|
|
61
|
-
};
|
|
62
|
-
console.error = (...args) => {
|
|
63
|
-
logger.error(args.map(arg => typeof arg === 'object' ? JSON.stringify(arg, null, 2) : arg).join(' '));
|
|
64
|
-
};
|
|
65
|
-
console.warn = (...args) => {
|
|
66
|
-
logger.warn(args.map(arg => typeof arg === 'object' ? JSON.stringify(arg, null, 2) : arg).join(' '));
|
|
67
|
-
};
|
|
68
|
-
console.info = (...args) => {
|
|
69
|
-
logger.info(args.map(arg => typeof arg === 'object' ? JSON.stringify(arg, null, 2) : arg).join(' '));
|
|
70
|
-
};
|
|
71
|
-
};
|
|
@@ -1,238 +0,0 @@
|
|
|
1
|
-
import { ShortTermMemory } from './short-term.js';
|
|
2
|
-
import { VectorMemory } from './vector.js';
|
|
3
|
-
import { StructuredMemory } from './structured.js';
|
|
4
|
-
import { brain } from '../brain.js';
|
|
5
|
-
import { config } from '../../config/loader.js';
|
|
6
|
-
export class MemoryManager {
|
|
7
|
-
constructor() {
|
|
8
|
-
this.shortTerm = ShortTermMemory.getInstance();
|
|
9
|
-
this.vector = VectorMemory.getInstance();
|
|
10
|
-
this.structured = StructuredMemory.getInstance();
|
|
11
|
-
}
|
|
12
|
-
static getInstance() {
|
|
13
|
-
if (!MemoryManager.instance) {
|
|
14
|
-
MemoryManager.instance = new MemoryManager();
|
|
15
|
-
}
|
|
16
|
-
return MemoryManager.instance;
|
|
17
|
-
}
|
|
18
|
-
// --- Layer 1: Short-term (Session) ---
|
|
19
|
-
async createSession(input) {
|
|
20
|
-
return this.shortTerm.createSession(input);
|
|
21
|
-
}
|
|
22
|
-
async getSession(id) {
|
|
23
|
-
return this.shortTerm.getSession(id);
|
|
24
|
-
}
|
|
25
|
-
async listSessions() {
|
|
26
|
-
return this.shortTerm.listSessions();
|
|
27
|
-
}
|
|
28
|
-
async updateSessionMeta(id, patch) {
|
|
29
|
-
return this.shortTerm.updateSessionMeta(id, patch);
|
|
30
|
-
}
|
|
31
|
-
async persistSession(id) {
|
|
32
|
-
return this.shortTerm.persistSession(id);
|
|
33
|
-
}
|
|
34
|
-
async deleteSession(id) {
|
|
35
|
-
return this.shortTerm.deleteSession(id);
|
|
36
|
-
}
|
|
37
|
-
async addMessage(sessionId, message) {
|
|
38
|
-
// 1. Add to Short-term
|
|
39
|
-
await this.shortTerm.addMessage(sessionId, message);
|
|
40
|
-
// 2. Add to Recent/Long-term (Vector) - Async/Background
|
|
41
|
-
// For now, we only embed user messages or significant assistant responses
|
|
42
|
-
// to avoid cluttering.
|
|
43
|
-
if (message.content.length > 10) { // Simple filter
|
|
44
|
-
const userId = config.userId || 'default';
|
|
45
|
-
this.vector.addMemory(message.content, 'recent', { sessionId, role: message.role, userId })
|
|
46
|
-
.catch(err => console.error('Background vector add failed:', err));
|
|
47
|
-
}
|
|
48
|
-
// 3. Extract Facts (Structured) - This usually requires an LLM call to extract
|
|
49
|
-
// structured info from the message. For MVP, we skip automatic extraction here
|
|
50
|
-
// but provide the API for the Brain to call explicitly.
|
|
51
|
-
}
|
|
52
|
-
async clearSessionMessages(sessionId) {
|
|
53
|
-
await this.shortTerm.clearMessages(sessionId);
|
|
54
|
-
}
|
|
55
|
-
updateClients() {
|
|
56
|
-
this.vector.updateClient();
|
|
57
|
-
}
|
|
58
|
-
async createRun(sessionId, userContent, runId) {
|
|
59
|
-
return this.shortTerm.createRun(sessionId, userContent, runId);
|
|
60
|
-
}
|
|
61
|
-
async updateRun(sessionId, runId, patch) {
|
|
62
|
-
return this.shortTerm.updateRun(sessionId, runId, patch);
|
|
63
|
-
}
|
|
64
|
-
async listRuns(sessionId) {
|
|
65
|
-
return this.shortTerm.listRuns(sessionId);
|
|
66
|
-
}
|
|
67
|
-
async getHistory(sessionId) {
|
|
68
|
-
return this.shortTerm.getMessages(sessionId);
|
|
69
|
-
}
|
|
70
|
-
// --- Retrieval ---
|
|
71
|
-
async getRelevantContext(query, sessionId, userId) {
|
|
72
|
-
const uid = userId || config.userId || 'default';
|
|
73
|
-
// 1. Get Short-term context (recent messages)
|
|
74
|
-
const history = await this.getHistory(sessionId);
|
|
75
|
-
const recentMessages = history.slice(-10).map(m => `${m.role}: ${m.content}`).join('\n');
|
|
76
|
-
// 2. Search Vector Memory (Recent & Long-term)
|
|
77
|
-
const vectorResults = await this.vector.search(query, undefined, 10);
|
|
78
|
-
const vectorFiltered = vectorResults.filter(r => (r.metadata?.userId || 'default') === uid).slice(0, 3);
|
|
79
|
-
const vectorContext = vectorFiltered.map(r => `[Memory]: ${r.text}`).join('\n');
|
|
80
|
-
// 3. Get User Profile (Structured)
|
|
81
|
-
const profile = await this.structured.getUserProfile(uid);
|
|
82
|
-
const profileContext = Object.entries(profile).map(([k, v]) => `[User Info] ${k}: ${v}`).join('\n');
|
|
83
|
-
return `
|
|
84
|
-
=== User Identity (userId: ${uid}) ===
|
|
85
|
-
${profileContext}
|
|
86
|
-
|
|
87
|
-
=== Relevant Memories ===
|
|
88
|
-
${vectorContext}
|
|
89
|
-
|
|
90
|
-
=== Recent Conversation ===
|
|
91
|
-
${recentMessages}
|
|
92
|
-
`;
|
|
93
|
-
}
|
|
94
|
-
getUserProfile(userId) {
|
|
95
|
-
const uid = userId || config.userId || 'default';
|
|
96
|
-
return this.structured.getUserProfile(uid);
|
|
97
|
-
}
|
|
98
|
-
updateUserProfile(userId, patch) {
|
|
99
|
-
const uid = userId || config.userId || 'default';
|
|
100
|
-
for (const [k, v] of Object.entries(patch || {})) {
|
|
101
|
-
const key = String(k).trim();
|
|
102
|
-
if (!key)
|
|
103
|
-
continue;
|
|
104
|
-
const value = v === null || v === undefined ? '' : String(v);
|
|
105
|
-
this.structured.updateUserProfile(uid, key, value);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
async runSessionArchiving() {
|
|
109
|
-
console.log('[MemoryManager] Running session archiving...');
|
|
110
|
-
const sessions = await this.listSessions();
|
|
111
|
-
const now = Date.now();
|
|
112
|
-
for (const session of sessions) {
|
|
113
|
-
try {
|
|
114
|
-
// Check if session has new activity since last archive
|
|
115
|
-
const lastArchived = session.lastArchivedAt || 0;
|
|
116
|
-
const lastActive = session.lastActiveAt || session.updatedAt || 0;
|
|
117
|
-
// If no new activity, skip
|
|
118
|
-
if (lastActive <= lastArchived)
|
|
119
|
-
continue;
|
|
120
|
-
// If less than 3 minutes since last archive, skip (though scheduler runs every 3 mins, so this check is redundant but safe)
|
|
121
|
-
// Actually, we want to archive if there is new content.
|
|
122
|
-
console.log(`[MemoryManager] Archiving session ${session.id} (Alias: ${session.alias || 'N/A'})...`);
|
|
123
|
-
const messages = await this.getHistory(session.id);
|
|
124
|
-
// Filter messages after lastArchived
|
|
125
|
-
const newMessages = messages.filter(m => (m.timestamp || 0) > lastArchived);
|
|
126
|
-
if (newMessages.length === 0) {
|
|
127
|
-
// Update lastArchivedAt to now to avoid re-checking empty interval
|
|
128
|
-
await this.updateSessionMeta(session.id, { lastArchivedAt: now });
|
|
129
|
-
continue;
|
|
130
|
-
}
|
|
131
|
-
// Process in chunks to avoid context overflow
|
|
132
|
-
const CHUNK_SIZE = 50; // Process 50 messages at a time
|
|
133
|
-
for (let i = 0; i < newMessages.length; i += CHUNK_SIZE) {
|
|
134
|
-
const chunk = newMessages.slice(i, i + CHUNK_SIZE);
|
|
135
|
-
const content = chunk.map(m => `${m.role}: ${m.content}`).join('\n');
|
|
136
|
-
// 1. Memory Archiving (Project or General)
|
|
137
|
-
const projectIds = session.projectIds || (session.projectId ? [session.projectId] : []);
|
|
138
|
-
if (projectIds.length > 0) {
|
|
139
|
-
// Project Context
|
|
140
|
-
const projectInfo = await brain.extractKeyInformation(content, 'project');
|
|
141
|
-
if (projectInfo) {
|
|
142
|
-
for (const pid of projectIds) {
|
|
143
|
-
await this.vector.addMemory(projectInfo, 'project_archive', {
|
|
144
|
-
sessionId: session.id,
|
|
145
|
-
projectId: pid,
|
|
146
|
-
archivedAt: now
|
|
147
|
-
});
|
|
148
|
-
console.log(`[MemoryManager] Archived project info for Project ${pid} (Chunk ${i / CHUNK_SIZE + 1})`);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
else {
|
|
153
|
-
// General Context (No Project)
|
|
154
|
-
const generalInfo = await brain.extractKeyInformation(content, 'general');
|
|
155
|
-
if (generalInfo) {
|
|
156
|
-
await this.vector.addMemory(generalInfo, 'long_term', {
|
|
157
|
-
sessionId: session.id,
|
|
158
|
-
archivedAt: now,
|
|
159
|
-
source: 'auto_archive'
|
|
160
|
-
});
|
|
161
|
-
console.log(`[MemoryManager] Archived general info for Session ${session.id} (Chunk ${i / CHUNK_SIZE + 1})`);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
// 2. Notebook Memory Archiving
|
|
165
|
-
if (session.notebookId) {
|
|
166
|
-
const notebook = this.structured.getNotebook(session.notebookId);
|
|
167
|
-
if (notebook) {
|
|
168
|
-
// Extract notes regardless of keywords (Brain handles fallback)
|
|
169
|
-
const notes = await brain.extractNotebookNotes(content, notebook.keywords);
|
|
170
|
-
if (notes && notes.length > 0) {
|
|
171
|
-
for (const note of notes) {
|
|
172
|
-
if (!note.title || !note.content)
|
|
173
|
-
continue;
|
|
174
|
-
this.structured.createNote(require('uuid').v4(), session.notebookId, note.title, note.content);
|
|
175
|
-
console.log(`[MemoryManager] Created note "${note.title}" in Notebook ${notebook.name} (Chunk ${i / CHUNK_SIZE + 1})`);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
// Update lastArchivedAt
|
|
182
|
-
await this.updateSessionMeta(session.id, { lastArchivedAt: now });
|
|
183
|
-
}
|
|
184
|
-
catch (e) {
|
|
185
|
-
console.error(`[MemoryManager] Failed to archive session ${session.id}:`, e);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
// --- Maintenance ---
|
|
190
|
-
// Managed by Scheduler
|
|
191
|
-
async runMaintenance(input) {
|
|
192
|
-
const sessionMaxAgeDays = input?.sessionMaxAgeDays ?? 5;
|
|
193
|
-
const vectorMaxAgeDays = input?.vectorMaxAgeDays ?? 15;
|
|
194
|
-
console.log(`[MemoryManager] Running maintenance (Sessions: ${sessionMaxAgeDays} days, Vector: ${vectorMaxAgeDays} days)...`);
|
|
195
|
-
try {
|
|
196
|
-
// 0. Auto-archive active sessions
|
|
197
|
-
await this.runSessionArchiving();
|
|
198
|
-
// 1. Clean up old sessions
|
|
199
|
-
const deletedSessions = await this.shortTerm.cleanupOldSessions(sessionMaxAgeDays);
|
|
200
|
-
if (deletedSessions > 0) {
|
|
201
|
-
console.log(`[MemoryManager] Deleted ${deletedSessions} old sessions.`);
|
|
202
|
-
}
|
|
203
|
-
// 2. Summarize and Prune Vector Memories
|
|
204
|
-
const oldMemories = await this.vector.getMemoriesOlderThan(vectorMaxAgeDays);
|
|
205
|
-
if (oldMemories.length > 0) {
|
|
206
|
-
console.log(`[MemoryManager] Found ${oldMemories.length} old memories to summarize.`);
|
|
207
|
-
// Batch process
|
|
208
|
-
const BATCH_SIZE = 10;
|
|
209
|
-
for (let i = 0; i < oldMemories.length; i += BATCH_SIZE) {
|
|
210
|
-
const batch = oldMemories.slice(i, i + BATCH_SIZE);
|
|
211
|
-
const batchText = batch.map(m => `[${new Date(m.metadata.timestamp).toISOString()}] ${m.text}`).join('\n');
|
|
212
|
-
try {
|
|
213
|
-
const summary = await brain.generateSummary(batchText);
|
|
214
|
-
if (summary) {
|
|
215
|
-
await this.vector.addMemory(summary, 'long_term', {
|
|
216
|
-
original_count: batch.length,
|
|
217
|
-
summary_date: Date.now(),
|
|
218
|
-
source: 'maintenance_summary'
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
catch (e) {
|
|
223
|
-
console.error('Failed to summarize batch:', e);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
// Prune after summarization
|
|
227
|
-
await this.vector.pruneOldMemories(vectorMaxAgeDays);
|
|
228
|
-
}
|
|
229
|
-
else {
|
|
230
|
-
// No old memories
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
catch (error) {
|
|
234
|
-
console.error('[MemoryManager] Maintenance failed:', error);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
export const memoryManager = MemoryManager.getInstance();
|