heyiam 0.1.7 → 0.1.8

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 (136) hide show
  1. package/dist/analyzer.d.ts +3 -3
  2. package/dist/archive.d.ts +14 -0
  3. package/dist/archive.js +125 -0
  4. package/dist/archive.js.map +1 -0
  5. package/dist/auth.d.ts +0 -6
  6. package/dist/auth.js +2 -4
  7. package/dist/auth.js.map +1 -1
  8. package/dist/autostart.d.ts +19 -0
  9. package/dist/autostart.js +103 -0
  10. package/dist/autostart.js.map +1 -0
  11. package/dist/bridge.d.ts +0 -2
  12. package/dist/bridge.js +33 -4
  13. package/dist/bridge.js.map +1 -1
  14. package/dist/config.d.ts +1 -1
  15. package/dist/config.js +2 -2
  16. package/dist/config.js.map +1 -1
  17. package/dist/context-export.d.ts +22 -0
  18. package/dist/context-export.js +230 -0
  19. package/dist/context-export.js.map +1 -0
  20. package/dist/daemon-install.d.ts +23 -0
  21. package/dist/daemon-install.js +155 -0
  22. package/dist/daemon-install.js.map +1 -0
  23. package/dist/db.d.ts +118 -0
  24. package/dist/db.js +444 -0
  25. package/dist/db.js.map +1 -0
  26. package/dist/export.d.ts +30 -0
  27. package/dist/export.js +377 -0
  28. package/dist/export.js.map +1 -0
  29. package/dist/format-utils.d.ts +6 -0
  30. package/dist/format-utils.js +15 -0
  31. package/dist/format-utils.js.map +1 -0
  32. package/dist/index.js +474 -117
  33. package/dist/index.js.map +1 -1
  34. package/dist/llm/project-enhance.js +1 -1
  35. package/dist/parsers/claude.js +73 -0
  36. package/dist/parsers/claude.js.map +1 -1
  37. package/dist/parsers/codex.js +1 -1
  38. package/dist/parsers/codex.js.map +1 -1
  39. package/dist/parsers/cursor.d.ts +2 -0
  40. package/dist/parsers/cursor.js +14 -26
  41. package/dist/parsers/cursor.js.map +1 -1
  42. package/dist/parsers/gemini.d.ts +3 -2
  43. package/dist/parsers/gemini.js +198 -21
  44. package/dist/parsers/gemini.js.map +1 -1
  45. package/dist/parsers/index.d.ts +1 -1
  46. package/dist/parsers/index.js +23 -7
  47. package/dist/parsers/index.js.map +1 -1
  48. package/dist/parsers/types.d.ts +27 -1
  49. package/dist/render/build-render-data.d.ts +59 -0
  50. package/dist/render/build-render-data.js +101 -0
  51. package/dist/render/build-render-data.js.map +1 -0
  52. package/dist/render/components/PortfolioPage.d.ts +4 -0
  53. package/dist/render/components/PortfolioPage.js +16 -0
  54. package/dist/render/components/PortfolioPage.js.map +1 -0
  55. package/dist/render/components/ProjectPage.d.ts +4 -0
  56. package/dist/render/components/ProjectPage.js +101 -0
  57. package/dist/render/components/ProjectPage.js.map +1 -0
  58. package/dist/render/components/SessionPage.d.ts +4 -0
  59. package/dist/render/components/SessionPage.js +29 -0
  60. package/dist/render/components/SessionPage.js.map +1 -0
  61. package/dist/render/index.d.ts +37 -0
  62. package/dist/render/index.js +140 -0
  63. package/dist/render/index.js.map +1 -0
  64. package/dist/render/types.d.ts +121 -0
  65. package/dist/render/types.js +9 -0
  66. package/dist/render/types.js.map +1 -0
  67. package/dist/routes/archive.d.ts +3 -0
  68. package/dist/routes/archive.js +56 -0
  69. package/dist/routes/archive.js.map +1 -0
  70. package/dist/routes/auth.d.ts +3 -0
  71. package/dist/routes/auth.js +116 -0
  72. package/dist/routes/auth.js.map +1 -0
  73. package/dist/routes/context.d.ts +61 -0
  74. package/dist/routes/context.js +356 -0
  75. package/dist/routes/context.js.map +1 -0
  76. package/dist/routes/dashboard.d.ts +3 -0
  77. package/dist/routes/dashboard.js +103 -0
  78. package/dist/routes/dashboard.js.map +1 -0
  79. package/dist/routes/enhance.d.ts +3 -0
  80. package/dist/routes/enhance.js +305 -0
  81. package/dist/routes/enhance.js.map +1 -0
  82. package/dist/routes/export.d.ts +3 -0
  83. package/dist/routes/export.js +145 -0
  84. package/dist/routes/export.js.map +1 -0
  85. package/dist/routes/index.d.ts +12 -0
  86. package/dist/routes/index.js +13 -0
  87. package/dist/routes/index.js.map +1 -0
  88. package/dist/routes/preview.d.ts +3 -0
  89. package/dist/routes/preview.js +191 -0
  90. package/dist/routes/preview.js.map +1 -0
  91. package/dist/routes/projects.d.ts +3 -0
  92. package/dist/routes/projects.js +356 -0
  93. package/dist/routes/projects.js.map +1 -0
  94. package/dist/routes/publish.d.ts +3 -0
  95. package/dist/routes/publish.js +466 -0
  96. package/dist/routes/publish.js.map +1 -0
  97. package/dist/routes/search.d.ts +3 -0
  98. package/dist/routes/search.js +110 -0
  99. package/dist/routes/search.js.map +1 -0
  100. package/dist/routes/sessions.d.ts +3 -0
  101. package/dist/routes/sessions.js +103 -0
  102. package/dist/routes/sessions.js.map +1 -0
  103. package/dist/routes/settings.d.ts +3 -0
  104. package/dist/routes/settings.js +30 -0
  105. package/dist/routes/settings.js.map +1 -0
  106. package/dist/screenshot.d.ts +5 -2
  107. package/dist/screenshot.js +187 -13
  108. package/dist/screenshot.js.map +1 -1
  109. package/dist/search.d.ts +30 -0
  110. package/dist/search.js +153 -0
  111. package/dist/search.js.map +1 -0
  112. package/dist/server.d.ts +1 -1
  113. package/dist/server.js +55 -1318
  114. package/dist/server.js.map +1 -1
  115. package/dist/settings.d.ts +23 -6
  116. package/dist/settings.js +36 -12
  117. package/dist/settings.js.map +1 -1
  118. package/dist/source-audit.d.ts +29 -0
  119. package/dist/source-audit.js +203 -0
  120. package/dist/source-audit.js.map +1 -0
  121. package/dist/sync.d.ts +74 -0
  122. package/dist/sync.js +358 -0
  123. package/dist/sync.js.map +1 -0
  124. package/dist/transcript.d.ts +68 -0
  125. package/dist/transcript.js +268 -0
  126. package/dist/transcript.js.map +1 -0
  127. package/package.json +5 -1
  128. package/app/dist/assets/html2canvas-Cwn_rrOw.js +0 -5
  129. package/app/dist/assets/index-CEQyTkgN.js +0 -14
  130. package/app/dist/assets/index-DLh5xRE8.css +0 -1
  131. package/app/dist/favicon.svg +0 -5
  132. package/app/dist/icons.svg +0 -24
  133. package/app/dist/index.html +0 -20
  134. package/dist/machine-key.d.ts +0 -10
  135. package/dist/machine-key.js +0 -51
  136. package/dist/machine-key.js.map +0 -1
@@ -0,0 +1,356 @@
1
+ /**
2
+ * Shared context and helper functions used by all route modules.
3
+ * Created during the server.ts refactor to avoid circular dependencies.
4
+ */
5
+ import path from 'node:path';
6
+ import { readFileSync } from 'node:fs';
7
+ import { fileURLToPath } from 'node:url';
8
+ import { listSessions, parseSession } from '../parsers/index.js';
9
+ import { bridgeToAnalyzer } from '../bridge.js';
10
+ import { analyzeSession } from '../analyzer.js';
11
+ import { loadEnhancedData, loadProjectEnhanceResult, getUploadedState, } from '../settings.js';
12
+ import { archiveSessionFiles } from '../archive.js';
13
+ import { getDatabase, openDatabase, getSessionStats as dbGetSessionStats, getSessionCount, getAllSessionMetas, getAllProjectStats, } from '../db.js';
14
+ import { ensureSessionIndexed, displayNameFromDir } from '../sync.js';
15
+ export { displayNameFromDir };
16
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
17
+ // ── Pure helpers ─────────────────────────────────────────────
18
+ import { escapeHtml } from '../format-utils.js';
19
+ export { escapeHtml };
20
+ /**
21
+ * Build an agent summary from child session metas. Returns null when
22
+ * there are no children (or none produce valid stats).
23
+ *
24
+ * @param childMetas - Array of child SessionMeta objects
25
+ * @param resolveStats - Async function that returns { duration, loc } for a child meta
26
+ * @param options.deduplicate - When true, only the first occurrence of each role is kept
27
+ */
28
+ export async function buildAgentSummary(childMetas, resolveStats, options) {
29
+ if (childMetas.length === 0)
30
+ return null;
31
+ const deduplicate = options?.deduplicate ?? false;
32
+ const seenRoles = new Set();
33
+ const agents = [];
34
+ for (const c of childMetas) {
35
+ if (deduplicate) {
36
+ const key = c.agentRole ?? c.sessionId;
37
+ if (seenRoles.has(key))
38
+ continue;
39
+ seenRoles.add(key);
40
+ }
41
+ const childStats = await resolveStats(c);
42
+ agents.push({
43
+ role: c.agentRole ?? 'agent',
44
+ duration_minutes: childStats.duration,
45
+ loc_changed: childStats.loc,
46
+ });
47
+ }
48
+ return agents.length > 0 ? { is_orchestrated: true, agents } : null;
49
+ }
50
+ export function createRouteContext(sessionsBasePath, dbPath) {
51
+ const db = dbPath ? openDatabase(dbPath) : getDatabase();
52
+ // ── getProjects ──────────────────────────────────────────
53
+ async function getProjects(basePath) {
54
+ // Fast path: read from SQLite when the DB is populated
55
+ if (!basePath && getSessionCount(db) > 0) {
56
+ return getProjectsFromDb();
57
+ }
58
+ // Slow path: filesystem scan (first run or custom basePath)
59
+ const allSessions = await listSessions(basePath);
60
+ if (!basePath) {
61
+ const archiveResult = await archiveSessionFiles(allSessions);
62
+ if (archiveResult.archived > 0) {
63
+ console.log(`Preserved ${archiveResult.archived} sessions → ~/.config/heyiam/sessions/`);
64
+ }
65
+ }
66
+ const byDir = new Map();
67
+ for (const s of allSessions) {
68
+ const existing = byDir.get(s.projectDir) ?? [];
69
+ existing.push(s);
70
+ byDir.set(s.projectDir, existing);
71
+ }
72
+ return [...byDir.entries()].map(([dirName, sessions]) => ({
73
+ name: displayNameFromDir(dirName),
74
+ dirName,
75
+ sessionCount: sessions.length,
76
+ sessions,
77
+ }));
78
+ }
79
+ function getProjectsFromDb() {
80
+ const metas = getAllSessionMetas(db);
81
+ // Group by project, reconstruct children
82
+ const byDir = new Map();
83
+ const childrenMap = new Map();
84
+ for (const m of metas) {
85
+ const meta = {
86
+ path: m.path,
87
+ source: m.source,
88
+ sessionId: m.sessionId,
89
+ projectDir: m.projectDir,
90
+ isSubagent: m.isSubagent,
91
+ parentSessionId: m.parentSessionId,
92
+ agentRole: m.agentRole,
93
+ };
94
+ if (m.isSubagent && m.parentSessionId) {
95
+ const children = childrenMap.get(m.parentSessionId) ?? [];
96
+ children.push(meta);
97
+ childrenMap.set(m.parentSessionId, children);
98
+ }
99
+ const existing = byDir.get(m.projectDir) ?? [];
100
+ existing.push(meta);
101
+ byDir.set(m.projectDir, existing);
102
+ }
103
+ // Attach children to parents
104
+ for (const sessions of byDir.values()) {
105
+ for (const s of sessions) {
106
+ const children = childrenMap.get(s.sessionId);
107
+ if (children)
108
+ s.children = children;
109
+ }
110
+ }
111
+ return [...byDir.entries()].map(([dirName, sessions]) => ({
112
+ name: displayNameFromDir(dirName),
113
+ dirName,
114
+ sessionCount: sessions.filter(s => !s.isSubagent).length,
115
+ sessions,
116
+ }));
117
+ }
118
+ // ── loadSession ──────────────────────────────────────────
119
+ function mergeEnhancedData(session) {
120
+ const enhanced = loadEnhancedData(session.id);
121
+ if (!enhanced)
122
+ return session;
123
+ return {
124
+ ...session,
125
+ title: enhanced.title,
126
+ developerTake: enhanced.developerTake,
127
+ context: enhanced.context,
128
+ skills: enhanced.skills,
129
+ executionPath: enhanced.executionSteps.map((s) => ({
130
+ stepNumber: s.stepNumber,
131
+ title: s.title,
132
+ description: s.body,
133
+ })),
134
+ qaPairs: enhanced.qaPairs,
135
+ status: enhanced.uploaded ? 'uploaded' : 'enhanced',
136
+ quickEnhanced: enhanced.quickEnhanced ?? false,
137
+ };
138
+ }
139
+ async function loadSession(sessionPath, projectName, sessionId) {
140
+ const parsed = await parseSession(sessionPath);
141
+ const analyzerInput = bridgeToAnalyzer(parsed, { sessionId, projectName });
142
+ const session = analyzeSession(analyzerInput);
143
+ return mergeEnhancedData(session);
144
+ }
145
+ // ── getSessionStats ──────────────────────────────────────
146
+ async function getSessionStats(meta, projectName) {
147
+ try {
148
+ await ensureSessionIndexed(db, meta, projectName);
149
+ }
150
+ catch { /* index failed -- fall through to fallback */ }
151
+ const dbStats = dbGetSessionStats(db, meta.sessionId);
152
+ if (dbStats) {
153
+ let endTime = dbStats.endTime;
154
+ if (!endTime && dbStats.date) {
155
+ const mins = dbStats.duration ?? 0;
156
+ if (mins > 0) {
157
+ endTime = new Date(new Date(dbStats.date).getTime() + mins * 60_000).toISOString();
158
+ }
159
+ }
160
+ return {
161
+ loc: dbStats.loc,
162
+ duration: dbStats.duration,
163
+ files: dbStats.files,
164
+ turns: dbStats.turns,
165
+ skills: dbStats.skills,
166
+ date: dbStats.date,
167
+ endTime,
168
+ };
169
+ }
170
+ // Fallback: parse on demand (shouldn't happen after ensureIndexed)
171
+ try {
172
+ const session = await loadSession(meta.path, projectName, meta.sessionId);
173
+ let endTime = session.endTime;
174
+ if (!endTime && session.date) {
175
+ const mins = session.wallClockMinutes ?? session.durationMinutes ?? 0;
176
+ if (mins > 0) {
177
+ endTime = new Date(new Date(session.date).getTime() + mins * 60_000).toISOString();
178
+ }
179
+ }
180
+ return {
181
+ loc: session.linesOfCode ?? 0,
182
+ duration: session.durationMinutes ?? 0,
183
+ files: session.filesChanged?.length ?? 0,
184
+ turns: session.turns ?? 0,
185
+ skills: session.skills ?? [],
186
+ date: session.date ?? '',
187
+ endTime,
188
+ };
189
+ }
190
+ catch {
191
+ return { loc: 0, duration: 0, files: 0, turns: 0, skills: [], date: '' };
192
+ }
193
+ }
194
+ // ── mergeSessionIntervals ────────────────────────────────
195
+ function mergeSessionIntervals(stats) {
196
+ const intervals = [];
197
+ let fallbackSum = 0;
198
+ for (const st of stats) {
199
+ if (st.date && st.endTime) {
200
+ const start = new Date(st.date).getTime();
201
+ const end = new Date(st.endTime).getTime();
202
+ if (!isNaN(start) && !isNaN(end) && end > start) {
203
+ intervals.push([start, end]);
204
+ continue;
205
+ }
206
+ }
207
+ fallbackSum += st.duration;
208
+ }
209
+ if (intervals.length === 0)
210
+ return fallbackSum;
211
+ intervals.sort((a, b) => a[0] - b[0]);
212
+ let totalMs = 0;
213
+ let [curStart, curEnd] = intervals[0];
214
+ for (let i = 1; i < intervals.length; i++) {
215
+ const [start, end] = intervals[i];
216
+ if (start <= curEnd) {
217
+ curEnd = Math.max(curEnd, end);
218
+ }
219
+ else {
220
+ totalMs += curEnd - curStart;
221
+ curStart = start;
222
+ curEnd = end;
223
+ }
224
+ }
225
+ totalMs += curEnd - curStart;
226
+ return Math.round(totalMs / 60_000) + fallbackSum;
227
+ }
228
+ // ── getProjectWithStats ──────────────────────────────────
229
+ // Cache of DB project stats, invalidated per request cycle
230
+ let _dbProjectStatsCache = null;
231
+ function getDbProjectStatsMap() {
232
+ if (!_dbProjectStatsCache) {
233
+ const stats = getAllProjectStats(db);
234
+ _dbProjectStatsCache = new Map(stats.map((s) => [s.projectDir, s]));
235
+ // Clear cache after this tick to avoid stale data across requests
236
+ setTimeout(() => { _dbProjectStatsCache = null; }, 0);
237
+ }
238
+ return _dbProjectStatsCache;
239
+ }
240
+ async function getProjectWithStats(proj) {
241
+ // Fast path: read aggregates from SQLite (single query, no per-session I/O)
242
+ const statsMap = getDbProjectStatsMap();
243
+ const dbStats = statsMap.get(proj.dirName);
244
+ const published = getUploadedState(proj.dirName);
245
+ const enhanceCache = loadProjectEnhanceResult(proj.dirName);
246
+ if (dbStats) {
247
+ // Compute agent duration from DB: sum of all session durations including subagents
248
+ const agentRow = db.prepare('SELECT COALESCE(SUM(duration_minutes), 0) as total FROM sessions WHERE project_dir = ?').get(proj.dirName);
249
+ return {
250
+ name: proj.name,
251
+ dirName: proj.dirName,
252
+ sessionCount: dbStats.sessionCount,
253
+ description: '',
254
+ totalLoc: dbStats.totalLoc,
255
+ totalDuration: dbStats.totalDuration,
256
+ totalFiles: db.prepare('SELECT COUNT(DISTINCT file_path) as c FROM session_files WHERE session_id IN (SELECT id FROM sessions WHERE project_dir = ? AND is_subagent = 0)').get(proj.dirName).c,
257
+ skills: dbStats.skills,
258
+ dateRange: (() => {
259
+ const row = db.prepare('SELECT MIN(start_time) as earliest, MAX(start_time) as latest FROM sessions WHERE project_dir = ? AND is_subagent = 0').get(proj.dirName);
260
+ return row?.earliest && row?.latest ? `${row.earliest}|${row.latest}` : '';
261
+ })(),
262
+ lastSessionDate: dbStats.latestDate,
263
+ isUploaded: !!published,
264
+ uploadedSessionCount: published?.uploadedSessions?.length ?? 0,
265
+ uploadedSessions: published?.uploadedSessions ?? [],
266
+ enhancedAt: enhanceCache?.enhancedAt ?? null,
267
+ totalAgentDuration: agentRow.total,
268
+ };
269
+ }
270
+ // Fallback: per-session stats (only if DB has no data for this project)
271
+ const parentMetas = proj.sessions.filter(s => !s.isSubagent);
272
+ const allStats = await Promise.all(parentMetas.map((m) => getSessionStats(m, proj.name)));
273
+ const totalLoc = allStats.reduce((s, st) => s + st.loc, 0);
274
+ const totalFiles = allStats.reduce((s, st) => s + st.files, 0);
275
+ const totalDuration = allStats.reduce((s, st) => s + st.duration, 0);
276
+ let totalAgentDuration = totalDuration;
277
+ for (const meta of parentMetas) {
278
+ for (const child of meta.children ?? []) {
279
+ const childStats = await getSessionStats(child, proj.name);
280
+ totalAgentDuration += childStats.duration;
281
+ }
282
+ }
283
+ const skillSet = new Set();
284
+ for (const st of allStats) {
285
+ for (const sk of st.skills)
286
+ skillSet.add(sk);
287
+ }
288
+ const dates = allStats.map((st) => st.date).filter(Boolean).sort();
289
+ const firstDate = dates[0] ?? '';
290
+ const lastDate = dates[dates.length - 1] ?? '';
291
+ return {
292
+ name: proj.name,
293
+ dirName: proj.dirName,
294
+ sessionCount: proj.sessionCount,
295
+ description: '',
296
+ totalLoc,
297
+ totalDuration,
298
+ totalFiles,
299
+ skills: [...skillSet],
300
+ dateRange: firstDate && lastDate ? `${firstDate}|${lastDate}` : '',
301
+ lastSessionDate: lastDate,
302
+ isUploaded: !!published,
303
+ uploadedSessionCount: published?.uploadedSessions?.length ?? 0,
304
+ uploadedSessions: published?.uploadedSessions ?? [],
305
+ enhancedAt: enhanceCache?.enhancedAt ?? null,
306
+ totalAgentDuration,
307
+ };
308
+ }
309
+ // ── buildPreviewPage ─────────────────────────────────────
310
+ function buildPreviewPage(title, bodyHtml, banner) {
311
+ const appCssPath = path.resolve(__dirname, '..', '..', 'app', 'src', 'App.css');
312
+ const indexCssPath = path.resolve(__dirname, '..', '..', 'app', 'src', 'index.css');
313
+ let inlineCss = '';
314
+ try {
315
+ inlineCss += readFileSync(indexCssPath, 'utf-8');
316
+ }
317
+ catch { /* */ }
318
+ try {
319
+ inlineCss += readFileSync(appCssPath, 'utf-8');
320
+ }
321
+ catch { /* */ }
322
+ const cssTag = `<style>${inlineCss}\n/* Preview override */\nbody { overflow: auto !important; min-height: auto !important; }\n#root { min-height: auto !important; }</style>`;
323
+ const bannerHtml = banner
324
+ ? `<div style="background: var(--primary, #084471); color: white; text-align: center; padding: 0.5rem; font-family: 'Inter', sans-serif; font-size: 0.75rem; letter-spacing: 0.05em;">${escapeHtml(banner)}</div>`
325
+ : '';
326
+ return `<!DOCTYPE html>
327
+ <html lang="en">
328
+ <head>
329
+ <meta charset="utf-8" />
330
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
331
+ <meta name="heyiam-api-base" content="/api" />
332
+ <title>${escapeHtml(title)} — Preview</title>
333
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
334
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
335
+ <link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600;700&family=Inter:wght@400;500;600;700&family=Space+Grotesk:wght@400;500;600;700&display=swap" rel="stylesheet" />
336
+ ${cssTag}
337
+ </head>
338
+ <body>
339
+ ${bannerHtml}
340
+ ${bodyHtml}
341
+ <script src="/heyiam-mount.js"></script>
342
+ </body>
343
+ </html>`;
344
+ }
345
+ return {
346
+ db,
347
+ sessionsBasePath,
348
+ getProjects: () => getProjects(sessionsBasePath),
349
+ loadSession,
350
+ getSessionStats,
351
+ mergeSessionIntervals,
352
+ getProjectWithStats,
353
+ buildPreviewPage,
354
+ };
355
+ }
356
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/routes/context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Router } from 'express';
2
+ import type { RouteContext } from './context.js';
3
+ export declare function createDashboardRouter(ctx: RouteContext): Router;
@@ -0,0 +1,103 @@
1
+ import { Router } from 'express';
2
+ import { readdirSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { homedir } from 'node:os';
5
+ import { getDashboardStats } from '../db.js';
6
+ import { getSyncState, onSyncProgress } from '../sync.js';
7
+ import { displayNameFromDir } from './context.js';
8
+ import { loadProjectEnhanceResult, isOnboardingComplete, completeOnboarding, resetOnboarding } from '../settings.js';
9
+ export function createDashboardRouter(ctx) {
10
+ const router = Router();
11
+ // ── GET /api/dashboard — single fast read from SQLite ──────
12
+ router.get('/api/dashboard', (_req, res) => {
13
+ try {
14
+ const stats = getDashboardStats(ctx.db);
15
+ const sync = getSyncState();
16
+ // Count enhanced projects by checking the enhance cache directory
17
+ let enhancedCount = 0;
18
+ const enhanceDir = join(homedir(), '.config', 'heyiam', 'project-enhance');
19
+ try {
20
+ const files = readdirSync(enhanceDir).filter((f) => f.endsWith('.json'));
21
+ enhancedCount = files.length;
22
+ }
23
+ catch { /* dir doesn't exist yet */ }
24
+ // Enrich projects with enhancedAt from cache
25
+ const projects = stats.projects.map((p) => {
26
+ const cache = loadProjectEnhanceResult(p.projectDir);
27
+ return {
28
+ ...p,
29
+ projectName: displayNameFromDir(p.projectDir),
30
+ enhancedAt: cache?.enhancedAt ?? null,
31
+ };
32
+ });
33
+ const isEmpty = stats.sessionCount === 0 && sync.status !== 'syncing';
34
+ res.json({
35
+ stats: {
36
+ sessionCount: stats.sessionCount,
37
+ projectCount: stats.projectCount,
38
+ sourceCount: stats.sourceCount,
39
+ enhancedCount,
40
+ },
41
+ projects,
42
+ sync: {
43
+ status: sync.status,
44
+ phase: sync.phase,
45
+ current: sync.current,
46
+ total: sync.total,
47
+ currentProject: sync.currentProject,
48
+ },
49
+ isEmpty,
50
+ onboardingComplete: isOnboardingComplete(),
51
+ });
52
+ }
53
+ catch (err) {
54
+ console.error('[dashboard]', err.message);
55
+ res.status(500).json({ error: 'Dashboard failed' });
56
+ }
57
+ });
58
+ // ── GET /api/sync/progress — SSE stream for first-run ──────
59
+ router.get('/api/sync/progress', (req, res) => {
60
+ res.writeHead(200, {
61
+ 'Content-Type': 'text/event-stream',
62
+ 'Cache-Control': 'no-cache',
63
+ 'Connection': 'keep-alive',
64
+ });
65
+ // Send current state immediately
66
+ const current = getSyncState();
67
+ res.write(`data: ${JSON.stringify(current)}\n\n`);
68
+ if (current.status === 'done' || current.status === 'idle') {
69
+ res.end();
70
+ return;
71
+ }
72
+ // Subscribe to updates
73
+ const unsubscribe = onSyncProgress((state) => {
74
+ res.write(`data: ${JSON.stringify(state)}\n\n`);
75
+ if (state.status === 'done') {
76
+ res.end();
77
+ }
78
+ });
79
+ req.on('close', unsubscribe);
80
+ });
81
+ // ── POST /api/onboarding/complete — mark onboarding done ───
82
+ router.post('/api/onboarding/complete', (_req, res) => {
83
+ try {
84
+ completeOnboarding();
85
+ res.json({ ok: true });
86
+ }
87
+ catch (err) {
88
+ res.status(500).json({ error: err.message });
89
+ }
90
+ });
91
+ // ── POST /api/onboarding/reset — reset onboarding (dev helper) ───
92
+ router.post('/api/onboarding/reset', (_req, res) => {
93
+ try {
94
+ resetOnboarding();
95
+ res.json({ ok: true, message: 'Onboarding reset. Refresh the page.' });
96
+ }
97
+ catch (err) {
98
+ res.status(500).json({ error: err.message });
99
+ }
100
+ });
101
+ return router;
102
+ }
103
+ //# sourceMappingURL=dashboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../src/routes/dashboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAA+B,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGrH,MAAM,UAAU,qBAAqB,CAAC,GAAiB;IACrD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;IAExB,8DAA8D;IAC9D,MAAM,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC,IAAa,EAAE,GAAa,EAAE,EAAE;QAC5D,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACxC,MAAM,IAAI,GAAG,YAAY,EAAE,CAAC;YAE5B,kEAAkE;YAClE,IAAI,aAAa,GAAG,CAAC,CAAC;YACtB,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,iBAAiB,CAAC,CAAC;YAC3E,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;gBACzE,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC;YAC/B,CAAC;YAAC,MAAM,CAAC,CAAC,2BAA2B,CAAC,CAAC;YAEvC,6CAA6C;YAC7C,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBACxC,MAAM,KAAK,GAAG,wBAAwB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;gBACrD,OAAO;oBACL,GAAG,CAAC;oBACJ,WAAW,EAAE,kBAAkB,CAAC,CAAC,CAAC,UAAU,CAAC;oBAC7C,UAAU,EAAE,KAAK,EAAE,UAAU,IAAI,IAAI;iBACtC,CAAC;YACJ,CAAC,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,KAAK,CAAC,YAAY,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC;YAEtE,GAAG,CAAC,IAAI,CAAC;gBACP,KAAK,EAAE;oBACL,YAAY,EAAE,KAAK,CAAC,YAAY;oBAChC,YAAY,EAAE,KAAK,CAAC,YAAY;oBAChC,WAAW,EAAE,KAAK,CAAC,WAAW;oBAC9B,aAAa;iBACd;gBACD,QAAQ;gBACR,IAAI,EAAE;oBACJ,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,OAAO,EAAE,IAAI,CAAC,OAAO;oBACrB,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,cAAc,EAAE,IAAI,CAAC,cAAc;iBACpC;gBACD,OAAO;gBACP,kBAAkB,EAAE,oBAAoB,EAAE;aAC3C,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,aAAa,EAAG,GAAa,CAAC,OAAO,CAAC,CAAC;YACrD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,CAAC;QACtD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,8DAA8D;IAC9D,MAAM,CAAC,GAAG,CAAC,oBAAoB,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;QAC/D,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;YACjB,cAAc,EAAE,mBAAmB;YACnC,eAAe,EAAE,UAAU;YAC3B,YAAY,EAAE,YAAY;SAC3B,CAAC,CAAC;QAEH,iCAAiC;QACjC,MAAM,OAAO,GAAG,YAAY,EAAE,CAAC;QAC/B,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAElD,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC3D,GAAG,CAAC,GAAG,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QAED,uBAAuB;QACvB,MAAM,WAAW,GAAG,cAAc,CAAC,CAAC,KAAK,EAAE,EAAE;YAC3C,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAChD,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBAC5B,GAAG,CAAC,GAAG,EAAE,CAAC;YACZ,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,8DAA8D;IAC9D,MAAM,CAAC,IAAI,CAAC,0BAA0B,EAAE,CAAC,IAAa,EAAE,GAAa,EAAE,EAAE;QACvE,IAAI,CAAC;YACH,kBAAkB,EAAE,CAAC;YACrB,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QACzB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAG,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,oEAAoE;IACpE,MAAM,CAAC,IAAI,CAAC,uBAAuB,EAAE,CAAC,IAAa,EAAE,GAAa,EAAE,EAAE;QACpE,IAAI,CAAC;YACH,eAAe,EAAE,CAAC;YAClB,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,qCAAqC,EAAE,CAAC,CAAC;QACzE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAG,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Router } from 'express';
2
+ import type { RouteContext } from './context.js';
3
+ export declare function createEnhanceRouter(ctx: RouteContext): Router;