@paigy/mcp 0.40.9 → 0.40.10

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.
@@ -4,7 +4,7 @@ import {
4
4
  requestCode,
5
5
  saveToken,
6
6
  sleep
7
- } from "./chunk-5OY6ED2Q.js";
7
+ } from "./chunk-HCCUK3ZL.js";
8
8
 
9
9
  // src/identity.ts
10
10
  var CLIENT_LABELS = {
@@ -1,6 +1,10 @@
1
1
  // ../../packages/sdk/dist/index.js
2
2
  import { createRequire as __sdkCreateRequire } from "module";
3
+ import { execFileSync } from "child_process";
3
4
  import { createHash, randomUUID } from "crypto";
5
+ import { readFileSync } from "fs";
6
+ import { homedir } from "os";
7
+ import { join } from "path";
4
8
  import { randomUUID as randomUUID3 } from "crypto";
5
9
  import { setTimeout as sleep2 } from "timers/promises";
6
10
  import { z as z3 } from "zod";
@@ -10,9 +14,9 @@ import { ZodFirstPartyTypeKind } from "zod/v3";
10
14
  import { ZodFirstPartyTypeKind as ZodFirstPartyTypeKind2 } from "zod/v3";
11
15
  import { z } from "zod";
12
16
  import { randomUUID as randomUUID2 } from "crypto";
13
- import { closeSync, existsSync, mkdirSync, openSync, readFileSync, rmSync, statSync, writeFileSync } from "fs";
14
- import { homedir } from "os";
15
- import { join } from "path";
17
+ import { closeSync, existsSync, mkdirSync, openSync, readFileSync as readFileSync2, rmSync, statSync, writeFileSync } from "fs";
18
+ import { homedir as homedir2 } from "os";
19
+ import { join as join2 } from "path";
16
20
  import { randomUUID as randomUUID4 } from "crypto";
17
21
  import { WebSocket } from "undici";
18
22
  var require2 = __sdkCreateRequire(import.meta.url);
@@ -36,15 +40,42 @@ var envSession = (key) => {
36
40
  const v = process.env[key];
37
41
  return v && v.trim() ? v : void 0;
38
42
  };
39
- var SESSION_ID = envSession("PAIGY_SESSION_ID") ?? envSession("CLAUDE_CODE_SESSION_ID") ?? envSession("CODEX_THREAD_ID") ?? envSession("CODEX_SESSION_ID") ?? WORKSPACE_ID;
43
+ function parentOf(pid) {
44
+ try {
45
+ if (process.platform === "win32") return void 0;
46
+ const ppid = process.platform === "linux" ? readFileSync(`/proc/${pid}/stat`, "utf8").split(") ")[1]?.split(" ")[1] : execFileSync("ps", ["-o", "ppid=", "-p", String(pid)], { encoding: "utf8", timeout: 1e3 });
47
+ return Number(ppid?.trim()) || void 0;
48
+ } catch {
49
+ return void 0;
50
+ }
51
+ }
52
+ var lineage;
53
+ function ancestors() {
54
+ if (lineage) return lineage;
55
+ lineage = [];
56
+ for (let pid = process.ppid; pid && pid > 1 && lineage.length < 5; pid = parentOf(pid)) lineage.push(pid);
57
+ return lineage;
58
+ }
59
+ function claudeConversation() {
60
+ if (!envSession("CLAUDE_CODE_SESSION_ID") || process.env.CLAUDE_CODE_CHILD_SESSION) return void 0;
61
+ const dir = envSession("CLAUDE_CONFIG_DIR") ?? join(homedir(), ".claude");
62
+ for (const pid of ancestors()) {
63
+ try {
64
+ const { sessionId: sessionId2 } = JSON.parse(readFileSync(join(dir, "sessions", `${pid}.json`), "utf8"));
65
+ return typeof sessionId2 === "string" && sessionId2.trim() ? sessionId2 : void 0;
66
+ } catch {
67
+ }
68
+ }
69
+ return void 0;
70
+ }
40
71
  function sessionId() {
41
- return SESSION_ID;
72
+ return envSession("PAIGY_SESSION_ID") ?? claudeConversation() ?? envSession("CLAUDE_CODE_SESSION_ID") ?? envSession("CODEX_THREAD_ID") ?? envSession("CODEX_SESSION_ID") ?? WORKSPACE_ID;
42
73
  }
43
74
  function isNetworkError(e) {
44
75
  return e instanceof Error && e.message.startsWith(NETWORK_MSG);
45
76
  }
46
77
  async function reach(url, init) {
47
- return send(url, init, SESSION_ID);
78
+ return send(url, init, sessionId());
48
79
  }
49
80
  async function send(url, init, session) {
50
81
  try {
@@ -2352,13 +2383,15 @@ function sessionSlot(sessionId2) {
2352
2383
  const id = sessionId2 ?? sessionId();
2353
2384
  return `session:${id.slice(0, 8)}`;
2354
2385
  }
2355
- var AGENT_NAME = process.env.PAIGY_AGENT || sessionSlot();
2356
- var TOKEN_PATH = join(homedir(), ".paigy", "token.json");
2357
- var KEY_PATH = join(homedir(), ".paigy", "key.json");
2386
+ function agentName() {
2387
+ return process.env.PAIGY_AGENT || sessionSlot();
2388
+ }
2389
+ var TOKEN_PATH = join2(homedir2(), ".paigy", "token.json");
2390
+ var KEY_PATH = join2(homedir2(), ".paigy", "key.json");
2358
2391
  function readTokenFile() {
2359
2392
  if (!existsSync(TOKEN_PATH)) return {};
2360
2393
  try {
2361
- const parsed = JSON.parse(readFileSync(TOKEN_PATH, "utf8"));
2394
+ const parsed = JSON.parse(readFileSync2(TOKEN_PATH, "utf8"));
2362
2395
  if (typeof parsed.access_token === "string") return {};
2363
2396
  const slots = parsed;
2364
2397
  delete slots["*"];
@@ -2370,7 +2403,7 @@ function readTokenFile() {
2370
2403
  function withTokenLock(mutate) {
2371
2404
  const lock = TOKEN_PATH + ".lock";
2372
2405
  const spin = new Int32Array(new SharedArrayBuffer(4));
2373
- mkdirSync(join(homedir(), ".paigy"), { recursive: true });
2406
+ mkdirSync(join2(homedir2(), ".paigy"), { recursive: true });
2374
2407
  for (const deadline = Date.now() + 5e3; Date.now() < deadline; ) {
2375
2408
  try {
2376
2409
  closeSync(openSync(lock, "wx"));
@@ -2387,14 +2420,14 @@ function withTokenLock(mutate) {
2387
2420
  rmSync(lock, { force: true });
2388
2421
  }
2389
2422
  }
2390
- function saveToken(token, agent2 = AGENT_NAME) {
2423
+ function saveToken(token, agent2 = agentName()) {
2391
2424
  withTokenLock(() => {
2392
2425
  const slots = { ...readTokenFile(), [agent2]: token };
2393
2426
  writeFileSync(TOKEN_PATH, JSON.stringify(slots, null, 2) + "\n", { mode: 384 });
2394
2427
  });
2395
2428
  }
2396
2429
  var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
2397
- function readToken(agent2 = AGENT_NAME) {
2430
+ function readToken(agent2 = agentName()) {
2398
2431
  if (process.env.PAIGY_TOKEN) return process.env.PAIGY_TOKEN;
2399
2432
  return readTokenFile()[agent2]?.access_token ?? "";
2400
2433
  }
@@ -2404,7 +2437,7 @@ function listSlots() {
2404
2437
  function slotName(agent2) {
2405
2438
  return readTokenFile()[agent2]?.name ?? null;
2406
2439
  }
2407
- function deleteToken(agent2 = AGENT_NAME) {
2440
+ function deleteToken(agent2 = agentName()) {
2408
2441
  return withTokenLock(() => {
2409
2442
  const slots = readTokenFile();
2410
2443
  if (!(agent2 in slots)) return false;
@@ -2421,7 +2454,7 @@ async function revokeToken(token) {
2421
2454
  });
2422
2455
  return res.ok;
2423
2456
  }
2424
- async function requestCode(suggestedName = AGENT_NAME, device) {
2457
+ async function requestCode(suggestedName = agentName(), device) {
2425
2458
  const res = await reach(`${BACKEND_URL}/api/device/code`, {
2426
2459
  method: "POST",
2427
2460
  headers: { "content-type": "application/json" },
@@ -2876,7 +2909,7 @@ async function subscribeWake(onNudge, opts = {}) {
2876
2909
  export {
2877
2910
  isNetworkError,
2878
2911
  sessionSlot,
2879
- AGENT_NAME,
2912
+ agentName,
2880
2913
  TOKEN_PATH,
2881
2914
  saveToken,
2882
2915
  sleep,
@@ -4,8 +4,8 @@ import {
4
4
  serverInstructions
5
5
  } from "./chunk-UFOR2QEP.js";
6
6
  import {
7
- AGENT_NAME
8
- } from "./chunk-5OY6ED2Q.js";
7
+ agentName
8
+ } from "./chunk-HCCUK3ZL.js";
9
9
 
10
10
  // src/toolset.ts
11
11
  var ONBOARD_DESCRIPTION = "Get this agent talking to Paigy \u2014 call it FIRST, before contact, and any time you're unsure who you are. One call, and it does whatever the situation needs: NOT SET UP \u2192 hatches an identity instantly if this machine holds a device credential (the user ran the Paigy desktop app or harness), otherwise starts the code ceremony; ALREADY SET UP \u2192 returns your current identity and offers the two things left to decide, renaming it or unpairing; TOKEN NO LONGER VALID \u2192 says so, then re-pairs. Pass { name, voice } to choose who you are when hatching, or to RENAME yourself when already set up (voices: rachel, george, jessica, brian, lily). Safe to call any time: idempotent, and it never writes settings \u2014 the tool-allowlist state it reports is read-only. If it returns a `user_code`, print it to the user immediately and call onboard again with the `device_code`. If it returns `enable_command`, PRINT that command for the user to run \u2014 you cannot apply it yourself (it writes your own permission allowlist, which hosts block as privilege escalation), so print it, don't wait for it, and carry on.";
@@ -88,7 +88,7 @@ function withPaigyMcpToml(existing, agent) {
88
88
  ].join("\n");
89
89
  return existing + entry;
90
90
  }
91
- function autoConfigureClients(skip = AGENT_NAME) {
91
+ function autoConfigureClients(skip = agentName()) {
92
92
  const home = homedir();
93
93
  const registered = [];
94
94
  if (skip !== "antigravity") {
@@ -124,7 +124,7 @@ function autoConfigureClients(skip = AGENT_NAME) {
124
124
  }
125
125
  return registered;
126
126
  }
127
- function claudeInstallHint(skip = AGENT_NAME) {
127
+ function claudeInstallHint(skip = agentName()) {
128
128
  if (skip.startsWith("claude")) return null;
129
129
  const claudeDir = join(homedir(), ".claude");
130
130
  if (!existsSync(claudeDir)) return null;
package/dist/enable.js CHANGED
@@ -2,9 +2,9 @@
2
2
  import {
3
3
  PAIGY_TOOL_IDS,
4
4
  enablePaigyTools
5
- } from "./chunk-UOROFXDI.js";
5
+ } from "./chunk-QAQET3PZ.js";
6
6
  import "./chunk-UFOR2QEP.js";
7
- import "./chunk-5OY6ED2Q.js";
7
+ import "./chunk-HCCUK3ZL.js";
8
8
 
9
9
  // src/enable.ts
10
10
  function main() {
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  resolvePairing,
6
6
  startPairing,
7
7
  suggestedAgentName
8
- } from "./chunk-LYPZ5QO2.js";
8
+ } from "./chunk-AK5AVPF6.js";
9
9
  import {
10
10
  ENABLE_COMMAND,
11
11
  OnboardSchema,
@@ -14,15 +14,15 @@ import {
14
14
  SERVER_INSTRUCTIONS,
15
15
  TOOLS,
16
16
  paigyToolsAllowlisted
17
- } from "./chunk-UOROFXDI.js";
17
+ } from "./chunk-QAQET3PZ.js";
18
18
  import "./chunk-UFOR2QEP.js";
19
19
  import {
20
20
  clearSurface,
21
21
  writeSurface
22
22
  } from "./chunk-3SVNPJPN.js";
23
23
  import {
24
- AGENT_NAME,
25
24
  UnpairedError,
25
+ agentName,
26
26
  deleteToken,
27
27
  hatch,
28
28
  heartbeat,
@@ -35,7 +35,7 @@ import {
35
35
  setIdentity,
36
36
  slotName,
37
37
  whoAmI
38
- } from "./chunk-5OY6ED2Q.js";
38
+ } from "./chunk-HCCUK3ZL.js";
39
39
 
40
40
  // src/index.ts
41
41
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
@@ -108,7 +108,7 @@ function renderPairOutcome(outcome, device_code) {
108
108
  function unidentifiedResult() {
109
109
  return { isError: true, content: [{ type: "text", text: JSON.stringify({
110
110
  error: "no_identity",
111
- slot: AGENT_NAME,
111
+ slot: agentName(),
112
112
  message: `This session has no Paigy identity yet, so nothing was sent \u2014 it will not speak as another session. This machine holds a device credential but hatching under it just failed (it may have been revoked), so call \`pair\` (no arguments) to set this session up, then retry \u2014 it re-hatches if the credential recovered and runs the code ceremony if it didn't. To reuse an existing identity instead, start the session with PAIGY_AGENT set to its slot (${listSlots().filter((s) => s !== "Desktop").join(", ") || "none yet"}).`
113
113
  }) }] };
114
114
  }
@@ -238,7 +238,7 @@ async function handleTool(request, signal) {
238
238
  case "onboard": {
239
239
  const { name, voice, device_code, scope } = OnboardSchema.parse(request.params.arguments ?? {});
240
240
  if (device_code) return runPair(device_code, name, voice);
241
- const slot = AGENT_NAME;
241
+ const slot = agentName();
242
242
  const secret = readToken();
243
243
  if (secret) {
244
244
  let who = await whoAmI().catch(() => null);
@@ -307,7 +307,7 @@ async function handleTool(request, signal) {
307
307
  default: {
308
308
  const name = request.params.name;
309
309
  const result = await runTool(name, request.params.arguments ?? {}, { waits: true, signal });
310
- const sentAs = name === "contact" ? slotName(AGENT_NAME) : null;
310
+ const sentAs = name === "contact" ? slotName(agentName()) : null;
311
311
  const shaped = sentAs && result && typeof result === "object" ? { ...result, sentAs } : result;
312
312
  return { content: [{ type: "text", text: JSON.stringify(shaped) }] };
313
313
  }
package/dist/listen.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  contact,
8
8
  getGoal,
9
9
  subscribeWake
10
- } from "./chunk-5OY6ED2Q.js";
10
+ } from "./chunk-HCCUK3ZL.js";
11
11
 
12
12
  // src/listen.ts
13
13
  import { spawn } from "child_process";
package/dist/onboard.js CHANGED
@@ -3,16 +3,16 @@ import {
3
3
  resolvePairing,
4
4
  startPairing,
5
5
  suggestedAgentName
6
- } from "./chunk-LYPZ5QO2.js";
6
+ } from "./chunk-AK5AVPF6.js";
7
7
  import {
8
8
  autoConfigureClients,
9
9
  claudeInstallHint,
10
10
  openBrowser
11
- } from "./chunk-UOROFXDI.js";
11
+ } from "./chunk-QAQET3PZ.js";
12
12
  import "./chunk-UFOR2QEP.js";
13
13
  import {
14
- AGENT_NAME,
15
14
  TOKEN_PATH,
15
+ agentName,
16
16
  hatch,
17
17
  listSlots,
18
18
  overrideToken,
@@ -20,7 +20,7 @@ import {
20
20
  saveToken,
21
21
  setIdentity,
22
22
  whoAmI
23
- } from "./chunk-5OY6ED2Q.js";
23
+ } from "./chunk-HCCUK3ZL.js";
24
24
 
25
25
  // src/onboard.ts
26
26
  function reportRegistered() {
@@ -36,7 +36,7 @@ function reportRegistered() {
36
36
  }
37
37
  async function main() {
38
38
  console.log(`
39
- Paigy MCP onboarding (agent: "${AGENT_NAME}")
39
+ Paigy MCP onboarding (agent: "${agentName()}")
40
40
  `);
41
41
  const chosen = process.env.PAIGY_NAME ?? suggestedAgentName();
42
42
  if (readToken()) {
package/dist/slot.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- AGENT_NAME
4
- } from "./chunk-5OY6ED2Q.js";
3
+ agentName
4
+ } from "./chunk-HCCUK3ZL.js";
5
5
 
6
6
  // src/slot.ts
7
- process.stdout.write(AGENT_NAME);
7
+ process.stdout.write(agentName());
@@ -7,7 +7,7 @@ import {
7
7
  readToken,
8
8
  sessionSlot,
9
9
  slotName
10
- } from "./chunk-5OY6ED2Q.js";
10
+ } from "./chunk-HCCUK3ZL.js";
11
11
 
12
12
  // src/statusline.ts
13
13
  import { realpathSync } from "fs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paigy/mcp",
3
- "version": "0.40.9",
3
+ "version": "0.40.10",
4
4
  "description": "Paigy MCP server — the AI agent harness that calls you. Lets an agent notify a user and await their reply.",
5
5
  "license": "MIT",
6
6
  "type": "module",