@paigy/mcp 0.40.25 → 0.40.27
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 +28 -18
- package/dist/{chunk-EJYXBEWN.js → chunk-4C6SDQ7A.js} +887 -661
- package/dist/{chunk-UAVXYNLV.js → chunk-A5FYZK6P.js} +18 -36
- package/dist/{chunk-2ROD77AW.js → chunk-UQDA7X3W.js} +3 -3
- package/dist/{chunk-GHSB2VP6.js → chunk-X3GTDW5G.js} +728 -539
- package/dist/{dist-NMHU2UNG.js → dist-N6ZJUJV7.js} +5 -7
- package/dist/enable.js +5 -5
- package/dist/index.js +57 -54
- package/dist/listen.js +8 -7
- package/dist/onboard.js +6 -6
- package/dist/slot.js +1 -1
- package/dist/stalled.js +2 -2
- package/dist/statusline.js +1 -1
- package/package.json +1 -1
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
acknowledge,
|
|
18
18
|
agentName,
|
|
19
19
|
authToken,
|
|
20
|
-
|
|
20
|
+
checkActivity,
|
|
21
21
|
claimSessionEnds,
|
|
22
22
|
claimSessions,
|
|
23
23
|
contact,
|
|
@@ -40,6 +40,7 @@ import {
|
|
|
40
40
|
pollToken,
|
|
41
41
|
reach,
|
|
42
42
|
reachAs,
|
|
43
|
+
readDelivery,
|
|
43
44
|
readSlot,
|
|
44
45
|
readToken,
|
|
45
46
|
receive,
|
|
@@ -61,12 +62,10 @@ import {
|
|
|
61
62
|
slotName,
|
|
62
63
|
submitTriage,
|
|
63
64
|
subscribeWake,
|
|
64
|
-
updateGoal,
|
|
65
65
|
updateSlot,
|
|
66
66
|
whoAmI,
|
|
67
|
-
whoIsWorking,
|
|
68
67
|
withCodexEnv
|
|
69
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-4C6SDQ7A.js";
|
|
70
69
|
export {
|
|
71
70
|
AGENT_TOOLS,
|
|
72
71
|
AGENT_TOOL_NAMES,
|
|
@@ -86,7 +85,7 @@ export {
|
|
|
86
85
|
acknowledge,
|
|
87
86
|
agentName,
|
|
88
87
|
authToken,
|
|
89
|
-
|
|
88
|
+
checkActivity,
|
|
90
89
|
claimSessionEnds,
|
|
91
90
|
claimSessions,
|
|
92
91
|
contact,
|
|
@@ -109,6 +108,7 @@ export {
|
|
|
109
108
|
pollToken,
|
|
110
109
|
reach,
|
|
111
110
|
reachAs,
|
|
111
|
+
readDelivery,
|
|
112
112
|
readSlot,
|
|
113
113
|
readToken,
|
|
114
114
|
receive,
|
|
@@ -130,9 +130,7 @@ export {
|
|
|
130
130
|
slotName,
|
|
131
131
|
submitTriage,
|
|
132
132
|
subscribeWake,
|
|
133
|
-
updateGoal,
|
|
134
133
|
updateSlot,
|
|
135
134
|
whoAmI,
|
|
136
|
-
whoIsWorking,
|
|
137
135
|
withCodexEnv
|
|
138
136
|
};
|
package/dist/enable.js
CHANGED
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
PAIGY_TOOL_IDS,
|
|
4
4
|
enablePaigyTools,
|
|
5
5
|
installSessionListening
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-A5FYZK6P.js";
|
|
7
|
+
import "./chunk-X3GTDW5G.js";
|
|
8
|
+
import "./chunk-4C6SDQ7A.js";
|
|
9
9
|
|
|
10
10
|
// src/enable.ts
|
|
11
11
|
function main() {
|
|
@@ -16,14 +16,14 @@ function main() {
|
|
|
16
16
|
if (arg === "-h" || arg === "--help") {
|
|
17
17
|
console.log("usage: paigy-enable-tools [--scope user|project]");
|
|
18
18
|
console.log("");
|
|
19
|
-
console.log("Allowlist Paigy's
|
|
19
|
+
console.log("Allowlist Paigy's tools in Claude Code so they run without an");
|
|
20
20
|
console.log("approval prompt each time \u2014 an unattended session can't stall on a dialog.");
|
|
21
21
|
console.log("");
|
|
22
22
|
console.log(" --scope user ~/.claude/settings.json (default) \u2014 every project");
|
|
23
23
|
console.log(" --scope project ./.claude/settings.json \u2014 just this repo");
|
|
24
24
|
console.log("");
|
|
25
25
|
console.log(`Adds: ${PAIGY_TOOL_IDS.join(", ")}`);
|
|
26
|
-
console.log("
|
|
26
|
+
console.log("Safe to re-run.");
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
29
29
|
if (arg === "--scope") {
|
package/dist/index.js
CHANGED
|
@@ -9,22 +9,22 @@ import {
|
|
|
9
9
|
resolvePairing,
|
|
10
10
|
startPairing,
|
|
11
11
|
suggestedAgentName
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-UQDA7X3W.js";
|
|
13
13
|
import {
|
|
14
|
+
ConfigureSchema,
|
|
14
15
|
ENABLE_COMMAND,
|
|
15
|
-
OnboardSchema,
|
|
16
16
|
PAIGY_TOOL_IDS,
|
|
17
|
-
PairSchema,
|
|
18
17
|
SERVER_INSTRUCTIONS,
|
|
19
18
|
TOOLS,
|
|
20
19
|
paigyToolsAllowlisted
|
|
21
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-A5FYZK6P.js";
|
|
22
21
|
import {
|
|
23
22
|
decideListen,
|
|
24
23
|
existingListener,
|
|
24
|
+
harnessDriven,
|
|
25
25
|
listenerKey,
|
|
26
26
|
wakeStatusPath
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-X3GTDW5G.js";
|
|
28
28
|
import {
|
|
29
29
|
clearSurface,
|
|
30
30
|
writeSurface
|
|
@@ -45,7 +45,7 @@ import {
|
|
|
45
45
|
setClient,
|
|
46
46
|
slotName,
|
|
47
47
|
whoAmI
|
|
48
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-4C6SDQ7A.js";
|
|
49
49
|
|
|
50
50
|
// src/index.ts
|
|
51
51
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -90,6 +90,12 @@ function traceTheTransport(transport2, log) {
|
|
|
90
90
|
};
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
// src/unpaired.ts
|
|
94
|
+
function afterUnpaired(hatched, deviceCredential) {
|
|
95
|
+
if (hatched && "ok" in hatched) return "retry";
|
|
96
|
+
return deviceCredential ? "unidentified" : "pair";
|
|
97
|
+
}
|
|
98
|
+
|
|
93
99
|
// src/index.ts
|
|
94
100
|
var JOIN_CAP_MS = 45e3;
|
|
95
101
|
function pairedResult(token, sas, note) {
|
|
@@ -106,7 +112,7 @@ function pairedResult(token, sas, note) {
|
|
|
106
112
|
if (note) base.note = note;
|
|
107
113
|
base.enable_tool_ids = PAIGY_TOOL_IDS;
|
|
108
114
|
base.enable_command = ENABLE_COMMAND;
|
|
109
|
-
base.enable_prompt = "REQUIRED \u2014 before you do anything else, print `enable_command` to the user and say: \"Run this to let Paigy's tools work without an approval prompt each time \u2014 it only allowlists
|
|
115
|
+
base.enable_prompt = "REQUIRED \u2014 before you do anything else, print `enable_command` to the user and say: \"Run this to let Paigy's tools work without an approval prompt each time \u2014 it only allowlists Paigy's own tools.\" Print it every time you pair; don't skip it.";
|
|
110
116
|
base.enable_apply = "You cannot apply this yourself, and must not try: it writes YOUR OWN permission allowlist, which hosts block as privilege escalation no matter what the user said here. PRINT the command and move on \u2014 don't wait for them to run it, and don't re-ask. Paigy's tools still work meanwhile; they just prompt for approval each time until the user runs it. If the host isn't Claude Code, tell them to add `enable_tool_ids` to that tool's own allowlist instead, merging \u2014 never clobbering.";
|
|
111
117
|
return { content: [{ type: "text", text: JSON.stringify(base) }] };
|
|
112
118
|
}
|
|
@@ -123,7 +129,7 @@ Check it matches the code on the phone, then type it there to confirm.` },
|
|
|
123
129
|
sas,
|
|
124
130
|
device_code,
|
|
125
131
|
user_message: `# ${sas}`,
|
|
126
|
-
verify_message: `STOP HERE: end your turn now with \`user_message\` (the bare code) as your entire reply \u2014 do NOT call
|
|
132
|
+
verify_message: `STOP HERE: end your turn now with \`user_message\` (the bare code) as your entire reply \u2014 do NOT call configure again in this same turn, or the code text is dropped before the user sees it. This is the verification code they compare + type on their phone; it REPLACES any earlier one. Poll for their confirmation by calling configure with this device_code on your NEXT turn.`,
|
|
127
133
|
message: "No token is issued until the user confirms the code match on their phone (E2EE account)."
|
|
128
134
|
})
|
|
129
135
|
}
|
|
@@ -145,7 +151,7 @@ function renderPairOutcome(outcome, device_code) {
|
|
|
145
151
|
text: JSON.stringify({
|
|
146
152
|
status: "pending",
|
|
147
153
|
device_code,
|
|
148
|
-
message: "Still awaiting approval \u2014 the user hasn't entered the code yet. Call
|
|
154
|
+
message: "Still awaiting approval \u2014 the user hasn't entered the code yet. Call configure again with this device_code RIGHT NOW to keep waiting; each call returns after ~45s so it can't be killed by a host tool-call timeout. Nothing is lost between calls: the code stays valid and approval keeps being polled in the background, so a re-call returns the instant they approve."
|
|
149
155
|
})
|
|
150
156
|
}]
|
|
151
157
|
};
|
|
@@ -155,7 +161,7 @@ function unidentifiedResult() {
|
|
|
155
161
|
return { isError: true, content: [{ type: "text", text: JSON.stringify({
|
|
156
162
|
error: "no_identity",
|
|
157
163
|
slot: agentName(),
|
|
158
|
-
message: `This session has no Paigy identity yet, so nothing was sent \u2014 it will not speak as another session. This machine holds a device credential but hatching under it just failed (it may have been revoked), so call \`
|
|
164
|
+
message: `This session has no Paigy identity yet, so nothing was sent \u2014 it will not speak as another session. This machine holds a device credential but hatching under it just failed (it may have been revoked), so call \`configure\` (no arguments) to set this session up, then retry \u2014 it re-hatches if the credential recovered and runs the code ceremony if it didn't. To reuse an existing identity instead, start the session with PAIGY_AGENT set to its slot (${listSlots().filter((s) => s !== "Desktop").join(", ") || "none yet"}).`
|
|
159
165
|
}) }] };
|
|
160
166
|
}
|
|
161
167
|
function pairStartResult(start, loggedOut) {
|
|
@@ -197,7 +203,7 @@ This session isn't on a connected computer, so it asks by code.`;
|
|
|
197
203
|
expires_in: start.expiresIn,
|
|
198
204
|
qr: ascii,
|
|
199
205
|
user_message: userMessage,
|
|
200
|
-
message: "REQUIRED: print user_message for the user \u2014 the LINK is the primary action, the code is the fallback, and `qr` is there for a phone when they ask. Then call
|
|
206
|
+
message: "REQUIRED: print user_message for the user \u2014 the LINK is the primary action, the code is the fallback, and `qr` is there for a phone when they ask. Then call configure again with device_code to collect approval. Do not open a browser yourself."
|
|
201
207
|
}) }
|
|
202
208
|
] };
|
|
203
209
|
}
|
|
@@ -234,7 +240,7 @@ async function runPair(device_code, name, voice, note) {
|
|
|
234
240
|
if ("ok" in dt) return pairedResult(
|
|
235
241
|
dt,
|
|
236
242
|
void 0,
|
|
237
|
-
"Hatched instantly under this device's credential \u2014 no code needed. " + (dt.message ? `${dt.message} Set it with
|
|
243
|
+
"Hatched instantly under this device's credential \u2014 no code needed. " + (dt.message ? `${dt.message} Set it with configure({ 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 call configure with { name, voice }.`)
|
|
238
244
|
);
|
|
239
245
|
miss = dt;
|
|
240
246
|
}
|
|
@@ -253,10 +259,11 @@ server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
|
253
259
|
return await handleTool(request, extra?.signal);
|
|
254
260
|
} catch (e) {
|
|
255
261
|
if (e instanceof UnpairedError) {
|
|
256
|
-
const IDENTITY_TOOLS = /* @__PURE__ */ new Set(["
|
|
262
|
+
const IDENTITY_TOOLS = /* @__PURE__ */ new Set(["configure"]);
|
|
257
263
|
const hatched = IDENTITY_TOOLS.has(request.params.name) ? null : await hatchUnderDevice();
|
|
258
|
-
|
|
259
|
-
if (
|
|
264
|
+
const next = afterUnpaired(hatched, listSlots().includes("Desktop"));
|
|
265
|
+
if (next === "retry") return await handleTool(request, extra?.signal);
|
|
266
|
+
if (next === "unidentified") return unidentifiedResult();
|
|
260
267
|
return pairStartResult(await startPairing(suggestedAgentName2()));
|
|
261
268
|
}
|
|
262
269
|
throw e;
|
|
@@ -265,26 +272,46 @@ server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
|
265
272
|
function suggestedAgentName2() {
|
|
266
273
|
return suggestedAgentName(server.getClientVersion?.()?.name);
|
|
267
274
|
}
|
|
275
|
+
async function logOutResult() {
|
|
276
|
+
const token = readToken();
|
|
277
|
+
let revoked = false;
|
|
278
|
+
if (token) {
|
|
279
|
+
try {
|
|
280
|
+
revoked = await revokeToken(token);
|
|
281
|
+
} catch {
|
|
282
|
+
revoked = false;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
const removed = deleteToken();
|
|
286
|
+
clearPairing();
|
|
287
|
+
return {
|
|
288
|
+
content: [{
|
|
289
|
+
type: "text",
|
|
290
|
+
text: JSON.stringify({
|
|
291
|
+
ok: true,
|
|
292
|
+
revoked,
|
|
293
|
+
removed,
|
|
294
|
+
message: token ? `Logged out. Server token ${revoked ? "revoked" : "revoke not confirmed"}; local token ${removed ? "deleted" : "was already absent"}.` : "No token found \u2014 already logged out."
|
|
295
|
+
})
|
|
296
|
+
}]
|
|
297
|
+
};
|
|
298
|
+
}
|
|
268
299
|
async function handleTool(request, signal) {
|
|
269
300
|
switch (request.params.name) {
|
|
270
|
-
case "pair": {
|
|
271
|
-
const a = PairSchema.parse(request.params.arguments ?? {});
|
|
272
|
-
return runPair(a.device_code, a.name, a.voice);
|
|
273
|
-
}
|
|
274
301
|
// ONE rail for "get this agent talking to Paigy" (#875). `pair`, the `paigy-mcp-onboard`
|
|
275
302
|
// CLI and `enable_tools` were three doors into one flow, each knowing a different slice
|
|
276
|
-
// of the state
|
|
277
|
-
//
|
|
278
|
-
//
|
|
303
|
+
// of the state, and a half-configured agent (paired but not allowlisted, or holding a token
|
|
304
|
+
// for a slot it can no longer resolve) had nothing to ask. Since 2026-10-07 (owner) it is
|
|
305
|
+
// `configure`, the only identity tool: `onboard` renamed, `pair` gone (this did all of it),
|
|
306
|
+
// and `unpair` folded in as `logOut`.
|
|
279
307
|
//
|
|
280
308
|
// It reports state and does the next thing, and it is IDEMPOTENT: calling it when
|
|
281
309
|
// everything is fine costs one round trip and returns who you are. Reporting never
|
|
282
310
|
// mutates — the allowlist check is read-only on purpose, because a status call that
|
|
283
311
|
// quietly edits the user's settings is the opposite of what this is for.
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
const { name, voice, device_code, scope } = OnboardSchema.parse(request.params.arguments ?? {});
|
|
312
|
+
case "configure": {
|
|
313
|
+
const { name, voice, device_code, scope, logOut } = ConfigureSchema.parse(request.params.arguments ?? {});
|
|
314
|
+
if (logOut) return logOutResult();
|
|
288
315
|
if (device_code) return runPair(device_code, name, voice);
|
|
289
316
|
const slot = agentName();
|
|
290
317
|
const secret = readToken();
|
|
@@ -303,14 +330,14 @@ async function handleTool(request, signal) {
|
|
|
303
330
|
...allowlisted ? {} : {
|
|
304
331
|
enable_tool_ids: PAIGY_TOOL_IDS,
|
|
305
332
|
enable_command: ENABLE_COMMAND,
|
|
306
|
-
enable_prompt: "Print `enable_command` to the user: \"Run this to let Paigy's tools work without an approval prompt each time \u2014 it only allowlists
|
|
333
|
+
enable_prompt: "Print `enable_command` to the user: \"Run this to let Paigy's tools work without an approval prompt each time \u2014 it only allowlists Paigy's own tools.\" You cannot run it yourself (it writes your own permission allowlist, which hosts block as privilege escalation) \u2014 print it, don't wait for it, and carry on."
|
|
307
334
|
},
|
|
308
335
|
// Setup is done, so the only things left are the user's to decide. Named here
|
|
309
336
|
// rather than left implicit: an agent that reports "ready" and stops gives the
|
|
310
337
|
// user no way to act on an identity they may not want.
|
|
311
338
|
actions: {
|
|
312
|
-
rename: "Call
|
|
313
|
-
|
|
339
|
+
rename: "Call configure again with { name } (and optionally { voice }) to change it.",
|
|
340
|
+
logOut: "Call configure({ logOut: true }) to log this agent out (other agents and this device stay paired)."
|
|
314
341
|
},
|
|
315
342
|
message: me.message
|
|
316
343
|
}) }]
|
|
@@ -320,41 +347,17 @@ async function handleTool(request, signal) {
|
|
|
320
347
|
}
|
|
321
348
|
return runPair(void 0, name, voice);
|
|
322
349
|
}
|
|
323
|
-
case "unpair": {
|
|
324
|
-
const token = readToken();
|
|
325
|
-
let revoked = false;
|
|
326
|
-
if (token) {
|
|
327
|
-
try {
|
|
328
|
-
revoked = await revokeToken(token);
|
|
329
|
-
} catch {
|
|
330
|
-
revoked = false;
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
const removed = deleteToken();
|
|
334
|
-
clearPairing();
|
|
335
|
-
return {
|
|
336
|
-
content: [{
|
|
337
|
-
type: "text",
|
|
338
|
-
text: JSON.stringify({
|
|
339
|
-
ok: true,
|
|
340
|
-
revoked,
|
|
341
|
-
removed,
|
|
342
|
-
message: token ? `Unpaired. Server token ${revoked ? "revoked" : "revoke not confirmed"}; local token ${removed ? "deleted" : "was already absent"}.` : "No token found \u2014 already unpaired."
|
|
343
|
-
})
|
|
344
|
-
}]
|
|
345
|
-
};
|
|
346
|
-
}
|
|
347
350
|
// AM I LISTENING? (#2265) Decides and hands over — `listening.ts` owns the rule and the four
|
|
348
351
|
// answers. The facts are read here, once: the harness's session mark, a token to listen as,
|
|
349
352
|
// a live listener's mark for this slot, and where THIS server's node and daemon live. The
|
|
350
353
|
// daemon is the `listen.js` beside our own entry, so the command never resolves a package.
|
|
351
354
|
case "listen": {
|
|
355
|
+
if (!harnessDriven(process.env) && !readToken()) throw new UnpairedError();
|
|
352
356
|
const slot = agentName();
|
|
353
357
|
const key = listenerKey(slot, process.env);
|
|
354
358
|
const pid = existingListener(slot, process.env);
|
|
355
359
|
const decision = decideListen({
|
|
356
360
|
env: process.env,
|
|
357
|
-
token: !!readToken(),
|
|
358
361
|
pidAlive: pid !== null,
|
|
359
362
|
wake: readWakeStatus(wakeStatusPath(key)),
|
|
360
363
|
...pid !== null ? { pid } : {},
|
package/dist/listen.js
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
WakeBridge
|
|
4
4
|
} from "./chunk-RK5LT7NH.js";
|
|
5
5
|
import {
|
|
6
|
+
entryUnit,
|
|
6
7
|
entryWords,
|
|
7
8
|
existingListener,
|
|
8
9
|
harnessDriven,
|
|
@@ -10,16 +11,16 @@ import {
|
|
|
10
11
|
removeListenMark,
|
|
11
12
|
wakeStatusPath,
|
|
12
13
|
writeListenMark
|
|
13
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-X3GTDW5G.js";
|
|
14
15
|
import {
|
|
15
16
|
agentName,
|
|
16
|
-
contact,
|
|
17
17
|
getGoal,
|
|
18
18
|
heartbeat,
|
|
19
|
+
readDelivery,
|
|
19
20
|
receive,
|
|
20
21
|
slotName,
|
|
21
22
|
subscribeWake
|
|
22
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-4C6SDQ7A.js";
|
|
23
24
|
|
|
24
25
|
// src/listen.ts
|
|
25
26
|
import { createHash } from "crypto";
|
|
@@ -134,7 +135,7 @@ var emit = (obj) => line(JSON.stringify(obj));
|
|
|
134
135
|
var listeningAs = () => slotName(agentName()) ?? agentName();
|
|
135
136
|
var SWEEP_EVERY_MS = Number(process.env.PAIGY_SWEEP_MS) || 9e4;
|
|
136
137
|
function saidIn(delivery) {
|
|
137
|
-
return ("entries" in delivery ? delivery.entries : []).filter((entry) => entry.kind === "contribution").map((entry) => entryWords(entry)).filter(Boolean).join("\n");
|
|
138
|
+
return ("entries" in delivery ? delivery.entries : []).filter((entry) => entry.kind === "contribution" && !entryUnit(entry)).map((entry) => entryWords(entry)).filter(Boolean).join("\n");
|
|
138
139
|
}
|
|
139
140
|
function leadOf(deliveries, goalId) {
|
|
140
141
|
return (goalId ? deliveries.find((d) => d.goalIds.includes(goalId)) : void 0) ?? deliveries[0];
|
|
@@ -144,9 +145,9 @@ function brief(waiting, reason, as, goalId) {
|
|
|
144
145
|
const stalled = waiting.stalled?.length ? ` \xB7 ${waiting.stalled.length} of your Goals stalled 3+ days: update, finish or cancel each` : "";
|
|
145
146
|
const review = waiting.review ?? [];
|
|
146
147
|
const named = (goalId ? review.find((g) => g.goalId === goalId) : void 0) ?? review[0];
|
|
147
|
-
const fresh = review.length ? ` \xB7 new on ${review.length === 1 ? "your Goal" : `${review.length} of your Goals`}, first ${named.goalId} ("${named.title}"):
|
|
148
|
+
const fresh = review.length ? ` \xB7 new on ${review.length === 1 ? "your Goal" : `${review.length} of your Goals`}, first ${named.goalId} ("${named.title}"): get_goal to read it` : "";
|
|
148
149
|
const assigned = waiting.assigned ?? [];
|
|
149
|
-
const mine = assigned.length ? ` \xB7 assigned to you: ${assigned.length === 1 ? "1 Goal" : `${assigned.length} Goals`}, first ${assigned[0].goalId} ("${assigned[0].title}"):
|
|
150
|
+
const mine = assigned.length ? ` \xB7 assigned to you: ${assigned.length === 1 ? "1 Goal" : `${assigned.length} Goals`}, first ${assigned[0].goalId} ("${assigned[0].title}"): get_goal({goalId}) to read it; your first write starts it` : "";
|
|
150
151
|
if (!lead) return `Paigy \xB7 ${reason === "boot" ? `listening as ${as}` : reason}${mine}${fresh || (mine ? "" : " \xB7 nothing waiting")}${stalled}`;
|
|
151
152
|
const said = saidIn(lead) || ("about" in lead ? lead.about : "");
|
|
152
153
|
const shown = said.length > 160 ? `${said.slice(0, 160)}\u2026` : said;
|
|
@@ -171,7 +172,7 @@ async function sweep(reason, goalId, bridge = new WakeBridge(process.env, wakeSt
|
|
|
171
172
|
});
|
|
172
173
|
const { deliveries: rows, stalled, review, assigned } = await receive();
|
|
173
174
|
const lead = leadOf(rows, goalId);
|
|
174
|
-
const full = lead ? await
|
|
175
|
+
const full = lead ? await readDelivery(lead.deliveryId).catch(() => null) : null;
|
|
175
176
|
const deliveries = rows.map((d) => d === lead && full ? full : d);
|
|
176
177
|
const leadGoalId = lead?.goalIds[0];
|
|
177
178
|
const goal = leadGoalId ? await getGoal(leadGoalId).then((g) => ({ goalId: leadGoalId, progress: g.progress })).catch(() => null) : null;
|
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-UQDA7X3W.js";
|
|
7
7
|
import {
|
|
8
8
|
autoConfigureClients,
|
|
9
9
|
claudeInstallHint,
|
|
10
10
|
openBrowser
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-A5FYZK6P.js";
|
|
12
|
+
import "./chunk-X3GTDW5G.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-
|
|
23
|
+
} from "./chunk-4C6SDQ7A.js";
|
|
24
24
|
|
|
25
25
|
// src/onboard.ts
|
|
26
26
|
function reportRegistered() {
|
|
@@ -58,8 +58,8 @@ Paigy MCP onboarding (agent: "${agentName()}")
|
|
|
58
58
|
console.log(`Already set up as "${who.name}"${who.voice ? ` (voice: ${who.voice})` : ""}.
|
|
59
59
|
`);
|
|
60
60
|
console.log("Nothing to do. What's left is yours to decide:");
|
|
61
|
-
console.log(' rename \u2014 PAIGY_NAME="New name" paigy-mcp-onboard (or the `
|
|
62
|
-
console.log("
|
|
61
|
+
console.log(' rename \u2014 PAIGY_NAME="New name" paigy-mcp-onboard (or the `configure` MCP tool)');
|
|
62
|
+
console.log(" log out \u2014 the MCP `configure` tool with { logOut: true }, or delete this slot from ~/.paigy/token.json\n");
|
|
63
63
|
return;
|
|
64
64
|
}
|
|
65
65
|
console.log("The saved token is no longer valid \u2014 re-pairing.\n");
|
package/dist/slot.js
CHANGED
package/dist/stalled.js
CHANGED
|
@@ -15,7 +15,7 @@ function stopReply(stalled, event = "Stop") {
|
|
|
15
15
|
if (!stalled.length) return null;
|
|
16
16
|
const list = stalled.slice(0, 8).map((g) => `"${g.title}" (${g.goalId})`).join(", ");
|
|
17
17
|
const more = stalled.length > 8 ? ` and ${stalled.length - 8} more` : "";
|
|
18
|
-
const reason = `Before you stop: ${stalled.length} of your Paigy Goals have had no progress for 3 days: ${list}${more}. For each,
|
|
18
|
+
const reason = `Before you stop: ${stalled.length} of your Paigy Goals have had no progress for 3 days: ${list}${more}. For each, report where it stands with a contact update, or finish or cancel it with manage_goals.`;
|
|
19
19
|
return event === "AfterAgent" ? { decision: "block", reason, systemMessage: reason } : { decision: "block", reason };
|
|
20
20
|
}
|
|
21
21
|
async function main() {
|
|
@@ -29,7 +29,7 @@ async function main() {
|
|
|
29
29
|
const dir = join(homedir(), ".paigy", "stalled-reminded");
|
|
30
30
|
const mark = join(dir, `${session || "session"}-${day}`);
|
|
31
31
|
if (existsSync(mark)) return;
|
|
32
|
-
const { receive } = await import("./dist-
|
|
32
|
+
const { receive } = await import("./dist-N6ZJUJV7.js");
|
|
33
33
|
const reply = stopReply((await receive()).stalled ?? [], input.hook_event_name ?? "Stop");
|
|
34
34
|
if (!reply) return;
|
|
35
35
|
mkdirSync(dir, { recursive: true });
|
package/dist/statusline.js
CHANGED
package/package.json
CHANGED