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,121 @@
1
+ /**
2
+ * Render data types for static HTML generation.
3
+ *
4
+ * These interfaces define the data shapes that the CLI render functions
5
+ * accept. They are intentionally separate from the interactive UI types
6
+ * in `app/src/types.ts` — the render pipeline owns its own contract.
7
+ */
8
+ import type { AgentSummary } from '../routes/context.js';
9
+ export interface UserInfo {
10
+ username: string;
11
+ accent: string;
12
+ }
13
+ export interface PortfolioUser extends UserInfo {
14
+ displayName: string;
15
+ bio: string;
16
+ location: string;
17
+ status: string;
18
+ }
19
+ export interface PortfolioProject {
20
+ slug: string;
21
+ title: string;
22
+ narrative: string;
23
+ totalSessions: number;
24
+ totalLoc: number;
25
+ totalDurationMinutes: number;
26
+ totalFilesChanged: number;
27
+ skills: string[];
28
+ publishedCount: number;
29
+ }
30
+ export interface PortfolioRenderData {
31
+ user: PortfolioUser;
32
+ projects: PortfolioProject[];
33
+ }
34
+ export interface ProjectTimeline {
35
+ period: string;
36
+ label: string;
37
+ sessions: Array<Record<string, unknown>>;
38
+ }
39
+ export interface ProjectDetail {
40
+ slug: string;
41
+ title: string;
42
+ narrative: string;
43
+ repoUrl?: string;
44
+ projectUrl?: string;
45
+ screenshotUrl?: string;
46
+ timeline: ProjectTimeline[];
47
+ skills: string[];
48
+ totalSessions: number;
49
+ totalLoc: number;
50
+ totalDurationMinutes: number;
51
+ totalAgentDurationMinutes?: number;
52
+ totalFilesChanged: number;
53
+ }
54
+ export interface SessionCard {
55
+ token: string;
56
+ slug: string;
57
+ title: string;
58
+ devTake: string;
59
+ durationMinutes: number;
60
+ turns: number;
61
+ locChanged: number;
62
+ filesChanged: number;
63
+ skills: string[];
64
+ recordedAt: string;
65
+ sourceTool: string;
66
+ agentSummary?: AgentSummary;
67
+ }
68
+ export interface ProjectRenderData {
69
+ user: UserInfo;
70
+ project: ProjectDetail;
71
+ /** Curated sessions for the card grid */
72
+ sessions: SessionCard[];
73
+ /** All sessions for work timeline and growth chart (falls back to sessions if not set) */
74
+ allSessions?: SessionCard[];
75
+ /** Base URL for session links. Defaults to /:username/:project */
76
+ sessionBaseUrl?: string;
77
+ }
78
+ export interface Beat {
79
+ stepNumber: number;
80
+ title: string;
81
+ body: string;
82
+ }
83
+ export interface QaPair {
84
+ question: string;
85
+ answer: string;
86
+ }
87
+ export interface ToolBreakdownEntry {
88
+ tool: string;
89
+ count: number;
90
+ }
91
+ export interface FileEntry {
92
+ path: string;
93
+ additions: number;
94
+ deletions: number;
95
+ }
96
+ export interface SessionDetail {
97
+ token: string;
98
+ title: string;
99
+ devTake: string;
100
+ context?: string;
101
+ durationMinutes: number;
102
+ turns: number;
103
+ filesChanged: number;
104
+ locChanged: number;
105
+ skills: string[];
106
+ narrative?: string;
107
+ beats?: Beat[];
108
+ qaPairs?: QaPair[];
109
+ highlights?: string[];
110
+ toolBreakdown?: ToolBreakdownEntry[];
111
+ topFiles?: FileEntry[];
112
+ recordedAt: string;
113
+ sourceTool: string;
114
+ template: string;
115
+ agentSummary?: AgentSummary;
116
+ }
117
+ export interface SessionRenderData {
118
+ user: UserInfo;
119
+ projectSlug?: string;
120
+ session: SessionDetail;
121
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Render data types for static HTML generation.
3
+ *
4
+ * These interfaces define the data shapes that the CLI render functions
5
+ * accept. They are intentionally separate from the interactive UI types
6
+ * in `app/src/types.ts` — the render pipeline owns its own contract.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/render/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -0,0 +1,3 @@
1
+ import { Router } from 'express';
2
+ import type { RouteContext } from './context.js';
3
+ export declare function createArchiveRouter(ctx: RouteContext): Router;
@@ -0,0 +1,56 @@
1
+ import { Router } from 'express';
2
+ import { archiveSessionFiles } from '../archive.js';
3
+ import { getSourceAudit, getArchiveStats } from '../source-audit.js';
4
+ export function createArchiveRouter(ctx) {
5
+ const router = Router();
6
+ router.get('/api/source-audit', async (_req, res) => {
7
+ try {
8
+ const result = await getSourceAudit();
9
+ res.json(result);
10
+ }
11
+ catch (err) {
12
+ console.error('[source-audit]', err.message);
13
+ res.status(500).json({ error: 'Source audit failed' });
14
+ }
15
+ });
16
+ router.get('/api/archive/stats', async (_req, res) => {
17
+ try {
18
+ const stats = await getArchiveStats();
19
+ res.json(stats);
20
+ }
21
+ catch (err) {
22
+ console.error('[archive-stats]', err.message);
23
+ res.status(500).json({ error: 'Archive stats failed' });
24
+ }
25
+ });
26
+ router.get('/api/archive/health', async (_req, res) => {
27
+ try {
28
+ const audit = await getSourceAudit();
29
+ const health = audit.sources.map((s) => ({
30
+ name: s.name,
31
+ health: s.health,
32
+ retentionRisk: s.retentionRisk ?? null,
33
+ }));
34
+ res.json({ sources: health });
35
+ }
36
+ catch (err) {
37
+ console.error('[archive-health]', err.message);
38
+ res.status(500).json({ error: 'Archive health failed' });
39
+ }
40
+ });
41
+ router.post('/api/archive/sync', async (_req, res) => {
42
+ try {
43
+ // Get session list from SQLite (fast), then archive their files
44
+ const projects = await ctx.getProjects();
45
+ const allSessions = projects.flatMap((p) => p.sessions);
46
+ const result = await archiveSessionFiles(allSessions);
47
+ res.json({ archived: result.archived, alreadyArchived: result.alreadyArchived });
48
+ }
49
+ catch (err) {
50
+ console.error('[archive-sync]', err.message);
51
+ res.status(500).json({ error: 'Archive sync failed' });
52
+ }
53
+ });
54
+ return router;
55
+ }
56
+ //# sourceMappingURL=archive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archive.js","sourceRoot":"","sources":["../../src/routes/archive.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 createAuthRouter(_ctx: RouteContext): Router;
@@ -0,0 +1,116 @@
1
+ import { Router } from 'express';
2
+ import { checkAuthStatus, saveAuthToken } from '../auth.js';
3
+ import { API_URL } from '../config.js';
4
+ export function createAuthRouter(_ctx) {
5
+ const router = Router();
6
+ router.get('/api/auth/status', async (_req, res) => {
7
+ try {
8
+ const status = await checkAuthStatus(API_URL);
9
+ res.json(status);
10
+ }
11
+ catch {
12
+ res.json({ authenticated: false });
13
+ }
14
+ });
15
+ // Start device auth flow -- proxy to Phoenix
16
+ router.post('/api/auth/login', async (_req, res) => {
17
+ try {
18
+ const response = await fetch(`${API_URL}/api/device/code`, { method: 'POST' });
19
+ if (!response.ok) {
20
+ res.status(response.status).json({ error: 'Failed to start device auth' });
21
+ return;
22
+ }
23
+ const data = await response.json();
24
+ res.json(data);
25
+ }
26
+ catch (err) {
27
+ console.error('[auth/login] EXCEPTION:', err);
28
+ res.status(500).json({ error: 'Device auth request failed' });
29
+ }
30
+ });
31
+ // Check username availability — proxy to Phoenix
32
+ router.get('/api/auth/check-username', async (req, res) => {
33
+ try {
34
+ const username = req.query.username;
35
+ if (!username || username.length < 2) {
36
+ res.json({ available: false, reason: 'Username must be at least 2 characters' });
37
+ return;
38
+ }
39
+ if (!/^[a-z0-9](?:[a-z0-9_-]*[a-z0-9])?$/i.test(username)) {
40
+ res.json({ available: false, reason: 'Letters, numbers, hyphens, and underscores only' });
41
+ return;
42
+ }
43
+ const response = await fetch(`${API_URL}/api/username/check?username=${encodeURIComponent(username)}`);
44
+ if (response.ok) {
45
+ const data = await response.json();
46
+ res.json(data);
47
+ }
48
+ else {
49
+ // If Phoenix doesn't have this endpoint yet, assume available
50
+ res.json({ available: true });
51
+ }
52
+ }
53
+ catch {
54
+ // Phoenix not reachable — assume available for now, signup will validate
55
+ res.json({ available: true });
56
+ }
57
+ });
58
+ // Start device auth with a preferred username
59
+ router.post('/api/auth/signup', async (req, res) => {
60
+ try {
61
+ const username = req.body?.username;
62
+ const response = await fetch(`${API_URL}/api/device/code`, {
63
+ method: 'POST',
64
+ headers: { 'Content-Type': 'application/json' },
65
+ body: JSON.stringify(username ? { preferred_username: username } : {}),
66
+ });
67
+ if (!response.ok) {
68
+ res.status(response.status).json({ error: 'Failed to start device auth' });
69
+ return;
70
+ }
71
+ const data = await response.json();
72
+ // Build signup URL: registration page with device code + username pre-filled
73
+ // After registration, Phoenix should redirect to /device?code=xxx to authorize
74
+ const baseUrl = new URL(data.verification_uri).origin;
75
+ const params = new URLSearchParams();
76
+ if (data.user_code)
77
+ params.set('device_code', data.user_code);
78
+ if (username)
79
+ params.set('username', username);
80
+ const signupUri = `${baseUrl}/users/register?${params.toString()}`;
81
+ res.json({ ...data, verification_uri: signupUri });
82
+ }
83
+ catch (err) {
84
+ console.error('[auth/signup] EXCEPTION:', err);
85
+ res.status(500).json({ error: 'Signup request failed' });
86
+ }
87
+ });
88
+ // Poll for device authorization completion
89
+ router.post('/api/auth/poll', async (req, res) => {
90
+ try {
91
+ const deviceCode = req.body?.device_code;
92
+ if (!deviceCode) {
93
+ res.status(400).json({ error: 'Missing device_code' });
94
+ return;
95
+ }
96
+ const response = await fetch(`${API_URL}/api/device/token`, {
97
+ method: 'POST',
98
+ headers: { 'Content-Type': 'application/json' },
99
+ body: JSON.stringify({ device_code: deviceCode }),
100
+ });
101
+ const data = await response.json();
102
+ if (response.ok && data.access_token) {
103
+ saveAuthToken(data.access_token, data.username);
104
+ res.json({ authenticated: true, username: data.username });
105
+ }
106
+ else {
107
+ res.status(response.status).json(data);
108
+ }
109
+ }
110
+ catch {
111
+ res.status(500).json({ error: 'Poll failed' });
112
+ }
113
+ });
114
+ return router;
115
+ }
116
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/routes/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ import type Database from 'better-sqlite3';
2
+ import { type SessionMeta } from '../parsers/index.js';
3
+ import { type Session } from '../analyzer.js';
4
+ import { displayNameFromDir } from '../sync.js';
5
+ export { displayNameFromDir };
6
+ export interface ProjectInfo {
7
+ name: string;
8
+ dirName: string;
9
+ sessionCount: number;
10
+ sessions: SessionMeta[];
11
+ }
12
+ export interface SessionStats {
13
+ loc: number;
14
+ duration: number;
15
+ files: number;
16
+ turns: number;
17
+ skills: string[];
18
+ date: string;
19
+ /** End time as ISO string (for interval merging of concurrent sessions) */
20
+ endTime?: string;
21
+ }
22
+ import { escapeHtml } from '../format-utils.js';
23
+ export { escapeHtml };
24
+ export interface AgentSummary {
25
+ is_orchestrated: true;
26
+ agents: Array<{
27
+ role: string;
28
+ duration_minutes: number;
29
+ loc_changed: number;
30
+ }>;
31
+ }
32
+ /**
33
+ * Build an agent summary from child session metas. Returns null when
34
+ * there are no children (or none produce valid stats).
35
+ *
36
+ * @param childMetas - Array of child SessionMeta objects
37
+ * @param resolveStats - Async function that returns { duration, loc } for a child meta
38
+ * @param options.deduplicate - When true, only the first occurrence of each role is kept
39
+ */
40
+ export declare function buildAgentSummary(childMetas: SessionMeta[], resolveStats: (child: SessionMeta) => Promise<{
41
+ duration: number;
42
+ loc: number;
43
+ }>, options?: {
44
+ deduplicate?: boolean;
45
+ }): Promise<AgentSummary | null>;
46
+ /**
47
+ * RouteContext bundles the database handle and helper closures that
48
+ * every router needs. Created once in createApp() and passed to each
49
+ * router factory.
50
+ */
51
+ export interface RouteContext {
52
+ db: Database.Database;
53
+ sessionsBasePath: string | undefined;
54
+ getProjects: () => Promise<ProjectInfo[]>;
55
+ loadSession: (sessionPath: string, projectName: string, sessionId: string) => Promise<Session>;
56
+ getSessionStats: (meta: SessionMeta, projectName: string) => Promise<SessionStats>;
57
+ mergeSessionIntervals: (stats: SessionStats[]) => number;
58
+ getProjectWithStats: (proj: ProjectInfo) => Promise<Record<string, unknown>>;
59
+ buildPreviewPage: (title: string, bodyHtml: string, banner?: string) => string;
60
+ }
61
+ export declare function createRouteContext(sessionsBasePath?: string, dbPath?: string): RouteContext;