@schlenkr/ragents 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/server/src/plugin-support/language-server/contract.ts +6 -1
- package/apps/server/src/plugin-support/language-server/tools.ts +29 -4
- package/apps/server/src/plugin-support/run-scripts.ts +4 -1
- package/apps/server/src/plugin-support/start-entries-contract.ts +4 -3
- package/apps/server/src/plugin-support/workspace-sandbox-host.ts +2 -0
- package/apps/web/src/App.tsx +0 -10
- package/apps/web/src/PluginChat.tsx +8 -8
- package/apps/web/src/PluginRegistry.tsx +0 -12
- package/apps/web/src/StartSurface.tsx +2 -2
- package/apps/web/src/ThemeSettings.tsx +1 -1
- package/apps/web/src/column/ColumnApp.tsx +83 -7
- package/apps/web/src/column/clipboard.ts +64 -0
- package/apps/web/src/column/host-contract.ts +10 -0
- package/apps/web/src/column.tsx +2 -0
- package/apps/web/src/panel/LoginForm.tsx +9 -3
- package/apps/web/src/panel/OverviewPage.tsx +187 -62
- package/apps/web/src/panel/PanelDialogs.tsx +115 -0
- package/apps/web/src/panel/PanelPage.tsx +1 -1
- package/apps/web/src/panel/SettingsPage.tsx +75 -79
- package/apps/web/src/panel/contract.ts +17 -9
- package/apps/web/src/panel/target-state.ts +27 -2
- package/apps/web/src/ui/theme.css +4 -0
- package/package.json +2 -2
- package/packages/ragents/src/plugin-host.ts +5 -2
- package/packages/ragents/src/plugin-types.ts +3 -2
- package/packages/workspace-executor/src/context.ts +4 -0
- package/packages/workspace-executor/src/executor.ts +9 -2
- package/packages/workspace-executor/src/index.ts +2 -0
- package/packages/workspace-executor/src/language-server/adapters/fsharp.ts +1 -0
- package/packages/workspace-executor/src/language-server/adapters/roslyn.ts +1 -0
- package/packages/workspace-executor/src/language-server/adapters/typescript.ts +34 -6
- package/packages/workspace-executor/src/language-server/contract.ts +7 -3
- package/packages/workspace-executor/src/language-server/host.ts +275 -138
- package/plugins/ragents.actor-programs/contract.ts +1 -1
- package/plugins/ragents.actor-programs/prompt.hbs +4 -4
- package/plugins/ragents.actor-programs/server/app-project.ts +0 -2
- package/plugins/ragents.actor-programs/server/runtime.ts +1 -1
- package/plugins/ragents.actor-programs/web/AppsPanel.tsx +3 -5
- package/plugins/ragents.actor-programs/web/EmbeddedApps.tsx +7 -39
- package/plugins/ragents.actor-programs/web/api.ts +1 -10
- package/plugins/ragents.lsp-roslyn/web/language-server-plugin.tsx +73 -44
- package/plugins/ragents.orchestration/canvas.hbs +28 -44
- package/plugins/ragents.orchestration/contract.ts +17 -287
- package/plugins/ragents.orchestration/server/canvas-tool.ts +18 -123
- package/plugins/ragents.orchestration/tiled-layout.ts +12 -4
- package/plugins/ragents.orchestration/web/ActorCanvasControls.tsx +23 -47
- package/plugins/ragents.orchestration/web/ActorChatPreview.tsx +3 -9
- package/plugins/ragents.orchestration/web/ActorShortcut.tsx +3 -5
- package/plugins/ragents.orchestration/web/ActorTile.tsx +3 -2
- package/plugins/ragents.orchestration/web/CanvasTiles.tsx +3 -3
- package/plugins/ragents.orchestration/web/Center.tsx +28 -463
- package/plugins/ragents.orchestration/web/MaterialBody.tsx +6 -87
- package/plugins/ragents.orchestration/web/TiledCanvas.tsx +2 -3
- package/plugins/ragents.orchestration/web/canvas-view-settings.ts +7 -13
- package/plugins/ragents.orchestration/web/column/RunColumn.tsx +44 -19
- package/plugins/ragents.orchestration/web/column/column-state.ts +13 -4
- package/plugins/ragents.orchestration/web/constants.ts +0 -2
- package/plugins/ragents.orchestration/web/index.tsx +0 -6
- package/plugins/ragents.orchestration/web/tile-docking.ts +7 -1
- package/plugins/ragents.orchestration/web/tiled-view-settings.ts +7 -9
- package/plugins/ragents.overseer/server/coordinator-prompt.ts +1 -1
- package/plugins/ragents.reference/examples.ts +1 -2
- package/plugins/ragents.reference/run-scripts/balcony-wizard/RUN.md +1 -1
- package/plugins/ragents.reference/run-scripts/balcony-wizard/actors/balcony-app/package.json +1 -1
- package/plugins/ragents.reference/run-scripts/balcony-wizard/src/server.ts +1 -1
- package/plugins/ragents.reference/run-scripts/balcony-wizard/tests/program.test.ts +2 -2
- package/plugins/ragents.reference/run-scripts/conversation-circle/RUN.md +3 -4
- package/plugins/ragents.reference/run-scripts/conversation-circle/src/server.ts +9 -15
- package/plugins/ragents.reference/run-scripts/conversation-circle/tests/program.test.ts +5 -3
- package/plugins/ragents.reference/run-scripts/learning-afternoon/package.json +1 -1
- package/plugins/ragents.reference/run-scripts/learning-afternoon/src/server.ts +14 -4
- package/plugins/ragents.reference/run-scripts/word-game/src/server.ts +1 -1
- package/plugins/ragents.reference/skills/210-moderator-handover/SKILL.md +1 -1
- package/plugins/ragents.reference/walkthroughs.ts +14 -14
- package/plugins/ragents.workspace/client/workspace-client.ts +4 -1
- package/scripts/package/publish-package.ts +4 -5
- package/scripts/workspace-client/run-workspace-client.ts +3 -1
- package/apps/web/src/MaterialSettings.tsx +0 -40
- package/apps/web/src/material-settings.ts +0 -104
- package/plugins/ragents.orchestration/web/ActorNet.tsx +0 -607
- package/plugins/ragents.orchestration/web/CardSizeSettings.tsx +0 -42
- package/plugins/ragents.orchestration/web/ScriptActorCard.tsx +0 -56
- package/plugins/ragents.orchestration/web/ZoomSettings.tsx +0 -38
- package/plugins/ragents.orchestration/web/canvas-layout-storage.ts +0 -39
- package/plugins/ragents.orchestration/web/canvas-layout.ts +0 -326
- package/plugins/ragents.orchestration/web/canvas-scene.ts +0 -311
- package/plugins/ragents.orchestration/web/card-size-settings.ts +0 -36
- package/plugins/ragents.orchestration/web/keyboard-navigation.ts +0 -55
- package/plugins/ragents.orchestration/web/material-layout.ts +0 -14
- package/plugins/ragents.orchestration/web/useCanvasMeasurements.ts +0 -78
- package/plugins/ragents.orchestration/web/zoom-settings.ts +0 -28
- package/plugins/ragents.reference/skills/120-canvas-conversation-circle/SKILL.md +0 -12
- package/plugins/ragents.reference/skills/130-canvas-pipeline-with-approval/SKILL.md +0 -12
- package/plugins/ragents.reference/skills/140-canvas-team-tree-and-topic-grid/SKILL.md +0 -12
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ColumnTheme } from "../column/host-contract";
|
|
2
2
|
|
|
3
|
-
/**
|
|
3
|
+
/** Eine Umgebung der Erweiterung: ein RAgents-Server oder ein lokales Profil, das sie selbst startet. */
|
|
4
4
|
export type TargetKind = "server" | "profile";
|
|
5
5
|
|
|
6
6
|
export type TargetState =
|
|
@@ -25,14 +25,16 @@ export interface TargetEntry {
|
|
|
25
25
|
readonly id: string;
|
|
26
26
|
readonly title: string;
|
|
27
27
|
readonly description: string;
|
|
28
|
-
readonly
|
|
28
|
+
readonly kind: "skill" | "script";
|
|
29
|
+
/** Die Gruppe der Kachelansicht; ein Run-Script ohne eigene Kategorie steht unter "Run-Scripts". */
|
|
30
|
+
readonly category: string;
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
export interface TargetView {
|
|
32
34
|
readonly name: string;
|
|
33
35
|
readonly kind: TargetKind;
|
|
34
|
-
/** Adresse des Servers oder
|
|
35
|
-
readonly
|
|
36
|
+
/** Adresse des Servers oder Pfad der Profildatei. */
|
|
37
|
+
readonly address: string;
|
|
36
38
|
readonly state: TargetState;
|
|
37
39
|
readonly runs: readonly TargetRun[];
|
|
38
40
|
readonly entries: readonly TargetEntry[];
|
|
@@ -42,9 +44,9 @@ export interface TargetView {
|
|
|
42
44
|
readonly user?: string;
|
|
43
45
|
/** Die zuletzt versuchte Kennung; das Anmeldeformular übernimmt sie. */
|
|
44
46
|
readonly loginUser?: string;
|
|
45
|
-
/** Anmeldedaten liegen in der SecretStorage, damit
|
|
47
|
+
/** Anmeldedaten liegen in der SecretStorage, damit die Umgebung sich still anmeldet. */
|
|
46
48
|
readonly savedLogin?: boolean;
|
|
47
|
-
/** Fehler der letzten Aktion an
|
|
49
|
+
/** Fehler der letzten Aktion an dieser Umgebung, direkt in ihrer Zeile. */
|
|
48
50
|
readonly problem?: string;
|
|
49
51
|
}
|
|
50
52
|
|
|
@@ -52,9 +54,11 @@ export interface PanelState {
|
|
|
52
54
|
readonly theme: ColumnTheme;
|
|
53
55
|
readonly page: "overview" | "settings";
|
|
54
56
|
readonly targets: readonly TargetView[];
|
|
57
|
+
/** Die Profildateien im Host-Ordner; der Dialog bietet sie an, ohne Host bleibt die Liste leer. */
|
|
58
|
+
readonly profileSuggestions: readonly string[];
|
|
55
59
|
/** Die Einstellung ragents.connections ist fehlerhaft; die Seite nennt den Grund. */
|
|
56
60
|
readonly problem?: string;
|
|
57
|
-
/** Der zuletzt über den Dateidialog gewählte Profilpfad;
|
|
61
|
+
/** Der zuletzt über den Dateidialog gewählte Profilpfad; der Dialog übernimmt ihn. */
|
|
58
62
|
readonly pickedProfileFile?: string;
|
|
59
63
|
}
|
|
60
64
|
|
|
@@ -71,7 +75,9 @@ export type PanelAction =
|
|
|
71
75
|
| { readonly action: "pickProfile" }
|
|
72
76
|
| { readonly action: "addServer"; readonly name: string; readonly url: string }
|
|
73
77
|
| { readonly action: "addProfile"; readonly name: string; readonly profileFile: string }
|
|
74
|
-
| { readonly action: "
|
|
78
|
+
| { readonly action: "updateServer"; readonly name: string; readonly newName: string; readonly url: string }
|
|
79
|
+
| { readonly action: "updateProfile"; readonly name: string; readonly newName: string; readonly profileFile: string }
|
|
80
|
+
| { readonly action: "remove" | "connect" | "disconnect" | "logout" | "startProfile" | "stopProfile" | "retry"; readonly name: string }
|
|
75
81
|
| { readonly action: "login"; readonly name: string; readonly user: string; readonly password: string }
|
|
76
82
|
| { readonly action: "login"; readonly name: string; readonly token: string }
|
|
77
83
|
| { readonly action: "openRun"; readonly name: string; readonly runId: string }
|
|
@@ -88,7 +94,9 @@ export const isPanelActionMessage = (value: unknown): value is PanelActionMessag
|
|
|
88
94
|
case "settingsFile": case "pickProfile": return true;
|
|
89
95
|
case "addServer": return text(value, "name") && text(value, "url");
|
|
90
96
|
case "addProfile": return text(value, "name") && text(value, "profileFile");
|
|
91
|
-
case "
|
|
97
|
+
case "updateServer": return text(value, "name") && text(value, "newName") && text(value, "url");
|
|
98
|
+
case "updateProfile": return text(value, "name") && text(value, "newName") && text(value, "profileFile");
|
|
99
|
+
case "remove": case "connect": case "disconnect": case "logout": case "startProfile": case "stopProfile": case "retry": return text(value, "name");
|
|
92
100
|
case "login": return text(value, "name") && (text(value, "token") || (text(value, "user") && text(value, "password")));
|
|
93
101
|
case "openRun": return text(value, "name") && text(value, "runId");
|
|
94
102
|
case "newRun": return text(value, "name") && ((value as { entryId?: unknown }).entryId === undefined || text(value, "entryId"));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { TargetRun, TargetView } from "./contract";
|
|
2
2
|
|
|
3
|
-
/** Wie der Zustand
|
|
3
|
+
/** Wie der Zustand einer Umgebung in ihrer Zeile steht; ein lokales Profil ist nicht getrennt, sondern nicht gestartet. */
|
|
4
4
|
export const stateLabel = (target: TargetView): string => {
|
|
5
5
|
switch (target.state.kind) {
|
|
6
6
|
case "stopped": return target.kind === "profile" ? "nicht gestartet" : "getrennt";
|
|
@@ -27,13 +27,17 @@ export const stateTone = (target: TargetView): string => {
|
|
|
27
27
|
}
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
-
/** Der Grund, der zum Zustand gehört; er steht unter der
|
|
30
|
+
/** Der Grund, der zum Zustand gehört; er steht unter der Zeile der Umgebung. */
|
|
31
31
|
export const stateDetail = (target: TargetView): string | undefined => {
|
|
32
32
|
const state = target.state;
|
|
33
33
|
if (state.kind === "unreachable" || state.kind === "forbidden" || state.kind === "failed") return state.message;
|
|
34
34
|
return undefined;
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
+
export const kindLabel = (target: TargetView): string => target.kind === "profile" ? "lokales Profil" : "Server";
|
|
38
|
+
|
|
39
|
+
export const busyState = (target: TargetView): boolean => target.state.kind === "starting" || target.state.kind === "connecting";
|
|
40
|
+
|
|
37
41
|
export const runStateLabel = (run: TargetRun): string => {
|
|
38
42
|
switch (run.state) {
|
|
39
43
|
case "running": return "läuft";
|
|
@@ -51,3 +55,24 @@ export const runTone = (run: TargetRun): string => {
|
|
|
51
55
|
case "idle": return "text-muted-foreground";
|
|
52
56
|
}
|
|
53
57
|
};
|
|
58
|
+
|
|
59
|
+
const MINUTE = 60_000;
|
|
60
|
+
const HOUR = 60 * MINUTE;
|
|
61
|
+
const DAY = 24 * HOUR;
|
|
62
|
+
|
|
63
|
+
/** Wann ein Run zuletzt etwas getan hat; alles ab gestern nennt das Datum statt einer Spanne. */
|
|
64
|
+
export const runTime = (run: TargetRun, now: number = Date.now()): string => {
|
|
65
|
+
const passed = now - run.updatedAt;
|
|
66
|
+
if (passed < MINUTE) return "gerade eben";
|
|
67
|
+
if (passed < HOUR) return `vor ${Math.floor(passed / MINUTE)} Min`;
|
|
68
|
+
if (passed < DAY) return `vor ${Math.floor(passed / HOUR)} Std`;
|
|
69
|
+
return new Date(run.updatedAt).toLocaleDateString("de-DE", { day: "2-digit", month: "2-digit", year: "numeric" });
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const HUES = [255, 170, 300, 10, 130, 210, 60, 330];
|
|
73
|
+
|
|
74
|
+
/** Die Farbe einer Umgebung hängt an ihrem Namen, nicht an ihrer Stelle in der Liste; Umsortieren ändert sie nicht. */
|
|
75
|
+
export const environmentHue = (name: string): number => {
|
|
76
|
+
const hash = [...name].reduce((value, character) => (value * 31 + character.codePointAt(0)!) % 100_003, 7);
|
|
77
|
+
return HUES[hash % HUES.length]!;
|
|
78
|
+
};
|
|
@@ -134,6 +134,8 @@
|
|
|
134
134
|
--warning-soft: #f3e4d8;
|
|
135
135
|
--info: #4b648a;
|
|
136
136
|
--teal: #356c70;
|
|
137
|
+
--env-lightness: 0.55;
|
|
138
|
+
--env-chroma: 0.12;
|
|
137
139
|
--border: #c9c4d5;
|
|
138
140
|
--border-soft: #dad6e3;
|
|
139
141
|
--border-strong: #a397b2;
|
|
@@ -186,6 +188,8 @@
|
|
|
186
188
|
--warning-soft: #43382b;
|
|
187
189
|
--info: #9dbade;
|
|
188
190
|
--teal: #8ec9c4;
|
|
191
|
+
--env-lightness: 0.79;
|
|
192
|
+
--env-chroma: 0.1;
|
|
189
193
|
--border: #555065;
|
|
190
194
|
--border-soft: #403c50;
|
|
191
195
|
--border-strong: #8e809f;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@schlenkr/ragents",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "RAgents-Host: Server, Engine, Plugins und Werkzeuge ohne Quell-Checkout",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|
|
@@ -77,6 +77,6 @@
|
|
|
77
77
|
"yaml": "2.9.0"
|
|
78
78
|
},
|
|
79
79
|
"ragents": {
|
|
80
|
-
"hostVersion": "
|
|
80
|
+
"hostVersion": "1f5768e0029dbc9663ecd4e31b365c4e4e99f531"
|
|
81
81
|
}
|
|
82
82
|
}
|
|
@@ -522,7 +522,10 @@ const validateStartEntry = (entry: StartEntryContribution): void => {
|
|
|
522
522
|
}
|
|
523
523
|
return;
|
|
524
524
|
case "script":
|
|
525
|
-
assertKnownFields(entry, entry, [...base, "script"], "Einstieg");
|
|
525
|
+
assertKnownFields(entry, entry, [...base, "script", "category"], "Einstieg");
|
|
526
|
+
if (entry.category !== undefined && (typeof entry.category !== "string" || !entry.category.trim() || entry.category !== entry.category.trim())) {
|
|
527
|
+
throw new Error(`Einstieg ${entry.id}: category muss ein einzelner nicht leerer Text sein`);
|
|
528
|
+
}
|
|
526
529
|
validateScriptPackage(entry, entry.script);
|
|
527
530
|
return;
|
|
528
531
|
default:
|
|
@@ -572,7 +575,7 @@ export class StartEntryContributionRegistry {
|
|
|
572
575
|
case "skill":
|
|
573
576
|
return { ...base, action: "skill", skill: value.skill, category: value.category, prompt: value.prompt };
|
|
574
577
|
case "script":
|
|
575
|
-
return { ...base, action: "script", coordinator: value.script.coordinator };
|
|
578
|
+
return { ...base, action: "script", coordinator: value.script.coordinator, ...(value.category !== undefined ? { category: value.category } : {}) };
|
|
576
579
|
}
|
|
577
580
|
})
|
|
578
581
|
.sort(byOrderThenId);
|
|
@@ -207,7 +207,8 @@ export interface RunScriptPackage {
|
|
|
207
207
|
|
|
208
208
|
export type StartEntryContribution = StartEntryBase & (
|
|
209
209
|
| { action: "skill"; skill: string; category: string; prompt: string }
|
|
210
|
-
|
|
210
|
+
/** A run script may name a category of its own; without one the start surfaces group it as a run script. */
|
|
211
|
+
| { action: "script"; script: RunScriptPackage; category?: string }
|
|
211
212
|
);
|
|
212
213
|
|
|
213
214
|
export type StartEntryAction = StartEntryContribution["action"];
|
|
@@ -215,7 +216,7 @@ export type StartEntryAction = StartEntryContribution["action"];
|
|
|
215
216
|
/** The entry as the web sees it: a script entry shows its kind and coordinator flag, never its source. */
|
|
216
217
|
export type PublicStartEntry = StartEntryBase & { owner: string } & (
|
|
217
218
|
| { action: "skill"; skill: string; category: string; prompt: string }
|
|
218
|
-
| { action: "script"; coordinator: boolean }
|
|
219
|
+
| { action: "script"; coordinator: boolean; category?: string }
|
|
219
220
|
);
|
|
220
221
|
|
|
221
222
|
export interface SkillContribution {
|
|
@@ -12,6 +12,8 @@ export interface WorkspaceProcessContext {
|
|
|
12
12
|
home: string;
|
|
13
13
|
/** Wohin ein Sprachserver Protokolle und Zwischenstände legen darf; nie das Home eines Entwicklers. */
|
|
14
14
|
logDirectory: string;
|
|
15
|
+
/** Die Wurzel des Hosts auf dieser Maschine, aus der ein Adapter seinen Sprachserver auflöst; ohne Host bleibt sie offen. */
|
|
16
|
+
hostRoot: string | undefined;
|
|
15
17
|
env: NodeJS.ProcessEnv;
|
|
16
18
|
uid?: number;
|
|
17
19
|
gid?: number;
|
|
@@ -78,6 +80,7 @@ export interface WorkspaceContextOptions {
|
|
|
78
80
|
root: string;
|
|
79
81
|
home: SandboxHomeEnvironment;
|
|
80
82
|
logDirectory: string;
|
|
83
|
+
hostRoot: string | undefined;
|
|
81
84
|
ident?: SessionIdent;
|
|
82
85
|
additionalRoots?: readonly ResolvedWorkspaceRoot[];
|
|
83
86
|
readOnlyRoots?: readonly ResolvedWorkspaceRoot[];
|
|
@@ -107,6 +110,7 @@ export const workspaceProcessContext = (options: WorkspaceContextOptions): Works
|
|
|
107
110
|
root: options.root,
|
|
108
111
|
home: options.home.home,
|
|
109
112
|
logDirectory: options.logDirectory,
|
|
113
|
+
hostRoot: options.hostRoot,
|
|
110
114
|
env: sandboxEnvironment(options.source ?? process.env, {
|
|
111
115
|
home: options.home,
|
|
112
116
|
...(options.ident ? { ident: options.ident } : {}),
|
|
@@ -12,6 +12,8 @@ export const languageServerOpenTool = (adapterId: string): string => `${adapterI
|
|
|
12
12
|
|
|
13
13
|
export const languageServerDiagnosticsTool = (adapterId: string): string => `${adapterId}_diagnostics`;
|
|
14
14
|
|
|
15
|
+
export const languageServerCloseTool = (adapterId: string): string => `${adapterId}_close`;
|
|
16
|
+
|
|
15
17
|
export const languageServerSnapshotTool = (adapterId: string): string => `${adapterId}_snapshot`;
|
|
16
18
|
|
|
17
19
|
export interface WorkspaceExecuteOptions {
|
|
@@ -62,6 +64,7 @@ export class SandboxWorkspaceExecutor implements WorkspaceExecutor {
|
|
|
62
64
|
const languageServer = this.#languageServers.find((host) =>
|
|
63
65
|
tool === languageServerOpenTool(host.adapter.id)
|
|
64
66
|
|| tool === languageServerDiagnosticsTool(host.adapter.id)
|
|
67
|
+
|| tool === languageServerCloseTool(host.adapter.id)
|
|
65
68
|
|| tool === languageServerSnapshotTool(host.adapter.id));
|
|
66
69
|
if (languageServer) return this.#languageServerCall(languageServer, runId, tool, input);
|
|
67
70
|
return this.#toolCall(runId, tool, input, options);
|
|
@@ -105,8 +108,12 @@ export class SandboxWorkspaceExecutor implements WorkspaceExecutor {
|
|
|
105
108
|
const { root } = input as { root: string };
|
|
106
109
|
return host.open(runId, root);
|
|
107
110
|
}
|
|
108
|
-
|
|
109
|
-
|
|
111
|
+
if (tool === languageServerCloseTool(host.adapter.id)) {
|
|
112
|
+
const { root } = (input ?? {}) as { root?: string };
|
|
113
|
+
return host.close(runId, root);
|
|
114
|
+
}
|
|
115
|
+
const { paths, warnings, root } = input as { paths?: readonly string[]; warnings?: boolean; root?: string };
|
|
116
|
+
return host.diagnostics(runId, paths, warnings ?? false, root);
|
|
110
117
|
}
|
|
111
118
|
|
|
112
119
|
#sandbox(runId: string): Promise<SandboxTools> {
|
|
@@ -9,6 +9,7 @@ export {
|
|
|
9
9
|
SandboxWorkspaceExecutor,
|
|
10
10
|
WORKSPACE_EXECUTOR_VERSION,
|
|
11
11
|
WORKSPACE_STOP_OPERATION,
|
|
12
|
+
languageServerCloseTool,
|
|
12
13
|
languageServerDiagnosticsTool,
|
|
13
14
|
languageServerOpenTool,
|
|
14
15
|
languageServerSnapshotTool,
|
|
@@ -38,6 +39,7 @@ export {
|
|
|
38
39
|
export {
|
|
39
40
|
type LanguageServerDiagnostic,
|
|
40
41
|
type LanguageServerFileDiagnostics,
|
|
42
|
+
type LanguageServerInstanceSnapshot,
|
|
41
43
|
type LanguageServerSeverity,
|
|
42
44
|
type LanguageServerSnapshot,
|
|
43
45
|
type LanguageServerState,
|
|
@@ -30,6 +30,7 @@ export const fsharpAdapter: LanguageServerAdapter = {
|
|
|
30
30
|
languages,
|
|
31
31
|
rootDescription: "the .sln file (or a single .fsproj)",
|
|
32
32
|
resolveRoot: (workspaceRoot, root) => resolveRootFile(workspaceRoot, root, [".sln", ".fsproj"]),
|
|
33
|
+
rootDirectory: (root) => path.dirname(root),
|
|
33
34
|
launch: async (context, root) => ({
|
|
34
35
|
label: "FSAC",
|
|
35
36
|
...dotnetCommand(serverPath(), ["--state-directory", path.join(context.logDirectory, "fsautocomplete")]),
|
|
@@ -27,6 +27,7 @@ export const roslynAdapter: LanguageServerAdapter = {
|
|
|
27
27
|
languages,
|
|
28
28
|
rootDescription: "the .sln file (or a single .csproj)",
|
|
29
29
|
resolveRoot: (workspaceRoot, root) => resolveRootFile(workspaceRoot, root, [".sln", ".slnx", ".csproj"]),
|
|
30
|
+
rootDirectory: (root) => path.dirname(root),
|
|
30
31
|
launch: async (context, root) => ({
|
|
31
32
|
label: "Roslyn",
|
|
32
33
|
...dotnetCommand(serverPath(), [
|
|
@@ -5,10 +5,6 @@ import { pathToFileURL } from "node:url";
|
|
|
5
5
|
import type { LanguageServerAdapter } from "../host.js";
|
|
6
6
|
import { resolveRootDirectory } from "../roots.js";
|
|
7
7
|
|
|
8
|
-
const require = createRequire(import.meta.url);
|
|
9
|
-
const serverScript = require.resolve("typescript-language-server/lib/cli.mjs");
|
|
10
|
-
const bundledTypeScriptLib = path.dirname(require.resolve("typescript"));
|
|
11
|
-
|
|
12
8
|
const languages = {
|
|
13
9
|
".ts": "typescript",
|
|
14
10
|
".tsx": "typescriptreact",
|
|
@@ -18,6 +14,37 @@ const languages = {
|
|
|
18
14
|
".jsx": "javascriptreact",
|
|
19
15
|
} as const;
|
|
20
16
|
|
|
17
|
+
/** Der Sprachserver liegt in den node_modules des Hosts; ohne Host gibt es ihn auf dieser Maschine nicht. */
|
|
18
|
+
const hostRequire = (hostRoot: string | undefined): NodeRequire => {
|
|
19
|
+
if (!hostRoot) {
|
|
20
|
+
throw new Error("Für TypeScript ist auf diesem Rechner kein Host bekannt, aus dem sich typescript-language-server "
|
|
21
|
+
+ "auflösen ließe. Ein Arbeitsplatz bekommt ihn mit der ersten Verbindung zu einem verteilenden Server oder über "
|
|
22
|
+
+ "die Einstellung ragents.hostPath");
|
|
23
|
+
}
|
|
24
|
+
return createRequire(path.join(hostRoot, "package.json"));
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const missing = (hostRoot: string | undefined, name: string, cause: unknown): Error =>
|
|
28
|
+
new Error(`${name} liegt nicht im Host ${hostRoot}: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
29
|
+
|
|
30
|
+
const serverScript = (hostRoot: string | undefined): string => {
|
|
31
|
+
const require = hostRequire(hostRoot);
|
|
32
|
+
try {
|
|
33
|
+
return require.resolve("typescript-language-server/lib/cli.mjs");
|
|
34
|
+
} catch (cause) {
|
|
35
|
+
throw missing(hostRoot, "typescript-language-server", cause);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const bundledTypeScriptLib = (hostRoot: string | undefined): string => {
|
|
40
|
+
const require = hostRequire(hostRoot);
|
|
41
|
+
try {
|
|
42
|
+
return path.dirname(require.resolve("typescript"));
|
|
43
|
+
} catch (cause) {
|
|
44
|
+
throw missing(hostRoot, "typescript", cause);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
21
48
|
const hasWorkspaceTypeScript = (root: string): Promise<boolean> =>
|
|
22
49
|
stat(path.join(root, "node_modules", "typescript", "lib", "tsserver.js")).then((info) => info.isFile(), () => false);
|
|
23
50
|
|
|
@@ -27,17 +54,18 @@ export const typescriptAdapter: LanguageServerAdapter = {
|
|
|
27
54
|
languages,
|
|
28
55
|
rootDescription: "the directory whose tsconfig.json projects should be served (e.g. src)",
|
|
29
56
|
resolveRoot: resolveRootDirectory,
|
|
57
|
+
rootDirectory: (root) => root,
|
|
30
58
|
launch: async (context, root) => ({
|
|
31
59
|
label: "TypeScript",
|
|
32
60
|
command: process.execPath,
|
|
33
|
-
args: [serverScript, "--stdio"],
|
|
61
|
+
args: [serverScript(context.hostRoot), "--stdio"],
|
|
34
62
|
cwd: root,
|
|
35
63
|
// Im Extension-Host ist process.execPath Electron; ohne diese Variable startet es die Anwendung statt des Skripts.
|
|
36
64
|
env: { ...context.env, ELECTRON_RUN_AS_NODE: "1" },
|
|
37
65
|
uid: context.uid,
|
|
38
66
|
gid: context.gid,
|
|
39
67
|
rootUri: pathToFileURL(root).href,
|
|
40
|
-
initializationOptions: await hasWorkspaceTypeScript(root) ? {} : { tsserver: { path: bundledTypeScriptLib } },
|
|
68
|
+
initializationOptions: await hasWorkspaceTypeScript(root) ? {} : { tsserver: { path: bundledTypeScriptLib(context.hostRoot) } },
|
|
41
69
|
languages,
|
|
42
70
|
publishesOnlyChangedDiagnostics: true,
|
|
43
71
|
}),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type LanguageServerState = "
|
|
1
|
+
export type LanguageServerState = "opening" | "ready" | "failed" | "suspended";
|
|
2
2
|
|
|
3
3
|
export type LanguageServerSeverity = "error" | "warning" | "information" | "hint";
|
|
4
4
|
|
|
@@ -15,9 +15,13 @@ export interface LanguageServerFileDiagnostics {
|
|
|
15
15
|
diagnostics: readonly LanguageServerDiagnostic[];
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
export interface
|
|
18
|
+
export interface LanguageServerInstanceSnapshot {
|
|
19
19
|
state: LanguageServerState;
|
|
20
|
-
root: string
|
|
20
|
+
root: string;
|
|
21
21
|
summary: string | null;
|
|
22
22
|
files: readonly LanguageServerFileDiagnostics[];
|
|
23
23
|
}
|
|
24
|
+
|
|
25
|
+
export interface LanguageServerSnapshot {
|
|
26
|
+
instances: readonly LanguageServerInstanceSnapshot[];
|
|
27
|
+
}
|