@jpoly1219/context-extractor 0.2.0 → 0.2.2
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/app.d.ts +27 -0
- package/dist/app.js +285 -0
- package/dist/codeql.d.ts +17 -0
- package/dist/codeql.js +1341 -0
- package/dist/constants.d.ts +11 -0
- package/dist/constants.js +62 -0
- package/dist/core.d.ts +20 -0
- package/dist/core.js +576 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +7 -0
- package/dist/main.d.ts +13 -0
- package/dist/main.js +255 -0
- package/dist/ocaml-driver.d.ts +30 -0
- package/dist/ocaml-driver.js +394 -0
- package/dist/ocaml-type-checker.d.ts +52 -0
- package/dist/ocaml-type-checker.js +286 -0
- package/dist/runner.d.ts +1 -0
- package/dist/runner.js +52 -0
- package/dist/types.d.ts +134 -0
- package/dist/types.js +14 -0
- package/dist/typescript-driver.d.ts +27 -0
- package/dist/typescript-driver.js +542 -0
- package/dist/typescript-type-checker.d.ts +64 -0
- package/dist/typescript-type-checker.js +512 -0
- package/dist/utils.d.ts +40 -0
- package/dist/utils.js +350 -0
- package/package.json +1 -1
package/dist/app.d.ts
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
import { Language, Context } from "./types";
|
2
|
+
export declare class App {
|
3
|
+
private language;
|
4
|
+
private languageDriver;
|
5
|
+
private languageServer;
|
6
|
+
private lspClient;
|
7
|
+
private sketchPath;
|
8
|
+
private repoPath;
|
9
|
+
private result;
|
10
|
+
private timeout;
|
11
|
+
constructor(language: Language, sketchPath: string, repoPath: string);
|
12
|
+
init(): Promise<void>;
|
13
|
+
run(): Promise<void>;
|
14
|
+
close(): void;
|
15
|
+
getSavedResult(): Context | null;
|
16
|
+
}
|
17
|
+
export declare class CompletionEngine {
|
18
|
+
private language;
|
19
|
+
private config;
|
20
|
+
private sketchPath;
|
21
|
+
constructor(language: Language, sketchPath: string, configPath: string);
|
22
|
+
completeWithLLM(context: Context): Promise<string>;
|
23
|
+
generateTypesAndHeadersPrompt(sketchFileContent: string, holeType: string, relevantTypes: string, relevantHeaders: string): {
|
24
|
+
role: string;
|
25
|
+
content: string;
|
26
|
+
}[];
|
27
|
+
}
|
package/dist/app.js
ADDED
@@ -0,0 +1,285 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3
|
+
if (k2 === undefined) k2 = k;
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
7
|
+
}
|
8
|
+
Object.defineProperty(o, k2, desc);
|
9
|
+
}) : (function(o, m, k, k2) {
|
10
|
+
if (k2 === undefined) k2 = k;
|
11
|
+
o[k2] = m[k];
|
12
|
+
}));
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
15
|
+
}) : function(o, v) {
|
16
|
+
o["default"] = v;
|
17
|
+
});
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
19
|
+
if (mod && mod.__esModule) return mod;
|
20
|
+
var result = {};
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
22
|
+
__setModuleDefault(result, mod);
|
23
|
+
return result;
|
24
|
+
};
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
27
|
+
};
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
29
|
+
exports.CompletionEngine = exports.App = void 0;
|
30
|
+
const path = __importStar(require("path"));
|
31
|
+
const fs = __importStar(require("fs"));
|
32
|
+
const child_process_1 = require("child_process");
|
33
|
+
const child_process_2 = require("child_process");
|
34
|
+
const openai_1 = __importDefault(require("openai"));
|
35
|
+
// import { LspClient, JSONRPCEndpoint } from "../ts-lsp-client-dist/src/main";
|
36
|
+
const ts_lsp_client_1 = require("ts-lsp-client");
|
37
|
+
const types_1 = require("./types");
|
38
|
+
// TODO: Bundle the drivers as barrel exports.
|
39
|
+
const typescript_driver_1 = require("./typescript-driver");
|
40
|
+
const ocaml_driver_1 = require("./ocaml-driver");
|
41
|
+
const utils_1 = require("./utils");
|
42
|
+
class App {
|
43
|
+
constructor(language, sketchPath, repoPath) {
|
44
|
+
// private result: {
|
45
|
+
// hole: string;
|
46
|
+
// relevantTypes: string[];
|
47
|
+
// relevantHeaders: string[];
|
48
|
+
// } | null = null;
|
49
|
+
this.result = null;
|
50
|
+
// Optional timeout for forced termination
|
51
|
+
this.timeout = setTimeout(() => {
|
52
|
+
if (!this.languageServer.killed) {
|
53
|
+
console.log('Forcibly killing the process...');
|
54
|
+
this.languageServer.kill('SIGKILL');
|
55
|
+
}
|
56
|
+
}, 5000);
|
57
|
+
this.language = language;
|
58
|
+
this.sketchPath = sketchPath;
|
59
|
+
this.repoPath = repoPath;
|
60
|
+
const r = (() => {
|
61
|
+
switch (language) {
|
62
|
+
case types_1.Language.TypeScript: {
|
63
|
+
this.languageDriver = new typescript_driver_1.TypeScriptDriver();
|
64
|
+
return (0, child_process_1.spawn)("typescript-language-server", ["--stdio"], { stdio: ["pipe", "pipe", "pipe"] });
|
65
|
+
}
|
66
|
+
case types_1.Language.OCaml: {
|
67
|
+
this.languageDriver = new ocaml_driver_1.OcamlDriver();
|
68
|
+
try {
|
69
|
+
(0, child_process_2.execSync)(`eval $(opam env --switch=. --set-switch)`, { shell: "/bin/bash" });
|
70
|
+
// execSync("opam switch .", { shell: "/bin/bash" })
|
71
|
+
const currDir = __dirname;
|
72
|
+
process.chdir(path.dirname(sketchPath));
|
73
|
+
// execSync("which dune", { shell: "/bin/bash" })
|
74
|
+
(0, child_process_1.spawn)("dune", ["build", "-w"]);
|
75
|
+
process.chdir(currDir);
|
76
|
+
}
|
77
|
+
catch (err) {
|
78
|
+
console.log("ERROR:", err);
|
79
|
+
}
|
80
|
+
// TODO: Spawn a dune build -w on sketch directory.
|
81
|
+
// try {
|
82
|
+
// execSync("which dune", { shell: "/bin/bash" })
|
83
|
+
// spawn("dune", ["build", "-w"]);
|
84
|
+
// } catch (err) {
|
85
|
+
// console.log("ERROR:", err)
|
86
|
+
// }
|
87
|
+
// process.chdir(currDir);
|
88
|
+
return (0, child_process_1.spawn)("ocamllsp", ["--stdio"]);
|
89
|
+
}
|
90
|
+
}
|
91
|
+
})();
|
92
|
+
const e = new ts_lsp_client_1.JSONRPCEndpoint(r.stdin, r.stdout);
|
93
|
+
const c = new ts_lsp_client_1.LspClient(e);
|
94
|
+
this.languageServer = r;
|
95
|
+
this.lspClient = c;
|
96
|
+
this.languageServer.on('close', (code) => {
|
97
|
+
if (code !== 0) {
|
98
|
+
console.log(`ls process exited with code ${code}`);
|
99
|
+
}
|
100
|
+
});
|
101
|
+
// Clear timeout once the process exits
|
102
|
+
this.languageServer.on('exit', () => {
|
103
|
+
clearTimeout(this.timeout);
|
104
|
+
console.log('Process terminated cleanly.');
|
105
|
+
});
|
106
|
+
// const logFile = fs.createWriteStream("log.txt");
|
107
|
+
// r.stdout.on('data', (d) => logFile.write(d));
|
108
|
+
}
|
109
|
+
async init() {
|
110
|
+
await this.languageDriver.init(this.lspClient, this.sketchPath);
|
111
|
+
}
|
112
|
+
async run() {
|
113
|
+
// const outputFile = fs.createWriteStream("output.txt");
|
114
|
+
try {
|
115
|
+
await this.init();
|
116
|
+
const holeContext = await this.languageDriver.getHoleContext(this.lspClient, this.sketchPath);
|
117
|
+
const relevantTypes = await this.languageDriver.extractRelevantTypes(this.lspClient, holeContext.fullHoverResult, holeContext.functionName, holeContext.range.start.line, holeContext.range.end.line, new Map(), holeContext.source);
|
118
|
+
// Postprocess the map.
|
119
|
+
if (this.language === types_1.Language.TypeScript) {
|
120
|
+
relevantTypes.delete("_()");
|
121
|
+
for (const [k, { typeSpan: v, sourceFile: src }] of relevantTypes.entries()) {
|
122
|
+
relevantTypes.set(k, { typeSpan: v.slice(0, -1), sourceFile: src });
|
123
|
+
}
|
124
|
+
}
|
125
|
+
else if (this.language === types_1.Language.OCaml) {
|
126
|
+
relevantTypes.delete("_");
|
127
|
+
}
|
128
|
+
console.log(path.join(path.dirname(this.sketchPath), `sketch${path.extname(this.sketchPath)}`));
|
129
|
+
let repo = [];
|
130
|
+
if (this.language === types_1.Language.TypeScript) {
|
131
|
+
repo = (0, utils_1.getAllTSFiles)(this.repoPath);
|
132
|
+
}
|
133
|
+
else if (this.language === types_1.Language.OCaml) {
|
134
|
+
repo = (0, utils_1.getAllOCamlFiles)(this.repoPath);
|
135
|
+
}
|
136
|
+
const relevantHeaders = await this.languageDriver.extractRelevantHeaders(this.lspClient, repo, relevantTypes, holeContext.functionTypeSpan);
|
137
|
+
// Postprocess the map.
|
138
|
+
if (this.language === types_1.Language.TypeScript) {
|
139
|
+
relevantTypes.delete("");
|
140
|
+
for (const [k, { typeSpan: v, sourceFile: src }] of relevantTypes.entries()) {
|
141
|
+
relevantTypes.set(k, { typeSpan: v + ";", sourceFile: src });
|
142
|
+
}
|
143
|
+
for (const obj of relevantHeaders) {
|
144
|
+
obj.typeSpan += ";";
|
145
|
+
}
|
146
|
+
}
|
147
|
+
const relevantTypesToReturn = new Map();
|
148
|
+
relevantTypes.forEach(({ typeSpan: v, sourceFile: src }, _) => {
|
149
|
+
if (relevantTypesToReturn.has(src)) {
|
150
|
+
const updated = relevantTypesToReturn.get(src);
|
151
|
+
updated.push(v);
|
152
|
+
relevantTypesToReturn.set(src, updated);
|
153
|
+
}
|
154
|
+
else {
|
155
|
+
relevantTypesToReturn.set(src, [v]);
|
156
|
+
}
|
157
|
+
});
|
158
|
+
const relevantHeadersToReturn = new Map();
|
159
|
+
relevantHeaders.forEach(({ typeSpan: v, sourceFile: src }) => {
|
160
|
+
if (relevantHeadersToReturn.has(src)) {
|
161
|
+
const updated = relevantHeadersToReturn.get(src);
|
162
|
+
if (!updated.includes(v)) {
|
163
|
+
updated.push(v);
|
164
|
+
}
|
165
|
+
relevantHeadersToReturn.set(src, updated);
|
166
|
+
}
|
167
|
+
else {
|
168
|
+
relevantHeadersToReturn.set(src, [v]);
|
169
|
+
}
|
170
|
+
});
|
171
|
+
this.result = {
|
172
|
+
holeType: holeContext.functionTypeSpan,
|
173
|
+
relevantTypes: relevantTypesToReturn,
|
174
|
+
relevantHeaders: relevantHeadersToReturn
|
175
|
+
};
|
176
|
+
}
|
177
|
+
catch (err) {
|
178
|
+
console.error("Error during execution:", err);
|
179
|
+
throw err;
|
180
|
+
}
|
181
|
+
finally {
|
182
|
+
// outputFile.end();
|
183
|
+
}
|
184
|
+
}
|
185
|
+
close() {
|
186
|
+
// TODO:
|
187
|
+
try {
|
188
|
+
this.lspClient.exit();
|
189
|
+
}
|
190
|
+
catch (err) {
|
191
|
+
console.log(err);
|
192
|
+
}
|
193
|
+
}
|
194
|
+
getSavedResult() {
|
195
|
+
return this.result;
|
196
|
+
}
|
197
|
+
}
|
198
|
+
exports.App = App;
|
199
|
+
class CompletionEngine {
|
200
|
+
constructor(language, sketchPath, configPath) {
|
201
|
+
this.language = language;
|
202
|
+
this.config = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
203
|
+
this.sketchPath = sketchPath;
|
204
|
+
}
|
205
|
+
async completeWithLLM(context) {
|
206
|
+
let joinedTypes = "";
|
207
|
+
let joinedHeaders = "";
|
208
|
+
context.relevantTypes.forEach((v, _) => {
|
209
|
+
joinedTypes = joinedTypes + v.join("\n") + "\n";
|
210
|
+
});
|
211
|
+
context.relevantHeaders.forEach((v, _) => {
|
212
|
+
joinedHeaders = joinedHeaders + v.join("\n") + "\n";
|
213
|
+
});
|
214
|
+
// Create a prompt.
|
215
|
+
const prompt = this.generateTypesAndHeadersPrompt(
|
216
|
+
// fs.readFileSync(path.join(targetDirectoryPath, "sketch.ts"), "utf8"),
|
217
|
+
fs.readFileSync(this.sketchPath, "utf8"), context.holeType, joinedTypes, joinedHeaders);
|
218
|
+
// Call the LLM to get completion results back.
|
219
|
+
const apiBase = this.config.apiBase;
|
220
|
+
const deployment = this.config.deployment;
|
221
|
+
const model = this.config.gptModel;
|
222
|
+
const apiVersion = this.config.apiVersion;
|
223
|
+
const apiKey = this.config.apiKey;
|
224
|
+
const openai = new openai_1.default({
|
225
|
+
apiKey,
|
226
|
+
baseURL: `${apiBase}/openai/deployments/${deployment}`,
|
227
|
+
defaultQuery: { "api-version": apiVersion },
|
228
|
+
defaultHeaders: { "api-key": apiKey }
|
229
|
+
});
|
230
|
+
const llmResult = await openai.chat.completions.create({
|
231
|
+
model,
|
232
|
+
messages: prompt,
|
233
|
+
temperature: this.config.temperature
|
234
|
+
});
|
235
|
+
return llmResult.choices[0].message.content;
|
236
|
+
}
|
237
|
+
generateTypesAndHeadersPrompt(sketchFileContent, holeType, relevantTypes, relevantHeaders) {
|
238
|
+
let holeConstruct = "";
|
239
|
+
switch (this.language) {
|
240
|
+
case types_1.Language.TypeScript: {
|
241
|
+
holeConstruct = "_()";
|
242
|
+
}
|
243
|
+
case types_1.Language.OCaml: {
|
244
|
+
holeConstruct = "_";
|
245
|
+
}
|
246
|
+
}
|
247
|
+
const prompt = [{
|
248
|
+
role: "system",
|
249
|
+
content: [
|
250
|
+
"CODE COMPLETION INSTRUCTIONS:",
|
251
|
+
`- Reply with a functional, idiomatic replacement for the program hole marked '${holeConstruct}' in the provided TypeScript program sketch`,
|
252
|
+
`- Reply only with a single replacement term for the unqiue distinguished hole marked '${holeConstruct}'`,
|
253
|
+
"Reply only with code",
|
254
|
+
"- DO NOT include the program sketch in your reply",
|
255
|
+
"- DO NOT include a period at the end of your response and DO NOT use markdown",
|
256
|
+
"- DO NOT include a type signature for the program hole, as this is redundant and is already in the provided program sketch"
|
257
|
+
].join("\n"),
|
258
|
+
}];
|
259
|
+
let userPrompt = {
|
260
|
+
role: "user",
|
261
|
+
content: ""
|
262
|
+
};
|
263
|
+
if (relevantTypes) {
|
264
|
+
userPrompt.content +=
|
265
|
+
`# The expected type of the goal completion is ${holeType} #
|
266
|
+
|
267
|
+
# The following type definitions are likely relevant: #
|
268
|
+
${relevantTypes}
|
269
|
+
|
270
|
+
`;
|
271
|
+
}
|
272
|
+
if (relevantHeaders) {
|
273
|
+
userPrompt.content += `
|
274
|
+
# Consider using these variables relevant to the expected type: #
|
275
|
+
${relevantHeaders}
|
276
|
+
|
277
|
+
`;
|
278
|
+
}
|
279
|
+
userPrompt.content += `# Program Sketch to be completed: #\n${(0, utils_1.removeLines)(sketchFileContent).join("\n")}`;
|
280
|
+
prompt.push(userPrompt);
|
281
|
+
return prompt;
|
282
|
+
}
|
283
|
+
;
|
284
|
+
}
|
285
|
+
exports.CompletionEngine = CompletionEngine;
|
package/dist/codeql.d.ts
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
import { relevantTypeObject, varsObject, typesObject } from "./types";
|
2
|
+
declare const createDatabaseWithCodeQL: (pathToCodeQL: string, targetPath: string) => string;
|
3
|
+
declare const extractHoleType: (pathToCodeQL: string, pathToQuery: string, pathToDatabase: string, outDir: string) => typesObject;
|
4
|
+
declare const extractRelevantTypesWithCodeQL: (pathToCodeQL: string, pathToQuery: string, pathToDatabase: string, outDir: string) => Map<string, relevantTypeObject>;
|
5
|
+
declare const extractHeadersWithCodeQL: (pathToCodeQL: string, pathToQuery: string, pathToDatabase: string, outDir: string) => Map<string, varsObject>;
|
6
|
+
declare const extractTypesAndLocations: (pathToCodeQL: string, pathToQuery: string, pathToDatabase: string, outDir: string) => {
|
7
|
+
locationToType: Map<string, string[]>;
|
8
|
+
typeToLocation: Map<string, string>;
|
9
|
+
};
|
10
|
+
declare const extractRelevantContextWithCodeQL: (pathToCodeQL: string, pathToQuery: string, pathToDatabase: string, outDir: string, headers: Map<string, varsObject>, relevantTypes: Map<string, relevantTypeObject>) => Set<string>;
|
11
|
+
declare const getRelevantHeaders: (pathToCodeQL: string, pathToQuery: string, pathToDatabase: string, outDir: string, headers: Map<string, varsObject>, holeType: typesObject) => Set<string>;
|
12
|
+
declare const getRelevantHeaders3: (pathToCodeQL: string, pathToQuery: string, pathToDatabase: string, outDir: string, headers: Map<string, varsObject>, holeType: typesObject, relevantTypes: Map<string, relevantTypeObject>) => Set<string>;
|
13
|
+
declare const getRelevantHeaders4: (pathToCodeQL: string, pathToQueryDir: string, pathToDatabase: string, outDir: string, headers: Map<string, varsObject>, holeType: typesObject, relevantTypes: Map<string, relevantTypeObject>, knownTypeLocations: {
|
14
|
+
locationToType: Map<string, string[]>;
|
15
|
+
typeToLocation: Map<string, string>;
|
16
|
+
}) => Set<string>;
|
17
|
+
export { createDatabaseWithCodeQL, extractHoleType, extractRelevantTypesWithCodeQL, extractHeadersWithCodeQL, extractRelevantContextWithCodeQL, extractTypesAndLocations, getRelevantHeaders, getRelevantHeaders3, getRelevantHeaders4 };
|