@evref-bl/plexus-core 0.1.0-alpha.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.
Files changed (73) hide show
  1. package/dist/cli.d.ts +3 -0
  2. package/dist/cli.d.ts.map +1 -0
  3. package/dist/cli.js +164 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/config.d.ts +15 -0
  6. package/dist/config.d.ts.map +1 -0
  7. package/dist/config.js +62 -0
  8. package/dist/config.js.map +1 -0
  9. package/dist/imageRescue.d.ts +136 -0
  10. package/dist/imageRescue.d.ts.map +1 -0
  11. package/dist/imageRescue.js +686 -0
  12. package/dist/imageRescue.js.map +1 -0
  13. package/dist/index.d.ts +16 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +16 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/pathStyle.d.ts +10 -0
  18. package/dist/pathStyle.d.ts.map +1 -0
  19. package/dist/pathStyle.js +33 -0
  20. package/dist/pathStyle.js.map +1 -0
  21. package/dist/pharoLauncherMcpClient.d.ts +12 -0
  22. package/dist/pharoLauncherMcpClient.d.ts.map +1 -0
  23. package/dist/pharoLauncherMcpClient.js +74 -0
  24. package/dist/pharoLauncherMcpClient.js.map +1 -0
  25. package/dist/pharoMcpHealth.d.ts +22 -0
  26. package/dist/pharoMcpHealth.d.ts.map +1 -0
  27. package/dist/pharoMcpHealth.js +80 -0
  28. package/dist/pharoMcpHealth.js.map +1 -0
  29. package/dist/projectClose.d.ts +28 -0
  30. package/dist/projectClose.d.ts.map +1 -0
  31. package/dist/projectClose.js +93 -0
  32. package/dist/projectClose.js.map +1 -0
  33. package/dist/projectConfig.d.ts +44 -0
  34. package/dist/projectConfig.d.ts.map +1 -0
  35. package/dist/projectConfig.js +208 -0
  36. package/dist/projectConfig.js.map +1 -0
  37. package/dist/projectLifecycle.d.ts +115 -0
  38. package/dist/projectLifecycle.d.ts.map +1 -0
  39. package/dist/projectLifecycle.js +495 -0
  40. package/dist/projectLifecycle.js.map +1 -0
  41. package/dist/projectOpen.d.ts +49 -0
  42. package/dist/projectOpen.d.ts.map +1 -0
  43. package/dist/projectOpen.js +218 -0
  44. package/dist/projectOpen.js.map +1 -0
  45. package/dist/projectStartupScript.d.ts +56 -0
  46. package/dist/projectStartupScript.d.ts.map +1 -0
  47. package/dist/projectStartupScript.js +150 -0
  48. package/dist/projectStartupScript.js.map +1 -0
  49. package/dist/projectState.d.ts +128 -0
  50. package/dist/projectState.d.ts.map +1 -0
  51. package/dist/projectState.js +192 -0
  52. package/dist/projectState.js.map +1 -0
  53. package/dist/scopedPharoLauncherServer.d.ts +87 -0
  54. package/dist/scopedPharoLauncherServer.d.ts.map +1 -0
  55. package/dist/scopedPharoLauncherServer.js +186 -0
  56. package/dist/scopedPharoLauncherServer.js.map +1 -0
  57. package/dist/scopedProjectContext.d.ts +93 -0
  58. package/dist/scopedProjectContext.d.ts.map +1 -0
  59. package/dist/scopedProjectContext.js +181 -0
  60. package/dist/scopedProjectContext.js.map +1 -0
  61. package/dist/server.d.ts +42 -0
  62. package/dist/server.d.ts.map +1 -0
  63. package/dist/server.js +133 -0
  64. package/dist/server.js.map +1 -0
  65. package/dist/target.d.ts +19 -0
  66. package/dist/target.d.ts.map +1 -0
  67. package/dist/target.js +2 -0
  68. package/dist/target.js.map +1 -0
  69. package/dist/workspaceMcpConfig.d.ts +42 -0
  70. package/dist/workspaceMcpConfig.d.ts.map +1 -0
  71. package/dist/workspaceMcpConfig.js +79 -0
  72. package/dist/workspaceMcpConfig.js.map +1 -0
  73. package/package.json +37 -0
@@ -0,0 +1,218 @@
1
+ import path from "node:path";
2
+ import { loadProjectConfig } from "./projectConfig.js";
3
+ import { createStdioPharoLauncherMcpClient, } from "./pharoLauncherMcpClient.js";
4
+ import { HttpPharoMcpHealthClient, } from "./pharoMcpHealth.js";
5
+ import { collectReservedProjectPorts, createProjectState, defaultWorkspaceId, loadProjectState, projectStatePathForConfig, sanitizeRuntimeId, saveProjectState, } from "./projectState.js";
6
+ import { writeProjectImageStartupScript } from "./projectStartupScript.js";
7
+ export class ProjectOpenError extends Error {
8
+ result;
9
+ constructor(message, result) {
10
+ super(message);
11
+ this.result = result;
12
+ this.name = "ProjectOpenError";
13
+ }
14
+ }
15
+ function defaultSleep(durationMs) {
16
+ return new Promise((resolve) => setTimeout(resolve, durationMs));
17
+ }
18
+ function errorMessage(error) {
19
+ return error instanceof Error ? error.message : String(error);
20
+ }
21
+ function closeClientQuietly(client) {
22
+ void client.close?.().catch(() => undefined);
23
+ }
24
+ function processMatchesImage(process, imageName) {
25
+ return (process.imageName === imageName ||
26
+ path.basename(process.imagePath ?? "", ".image") === imageName ||
27
+ process.commandLine.includes(`${imageName}.image`) ||
28
+ process.commandLine.includes(imageName));
29
+ }
30
+ function launcherResultData(result) {
31
+ return result.ok ? result.data : undefined;
32
+ }
33
+ function assertLauncherOk(result, toolName) {
34
+ if (result && result.ok === false) {
35
+ throw new Error(`${toolName} returned ok: false`);
36
+ }
37
+ }
38
+ async function pollUntil(timeoutMs, intervalMs, sleep, attempt) {
39
+ const startedAt = Date.now();
40
+ while (Date.now() - startedAt <= timeoutMs) {
41
+ const result = await attempt();
42
+ if (result !== undefined) {
43
+ return result;
44
+ }
45
+ await sleep(intervalMs);
46
+ }
47
+ return undefined;
48
+ }
49
+ async function pollProcessForImage(client, imageName, timeoutMs, intervalMs, sleep) {
50
+ return pollUntil(timeoutMs, intervalMs, sleep, async () => {
51
+ const result = await client.callTool("pharo_launcher_process_list", {});
52
+ assertLauncherOk(result, "pharo_launcher_process_list");
53
+ const processes = launcherResultData(result) ?? [];
54
+ return processes.find((process) => processMatchesImage(process, imageName));
55
+ });
56
+ }
57
+ async function pollHealth(healthClient, port, timeoutMs, intervalMs, sleep) {
58
+ const result = await pollUntil(timeoutMs, intervalMs, sleep, async () => (await healthClient.check(port)) ? true : undefined);
59
+ return result === true;
60
+ }
61
+ async function launchImageAndPollProcess(launchClient, processClient, imageName, startupScriptPath, timeoutMs, intervalMs, sleep) {
62
+ const launchOutcome = launchClient
63
+ .callTool("pharo_launcher_image_launch", {
64
+ imageName,
65
+ detached: true,
66
+ script: startupScriptPath,
67
+ })
68
+ .then((result) => ({ kind: "launch", result }), (error) => ({ kind: "launchError", error }));
69
+ const immediateLaunch = await Promise.race([
70
+ launchOutcome,
71
+ new Promise((resolve) => setTimeout(() => resolve(undefined), 0)),
72
+ ]);
73
+ if (immediateLaunch?.kind === "launchError") {
74
+ throw immediateLaunch.error;
75
+ }
76
+ if (immediateLaunch?.kind === "launch") {
77
+ assertLauncherOk(immediateLaunch.result, "pharo_launcher_image_launch");
78
+ const process = await pollProcessForImage(processClient, imageName, timeoutMs, intervalMs, sleep);
79
+ if (process) {
80
+ return process;
81
+ }
82
+ throw new Error(`Timed out waiting for PharoLauncher process for image ${imageName}`);
83
+ }
84
+ const processOutcome = pollProcessForImage(processClient, imageName, timeoutMs, intervalMs, sleep).then((process) => ({ kind: "process", process }));
85
+ const first = await Promise.race([launchOutcome, processOutcome]);
86
+ if (first.kind === "launchError") {
87
+ throw first.error;
88
+ }
89
+ if (first.kind === "launch") {
90
+ assertLauncherOk(first.result, "pharo_launcher_image_launch");
91
+ const { process } = await processOutcome;
92
+ if (process) {
93
+ return process;
94
+ }
95
+ }
96
+ else if (first.process) {
97
+ return first.process;
98
+ }
99
+ throw new Error(`Timed out waiting for PharoLauncher process for image ${imageName}`);
100
+ }
101
+ function activeStateImages(state) {
102
+ return state.images.filter((image) => image.status === "starting");
103
+ }
104
+ function applyScopedImageSelection(state, imageIds) {
105
+ if (!imageIds) {
106
+ return;
107
+ }
108
+ const selectedIds = new Set(imageIds);
109
+ for (const image of state.images) {
110
+ if (!selectedIds.has(image.id)) {
111
+ image.status = "stopped";
112
+ }
113
+ }
114
+ }
115
+ export async function openProject(options) {
116
+ const projectRoot = path.resolve(options.projectRoot);
117
+ const config = loadProjectConfig(projectRoot);
118
+ const workspaceId = options.workspaceId
119
+ ? sanitizeRuntimeId(options.workspaceId)
120
+ : defaultWorkspaceId(projectRoot);
121
+ const statePath = projectStatePathForConfig({
122
+ projectRoot,
123
+ config,
124
+ workspaceId,
125
+ stateRoot: options.stateRoot,
126
+ });
127
+ const previousState = loadProjectState(statePath);
128
+ const now = options.now ?? (() => new Date());
129
+ const reservedPorts = collectReservedProjectPorts({
130
+ projectRoot,
131
+ projectId: config.kanban.projectId,
132
+ stateRoot: options.stateRoot,
133
+ excludeWorkspaceId: workspaceId,
134
+ });
135
+ const state = createProjectState(config, {
136
+ updatedAt: now().toISOString(),
137
+ previousState,
138
+ workspaceId,
139
+ targetId: options.targetId,
140
+ reservedPorts,
141
+ ...(options.portRange ? { portRange: options.portRange } : {}),
142
+ });
143
+ applyScopedImageSelection(state, options.imageIds);
144
+ const client = options.pharoLauncherMcpClient ??
145
+ (await createStdioPharoLauncherMcpClient());
146
+ const ownsClient = !options.pharoLauncherMcpClient;
147
+ const healthClient = options.healthClient ?? new HttpPharoMcpHealthClient();
148
+ const poll = {
149
+ intervalMs: options.poll?.intervalMs ?? 500,
150
+ processTimeoutMs: options.poll?.processTimeoutMs ?? 30_000,
151
+ healthTimeoutMs: options.poll?.healthTimeoutMs ?? 5 * 60_000,
152
+ };
153
+ const sleep = options.sleep ?? defaultSleep;
154
+ const failures = [];
155
+ try {
156
+ for (const imageState of activeStateImages(state)) {
157
+ const imageConfig = config.images.find((image) => image.id === imageState.id);
158
+ if (!imageConfig) {
159
+ continue;
160
+ }
161
+ try {
162
+ const startupScript = writeProjectImageStartupScript({
163
+ projectRoot,
164
+ config,
165
+ imageId: imageState.id,
166
+ imageState,
167
+ workspaceId,
168
+ stateRoot: options.stateRoot,
169
+ });
170
+ const launchClient = options.pharoLauncherMcpClient
171
+ ? client
172
+ : await createStdioPharoLauncherMcpClient();
173
+ const ownsLaunchClient = !options.pharoLauncherMcpClient;
174
+ try {
175
+ const process = await launchImageAndPollProcess(launchClient, client, imageState.imageName, startupScript.filePath, poll.processTimeoutMs, poll.intervalMs, sleep);
176
+ imageState.pid = process.pid;
177
+ const healthy = await pollHealth(healthClient, imageState.assignedPort, poll.healthTimeoutMs, poll.intervalMs, sleep);
178
+ if (!healthy) {
179
+ throw new Error(`Timed out waiting for Pharo MCP health on port ${imageState.assignedPort}`);
180
+ }
181
+ }
182
+ finally {
183
+ if (ownsLaunchClient) {
184
+ closeClientQuietly(launchClient);
185
+ }
186
+ }
187
+ imageState.status = "running";
188
+ }
189
+ catch (error) {
190
+ imageState.status = "failed";
191
+ failures.push({
192
+ imageId: imageState.id,
193
+ imageName: imageState.imageName,
194
+ message: errorMessage(error),
195
+ });
196
+ }
197
+ }
198
+ state.updatedAt = now().toISOString();
199
+ saveProjectState(statePath, state);
200
+ const result = {
201
+ ok: failures.length === 0,
202
+ projectRoot,
203
+ statePath,
204
+ state,
205
+ failures,
206
+ };
207
+ if (!result.ok) {
208
+ throw new ProjectOpenError("One or more project images failed to open", result);
209
+ }
210
+ return result;
211
+ }
212
+ finally {
213
+ if (ownsClient) {
214
+ await client.close?.();
215
+ }
216
+ }
217
+ }
218
+ //# sourceMappingURL=projectOpen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectOpen.js","sourceRoot":"","sources":["../src/projectOpen.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ import type { ProjectConfig, ProjectImageConfig } from "./projectConfig.js";
2
+ import { type ProjectImageState, type ProjectStatePathOptions } from "./projectState.js";
3
+ export declare const projectScriptsDirectoryName = "scripts";
4
+ export declare const defaultPharoMcpMetacelloRepository: {
5
+ readonly githubUser: "Evref-BL";
6
+ readonly project: "MCP";
7
+ readonly commitish: "main";
8
+ readonly path: "";
9
+ readonly baseline: "MCP";
10
+ };
11
+ export interface PharoMcpMetacelloRepository {
12
+ githubUser: string;
13
+ project: string;
14
+ commitish: string;
15
+ path: string;
16
+ baseline: string;
17
+ }
18
+ export interface ProjectScriptsDirectoryPathOptions extends ProjectStatePathOptions {
19
+ }
20
+ export interface ProjectImageStartupScriptPathOptions extends ProjectStatePathOptions {
21
+ imageId: string;
22
+ }
23
+ export interface GenerateImageStartupScriptOptions {
24
+ projectRoot: string;
25
+ imageConfig: ProjectImageConfig;
26
+ imageState: ProjectImageState;
27
+ repository?: PharoMcpMetacelloRepository;
28
+ }
29
+ export interface WriteImageStartupScriptOptions extends GenerateImageStartupScriptOptions {
30
+ projectId: string;
31
+ workspaceId?: string;
32
+ stateRoot?: string;
33
+ }
34
+ export interface WriteProjectImageStartupScriptOptions {
35
+ projectRoot: string;
36
+ config: ProjectConfig;
37
+ imageId: string;
38
+ imageState: ProjectImageState;
39
+ workspaceId?: string;
40
+ stateRoot?: string;
41
+ repository?: PharoMcpMetacelloRepository;
42
+ }
43
+ export interface WrittenImageStartupScript {
44
+ filePath: string;
45
+ source: string;
46
+ }
47
+ export declare class ProjectStartupScriptError extends Error {
48
+ constructor(message: string);
49
+ }
50
+ export declare function projectScriptsDirectoryPath(options: ProjectScriptsDirectoryPathOptions): string;
51
+ export declare function imageStartupScriptFileName(imageId: string): string;
52
+ export declare function imageStartupScriptPath(options: ProjectImageStartupScriptPathOptions): string;
53
+ export declare function generateImageStartupScript(options: GenerateImageStartupScriptOptions): string;
54
+ export declare function writeImageStartupScript(options: WriteImageStartupScriptOptions): WrittenImageStartupScript;
55
+ export declare function writeProjectImageStartupScript(options: WriteProjectImageStartupScriptOptions): WrittenImageStartupScript;
56
+ //# sourceMappingURL=projectStartupScript.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectStartupScript.d.ts","sourceRoot":"","sources":["../src/projectStartupScript.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAO5E,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,EAC7B,MAAM,mBAAmB,CAAC;AAE3B,eAAO,MAAM,2BAA2B,YAAY,CAAC;AAErD,eAAO,MAAM,kCAAkC;;;;;;CAMrC,CAAC;AAEX,MAAM,WAAW,2BAA2B;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kCACf,SAAQ,uBAAuB;CAAG;AAEpC,MAAM,WAAW,oCACf,SAAQ,uBAAuB;IAC/B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iCAAiC;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,kBAAkB,CAAC;IAChC,UAAU,EAAE,iBAAiB,CAAC;IAC9B,UAAU,CAAC,EAAE,2BAA2B,CAAC;CAC1C;AAED,MAAM,WAAW,8BACf,SAAQ,iCAAiC;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qCAAqC;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,iBAAiB,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,2BAA2B,CAAC;CAC1C;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,yBAA0B,SAAQ,KAAK;gBACtC,OAAO,EAAE,MAAM;CAI5B;AAED,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,kCAAkC,GAC1C,MAAM,CAKR;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAQlE;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,oCAAoC,GAC5C,MAAM,CAKR;AA4FD,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,iCAAiC,GACzC,MAAM,CA2CR;AAED,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,8BAA8B,GACtC,yBAAyB,CAc3B;AAED,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,qCAAqC,GAC7C,yBAAyB,CAY3B"}
@@ -0,0 +1,150 @@
1
+ import fs from "node:fs";
2
+ import { dirnamePathLike, isAbsolutePathLike, joinPathLike, resolvePathLike, } from "./pathStyle.js";
3
+ import { projectStateDirectoryPath, } from "./projectState.js";
4
+ export const projectScriptsDirectoryName = "scripts";
5
+ export const defaultPharoMcpMetacelloRepository = {
6
+ githubUser: "Evref-BL",
7
+ project: "MCP",
8
+ commitish: "main",
9
+ path: "",
10
+ baseline: "MCP",
11
+ };
12
+ export class ProjectStartupScriptError extends Error {
13
+ constructor(message) {
14
+ super(message);
15
+ this.name = "ProjectStartupScriptError";
16
+ }
17
+ }
18
+ export function projectScriptsDirectoryPath(options) {
19
+ return joinPathLike(projectStateDirectoryPath(options), projectScriptsDirectoryName);
20
+ }
21
+ export function imageStartupScriptFileName(imageId) {
22
+ if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(imageId)) {
23
+ throw new ProjectStartupScriptError(`Image id must be file-safe to generate a startup script: ${imageId}`);
24
+ }
25
+ return `start-${imageId}.st`;
26
+ }
27
+ export function imageStartupScriptPath(options) {
28
+ return joinPathLike(projectScriptsDirectoryPath(options), imageStartupScriptFileName(options.imageId));
29
+ }
30
+ function smalltalkString(value) {
31
+ return `'${value.replaceAll("'", "''")}'`;
32
+ }
33
+ function smalltalkPath(value) {
34
+ return smalltalkString(value.replace(/\\/g, "/"));
35
+ }
36
+ function generateGitConfigurationScript(imageConfig) {
37
+ if (!imageConfig.git) {
38
+ return "";
39
+ }
40
+ const git = imageConfig.git;
41
+ const requiresCredentialsProvider = Boolean(git.ssh || git.plainCredentials);
42
+ const lines = [
43
+ `"Configure image-local Git transport and credentials."`,
44
+ `Smalltalk globals at: #PLexusGitTransport put: ${smalltalkString(git.transport)}.`,
45
+ `(Smalltalk globals includesKey: #IceCredentialsProvider)`,
46
+ ` ifTrue: [`,
47
+ ` | credentialsProvider |`,
48
+ ` credentialsProvider := Smalltalk globals at: #IceCredentialsProvider.`,
49
+ ];
50
+ if (git.transport === "ssh") {
51
+ if (git.ssh) {
52
+ lines.push(` credentialsProvider useCustomSsh: true.`, ` credentialsProvider sshCredentials`, ` username: 'git';`, ` publicKey: ${smalltalkPath(git.ssh.publicKey)};`, ` privateKey: ${smalltalkPath(git.ssh.privateKey)}.`);
53
+ }
54
+ else {
55
+ lines.push(` "Use the image or platform SSH agent/defaults unless explicit keys are configured."`, ` credentialsProvider useCustomSsh: false.`);
56
+ }
57
+ }
58
+ else {
59
+ lines.push(` credentialsProvider useCustomSsh: false.`);
60
+ if (git.plainCredentials) {
61
+ lines.push(` (Smalltalk globals includesKey: #IcePlaintextCredentials)`, ` ifTrue: [`, ` credentialsProvider plaintextCredentials: ((Smalltalk globals at: #IcePlaintextCredentials) new`, ` username: ${smalltalkString(git.plainCredentials.username)};`, ` password: ${smalltalkString(git.plainCredentials.password)};`, ` yourself) ]`, ` ifFalse: [ Error signal: 'IcePlaintextCredentials class is not available.' ].`);
62
+ }
63
+ }
64
+ lines.push(`]`);
65
+ if (requiresCredentialsProvider) {
66
+ lines.push(` ifFalse: [ Error signal: 'IceCredentialsProvider class is not available.' ].`);
67
+ }
68
+ else {
69
+ lines.push(` ifFalse: [ nil ].`);
70
+ }
71
+ return lines.join("\n");
72
+ }
73
+ function resolveLoadScriptPath(projectRoot, imageConfig) {
74
+ return isAbsolutePathLike(imageConfig.mcp.loadScript)
75
+ ? resolvePathLike(imageConfig.mcp.loadScript)
76
+ : resolvePathLike(projectRoot, imageConfig.mcp.loadScript);
77
+ }
78
+ function findProjectImageConfig(config, imageId) {
79
+ const imageConfig = config.images.find((image) => image.id === imageId);
80
+ if (!imageConfig) {
81
+ throw new ProjectStartupScriptError(`Project config does not define image id: ${imageId}`);
82
+ }
83
+ return imageConfig;
84
+ }
85
+ export function generateImageStartupScript(options) {
86
+ const repository = options.repository ?? defaultPharoMcpMetacelloRepository;
87
+ const loadScriptPath = resolveLoadScriptPath(options.projectRoot, options.imageConfig);
88
+ const gitConfiguration = generateGitConfigurationScript(options.imageConfig);
89
+ return `"Generated by PLexus. Do not edit."
90
+
91
+ | loadScript mcp |
92
+
93
+ ${gitConfiguration}
94
+
95
+ "Load the Pharo MCP project if the image does not already provide it."
96
+ (Smalltalk globals includesKey: #MCP) ifFalse: [
97
+ loadScript := ${smalltalkPath(loadScriptPath)} asFileReference.
98
+ loadScript exists
99
+ ifTrue: [ loadScript fileIn ]
100
+ ifFalse: [
101
+ Metacello new
102
+ githubUser: ${smalltalkString(repository.githubUser)} project: ${smalltalkString(repository.project)} commitish: ${smalltalkString(repository.commitish)} path: ${smalltalkString(repository.path)};
103
+ baseline: ${smalltalkString(repository.baseline)};
104
+ load ] ].
105
+
106
+ (Smalltalk globals includesKey: #MCP)
107
+ ifFalse: [ Error signal: 'MCP class is not available after loading.' ].
108
+
109
+ "Stop the previous server registered by PLexus before starting a new one."
110
+ (Smalltalk globals at: #PLexusMCPServer ifAbsent: [ nil ])
111
+ ifNotNil: [ :existingServer |
112
+ [ existingServer stop ] on: Error do: [ :error | nil ] ].
113
+
114
+ "Configure and start the MCP server."
115
+ mcp := (Smalltalk globals at: #MCP) new.
116
+ mcp port: ${options.imageState.assignedPort}.
117
+ mcp start.
118
+
119
+ Smalltalk globals at: #PLexusMCPServer put: mcp.
120
+
121
+ "Keep the headless eval process alive while the MCP server accepts requests."
122
+ Semaphore new wait.
123
+ `;
124
+ }
125
+ export function writeImageStartupScript(options) {
126
+ const filePath = imageStartupScriptPath({
127
+ projectRoot: options.projectRoot,
128
+ projectId: options.projectId,
129
+ workspaceId: options.workspaceId,
130
+ imageId: options.imageConfig.id,
131
+ stateRoot: options.stateRoot,
132
+ });
133
+ const source = generateImageStartupScript(options);
134
+ fs.mkdirSync(dirnamePathLike(filePath), { recursive: true });
135
+ fs.writeFileSync(filePath, source, "utf8");
136
+ return { filePath, source };
137
+ }
138
+ export function writeProjectImageStartupScript(options) {
139
+ const imageConfig = findProjectImageConfig(options.config, options.imageId);
140
+ return writeImageStartupScript({
141
+ projectRoot: options.projectRoot,
142
+ projectId: options.config.kanban.projectId,
143
+ imageConfig,
144
+ imageState: options.imageState,
145
+ workspaceId: options.workspaceId,
146
+ stateRoot: options.stateRoot,
147
+ repository: options.repository,
148
+ });
149
+ }
150
+ //# sourceMappingURL=projectStartupScript.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectStartupScript.js","sourceRoot":"","sources":["../src/projectStartupScript.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,128 @@
1
+ import type { ProjectConfig } from "./projectConfig.js";
2
+ export declare const plexusStateDirectoryName = ".plexus";
3
+ export declare const plexusProjectsStateDirectoryName = "projects";
4
+ export declare const plexusWorkspacesStateDirectoryName = "workspaces";
5
+ export declare const projectStateFileName = "state.json";
6
+ export declare const defaultWorkspaceIdValue = "default";
7
+ export declare const defaultProjectPortRange: {
8
+ readonly start: 7100;
9
+ readonly end: 7199;
10
+ };
11
+ export type ProjectImageStatus = "starting" | "running" | "stopped" | "failed";
12
+ export type PharoMcpContractStatus = "unknown" | "matching" | "mismatched";
13
+ export interface PharoMcpContractReference {
14
+ id?: string;
15
+ hash?: string;
16
+ }
17
+ export interface ProjectImagePharoMcpContractState extends PharoMcpContractReference {
18
+ status?: PharoMcpContractStatus;
19
+ expectedId?: string;
20
+ expectedHash?: string;
21
+ }
22
+ export interface ProjectImageState {
23
+ id: string;
24
+ imageName: string;
25
+ assignedPort: number;
26
+ pid?: number;
27
+ status: ProjectImageStatus;
28
+ pharoMcpContract?: ProjectImagePharoMcpContractState;
29
+ imagePath?: string;
30
+ imageDirectoryPath?: string;
31
+ changesPath?: string;
32
+ localDirectoryPath?: string;
33
+ ombuDirectoryPath?: string;
34
+ vmId?: string;
35
+ pharoVersion?: string;
36
+ originTemplate?: {
37
+ name?: string;
38
+ url?: string;
39
+ };
40
+ rescueSnapshot?: {
41
+ capturedAt: string;
42
+ launcherImage?: {
43
+ name?: string;
44
+ pharoVersion?: string;
45
+ imagePath?: string;
46
+ originTemplate?: {
47
+ name?: string;
48
+ url?: string;
49
+ };
50
+ vmId?: string;
51
+ };
52
+ paths: {
53
+ imagePath?: string;
54
+ imageDirectoryPath?: string;
55
+ changesPath?: string;
56
+ localDirectoryPath?: string;
57
+ ombuDirectoryPath?: string;
58
+ };
59
+ repositories?: {
60
+ capturedAt: string;
61
+ status: "captured" | "unavailable";
62
+ repositories: Record<string, unknown>[];
63
+ error?: string;
64
+ };
65
+ };
66
+ }
67
+ export interface ProjectState {
68
+ projectId: string;
69
+ projectName: string;
70
+ workspaceId: string;
71
+ targetId: string;
72
+ pharoMcpContract?: PharoMcpContractReference;
73
+ images: ProjectImageState[];
74
+ updatedAt: string;
75
+ }
76
+ export interface ProjectPortRange {
77
+ start: number;
78
+ end: number;
79
+ }
80
+ export interface CreateProjectStateOptions {
81
+ updatedAt?: string;
82
+ previousState?: ProjectState;
83
+ portRange?: ProjectPortRange;
84
+ reservedPorts?: Iterable<number>;
85
+ workspaceId?: string;
86
+ targetId?: string;
87
+ }
88
+ export interface ProjectStatePathOptions {
89
+ projectRoot: string;
90
+ projectId: string;
91
+ workspaceId?: string;
92
+ stateRoot?: string;
93
+ }
94
+ export interface ProjectStatePathForConfigOptions {
95
+ projectRoot: string;
96
+ config: ProjectConfig;
97
+ workspaceId?: string;
98
+ stateRoot?: string;
99
+ }
100
+ export declare class PortAllocationError extends Error {
101
+ constructor(message: string);
102
+ }
103
+ export declare class ProjectStateError extends Error {
104
+ constructor(message: string);
105
+ }
106
+ export declare function defaultPlexusStateRoot(projectRoot: string): string;
107
+ export declare function sanitizeRuntimeId(value: string): string;
108
+ export declare function defaultWorkspaceId(projectRoot: string): string;
109
+ export declare function defaultTargetId(projectId: string, workspaceId: string): string;
110
+ export declare function projectWorkspacesStateDirectoryPath(options: Omit<ProjectStatePathOptions, "workspaceId">): string;
111
+ export declare function projectStateDirectoryPath(options: ProjectStatePathOptions): string;
112
+ export declare function projectStatePath(options: ProjectStatePathOptions): string;
113
+ export declare function projectStatePathForConfig(options: ProjectStatePathForConfigOptions): string;
114
+ export declare function loadProjectState(filePath: string): ProjectState | undefined;
115
+ export declare function saveProjectState(filePath: string, state: ProjectState): void;
116
+ export declare function collectReservedProjectPorts(options: Omit<ProjectStatePathOptions, "workspaceId"> & {
117
+ excludeWorkspaceId?: string;
118
+ }): number[];
119
+ export interface ProjectImageNameTemplateContext {
120
+ projectId: string;
121
+ projectName: string;
122
+ workspaceId: string;
123
+ targetId: string;
124
+ imageId: string;
125
+ }
126
+ export declare function renderProjectImageName(template: string, context: ProjectImageNameTemplateContext): string;
127
+ export declare function createProjectState(config: ProjectConfig, optionsOrUpdatedAt?: string | CreateProjectStateOptions): ProjectState;
128
+ //# sourceMappingURL=projectState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectState.d.ts","sourceRoot":"","sources":["../src/projectState.ts"],"names":[],"mappings":"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"}