@paigy/mcp 0.28.1 → 0.29.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.
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// ../../packages/sdk/dist/index.js
|
|
2
2
|
import { createRequire as __sdkCreateRequire } from "module";
|
|
3
3
|
import { z } from "zod";
|
|
4
|
-
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "fs";
|
|
4
|
+
import { closeSync, existsSync, mkdirSync, openSync, readFileSync, rmSync, statSync, writeFileSync } from "fs";
|
|
5
|
+
import { randomUUID } from "crypto";
|
|
5
6
|
import { homedir } from "os";
|
|
6
7
|
import { join } from "path";
|
|
7
8
|
var require2 = __sdkCreateRequire(import.meta.url);
|
|
@@ -3555,7 +3556,11 @@ function verifyPairingCommit(commitment, proto, role, x25519Pub, ed25519Pub, non
|
|
|
3555
3556
|
return false;
|
|
3556
3557
|
}
|
|
3557
3558
|
}
|
|
3558
|
-
|
|
3559
|
+
function sessionSlot(sessionId) {
|
|
3560
|
+
const id = sessionId ?? process.env.PAIGY_SESSION_ID ?? process.env.CLAUDE_CODE_SESSION_ID ?? randomUUID();
|
|
3561
|
+
return `session:${id.slice(0, 8)}`;
|
|
3562
|
+
}
|
|
3563
|
+
var AGENT_NAME = process.env.PAIGY_AGENT || sessionSlot();
|
|
3559
3564
|
var PROTO = "paigy-pair-v2|sas=24";
|
|
3560
3565
|
var SAS_BITS = 24;
|
|
3561
3566
|
var TOKEN_PATH = join(homedir(), ".paigy", "token.json");
|
|
@@ -3572,10 +3577,31 @@ function readTokenFile() {
|
|
|
3572
3577
|
return {};
|
|
3573
3578
|
}
|
|
3574
3579
|
}
|
|
3575
|
-
function
|
|
3576
|
-
const
|
|
3580
|
+
function withTokenLock(mutate) {
|
|
3581
|
+
const lock = TOKEN_PATH + ".lock";
|
|
3582
|
+
const spin = new Int32Array(new SharedArrayBuffer(4));
|
|
3577
3583
|
mkdirSync(join(homedir(), ".paigy"), { recursive: true });
|
|
3578
|
-
|
|
3584
|
+
for (const deadline = Date.now() + 5e3; Date.now() < deadline; ) {
|
|
3585
|
+
try {
|
|
3586
|
+
closeSync(openSync(lock, "wx"));
|
|
3587
|
+
break;
|
|
3588
|
+
} catch {
|
|
3589
|
+
const held = statSync(lock, { throwIfNoEntry: false })?.mtimeMs ?? Date.now();
|
|
3590
|
+
if (Date.now() - held > 5e3) rmSync(lock, { force: true });
|
|
3591
|
+
else Atomics.wait(spin, 0, 0, 25);
|
|
3592
|
+
}
|
|
3593
|
+
}
|
|
3594
|
+
try {
|
|
3595
|
+
return mutate();
|
|
3596
|
+
} finally {
|
|
3597
|
+
rmSync(lock, { force: true });
|
|
3598
|
+
}
|
|
3599
|
+
}
|
|
3600
|
+
function saveToken(token, agent2 = AGENT_NAME) {
|
|
3601
|
+
withTokenLock(() => {
|
|
3602
|
+
const slots = { ...readTokenFile(), [agent2]: token };
|
|
3603
|
+
writeFileSync(TOKEN_PATH, JSON.stringify(slots, null, 2) + "\n", { mode: 384 });
|
|
3604
|
+
});
|
|
3579
3605
|
}
|
|
3580
3606
|
var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
3581
3607
|
function readToken(agent2 = AGENT_NAME) {
|
|
@@ -3585,13 +3611,18 @@ function readToken(agent2 = AGENT_NAME) {
|
|
|
3585
3611
|
function listSlots() {
|
|
3586
3612
|
return Object.keys(readTokenFile());
|
|
3587
3613
|
}
|
|
3614
|
+
function slotName(agent2) {
|
|
3615
|
+
return readTokenFile()[agent2]?.name ?? null;
|
|
3616
|
+
}
|
|
3588
3617
|
function deleteToken(agent2 = AGENT_NAME) {
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3618
|
+
return withTokenLock(() => {
|
|
3619
|
+
const slots = readTokenFile();
|
|
3620
|
+
if (!(agent2 in slots)) return false;
|
|
3621
|
+
delete slots[agent2];
|
|
3622
|
+
if (Object.keys(slots).length === 0) rmSync(TOKEN_PATH);
|
|
3623
|
+
else writeFileSync(TOKEN_PATH, JSON.stringify(slots, null, 2) + "\n", { mode: 384 });
|
|
3624
|
+
return true;
|
|
3625
|
+
});
|
|
3595
3626
|
}
|
|
3596
3627
|
async function revokeToken(token) {
|
|
3597
3628
|
const res = await reach(`${BACKEND_URL}/api/device/revoke`, {
|
|
@@ -3978,6 +4009,7 @@ export {
|
|
|
3978
4009
|
sleep,
|
|
3979
4010
|
readToken,
|
|
3980
4011
|
listSlots,
|
|
4012
|
+
slotName,
|
|
3981
4013
|
deleteToken,
|
|
3982
4014
|
revokeToken,
|
|
3983
4015
|
requestCode,
|
package/dist/index.js
CHANGED
|
@@ -7,12 +7,13 @@ import {
|
|
|
7
7
|
autoConfigureClients,
|
|
8
8
|
claudeInstallHint,
|
|
9
9
|
enablePaigyTools
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-JG2XL7Y3.js";
|
|
11
11
|
import {
|
|
12
12
|
clearSurface,
|
|
13
13
|
writeSurface
|
|
14
14
|
} from "./chunk-3SVNPJPN.js";
|
|
15
15
|
import {
|
|
16
|
+
AGENT_NAME,
|
|
16
17
|
NotifyRequestSchema,
|
|
17
18
|
ScheduleCallbackSchema,
|
|
18
19
|
SetTaskStateSchema,
|
|
@@ -42,9 +43,10 @@ import {
|
|
|
42
43
|
searchThreads,
|
|
43
44
|
setTaskState,
|
|
44
45
|
sleep,
|
|
46
|
+
slotName,
|
|
45
47
|
startE2ee,
|
|
46
48
|
submitNotification
|
|
47
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-BJW6Z2OY.js";
|
|
48
50
|
|
|
49
51
|
// src/index.ts
|
|
50
52
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -233,7 +235,7 @@ var AwaitReplySchema = z.object({
|
|
|
233
235
|
var JOIN_CAP_MS = 45e3;
|
|
234
236
|
var PairSchema = z.object({
|
|
235
237
|
device_code: z.string().optional().describe("Omit to start pairing (returns an approval link to show the user). Pass the device_code from that first call to finish, once the user has approved."),
|
|
236
|
-
name: z.string().min(1).max(60).optional().describe("Hatch path only: the name you choose for this identity. Pick your own \u2014
|
|
238
|
+
name: z.string().min(1).max(60).optional().describe("Hatch path only: the name you choose for this identity. Pick your own \u2014 ONE or TWO words, the way you'd introduce yourself on a call (it is spoken aloud and shown in lists). 'Piper', 'Blue Heron' \u2014 never a sentence or a task description."),
|
|
237
239
|
voice: z.string().optional().describe("Hatch path only: your voice on calls \u2014 one of rachel, george, jessica, brian, lily.")
|
|
238
240
|
});
|
|
239
241
|
var GetThreadSchema = z.object({
|
|
@@ -340,6 +342,13 @@ function renderPairOutcome(outcome, device_code) {
|
|
|
340
342
|
};
|
|
341
343
|
}
|
|
342
344
|
}
|
|
345
|
+
function unidentifiedResult() {
|
|
346
|
+
return { isError: true, content: [{ type: "text", text: JSON.stringify({
|
|
347
|
+
error: "no_identity",
|
|
348
|
+
slot: AGENT_NAME,
|
|
349
|
+
message: `This session has no Paigy identity yet, so nothing was sent \u2014 it will not speak as another session. This machine is already paired, so call \`pair\` (no arguments) to hatch this session its own identity instantly, then retry. To reuse an existing one instead, start the session with PAIGY_AGENT set to its slot (${listSlots().filter((s) => s !== "Desktop").join(", ") || "none yet"}).`
|
|
350
|
+
}) }] };
|
|
351
|
+
}
|
|
343
352
|
function pairStartResult(start) {
|
|
344
353
|
writeSurface("pairing code", start.userCode, start.expiresIn);
|
|
345
354
|
const qr = qrcode(0, "M");
|
|
@@ -441,7 +450,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
|
441
450
|
try {
|
|
442
451
|
return await handleTool(request, extra?.signal);
|
|
443
452
|
} catch (e) {
|
|
444
|
-
if (e instanceof UnpairedError)
|
|
453
|
+
if (e instanceof UnpairedError) {
|
|
454
|
+
if (listSlots().includes("Desktop")) return unidentifiedResult();
|
|
455
|
+
return pairStartResult(await startPairing(suggestedAgentName()));
|
|
456
|
+
}
|
|
445
457
|
throw e;
|
|
446
458
|
}
|
|
447
459
|
});
|
|
@@ -544,7 +556,8 @@ async function handleTool(request, signal) {
|
|
|
544
556
|
branch: parsed.branch ?? git.branch
|
|
545
557
|
};
|
|
546
558
|
const result = await submitNotification(enriched);
|
|
547
|
-
|
|
559
|
+
const sentAs = slotName(AGENT_NAME);
|
|
560
|
+
return { content: [{ type: "text", text: JSON.stringify(sentAs ? { ...result, sentAs } : result) }] };
|
|
548
561
|
}
|
|
549
562
|
case "await_reply": {
|
|
550
563
|
const { notificationId, maxWaitSeconds } = AwaitReplySchema.parse(request.params.arguments);
|
package/dist/listen.js
CHANGED
package/dist/onboard.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
autoConfigureClients,
|
|
4
4
|
claudeInstallHint,
|
|
5
5
|
openBrowser
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-JG2XL7Y3.js";
|
|
7
7
|
import {
|
|
8
8
|
AGENT_NAME,
|
|
9
9
|
TOKEN_PATH,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
requestCode,
|
|
12
12
|
saveToken,
|
|
13
13
|
sleep
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-BJW6Z2OY.js";
|
|
15
15
|
|
|
16
16
|
// src/onboard.ts
|
|
17
17
|
async function main() {
|
package/dist/statusline.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paigy/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.0",
|
|
4
4
|
"description": "Paigy MCP server — a voice inbox for your AI agents. Lets an agent notify a user and await their reply.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"typescript": "^5.7.2",
|
|
38
38
|
"vitest": "^2.1.8",
|
|
39
39
|
"@paigy/crypto": "0.0.0",
|
|
40
|
-
"@paigy/
|
|
41
|
-
"@paigy/
|
|
40
|
+
"@paigy/schema": "0.0.0",
|
|
41
|
+
"@paigy/sdk": "0.2.0"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"build": "tsup",
|