@paigy/mcp 0.40.16 → 0.40.19

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/index.js CHANGED
@@ -1,11 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  clearPairing,
4
+ identify,
4
5
  joinBackgroundPair,
5
6
  resolvePairing,
6
7
  startPairing,
7
8
  suggestedAgentName
8
- } from "./chunk-OGTH55QH.js";
9
+ } from "./chunk-TRMYDJ5H.js";
9
10
  import {
10
11
  ENABLE_COMMAND,
11
12
  OnboardSchema,
@@ -14,11 +15,11 @@ import {
14
15
  SERVER_INSTRUCTIONS,
15
16
  TOOLS,
16
17
  paigyToolsAllowlisted
17
- } from "./chunk-JWMR6K6D.js";
18
+ } from "./chunk-76ILN3YV.js";
18
19
  import {
19
20
  decideListen,
20
21
  listenerAlive
21
- } from "./chunk-SFGGZLVO.js";
22
+ } from "./chunk-HGXXGOGG.js";
22
23
  import {
23
24
  clearSurface,
24
25
  writeSurface
@@ -36,10 +37,9 @@ import {
36
37
  runTool,
37
38
  saveToken,
38
39
  sessionId,
39
- setIdentity,
40
40
  slotName,
41
41
  whoAmI
42
- } from "./chunk-6OBUH2FB.js";
42
+ } from "./chunk-VYWIPFEY.js";
43
43
 
44
44
  // src/index.ts
45
45
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
@@ -177,7 +177,7 @@ async function hatchUnderDevice(name, voice) {
177
177
  const minted = await hatch(name ?? suggestedAgentName2() ?? "Agent", voice ?? null);
178
178
  const dt = { ok: true, access_token: minted.token, name: minted.name, device: null };
179
179
  saveToken(dt);
180
- return dt;
180
+ return minted.message ? { ...dt, message: minted.message } : dt;
181
181
  } catch (e) {
182
182
  return { why: "credential-rejected", detail: String(e?.message ?? e).slice(0, 200) };
183
183
  } finally {
@@ -191,7 +191,7 @@ async function runPair(device_code, name, voice, note) {
191
191
  if ("ok" in dt) return pairedResult(
192
192
  dt,
193
193
  void 0,
194
- "Hatched instantly under this device's credential \u2014 no code needed. " + (name ? "" : `You were given a default name ("${dt.name}") \u2014 the user never chose it, so don't announce it as their agent's identity. They can rename it in the app, or you can re-call pair with { name, voice }.`)
194
+ "Hatched instantly under this device's credential \u2014 no code needed. " + (dt.message ? `${dt.message} Set it with onboard({ name }).` : name ? "" : `You were given a default name ("${dt.name}") \u2014 the user never chose it, so don't announce it as their agent's identity. They can rename it in the app, or you can re-call pair with { name, voice }.`)
195
195
  );
196
196
  miss = dt;
197
197
  }
@@ -246,24 +246,16 @@ async function handleTool(request, signal) {
246
246
  const slot = agentName();
247
247
  const secret = readToken();
248
248
  if (secret) {
249
- let who = await whoAmI().catch(() => null);
249
+ const who = await whoAmI().catch(() => null);
250
250
  if (who) {
251
- let renamed = false;
252
- if (name || voice) {
253
- try {
254
- who = await setIdentity({ ...name ? { name } : {}, ...voice ? { voice } : {} });
255
- renamed = true;
256
- } catch {
257
- }
258
- }
251
+ const me = await identify(who, { ...name ? { name } : {}, ...voice ? { voice } : {} });
259
252
  const allowlisted = paigyToolsAllowlisted(scope ?? "user");
260
- const display = who?.name ?? slotName(slot) ?? slot;
261
253
  return {
262
254
  content: [{ type: "text", text: JSON.stringify({
263
255
  status: "ready",
264
256
  slot,
265
- name: display,
266
- voice: who?.voice ?? null,
257
+ name: me.name,
258
+ voice: me.voice,
267
259
  tools_allowlisted: allowlisted,
268
260
  ...allowlisted ? {} : {
269
261
  enable_tool_ids: PAIGY_TOOL_IDS,
@@ -277,7 +269,7 @@ async function handleTool(request, signal) {
277
269
  rename: "Call onboard again with { name } (and optionally { voice }) to change it.",
278
270
  unpair: "Call the `unpair` tool to disconnect this agent from the account."
279
271
  },
280
- message: renamed ? `Renamed \u2014 this agent is "${display}" now.` : `Already set up as "${display}". Ask the user if they want to rename it or unpair; otherwise carry on.`
272
+ message: me.message
281
273
  }) }]
282
274
  };
283
275
  }
package/dist/listen.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  entryWords,
4
4
  removeListenMark,
5
5
  writeListenMark
6
- } from "./chunk-SFGGZLVO.js";
6
+ } from "./chunk-HGXXGOGG.js";
7
7
  import {
8
8
  agentName,
9
9
  checkReplies,
@@ -11,7 +11,7 @@ import {
11
11
  getGoal,
12
12
  slotName,
13
13
  subscribeWake
14
- } from "./chunk-6OBUH2FB.js";
14
+ } from "./chunk-VYWIPFEY.js";
15
15
 
16
16
  // src/listen.ts
17
17
  import { spawn } from "child_process";
@@ -136,11 +136,13 @@ function brief(waiting, reason, as, goalId) {
136
136
  const review = waiting.review ?? [];
137
137
  const named = (goalId ? review.find((g) => g.goalId === goalId) : void 0) ?? review[0];
138
138
  const fresh = review.length ? ` \xB7 new on ${review.length === 1 ? "your Goal" : `${review.length} of your Goals`}, first ${named.goalId} ("${named.title}"): claim_goal to read it` : "";
139
- if (!lead) return `Paigy \xB7 ${reason === "boot" ? `listening as ${as}` : reason}${fresh || " \xB7 nothing waiting"}${stalled}`;
139
+ const assigned = waiting.assigned ?? [];
140
+ const mine = assigned.length ? ` \xB7 assigned to you: ${assigned.length === 1 ? "1 Goal" : `${assigned.length} Goals`}, first ${assigned[0].goalId} ("${assigned[0].title}"): claim_goal({goalId}) to start it` : "";
141
+ if (!lead) return `Paigy \xB7 ${reason === "boot" ? `listening as ${as}` : reason}${mine}${fresh || (mine ? "" : " \xB7 nothing waiting")}${stalled}`;
140
142
  const said = saidIn(lead) || ("about" in lead ? lead.about : "");
141
143
  const shown = said.length > 160 ? `${said.slice(0, 160)}\u2026` : said;
142
144
  const goal = waiting.goal?.goalId ?? lead.goalIds[0];
143
- return `Paigy \xB7 ${reason} \xB7 ${waiting.deliveries.length} waiting \xB7 lead ${lead.deliveryId} on Goal ${goal}: "${shown}"${fresh}${stalled}`;
145
+ return `Paigy \xB7 ${reason} \xB7 ${waiting.deliveries.length} waiting \xB7 lead ${lead.deliveryId} on Goal ${goal}: "${shown}"${mine}${fresh}${stalled}`;
144
146
  }
145
147
  function launchEnv(waiting, reason, goalId) {
146
148
  const env = { PAIGY_WORK: JSON.stringify(waiting), PAIGY_EVENT: reason };
@@ -157,16 +159,16 @@ function launchEnv(waiting, reason, goalId) {
157
159
  async function sweep(reason, goalId) {
158
160
  try {
159
161
  const cmd = process.env.PAIGY_ON_WAKE;
160
- const { deliveries: rows, stalled, review } = await checkReplies();
162
+ const { deliveries: rows, stalled, review, assigned } = await checkReplies();
161
163
  const lead = leadOf(rows, goalId);
162
- const full = lead ? await contact({ deliveryId: lead.deliveryId }, { waits: false }).then((d) => "recorded" in d ? null : d).catch(() => null) : null;
164
+ const full = lead ? await contact({ deliveryId: lead.deliveryId }, { waits: false }).then((d) => "sent" in d ? null : d).catch(() => null) : null;
163
165
  const deliveries = rows.map((d) => d === lead && full ? full : d);
164
166
  const leadGoalId = lead?.goalIds[0];
165
167
  const goal = leadGoalId ? await getGoal(leadGoalId).then((g) => ({ goalId: leadGoalId, progress: g.progress })).catch(() => null) : null;
166
- const waiting = { deliveries, goal, ...stalled?.length ? { stalled } : {}, ...review?.length ? { review } : {} };
168
+ const waiting = { deliveries, goal, ...stalled?.length ? { stalled } : {}, ...review?.length ? { review } : {}, ...assigned?.length ? { assigned } : {} };
167
169
  if (BRIEF) line(brief(waiting, reason, listeningAs(), goalId));
168
170
  else emit({ type: "sweep", reason, ...goalId ? { about: goalId } : {}, ...waiting });
169
- if (cmd && (deliveries.length || waiting.review?.length || reason === "boot" && waiting.stalled?.length)) {
171
+ if (cmd && (deliveries.length || waiting.review?.length || waiting.assigned?.length || reason === "boot" && waiting.stalled?.length)) {
170
172
  spawn(cmd, { shell: true, stdio: "inherit", env: { ...process.env, ...launchEnv(waiting, reason, goalId) } });
171
173
  }
172
174
  } catch (e) {
@@ -174,8 +176,17 @@ async function sweep(reason, goalId) {
174
176
  else emit({ type: "error", reason, message: e.message });
175
177
  }
176
178
  }
179
+ function catchUpReason(joins) {
180
+ return joins > 1 ? "resubscribed" : null;
181
+ }
177
182
  async function main() {
178
- const sub = await subscribeWake((nudge) => void sweep(`wake:${nudge.kind ?? "?"}`, nudge.parentId), { release: RELEASE });
183
+ const sub = await subscribeWake((nudge) => void sweep(`wake:${nudge.kind ?? "?"}`, nudge.parentId), {
184
+ release: RELEASE,
185
+ onJoined: (joins) => {
186
+ const reason = catchUpReason(joins);
187
+ if (reason) void sweep(reason);
188
+ }
189
+ });
179
190
  const slot = agentName();
180
191
  writeListenMark(slot, process.pid);
181
192
  process.on("exit", () => removeListenMark(slot));
@@ -214,6 +225,7 @@ if (isEntry()) {
214
225
  }
215
226
  export {
216
227
  brief,
228
+ catchUpReason,
217
229
  launchEnv,
218
230
  leadOf,
219
231
  listenOptions,
package/dist/onboard.js CHANGED
@@ -3,13 +3,13 @@ import {
3
3
  resolvePairing,
4
4
  startPairing,
5
5
  suggestedAgentName
6
- } from "./chunk-OGTH55QH.js";
6
+ } from "./chunk-TRMYDJ5H.js";
7
7
  import {
8
8
  autoConfigureClients,
9
9
  claudeInstallHint,
10
10
  openBrowser
11
- } from "./chunk-JWMR6K6D.js";
12
- import "./chunk-SFGGZLVO.js";
11
+ } from "./chunk-76ILN3YV.js";
12
+ import "./chunk-HGXXGOGG.js";
13
13
  import {
14
14
  TOKEN_PATH,
15
15
  agentName,
@@ -20,7 +20,7 @@ import {
20
20
  saveToken,
21
21
  setIdentity,
22
22
  whoAmI
23
- } from "./chunk-6OBUH2FB.js";
23
+ } from "./chunk-VYWIPFEY.js";
24
24
 
25
25
  // src/onboard.ts
26
26
  function reportRegistered() {
package/dist/slot.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  agentName
4
- } from "./chunk-6OBUH2FB.js";
4
+ } from "./chunk-VYWIPFEY.js";
5
5
 
6
6
  // src/slot.ts
7
7
  process.stdout.write(agentName());
package/dist/stalled.js CHANGED
@@ -4,26 +4,33 @@
4
4
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
5
5
  import { homedir } from "os";
6
6
  import { join } from "path";
7
- function stopReply(stalled) {
7
+ function agentFlag(argv) {
8
+ const inline = argv.find((arg) => arg.startsWith("--agent="));
9
+ if (inline) return inline.slice("--agent=".length) || null;
10
+ const at = argv.indexOf("--agent");
11
+ if (at === -1) return null;
12
+ return argv[at + 1] ?? null;
13
+ }
14
+ function stopReply(stalled, event = "Stop") {
8
15
  if (!stalled.length) return null;
9
16
  const list = stalled.slice(0, 8).map((g) => `"${g.title}" (${g.goalId})`).join(", ");
10
17
  const more = stalled.length > 8 ? ` and ${stalled.length - 8} more` : "";
11
- return {
12
- decision: "block",
13
- reason: `Before you stop: ${stalled.length} of your Paigy Goals have had no progress for 3 days: ${list}${more}. For each, update_goal with progress, finish it, or cancel it.`
14
- };
18
+ const reason = `Before you stop: ${stalled.length} of your Paigy Goals have had no progress for 3 days: ${list}${more}. For each, update_goal with progress, finish it, or cancel it.`;
19
+ return event === "AfterAgent" ? { decision: "block", reason, systemMessage: reason } : { decision: "block", reason };
15
20
  }
16
21
  async function main() {
17
22
  const input = JSON.parse(readFileSync(0, "utf8") || "{}");
18
23
  if (input.stop_hook_active) return;
19
24
  const session = input.session_id ?? "";
20
25
  if (session) process.env.PAIGY_SESSION_ID = session;
26
+ const slot = agentFlag(process.argv);
27
+ if (slot && !process.env.PAIGY_AGENT) process.env.PAIGY_AGENT = slot;
21
28
  const day = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
22
29
  const dir = join(homedir(), ".paigy", "stalled-reminded");
23
30
  const mark = join(dir, `${session || "session"}-${day}`);
24
31
  if (existsSync(mark)) return;
25
- const { checkReplies } = await import("./dist-6F22VALF.js");
26
- const reply = stopReply((await checkReplies()).stalled ?? []);
32
+ const { checkReplies } = await import("./dist-GJOOJ4FR.js");
33
+ const reply = stopReply((await checkReplies()).stalled ?? [], input.hook_event_name ?? "Stop");
27
34
  if (!reply) return;
28
35
  mkdirSync(dir, { recursive: true });
29
36
  writeFileSync(mark, "");
@@ -31,5 +38,6 @@ async function main() {
31
38
  }
32
39
  if (process.argv[1] && /stalled(\.[jt]s)?$/.test(process.argv[1])) main().catch(() => void 0);
33
40
  export {
41
+ agentFlag,
34
42
  stopReply
35
43
  };
@@ -7,7 +7,7 @@ import {
7
7
  readToken,
8
8
  sessionSlot,
9
9
  slotName
10
- } from "./chunk-6OBUH2FB.js";
10
+ } from "./chunk-VYWIPFEY.js";
11
11
 
12
12
  // src/statusline.ts
13
13
  import { realpathSync } from "fs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paigy/mcp",
3
- "version": "0.40.16",
3
+ "version": "0.40.19",
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",