@evref-bl/pharo-agent 0.9.1 → 0.10.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/.claude-plugin/plugin.json +1 -1
- package/package.json +8 -4
- package/plugin.json +1 -1
- package/skills/pharo-setup/SKILL.md +1 -1
- package/src/gateway.js +8 -12
- package/src/images.js +3 -1
- package/src/init.js +1 -0
- package/src/live.js +4 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evref-bl/pharo-agent",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Terminal-first Pharo integration for coding agents.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -26,13 +26,17 @@
|
|
|
26
26
|
"node": ">=22.12.0"
|
|
27
27
|
},
|
|
28
28
|
"scripts": {
|
|
29
|
-
"check": "
|
|
29
|
+
"check": "tsc --noEmit",
|
|
30
30
|
"package:check": "npm pack --dry-run",
|
|
31
31
|
"test": "node --test"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@evref-bl/pharo-mcp": "3.3.
|
|
35
|
-
"@evref-bl/plexus": "0.
|
|
34
|
+
"@evref-bl/pharo-mcp": "3.3.1",
|
|
35
|
+
"@evref-bl/plexus": "0.10.1",
|
|
36
36
|
"@modelcontextprotocol/sdk": "1.32.1"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/node": "^22.20.5",
|
|
40
|
+
"typescript": "^5.9.3"
|
|
37
41
|
}
|
|
38
42
|
}
|
package/plugin.json
CHANGED
|
@@ -8,7 +8,7 @@ Run this only when the user asks to enable or refresh Pharo tooling in this proj
|
|
|
8
8
|
From the project root, run the released CLI that matches this plugin:
|
|
9
9
|
|
|
10
10
|
```sh
|
|
11
|
-
npx --yes @evref-bl/pharo-agent@0.
|
|
11
|
+
npx --yes @evref-bl/pharo-agent@0.10.1 init --host claude
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
Name the host this chat runs in: `--host claude` in Claude Code,
|
package/src/gateway.js
CHANGED
|
@@ -17,28 +17,24 @@ import {
|
|
|
17
17
|
// release to forget, and the host shows this one to the user.
|
|
18
18
|
export const { version } = createRequire(import.meta.url)("../package.json");
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
// A route source is the directory, not the route. PLexus re-reads the state
|
|
21
|
+
// file and the image's endpoint handoff every time it resolves one, so there
|
|
22
|
+
// is nothing to register here and nothing that can go stale between the call
|
|
23
|
+
// that opened the image and this one.
|
|
24
|
+
export function imageGateway(projectRoot, open) {
|
|
21
25
|
const state = readJson(open.statePath);
|
|
22
26
|
const { image, mcpServerId } = selectRunningImage(state, open.imageId);
|
|
23
27
|
if (image.id !== open.imageId || mcpServerId !== open.mcpServerId) {
|
|
24
28
|
throw new Error(`The PLexus image ${open.imageId} changed; run pharo-agent open again.`);
|
|
25
29
|
}
|
|
26
30
|
const gateway = new PlexusGateway({
|
|
31
|
+
routeSources: [{ projectRoot, statePath: open.statePath }],
|
|
27
32
|
pharoScope: {
|
|
28
33
|
projectId: state.projectId,
|
|
29
34
|
workspaceId: state.workspaceId,
|
|
30
|
-
targetId: state.targetId,
|
|
31
35
|
},
|
|
32
36
|
pharoToolSchemaMcpServerId: mcpServerId,
|
|
33
37
|
});
|
|
34
|
-
const registered = await gateway.registerProjectRoute({
|
|
35
|
-
projectRoot,
|
|
36
|
-
statePath: open.statePath,
|
|
37
|
-
state,
|
|
38
|
-
});
|
|
39
|
-
if (!registered.ok) {
|
|
40
|
-
throw new Error(registered.error ?? "Cannot register the PLexus route.");
|
|
41
|
-
}
|
|
42
38
|
return { gateway, mcpServerId, image };
|
|
43
39
|
}
|
|
44
40
|
|
|
@@ -54,7 +50,7 @@ export function toolFailureMessage(error, image) {
|
|
|
54
50
|
}
|
|
55
51
|
|
|
56
52
|
export async function callImageTool(projectRoot, open, toolName, argumentsValue) {
|
|
57
|
-
const { gateway, mcpServerId, image } =
|
|
53
|
+
const { gateway, mcpServerId, image } = imageGateway(projectRoot, open);
|
|
58
54
|
const result = await gateway.routeToImage({
|
|
59
55
|
mcpServerId,
|
|
60
56
|
toolName,
|
|
@@ -69,7 +65,7 @@ export async function callImageTool(projectRoot, open, toolName, argumentsValue)
|
|
|
69
65
|
}
|
|
70
66
|
|
|
71
67
|
export async function listImageTools(projectRoot, open) {
|
|
72
|
-
const { gateway } =
|
|
68
|
+
const { gateway } = imageGateway(projectRoot, open);
|
|
73
69
|
return gateway.refreshPharoTools();
|
|
74
70
|
}
|
|
75
71
|
|
package/src/images.js
CHANGED
|
@@ -37,7 +37,9 @@ export function listImages(projectRoot) {
|
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
/** @param {{ id: string, template?: string, category?: string, profile?: string }} request */
|
|
41
|
+
export function addImage(projectRoot, request) {
|
|
42
|
+
const { id, template, category, profile } = request;
|
|
41
43
|
const config = readProjectConfig(projectRoot);
|
|
42
44
|
const images = Array.isArray(config.images) ? config.images : [];
|
|
43
45
|
if (images.some((image) => image.id === id)) {
|
package/src/init.js
CHANGED
|
@@ -181,6 +181,7 @@ function resolveInitProjectRoot(cwd) {
|
|
|
181
181
|
return { projectRoot, createdProjectConfig: true };
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
+
/** @param {{ host: string, mountRoot?: string, cwd?: string }} options */
|
|
184
185
|
export function initialize({ host, mountRoot, cwd = process.cwd() }) {
|
|
185
186
|
const guideName = guideForHost(host);
|
|
186
187
|
if (!guideName) {
|
package/src/live.js
CHANGED
|
@@ -360,7 +360,10 @@ export function agentImageStatus(projectRoot) {
|
|
|
360
360
|
export async function listImageTemplates(projectRoot) {
|
|
361
361
|
// `image add --template` takes a name the launcher must already know, and a
|
|
362
362
|
// name that lands in two categories needs the category as well, so answer
|
|
363
|
-
// both rather than leave the caller guessing a magic string.
|
|
363
|
+
// both rather than leave the caller guessing a magic string. Listing without
|
|
364
|
+
// a category walks the groups and stamps `templateCategory` on each row, and
|
|
365
|
+
// neither it nor the launcher's own `category` is promised when the sources
|
|
366
|
+
// list names no group at all, which is why both are optional.
|
|
364
367
|
const listed = await new ScopedPharoLauncher({ projectRoot }).listTemplates();
|
|
365
368
|
const counts = new Map();
|
|
366
369
|
for (const template of listed.templates) {
|