@paigy/mcp 0.28.0 → 0.28.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/dist/{chunk-TE57PAKM.js → chunk-7P4WMXGB.js} +36 -6
- package/dist/{chunk-XQVQ4JRT.js → chunk-EQAFMUQC.js} +1 -1
- package/dist/{chunk-FRYGTKLM.js → chunk-ZFBYZWK7.js} +17 -2
- package/dist/index.js +5 -4
- package/dist/listen.js +5 -2
- package/dist/onboard.js +2 -2
- package/dist/statusline.js +1 -1
- package/package.json +3 -3
|
@@ -2280,14 +2280,28 @@ var CHUNK_MAX = 300;
|
|
|
2280
2280
|
var ASK_MAX = 1e4;
|
|
2281
2281
|
var OPTION_MAX = 80;
|
|
2282
2282
|
var NEEDS_MAX = 6;
|
|
2283
|
-
var UNSPEAKABLE =
|
|
2283
|
+
var UNSPEAKABLE = /```/;
|
|
2284
|
+
function normalizeSpeech(req) {
|
|
2285
|
+
const flat = (s) => s.replace(/\s+/g, " ").trim();
|
|
2286
|
+
return {
|
|
2287
|
+
...req,
|
|
2288
|
+
...req.ask !== void 0 ? { ask: flat(req.ask) } : {},
|
|
2289
|
+
...req.context ? {
|
|
2290
|
+
context: {
|
|
2291
|
+
...req.context,
|
|
2292
|
+
title: flat(req.context.title),
|
|
2293
|
+
description: req.context.description.map(flat)
|
|
2294
|
+
}
|
|
2295
|
+
} : {}
|
|
2296
|
+
};
|
|
2297
|
+
}
|
|
2284
2298
|
function lintNotify(req) {
|
|
2285
2299
|
const problems = [];
|
|
2286
2300
|
if (req.ask !== void 0) {
|
|
2287
2301
|
if (req.ask.length > ASK_MAX)
|
|
2288
2302
|
problems.push(`ask is ${req.ask.length} chars \u2014 state the need and why it matters now in \u2264${ASK_MAX}; move detail into a smaller follow-up`);
|
|
2289
2303
|
if (UNSPEAKABLE.test(req.ask))
|
|
2290
|
-
problems.push("ask contains code
|
|
2304
|
+
problems.push("ask contains a code fence \u2014 write it as plain prose (it may be read aloud on a call)");
|
|
2291
2305
|
for (const n of req.needs ?? []) {
|
|
2292
2306
|
if (n.length > OPTION_MAX) problems.push(`need "${n.slice(0, 40)}\u2026" is too long \u2014 each need is a short phrase (\u2264${OPTION_MAX} chars)`);
|
|
2293
2307
|
}
|
|
@@ -2300,7 +2314,7 @@ function lintNotify(req) {
|
|
|
2300
2314
|
if (req.context.title.length > TITLE_MAX)
|
|
2301
2315
|
problems.push(`title is ${req.context.title.length} chars \u2014 shorten to \u2264${TITLE_MAX} (it's what shows on the banner / gets spoken on a ring)`);
|
|
2302
2316
|
if (UNSPEAKABLE.test(req.context.title))
|
|
2303
|
-
problems.push("title contains code
|
|
2317
|
+
problems.push("title contains a code fence \u2014 one plain-prose line");
|
|
2304
2318
|
if (req.context.description.length > CHUNKS_MAX)
|
|
2305
2319
|
problems.push(`${req.context.description.length} description chunks \u2014 cap at ${CHUNKS_MAX}; merge or drop the rest`);
|
|
2306
2320
|
for (const [i, chunk] of req.context.description.entries()) {
|
|
@@ -2308,7 +2322,7 @@ function lintNotify(req) {
|
|
|
2308
2322
|
problems.push(`description[${i}] is ${chunk.length} chars \u2014 split it into standalone points of \u2264${CHUNK_MAX}`);
|
|
2309
2323
|
}
|
|
2310
2324
|
if (spoken && UNSPEAKABLE.test(req.context.description.join(" ")))
|
|
2311
|
-
problems.push("urgency is 'call'/'banner' but the description has code
|
|
2325
|
+
problems.push("urgency is 'call'/'banner' but the description has a code fence \u2014 rewrite in spoken register (it will be read aloud)");
|
|
2312
2326
|
}
|
|
2313
2327
|
for (const o of req.options ?? []) {
|
|
2314
2328
|
if (o.label.length > OPTION_MAX)
|
|
@@ -2576,7 +2590,12 @@ var UserAnswerSchema = z.discriminatedUnion("kind", [
|
|
|
2576
2590
|
z.object({ kind: z.literal("ranked"), optionIds: z.array(z.string()), labels: z.array(z.string()).optional() }),
|
|
2577
2591
|
z.object({ kind: z.literal("clarify"), chunks: z.array(z.string()).min(1) }),
|
|
2578
2592
|
z.object({ kind: z.literal("confirm"), approved: z.boolean() }),
|
|
2579
|
-
z.object({ kind: z.literal("turns"), turns: z.array(TurnSchema).min(1) })
|
|
2593
|
+
z.object({ kind: z.literal("turns"), turns: z.array(TurnSchema).min(1) }),
|
|
2594
|
+
/** An auto-answer derived from the user's PAST decisions (broker/precedent-design.md §2):
|
|
2595
|
+
* delivered through the same settle/await path as a human answer, carrying the judge's
|
|
2596
|
+
* derivation and the precedent ids it grew from. Always paired with a visible trail
|
|
2597
|
+
* card the user can reply to — the broker never overrides the user. */
|
|
2598
|
+
z.object({ kind: z.literal("precedent"), answer: z.string(), derivation: z.string(), sources: z.array(z.string()).min(1) })
|
|
2580
2599
|
]);
|
|
2581
2600
|
var IntentSchema = z.object({
|
|
2582
2601
|
// The full vocabulary the bot's mapper emits (mapper.INTENT_KINDS) — the schema lagged
|
|
@@ -2589,7 +2608,12 @@ var IntentSchema = z.object({
|
|
|
2589
2608
|
* "after lunch") against the agent machine's clock — the user's — and attaches
|
|
2590
2609
|
* the seconds, ready to pass straight to schedule_callback. Absent when the
|
|
2591
2610
|
* detail didn't parse (the agent interprets it) or the kind isn't defer. */
|
|
2592
|
-
dueInSeconds: z.number().int().positive().optional()
|
|
2611
|
+
dueInSeconds: z.number().int().positive().optional(),
|
|
2612
|
+
/** Feedback only (#812): WHICH failure the complaint names — typed by the mapper that
|
|
2613
|
+
* already read the utterance, so `feedback_from_call.kind` stops defaulting to
|
|
2614
|
+
* 'other' on every row. A table that records that something was wrong and nothing
|
|
2615
|
+
* about what cannot answer "is the bot looping less this week?". */
|
|
2616
|
+
fault: z.enum(["loop", "unanswered", "overridden", "misheard", "slow", "other"]).optional()
|
|
2593
2617
|
});
|
|
2594
2618
|
var AwaitItemSchema = z.discriminatedUnion("type", [
|
|
2595
2619
|
z.object({
|
|
@@ -2759,6 +2783,11 @@ var AgendaTurnSchema = z.object({
|
|
|
2759
2783
|
claimId: z.string().optional(),
|
|
2760
2784
|
/** The claim's voice key (#462) — the OUTBOUND identity, audible who-is-asking. */
|
|
2761
2785
|
voice: z.string().optional(),
|
|
2786
|
+
/** The claim's AGENT NAME (#838) — the spoken identity. A voice alone doesn't say
|
|
2787
|
+
* whose request this is: an item that folded in from another agent arrived as a bare
|
|
2788
|
+
* non-sequitur ("First real production sign-in is yours to make whenever you want.")
|
|
2789
|
+
* and the owner answered "What?". The bot names the agent before its first turn. */
|
|
2790
|
+
agent: z.string().optional(),
|
|
2762
2791
|
select: SelectShapeSchema.optional(),
|
|
2763
2792
|
options: z.array(OptionSchema.omit({ id: true })).optional(),
|
|
2764
2793
|
/** The seat was satisfied by the call's own ACCOUNT (replan-design.md, user_info): the
|
|
@@ -3938,6 +3967,7 @@ async function handoff(req) {
|
|
|
3938
3967
|
export {
|
|
3939
3968
|
BACKEND_URL,
|
|
3940
3969
|
reach,
|
|
3970
|
+
normalizeSpeech,
|
|
3941
3971
|
lintNotify,
|
|
3942
3972
|
NotifyRequestSchema,
|
|
3943
3973
|
SetTaskStateSchema,
|
|
@@ -215,7 +215,12 @@ var UserAnswerSchema = z.discriminatedUnion("kind", [
|
|
|
215
215
|
z.object({ kind: z.literal("ranked"), optionIds: z.array(z.string()), labels: z.array(z.string()).optional() }),
|
|
216
216
|
z.object({ kind: z.literal("clarify"), chunks: z.array(z.string()).min(1) }),
|
|
217
217
|
z.object({ kind: z.literal("confirm"), approved: z.boolean() }),
|
|
218
|
-
z.object({ kind: z.literal("turns"), turns: z.array(TurnSchema).min(1) })
|
|
218
|
+
z.object({ kind: z.literal("turns"), turns: z.array(TurnSchema).min(1) }),
|
|
219
|
+
/** An auto-answer derived from the user's PAST decisions (broker/precedent-design.md §2):
|
|
220
|
+
* delivered through the same settle/await path as a human answer, carrying the judge's
|
|
221
|
+
* derivation and the precedent ids it grew from. Always paired with a visible trail
|
|
222
|
+
* card the user can reply to — the broker never overrides the user. */
|
|
223
|
+
z.object({ kind: z.literal("precedent"), answer: z.string(), derivation: z.string(), sources: z.array(z.string()).min(1) })
|
|
219
224
|
]);
|
|
220
225
|
var IntentSchema = z.object({
|
|
221
226
|
// The full vocabulary the bot's mapper emits (mapper.INTENT_KINDS) — the schema lagged
|
|
@@ -228,7 +233,12 @@ var IntentSchema = z.object({
|
|
|
228
233
|
* "after lunch") against the agent machine's clock — the user's — and attaches
|
|
229
234
|
* the seconds, ready to pass straight to schedule_callback. Absent when the
|
|
230
235
|
* detail didn't parse (the agent interprets it) or the kind isn't defer. */
|
|
231
|
-
dueInSeconds: z.number().int().positive().optional()
|
|
236
|
+
dueInSeconds: z.number().int().positive().optional(),
|
|
237
|
+
/** Feedback only (#812): WHICH failure the complaint names — typed by the mapper that
|
|
238
|
+
* already read the utterance, so `feedback_from_call.kind` stops defaulting to
|
|
239
|
+
* 'other' on every row. A table that records that something was wrong and nothing
|
|
240
|
+
* about what cannot answer "is the bot looping less this week?". */
|
|
241
|
+
fault: z.enum(["loop", "unanswered", "overridden", "misheard", "slow", "other"]).optional()
|
|
232
242
|
});
|
|
233
243
|
var AwaitItemSchema = z.discriminatedUnion("type", [
|
|
234
244
|
z.object({
|
|
@@ -398,6 +408,11 @@ var AgendaTurnSchema = z.object({
|
|
|
398
408
|
claimId: z.string().optional(),
|
|
399
409
|
/** The claim's voice key (#462) — the OUTBOUND identity, audible who-is-asking. */
|
|
400
410
|
voice: z.string().optional(),
|
|
411
|
+
/** The claim's AGENT NAME (#838) — the spoken identity. A voice alone doesn't say
|
|
412
|
+
* whose request this is: an item that folded in from another agent arrived as a bare
|
|
413
|
+
* non-sequitur ("First real production sign-in is yours to make whenever you want.")
|
|
414
|
+
* and the owner answered "What?". The bot names the agent before its first turn. */
|
|
415
|
+
agent: z.string().optional(),
|
|
401
416
|
select: SelectShapeSchema.optional(),
|
|
402
417
|
options: z.array(OptionSchema.omit({ id: true })).optional(),
|
|
403
418
|
/** The seat was satisfied by the call's own ACCOUNT (replan-design.md, user_info): the
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
HandoffSchema
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ZFBYZWK7.js";
|
|
5
5
|
import {
|
|
6
6
|
PAIGY_TOOL_IDS,
|
|
7
7
|
autoConfigureClients,
|
|
8
8
|
claudeInstallHint,
|
|
9
9
|
enablePaigyTools
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-EQAFMUQC.js";
|
|
11
11
|
import {
|
|
12
12
|
clearSurface,
|
|
13
13
|
writeSurface
|
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
hatch,
|
|
30
30
|
lintNotify,
|
|
31
31
|
listSlots,
|
|
32
|
+
normalizeSpeech,
|
|
32
33
|
overrideToken,
|
|
33
34
|
pairStep,
|
|
34
35
|
readKeyFile,
|
|
@@ -43,7 +44,7 @@ import {
|
|
|
43
44
|
sleep,
|
|
44
45
|
startE2ee,
|
|
45
46
|
submitNotification
|
|
46
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-7P4WMXGB.js";
|
|
47
48
|
|
|
48
49
|
// src/index.ts
|
|
49
50
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -528,7 +529,7 @@ async function handleTool(request, signal) {
|
|
|
528
529
|
case "contact":
|
|
529
530
|
case "notify":
|
|
530
531
|
case "notify_user": {
|
|
531
|
-
const parsed = NotifyRequestSchema.parse(request.params.arguments);
|
|
532
|
+
const parsed = normalizeSpeech(NotifyRequestSchema.parse(request.params.arguments));
|
|
532
533
|
const problems = lintNotify(parsed);
|
|
533
534
|
if (problems.length) {
|
|
534
535
|
return {
|
package/dist/listen.js
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
import {
|
|
3
3
|
WAKE_EVENT,
|
|
4
4
|
wakeChannel
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-ZFBYZWK7.js";
|
|
6
6
|
import {
|
|
7
7
|
checkReplies,
|
|
8
8
|
registerDelivery
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-7P4WMXGB.js";
|
|
10
10
|
|
|
11
11
|
// src/listen.ts
|
|
12
12
|
import { createClient } from "@supabase/supabase-js";
|
|
@@ -130,6 +130,9 @@ function answerText(answer) {
|
|
|
130
130
|
// (the full exchange is in PAIGY_WORK for a launcher that wants it).
|
|
131
131
|
case "turns":
|
|
132
132
|
return answer.turns.map((t) => t.reply).join(" ");
|
|
133
|
+
// An auto-answer derived from the user's past decisions — reads like a fast human.
|
|
134
|
+
case "precedent":
|
|
135
|
+
return answer.answer;
|
|
133
136
|
case "ignored":
|
|
134
137
|
return "";
|
|
135
138
|
}
|
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-EQAFMUQC.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-7P4WMXGB.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.28.
|
|
3
|
+
"version": "0.28.1",
|
|
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/sdk": "0.1.0",
|
|
41
|
+
"@paigy/schema": "0.0.0"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"build": "tsup",
|