@paigy/mcp 0.12.1 → 0.13.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.
- package/dist/chunk-KNCXKXUG.js +224 -0
- package/dist/chunk-O6W2T6D2.js +3312 -0
- package/dist/index.js +134 -22
- package/dist/listen.js +6 -4
- package/dist/onboard.js +2 -2
- package/dist/statusline.js +3 -4
- package/package.json +4 -3
- package/dist/chunk-ACPCCDHI.js +0 -451
- package/dist/chunk-AILC3H3U.js +0 -81
- package/dist/chunk-GU7C5H6L.js +0 -15
package/dist/chunk-ACPCCDHI.js
DELETED
|
@@ -1,451 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BACKEND_URL,
|
|
3
|
-
reach
|
|
4
|
-
} from "./chunk-GU7C5H6L.js";
|
|
5
|
-
|
|
6
|
-
// ../../packages/schema/dist/index.js
|
|
7
|
-
import { z } from "zod";
|
|
8
|
-
var ContextSchema = z.object({
|
|
9
|
-
title: z.string().min(1).describe("One-line headline of what you need (required, non-empty)."),
|
|
10
|
-
description: z.array(z.string().min(1)).min(1).describe("Semantic chunks of detail (each a standalone, non-empty piece). The user can select chunks to ask you to expand.")
|
|
11
|
-
});
|
|
12
|
-
var OptionSchema = z.object({
|
|
13
|
-
id: z.string(),
|
|
14
|
-
label: z.string(),
|
|
15
|
-
// .describe() flows into the MCP notify_user JSON schema (zodToJsonSchema), so
|
|
16
|
-
// the constraints below are what an agent reads when deciding to use these.
|
|
17
|
-
html: z.string().max(16384).describe(
|
|
18
|
-
"Optional sandboxed HTML/CSS preview for a visual 'pick one' (shown in the option card). Untrusted-sandboxed: NO JavaScript, NO external network or images \u2014 inline CSS and data: URIs only; <=16KB. Use for layout/CSS mockups, tables, diffs. For a hosted image use `image` instead."
|
|
19
|
-
).optional(),
|
|
20
|
-
image: z.string().url().describe(
|
|
21
|
-
"Optional image URL rendered as the option's preview (plain image, not sandboxed). For agent-generated HTML/CSS mockups, use `html` instead."
|
|
22
|
-
).optional()
|
|
23
|
-
});
|
|
24
|
-
var VisualSchema = z.object({
|
|
25
|
-
url: z.string().url(),
|
|
26
|
-
label: z.string().optional()
|
|
27
|
-
});
|
|
28
|
-
var NotifyLevelSchema = z.enum(["inbox", "push", "banner", "call"]);
|
|
29
|
-
var NotifyRequestSchema = z.object({
|
|
30
|
-
context: ContextSchema,
|
|
31
|
-
options: z.array(OptionSchema.omit({ id: true })).min(1).optional().describe(
|
|
32
|
-
"The choices, in order \u2014 required when select is 'one'/'many'/'rank', omitted otherwise. Ids are assigned automatically by position ('1', '2', \u2026); the user's answer references them as optionId(s)."
|
|
33
|
-
),
|
|
34
|
-
visuals: z.array(VisualSchema).optional().describe(
|
|
35
|
-
"Images attached to the message itself \u2014 context for the whole question (a screenshot, a chart). For a preview on one selectable choice, use that option's `html`/`image` instead."
|
|
36
|
-
),
|
|
37
|
-
/** Git repo the agent is working in ("owner/name"). Local MCP fills this from the checkout — omit unless overriding. */
|
|
38
|
-
repo: z.string().optional(),
|
|
39
|
-
/** Git branch the agent is on. Local MCP fills this from the checkout — omit unless overriding. */
|
|
40
|
-
branch: z.string().optional(),
|
|
41
|
-
/** Continue an existing conversation; omitted = start a new thread. */
|
|
42
|
-
threadId: z.string().uuid().optional(),
|
|
43
|
-
urgency: NotifyLevelSchema.default("inbox").describe(
|
|
44
|
-
"The level you're requesting \u2014 the user's account permissions + session mode can lower it. 'inbox' (default) = sits silently in the inbox for the user to get to. 'push' = a quiet passive push (lands in Notification Center, no sound) \u2014 a gentle heads-up. 'banner' = a time-sensitive banner/lock-screen push with sound (a 'paige') they tap to open \u2014 use when you need them soon-ish but it's not worth ringing them. 'call' = rings the user's phone now (a CallKit voice call) \u2014 use only when you genuinely need them in the moment (blocked and waiting, time-sensitive). context.title is what they see on the banner/ring, so make it specific."
|
|
45
|
-
),
|
|
46
|
-
/** The request this one was spawned from, for a clarification. */
|
|
47
|
-
parentId: z.string().optional(),
|
|
48
|
-
select: z.enum(["one", "many", "rank", "confirm", "text"]).describe(
|
|
49
|
-
"How the user answers \u2014 required, pick the shape that fits the question: 'one' = pick one option, 'many' = pick several, 'rank' = pick & order (each needs `options`); 'confirm' = yes/no or approve/deny; 'text' = free-form reply only (status updates, open questions). 'confirm' and 'text' take no options."
|
|
50
|
-
),
|
|
51
|
-
confirmStyle: z.enum(["yesno", "approve"]).default("yesno").describe(
|
|
52
|
-
"Labels for a select:'confirm' paige \u2014 'yesno' (Yes/No) or 'approve' (Approve/Deny). Ignored unless select is 'confirm'."
|
|
53
|
-
),
|
|
54
|
-
blocking: z.boolean().default(false).describe(
|
|
55
|
-
"Set true when real downstream work is stuck behind this specific decision \u2014 you can't make meaningful progress until it's answered. This is the real signal for how urgently the user should be reached; it's what the premier use case (an agent that stays unblocked instead of going idle) depends on. Independent of `urgency`: a `banner`-level question can still be `blocking` (something IS stuck, just not time-critical enough to ring for immediately) \u2014 if it goes unanswered a while, Paigy escalates it to a real call using this flag rather than guessing from how many other things happen to be pending. Leave false for anything you could work around, defer, or where other useful work exists meanwhile."
|
|
56
|
-
)
|
|
57
|
-
}).superRefine((r, ctx) => {
|
|
58
|
-
const needsOptions = r.select === "one" || r.select === "many" || r.select === "rank";
|
|
59
|
-
if (needsOptions && !r.options?.length)
|
|
60
|
-
ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["options"], message: `select:'${r.select}' requires options` });
|
|
61
|
-
if (!needsOptions && r.options?.length)
|
|
62
|
-
ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["options"], message: `select:'${r.select}' takes no options` });
|
|
63
|
-
});
|
|
64
|
-
var NotifyStatusSchema = z.enum(["pending", "answered", "ignored"]);
|
|
65
|
-
var AgentStateSchema = z.enum(["idle", "in_progress", "completed", "needs_input"]);
|
|
66
|
-
var SetTaskStateSchema = z.object({
|
|
67
|
-
state: z.enum(["in_progress", "completed", "needs_input"])
|
|
68
|
-
});
|
|
69
|
-
var TurnSchema = z.object({
|
|
70
|
-
prompt: z.string(),
|
|
71
|
-
reply: z.string()
|
|
72
|
-
});
|
|
73
|
-
var UserAnswerSchema = z.discriminatedUnion("kind", [
|
|
74
|
-
z.object({ kind: z.literal("option"), optionId: z.string() }),
|
|
75
|
-
z.object({ kind: z.literal("text"), text: z.string() }),
|
|
76
|
-
z.object({ kind: z.literal("ignored") }),
|
|
77
|
-
z.object({ kind: z.literal("multi"), optionIds: z.array(z.string()) }),
|
|
78
|
-
z.object({ kind: z.literal("ranked"), optionIds: z.array(z.string()) }),
|
|
79
|
-
z.object({ kind: z.literal("clarify"), chunks: z.array(z.string()).min(1) }),
|
|
80
|
-
z.object({ kind: z.literal("confirm"), approved: z.boolean() }),
|
|
81
|
-
z.object({ kind: z.literal("turns"), turns: z.array(TurnSchema).min(1) })
|
|
82
|
-
]);
|
|
83
|
-
var AwaitItemSchema = z.discriminatedUnion("type", [
|
|
84
|
-
z.object({
|
|
85
|
-
type: z.literal("reply"),
|
|
86
|
-
threadId: z.string(),
|
|
87
|
-
notificationId: z.string(),
|
|
88
|
-
answer: UserAnswerSchema
|
|
89
|
-
}),
|
|
90
|
-
z.object({
|
|
91
|
-
type: z.literal("remind"),
|
|
92
|
-
threadId: z.string(),
|
|
93
|
-
notificationId: z.string(),
|
|
94
|
-
remindAt: z.string().datetime({ offset: true }),
|
|
95
|
-
/** Seconds until remindAt, server-computed — pass straight to ScheduleWakeup. */
|
|
96
|
-
remindInSeconds: z.number()
|
|
97
|
-
}),
|
|
98
|
-
z.object({ type: z.literal("idle") })
|
|
99
|
-
]);
|
|
100
|
-
var CallbackTriggerSchema = z.enum(["on_done", "on_blocked", "scheduled"]);
|
|
101
|
-
var ScheduleCallbackSchema = z.object({
|
|
102
|
-
threadId: z.string().describe("The thread to call back on (from a prior notify_user / reply / request)."),
|
|
103
|
-
trigger: CallbackTriggerSchema,
|
|
104
|
-
dueInSeconds: z.number().int().positive().optional().describe("For 'scheduled' only: how many seconds from now to fire."),
|
|
105
|
-
note: z.string().optional().describe("What to tell the user when you follow up.")
|
|
106
|
-
});
|
|
107
|
-
var PendingRepliesSchema = z.object({
|
|
108
|
-
replies: z.array(
|
|
109
|
-
z.object({ threadId: z.string(), notificationId: z.string(), answer: UserAnswerSchema })
|
|
110
|
-
),
|
|
111
|
-
pending: z.array(
|
|
112
|
-
z.object({ threadId: z.string(), notificationId: z.string(), createdAt: z.string() })
|
|
113
|
-
),
|
|
114
|
-
/** User-initiated requests addressed to this agent; act on them and reply via
|
|
115
|
-
* notify_user on the same threadId. Keeps reappearing until you call
|
|
116
|
-
* set_task_state on its notificationId. */
|
|
117
|
-
requests: z.array(
|
|
118
|
-
z.object({ threadId: z.string(), notificationId: z.string(), text: z.string(), createdAt: z.string() })
|
|
119
|
-
),
|
|
120
|
-
/** Callbacks you owe the user that are now DUE (you said you'd follow up when done,
|
|
121
|
-
* if blocked, or at a time that has passed). Re-surfaced every sweep until you
|
|
122
|
-
* fulfill one by calling notify_user on its threadId. */
|
|
123
|
-
owedCallbacks: z.array(
|
|
124
|
-
z.object({ threadId: z.string(), trigger: CallbackTriggerSchema, note: z.string() })
|
|
125
|
-
),
|
|
126
|
-
/** Work (either direction) you reported in_progress a while ago and never reported
|
|
127
|
-
* completed — likely left half-done by this session or a prior one that crashed or
|
|
128
|
-
* went idle. Report a real state (set_task_state) or continue the work. */
|
|
129
|
-
stalled: z.array(
|
|
130
|
-
z.object({ threadId: z.string(), notificationId: z.string(), title: z.string().nullable(), startedAt: z.string() })
|
|
131
|
-
)
|
|
132
|
-
});
|
|
133
|
-
var NotifyResponseSchema = z.object({
|
|
134
|
-
notificationId: z.string(),
|
|
135
|
-
status: NotifyStatusSchema,
|
|
136
|
-
createdAt: z.string().datetime(),
|
|
137
|
-
answer: UserAnswerSchema.optional(),
|
|
138
|
-
answeredAt: z.string().datetime().optional()
|
|
139
|
-
});
|
|
140
|
-
var UserResponseSchema = z.object({
|
|
141
|
-
requestId: z.string(),
|
|
142
|
-
answer: UserAnswerSchema,
|
|
143
|
-
answeredAt: z.string().datetime()
|
|
144
|
-
});
|
|
145
|
-
var InboxItemSchema = z.object({
|
|
146
|
-
id: z.string(),
|
|
147
|
-
status: NotifyStatusSchema,
|
|
148
|
-
context: ContextSchema,
|
|
149
|
-
options: z.array(OptionSchema).optional(),
|
|
150
|
-
visuals: z.array(VisualSchema).optional(),
|
|
151
|
-
agent: z.string(),
|
|
152
|
-
nickname: z.string(),
|
|
153
|
-
repo: z.string().optional(),
|
|
154
|
-
branch: z.string().optional(),
|
|
155
|
-
createdAt: z.string().datetime(),
|
|
156
|
-
snoozedUntil: z.string().datetime().optional(),
|
|
157
|
-
agentState: AgentStateSchema.default("idle"),
|
|
158
|
-
/** Whose action the item is waiting on: "you" = an agent asked you (the default,
|
|
159
|
-
* every agent→user notification); "agent" = you sent a request and it's awaiting the
|
|
160
|
-
* agent (held in the inbox until the agent replies on the thread). */
|
|
161
|
-
turn: z.enum(["you", "agent"]).default("you"),
|
|
162
|
-
/** Hard error reason on an awaiting request (turn="agent") — the wake failed to reach
|
|
163
|
-
* the agent (provider-agnostic; set server-side). Absent = no hard error, though the
|
|
164
|
-
* client may still flag a stall by age. Drives the inbox error badge + Retry. */
|
|
165
|
-
error: z.string().optional(),
|
|
166
|
-
parentId: z.string().optional(),
|
|
167
|
-
select: z.enum(["one", "many", "rank", "confirm", "text"]).default("one"),
|
|
168
|
-
confirmStyle: z.enum(["yesno", "approve"]).default("yesno").describe(
|
|
169
|
-
"Labels for a select:'confirm' paige \u2014 'yesno' (Yes/No) or 'approve' (Approve/Deny). Ignored unless select is 'confirm'."
|
|
170
|
-
),
|
|
171
|
-
/** Real downstream work is stuck behind this one — set by the agent, independent of
|
|
172
|
-
* urgency (see the main README's "premier use case" + notify/states.md). Drives the
|
|
173
|
-
* inbox's blocking badge and the extra confirm step before dismissing it. */
|
|
174
|
-
blocking: z.boolean().default(false),
|
|
175
|
-
/** The user's locked-in answer; present only for replied items (GET /api/replied/:id). */
|
|
176
|
-
answer: UserAnswerSchema.optional()
|
|
177
|
-
});
|
|
178
|
-
var SnoozeRequestSchema = z.object({
|
|
179
|
-
requestId: z.string(),
|
|
180
|
-
until: z.string().datetime()
|
|
181
|
-
});
|
|
182
|
-
var PushTokenSchema = z.object({
|
|
183
|
-
voipToken: z.string().min(1).optional(),
|
|
184
|
-
alertToken: z.string().min(1).optional(),
|
|
185
|
-
fcmToken: z.string().min(1).optional(),
|
|
186
|
-
platform: z.enum(["ios", "android"])
|
|
187
|
-
});
|
|
188
|
-
var MissedCallSchema = z.enum([
|
|
189
|
-
"retry_10m",
|
|
190
|
-
"retry_30m",
|
|
191
|
-
"retry_60m",
|
|
192
|
-
"backoff_gentle",
|
|
193
|
-
"backoff_standard",
|
|
194
|
-
"backoff_aggressive",
|
|
195
|
-
"inbox",
|
|
196
|
-
"dismiss"
|
|
197
|
-
]);
|
|
198
|
-
var UserSettingsSchema = z.object({
|
|
199
|
-
permissions: z.object({
|
|
200
|
-
call: z.boolean(),
|
|
201
|
-
banner: z.boolean(),
|
|
202
|
-
push: z.boolean()
|
|
203
|
-
}),
|
|
204
|
-
sessionMode: z.enum(["default", "all_calls", "silent"]),
|
|
205
|
-
silentPush: z.boolean(),
|
|
206
|
-
autoCallback: z.boolean(),
|
|
207
|
-
/** Opt-in (default false) to using your content to improve Paigy and train models. */
|
|
208
|
-
improveConsent: z.boolean(),
|
|
209
|
-
missedCall: MissedCallSchema.default("backoff_standard"),
|
|
210
|
-
/** Where voice audio is processed. 'hosted' (default) = Paigy's voice services
|
|
211
|
-
* (ElevenLabs TTS, faster-whisper STT, the call bot); 'on_device' = the phone
|
|
212
|
-
* synthesizes and transcribes locally — no audio or spoken text leaves it.
|
|
213
|
-
* Optional, NOT defaulted: a stale client PATCHing the full settings object
|
|
214
|
-
* must not silently reset this privacy choice. Absent = leave unchanged on
|
|
215
|
-
* write, 'hosted' on read (see store.ts). */
|
|
216
|
-
voiceMode: z.enum(["hosted", "on_device"]).optional()
|
|
217
|
-
});
|
|
218
|
-
var HistoryItemSchema = z.object({
|
|
219
|
-
id: z.string(),
|
|
220
|
-
threadId: z.string(),
|
|
221
|
-
/** 'user' = a request you sent; 'agent' = a notification an agent sent you. */
|
|
222
|
-
initiator: z.enum(["user", "agent"]),
|
|
223
|
-
title: z.string(),
|
|
224
|
-
/** The agent on the other end (nickname). */
|
|
225
|
-
agent: z.string(),
|
|
226
|
-
createdAt: z.string(),
|
|
227
|
-
/** When the agent fetched your request (user→agent only). */
|
|
228
|
-
agentAckedAt: z.string().nullable(),
|
|
229
|
-
/** When you answered the agent's notification (agent→user only). */
|
|
230
|
-
humanAckedAt: z.string().nullable()
|
|
231
|
-
});
|
|
232
|
-
var ConnectionSummarySchema = z.object({
|
|
233
|
-
/** The connection = the agent's token id (used to address a request). */
|
|
234
|
-
id: z.string(),
|
|
235
|
-
agent: z.string(),
|
|
236
|
-
device: z.string().nullable(),
|
|
237
|
-
nickname: z.string(),
|
|
238
|
-
createdAt: z.string().datetime(),
|
|
239
|
-
/** Most recent notification on this connection, either direction. Null = no contact yet.
|
|
240
|
-
* Drives the agents-page recency grouping (Today / This week / …). */
|
|
241
|
-
lastContactAt: z.string().datetime().nullable(),
|
|
242
|
-
/** True = a provider-managed agent running in the provider's cloud (e.g. Anthropic CMA);
|
|
243
|
-
* false = a local MCP connection running on the user's computer (Claude Code/Codex/…). */
|
|
244
|
-
managed: z.boolean()
|
|
245
|
-
});
|
|
246
|
-
var CreateRequestSchema = z.object({
|
|
247
|
-
/** The connection (token id) to send to, from GET /api/tokens. */
|
|
248
|
-
tokenId: z.string(),
|
|
249
|
-
/** The user's message to the agent. */
|
|
250
|
-
text: z.string().min(1)
|
|
251
|
-
});
|
|
252
|
-
var DeliveryModeSchema = z.enum(["poll", "self_hosted"]);
|
|
253
|
-
var WAKE_EVENT = "wake";
|
|
254
|
-
var wakeChannel = (tokenId) => `wake:${tokenId}`;
|
|
255
|
-
var RegisterDeliverySchema = z.object({ mode: DeliveryModeSchema });
|
|
256
|
-
var OAuthStartSchema = z.object({
|
|
257
|
-
provider: z.enum(["cma"]),
|
|
258
|
-
returnTo: z.string().min(1)
|
|
259
|
-
});
|
|
260
|
-
var DeliveryConfigSchema = z.object({
|
|
261
|
-
tokenId: z.string(),
|
|
262
|
-
mode: DeliveryModeSchema,
|
|
263
|
-
/** null when the server has no SUPABASE_ANON_KEY set — the listener then falls
|
|
264
|
-
* back to its own PAIGY_SUPABASE_URL / PAIGY_SUPABASE_ANON_KEY env. */
|
|
265
|
-
realtime: z.object({ url: z.string(), anonKey: z.string() }).nullable()
|
|
266
|
-
});
|
|
267
|
-
var StatusSchema = z.object({
|
|
268
|
-
agent: z.string(),
|
|
269
|
-
nickname: z.string(),
|
|
270
|
-
sessionMode: z.enum(["default", "all_calls", "silent"]),
|
|
271
|
-
/** A phone is registered for push/ring (any push token on the account). */
|
|
272
|
-
phone: z.boolean()
|
|
273
|
-
});
|
|
274
|
-
var EnvelopeRecipientSchema = z.object({
|
|
275
|
-
keyId: z.string(),
|
|
276
|
-
epk: z.string(),
|
|
277
|
-
wnonce: z.string(),
|
|
278
|
-
wrap: z.string()
|
|
279
|
-
});
|
|
280
|
-
var EnvelopeHeaderSchema = z.object({
|
|
281
|
-
field: z.enum(["context", "options", "visuals", "answer"]),
|
|
282
|
-
kind: z.string(),
|
|
283
|
-
senderRole: z.enum(["agent", "user"]),
|
|
284
|
-
recipientKeyIds: z.array(z.string()),
|
|
285
|
-
seq: z.number().int().nonnegative()
|
|
286
|
-
});
|
|
287
|
-
var EnvelopeSchema = z.object({
|
|
288
|
-
v: z.literal(1),
|
|
289
|
-
alg: z.literal("x25519-xsalsa20poly1305"),
|
|
290
|
-
msgId: z.string(),
|
|
291
|
-
hdr: EnvelopeHeaderSchema,
|
|
292
|
-
recipients: z.array(EnvelopeRecipientSchema).min(1),
|
|
293
|
-
nonce: z.string(),
|
|
294
|
-
ct: z.string()
|
|
295
|
-
});
|
|
296
|
-
var SealedAnswerSchema = z.object({
|
|
297
|
-
ignored: z.boolean(),
|
|
298
|
-
envelope: EnvelopeSchema
|
|
299
|
-
});
|
|
300
|
-
var DeviceCredentialSchema = z.object({
|
|
301
|
-
deviceId: z.string(),
|
|
302
|
-
kind: z.enum(["phone", "web", "agent"]),
|
|
303
|
-
x25519Pub: z.string(),
|
|
304
|
-
ed25519Pub: z.string(),
|
|
305
|
-
sig: z.string()
|
|
306
|
-
});
|
|
307
|
-
var DeviceRosterSchema = z.object({
|
|
308
|
-
uikPub: z.string(),
|
|
309
|
-
devices: z.array(DeviceCredentialSchema)
|
|
310
|
-
});
|
|
311
|
-
var WakeNudgeSchema = z.object({
|
|
312
|
-
kind: z.enum(["reply", "request", "callback"]),
|
|
313
|
-
notificationId: z.string().optional(),
|
|
314
|
-
threadId: z.string()
|
|
315
|
-
});
|
|
316
|
-
var DeviceAgentTokenSchema = z.object({
|
|
317
|
-
token: z.string(),
|
|
318
|
-
deviceId: z.string(),
|
|
319
|
-
agentName: z.string(),
|
|
320
|
-
/** User-chosen session label; defaults to `<agent> <device>`. */
|
|
321
|
-
nickname: z.string(),
|
|
322
|
-
createdAt: z.string().datetime()
|
|
323
|
-
});
|
|
324
|
-
var PairingStatusSchema = z.enum(["pending", "approved", "denied", "expired"]);
|
|
325
|
-
var DeviceCodeSchema = z.object({
|
|
326
|
-
device_code: z.string(),
|
|
327
|
-
user_code: z.string(),
|
|
328
|
-
verification_uri: z.string().url(),
|
|
329
|
-
verification_uri_complete: z.string().url(),
|
|
330
|
-
interval: z.number(),
|
|
331
|
-
expires_in: z.number()
|
|
332
|
-
});
|
|
333
|
-
var DeviceInfoSchema = z.object({
|
|
334
|
-
code: z.string(),
|
|
335
|
-
agent: z.string(),
|
|
336
|
-
device: z.string().nullable(),
|
|
337
|
-
status: PairingStatusSchema
|
|
338
|
-
});
|
|
339
|
-
var DeviceTokenSchema = z.object({
|
|
340
|
-
access_token: z.string(),
|
|
341
|
-
nickname: z.string(),
|
|
342
|
-
agent: z.string(),
|
|
343
|
-
device: z.string().nullable()
|
|
344
|
-
});
|
|
345
|
-
var SupportRequestSchema = z.object({
|
|
346
|
-
email: z.string().email().max(320),
|
|
347
|
-
message: z.string().trim().min(1).max(5e3),
|
|
348
|
-
name: z.string().trim().max(120).optional()
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
// src/client.ts
|
|
352
|
-
import { existsSync, readFileSync } from "fs";
|
|
353
|
-
import { homedir } from "os";
|
|
354
|
-
import { join } from "path";
|
|
355
|
-
var TOKEN_PATH = join(homedir(), ".paigy", "token.json");
|
|
356
|
-
function loadToken() {
|
|
357
|
-
if (process.env.PAIGY_TOKEN) return process.env.PAIGY_TOKEN;
|
|
358
|
-
if (existsSync(TOKEN_PATH)) {
|
|
359
|
-
try {
|
|
360
|
-
const raw = readFileSync(TOKEN_PATH, "utf8");
|
|
361
|
-
const parsed = JSON.parse(raw);
|
|
362
|
-
if (parsed.access_token) return parsed.access_token;
|
|
363
|
-
} catch {
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
return "";
|
|
367
|
-
}
|
|
368
|
-
var ONBOARD_MSG = "Not paired with Paigy yet \u2014 call the `pair` tool to connect this agent (it returns an approval link to show the user), then retry. Manual fallback: `npx -y @paigy/mcp paigy-mcp-onboard`.";
|
|
369
|
-
function ensureAuthed(res) {
|
|
370
|
-
if (res.status === 401) throw new Error(ONBOARD_MSG);
|
|
371
|
-
return res;
|
|
372
|
-
}
|
|
373
|
-
async function submitNotification(req) {
|
|
374
|
-
const token = loadToken();
|
|
375
|
-
const res = ensureAuthed(await reach(`${BACKEND_URL}/api/notify`, {
|
|
376
|
-
method: "POST",
|
|
377
|
-
headers: { "content-type": "application/json", authorization: `Bearer ${token}` },
|
|
378
|
-
body: JSON.stringify(req)
|
|
379
|
-
}));
|
|
380
|
-
if (!res.ok) throw new Error(`notify failed: ${res.status} ${await res.text()}`);
|
|
381
|
-
return await res.json();
|
|
382
|
-
}
|
|
383
|
-
var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
384
|
-
async function awaitReply(notificationId, opts = {}) {
|
|
385
|
-
const intervalMs = opts.intervalMs ?? 5e3;
|
|
386
|
-
const windowMs = opts.windowMs ?? 3e5;
|
|
387
|
-
const doSleep = opts.sleep ?? sleep;
|
|
388
|
-
const now = opts.now ?? Date.now;
|
|
389
|
-
const token = loadToken();
|
|
390
|
-
const start = now();
|
|
391
|
-
while (true) {
|
|
392
|
-
const res = ensureAuthed(await reach(`${BACKEND_URL}/api/await?notificationId=${encodeURIComponent(notificationId)}`, {
|
|
393
|
-
headers: { authorization: `Bearer ${token}` }
|
|
394
|
-
}));
|
|
395
|
-
if (!res.ok) throw new Error(`await failed: ${res.status} ${await res.text()}`);
|
|
396
|
-
const item = await res.json();
|
|
397
|
-
if (item.type !== "idle") return item;
|
|
398
|
-
if (now() - start >= windowMs) return { type: "idle" };
|
|
399
|
-
await doSleep(intervalMs);
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
async function checkReplies() {
|
|
403
|
-
const token = loadToken();
|
|
404
|
-
const res = ensureAuthed(await reach(`${BACKEND_URL}/api/pending`, {
|
|
405
|
-
headers: { authorization: `Bearer ${token}` }
|
|
406
|
-
}));
|
|
407
|
-
if (!res.ok) throw new Error(`check_replies failed: ${res.status} ${await res.text()}`);
|
|
408
|
-
return await res.json();
|
|
409
|
-
}
|
|
410
|
-
async function setTaskState(notificationId, state) {
|
|
411
|
-
const res = ensureAuthed(await reach(`${BACKEND_URL}/api/notify/${notificationId}/state`, {
|
|
412
|
-
method: "PATCH",
|
|
413
|
-
headers: { "content-type": "application/json", authorization: `Bearer ${loadToken()}` },
|
|
414
|
-
body: JSON.stringify({ state })
|
|
415
|
-
}));
|
|
416
|
-
if (!res.ok) throw new Error(`set_task_state failed: ${res.status} ${await res.text()}`);
|
|
417
|
-
return await res.json();
|
|
418
|
-
}
|
|
419
|
-
async function registerDelivery(mode) {
|
|
420
|
-
const res = ensureAuthed(await reach(`${BACKEND_URL}/api/delivery`, {
|
|
421
|
-
method: "POST",
|
|
422
|
-
headers: { "content-type": "application/json", authorization: `Bearer ${loadToken()}` },
|
|
423
|
-
body: JSON.stringify({ mode })
|
|
424
|
-
}));
|
|
425
|
-
if (!res.ok) throw new Error(`register_delivery failed: ${res.status} ${await res.text()}`);
|
|
426
|
-
return await res.json();
|
|
427
|
-
}
|
|
428
|
-
async function scheduleCallback(req) {
|
|
429
|
-
const token = loadToken();
|
|
430
|
-
const res = ensureAuthed(await reach(`${BACKEND_URL}/api/callback`, {
|
|
431
|
-
method: "POST",
|
|
432
|
-
headers: { "content-type": "application/json", authorization: `Bearer ${token}` },
|
|
433
|
-
body: JSON.stringify(req)
|
|
434
|
-
}));
|
|
435
|
-
if (!res.ok) throw new Error(`schedule_callback failed: ${res.status} ${await res.text()}`);
|
|
436
|
-
return await res.json();
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
export {
|
|
440
|
-
NotifyRequestSchema,
|
|
441
|
-
SetTaskStateSchema,
|
|
442
|
-
ScheduleCallbackSchema,
|
|
443
|
-
WAKE_EVENT,
|
|
444
|
-
wakeChannel,
|
|
445
|
-
submitNotification,
|
|
446
|
-
awaitReply,
|
|
447
|
-
checkReplies,
|
|
448
|
-
setTaskState,
|
|
449
|
-
registerDelivery,
|
|
450
|
-
scheduleCallback
|
|
451
|
-
};
|
package/dist/chunk-AILC3H3U.js
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BACKEND_URL,
|
|
3
|
-
reach
|
|
4
|
-
} from "./chunk-GU7C5H6L.js";
|
|
5
|
-
|
|
6
|
-
// src/device.ts
|
|
7
|
-
import { execFile } from "child_process";
|
|
8
|
-
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "fs";
|
|
9
|
-
import { homedir, platform } from "os";
|
|
10
|
-
import { join } from "path";
|
|
11
|
-
var AGENT_NAME = process.env.PAIGY_AGENT ?? "mcp-agent";
|
|
12
|
-
var TOKEN_PATH = join(homedir(), ".paigy", "token.json");
|
|
13
|
-
function openBrowser(url) {
|
|
14
|
-
const cmd = platform() === "darwin" ? "open" : platform() === "win32" ? "cmd" : "xdg-open";
|
|
15
|
-
const args = platform() === "win32" ? ["/c", "start", url] : [url];
|
|
16
|
-
execFile(cmd, args, () => {
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
function saveToken(token) {
|
|
20
|
-
mkdirSync(join(homedir(), ".paigy"), { recursive: true });
|
|
21
|
-
writeFileSync(TOKEN_PATH, JSON.stringify(token, null, 2) + "\n", { mode: 384 });
|
|
22
|
-
}
|
|
23
|
-
var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
24
|
-
function readToken() {
|
|
25
|
-
if (process.env.PAIGY_TOKEN) return process.env.PAIGY_TOKEN;
|
|
26
|
-
if (existsSync(TOKEN_PATH)) {
|
|
27
|
-
try {
|
|
28
|
-
return JSON.parse(readFileSync(TOKEN_PATH, "utf8")).access_token ?? "";
|
|
29
|
-
} catch {
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
return "";
|
|
33
|
-
}
|
|
34
|
-
function deleteToken() {
|
|
35
|
-
if (!existsSync(TOKEN_PATH)) return false;
|
|
36
|
-
rmSync(TOKEN_PATH);
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
39
|
-
async function revokeToken(token) {
|
|
40
|
-
const res = await reach(`${BACKEND_URL}/api/device/revoke`, {
|
|
41
|
-
method: "POST",
|
|
42
|
-
headers: { authorization: `Bearer ${token}` }
|
|
43
|
-
});
|
|
44
|
-
return res.ok;
|
|
45
|
-
}
|
|
46
|
-
async function requestCode(agent = AGENT_NAME) {
|
|
47
|
-
const res = await reach(`${BACKEND_URL}/api/device/code`, {
|
|
48
|
-
method: "POST",
|
|
49
|
-
headers: { "content-type": "application/json" },
|
|
50
|
-
body: JSON.stringify({ agent })
|
|
51
|
-
});
|
|
52
|
-
if (!res.ok) throw new Error(`/api/device/code failed: ${res.status} ${await res.text()}`);
|
|
53
|
-
return await res.json();
|
|
54
|
-
}
|
|
55
|
-
async function pollToken(deviceCode) {
|
|
56
|
-
const res = await reach(`${BACKEND_URL}/api/device/token`, {
|
|
57
|
-
method: "POST",
|
|
58
|
-
headers: { "content-type": "application/json" },
|
|
59
|
-
body: JSON.stringify({ device_code: deviceCode })
|
|
60
|
-
});
|
|
61
|
-
if (res.ok) return await res.json();
|
|
62
|
-
const body = await res.json().catch(() => ({ error: "unknown" }));
|
|
63
|
-
const err = body.error ?? "unknown";
|
|
64
|
-
if (err === "authorization_pending") return null;
|
|
65
|
-
if (err === "expired_token") throw new Error("Device code expired. Start pairing again.");
|
|
66
|
-
if (err === "access_denied") throw new Error("Access denied by user. Pairing cancelled.");
|
|
67
|
-
throw new Error(`Unexpected error from /api/device/token: ${err}`);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export {
|
|
71
|
-
AGENT_NAME,
|
|
72
|
-
TOKEN_PATH,
|
|
73
|
-
openBrowser,
|
|
74
|
-
saveToken,
|
|
75
|
-
sleep,
|
|
76
|
-
readToken,
|
|
77
|
-
deleteToken,
|
|
78
|
-
revokeToken,
|
|
79
|
-
requestCode,
|
|
80
|
-
pollToken
|
|
81
|
-
};
|
package/dist/chunk-GU7C5H6L.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
// src/http.ts
|
|
2
|
-
var BACKEND_URL = process.env.PAIGY_BACKEND_URL ?? "https://paigy.ai";
|
|
3
|
-
var NETWORK_MSG = `Can't reach ${BACKEND_URL} \u2014 the connection was blocked or dropped before an HTTP response. If this agent runs in a sandboxed environment with a network allowlist (e.g. Claude Code on the web, CI), ask the user to add the Paigy domain (paigy.ai) to the environment's allowed domains, then retry.`;
|
|
4
|
-
async function reach(url, init) {
|
|
5
|
-
try {
|
|
6
|
-
return await fetch(url, init);
|
|
7
|
-
} catch (e) {
|
|
8
|
-
throw new Error(`${NETWORK_MSG} (${e?.message ?? String(e)})`);
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export {
|
|
13
|
-
BACKEND_URL,
|
|
14
|
-
reach
|
|
15
|
-
};
|