@paigy/mcp 0.40.9 → 0.40.11
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-UOROFXDI.js → chunk-FQVK7SO4.js} +5 -5
- package/dist/{chunk-5OY6ED2Q.js → chunk-H5GGWCPS.js} +62 -22
- package/dist/{chunk-UFOR2QEP.js → chunk-I5QINUN6.js} +16 -12
- package/dist/{chunk-LYPZ5QO2.js → chunk-XIHVHYDU.js} +1 -1
- package/dist/enable.js +3 -3
- package/dist/index.js +8 -8
- package/dist/listen.js +2 -2
- package/dist/onboard.js +6 -6
- package/dist/slot.js +3 -3
- package/dist/statusline.js +1 -1
- package/package.json +1 -1
|
@@ -2,10 +2,10 @@ import {
|
|
|
2
2
|
AGENT_TOOLS,
|
|
3
3
|
mcpInputSchema,
|
|
4
4
|
serverInstructions
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-I5QINUN6.js";
|
|
6
6
|
import {
|
|
7
|
-
|
|
8
|
-
} from "./chunk-
|
|
7
|
+
agentName
|
|
8
|
+
} from "./chunk-H5GGWCPS.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.";
|
|
@@ -88,7 +88,7 @@ function withPaigyMcpToml(existing, agent) {
|
|
|
88
88
|
].join("\n");
|
|
89
89
|
return existing + entry;
|
|
90
90
|
}
|
|
91
|
-
function autoConfigureClients(skip =
|
|
91
|
+
function autoConfigureClients(skip = agentName()) {
|
|
92
92
|
const home = homedir();
|
|
93
93
|
const registered = [];
|
|
94
94
|
if (skip !== "antigravity") {
|
|
@@ -124,7 +124,7 @@ function autoConfigureClients(skip = AGENT_NAME) {
|
|
|
124
124
|
}
|
|
125
125
|
return registered;
|
|
126
126
|
}
|
|
127
|
-
function claudeInstallHint(skip =
|
|
127
|
+
function claudeInstallHint(skip = agentName()) {
|
|
128
128
|
if (skip.startsWith("claude")) return null;
|
|
129
129
|
const claudeDir = join(homedir(), ".claude");
|
|
130
130
|
if (!existsSync(claudeDir)) return null;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
// ../../packages/sdk/dist/index.js
|
|
2
2
|
import { createRequire as __sdkCreateRequire } from "module";
|
|
3
|
+
import { execFileSync } from "child_process";
|
|
3
4
|
import { createHash, randomUUID } from "crypto";
|
|
5
|
+
import { readFileSync } from "fs";
|
|
6
|
+
import { homedir } from "os";
|
|
7
|
+
import { join } from "path";
|
|
4
8
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
5
9
|
import { setTimeout as sleep2 } from "timers/promises";
|
|
6
10
|
import { z as z3 } from "zod";
|
|
@@ -10,9 +14,9 @@ import { ZodFirstPartyTypeKind } from "zod/v3";
|
|
|
10
14
|
import { ZodFirstPartyTypeKind as ZodFirstPartyTypeKind2 } from "zod/v3";
|
|
11
15
|
import { z } from "zod";
|
|
12
16
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
13
|
-
import { closeSync, existsSync, mkdirSync, openSync, readFileSync, rmSync, statSync, writeFileSync } from "fs";
|
|
14
|
-
import { homedir } from "os";
|
|
15
|
-
import { join } from "path";
|
|
17
|
+
import { closeSync, existsSync, mkdirSync, openSync, readFileSync as readFileSync2, rmSync, statSync, writeFileSync } from "fs";
|
|
18
|
+
import { homedir as homedir2 } from "os";
|
|
19
|
+
import { join as join2 } from "path";
|
|
16
20
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
17
21
|
import { WebSocket } from "undici";
|
|
18
22
|
var require2 = __sdkCreateRequire(import.meta.url);
|
|
@@ -36,15 +40,42 @@ var envSession = (key) => {
|
|
|
36
40
|
const v = process.env[key];
|
|
37
41
|
return v && v.trim() ? v : void 0;
|
|
38
42
|
};
|
|
39
|
-
|
|
43
|
+
function parentOf(pid) {
|
|
44
|
+
try {
|
|
45
|
+
if (process.platform === "win32") return void 0;
|
|
46
|
+
const ppid = process.platform === "linux" ? readFileSync(`/proc/${pid}/stat`, "utf8").split(") ")[1]?.split(" ")[1] : execFileSync("ps", ["-o", "ppid=", "-p", String(pid)], { encoding: "utf8", timeout: 1e3 });
|
|
47
|
+
return Number(ppid?.trim()) || void 0;
|
|
48
|
+
} catch {
|
|
49
|
+
return void 0;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
var lineage;
|
|
53
|
+
function ancestors() {
|
|
54
|
+
if (lineage) return lineage;
|
|
55
|
+
lineage = [];
|
|
56
|
+
for (let pid = process.ppid; pid && pid > 1 && lineage.length < 5; pid = parentOf(pid)) lineage.push(pid);
|
|
57
|
+
return lineage;
|
|
58
|
+
}
|
|
59
|
+
function claudeConversation() {
|
|
60
|
+
if (!envSession("CLAUDE_CODE_SESSION_ID") || process.env.CLAUDE_CODE_CHILD_SESSION) return void 0;
|
|
61
|
+
const dir = envSession("CLAUDE_CONFIG_DIR") ?? join(homedir(), ".claude");
|
|
62
|
+
for (const pid of ancestors()) {
|
|
63
|
+
try {
|
|
64
|
+
const { sessionId: sessionId2 } = JSON.parse(readFileSync(join(dir, "sessions", `${pid}.json`), "utf8"));
|
|
65
|
+
return typeof sessionId2 === "string" && sessionId2.trim() ? sessionId2 : void 0;
|
|
66
|
+
} catch {
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return void 0;
|
|
70
|
+
}
|
|
40
71
|
function sessionId() {
|
|
41
|
-
return
|
|
72
|
+
return envSession("PAIGY_SESSION_ID") ?? claudeConversation() ?? envSession("CLAUDE_CODE_SESSION_ID") ?? envSession("CODEX_THREAD_ID") ?? envSession("CODEX_SESSION_ID") ?? WORKSPACE_ID;
|
|
42
73
|
}
|
|
43
74
|
function isNetworkError(e) {
|
|
44
75
|
return e instanceof Error && e.message.startsWith(NETWORK_MSG);
|
|
45
76
|
}
|
|
46
77
|
async function reach(url, init) {
|
|
47
|
-
return send(url, init,
|
|
78
|
+
return send(url, init, sessionId());
|
|
48
79
|
}
|
|
49
80
|
async function send(url, init, session) {
|
|
50
81
|
try {
|
|
@@ -1270,6 +1301,7 @@ var zodToJsonSchema = (schema, options) => {
|
|
|
1270
1301
|
};
|
|
1271
1302
|
var OPTIONS_MIN = 2;
|
|
1272
1303
|
var OPTIONS_MAX = 6;
|
|
1304
|
+
var NIGHT = { from: 23, to: 7 };
|
|
1273
1305
|
function draft2020(node) {
|
|
1274
1306
|
if (Array.isArray(node)) return node.map(draft2020);
|
|
1275
1307
|
if (node && typeof node === "object") {
|
|
@@ -1301,7 +1333,7 @@ function mcpInputSchema(s) {
|
|
|
1301
1333
|
}
|
|
1302
1334
|
var AskInputSchema = z.object({
|
|
1303
1335
|
id: z.string().optional().describe("Optional idempotency key or client-side ID for this specific ask."),
|
|
1304
|
-
parentId: z.string().uuid().optional().describe("
|
|
1336
|
+
parentId: z.string().uuid().optional().describe("The Goal this question is about \u2014 usually the one you are working on. The question goes onto that Goal and its answer comes back there. Omit it and Paigy places the question in the tree itself."),
|
|
1305
1337
|
repo: z.string().optional().describe("Optional repository context."),
|
|
1306
1338
|
ask: z.string().trim().min(1).max(1e4).describe(
|
|
1307
1339
|
"The question, and only what is needed to answer it. News, progress and findings are their own contact \u2014 a call contact JOINS a call already happening, so several arrive as one call. Do not bundle: a DecisionNeed is settled only by an answer in the shape this ask declares, so someone who answers the part that interested them settles nothing and is asked again."
|
|
@@ -1320,7 +1352,7 @@ var StartContactSchema = z.object({
|
|
|
1320
1352
|
}).strict();
|
|
1321
1353
|
var ContactSchema = z.union([StartContactSchema, z.object({ deliveryId: z.string().uuid() }).strict()]);
|
|
1322
1354
|
var CONTACT_SCHEMA = { type: "object", ...mcpInputSchema(ContactSchema) };
|
|
1323
|
-
var CONTACT_DESCRIPTION = "Contact the user with one or more asks/questions. Pass an array of asks (each with 'ask', optional 'options', 'id', 'parentId', 'repo'), plus channel:'notification'|'call', and waiting:'none'|'hard'.
|
|
1355
|
+
var CONTACT_DESCRIPTION = "Contact the user with one or more asks/questions. Pass an array of asks (each with 'ask', optional 'options', 'id', 'parentId', 'repo'), plus channel:'notification'|'call', and waiting:'none'|'hard'. An ask that names a Goal (parentId) goes onto that Goal; one that names none is placed in the person's tree by Paigy. Notification returns immediately; collect durable answers with check_replies. On stdio, a Call holds one cancellable ~45s window; continue with ONLY {deliveryId}. Never bundle multiple questions into a single 'ask' string; pass them as separate objects in the 'asks' array.";
|
|
1324
1356
|
var CreateGoalSchema = z2.object({
|
|
1325
1357
|
outcome: z2.string().trim().min(1).max(1e4),
|
|
1326
1358
|
/** The work's NAME (#2115) — one to five words, how a person refers to it out loud ("the night
|
|
@@ -1376,9 +1408,9 @@ var CLAIM_GOAL_DESCRIPTION = "Claim the oldest runnable or review-pending Goal y
|
|
|
1376
1408
|
var CHECK_REPLIES_DESCRIPTION = "Your open Deliveries: every Notification or Call currently addressed to you \u2014 a request the user started toward you, an answer relayed to something you asked, a handoff \u2014 one row each: its Goals, how many decisions are still open, and the newest words in brief. A pure read with no arguments: nothing is consumed, acknowledged or claimed by reading it, so call it on startup, after a long wait, or whenever you want to know what is outstanding. To act on one, claim its Goal (claim_goal) or reread it in full with contact({deliveryId}). Once you have acted on what arrived, update_goal with reviewed: true closes the Deliveries addressed to you on that Goal. Your runnable and review-pending Goals come from claim_goal, not from here.";
|
|
1377
1409
|
var CheckRepliesSchema = z2.object({}).strict();
|
|
1378
1410
|
var GetThreadSchema = z2.object({
|
|
1379
|
-
parentId: z2.string().describe("The Thread to read \u2014 the
|
|
1411
|
+
parentId: z2.string().describe("The Thread to read \u2014 the parentId of a search_threads hit.")
|
|
1380
1412
|
}).strict();
|
|
1381
|
-
var GET_THREAD_DESCRIPTION = "Read the authorized durable Entries on one conversation Thread \u2014 what you wrote there and what was delivered to you, oldest first. Use claim_goal to find the work to resume; use this to rehydrate a Thread that a search hit
|
|
1413
|
+
var GET_THREAD_DESCRIPTION = "Read the authorized durable Entries on one conversation Thread \u2014 what you wrote there and what was delivered to you, oldest first. Use claim_goal to find the work to resume and get_goal for the conversation on a Goal; use this only to rehydrate a Thread that a search hit named.";
|
|
1382
1414
|
var SearchThreadsSchema = z2.object({
|
|
1383
1415
|
q: z2.string().describe("What to look for \u2014 plain words or a phrase (e.g. 'the livekit timeout', 'deploy to prod').")
|
|
1384
1416
|
}).strict();
|
|
@@ -1856,7 +1888,7 @@ var InboxItemSchema = z3.object({
|
|
|
1856
1888
|
error: z3.string().optional(),
|
|
1857
1889
|
clarifies: z3.string().optional(),
|
|
1858
1890
|
/** The ring ladder ran out while this was still pending — we tried to reach you and
|
|
1859
|
-
* STOPPED trying (`arbitration/arbitrate.ts` `
|
|
1891
|
+
* STOPPED trying (`arbitration/arbitrate.ts` `ringAt` → null). Distinct from an
|
|
1860
1892
|
* agent with nothing to say, which the roster drew identically until now: "nothing to
|
|
1861
1893
|
* say" and "gave up saying it" are opposite situations wearing the same face
|
|
1862
1894
|
* (navigation-design.md, gap 1). False for anything that never rang. */
|
|
@@ -1925,6 +1957,8 @@ var MissedCallSchema = z3.enum([
|
|
|
1925
1957
|
"inbox",
|
|
1926
1958
|
"dismiss"
|
|
1927
1959
|
]);
|
|
1960
|
+
var clock = (h) => h === 0 ? "midnight" : h === 12 ? "noon" : h < 12 ? `${h} am` : `${h - 12} pm`;
|
|
1961
|
+
var QUIET = ` Nothing rings from ${clock(NIGHT.from)} to ${clock(NIGHT.to)} your time; the count waits for morning.`;
|
|
1928
1962
|
var BrokerTuningSchema = z3.object({
|
|
1929
1963
|
/** 'none' = skip the spoken ack after a mapped answer (power users find it slow). */
|
|
1930
1964
|
ackVerbosity: z3.enum(["normal", "none"]).optional(),
|
|
@@ -2352,13 +2386,15 @@ function sessionSlot(sessionId2) {
|
|
|
2352
2386
|
const id = sessionId2 ?? sessionId();
|
|
2353
2387
|
return `session:${id.slice(0, 8)}`;
|
|
2354
2388
|
}
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2389
|
+
function agentName() {
|
|
2390
|
+
return process.env.PAIGY_AGENT || sessionSlot();
|
|
2391
|
+
}
|
|
2392
|
+
var TOKEN_PATH = join2(homedir2(), ".paigy", "token.json");
|
|
2393
|
+
var KEY_PATH = join2(homedir2(), ".paigy", "key.json");
|
|
2358
2394
|
function readTokenFile() {
|
|
2359
2395
|
if (!existsSync(TOKEN_PATH)) return {};
|
|
2360
2396
|
try {
|
|
2361
|
-
const parsed = JSON.parse(
|
|
2397
|
+
const parsed = JSON.parse(readFileSync2(TOKEN_PATH, "utf8"));
|
|
2362
2398
|
if (typeof parsed.access_token === "string") return {};
|
|
2363
2399
|
const slots = parsed;
|
|
2364
2400
|
delete slots["*"];
|
|
@@ -2370,7 +2406,7 @@ function readTokenFile() {
|
|
|
2370
2406
|
function withTokenLock(mutate) {
|
|
2371
2407
|
const lock = TOKEN_PATH + ".lock";
|
|
2372
2408
|
const spin = new Int32Array(new SharedArrayBuffer(4));
|
|
2373
|
-
mkdirSync(
|
|
2409
|
+
mkdirSync(join2(homedir2(), ".paigy"), { recursive: true });
|
|
2374
2410
|
for (const deadline = Date.now() + 5e3; Date.now() < deadline; ) {
|
|
2375
2411
|
try {
|
|
2376
2412
|
closeSync(openSync(lock, "wx"));
|
|
@@ -2387,14 +2423,14 @@ function withTokenLock(mutate) {
|
|
|
2387
2423
|
rmSync(lock, { force: true });
|
|
2388
2424
|
}
|
|
2389
2425
|
}
|
|
2390
|
-
function saveToken(token, agent2 =
|
|
2426
|
+
function saveToken(token, agent2 = agentName()) {
|
|
2391
2427
|
withTokenLock(() => {
|
|
2392
2428
|
const slots = { ...readTokenFile(), [agent2]: token };
|
|
2393
2429
|
writeFileSync(TOKEN_PATH, JSON.stringify(slots, null, 2) + "\n", { mode: 384 });
|
|
2394
2430
|
});
|
|
2395
2431
|
}
|
|
2396
2432
|
var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
2397
|
-
function readToken(agent2 =
|
|
2433
|
+
function readToken(agent2 = agentName()) {
|
|
2398
2434
|
if (process.env.PAIGY_TOKEN) return process.env.PAIGY_TOKEN;
|
|
2399
2435
|
return readTokenFile()[agent2]?.access_token ?? "";
|
|
2400
2436
|
}
|
|
@@ -2404,7 +2440,7 @@ function listSlots() {
|
|
|
2404
2440
|
function slotName(agent2) {
|
|
2405
2441
|
return readTokenFile()[agent2]?.name ?? null;
|
|
2406
2442
|
}
|
|
2407
|
-
function deleteToken(agent2 =
|
|
2443
|
+
function deleteToken(agent2 = agentName()) {
|
|
2408
2444
|
return withTokenLock(() => {
|
|
2409
2445
|
const slots = readTokenFile();
|
|
2410
2446
|
if (!(agent2 in slots)) return false;
|
|
@@ -2421,7 +2457,7 @@ async function revokeToken(token) {
|
|
|
2421
2457
|
});
|
|
2422
2458
|
return res.ok;
|
|
2423
2459
|
}
|
|
2424
|
-
async function requestCode(suggestedName =
|
|
2460
|
+
async function requestCode(suggestedName = agentName(), device) {
|
|
2425
2461
|
const res = await reach(`${BACKEND_URL}/api/device/code`, {
|
|
2426
2462
|
method: "POST",
|
|
2427
2463
|
headers: { "content-type": "application/json" },
|
|
@@ -2613,10 +2649,12 @@ async function contact(input, opts = {}) {
|
|
|
2613
2649
|
deliveryId = deliveries[0]?.deliveryId ?? "";
|
|
2614
2650
|
if (!deliveryId) throw new Error("Goal contact returned no valid Delivery identity");
|
|
2615
2651
|
}
|
|
2652
|
+
const all = deliveries.filter((d) => !!d.deliveryId && !!d.goalId);
|
|
2616
2653
|
const read = async (signal2) => {
|
|
2617
2654
|
const res = ensureAuthed(await send2(`${BACKEND_URL}/api/deliveries/${encodeURIComponent(deliveryId)}`, { headers, signal: signal2 }));
|
|
2618
2655
|
if (!res.ok) await fail("read_delivery", res);
|
|
2619
|
-
|
|
2656
|
+
const one = await res.json();
|
|
2657
|
+
return all.length > 1 ? { ...one, deliveries: all } : one;
|
|
2620
2658
|
};
|
|
2621
2659
|
const settled = (d) => d.kind === "notification" || d.state === "closed" || d.answers.length > 0 || d.entries.some((e) => e.kind === "contribution");
|
|
2622
2660
|
if (opts.waits === false) return read(opts.signal);
|
|
@@ -2712,6 +2750,8 @@ function deliveryView(d) {
|
|
|
2712
2750
|
state: d.state,
|
|
2713
2751
|
goalIds: d.goalIds,
|
|
2714
2752
|
conversation: conversation(d),
|
|
2753
|
+
// Each ask's own Delivery when a contact carried several — the only handle on the others.
|
|
2754
|
+
deliveries: d.deliveries,
|
|
2715
2755
|
next: d.kind === "notification" ? "Answers land on the Goal: read them with claim_goal or get_goal. Do not poll this notification." : d.message
|
|
2716
2756
|
});
|
|
2717
2757
|
}
|
|
@@ -2876,7 +2916,7 @@ async function subscribeWake(onNudge, opts = {}) {
|
|
|
2876
2916
|
export {
|
|
2877
2917
|
isNetworkError,
|
|
2878
2918
|
sessionSlot,
|
|
2879
|
-
|
|
2919
|
+
agentName,
|
|
2880
2920
|
TOKEN_PATH,
|
|
2881
2921
|
saveToken,
|
|
2882
2922
|
sleep,
|
|
@@ -5,6 +5,7 @@ import { zodToJsonSchema } from "zod-to-json-schema";
|
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
var OPTIONS_MIN = 2;
|
|
7
7
|
var OPTIONS_MAX = 6;
|
|
8
|
+
var NIGHT = { from: 23, to: 7 };
|
|
8
9
|
function draft2020(node) {
|
|
9
10
|
if (Array.isArray(node)) return node.map(draft2020);
|
|
10
11
|
if (node && typeof node === "object") {
|
|
@@ -36,7 +37,7 @@ function mcpInputSchema(s) {
|
|
|
36
37
|
}
|
|
37
38
|
var AskInputSchema = z.object({
|
|
38
39
|
id: z.string().optional().describe("Optional idempotency key or client-side ID for this specific ask."),
|
|
39
|
-
parentId: z.string().uuid().optional().describe("
|
|
40
|
+
parentId: z.string().uuid().optional().describe("The Goal this question is about \u2014 usually the one you are working on. The question goes onto that Goal and its answer comes back there. Omit it and Paigy places the question in the tree itself."),
|
|
40
41
|
repo: z.string().optional().describe("Optional repository context."),
|
|
41
42
|
ask: z.string().trim().min(1).max(1e4).describe(
|
|
42
43
|
"The question, and only what is needed to answer it. News, progress and findings are their own contact \u2014 a call contact JOINS a call already happening, so several arrive as one call. Do not bundle: a DecisionNeed is settled only by an answer in the shape this ask declares, so someone who answers the part that interested them settles nothing and is asked again."
|
|
@@ -55,7 +56,7 @@ var StartContactSchema = z.object({
|
|
|
55
56
|
}).strict();
|
|
56
57
|
var ContactSchema = z.union([StartContactSchema, z.object({ deliveryId: z.string().uuid() }).strict()]);
|
|
57
58
|
var CONTACT_SCHEMA = { type: "object", ...mcpInputSchema(ContactSchema) };
|
|
58
|
-
var CONTACT_DESCRIPTION = "Contact the user with one or more asks/questions. Pass an array of asks (each with 'ask', optional 'options', 'id', 'parentId', 'repo'), plus channel:'notification'|'call', and waiting:'none'|'hard'.
|
|
59
|
+
var CONTACT_DESCRIPTION = "Contact the user with one or more asks/questions. Pass an array of asks (each with 'ask', optional 'options', 'id', 'parentId', 'repo'), plus channel:'notification'|'call', and waiting:'none'|'hard'. An ask that names a Goal (parentId) goes onto that Goal; one that names none is placed in the person's tree by Paigy. Notification returns immediately; collect durable answers with check_replies. On stdio, a Call holds one cancellable ~45s window; continue with ONLY {deliveryId}. Never bundle multiple questions into a single 'ask' string; pass them as separate objects in the 'asks' array.";
|
|
59
60
|
var CreateGoalSchema = z2.object({
|
|
60
61
|
outcome: z2.string().trim().min(1).max(1e4),
|
|
61
62
|
/** The work's NAME (#2115) — one to five words, how a person refers to it out loud ("the night
|
|
@@ -111,9 +112,9 @@ var CLAIM_GOAL_DESCRIPTION = "Claim the oldest runnable or review-pending Goal y
|
|
|
111
112
|
var CHECK_REPLIES_DESCRIPTION = "Your open Deliveries: every Notification or Call currently addressed to you \u2014 a request the user started toward you, an answer relayed to something you asked, a handoff \u2014 one row each: its Goals, how many decisions are still open, and the newest words in brief. A pure read with no arguments: nothing is consumed, acknowledged or claimed by reading it, so call it on startup, after a long wait, or whenever you want to know what is outstanding. To act on one, claim its Goal (claim_goal) or reread it in full with contact({deliveryId}). Once you have acted on what arrived, update_goal with reviewed: true closes the Deliveries addressed to you on that Goal. Your runnable and review-pending Goals come from claim_goal, not from here.";
|
|
112
113
|
var CheckRepliesSchema = z2.object({}).strict();
|
|
113
114
|
var GetThreadSchema = z2.object({
|
|
114
|
-
parentId: z2.string().describe("The Thread to read \u2014 the
|
|
115
|
+
parentId: z2.string().describe("The Thread to read \u2014 the parentId of a search_threads hit.")
|
|
115
116
|
}).strict();
|
|
116
|
-
var GET_THREAD_DESCRIPTION = "Read the authorized durable Entries on one conversation Thread \u2014 what you wrote there and what was delivered to you, oldest first. Use claim_goal to find the work to resume; use this to rehydrate a Thread that a search hit
|
|
117
|
+
var GET_THREAD_DESCRIPTION = "Read the authorized durable Entries on one conversation Thread \u2014 what you wrote there and what was delivered to you, oldest first. Use claim_goal to find the work to resume and get_goal for the conversation on a Goal; use this only to rehydrate a Thread that a search hit named.";
|
|
117
118
|
var SearchThreadsSchema = z2.object({
|
|
118
119
|
q: z2.string().describe("What to look for \u2014 plain words or a phrase (e.g. 'the livekit timeout', 'deploy to prod').")
|
|
119
120
|
}).strict();
|
|
@@ -129,14 +130,15 @@ var AGENT_TOOLS = [
|
|
|
129
130
|
{ name: "update_goal", description: UPDATE_GOAL_DESCRIPTION, inputSchema: mcpInputSchema(UpdateGoalToolSchema) }
|
|
130
131
|
];
|
|
131
132
|
var AGENT_TOOL_NAMES = AGENT_TOOLS.map((t) => t.name);
|
|
132
|
-
function serverInstructions(
|
|
133
|
-
|
|
133
|
+
function serverInstructions(opts) {
|
|
134
|
+
const calls = opts.waits ? "A Call holds one bounded window here; continue with contact({deliveryId}) to hold the next or reread that exact Delivery." : "A Call returns after one read; continue with contact({deliveryId}) to reread that exact Delivery.";
|
|
135
|
+
return `On startup and after a wake, call check_replies for the open Deliveries addressed to you, and claim_goal for your runnable or review-pending Goal and the conversation on it. get_goal rereads it without claiming. Every read ends in \`next\`, the one step to take. Notifications return immediately: keep working and collect answers through claim_goal/get_goal. ${calls} Evidence can repeat: reads do not acknowledge or hide it. Report progress and acknowledge review with update_goal, never as a contact. Never infer ringing from an open Call Delivery. Soft waiting and re-presentation are unsupported. Your user is remote. Always interact with the user through Paigy. For decisions, approvals, or questions, contact them with structured options. Never assume anyone is reading the terminal stdout.
|
|
134
136
|
|
|
135
|
-
|
|
136
|
-
1.
|
|
137
|
-
2.
|
|
138
|
-
3.
|
|
139
|
-
4.
|
|
137
|
+
HOW TO ASK:
|
|
138
|
+
1. One question per ask. Five questions are five objects in \`asks\`, in one contact, so each can be answered on its own; one question with five parts settles nothing until all five are answered.
|
|
139
|
+
2. Name the Goal you are working on as the ask's \`parentId\`: the question goes onto that Goal and its answer comes back there. Without one, Paigy places it.
|
|
140
|
+
3. \`waiting: hard\` only for a decision you are blocked on; \`waiting: none\` for a question you can keep working around.
|
|
141
|
+
4. Never hold the process open with while-loops. Let the current process finish or schedule a wakeup, and collect answers with \`check_replies\` or \`claim_goal\` on the next wake.`;
|
|
140
142
|
}
|
|
141
143
|
function entryWords(entry) {
|
|
142
144
|
const content = entry.content;
|
|
@@ -600,7 +602,7 @@ var InboxItemSchema = z3.object({
|
|
|
600
602
|
error: z3.string().optional(),
|
|
601
603
|
clarifies: z3.string().optional(),
|
|
602
604
|
/** The ring ladder ran out while this was still pending — we tried to reach you and
|
|
603
|
-
* STOPPED trying (`arbitration/arbitrate.ts` `
|
|
605
|
+
* STOPPED trying (`arbitration/arbitrate.ts` `ringAt` → null). Distinct from an
|
|
604
606
|
* agent with nothing to say, which the roster drew identically until now: "nothing to
|
|
605
607
|
* say" and "gave up saying it" are opposite situations wearing the same face
|
|
606
608
|
* (navigation-design.md, gap 1). False for anything that never rang. */
|
|
@@ -669,6 +671,8 @@ var MissedCallSchema = z3.enum([
|
|
|
669
671
|
"inbox",
|
|
670
672
|
"dismiss"
|
|
671
673
|
]);
|
|
674
|
+
var clock = (h) => h === 0 ? "midnight" : h === 12 ? "noon" : h < 12 ? `${h} am` : `${h - 12} pm`;
|
|
675
|
+
var QUIET = ` Nothing rings from ${clock(NIGHT.from)} to ${clock(NIGHT.to)} your time; the count waits for morning.`;
|
|
672
676
|
var BrokerTuningSchema = z3.object({
|
|
673
677
|
/** 'none' = skip the spoken ack after a mapped answer (power users find it slow). */
|
|
674
678
|
ackVerbosity: z3.enum(["normal", "none"]).optional(),
|
package/dist/enable.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
PAIGY_TOOL_IDS,
|
|
4
4
|
enablePaigyTools
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-FQVK7SO4.js";
|
|
6
|
+
import "./chunk-I5QINUN6.js";
|
|
7
|
+
import "./chunk-H5GGWCPS.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-
|
|
8
|
+
} from "./chunk-XIHVHYDU.js";
|
|
9
9
|
import {
|
|
10
10
|
ENABLE_COMMAND,
|
|
11
11
|
OnboardSchema,
|
|
@@ -14,15 +14,15 @@ import {
|
|
|
14
14
|
SERVER_INSTRUCTIONS,
|
|
15
15
|
TOOLS,
|
|
16
16
|
paigyToolsAllowlisted
|
|
17
|
-
} from "./chunk-
|
|
18
|
-
import "./chunk-
|
|
17
|
+
} from "./chunk-FQVK7SO4.js";
|
|
18
|
+
import "./chunk-I5QINUN6.js";
|
|
19
19
|
import {
|
|
20
20
|
clearSurface,
|
|
21
21
|
writeSurface
|
|
22
22
|
} from "./chunk-3SVNPJPN.js";
|
|
23
23
|
import {
|
|
24
|
-
AGENT_NAME,
|
|
25
24
|
UnpairedError,
|
|
25
|
+
agentName,
|
|
26
26
|
deleteToken,
|
|
27
27
|
hatch,
|
|
28
28
|
heartbeat,
|
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
setIdentity,
|
|
36
36
|
slotName,
|
|
37
37
|
whoAmI
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-H5GGWCPS.js";
|
|
39
39
|
|
|
40
40
|
// src/index.ts
|
|
41
41
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -108,7 +108,7 @@ function renderPairOutcome(outcome, device_code) {
|
|
|
108
108
|
function unidentifiedResult() {
|
|
109
109
|
return { isError: true, content: [{ type: "text", text: JSON.stringify({
|
|
110
110
|
error: "no_identity",
|
|
111
|
-
slot:
|
|
111
|
+
slot: agentName(),
|
|
112
112
|
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 \`pair\` (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"}).`
|
|
113
113
|
}) }] };
|
|
114
114
|
}
|
|
@@ -238,7 +238,7 @@ async function handleTool(request, signal) {
|
|
|
238
238
|
case "onboard": {
|
|
239
239
|
const { name, voice, device_code, scope } = OnboardSchema.parse(request.params.arguments ?? {});
|
|
240
240
|
if (device_code) return runPair(device_code, name, voice);
|
|
241
|
-
const slot =
|
|
241
|
+
const slot = agentName();
|
|
242
242
|
const secret = readToken();
|
|
243
243
|
if (secret) {
|
|
244
244
|
let who = await whoAmI().catch(() => null);
|
|
@@ -307,7 +307,7 @@ async function handleTool(request, signal) {
|
|
|
307
307
|
default: {
|
|
308
308
|
const name = request.params.name;
|
|
309
309
|
const result = await runTool(name, request.params.arguments ?? {}, { waits: true, signal });
|
|
310
|
-
const sentAs = name === "contact" ? slotName(
|
|
310
|
+
const sentAs = name === "contact" ? slotName(agentName()) : null;
|
|
311
311
|
const shaped = sentAs && result && typeof result === "object" ? { ...result, sentAs } : result;
|
|
312
312
|
return { content: [{ type: "text", text: JSON.stringify(shaped) }] };
|
|
313
313
|
}
|
package/dist/listen.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
entryWords
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-I5QINUN6.js";
|
|
5
5
|
import {
|
|
6
6
|
checkReplies,
|
|
7
7
|
contact,
|
|
8
8
|
getGoal,
|
|
9
9
|
subscribeWake
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-H5GGWCPS.js";
|
|
11
11
|
|
|
12
12
|
// src/listen.ts
|
|
13
13
|
import { spawn } from "child_process";
|
package/dist/onboard.js
CHANGED
|
@@ -3,16 +3,16 @@ import {
|
|
|
3
3
|
resolvePairing,
|
|
4
4
|
startPairing,
|
|
5
5
|
suggestedAgentName
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-XIHVHYDU.js";
|
|
7
7
|
import {
|
|
8
8
|
autoConfigureClients,
|
|
9
9
|
claudeInstallHint,
|
|
10
10
|
openBrowser
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-FQVK7SO4.js";
|
|
12
|
+
import "./chunk-I5QINUN6.js";
|
|
13
13
|
import {
|
|
14
|
-
AGENT_NAME,
|
|
15
14
|
TOKEN_PATH,
|
|
15
|
+
agentName,
|
|
16
16
|
hatch,
|
|
17
17
|
listSlots,
|
|
18
18
|
overrideToken,
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
saveToken,
|
|
21
21
|
setIdentity,
|
|
22
22
|
whoAmI
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-H5GGWCPS.js";
|
|
24
24
|
|
|
25
25
|
// src/onboard.ts
|
|
26
26
|
function reportRegistered() {
|
|
@@ -36,7 +36,7 @@ function reportRegistered() {
|
|
|
36
36
|
}
|
|
37
37
|
async function main() {
|
|
38
38
|
console.log(`
|
|
39
|
-
Paigy MCP onboarding (agent: "${
|
|
39
|
+
Paigy MCP onboarding (agent: "${agentName()}")
|
|
40
40
|
`);
|
|
41
41
|
const chosen = process.env.PAIGY_NAME ?? suggestedAgentName();
|
|
42
42
|
if (readToken()) {
|
package/dist/slot.js
CHANGED
package/dist/statusline.js
CHANGED
package/package.json
CHANGED