doppelgangers 0.0.1

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAoC/B,MAAM,UAAU,KAAK,CAAC,OAAqB,EAAQ;IAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAEhD,MAAM,KAAK,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC7E,MAAM,OAAO,GAAqB,EAAE,CAAC;IACrC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,IAAI,CAAC;YACJ,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACR,qBAAqB;QACtB,CAAC;IACF,CAAC;IAED,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAC3D,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAE1D,IAAI,QAAoB,CAAC;IACzB,IAAI,QAAoB,CAAC;IAEzB,IAAI,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,mCAAmC,eAAe,EAAE,CAAC,CAAC;QAClE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC;QACpE,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;QAC3B,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IAC5B,CAAC;SAAM,CAAC;QACP,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC;YACvB,WAAW,EAAE,CAAC;YACd,UAAU,EAAE,OAAO,CAAC,SAAS;YAC7B,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,MAAM,EAAE,IAAI,CAAC,MAAM;SACnB,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC;YACvB,WAAW,EAAE,CAAC;YACd,UAAU,EAAE,OAAO,CAAC,SAAS;YAC7B,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,MAAM,EAAE,IAAI,CAAC,MAAM;SACnB,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,sBAAsB,UAAU,CAAC,MAAM,aAAa,CAAC,CAAC;QAClE,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,sBAAsB,UAAU,CAAC,MAAM,aAAa,CAAC,CAAC;QAClE,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAElC,EAAE,CAAC,aAAa,CAAC,eAAe,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;QAC1E,OAAO,CAAC,GAAG,CAAC,wBAAwB,eAAe,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,MAAM,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;IAC7B,MAAM,MAAM,GAAG,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC;IAChC,MAAM,MAAM,GAAG,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC;IAEhC,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACtC,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACtC,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACtC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;IAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;IAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;IAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;IAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;IAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;IAC/B,MAAM,OAAO,GAAG,KAAK,GAAG,KAAK,IAAI,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,KAAK,GAAG,KAAK,IAAI,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,KAAK,GAAG,KAAK,IAAI,CAAC,CAAC;IAEnC,MAAM,MAAM,GAAY,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC;QACtD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;QAC7B,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7C,OAAO;YACN,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,MAAM;YAC7B,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,MAAM;YAC7B,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,OAAO;YACnC,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,OAAO;YACnC,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,OAAO;YACnC,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,EAAE;YACxB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,GAAG,EAAE,KAAK,CAAC,GAAG,IAAI,EAAE;YACpB,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE;YACtB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,SAAS,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;SAClE,CAAC;IAAA,CACF,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAEjE,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IAEpC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IAEnC,OAAO,CAAC,GAAG,CAAC,SAAS,UAAU,EAAE,CAAC,CAAC;AAAA,CACnC;AAED,SAAS,YAAY,CAAC,QAAgB,EAAU;IAC/C,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBA+Sa,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAugBrB,CAAC;AAAA,CACR;AAED,kBAAkB;AAClB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;IACpF,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,OAAO,GAAiB;QAC7B,KAAK,EAAE,kBAAkB;QACzB,MAAM,EAAE,aAAa;QACrB,WAAW,EAAE,kBAAkB;QAC/B,SAAS,EAAE,EAAE;QACb,OAAO,EAAE,GAAG;QACZ,iBAAiB,EAAE,KAAK;KACxB,CAAC;IAEF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACzC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACvB,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3B,CAAC;aAAM,IAAI,GAAG,KAAK,UAAU,EAAE,CAAC;YAC/B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5B,CAAC;aAAM,IAAI,GAAG,KAAK,eAAe,EAAE,CAAC;YACpC,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACjC,CAAC;aAAM,IAAI,GAAG,KAAK,aAAa,EAAE,CAAC;YAClC,OAAO,CAAC,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACvC,CAAC;aAAM,IAAI,GAAG,KAAK,YAAY,EAAE,CAAC;YACjC,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACrC,CAAC;aAAM,IAAI,GAAG,KAAK,UAAU,EAAE,CAAC;YAC/B,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAClC,CAAC;IACF,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,CAAC;AAChB,CAAC"}
@@ -0,0 +1,11 @@
1
+ export interface EmbedOptions {
2
+ input: string;
3
+ output: string;
4
+ model: string;
5
+ batchSize: number;
6
+ maxChars: number;
7
+ bodyChars: number;
8
+ resume: boolean;
9
+ }
10
+ export declare function embed(options: EmbedOptions): Promise<void>;
11
+ //# sourceMappingURL=embed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embed.d.ts","sourceRoot":"","sources":["../src/embed.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;CAChB;AAkCD,wBAAsB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAoGhE"}
package/dist/embed.js ADDED
@@ -0,0 +1,147 @@
1
+ import fs from "fs";
2
+ import OpenAI from "openai";
3
+ import path from "path";
4
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
5
+ const buildText = (title, body, maxChars) => {
6
+ const bodyText = (body || "").replace(/\r\n/g, "\n").trim();
7
+ const combined = `${title}\n\n${bodyText}`.trim();
8
+ return combined.slice(0, maxChars);
9
+ };
10
+ const buildSnippet = (body, bodyChars) => {
11
+ if (!body)
12
+ return "";
13
+ return body.replace(/\s+/g, " ").trim().slice(0, bodyChars);
14
+ };
15
+ export async function embed(options) {
16
+ if (!process.env.OPENAI_API_KEY) {
17
+ console.error("OPENAI_API_KEY is required");
18
+ process.exit(1);
19
+ }
20
+ const inputPath = path.resolve(options.input);
21
+ const outputPath = path.resolve(options.output);
22
+ const items = JSON.parse(fs.readFileSync(inputPath, "utf8"));
23
+ const existing = new Map();
24
+ if (options.resume && fs.existsSync(outputPath)) {
25
+ const lines = fs.readFileSync(outputPath, "utf8").split("\n").filter(Boolean);
26
+ for (const line of lines) {
27
+ try {
28
+ const item = JSON.parse(line);
29
+ if (item.url)
30
+ existing.set(item.url, item);
31
+ }
32
+ catch {
33
+ // skip invalid lines
34
+ }
35
+ }
36
+ }
37
+ const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
38
+ const outputDir = path.dirname(outputPath);
39
+ fs.mkdirSync(outputDir, { recursive: true });
40
+ const outputStream = fs.createWriteStream(outputPath, { flags: options.resume ? "a" : "w" });
41
+ const pending = items.filter((item) => item?.url && !existing.has(item.url));
42
+ const total = pending.length;
43
+ let processed = 0;
44
+ const skipped = items.length - pending.length;
45
+ let batchInputs = [];
46
+ let batchMeta = [];
47
+ const createEmbeddings = async (inputs, attempt = 1) => {
48
+ try {
49
+ const response = await client.embeddings.create({
50
+ model: options.model,
51
+ input: inputs,
52
+ });
53
+ return response.data.map((item) => item.embedding);
54
+ }
55
+ catch (error) {
56
+ if (attempt >= 5)
57
+ throw error;
58
+ const delay = 1000 * attempt;
59
+ console.warn(`Embedding request failed, retrying in ${delay}ms`, error.message);
60
+ await sleep(delay);
61
+ return createEmbeddings(inputs, attempt + 1);
62
+ }
63
+ };
64
+ const flushBatch = async () => {
65
+ if (!batchInputs.length)
66
+ return;
67
+ const embeddings = await createEmbeddings(batchInputs);
68
+ for (let i = 0; i < embeddings.length; i += 1) {
69
+ const meta = batchMeta[i];
70
+ const record = {
71
+ url: meta.url,
72
+ number: meta.number,
73
+ title: meta.title,
74
+ body: meta.body,
75
+ state: meta.state,
76
+ type: meta.type,
77
+ embedding: embeddings[i],
78
+ };
79
+ outputStream.write(`${JSON.stringify(record)}\n`);
80
+ processed += 1;
81
+ if (processed % 50 === 0 || processed === total) {
82
+ console.log(`Embedded ${processed}/${total} items`);
83
+ }
84
+ }
85
+ batchInputs = [];
86
+ batchMeta = [];
87
+ };
88
+ for (const item of pending) {
89
+ const title = item.title || "";
90
+ const body = item.body || "";
91
+ const text = buildText(title, body, options.maxChars);
92
+ batchInputs.push(text || title || item.url);
93
+ batchMeta.push({
94
+ url: item.url,
95
+ number: item.number,
96
+ title,
97
+ body: buildSnippet(body, options.bodyChars),
98
+ state: item.state,
99
+ type: item.type,
100
+ });
101
+ if (batchInputs.length >= options.batchSize) {
102
+ await flushBatch();
103
+ }
104
+ }
105
+ await flushBatch();
106
+ outputStream.end();
107
+ console.log(`Done. Embedded ${processed}/${total} PRs, skipped ${skipped}.`);
108
+ }
109
+ // CLI entry point
110
+ if (process.argv[1]?.endsWith("embed.js") || process.argv[1]?.endsWith("embed.ts")) {
111
+ const args = process.argv.slice(2);
112
+ const options = {
113
+ input: "prs.json",
114
+ output: "embeddings.jsonl",
115
+ model: "text-embedding-3-small",
116
+ batchSize: 100,
117
+ maxChars: 4000,
118
+ bodyChars: 2000,
119
+ resume: true,
120
+ };
121
+ for (let i = 0; i < args.length; i += 1) {
122
+ const arg = args[i];
123
+ if (arg === "--input") {
124
+ options.input = args[++i];
125
+ }
126
+ else if (arg === "--output") {
127
+ options.output = args[++i];
128
+ }
129
+ else if (arg === "--model") {
130
+ options.model = args[++i];
131
+ }
132
+ else if (arg === "--batch") {
133
+ options.batchSize = Number(args[++i]);
134
+ }
135
+ else if (arg === "--max-chars") {
136
+ options.maxChars = Number(args[++i]);
137
+ }
138
+ else if (arg === "--body-chars") {
139
+ options.bodyChars = Number(args[++i]);
140
+ }
141
+ else if (arg === "--no-resume") {
142
+ options.resume = false;
143
+ }
144
+ }
145
+ embed(options);
146
+ }
147
+ //# sourceMappingURL=embed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embed.js","sourceRoot":"","sources":["../src/embed.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=triage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"triage.d.ts","sourceRoot":"","sources":["../src/triage.ts"],"names":[],"mappings":""}
package/dist/triage.js ADDED
@@ -0,0 +1,220 @@
1
+ #!/usr/bin/env node
2
+ import { spawn } from "child_process";
3
+ import fs from "fs";
4
+ import path from "path";
5
+ import readline from "readline";
6
+ import { build } from "./build.js";
7
+ import { embed } from "./embed.js";
8
+ function parseRepo(repo) {
9
+ const trimmed = repo.replace(/\s+/g, "");
10
+ const match = trimmed.match(/github\.com[/:]([^/]+)\/([^/.]+)(?:\.git)?/i);
11
+ if (match) {
12
+ return { owner: match[1], name: match[2] };
13
+ }
14
+ if (trimmed.includes("/")) {
15
+ const [owner, name] = trimmed.split("/");
16
+ if (owner && name)
17
+ return { owner, name };
18
+ }
19
+ return null;
20
+ }
21
+ async function fetchItems(owner, name, state, type, outputPath) {
22
+ fs.mkdirSync(path.dirname(outputPath), { recursive: true });
23
+ const repoLabel = `${owner}/${name}`;
24
+ const items = [];
25
+ let prCount = 0;
26
+ let issueCount = 0;
27
+ const fetchEndpoint = async (endpoint, itemType) => {
28
+ const jqFilter = itemType === "issue"
29
+ ? '.[] | select(.pull_request == null) | {url: .html_url, number: .number, title: .title, body: .body, state: .state, type: "issue"}'
30
+ : '.[] | {url: .html_url, number: .number, title: .title, body: .body, state: .state, type: "pr"}';
31
+ const gh = spawn("gh", ["api", "--paginate", endpoint, "--jq", jqFilter], {
32
+ stdio: ["ignore", "pipe", "inherit"],
33
+ });
34
+ const rl = readline.createInterface({
35
+ input: gh.stdout,
36
+ crlfDelay: Number.POSITIVE_INFINITY,
37
+ });
38
+ const readPromise = (async () => {
39
+ for await (const line of rl) {
40
+ const trimmed = line.trim();
41
+ if (!trimmed)
42
+ continue;
43
+ try {
44
+ const item = JSON.parse(trimmed);
45
+ items.push(item);
46
+ if (itemType === "pr")
47
+ prCount++;
48
+ else
49
+ issueCount++;
50
+ const total = prCount + issueCount;
51
+ if (total % 200 === 0) {
52
+ console.log(`[${repoLabel}] Fetched ${prCount} PRs, ${issueCount} issues`);
53
+ }
54
+ }
55
+ catch {
56
+ // skip invalid JSON
57
+ }
58
+ }
59
+ })();
60
+ const exitPromise = new Promise((resolve, reject) => {
61
+ gh.on("close", (code) => {
62
+ if (code === 0)
63
+ resolve();
64
+ else
65
+ reject(new Error(`gh api ${endpoint} exited with code ${code}`));
66
+ });
67
+ gh.on("error", reject);
68
+ });
69
+ await Promise.all([readPromise, exitPromise]);
70
+ };
71
+ if (type === "pr" || type === "all") {
72
+ const prEndpoint = `/repos/${owner}/${name}/pulls?state=${state}&per_page=100`;
73
+ await fetchEndpoint(prEndpoint, "pr");
74
+ }
75
+ if (type === "issue" || type === "all") {
76
+ const issueEndpoint = `/repos/${owner}/${name}/issues?state=${state}&per_page=100`;
77
+ await fetchEndpoint(issueEndpoint, "issue");
78
+ }
79
+ fs.writeFileSync(outputPath, JSON.stringify(items, null, 2));
80
+ return { total: items.length, prs: prCount, issues: issueCount };
81
+ }
82
+ async function main() {
83
+ const args = process.argv.slice(2);
84
+ const options = {
85
+ repo: null,
86
+ state: "open",
87
+ type: "all",
88
+ output: "prs.json",
89
+ embeddings: "embeddings.jsonl",
90
+ html: "triage.html",
91
+ model: "text-embedding-3-small",
92
+ batch: 100,
93
+ maxChars: 4000,
94
+ bodyChars: 2000,
95
+ neighbors: 15,
96
+ minDist: 0.1,
97
+ search: false,
98
+ };
99
+ for (let i = 0; i < args.length; i += 1) {
100
+ const arg = args[i];
101
+ if (arg === "--repo") {
102
+ options.repo = args[++i];
103
+ }
104
+ else if (arg === "--state") {
105
+ const val = args[++i];
106
+ if (val !== "open" && val !== "closed" && val !== "all") {
107
+ console.error("--state must be open, closed, or all");
108
+ process.exit(1);
109
+ }
110
+ options.state = val;
111
+ }
112
+ else if (arg === "--type") {
113
+ const val = args[++i];
114
+ if (val !== "pr" && val !== "issue" && val !== "all") {
115
+ console.error("--type must be pr, issue, or all");
116
+ process.exit(1);
117
+ }
118
+ options.type = val;
119
+ }
120
+ else if (arg === "--output") {
121
+ options.output = args[++i];
122
+ }
123
+ else if (arg === "--embeddings") {
124
+ options.embeddings = args[++i];
125
+ }
126
+ else if (arg === "--html") {
127
+ options.html = args[++i];
128
+ }
129
+ else if (arg === "--model") {
130
+ options.model = args[++i];
131
+ }
132
+ else if (arg === "--batch") {
133
+ options.batch = Number(args[++i]);
134
+ }
135
+ else if (arg === "--max-chars") {
136
+ options.maxChars = Number(args[++i]);
137
+ }
138
+ else if (arg === "--body-chars") {
139
+ options.bodyChars = Number(args[++i]);
140
+ }
141
+ else if (arg === "--neighbors") {
142
+ options.neighbors = Number(args[++i]);
143
+ }
144
+ else if (arg === "--min-dist") {
145
+ options.minDist = Number(args[++i]);
146
+ }
147
+ else if (arg === "--search") {
148
+ options.search = true;
149
+ }
150
+ else if (arg === "--help" || arg === "-h") {
151
+ console.log(`
152
+ doppelgangers - Find duplicate PRs through embedding visualization
153
+
154
+ Usage:
155
+ doppelgangers --repo <owner/repo>
156
+
157
+ Options:
158
+ --repo <url|owner/repo> GitHub repository (required)
159
+ --state <state> Item state: open, closed, or all (default: open)
160
+ --type <type> Item type: pr, issue, or all (default: all)
161
+ --output <path> Output path for items JSON (default: prs.json)
162
+ --embeddings <path> Output path for embeddings (default: embeddings.jsonl)
163
+ --html <path> Output path for HTML viewer (default: triage.html)
164
+ --model <model> OpenAI embedding model (default: text-embedding-3-small)
165
+ --batch <n> Batch size for embeddings (default: 100)
166
+ --max-chars <n> Max chars for embedding input (default: 4000)
167
+ --body-chars <n> Max chars for body snippet (default: 2000)
168
+ --neighbors <n> UMAP neighbors (default: 15)
169
+ --min-dist <n> UMAP min distance (default: 0.1)
170
+ --search Include embeddings for semantic search (increases file size)
171
+
172
+ Environment:
173
+ OPENAI_API_KEY Required for embedding generation
174
+ `);
175
+ process.exit(0);
176
+ }
177
+ }
178
+ if (!options.repo) {
179
+ console.error("--repo is required. Use --help for usage.");
180
+ process.exit(1);
181
+ }
182
+ const repoInfo = parseRepo(options.repo);
183
+ if (!repoInfo) {
184
+ console.error("Could not parse repo. Use https://github.com/org/repo or org/repo");
185
+ process.exit(1);
186
+ }
187
+ const { owner, name } = repoInfo;
188
+ const typeLabel = options.type === "all" ? "PRs and issues" : options.type === "pr" ? "PRs" : "issues";
189
+ console.log(`Fetching ${options.state} ${typeLabel} for ${owner}/${name}`);
190
+ const outputPath = path.resolve(options.output);
191
+ const result = await fetchItems(owner, name, options.state, options.type, outputPath);
192
+ console.log(`Wrote ${outputPath} (${result.prs} PRs, ${result.issues} issues)`);
193
+ const embedOptions = {
194
+ input: outputPath,
195
+ output: path.resolve(options.embeddings),
196
+ model: options.model,
197
+ batchSize: options.batch,
198
+ maxChars: options.maxChars,
199
+ bodyChars: options.bodyChars,
200
+ resume: false,
201
+ };
202
+ await embed(embedOptions);
203
+ const embeddingsPath = path.resolve(options.embeddings);
204
+ const projectionsPath = embeddingsPath.replace(/\.[^.]+$/, "-projections.json");
205
+ const buildOptions = {
206
+ input: embeddingsPath,
207
+ output: path.resolve(options.html),
208
+ projections: projectionsPath,
209
+ neighbors: options.neighbors,
210
+ minDist: options.minDist,
211
+ includeEmbeddings: options.search,
212
+ };
213
+ build(buildOptions);
214
+ console.log(`Done. Open ${path.resolve(options.html)}`);
215
+ }
216
+ main().catch((error) => {
217
+ console.error(error);
218
+ process.exit(1);
219
+ });
220
+ //# sourceMappingURL=triage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"triage.js","sourceRoot":"","sources":["../src/triage.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "doppelgangers",
3
+ "version": "0.0.1",
4
+ "description": "Find duplicate PRs through embedding visualization",
5
+ "type": "module",
6
+ "bin": {
7
+ "doppelgangers": "./dist/triage.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsgo",
11
+ "dev": "tsgo --watch",
12
+ "check": "biome check --write . && tsgo --noEmit",
13
+ "prepare": "husky"
14
+ },
15
+ "keywords": ["github", "pull-request", "triage", "embeddings", "visualization", "umap"],
16
+ "author": "Mario Zechner",
17
+ "license": "MIT",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/badlogic/doppelgangers.git"
21
+ },
22
+ "dependencies": {
23
+ "openai": "^4.104.0",
24
+ "umap-js": "^1.4.0"
25
+ },
26
+ "devDependencies": {
27
+ "@biomejs/biome": "2.3.5",
28
+ "@types/node": "^22.10.5",
29
+ "@typescript/native-preview": "7.0.0-dev.20260120.1",
30
+ "husky": "^9.1.7",
31
+ "typescript": "^5.9.2"
32
+ },
33
+ "engines": {
34
+ "node": ">=20.0.0"
35
+ }
36
+ }