ideaco 1.1.5

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 (159) hide show
  1. package/.dockerignore +33 -0
  2. package/.nvmrc +1 -0
  3. package/ARCHITECTURE.md +394 -0
  4. package/Dockerfile +50 -0
  5. package/LICENSE +29 -0
  6. package/README.md +206 -0
  7. package/bin/i18n.js +46 -0
  8. package/bin/ideaco.js +494 -0
  9. package/deploy.sh +15 -0
  10. package/docker-compose.yml +30 -0
  11. package/electron/main.cjs +986 -0
  12. package/electron/preload.cjs +14 -0
  13. package/electron/web-backends.cjs +854 -0
  14. package/jsconfig.json +8 -0
  15. package/next.config.mjs +34 -0
  16. package/package.json +134 -0
  17. package/postcss.config.mjs +6 -0
  18. package/public/demo/dashboard.png +0 -0
  19. package/public/demo/employee.png +0 -0
  20. package/public/demo/messages.png +0 -0
  21. package/public/demo/office.png +0 -0
  22. package/public/demo/requirement.png +0 -0
  23. package/public/logo.jpeg +0 -0
  24. package/public/logo.png +0 -0
  25. package/scripts/prepare-electron.js +67 -0
  26. package/scripts/release.js +76 -0
  27. package/src/app/api/agents/[agentId]/chat/route.js +70 -0
  28. package/src/app/api/agents/[agentId]/conversations/route.js +35 -0
  29. package/src/app/api/agents/[agentId]/route.js +106 -0
  30. package/src/app/api/avatar/route.js +104 -0
  31. package/src/app/api/browse-dir/route.js +44 -0
  32. package/src/app/api/chat/route.js +265 -0
  33. package/src/app/api/company/factory-reset/route.js +43 -0
  34. package/src/app/api/company/route.js +82 -0
  35. package/src/app/api/departments/[deptId]/agents/[agentId]/dismiss/route.js +19 -0
  36. package/src/app/api/departments/route.js +92 -0
  37. package/src/app/api/group-chat-loop/events/route.js +70 -0
  38. package/src/app/api/group-chat-loop/route.js +94 -0
  39. package/src/app/api/mailbox/route.js +100 -0
  40. package/src/app/api/messages/route.js +14 -0
  41. package/src/app/api/providers/[id]/configure/route.js +21 -0
  42. package/src/app/api/providers/[id]/refresh-cookie/route.js +38 -0
  43. package/src/app/api/providers/[id]/test-cookie/route.js +28 -0
  44. package/src/app/api/providers/route.js +11 -0
  45. package/src/app/api/requirements/route.js +242 -0
  46. package/src/app/api/secretary/route.js +65 -0
  47. package/src/app/api/system/cli-backends/route.js +91 -0
  48. package/src/app/api/system/cron/route.js +110 -0
  49. package/src/app/api/system/knowledge/route.js +104 -0
  50. package/src/app/api/system/plugins/route.js +40 -0
  51. package/src/app/api/system/skills/route.js +46 -0
  52. package/src/app/api/system/status/route.js +46 -0
  53. package/src/app/api/talent-market/[profileId]/recall/route.js +22 -0
  54. package/src/app/api/talent-market/[profileId]/route.js +17 -0
  55. package/src/app/api/talent-market/route.js +26 -0
  56. package/src/app/api/teams/route.js +773 -0
  57. package/src/app/api/ws-files/[departmentId]/file/route.js +27 -0
  58. package/src/app/api/ws-files/[departmentId]/files/route.js +22 -0
  59. package/src/app/globals.css +130 -0
  60. package/src/app/layout.jsx +40 -0
  61. package/src/app/page.jsx +97 -0
  62. package/src/components/AgentChatModal.jsx +164 -0
  63. package/src/components/AgentDetailModal.jsx +425 -0
  64. package/src/components/AgentSpyModal.jsx +481 -0
  65. package/src/components/AvatarGrid.jsx +29 -0
  66. package/src/components/BossProfileModal.jsx +162 -0
  67. package/src/components/CachedAvatar.jsx +77 -0
  68. package/src/components/ChatPanel.jsx +219 -0
  69. package/src/components/ChatShared.jsx +255 -0
  70. package/src/components/DepartmentDetail.jsx +842 -0
  71. package/src/components/DepartmentView.jsx +367 -0
  72. package/src/components/FileReference.jsx +260 -0
  73. package/src/components/FilesView.jsx +465 -0
  74. package/src/components/GroupChatView.jsx +799 -0
  75. package/src/components/Mailbox.jsx +926 -0
  76. package/src/components/MessagesView.jsx +112 -0
  77. package/src/components/OnboardingGuide.jsx +209 -0
  78. package/src/components/OrgTree.jsx +151 -0
  79. package/src/components/Overview.jsx +391 -0
  80. package/src/components/PixelOffice.jsx +2281 -0
  81. package/src/components/ProviderGrid.jsx +551 -0
  82. package/src/components/ProvidersBoard.jsx +16 -0
  83. package/src/components/RequirementDetail.jsx +1279 -0
  84. package/src/components/RequirementsBoard.jsx +187 -0
  85. package/src/components/SecretarySettings.jsx +295 -0
  86. package/src/components/SetupWizard.jsx +388 -0
  87. package/src/components/Sidebar.jsx +169 -0
  88. package/src/components/SystemMonitor.jsx +808 -0
  89. package/src/components/TalentMarket.jsx +183 -0
  90. package/src/components/TeamDetail.jsx +697 -0
  91. package/src/core/agent/base-agent.js +104 -0
  92. package/src/core/agent/chat-store.js +602 -0
  93. package/src/core/agent/cli-agent/backends/claude-code/README.md +52 -0
  94. package/src/core/agent/cli-agent/backends/claude-code/config.js +27 -0
  95. package/src/core/agent/cli-agent/backends/codebuddy/README.md +236 -0
  96. package/src/core/agent/cli-agent/backends/codebuddy/config.js +27 -0
  97. package/src/core/agent/cli-agent/backends/codex/README.md +51 -0
  98. package/src/core/agent/cli-agent/backends/codex/config.js +27 -0
  99. package/src/core/agent/cli-agent/backends/index.js +27 -0
  100. package/src/core/agent/cli-agent/backends/registry.js +580 -0
  101. package/src/core/agent/cli-agent/index.js +154 -0
  102. package/src/core/agent/index.js +60 -0
  103. package/src/core/agent/llm-agent/client.js +320 -0
  104. package/src/core/agent/llm-agent/index.js +97 -0
  105. package/src/core/agent/message-bus.js +211 -0
  106. package/src/core/agent/session.js +608 -0
  107. package/src/core/agent/tools.js +596 -0
  108. package/src/core/agent/web-agent/backends/base-backend.js +180 -0
  109. package/src/core/agent/web-agent/backends/chatgpt/client.js +146 -0
  110. package/src/core/agent/web-agent/backends/chatgpt/config.js +148 -0
  111. package/src/core/agent/web-agent/backends/chatgpt/dom-scripts.js +303 -0
  112. package/src/core/agent/web-agent/backends/index.js +91 -0
  113. package/src/core/agent/web-agent/index.js +278 -0
  114. package/src/core/agent/web-agent/web-client.js +407 -0
  115. package/src/core/employee/base-employee.js +1088 -0
  116. package/src/core/employee/index.js +35 -0
  117. package/src/core/employee/knowledge.js +327 -0
  118. package/src/core/employee/lifecycle.js +990 -0
  119. package/src/core/employee/memory/index.js +642 -0
  120. package/src/core/employee/memory/store.js +143 -0
  121. package/src/core/employee/performance.js +224 -0
  122. package/src/core/employee/secretary.js +625 -0
  123. package/src/core/employee/skills.js +398 -0
  124. package/src/core/index.js +38 -0
  125. package/src/core/organization/company.js +2600 -0
  126. package/src/core/organization/department.js +737 -0
  127. package/src/core/organization/group-chat-loop.js +264 -0
  128. package/src/core/organization/index.js +8 -0
  129. package/src/core/organization/persistence.js +111 -0
  130. package/src/core/organization/team.js +267 -0
  131. package/src/core/organization/workforce/hr.js +377 -0
  132. package/src/core/organization/workforce/providers.js +468 -0
  133. package/src/core/organization/workforce/role-archetypes.js +805 -0
  134. package/src/core/organization/workforce/talent-market.js +205 -0
  135. package/src/core/prompts.js +532 -0
  136. package/src/core/requirement.js +1789 -0
  137. package/src/core/system/audit.js +483 -0
  138. package/src/core/system/cron.js +449 -0
  139. package/src/core/system/index.js +7 -0
  140. package/src/core/system/plugin.js +2183 -0
  141. package/src/core/utils/json-parse.js +188 -0
  142. package/src/core/workspace.js +239 -0
  143. package/src/lib/api-i18n.js +211 -0
  144. package/src/lib/avatar.js +268 -0
  145. package/src/lib/client-store.js +1025 -0
  146. package/src/lib/config-validator.js +483 -0
  147. package/src/lib/format-time.js +22 -0
  148. package/src/lib/hooks.js +414 -0
  149. package/src/lib/i18n.js +134 -0
  150. package/src/lib/paths.js +23 -0
  151. package/src/lib/store.js +72 -0
  152. package/src/locales/de.js +393 -0
  153. package/src/locales/en.js +1054 -0
  154. package/src/locales/es.js +393 -0
  155. package/src/locales/fr.js +393 -0
  156. package/src/locales/ja.js +501 -0
  157. package/src/locales/ko.js +513 -0
  158. package/src/locales/zh.js +828 -0
  159. package/tailwind.config.mjs +11 -0
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Independent Memory File Management Module
3
+ *
4
+ * Each Employee's memory is stored in a separate JSON file (data/memories/{employeeId}.json),
5
+ * preventing all memories from being stuffed into company-state.json causing file bloat.
6
+ *
7
+ * Workflow:
8
+ * 1. When saving company state, memory only serializes a summary (counts); full memory goes to separate files
9
+ * 2. When restoring company state, load each Employee's full memory from separate files
10
+ * 3. When memory changes, save only that Employee's memory file (no need to rewrite entire company state)
11
+ */
12
+ import fs from 'fs';
13
+ import path from 'path';
14
+ import { MEMORY_DIR } from '../../../lib/paths.js';
15
+
16
+ // Ensure directory exists
17
+ if (!fs.existsSync(MEMORY_DIR)) {
18
+ fs.mkdirSync(MEMORY_DIR, { recursive: true });
19
+ }
20
+
21
+ /**
22
+ * Save a single Employee's memory to a separate file
23
+ * @param {string} agentId - Employee ID
24
+ * @param {object} memoryData - Serialized memory data { shortTerm, longTerm }
25
+ * @param {object} meta - Metadata { name, role, department }
26
+ */
27
+ export function saveAgentMemory(agentId, memoryData, meta = {}) {
28
+ if (!agentId || !memoryData) return;
29
+ try {
30
+ const filePath = path.join(MEMORY_DIR, `${agentId}.json`);
31
+ const data = {
32
+ agentId,
33
+ name: meta.name || 'unknown',
34
+ role: meta.role || 'unknown',
35
+ department: meta.department || 'unknown',
36
+ shortTerm: memoryData.shortTerm || [],
37
+ longTerm: memoryData.longTerm || [],
38
+ historySummary: memoryData.historySummary || {},
39
+ relationships: memoryData.relationships || {},
40
+ savedAt: new Date().toISOString(),
41
+ };
42
+ fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');
43
+ } catch (e) {
44
+ console.error(`āŒ Failed to save memory [${agentId}]:`, e.message);
45
+ }
46
+ }
47
+
48
+ /**
49
+ * Load a single Employee's memory
50
+ * @param {string} agentId - Employee ID
51
+ * @returns {object|null} { shortTerm, longTerm } or null
52
+ */
53
+ export function loadAgentMemory(agentId) {
54
+ if (!agentId) return null;
55
+ try {
56
+ const filePath = path.join(MEMORY_DIR, `${agentId}.json`);
57
+ if (!fs.existsSync(filePath)) return null;
58
+ const json = fs.readFileSync(filePath, 'utf-8');
59
+ const data = JSON.parse(json);
60
+ return {
61
+ shortTerm: data.shortTerm || [],
62
+ longTerm: data.longTerm || [],
63
+ historySummary: data.historySummary || {},
64
+ relationships: data.relationships || {},
65
+ };
66
+ } catch (e) {
67
+ console.error(`āŒ Failed to load memory [${agentId}]:`, e.message);
68
+ return null;
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Batch save multiple Employees' memories
74
+ * @param {Array<{agentId, memoryData, meta}>} agents - Employee memory array
75
+ */
76
+ export function saveAllAgentMemories(agents) {
77
+ let saved = 0;
78
+ for (const { agentId, memoryData, meta } of agents) {
79
+ saveAgentMemory(agentId, memoryData, meta);
80
+ saved++;
81
+ }
82
+ if (saved > 0) {
83
+ console.log(`🧠 Saved ${saved} Employee memory files`);
84
+ }
85
+ }
86
+
87
+ /**
88
+ * Delete an Employee's memory file
89
+ * @param {string} agentId - Employee ID
90
+ */
91
+ export function deleteAgentMemory(agentId) {
92
+ try {
93
+ const filePath = path.join(MEMORY_DIR, `${agentId}.json`);
94
+ if (fs.existsSync(filePath)) {
95
+ fs.unlinkSync(filePath);
96
+ console.log(`šŸ—‘ļø Deleted Employee [${agentId}] memory file`);
97
+ }
98
+ } catch (e) {
99
+ console.error(`āŒ Failed to delete memory file [${agentId}]:`, e.message);
100
+ }
101
+ }
102
+
103
+ /**
104
+ * List all saved memory files
105
+ * @returns {Array<{agentId, name, role, shortTermCount, longTermCount, savedAt}>}
106
+ */
107
+ export function listMemoryFiles() {
108
+ try {
109
+ const files = fs.readdirSync(MEMORY_DIR).filter(f => f.endsWith('.json'));
110
+ return files.map(f => {
111
+ try {
112
+ const json = fs.readFileSync(path.join(MEMORY_DIR, f), 'utf-8');
113
+ const data = JSON.parse(json);
114
+ return {
115
+ agentId: data.agentId,
116
+ name: data.name,
117
+ role: data.role,
118
+ department: data.department,
119
+ shortTermCount: data.shortTerm?.length || 0,
120
+ longTermCount: data.longTerm?.length || 0,
121
+ savedAt: data.savedAt,
122
+ };
123
+ } catch {
124
+ return null;
125
+ }
126
+ }).filter(Boolean);
127
+ } catch {
128
+ return [];
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Clear all memory files
134
+ */
135
+ export function clearAllMemories() {
136
+ try {
137
+ const files = fs.readdirSync(MEMORY_DIR).filter(f => f.endsWith('.json'));
138
+ files.forEach(f => fs.unlinkSync(path.join(MEMORY_DIR, f)));
139
+ console.log(`šŸ—‘ļø Cleared ${files.length} memory files`);
140
+ } catch (e) {
141
+ console.error('āŒ Failed to clear memory files:', e.message);
142
+ }
143
+ }
@@ -0,0 +1,224 @@
1
+ import { v4 as uuidv4 } from 'uuid';
2
+
3
+ /**
4
+ * Performance Evaluation System
5
+ * Supervisors evaluate employees' work results; employees provide self-feedback based on scores
6
+ */
7
+
8
+ /** Performance scoring dimensions */
9
+ export const PerformanceDimensions = {
10
+ QUALITY: 'quality', // Work quality
11
+ EFFICIENCY: 'efficiency', // Work efficiency
12
+ COLLABORATION: 'collaboration', // Collaboration ability
13
+ INNOVATION: 'innovation', // Innovation ability
14
+ COMMUNICATION: 'communication', // Communication skills
15
+ };
16
+
17
+ /** Performance levels */
18
+ export const PerformanceLevel = {
19
+ EXCELLENT: { label: 'Excellent', minScore: 90, emoji: '🌟' },
20
+ GOOD: { label: 'Good', minScore: 75, emoji: '⭐' },
21
+ AVERAGE: { label: 'Average', minScore: 60, emoji: 'šŸ‘' },
22
+ BELOW_AVERAGE: { label: 'Needs Improvement', minScore: 40, emoji: 'āš ļø' },
23
+ POOR: { label: 'Poor', minScore: 0, emoji: 'āŒ' },
24
+ };
25
+
26
+ /**
27
+ * Get performance level
28
+ */
29
+ export function getPerformanceLevel(score) {
30
+ if (score >= 90) return PerformanceLevel.EXCELLENT;
31
+ if (score >= 75) return PerformanceLevel.GOOD;
32
+ if (score >= 60) return PerformanceLevel.AVERAGE;
33
+ if (score >= 40) return PerformanceLevel.BELOW_AVERAGE;
34
+ return PerformanceLevel.POOR;
35
+ }
36
+
37
+ /**
38
+ * Single performance review record
39
+ */
40
+ export class PerformanceReview {
41
+ constructor({ agentId, agentName, reviewerId, reviewerName, taskTitle, scores, comment }) {
42
+ this.id = uuidv4();
43
+ this.agentId = agentId; // Reviewee
44
+ this.agentName = agentName;
45
+ this.reviewerId = reviewerId; // Reviewer (supervisor)
46
+ this.reviewerName = reviewerName;
47
+ this.taskTitle = taskTitle; // Associated task
48
+ this.scores = scores; // Dimension scores { quality: 85, efficiency: 90, ... }
49
+ this.overallScore = this._calcOverall(scores); // Overall score
50
+ this.level = getPerformanceLevel(this.overallScore); // Performance level
51
+ this.comment = comment || ''; // Supervisor's comment
52
+ this.selfReflection = null; // Employee's self-feedback (filled later)
53
+ this.createdAt = new Date();
54
+ }
55
+
56
+ /** Calculate overall score (weighted average) */
57
+ _calcOverall(scores) {
58
+ const weights = {
59
+ [PerformanceDimensions.QUALITY]: 0.3,
60
+ [PerformanceDimensions.EFFICIENCY]: 0.25,
61
+ [PerformanceDimensions.COLLABORATION]: 0.15,
62
+ [PerformanceDimensions.INNOVATION]: 0.15,
63
+ [PerformanceDimensions.COMMUNICATION]: 0.15,
64
+ };
65
+
66
+ let total = 0;
67
+ let weightSum = 0;
68
+ for (const [dim, score] of Object.entries(scores)) {
69
+ const weight = weights[dim] || 0.2;
70
+ total += score * weight;
71
+ weightSum += weight;
72
+ }
73
+
74
+ return Math.round(total / (weightSum || 1));
75
+ }
76
+
77
+ /** Employee fills in self-feedback */
78
+ addSelfReflection(reflection) {
79
+ this.selfReflection = reflection;
80
+ }
81
+
82
+ /** Get summary */
83
+ getSummary() {
84
+ return {
85
+ id: this.id,
86
+ agent: this.agentName,
87
+ reviewer: this.reviewerName,
88
+ task: this.taskTitle,
89
+ overallScore: this.overallScore,
90
+ level: `${this.level.emoji} ${this.level.label}`,
91
+ scores: this.scores,
92
+ comment: this.comment,
93
+ selfReflection: this.selfReflection,
94
+ };
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Performance Management System - Manages all Agent performance records
100
+ */
101
+ export class PerformanceSystem {
102
+ constructor() {
103
+ this.reviews = new Map(); // agentId => PerformanceReview[]
104
+ }
105
+
106
+ /**
107
+ * Supervisor evaluates an employee
108
+ * @param {object} params
109
+ * @param {Agent} params.agent - Employee being evaluated
110
+ * @param {Agent} params.reviewer - Evaluator (supervisor)
111
+ * @param {string} params.taskTitle - Task name
112
+ * @param {object} params.scores - Dimension scores
113
+ * @param {string} [params.comment] - Comment
114
+ * @returns {PerformanceReview}
115
+ */
116
+ evaluate({ agent, reviewer, taskTitle, scores, comment }) {
117
+ const review = new PerformanceReview({
118
+ agentId: agent.id,
119
+ agentName: agent.name,
120
+ reviewerId: reviewer.id,
121
+ reviewerName: reviewer.name,
122
+ taskTitle,
123
+ scores,
124
+ comment,
125
+ });
126
+
127
+ if (!this.reviews.has(agent.id)) {
128
+ this.reviews.set(agent.id, []);
129
+ }
130
+ this.reviews.get(agent.id).push(review);
131
+
132
+ console.log(` šŸ“Š Performance review: [${reviewer.name}] evaluated [${agent.name}]`);
133
+ console.log(` Task: "${taskTitle}"`);
134
+ console.log(` Overall score: ${review.overallScore} ${review.level.emoji} ${review.level.label}`);
135
+ Object.entries(scores).forEach(([dim, score]) => {
136
+ console.log(` - ${dim}: ${score}`);
137
+ });
138
+ if (comment) {
139
+ console.log(` Comment: "${comment}"`);
140
+ }
141
+
142
+ return review;
143
+ }
144
+
145
+ /**
146
+ * Simulated auto-evaluation by supervisor (generate scores based on task results)
147
+ */
148
+ autoEvaluate({ agent, reviewer, taskTitle }) {
149
+ // Simulated scoring: base score 60-95 random + some variance
150
+ const baseScore = 60 + Math.floor(Math.random() * 35);
151
+ const scores = {
152
+ [PerformanceDimensions.QUALITY]: Math.min(100, baseScore + Math.floor(Math.random() * 10 - 5)),
153
+ [PerformanceDimensions.EFFICIENCY]: Math.min(100, baseScore + Math.floor(Math.random() * 10 - 5)),
154
+ [PerformanceDimensions.COLLABORATION]: Math.min(100, baseScore + Math.floor(Math.random() * 10 - 5)),
155
+ [PerformanceDimensions.INNOVATION]: Math.min(100, baseScore + Math.floor(Math.random() * 10 - 5)),
156
+ [PerformanceDimensions.COMMUNICATION]: Math.min(100, baseScore + Math.floor(Math.random() * 10 - 5)),
157
+ };
158
+
159
+ const comments = {
160
+ 90: 'Outstanding performance, exceeded expectations, a benchmark for the team!',
161
+ 75: 'Excellent work quality, keep it up.',
162
+ 60: 'Task completed adequately, but there is room for improvement.',
163
+ 40: 'Performance was not ideal, improvement needed.',
164
+ 0: 'Work output fell below standards, needs serious attention.',
165
+ };
166
+
167
+ const overallScore = Object.values(scores).reduce((a, b) => a + b, 0) / Object.values(scores).length;
168
+ let comment = comments[0];
169
+ for (const [threshold, c] of Object.entries(comments).sort((a, b) => b[0] - a[0])) {
170
+ if (overallScore >= Number(threshold)) {
171
+ comment = c;
172
+ break;
173
+ }
174
+ }
175
+
176
+ return this.evaluate({ agent, reviewer, taskTitle, scores, comment });
177
+ }
178
+
179
+ /**
180
+ * Get all performance records for an employee
181
+ */
182
+ getReviews(agentId) {
183
+ return this.reviews.get(agentId) || [];
184
+ }
185
+
186
+ /**
187
+ * Get an employee's average performance score
188
+ */
189
+ getAverageScore(agentId) {
190
+ const reviews = this.getReviews(agentId);
191
+ if (reviews.length === 0) return null;
192
+ const total = reviews.reduce((sum, r) => sum + r.overallScore, 0);
193
+ return Math.round(total / reviews.length);
194
+ }
195
+
196
+ /**
197
+ * Get an employee's latest review
198
+ */
199
+ getLatestReview(agentId) {
200
+ const reviews = this.getReviews(agentId);
201
+ return reviews.length > 0 ? reviews[reviews.length - 1] : null;
202
+ }
203
+
204
+ /**
205
+ * Print employee performance report
206
+ */
207
+ printReport(agentId, agentName = '') {
208
+ const reviews = this.getReviews(agentId);
209
+ const avg = this.getAverageScore(agentId);
210
+ const level = avg !== null ? getPerformanceLevel(avg) : null;
211
+
212
+ console.log(`\nšŸ“‹ ${agentName ? `[${agentName}]` : ''} Performance Report:`);
213
+ console.log(` Review count: ${reviews.length}`);
214
+ if (avg !== null) {
215
+ console.log(` Average score: ${avg} ${level.emoji} ${level.label}`);
216
+ }
217
+ reviews.forEach((r, i) => {
218
+ console.log(` #${i + 1}: "${r.taskTitle}" - ${r.overallScore} pts ${r.level.emoji}`);
219
+ if (r.selfReflection) {
220
+ console.log(` Self-reflection: "${r.selfReflection}"`);
221
+ }
222
+ });
223
+ }
224
+ }