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.
- package/dist/analyzer.d.ts +3 -3
- package/dist/archive.d.ts +14 -0
- package/dist/archive.js +125 -0
- package/dist/archive.js.map +1 -0
- package/dist/auth.d.ts +0 -6
- package/dist/auth.js +2 -4
- package/dist/auth.js.map +1 -1
- package/dist/autostart.d.ts +19 -0
- package/dist/autostart.js +103 -0
- package/dist/autostart.js.map +1 -0
- package/dist/bridge.d.ts +0 -2
- package/dist/bridge.js +33 -4
- package/dist/bridge.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +2 -2
- package/dist/config.js.map +1 -1
- package/dist/context-export.d.ts +22 -0
- package/dist/context-export.js +230 -0
- package/dist/context-export.js.map +1 -0
- package/dist/daemon-install.d.ts +23 -0
- package/dist/daemon-install.js +155 -0
- package/dist/daemon-install.js.map +1 -0
- package/dist/db.d.ts +118 -0
- package/dist/db.js +444 -0
- package/dist/db.js.map +1 -0
- package/dist/export.d.ts +30 -0
- package/dist/export.js +377 -0
- package/dist/export.js.map +1 -0
- package/dist/format-utils.d.ts +6 -0
- package/dist/format-utils.js +15 -0
- package/dist/format-utils.js.map +1 -0
- package/dist/index.js +474 -117
- package/dist/index.js.map +1 -1
- package/dist/llm/project-enhance.js +1 -1
- package/dist/parsers/claude.js +73 -0
- package/dist/parsers/claude.js.map +1 -1
- package/dist/parsers/codex.js +1 -1
- package/dist/parsers/codex.js.map +1 -1
- package/dist/parsers/cursor.d.ts +2 -0
- package/dist/parsers/cursor.js +14 -26
- package/dist/parsers/cursor.js.map +1 -1
- package/dist/parsers/gemini.d.ts +3 -2
- package/dist/parsers/gemini.js +198 -21
- package/dist/parsers/gemini.js.map +1 -1
- package/dist/parsers/index.d.ts +1 -1
- package/dist/parsers/index.js +23 -7
- package/dist/parsers/index.js.map +1 -1
- package/dist/parsers/types.d.ts +27 -1
- package/dist/render/build-render-data.d.ts +59 -0
- package/dist/render/build-render-data.js +101 -0
- package/dist/render/build-render-data.js.map +1 -0
- package/dist/render/components/PortfolioPage.d.ts +4 -0
- package/dist/render/components/PortfolioPage.js +16 -0
- package/dist/render/components/PortfolioPage.js.map +1 -0
- package/dist/render/components/ProjectPage.d.ts +4 -0
- package/dist/render/components/ProjectPage.js +101 -0
- package/dist/render/components/ProjectPage.js.map +1 -0
- package/dist/render/components/SessionPage.d.ts +4 -0
- package/dist/render/components/SessionPage.js +29 -0
- package/dist/render/components/SessionPage.js.map +1 -0
- package/dist/render/index.d.ts +37 -0
- package/dist/render/index.js +140 -0
- package/dist/render/index.js.map +1 -0
- package/dist/render/types.d.ts +121 -0
- package/dist/render/types.js +9 -0
- package/dist/render/types.js.map +1 -0
- package/dist/routes/archive.d.ts +3 -0
- package/dist/routes/archive.js +56 -0
- package/dist/routes/archive.js.map +1 -0
- package/dist/routes/auth.d.ts +3 -0
- package/dist/routes/auth.js +116 -0
- package/dist/routes/auth.js.map +1 -0
- package/dist/routes/context.d.ts +61 -0
- package/dist/routes/context.js +356 -0
- package/dist/routes/context.js.map +1 -0
- package/dist/routes/dashboard.d.ts +3 -0
- package/dist/routes/dashboard.js +103 -0
- package/dist/routes/dashboard.js.map +1 -0
- package/dist/routes/enhance.d.ts +3 -0
- package/dist/routes/enhance.js +305 -0
- package/dist/routes/enhance.js.map +1 -0
- package/dist/routes/export.d.ts +3 -0
- package/dist/routes/export.js +145 -0
- package/dist/routes/export.js.map +1 -0
- package/dist/routes/index.d.ts +12 -0
- package/dist/routes/index.js +13 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/preview.d.ts +3 -0
- package/dist/routes/preview.js +191 -0
- package/dist/routes/preview.js.map +1 -0
- package/dist/routes/projects.d.ts +3 -0
- package/dist/routes/projects.js +356 -0
- package/dist/routes/projects.js.map +1 -0
- package/dist/routes/publish.d.ts +3 -0
- package/dist/routes/publish.js +466 -0
- package/dist/routes/publish.js.map +1 -0
- package/dist/routes/search.d.ts +3 -0
- package/dist/routes/search.js +110 -0
- package/dist/routes/search.js.map +1 -0
- package/dist/routes/sessions.d.ts +3 -0
- package/dist/routes/sessions.js +103 -0
- package/dist/routes/sessions.js.map +1 -0
- package/dist/routes/settings.d.ts +3 -0
- package/dist/routes/settings.js +30 -0
- package/dist/routes/settings.js.map +1 -0
- package/dist/screenshot.d.ts +5 -2
- package/dist/screenshot.js +187 -13
- package/dist/screenshot.js.map +1 -1
- package/dist/search.d.ts +30 -0
- package/dist/search.js +153 -0
- package/dist/search.js.map +1 -0
- package/dist/server.d.ts +1 -1
- package/dist/server.js +55 -1318
- package/dist/server.js.map +1 -1
- package/dist/settings.d.ts +23 -6
- package/dist/settings.js +36 -12
- package/dist/settings.js.map +1 -1
- package/dist/source-audit.d.ts +29 -0
- package/dist/source-audit.js +203 -0
- package/dist/source-audit.js.map +1 -0
- package/dist/sync.d.ts +74 -0
- package/dist/sync.js +358 -0
- package/dist/sync.js.map +1 -0
- package/dist/transcript.d.ts +68 -0
- package/dist/transcript.js +268 -0
- package/dist/transcript.js.map +1 -0
- package/package.json +5 -1
- package/app/dist/assets/html2canvas-Cwn_rrOw.js +0 -5
- package/app/dist/assets/index-CEQyTkgN.js +0 -14
- package/app/dist/assets/index-DLh5xRE8.css +0 -1
- package/app/dist/favicon.svg +0 -5
- package/app/dist/icons.svg +0 -24
- package/app/dist/index.html +0 -20
- package/dist/machine-key.d.ts +0 -10
- package/dist/machine-key.js +0 -51
- package/dist/machine-key.js.map +0 -1
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import { listSessions, parseSession } from '../parsers/index.js';
|
|
3
|
+
import { bridgeToAnalyzer } from '../bridge.js';
|
|
4
|
+
import { analyzeSession } from '../analyzer.js';
|
|
5
|
+
import { getSessionRow } from '../db.js';
|
|
6
|
+
import { ensureSessionIndexed } from '../sync.js';
|
|
7
|
+
import { exportSessionContext } from '../context-export.js';
|
|
8
|
+
import { buildTranscriptResponse } from '../transcript.js';
|
|
9
|
+
import { displayNameFromDir } from './context.js';
|
|
10
|
+
/**
|
|
11
|
+
* Find a session's file path and project name, checking the DB first,
|
|
12
|
+
* then falling back to live discovery (triggers indexing as a side effect).
|
|
13
|
+
*/
|
|
14
|
+
async function resolveSession(ctx, id) {
|
|
15
|
+
// Try DB first
|
|
16
|
+
const row = getSessionRow(ctx.db, id);
|
|
17
|
+
if (row?.file_path) {
|
|
18
|
+
return { filePath: row.file_path, projectName: displayNameFromDir(row.project_dir) };
|
|
19
|
+
}
|
|
20
|
+
// Fallback: discover live sessions and index the match
|
|
21
|
+
const allSessions = await listSessions(ctx.sessionsBasePath);
|
|
22
|
+
const meta = allSessions.find((s) => s.sessionId === id);
|
|
23
|
+
if (!meta)
|
|
24
|
+
return null;
|
|
25
|
+
const projectName = displayNameFromDir(meta.projectDir);
|
|
26
|
+
try {
|
|
27
|
+
await ensureSessionIndexed(ctx.db, meta, projectName);
|
|
28
|
+
}
|
|
29
|
+
catch { /* best effort */ }
|
|
30
|
+
return { filePath: meta.path, projectName };
|
|
31
|
+
}
|
|
32
|
+
export function createSessionsRouter(ctx) {
|
|
33
|
+
const router = Router();
|
|
34
|
+
// Session by ID (cross-project lookup)
|
|
35
|
+
router.get('/api/sessions/:id', async (req, res) => {
|
|
36
|
+
try {
|
|
37
|
+
const id = String(req.params.id);
|
|
38
|
+
const resolved = await resolveSession(ctx, id);
|
|
39
|
+
if (!resolved) {
|
|
40
|
+
res.status(404).json({ error: { code: 'SESSION_NOT_FOUND', message: 'Session not found' } });
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const session = await ctx.loadSession(resolved.filePath, resolved.projectName, id);
|
|
44
|
+
res.json({ session });
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
res.status(500).json({ error: { code: 'LOAD_FAILED', message: err.message } });
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
// Session context export
|
|
51
|
+
router.get('/api/sessions/:id/context', async (req, res) => {
|
|
52
|
+
try {
|
|
53
|
+
const id = String(req.params.id);
|
|
54
|
+
const format = (String(req.query.format ?? 'summary'));
|
|
55
|
+
const resolved = await resolveSession(ctx, id);
|
|
56
|
+
if (!resolved) {
|
|
57
|
+
res.status(404).json({ error: { code: 'SESSION_NOT_FOUND', message: 'Session not found' } });
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const parsed = await parseSession(resolved.filePath);
|
|
61
|
+
const analyzerInput = bridgeToAnalyzer(parsed, { sessionId: id, projectName: resolved.projectName });
|
|
62
|
+
const session = analyzeSession(analyzerInput);
|
|
63
|
+
const turns = analyzerInput.turns;
|
|
64
|
+
const result = exportSessionContext(session, turns, { tier: format });
|
|
65
|
+
res.json({
|
|
66
|
+
content: result.content,
|
|
67
|
+
tokens: result.tokens,
|
|
68
|
+
format: result.tier,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
res.status(500).json({ error: { code: 'CONTEXT_EXPORT_FAILED', message: err.message } });
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
// Session transcript — full conversation for the viewer
|
|
76
|
+
router.get('/api/sessions/:id/transcript', async (req, res) => {
|
|
77
|
+
try {
|
|
78
|
+
const id = String(req.params.id);
|
|
79
|
+
const resolved = await resolveSession(ctx, id);
|
|
80
|
+
if (!resolved) {
|
|
81
|
+
res.status(404).json({ error: { code: 'SESSION_NOT_FOUND', message: 'Session not found' } });
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const parsed = await parseSession(resolved.filePath);
|
|
85
|
+
const transcript = buildTranscriptResponse(parsed.raw_entries, {
|
|
86
|
+
cwd: parsed.cwd,
|
|
87
|
+
activeMinutes: parsed.duration_ms > 0 ? Math.max(1, Math.round(parsed.duration_ms / 60_000)) : 0,
|
|
88
|
+
wallClockMinutes: parsed.wall_clock_ms > 0 ? Math.max(1, Math.round(parsed.wall_clock_ms / 60_000)) : 0,
|
|
89
|
+
tokenUsage: parsed.token_usage ? {
|
|
90
|
+
input_tokens: parsed.token_usage.input_tokens,
|
|
91
|
+
output_tokens: parsed.token_usage.output_tokens,
|
|
92
|
+
} : undefined,
|
|
93
|
+
modelsUsed: parsed.models_used,
|
|
94
|
+
});
|
|
95
|
+
res.json(transcript);
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
res.status(500).json({ error: { code: 'TRANSCRIPT_FAILED', message: err.message } });
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
return router;
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=sessions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/routes/sessions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import { saveAnthropicApiKey, clearAnthropicApiKey, getAnthropicApiKey } from '../settings.js';
|
|
3
|
+
import { getEnhanceMode } from '../llm/index.js';
|
|
4
|
+
export function createSettingsRouter(_ctx) {
|
|
5
|
+
const router = Router();
|
|
6
|
+
// Save or clear the Anthropic API key
|
|
7
|
+
router.post('/api/settings/api-key', (req, res) => {
|
|
8
|
+
const { apiKey } = req.body;
|
|
9
|
+
if (apiKey && typeof apiKey === 'string' && apiKey.trim()) {
|
|
10
|
+
saveAnthropicApiKey(apiKey.trim());
|
|
11
|
+
console.log('[settings] API key saved');
|
|
12
|
+
res.json({ ok: true, mode: getEnhanceMode() });
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
clearAnthropicApiKey();
|
|
16
|
+
console.log('[settings] API key cleared');
|
|
17
|
+
res.json({ ok: true, mode: getEnhanceMode() });
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
// Get current API key status (masked)
|
|
21
|
+
router.get('/api/settings/api-key', (_req, res) => {
|
|
22
|
+
const key = getAnthropicApiKey();
|
|
23
|
+
res.json({
|
|
24
|
+
hasKey: !!key,
|
|
25
|
+
maskedKey: key ? `${key.slice(0, 4)}...` : null,
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
return router;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/routes/settings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAA+B,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAC/F,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGjD,MAAM,UAAU,oBAAoB,CAAC,IAAkB;IACrD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;IAExB,sCAAsC;IACtC,MAAM,CAAC,IAAI,CAAC,uBAAuB,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;QACnE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,IAA2B,CAAC;QACnD,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;YAC1D,mBAAmB,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YACnC,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;YACxC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,CAAC,CAAC;QACjD,CAAC;aAAM,CAAC;YACN,oBAAoB,EAAE,CAAC;YACvB,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;YAC1C,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,CAAC,CAAC;QACjD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,sCAAsC;IACtC,MAAM,CAAC,GAAG,CAAC,uBAAuB,EAAE,CAAC,IAAa,EAAE,GAAa,EAAE,EAAE;QACnE,MAAM,GAAG,GAAG,kBAAkB,EAAE,CAAC;QACjC,GAAG,CAAC,IAAI,CAAC;YACP,MAAM,EAAE,CAAC,CAAC,GAAG;YACb,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;SAChD,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/screenshot.d.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
export declare const SCREENSHOTS_DIR: string;
|
|
1
2
|
/**
|
|
2
3
|
* Find the first available Chrome binary on the system.
|
|
3
4
|
* Returns the path or null if not found.
|
|
4
5
|
*/
|
|
5
6
|
export declare function findChrome(): string | null;
|
|
6
7
|
/**
|
|
7
|
-
* Capture a screenshot
|
|
8
|
-
*
|
|
8
|
+
* Capture a full-page screenshot using Chrome DevTools Protocol.
|
|
9
|
+
* Uses Page.getLayoutMetrics for exact content height, then
|
|
10
|
+
* Page.captureScreenshot with captureBeyondViewport for a full capture.
|
|
11
|
+
* Falls back to CLI --screenshot on Node < 22 (no built-in WebSocket).
|
|
9
12
|
*/
|
|
10
13
|
export declare function captureScreenshot(url: string, slug: string): Promise<string | null>;
|
package/dist/screenshot.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { execFile } from 'node:child_process';
|
|
2
|
-
import { existsSync, mkdirSync } from 'node:fs';
|
|
1
|
+
import { spawn, execFile } from 'node:child_process';
|
|
2
|
+
import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { homedir, platform } from 'node:os';
|
|
5
|
-
|
|
5
|
+
import { get as httpGet } from 'node:http';
|
|
6
|
+
export const SCREENSHOTS_DIR = join(homedir(), '.config', 'heyiam', 'screenshots');
|
|
6
7
|
/** Known Chrome binary paths by platform */
|
|
7
8
|
const CHROME_PATHS = {
|
|
8
9
|
darwin: [
|
|
@@ -35,15 +36,98 @@ export function findChrome() {
|
|
|
35
36
|
return null;
|
|
36
37
|
}
|
|
37
38
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
39
|
+
* Validate that a URL is safe for screenshot capture.
|
|
40
|
+
* Only allows http/https schemes and rejects private/internal IPs.
|
|
40
41
|
*/
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
function isUrlSafe(raw) {
|
|
43
|
+
let parsed;
|
|
44
|
+
try {
|
|
45
|
+
parsed = new URL(raw);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
// Only allow http(s)
|
|
51
|
+
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:')
|
|
52
|
+
return false;
|
|
53
|
+
// Reject localhost and private IPs
|
|
54
|
+
const host = parsed.hostname.toLowerCase();
|
|
55
|
+
if (host === 'localhost' || host === '127.0.0.1' || host === '::1') {
|
|
56
|
+
// Allow our own preview server
|
|
57
|
+
const port = parsed.port || (parsed.protocol === 'https:' ? '443' : '80');
|
|
58
|
+
if (port !== '17845')
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
// Reject private IP ranges
|
|
62
|
+
if (/^(10\.|172\.(1[6-9]|2\d|3[01])\.|192\.168\.|169\.254\.|0\.)/.test(host))
|
|
63
|
+
return false;
|
|
64
|
+
if (host.endsWith('.local') || host.endsWith('.internal'))
|
|
65
|
+
return false;
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Sanitize a slug for use as a filename — alphanumeric, hyphens, underscores only.
|
|
70
|
+
*/
|
|
71
|
+
function sanitizeSlug(slug) {
|
|
72
|
+
return slug.replace(/[^a-zA-Z0-9_-]/g, '_').slice(0, 200);
|
|
73
|
+
}
|
|
74
|
+
/** Send a CDP command over WebSocket and wait for the response */
|
|
75
|
+
function cdpSend(ws, method, params = {}) {
|
|
76
|
+
const id = Math.floor(Math.random() * 1e9);
|
|
77
|
+
return new Promise((resolve, reject) => {
|
|
78
|
+
const timeout = setTimeout(() => reject(new Error(`CDP timeout: ${method}`)), 15_000);
|
|
79
|
+
const handler = (event) => {
|
|
80
|
+
const msg = JSON.parse(String(event.data));
|
|
81
|
+
if (msg.id === id) {
|
|
82
|
+
ws.removeEventListener('message', handler);
|
|
83
|
+
clearTimeout(timeout);
|
|
84
|
+
if (msg.error)
|
|
85
|
+
reject(new Error(msg.error.message));
|
|
86
|
+
else
|
|
87
|
+
resolve(msg.result ?? {});
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
ws.addEventListener('message', handler);
|
|
91
|
+
ws.send(JSON.stringify({ id, method, params }));
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
/** Wait for a specific CDP event */
|
|
95
|
+
function cdpWaitFor(ws, eventName, timeoutMs = 15_000) {
|
|
96
|
+
return new Promise((resolve, reject) => {
|
|
97
|
+
const timeout = setTimeout(() => reject(new Error(`CDP event timeout: ${eventName}`)), timeoutMs);
|
|
98
|
+
const handler = (event) => {
|
|
99
|
+
const msg = JSON.parse(String(event.data));
|
|
100
|
+
if (msg.method === eventName) {
|
|
101
|
+
ws.removeEventListener('message', handler);
|
|
102
|
+
clearTimeout(timeout);
|
|
103
|
+
resolve();
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
ws.addEventListener('message', handler);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
/** Fetch JSON from a local HTTP endpoint */
|
|
110
|
+
function fetchJson(url) {
|
|
111
|
+
return new Promise((resolve, reject) => {
|
|
112
|
+
httpGet(url, (res) => {
|
|
113
|
+
let data = '';
|
|
114
|
+
res.on('data', (chunk) => { data += chunk.toString(); });
|
|
115
|
+
res.on('end', () => {
|
|
116
|
+
try {
|
|
117
|
+
resolve(JSON.parse(data));
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
reject(new Error('Invalid JSON'));
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}).on('error', reject);
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Fallback: capture using Chrome CLI --screenshot (viewport-only, not full page).
|
|
128
|
+
* Used when WebSocket is unavailable (Node < 22).
|
|
129
|
+
*/
|
|
130
|
+
async function captureScreenshotFallback(chrome, url, outPath) {
|
|
47
131
|
try {
|
|
48
132
|
await new Promise((resolve, reject) => {
|
|
49
133
|
execFile(chrome, [
|
|
@@ -69,12 +153,102 @@ export async function captureScreenshot(url, slug) {
|
|
|
69
153
|
resolve();
|
|
70
154
|
});
|
|
71
155
|
});
|
|
72
|
-
|
|
73
|
-
|
|
156
|
+
return existsSync(outPath) ? outPath : null;
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Capture a full-page screenshot using Chrome DevTools Protocol.
|
|
164
|
+
* Uses Page.getLayoutMetrics for exact content height, then
|
|
165
|
+
* Page.captureScreenshot with captureBeyondViewport for a full capture.
|
|
166
|
+
* Falls back to CLI --screenshot on Node < 22 (no built-in WebSocket).
|
|
167
|
+
*/
|
|
168
|
+
export async function captureScreenshot(url, slug) {
|
|
169
|
+
if (!isUrlSafe(url))
|
|
170
|
+
return null;
|
|
171
|
+
const chrome = findChrome();
|
|
172
|
+
if (!chrome)
|
|
74
173
|
return null;
|
|
174
|
+
mkdirSync(SCREENSHOTS_DIR, { recursive: true });
|
|
175
|
+
const safeSlug = sanitizeSlug(slug);
|
|
176
|
+
const outPath = join(SCREENSHOTS_DIR, `${safeSlug}.png`);
|
|
177
|
+
// Fall back to CLI --screenshot if WebSocket is unavailable (Node < 22)
|
|
178
|
+
if (typeof globalThis.WebSocket === 'undefined') {
|
|
179
|
+
return captureScreenshotFallback(chrome, url, outPath);
|
|
180
|
+
}
|
|
181
|
+
// Launch Chrome with remote debugging on auto-assigned port
|
|
182
|
+
const proc = spawn(chrome, [
|
|
183
|
+
'--headless=new',
|
|
184
|
+
'--disable-gpu',
|
|
185
|
+
'--no-sandbox',
|
|
186
|
+
'--disable-software-rasterizer',
|
|
187
|
+
'--window-size=1280,800',
|
|
188
|
+
'--hide-scrollbars',
|
|
189
|
+
'--disable-extensions',
|
|
190
|
+
'--disable-background-networking',
|
|
191
|
+
'--disable-sync',
|
|
192
|
+
'--disable-translate',
|
|
193
|
+
'--disable-default-apps',
|
|
194
|
+
'--mute-audio',
|
|
195
|
+
'--no-first-run',
|
|
196
|
+
'--remote-debugging-port=0',
|
|
197
|
+
'about:blank',
|
|
198
|
+
], { stdio: ['ignore', 'ignore', 'pipe'] });
|
|
199
|
+
try {
|
|
200
|
+
// Parse the debug port from Chrome's stderr
|
|
201
|
+
const port = await new Promise((resolve, reject) => {
|
|
202
|
+
const timeout = setTimeout(() => reject(new Error('Chrome startup timeout')), 10_000);
|
|
203
|
+
let stderr = '';
|
|
204
|
+
proc.stderr.on('data', (chunk) => {
|
|
205
|
+
stderr += chunk.toString();
|
|
206
|
+
const match = stderr.match(/DevTools listening on ws:\/\/127\.0\.0\.1:(\d+)\//);
|
|
207
|
+
if (match) {
|
|
208
|
+
clearTimeout(timeout);
|
|
209
|
+
resolve(parseInt(match[1], 10));
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
proc.on('exit', () => { clearTimeout(timeout); reject(new Error('Chrome exited early')); });
|
|
213
|
+
});
|
|
214
|
+
// Find the page target's WebSocket URL
|
|
215
|
+
const targets = await fetchJson(`http://127.0.0.1:${port}/json/list`);
|
|
216
|
+
const pageTarget = targets.find((t) => t.type === 'page');
|
|
217
|
+
if (!pageTarget)
|
|
218
|
+
throw new Error('No page target found');
|
|
219
|
+
// Connect via CDP
|
|
220
|
+
const ws = new WebSocket(pageTarget.webSocketDebuggerUrl);
|
|
221
|
+
await new Promise((resolve, reject) => {
|
|
222
|
+
ws.addEventListener('open', () => resolve());
|
|
223
|
+
ws.addEventListener('error', () => reject(new Error('WebSocket connection failed')));
|
|
224
|
+
});
|
|
225
|
+
// Enable Page events and navigate
|
|
226
|
+
await cdpSend(ws, 'Page.enable');
|
|
227
|
+
const loadPromise = cdpWaitFor(ws, 'Page.loadEventFired', 20_000);
|
|
228
|
+
await cdpSend(ws, 'Page.navigate', { url });
|
|
229
|
+
await loadPromise;
|
|
230
|
+
// Small delay for lazy-loaded content / animations
|
|
231
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
232
|
+
// Get the actual content dimensions
|
|
233
|
+
const metrics = await cdpSend(ws, 'Page.getLayoutMetrics');
|
|
234
|
+
const width = 1280;
|
|
235
|
+
const height = Math.min(Math.ceil(metrics.contentSize.height), 10_000); // cap at 10k px
|
|
236
|
+
// Capture full-page screenshot
|
|
237
|
+
const result = await cdpSend(ws, 'Page.captureScreenshot', {
|
|
238
|
+
format: 'png',
|
|
239
|
+
captureBeyondViewport: true,
|
|
240
|
+
clip: { x: 0, y: 0, width, height, scale: 1 },
|
|
241
|
+
});
|
|
242
|
+
// Write to disk
|
|
243
|
+
writeFileSync(outPath, Buffer.from(result.data, 'base64'));
|
|
244
|
+
ws.close();
|
|
245
|
+
return outPath;
|
|
75
246
|
}
|
|
76
247
|
catch {
|
|
77
248
|
return null;
|
|
78
249
|
}
|
|
250
|
+
finally {
|
|
251
|
+
proc.kill();
|
|
252
|
+
}
|
|
79
253
|
}
|
|
80
254
|
//# sourceMappingURL=screenshot.js.map
|
package/dist/screenshot.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../src/screenshot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../src/screenshot.ts"],"names":[],"mappings":"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"}
|
package/dist/search.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type Database from 'better-sqlite3';
|
|
2
|
+
export interface SearchFilters {
|
|
3
|
+
project?: string;
|
|
4
|
+
source?: string;
|
|
5
|
+
after?: string;
|
|
6
|
+
before?: string;
|
|
7
|
+
skill?: string;
|
|
8
|
+
file?: string;
|
|
9
|
+
minDuration?: number;
|
|
10
|
+
}
|
|
11
|
+
export interface SearchResult {
|
|
12
|
+
sessionId: string;
|
|
13
|
+
title: string;
|
|
14
|
+
projectDir: string;
|
|
15
|
+
projectName: string;
|
|
16
|
+
source: string;
|
|
17
|
+
date: string;
|
|
18
|
+
durationMinutes: number;
|
|
19
|
+
turns: number;
|
|
20
|
+
linesOfCode: number;
|
|
21
|
+
skills: string[];
|
|
22
|
+
snippet: string;
|
|
23
|
+
score: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Decode projectDir to a human-readable project name.
|
|
27
|
+
* e.g. "-Users-test-Dev-myapp" → "Users/test/Dev/myapp"
|
|
28
|
+
*/
|
|
29
|
+
export declare function decodeProjectName(projectDir: string): string;
|
|
30
|
+
export declare function searchSessions(db: Database.Database, query?: string, filters?: SearchFilters): SearchResult[];
|
package/dist/search.js
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
// Search logic combining FTS5 content search with metadata filters
|
|
2
|
+
import { searchFts } from './db.js';
|
|
3
|
+
// ── Helpers ──────────────────────────────────────────────────
|
|
4
|
+
/**
|
|
5
|
+
* Decode projectDir to a human-readable project name.
|
|
6
|
+
* e.g. "-Users-test-Dev-myapp" → "Users/test/Dev/myapp"
|
|
7
|
+
*/
|
|
8
|
+
export function decodeProjectName(projectDir) {
|
|
9
|
+
return projectDir.replace(/^-/, '').replace(/-/g, '/');
|
|
10
|
+
}
|
|
11
|
+
function rowToResult(row, snippet, score) {
|
|
12
|
+
const skills = row.skills ? JSON.parse(row.skills) : [];
|
|
13
|
+
return {
|
|
14
|
+
sessionId: row.id,
|
|
15
|
+
title: row.title ?? '',
|
|
16
|
+
projectDir: row.project_dir,
|
|
17
|
+
projectName: decodeProjectName(row.project_dir),
|
|
18
|
+
source: row.source,
|
|
19
|
+
date: row.start_time ?? '',
|
|
20
|
+
durationMinutes: row.duration_minutes ?? 0,
|
|
21
|
+
turns: row.turns ?? 0,
|
|
22
|
+
linesOfCode: (row.loc_added ?? 0) + (row.loc_removed ?? 0),
|
|
23
|
+
skills,
|
|
24
|
+
snippet,
|
|
25
|
+
score,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
// ── Main Search Function ─────────────────────────────────────
|
|
29
|
+
const MAX_RESULTS = 50;
|
|
30
|
+
export function searchSessions(db, query, filters) {
|
|
31
|
+
if (query) {
|
|
32
|
+
return searchWithFts(db, query, filters);
|
|
33
|
+
}
|
|
34
|
+
return searchWithFilters(db, filters);
|
|
35
|
+
}
|
|
36
|
+
// ── FTS path: query provided ─────────────────────────────────
|
|
37
|
+
function searchWithFts(db, query, filters) {
|
|
38
|
+
// FTS now returns deduplicated results (one per session, best rank)
|
|
39
|
+
const ftsResults = searchFts(db, query, MAX_RESULTS * 3);
|
|
40
|
+
if (ftsResults.length === 0)
|
|
41
|
+
return [];
|
|
42
|
+
const fileSessionIds = filters?.file ? getFileFilteredSessionIds(db, filters.file) : null;
|
|
43
|
+
// F10: Batch fetch all session rows in one query instead of N+1
|
|
44
|
+
const ftsIds = ftsResults.map((r) => r.sessionId);
|
|
45
|
+
const placeholders = ftsIds.map(() => '?').join(',');
|
|
46
|
+
const allRows = db.prepare(`SELECT * FROM sessions WHERE id IN (${placeholders})`).all(...ftsIds);
|
|
47
|
+
const rowMap = new Map();
|
|
48
|
+
for (const row of allRows)
|
|
49
|
+
rowMap.set(row.id, row);
|
|
50
|
+
// Apply metadata filters and build results in FTS rank order
|
|
51
|
+
const results = [];
|
|
52
|
+
for (const fts of ftsResults) {
|
|
53
|
+
if (fileSessionIds && !fileSessionIds.has(fts.sessionId))
|
|
54
|
+
continue;
|
|
55
|
+
const row = rowMap.get(fts.sessionId);
|
|
56
|
+
if (!row)
|
|
57
|
+
continue;
|
|
58
|
+
if (!matchesFilters(row, filters))
|
|
59
|
+
continue;
|
|
60
|
+
results.push(rowToResult(row, fts.snippet, fts.rank));
|
|
61
|
+
if (results.length >= MAX_RESULTS)
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
return results;
|
|
65
|
+
}
|
|
66
|
+
// ── Filter-only path: no text query ──────────────────────────
|
|
67
|
+
function searchWithFilters(db, filters) {
|
|
68
|
+
const conditions = [];
|
|
69
|
+
const params = [];
|
|
70
|
+
if (filters?.project) {
|
|
71
|
+
conditions.push('s.project_dir LIKE ?');
|
|
72
|
+
params.push(`%${filters.project}%`);
|
|
73
|
+
}
|
|
74
|
+
if (filters?.source) {
|
|
75
|
+
conditions.push('s.source = ?');
|
|
76
|
+
params.push(filters.source);
|
|
77
|
+
}
|
|
78
|
+
if (filters?.after) {
|
|
79
|
+
conditions.push('s.start_time >= ?');
|
|
80
|
+
params.push(filters.after);
|
|
81
|
+
}
|
|
82
|
+
if (filters?.before) {
|
|
83
|
+
conditions.push('s.start_time <= ?');
|
|
84
|
+
params.push(filters.before);
|
|
85
|
+
}
|
|
86
|
+
if (filters?.minDuration) {
|
|
87
|
+
conditions.push('s.duration_minutes >= ?');
|
|
88
|
+
params.push(filters.minDuration);
|
|
89
|
+
}
|
|
90
|
+
if (filters?.skill) {
|
|
91
|
+
// F25: Use json_each for proper JSON array searching instead of LIKE
|
|
92
|
+
conditions.push('EXISTS (SELECT 1 FROM json_each(s.skills) WHERE value = ?)');
|
|
93
|
+
params.push(filters.skill);
|
|
94
|
+
}
|
|
95
|
+
let sql;
|
|
96
|
+
if (filters?.file) {
|
|
97
|
+
sql = `
|
|
98
|
+
SELECT DISTINCT s.*
|
|
99
|
+
FROM sessions s
|
|
100
|
+
JOIN session_files sf ON sf.session_id = s.id
|
|
101
|
+
WHERE sf.file_path LIKE ?
|
|
102
|
+
${conditions.length ? 'AND ' + conditions.join(' AND ') : ''}
|
|
103
|
+
ORDER BY s.start_time DESC
|
|
104
|
+
LIMIT ?
|
|
105
|
+
`;
|
|
106
|
+
params.unshift(`%${filters.file}%`);
|
|
107
|
+
params.push(MAX_RESULTS);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
sql = `
|
|
111
|
+
SELECT s.*
|
|
112
|
+
FROM sessions s
|
|
113
|
+
${conditions.length ? 'WHERE ' + conditions.join(' AND ') : ''}
|
|
114
|
+
ORDER BY s.start_time DESC
|
|
115
|
+
LIMIT ?
|
|
116
|
+
`;
|
|
117
|
+
params.push(MAX_RESULTS);
|
|
118
|
+
}
|
|
119
|
+
const rows = db.prepare(sql).all(...params);
|
|
120
|
+
return rows.map((row, i) => rowToResult(row, '', i));
|
|
121
|
+
}
|
|
122
|
+
// ── Filter helpers ───────────────────────────────────────────
|
|
123
|
+
function matchesFilters(row, filters) {
|
|
124
|
+
if (!filters)
|
|
125
|
+
return true;
|
|
126
|
+
if (filters.project && !row.project_dir.includes(filters.project)) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
if (filters.source && row.source !== filters.source) {
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
if (filters.after && (row.start_time ?? '') < filters.after) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
if (filters.before && (row.start_time ?? '') > filters.before) {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
if (filters.minDuration && (row.duration_minutes ?? 0) < filters.minDuration) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
if (filters.skill) {
|
|
142
|
+
const skills = row.skills ? JSON.parse(row.skills) : [];
|
|
143
|
+
if (!skills.includes(filters.skill)) {
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
function getFileFilteredSessionIds(db, filePath) {
|
|
150
|
+
const rows = db.prepare('SELECT DISTINCT session_id FROM session_files WHERE file_path LIKE ?').all(`%${filePath}%`);
|
|
151
|
+
return new Set(rows.map((r) => r.session_id));
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { Server } from 'node:http';
|
|
2
|
-
export declare function createApp(sessionsBasePath?: string): import("express-serve-static-core").Express;
|
|
2
|
+
export declare function createApp(sessionsBasePath?: string, dbPath?: string): import("express-serve-static-core").Express;
|
|
3
3
|
export declare function startServer(port?: number): Promise<Server>;
|