Github CopilotGitHubOpenAICopilot
VSCode
Copilot
VSCodeextension.js
mac~/.vscode
webpack_modules
webpackjsbundle
AST
babel-parserAST
const ast = parser.parse(source);
babel-traverseASTmodules
function parseModules() {
traverse(ast, {
enter(path) {
if (
path.node.type === "VariableDeclarator" &&
path.node.id.name === "__webpack_modules__"
) {
const modules = path.node.init.properties;
for (const module of modules) {
const moduleId = module.key.value;
const moduleAst = module.value;
const moduleSource = generate(moduleAst).code;
try {
const ast = transformRequire(prettier(clearfyParams(moduleId, moduleSource)));
const mainBody = ast.program.body[0].expression.body.body;
const moduleCode = generate(types.Program(mainBody)).code;
fs.writeFileSync(
"./prettier/modules/" + moduleId + ".js",
moduleCode,
"utf8"
);
} catch (e) {
console.log(e);
}
}
}
},
});
}
astbabel-generatorbabel-typesast
idbundlecopilotbundle752
bundle
webpackmodule``exports``require
function clearfyParams(moduleId, moduleSource) {
if (moduleSource.trim().startsWith("function")) {
// change `function(e, t, n) {` to `(e, t, n) => {`
moduleSource = moduleSource.replace("function", "");
moduleSource = moduleSource.replace(")", ") =>");
}
const moduleAst = parser.parse(moduleSource);
let flag = false;
traverse(moduleAst, {
ArrowFunctionExpression(path) {
if (flag) return;
const params = path.node.params;
params.forEach((param) => {
if (param.name === "e" || param.name === "t" || param.name === "n") {
path.scope.rename(
param.name,
{
e: "module",
t: "exports",
n: "require",
}[param.name]
);
}
});
flag = true;
},
});
return moduleAst;
}
requireexports
var r = require(12781).Stream;
var i = require(73837);
function o() {
this.source = null;
this.dataSize = 0;
this.maxDataSize = 1048576;
this.pauseStream = !0;
this._maxDataSizeExceeded = !1;
this._released = !1;
this._bufferedEvents = [];
}
module.exports = o;
JShttps://github.com/thakkarparth007/copilot-explorer
function prettier(ast) {
const moduleTransformer = {
// e.g., `(0, r.getConfig)(e, r.ConfigKey.DebugOverrideProxyUrl);`
// gets transformed to r.getConfig(e, r.ConfigKey.DebugOverrideProxyUrl);
CallExpression(path) {
if (path.node.callee.type != "SequenceExpression") {
return;
}
if (
path.node.callee.expressions.length == 2 &&
path.node.callee.expressions[0].type == "NumericLiteral"
) {
path.node.callee = path.node.callee.expressions[1];
}
},
ExpressionStatement(path) {
if (path.node.expression.type == "SequenceExpression") {
const exprs = path.node.expression.expressions;
let exprStmts = exprs.map((e) => {
return types.expressionStatement(e);
});
path.replaceWithMultiple(exprStmts);
return;
}
if (path.node.expression.type == "AssignmentExpression") {
// handle cases like: `a = (expr1, expr2, expr3)`
// convert to: `expr1; expr2; a = expr3;`
if (path.node.expression.right.type == "SequenceExpression") {
const exprs = path.node.expression.right.expressions;
let exprStmts = exprs.map((e) => {
return types.expressionStatement(e);
});
let lastExpr = exprStmts.pop();
path.node.expression.right = lastExpr.expression;
exprStmts.push(path.node);
path.replaceWithMultiple(exprStmts);
return;
}
// handle cases like: `exports.GoodExplainableName = a;` where `a` is a function or a class
// rename `a` to `GoodExplainableName` everywhere in the module
if (
path.node.expression.left.type == "MemberExpression" &&
path.node.expression.left.object.type == "Identifier" &&
path.node.expression.left.object.name == "exports" &&
path.node.expression.left.property.type == "Identifier" &&
path.node.expression.left.property.name != "default" &&
path.node.expression.right.type == "Identifier" &&
path.node.expression.right.name.length == 1
) {
path.scope.rename(
path.node.expression.right.name,
path.node.expression.left.property.name
);
return;
}
}
if (path.node.expression.type == "ConditionalExpression") {
// handle cases like: `<test> ? c : d;`
// convert to: `if (<test>) { c; } else { d; }`
const test = path.node.expression.test;
const consequent = path.node.expression.consequent;
const alternate = path.node.expression.alternate;
const ifStmt = types.ifStatement(
test,
types.blockStatement([types.expressionStatement(consequent)]),
types.blockStatement([types.expressionStatement(alternate)])
);
path.replaceWith(ifStmt);
return;
}
if (path.node.expression.type == "LogicalExpression") {
// handle cases like: `a && b;`
// convert to: `if (a) { b; }`
const test = path.node.expression.left;
const consequent = path.node.expression.right;
const ifStmt = types.ifStatement(
test,
types.blockStatement([types.expressionStatement(consequent)]),
null
);
path.replaceWith(ifStmt);
return;
}
},
IfStatement(path) {
if (!path.node.test || path.node.test.type != "SequenceExpression") {
return;
}
const exprs = path.node.test.expressions;
let exprStmts = exprs.map((e) => {
return types.expressionStatement(e);
});
let lastExpr = exprStmts.pop();
path.node.test = lastExpr.expression;
exprStmts.push(path.node);
path.replaceWithMultiple(exprStmts);
},
ReturnStatement(path) {
if (
!path.node.argument ||
path.node.argument.type != "SequenceExpression"
) {
return;
}
const exprs = path.node.argument.expressions;
let exprStmts = exprs.map((e) => {
return types.expressionStatement(e);
});
let lastExpr = exprStmts.pop();
let returnStmt = types.returnStatement(lastExpr.expression);
exprStmts.push(returnStmt);
path.replaceWithMultiple(exprStmts);
},
VariableDeclaration(path) {
// change `const a = 1, b = 2;` to `const a = 1; const b = 2;`
if (path.node.declarations.length > 1) {
let newDecls = path.node.declarations.map((d) => {
return types.variableDeclaration(path.node.kind, [d]);
});
path.replaceWithMultiple(newDecls);
}
},
};
traverse(ast, moduleTransformer);
return ast;
}
requiremoduleidGPTmapastid
function transformRequire(ast) {
const moduleTransformer = {
VariableDeclaration(path) {
if (path.node.declarations[0].init && path.node.declarations[0].init.type === "CallExpression") {
if (path.node.declarations[0].init.callee.name === "require") {
const moduleId = path.node.declarations[0].init.arguments[0].value;
if (NameMap[moduleId]) {
const { name, path: modulePath} = NameMap[moduleId];
path.node.declarations[0].init.arguments[0].value = '"'+modulePath+'"';
path.scope.rename(path.node.declarations[0].id.name, name);
}
}
}
},
};
traverse(ast, moduleTransformer);
return ast;
}
JS
id91238
VSCodeactivecopilotcontextcontext
copilot
registerGhostText
vscodeInlineCompletionItemProvider
InlineSuggestEnable
documentreturngetGhostText
textscompletionsFromGhostTextResults
completionsTabgetGhostText
const prompt = await extractprompt.extractPrompt(ctx, document, position);
prompt
if ("copilotNotAvailable" === prompt.type) {
exports.ghostTextLogger.debug(
ctx,
"Copilot not available, due to the .copilotignore settings"
);
return {
type: "abortedBeforeIssued",
reason: "Copilot not available due to the .copilotignore settings",
};
}
if ("contextTooShort" === prompt.type) {
exports.ghostTextLogger.debug(ctx, "Breaking, not enough context");
return {
type: "abortedBeforeIssued",
reason: "Not enough context",
};
}
if (token?.isCancellationRequested) {
exports.ghostTextLogger.info(ctx, "Cancelled after extractPrompt");
return {
type: "abortedBeforeIssued",
reason: "Cancelled after extractPrompt",
};
}
copilotprefix``suffix
function updateGlobalCacheKey(prefix, suffix, promptKey) {
prefixCache = prefix;
suffixCache = suffix;
promptKeyCache = promptKey;
}
promptKey``prefix``suffix
copilotprefixsuffix
copilotprompt
copilotLRUprompt100
exports.completionCache = new s.LRUCacheMap(100);
keyForPromptprefixsuffixhash
exports.keyForPrompt = function (e) {
return r.SHA256(e.prefix + e.suffix).toString();
};
promptcopilot
Debounce
contexualFilterScore
copilotdebouncedebouncecopilotdebounce
exports.getDebounceLimit = async function (e, t) {
let n;
if ((await e.get(r.Features).debouncePredict()) && t.measurements.contextualFilterScore) {
const e = t.measurements.contextualFilterScore;
const r = .3475;
const i = 7;
n = 25 + 250 / (1 + Math.pow(e / r, i));
} else n = await e.get(r.Features).debounceMs();
return n > 0 ? n : 75;
};
copilotdebounce75ms
contexualFilterScore
copilot
35%contextualFilterEnable
copilot
Extractprompt
getPrompt
getPromptprompt
copilotVSCodeAB
async fetchExperiments(e, t) {
const n = e.get(r.Fetcher);
let o;
try {
o = await n.fetch("https://default.exp-tas.com/vscode/ab", {
method: "GET",
headers: t
});
} catch (t) {
return i.ExpConfig.createFallbackConfig(e, `Error fetching ExP config: ${t}`);
}
if (!o.ok) return i.ExpConfig.createFallbackConfig(e, `ExP responded with ${o.status}`);
const s = await o.json(),
a = s.Configs.find(e => "vscode" === e.Id) ?? {
Id: "vscode",
Parameters: {}
},
c = Object.entries(a.Parameters).map(([e, t]) => e + (t ? "" : "cf"));
return new i.ExpConfig(a.Parameters, s.AssignmentContext, c.join(";"));
}
abcopilot
Copilot
suffixPercent
15.fimSuffixLengthThreshold
0maxPromptCompletionTokens
2048neighboringTabsOption
eagerneighboringSnippetTypes
NeighboringSnippetsnumberOfSnippets
4snippetPercent
0suffixStartMode
CursorTrimStarttokenizerName
cushman002indentationMinLength
undefinedindentationMaxLength
undefinedcursorContextFix
falsePromptgetPrompt
getPrompt
languageMarker
ToppathMarker
ToplocalImportContext
DeclarationssnippetPosition
TopOfTextlineEnding
ConvertToUnixsuffixMatchThreshold
0suffixMatchCriteria``Levenshtein
cursorSnippetsPickingStrategy``CursorJaccard
CopilotpromptPromptElementKind
BeforeCursor
AfterCursor
SimilarFile
ImportedFile
importLanguageMarkder
PathMarker
CopilotElement
class Priorities {
constructor() {
this.registeredPriorities = [0, 1];
}
register(e) {
if (e > Priorities.TOP || e < Priorities.BOTTOM) throw new Error("Priority must be between 0 and 1");
this.registeredPriorities.push(e);
return e;
}
justAbove(...e) {
const t = Math.max(...e);
const n = Math.min(...this.registeredPriorities.filter(e => e > t));
return this.register((n + t) / 2);
}
justBelow(...e) {
const t = Math.min(...e);
const n = Math.max(...this.registeredPriorities.filter(e => e < t));
return this.register((n + t) / 2);
}
between(e, t) {
if (this.registeredPriorities.some(n => n > e && n < t) || !this.registeredPriorities.includes(e) || !this.registeredPriorities.includes(t)) throw new Error("Priorities must be adjacent in the list of priorities");
return this.register((e + t) / 2);
}
}
justAbovejustBelow
Copilot
const beforeCursorPriority = priorities.justBelow(p.Priorities.TOP);
const languageMarkerPriority =
promptOpts.languageMarker === h.Always
? priorities.justBelow(p.Priorities.TOP)
: priorities.justBelow(beforeCursorPriority);
const pathMarkerPriority =
promptOpts.pathMarker === f.Always ? priorities.justBelow(p.Priorities.TOP) : priorities.justBelow(beforeCursorPriority);
const importedFilePriority = priorities.justBelow(beforeCursorPriority);
const lowSnippetPriority = priorities.justBelow(importedFilePriority);
const highSnippetPriority = priorities.justAbove(beforeCursorPriority);
beforeCursorPriority
0.5languageMarkerPriority
0.25pathMarkderPriority
0.375importedFilePriority
0.4375lowSnippetPriority
0.40625highSnippetPriority
0.75highSnippetPriority
> beforeCursorPriority
> importedFilePriority
> lowSnippetPriority
> pathMarkderPriority
> languageMarkerPriority
languageMarkerpathMarker
languageMarkerpathMarkerpromptWishListlanguageMarkerpathMarker
if (promptOpts.languageMarker !== h.NoMarker) {
const e = newLineEnded(r.getLanguageMarker(resourceInfo));
languageMarkerId = promptWishlist.append(e, p.PromptElementKind.LanguageMarker, languageMarkerPriority);
}
if (promptOpts.pathMarker !== f.NoMarker) {
const e = newLineEnded(r.getPathMarker(resourceInfo));
if (e.length > 0) {
pathMarkerId = promptWishlist.append(e, p.PromptElementKind.PathMarker, pathMarkerPriority);
}
}
getLanguageMarker
```jsx
exports.getLanguageMarker = function (e) {
const {
languageId: t
} = e;
return -1 !== n.indexOf(t) || hasLanguageMarker(e) ? "" : t in r ? r[t] : comment(`Language: ${t}`, t);
};
```
languageIdignoreListcopilot
```jsx
const n = ["php", "plaintext"];
```
MapHTMLPythonRubyShellYAML
```jsx
const r = {
html: "<!DOCTYPE html>",
python: "#!/usr/bin/env python3",
ruby: "#!/usr/bin/env ruby",
shellscript: "#!/bin/sh",
yaml: "# YAML data"
};
```
```jsx
// Language: ${languageId}
```
getPathMarker
```jsx
exports.getPathMarker = function (e) {
return e.relativePath ? comment(`Path: ${e.relativePath}`, e.languageId) : "";
};
```
localImportContext
localImportContext
if (promptOpts.localImportContext !== y.NoContext)
for (const e of await i.extractLocalImportContext(resourceInfo, promptOpts.fs))
promptWishlist.append(newLineEnded(e), p.PromptElementKind.ImportedFile, importedFilePriority);
extractLocalImportContext
const reg = /^\s*import\s*(type|)\s*\{[^}]*\}\s*from\s*['"]\./gm;
exports.extractLocalImportContext = async function (resourceInfo, fs) {
let {
source: source,
uri: uri,
languageId: languageId
} = resourceInfo;
return fs && "typescript" === languageId ? async function (source, uri, fs) {
let language = "typescript";
let result = [];
const importEndIndex = function (source) {
let match;
let lastIndex = -1;
reg.lastIndex = -1;
do {
match = reg.exec(source);
if (match) {
lastIndex = reg.lastIndex + match.length;
}
} while (match);
if (-1 === lastIndex) return -1;
const nextNewLine = source.indexOf("\n", lastIndex);
return -1 !== nextNewLine ? nextNewLine : source.length;
}(source);
if (-1 === importEndIndex) return result;
source = source.substring(0, importEndIndex);
let ast = await i.parseTreeSitter(language, source);
try {
for (let node of function (node) {
let t = [];
for (let childNode of node.namedChildren) if ("import_statement" === childNode.type) {
t.push(childNode);
}
return t;
}(ast.rootNode)) {
let filePath = getTSFilePath(uri, node);
if (!filePath) continue;
let namedImports = parseNamedImport(node);
if (0 === namedImports.length) continue;
let exports = await getExports(filePath, language, fs);
for (let e of namedImports) if (exports.has(e.name)) {
result.push(...exports.get(e.name));
}
}
} finally {
ast.delete();
}
return result;
}(source, uri, fs) : [];
}
TypescriptCopilottsimport
importcopilotwasmtree-sitter
copilotimportnamed importexportexportextract
snippets
snippetsCopilotsnippets
const snippets = [
...retrievalSnippets,
...(promptOpts.neighboringTabs === a.NeighboringTabsOption.None || 0 === neighborDocs.length
? []
: await a.getNeighborSnippets(
resourceInfo,
neighborDocs,
promptOpts.neighboringSnippetTypes,
promptOpts.neighboringTabs,
promptOpts.cursorContextFix,
promptOpts.indentationMinLength,
promptOpts.indentationMaxLength,
promptOpts.snippetSelection,
promptOpts.snippetSelectionK,
lineCursorHistory,
promptOpts.cursorSnippetsPickingStrategy
)),
];
retrievalSnippets``neighboringTabs``eager``getNeighborSnippets
neighborDocs
extract
let neighborDocs = [];
let neighborSource = new Map();
try {
const t = await u.NeighborSource.getNeighborFiles(ctx, uri, repoUserData);
neighborDocs = t.docs;
neighborSource = t.neighborSource;
} catch (t) {
telemetry.telemetryException(ctx, t, "prompt.getPromptForSource.exception");
}
fileTypeOpenTabs
VSCodetab()
exports.OpenTabFiles = class {
constructor(e, t) {
this.docManager = e;
this.neighboringLanguageType = t;
}
async truncateDocs(e, t, n, r) {
const o = [];
let s = 0;
for (const a of e) if (!(s + a.getText().length > i.NeighborSource.MAX_NEIGHBOR_AGGREGATE_LENGTH) && ("file" == a.uri.scheme && a.fileName !== t && i.considerNeighborFile(n, a.languageId, this.neighboringLanguageType) && (o.push({
uri: a.uri.toString(),
relativePath: await this.docManager.getRelativePath(a),
languageId: a.languageId,
source: a.getText()
}), s += a.getText().length), o.length >= r)) break;
return o;
}
async getNeighborFiles(e, t, n, o) {
let s = [];
const a = new Map();
s = await this.truncateDocs(utils2.sortByAccessTimes(this.docManager.textDocuments), e.fsPath, n, o);
a.set(i.NeighboringFileType.OpenTabs, s.map(e => e.uri));
return {
docs: s,
neighborSource: a
};
}
};
getNeighborSnippets
exports.getNeighborSnippets = async function (
resourceInfo,
neighborDocs,
neighboringSnippetTypes,
neighboringTabs,
cursorContextFix,
indentationMinLength,
indentationMaxLength,
snippetSelection,
snippetSelectionK,
lineCursorHistory,
cursorSnippetsPickingStrategy
) {
const options = {
...exports.neighborOptionToSelection[neighboringTabs],
};
const y = (function (
resourceInfo,
neighboringSnippetTypes,
options,
cursorContextFix,
indentationMinLength,
indentationMaxLength,
lineCursorHistory,
cursorSnippetsPickingStrategy = i.CursorSnippetsPickingStrategy
.CursorJaccard
) {
let d;
if (neighboringSnippetTypes === s.NeighboringSnippets) {
d =
void 0 !== indentationMinLength && void 0 !== indentationMaxLength
? o.IndentationBasedJaccardMatcher.FACTORY(
indentationMinLength,
indentationMaxLength,
cursorContextFix
)
: o.FixedWindowSizeJaccardMatcher.FACTORY(
options.snippetLength,
cursorContextFix
);
} else {
if (neighboringSnippetTypes === s.NeighboringFunctions) {
d = o.FunctionJaccardMatcher.FACTORY(
options.snippetLength,
cursorContextFix,
indentationMinLength,
indentationMaxLength
);
} else {
r.ok(
void 0 !== lineCursorHistory,
"lineCursorHistory should not be undefined"
);
d = i.CursorHistoryMatcher.FACTORY(
options.snippetLength,
lineCursorHistory,
cursorSnippetsPickingStrategy,
cursorContextFix
);
}
}
return d.to(resourceInfo);
})(
resourceInfo,
neighboringSnippetTypes,
options,
cursorContextFix,
indentationMinLength,
indentationMaxLength,
lineCursorHistory,
cursorSnippetsPickingStrategy
);
return 0 === options.numberOfSnippets
? []
: (
await neighborDocs
.filter((e) => e.source.length < 1e4 && e.source.length > 0)
.slice(0, 20)
.reduce(
async (e, t) =>
(
await e
).concat(
(
await y.findMatches(t, snippetSelection, snippetSelectionK)
).map((e) => ({
relativePath: t.relativePath,
...e,
}))
),
Promise.resolve([])
)
)
.filter((e) => e.score && e.snippet && e.score > options.threshold)
.sort((e, t) => e.score - t.score)
.slice(-options.numberOfSnippets);
};
FixedWindowSizeJaccardMatcher
FixedWindowSizeJaccardMatcher
class FixedWindowSizeJaccardMatcher extends i.WindowedMatcher {
constructor(resourceInfo, snippetLength, cursorContextFix) {
super(resourceInfo, cursorContextFix);
this.windowLength = snippetLength;
this.cursorContextFix = cursorContextFix;
}
id() {
return "fixed:" + this.windowLength;
}
getWindowsDelineations(e) {
return o.getBasicWindowDelineations(this.windowLength, e);
}
trimDocument(e) {
return e.source.slice(0, e.offset).split("\n").slice(-this.windowLength).join("\n");
}
_getCursorContextInfo(e) {
return r.getCursorContext(e, {
maxLineCount: this.windowLength,
cursorContextFix: this.cursorContextFix
});
}
similarityScore(e, t) {
return computeScore(e, t);
}
}
snippetLength
eager60snippet60
WindowedMatcher
findMatchesWindowedMatcher
async findMatches(e, t = i.SnippetSelectionOption.BestMatch, n) {
if (t == i.SnippetSelectionOption.BestMatch) {
const t = await this.findBestMatch(e);
return t ? [t] : [];
}
return t == i.SnippetSelectionOption.TopK && (await this.findTopKMatches(e, n)) || [];
}
undefinedBestMatch
async findBestMatch(e) {
if (0 === e.source.length || 0 === this.referenceTokens.size) return;
const t = e.source.split("\n");
const n = this.retrieveAllSnippets(e, s.Descending);
return 0 !== n.length && 0 !== n[0].score ? {
snippet: t.slice(n[0].startLine, n[0].endLine).join("\n"),
semantics: o.SnippetSemantics.Snippet,
provider: o.SnippetProvider.NeighboringTabs,
...n[0]
} : void 0;
}
BestMatchretrieveAllSnippets
0snippet
retrieveAllSnippets(e, t = s.Descending) {
const n = [];
if (0 === e.source.length || 0 === this.referenceTokens.size) return n;
const sourceArr = e.source.split("\n");
const key = this.id() + ":" + e.source;
const result = c.get(key) ?? [];
const noCache = 0 == result.length;
const tokens = noCache ? sourceArr.map(this.tokenizer.tokenize, this.tokenizer) : [];
for (const [index, [startLine, endLine]] of this.getWindowsDelineations(sourceArr).entries()) {
if (noCache) {
const e = new Set();
tokens.slice(startLine, endLine).forEach(t => t.forEach(e.add, e));
result.push(e);
}
const r = result[index];
const s = this.similarityScore(r, this.referenceTokens);
n.push({
score: s,
startLine: startLine,
endLine: endLine
});
}
if (noCache) {
c.put(key, result);
}
return this.sortScoredSnippets(n, t);
}
Jaccard
tokenizetoken
const p = new Set(["we", "our", "you", "it", "its", "they", "them", "their", "this", "that", "these", "those", "is", "are", "was", "were", "be", "been", "being", "have", "has", "had", "having", "do", "does", "did", "doing", "can", "don", "t", "s", "will", "would", "should", "what", "which", "who", "when", "where", "why", "how", "a", "an", "the", "and", "or", "not", "no", "but", "because", "as", "until", "again", "further", "then", "once", "here", "there", "all", "any", "both", "each", "few", "more", "most", "other", "some", "such", "above", "below", "to", "during", "before", "after", "of", "at", "by", "about", "between", "into", "through", "from", "up", "down", "in", "out", "on", "off", "over", "under", "only", "own", "same", "so", "than", "too", "very", "just", "now"]);
const d = new Set(["if", "then", "else", "for", "while", "with", "def", "function", "return", "TODO", "import", "try", "catch", "raise", "finally", "repeat", "switch", "case", "match", "assert", "continue", "break", "const", "class", "enum", "struct", "static", "new", "super", "this", "var", ...p]);
tokenize(e) {
return new Set(splitIntoWords(e).filter(e => !this.stopsForLanguage.has(e)));
}
function splitIntoWords(e) {
return e.split(/[^a-zA-Z0-9]/).filter(e => e.length > 0);
}
tokensiffor
getWindowsDelineations
exports.getBasicWindowDelineations = function (e, t) {
const n = [];
const r = t.length;
if (0 == r) return [];
if (r < e) return [[0, r]];
for (let t = 0; t < r - e + 1; t++) n.push([t, t + e]);
return n;
};
getWindowsDelineations
windowSize1windowSize
windowSizesnippet
get referenceTokens() {
if (void 0 === this._referenceTokens) {
this._referenceTokens = this.tokenizer.tokenize(this._getCursorContextInfo(this.referenceDoc).context);
}
return this._referenceTokens;
}
exports.getCursorContext = function e(doc, opts = {}) {
const opts = function (e) {
return {
...i,
...e
};
}(opts);
const s = r.getTokenizer(opts.tokenizerName);
if (void 0 === opts.maxTokenLength && void 0 !== opts.maxLineCount) {
const e = doc.source.slice(0, doc.offset).split("\n").slice(-opts.maxLineCount);
const n = e.join("\n");
return {
context: n,
lineCount: e.length,
tokenLength: s.tokenLength(n),
tokenizerName: opts.tokenizerName
};
}
// ...
};
tokentoken
Jaccard
Copilot**Jaccard
**
function computeScore(e, t) {
const n = new Set();
e.forEach(e => {
if (t.has(e)) {
n.add(e);
}
});
return n.size / (e.size + t.size - n.size);
}
Jaccard
Copilot
copilotprocessSnippetsForWishlistsnippetwishList
function $() {
const maxSnippetLength = Math.round((promptOpts.snippetPercent / 100) * promptOpts.maxPromptLength);
c.processSnippetsForWishlist(
snippets,
resourceInfo.languageId,
tokenizer,
promptOpts.snippetProviderOptions,
{
priorities: priorities,
low: lowSnippetPriority,
high: highSnippetPriority,
},
promptOpts.numberOfSnippets,
maxSnippetLength
).forEach((e) => {
let t = p.PromptElementKind.SimilarFile;
if (e.provider === c.SnippetProvider.Retrieval) {
t = p.PromptElementKind.RetrievalSnippet;
} else {
if (e.provider == c.SnippetProvider.SymbolDef) {
t = p.PromptElementKind.SymbolDefinition;
}
}
promptWishlist.append(e.announcedSnippet, t, e.priority, e.tokens, e.normalizedScore);
});
}
snippetPercent0maxSnippetLength0.
processSnippetsForWishList
exports.processSnippetsForWishlist = function (snippets, languageId, tokenizer, snippetProviderOptions, priorities, numberOfSnippets, maxSnippetLength) {
const {
reserved: reserved,
candidates: candidates
} = selectSnippets(snippets, numberOfSnippets, snippetProviderOptions);
let d = 0;
let h = [];
let highPriorities = priorities.high;
let lowPriorities = priorities.low;
function g(snippet, r) {
const o = announceSnippet(snippet, languageId);
const c = tokenizer.tokenLength(o);
let l;
if (r + c <= maxSnippetLength) {
l = highPriorities;
highPriorities = priorities.priorities.justBelow(l);
} else {
l = lowPriorities;
lowPriorities = priorities.priorities.justBelow(l);
}
h.push({
announcedSnippet: o,
provider: snippet.provider,
providerScore: snippet.providerScore,
normalizedScore: snippet.normalizedScore,
priority: l,
tokens: c,
relativePath: snippet.relativePath
});
return r + c;
}
for (const snippet of [...reserved, ...candidates]) {
if (h.length >= numberOfSnippets) break;
d = g(snippete, d);
}
l(h);
h.reverse();
return h;
};
maxSnippetLengthPrioritylowPriority
scoreannouncedSnippetannounceSnippetPrompt
function announceSnippet(e, t) {
const n = s[e.semantics];
let i = (e.relativePath ? `Compare this ${n} from ${e.relativePath}:` : `Compare this ${n}:`) + "\n" + e.snippet;
if (i.endsWith("\n")) {
i += "\n";
}
return r.commentBlockAsSingles(i, t);
}
snippetCompare this
beforeCursor
beforeCursor
promptWishlist.appendLineForLine(source.substring(0, offset), p.PromptElementKind.BeforeCursor, beforeCursorPriority).forEach((e) =>
V.push(e)
);
appendLineForLineappendappendLineForLine
appendLineForLine(text, kind, priority) {
const lineArr = (lines = this.convertLineEndings(text)).split("\n");
for (let i = 0; i < lineArr.length - 1; i++) lineArr[i] += "\n";
const lines = [];
lineArr.forEach((line) => {
if ("\n" === line && lines.length > 0 && !lines[lines.length - 1].endsWith("\n\n")) {
lines[lines.length - 1] += "\n";
} else {
lines.push(line);
}
});
const result = [];
lines.forEach((text, index) => {
if ("" !== text) {
result.push(this.append(text, kind, priority));
if (index > 0) {
this.content[this.content.length - 2].requires = [
this.content[this.content.length - 1],
];
}
}
});
return result;
}
appendtoken
if (h.Top === promptOpts.languageMarker && V.length > 0 && void 0 !== languageMarkerId) {
promptWishlist.require(languageMarkerId, V[0]);
}
if (f.Top === promptOpts.pathMarker && V.length > 0 && void 0 !== pathMarkerId) {
if (languageMarkerId) {
promptWishlist.require(pathMarkerId, languageMarkerId);
} else {
promptWishlist.require(pathMarkerId, V[0]);
}
}
if (void 0 !== languageMarkerId && void 0 !== pathMarkerId) {
promptWishlist.exclude(pathMarkerId, languageMarkerId);
}
pathMarkerlanguageMarkerpathMarkerlanguageMarkerexcludelanguageMarker
suffixPercent0fullfill
if (0 === promptOpts.suffixPercent || q.length <= promptOpts.fimSuffixLengthThreshold)
return promptWishlist.fulfill(promptOpts.maxPromptLength);
suffixPercent150suffix
fullfillsuffix:
fulfill(maxPromptLength) {
const promptChoices = new PromptChoices();
const promptBackground = new PromptBackground();
const elements = this.content.map((e, t) => ({
element: e,
index: t,
}));
elements.sort((e, t) =>
e.element.priority === t.element.priority
? t.index - e.index
: t.element.priority - e.element.priority
);
const requires = new Set();
const excludes = new Set();
let lastElement;
const results = [];
let promptLength = maxPromptLength;
elements.forEach((e) => {
const element = e.element;
const index = e.index;
if (
promptLength >= 0 &&
(promptLength > 0 || void 0 === lastElement) &&
element.requires.every((e) => requires.has(e.id)) &&
!excludes.has(r.id)
) {
let tokens = element.tokens;
const nextElement = (function (e, t) {
let n;
let r = 1 / 0;
for (const i of e)
if (i.index > t && i.index < r) {
n = i;
r = i.index;
}
return n;
})(results, index)?.element;
if (element.text.endsWith("\n\n") && nextElement && !nextElement.text.match(/^\s/)) {
tokens++;
}
if (promptLength >= tokens) {
promptLength -= tokens;
requires.add(r.id);
element.excludes.forEach((e) => excludes.add(e.id));
promptChoices.markUsed(element);
promptBackground.markUsed(element);
results.push(e);
} else {
if (void 0 === lastElement) {
lastElement = e;
} else {
promptChoices.markUnused(e.element);
promptBackground.markUnused(e.element);
}
}
} else {
promptChoices.markUnused(element);
promptBackground.markUnused(element);
}
});
results.sort((e, t) => e.index - t.index);
let prefix = results.reduce((e, t) => e + t.element.text, "");
let prefixLength = this.tokenizer.tokenLength(prefix);
for (; prefixLength > maxPromptLength; ) {
u.sort((e, t) =>
t.element.priority === e.element.priority
? t.index - e.index
: t.element.priority - e.element.priority
);
const e = u.pop();
if (e) {
promptChoices.undoMarkUsed(e.element);
promptChoices.markUnused(e.element);
promptBackground.undoMarkUsed(e.element);
promptBackground.markUnused(e.element);
if (void 0 !== lastElement) {
promptChoices.markUnused(lastElement.element);
promptBackground.markUnused(lastElement.element);
}
lastElement = void 0;
}
u.sort((e, t) => e.index - t.index);
prefix = u.reduce((e, t) => e + t.element.text, "");
prefixLength = this.tokenizer.tokenLength(prefix);
}
const f = [...u];
if (void 0 !== lastElement) {
f.push(lastElement);
f.sort((e, t) => e.index - t.index);
const prefix = f.reduce((e, t) => e + t.element.text, "");
const prefixLength = this.tokenizer.tokenLength(prefix);
if (prefixLength <= maxPromptLength) {
promptChoices.markUsed(l.element);
promptBackground.markUsed(l.element);
const promptElementRanges = new PromptElementRanges(f);
return {
prefix: prefix,
suffix: "",
prefixLength: prefixLength,
suffixLength: 0,
promptChoices: promptChoices,
promptBackground: promptBackground,
promptElementRanges: promptElementRanges,
};
}
promptChoices.markUnused(l.element);
promptBackground.markUnused(l.element);
}
const m = new PromptElementRanges(u);
return {
prefix: prefix,
suffix: "",
prefixLength: prefixLength,
suffixLength: 0,
promptChoices: promptChoices,
promptBackground: promptBackground,
promptElementRanges: m,
};
}
fullfill
PriorityPriorityindexTokenPriority
indexPriorityprefixwishList
languageMarker
pathMarkder
importedFile
Snippet
beforeCursor
beforeCursor
importedFile
Snippet
pathMarkder
languageMarker
promptprefix
TS
CopilotpromptPath MarkerBeforeCursor
snippet
snippet
Copilot
CopilotGithub