@bolloon/bolloon-agent 0.1.2 → 0.1.4
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/bolloon-cli.cjs +15 -7
- package/dist/agents/pi-sdk.js +12 -4
- package/dist/llm/config-store.js +8 -5
- package/dist/web/components/p2p/P2PModal.js +188 -0
- package/dist/web/components/p2p/index.js +264 -226
- package/dist/web/components/p2p/p2p-modal.js +657 -0
- package/dist/web/components/p2p/p2p-tools.js +248 -0
- package/dist/web/server.js +1890 -0
- package/package.json +1 -1
- package/src/web/server.ts +25 -26
package/package.json
CHANGED
package/src/web/server.ts
CHANGED
|
@@ -71,6 +71,7 @@ interface SessionMessage {
|
|
|
71
71
|
|
|
72
72
|
interface Session {
|
|
73
73
|
channelId: string;
|
|
74
|
+
sessionId: string;
|
|
74
75
|
messages: SessionMessage[];
|
|
75
76
|
lastUpdated: string;
|
|
76
77
|
}
|
|
@@ -103,8 +104,10 @@ async function saveChannels(channels: Channel[]): Promise<void> {
|
|
|
103
104
|
});
|
|
104
105
|
}
|
|
105
106
|
|
|
106
|
-
async function loadSession(channelId: string): Promise<Session | null> {
|
|
107
|
-
|
|
107
|
+
async function loadSession(channelId: string, sessionId?: string): Promise<Session | null> {
|
|
108
|
+
// sessionId is optional for backward compatibility; if provided, load specific session
|
|
109
|
+
const key = sessionId ? `${channelId}:${sessionId}` : channelId;
|
|
110
|
+
const sessionPath = path.join(SESSION_CACHE_PATH, `${key}.json`);
|
|
108
111
|
try {
|
|
109
112
|
const data = await fs.readFile(sessionPath, 'utf-8');
|
|
110
113
|
return JSON.parse(data);
|
|
@@ -114,7 +117,8 @@ async function loadSession(channelId: string): Promise<Session | null> {
|
|
|
114
117
|
}
|
|
115
118
|
|
|
116
119
|
async function saveSession(session: Session): Promise<void> {
|
|
117
|
-
const
|
|
120
|
+
const key = session.sessionId ? `${session.channelId}:${session.sessionId}` : session.channelId;
|
|
121
|
+
const sessionPath = path.join(SESSION_CACHE_PATH, `${key}.json`);
|
|
118
122
|
await fs.writeFile(sessionPath, JSON.stringify(session, null, 2));
|
|
119
123
|
}
|
|
120
124
|
|
|
@@ -541,6 +545,7 @@ export async function createWebServer(port: number = 3000) {
|
|
|
541
545
|
// 获取频道信息,包括真实 DID 和完整 DID 文档
|
|
542
546
|
const channels = await loadChannels();
|
|
543
547
|
const channel = channels.find(c => c.id === channelId);
|
|
548
|
+
const currentSessionId = channel?.currentSessionId || 'default';
|
|
544
549
|
const realChannelDid = channelDid || channel?.did || '';
|
|
545
550
|
const realChannelName = channel?.name || '';
|
|
546
551
|
const realChannelDidDoc = channel?.didDocument;
|
|
@@ -568,7 +573,7 @@ export async function createWebServer(port: number = 3000) {
|
|
|
568
573
|
}
|
|
569
574
|
};
|
|
570
575
|
|
|
571
|
-
console.log(`[消息处理] 开始处理用户消息, channelId: ${channelId}`);
|
|
576
|
+
console.log(`[消息处理] 开始处理用户消息, channelId: ${channelId}, sessionId: ${currentSessionId}`);
|
|
572
577
|
|
|
573
578
|
// 将真实 DID 作为上下文前缀,让 AI 使用真实的 DID 而不是自己编造的
|
|
574
579
|
const contextHint = realChannelDid ? `[系统上下文] 当前频道名称: ${realChannelName}, 你的真实 DID: ${realChannelDid}\n\n` : '';
|
|
@@ -576,8 +581,9 @@ export async function createWebServer(port: number = 3000) {
|
|
|
576
581
|
|
|
577
582
|
broadcast({ type: 'ai', content: fullResponse }, channelId);
|
|
578
583
|
|
|
579
|
-
const existingSession = await loadSession(channelId);
|
|
580
|
-
const session: Session = existingSession || { channelId, messages: [], lastUpdated: new Date().toISOString() };
|
|
584
|
+
const existingSession = await loadSession(channelId, currentSessionId);
|
|
585
|
+
const session: Session = existingSession || { channelId, sessionId: currentSessionId, messages: [], lastUpdated: new Date().toISOString() };
|
|
586
|
+
session.sessionId = currentSessionId;
|
|
581
587
|
session.messages.push({ id: crypto.randomUUID(), type: 'user' as const, content: text, timestamp: new Date().toISOString() });
|
|
582
588
|
session.messages.push({ id: crypto.randomUUID(), type: 'ai' as const, content: fullResponse, timestamp: new Date().toISOString() });
|
|
583
589
|
session.lastUpdated = new Date().toISOString();
|
|
@@ -707,7 +713,7 @@ app.get('/channels', async (_req, res) => {
|
|
|
707
713
|
console.log(`[创建频道] 先保存频道 ID: ${id}`);
|
|
708
714
|
channels.push(channel);
|
|
709
715
|
await saveChannels(channels);
|
|
710
|
-
await saveSession({ channelId: id, messages: [], lastUpdated: new Date().toISOString() });
|
|
716
|
+
await saveSession({ channelId: id, sessionId: 'default', messages: [], lastUpdated: new Date().toISOString() });
|
|
711
717
|
res.json(channel);
|
|
712
718
|
|
|
713
719
|
// 后台生成 DID
|
|
@@ -907,6 +913,7 @@ app.get('/channels', async (_req, res) => {
|
|
|
907
913
|
try {
|
|
908
914
|
const channels = await loadChannels();
|
|
909
915
|
const channel = channels.find(c => c.id === channelId);
|
|
916
|
+
const currentSessionId = channel?.currentSessionId || 'default';
|
|
910
917
|
const realChannelDid = channel?.did || '';
|
|
911
918
|
const realChannelName = channel?.name || '';
|
|
912
919
|
const realChannelDidDoc = channel?.didDocument;
|
|
@@ -933,7 +940,7 @@ app.get('/channels', async (_req, res) => {
|
|
|
933
940
|
broadcast({ type: 'ai', content: fullResponse }, channelId);
|
|
934
941
|
|
|
935
942
|
// 更新 session
|
|
936
|
-
const existingSession = await loadSession(channelId);
|
|
943
|
+
const existingSession = await loadSession(channelId, currentSessionId);
|
|
937
944
|
if (existingSession && existingSession.messages.length > 0) {
|
|
938
945
|
// 移除最后一个 AI 消息,替换为新的
|
|
939
946
|
const lastAiIndex = existingSession.messages.map((m: any) => m.type).lastIndexOf('ai');
|
|
@@ -1699,26 +1706,18 @@ app.get('/channels', async (_req, res) => {
|
|
|
1699
1706
|
return;
|
|
1700
1707
|
}
|
|
1701
1708
|
|
|
1702
|
-
// 通过 P2P
|
|
1703
|
-
|
|
1704
|
-
const
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
// 找到连接并发送
|
|
1711
|
-
const connections = p2pCommunicator.getConnections();
|
|
1712
|
-
for (const conn of connections) {
|
|
1713
|
-
if (conn.publicKey.includes(targetPeerId) || targetPeerId.includes(conn.publicKey.substring(0, 16))) {
|
|
1714
|
-
conn.send(payload);
|
|
1715
|
-
res.json({ ok: true, sent: true });
|
|
1716
|
-
return;
|
|
1717
|
-
}
|
|
1709
|
+
// 通过 P2P 发送消息(如果可用)
|
|
1710
|
+
try {
|
|
1711
|
+
const comm = p2pCommunicator as any;
|
|
1712
|
+
if (comm && typeof comm.send === 'function') {
|
|
1713
|
+
await comm.send(message, targetPeerId);
|
|
1714
|
+
res.json({ ok: true, sent: true });
|
|
1715
|
+
return;
|
|
1718
1716
|
}
|
|
1719
|
-
}
|
|
1717
|
+
} catch {}
|
|
1720
1718
|
|
|
1721
|
-
|
|
1719
|
+
// 如果 P2P 不可用,消息已在上面加入队列
|
|
1720
|
+
res.json({ ok: true, queued: true, message: '消息已加入队列,等待对方上线' });
|
|
1722
1721
|
} catch (err: any) {
|
|
1723
1722
|
res.status(500).json({ error: err.message });
|
|
1724
1723
|
}
|