glimmervoid 0.0.0-stage → 0.30.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/LICENSE +48 -0
- package/README.md +195 -2
- package/dist/bin/glimmervoid.js +275 -0
- package/dist/chunks/adapters-Dho1VSY5.js +2 -0
- package/dist/chunks/adapters-zPDx1Xox.js +575 -0
- package/dist/chunks/agent-api-cli-D0MmtEdz.js +71 -0
- package/dist/chunks/agent-api-core-Dz0r21y9.js +103 -0
- package/dist/chunks/agent-setup-cli-B5Atxr3F.js +139 -0
- package/dist/chunks/ascii-figure-core-pDAwtlKO.js +45 -0
- package/dist/chunks/child-process-safe-DRGsp0TE.js +69 -0
- package/dist/chunks/child-process-safe-DvQjXsgz.js +2 -0
- package/dist/chunks/config-path-core-DFt-TemS.js +38 -0
- package/dist/chunks/config-store-CC8T3okC.js +2 -0
- package/dist/chunks/config-store-mm7MgzoL.js +1412 -0
- package/dist/chunks/contracts-DGkKNh9W.js +3020 -0
- package/dist/chunks/grok-DuU8xVLZ.js +436 -0
- package/dist/chunks/hook-command-core-DclEoE9e.js +14 -0
- package/dist/chunks/hook-relay-core-BHfYFnYV.js +88 -0
- package/dist/chunks/hook-tools-pSJia7ks.js +74 -0
- package/dist/chunks/ingest-core-DWI1Mbu4.js +342 -0
- package/dist/chunks/ingest-editor-core-BuI1gMF_.js +445 -0
- package/dist/chunks/loopback-post-C7C22eYi.js +79 -0
- package/dist/chunks/main-CuIZQPhZ.js +43559 -0
- package/dist/chunks/node-pty-preflight-CK1knGIR.js +162 -0
- package/dist/chunks/pair-cli-w-gCAF-1.js +110 -0
- package/dist/chunks/path-doctor-C23VAqeu.js +63 -0
- package/dist/chunks/refocus-core-BKQKllq7.js +38 -0
- package/dist/chunks/relay-stdin-CpHvLu6M.js +20 -0
- package/dist/chunks/remote-config-C2ytQwrs.js +525 -0
- package/dist/chunks/rtk-hook-core-Bl6gYHPN.js +133 -0
- package/dist/chunks/rtk-resolver-CLo-gZzw.js +21 -0
- package/dist/chunks/rtk-resolver-CMQAidlI.js +2 -0
- package/dist/chunks/runtime-paths-Ci_ksSkj.js +75 -0
- package/dist/chunks/runtime-paths-JLrZ3wyi.js +2 -0
- package/dist/chunks/sandbox-deps-Dd5-kZnf.js +67 -0
- package/dist/chunks/session-Cez8aIWg.js +164 -0
- package/dist/chunks/spawn-command-Cc40FiZI.js +134 -0
- package/dist/chunks/visions-cli-BXQFIBCX.js +98 -0
- package/dist/chunks/visions-setup-CvVnOe1r.js +1753 -0
- package/dist/client/assets/favicon-CKygeLwW.svg +7 -0
- package/dist/client/assets/index-B1MFijjb.css +1 -0
- package/dist/client/assets/index-CU1iPPdn.js +249 -0
- package/dist/client/index.html +108 -0
- package/dist/package.json +3 -0
- package/dist/scripts/postinstall-path-check.js +36 -0
- package/dist/server/index.js +92 -0
- package/dist/session/command-hook-relay.js +16 -0
- package/dist/session/hook-relay.js +24 -0
- package/dist/session/hook-tool-relay.js +107 -0
- package/dist/session/statusline-relay.js +82 -0
- package/dist/session/visions-relay.js +627 -0
- package/dist/tools/vscode-visions/extension.js +289 -0
- package/dist/tools/vscode-visions/lsp-convert.js +80 -0
- package/dist/tools/vscode-visions/package.json +32 -0
- package/dist/tools/vscode-visions/visions-lsp-core.js +112 -0
- package/package.json +96 -4
- package/scripts/postinstall.mjs +4 -0
- package/scripts/prepare-build.js +38 -0
- package/scripts/recover-handoff.mjs +82 -0
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
//#region server/core/visions-buffer-core.ts
|
|
2
|
+
function createDocStore() {
|
|
3
|
+
return { docsByUri: Object.create(null) };
|
|
4
|
+
}
|
|
5
|
+
function uriOfParams(params) {
|
|
6
|
+
const uri = params?.textDocument?.uri;
|
|
7
|
+
if (typeof uri === "string" && uri !== "") return uri;
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
function applyDidOpen(store, params) {
|
|
11
|
+
const textDocument = params?.textDocument;
|
|
12
|
+
if (!textDocument || typeof textDocument.uri !== "string" || !textDocument.uri) return {
|
|
13
|
+
applied: false,
|
|
14
|
+
reason: "invalid-params"
|
|
15
|
+
};
|
|
16
|
+
store.docsByUri[textDocument.uri] = {
|
|
17
|
+
uri: textDocument.uri,
|
|
18
|
+
languageId: typeof textDocument.languageId === "string" ? textDocument.languageId : "",
|
|
19
|
+
version: Number(textDocument.version),
|
|
20
|
+
text: typeof textDocument.text === "string" ? textDocument.text : ""
|
|
21
|
+
};
|
|
22
|
+
return { applied: true };
|
|
23
|
+
}
|
|
24
|
+
function lineStartOffsets(text) {
|
|
25
|
+
const starts = [0];
|
|
26
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
27
|
+
const char = text[index];
|
|
28
|
+
if (char === "\n") starts.push(index + 1);
|
|
29
|
+
if (char === "\r" && text[index + 1] !== "\n") starts.push(index + 1);
|
|
30
|
+
}
|
|
31
|
+
return starts;
|
|
32
|
+
}
|
|
33
|
+
function lineOfOffset(lineStarts, offset) {
|
|
34
|
+
let low = 0;
|
|
35
|
+
let high = lineStarts.length - 1;
|
|
36
|
+
while (low < high) {
|
|
37
|
+
const middle = Math.ceil((low + high) / 2);
|
|
38
|
+
if (lineStarts[middle] <= offset) {
|
|
39
|
+
low = middle;
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
high = middle - 1;
|
|
43
|
+
}
|
|
44
|
+
return low + 1;
|
|
45
|
+
}
|
|
46
|
+
function isPositionShape(position) {
|
|
47
|
+
if (!position || typeof position !== "object") return false;
|
|
48
|
+
const candidate = position;
|
|
49
|
+
if (typeof candidate.line !== "number" || !Number.isInteger(candidate.line) || candidate.line < 0) return false;
|
|
50
|
+
return typeof candidate.character === "number" && Number.isInteger(candidate.character) && candidate.character >= 0;
|
|
51
|
+
}
|
|
52
|
+
function lineEndBeforeBreak(text, nextLineStart) {
|
|
53
|
+
const breakIndex = nextLineStart - 1;
|
|
54
|
+
if (breakIndex > 0 && text[breakIndex] === "\n" && text[breakIndex - 1] === "\r") return breakIndex - 1;
|
|
55
|
+
return breakIndex;
|
|
56
|
+
}
|
|
57
|
+
function offsetOfPosition(text, lineStarts, position) {
|
|
58
|
+
if (position.line >= lineStarts.length) return text.length;
|
|
59
|
+
const lineStart = lineStarts[position.line];
|
|
60
|
+
const nextLineStart = lineStarts[position.line + 1];
|
|
61
|
+
const lineEnd = nextLineStart === void 0 ? text.length : lineEndBeforeBreak(text, nextLineStart);
|
|
62
|
+
return Math.min(lineStart + position.character, lineEnd);
|
|
63
|
+
}
|
|
64
|
+
function applyContentChange(text, change) {
|
|
65
|
+
if (!change || typeof change !== "object") return {
|
|
66
|
+
ok: false,
|
|
67
|
+
reason: "invalid-range"
|
|
68
|
+
};
|
|
69
|
+
if (change.range === void 0 || change.range === null) return {
|
|
70
|
+
ok: true,
|
|
71
|
+
text: typeof change.text === "string" ? change.text : ""
|
|
72
|
+
};
|
|
73
|
+
const { range } = change;
|
|
74
|
+
if (typeof range !== "object" || !isPositionShape(range.start) || !isPositionShape(range.end)) return {
|
|
75
|
+
ok: false,
|
|
76
|
+
reason: "invalid-range"
|
|
77
|
+
};
|
|
78
|
+
if (typeof change.text !== "string") return {
|
|
79
|
+
ok: false,
|
|
80
|
+
reason: "invalid-text"
|
|
81
|
+
};
|
|
82
|
+
const lineStarts = lineStartOffsets(text);
|
|
83
|
+
const start = offsetOfPosition(text, lineStarts, range.start);
|
|
84
|
+
const end = offsetOfPosition(text, lineStarts, range.end);
|
|
85
|
+
if (start > end) return {
|
|
86
|
+
ok: false,
|
|
87
|
+
reason: "invalid-range"
|
|
88
|
+
};
|
|
89
|
+
return {
|
|
90
|
+
ok: true,
|
|
91
|
+
text: text.slice(0, start) + change.text + text.slice(end)
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function formatRange(range) {
|
|
95
|
+
if (!range || typeof range !== "object") return "<none>";
|
|
96
|
+
return `${formatPosition(range.start)}-${formatPosition(range.end)}`;
|
|
97
|
+
}
|
|
98
|
+
function formatPosition(position) {
|
|
99
|
+
if (!position || typeof position !== "object") return "?";
|
|
100
|
+
return `${position.line}:${position.character}`;
|
|
101
|
+
}
|
|
102
|
+
function applyDidChange(store, params) {
|
|
103
|
+
const textDocument = params?.textDocument;
|
|
104
|
+
const uri = typeof textDocument?.uri === "string" ? textDocument.uri : "";
|
|
105
|
+
const doc = uri ? store.docsByUri[uri] : null;
|
|
106
|
+
if (!doc) return {
|
|
107
|
+
applied: false,
|
|
108
|
+
reason: "unknown-uri"
|
|
109
|
+
};
|
|
110
|
+
const version = textDocument?.version;
|
|
111
|
+
if (typeof version !== "number" || !Number.isFinite(version)) return {
|
|
112
|
+
applied: false,
|
|
113
|
+
reason: "invalid-version"
|
|
114
|
+
};
|
|
115
|
+
if (typeof doc.version === "number" && version <= doc.version) return {
|
|
116
|
+
applied: false,
|
|
117
|
+
reason: "stale-version",
|
|
118
|
+
version,
|
|
119
|
+
currentVersion: doc.version
|
|
120
|
+
};
|
|
121
|
+
const changes = Array.isArray(params?.contentChanges) ? params.contentChanges : [];
|
|
122
|
+
let text = doc.text;
|
|
123
|
+
const applied = [];
|
|
124
|
+
for (let index = 0; index < changes.length; index += 1) {
|
|
125
|
+
const change = changes[index];
|
|
126
|
+
const spliced = applyContentChange(text, change);
|
|
127
|
+
if (!spliced.ok) return {
|
|
128
|
+
applied: false,
|
|
129
|
+
reason: spliced.reason,
|
|
130
|
+
index,
|
|
131
|
+
range: change?.range ?? null
|
|
132
|
+
};
|
|
133
|
+
applied.push({
|
|
134
|
+
change,
|
|
135
|
+
textBefore: text
|
|
136
|
+
});
|
|
137
|
+
text = spliced.text;
|
|
138
|
+
}
|
|
139
|
+
store.docsByUri[uri] = {
|
|
140
|
+
uri,
|
|
141
|
+
languageId: doc.languageId,
|
|
142
|
+
version,
|
|
143
|
+
text
|
|
144
|
+
};
|
|
145
|
+
return {
|
|
146
|
+
applied: true,
|
|
147
|
+
changeCount: changes.length,
|
|
148
|
+
size: text.length,
|
|
149
|
+
changes: applied
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function isNewlineWithOptionalIndent(text) {
|
|
153
|
+
return typeof text === "string" && /^\r?\n[ \t]*$/.test(text);
|
|
154
|
+
}
|
|
155
|
+
function isLineBlankAtOffset(text, offset) {
|
|
156
|
+
const lineStarts = lineStartOffsets(text);
|
|
157
|
+
let lineIndex = lineStarts.length - 1;
|
|
158
|
+
for (let index = 0; index < lineStarts.length; index += 1) {
|
|
159
|
+
const nextLineStart = lineStarts[index + 1];
|
|
160
|
+
if (nextLineStart !== void 0 && offset >= nextLineStart) continue;
|
|
161
|
+
lineIndex = index;
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
const lineStart = lineStarts[lineIndex];
|
|
165
|
+
const nextLineStart = lineStarts[lineIndex + 1];
|
|
166
|
+
const lineEnd = nextLineStart === void 0 ? text.length : lineEndBeforeBreak(text, nextLineStart);
|
|
167
|
+
return /^[ \t]*$/.test(text.slice(lineStart, lineEnd));
|
|
168
|
+
}
|
|
169
|
+
function isBoundaryInsertion(previousText, nextText, insertionOffset, insertedText) {
|
|
170
|
+
if (!isNewlineWithOptionalIndent(insertedText)) return false;
|
|
171
|
+
if (nextText !== previousText.slice(0, insertionOffset) + insertedText + previousText.slice(insertionOffset)) return false;
|
|
172
|
+
return isLineBlankAtOffset(nextText, insertionOffset + insertedText.length);
|
|
173
|
+
}
|
|
174
|
+
function movedTextRotatedToLineStart({ previousText, offset, movedText }) {
|
|
175
|
+
const lineStarts = lineStartOffsets(previousText);
|
|
176
|
+
let rotatedOffset = offset;
|
|
177
|
+
let rotatedText = movedText;
|
|
178
|
+
while (rotatedOffset > 0 && !lineStarts.includes(rotatedOffset)) {
|
|
179
|
+
const lastMovedChar = rotatedText.at(-1);
|
|
180
|
+
if (lastMovedChar === void 0 || previousText[rotatedOffset - 1] !== lastMovedChar) break;
|
|
181
|
+
rotatedText = `${lastMovedChar}${rotatedText.slice(0, -1)}`;
|
|
182
|
+
rotatedOffset -= 1;
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
offset: rotatedOffset,
|
|
186
|
+
movedText: rotatedText
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
function commonAffixSpan(previousText, nextText) {
|
|
190
|
+
let prefixLength = 0;
|
|
191
|
+
while (prefixLength < previousText.length && prefixLength < nextText.length && previousText[prefixLength] === nextText[prefixLength]) prefixLength += 1;
|
|
192
|
+
let suffixLength = 0;
|
|
193
|
+
while (suffixLength < previousText.length - prefixLength && suffixLength < nextText.length - prefixLength && previousText[previousText.length - 1 - suffixLength] === nextText[nextText.length - 1 - suffixLength]) suffixLength += 1;
|
|
194
|
+
return {
|
|
195
|
+
offset: prefixLength,
|
|
196
|
+
removedText: previousText.slice(prefixLength, previousText.length - suffixLength),
|
|
197
|
+
insertedText: nextText.slice(prefixLength, nextText.length - suffixLength)
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
function replacedSpanOfWholeTextChange(previousText, nextText) {
|
|
201
|
+
if (typeof previousText !== "string" || typeof nextText !== "string") return null;
|
|
202
|
+
if (previousText === nextText) return null;
|
|
203
|
+
const { offset, removedText, insertedText } = commonAffixSpan(previousText, nextText);
|
|
204
|
+
if (removedText !== "" && insertedText !== "") return {
|
|
205
|
+
offset,
|
|
206
|
+
removedText,
|
|
207
|
+
insertedText
|
|
208
|
+
};
|
|
209
|
+
const rotated = movedTextRotatedToLineStart({
|
|
210
|
+
previousText,
|
|
211
|
+
offset,
|
|
212
|
+
movedText: removedText || insertedText
|
|
213
|
+
});
|
|
214
|
+
if (removedText === "") return {
|
|
215
|
+
offset: rotated.offset,
|
|
216
|
+
removedText: "",
|
|
217
|
+
insertedText: rotated.movedText
|
|
218
|
+
};
|
|
219
|
+
return {
|
|
220
|
+
offset: rotated.offset,
|
|
221
|
+
removedText: rotated.movedText,
|
|
222
|
+
insertedText: ""
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
function insertionFromWholeTextChange(previousText, nextText) {
|
|
226
|
+
if (nextText.length <= previousText.length) return null;
|
|
227
|
+
const span = commonAffixSpan(previousText, nextText);
|
|
228
|
+
if (span.removedText !== "") return null;
|
|
229
|
+
return {
|
|
230
|
+
offset: span.offset,
|
|
231
|
+
text: span.insertedText
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
function detectBlankLineBoundary({ previousText, nextText, changes }) {
|
|
235
|
+
if (typeof previousText !== "string" || typeof nextText !== "string") return false;
|
|
236
|
+
if (previousText === nextText) return false;
|
|
237
|
+
if (!Array.isArray(changes) || changes.length !== 1) return false;
|
|
238
|
+
const [change] = changes;
|
|
239
|
+
if (!change || typeof change !== "object") return false;
|
|
240
|
+
if (change.range === void 0 || change.range === null) {
|
|
241
|
+
const insertion = insertionFromWholeTextChange(previousText, nextText);
|
|
242
|
+
if (!insertion) return false;
|
|
243
|
+
return isBoundaryInsertion(previousText, nextText, insertion.offset, insertion.text);
|
|
244
|
+
}
|
|
245
|
+
const { range } = change;
|
|
246
|
+
if (typeof range !== "object" || !isPositionShape(range.start) || !isPositionShape(range.end)) return false;
|
|
247
|
+
if (range.start.line !== range.end.line || range.start.character !== range.end.character) return false;
|
|
248
|
+
return isBoundaryInsertion(previousText, nextText, offsetOfPosition(previousText, lineStartOffsets(previousText), range.start), change.text);
|
|
249
|
+
}
|
|
250
|
+
function applyDidClose(store, params) {
|
|
251
|
+
const textDocument = params?.textDocument;
|
|
252
|
+
const uri = typeof textDocument?.uri === "string" ? textDocument.uri : "";
|
|
253
|
+
if (!uri || !store.docsByUri[uri]) return {
|
|
254
|
+
applied: false,
|
|
255
|
+
reason: "unknown-uri"
|
|
256
|
+
};
|
|
257
|
+
delete store.docsByUri[uri];
|
|
258
|
+
return { applied: true };
|
|
259
|
+
}
|
|
260
|
+
function getDoc(store, uri) {
|
|
261
|
+
const doc = store.docsByUri[uri];
|
|
262
|
+
if (!doc) return null;
|
|
263
|
+
return {
|
|
264
|
+
uri: doc.uri,
|
|
265
|
+
languageId: doc.languageId,
|
|
266
|
+
version: doc.version,
|
|
267
|
+
text: doc.text
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
function listDocs(store) {
|
|
271
|
+
return Object.keys(store.docsByUri).map((uri) => getDoc(store, uri));
|
|
272
|
+
}
|
|
273
|
+
//#endregion
|
|
274
|
+
//#region server/core/visions-scope-core.ts
|
|
275
|
+
function collapseDotSegments(value) {
|
|
276
|
+
const out = [];
|
|
277
|
+
for (const part of value.split("/")) {
|
|
278
|
+
if (part === ".") continue;
|
|
279
|
+
if (part === ".." && out.length > 0 && out[out.length - 1] !== ".." && out[out.length - 1] !== "") {
|
|
280
|
+
out.pop();
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
if (part === ".." && out.length === 1 && out[0] === "") continue;
|
|
284
|
+
out.push(part);
|
|
285
|
+
}
|
|
286
|
+
return out.join("/");
|
|
287
|
+
}
|
|
288
|
+
function normalizeShapePath(input) {
|
|
289
|
+
const raw = String(input == null ? "" : input).trim();
|
|
290
|
+
if (!raw) return "";
|
|
291
|
+
let normalized = raw.replace(/\\/g, "/");
|
|
292
|
+
const isUnc = normalized.startsWith("//");
|
|
293
|
+
normalized = collapseDotSegments(normalized.replace(/\/{2,}/g, "/"));
|
|
294
|
+
if (isUnc) normalized = `/${normalized}`;
|
|
295
|
+
if (normalized.length > 1) normalized = normalized.replace(/\/+$/, "");
|
|
296
|
+
if (isUnc || /^[a-zA-Z]:($|\/)/.test(normalized)) return normalized.toLowerCase();
|
|
297
|
+
return normalized;
|
|
298
|
+
}
|
|
299
|
+
function pathOfFileUri(uri) {
|
|
300
|
+
if (typeof uri !== "string" || !uri) return null;
|
|
301
|
+
let parsed;
|
|
302
|
+
try {
|
|
303
|
+
parsed = new URL(uri);
|
|
304
|
+
} catch {
|
|
305
|
+
return null;
|
|
306
|
+
}
|
|
307
|
+
if (parsed.protocol !== "file:") return null;
|
|
308
|
+
let pathname = "";
|
|
309
|
+
try {
|
|
310
|
+
pathname = decodeURIComponent(parsed.pathname || "");
|
|
311
|
+
} catch {
|
|
312
|
+
return null;
|
|
313
|
+
}
|
|
314
|
+
if (parsed.hostname) return normalizeShapePath(`//${parsed.hostname}${pathname}`);
|
|
315
|
+
const drivePath = pathname.match(/^\/([a-zA-Z]:)(\/.*|$)/);
|
|
316
|
+
if (drivePath) return normalizeShapePath(`${drivePath[1]}${drivePath[2]}`);
|
|
317
|
+
return normalizeShapePath(pathname);
|
|
318
|
+
}
|
|
319
|
+
function isWithin(scopePath, uriPath, foldCase = false) {
|
|
320
|
+
if (!scopePath || !uriPath) return false;
|
|
321
|
+
const scopeKey = foldCase ? scopePath.toLowerCase() : scopePath;
|
|
322
|
+
const uriKey = foldCase ? uriPath.toLowerCase() : uriPath;
|
|
323
|
+
if (uriKey === scopeKey) return true;
|
|
324
|
+
const prefix = scopeKey.endsWith("/") ? scopeKey : `${scopeKey}/`;
|
|
325
|
+
return uriKey.startsWith(prefix);
|
|
326
|
+
}
|
|
327
|
+
function isUriInProjects(uri, normalizedProjectPaths, foldCase = false) {
|
|
328
|
+
const uriPath = pathOfFileUri(uri);
|
|
329
|
+
if (!uriPath) return false;
|
|
330
|
+
return (Array.isArray(normalizedProjectPaths) ? normalizedProjectPaths : []).some((scopePath) => isWithin(scopePath, uriPath, foldCase));
|
|
331
|
+
}
|
|
332
|
+
function deepestRootFor(normalizedPath, roots, foldCase = false) {
|
|
333
|
+
let owner = null;
|
|
334
|
+
for (const raw of Array.isArray(roots) ? roots : []) {
|
|
335
|
+
const root = normalizeShapePath(raw);
|
|
336
|
+
if (!isWithin(root, normalizedPath, foldCase)) continue;
|
|
337
|
+
if (owner && owner.length >= root.length) continue;
|
|
338
|
+
owner = root;
|
|
339
|
+
}
|
|
340
|
+
return owner;
|
|
341
|
+
}
|
|
342
|
+
function projectForUri(uri, scopeProjects, foldCase = false) {
|
|
343
|
+
if (!Array.isArray(scopeProjects) || scopeProjects.length === 0) return null;
|
|
344
|
+
const uriPath = pathOfFileUri(uri);
|
|
345
|
+
if (!uriPath) return null;
|
|
346
|
+
const owned = scopeProjects.filter((entry) => Boolean(entry) && typeof entry.id === "string" && entry.id !== "").map((entry) => ({
|
|
347
|
+
id: entry.id,
|
|
348
|
+
path: normalizeShapePath(entry.path)
|
|
349
|
+
}));
|
|
350
|
+
const root = deepestRootFor(uriPath, owned.map((entry) => entry.path), foldCase);
|
|
351
|
+
const owner = owned.find((entry) => entry.path === root);
|
|
352
|
+
return owner ? owner.id : null;
|
|
353
|
+
}
|
|
354
|
+
function scopePathsOf(scopeProjects) {
|
|
355
|
+
const paths = [];
|
|
356
|
+
for (const entry of Array.isArray(scopeProjects) ? scopeProjects : []) {
|
|
357
|
+
const scopePath = normalizeShapePath(entry?.path);
|
|
358
|
+
if (!scopePath || paths.includes(scopePath)) continue;
|
|
359
|
+
paths.push(scopePath);
|
|
360
|
+
}
|
|
361
|
+
return paths;
|
|
362
|
+
}
|
|
363
|
+
function resolveVisionsScopeProjects({ configuredIds, projects, warn }) {
|
|
364
|
+
const usable = [];
|
|
365
|
+
const seenPaths = /* @__PURE__ */ new Set();
|
|
366
|
+
for (const project of Array.isArray(projects) ? projects : []) {
|
|
367
|
+
if (!project || typeof project.id !== "string" || project.id === "") continue;
|
|
368
|
+
const normalizedPath = normalizeShapePath(project.path);
|
|
369
|
+
if (!normalizedPath || seenPaths.has(normalizedPath)) continue;
|
|
370
|
+
seenPaths.add(normalizedPath);
|
|
371
|
+
usable.push({
|
|
372
|
+
id: project.id,
|
|
373
|
+
path: normalizedPath
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
const ids = Array.isArray(configuredIds) ? configuredIds.filter((id) => typeof id === "string" && id !== "") : [];
|
|
377
|
+
if (ids.length === 0) return usable;
|
|
378
|
+
const wanted = new Set(ids);
|
|
379
|
+
for (const id of ids) if (!usable.some((project) => project.id === id)) warn(`[visions] configured project id not found or has no usable path: ${id}`);
|
|
380
|
+
return usable.filter((project) => wanted.has(project.id));
|
|
381
|
+
}
|
|
382
|
+
//#endregion
|
|
383
|
+
//#region server/core/ingest-editor-core.ts
|
|
384
|
+
var SOURCE = "editor";
|
|
385
|
+
var ACTIVITY_METHOD = "visions/editorActivity";
|
|
386
|
+
var KIND_BY_METHOD = Object.freeze({
|
|
387
|
+
"textDocument/didOpen": "doc-open",
|
|
388
|
+
"textDocument/didSave": "doc-save",
|
|
389
|
+
"textDocument/didClose": "doc-close"
|
|
390
|
+
});
|
|
391
|
+
var VERB_BY_KIND = Object.freeze({
|
|
392
|
+
"doc-open": "opened",
|
|
393
|
+
"doc-save": "saved",
|
|
394
|
+
"doc-close": "closed"
|
|
395
|
+
});
|
|
396
|
+
function createEditorState() {
|
|
397
|
+
return { openUris: /* @__PURE__ */ new Set() };
|
|
398
|
+
}
|
|
399
|
+
function relativeTo(root, normalizedPath) {
|
|
400
|
+
if (!root || root === normalizedPath) return normalizedPath.split("/").pop() || normalizedPath;
|
|
401
|
+
return normalizedPath.slice(root.length + 1);
|
|
402
|
+
}
|
|
403
|
+
function applyEditorNotification(state, { method, uri, roots = [], foldCase = false, now = 0 } = {}) {
|
|
404
|
+
if (typeof method !== "string" || typeof uri !== "string") return {
|
|
405
|
+
state,
|
|
406
|
+
event: null
|
|
407
|
+
};
|
|
408
|
+
const kind = KIND_BY_METHOD[method];
|
|
409
|
+
if (!kind) return {
|
|
410
|
+
state,
|
|
411
|
+
event: null
|
|
412
|
+
};
|
|
413
|
+
const normalizedPath = normalizeShapePath(pathOfFileUri(uri));
|
|
414
|
+
if (!normalizedPath) return {
|
|
415
|
+
state,
|
|
416
|
+
event: null
|
|
417
|
+
};
|
|
418
|
+
if (kind === "doc-open" && state.openUris.has(uri)) return {
|
|
419
|
+
state,
|
|
420
|
+
event: null
|
|
421
|
+
};
|
|
422
|
+
if (kind === "doc-close" && !state.openUris.has(uri)) return {
|
|
423
|
+
state,
|
|
424
|
+
event: null
|
|
425
|
+
};
|
|
426
|
+
if (kind === "doc-open") state.openUris.add(uri);
|
|
427
|
+
if (kind === "doc-close") state.openUris.delete(uri);
|
|
428
|
+
const root = deepestRootFor(normalizedPath, roots, foldCase);
|
|
429
|
+
return {
|
|
430
|
+
state,
|
|
431
|
+
event: {
|
|
432
|
+
source: SOURCE,
|
|
433
|
+
kind,
|
|
434
|
+
ts: now,
|
|
435
|
+
scope: {
|
|
436
|
+
root: root || null,
|
|
437
|
+
sessionId: null
|
|
438
|
+
},
|
|
439
|
+
summary: `${VERB_BY_KIND[kind]} ${relativeTo(root, normalizedPath)}`,
|
|
440
|
+
detail: { path: relativeTo(root, normalizedPath) }
|
|
441
|
+
}
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
//#endregion
|
|
445
|
+
export { listDocs as _, projectForUri as a, uriOfParams as b, applyDidChange as c, createDocStore as d, detectBlankLineBoundary as f, lineStartOffsets as g, lineOfOffset as h, isUriInProjects as i, applyDidClose as l, getDoc as m, applyEditorNotification as n, resolveVisionsScopeProjects as o, formatRange as p, createEditorState as r, scopePathsOf as s, ACTIVITY_METHOD as t, applyDidOpen as u, offsetOfPosition as v, replacedSpanOfWholeTextChange as y };
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import "./hook-relay-core-BHfYFnYV.js";
|
|
2
|
+
import http from "node:http";
|
|
3
|
+
//#region session/loopback-post.ts
|
|
4
|
+
var POST_TIMEOUT_MS = 1500;
|
|
5
|
+
var LOOPBACK_HOSTS = /* @__PURE__ */ new Set([
|
|
6
|
+
"127.0.0.1",
|
|
7
|
+
"::1",
|
|
8
|
+
"[::1]",
|
|
9
|
+
"localhost"
|
|
10
|
+
]);
|
|
11
|
+
function postToLoopback(url, body) {
|
|
12
|
+
return new Promise((resolve) => {
|
|
13
|
+
let settled = false;
|
|
14
|
+
const done = (reason, responseBody = null) => {
|
|
15
|
+
if (settled) return;
|
|
16
|
+
settled = true;
|
|
17
|
+
resolve({
|
|
18
|
+
reason,
|
|
19
|
+
responseBody
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
let target;
|
|
23
|
+
try {
|
|
24
|
+
target = new URL(url);
|
|
25
|
+
} catch {
|
|
26
|
+
done("bad-url");
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (target.protocol !== "http:") {
|
|
30
|
+
done("not-http");
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (!LOOPBACK_HOSTS.has(target.hostname)) {
|
|
34
|
+
done("not-loopback");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const request = http.request({
|
|
39
|
+
hostname: target.hostname,
|
|
40
|
+
port: target.port,
|
|
41
|
+
path: `${target.pathname}${target.search}`,
|
|
42
|
+
method: "POST",
|
|
43
|
+
headers: {
|
|
44
|
+
"content-type": "application/json",
|
|
45
|
+
"content-length": Buffer.byteLength(body)
|
|
46
|
+
}
|
|
47
|
+
}, (response) => {
|
|
48
|
+
const chunks = [];
|
|
49
|
+
let responseBytes = 0;
|
|
50
|
+
response.on("data", (chunk) => {
|
|
51
|
+
if (settled) return;
|
|
52
|
+
responseBytes += chunk.length;
|
|
53
|
+
if (responseBytes > 65536) {
|
|
54
|
+
response.destroy();
|
|
55
|
+
done("response-too-large");
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
chunks.push(chunk);
|
|
59
|
+
});
|
|
60
|
+
response.on("end", () => done(`status-${response.statusCode}`, Buffer.concat(chunks).toString("utf8")));
|
|
61
|
+
response.on("error", () => done("response-error"));
|
|
62
|
+
response.on("close", () => done("response-error"));
|
|
63
|
+
});
|
|
64
|
+
request.on("error", () => done("request-error"));
|
|
65
|
+
request.setTimeout(POST_TIMEOUT_MS, () => {
|
|
66
|
+
request.destroy();
|
|
67
|
+
done("timeout");
|
|
68
|
+
});
|
|
69
|
+
request.end(body);
|
|
70
|
+
} catch {
|
|
71
|
+
done("request-throw");
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
async function postPayload(url, body) {
|
|
76
|
+
return (await postToLoopback(url, body)).responseBody;
|
|
77
|
+
}
|
|
78
|
+
//#endregion
|
|
79
|
+
export { postToLoopback as n, postPayload as t };
|