paseo-smart-session 1.2.1 → 1.2.3

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/README.md CHANGED
@@ -37,13 +37,13 @@ That history remains useful after an individual session ends or a provider cache
37
37
  Install from npm on Paseo 0.9.0 or newer:
38
38
 
39
39
  ```sh
40
- paseo plugin install npm:paseo-smart-session@1.2.1
40
+ paseo plugin install npm:paseo-smart-session
41
41
  ```
42
42
 
43
43
  Paseo 0.8 can install the same plugin from Git:
44
44
 
45
45
  ```sh
46
- paseo plugin add tomgrin10/paseo-smart-session --ref v1.2.1
46
+ paseo plugin add tomgrin10/paseo-smart-session
47
47
  ```
48
48
 
49
49
  ```sh
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "paseo-smart-session",
3
3
  "type": "module",
4
- "version": "1.2.1",
4
+ "version": "1.2.3",
5
5
  "license": "MIT",
6
6
  "description": "Records Claude plan-usage history and lets a Paseo agent manage its own context.",
7
7
  "repository": {
@@ -11,7 +11,13 @@
11
11
  "homepage": "https://github.com/tomgrin10/paseo-smart-session#readme",
12
12
  "bugs": "https://github.com/tomgrin10/paseo-smart-session/issues",
13
13
  "author": "Tom Gringauz",
14
- "keywords": ["paseo", "paseo-plugin", "context", "monitoring", "productivity"],
14
+ "keywords": [
15
+ "paseo",
16
+ "paseo-plugin",
17
+ "context",
18
+ "monitoring",
19
+ "productivity"
20
+ ],
15
21
  "files": [
16
22
  "paseo-plugin.json",
17
23
  "index.client.tsx",
@@ -25,6 +25,7 @@ void install()
25
25
  console.log(`[smart-session] registered ${report.hooks.join(", ")} in ${report.settingsPath}`);
26
26
  }
27
27
  if (report.mcp === "added") console.log("[smart-session] registered the agent-facing MCP server");
28
+ if (report.mcp === "updated") console.log("[smart-session] updated the agent-facing MCP server path");
28
29
  if (report.mcp === "unavailable") {
29
30
  console.error(
30
31
  "[smart-session] could not reach the `claude` CLI to register the MCP server; run `claude mcp add-json --scope user smart-session` by hand if the agent tools are missing",
package/server/install.ts CHANGED
@@ -78,7 +78,7 @@ export interface InstallReport {
78
78
  readonly changed: boolean;
79
79
  /** One line per managed event, for the surface to show. */
80
80
  readonly hooks: string[];
81
- readonly mcp: "present" | "added" | "unavailable" | "skipped";
81
+ readonly mcp: "present" | "added" | "updated" | "unavailable" | "skipped";
82
82
  readonly error: string | null;
83
83
  }
84
84
 
@@ -204,15 +204,26 @@ async function writeAtomic(path: string, text: string): Promise<void> {
204
204
  * `~/.claude.json` is where the MCP list lives, and it is also where credentials
205
205
  * live, so this plugin does not write it: `claude mcp add-json` does, which keeps
206
206
  * us out of a file we have no business editing. Only ever called when the server is
207
- * absent, because shelling out on every load would be absurd.
207
+ * absent or points at an older installation path. Managed npm and Git updates
208
+ * install into a new directory, so an entry can exist while its script no longer
209
+ * does.
208
210
  */
211
+ export function mcpPointsAtPlugin(output: string, pluginDir: string): boolean {
212
+ const lines = output.split(/\r?\n/).map((line) => line.trim());
213
+ return lines.includes("Scope: User config (available in all your projects)")
214
+ && lines.includes("Command: node")
215
+ && lines.includes(`Args: ${join(pluginDir, "mcp.mjs")}`);
216
+ }
217
+
209
218
  async function ensureMcp(pluginDir: string): Promise<InstallReport["mcp"]> {
210
219
  const run = (args: string[]): Promise<{ stdout: string }> =>
211
220
  execFileAsync("claude", args, { timeout: 20_000, maxBuffer: 1024 * 1024 });
212
221
 
222
+ let existing = false;
213
223
  try {
214
- await run(["mcp", "get", "smart-session"]);
215
- return "present";
224
+ const { stdout } = await run(["mcp", "get", "smart-session"]);
225
+ if (mcpPointsAtPlugin(stdout, pluginDir)) return "present";
226
+ existing = true;
216
227
  } catch {
217
228
  // Absent, or no `claude` on PATH. The add below tells the two apart.
218
229
  }
@@ -223,8 +234,9 @@ async function ensureMcp(pluginDir: string): Promise<InstallReport["mcp"]> {
223
234
  args: [join(pluginDir, "mcp.mjs")],
224
235
  });
225
236
  try {
237
+ if (existing) await run(["mcp", "remove", "smart-session", "--scope", "user"]);
226
238
  await run(["mcp", "add-json", "--scope", "user", "smart-session", definition]);
227
- return "added";
239
+ return existing ? "updated" : "added";
228
240
  } catch {
229
241
  // No `claude` binary on the daemon's PATH is the usual reason, and it is not
230
242
  // an error worth failing a plugin load over.
@@ -109,7 +109,7 @@ export const InstallReportSchema = z.object({
109
109
  settingsPath: z.string(),
110
110
  changed: z.boolean(),
111
111
  hooks: z.array(z.string()),
112
- mcp: z.enum(["present", "added", "unavailable", "skipped"]),
112
+ mcp: z.enum(["present", "added", "updated", "unavailable", "skipped"]),
113
113
  error: z.string().nullable(),
114
114
  });
115
115