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,191 @@
1
+ import { Router } from 'express';
2
+ import path from 'node:path';
3
+ import { readFileSync, existsSync } from 'node:fs';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { getAuthToken } from '../auth.js';
6
+ import { loadEnhancedData, loadProjectEnhanceResult } from '../settings.js';
7
+ import { SCREENSHOTS_DIR } from '../screenshot.js';
8
+ import { renderProjectHtml, renderSessionHtml } from '../render/index.js';
9
+ import { buildSessionRenderData, buildSessionCard, buildProjectRenderData } from '../render/build-render-data.js';
10
+ import { buildAgentSummary } from './context.js';
11
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
12
+ export function createPreviewRouter(ctx) {
13
+ const router = Router();
14
+ // Serve local screenshot files
15
+ router.get('/screenshots/:slug.png', (req, res) => {
16
+ const filePath = path.join(SCREENSHOTS_DIR, `${req.params.slug}.png`);
17
+ if (existsSync(filePath)) {
18
+ res.setHeader('Content-Type', 'image/png');
19
+ res.setHeader('Cache-Control', 'no-cache');
20
+ res.send(readFileSync(filePath));
21
+ }
22
+ else {
23
+ res.status(404).end();
24
+ }
25
+ });
26
+ // Project preview -- serves full standalone HTML page identical to heyi.am
27
+ router.get('/preview/project/:project', async (req, res) => {
28
+ try {
29
+ const projectParam = String(req.params.project);
30
+ const rawProjects = await ctx.getProjects();
31
+ const rawProj = rawProjects.find((p) => p.name === projectParam || p.dirName === projectParam);
32
+ if (!rawProj) {
33
+ res.status(404).send('Project not found');
34
+ return;
35
+ }
36
+ const proj = await ctx.getProjectWithStats(rawProj);
37
+ const cached = loadProjectEnhanceResult(proj.dirName);
38
+ const auth = getAuthToken();
39
+ // Build session cards from parsed sessions + enhanced data
40
+ const sessionCards = [];
41
+ if (cached?.selectedSessionIds) {
42
+ for (const sid of cached.selectedSessionIds) {
43
+ const meta = rawProj.sessions.find((s) => s.sessionId === sid);
44
+ if (!meta)
45
+ continue;
46
+ try {
47
+ const session = await ctx.loadSession(meta.path, rawProj.name, sid);
48
+ const enhanced = loadEnhancedData(sid);
49
+ const agentSummary = await buildAgentSummary(meta.children ?? [], (c) => ctx.getSessionStats(c, rawProj.name), { deduplicate: true });
50
+ sessionCards.push(buildSessionCard({
51
+ sessionId: sid,
52
+ session,
53
+ enhanced,
54
+ username: auth?.username || 'preview',
55
+ projectSlug: proj.dirName,
56
+ sessionSlug: sid,
57
+ sourceTool: session.source || 'claude',
58
+ agentSummary,
59
+ }));
60
+ }
61
+ catch { /* skip sessions that fail to parse */ }
62
+ }
63
+ }
64
+ const enhanceResult = cached?.result;
65
+ // Build cards for ALL sessions (for work timeline + growth chart)
66
+ const allSessionCards = [];
67
+ const sessionStatsMap = new Map();
68
+ for (const meta of rawProj.sessions) {
69
+ try {
70
+ const s = await ctx.loadSession(meta.path, rawProj.name, meta.sessionId);
71
+ const enhanced = loadEnhancedData(meta.sessionId);
72
+ sessionStatsMap.set(meta.sessionId, {
73
+ duration: s.durationMinutes ?? 0,
74
+ date: s.date || undefined,
75
+ skills: enhanced?.skills ?? s.skills ?? [],
76
+ description: enhanced?.context || '',
77
+ });
78
+ const allAgentSummary = await buildAgentSummary(meta.children ?? [], (c) => ctx.getSessionStats(c, rawProj.name));
79
+ allSessionCards.push(buildSessionCard({
80
+ sessionId: meta.sessionId,
81
+ session: s,
82
+ enhanced,
83
+ username: auth?.username || 'preview',
84
+ projectSlug: proj.dirName,
85
+ sessionSlug: meta.sessionId,
86
+ sourceTool: s.source || 'claude',
87
+ agentSummary: allAgentSummary,
88
+ }));
89
+ }
90
+ catch { /* skip */ }
91
+ }
92
+ // Enrich timeline sessions with real stats
93
+ const enrichedTimeline = (enhanceResult?.timeline || []).map((period) => ({
94
+ period: period.period,
95
+ label: period.label,
96
+ sessions: period.sessions.map((s) => {
97
+ const stats = sessionStatsMap.get(s.sessionId);
98
+ return {
99
+ ...s,
100
+ duration: stats?.duration ?? 0,
101
+ date: stats?.date,
102
+ skills: stats?.skills,
103
+ description: stats?.description,
104
+ };
105
+ }),
106
+ }));
107
+ const projAny = proj;
108
+ const renderData = buildProjectRenderData({
109
+ username: auth?.username || 'preview',
110
+ slug: projAny.dirName,
111
+ title: projAny.name,
112
+ narrative: enhanceResult?.narrative || projAny.description || '',
113
+ repoUrl: req.query.repoUrl || undefined,
114
+ projectUrl: req.query.projectUrl || undefined,
115
+ screenshotUrl: (() => {
116
+ const ssSlug = projAny.name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
117
+ return existsSync(path.join(SCREENSHOTS_DIR, `${ssSlug}.png`))
118
+ ? `/screenshots/${ssSlug}.png`
119
+ : undefined;
120
+ })(),
121
+ timeline: enrichedTimeline,
122
+ skills: enhanceResult?.skills || projAny.skills || [],
123
+ totalSessions: projAny.sessionCount,
124
+ totalLoc: projAny.totalLoc,
125
+ totalDurationMinutes: projAny.totalDuration,
126
+ totalAgentDurationMinutes: projAny.totalAgentDuration,
127
+ totalFilesChanged: projAny.totalFiles,
128
+ sessionCards,
129
+ allSessionCards,
130
+ sessionBaseUrl: `/preview/project/${encodeURIComponent(projectParam)}/session`,
131
+ });
132
+ const bodyHtml = renderProjectHtml(renderData);
133
+ res.type('html').send(ctx.buildPreviewPage(projAny.name, bodyHtml, 'PREVIEW — this is how your project will appear on heyi.am'));
134
+ }
135
+ catch (err) {
136
+ console.error('[preview] Error:', err.message);
137
+ res.status(500).send('Preview rendering failed');
138
+ }
139
+ });
140
+ // Session preview
141
+ router.get('/preview/project/:project/session/:sessionId', async (req, res) => {
142
+ try {
143
+ const projectParam = String(req.params.project);
144
+ const sessionId = String(req.params.sessionId);
145
+ const rawProjects = await ctx.getProjects();
146
+ const rawProj = rawProjects.find((p) => p.name === projectParam || p.dirName === projectParam);
147
+ if (!rawProj) {
148
+ res.status(404).send('Project not found');
149
+ return;
150
+ }
151
+ const meta = rawProj.sessions.find((s) => s.sessionId === sessionId);
152
+ if (!meta) {
153
+ res.status(404).send('Session not found');
154
+ return;
155
+ }
156
+ const auth = getAuthToken();
157
+ const session = await ctx.loadSession(meta.path, rawProj.name, sessionId);
158
+ const enhanced = loadEnhancedData(sessionId);
159
+ const agentSummary = await buildAgentSummary(meta.children ?? [], (c) => ctx.getSessionStats(c, rawProj.name));
160
+ const renderData = buildSessionRenderData({
161
+ sessionId,
162
+ session,
163
+ enhanced,
164
+ username: auth?.username || 'preview',
165
+ projectSlug: rawProj.dirName,
166
+ sessionSlug: sessionId,
167
+ sourceTool: session.source || 'claude',
168
+ agentSummary,
169
+ });
170
+ const bodyHtml = renderSessionHtml(renderData);
171
+ res.type('html').send(ctx.buildPreviewPage(session.title || sessionId, bodyHtml, 'PREVIEW — this is how your session will appear on heyi.am'));
172
+ }
173
+ catch (err) {
174
+ console.error('[session-preview] Error:', err.message);
175
+ res.status(500).send('Session preview failed');
176
+ }
177
+ });
178
+ // Serve @heyiam/ui mount script for preview pages
179
+ router.get('/heyiam-mount.js', (_req, res) => {
180
+ const mountPath = path.resolve(__dirname, '..', '..', '..', 'packages', 'ui', 'dist', 'mount.js');
181
+ try {
182
+ const js = readFileSync(mountPath, 'utf-8');
183
+ res.type('application/javascript').send(js);
184
+ }
185
+ catch {
186
+ res.status(404).send('// mount.js not built — run: cd packages/ui && npm run build');
187
+ }
188
+ });
189
+ return router;
190
+ }
191
+ //# sourceMappingURL=preview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview.js","sourceRoot":"","sources":["../../src/routes/preview.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 createProjectsRouter(ctx: RouteContext): Router;
@@ -0,0 +1,356 @@
1
+ import { Router } from 'express';
2
+ import { statSync } from 'node:fs';
3
+ import { toAgentChild, bridgeChildSessions, aggregateChildStats } from '../bridge.js';
4
+ import { getAuthToken } from '../auth.js';
5
+ import { API_URL } from '../config.js';
6
+ import { loadEnhancedData, loadProjectEnhanceResult, getUploadedState } from '../settings.js';
7
+ import { getSessionsByProject } from '../db.js';
8
+ export function createProjectsRouter(ctx) {
9
+ const router = Router();
10
+ router.get('/api/projects', async (_req, res) => {
11
+ try {
12
+ const projects = await ctx.getProjects();
13
+ const projectsWithStats = await Promise.all(projects.map((p) => ctx.getProjectWithStats(p)));
14
+ // Sort by most recent session first
15
+ projectsWithStats.sort((a, b) => (b.lastSessionDate ?? '').localeCompare(a.lastSessionDate ?? ''));
16
+ res.json({ projects: projectsWithStats });
17
+ }
18
+ catch (err) {
19
+ res.status(500).json({ error: { code: 'SCAN_FAILED', message: err.message } });
20
+ }
21
+ });
22
+ // ── Time stats -- rich per-project agent breakdown ──────────
23
+ router.get('/api/time-stats', async (_req, res) => {
24
+ try {
25
+ const projects = await ctx.getProjects();
26
+ const projectStats = await Promise.all(projects.map(async (proj) => {
27
+ const parents = proj.sessions.filter(s => !s.isSubagent);
28
+ let yourMinutes = 0;
29
+ let agentMinutes = 0;
30
+ let orchestratedCount = 0;
31
+ let maxParallelAgents = 0;
32
+ let totalChildAgents = 0;
33
+ const roleSet = new Set();
34
+ for (const meta of parents) {
35
+ const stats = await ctx.getSessionStats(meta, proj.name);
36
+ const dur = stats.duration;
37
+ yourMinutes += dur;
38
+ agentMinutes += dur;
39
+ const children = meta.children ?? [];
40
+ if (children.length > 0) {
41
+ orchestratedCount++;
42
+ maxParallelAgents = Math.max(maxParallelAgents, children.length);
43
+ totalChildAgents += children.length;
44
+ }
45
+ for (const child of children) {
46
+ const childStats = await ctx.getSessionStats(child, proj.name);
47
+ agentMinutes += childStats.duration;
48
+ if (child.agentRole)
49
+ roleSet.add(child.agentRole);
50
+ }
51
+ }
52
+ if (yourMinutes === 0)
53
+ return null;
54
+ return {
55
+ name: proj.name,
56
+ dirName: proj.dirName,
57
+ sessions: parents.length,
58
+ yourMinutes,
59
+ agentMinutes,
60
+ orchestratedSessions: orchestratedCount,
61
+ maxParallelAgents,
62
+ avgAgentsPerSession: parents.length > 0
63
+ ? +((totalChildAgents / parents.length) + 1).toFixed(1)
64
+ : 1,
65
+ uniqueRoles: [...roleSet],
66
+ };
67
+ }));
68
+ const results = projectStats.filter(Boolean);
69
+ results.sort((a, b) => b.agentMinutes - a.agentMinutes);
70
+ const totalYou = results.reduce((s, p) => s + p.yourMinutes, 0);
71
+ const totalAgent = results.reduce((s, p) => s + p.agentMinutes, 0);
72
+ const totalSessions = results.reduce((s, p) => s + p.sessions, 0);
73
+ res.json({
74
+ projects: results,
75
+ totals: {
76
+ yourMinutes: totalYou,
77
+ agentMinutes: totalAgent,
78
+ sessions: totalSessions,
79
+ },
80
+ });
81
+ }
82
+ catch (err) {
83
+ res.status(500).json({ error: { code: 'STATS_FAILED', message: err.message } });
84
+ }
85
+ });
86
+ // Proxy publish time stats to Phoenix
87
+ router.post('/api/upload-time-stats', async (req, res) => {
88
+ const auth = getAuthToken();
89
+ if (!auth) {
90
+ res.status(401).json({ error: 'Authentication required. Run heyiam login first.' });
91
+ return;
92
+ }
93
+ try {
94
+ const phoenixRes = await fetch(`${API_URL}/api/time-stats`, {
95
+ method: 'POST',
96
+ headers: {
97
+ 'Content-Type': 'application/json',
98
+ Authorization: `Bearer ${auth.token}`,
99
+ },
100
+ body: JSON.stringify(req.body),
101
+ });
102
+ const result = await phoenixRes.json();
103
+ res.status(phoenixRes.status).json(result);
104
+ }
105
+ catch (err) {
106
+ res.status(500).json({ error: err.message });
107
+ }
108
+ });
109
+ // Aggregated project detail for the hub screen
110
+ router.get('/api/projects/:project/detail', async (req, res) => {
111
+ try {
112
+ const { project } = req.params;
113
+ const projects = await ctx.getProjects();
114
+ const proj = projects.find((p) => p.name === project || p.dirName === project);
115
+ if (!proj) {
116
+ res.status(404).json({ error: 'Project not found' });
117
+ return;
118
+ }
119
+ const enhanceCache = loadProjectEnhanceResult(proj.dirName);
120
+ // Build session list from DB (fast) + enhanced data files (small reads)
121
+ const dbSessions = getSessionsByProject(ctx.db, proj.dirName);
122
+ const parentSessions = dbSessions.filter((r) => !r.is_subagent);
123
+ const childMap = new Map();
124
+ for (const r of dbSessions) {
125
+ if (r.is_subagent && r.parent_session_id) {
126
+ const children = childMap.get(r.parent_session_id) ?? [];
127
+ children.push({
128
+ sessionId: r.id,
129
+ role: r.agent_role ?? 'agent',
130
+ durationMinutes: r.duration_minutes ?? 0,
131
+ linesOfCode: (r.loc_added ?? 0) + (r.loc_removed ?? 0),
132
+ date: r.start_time ?? '',
133
+ });
134
+ childMap.set(r.parent_session_id, children);
135
+ }
136
+ }
137
+ const sessionStats = parentSessions.map((r) => {
138
+ const enhanced = loadEnhancedData(r.id);
139
+ const children = childMap.get(r.id);
140
+ const skills = enhanced?.skills ?? (r.skills ? JSON.parse(r.skills) : []);
141
+ const locAdded = r.loc_added ?? 0;
142
+ const locRemoved = r.loc_removed ?? 0;
143
+ // Synthesize filesChanged from DB aggregates so the growth chart
144
+ // can show additions vs deletions (red/green) instead of treating
145
+ // linesOfCode as pure additions.
146
+ const filesChanged = (locAdded > 0 || locRemoved > 0)
147
+ ? [{ path: '(aggregate)', additions: locAdded, deletions: locRemoved }]
148
+ : [];
149
+ return {
150
+ id: r.id,
151
+ title: enhanced?.title ?? r.title ?? 'Untitled session',
152
+ date: r.start_time ?? '',
153
+ endTime: r.end_time ?? undefined,
154
+ durationMinutes: r.duration_minutes ?? 0,
155
+ wallClockMinutes: r.wall_clock_minutes ?? undefined,
156
+ turns: r.turns ?? 0,
157
+ linesOfCode: locAdded + locRemoved,
158
+ filesChanged,
159
+ status: (enhanced?.uploaded ? 'uploaded' : enhanced ? 'enhanced' : 'draft'),
160
+ projectName: proj.name,
161
+ rawLog: [],
162
+ skills,
163
+ source: r.source,
164
+ developerTake: enhanced?.developerTake,
165
+ context: enhanced?.context,
166
+ executionPath: enhanced?.executionSteps?.map((s) => ({
167
+ stepNumber: s.stepNumber,
168
+ title: s.title,
169
+ description: s.body,
170
+ })),
171
+ qaPairs: enhanced?.qaPairs,
172
+ childCount: children?.length ?? 0,
173
+ children,
174
+ };
175
+ });
176
+ const totalLoc = sessionStats.reduce((sum, s) => sum + (s.linesOfCode || 0), 0);
177
+ const totalDuration = sessionStats.reduce((sum, s) => sum + (s.durationMinutes || 0), 0);
178
+ const totalFiles = ctx.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;
179
+ // Total agent duration: sum of ALL session durations (parents + subagents)
180
+ const agentDurationRow = ctx.db.prepare('SELECT COALESCE(SUM(duration_minutes), 0) as total FROM sessions WHERE project_dir = ? AND is_subagent = 1').get(proj.dirName);
181
+ const totalAgentDuration = totalDuration + agentDurationRow.total;
182
+ const allSkills = [...new Set(sessionStats.flatMap((s) => s.skills || []))];
183
+ const uploaded = getUploadedState(proj.dirName);
184
+ const dates = sessionStats.map(s => s.date).filter(Boolean).sort();
185
+ res.json({
186
+ project: {
187
+ name: proj.name,
188
+ dirName: proj.dirName,
189
+ sessionCount: proj.sessionCount,
190
+ description: enhanceCache?.result?.narrative ?? '',
191
+ totalLoc,
192
+ totalDuration,
193
+ totalFiles,
194
+ totalAgentDuration: totalAgentDuration > totalDuration ? totalAgentDuration : undefined,
195
+ skills: allSkills,
196
+ dateRange: dates.length ? `${dates[0]}|${dates[dates.length - 1]}` : '',
197
+ lastSessionDate: dates[dates.length - 1] || null,
198
+ isUploaded: !!uploaded,
199
+ uploadedSessionCount: uploaded?.uploadedSessions?.length || 0,
200
+ enhancedAt: enhanceCache?.enhancedAt ?? null,
201
+ },
202
+ sessions: sessionStats.filter((s) => s.date),
203
+ enhanceCache: enhanceCache ?? null,
204
+ });
205
+ }
206
+ catch (err) {
207
+ res.status(500).json({ error: err.message });
208
+ }
209
+ });
210
+ router.get('/api/projects/:project/sessions', async (req, res) => {
211
+ try {
212
+ const { project } = req.params;
213
+ const projects = await ctx.getProjects();
214
+ const proj = projects.find((p) => p.name === project || p.dirName === project);
215
+ if (!proj) {
216
+ res.json({ sessions: [] });
217
+ return;
218
+ }
219
+ const sessions = await Promise.all(proj.sessions.map(async (meta) => {
220
+ const seenIds = new Set();
221
+ const children = [];
222
+ for (const c of meta.children ?? []) {
223
+ if (seenIds.has(c.sessionId))
224
+ continue;
225
+ seenIds.add(c.sessionId);
226
+ const childStats = await ctx.getSessionStats(c, proj.name);
227
+ children.push({
228
+ sessionId: c.sessionId,
229
+ role: c.agentRole ?? 'agent',
230
+ durationMinutes: childStats.duration,
231
+ linesOfCode: childStats.loc,
232
+ date: childStats.date,
233
+ });
234
+ }
235
+ const childCount = children.length;
236
+ try {
237
+ const session = await ctx.loadSession(meta.path, proj.name, meta.sessionId);
238
+ return { ...session, childCount, children: childCount > 0 ? children : undefined };
239
+ }
240
+ catch {
241
+ const stats = await ctx.getSessionStats(meta, proj.name);
242
+ let fallbackDate = stats.date || '';
243
+ if (!fallbackDate) {
244
+ try {
245
+ fallbackDate = statSync(meta.path).mtime.toISOString();
246
+ }
247
+ catch { /* file gone -- will be filtered */ }
248
+ }
249
+ return {
250
+ id: meta.sessionId,
251
+ title: 'Untitled session',
252
+ date: fallbackDate,
253
+ durationMinutes: stats.duration,
254
+ turns: stats.turns,
255
+ linesOfCode: stats.loc,
256
+ status: 'draft',
257
+ projectName: proj.name,
258
+ rawLog: [],
259
+ skills: stats.skills,
260
+ source: meta.source,
261
+ childCount,
262
+ children: childCount > 0 ? children : undefined,
263
+ };
264
+ }
265
+ }));
266
+ res.json({ sessions: sessions.filter((s) => s.date) });
267
+ }
268
+ catch (err) {
269
+ res.status(500).json({ error: { code: 'LIST_FAILED', message: err.message } });
270
+ }
271
+ });
272
+ router.get('/api/projects/:project/sessions/:id', async (req, res) => {
273
+ try {
274
+ const { project, id } = req.params;
275
+ const projects = await ctx.getProjects();
276
+ const proj = projects.find((p) => p.name === project || p.dirName === project);
277
+ if (!proj) {
278
+ res.status(404).json({ error: { code: 'PROJECT_NOT_FOUND', message: 'Project not found' } });
279
+ return;
280
+ }
281
+ const meta = proj.sessions.find((s) => s.sessionId === id);
282
+ if (!meta) {
283
+ res.status(404).json({ error: { code: 'SESSION_NOT_FOUND', message: 'Session not found' } });
284
+ return;
285
+ }
286
+ const session = await ctx.loadSession(meta.path, proj.name, meta.sessionId);
287
+ const parsedChildren = await bridgeChildSessions(meta, proj.name);
288
+ const children = parsedChildren.map(toAgentChild);
289
+ const aggregated = children.length > 0 ? aggregateChildStats(parsedChildren) : undefined;
290
+ res.json({
291
+ session: {
292
+ ...session,
293
+ ...(children.length > 0 ? { children, isOrchestrated: true } : {}),
294
+ ...(aggregated ? { aggregatedStats: aggregated } : {}),
295
+ },
296
+ });
297
+ }
298
+ catch (err) {
299
+ res.status(500).json({ error: { code: 'PARSE_FAILED', message: err.message } });
300
+ }
301
+ });
302
+ // Git remote auto-detection
303
+ router.get('/api/projects/:project/git-remote', async (req, res) => {
304
+ const { execFileSync } = await import('node:child_process');
305
+ try {
306
+ const { project } = req.params;
307
+ const projects = await ctx.getProjects();
308
+ const proj = projects.find((p) => p.name === project || p.dirName === project);
309
+ if (!proj) {
310
+ res.status(404).json({ error: { code: 'PROJECT_NOT_FOUND', message: 'Project not found' } });
311
+ return;
312
+ }
313
+ let projectPath = null;
314
+ for (const meta of proj.sessions) {
315
+ try {
316
+ const parsed = await ctx.loadSession(meta.path, proj.name, meta.sessionId);
317
+ if (parsed.cwd) {
318
+ projectPath = parsed.cwd;
319
+ break;
320
+ }
321
+ }
322
+ catch { /* skip unparseable sessions */ }
323
+ }
324
+ let remoteUrl = null;
325
+ if (projectPath) {
326
+ try {
327
+ const raw = execFileSync('git', ['-C', projectPath, 'remote', 'get-url', 'origin'], {
328
+ timeout: 5000,
329
+ encoding: 'utf-8',
330
+ stdio: ['pipe', 'pipe', 'pipe'],
331
+ }).trim();
332
+ remoteUrl = raw
333
+ .replace(/\.git$/, '')
334
+ .replace(/^git@([^:]+):/, '$1/')
335
+ .replace(/^https?:\/\//, '');
336
+ }
337
+ catch {
338
+ // No git remote or not a git repo -- return null
339
+ }
340
+ }
341
+ res.json({ url: remoteUrl });
342
+ }
343
+ catch (err) {
344
+ res.status(500).json({ error: { code: 'GIT_REMOTE_FAILED', message: err.message } });
345
+ }
346
+ });
347
+ // ── Boundaries ────────────────────────────────────────────────
348
+ router.get('/api/projects/:project/boundaries', (_req, res) => {
349
+ res.json({ selectedSessionIds: [], skippedSessions: [] });
350
+ });
351
+ router.put('/api/projects/:project/boundaries', (_req, res) => {
352
+ res.json({ ok: true });
353
+ });
354
+ return router;
355
+ }
356
+ //# sourceMappingURL=projects.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projects.js","sourceRoot":"","sources":["../../src/routes/projects.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 createPublishRouter(ctx: RouteContext): Router;