clawmate 1.4.0 → 1.4.2

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.
Files changed (42) hide show
  1. package/index.js +441 -442
  2. package/main/ai-bridge.js +59 -59
  3. package/main/ai-connector.js +60 -60
  4. package/main/autostart.js +6 -6
  5. package/main/desktop-path.js +4 -4
  6. package/main/file-command-parser.js +46 -46
  7. package/main/file-ops.js +27 -27
  8. package/main/index.js +17 -17
  9. package/main/ipc-handlers.js +24 -24
  10. package/main/manifest.js +2 -2
  11. package/main/platform.js +16 -16
  12. package/main/smart-file-ops.js +64 -64
  13. package/main/store.js +1 -1
  14. package/main/telegram.js +137 -137
  15. package/main/tray.js +61 -61
  16. package/main/updater.js +13 -13
  17. package/openclaw.plugin.json +1 -1
  18. package/package.json +2 -2
  19. package/preload/preload.js +18 -18
  20. package/renderer/css/effects.css +6 -6
  21. package/renderer/css/pet.css +8 -8
  22. package/renderer/css/speech.css +5 -5
  23. package/renderer/first-run.html +14 -14
  24. package/renderer/index.html +4 -4
  25. package/renderer/js/ai-controller.js +91 -91
  26. package/renderer/js/app.js +24 -24
  27. package/renderer/js/browser-watcher.js +32 -32
  28. package/renderer/js/character.js +33 -33
  29. package/renderer/js/interactions.js +21 -21
  30. package/renderer/js/memory.js +60 -60
  31. package/renderer/js/metrics.js +141 -141
  32. package/renderer/js/mode-manager.js +13 -13
  33. package/renderer/js/pet-engine.js +236 -236
  34. package/renderer/js/speech.js +19 -19
  35. package/renderer/js/state-machine.js +23 -23
  36. package/renderer/js/time-aware.js +15 -15
  37. package/renderer/launcher.html +8 -8
  38. package/shared/constants.js +11 -11
  39. package/shared/messages.js +130 -130
  40. package/shared/personalities.js +44 -44
  41. package/skills/launch-pet/index.js +57 -47
  42. package/skills/launch-pet/skill.json +12 -23
@@ -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,16 +13,16 @@ const Memory = (() => {
13
13
  lastVisitDate: null,
14
14
  milestones: [],
15
15
  evolutionStage: 0,
16
- interactionStreak: 0, // 연속 방문 일수
16
+ interactionStreak: 0, // Consecutive visit days
17
17
 
18
- // --- 모션 히스토리 ---
19
- motionHistory: [], // 최근 100 상태 전환 기록 [{state, timestamp, duration}]
20
- motionStats: {}, // 상태별 누적 시간 {idle: 12345, walking: 6789, ...}
18
+ // --- Motion history ---
19
+ motionHistory: [], // Recent 100 state transition records [{state, timestamp, duration}]
20
+ motionStats: {}, // Accumulated time per state {idle: 12345, walking: 6789, ...}
21
21
 
22
- // --- 유저 반응 저장 ---
23
- reactionLog: [], // 최근 50 유저 반응 [{action, reaction, timestamp}]
24
- favoriteActions: {}, // 행동별 긍정 반응 횟수 {excited: 5, walking: 2, ...}
25
- dislikedActions: {}, // 행동별 부정 반응 횟수 (무시/이탈)
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)
26
26
  };
27
27
 
28
28
  let lastMotionState = null;
@@ -40,22 +40,22 @@ const Memory = (() => {
40
40
 
41
41
  evolutionStages = window._evolutionStages;
42
42
 
43
- // 실행
43
+ // First run
44
44
  if (!data.firstRunDate) {
45
45
  data.firstRunDate = new Date().toISOString();
46
46
  await save();
47
47
  }
48
48
 
49
- // 일수 계산
49
+ // Calculate days
50
50
  updateDayCount();
51
51
 
52
- // 마일스톤 체크
52
+ // Check milestones
53
53
  checkMilestones();
54
54
 
55
- // 진화 체크
55
+ // Check evolution
56
56
  checkEvolution();
57
57
 
58
- // 진화 시각 효과 적용
58
+ // Apply evolution visual effects
59
59
  applyEvolutionVisuals();
60
60
  }
61
61
 
@@ -64,7 +64,7 @@ const Memory = (() => {
64
64
  const now = new Date();
65
65
  data.totalDays = Math.floor((now - firstRun) / (1000 * 60 * 60 * 24));
66
66
 
67
- // 연속 방문 체크
67
+ // Check consecutive visits
68
68
  const lastVisit = data.lastVisitDate ? new Date(data.lastVisitDate) : null;
69
69
  const today = now.toDateString();
70
70
  if (lastVisit && lastVisit.toDateString() !== today) {
@@ -103,7 +103,7 @@ const Memory = (() => {
103
103
  data.milestones.push(check.key);
104
104
  const msg = Speech.getMilestoneMessage(check.key);
105
105
  if (msg) {
106
- // 약간의 딜레이 마일스톤 메시지 표시
106
+ // Display milestone message after a slight delay
107
107
  setTimeout(() => {
108
108
  Speech.show(msg);
109
109
  Interactions.spawnStarEffect();
@@ -114,9 +114,9 @@ const Memory = (() => {
114
114
  }
115
115
 
116
116
  /**
117
- * 진화 단계 체크
118
- * 항상 올라가기만 (퇴화 없음)
119
- * 조건: 클릭 횟수 + 함께한 일수 모두 충족
117
+ * Check evolution stage
118
+ * Only goes up (no devolution)
119
+ * Condition: both click count and days together must be met
120
120
  */
121
121
  function checkEvolution() {
122
122
  if (!evolutionStages) return;
@@ -141,22 +141,22 @@ const Memory = (() => {
141
141
  }
142
142
 
143
143
  /**
144
- * 진화 발생 시 이벤트
145
- * - 밝은 플래시 효과 (부드러운 )
146
- * - 반짝이 파티클
147
- * - 축하 메시지
144
+ * Evolution event handler
145
+ * - Bright flash effect (soft light)
146
+ * - Sparkle particles
147
+ * - Congratulatory message
148
148
  */
149
149
  function onEvolution(prevStage, newStage) {
150
150
  const msgs = window._messages;
151
151
  const stageInfo = evolutionStages[newStage];
152
152
 
153
- // 밝은 플래시 (무섭지 않은 부드러운 효과)
153
+ // Bright flash (soft, non-scary effect)
154
154
  const flash = document.createElement('div');
155
155
  flash.className = 'evolve-flash';
156
156
  document.body.appendChild(flash);
157
157
  setTimeout(() => flash.remove(), 600);
158
158
 
159
- // 진화 반짝임 파티클 (밝은 색상만)
159
+ // Evolution sparkle particles (bright colors only)
160
160
  const pos = PetEngine.getPosition();
161
161
  const sparkleColors = ['#FFD700', '#FF69B4', '#87CEEB', '#98FB98', '#DDA0DD'];
162
162
  for (let i = 0; i < 16; i++) {
@@ -169,7 +169,7 @@ const Memory = (() => {
169
169
  setTimeout(() => sparkle.remove(), 800);
170
170
  }
171
171
 
172
- // 진화 이펙트 (따뜻한 )
172
+ // Evolution ring effect (warm colors)
173
173
  const ring = document.createElement('div');
174
174
  ring.className = 'evolve-ring';
175
175
  ring.style.width = '64px';
@@ -180,7 +180,7 @@ const Memory = (() => {
180
180
  document.getElementById('world').appendChild(ring);
181
181
  setTimeout(() => ring.remove(), 1000);
182
182
 
183
- // 축하 메시지
183
+ // Congratulatory message
184
184
  if (msgs && msgs.evolution) {
185
185
  const evolveMsg = msgs.evolution[`stage_${newStage}`];
186
186
  if (evolveMsg) {
@@ -188,13 +188,13 @@ const Memory = (() => {
188
188
  }
189
189
  }
190
190
 
191
- // 시각 효과 업데이트
191
+ // Update visual effects
192
192
  applyEvolutionVisuals();
193
193
  }
194
194
 
195
195
  /**
196
- * 진화 단계에 따른 시각적 변화 적용
197
- * 항상 긍정적: 밝아지고, 반짝이고, 귀여운 악세사리 추가
196
+ * Apply visual changes based on evolution stage
197
+ * Always positive: gets brighter, sparkly, and cute accessories added
198
198
  */
199
199
  function applyEvolutionVisuals() {
200
200
  if (!evolutionStages) return;
@@ -204,17 +204,17 @@ const Memory = (() => {
204
204
  const pet = document.getElementById('pet-container');
205
205
  if (!pet) return;
206
206
 
207
- // 크기 스케일
207
+ // Size scale
208
208
  pet.style.transform = pet.style.transform || '';
209
209
 
210
- // 밝기/채도 진화할수록 밝고 화사해짐
210
+ // Brightness/saturation -- gets brighter and more vibrant with evolution
211
211
  const { brightness, saturation } = stage.colorMod;
212
212
  const canvas = pet.querySelector('canvas');
213
213
  if (canvas) {
214
214
  canvas.style.filter = `brightness(${brightness}) saturate(${saturation})`;
215
215
  }
216
216
 
217
- // 악세사리 제거 재적용
217
+ // Remove accessories then reapply
218
218
  pet.querySelectorAll('.accessory').forEach(a => a.remove());
219
219
 
220
220
  for (const acc of stage.accessories) {
@@ -223,8 +223,8 @@ const Memory = (() => {
223
223
  }
224
224
 
225
225
  /**
226
- * 귀여운 악세사리 추가
227
- * 모든 악세사리는 밝고 귀여운 요소만
226
+ * Add cute accessories
227
+ * All accessories are bright and cute elements only
228
228
  */
229
229
  function addAccessory(container, type) {
230
230
  const acc = document.createElement('div');
@@ -235,7 +235,7 @@ const Memory = (() => {
235
235
 
236
236
  switch (type) {
237
237
  case 'blush':
238
- // 볼에 핑크 동그라미
238
+ // Pink circles on both cheeks
239
239
  acc.style.width = '8px';
240
240
  acc.style.height = '6px';
241
241
  acc.style.borderRadius = '50%';
@@ -243,14 +243,14 @@ const Memory = (() => {
243
243
  acc.style.left = '12px';
244
244
  acc.style.top = '38px';
245
245
  container.appendChild(acc);
246
- // 오른쪽
246
+ // Right cheek
247
247
  const blush2 = acc.cloneNode();
248
248
  blush2.style.left = '44px';
249
249
  container.appendChild(blush2);
250
250
  return;
251
251
 
252
252
  case 'sparkle_eyes':
253
- // 눈에 반짝임 (흰색 작은 )
253
+ // Eye sparkles (small white dots)
254
254
  acc.style.width = '3px';
255
255
  acc.style.height = '3px';
256
256
  acc.style.borderRadius = '50%';
@@ -300,14 +300,14 @@ const Memory = (() => {
300
300
  break;
301
301
 
302
302
  case 'wings':
303
- // 작은 천사 날개 (왼쪽)
303
+ // Small angel wings (left)
304
304
  acc.textContent = '\u{1FABD}';
305
305
  acc.style.fontSize = '10px';
306
306
  acc.style.left = '-6px';
307
307
  acc.style.top = '20px';
308
308
  acc.style.opacity = '0.7';
309
309
  container.appendChild(acc);
310
- // 오른쪽 날개
310
+ // Right wing
311
311
  const wing2 = acc.cloneNode(true);
312
312
  wing2.style.left = '58px';
313
313
  wing2.style.transform = 'scaleX(-1)';
@@ -318,30 +318,30 @@ const Memory = (() => {
318
318
  container.appendChild(acc);
319
319
  }
320
320
 
321
- // --- 모션 히스토리 기록 ---
321
+ // --- Motion history recording ---
322
322
 
323
323
  /**
324
- * 상태 전환 기록
325
- * StateMachine에서 상태 변경 호출
324
+ * Record state transition
325
+ * Called when state changes in StateMachine
326
326
  */
327
327
  function recordMotion(newState) {
328
328
  const now = Date.now();
329
329
 
330
- // 이전 상태의 지속 시간 계산 통계 누적
330
+ // Calculate previous state duration -> accumulate statistics
331
331
  if (lastMotionState && lastMotionTime > 0) {
332
332
  const duration = now - lastMotionTime;
333
333
  if (!data.motionStats[lastMotionState]) data.motionStats[lastMotionState] = 0;
334
334
  data.motionStats[lastMotionState] += duration;
335
335
  }
336
336
 
337
- // 히스토리에 추가
337
+ // Add to history
338
338
  data.motionHistory.push({
339
339
  state: newState,
340
340
  timestamp: now,
341
341
  from: lastMotionState || 'init',
342
342
  });
343
343
 
344
- // 최대 크기 초과 오래된 제거
344
+ // Remove old entries when exceeding max size
345
345
  if (data.motionHistory.length > MAX_MOTION_HISTORY) {
346
346
  data.motionHistory = data.motionHistory.slice(-MAX_MOTION_HISTORY);
347
347
  }
@@ -349,32 +349,32 @@ const Memory = (() => {
349
349
  lastMotionState = newState;
350
350
  lastMotionTime = now;
351
351
 
352
- // 10회 전환마다 자동 저장
352
+ // Auto-save every 10 transitions
353
353
  if (data.motionHistory.length % 10 === 0) save();
354
354
  }
355
355
 
356
356
  /**
357
- * 유저 반응 기록
358
- * 특정 행동 사용자가 클릭/드래그 등의 반응을 보인 경우
357
+ * Record user reaction
358
+ * When user shows reactions like click/drag during a specific action
359
359
  *
360
- * @param {string} action - 펫이 하고 있던 행동
360
+ * @param {string} action - Action the pet was performing
361
361
  * @param {string} reaction - 'click' | 'drag' | 'cursor_near' | 'triple_click' | 'double_click'
362
362
  */
363
363
  function recordReaction(action, reaction) {
364
364
  const now = Date.now();
365
365
 
366
- // 반응 로그 추가
366
+ // Add to reaction log
367
367
  data.reactionLog.push({ action, reaction, timestamp: now });
368
368
  if (data.reactionLog.length > MAX_REACTION_LOG) {
369
369
  data.reactionLog = data.reactionLog.slice(-MAX_REACTION_LOG);
370
370
  }
371
371
 
372
- // 클릭/더블클릭은 긍정 반응으로 분류
372
+ // Click/double-click classified as positive reactions
373
373
  if (reaction === 'click' || reaction === 'double_click' || reaction === 'cursor_near') {
374
374
  if (!data.favoriteActions[action]) data.favoriteActions[action] = 0;
375
375
  data.favoriteActions[action]++;
376
376
  }
377
- // 드래그(잡아서 옮김) 약간 부정 반응
377
+ // Drag (grab and move) is a slightly negative reaction
378
378
  if (reaction === 'drag') {
379
379
  if (!data.dislikedActions[action]) data.dislikedActions[action] = 0;
380
380
  data.dislikedActions[action]++;
@@ -384,8 +384,8 @@ const Memory = (() => {
384
384
  }
385
385
 
386
386
  /**
387
- * 사용자 선호 행동 Top N 반환
388
- * AI 행동 결정 시 참고
387
+ * Return top N user-preferred actions
388
+ * Referenced by AI when deciding actions
389
389
  */
390
390
  function getFavoriteActions(topN = 5) {
391
391
  const entries = Object.entries(data.favoriteActions || {});
@@ -394,14 +394,14 @@ const Memory = (() => {
394
394
  }
395
395
 
396
396
  /**
397
- * 최근 모션 히스토리 반환
397
+ * Return recent motion history
398
398
  */
399
399
  function getMotionHistory(limit = 20) {
400
400
  return (data.motionHistory || []).slice(-limit);
401
401
  }
402
402
 
403
403
  /**
404
- * 상태별 누적 시간 반환
404
+ * Return accumulated time per state
405
405
  */
406
406
  function getMotionStats() {
407
407
  return { ...(data.motionStats || {}) };