@oscharko-dev/keiko-server 0.2.8 → 0.2.9
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/.tsbuildinfo +1 -1
- package/dist/chat-handlers.d.ts +18 -2
- package/dist/chat-handlers.d.ts.map +1 -1
- package/dist/chat-handlers.js +185 -3
- package/dist/command-runner-errors.d.ts +17 -0
- package/dist/command-runner-errors.d.ts.map +1 -0
- package/dist/command-runner-errors.js +37 -0
- package/dist/command-runner-evidence.d.ts +23 -0
- package/dist/command-runner-evidence.d.ts.map +1 -0
- package/dist/command-runner-evidence.js +69 -0
- package/dist/command-runner-routes.d.ts +7 -0
- package/dist/command-runner-routes.d.ts.map +1 -0
- package/dist/command-runner-routes.js +175 -0
- package/dist/command-runner.d.ts +29 -0
- package/dist/command-runner.d.ts.map +1 -0
- package/dist/command-runner.js +348 -0
- package/dist/conversation-prompt.d.ts +2 -2
- package/dist/conversation-prompt.d.ts.map +1 -1
- package/dist/conversation-prompt.js +17 -1
- package/dist/csp.d.ts.map +1 -1
- package/dist/csp.js +3 -0
- package/dist/deps.d.ts +27 -1
- package/dist/deps.d.ts.map +1 -1
- package/dist/deps.js +288 -13
- package/dist/discussion-prompt.d.ts +4 -0
- package/dist/discussion-prompt.d.ts.map +1 -0
- package/dist/discussion-prompt.js +19 -0
- package/dist/editor/agentActionAudit.d.ts +18 -0
- package/dist/editor/agentActionAudit.d.ts.map +1 -0
- package/dist/editor/agentActionAudit.js +80 -0
- package/dist/editor/agentRoutes.d.ts +1 -0
- package/dist/editor/agentRoutes.d.ts.map +1 -1
- package/dist/editor/agentRoutes.js +292 -55
- package/dist/editor/agentSessionRegistry.d.ts +35 -0
- package/dist/editor/agentSessionRegistry.d.ts.map +1 -0
- package/dist/editor/agentSessionRegistry.js +243 -0
- package/dist/editor/completionRoutes.d.ts.map +1 -1
- package/dist/editor/completionRoutes.js +5 -10
- package/dist/editor/languageRoutes.d.ts +12 -1
- package/dist/editor/languageRoutes.d.ts.map +1 -1
- package/dist/editor/languageRoutes.js +71 -8
- package/dist/editor/languageService.d.ts +3 -2
- package/dist/editor/languageService.d.ts.map +1 -1
- package/dist/editor/languageService.js +41 -3
- package/dist/editor/languageServiceHost.d.ts.map +1 -1
- package/dist/editor/languageServiceHost.js +2 -2
- package/dist/editor/lsp/hostLanguageOperation.d.ts +17 -0
- package/dist/editor/lsp/hostLanguageOperation.d.ts.map +1 -0
- package/dist/editor/lsp/hostLanguageOperation.js +436 -0
- package/dist/editor/lsp/hostLanguageProviders.d.ts +26 -0
- package/dist/editor/lsp/hostLanguageProviders.d.ts.map +1 -0
- package/dist/editor/lsp/hostLanguageProviders.js +161 -0
- package/dist/editor/lsp/lspFrameCodec.d.ts +13 -0
- package/dist/editor/lsp/lspFrameCodec.d.ts.map +1 -0
- package/dist/editor/lsp/lspFrameCodec.js +164 -0
- package/dist/editor/lsp/lspJsonRpcClient.d.ts +34 -0
- package/dist/editor/lsp/lspJsonRpcClient.d.ts.map +1 -0
- package/dist/editor/lsp/lspJsonRpcClient.js +173 -0
- package/dist/editor/lsp/lspLanguageProvider.d.ts +7 -0
- package/dist/editor/lsp/lspLanguageProvider.d.ts.map +1 -0
- package/dist/editor/lsp/lspLanguageProvider.js +29 -0
- package/dist/editor/lsp/lspLifecycleLedger.d.ts +5 -0
- package/dist/editor/lsp/lspLifecycleLedger.d.ts.map +1 -0
- package/dist/editor/lsp/lspLifecycleLedger.js +37 -0
- package/dist/editor/lsp/lspNodeAdapter.d.ts +31 -0
- package/dist/editor/lsp/lspNodeAdapter.d.ts.map +1 -0
- package/dist/editor/lsp/lspNodeAdapter.js +230 -0
- package/dist/editor/lsp/lspProcessManager.d.ts +24 -0
- package/dist/editor/lsp/lspProcessManager.d.ts.map +1 -0
- package/dist/editor/lsp/lspProcessManager.js +255 -0
- package/dist/editor/lsp/lspRestartThrottle.d.ts +6 -0
- package/dist/editor/lsp/lspRestartThrottle.d.ts.map +1 -0
- package/dist/editor/lsp/lspRestartThrottle.js +24 -0
- package/dist/editor/lsp/lspStatusRoute.d.ts +8 -0
- package/dist/editor/lsp/lspStatusRoute.d.ts.map +1 -0
- package/dist/editor/lsp/lspStatusRoute.js +22 -0
- package/dist/editor/lsp/lspTransport.d.ts +19 -0
- package/dist/editor/lsp/lspTransport.d.ts.map +1 -0
- package/dist/editor/lsp/lspTransport.js +55 -0
- package/dist/editor/lsp/testing/fakeLspProcess.d.ts +23 -0
- package/dist/editor/lsp/testing/fakeLspProcess.d.ts.map +1 -0
- package/dist/editor/lsp/testing/fakeLspProcess.js +132 -0
- package/dist/files.d.ts +45 -0
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js +631 -7
- package/dist/gateway-readiness.js +3 -3
- package/dist/gateway-setup.d.ts +2 -0
- package/dist/gateway-setup.d.ts.map +1 -1
- package/dist/gateway-setup.js +275 -11
- package/dist/gitDelivery/actionSheetProjection.d.ts +30 -0
- package/dist/gitDelivery/actionSheetProjection.d.ts.map +1 -0
- package/dist/gitDelivery/actionSheetProjection.js +206 -0
- package/dist/gitDelivery/actionSheetRoutes.d.ts +29 -0
- package/dist/gitDelivery/actionSheetRoutes.d.ts.map +1 -0
- package/dist/gitDelivery/actionSheetRoutes.js +293 -0
- package/dist/gitDelivery/agentOperationsRoutes.d.ts +33 -0
- package/dist/gitDelivery/agentOperationsRoutes.d.ts.map +1 -0
- package/dist/gitDelivery/agentOperationsRoutes.js +405 -0
- package/dist/gitDelivery/commitRoutes.d.ts +23 -0
- package/dist/gitDelivery/commitRoutes.d.ts.map +1 -0
- package/dist/gitDelivery/commitRoutes.js +204 -0
- package/dist/gitDelivery/evidenceRoutes.d.ts +9 -0
- package/dist/gitDelivery/evidenceRoutes.d.ts.map +1 -0
- package/dist/gitDelivery/evidenceRoutes.js +101 -0
- package/dist/gitDelivery/execution.d.ts +38 -0
- package/dist/gitDelivery/execution.d.ts.map +1 -0
- package/dist/gitDelivery/execution.js +117 -0
- package/dist/gitDelivery/localMutationRoutes.d.ts +30 -0
- package/dist/gitDelivery/localMutationRoutes.d.ts.map +1 -0
- package/dist/gitDelivery/localMutationRoutes.js +165 -0
- package/dist/gitDelivery/mergeExecution.d.ts +63 -0
- package/dist/gitDelivery/mergeExecution.d.ts.map +1 -0
- package/dist/gitDelivery/mergeExecution.js +168 -0
- package/dist/gitDelivery/mergeRoutes.d.ts +12 -0
- package/dist/gitDelivery/mergeRoutes.d.ts.map +1 -0
- package/dist/gitDelivery/mergeRoutes.js +218 -0
- package/dist/gitDelivery/mutationEvidenceLedger.d.ts +23 -0
- package/dist/gitDelivery/mutationEvidenceLedger.d.ts.map +1 -0
- package/dist/gitDelivery/mutationEvidenceLedger.js +87 -0
- package/dist/gitDelivery/prExecution.d.ts +54 -0
- package/dist/gitDelivery/prExecution.d.ts.map +1 -0
- package/dist/gitDelivery/prExecution.js +192 -0
- package/dist/gitDelivery/prRoutes.d.ts +12 -0
- package/dist/gitDelivery/prRoutes.d.ts.map +1 -0
- package/dist/gitDelivery/prRoutes.js +256 -0
- package/dist/gitDelivery/pushExecution.d.ts +43 -0
- package/dist/gitDelivery/pushExecution.d.ts.map +1 -0
- package/dist/gitDelivery/pushExecution.js +124 -0
- package/dist/gitDelivery/pushRoutes.d.ts +12 -0
- package/dist/gitDelivery/pushRoutes.d.ts.map +1 -0
- package/dist/gitDelivery/pushRoutes.js +200 -0
- package/dist/gitDelivery/requestGuards.d.ts +15 -0
- package/dist/gitDelivery/requestGuards.d.ts.map +1 -0
- package/dist/gitDelivery/requestGuards.js +97 -0
- package/dist/gitDelivery/syncEvidence.d.ts +37 -0
- package/dist/gitDelivery/syncEvidence.d.ts.map +1 -0
- package/dist/gitDelivery/syncEvidence.js +85 -0
- package/dist/gitDelivery/syncExecution.d.ts +30 -0
- package/dist/gitDelivery/syncExecution.d.ts.map +1 -0
- package/dist/gitDelivery/syncExecution.js +266 -0
- package/dist/gitDelivery/syncRoutes.d.ts +13 -0
- package/dist/gitDelivery/syncRoutes.d.ts.map +1 -0
- package/dist/gitDelivery/syncRoutes.js +200 -0
- package/dist/gitPorcelainStatus.d.ts +15 -0
- package/dist/gitPorcelainStatus.d.ts.map +1 -0
- package/dist/gitPorcelainStatus.js +104 -0
- package/dist/gitRepositoryReads.d.ts +10 -0
- package/dist/gitRepositoryReads.d.ts.map +1 -0
- package/dist/gitRepositoryReads.js +314 -0
- package/dist/gitRepositoryRoutes.d.ts +7 -0
- package/dist/gitRepositoryRoutes.d.ts.map +1 -0
- package/dist/gitRepositoryRoutes.js +221 -0
- package/dist/gitRoutes.d.ts +66 -0
- package/dist/gitRoutes.d.ts.map +1 -0
- package/dist/gitRoutes.js +543 -0
- package/dist/governed-workflow.d.ts +2 -0
- package/dist/governed-workflow.d.ts.map +1 -1
- package/dist/governed-workflow.js +4 -0
- package/dist/grounded-qa.d.ts +11 -0
- package/dist/grounded-qa.d.ts.map +1 -1
- package/dist/grounded-qa.js +13 -4
- package/dist/headers.d.ts +4 -1
- package/dist/headers.d.ts.map +1 -1
- package/dist/headers.js +11 -4
- package/dist/index.d.ts +8 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/qualityIntelligence/figmaSnapshotRoutes.d.ts +1 -1
- package/dist/qualityIntelligence/figmaSnapshotRoutes.d.ts.map +1 -1
- package/dist/qualityIntelligence/figmaSnapshotRoutes.js +1 -1
- package/dist/read-handlers.d.ts +5 -0
- package/dist/read-handlers.d.ts.map +1 -1
- package/dist/read-handlers.js +57 -1
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +259 -6
- package/dist/run-engine.d.ts.map +1 -1
- package/dist/run-engine.js +3 -0
- package/dist/run-handlers.d.ts.map +1 -1
- package/dist/run-handlers.js +74 -4
- package/dist/run-request.d.ts +11 -0
- package/dist/run-request.d.ts.map +1 -1
- package/dist/run-request.js +158 -10
- package/dist/runtime/capabilityDetector.d.ts +38 -0
- package/dist/runtime/capabilityDetector.d.ts.map +1 -0
- package/dist/runtime/capabilityDetector.js +443 -0
- package/dist/runtime/capabilityRoutes.d.ts +9 -0
- package/dist/runtime/capabilityRoutes.d.ts.map +1 -0
- package/dist/runtime/capabilityRoutes.js +45 -0
- package/dist/runtime/containerEngineDetector.d.ts +17 -0
- package/dist/runtime/containerEngineDetector.d.ts.map +1 -0
- package/dist/runtime/containerEngineDetector.js +222 -0
- package/dist/runtime/containerRoutes.d.ts +8 -0
- package/dist/runtime/containerRoutes.d.ts.map +1 -0
- package/dist/runtime/containerRoutes.js +207 -0
- package/dist/runtime/containerRunner-errors.d.ts +18 -0
- package/dist/runtime/containerRunner-errors.d.ts.map +1 -0
- package/dist/runtime/containerRunner-errors.js +42 -0
- package/dist/runtime/containerRunner-evidence.d.ts +24 -0
- package/dist/runtime/containerRunner-evidence.d.ts.map +1 -0
- package/dist/runtime/containerRunner-evidence.js +74 -0
- package/dist/runtime/containerRunner.d.ts +37 -0
- package/dist/runtime/containerRunner.d.ts.map +1 -0
- package/dist/runtime/containerRunner.js +443 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +24 -4
- package/dist/store/schema.d.ts +1 -1
- package/dist/store/schema.d.ts.map +1 -1
- package/dist/store/schema.js +62 -1
- package/dist/task-workspace/active-store.d.ts +21 -0
- package/dist/task-workspace/active-store.d.ts.map +1 -0
- package/dist/task-workspace/active-store.js +55 -0
- package/dist/task-workspace/authorization.d.ts +7 -0
- package/dist/task-workspace/authorization.d.ts.map +1 -0
- package/dist/task-workspace/authorization.js +54 -0
- package/dist/task-workspace/binding.d.ts +3 -0
- package/dist/task-workspace/binding.d.ts.map +1 -0
- package/dist/task-workspace/binding.js +22 -0
- package/dist/task-workspace/cleanup.d.ts +4 -0
- package/dist/task-workspace/cleanup.d.ts.map +1 -0
- package/dist/task-workspace/cleanup.js +428 -0
- package/dist/task-workspace/errors.d.ts +14 -0
- package/dist/task-workspace/errors.d.ts.map +1 -0
- package/dist/task-workspace/errors.js +81 -0
- package/dist/task-workspace/evidence.d.ts +32 -0
- package/dist/task-workspace/evidence.d.ts.map +1 -0
- package/dist/task-workspace/evidence.js +52 -0
- package/dist/task-workspace/field-safety.d.ts +3 -0
- package/dist/task-workspace/field-safety.d.ts.map +1 -0
- package/dist/task-workspace/field-safety.js +42 -0
- package/dist/task-workspace/health.d.ts +4 -0
- package/dist/task-workspace/health.d.ts.map +1 -0
- package/dist/task-workspace/health.js +163 -0
- package/dist/task-workspace/lifecycle.d.ts +3 -0
- package/dist/task-workspace/lifecycle.d.ts.map +1 -0
- package/dist/task-workspace/lifecycle.js +248 -0
- package/dist/task-workspace/locks.d.ts +13 -0
- package/dist/task-workspace/locks.d.ts.map +1 -0
- package/dist/task-workspace/locks.js +44 -0
- package/dist/task-workspace/managed-root.d.ts +7 -0
- package/dist/task-workspace/managed-root.d.ts.map +1 -0
- package/dist/task-workspace/managed-root.js +98 -0
- package/dist/task-workspace/mutex.d.ts +8 -0
- package/dist/task-workspace/mutex.d.ts.map +1 -0
- package/dist/task-workspace/mutex.js +82 -0
- package/dist/task-workspace/naming.d.ts +15 -0
- package/dist/task-workspace/naming.d.ts.map +1 -0
- package/dist/task-workspace/naming.js +0 -0
- package/dist/task-workspace/provisioning.d.ts +3 -0
- package/dist/task-workspace/provisioning.d.ts.map +1 -0
- package/dist/task-workspace/provisioning.js +528 -0
- package/dist/task-workspace/reconciliation.d.ts +15 -0
- package/dist/task-workspace/reconciliation.d.ts.map +1 -0
- package/dist/task-workspace/reconciliation.js +274 -0
- package/dist/task-workspace/repair.d.ts +3 -0
- package/dist/task-workspace/repair.d.ts.map +1 -0
- package/dist/task-workspace/repair.js +286 -0
- package/dist/task-workspace/routes.d.ts +19 -0
- package/dist/task-workspace/routes.d.ts.map +1 -0
- package/dist/task-workspace/routes.js +481 -0
- package/dist/task-workspace/store.d.ts +12 -0
- package/dist/task-workspace/store.d.ts.map +1 -0
- package/dist/task-workspace/store.js +128 -0
- package/dist/task-workspace/types.d.ts +170 -0
- package/dist/task-workspace/types.d.ts.map +1 -0
- package/dist/task-workspace/types.js +5 -0
- package/dist/voice-action-governance.d.ts +23 -0
- package/dist/voice-action-governance.d.ts.map +1 -0
- package/dist/voice-action-governance.js +126 -0
- package/dist/voice-handlers.d.ts +6 -0
- package/dist/voice-handlers.d.ts.map +1 -0
- package/dist/voice-handlers.js +570 -0
- package/dist/voice-realtime-grounded-tool.d.ts +31 -0
- package/dist/voice-realtime-grounded-tool.d.ts.map +1 -0
- package/dist/voice-realtime-grounded-tool.js +322 -0
- package/dist/voice-realtime.d.ts +69 -0
- package/dist/voice-realtime.d.ts.map +1 -0
- package/dist/voice-realtime.js +787 -0
- package/dist/workspace-state-handlers.d.ts +5 -0
- package/dist/workspace-state-handlers.d.ts.map +1 -0
- package/dist/workspace-state-handlers.js +106 -0
- package/package.json +20 -19
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
import { pathToFileURL } from "node:url";
|
|
2
|
+
import { DEFAULT_LSP_PROCESS_CONFIG, DEFAULT_LANGUAGE_SERVICE_LIMITS, } from "@oscharko-dev/keiko-contracts";
|
|
3
|
+
import { sanitizeCompletion, sanitizeDiagnostics, sanitizeFormatting, sanitizeHover, sanitizeSymbols, } from "../languageSanitize.js";
|
|
4
|
+
import { createLspProcessManager } from "./lspProcessManager.js";
|
|
5
|
+
import { LspProcessError } from "./lspNodeAdapter.js";
|
|
6
|
+
import { detectHostLanguageProviderDescriptors, HOST_LANGUAGE_PROVIDER_SPECS, } from "./hostLanguageProviders.js";
|
|
7
|
+
const MAX_HOST_LSP_OPERATIONS = 1;
|
|
8
|
+
let activeHostLspOperations = 0;
|
|
9
|
+
function successBody(request, result) {
|
|
10
|
+
return { kind: request.operation, result };
|
|
11
|
+
}
|
|
12
|
+
function errorOutcome(code, message) {
|
|
13
|
+
return { kind: "error", code, message };
|
|
14
|
+
}
|
|
15
|
+
function findSpec(languageId) {
|
|
16
|
+
return HOST_LANGUAGE_PROVIDER_SPECS.find((spec) => spec.languages.includes(languageId));
|
|
17
|
+
}
|
|
18
|
+
function makeConfig(spec) {
|
|
19
|
+
return {
|
|
20
|
+
...DEFAULT_LSP_PROCESS_CONFIG,
|
|
21
|
+
managerId: spec.id,
|
|
22
|
+
executableName: spec.executableName,
|
|
23
|
+
executableArgs: spec.executableArgs,
|
|
24
|
+
envAllowlist: spec.envAllowlist,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function matchingAvailableProvider(spec, options) {
|
|
28
|
+
const [descriptor] = detectHostLanguageProviderDescriptors({
|
|
29
|
+
workspace: options.workspace,
|
|
30
|
+
processEnv: options.processEnv,
|
|
31
|
+
commandRules: options.commandRules,
|
|
32
|
+
specs: [spec],
|
|
33
|
+
});
|
|
34
|
+
return descriptor?.availability === "available";
|
|
35
|
+
}
|
|
36
|
+
function mapProcessError(error) {
|
|
37
|
+
if (error instanceof LspProcessError) {
|
|
38
|
+
if (error.code === "CANCELLED") {
|
|
39
|
+
return errorOutcome("CANCELLED", "The request was cancelled.");
|
|
40
|
+
}
|
|
41
|
+
return errorOutcome("TIMED_OUT", "The language provider did not complete within the time budget.");
|
|
42
|
+
}
|
|
43
|
+
return errorOutcome("TIMED_OUT", "The language provider did not complete within the time budget.");
|
|
44
|
+
}
|
|
45
|
+
function acquireHostLspSlot() {
|
|
46
|
+
if (activeHostLspOperations >= MAX_HOST_LSP_OPERATIONS) {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
activeHostLspOperations += 1;
|
|
50
|
+
let released = false;
|
|
51
|
+
return () => {
|
|
52
|
+
if (released)
|
|
53
|
+
return;
|
|
54
|
+
released = true;
|
|
55
|
+
activeHostLspOperations -= 1;
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function delay(ms, signal) {
|
|
59
|
+
if (signal.aborted)
|
|
60
|
+
return Promise.reject(new LspProcessError("CANCELLED"));
|
|
61
|
+
return new Promise((resolve, reject) => {
|
|
62
|
+
const timer = setTimeout(resolve, ms);
|
|
63
|
+
const onAbort = () => {
|
|
64
|
+
clearTimeout(timer);
|
|
65
|
+
reject(new LspProcessError("CANCELLED"));
|
|
66
|
+
};
|
|
67
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
async function waitForReady(manager, initializeTimeoutMs, signal) {
|
|
71
|
+
const deadline = Date.now() + initializeTimeoutMs;
|
|
72
|
+
while (Date.now() <= deadline) {
|
|
73
|
+
const status = manager.getLspProcessStatus();
|
|
74
|
+
if (status === "READY")
|
|
75
|
+
return true;
|
|
76
|
+
if (status === "EXECUTABLE_NOT_FOUND" ||
|
|
77
|
+
status === "SPAWN_FAILED" ||
|
|
78
|
+
status === "INITIALIZE_TIMEOUT" ||
|
|
79
|
+
status === "RESTART_THROTTLED" ||
|
|
80
|
+
status === "CRASHED") {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
await delay(20, signal);
|
|
84
|
+
}
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
function isRecord(value) {
|
|
88
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
89
|
+
}
|
|
90
|
+
function isPosition(value) {
|
|
91
|
+
if (!isRecord(value))
|
|
92
|
+
return false;
|
|
93
|
+
return Number.isInteger(value.line) && Number.isInteger(value.character);
|
|
94
|
+
}
|
|
95
|
+
function isRange(value) {
|
|
96
|
+
if (!isRecord(value))
|
|
97
|
+
return false;
|
|
98
|
+
return isPosition(value.start) && isPosition(value.end);
|
|
99
|
+
}
|
|
100
|
+
function stringValue(value) {
|
|
101
|
+
return typeof value === "string" ? value : undefined;
|
|
102
|
+
}
|
|
103
|
+
const COMPLETION_KIND_BY_LSP = {
|
|
104
|
+
1: "text",
|
|
105
|
+
2: "method",
|
|
106
|
+
3: "function",
|
|
107
|
+
4: "constructor",
|
|
108
|
+
5: "field",
|
|
109
|
+
6: "variable",
|
|
110
|
+
7: "class",
|
|
111
|
+
8: "interface",
|
|
112
|
+
9: "module",
|
|
113
|
+
10: "property",
|
|
114
|
+
12: "value",
|
|
115
|
+
13: "enum",
|
|
116
|
+
14: "keyword",
|
|
117
|
+
15: "snippet",
|
|
118
|
+
21: "constant",
|
|
119
|
+
22: "struct",
|
|
120
|
+
25: "typeParameter",
|
|
121
|
+
};
|
|
122
|
+
const SYMBOL_KIND_BY_LSP = {
|
|
123
|
+
1: "file",
|
|
124
|
+
2: "module",
|
|
125
|
+
3: "namespace",
|
|
126
|
+
5: "class",
|
|
127
|
+
6: "method",
|
|
128
|
+
7: "property",
|
|
129
|
+
8: "field",
|
|
130
|
+
9: "constructor",
|
|
131
|
+
10: "enum",
|
|
132
|
+
11: "interface",
|
|
133
|
+
12: "function",
|
|
134
|
+
13: "variable",
|
|
135
|
+
14: "constant",
|
|
136
|
+
23: "struct",
|
|
137
|
+
22: "enumMember",
|
|
138
|
+
26: "typeParameter",
|
|
139
|
+
};
|
|
140
|
+
function diagnosticSeverity(value) {
|
|
141
|
+
if (value === 1)
|
|
142
|
+
return "error";
|
|
143
|
+
if (value === 2)
|
|
144
|
+
return "warning";
|
|
145
|
+
if (value === 4)
|
|
146
|
+
return "hint";
|
|
147
|
+
return "info";
|
|
148
|
+
}
|
|
149
|
+
function diagnosticCode(value) {
|
|
150
|
+
if (typeof value === "string")
|
|
151
|
+
return value;
|
|
152
|
+
if (typeof value === "number")
|
|
153
|
+
return String(value);
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
function mapDiagnostic(value, source) {
|
|
157
|
+
if (!isRecord(value) || !isRange(value.range) || typeof value.message !== "string") {
|
|
158
|
+
return undefined;
|
|
159
|
+
}
|
|
160
|
+
const code = diagnosticCode(value.code);
|
|
161
|
+
return {
|
|
162
|
+
range: value.range,
|
|
163
|
+
severity: diagnosticSeverity(value.severity),
|
|
164
|
+
message: value.message,
|
|
165
|
+
source: stringValue(value.source) ?? source,
|
|
166
|
+
...(code !== undefined ? { code } : {}),
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
function diagnosticsFromList(value, source) {
|
|
170
|
+
if (!Array.isArray(value))
|
|
171
|
+
return [];
|
|
172
|
+
return value.flatMap((entry) => {
|
|
173
|
+
const diagnostic = mapDiagnostic(entry, source);
|
|
174
|
+
return diagnostic === undefined ? [] : [diagnostic];
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
function diagnosticsFromPullReport(value, source) {
|
|
178
|
+
if (!isRecord(value))
|
|
179
|
+
return [];
|
|
180
|
+
const direct = diagnosticsFromList(value.items, source);
|
|
181
|
+
if (direct.length > 0)
|
|
182
|
+
return direct;
|
|
183
|
+
if (!Array.isArray(value.items))
|
|
184
|
+
return [];
|
|
185
|
+
return value.items.flatMap((item) => isRecord(item) ? diagnosticsFromList(item.items, source) : []);
|
|
186
|
+
}
|
|
187
|
+
function completionDocumentation(value) {
|
|
188
|
+
if (typeof value === "string")
|
|
189
|
+
return value;
|
|
190
|
+
if (isRecord(value) && typeof value.value === "string")
|
|
191
|
+
return value.value;
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
194
|
+
function completionItems(value) {
|
|
195
|
+
if (Array.isArray(value))
|
|
196
|
+
return { items: value, isIncomplete: false };
|
|
197
|
+
if (isRecord(value) && Array.isArray(value.items)) {
|
|
198
|
+
return { items: value.items, isIncomplete: value.isIncomplete === true };
|
|
199
|
+
}
|
|
200
|
+
return { items: [], isIncomplete: false };
|
|
201
|
+
}
|
|
202
|
+
function completionKind(value) {
|
|
203
|
+
return typeof value === "number" ? (COMPLETION_KIND_BY_LSP[value] ?? "text") : "text";
|
|
204
|
+
}
|
|
205
|
+
function completionInsertText(value) {
|
|
206
|
+
const textEdit = isRecord(value.textEdit) ? stringValue(value.textEdit.newText) : undefined;
|
|
207
|
+
return stringValue(value.insertText) ?? textEdit;
|
|
208
|
+
}
|
|
209
|
+
function mapCompletionItem(value) {
|
|
210
|
+
if (!isRecord(value) || typeof value.label !== "string")
|
|
211
|
+
return undefined;
|
|
212
|
+
const insertText = completionInsertText(value);
|
|
213
|
+
const detail = stringValue(value.detail);
|
|
214
|
+
const documentation = completionDocumentation(value.documentation);
|
|
215
|
+
const sortText = stringValue(value.sortText);
|
|
216
|
+
return {
|
|
217
|
+
label: value.label,
|
|
218
|
+
kind: completionKind(value.kind),
|
|
219
|
+
...(detail !== undefined ? { detail } : {}),
|
|
220
|
+
...(documentation !== undefined ? { documentation } : {}),
|
|
221
|
+
...(insertText !== undefined ? { insertText } : {}),
|
|
222
|
+
...(sortText !== undefined ? { sortText } : {}),
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
function hoverContents(value) {
|
|
226
|
+
if (typeof value === "string")
|
|
227
|
+
return value;
|
|
228
|
+
if (Array.isArray(value))
|
|
229
|
+
return value.map(hoverContents).filter(Boolean).join("\n\n") || null;
|
|
230
|
+
if (isRecord(value) && typeof value.value === "string")
|
|
231
|
+
return value.value;
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
function mapHover(value) {
|
|
235
|
+
if (!isRecord(value))
|
|
236
|
+
return { contents: null };
|
|
237
|
+
return {
|
|
238
|
+
contents: hoverContents(value.contents),
|
|
239
|
+
...(isRange(value.range) ? { range: value.range } : {}),
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
function symbolKind(value) {
|
|
243
|
+
return typeof value === "number" ? (SYMBOL_KIND_BY_LSP[value] ?? "variable") : "variable";
|
|
244
|
+
}
|
|
245
|
+
function mapDocumentSymbol(value, containerName) {
|
|
246
|
+
if (!isRecord(value) || typeof value.name !== "string")
|
|
247
|
+
return [];
|
|
248
|
+
if (!isRange(value.range))
|
|
249
|
+
return [];
|
|
250
|
+
const name = value.name;
|
|
251
|
+
const detail = stringValue(value.detail);
|
|
252
|
+
const current = {
|
|
253
|
+
name,
|
|
254
|
+
kind: symbolKind(value.kind),
|
|
255
|
+
range: value.range,
|
|
256
|
+
...(detail !== undefined ? { detail } : {}),
|
|
257
|
+
...(containerName !== undefined ? { containerName } : {}),
|
|
258
|
+
};
|
|
259
|
+
const children = Array.isArray(value.children)
|
|
260
|
+
? value.children.flatMap((child) => mapDocumentSymbol(child, name))
|
|
261
|
+
: [];
|
|
262
|
+
return [current, ...children];
|
|
263
|
+
}
|
|
264
|
+
function mapSymbolInformation(value) {
|
|
265
|
+
if (!isRecord(value) || typeof value.name !== "string" || !isRecord(value.location))
|
|
266
|
+
return [];
|
|
267
|
+
const range = isRange(value.location.range) ? value.location.range : undefined;
|
|
268
|
+
if (range === undefined)
|
|
269
|
+
return [];
|
|
270
|
+
const containerName = stringValue(value.containerName);
|
|
271
|
+
return [
|
|
272
|
+
{
|
|
273
|
+
name: value.name,
|
|
274
|
+
kind: symbolKind(value.kind),
|
|
275
|
+
range,
|
|
276
|
+
...(containerName !== undefined ? { containerName } : {}),
|
|
277
|
+
},
|
|
278
|
+
];
|
|
279
|
+
}
|
|
280
|
+
function symbolsFromResult(value) {
|
|
281
|
+
if (!Array.isArray(value))
|
|
282
|
+
return [];
|
|
283
|
+
return value.flatMap((entry) => {
|
|
284
|
+
const documentSymbols = mapDocumentSymbol(entry);
|
|
285
|
+
return documentSymbols.length > 0 ? documentSymbols : mapSymbolInformation(entry);
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
function textEditsFromResult(value) {
|
|
289
|
+
if (!Array.isArray(value))
|
|
290
|
+
return [];
|
|
291
|
+
return value.flatMap((entry) => {
|
|
292
|
+
if (!isRecord(entry) || !isRange(entry.range) || typeof entry.newText !== "string")
|
|
293
|
+
return [];
|
|
294
|
+
return [{ range: entry.range, newText: entry.newText }];
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
function textDocumentParams(ctx) {
|
|
298
|
+
return { textDocument: { uri: ctx.uri } };
|
|
299
|
+
}
|
|
300
|
+
async function runDiagnostics(ctx) {
|
|
301
|
+
let published = [];
|
|
302
|
+
ctx.manager.onNotification((method, params) => {
|
|
303
|
+
if (method !== "textDocument/publishDiagnostics" || !isRecord(params))
|
|
304
|
+
return;
|
|
305
|
+
if (params.uri !== ctx.uri)
|
|
306
|
+
return;
|
|
307
|
+
published = diagnosticsFromList(params.diagnostics, ctx.spec.id);
|
|
308
|
+
});
|
|
309
|
+
ctx.manager.sendNotification("textDocument/didOpen", didOpenParams(ctx));
|
|
310
|
+
let pulled = [];
|
|
311
|
+
try {
|
|
312
|
+
const result = await ctx.manager.sendRequest("textDocument/diagnostic", textDocumentParams(ctx), ctx.signal);
|
|
313
|
+
pulled = diagnosticsFromPullReport(result, ctx.spec.id);
|
|
314
|
+
}
|
|
315
|
+
catch {
|
|
316
|
+
await delay(50, ctx.signal);
|
|
317
|
+
}
|
|
318
|
+
const diagnostics = pulled.length > 0 ? pulled : published;
|
|
319
|
+
return successBody(ctx.request, sanitizeDiagnostics({ diagnostics, truncated: false }, ctx.limits));
|
|
320
|
+
}
|
|
321
|
+
async function runCompletion(ctx) {
|
|
322
|
+
const request = ctx.request;
|
|
323
|
+
ctx.manager.sendNotification("textDocument/didOpen", didOpenParams(ctx));
|
|
324
|
+
const result = await ctx.manager.sendRequest("textDocument/completion", { ...textDocumentParams(ctx), position: request.position, context: { triggerKind: 1 } }, ctx.signal);
|
|
325
|
+
const completion = completionItems(result);
|
|
326
|
+
return successBody(ctx.request, sanitizeCompletion({
|
|
327
|
+
items: completion.items.flatMap((entry) => {
|
|
328
|
+
const item = mapCompletionItem(entry);
|
|
329
|
+
return item === undefined ? [] : [item];
|
|
330
|
+
}),
|
|
331
|
+
isIncomplete: completion.isIncomplete,
|
|
332
|
+
truncated: false,
|
|
333
|
+
}, ctx.limits));
|
|
334
|
+
}
|
|
335
|
+
async function runHover(ctx) {
|
|
336
|
+
const request = ctx.request;
|
|
337
|
+
ctx.manager.sendNotification("textDocument/didOpen", didOpenParams(ctx));
|
|
338
|
+
const result = await ctx.manager.sendRequest("textDocument/hover", { ...textDocumentParams(ctx), position: request.position }, ctx.signal);
|
|
339
|
+
return successBody(ctx.request, sanitizeHover(mapHover(result), ctx.limits));
|
|
340
|
+
}
|
|
341
|
+
async function runSymbols(ctx) {
|
|
342
|
+
ctx.manager.sendNotification("textDocument/didOpen", didOpenParams(ctx));
|
|
343
|
+
const result = await ctx.manager.sendRequest("textDocument/documentSymbol", textDocumentParams(ctx), ctx.signal);
|
|
344
|
+
return successBody(ctx.request, sanitizeSymbols({ symbols: symbolsFromResult(result), truncated: false }, ctx.limits));
|
|
345
|
+
}
|
|
346
|
+
async function runFormatting(ctx) {
|
|
347
|
+
const request = ctx.request;
|
|
348
|
+
ctx.manager.sendNotification("textDocument/didOpen", didOpenParams(ctx));
|
|
349
|
+
const options = request.options ?? {};
|
|
350
|
+
const result = await ctx.manager.sendRequest("textDocument/formatting", {
|
|
351
|
+
...textDocumentParams(ctx),
|
|
352
|
+
options: { tabSize: options.tabSize ?? 2, insertSpaces: options.insertSpaces ?? true },
|
|
353
|
+
}, ctx.signal);
|
|
354
|
+
return successBody(ctx.request, sanitizeFormatting({ edits: textEditsFromResult(result), truncated: false }, ctx.limits));
|
|
355
|
+
}
|
|
356
|
+
function didOpenParams(ctx) {
|
|
357
|
+
return {
|
|
358
|
+
textDocument: {
|
|
359
|
+
uri: ctx.uri,
|
|
360
|
+
languageId: ctx.request.document.languageId,
|
|
361
|
+
version: 1,
|
|
362
|
+
text: ctx.request.document.text,
|
|
363
|
+
},
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
function didCloseParams(ctx) {
|
|
367
|
+
return { textDocument: { uri: ctx.uri } };
|
|
368
|
+
}
|
|
369
|
+
async function runLspRequest(ctx) {
|
|
370
|
+
try {
|
|
371
|
+
switch (ctx.request.operation) {
|
|
372
|
+
case "diagnostics":
|
|
373
|
+
return await runDiagnostics(ctx);
|
|
374
|
+
case "completion":
|
|
375
|
+
return await runCompletion(ctx);
|
|
376
|
+
case "hover":
|
|
377
|
+
return await runHover(ctx);
|
|
378
|
+
case "symbols":
|
|
379
|
+
return await runSymbols(ctx);
|
|
380
|
+
case "formatting":
|
|
381
|
+
return await runFormatting(ctx);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
finally {
|
|
385
|
+
ctx.manager.sendNotification("textDocument/didClose", didCloseParams(ctx));
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
export async function runHostLanguageOperation(request, options) {
|
|
389
|
+
const spec = findSpec(request.document.languageId);
|
|
390
|
+
if (spec === undefined)
|
|
391
|
+
return undefined;
|
|
392
|
+
if (!spec.operations.includes(request.operation)) {
|
|
393
|
+
return errorOutcome("UNSUPPORTED_OPERATION", "The provider does not serve this operation.");
|
|
394
|
+
}
|
|
395
|
+
if (!matchingAvailableProvider(spec, options))
|
|
396
|
+
return undefined;
|
|
397
|
+
const releaseSlot = acquireHostLspSlot();
|
|
398
|
+
if (releaseSlot === undefined) {
|
|
399
|
+
return errorOutcome("TIMED_OUT", "The language provider is busy.");
|
|
400
|
+
}
|
|
401
|
+
const limits = options.limits ?? DEFAULT_LANGUAGE_SERVICE_LIMITS;
|
|
402
|
+
const config = makeConfig(spec);
|
|
403
|
+
const manager = createLspProcessManager({
|
|
404
|
+
config,
|
|
405
|
+
workspace: options.workspace,
|
|
406
|
+
processEnv: options.processEnv,
|
|
407
|
+
commandRules: options.commandRules,
|
|
408
|
+
now: options.now,
|
|
409
|
+
...(options.spawn !== undefined ? { spawn: options.spawn } : {}),
|
|
410
|
+
});
|
|
411
|
+
try {
|
|
412
|
+
if (!(await waitForReady(manager, config.initializeTimeoutMs, options.signal))) {
|
|
413
|
+
return errorOutcome("TIMED_OUT", "The language provider did not complete within the time budget.");
|
|
414
|
+
}
|
|
415
|
+
manager.sendNotification("initialized", {});
|
|
416
|
+
return await runLspRequest({
|
|
417
|
+
spec,
|
|
418
|
+
manager,
|
|
419
|
+
request,
|
|
420
|
+
uri: pathToFileURL(options.overlayAbsolutePath).href,
|
|
421
|
+
signal: options.signal,
|
|
422
|
+
limits,
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
catch (error) {
|
|
426
|
+
return mapProcessError(error);
|
|
427
|
+
}
|
|
428
|
+
finally {
|
|
429
|
+
try {
|
|
430
|
+
await manager.dispose();
|
|
431
|
+
}
|
|
432
|
+
finally {
|
|
433
|
+
releaseSlot();
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type LanguageProviderDescriptor, type LanguageServiceOperation } from "@oscharko-dev/keiko-contracts";
|
|
2
|
+
import { type CommandRule } from "@oscharko-dev/keiko-tools";
|
|
3
|
+
import type { WorkspaceInfo } from "@oscharko-dev/keiko-workspace";
|
|
4
|
+
export interface HostLanguageProviderSpec {
|
|
5
|
+
readonly id: string;
|
|
6
|
+
readonly label: string;
|
|
7
|
+
readonly languages: readonly string[];
|
|
8
|
+
readonly operations: readonly LanguageServiceOperation[];
|
|
9
|
+
readonly executableName: string;
|
|
10
|
+
readonly executableArgs: readonly string[];
|
|
11
|
+
readonly requiredExecutables: readonly string[];
|
|
12
|
+
readonly envAllowlist: readonly string[];
|
|
13
|
+
readonly envFlag: string;
|
|
14
|
+
}
|
|
15
|
+
export interface HostLanguageProviderDetectionDeps {
|
|
16
|
+
readonly workspace: WorkspaceInfo;
|
|
17
|
+
readonly processEnv: NodeJS.ProcessEnv;
|
|
18
|
+
readonly commandRules: readonly CommandRule[];
|
|
19
|
+
readonly specs?: readonly HostLanguageProviderSpec[] | undefined;
|
|
20
|
+
}
|
|
21
|
+
export declare const HOST_LSP_MISSING_REASON: "Required host language tool is missing or resolves inside the workspace.";
|
|
22
|
+
export declare const HOST_LSP_POLICY_BLOCKED_REASON: "Required host language tool is blocked by host execution policy.";
|
|
23
|
+
export declare const HOST_LSP_DISABLED_REASON: "Host language provider is disabled by policy.";
|
|
24
|
+
export declare const HOST_LANGUAGE_PROVIDER_SPECS: readonly HostLanguageProviderSpec[];
|
|
25
|
+
export declare function detectHostLanguageProviderDescriptors(deps: HostLanguageProviderDetectionDeps): readonly LanguageProviderDescriptor[];
|
|
26
|
+
//# sourceMappingURL=hostLanguageProviders.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hostLanguageProviders.d.ts","sourceRoot":"","sources":["../../../src/editor/lsp/hostLanguageProviders.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,0BAA0B,EAC/B,KAAK,wBAAwB,EAC9B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAGnE,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,UAAU,EAAE,SAAS,wBAAwB,EAAE,CAAC;IACzD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,QAAQ,CAAC,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAC;IAChD,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,iCAAiC;IAChD,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;IACvC,QAAQ,CAAC,YAAY,EAAE,SAAS,WAAW,EAAE,CAAC;IAC9C,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,wBAAwB,EAAE,GAAG,SAAS,CAAC;CAClE;AAED,eAAO,MAAM,uBAAuB,EAClC,0EAAmF,CAAC;AACtF,eAAO,MAAM,8BAA8B,EACzC,kEAA2E,CAAC;AAC9E,eAAO,MAAM,wBAAwB,EAAG,+CAAwD,CAAC;AAiBjG,eAAO,MAAM,4BAA4B,EAAE,SAAS,wBAAwB,EAoF1E,CAAC;AA0EH,wBAAgB,qCAAqC,CACnD,IAAI,EAAE,iCAAiC,GACtC,SAAS,0BAA0B,EAAE,CAEvC"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { DEFAULT_LSP_PROCESS_CONFIG, } from "@oscharko-dev/keiko-contracts";
|
|
2
|
+
import { isCommandAllowed } from "@oscharko-dev/keiko-tools";
|
|
3
|
+
import { resolveExecutableOutsideWorkspace } from "./lspNodeAdapter.js";
|
|
4
|
+
export const HOST_LSP_MISSING_REASON = "Required host language tool is missing or resolves inside the workspace.";
|
|
5
|
+
export const HOST_LSP_POLICY_BLOCKED_REASON = "Required host language tool is blocked by host execution policy.";
|
|
6
|
+
export const HOST_LSP_DISABLED_REASON = "Host language provider is disabled by policy.";
|
|
7
|
+
const DEFAULT_HOST_LSP_ENV_ALLOWLIST = Object.freeze([
|
|
8
|
+
...DEFAULT_LSP_PROCESS_CONFIG.envAllowlist,
|
|
9
|
+
"TMPDIR",
|
|
10
|
+
"TEMP",
|
|
11
|
+
"TMP",
|
|
12
|
+
"PYTHONPATH",
|
|
13
|
+
"VIRTUAL_ENV",
|
|
14
|
+
"GOMODCACHE",
|
|
15
|
+
"GOCACHE",
|
|
16
|
+
"GOPATH",
|
|
17
|
+
"JAVA_HOME",
|
|
18
|
+
"RUSTUP_HOME",
|
|
19
|
+
"CARGO_HOME",
|
|
20
|
+
]);
|
|
21
|
+
export const HOST_LANGUAGE_PROVIDER_SPECS = Object.freeze([
|
|
22
|
+
Object.freeze({
|
|
23
|
+
id: "python-lsp",
|
|
24
|
+
label: "Pyright",
|
|
25
|
+
languages: Object.freeze(["python"]),
|
|
26
|
+
operations: Object.freeze([
|
|
27
|
+
"diagnostics",
|
|
28
|
+
"completion",
|
|
29
|
+
"hover",
|
|
30
|
+
"symbols",
|
|
31
|
+
]),
|
|
32
|
+
executableName: "pyright-langserver",
|
|
33
|
+
executableArgs: Object.freeze(["--stdio"]),
|
|
34
|
+
requiredExecutables: Object.freeze(["pyright-langserver"]),
|
|
35
|
+
envAllowlist: DEFAULT_HOST_LSP_ENV_ALLOWLIST,
|
|
36
|
+
envFlag: "KEIKO_EDITOR_LSP_PYTHON",
|
|
37
|
+
}),
|
|
38
|
+
Object.freeze({
|
|
39
|
+
id: "java-lsp",
|
|
40
|
+
label: "Eclipse JDT LS",
|
|
41
|
+
languages: Object.freeze(["java"]),
|
|
42
|
+
operations: Object.freeze([
|
|
43
|
+
"diagnostics",
|
|
44
|
+
"completion",
|
|
45
|
+
"hover",
|
|
46
|
+
"symbols",
|
|
47
|
+
"formatting",
|
|
48
|
+
]),
|
|
49
|
+
executableName: "jdtls",
|
|
50
|
+
executableArgs: Object.freeze([]),
|
|
51
|
+
requiredExecutables: Object.freeze(["java", "jdtls"]),
|
|
52
|
+
envAllowlist: DEFAULT_HOST_LSP_ENV_ALLOWLIST,
|
|
53
|
+
envFlag: "KEIKO_EDITOR_LSP_JAVA",
|
|
54
|
+
}),
|
|
55
|
+
Object.freeze({
|
|
56
|
+
id: "go-lsp",
|
|
57
|
+
label: "gopls",
|
|
58
|
+
languages: Object.freeze(["go"]),
|
|
59
|
+
operations: Object.freeze([
|
|
60
|
+
"diagnostics",
|
|
61
|
+
"completion",
|
|
62
|
+
"hover",
|
|
63
|
+
"symbols",
|
|
64
|
+
"formatting",
|
|
65
|
+
]),
|
|
66
|
+
executableName: "gopls",
|
|
67
|
+
executableArgs: Object.freeze([]),
|
|
68
|
+
requiredExecutables: Object.freeze(["gopls"]),
|
|
69
|
+
envAllowlist: DEFAULT_HOST_LSP_ENV_ALLOWLIST,
|
|
70
|
+
envFlag: "KEIKO_EDITOR_LSP_GO",
|
|
71
|
+
}),
|
|
72
|
+
Object.freeze({
|
|
73
|
+
id: "rust-lsp",
|
|
74
|
+
label: "rust-analyzer",
|
|
75
|
+
languages: Object.freeze(["rust"]),
|
|
76
|
+
operations: Object.freeze([
|
|
77
|
+
"diagnostics",
|
|
78
|
+
"completion",
|
|
79
|
+
"hover",
|
|
80
|
+
"symbols",
|
|
81
|
+
"formatting",
|
|
82
|
+
]),
|
|
83
|
+
executableName: "rust-analyzer",
|
|
84
|
+
executableArgs: Object.freeze([]),
|
|
85
|
+
requiredExecutables: Object.freeze(["rust-analyzer"]),
|
|
86
|
+
envAllowlist: DEFAULT_HOST_LSP_ENV_ALLOWLIST,
|
|
87
|
+
envFlag: "KEIKO_EDITOR_LSP_RUST",
|
|
88
|
+
}),
|
|
89
|
+
Object.freeze({
|
|
90
|
+
id: "shell-lsp",
|
|
91
|
+
label: "Bash Language Server",
|
|
92
|
+
languages: Object.freeze(["shell"]),
|
|
93
|
+
operations: Object.freeze([
|
|
94
|
+
"diagnostics",
|
|
95
|
+
"completion",
|
|
96
|
+
"hover",
|
|
97
|
+
"symbols",
|
|
98
|
+
]),
|
|
99
|
+
executableName: "bash-language-server",
|
|
100
|
+
executableArgs: Object.freeze(["start"]),
|
|
101
|
+
requiredExecutables: Object.freeze(["bash-language-server", "shellcheck"]),
|
|
102
|
+
envAllowlist: DEFAULT_HOST_LSP_ENV_ALLOWLIST,
|
|
103
|
+
envFlag: "KEIKO_EDITOR_LSP_SHELL",
|
|
104
|
+
}),
|
|
105
|
+
]);
|
|
106
|
+
function trueLike(value) {
|
|
107
|
+
return ["1", "true", "on", "yes", "enabled"].includes(value.trim().toLowerCase());
|
|
108
|
+
}
|
|
109
|
+
function providerEnabled(spec, processEnv) {
|
|
110
|
+
const value = processEnv[spec.envFlag];
|
|
111
|
+
return value !== undefined && trueLike(value);
|
|
112
|
+
}
|
|
113
|
+
function unavailableDescriptor(spec, reason) {
|
|
114
|
+
return {
|
|
115
|
+
id: spec.id,
|
|
116
|
+
languages: spec.languages,
|
|
117
|
+
operations: spec.operations,
|
|
118
|
+
availability: "unavailable",
|
|
119
|
+
unavailableReason: reason,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function availableDescriptor(spec) {
|
|
123
|
+
return {
|
|
124
|
+
id: spec.id,
|
|
125
|
+
languages: spec.languages,
|
|
126
|
+
operations: spec.operations,
|
|
127
|
+
availability: "available",
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
function commandAllowed(commandRules, executable, args) {
|
|
131
|
+
return isCommandAllowed(commandRules, executable, args).allowed;
|
|
132
|
+
}
|
|
133
|
+
function requiredExecutableAvailable(executable, deps) {
|
|
134
|
+
try {
|
|
135
|
+
resolveExecutableOutsideWorkspace(executable, deps.workspace, deps.processEnv);
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function detectSpec(spec, deps) {
|
|
143
|
+
if (!providerEnabled(spec, deps.processEnv)) {
|
|
144
|
+
return unavailableDescriptor(spec, HOST_LSP_DISABLED_REASON);
|
|
145
|
+
}
|
|
146
|
+
if (!commandAllowed(deps.commandRules, spec.executableName, spec.executableArgs)) {
|
|
147
|
+
return unavailableDescriptor(spec, HOST_LSP_POLICY_BLOCKED_REASON);
|
|
148
|
+
}
|
|
149
|
+
for (const executable of spec.requiredExecutables) {
|
|
150
|
+
if (!commandAllowed(deps.commandRules, executable, [])) {
|
|
151
|
+
return unavailableDescriptor(spec, HOST_LSP_POLICY_BLOCKED_REASON);
|
|
152
|
+
}
|
|
153
|
+
if (!requiredExecutableAvailable(executable, deps)) {
|
|
154
|
+
return unavailableDescriptor(spec, HOST_LSP_MISSING_REASON);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return availableDescriptor(spec);
|
|
158
|
+
}
|
|
159
|
+
export function detectHostLanguageProviderDescriptors(deps) {
|
|
160
|
+
return (deps.specs ?? HOST_LANGUAGE_PROVIDER_SPECS).map((spec) => detectSpec(spec, deps));
|
|
161
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { LspFrameRejectReason } from "@oscharko-dev/keiko-contracts";
|
|
2
|
+
export type LspBytes = Buffer;
|
|
3
|
+
export declare class LspFrameRejectError extends Error {
|
|
4
|
+
readonly reason: LspFrameRejectReason;
|
|
5
|
+
constructor(reason: LspFrameRejectReason);
|
|
6
|
+
}
|
|
7
|
+
export type LspByteSource = AsyncIterable<LspBytes>;
|
|
8
|
+
export declare function createLspFrameReader(source: LspByteSource, maxFrameBytes: number): AsyncGenerator<LspBytes, void, void>;
|
|
9
|
+
export interface LspByteSink {
|
|
10
|
+
write(chunk: Buffer): void;
|
|
11
|
+
}
|
|
12
|
+
export declare function writeLspFrame(sink: LspByteSink, body: string): void;
|
|
13
|
+
//# sourceMappingURL=lspFrameCodec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lspFrameCodec.d.ts","sourceRoot":"","sources":["../../../src/editor/lsp/lspFrameCodec.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAc1E,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAI9B,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,SAAgB,MAAM,EAAE,oBAAoB,CAAC;gBAE1B,MAAM,EAAE,oBAAoB;CAKhD;AAID,MAAM,MAAM,aAAa,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;AA6CpD,wBAAuB,oBAAoB,CACzC,MAAM,EAAE,aAAa,EACrB,aAAa,EAAE,MAAM,GACpB,cAAc,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,CAMtC;AAwHD,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAID,wBAAgB,aAAa,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAInE"}
|