@paigy/mcp 0.40.0 → 0.40.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/README.md +18 -8
- package/dist/{chunk-DM6YPBQH.js → chunk-3QUIB42M.js} +604 -614
- package/dist/{chunk-CWGZVTPZ.js → chunk-4UZAPBKK.js} +740 -905
- package/dist/{chunk-BOLKVO6W.js → chunk-CXABA27N.js} +1 -1
- package/dist/{chunk-FYH6FW2D.js → chunk-TLASZUJD.js} +6 -91
- package/dist/enable.js +3 -3
- package/dist/index.js +11 -153
- package/dist/listen.js +25 -5
- package/dist/onboard.js +4 -4
- package/dist/slot.js +1 -1
- package/dist/statusline.js +4 -2
- package/package.json +12 -13
- package/dist/chunk-2SWUY5WK.js +0 -57
|
@@ -1,22 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
CONTACT_DESCRIPTION,
|
|
4
|
-
CONTACT_SCHEMA,
|
|
5
|
-
CREATE_GOAL_DESCRIPTION,
|
|
6
|
-
CreateGoalSchema,
|
|
7
|
-
HandoffSchema,
|
|
8
|
-
SCHEDULE_CALLBACK_DESCRIPTION,
|
|
9
|
-
SEARCH_THREADS_DESCRIPTION,
|
|
10
|
-
SET_WORK_STATE_DESCRIPTION,
|
|
11
|
-
ScheduleCallbackSchema,
|
|
12
|
-
SetTaskStateSchema,
|
|
13
|
-
SetWorkStateSchema,
|
|
2
|
+
AGENT_TOOLS,
|
|
14
3
|
mcpInputSchema,
|
|
15
4
|
serverInstructions
|
|
16
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-3QUIB42M.js";
|
|
17
6
|
import {
|
|
18
7
|
AGENT_NAME
|
|
19
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-4UZAPBKK.js";
|
|
20
9
|
|
|
21
10
|
// src/toolset.ts
|
|
22
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.";
|
|
@@ -24,8 +13,6 @@ var SERVER_INSTRUCTIONS = serverInstructions({ waits: true });
|
|
|
24
13
|
|
|
25
14
|
// src/tools.ts
|
|
26
15
|
import { z } from "zod";
|
|
27
|
-
var UpdateGoalToolSchema = z.object({ goalId: z.string().uuid(), revision: z.number().int().positive(), changes: z.record(z.unknown()), reason: z.string().min(1) });
|
|
28
|
-
var ClaimGoalSchema = z.object({ goalId: z.string().uuid() });
|
|
29
16
|
var OnboardSchema = z.object({
|
|
30
17
|
name: z.string().max(60).optional(),
|
|
31
18
|
voice: z.string().max(40).optional(),
|
|
@@ -39,29 +26,7 @@ var PairSchema = z.object({
|
|
|
39
26
|
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."),
|
|
40
27
|
voice: z.string().optional().describe("Hatch path only: your voice on calls \u2014 one of rachel, george, jessica, brian, lily.")
|
|
41
28
|
});
|
|
42
|
-
var
|
|
43
|
-
parentId: z.string().describe("The thread to read \u2014 from a reply, request, or past notification.")
|
|
44
|
-
});
|
|
45
|
-
var SearchThreadsSchema = z.object({
|
|
46
|
-
q: z.string().describe("What to look for \u2014 plain words or a phrase (e.g. 'the livekit timeout', 'deploy to prod').")
|
|
47
|
-
});
|
|
48
|
-
var SetTaskStateToolSchema = z.object({
|
|
49
|
-
notificationId: z.string(),
|
|
50
|
-
state: SetTaskStateSchema.shape.state
|
|
51
|
-
});
|
|
52
|
-
var AnswerCallerQuestionSchema = z.object({
|
|
53
|
-
notificationId: z.string().describe("The notification whose call carried the caller's question \u2014 from the partial turn or the settled reply."),
|
|
54
|
-
answer: z.string().min(1).max(1500).describe("The answer, as one or two short SPOKEN sentences \u2014 it may be read aloud on the live call.")
|
|
55
|
-
});
|
|
56
|
-
var TOOLS = [
|
|
57
|
-
{
|
|
58
|
-
// #575: THE attention verb — the one model-facing surface, every agent.
|
|
59
|
-
// The retired names (notify/notify_user) stay callable as hidden aliases
|
|
60
|
-
// for stale prompts and cached servers; see toolset.ts for the design.
|
|
61
|
-
name: "contact",
|
|
62
|
-
description: CONTACT_DESCRIPTION,
|
|
63
|
-
inputSchema: CONTACT_SCHEMA
|
|
64
|
-
},
|
|
29
|
+
var IDENTITY_TOOLS = [
|
|
65
30
|
{
|
|
66
31
|
// ONE rail for starting a session (#875). `pair`, the `paigy-mcp-onboard` CLI and
|
|
67
32
|
// `enable_tools` were three doors into one flow, and "onboard" was the word people
|
|
@@ -79,55 +44,11 @@ var TOOLS = [
|
|
|
79
44
|
name: "unpair",
|
|
80
45
|
description: "Log out / unpair this agent from the user's Paigy account: revokes the token server-side (it stops working everywhere) and deletes the local ~/.paigy/token.json. Takes no arguments. After this, contact won't work until the user pairs again with the pair tool.",
|
|
81
46
|
inputSchema: mcpInputSchema(z.object({}))
|
|
82
|
-
},
|
|
83
|
-
// `await_reply` is GONE (owner, 2026-09-06, hard cutover): the wait is contact's — it holds
|
|
84
|
-
// the first window of a call it placed, and `contact({ wait: notificationId })` holds the
|
|
85
|
-
// next. One tool, one loop; the reply-reading guidance moved into CONTACT_DESCRIPTION.
|
|
86
|
-
{
|
|
87
|
-
name: "check_replies",
|
|
88
|
-
description: CHECK_REPLIES_DESCRIPTION,
|
|
89
|
-
inputSchema: mcpInputSchema(z.object({}))
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
name: "get_thread",
|
|
93
|
-
description: "The chronological transcript of one Paigy conversation thread \u2014 every past ask, answer, and user request on it. Call this to REHYDRATE when you're resuming or being seeded: a check_replies request whose parentId you don't recognize means the user is continuing an old conversation with you, and one carrying a contextParentId means they want a past conversation (possibly with a DIFFERENT agent) as your starting context \u2014 in both cases call get_thread FIRST and read the turns as prior conversation you were part of, not as new input. Turns: { role:'agent', title, description[], answer }, { role:'user', text }, and context turns { role:'handoff'|'recap', title, description[] } \u2014 a handoff is a predecessor's brief for you; a recap SUMMARIZES everything before it (the transcript starts at the latest recap, so treat it as the base and the turns after it as what happened since). Oldest first, capped at the most recent 30.",
|
|
94
|
-
inputSchema: mcpInputSchema(GetThreadSchema)
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
name: "search_threads",
|
|
98
|
-
description: SEARCH_THREADS_DESCRIPTION,
|
|
99
|
-
inputSchema: mcpInputSchema(SearchThreadsSchema)
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
name: "create_goal",
|
|
103
|
-
description: CREATE_GOAL_DESCRIPTION,
|
|
104
|
-
inputSchema: mcpInputSchema(CreateGoalSchema)
|
|
105
|
-
},
|
|
106
|
-
{ name: "claim_goal", description: "Claim a ready Goal you own and begin work. Returns its active revision.", inputSchema: mcpInputSchema(ClaimGoalSchema) },
|
|
107
|
-
{ name: "update_goal", description: "Update an owned Goal at an exact revision; stale revisions are rejected.", inputSchema: mcpInputSchema(UpdateGoalToolSchema) },
|
|
108
|
-
{
|
|
109
|
-
name: "set_work_state",
|
|
110
|
-
description: SET_WORK_STATE_DESCRIPTION,
|
|
111
|
-
inputSchema: mcpInputSchema(SetWorkStateSchema)
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
name: "answer_caller_question",
|
|
115
|
-
description: "Answer a question the user asked DURING a live call, while they're still on it. When a partial turn or a settled reply carries a `question` intent aimed at you, answer it here immediately: if their call is still live, your answer is spoken to them on that same call (returns live: true). If the call already ended (live: false), send the answer as a threaded contact instead \u2014 never drop it. Short spoken sentences only; this may be read aloud.",
|
|
116
|
-
inputSchema: mcpInputSchema(AnswerCallerQuestionSchema)
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
name: "schedule_callback",
|
|
120
|
-
description: SCHEDULE_CALLBACK_DESCRIPTION,
|
|
121
|
-
inputSchema: mcpInputSchema(ScheduleCallbackSchema)
|
|
122
|
-
},
|
|
123
|
-
{
|
|
124
|
-
name: "handoff",
|
|
125
|
-
description: "Deposit your working context for a SUCCESSOR agent \u2014 what you did, what's left, links, gotchas \u2014 as one note on a thread ({ title, notes[] }). This does NOT ring the user or enter their inbox: it's context, not a question. The successor reads it back with get_thread. Pass `target` (a sibling connection's token id or agent name, SAME account only) to hand off DIRECTLY to that agent \u2014 the note is dispatched to it as a request it picks up. Pass `workId` to move that existing outcome and its pending replies to the successor without reminting it; a target is required in that form. Omit `target` to leave the thread for the user to hand off to an agent themselves in the app. Pass `parentId` to land the handoff on an existing conversation; omit it to mint a fresh thread. Returns { parentId }. Pass recap:true when the note SUMMARIZES the thread so far (for a successor OR for your own later session): a recap resets the rehydration window \u2014 get_thread returns the latest recap + only the turns after it. Write one whenever a thread has grown long and you're pausing, handing off, or nearing your context limit.",
|
|
126
|
-
inputSchema: mcpInputSchema(HandoffSchema)
|
|
127
47
|
}
|
|
128
48
|
];
|
|
49
|
+
var TOOLS = [...AGENT_TOOLS, ...IDENTITY_TOOLS];
|
|
129
50
|
var TOOL_NAMES = TOOLS.map((t) => t.name);
|
|
130
|
-
var HIDDEN_ALIASES = [
|
|
51
|
+
var HIDDEN_ALIASES = [];
|
|
131
52
|
|
|
132
53
|
// src/clients.ts
|
|
133
54
|
import { execFile } from "child_process";
|
|
@@ -290,14 +211,8 @@ function enablePaigyTools(scope = "user", cwd = process.cwd()) {
|
|
|
290
211
|
|
|
291
212
|
export {
|
|
292
213
|
SERVER_INSTRUCTIONS,
|
|
293
|
-
UpdateGoalToolSchema,
|
|
294
|
-
ClaimGoalSchema,
|
|
295
214
|
OnboardSchema,
|
|
296
215
|
PairSchema,
|
|
297
|
-
GetThreadSchema,
|
|
298
|
-
SearchThreadsSchema,
|
|
299
|
-
SetTaskStateToolSchema,
|
|
300
|
-
AnswerCallerQuestionSchema,
|
|
301
216
|
TOOLS,
|
|
302
217
|
openBrowser,
|
|
303
218
|
autoConfigureClients,
|
package/dist/enable.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
PAIGY_TOOL_IDS,
|
|
4
4
|
enablePaigyTools
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-TLASZUJD.js";
|
|
6
|
+
import "./chunk-3QUIB42M.js";
|
|
7
|
+
import "./chunk-4UZAPBKK.js";
|
|
8
8
|
|
|
9
9
|
// src/enable.ts
|
|
10
10
|
function main() {
|
package/dist/index.js
CHANGED
|
@@ -1,74 +1,44 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
awaitMessage,
|
|
4
|
-
contactMessage,
|
|
5
|
-
waitNow
|
|
6
|
-
} from "./chunk-2SWUY5WK.js";
|
|
7
2
|
import {
|
|
8
3
|
clearPairing,
|
|
9
4
|
joinBackgroundPair,
|
|
10
5
|
resolvePairing,
|
|
11
6
|
startPairing,
|
|
12
7
|
suggestedAgentName
|
|
13
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-CXABA27N.js";
|
|
14
9
|
import {
|
|
15
|
-
AnswerCallerQuestionSchema,
|
|
16
|
-
ClaimGoalSchema,
|
|
17
10
|
ENABLE_COMMAND,
|
|
18
|
-
GetThreadSchema,
|
|
19
11
|
OnboardSchema,
|
|
20
12
|
PAIGY_TOOL_IDS,
|
|
21
13
|
PairSchema,
|
|
22
14
|
SERVER_INSTRUCTIONS,
|
|
23
|
-
SearchThreadsSchema,
|
|
24
|
-
SetTaskStateToolSchema,
|
|
25
15
|
TOOLS,
|
|
26
|
-
UpdateGoalToolSchema,
|
|
27
16
|
autoConfigureClients,
|
|
28
17
|
claudeInstallHint,
|
|
29
18
|
paigyToolsAllowlisted
|
|
30
|
-
} from "./chunk-
|
|
31
|
-
import
|
|
32
|
-
CreateGoalSchema,
|
|
33
|
-
HandoffSchema
|
|
34
|
-
} from "./chunk-DM6YPBQH.js";
|
|
19
|
+
} from "./chunk-TLASZUJD.js";
|
|
20
|
+
import "./chunk-3QUIB42M.js";
|
|
35
21
|
import {
|
|
36
22
|
clearSurface,
|
|
37
23
|
writeSurface
|
|
38
24
|
} from "./chunk-3SVNPJPN.js";
|
|
39
25
|
import {
|
|
40
26
|
AGENT_NAME,
|
|
41
|
-
NotifyRequestSchema,
|
|
42
|
-
ScheduleCallbackSchema,
|
|
43
|
-
SetWorkStateSchema,
|
|
44
27
|
UnpairedError,
|
|
45
|
-
answerCallerQuestion,
|
|
46
|
-
awaitReply2,
|
|
47
|
-
checkReplies,
|
|
48
|
-
claimGoal,
|
|
49
|
-
contactParentId,
|
|
50
|
-
createGoal,
|
|
51
28
|
deleteKeyFile,
|
|
52
29
|
deleteToken,
|
|
53
|
-
getThread,
|
|
54
|
-
handoff,
|
|
55
30
|
hatch,
|
|
56
31
|
heartbeat,
|
|
57
32
|
listSlots,
|
|
58
33
|
overrideToken,
|
|
59
34
|
readToken,
|
|
60
35
|
revokeToken,
|
|
36
|
+
runTool,
|
|
61
37
|
saveToken,
|
|
62
|
-
scheduleCallback,
|
|
63
|
-
searchThreads,
|
|
64
38
|
setIdentity,
|
|
65
|
-
setTaskState,
|
|
66
|
-
setWorkState,
|
|
67
39
|
slotName,
|
|
68
|
-
submitNotification,
|
|
69
|
-
updateGoal,
|
|
70
40
|
whoAmI
|
|
71
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-4UZAPBKK.js";
|
|
72
42
|
|
|
73
43
|
// src/index.ts
|
|
74
44
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -77,36 +47,8 @@ import {
|
|
|
77
47
|
CallToolRequestSchema,
|
|
78
48
|
ListToolsRequestSchema
|
|
79
49
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
80
|
-
import { execSync } from "child_process";
|
|
81
50
|
import qrcode from "qrcode-generator";
|
|
82
51
|
var JOIN_CAP_MS = 45e3;
|
|
83
|
-
function fixAndRetry(err) {
|
|
84
|
-
const msg = String(err?.message ?? err);
|
|
85
|
-
const m = msg.match(/^notify failed: 422 (\{[\s\S]*\})$/);
|
|
86
|
-
if (!m) return null;
|
|
87
|
-
try {
|
|
88
|
-
const body = JSON.parse(m[1]);
|
|
89
|
-
return body.error === "fix_and_retry" ? { error: "fix_and_retry", problems: body.problems ?? [] } : null;
|
|
90
|
-
} catch {
|
|
91
|
-
return null;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
function detectGit() {
|
|
95
|
-
const run = (cmd) => {
|
|
96
|
-
try {
|
|
97
|
-
return execSync(cmd, { stdio: ["ignore", "pipe", "ignore"], encoding: "utf8" }).trim();
|
|
98
|
-
} catch {
|
|
99
|
-
return "";
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
const remote = run("git remote get-url origin");
|
|
103
|
-
const match = remote.match(/[:/]([^/:]+\/[^/]+?)(?:\.git)?$/);
|
|
104
|
-
const branch = run("git rev-parse --abbrev-ref HEAD");
|
|
105
|
-
return {
|
|
106
|
-
repo: match ? match[1] : void 0,
|
|
107
|
-
branch: branch && branch !== "HEAD" ? branch : void 0
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
52
|
function pairedResult(token, sas, note, e2ee) {
|
|
111
53
|
clearSurface();
|
|
112
54
|
const base = {
|
|
@@ -379,97 +321,13 @@ async function handleTool(request, signal) {
|
|
|
379
321
|
}]
|
|
380
322
|
};
|
|
381
323
|
}
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
const args = request.params.arguments ?? {};
|
|
389
|
-
if (typeof args.wait === "string" && args.ask === void 0) {
|
|
390
|
-
const item = await awaitReply2(args.wait, { ...signal ? { signal } : {} });
|
|
391
|
-
return { content: [{ type: "text", text: JSON.stringify({ ...item, message: awaitMessage(item) }) }] };
|
|
392
|
-
}
|
|
393
|
-
const parsed = NotifyRequestSchema.parse(request.params.arguments);
|
|
394
|
-
const git = detectGit();
|
|
395
|
-
const enriched = {
|
|
396
|
-
...parsed,
|
|
397
|
-
repo: parsed.repo ?? git.repo,
|
|
398
|
-
branch: parsed.branch ?? git.branch,
|
|
399
|
-
// THREAD-SCOPED IDENTITY (stage 3, identity-ownership-design.md). A worker subagent
|
|
400
|
-
// shares the parent's identity/slot, so its requests would otherwise scatter across
|
|
401
|
-
// fresh threads and mix with a sibling's. Default an unthreaded contact to THIS
|
|
402
|
-
// subagent's own thread so its requests group and siblings never collide. An explicit
|
|
403
|
-
// parentId (continuing a specific conversation) always wins; a top-level parent session
|
|
404
|
-
// is left untouched (undefined ⇒ the server mints a fresh thread, exactly as today).
|
|
405
|
-
parentId: contactParentId(parsed.parentId)
|
|
406
|
-
};
|
|
407
|
-
let result;
|
|
408
|
-
try {
|
|
409
|
-
result = await submitNotification(enriched);
|
|
410
|
-
} catch (err) {
|
|
411
|
-
const fixable = fixAndRetry(err);
|
|
412
|
-
if (fixable) return { isError: true, content: [{ type: "text", text: JSON.stringify(fixable) }] };
|
|
413
|
-
throw err;
|
|
414
|
-
}
|
|
415
|
-
const sentAs = slotName(AGENT_NAME);
|
|
416
|
-
const shown = waitNow(result) ? await (async () => {
|
|
417
|
-
const wait = await awaitReply2(result.notificationId, { ...signal ? { signal } : {} });
|
|
418
|
-
return { ...result, wait, message: awaitMessage(wait) };
|
|
419
|
-
})() : { ...result, message: contactMessage(result) };
|
|
420
|
-
return { content: [{ type: "text", text: JSON.stringify(sentAs ? { ...shown, sentAs } : shown) }] };
|
|
421
|
-
}
|
|
422
|
-
case "check_replies": {
|
|
423
|
-
const result = await checkReplies();
|
|
424
|
-
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
425
|
-
}
|
|
426
|
-
case "get_thread": {
|
|
427
|
-
const { parentId } = GetThreadSchema.parse(request.params.arguments);
|
|
428
|
-
return { content: [{ type: "text", text: JSON.stringify(await getThread(parentId)) }] };
|
|
429
|
-
}
|
|
430
|
-
case "search_threads": {
|
|
431
|
-
const { q } = SearchThreadsSchema.parse(request.params.arguments);
|
|
432
|
-
return { content: [{ type: "text", text: JSON.stringify(await searchThreads(q)) }] };
|
|
433
|
-
}
|
|
434
|
-
case "answer_caller_question": {
|
|
435
|
-
const { notificationId, answer } = AnswerCallerQuestionSchema.parse(request.params.arguments);
|
|
436
|
-
const result = await answerCallerQuestion(notificationId, answer);
|
|
437
|
-
return { content: [{ type: "text", text: JSON.stringify({
|
|
438
|
-
...result,
|
|
439
|
-
...result.live ? {} : { note: "The call already ended \u2014 send this as a threaded contact instead so the answer still reaches them." }
|
|
440
|
-
}) }] };
|
|
441
|
-
}
|
|
442
|
-
case "set_task_state": {
|
|
443
|
-
const { notificationId, state } = SetTaskStateToolSchema.parse(request.params.arguments);
|
|
444
|
-
const result = await setTaskState(notificationId, state);
|
|
445
|
-
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
446
|
-
}
|
|
447
|
-
case "set_work_state": {
|
|
448
|
-
const result = await setWorkState(SetWorkStateSchema.parse(request.params.arguments));
|
|
449
|
-
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
450
|
-
}
|
|
451
|
-
case "create_goal": {
|
|
452
|
-
const result = await createGoal(CreateGoalSchema.parse(request.params.arguments));
|
|
453
|
-
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
454
|
-
}
|
|
455
|
-
case "claim_goal": {
|
|
456
|
-
const { goalId } = ClaimGoalSchema.parse(request.params.arguments);
|
|
457
|
-
return { content: [{ type: "text", text: JSON.stringify(await claimGoal(goalId)) }] };
|
|
458
|
-
}
|
|
459
|
-
case "update_goal": {
|
|
460
|
-
const { goalId, ...input } = UpdateGoalToolSchema.parse(request.params.arguments);
|
|
461
|
-
return { content: [{ type: "text", text: JSON.stringify(await updateGoal(goalId, input)) }] };
|
|
462
|
-
}
|
|
463
|
-
case "schedule_callback": {
|
|
464
|
-
const result = await scheduleCallback(ScheduleCallbackSchema.parse(request.params.arguments));
|
|
465
|
-
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
466
|
-
}
|
|
467
|
-
case "handoff": {
|
|
468
|
-
const result = await handoff(HandoffSchema.parse(request.params.arguments));
|
|
469
|
-
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
324
|
+
default: {
|
|
325
|
+
const name = request.params.name;
|
|
326
|
+
const result = await runTool(name, request.params.arguments ?? {}, { waits: true, signal });
|
|
327
|
+
const sentAs = name === "contact" ? slotName(AGENT_NAME) : null;
|
|
328
|
+
const shaped = sentAs && result && typeof result === "object" ? { ...result, sentAs } : result;
|
|
329
|
+
return { content: [{ type: "text", text: JSON.stringify(shaped) }] };
|
|
470
330
|
}
|
|
471
|
-
default:
|
|
472
|
-
throw new Error(`Unknown tool: ${request.params.name}`);
|
|
473
331
|
}
|
|
474
332
|
}
|
|
475
333
|
var beatDown = false;
|
package/dist/listen.js
CHANGED
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
answerText
|
|
4
|
-
} from "./chunk-2SWUY5WK.js";
|
|
5
2
|
import {
|
|
6
3
|
WAKE_EVENT,
|
|
7
4
|
wakeChannel
|
|
8
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-3QUIB42M.js";
|
|
9
6
|
import {
|
|
10
7
|
ackReply,
|
|
11
8
|
authToken,
|
|
12
9
|
decodeReply,
|
|
13
10
|
registerDelivery,
|
|
14
11
|
sweepLeased
|
|
15
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-4UZAPBKK.js";
|
|
16
13
|
|
|
17
14
|
// src/listen.ts
|
|
18
15
|
import { createClient } from "@supabase/supabase-js";
|
|
@@ -117,6 +114,29 @@ function uninstallService() {
|
|
|
117
114
|
return unit;
|
|
118
115
|
}
|
|
119
116
|
|
|
117
|
+
// src/message.ts
|
|
118
|
+
function answerText(answer) {
|
|
119
|
+
switch (answer.kind) {
|
|
120
|
+
case "text":
|
|
121
|
+
return answer.text;
|
|
122
|
+
case "option":
|
|
123
|
+
return answer.label ?? answer.optionId;
|
|
124
|
+
case "multi":
|
|
125
|
+
case "ranked":
|
|
126
|
+
return (answer.labels ?? answer.optionIds).join(", ");
|
|
127
|
+
case "confirm":
|
|
128
|
+
return answer.approved ? "approved" : "declined";
|
|
129
|
+
case "clarify":
|
|
130
|
+
return answer.chunks.join(" ");
|
|
131
|
+
case "turns":
|
|
132
|
+
return answer.turns.map((turn) => turn.reply).join(" ");
|
|
133
|
+
case "precedent":
|
|
134
|
+
return answer.answer;
|
|
135
|
+
case "ignored":
|
|
136
|
+
return "";
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
120
140
|
// src/listen.ts
|
|
121
141
|
var emit = (obj) => void process.stdout.write(JSON.stringify(obj) + "\n");
|
|
122
142
|
function launchEnv(work, reason) {
|
package/dist/onboard.js
CHANGED
|
@@ -3,13 +3,13 @@ import {
|
|
|
3
3
|
resolvePairing,
|
|
4
4
|
startPairing,
|
|
5
5
|
suggestedAgentName
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-CXABA27N.js";
|
|
7
7
|
import {
|
|
8
8
|
autoConfigureClients,
|
|
9
9
|
claudeInstallHint,
|
|
10
10
|
openBrowser
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-TLASZUJD.js";
|
|
12
|
+
import "./chunk-3QUIB42M.js";
|
|
13
13
|
import {
|
|
14
14
|
AGENT_NAME,
|
|
15
15
|
TOKEN_PATH,
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
saveToken,
|
|
21
21
|
setIdentity,
|
|
22
22
|
whoAmI
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-4UZAPBKK.js";
|
|
24
24
|
|
|
25
25
|
// src/onboard.ts
|
|
26
26
|
function reportRegistered() {
|
package/dist/slot.js
CHANGED
package/dist/statusline.js
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
readToken,
|
|
10
10
|
sessionSlot,
|
|
11
11
|
slotName
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-4UZAPBKK.js";
|
|
13
13
|
|
|
14
14
|
// src/statusline.ts
|
|
15
15
|
import { mkdirSync, readFileSync, realpathSync, writeFileSync } from "fs";
|
|
@@ -35,7 +35,9 @@ function render(v) {
|
|
|
35
35
|
case "session": {
|
|
36
36
|
const who = v.name ? `${v.name} \xB7 ` : "";
|
|
37
37
|
if (!v.status) return `paigy: ${who}revoked`;
|
|
38
|
-
|
|
38
|
+
const n = v.status.waiting ?? 0;
|
|
39
|
+
const waiting = n > 0 ? ` \xB7 ${n} waiting` : "";
|
|
40
|
+
return `paigy: ${who}${MODE_LABEL[v.status.sessionMode]} \xB7 ${v.status.phone ? "phone \u2713" : "no phone"}${waiting}`;
|
|
39
41
|
}
|
|
40
42
|
}
|
|
41
43
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paigy/mcp",
|
|
3
|
-
"version": "0.40.
|
|
3
|
+
"version": "0.40.1",
|
|
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",
|
|
@@ -24,13 +24,6 @@
|
|
|
24
24
|
"url": "git+https://github.com/mauurda/paigy.git",
|
|
25
25
|
"directory": "apps/mcp"
|
|
26
26
|
},
|
|
27
|
-
"scripts": {
|
|
28
|
-
"build": "tsup",
|
|
29
|
-
"dev": "tsup --watch",
|
|
30
|
-
"typecheck": "tsc --noEmit",
|
|
31
|
-
"test": "vitest run",
|
|
32
|
-
"prepublishOnly": "pnpm --filter @paigy/schema build && pnpm --filter @paigy/crypto build && pnpm --filter @paigy/sdk build && pnpm build"
|
|
33
|
-
},
|
|
34
27
|
"dependencies": {
|
|
35
28
|
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
36
29
|
"@supabase/supabase-js": "^2.47.10",
|
|
@@ -40,13 +33,19 @@
|
|
|
40
33
|
"zod-to-json-schema": "^3.24.1"
|
|
41
34
|
},
|
|
42
35
|
"devDependencies": {
|
|
43
|
-
"@paigy/crypto": "workspace:*",
|
|
44
|
-
"@paigy/schema": "workspace:*",
|
|
45
|
-
"@paigy/sdk": "workspace:*",
|
|
46
36
|
"@types/node": "^22.0.0",
|
|
47
37
|
"@types/qrcode-generator": "^1.0.6",
|
|
48
38
|
"tsup": "^8.3.5",
|
|
49
39
|
"typescript": "^5.7.2",
|
|
50
|
-
"vitest": "^2.1.8"
|
|
40
|
+
"vitest": "^2.1.8",
|
|
41
|
+
"@paigy/crypto": "0.0.0",
|
|
42
|
+
"@paigy/schema": "0.0.0",
|
|
43
|
+
"@paigy/sdk": "0.2.1"
|
|
44
|
+
},
|
|
45
|
+
"scripts": {
|
|
46
|
+
"build": "tsup",
|
|
47
|
+
"dev": "tsup --watch",
|
|
48
|
+
"typecheck": "tsc --noEmit",
|
|
49
|
+
"test": "vitest run"
|
|
51
50
|
}
|
|
52
|
-
}
|
|
51
|
+
}
|
package/dist/chunk-2SWUY5WK.js
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
// src/message.ts
|
|
2
|
-
function waitNow(result) {
|
|
3
|
-
const units = result.plan?.units ?? [];
|
|
4
|
-
return units.some((unit) => unit.level === "call") || units.length > 0 && units.every((unit) => unit.settled);
|
|
5
|
-
}
|
|
6
|
-
function contactMessage(result) {
|
|
7
|
-
return result.message;
|
|
8
|
-
}
|
|
9
|
-
function answerText(answer) {
|
|
10
|
-
switch (answer.kind) {
|
|
11
|
-
case "text":
|
|
12
|
-
return answer.text;
|
|
13
|
-
case "option":
|
|
14
|
-
return answer.label ?? answer.optionId;
|
|
15
|
-
case "multi":
|
|
16
|
-
case "ranked":
|
|
17
|
-
return (answer.labels ?? answer.optionIds).join(", ");
|
|
18
|
-
case "confirm":
|
|
19
|
-
return answer.approved ? "approved" : "declined";
|
|
20
|
-
case "clarify":
|
|
21
|
-
return answer.chunks.join(" ");
|
|
22
|
-
case "turns":
|
|
23
|
-
return answer.turns.map((turn) => turn.reply).join(" ");
|
|
24
|
-
case "precedent":
|
|
25
|
-
return answer.answer;
|
|
26
|
-
case "ignored":
|
|
27
|
-
return "";
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
function awaitMessage(item) {
|
|
31
|
-
switch (item.type) {
|
|
32
|
-
case "partial":
|
|
33
|
-
return `The user is on the call. This is provisional: ${item.turn.reply}`;
|
|
34
|
-
case "idle":
|
|
35
|
-
return item.inFlight === false ? "No call is live for this ask \u2014 it was delivered as a message. The reply arrives through check_replies (or your wake); do not wait on it again." : "Still waiting for the user. Call contact again with only { wait: notificationId } to keep waiting.";
|
|
36
|
-
case "remind":
|
|
37
|
-
return `The user asked to be reminded in ${item.remindInSeconds} seconds. Schedule a wake-up, then call contact again with only { wait: notificationId }.`;
|
|
38
|
-
case "superseded":
|
|
39
|
-
return "This ask was superseded. Stop waiting on it and re-orient on the thread.";
|
|
40
|
-
case "reply": {
|
|
41
|
-
const ended = item.transcript !== void 0 || item.answer.kind === "turns" ? "The call ended. " : "";
|
|
42
|
-
if (item.answer.kind === "option" || item.answer.kind === "multi" || item.answer.kind === "ranked") {
|
|
43
|
-
return `${ended}The user chose ${answerText(item.answer)}.`;
|
|
44
|
-
}
|
|
45
|
-
if (item.answer.kind === "confirm") return `${ended}The user ${answerText(item.answer)}.`;
|
|
46
|
-
if (item.answer.kind === "ignored") return `${ended}The user did not answer.`;
|
|
47
|
-
return `${ended}The user replied: ${answerText(item.answer)}`;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export {
|
|
53
|
-
waitNow,
|
|
54
|
-
contactMessage,
|
|
55
|
-
answerText,
|
|
56
|
-
awaitMessage
|
|
57
|
-
};
|