@paigy/mcp 0.13.0 → 0.14.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.
|
@@ -2597,6 +2597,15 @@ var MissedCallSchema = z.enum([
|
|
|
2597
2597
|
"inbox",
|
|
2598
2598
|
"dismiss"
|
|
2599
2599
|
]);
|
|
2600
|
+
var BrokerTuningSchema = z.object({
|
|
2601
|
+
/** 'none' = skip the spoken ack after a mapped answer (power users find it slow). */
|
|
2602
|
+
ackVerbosity: z.enum(["normal", "none"]).optional(),
|
|
2603
|
+
/** How readily the mapper asks its one clarification: 'low' = only when truly
|
|
2604
|
+
* uninterpretable, 'high' = whenever not fully certain. */
|
|
2605
|
+
clarifyEagerness: z.enum(["low", "normal", "high"]).optional(),
|
|
2606
|
+
/** The user's own shorthand: when they say `say`, they mean `mean`. */
|
|
2607
|
+
phrasebook: z.array(z.object({ say: z.string().min(1).max(60), mean: z.string().min(1).max(120) })).max(24).optional()
|
|
2608
|
+
});
|
|
2600
2609
|
var UserSettingsSchema = z.object({
|
|
2601
2610
|
permissions: z.object({
|
|
2602
2611
|
call: z.boolean(),
|
|
@@ -2622,7 +2631,10 @@ var UserSettingsSchema = z.object({
|
|
|
2622
2631
|
* settings object without it can't silently flip the account's E2EE state.
|
|
2623
2632
|
* Absent = leave unchanged on write, 'off' on read (see store.ts). The demo
|
|
2624
2633
|
* account is plaintext by construction and refuses any non-'off' value. */
|
|
2625
|
-
e2eeMode: z.enum(["off", "on"]).optional()
|
|
2634
|
+
e2eeMode: z.enum(["off", "on"]).optional(),
|
|
2635
|
+
/** Rung-2 broker tuning (#381). Optional and NOT defaulted, same stale-client
|
|
2636
|
+
* clobber guard as voiceMode: absent = leave unchanged on write. */
|
|
2637
|
+
broker: BrokerTuningSchema.optional()
|
|
2626
2638
|
});
|
|
2627
2639
|
var HistoryItemSchema = z.object({
|
|
2628
2640
|
id: z.string(),
|
|
@@ -3091,6 +3103,32 @@ var PROTO = "paigy-pair-v2|sas=24";
|
|
|
3091
3103
|
var SAS_BITS = 24;
|
|
3092
3104
|
var TOKEN_PATH = join(homedir(), ".paigy", "token.json");
|
|
3093
3105
|
var KEY_PATH = join(homedir(), ".paigy", "key.json");
|
|
3106
|
+
var SURFACE_PATH = join(homedir(), ".paigy", "surface.json");
|
|
3107
|
+
function writeSurface(label, code, ttlSeconds) {
|
|
3108
|
+
try {
|
|
3109
|
+
mkdirSync(join(homedir(), ".paigy"), { recursive: true });
|
|
3110
|
+
writeFileSync(
|
|
3111
|
+
SURFACE_PATH,
|
|
3112
|
+
JSON.stringify({ label, code, expiresAt: Date.now() + ttlSeconds * 1e3 }),
|
|
3113
|
+
{ mode: 384 }
|
|
3114
|
+
);
|
|
3115
|
+
} catch {
|
|
3116
|
+
}
|
|
3117
|
+
}
|
|
3118
|
+
function clearSurface() {
|
|
3119
|
+
try {
|
|
3120
|
+
rmSync(SURFACE_PATH, { force: true });
|
|
3121
|
+
} catch {
|
|
3122
|
+
}
|
|
3123
|
+
}
|
|
3124
|
+
function readSurface(now = Date.now) {
|
|
3125
|
+
try {
|
|
3126
|
+
const { label, code, expiresAt } = JSON.parse(readFileSync(SURFACE_PATH, "utf8"));
|
|
3127
|
+
return label && code && typeof expiresAt === "number" && expiresAt > now() ? { label, code } : null;
|
|
3128
|
+
} catch {
|
|
3129
|
+
return null;
|
|
3130
|
+
}
|
|
3131
|
+
}
|
|
3094
3132
|
function openBrowser(url) {
|
|
3095
3133
|
const cmd = platform() === "darwin" ? "open" : platform() === "win32" ? "cmd" : "xdg-open";
|
|
3096
3134
|
const args = platform() === "win32" ? ["/c", "start", url] : [url];
|
|
@@ -3290,6 +3328,9 @@ export {
|
|
|
3290
3328
|
reach,
|
|
3291
3329
|
AGENT_NAME,
|
|
3292
3330
|
TOKEN_PATH,
|
|
3331
|
+
writeSurface,
|
|
3332
|
+
clearSurface,
|
|
3333
|
+
readSurface,
|
|
3293
3334
|
openBrowser,
|
|
3294
3335
|
saveToken,
|
|
3295
3336
|
sleep,
|
package/dist/index.js
CHANGED
|
@@ -6,16 +6,16 @@ import {
|
|
|
6
6
|
scheduleCallback,
|
|
7
7
|
setTaskState,
|
|
8
8
|
submitNotification
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-OSQ3UXY6.js";
|
|
10
10
|
import {
|
|
11
11
|
NotifyRequestSchema,
|
|
12
12
|
ScheduleCallbackSchema,
|
|
13
13
|
SetTaskStateSchema,
|
|
14
|
+
clearSurface,
|
|
14
15
|
deleteKeyFile,
|
|
15
16
|
deleteToken,
|
|
16
17
|
fetchCredential,
|
|
17
18
|
finalizeE2ee,
|
|
18
|
-
openBrowser,
|
|
19
19
|
pairStep,
|
|
20
20
|
readKeyFile,
|
|
21
21
|
readToken,
|
|
@@ -24,8 +24,9 @@ import {
|
|
|
24
24
|
saveKeyFile,
|
|
25
25
|
saveToken,
|
|
26
26
|
sleep,
|
|
27
|
-
startE2ee
|
|
28
|
-
|
|
27
|
+
startE2ee,
|
|
28
|
+
writeSurface
|
|
29
|
+
} from "./chunk-WGOGS2JC.js";
|
|
29
30
|
|
|
30
31
|
// src/index.ts
|
|
31
32
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -137,6 +138,7 @@ function detectGit() {
|
|
|
137
138
|
};
|
|
138
139
|
}
|
|
139
140
|
function pairedResult(token, sas, note, e2ee) {
|
|
141
|
+
clearSurface();
|
|
140
142
|
const base = {
|
|
141
143
|
status: "paired",
|
|
142
144
|
nickname: token.nickname,
|
|
@@ -152,6 +154,7 @@ function pairedResult(token, sas, note, e2ee) {
|
|
|
152
154
|
return { content: [{ type: "text", text: JSON.stringify(base) }] };
|
|
153
155
|
}
|
|
154
156
|
function awaitingConfirmResult(sas, device_code) {
|
|
157
|
+
writeSurface("verify code", sas, 600);
|
|
155
158
|
return {
|
|
156
159
|
content: [{
|
|
157
160
|
type: "text",
|
|
@@ -160,8 +163,8 @@ function awaitingConfirmResult(sas, device_code) {
|
|
|
160
163
|
e2ee: true,
|
|
161
164
|
sas,
|
|
162
165
|
device_code,
|
|
163
|
-
verify_message: `
|
|
164
|
-
message: "
|
|
166
|
+
verify_message: `YOUR NEXT MESSAGE TO THE USER MUST BE EXACTLY THIS CODE AND NOTHING ELSE, displayed large (a markdown heading): ${sas} \u2014 it is the verification code they must compare and type on their phone. Do not wrap it in explanation; every extra sentence buries it. This code REPLACES any earlier one (older pairing attempts are now stale).`,
|
|
167
|
+
message: "No token is issued until the user confirms the code match on their phone (E2EE account). After sending the bare code, call pair again with this device_code to keep waiting \u2014 the token arrives only after they confirm."
|
|
165
168
|
})
|
|
166
169
|
}]
|
|
167
170
|
};
|
|
@@ -220,7 +223,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
220
223
|
const { keyFile, offer } = startE2ee();
|
|
221
224
|
const code = await requestCode(void 0, offer);
|
|
222
225
|
saveKeyFile({ ...keyFile, userCode: code.user_code });
|
|
223
|
-
|
|
226
|
+
writeSurface("pairing code", code.user_code, code.expires_in);
|
|
224
227
|
const qr = qrcode(0, "M");
|
|
225
228
|
qr.addData(code.verification_uri_complete);
|
|
226
229
|
qr.make();
|
|
@@ -234,7 +237,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
234
237
|
device_code: code.device_code,
|
|
235
238
|
expires_in: code.expires_in,
|
|
236
239
|
qr: qr.createASCII(1, 2),
|
|
237
|
-
message:
|
|
240
|
+
message: `YOUR NEXT MESSAGE TO THE USER MUST BE EXACTLY THIS CODE displayed large (a markdown heading): ${code.user_code} \u2014 plus ONE short line: enter it in the Paigy app (Inbox \u2192 Add a new agent). No other prose. Do NOT open a browser for the user. If their phone is handy they may prefer scanning \`qr\` (print it verbatim in a fenced code block on request). Then immediately call pair again with this device_code \u2014 it polls for the approval.`
|
|
238
241
|
})
|
|
239
242
|
}]
|
|
240
243
|
};
|
|
@@ -243,7 +246,13 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
243
246
|
const start = Date.now();
|
|
244
247
|
const capMs = 9e4;
|
|
245
248
|
while (Date.now() - start < capMs) {
|
|
246
|
-
|
|
249
|
+
let step;
|
|
250
|
+
try {
|
|
251
|
+
step = await pairStep(device_code, kf);
|
|
252
|
+
} catch (e) {
|
|
253
|
+
clearSurface();
|
|
254
|
+
throw e;
|
|
255
|
+
}
|
|
247
256
|
if (step.kind === "e2ee_aborted") {
|
|
248
257
|
deleteKeyFile();
|
|
249
258
|
kf = null;
|
package/dist/listen.js
CHANGED
|
@@ -3,11 +3,11 @@ import { createRequire as __createRequire } from 'node:module'; const require =
|
|
|
3
3
|
import {
|
|
4
4
|
checkReplies,
|
|
5
5
|
registerDelivery
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-OSQ3UXY6.js";
|
|
7
7
|
import {
|
|
8
8
|
WAKE_EVENT,
|
|
9
9
|
wakeChannel
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-WGOGS2JC.js";
|
|
11
11
|
|
|
12
12
|
// src/listen.ts
|
|
13
13
|
import { createClient } from "@supabase/supabase-js";
|
package/dist/onboard.js
CHANGED
package/dist/statusline.js
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
BACKEND_URL,
|
|
5
|
+
readSurface,
|
|
5
6
|
readToken
|
|
6
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-WGOGS2JC.js";
|
|
7
8
|
|
|
8
9
|
// src/statusline.ts
|
|
9
10
|
import { mkdirSync, readFileSync, realpathSync, writeFileSync } from "fs";
|
|
@@ -18,7 +19,8 @@ var MODE_LABEL = {
|
|
|
18
19
|
all_calls: "all calls",
|
|
19
20
|
silent: "silent"
|
|
20
21
|
};
|
|
21
|
-
function render(status) {
|
|
22
|
+
function render(status, surface = null) {
|
|
23
|
+
if (surface) return `paigy \u26A0 ${surface.label}: ${surface.code}`;
|
|
22
24
|
if (!status) return "paigy: unpaired";
|
|
23
25
|
return `paigy: ${MODE_LABEL[status.sessionMode]} \xB7 ${status.phone ? "phone \u2713" : "no phone"}`;
|
|
24
26
|
}
|
|
@@ -44,6 +46,8 @@ async function fetchStatus(token) {
|
|
|
44
46
|
return await res.json();
|
|
45
47
|
}
|
|
46
48
|
async function main() {
|
|
49
|
+
const surface = readSurface();
|
|
50
|
+
if (surface) return render(null, surface);
|
|
47
51
|
const token = readToken();
|
|
48
52
|
if (!token) return render(null);
|
|
49
53
|
const cached = readCache();
|