markdown-markdown 0.2.0
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/AGENT.md +47 -0
- package/LICENSE +21 -0
- package/README.md +110 -0
- package/dist/cli.d.ts +13 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +308 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/lifecycle.d.ts +18 -0
- package/dist/lib/lifecycle.d.ts.map +1 -0
- package/dist/lib/lifecycle.js +48 -0
- package/dist/lib/lifecycle.js.map +1 -0
- package/dist/lib/review.d.ts +27 -0
- package/dist/lib/review.d.ts.map +1 -0
- package/dist/lib/review.js +124 -0
- package/dist/lib/review.js.map +1 -0
- package/dist/lib/utils.d.ts +3 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +6 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/server/browser.d.ts +13 -0
- package/dist/server/browser.d.ts.map +1 -0
- package/dist/server/browser.js +135 -0
- package/dist/server/browser.js.map +1 -0
- package/dist/server/runtime.d.ts +15 -0
- package/dist/server/runtime.d.ts.map +1 -0
- package/dist/server/runtime.js +69 -0
- package/dist/server/runtime.js.map +1 -0
- package/dist/server/session.d.ts +12 -0
- package/dist/server/session.d.ts.map +1 -0
- package/dist/server/session.js +61 -0
- package/dist/server/session.js.map +1 -0
- package/dist/server/tunnel.d.ts +13 -0
- package/dist/server/tunnel.d.ts.map +1 -0
- package/dist/server/tunnel.js +131 -0
- package/dist/server/tunnel.js.map +1 -0
- package/dist/types.d.ts +64 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/web/assets/_baseUniq-DWSAgCYE.js +1 -0
- package/dist/web/assets/arc-BLgyBygL.js +1 -0
- package/dist/web/assets/architectureDiagram-Q4EWVU46-WgZ5UMvM.js +36 -0
- package/dist/web/assets/blockDiagram-DXYQGD6D-CLfiyr9S.js +132 -0
- package/dist/web/assets/c4Diagram-AHTNJAMY-DetWrVzN.js +10 -0
- package/dist/web/assets/channel-B52zE7C-.js +1 -0
- package/dist/web/assets/chunk-4BX2VUAB-CwFW4HRp.js +1 -0
- package/dist/web/assets/chunk-4TB4RGXK-jdkxDJTI.js +206 -0
- package/dist/web/assets/chunk-55IACEB6-LHLQ9Mhr.js +1 -0
- package/dist/web/assets/chunk-EDXVE4YY-gXBG7iiV.js +1 -0
- package/dist/web/assets/chunk-FMBD7UC4-D0c2ufl0.js +15 -0
- package/dist/web/assets/chunk-OYMX7WX6-Cam5t0AC.js +231 -0
- package/dist/web/assets/chunk-QZHKN3VN-VDTy7PR1.js +1 -0
- package/dist/web/assets/chunk-YZCP3GAM-DDQlY4hF.js +1 -0
- package/dist/web/assets/classDiagram-6PBFFD2Q-Bn5mNtvt.js +1 -0
- package/dist/web/assets/classDiagram-v2-HSJHXN6E-Bn5mNtvt.js +1 -0
- package/dist/web/assets/clone-CWdO33LD.js +1 -0
- package/dist/web/assets/cose-bilkent-S5V4N54A-CydpJVOO.js +1 -0
- package/dist/web/assets/cytoscape.esm-DxGcaOPV.js +331 -0
- package/dist/web/assets/dagre-KV5264BT-DfWRqVQs.js +4 -0
- package/dist/web/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/dist/web/assets/diagram-5BDNPKRD-DYocjsGb.js +10 -0
- package/dist/web/assets/diagram-G4DWMVQ6-BwxP9kS5.js +24 -0
- package/dist/web/assets/diagram-MMDJMWI5-BmV1mUfz.js +43 -0
- package/dist/web/assets/diagram-TYMM5635-DMUZyCDV.js +24 -0
- package/dist/web/assets/erDiagram-SMLLAGMA-CDgJ2VS3.js +85 -0
- package/dist/web/assets/flowDiagram-DWJPFMVM-aLxzOWpe.js +162 -0
- package/dist/web/assets/ganttDiagram-T4ZO3ILL-ct-v0U4O.js +292 -0
- package/dist/web/assets/gitGraphDiagram-UUTBAWPF-DJ-FLYU_.js +106 -0
- package/dist/web/assets/graph-DUCnU9ms.js +1 -0
- package/dist/web/assets/index-D7013kRO.js +492 -0
- package/dist/web/assets/index-Lxs7QZQJ.css +1 -0
- package/dist/web/assets/infoDiagram-42DDH7IO-DmMBz9mk.js +2 -0
- package/dist/web/assets/init-Gi6I4Gst.js +1 -0
- package/dist/web/assets/ishikawaDiagram-UXIWVN3A-D-dfZT_7.js +70 -0
- package/dist/web/assets/journeyDiagram-VCZTEJTY-DCLyO8ny.js +139 -0
- package/dist/web/assets/kanban-definition-6JOO6SKY-DaSer7-n.js +89 -0
- package/dist/web/assets/katex-DkKDou_j.js +257 -0
- package/dist/web/assets/layout-BaZRT940.js +1 -0
- package/dist/web/assets/linear-CH1vCRmv.js +1 -0
- package/dist/web/assets/min-C200fz71.js +1 -0
- package/dist/web/assets/mindmap-definition-QFDTVHPH-CCqZjE9I.js +96 -0
- package/dist/web/assets/ordinal-Cboi1Yqb.js +1 -0
- package/dist/web/assets/pieDiagram-DEJITSTG-Beh4XRu6.js +30 -0
- package/dist/web/assets/quadrantDiagram-34T5L4WZ-DOPc33qF.js +7 -0
- package/dist/web/assets/requirementDiagram-MS252O5E-DwblBLZK.js +84 -0
- package/dist/web/assets/sankeyDiagram-XADWPNL6-DlMTDWAl.js +10 -0
- package/dist/web/assets/sequenceDiagram-FGHM5R23-CPvNK8NS.js +157 -0
- package/dist/web/assets/stateDiagram-FHFEXIEX-C51anF0K.js +1 -0
- package/dist/web/assets/stateDiagram-v2-QKLJ7IA2-DgIcCuV2.js +1 -0
- package/dist/web/assets/timeline-definition-GMOUNBTQ-B0M6txNM.js +120 -0
- package/dist/web/assets/vennDiagram-DHZGUBPP-DuNg6iKA.js +34 -0
- package/dist/web/assets/wardley-RL74JXVD-CnLmvQxW.js +162 -0
- package/dist/web/assets/wardleyDiagram-NUSXRM2D-DVMWnQbQ.js +20 -0
- package/dist/web/assets/xychartDiagram-5P7HB3ND-Cec8luZO.js +7 -0
- package/dist/web/index.html +14 -0
- package/package.json +67 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
function normalizeWhitespace(text) {
|
|
2
|
+
return text.replace(/\s+/g, ' ').trim();
|
|
3
|
+
}
|
|
4
|
+
function escapeForQuotes(text) {
|
|
5
|
+
return text.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
6
|
+
}
|
|
7
|
+
function truncateMiddle(text, maxLength) {
|
|
8
|
+
const compact = normalizeWhitespace(text);
|
|
9
|
+
if (compact.length <= maxLength) {
|
|
10
|
+
return compact;
|
|
11
|
+
}
|
|
12
|
+
const headLength = Math.max(18, Math.floor(maxLength * 0.6));
|
|
13
|
+
const tailLength = Math.max(10, maxLength - headLength - 1);
|
|
14
|
+
return `${compact.slice(0, headLength).trimEnd()}…${compact.slice(-tailLength).trimStart()}`;
|
|
15
|
+
}
|
|
16
|
+
function getMeaningfulLines(selectedText) {
|
|
17
|
+
return selectedText
|
|
18
|
+
.split('\n')
|
|
19
|
+
.map((line) => line.trim())
|
|
20
|
+
.filter((line) => line.length > 0);
|
|
21
|
+
}
|
|
22
|
+
function classifySelectedText(selectedText) {
|
|
23
|
+
const lines = getMeaningfulLines(selectedText);
|
|
24
|
+
const firstLine = lines[0] ?? '';
|
|
25
|
+
if (/^```/.test(firstLine)) {
|
|
26
|
+
return 'code block';
|
|
27
|
+
}
|
|
28
|
+
if (/^!\[[^\]]*\]\(/.test(firstLine)) {
|
|
29
|
+
return 'image';
|
|
30
|
+
}
|
|
31
|
+
if (/^#{1,6}\s/.test(firstLine)) {
|
|
32
|
+
return 'heading';
|
|
33
|
+
}
|
|
34
|
+
if (/^>\s?/.test(firstLine)) {
|
|
35
|
+
return 'blockquote';
|
|
36
|
+
}
|
|
37
|
+
if (/^([-*+]\s|\d+[.)]\s)/.test(firstLine)) {
|
|
38
|
+
return 'list item';
|
|
39
|
+
}
|
|
40
|
+
if (/^\s*[-*_]{3,}\s*$/.test(firstLine)) {
|
|
41
|
+
return 'separator';
|
|
42
|
+
}
|
|
43
|
+
if (lines.length >= 2 && lines.every((line) => line.includes('|'))) {
|
|
44
|
+
return 'table';
|
|
45
|
+
}
|
|
46
|
+
return 'paragraph';
|
|
47
|
+
}
|
|
48
|
+
function formatSnippet(selectedText, kind) {
|
|
49
|
+
const lines = getMeaningfulLines(selectedText);
|
|
50
|
+
if (lines.length === 0) {
|
|
51
|
+
return '';
|
|
52
|
+
}
|
|
53
|
+
if (kind === 'image') {
|
|
54
|
+
const altMatch = lines[0].match(/!\[([^\]]*)\]/);
|
|
55
|
+
if (altMatch?.[1]) {
|
|
56
|
+
return `image alt: "${escapeForQuotes(truncateMiddle(altMatch[1], 48))}"`;
|
|
57
|
+
}
|
|
58
|
+
return truncateMiddle(lines[0], 48);
|
|
59
|
+
}
|
|
60
|
+
if (kind === 'separator') {
|
|
61
|
+
return truncateMiddle(lines[0], 24);
|
|
62
|
+
}
|
|
63
|
+
if (kind === 'code block') {
|
|
64
|
+
const bodyLines = lines.filter((line) => !/^```/.test(line));
|
|
65
|
+
const firstLine = bodyLines[0] ?? lines[0];
|
|
66
|
+
const lastLine = bodyLines[bodyLines.length - 1] ?? firstLine;
|
|
67
|
+
if (bodyLines.length <= 1 || firstLine === lastLine) {
|
|
68
|
+
return truncateMiddle(firstLine, 44);
|
|
69
|
+
}
|
|
70
|
+
return `${truncateMiddle(firstLine, 34)} … ${truncateMiddle(lastLine, 34)}`;
|
|
71
|
+
}
|
|
72
|
+
if (kind === 'table') {
|
|
73
|
+
const firstRow = lines[0];
|
|
74
|
+
const lastRow = lines[lines.length - 1];
|
|
75
|
+
if (firstRow === lastRow) {
|
|
76
|
+
return truncateMiddle(firstRow, 48);
|
|
77
|
+
}
|
|
78
|
+
return `${truncateMiddle(firstRow, 34)} … ${truncateMiddle(lastRow, 34)}`;
|
|
79
|
+
}
|
|
80
|
+
if (kind === 'heading' || kind === 'blockquote' || kind === 'list item') {
|
|
81
|
+
const firstLine = lines[0];
|
|
82
|
+
const lastLine = lines[lines.length - 1];
|
|
83
|
+
if (firstLine === lastLine) {
|
|
84
|
+
return truncateMiddle(firstLine, 46);
|
|
85
|
+
}
|
|
86
|
+
return `${truncateMiddle(firstLine, 34)} … ${truncateMiddle(lastLine, 34)}`;
|
|
87
|
+
}
|
|
88
|
+
const firstLine = lines[0];
|
|
89
|
+
const lastLine = lines[lines.length - 1];
|
|
90
|
+
if (firstLine === lastLine) {
|
|
91
|
+
return truncateMiddle(firstLine, 48);
|
|
92
|
+
}
|
|
93
|
+
return `${truncateMiddle(firstLine, 34)} … ${truncateMiddle(lastLine, 34)}`;
|
|
94
|
+
}
|
|
95
|
+
export function buildReviewPrompt({ rootPath, files, annotations }) {
|
|
96
|
+
const sections = files
|
|
97
|
+
.map((file) => {
|
|
98
|
+
const fileAnnotations = annotations.filter((annotation) => annotation.filePath === file.relativePath);
|
|
99
|
+
if (fileAnnotations.length === 0) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
const lines = [`## ${file.relativePath} (${fileAnnotations.length} notes)`];
|
|
103
|
+
for (const annotation of fileAnnotations) {
|
|
104
|
+
const kind = classifySelectedText(annotation.selectedText);
|
|
105
|
+
const snippet = formatSnippet(annotation.selectedText, kind);
|
|
106
|
+
const note = annotation.note.trim();
|
|
107
|
+
const detail = snippet ? ` · anchor: "${escapeForQuotes(snippet)}"` : '';
|
|
108
|
+
lines.push(`- L${annotation.selection.startLine}-L${annotation.selection.endLine} · ${kind}${detail} -> ${note}`);
|
|
109
|
+
}
|
|
110
|
+
return lines.join('\n');
|
|
111
|
+
})
|
|
112
|
+
.filter((section) => Boolean(section));
|
|
113
|
+
const header = [
|
|
114
|
+
`Review notes for ${rootPath}`,
|
|
115
|
+
'',
|
|
116
|
+
'Use the file path, line range, and short anchor text to update the markdown files. Keep edits surgical.',
|
|
117
|
+
'',
|
|
118
|
+
];
|
|
119
|
+
if (sections.length === 0) {
|
|
120
|
+
return [...header, 'No annotations were submitted.'].join('\n');
|
|
121
|
+
}
|
|
122
|
+
return [...header, ...sections].join('\n');
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=review.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review.js","sourceRoot":"","sources":["../../src/lib/review.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,UAAU,EAAE,MAAM,MAAM,CAAC;AAG7C,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,UAEzC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAmB,MAAM,MAAM,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC,MAAM,UAAU,EAAE,CAAC,GAAG,MAAoB;IACxC,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ChildProcess } from 'node:child_process';
|
|
2
|
+
export interface BrowserHandle {
|
|
3
|
+
process: ChildProcess | null;
|
|
4
|
+
browserName: string;
|
|
5
|
+
userDataDir: string | null;
|
|
6
|
+
close: () => Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
export interface LaunchBrowserOptions {
|
|
9
|
+
executableCandidates?: string[];
|
|
10
|
+
allowSystemFallback?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare function launchBrowser(url: string, options?: LaunchBrowserOptions): Promise<BrowserHandle>;
|
|
13
|
+
//# sourceMappingURL=browser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/server/browser.ts"],"names":[],"mappings":"AAEA,OAAO,EAAoB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAIzE,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACnC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AA8ED,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,aAAa,CAAC,CAsE3G"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { mkdtempSync, rmSync } from 'node:fs';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { spawn, spawnSync } from 'node:child_process';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
const BROWSER_CANDIDATES = {
|
|
7
|
+
darwin: [
|
|
8
|
+
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
|
|
9
|
+
'/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge',
|
|
10
|
+
'/Applications/Chromium.app/Contents/MacOS/Chromium',
|
|
11
|
+
'google-chrome',
|
|
12
|
+
'google-chrome-stable',
|
|
13
|
+
'chromium',
|
|
14
|
+
'chromium-browser',
|
|
15
|
+
'microsoft-edge',
|
|
16
|
+
],
|
|
17
|
+
linux: [
|
|
18
|
+
'google-chrome',
|
|
19
|
+
'google-chrome-stable',
|
|
20
|
+
'chromium',
|
|
21
|
+
'chromium-browser',
|
|
22
|
+
'microsoft-edge',
|
|
23
|
+
'brave-browser',
|
|
24
|
+
],
|
|
25
|
+
win32: [
|
|
26
|
+
'chrome.exe',
|
|
27
|
+
'msedge.exe',
|
|
28
|
+
'chromium.exe',
|
|
29
|
+
],
|
|
30
|
+
aix: [],
|
|
31
|
+
android: [],
|
|
32
|
+
freebsd: [],
|
|
33
|
+
haiku: [],
|
|
34
|
+
illumos: [],
|
|
35
|
+
netbsd: [],
|
|
36
|
+
openbsd: [],
|
|
37
|
+
sunos: [],
|
|
38
|
+
};
|
|
39
|
+
function commandExists(command) {
|
|
40
|
+
if (path.isAbsolute(command)) {
|
|
41
|
+
return existsSync(command);
|
|
42
|
+
}
|
|
43
|
+
const result = spawnSync(command, ['--version'], { stdio: 'ignore' });
|
|
44
|
+
return result.status === 0 || result.status === 1;
|
|
45
|
+
}
|
|
46
|
+
function pickBrowserExecutable() {
|
|
47
|
+
for (const candidate of BROWSER_CANDIDATES[process.platform] ?? []) {
|
|
48
|
+
if (commandExists(candidate)) {
|
|
49
|
+
return candidate;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
async function killBrowserProcess(processHandle) {
|
|
55
|
+
if (!processHandle?.pid) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (process.platform === 'win32') {
|
|
59
|
+
spawnSync('taskkill', ['/pid', String(processHandle.pid), '/t', '/f'], {
|
|
60
|
+
stdio: 'ignore',
|
|
61
|
+
});
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
process.kill(-processHandle.pid, 'SIGTERM');
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
try {
|
|
69
|
+
processHandle.kill('SIGTERM');
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// Ignore shutdown errors; we already tried the best-effort path.
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
export async function launchBrowser(url, options = {}) {
|
|
77
|
+
const executable = options.executableCandidates
|
|
78
|
+
? options.executableCandidates.find((candidate) => commandExists(candidate)) ?? null
|
|
79
|
+
: pickBrowserExecutable();
|
|
80
|
+
if (!executable) {
|
|
81
|
+
if (options.allowSystemFallback === false) {
|
|
82
|
+
throw new Error('No supported browser launcher was found on this system.');
|
|
83
|
+
}
|
|
84
|
+
if (process.platform === 'darwin' && commandExists('open')) {
|
|
85
|
+
spawn('open', [url], { stdio: 'ignore', detached: true }).unref();
|
|
86
|
+
return {
|
|
87
|
+
process: null,
|
|
88
|
+
browserName: 'system-default',
|
|
89
|
+
userDataDir: null,
|
|
90
|
+
close: async () => { },
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
if (process.platform === 'win32' && commandExists('cmd')) {
|
|
94
|
+
spawn('cmd', ['/c', 'start', '""', url], { stdio: 'ignore', detached: true }).unref();
|
|
95
|
+
return {
|
|
96
|
+
process: null,
|
|
97
|
+
browserName: 'system-default',
|
|
98
|
+
userDataDir: null,
|
|
99
|
+
close: async () => { },
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
if (commandExists('xdg-open')) {
|
|
103
|
+
spawn('xdg-open', [url], { stdio: 'ignore', detached: true }).unref();
|
|
104
|
+
return {
|
|
105
|
+
process: null,
|
|
106
|
+
browserName: 'system-default',
|
|
107
|
+
userDataDir: null,
|
|
108
|
+
close: async () => { },
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
throw new Error('No supported browser launcher was found on this system.');
|
|
112
|
+
}
|
|
113
|
+
const userDataDir = mkdtempSync(path.join(os.tmpdir(), 'markdown-markdown-browser-'));
|
|
114
|
+
const childProcess = spawn(executable, [
|
|
115
|
+
`--app=${url}`,
|
|
116
|
+
`--user-data-dir=${userDataDir}`,
|
|
117
|
+
'--no-first-run',
|
|
118
|
+
'--disable-extensions',
|
|
119
|
+
'--disable-session-crashed-bubble',
|
|
120
|
+
], {
|
|
121
|
+
detached: true,
|
|
122
|
+
stdio: 'ignore',
|
|
123
|
+
});
|
|
124
|
+
childProcess.unref();
|
|
125
|
+
return {
|
|
126
|
+
process: childProcess,
|
|
127
|
+
browserName: path.basename(executable),
|
|
128
|
+
userDataDir,
|
|
129
|
+
close: async () => {
|
|
130
|
+
await killBrowserProcess(childProcess);
|
|
131
|
+
rmSync(userDataDir, { recursive: true, force: true });
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/server/browser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { MarkdownFile, ReviewSubmissionResult } from '../types.js';
|
|
2
|
+
export interface ReviewRuntimeOptions {
|
|
3
|
+
rootPath: string;
|
|
4
|
+
mode: 'file' | 'directory';
|
|
5
|
+
files: MarkdownFile[];
|
|
6
|
+
staticDir: string;
|
|
7
|
+
}
|
|
8
|
+
export interface ReviewRuntimeHandle {
|
|
9
|
+
port: number;
|
|
10
|
+
url: string;
|
|
11
|
+
result: Promise<ReviewSubmissionResult>;
|
|
12
|
+
close: () => Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
export declare function startReviewRuntime({ rootPath, mode, files, staticDir, }: ReviewRuntimeOptions): Promise<ReviewRuntimeHandle>;
|
|
15
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/server/runtime.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,YAAY,EAGZ,sBAAsB,EACvB,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACxC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAiBD,wBAAsB,kBAAkB,CAAC,EACvC,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,SAAS,GACV,EAAE,oBAAoB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA8DrD"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import { createServer } from 'node:http';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { buildReviewPrompt } from '../lib/review.js';
|
|
5
|
+
function listen(server) {
|
|
6
|
+
return new Promise((resolve, reject) => {
|
|
7
|
+
server.once('error', reject);
|
|
8
|
+
server.listen(0, '127.0.0.1', () => {
|
|
9
|
+
const address = server.address();
|
|
10
|
+
if (typeof address === 'object' && address) {
|
|
11
|
+
resolve(address.port);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
reject(new Error('Unable to determine review server port.'));
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
export async function startReviewRuntime({ rootPath, mode, files, staticDir, }) {
|
|
19
|
+
const app = express();
|
|
20
|
+
app.use(express.json({ limit: '2mb' }));
|
|
21
|
+
const sessionData = {
|
|
22
|
+
rootPath,
|
|
23
|
+
mode,
|
|
24
|
+
files,
|
|
25
|
+
annotations: [],
|
|
26
|
+
};
|
|
27
|
+
let resolvedResult = null;
|
|
28
|
+
let resolveResult = () => { };
|
|
29
|
+
const result = new Promise((resolve) => {
|
|
30
|
+
resolveResult = resolve;
|
|
31
|
+
});
|
|
32
|
+
app.get('/api/session', (_request, response) => {
|
|
33
|
+
response.json(sessionData);
|
|
34
|
+
});
|
|
35
|
+
app.post('/api/submit', (request, response) => {
|
|
36
|
+
if (resolvedResult) {
|
|
37
|
+
response.json(resolvedResult);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const body = request.body;
|
|
41
|
+
const annotations = Array.isArray(body?.annotations) ? body.annotations : [];
|
|
42
|
+
const submittedAt = new Date().toISOString();
|
|
43
|
+
const prompt = buildReviewPrompt({ rootPath, files, annotations });
|
|
44
|
+
resolvedResult = {
|
|
45
|
+
...sessionData,
|
|
46
|
+
annotations,
|
|
47
|
+
prompt,
|
|
48
|
+
submittedAt,
|
|
49
|
+
};
|
|
50
|
+
response.json(resolvedResult);
|
|
51
|
+
resolveResult(resolvedResult);
|
|
52
|
+
});
|
|
53
|
+
app.use(express.static(staticDir));
|
|
54
|
+
app.get('*', (_request, response) => {
|
|
55
|
+
response.sendFile(path.join(staticDir, 'index.html'));
|
|
56
|
+
});
|
|
57
|
+
const server = createServer(app);
|
|
58
|
+
const port = await listen(server);
|
|
59
|
+
const url = `http://127.0.0.1:${port}`;
|
|
60
|
+
return {
|
|
61
|
+
port,
|
|
62
|
+
url,
|
|
63
|
+
result,
|
|
64
|
+
close: () => new Promise((resolve) => {
|
|
65
|
+
server.close(() => resolve());
|
|
66
|
+
}),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/server/runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { buildReviewPrompt } from '../lib/review.js';
|
|
2
|
+
export interface MarkdownSource {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
absolutePath: string;
|
|
6
|
+
relativePath: string;
|
|
7
|
+
content: string;
|
|
8
|
+
lineCount: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function discoverMarkdownFiles(targetPath: string): Promise<MarkdownSource[]>;
|
|
11
|
+
export { buildReviewPrompt };
|
|
12
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/server/session.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AA0DD,wBAAsB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAazF;AAED,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { readdir, readFile, stat } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { buildReviewPrompt } from '../lib/review.js';
|
|
4
|
+
const MARKDOWN_EXTENSIONS = new Set(['.md', '.markdown']);
|
|
5
|
+
const SKIP_DIRECTORIES = new Set(['.git', 'node_modules', 'dist', 'coverage']);
|
|
6
|
+
function isMarkdownFile(fileName) {
|
|
7
|
+
return MARKDOWN_EXTENSIONS.has(path.extname(fileName).toLowerCase());
|
|
8
|
+
}
|
|
9
|
+
function toPosixRelativePath(filePath) {
|
|
10
|
+
return filePath.split(path.sep).join('/');
|
|
11
|
+
}
|
|
12
|
+
function countLines(content) {
|
|
13
|
+
if (content.length === 0) {
|
|
14
|
+
return 0;
|
|
15
|
+
}
|
|
16
|
+
return content.split('\n').length;
|
|
17
|
+
}
|
|
18
|
+
async function readMarkdownSource(rootPath, absolutePath) {
|
|
19
|
+
const content = await readFile(absolutePath, 'utf8');
|
|
20
|
+
const relativePath = toPosixRelativePath(path.relative(rootPath, absolutePath));
|
|
21
|
+
const name = path.basename(absolutePath);
|
|
22
|
+
return {
|
|
23
|
+
id: relativePath,
|
|
24
|
+
name,
|
|
25
|
+
absolutePath,
|
|
26
|
+
relativePath,
|
|
27
|
+
content,
|
|
28
|
+
lineCount: countLines(content),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
async function walkMarkdownDirectory(rootPath, currentPath) {
|
|
32
|
+
const entries = await readdir(currentPath, { withFileTypes: true });
|
|
33
|
+
const collected = [];
|
|
34
|
+
for (const entry of entries) {
|
|
35
|
+
if (entry.isDirectory()) {
|
|
36
|
+
if (SKIP_DIRECTORIES.has(entry.name) || entry.name.startsWith('.')) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const nested = await walkMarkdownDirectory(rootPath, path.join(currentPath, entry.name));
|
|
40
|
+
collected.push(...nested);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (entry.isFile() && isMarkdownFile(entry.name)) {
|
|
44
|
+
collected.push(await readMarkdownSource(rootPath, path.join(currentPath, entry.name)));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return collected;
|
|
48
|
+
}
|
|
49
|
+
export async function discoverMarkdownFiles(targetPath) {
|
|
50
|
+
const targetStat = await stat(targetPath);
|
|
51
|
+
if (targetStat.isFile()) {
|
|
52
|
+
if (!isMarkdownFile(targetPath)) {
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
return [await readMarkdownSource(path.dirname(targetPath), targetPath)];
|
|
56
|
+
}
|
|
57
|
+
const files = await walkMarkdownDirectory(targetPath, targetPath);
|
|
58
|
+
return files.sort((left, right) => left.relativePath.localeCompare(right.relativePath));
|
|
59
|
+
}
|
|
60
|
+
export { buildReviewPrompt };
|
|
61
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/server/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ChildProcess } from 'node:child_process';
|
|
2
|
+
export interface CloudflaredTunnelHandle {
|
|
3
|
+
process: ChildProcess | null;
|
|
4
|
+
publicUrl: string;
|
|
5
|
+
close: () => Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
export interface LaunchCloudflaredTunnelOptions {
|
|
8
|
+
executableCandidates?: string[];
|
|
9
|
+
timeoutMs?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function hasCloudflaredExecutable(): boolean;
|
|
12
|
+
export declare function launchCloudflaredTunnel(localUrl: string, options?: LaunchCloudflaredTunnelOptions): Promise<CloudflaredTunnelHandle | null>;
|
|
13
|
+
//# sourceMappingURL=tunnel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tunnel.d.ts","sourceRoot":"","sources":["../../src/server/tunnel.ts"],"names":[],"mappings":"AACA,OAAO,EAAoB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGzE,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAED,MAAM,WAAW,8BAA8B;IAC7C,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA6BD,wBAAgB,wBAAwB,IAAI,OAAO,CAElD;AAwDD,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,8BAAmC,GAC3C,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAqEzC"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { spawn, spawnSync } from 'node:child_process';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
const TUNNEL_CANDIDATES = {
|
|
5
|
+
darwin: ['cloudflared', '/opt/homebrew/bin/cloudflared', '/usr/local/bin/cloudflared'],
|
|
6
|
+
linux: ['cloudflared'],
|
|
7
|
+
win32: ['cloudflared.exe'],
|
|
8
|
+
aix: [],
|
|
9
|
+
android: [],
|
|
10
|
+
freebsd: [],
|
|
11
|
+
haiku: [],
|
|
12
|
+
illumos: [],
|
|
13
|
+
netbsd: [],
|
|
14
|
+
openbsd: [],
|
|
15
|
+
sunos: [],
|
|
16
|
+
};
|
|
17
|
+
function commandExists(command) {
|
|
18
|
+
if (path.isAbsolute(command)) {
|
|
19
|
+
return existsSync(command);
|
|
20
|
+
}
|
|
21
|
+
const result = spawnSync(command, ['--version'], { stdio: 'ignore' });
|
|
22
|
+
return result.status === 0 || result.status === 1;
|
|
23
|
+
}
|
|
24
|
+
function pickTunnelExecutable(candidates) {
|
|
25
|
+
return candidates.find((candidate) => commandExists(candidate)) ?? null;
|
|
26
|
+
}
|
|
27
|
+
export function hasCloudflaredExecutable() {
|
|
28
|
+
return pickTunnelExecutable(TUNNEL_CANDIDATES[process.platform] ?? []) !== null;
|
|
29
|
+
}
|
|
30
|
+
function extractPublicUrl(output) {
|
|
31
|
+
const match = output.match(/https:\/\/[^\s"'`]+\.trycloudflare\.com/);
|
|
32
|
+
return match?.[0] ?? null;
|
|
33
|
+
}
|
|
34
|
+
function stopProcess(childProcess) {
|
|
35
|
+
return new Promise((resolve) => {
|
|
36
|
+
if (!childProcess?.pid) {
|
|
37
|
+
resolve();
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
let settled = false;
|
|
41
|
+
const finish = () => {
|
|
42
|
+
if (settled) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
settled = true;
|
|
46
|
+
childProcess.off('exit', finish);
|
|
47
|
+
childProcess.off('close', finish);
|
|
48
|
+
resolve();
|
|
49
|
+
};
|
|
50
|
+
if (childProcess.exitCode !== null || childProcess.signalCode !== null) {
|
|
51
|
+
resolve();
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
childProcess.once('exit', finish);
|
|
55
|
+
childProcess.once('close', finish);
|
|
56
|
+
try {
|
|
57
|
+
childProcess.kill('SIGTERM');
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
finish();
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const timeout = setTimeout(() => {
|
|
64
|
+
if (childProcess.exitCode === null && childProcess.signalCode === null) {
|
|
65
|
+
try {
|
|
66
|
+
childProcess.kill('SIGKILL');
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
// Ignore shutdown errors; the process is already on the way out.
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}, 2000);
|
|
73
|
+
timeout.unref();
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
export async function launchCloudflaredTunnel(localUrl, options = {}) {
|
|
77
|
+
const executable = options.executableCandidates
|
|
78
|
+
? pickTunnelExecutable(options.executableCandidates)
|
|
79
|
+
: pickTunnelExecutable(TUNNEL_CANDIDATES[process.platform] ?? []);
|
|
80
|
+
if (!executable) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
const childProcess = spawn(executable, ['tunnel', '--url', localUrl], {
|
|
84
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
85
|
+
});
|
|
86
|
+
const timeoutMs = options.timeoutMs ?? 15_000;
|
|
87
|
+
const bufferedOutput = [];
|
|
88
|
+
const publicUrlPromise = new Promise((resolve, reject) => {
|
|
89
|
+
const timer = setTimeout(() => {
|
|
90
|
+
reject(new Error('Timed out waiting for cloudflared to report a public URL.'));
|
|
91
|
+
}, timeoutMs);
|
|
92
|
+
timer.unref();
|
|
93
|
+
const resolveFromChunk = (chunk) => {
|
|
94
|
+
const text = chunk.toString();
|
|
95
|
+
bufferedOutput.push(text);
|
|
96
|
+
const publicUrl = extractPublicUrl(bufferedOutput.join(''));
|
|
97
|
+
if (publicUrl) {
|
|
98
|
+
clearTimeout(timer);
|
|
99
|
+
resolve(publicUrl);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
childProcess.stdout?.on('data', resolveFromChunk);
|
|
103
|
+
childProcess.stderr?.on('data', resolveFromChunk);
|
|
104
|
+
childProcess.once('error', (error) => {
|
|
105
|
+
clearTimeout(timer);
|
|
106
|
+
reject(error);
|
|
107
|
+
});
|
|
108
|
+
childProcess.once('close', () => {
|
|
109
|
+
clearTimeout(timer);
|
|
110
|
+
const publicUrl = extractPublicUrl(bufferedOutput.join(''));
|
|
111
|
+
if (publicUrl) {
|
|
112
|
+
resolve(publicUrl);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
reject(new Error('cloudflared exited before reporting a public URL.'));
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
try {
|
|
119
|
+
const publicUrl = await publicUrlPromise;
|
|
120
|
+
return {
|
|
121
|
+
process: childProcess,
|
|
122
|
+
publicUrl,
|
|
123
|
+
close: () => stopProcess(childProcess),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
await stopProcess(childProcess);
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=tunnel.js.map
|