xiaozuoassistant 0.1.44 → 0.1.45
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/client/assets/{browser-ponyfill-DNlTAU2D.js → browser-ponyfill-C0qLfQMC.js} +1 -1
- package/dist/client/assets/index-BfEuvtsz.js +158 -0
- package/dist/client/assets/index-C72E_nIr.css +1 -0
- package/dist/client/index.html +2 -2
- package/dist/client/locales/en/translation.json +11 -2
- package/dist/client/locales/zh/translation.json +11 -2
- package/dist/server/config/paths.js +24 -0
- package/dist/server/core/agents/runtime.js +5 -2
- package/dist/server/core/brain.js +5 -2
- package/dist/server/core/memories/manager.js +6 -4
- package/dist/server/core/memories/short-term.js +216 -89
- package/dist/server/index.js +70 -16
- package/dist/server/skills/create-agent.js +1 -1
- package/dist/server/skills/delegate.js +1 -1
- package/dist/server/skills/file-system.js +17 -12
- package/dist/server/skills/list-agents.js +1 -1
- package/dist/server/skills/office-excel.js +2 -2
- package/dist/server/skills/office-ppt.js +1 -1
- package/dist/server/skills/office-word.js +2 -2
- package/dist/server/skills/search.js +1 -1
- package/dist/server/skills/system-time.js +1 -1
- package/package.json +1 -1
- package/public/locales/en/translation.json +11 -2
- package/public/locales/zh/translation.json +11 -2
- package/dist/client/assets/index-BPATxdcV.js +0 -153
- package/dist/client/assets/index-CgL5gMVL.css +0 -1
package/dist/server/index.js
CHANGED
|
@@ -70,28 +70,69 @@ app.get('/api/health', (req, res) => {
|
|
|
70
70
|
});
|
|
71
71
|
// 获取所有会话
|
|
72
72
|
app.get('/api/sessions', async (req, res) => {
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
try {
|
|
74
|
+
const sessions = await memory.listSessions();
|
|
75
|
+
res.json(sessions);
|
|
76
|
+
}
|
|
77
|
+
catch (e) {
|
|
78
|
+
res.status(500).json({ error: e.message });
|
|
79
|
+
}
|
|
75
80
|
});
|
|
76
81
|
// 获取会话详情
|
|
77
82
|
app.get('/api/sessions/:id', async (req, res) => {
|
|
78
|
-
|
|
79
|
-
|
|
83
|
+
try {
|
|
84
|
+
const session = await memory.getSession(req.params.id);
|
|
85
|
+
if (!session) {
|
|
86
|
+
res.status(404).json({ error: 'Session not found' });
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
80
89
|
res.json(session);
|
|
81
90
|
}
|
|
82
|
-
|
|
83
|
-
res.status(
|
|
91
|
+
catch (e) {
|
|
92
|
+
res.status(500).json({ error: e.message });
|
|
84
93
|
}
|
|
85
94
|
});
|
|
86
95
|
// 创建新会话
|
|
87
96
|
app.post('/api/sessions', async (req, res) => {
|
|
88
|
-
|
|
89
|
-
|
|
97
|
+
try {
|
|
98
|
+
const { alias, workspace } = req.body || {};
|
|
99
|
+
const session = await memory.createSession({ alias, workspace });
|
|
100
|
+
res.json(session.meta);
|
|
101
|
+
}
|
|
102
|
+
catch (e) {
|
|
103
|
+
res.status(500).json({ error: e.message });
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
// 更新会话元信息
|
|
107
|
+
app.patch('/api/sessions/:id', async (req, res) => {
|
|
108
|
+
try {
|
|
109
|
+
const { alias, workspace } = req.body || {};
|
|
110
|
+
const meta = await memory.updateSessionMeta(req.params.id, { alias, workspace });
|
|
111
|
+
res.json(meta);
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
114
|
+
const msg = String(e?.message || 'Unknown error');
|
|
115
|
+
if (msg.toLowerCase().includes('not found')) {
|
|
116
|
+
res.status(404).json({ error: 'Session not found' });
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
res.status(500).json({ error: msg });
|
|
120
|
+
}
|
|
90
121
|
});
|
|
91
122
|
// 删除会话
|
|
92
123
|
app.delete('/api/sessions/:id', async (req, res) => {
|
|
93
|
-
|
|
94
|
-
|
|
124
|
+
try {
|
|
125
|
+
await memory.deleteSession(req.params.id);
|
|
126
|
+
res.json({ status: 'success', message: 'Session deleted' });
|
|
127
|
+
}
|
|
128
|
+
catch (e) {
|
|
129
|
+
const msg = String(e?.message || 'Unknown error');
|
|
130
|
+
if (msg.toLowerCase().includes('not found')) {
|
|
131
|
+
res.status(404).json({ error: 'Session not found' });
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
res.status(500).json({ error: msg });
|
|
135
|
+
}
|
|
95
136
|
});
|
|
96
137
|
// 文件选择接口 (使用系统默认文件对话框可能需要Electron,这里作为Web服务,我们提供目录列表供选择)
|
|
97
138
|
// 简单的目录列举接口
|
|
@@ -246,13 +287,12 @@ eventBus.onEvent('message', async (event) => {
|
|
|
246
287
|
const content = payload.content;
|
|
247
288
|
try {
|
|
248
289
|
// 1. 获取会话上下文
|
|
249
|
-
|
|
290
|
+
const session = await memory.getSession(sessionId);
|
|
250
291
|
if (!session) {
|
|
251
|
-
|
|
252
|
-
// 如果是新创建的会话,可能需要通知前端更新 ID(略复杂,暂且假设前端已获取 ID)
|
|
292
|
+
throw new Error('Session not found. Please create or select a session first.');
|
|
253
293
|
}
|
|
254
294
|
// 2. 记录用户消息
|
|
255
|
-
await memory.addMessage(sessionId, { role: 'user', content });
|
|
295
|
+
await memory.addMessage(sessionId, { role: 'user', content, timestamp: Date.now() });
|
|
256
296
|
// 3. Brain 处理
|
|
257
297
|
// Use MemoryManager to retrieve full context (Short-term + Recent + Structured)
|
|
258
298
|
const context = await memory.getRelevantContext(content, sessionId);
|
|
@@ -262,7 +302,11 @@ eventBus.onEvent('message', async (event) => {
|
|
|
262
302
|
// Or simpler: We just pass session.messages as before, but Brain needs to know about the context.
|
|
263
303
|
// Let's change how we call brain.processMessage.
|
|
264
304
|
// Construct a temporary history with enhanced context for the LLM
|
|
305
|
+
const sessionAlias = session.meta.alias ? `Session Alias: ${session.meta.alias}` : '';
|
|
306
|
+
const workspaceLine = session.meta.workspace ? `Current Workspace: ${session.meta.workspace}` : '';
|
|
265
307
|
const enhancedSystemPrompt = `You are xiaozuoAssistant, a helpful AI assistant.
|
|
308
|
+
${sessionAlias}
|
|
309
|
+
${workspaceLine}
|
|
266
310
|
Here is some relevant context from your memory:
|
|
267
311
|
${context}`;
|
|
268
312
|
// We need to inject this into the Brain.
|
|
@@ -270,9 +314,19 @@ ${context}`;
|
|
|
270
314
|
// We can modify Brain to accept a system prompt override.
|
|
271
315
|
// Or we can just create a new method in Brain or pass it as an argument.
|
|
272
316
|
// Let's update Brain.processMessage signature in next step. For now, let's just pass the history.
|
|
273
|
-
const
|
|
317
|
+
const ctx = {
|
|
318
|
+
sessionId,
|
|
319
|
+
history: session.messages,
|
|
320
|
+
channel: channelName,
|
|
321
|
+
session: session.meta,
|
|
322
|
+
metadata: {
|
|
323
|
+
workspace: session.meta.workspace,
|
|
324
|
+
alias: session.meta.alias
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
const responseContent = await brain.processMessage(session.messages, content, enhancedSystemPrompt, ctx);
|
|
274
328
|
// 4. 记录 AI 响应
|
|
275
|
-
await memory.addMessage(sessionId, { role: 'assistant', content: responseContent });
|
|
329
|
+
await memory.addMessage(sessionId, { role: 'assistant', content: responseContent, timestamp: Date.now() });
|
|
276
330
|
// 5. 发送响应事件
|
|
277
331
|
eventBus.emitEvent({
|
|
278
332
|
type: 'response',
|
|
@@ -33,7 +33,7 @@ export class CreateAgentSkill extends BaseSkill {
|
|
|
33
33
|
required: ['name', 'description', 'systemPrompt']
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
|
-
async execute(args) {
|
|
36
|
+
async execute(args, _ctx) {
|
|
37
37
|
if (agentManager.getAgent(args.name)) {
|
|
38
38
|
return { error: `Agent '${args.name}' already exists.` };
|
|
39
39
|
}
|
|
@@ -21,7 +21,7 @@ export class DelegateSkill extends BaseSkill {
|
|
|
21
21
|
required: ['agentName', 'task']
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
|
-
async execute(args) {
|
|
24
|
+
async execute(args, _ctx) {
|
|
25
25
|
const agent = agentManager.getAgent(args.agentName);
|
|
26
26
|
if (!agent) {
|
|
27
27
|
return { error: `Agent '${args.agentName}' not found. Available agents: ${agentManager.getAllAgents().map(a => a.name).join(', ')}` };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BaseSkill } from './base-skill.js';
|
|
2
2
|
import fs from 'fs/promises';
|
|
3
3
|
import path from 'path';
|
|
4
|
+
import { resolvePathWithinWorkspace, resolveSessionWorkspace } from '../config/paths.js';
|
|
4
5
|
export class ListDirectorySkill extends BaseSkill {
|
|
5
6
|
constructor() {
|
|
6
7
|
super(...arguments);
|
|
@@ -11,14 +12,15 @@ export class ListDirectorySkill extends BaseSkill {
|
|
|
11
12
|
properties: {
|
|
12
13
|
path: {
|
|
13
14
|
type: 'string',
|
|
14
|
-
description: '
|
|
15
|
+
description: 'Absolute path, or relative to the current session workspace. Defaults to the session workspace.'
|
|
15
16
|
}
|
|
16
17
|
},
|
|
17
18
|
required: []
|
|
18
19
|
};
|
|
19
20
|
}
|
|
20
|
-
async execute(params) {
|
|
21
|
-
const
|
|
21
|
+
async execute(params, ctx) {
|
|
22
|
+
const workspace = resolveSessionWorkspace(ctx);
|
|
23
|
+
const dirPath = params.path ? resolvePathWithinWorkspace(workspace, String(params.path)) : workspace;
|
|
22
24
|
try {
|
|
23
25
|
const files = await fs.readdir(dirPath, { withFileTypes: true });
|
|
24
26
|
return files.map(file => ({
|
|
@@ -41,7 +43,7 @@ export class ReadFileSkill extends BaseSkill {
|
|
|
41
43
|
properties: {
|
|
42
44
|
path: {
|
|
43
45
|
type: 'string',
|
|
44
|
-
description: '
|
|
46
|
+
description: 'Absolute path, or relative to the current session workspace.'
|
|
45
47
|
},
|
|
46
48
|
encoding: {
|
|
47
49
|
type: 'string',
|
|
@@ -52,8 +54,9 @@ export class ReadFileSkill extends BaseSkill {
|
|
|
52
54
|
required: ['path']
|
|
53
55
|
};
|
|
54
56
|
}
|
|
55
|
-
async execute(params) {
|
|
56
|
-
const
|
|
57
|
+
async execute(params, ctx) {
|
|
58
|
+
const workspace = resolveSessionWorkspace(ctx);
|
|
59
|
+
const filePath = resolvePathWithinWorkspace(workspace, String(params.path));
|
|
57
60
|
const encoding = params.encoding || 'utf-8';
|
|
58
61
|
try {
|
|
59
62
|
const content = await fs.readFile(filePath, { encoding: encoding });
|
|
@@ -74,7 +77,7 @@ export class WriteFileSkill extends BaseSkill {
|
|
|
74
77
|
properties: {
|
|
75
78
|
path: {
|
|
76
79
|
type: 'string',
|
|
77
|
-
description: '
|
|
80
|
+
description: 'Absolute path, or relative to the current session workspace.'
|
|
78
81
|
},
|
|
79
82
|
content: {
|
|
80
83
|
type: 'string',
|
|
@@ -84,8 +87,9 @@ export class WriteFileSkill extends BaseSkill {
|
|
|
84
87
|
required: ['path', 'content']
|
|
85
88
|
};
|
|
86
89
|
}
|
|
87
|
-
async execute(params) {
|
|
88
|
-
const
|
|
90
|
+
async execute(params, ctx) {
|
|
91
|
+
const workspace = resolveSessionWorkspace(ctx);
|
|
92
|
+
const filePath = resolvePathWithinWorkspace(workspace, String(params.path));
|
|
89
93
|
try {
|
|
90
94
|
// Ensure directory exists
|
|
91
95
|
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
@@ -107,7 +111,7 @@ export class DeleteFileSkill extends BaseSkill {
|
|
|
107
111
|
properties: {
|
|
108
112
|
path: {
|
|
109
113
|
type: 'string',
|
|
110
|
-
description: '
|
|
114
|
+
description: 'Absolute path, or relative to the current session workspace.'
|
|
111
115
|
},
|
|
112
116
|
recursive: {
|
|
113
117
|
type: 'boolean',
|
|
@@ -117,8 +121,9 @@ export class DeleteFileSkill extends BaseSkill {
|
|
|
117
121
|
required: ['path']
|
|
118
122
|
};
|
|
119
123
|
}
|
|
120
|
-
async execute(params) {
|
|
121
|
-
const
|
|
124
|
+
async execute(params, ctx) {
|
|
125
|
+
const workspace = resolveSessionWorkspace(ctx);
|
|
126
|
+
const filePath = resolvePathWithinWorkspace(workspace, String(params.path));
|
|
122
127
|
const recursive = params.recursive || false;
|
|
123
128
|
try {
|
|
124
129
|
const stats = await fs.stat(filePath);
|
|
@@ -21,7 +21,7 @@ export class ReadExcelSkill extends BaseSkill {
|
|
|
21
21
|
required: ['file_path']
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
|
-
async execute(args) {
|
|
24
|
+
async execute(args, _ctx) {
|
|
25
25
|
try {
|
|
26
26
|
if (!fs.existsSync(args.file_path)) {
|
|
27
27
|
return { error: `File not found: ${args.file_path}` };
|
|
@@ -68,7 +68,7 @@ export class CreateExcelSkill extends BaseSkill {
|
|
|
68
68
|
required: ['file_path', 'data']
|
|
69
69
|
};
|
|
70
70
|
}
|
|
71
|
-
async execute(args) {
|
|
71
|
+
async execute(args, _ctx) {
|
|
72
72
|
try {
|
|
73
73
|
const workbook = xlsx.utils.book_new();
|
|
74
74
|
const sheet = xlsx.utils.json_to_sheet(args.data);
|
|
@@ -31,7 +31,7 @@ export class CreatePptxSkill extends BaseSkill {
|
|
|
31
31
|
required: ['file_path', 'slides']
|
|
32
32
|
};
|
|
33
33
|
}
|
|
34
|
-
async execute(args) {
|
|
34
|
+
async execute(args, _ctx) {
|
|
35
35
|
try {
|
|
36
36
|
// Handle different import styles (ESM/CJS interop)
|
|
37
37
|
const PptxGenJS = pptxgen.default || pptxgen;
|
|
@@ -18,7 +18,7 @@ export class ReadWordSkill extends BaseSkill {
|
|
|
18
18
|
required: ['file_path']
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
|
-
async execute(args) {
|
|
21
|
+
async execute(args, _ctx) {
|
|
22
22
|
try {
|
|
23
23
|
if (!fs.existsSync(args.file_path)) {
|
|
24
24
|
return { error: `File not found: ${args.file_path}` };
|
|
@@ -55,7 +55,7 @@ export class CreateWordSkill extends BaseSkill {
|
|
|
55
55
|
required: ['file_path', 'content']
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
|
-
async execute(args) {
|
|
58
|
+
async execute(args, _ctx) {
|
|
59
59
|
return new Promise((resolve, reject) => {
|
|
60
60
|
try {
|
|
61
61
|
const docx = officegen('docx');
|
package/package.json
CHANGED
|
@@ -16,11 +16,20 @@
|
|
|
16
16
|
"title": "xiaozuoAssistant",
|
|
17
17
|
"newChat": "New chat",
|
|
18
18
|
"recent": "Recent",
|
|
19
|
-
"defaultSession": "Default Session",
|
|
20
|
-
"newConversation": "New Conversation",
|
|
21
19
|
"settings": "Settings",
|
|
20
|
+
"editSession": "Edit session",
|
|
22
21
|
"deleteConfirm": "Are you sure you want to delete this session?"
|
|
23
22
|
},
|
|
23
|
+
"sessionMeta": {
|
|
24
|
+
"title": "Session Settings",
|
|
25
|
+
"aliasLabel": "Alias (optional)",
|
|
26
|
+
"aliasPlaceholder": "e.g., Project A / Requirements",
|
|
27
|
+
"aliasHint": "Alias is shown in the list and header. Empty falls back to session ID.",
|
|
28
|
+
"workspaceLabel": "Workspace",
|
|
29
|
+
"workspaceHint": "File tools default to this workspace and are restricted to it.",
|
|
30
|
+
"selectWorkspace": "Select workspace",
|
|
31
|
+
"selectCurrentFolder": "Select current folder"
|
|
32
|
+
},
|
|
24
33
|
"settings": {
|
|
25
34
|
"title": "Settings",
|
|
26
35
|
"tabs": {
|
|
@@ -16,11 +16,20 @@
|
|
|
16
16
|
"title": "xiaozuoAssistant",
|
|
17
17
|
"newChat": "新对话",
|
|
18
18
|
"recent": "最近",
|
|
19
|
-
"defaultSession": "默认会话",
|
|
20
|
-
"newConversation": "新会话",
|
|
21
19
|
"settings": "设置",
|
|
20
|
+
"editSession": "编辑会话",
|
|
22
21
|
"deleteConfirm": "确定要删除这个会话吗?"
|
|
23
22
|
},
|
|
23
|
+
"sessionMeta": {
|
|
24
|
+
"title": "会话设置",
|
|
25
|
+
"aliasLabel": "会话别名(可选)",
|
|
26
|
+
"aliasPlaceholder": "例如:项目A / 需求讨论",
|
|
27
|
+
"aliasHint": "列表与聊天头部将优先展示别名。留空将回退显示会话 ID。",
|
|
28
|
+
"workspaceLabel": "Workspace(工作目录)",
|
|
29
|
+
"workspaceHint": "文件相关工具默认以该目录为工作区,并限制访问范围。",
|
|
30
|
+
"selectWorkspace": "选择工作目录",
|
|
31
|
+
"selectCurrentFolder": "选择当前目录"
|
|
32
|
+
},
|
|
24
33
|
"settings": {
|
|
25
34
|
"title": "设置",
|
|
26
35
|
"tabs": {
|