clawmate 1.3.0 → 1.4.1
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/electron-builder.yml +1 -1
- package/index.js +589 -406
- package/main/ai-bridge.js +64 -58
- package/main/ai-connector.js +67 -62
- package/main/autostart.js +7 -7
- package/main/desktop-path.js +4 -4
- package/main/file-command-parser.js +77 -41
- package/main/file-ops.js +27 -27
- package/main/index.js +18 -16
- package/main/ipc-handlers.js +27 -24
- package/main/manifest.js +2 -2
- package/main/platform.js +16 -16
- package/main/smart-file-ops.js +64 -64
- package/main/store.js +1 -1
- package/main/telegram.js +154 -121
- package/main/tray.js +226 -71
- package/main/updater.js +13 -13
- package/openclaw.plugin.json +1 -1
- package/package.json +3 -4
- package/preload/preload.js +18 -18
- package/renderer/css/effects.css +6 -6
- package/renderer/css/pet.css +8 -8
- package/renderer/css/speech.css +5 -5
- package/renderer/first-run.html +15 -15
- package/renderer/index.html +4 -4
- package/renderer/js/ai-controller.js +99 -88
- package/renderer/js/app.js +26 -23
- package/renderer/js/browser-watcher.js +32 -32
- package/renderer/js/character.js +33 -33
- package/renderer/js/interactions.js +57 -14
- package/renderer/js/memory.js +144 -37
- package/renderer/js/metrics.js +141 -141
- package/renderer/js/mode-manager.js +59 -15
- package/renderer/js/pet-engine.js +236 -236
- package/renderer/js/speech.js +19 -19
- package/renderer/js/state-machine.js +23 -23
- package/renderer/js/time-aware.js +15 -15
- package/renderer/launcher.html +9 -9
- package/shared/constants.js +11 -11
- package/shared/messages.js +130 -130
- package/shared/personalities.js +72 -37
- package/skills/launch-pet/index.js +13 -13
- package/skills/launch-pet/skill.json +12 -23
package/renderer/js/memory.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* User interaction memory + evolution system
|
|
3
3
|
*
|
|
4
|
-
* -
|
|
5
|
-
* -
|
|
6
|
-
* -
|
|
4
|
+
* - Tracks click count, days, milestones
|
|
5
|
+
* - Evolution stage management: always evolves in positive/cute directions only
|
|
6
|
+
* - Never transforms into scary/creepy appearances
|
|
7
7
|
*/
|
|
8
8
|
const Memory = (() => {
|
|
9
9
|
let data = {
|
|
@@ -13,9 +13,23 @@ const Memory = (() => {
|
|
|
13
13
|
lastVisitDate: null,
|
|
14
14
|
milestones: [],
|
|
15
15
|
evolutionStage: 0,
|
|
16
|
-
interactionStreak: 0, //
|
|
16
|
+
interactionStreak: 0, // Consecutive visit days
|
|
17
|
+
|
|
18
|
+
// --- Motion history ---
|
|
19
|
+
motionHistory: [], // Recent 100 state transition records [{state, timestamp, duration}]
|
|
20
|
+
motionStats: {}, // Accumulated time per state {idle: 12345, walking: 6789, ...}
|
|
21
|
+
|
|
22
|
+
// --- User reaction storage ---
|
|
23
|
+
reactionLog: [], // Recent 50 user reactions [{action, reaction, timestamp}]
|
|
24
|
+
favoriteActions: {}, // Positive reaction count per action {excited: 5, walking: 2, ...}
|
|
25
|
+
dislikedActions: {}, // Negative reaction count per action (ignored/abandoned)
|
|
17
26
|
};
|
|
18
27
|
|
|
28
|
+
let lastMotionState = null;
|
|
29
|
+
let lastMotionTime = 0;
|
|
30
|
+
const MAX_MOTION_HISTORY = 100;
|
|
31
|
+
const MAX_REACTION_LOG = 50;
|
|
32
|
+
|
|
19
33
|
let evolutionStages = null;
|
|
20
34
|
|
|
21
35
|
async function init() {
|
|
@@ -26,22 +40,22 @@ const Memory = (() => {
|
|
|
26
40
|
|
|
27
41
|
evolutionStages = window._evolutionStages;
|
|
28
42
|
|
|
29
|
-
//
|
|
43
|
+
// First run
|
|
30
44
|
if (!data.firstRunDate) {
|
|
31
45
|
data.firstRunDate = new Date().toISOString();
|
|
32
46
|
await save();
|
|
33
47
|
}
|
|
34
48
|
|
|
35
|
-
//
|
|
49
|
+
// Calculate days
|
|
36
50
|
updateDayCount();
|
|
37
51
|
|
|
38
|
-
//
|
|
52
|
+
// Check milestones
|
|
39
53
|
checkMilestones();
|
|
40
54
|
|
|
41
|
-
//
|
|
55
|
+
// Check evolution
|
|
42
56
|
checkEvolution();
|
|
43
57
|
|
|
44
|
-
//
|
|
58
|
+
// Apply evolution visual effects
|
|
45
59
|
applyEvolutionVisuals();
|
|
46
60
|
}
|
|
47
61
|
|
|
@@ -50,7 +64,7 @@ const Memory = (() => {
|
|
|
50
64
|
const now = new Date();
|
|
51
65
|
data.totalDays = Math.floor((now - firstRun) / (1000 * 60 * 60 * 24));
|
|
52
66
|
|
|
53
|
-
//
|
|
67
|
+
// Check consecutive visits
|
|
54
68
|
const lastVisit = data.lastVisitDate ? new Date(data.lastVisitDate) : null;
|
|
55
69
|
const today = now.toDateString();
|
|
56
70
|
if (lastVisit && lastVisit.toDateString() !== today) {
|
|
@@ -89,7 +103,7 @@ const Memory = (() => {
|
|
|
89
103
|
data.milestones.push(check.key);
|
|
90
104
|
const msg = Speech.getMilestoneMessage(check.key);
|
|
91
105
|
if (msg) {
|
|
92
|
-
//
|
|
106
|
+
// Display milestone message after a slight delay
|
|
93
107
|
setTimeout(() => {
|
|
94
108
|
Speech.show(msg);
|
|
95
109
|
Interactions.spawnStarEffect();
|
|
@@ -100,9 +114,9 @@ const Memory = (() => {
|
|
|
100
114
|
}
|
|
101
115
|
|
|
102
116
|
/**
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
117
|
+
* Check evolution stage
|
|
118
|
+
* Only goes up (no devolution)
|
|
119
|
+
* Condition: both click count and days together must be met
|
|
106
120
|
*/
|
|
107
121
|
function checkEvolution() {
|
|
108
122
|
if (!evolutionStages) return;
|
|
@@ -127,22 +141,22 @@ const Memory = (() => {
|
|
|
127
141
|
}
|
|
128
142
|
|
|
129
143
|
/**
|
|
130
|
-
*
|
|
131
|
-
* -
|
|
132
|
-
* -
|
|
133
|
-
* -
|
|
144
|
+
* Evolution event handler
|
|
145
|
+
* - Bright flash effect (soft light)
|
|
146
|
+
* - Sparkle particles
|
|
147
|
+
* - Congratulatory message
|
|
134
148
|
*/
|
|
135
149
|
function onEvolution(prevStage, newStage) {
|
|
136
150
|
const msgs = window._messages;
|
|
137
151
|
const stageInfo = evolutionStages[newStage];
|
|
138
152
|
|
|
139
|
-
//
|
|
153
|
+
// Bright flash (soft, non-scary effect)
|
|
140
154
|
const flash = document.createElement('div');
|
|
141
155
|
flash.className = 'evolve-flash';
|
|
142
156
|
document.body.appendChild(flash);
|
|
143
157
|
setTimeout(() => flash.remove(), 600);
|
|
144
158
|
|
|
145
|
-
//
|
|
159
|
+
// Evolution sparkle particles (bright colors only)
|
|
146
160
|
const pos = PetEngine.getPosition();
|
|
147
161
|
const sparkleColors = ['#FFD700', '#FF69B4', '#87CEEB', '#98FB98', '#DDA0DD'];
|
|
148
162
|
for (let i = 0; i < 16; i++) {
|
|
@@ -155,7 +169,7 @@ const Memory = (() => {
|
|
|
155
169
|
setTimeout(() => sparkle.remove(), 800);
|
|
156
170
|
}
|
|
157
171
|
|
|
158
|
-
//
|
|
172
|
+
// Evolution ring effect (warm colors)
|
|
159
173
|
const ring = document.createElement('div');
|
|
160
174
|
ring.className = 'evolve-ring';
|
|
161
175
|
ring.style.width = '64px';
|
|
@@ -166,7 +180,7 @@ const Memory = (() => {
|
|
|
166
180
|
document.getElementById('world').appendChild(ring);
|
|
167
181
|
setTimeout(() => ring.remove(), 1000);
|
|
168
182
|
|
|
169
|
-
//
|
|
183
|
+
// Congratulatory message
|
|
170
184
|
if (msgs && msgs.evolution) {
|
|
171
185
|
const evolveMsg = msgs.evolution[`stage_${newStage}`];
|
|
172
186
|
if (evolveMsg) {
|
|
@@ -174,13 +188,13 @@ const Memory = (() => {
|
|
|
174
188
|
}
|
|
175
189
|
}
|
|
176
190
|
|
|
177
|
-
//
|
|
191
|
+
// Update visual effects
|
|
178
192
|
applyEvolutionVisuals();
|
|
179
193
|
}
|
|
180
194
|
|
|
181
195
|
/**
|
|
182
|
-
*
|
|
183
|
-
*
|
|
196
|
+
* Apply visual changes based on evolution stage
|
|
197
|
+
* Always positive: gets brighter, sparkly, and cute accessories added
|
|
184
198
|
*/
|
|
185
199
|
function applyEvolutionVisuals() {
|
|
186
200
|
if (!evolutionStages) return;
|
|
@@ -190,17 +204,17 @@ const Memory = (() => {
|
|
|
190
204
|
const pet = document.getElementById('pet-container');
|
|
191
205
|
if (!pet) return;
|
|
192
206
|
|
|
193
|
-
//
|
|
207
|
+
// Size scale
|
|
194
208
|
pet.style.transform = pet.style.transform || '';
|
|
195
209
|
|
|
196
|
-
//
|
|
210
|
+
// Brightness/saturation -- gets brighter and more vibrant with evolution
|
|
197
211
|
const { brightness, saturation } = stage.colorMod;
|
|
198
212
|
const canvas = pet.querySelector('canvas');
|
|
199
213
|
if (canvas) {
|
|
200
214
|
canvas.style.filter = `brightness(${brightness}) saturate(${saturation})`;
|
|
201
215
|
}
|
|
202
216
|
|
|
203
|
-
//
|
|
217
|
+
// Remove accessories then reapply
|
|
204
218
|
pet.querySelectorAll('.accessory').forEach(a => a.remove());
|
|
205
219
|
|
|
206
220
|
for (const acc of stage.accessories) {
|
|
@@ -209,8 +223,8 @@ const Memory = (() => {
|
|
|
209
223
|
}
|
|
210
224
|
|
|
211
225
|
/**
|
|
212
|
-
*
|
|
213
|
-
*
|
|
226
|
+
* Add cute accessories
|
|
227
|
+
* All accessories are bright and cute elements only
|
|
214
228
|
*/
|
|
215
229
|
function addAccessory(container, type) {
|
|
216
230
|
const acc = document.createElement('div');
|
|
@@ -221,7 +235,7 @@ const Memory = (() => {
|
|
|
221
235
|
|
|
222
236
|
switch (type) {
|
|
223
237
|
case 'blush':
|
|
224
|
-
//
|
|
238
|
+
// Pink circles on both cheeks
|
|
225
239
|
acc.style.width = '8px';
|
|
226
240
|
acc.style.height = '6px';
|
|
227
241
|
acc.style.borderRadius = '50%';
|
|
@@ -229,14 +243,14 @@ const Memory = (() => {
|
|
|
229
243
|
acc.style.left = '12px';
|
|
230
244
|
acc.style.top = '38px';
|
|
231
245
|
container.appendChild(acc);
|
|
232
|
-
//
|
|
246
|
+
// Right cheek
|
|
233
247
|
const blush2 = acc.cloneNode();
|
|
234
248
|
blush2.style.left = '44px';
|
|
235
249
|
container.appendChild(blush2);
|
|
236
250
|
return;
|
|
237
251
|
|
|
238
252
|
case 'sparkle_eyes':
|
|
239
|
-
//
|
|
253
|
+
// Eye sparkles (small white dots)
|
|
240
254
|
acc.style.width = '3px';
|
|
241
255
|
acc.style.height = '3px';
|
|
242
256
|
acc.style.borderRadius = '50%';
|
|
@@ -286,14 +300,14 @@ const Memory = (() => {
|
|
|
286
300
|
break;
|
|
287
301
|
|
|
288
302
|
case 'wings':
|
|
289
|
-
//
|
|
303
|
+
// Small angel wings (left)
|
|
290
304
|
acc.textContent = '\u{1FABD}';
|
|
291
305
|
acc.style.fontSize = '10px';
|
|
292
306
|
acc.style.left = '-6px';
|
|
293
307
|
acc.style.top = '20px';
|
|
294
308
|
acc.style.opacity = '0.7';
|
|
295
309
|
container.appendChild(acc);
|
|
296
|
-
//
|
|
310
|
+
// Right wing
|
|
297
311
|
const wing2 = acc.cloneNode(true);
|
|
298
312
|
wing2.style.left = '58px';
|
|
299
313
|
wing2.style.transform = 'scaleX(-1)';
|
|
@@ -304,6 +318,95 @@ const Memory = (() => {
|
|
|
304
318
|
container.appendChild(acc);
|
|
305
319
|
}
|
|
306
320
|
|
|
321
|
+
// --- Motion history recording ---
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Record state transition
|
|
325
|
+
* Called when state changes in StateMachine
|
|
326
|
+
*/
|
|
327
|
+
function recordMotion(newState) {
|
|
328
|
+
const now = Date.now();
|
|
329
|
+
|
|
330
|
+
// Calculate previous state duration -> accumulate statistics
|
|
331
|
+
if (lastMotionState && lastMotionTime > 0) {
|
|
332
|
+
const duration = now - lastMotionTime;
|
|
333
|
+
if (!data.motionStats[lastMotionState]) data.motionStats[lastMotionState] = 0;
|
|
334
|
+
data.motionStats[lastMotionState] += duration;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Add to history
|
|
338
|
+
data.motionHistory.push({
|
|
339
|
+
state: newState,
|
|
340
|
+
timestamp: now,
|
|
341
|
+
from: lastMotionState || 'init',
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
// Remove old entries when exceeding max size
|
|
345
|
+
if (data.motionHistory.length > MAX_MOTION_HISTORY) {
|
|
346
|
+
data.motionHistory = data.motionHistory.slice(-MAX_MOTION_HISTORY);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
lastMotionState = newState;
|
|
350
|
+
lastMotionTime = now;
|
|
351
|
+
|
|
352
|
+
// Auto-save every 10 transitions
|
|
353
|
+
if (data.motionHistory.length % 10 === 0) save();
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Record user reaction
|
|
358
|
+
* When user shows reactions like click/drag during a specific action
|
|
359
|
+
*
|
|
360
|
+
* @param {string} action - Action the pet was performing
|
|
361
|
+
* @param {string} reaction - 'click' | 'drag' | 'cursor_near' | 'triple_click' | 'double_click'
|
|
362
|
+
*/
|
|
363
|
+
function recordReaction(action, reaction) {
|
|
364
|
+
const now = Date.now();
|
|
365
|
+
|
|
366
|
+
// Add to reaction log
|
|
367
|
+
data.reactionLog.push({ action, reaction, timestamp: now });
|
|
368
|
+
if (data.reactionLog.length > MAX_REACTION_LOG) {
|
|
369
|
+
data.reactionLog = data.reactionLog.slice(-MAX_REACTION_LOG);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Click/double-click classified as positive reactions
|
|
373
|
+
if (reaction === 'click' || reaction === 'double_click' || reaction === 'cursor_near') {
|
|
374
|
+
if (!data.favoriteActions[action]) data.favoriteActions[action] = 0;
|
|
375
|
+
data.favoriteActions[action]++;
|
|
376
|
+
}
|
|
377
|
+
// Drag (grab and move) is a slightly negative reaction
|
|
378
|
+
if (reaction === 'drag') {
|
|
379
|
+
if (!data.dislikedActions[action]) data.dislikedActions[action] = 0;
|
|
380
|
+
data.dislikedActions[action]++;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
save();
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Return top N user-preferred actions
|
|
388
|
+
* Referenced by AI when deciding actions
|
|
389
|
+
*/
|
|
390
|
+
function getFavoriteActions(topN = 5) {
|
|
391
|
+
const entries = Object.entries(data.favoriteActions || {});
|
|
392
|
+
entries.sort((a, b) => b[1] - a[1]);
|
|
393
|
+
return entries.slice(0, topN).map(([action, count]) => ({ action, count }));
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Return recent motion history
|
|
398
|
+
*/
|
|
399
|
+
function getMotionHistory(limit = 20) {
|
|
400
|
+
return (data.motionHistory || []).slice(-limit);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Return accumulated time per state
|
|
405
|
+
*/
|
|
406
|
+
function getMotionStats() {
|
|
407
|
+
return { ...(data.motionStats || {}) };
|
|
408
|
+
}
|
|
409
|
+
|
|
307
410
|
async function save() {
|
|
308
411
|
try {
|
|
309
412
|
await window.clawmate.saveMemory(data);
|
|
@@ -318,5 +421,9 @@ const Memory = (() => {
|
|
|
318
421
|
return data.evolutionStage;
|
|
319
422
|
}
|
|
320
423
|
|
|
321
|
-
return {
|
|
424
|
+
return {
|
|
425
|
+
init, recordClick, getData, getEvolutionStage, save,
|
|
426
|
+
recordMotion, recordReaction, getFavoriteActions,
|
|
427
|
+
getMotionHistory, getMotionStats,
|
|
428
|
+
};
|
|
322
429
|
})();
|