@yeaft/webchat-agent 0.1.124 → 0.1.126
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/claude.js +0 -224
- package/connection/message-router.js +2 -6
- package/conversation.js +8 -317
- package/crew/context-loader.js +171 -0
- package/crew.js +3 -0
- package/package.json +1 -1
- package/roleplay-dir.js +0 -305
- package/roleplay-i18n.js +0 -574
- package/roleplay-session.js +0 -184
- package/roleplay.js +0 -1061
package/roleplay-session.js
DELETED
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* RolePlay Session — session index management for .roleplay/session.json.
|
|
3
|
-
*
|
|
4
|
-
* Analogous to agent/crew/session.js but much simpler:
|
|
5
|
-
* - No multi-process concerns (single process)
|
|
6
|
-
* - No worktree management
|
|
7
|
-
* - Atomic write for crash safety
|
|
8
|
-
*
|
|
9
|
-
* session.json schema:
|
|
10
|
-
* {
|
|
11
|
-
* sessions: [{ name, teamType, language, projectDir, conversationId,
|
|
12
|
-
* roles, createdAt, updatedAt, status }],
|
|
13
|
-
* activeSession: string | null
|
|
14
|
-
* }
|
|
15
|
-
*/
|
|
16
|
-
import { promises as fs } from 'fs';
|
|
17
|
-
import { join } from 'path';
|
|
18
|
-
import { existsSync, readFileSync, writeFileSync, renameSync } from 'fs';
|
|
19
|
-
|
|
20
|
-
const SESSION_FILE = 'session.json';
|
|
21
|
-
|
|
22
|
-
// ─── Read / Write ───────────────────────────────────────────────────
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Load .roleplay/session.json.
|
|
26
|
-
* Returns { sessions: [], activeSession: null } if file doesn't exist or is corrupt.
|
|
27
|
-
*
|
|
28
|
-
* @param {string} projectDir
|
|
29
|
-
* @returns {{ sessions: Array, activeSession: string|null }}
|
|
30
|
-
*/
|
|
31
|
-
export function loadRolePlaySessionIndex(projectDir) {
|
|
32
|
-
const filePath = join(projectDir, '.roleplay', SESSION_FILE);
|
|
33
|
-
if (!existsSync(filePath)) {
|
|
34
|
-
return { sessions: [], activeSession: null };
|
|
35
|
-
}
|
|
36
|
-
try {
|
|
37
|
-
const raw = readFileSync(filePath, 'utf-8');
|
|
38
|
-
const data = JSON.parse(raw);
|
|
39
|
-
return {
|
|
40
|
-
sessions: Array.isArray(data.sessions) ? data.sessions : [],
|
|
41
|
-
activeSession: data.activeSession || null,
|
|
42
|
-
};
|
|
43
|
-
} catch (e) {
|
|
44
|
-
console.warn('[RolePlaySession] Failed to load session.json:', e.message);
|
|
45
|
-
return { sessions: [], activeSession: null };
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Save .roleplay/session.json atomically (write tmp → rename).
|
|
51
|
-
*
|
|
52
|
-
* @param {string} projectDir
|
|
53
|
-
* @param {{ sessions: Array, activeSession: string|null }} data
|
|
54
|
-
*/
|
|
55
|
-
export async function saveRolePlaySessionIndex(projectDir, data) {
|
|
56
|
-
const rpDir = join(projectDir, '.roleplay');
|
|
57
|
-
const filePath = join(rpDir, SESSION_FILE);
|
|
58
|
-
const tmpPath = `${filePath}.tmp.${Date.now()}`;
|
|
59
|
-
|
|
60
|
-
const content = JSON.stringify(data, null, 2);
|
|
61
|
-
try {
|
|
62
|
-
await fs.mkdir(rpDir, { recursive: true });
|
|
63
|
-
await fs.writeFile(tmpPath, content);
|
|
64
|
-
await fs.rename(tmpPath, filePath);
|
|
65
|
-
} catch (e) {
|
|
66
|
-
console.error('[RolePlaySession] Failed to save session.json:', e.message);
|
|
67
|
-
// Clean up tmp file if rename failed
|
|
68
|
-
try { await fs.unlink(tmpPath); } catch {}
|
|
69
|
-
throw e;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// ─── Session CRUD ───────────────────────────────────────────────────
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Add a new session entry to .roleplay/session.json.
|
|
77
|
-
* Sets it as the activeSession.
|
|
78
|
-
*
|
|
79
|
-
* @param {string} projectDir
|
|
80
|
-
* @param {object} session - session entry to add:
|
|
81
|
-
* { name, teamType, language, projectDir, conversationId, roles, createdAt }
|
|
82
|
-
* @returns {object} the session entry with updatedAt/status fields added
|
|
83
|
-
*/
|
|
84
|
-
export async function addRolePlaySession(projectDir, session) {
|
|
85
|
-
const index = loadRolePlaySessionIndex(projectDir);
|
|
86
|
-
|
|
87
|
-
// Check for duplicate session name
|
|
88
|
-
const existing = index.sessions.find(s => s.name === session.name);
|
|
89
|
-
if (existing) {
|
|
90
|
-
// Update existing entry instead of creating duplicate
|
|
91
|
-
Object.assign(existing, {
|
|
92
|
-
...session,
|
|
93
|
-
updatedAt: Date.now(),
|
|
94
|
-
status: 'active',
|
|
95
|
-
});
|
|
96
|
-
index.activeSession = session.name;
|
|
97
|
-
await saveRolePlaySessionIndex(projectDir, index);
|
|
98
|
-
return existing;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const entry = {
|
|
102
|
-
...session,
|
|
103
|
-
updatedAt: Date.now(),
|
|
104
|
-
status: 'active',
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
index.sessions.push(entry);
|
|
108
|
-
index.activeSession = session.name;
|
|
109
|
-
await saveRolePlaySessionIndex(projectDir, index);
|
|
110
|
-
return entry;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Remove (archive) a session from .roleplay/session.json.
|
|
115
|
-
* The session entry is marked as 'archived', not deleted,
|
|
116
|
-
* so the context/ directory content remains valid.
|
|
117
|
-
*
|
|
118
|
-
* Optionally removes the session's roles/ directory.
|
|
119
|
-
*
|
|
120
|
-
* @param {string} projectDir
|
|
121
|
-
* @param {string} sessionName
|
|
122
|
-
* @param {object} [options]
|
|
123
|
-
* @param {boolean} [options.removeDir=true] - remove .roleplay/roles/{sessionName}/
|
|
124
|
-
*/
|
|
125
|
-
export async function removeRolePlaySession(projectDir, sessionName, options = {}) {
|
|
126
|
-
const { removeDir = true } = options;
|
|
127
|
-
const index = loadRolePlaySessionIndex(projectDir);
|
|
128
|
-
|
|
129
|
-
const session = index.sessions.find(s => s.name === sessionName);
|
|
130
|
-
if (session) {
|
|
131
|
-
session.status = 'archived';
|
|
132
|
-
session.updatedAt = Date.now();
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Clear activeSession if it was the removed one
|
|
136
|
-
if (index.activeSession === sessionName) {
|
|
137
|
-
// Pick next active session (most recently updated non-archived)
|
|
138
|
-
const active = index.sessions
|
|
139
|
-
.filter(s => s.status === 'active')
|
|
140
|
-
.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0));
|
|
141
|
-
index.activeSession = active[0]?.name || null;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
await saveRolePlaySessionIndex(projectDir, index);
|
|
145
|
-
|
|
146
|
-
// Remove the session directory (but keep context/)
|
|
147
|
-
if (removeDir) {
|
|
148
|
-
const sessionDir = join(projectDir, '.roleplay', 'roles', sessionName);
|
|
149
|
-
try {
|
|
150
|
-
await fs.rm(sessionDir, { recursive: true, force: true });
|
|
151
|
-
} catch {
|
|
152
|
-
// Not critical — may not exist
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Find a session entry by conversationId.
|
|
159
|
-
*
|
|
160
|
-
* @param {string} projectDir
|
|
161
|
-
* @param {string} conversationId
|
|
162
|
-
* @returns {object|null} session entry or null
|
|
163
|
-
*/
|
|
164
|
-
export function findRolePlaySessionByConversationId(projectDir, conversationId) {
|
|
165
|
-
if (!conversationId) return null;
|
|
166
|
-
const index = loadRolePlaySessionIndex(projectDir);
|
|
167
|
-
return index.sessions.find(s => s.conversationId === conversationId) || null;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Update the activeSession pointer and updatedAt timestamp.
|
|
172
|
-
*
|
|
173
|
-
* @param {string} projectDir
|
|
174
|
-
* @param {string} sessionName
|
|
175
|
-
*/
|
|
176
|
-
export async function setActiveRolePlaySession(projectDir, sessionName) {
|
|
177
|
-
const index = loadRolePlaySessionIndex(projectDir);
|
|
178
|
-
const session = index.sessions.find(s => s.name === sessionName);
|
|
179
|
-
if (session) {
|
|
180
|
-
session.updatedAt = Date.now();
|
|
181
|
-
index.activeSession = sessionName;
|
|
182
|
-
await saveRolePlaySessionIndex(projectDir, index);
|
|
183
|
-
}
|
|
184
|
-
}
|