@paigy/mcp 0.40.2 → 0.40.4

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.
@@ -10,7 +10,7 @@ import {
10
10
  saveToken,
11
11
  sleep,
12
12
  startE2ee
13
- } from "./chunk-YJEJZT56.js";
13
+ } from "./chunk-QCWXYJ64.js";
14
14
 
15
15
  // src/identity.ts
16
16
  var CLIENT_LABELS = {
@@ -74,14 +74,14 @@ var CreateGoalSchema = z2.object({
74
74
  * worked"). It could not have been: this door took no parent, so the only route was
75
75
  * create -> claim -> `update_goal`, three calls with a lease in the middle, and every agent
76
76
  * took the short one. The hierarchy has been modelled since Goals existed and had been used
77
- * ZERO times in 2,031 of them. Absent still means a root, which is what every caller meant
78
- * before this existed. The writer refuses a Goal belonging to another account. */
77
+ * ZERO times in 2,031 of them. Absent, the server judges it against the caller's open Goals
78
+ * (`apps/api/src/goal/intake.ts`). The writer refuses a Goal belonging to another account. */
79
79
  parentGoalId: z2.string().uuid().optional()
80
80
  });
81
81
  var CreateGoalToolSchema = CreateGoalSchema.extend({
82
82
  idempotencyKey: CreateGoalSchema.shape.idempotencyKey.optional().describe("Optional. One is minted per call; pass your own only so a retry lands on the same Goal.")
83
83
  }).strict();
84
- var CREATE_GOAL_DESCRIPTION = "Create a durable Goal for an outcome. Pass parentGoalId to create it UNDER an existing Goal \u2014 do that whenever the work is part of something already being tracked, rather than minting a root and leaving the relationship unsaid; absent means a root. Admission only: the owner must claim it before doing work, then update it as it advances. Returns an admission receipt with goalId, current state, revision, ownerParticipant, and the next step; no Goal content or execution lease.";
84
+ var CREATE_GOAL_DESCRIPTION = "Create a durable Goal for an outcome. Without parentGoalId it is placed against your open Goals: if one already IS this work, that Goal comes back (existing: true) and nothing new is created \u2014 continue it; if the work belongs under one, it is created there (parentGoalId in the receipt); otherwise it is a root. Pass parentGoalId yourself to put it under a specific Goal. Admission only: the owner must claim it before doing work, then update it as it advances. Returns an admission receipt with goalId, current state, revision, ownerParticipant, and the next step; no Goal content or execution lease.";
85
85
  var UpdateGoalSchema = z2.object({
86
86
  revision: z2.number().int().positive(),
87
87
  changes: z2.object({
@@ -372,9 +372,6 @@ var NotifyRequestSchema = NotifyRequestFields.superRefine((r, ctx) => {
372
372
  });
373
373
  var NotifyStatusSchema = z3.enum(["pending", "answered", "ignored"]);
374
374
  var AgentStateSchema = z3.enum(["idle", "in_progress", "completed", "needs_input"]);
375
- var SetTaskStateSchema = z3.object({
376
- state: z3.enum(["in_progress", "completed", "needs_input"])
377
- });
378
375
  var TurnSchema = z3.object({
379
376
  prompt: z3.string(),
380
377
  reply: z3.string()
@@ -504,101 +501,6 @@ var AwaitItemSchema = z3.discriminatedUnion("type", [
504
501
  })
505
502
  ]);
506
503
  var CallbackTriggerSchema = z3.enum(["on_done", "on_blocked", "scheduled"]);
507
- var PendingRepliesSchema = z3.object({
508
- replies: z3.array(
509
- z3.object({
510
- parentId: z3.string(),
511
- notificationId: z3.string(),
512
- workId: z3.string().uuid().optional(),
513
- decisionId: z3.string().uuid().optional(),
514
- answer: UserAnswerSchema,
515
- /** E2EE: the sealed answer (opaque envelope + plaintext `ignored` hint) when the
516
- * pairing is E2EE — the agent opens it and re-derives the real answer. Absent =
517
- * plaintext answer (in `answer`). See AwaitItemSchema's reply variant. */
518
- sealed: z3.lazy(() => SealedAnswerSchema).optional(),
519
- /** The call record rendered for THIS agent: the raw words the shaped answer was
520
- * mapped from, filtered to its own claims. See AwaitItemSchema's reply variant. */
521
- transcript: z3.string().optional(),
522
- /** Coverage report (#396): which declared `points` this answer addressed. */
523
- covered: z3.array(z3.string()).optional()
524
- })
525
- ),
526
- pending: z3.array(
527
- z3.object({ parentId: z3.string(), notificationId: z3.string(), createdAt: z3.string() })
528
- ),
529
- /** WHO YOU ARE on this account (field report 2026-08-28): the name and device the user
530
- * sees for this session's identity. From inside a session there was no way to find out —
531
- * `pair` with no arguments can HATCH a fresh identity, so it is not a safe probe — and an
532
- * agent that cannot tell which agent it is cannot tell whether work addressed to
533
- * "Reta" was addressed to it. Absent only for a token with no pairing behind it. */
534
- you: z3.object({ name: z3.string(), device: z3.string().nullable(), tokenId: z3.string() }).optional(),
535
- /** User-initiated requests addressed to this agent; act on them and reply via
536
- * contact on the same parentId. Keeps reappearing until you call
537
- * set_work_state on its workId (or notificationId once while bootstrapping). */
538
- requests: z3.array(
539
- z3.object({
540
- parentId: z3.string(),
541
- notificationId: z3.string(),
542
- workId: z3.string().uuid().optional(),
543
- text: z3.string(),
544
- createdAt: z3.string(),
545
- /** The user seeded this request with a past conversation — call get_thread on it
546
- * FIRST and treat the transcript as prior context (#57/#251). */
547
- contextParentId: z3.string().optional(),
548
- /** STRANDED (field report 2026-08-28): this request was addressed to ANOTHER agent on
549
- * the account — the name here — which has not been seen since it landed, so nobody
550
- * came for it. Handed to you because you are the session that is here. Take it like
551
- * any request (set_work_state claims it, reply with contact on its parentId), and say
552
- * whose it was, because the user chose that agent on purpose. */
553
- stranded: z3.string().optional()
554
- })
555
- ),
556
- /** Durable outcomes currently owned by this agent. This is the Work-native queue; flat
557
- * notification lists remain during migration so old clients keep their existing view. */
558
- work: z3.array(z3.object({
559
- workId: z3.string().uuid(),
560
- parentId: z3.string().optional(),
561
- objective: z3.string().nullable(),
562
- state: z3.enum(["active", "blocked", "waiting_external"]),
563
- blockedOn: z3.array(z3.string().uuid()),
564
- updatedAt: z3.string()
565
- })).optional(),
566
- /** Callbacks you owe the user that are now DUE (you said you'd follow up when done,
567
- * if blocked, or at a time that has passed). Re-surfaced every sweep until you
568
- * fulfill one by calling contact on its parentId. */
569
- /** Ride-alongs (RideAlongSchema): notes assigned to this agent that no wake could
570
- * reach. Same array the contact/await replies carry — one queue, every carrier. */
571
- also: z3.array(RideAlongSchema).optional(),
572
- owedCallbacks: z3.array(
573
- z3.object({ parentId: z3.string(), trigger: CallbackTriggerSchema, note: z3.string() })
574
- ),
575
- /** Work (either direction) you reported in_progress a while ago and never reported
576
- * completed — likely left half-done by this session or a prior one that crashed or
577
- * went idle. Report a real state (set_work_state) or continue the work. */
578
- stalled: z3.array(
579
- z3.object({ parentId: z3.string(), notificationId: z3.string(), title: z3.string().nullable(), startedAt: z3.string() })
580
- ),
581
- /** The queue rail (#614, pending/design.md): the same replies + requests, grouped by
582
- * thread and ordered oldest-thread-first, so you work ONE thread at a time — fold all of
583
- * a thread's `items` into a single turn rather than interleaving threads. `busy` = the
584
- * thread already has a turn in progress (younger than the stall cutoff); let it finish and
585
- * ride the next turn. `items` are that thread's replies/requests in arrival order; the
586
- * full payload for each is in the flat `replies`/`requests` arrays (matched by
587
- * notificationId). Derived, never stored — a crashed agent recomputes it exactly. */
588
- threads: z3.array(
589
- z3.object({
590
- parentId: z3.string(),
591
- busy: z3.boolean(),
592
- items: z3.array(
593
- z3.object({
594
- kind: z3.enum(["reply", "request"]),
595
- notificationId: z3.string(),
596
- at: z3.string()
597
- })
598
- )
599
- })
600
- )
601
- });
602
504
  var NotifyResponseSchema = z3.object({
603
505
  notificationId: z3.string(),
604
506
  workId: z3.string().uuid().optional(),
@@ -1001,6 +903,9 @@ var ConnectionSummarySchema = z3.object({
1001
903
  * harness availabilities + granted workspaces — the option set the phone's
1002
904
  * "new session" sheet offers. Absent for ordinary MCP agents. */
1003
905
  runtime: z3.object({
906
+ /** The @paigy/harness this host is running — a machine the self-update has not reached
907
+ * shows its age here (`apps/desktop/src/update.ts`). */
908
+ version: z3.string().optional(),
1004
909
  harnesses: z3.array(z3.object({ name: z3.string(), label: z3.string(), status: z3.string() })).optional(),
1005
910
  workspaces: z3.array(z3.string()).optional()
1006
911
  }).optional(),
@@ -2,10 +2,10 @@ import {
2
2
  AGENT_TOOLS,
3
3
  mcpInputSchema,
4
4
  serverInstructions
5
- } from "./chunk-FFI3AIZE.js";
5
+ } from "./chunk-CL5P4IVS.js";
6
6
  import {
7
7
  AGENT_NAME
8
- } from "./chunk-YJEJZT56.js";
8
+ } from "./chunk-QCWXYJ64.js";
9
9
 
10
10
  // src/toolset.ts
11
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.";
@@ -14,7 +14,7 @@ import { closeSync, existsSync, mkdirSync, openSync, readFileSync, rmSync, statS
14
14
  import { homedir } from "os";
15
15
  import { join } from "path";
16
16
  import { randomUUID as randomUUID4 } from "crypto";
17
- import { createClient } from "@supabase/supabase-js";
17
+ import { WebSocket } from "undici";
18
18
  var require2 = __sdkCreateRequire(import.meta.url);
19
19
  var __create = Object.create;
20
20
  var __defProp = Object.defineProperty;
@@ -3590,14 +3590,14 @@ var CreateGoalSchema = z2.object({
3590
3590
  * worked"). It could not have been: this door took no parent, so the only route was
3591
3591
  * create -> claim -> `update_goal`, three calls with a lease in the middle, and every agent
3592
3592
  * took the short one. The hierarchy has been modelled since Goals existed and had been used
3593
- * ZERO times in 2,031 of them. Absent still means a root, which is what every caller meant
3594
- * before this existed. The writer refuses a Goal belonging to another account. */
3593
+ * ZERO times in 2,031 of them. Absent, the server judges it against the caller's open Goals
3594
+ * (`apps/api/src/goal/intake.ts`). The writer refuses a Goal belonging to another account. */
3595
3595
  parentGoalId: z2.string().uuid().optional()
3596
3596
  });
3597
3597
  var CreateGoalToolSchema = CreateGoalSchema.extend({
3598
3598
  idempotencyKey: CreateGoalSchema.shape.idempotencyKey.optional().describe("Optional. One is minted per call; pass your own only so a retry lands on the same Goal.")
3599
3599
  }).strict();
3600
- var CREATE_GOAL_DESCRIPTION = "Create a durable Goal for an outcome. Pass parentGoalId to create it UNDER an existing Goal \u2014 do that whenever the work is part of something already being tracked, rather than minting a root and leaving the relationship unsaid; absent means a root. Admission only: the owner must claim it before doing work, then update it as it advances. Returns an admission receipt with goalId, current state, revision, ownerParticipant, and the next step; no Goal content or execution lease.";
3600
+ var CREATE_GOAL_DESCRIPTION = "Create a durable Goal for an outcome. Without parentGoalId it is placed against your open Goals: if one already IS this work, that Goal comes back (existing: true) and nothing new is created \u2014 continue it; if the work belongs under one, it is created there (parentGoalId in the receipt); otherwise it is a root. Pass parentGoalId yourself to put it under a specific Goal. Admission only: the owner must claim it before doing work, then update it as it advances. Returns an admission receipt with goalId, current state, revision, ownerParticipant, and the next step; no Goal content or execution lease.";
3601
3601
  var UpdateGoalSchema = z2.object({
3602
3602
  revision: z2.number().int().positive(),
3603
3603
  changes: z2.object({
@@ -3925,9 +3925,6 @@ function deriveAsk(req) {
3925
3925
  }
3926
3926
  var NotifyStatusSchema = z3.enum(["pending", "answered", "ignored"]);
3927
3927
  var AgentStateSchema = z3.enum(["idle", "in_progress", "completed", "needs_input"]);
3928
- var SetTaskStateSchema = z3.object({
3929
- state: z3.enum(["in_progress", "completed", "needs_input"])
3930
- });
3931
3928
  var TurnSchema = z3.object({
3932
3929
  prompt: z3.string(),
3933
3930
  reply: z3.string()
@@ -4057,101 +4054,6 @@ var AwaitItemSchema = z3.discriminatedUnion("type", [
4057
4054
  })
4058
4055
  ]);
4059
4056
  var CallbackTriggerSchema = z3.enum(["on_done", "on_blocked", "scheduled"]);
4060
- var PendingRepliesSchema = z3.object({
4061
- replies: z3.array(
4062
- z3.object({
4063
- parentId: z3.string(),
4064
- notificationId: z3.string(),
4065
- workId: z3.string().uuid().optional(),
4066
- decisionId: z3.string().uuid().optional(),
4067
- answer: UserAnswerSchema,
4068
- /** E2EE: the sealed answer (opaque envelope + plaintext `ignored` hint) when the
4069
- * pairing is E2EE — the agent opens it and re-derives the real answer. Absent =
4070
- * plaintext answer (in `answer`). See AwaitItemSchema's reply variant. */
4071
- sealed: z3.lazy(() => SealedAnswerSchema).optional(),
4072
- /** The call record rendered for THIS agent: the raw words the shaped answer was
4073
- * mapped from, filtered to its own claims. See AwaitItemSchema's reply variant. */
4074
- transcript: z3.string().optional(),
4075
- /** Coverage report (#396): which declared `points` this answer addressed. */
4076
- covered: z3.array(z3.string()).optional()
4077
- })
4078
- ),
4079
- pending: z3.array(
4080
- z3.object({ parentId: z3.string(), notificationId: z3.string(), createdAt: z3.string() })
4081
- ),
4082
- /** WHO YOU ARE on this account (field report 2026-08-28): the name and device the user
4083
- * sees for this session's identity. From inside a session there was no way to find out —
4084
- * `pair` with no arguments can HATCH a fresh identity, so it is not a safe probe — and an
4085
- * agent that cannot tell which agent it is cannot tell whether work addressed to
4086
- * "Reta" was addressed to it. Absent only for a token with no pairing behind it. */
4087
- you: z3.object({ name: z3.string(), device: z3.string().nullable(), tokenId: z3.string() }).optional(),
4088
- /** User-initiated requests addressed to this agent; act on them and reply via
4089
- * contact on the same parentId. Keeps reappearing until you call
4090
- * set_work_state on its workId (or notificationId once while bootstrapping). */
4091
- requests: z3.array(
4092
- z3.object({
4093
- parentId: z3.string(),
4094
- notificationId: z3.string(),
4095
- workId: z3.string().uuid().optional(),
4096
- text: z3.string(),
4097
- createdAt: z3.string(),
4098
- /** The user seeded this request with a past conversation — call get_thread on it
4099
- * FIRST and treat the transcript as prior context (#57/#251). */
4100
- contextParentId: z3.string().optional(),
4101
- /** STRANDED (field report 2026-08-28): this request was addressed to ANOTHER agent on
4102
- * the account — the name here — which has not been seen since it landed, so nobody
4103
- * came for it. Handed to you because you are the session that is here. Take it like
4104
- * any request (set_work_state claims it, reply with contact on its parentId), and say
4105
- * whose it was, because the user chose that agent on purpose. */
4106
- stranded: z3.string().optional()
4107
- })
4108
- ),
4109
- /** Durable outcomes currently owned by this agent. This is the Work-native queue; flat
4110
- * notification lists remain during migration so old clients keep their existing view. */
4111
- work: z3.array(z3.object({
4112
- workId: z3.string().uuid(),
4113
- parentId: z3.string().optional(),
4114
- objective: z3.string().nullable(),
4115
- state: z3.enum(["active", "blocked", "waiting_external"]),
4116
- blockedOn: z3.array(z3.string().uuid()),
4117
- updatedAt: z3.string()
4118
- })).optional(),
4119
- /** Callbacks you owe the user that are now DUE (you said you'd follow up when done,
4120
- * if blocked, or at a time that has passed). Re-surfaced every sweep until you
4121
- * fulfill one by calling contact on its parentId. */
4122
- /** Ride-alongs (RideAlongSchema): notes assigned to this agent that no wake could
4123
- * reach. Same array the contact/await replies carry — one queue, every carrier. */
4124
- also: z3.array(RideAlongSchema).optional(),
4125
- owedCallbacks: z3.array(
4126
- z3.object({ parentId: z3.string(), trigger: CallbackTriggerSchema, note: z3.string() })
4127
- ),
4128
- /** Work (either direction) you reported in_progress a while ago and never reported
4129
- * completed — likely left half-done by this session or a prior one that crashed or
4130
- * went idle. Report a real state (set_work_state) or continue the work. */
4131
- stalled: z3.array(
4132
- z3.object({ parentId: z3.string(), notificationId: z3.string(), title: z3.string().nullable(), startedAt: z3.string() })
4133
- ),
4134
- /** The queue rail (#614, pending/design.md): the same replies + requests, grouped by
4135
- * thread and ordered oldest-thread-first, so you work ONE thread at a time — fold all of
4136
- * a thread's `items` into a single turn rather than interleaving threads. `busy` = the
4137
- * thread already has a turn in progress (younger than the stall cutoff); let it finish and
4138
- * ride the next turn. `items` are that thread's replies/requests in arrival order; the
4139
- * full payload for each is in the flat `replies`/`requests` arrays (matched by
4140
- * notificationId). Derived, never stored — a crashed agent recomputes it exactly. */
4141
- threads: z3.array(
4142
- z3.object({
4143
- parentId: z3.string(),
4144
- busy: z3.boolean(),
4145
- items: z3.array(
4146
- z3.object({
4147
- kind: z3.enum(["reply", "request"]),
4148
- notificationId: z3.string(),
4149
- at: z3.string()
4150
- })
4151
- )
4152
- })
4153
- )
4154
- });
4155
4057
  var NotifyResponseSchema = z3.object({
4156
4058
  notificationId: z3.string(),
4157
4059
  workId: z3.string().uuid().optional(),
@@ -4554,6 +4456,9 @@ var ConnectionSummarySchema = z3.object({
4554
4456
  * harness availabilities + granted workspaces — the option set the phone's
4555
4457
  * "new session" sheet offers. Absent for ordinary MCP agents. */
4556
4458
  runtime: z3.object({
4459
+ /** The @paigy/harness this host is running — a machine the self-update has not reached
4460
+ * shows its age here (`apps/desktop/src/update.ts`). */
4461
+ version: z3.string().optional(),
4557
4462
  harnesses: z3.array(z3.object({ name: z3.string(), label: z3.string(), status: z3.string() })).optional(),
4558
4463
  workspaces: z3.array(z3.string()).optional()
4559
4464
  }).optional(),
@@ -5578,19 +5483,98 @@ async function runTool(name, args, opts) {
5578
5483
  throw new Error(`Unknown tool: ${name}`);
5579
5484
  }
5580
5485
  }
5486
+ var HEARTBEAT_MS = 25e3;
5487
+ var RETRY_MS = [1e3, 2e3, 5e3, 1e4, 3e4];
5488
+ var JOIN = { config: { broadcast: { self: false } } };
5489
+ var lines = /* @__PURE__ */ new Map();
5490
+ function frame(line, topic, event, payload) {
5491
+ try {
5492
+ line.ws?.send(JSON.stringify({ topic, event, payload, ref: String(++line.ref) }));
5493
+ } catch {
5494
+ }
5495
+ }
5496
+ function stop(line) {
5497
+ line.open = false;
5498
+ clearInterval(line.heart);
5499
+ clearTimeout(line.retry);
5500
+ }
5501
+ function connect(line) {
5502
+ const base = line.url.replace(/^http/, "ws").replace(/\/+$/, "");
5503
+ const ws = line.ws = new WebSocket(`${base}/realtime/v1/websocket?apikey=${encodeURIComponent(line.anonKey)}&vsn=1.0.0`);
5504
+ ws.addEventListener("open", () => {
5505
+ line.open = true;
5506
+ line.attempt = 0;
5507
+ for (const topic of line.topics.keys()) frame(line, `realtime:${topic}`, "phx_join", JOIN);
5508
+ line.heart = setInterval(() => frame(line, "phoenix", "heartbeat", {}), HEARTBEAT_MS);
5509
+ });
5510
+ ws.addEventListener("message", (e) => {
5511
+ let m;
5512
+ try {
5513
+ m = JSON.parse(String(e.data));
5514
+ } catch {
5515
+ return;
5516
+ }
5517
+ if (m.event !== "broadcast" || !m.topic?.startsWith("realtime:")) return;
5518
+ for (const l of line.topics.get(m.topic.slice("realtime:".length)) ?? []) {
5519
+ if (m.payload?.event === l.event) l.onMessage(m.payload.payload);
5520
+ }
5521
+ });
5522
+ let gone = false;
5523
+ const again = () => {
5524
+ if (gone) return;
5525
+ gone = true;
5526
+ stop(line);
5527
+ if (!line.topics.size) return;
5528
+ line.retry = setTimeout(() => connect(line), RETRY_MS[Math.min(line.attempt++, RETRY_MS.length - 1)]);
5529
+ };
5530
+ ws.addEventListener("close", again);
5531
+ ws.addEventListener("error", again);
5532
+ }
5533
+ function subscribeRealtime(args) {
5534
+ const key = `${args.url} ${args.anonKey}`;
5535
+ let line = lines.get(key);
5536
+ if (!line) lines.set(key, line = { url: args.url, anonKey: args.anonKey, open: false, attempt: 0, ref: 0, topics: /* @__PURE__ */ new Map() });
5537
+ let heard = line.topics.get(args.topic);
5538
+ if (!heard) {
5539
+ line.topics.set(args.topic, heard = /* @__PURE__ */ new Set());
5540
+ if (line.open) frame(line, `realtime:${args.topic}`, "phx_join", JOIN);
5541
+ }
5542
+ const me = { event: args.event, onMessage: args.onMessage };
5543
+ heard.add(me);
5544
+ if (!line.ws) connect(line);
5545
+ return {
5546
+ close: () => {
5547
+ if (!heard.delete(me) || heard.size) return;
5548
+ line.topics.delete(args.topic);
5549
+ if (line.topics.size) {
5550
+ if (line.open) frame(line, `realtime:${args.topic}`, "phx_leave", {});
5551
+ return;
5552
+ }
5553
+ lines.delete(key);
5554
+ stop(line);
5555
+ try {
5556
+ line.ws?.close();
5557
+ } catch {
5558
+ }
5559
+ }
5560
+ };
5561
+ }
5581
5562
  async function subscribeWake(onNudge, opts = {}) {
5582
5563
  const cfg = await registerDelivery("self_hosted", opts);
5583
5564
  const { url, anonKey } = cfg.realtime;
5584
5565
  const channel = wakeChannel(cfg.tokenId);
5585
- const sb = createClient(url, anonKey, { auth: { persistSession: false } });
5586
- const ch = sb.channel(channel).on("broadcast", { event: WAKE_EVENT }, (msg) => onNudge(msg.payload ?? {}));
5587
- ch.subscribe();
5566
+ const ch = subscribeRealtime({
5567
+ url,
5568
+ anonKey,
5569
+ topic: channel,
5570
+ event: WAKE_EVENT,
5571
+ onMessage: (payload) => onNudge(payload ?? {})
5572
+ });
5588
5573
  return {
5589
5574
  tokenId: cfg.tokenId,
5590
5575
  channel,
5591
5576
  close: async () => {
5592
- await sb.removeChannel(ch).catch(() => {
5593
- });
5577
+ ch.close();
5594
5578
  await registerDelivery("poll", opts).catch(() => {
5595
5579
  });
5596
5580
  }
package/dist/enable.js CHANGED
@@ -2,9 +2,9 @@
2
2
  import {
3
3
  PAIGY_TOOL_IDS,
4
4
  enablePaigyTools
5
- } from "./chunk-647HS22P.js";
6
- import "./chunk-FFI3AIZE.js";
7
- import "./chunk-YJEJZT56.js";
5
+ } from "./chunk-IXVUUHTY.js";
6
+ import "./chunk-CL5P4IVS.js";
7
+ import "./chunk-QCWXYJ64.js";
8
8
 
9
9
  // src/enable.ts
10
10
  function main() {
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  resolvePairing,
6
6
  startPairing,
7
7
  suggestedAgentName
8
- } from "./chunk-BUTCP2ED.js";
8
+ } from "./chunk-4KN5TGBJ.js";
9
9
  import {
10
10
  ENABLE_COMMAND,
11
11
  OnboardSchema,
@@ -16,8 +16,8 @@ import {
16
16
  autoConfigureClients,
17
17
  claudeInstallHint,
18
18
  paigyToolsAllowlisted
19
- } from "./chunk-647HS22P.js";
20
- import "./chunk-FFI3AIZE.js";
19
+ } from "./chunk-IXVUUHTY.js";
20
+ import "./chunk-CL5P4IVS.js";
21
21
  import {
22
22
  clearSurface,
23
23
  writeSurface
@@ -38,7 +38,7 @@ import {
38
38
  setIdentity,
39
39
  slotName,
40
40
  whoAmI
41
- } from "./chunk-YJEJZT56.js";
41
+ } from "./chunk-QCWXYJ64.js";
42
42
 
43
43
  // src/index.ts
44
44
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
package/dist/listen.js CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  entryWords
4
- } from "./chunk-FFI3AIZE.js";
4
+ } from "./chunk-CL5P4IVS.js";
5
5
  import {
6
6
  checkReplies,
7
7
  getGoal,
8
8
  subscribeWake
9
- } from "./chunk-YJEJZT56.js";
9
+ } from "./chunk-QCWXYJ64.js";
10
10
 
11
11
  // src/listen.ts
12
12
  import { spawn } from "child_process";
package/dist/onboard.js CHANGED
@@ -3,13 +3,13 @@ import {
3
3
  resolvePairing,
4
4
  startPairing,
5
5
  suggestedAgentName
6
- } from "./chunk-BUTCP2ED.js";
6
+ } from "./chunk-4KN5TGBJ.js";
7
7
  import {
8
8
  autoConfigureClients,
9
9
  claudeInstallHint,
10
10
  openBrowser
11
- } from "./chunk-647HS22P.js";
12
- import "./chunk-FFI3AIZE.js";
11
+ } from "./chunk-IXVUUHTY.js";
12
+ import "./chunk-CL5P4IVS.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-YJEJZT56.js";
23
+ } from "./chunk-QCWXYJ64.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
  AGENT_NAME
4
- } from "./chunk-YJEJZT56.js";
4
+ } from "./chunk-QCWXYJ64.js";
5
5
 
6
6
  // src/slot.ts
7
7
  process.stdout.write(AGENT_NAME);
@@ -9,7 +9,7 @@ import {
9
9
  readToken,
10
10
  sessionSlot,
11
11
  slotName
12
- } from "./chunk-YJEJZT56.js";
12
+ } from "./chunk-QCWXYJ64.js";
13
13
 
14
14
  // src/statusline.ts
15
15
  import { mkdirSync, readFileSync, realpathSync, writeFileSync } from "fs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paigy/mcp",
3
- "version": "0.40.2",
3
+ "version": "0.40.4",
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,28 +24,28 @@
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
+ },
27
34
  "dependencies": {
28
35
  "@modelcontextprotocol/sdk": "^1.0.4",
29
- "@supabase/supabase-js": "^2.47.10",
30
36
  "qrcode-generator": "^2.0.4",
31
37
  "undici": "^6.27.0",
32
38
  "zod": "^3.24.1",
33
39
  "zod-to-json-schema": "^3.24.1"
34
40
  },
35
41
  "devDependencies": {
42
+ "@paigy/crypto": "workspace:*",
43
+ "@paigy/schema": "workspace:*",
44
+ "@paigy/sdk": "workspace:*",
36
45
  "@types/node": "^22.0.0",
37
46
  "@types/qrcode-generator": "^1.0.6",
38
47
  "tsup": "^8.3.5",
39
48
  "typescript": "^5.7.2",
40
- "vitest": "^2.1.8",
41
- "@paigy/crypto": "0.0.0",
42
- "@paigy/sdk": "0.2.1",
43
- "@paigy/schema": "0.0.0"
44
- },
45
- "scripts": {
46
- "build": "tsup",
47
- "dev": "tsup --watch",
48
- "typecheck": "tsc --noEmit",
49
- "test": "vitest run"
49
+ "vitest": "^2.1.8"
50
50
  }
51
- }
51
+ }