@paigy/mcp 0.40.19 → 0.40.20
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-VYWIPFEY.js → chunk-6C6CO7H3.js} +125 -46
- package/dist/{chunk-76ILN3YV.js → chunk-6MEUSSRH.js} +2 -2
- package/dist/{chunk-HGXXGOGG.js → chunk-RLN2B5IZ.js} +59 -22
- package/dist/{chunk-TRMYDJ5H.js → chunk-YNKTKLQD.js} +1 -1
- package/dist/{dist-GJOOJ4FR.js → dist-33DA5X2G.js} +5 -1
- package/dist/enable.js +3 -3
- package/dist/index.js +4 -4
- package/dist/listen.js +7 -2
- package/dist/onboard.js +4 -4
- package/dist/slot.js +1 -1
- package/dist/stalled.js +1 -1
- package/dist/statusline.js +1 -1
- package/package.json +1 -1
|
@@ -1525,18 +1525,18 @@ var AskInputSchema = z2.object({
|
|
|
1525
1525
|
parentId: z2.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."),
|
|
1526
1526
|
repo: z2.string().optional().describe("Optional repository context."),
|
|
1527
1527
|
ask: z2.string().trim().min(1).max(1e4).describe(
|
|
1528
|
-
"ONE question, and only what is needed to answer it. Several questions are several asks in the array, one each: an answer settles the one ask it was given in the shape that ask declares, so a person who answers the part of a bundled ask that interested them settles nothing and is asked again. Paigy reads every ask once and takes a bundled one apart into its own cards anyway \u2014
|
|
1528
|
+
"ONE question, and only what is needed to answer it. Several questions are several asks in the array, one each: an answer settles the one ask it was given in the shape that ask declares, so a person who answers the part of a bundled ask that interested them settles nothing and is asked again. Paigy reads every ask once and takes a bundled one apart into its own cards anyway \u2014 each question a Question on the one Goal the ask lands on, never a Goal of its own \u2014 but the words it splits are its reading, not yours. News, progress and findings are their own contact; ANY contact for a person already on a call JOINS that call, whatever channel you asked for, so several arrive as one call."
|
|
1529
1529
|
),
|
|
1530
|
-
options: z2.array(OptionInputSchema).min(
|
|
1530
|
+
options: z2.array(OptionInputSchema).min(1).max(6).optional()
|
|
1531
1531
|
}).strict();
|
|
1532
1532
|
var StartContactSchema = z2.object({
|
|
1533
1533
|
asks: z2.array(AskInputSchema).min(1).describe("The questions to pose, one per object. An ask with a parentId is filed on that Goal as it is; only an ask naming no Goal is placed in the tree by Paigy."),
|
|
1534
|
-
waiting: z2.enum(["none", "hard"]).default("none"),
|
|
1534
|
+
waiting: z2.enum(["none", "hard"]).default("none").describe("hard requests a call even when channel is notification; user permissions and ring cooldowns still apply."),
|
|
1535
1535
|
channel: z2.enum(["notification", "call"]).default("notification")
|
|
1536
1536
|
}).strict();
|
|
1537
1537
|
var ContactSchema = z2.union([StartContactSchema, z2.object({ deliveryId: z2.string().uuid() }).strict()]);
|
|
1538
1538
|
var CONTACT_SCHEMA = { type: "object", ...mcpInputSchema(ContactSchema) };
|
|
1539
|
-
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}. One question per 'ask'; several questions are several objects in 'asks'. A bundled ask is taken apart into its own cards by Paigy's one intake read
|
|
1539
|
+
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}. One question per 'ask'; several questions are several objects in 'asks'. A bundled ask is taken apart into its own cards by Paigy's one intake read, every one on the Goal the ask lands on; separate pieces of work are separate asks. An ask with no options that is not blocking is a report, and a report is an UPDATE, never a claim on them: it reaches them and is listed apart from what waits on them, so no answer is owed and none should be awaited. On a Goal whose report card is still open it is added to that card, with no new push; one that only says where your work stands while under way is recorded as the Goal's progress, not sent (the result says so). Send options (or waiting:'hard') when you actually need an answer. If the person is already on a call, your contact joins that call automatically \u2014 whatever channel you asked for, with no ring \u2014 and the Delivery it returns IS that call: reread it with contact({deliveryId}) to see everything answered on it so far, and contact again while it is live to add information or a further question to the same call.";
|
|
1540
1540
|
var CreateGoalSchema = z3.object({
|
|
1541
1541
|
outcome: z3.string().trim().min(1).max(1e4),
|
|
1542
1542
|
/** The work's NAME (#2115) — one to five words, how a person refers to it out loud ("the night
|
|
@@ -1574,7 +1574,11 @@ var UpdateGoalSchema = z3.object({
|
|
|
1574
1574
|
state: z3.enum(["active", "done", "cancelled"]).optional(),
|
|
1575
1575
|
progress: z3.string().trim().min(1).max(1e4).optional(),
|
|
1576
1576
|
reviewed: z3.literal(true).optional(),
|
|
1577
|
-
dueAt: z3.string().datetime({ offset: true }).nullable().optional()
|
|
1577
|
+
dueAt: z3.string().datetime({ offset: true }).nullable().optional(),
|
|
1578
|
+
/** WITHDRAW YOUR OWN QUESTION (#2777, owner 2026-09-30). The question's id as every read shows it
|
|
1579
|
+
* (the conversation's `id`, eight characters, or the whole request Entry id), on THIS Goal, asked
|
|
1580
|
+
* by you and still open. It is cancelled, not answered: its cards close and nothing rings for it. */
|
|
1581
|
+
withdraw: z3.array(z3.string().trim().regex(/^[0-9a-fA-F-]{8,36}$/)).min(1).max(10).optional()
|
|
1578
1582
|
}).strict().refine((v) => Object.keys(v).length > 0),
|
|
1579
1583
|
reason: z3.string().trim().min(1).max(2e3),
|
|
1580
1584
|
operationId: z3.string().uuid().optional()
|
|
@@ -1585,10 +1589,14 @@ var GetGoalSchema = z3.object({
|
|
|
1585
1589
|
goalId: z3.string().uuid(),
|
|
1586
1590
|
/** Every entry in full. Without it the read carries the person's words, open questions and your
|
|
1587
1591
|
* newest entry, and counts what it left out (`apps/api/src/goal/collapse.ts`). */
|
|
1588
|
-
history: z3.boolean().optional()
|
|
1592
|
+
history: z3.boolean().optional(),
|
|
1593
|
+
/** WHEN A READ HAS CONFUSED YOU. Adds `diagnosis`: every reader that already answers a question
|
|
1594
|
+
* about this work, each answer attributed to the reader that gave it, and every disagreement
|
|
1595
|
+
* between two of them named. Off by default; `apps/api/src/goal/diagnose-design.md`. */
|
|
1596
|
+
diagnose: z3.boolean().optional()
|
|
1589
1597
|
}).strict();
|
|
1590
|
-
var GET_GOAL_DESCRIPTION = "Read one Goal without claiming it: its outcome, state, revision, progress, blockers, the conversation on it (each question with its options and what was decided), `next`, the one step to take, and `more`, where to read further. The conversation carries everything the person said, every open question and your newest entry; your older entries are left out and counted \u2014 history: true reads every entry in full. Another account's Goals, and another agent's Goal that is not below one of yours, are not disclosed.";
|
|
1591
|
-
var UPDATE_GOAL_DESCRIPTION = `Update an owned Goal at an exact revision. State, ownership, dependencies, children, progress, title, and review acknowledgement are explicit; stale revisions are rejected. title is the work's name in one to five words, as a person would refer to it out loud (it is spoken on a call and heads every list); null clears it. reviewed: true acknowledges new evidence and closes the Deliveries addressed to you on that Goal, never over an open decision. dueAt (an ISO instant, or null) makes the Goal wait until then; when it passes you are woken for it \u2014 use it for a promise to follow up later. state: done means the work was accomplished, and it can be reopened: when the person says it is not done ("it's not working"), set state: active on that same Goal instead of starting a new one; its parent reopens with it. cancelled is final. Returns the Goal as get_goal reads it, at its new revision.`;
|
|
1598
|
+
var GET_GOAL_DESCRIPTION = "Read one Goal without claiming it: its outcome, state, revision, progress, blockers, the conversation on it (each question with its options and what was decided), `next`, the one step to take, and `more`, where to read further. The conversation carries everything the person said, every open question and your newest entry; your older entries are left out and counted \u2014 history: true reads every entry in full. Another account's Goals, and another agent's Goal that is not below one of yours, are not disclosed.\n\ndiagnose: true is for when a read has CONFUSED you \u2014 not for the working loop. It adds `diagnosis`, which asks every reader that already answers a question about your work and NAMES the reader behind every value, so you never guess which of two places to look: what state your work is really in (the stored `goals.state` beside the derived `goal_execution_state`, which can differ); whether anything is armed to ring and when (`ladder_candidates`, with the ladder's own last decision); whether a wake fired for you and what it did (durable `wake.*` events, beside when your process was last heard from); and what has reached you (`list_waiting` \u2014 review flags, unstarted work, open questions, the person's newest words). Read `diagnosis.disagreements` FIRST: each one is two readers giving different values for the same fact, with both values and both sources, and it never chooses between them \u2014 that is yours to do, from the Goal's own history. `diagnosis.looked` names every reader asked, including any that could not answer, so an empty answer is never confused with a broken one.";
|
|
1599
|
+
var UPDATE_GOAL_DESCRIPTION = `Update an owned Goal at an exact revision. State, ownership, dependencies, children, progress, title, and review acknowledgement are explicit; stale revisions are rejected. title is the work's name in one to five words, as a person would refer to it out loud (it is spoken on a call and heads every list); null clears it. reviewed: true acknowledges new evidence and closes the Deliveries addressed to you on that Goal, never over an open decision. dueAt (an ISO instant, or null) makes the Goal wait until then; when it passes you are woken for it \u2014 use it for a promise to follow up later. withdraw: [questionId] takes back a question YOU asked on this Goal that is still open \u2014 because you acted on it yourself, it no longer matters, or you asked it wrongly (e.g. waiting: hard when nothing was blocked): it is cancelled, not answered, its card closes and it stops ringing; the id is the one the conversation shows. state: done means the work was accomplished, and it can be reopened: when the person says it is not done ("it's not working"), set state: active on that same Goal instead of starting a new one; its parent reopens with it. state: done while children are still open records your part as done: the Goal waits and closes by itself when its last open child closes. cancelled is final. Returns the Goal as get_goal reads it, at its new revision.`;
|
|
1592
1600
|
var CLAIM_GOAL_DESCRIPTION = "Claim the oldest runnable or review-pending Goal you own, or pass goalId to claim that Goal. Another agent's Goal that has gone quiet for 3 days (check_replies lists them as stalledOthers) is taken over when you claim it, and becomes yours to finish or cancel. Returns the Goal as get_goal reads it, and creates or renews the execution lease.";
|
|
1593
1601
|
var CHECK_REPLIES_DESCRIPTION = "What is waiting for you: your open Deliveries (a request the user started toward you, a handoff), one row each with its Goals, how many decisions are still open, and the newest words in brief; `assigned`, your Goals nobody has started yet, however they became yours (claim_goal({goalId}) starts one); and `review`, your Goals with something new on them \u2014 the user's answers and notes are Entries on the Goal, not Deliveries. 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 a Delivery in full with contact({deliveryId}). Once you have acted on what arrived, update_goal with reviewed: true clears the Goal from `review` and closes the Deliveries addressed to you on it.";
|
|
1594
1602
|
var CheckRepliesSchema = z3.object({}).strict();
|
|
@@ -2207,18 +2215,20 @@ var UserSettingsSchema = z4.object({
|
|
|
2207
2215
|
* clobber guard as voiceMode: absent = leave unchanged on write. */
|
|
2208
2216
|
broker: BrokerTuningSchema.optional()
|
|
2209
2217
|
});
|
|
2210
|
-
var
|
|
2218
|
+
var HistoryWorkSchema = z4.object({
|
|
2211
2219
|
id: z4.string(),
|
|
2212
|
-
/** 'user' = a request you sent; 'agent' = a notification an agent sent you. */
|
|
2213
|
-
initiator: z4.enum(["user", "agent"]),
|
|
2214
2220
|
title: z4.string(),
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2221
|
+
state: z4.enum(["done", "cancelled"]),
|
|
2222
|
+
/** Who held it (`agent:<tokenId>` or `human:<userId>`). */
|
|
2223
|
+
assignee: z4.string()
|
|
2224
|
+
});
|
|
2225
|
+
var HistoryEntrySchema = z4.union([
|
|
2226
|
+
z4.object({ at: z4.string(), card: InboxItemSchema }),
|
|
2227
|
+
z4.object({ at: z4.string(), work: HistoryWorkSchema })
|
|
2228
|
+
]);
|
|
2229
|
+
var HistoryPageSchema = z4.object({
|
|
2230
|
+
entries: z4.array(HistoryEntrySchema),
|
|
2231
|
+
next: z4.string().nullable()
|
|
2222
2232
|
});
|
|
2223
2233
|
var ACTIVITY_LINES = 2;
|
|
2224
2234
|
var ACTIVITY_LINE_MAX = 80;
|
|
@@ -2402,6 +2412,9 @@ var QueueItemSchema = z4.object({
|
|
|
2402
2412
|
progressLine: z4.string().nullable().optional(),
|
|
2403
2413
|
reviewPending: z4.boolean().default(false),
|
|
2404
2414
|
dueAt: z4.string().nullable().default(null),
|
|
2415
|
+
/** WHEN ITS OWNER SAID DONE WHILE CHILDREN WERE OPEN (#2704): its own work is finished and it closes
|
|
2416
|
+
* with its last open child. Null otherwise; optional, so hand-built queues need not spell it. */
|
|
2417
|
+
finishedAt: z4.string().nullable().optional(),
|
|
2405
2418
|
/** The Goal this one was opened under; null at the root. */
|
|
2406
2419
|
parentGoalId: z4.string().nullable().default(null),
|
|
2407
2420
|
/** Goals opened under this one — only those the same list holds. */
|
|
@@ -2410,8 +2423,17 @@ var QueueItemSchema = z4.object({
|
|
|
2410
2423
|
dependencyGoalIds: z4.array(z4.string()).default([]),
|
|
2411
2424
|
/** True while any gate is on a Goal that is not done — the walk draws it dashed. */
|
|
2412
2425
|
blocked: z4.boolean().default(false),
|
|
2413
|
-
/**
|
|
2426
|
+
/** Its questions: every OPEN one, and at most ten settled, newest settled first
|
|
2427
|
+
* (20260929133308) — the page decides which of them to show. NOT the whole set: `asked` and
|
|
2428
|
+
* `answered` are, and a settled one's words are a line (280 characters), its body read when the
|
|
2429
|
+
* question is opened. */
|
|
2414
2430
|
questions: z4.array(QueueQuestionSchema).default([]),
|
|
2431
|
+
/** HOW MANY QUESTIONS THIS WORK HAS ASKED, and how many are answered — the Goal's own totals,
|
|
2432
|
+
* bounded at 100 server-side. A tally counted off `questions` is a wrong number that looks
|
|
2433
|
+
* right once the cap bites (`walk/trees.ts` `tallyOf`). Optional, and defaulted from the array
|
|
2434
|
+
* by the projection, so hand-built queues (fixtures, the demo) need not spell them. */
|
|
2435
|
+
asked: z4.number().optional(),
|
|
2436
|
+
answered: z4.number().optional(),
|
|
2415
2437
|
/** Every note on it the person replied to (`QueueReplySchema`) — the page decides which to show.
|
|
2416
2438
|
* Optional, not defaulted: absent is none, and every hand-built queue (fixtures, the demo) need
|
|
2417
2439
|
* not spell an empty list. */
|
|
@@ -2548,6 +2570,19 @@ var DeliveryConfigSchema = z4.object({
|
|
|
2548
2570
|
* carries credentials; only a `poll` registration can come back with null here. */
|
|
2549
2571
|
realtime: z4.object({ url: z4.string(), anonKey: z4.string() }).nullable()
|
|
2550
2572
|
});
|
|
2573
|
+
var HostDecisionSchema = z4.object({
|
|
2574
|
+
/** The agent's token id: the row's `recipient`. */
|
|
2575
|
+
agent: z4.string().uuid(),
|
|
2576
|
+
decision: z4.enum(["stood_back", "took_over"]),
|
|
2577
|
+
/** The work it was about: the Goal `claim_goal` would hand that agent next. */
|
|
2578
|
+
goalId: z4.string().uuid().nullable().optional(),
|
|
2579
|
+
/** When the server last heard from the agent, as the host read it: the presence it stood back for. */
|
|
2580
|
+
seenAt: z4.string().datetime().nullable().optional(),
|
|
2581
|
+
/** When that work last moved (`claimable.since` on `check_replies`), the fact the bound is judged on. */
|
|
2582
|
+
since: z4.string().datetime().nullable().optional(),
|
|
2583
|
+
/** What the host said, in its log's own words: why it stood back, or what the take-over did. */
|
|
2584
|
+
said: z4.string().max(300).optional()
|
|
2585
|
+
});
|
|
2551
2586
|
var WakeNudgeSchema = z4.object({
|
|
2552
2587
|
kind: z4.enum(["reply", "request", "callback"]),
|
|
2553
2588
|
notificationId: z4.string().optional(),
|
|
@@ -2592,6 +2627,9 @@ var DeviceTokenSchema = z4.object({
|
|
|
2592
2627
|
* landed in the FIRST granted workspace and the agent rediscovered its own repo from
|
|
2593
2628
|
* the thread each time (host.ts, live catch 2026-08-06 — prompt-papered until now). */
|
|
2594
2629
|
workspace: z4.string().nullable().optional(),
|
|
2630
|
+
/** Local host recovery must preserve the launch's runtime and Paigy identity. */
|
|
2631
|
+
harness: z4.enum(["claude", "codex", "agy"]).optional(),
|
|
2632
|
+
session_id: z4.string().uuid().optional(),
|
|
2595
2633
|
uik_pub: z4.string().nullable().optional()
|
|
2596
2634
|
});
|
|
2597
2635
|
var SupportRequestSchema = z4.object({
|
|
@@ -2771,7 +2809,7 @@ function updateSlot(agent2, patch) {
|
|
|
2771
2809
|
}
|
|
2772
2810
|
function slotIdentity(agent2) {
|
|
2773
2811
|
const t = readTokenFile()[agent2];
|
|
2774
|
-
return { name: t?.name ?? null, voice: t?.voice ?? null, tokenId: t?.token_id ?? null, workspace: t?.workspace ?? null };
|
|
2812
|
+
return { name: t?.name ?? null, voice: t?.voice ?? null, tokenId: t?.token_id ?? null, workspace: t?.workspace ?? null, harness: t?.harness ?? null, sessionId: t?.session_id ?? null };
|
|
2775
2813
|
}
|
|
2776
2814
|
var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
2777
2815
|
function readToken(agent2 = agentName()) {
|
|
@@ -2835,9 +2873,21 @@ var UnpairedError = class extends Error {
|
|
|
2835
2873
|
this.name = "UnpairedError";
|
|
2836
2874
|
}
|
|
2837
2875
|
};
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2876
|
+
var RevokedError = class extends UnpairedError {
|
|
2877
|
+
constructor() {
|
|
2878
|
+
super();
|
|
2879
|
+
this.message = "This identity was revoked (the API answered 401 revoked): its credential is gone for good. Pairing again makes a new identity.";
|
|
2880
|
+
this.name = "RevokedError";
|
|
2881
|
+
}
|
|
2882
|
+
};
|
|
2883
|
+
async function ensureAuthed(res) {
|
|
2884
|
+
if (res.status !== 401) return res;
|
|
2885
|
+
let body = null;
|
|
2886
|
+
try {
|
|
2887
|
+
body = await res.json();
|
|
2888
|
+
} catch {
|
|
2889
|
+
}
|
|
2890
|
+
throw body?.error === "revoked" ? new RevokedError() : new UnpairedError();
|
|
2841
2891
|
}
|
|
2842
2892
|
var ApiError = class extends Error {
|
|
2843
2893
|
status;
|
|
@@ -2864,7 +2914,7 @@ async function fail(what, res) {
|
|
|
2864
2914
|
}
|
|
2865
2915
|
async function createGoal(input, opts = {}) {
|
|
2866
2916
|
const token = authToken(opts.token) ?? "";
|
|
2867
|
-
const res = ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals`, {
|
|
2917
|
+
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals`, {
|
|
2868
2918
|
method: "POST",
|
|
2869
2919
|
headers: { "content-type": "application/json", authorization: `Bearer ${token}`, "x-paigy-model": "goal-entry-v1" },
|
|
2870
2920
|
body: JSON.stringify(input)
|
|
@@ -2874,13 +2924,14 @@ async function createGoal(input, opts = {}) {
|
|
|
2874
2924
|
}
|
|
2875
2925
|
async function claimGoal(goalId, opts = {}) {
|
|
2876
2926
|
const token = authToken(opts.token) ?? "";
|
|
2877
|
-
const res = ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/claim`, { method: "POST", headers: { "content-type": "application/json", authorization: `Bearer ${token}`, "x-paigy-model": "goal-entry-v1" }, body: JSON.stringify(goalId ? { goalId } : {}) }));
|
|
2927
|
+
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/claim`, { method: "POST", headers: { "content-type": "application/json", authorization: `Bearer ${token}`, "x-paigy-model": "goal-entry-v1" }, body: JSON.stringify(goalId ? { goalId } : {}) }));
|
|
2878
2928
|
if (!res.ok) await fail("claim_goal", res);
|
|
2879
2929
|
return await res.json();
|
|
2880
2930
|
}
|
|
2881
2931
|
async function getGoal(goalId, opts = {}, read = {}) {
|
|
2882
2932
|
const token = authToken(opts.token) ?? "";
|
|
2883
|
-
const
|
|
2933
|
+
const query = [read.history ? "history=1" : "", read.diagnose ? "diagnose=1" : ""].filter(Boolean).join("&");
|
|
2934
|
+
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/${encodeURIComponent(goalId)}${query ? `?${query}` : ""}`, {
|
|
2884
2935
|
method: "GET",
|
|
2885
2936
|
headers: { authorization: `Bearer ${token}`, "x-paigy-model": "goal-entry-v1" }
|
|
2886
2937
|
}));
|
|
@@ -2890,13 +2941,13 @@ async function getGoal(goalId, opts = {}, read = {}) {
|
|
|
2890
2941
|
async function updateGoal(goalId, input, opts = {}) {
|
|
2891
2942
|
const token = authToken(opts.token) ?? "";
|
|
2892
2943
|
const operationId = input.operationId ?? randomUUID2();
|
|
2893
|
-
const res = ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/${encodeURIComponent(goalId)}`, { method: "PATCH", headers: { "content-type": "application/json", authorization: `Bearer ${token}`, "x-paigy-model": "goal-entry-v1" }, body: JSON.stringify({ ...input, operationId }) }));
|
|
2944
|
+
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/${encodeURIComponent(goalId)}`, { method: "PATCH", headers: { "content-type": "application/json", authorization: `Bearer ${token}`, "x-paigy-model": "goal-entry-v1" }, body: JSON.stringify({ ...input, operationId }) }));
|
|
2894
2945
|
if (!res.ok) await fail("update_goal", res);
|
|
2895
2946
|
return await res.json();
|
|
2896
2947
|
}
|
|
2897
2948
|
var AWAIT_WINDOW_MS = 45e3;
|
|
2898
2949
|
async function hatch(name, voice = null) {
|
|
2899
|
-
const res = ensureAuthed(await reach(`${BACKEND_URL}/api/hatch`, {
|
|
2950
|
+
const res = await ensureAuthed(await reach(`${BACKEND_URL}/api/hatch`, {
|
|
2900
2951
|
method: "POST",
|
|
2901
2952
|
headers: { "content-type": "application/json", authorization: `Bearer ${authToken()}` },
|
|
2902
2953
|
body: JSON.stringify({ name, voice })
|
|
@@ -2918,7 +2969,7 @@ var NameTakenError = class extends Error {
|
|
|
2918
2969
|
code = "agent_name_taken";
|
|
2919
2970
|
};
|
|
2920
2971
|
async function setIdentity(patch, opts = {}) {
|
|
2921
|
-
const res = ensureAuthed(await reach(`${BACKEND_URL}/api/identity`, {
|
|
2972
|
+
const res = await ensureAuthed(await reach(`${BACKEND_URL}/api/identity`, {
|
|
2922
2973
|
method: "PATCH",
|
|
2923
2974
|
headers: { "content-type": "application/json", authorization: `Bearer ${authToken(opts.token)}` },
|
|
2924
2975
|
body: JSON.stringify(patch)
|
|
@@ -2938,19 +2989,27 @@ async function setIdentity(patch, opts = {}) {
|
|
|
2938
2989
|
return await res.json();
|
|
2939
2990
|
}
|
|
2940
2991
|
async function claimSessions(opts = {}) {
|
|
2941
|
-
const res = ensureAuthed(await reach(`${BACKEND_URL}/api/sessions/claim`, {
|
|
2992
|
+
const res = await ensureAuthed(await reach(`${BACKEND_URL}/api/sessions/claim`, {
|
|
2942
2993
|
headers: { authorization: `Bearer ${authToken(opts.token)}` }
|
|
2943
2994
|
// the HOST's identity
|
|
2944
2995
|
}));
|
|
2945
2996
|
if (!res.ok) throw new Error(`claim_sessions failed: ${res.status}`);
|
|
2946
2997
|
return (await res.json()).sessions;
|
|
2947
2998
|
}
|
|
2999
|
+
async function recordDecision(decision, opts = {}) {
|
|
3000
|
+
const res = await ensureAuthed(await reach(`${BACKEND_URL}/api/host/decisions`, {
|
|
3001
|
+
method: "POST",
|
|
3002
|
+
headers: { "content-type": "application/json", authorization: `Bearer ${authToken(opts.token)}` },
|
|
3003
|
+
body: JSON.stringify(decision)
|
|
3004
|
+
}));
|
|
3005
|
+
if (!res.ok) await fail("record_decision", res);
|
|
3006
|
+
}
|
|
2948
3007
|
async function heartbeat(runtime, opts = {}) {
|
|
2949
3008
|
const body = {
|
|
2950
3009
|
...runtime !== void 0 ? { runtime } : {},
|
|
2951
3010
|
...opts.activity !== void 0 ? { activity: opts.activity } : {}
|
|
2952
3011
|
};
|
|
2953
|
-
const res = ensureAuthed(await reach(`${BACKEND_URL}/api/presence`, {
|
|
3012
|
+
const res = await ensureAuthed(await reach(`${BACKEND_URL}/api/presence`, {
|
|
2954
3013
|
method: "POST",
|
|
2955
3014
|
headers: { "content-type": "application/json", authorization: `Bearer ${authToken(opts.token)}` },
|
|
2956
3015
|
...Object.keys(body).length > 0 ? { body: JSON.stringify(body) } : {}
|
|
@@ -2958,7 +3017,7 @@ async function heartbeat(runtime, opts = {}) {
|
|
|
2958
3017
|
if (!res.ok) throw new Error(`heartbeat failed: ${res.status}`);
|
|
2959
3018
|
}
|
|
2960
3019
|
async function registerDelivery(mode, opts = {}) {
|
|
2961
|
-
const res = ensureAuthed(await reach(`${BACKEND_URL}/api/delivery`, {
|
|
3020
|
+
const res = await ensureAuthed(await reach(`${BACKEND_URL}/api/delivery`, {
|
|
2962
3021
|
method: "POST",
|
|
2963
3022
|
headers: { "content-type": "application/json", authorization: `Bearer ${authToken(opts.token)}` },
|
|
2964
3023
|
body: JSON.stringify({ mode })
|
|
@@ -2967,21 +3026,21 @@ async function registerDelivery(mode, opts = {}) {
|
|
|
2967
3026
|
return await res.json();
|
|
2968
3027
|
}
|
|
2969
3028
|
async function listNotes(opts = {}) {
|
|
2970
|
-
const res = ensureAuthed(await reach(`${BACKEND_URL}/api/notes`, {
|
|
3029
|
+
const res = await ensureAuthed(await reach(`${BACKEND_URL}/api/notes`, {
|
|
2971
3030
|
headers: { authorization: `Bearer ${authToken(opts.token)}` }
|
|
2972
3031
|
}));
|
|
2973
3032
|
if (!res.ok) throw new Error(`list_notes failed: ${res.status} ${await res.text()}`);
|
|
2974
3033
|
return await res.json();
|
|
2975
3034
|
}
|
|
2976
3035
|
async function listConnections(opts = {}) {
|
|
2977
|
-
const res = ensureAuthed(await reach(`${BACKEND_URL}/api/tokens`, {
|
|
3036
|
+
const res = await ensureAuthed(await reach(`${BACKEND_URL}/api/tokens`, {
|
|
2978
3037
|
headers: { authorization: `Bearer ${authToken(opts.token)}`, "x-paigy-model": "goal-entry-v1" }
|
|
2979
3038
|
}));
|
|
2980
3039
|
if (!res.ok) throw new Error(`list_connections failed: ${res.status} ${await res.text()}`);
|
|
2981
3040
|
return await res.json();
|
|
2982
3041
|
}
|
|
2983
3042
|
async function submitTriage(run, opts = {}) {
|
|
2984
|
-
const res = ensureAuthed(await reach(`${BACKEND_URL}/api/triage`, {
|
|
3043
|
+
const res = await ensureAuthed(await reach(`${BACKEND_URL}/api/triage`, {
|
|
2985
3044
|
method: "POST",
|
|
2986
3045
|
headers: { "content-type": "application/json", authorization: `Bearer ${authToken(opts.token)}` },
|
|
2987
3046
|
body: JSON.stringify(run)
|
|
@@ -2990,14 +3049,14 @@ async function submitTriage(run, opts = {}) {
|
|
|
2990
3049
|
return await res.json();
|
|
2991
3050
|
}
|
|
2992
3051
|
async function getTriage(opts = {}) {
|
|
2993
|
-
const res = ensureAuthed(await reach(`${BACKEND_URL}/api/triage`, {
|
|
3052
|
+
const res = await ensureAuthed(await reach(`${BACKEND_URL}/api/triage`, {
|
|
2994
3053
|
headers: { authorization: `Bearer ${authToken(opts.token)}` }
|
|
2995
3054
|
}));
|
|
2996
3055
|
if (!res.ok) throw new Error(`get_triage failed: ${res.status} ${await res.text()}`);
|
|
2997
3056
|
return await res.json();
|
|
2998
3057
|
}
|
|
2999
3058
|
async function acceptTriage(proposalId, body, opts = {}) {
|
|
3000
|
-
const res = ensureAuthed(await reach(`${BACKEND_URL}/api/triage/${encodeURIComponent(proposalId)}/accept`, {
|
|
3059
|
+
const res = await ensureAuthed(await reach(`${BACKEND_URL}/api/triage/${encodeURIComponent(proposalId)}/accept`, {
|
|
3001
3060
|
method: "POST",
|
|
3002
3061
|
headers: { "content-type": "application/json", authorization: `Bearer ${authToken(opts.token)}` },
|
|
3003
3062
|
body: JSON.stringify(body)
|
|
@@ -3006,7 +3065,7 @@ async function acceptTriage(proposalId, body, opts = {}) {
|
|
|
3006
3065
|
return await res.json();
|
|
3007
3066
|
}
|
|
3008
3067
|
async function dismissTriage(proposalId, opts = {}) {
|
|
3009
|
-
const res = ensureAuthed(await reach(`${BACKEND_URL}/api/triage/${encodeURIComponent(proposalId)}/dismiss`, {
|
|
3068
|
+
const res = await ensureAuthed(await reach(`${BACKEND_URL}/api/triage/${encodeURIComponent(proposalId)}/dismiss`, {
|
|
3010
3069
|
method: "POST",
|
|
3011
3070
|
headers: { authorization: `Bearer ${authToken(opts.token)}` }
|
|
3012
3071
|
}));
|
|
@@ -3062,7 +3121,7 @@ async function contact(input, opts = {}) {
|
|
|
3062
3121
|
ask: a.ask,
|
|
3063
3122
|
options: a.options ?? []
|
|
3064
3123
|
}));
|
|
3065
|
-
const res = ensureAuthed(await send2(`${BACKEND_URL}/api/goals/contact`, {
|
|
3124
|
+
const res = await ensureAuthed(await send2(`${BACKEND_URL}/api/goals/contact`, {
|
|
3066
3125
|
method: "POST",
|
|
3067
3126
|
headers,
|
|
3068
3127
|
signal: opts.signal,
|
|
@@ -3084,15 +3143,17 @@ async function contact(input, opts = {}) {
|
|
|
3084
3143
|
}
|
|
3085
3144
|
const all = deliveries.filter((d) => !!d.deliveryId && !!d.goalId).map(({ id, deliveryId: deliveryId2, goalId }) => ({ ...id ? { id } : {}, deliveryId: deliveryId2, goalId }));
|
|
3086
3145
|
const joinedCard = deliveries[0]?.joinedCard === true;
|
|
3146
|
+
const joinedCall = deliveries[0]?.joinedCall === true;
|
|
3087
3147
|
const read = async (signal2) => {
|
|
3088
|
-
const res = ensureAuthed(await send2(`${BACKEND_URL}/api/deliveries/${encodeURIComponent(deliveryId)}`, { headers, signal: signal2 }));
|
|
3148
|
+
const res = await ensureAuthed(await send2(`${BACKEND_URL}/api/deliveries/${encodeURIComponent(deliveryId)}`, { headers, signal: signal2 }));
|
|
3089
3149
|
if (!res.ok) await fail("read_delivery", res);
|
|
3090
3150
|
const one = await res.json();
|
|
3091
3151
|
return {
|
|
3092
3152
|
...one,
|
|
3093
3153
|
...all.length > 1 ? { deliveries: all } : {},
|
|
3094
3154
|
...recorded.length ? { recorded, notSent: NOT_SENT } : {},
|
|
3095
|
-
...joinedCard ? { joinedCard: true } : {}
|
|
3155
|
+
...joinedCard ? { joinedCard: true } : {},
|
|
3156
|
+
...joinedCall ? { joinedCall: true } : {}
|
|
3096
3157
|
};
|
|
3097
3158
|
};
|
|
3098
3159
|
const settled = (d) => d.kind === "notification" || d.state === "closed" || d.answers.length > 0 || d.entries.some((e) => e.kind === "contribution");
|
|
@@ -3114,7 +3175,7 @@ async function contact(input, opts = {}) {
|
|
|
3114
3175
|
}
|
|
3115
3176
|
}
|
|
3116
3177
|
async function checkReplies(opts = {}) {
|
|
3117
|
-
const res = ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/deliveries`, {
|
|
3178
|
+
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/deliveries`, {
|
|
3118
3179
|
headers: { authorization: `Bearer ${authToken(opts.token) ?? ""}`, "x-paigy-model": "goal-entry-v1" }
|
|
3119
3180
|
}));
|
|
3120
3181
|
if (!res.ok) await fail("check_replies", res);
|
|
@@ -3206,6 +3267,7 @@ function goalView(g) {
|
|
|
3206
3267
|
more: more(g)
|
|
3207
3268
|
});
|
|
3208
3269
|
}
|
|
3270
|
+
var JOINED_CALL = "This ask joined the call the person is ALREADY ON \u2014 no ring, no card of its own. `conversation` above is that whole call, so the answers already given on it before your ask arrived are in it. Yours is queued for the bot's next turn: call contact({deliveryId}) again to keep reading this same call until your answer lands \u2014 do not resend the ask. To add information or a further question to the same call, contact again while it is live; that joins it too.";
|
|
3209
3271
|
function deliveryView(d) {
|
|
3210
3272
|
const answers = "Answers land on the Goal: read them with claim_goal or get_goal. Do not poll this notification.";
|
|
3211
3273
|
return compact({
|
|
@@ -3220,7 +3282,8 @@ function deliveryView(d) {
|
|
|
3220
3282
|
recorded: d.recorded,
|
|
3221
3283
|
notSent: d.notSent,
|
|
3222
3284
|
joinedCard: d.joinedCard,
|
|
3223
|
-
|
|
3285
|
+
joinedCall: d.joinedCall,
|
|
3286
|
+
next: d.joinedCall ? `${JOINED_CALL}${d.message ? ` ${d.message}` : ""}` : d.kind === "notification" ? d.joinedCard ? `Added to the open report card on its Goal; no new push was sent. ${answers}` : answers : d.state === "open" && d.decisionNeeds.some((n) => n.state === "open") ? `Decision pending. Call contact(${JSON.stringify({ deliveryId: d.deliveryId })}) now to continue this same Call; do not resend the ask or end your turn merely because this wait window returned. ${d.message ?? ""}`.trim() : d.message
|
|
3224
3287
|
});
|
|
3225
3288
|
}
|
|
3226
3289
|
function repliesView(r) {
|
|
@@ -3255,7 +3318,11 @@ function repliesView(r) {
|
|
|
3255
3318
|
next: [
|
|
3256
3319
|
deliveries.length || r.claimable || review.length || assigned.length ? "Act on a Goal with claim_goal; reread one Delivery in full with contact({deliveryId})." : "Nothing is waiting.",
|
|
3257
3320
|
...assigned.length ? [`${assigned.length} of your Goals are assigned to you and not started (assigned): claim_goal({goalId}) to start one.`] : [],
|
|
3258
|
-
|
|
3321
|
+
// THE PERSON SPOKE, AND THAT IS NOT "SOMETHING NEW" (2026-09-29). This line said only how
|
|
3322
|
+
// many Goals were flagged, so four things the owner said on a call read as four chores. The
|
|
3323
|
+
// rows carry their words now (`said`, `saidAt`, newest first, `delivery/read.ts`); the
|
|
3324
|
+
// sentence names the person and quotes the freshest one, because a count is not a message.
|
|
3325
|
+
...review.length ? [spoke(review) ?? `${review.length} of your Goals have something new (review): read each with claim_goal or get_goal, then update_goal with reviewed: true.`] : [],
|
|
3259
3326
|
...stalled.length ? [`${stalled.length} of your Goals have had no progress for 3 days: update_goal each with progress, finish it, or cancel it.`] : [],
|
|
3260
3327
|
...others.length ? [`${others.length} of other agents' Goals have gone quiet for 3 days: claim_goal({goalId}) takes one over, then finish or cancel it with update_goal.`] : [],
|
|
3261
3328
|
// No name of its own (#2525): the API's ask, verbatim.
|
|
@@ -3263,6 +3330,13 @@ function repliesView(r) {
|
|
|
3263
3330
|
].join(" ")
|
|
3264
3331
|
};
|
|
3265
3332
|
}
|
|
3333
|
+
function spoke(review) {
|
|
3334
|
+
const withWords = review.filter((r) => r.said?.trim());
|
|
3335
|
+
if (!withWords.length) return null;
|
|
3336
|
+
const newest = withWords[0];
|
|
3337
|
+
const rest = review.length - 1;
|
|
3338
|
+
return `The person has spoken on ${withWords.length === 1 ? "one of your Goals" : `${withWords.length} of your Goals`} \u2014 newest, on ${newest.title ?? newest.goalId}: "${newest.said}". Read it with claim_goal or get_goal, answer what it asks, then update_goal with reviewed: true.${rest > 0 ? ` (${rest} more flagged; see review.)` : ""}`;
|
|
3339
|
+
}
|
|
3266
3340
|
async function runTool(name, args, opts) {
|
|
3267
3341
|
const { waits, signal, ...client } = opts;
|
|
3268
3342
|
const input = args ?? {};
|
|
@@ -3283,8 +3357,11 @@ async function runTool(name, args, opts) {
|
|
|
3283
3357
|
return goalView(await claimGoal(goalId, client));
|
|
3284
3358
|
}
|
|
3285
3359
|
case "get_goal": {
|
|
3286
|
-
const { goalId, history } = GetGoalSchema.parse(input);
|
|
3287
|
-
|
|
3360
|
+
const { goalId, history, diagnose } = GetGoalSchema.parse(input);
|
|
3361
|
+
const goal = await getGoal(goalId, client, { history, diagnose });
|
|
3362
|
+
const view = goalView(goal);
|
|
3363
|
+
const diagnosis = goal.diagnosis;
|
|
3364
|
+
return diagnosis === void 0 ? view : { ...view, diagnosis };
|
|
3288
3365
|
}
|
|
3289
3366
|
case "update_goal": {
|
|
3290
3367
|
const { goalId, ...body } = UpdateGoalToolSchema.parse(input);
|
|
@@ -3499,6 +3576,7 @@ export {
|
|
|
3499
3576
|
requestCode,
|
|
3500
3577
|
pollToken,
|
|
3501
3578
|
UnpairedError,
|
|
3579
|
+
RevokedError,
|
|
3502
3580
|
ApiError,
|
|
3503
3581
|
overrideToken,
|
|
3504
3582
|
authToken,
|
|
@@ -3512,6 +3590,7 @@ export {
|
|
|
3512
3590
|
NameTakenError,
|
|
3513
3591
|
setIdentity,
|
|
3514
3592
|
claimSessions,
|
|
3593
|
+
recordDecision,
|
|
3515
3594
|
heartbeat,
|
|
3516
3595
|
registerDelivery,
|
|
3517
3596
|
listNotes,
|
|
@@ -4,10 +4,10 @@ import {
|
|
|
4
4
|
serverInstructions,
|
|
5
5
|
sessionStartHook,
|
|
6
6
|
withSessionStartHook
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-RLN2B5IZ.js";
|
|
8
8
|
import {
|
|
9
9
|
agentName
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-6C6CO7H3.js";
|
|
11
11
|
|
|
12
12
|
// src/toolset.ts
|
|
13
13
|
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.";
|
|
@@ -57,18 +57,18 @@ var AskInputSchema = z2.object({
|
|
|
57
57
|
parentId: z2.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."),
|
|
58
58
|
repo: z2.string().optional().describe("Optional repository context."),
|
|
59
59
|
ask: z2.string().trim().min(1).max(1e4).describe(
|
|
60
|
-
"ONE question, and only what is needed to answer it. Several questions are several asks in the array, one each: an answer settles the one ask it was given in the shape that ask declares, so a person who answers the part of a bundled ask that interested them settles nothing and is asked again. Paigy reads every ask once and takes a bundled one apart into its own cards anyway \u2014
|
|
60
|
+
"ONE question, and only what is needed to answer it. Several questions are several asks in the array, one each: an answer settles the one ask it was given in the shape that ask declares, so a person who answers the part of a bundled ask that interested them settles nothing and is asked again. Paigy reads every ask once and takes a bundled one apart into its own cards anyway \u2014 each question a Question on the one Goal the ask lands on, never a Goal of its own \u2014 but the words it splits are its reading, not yours. News, progress and findings are their own contact; ANY contact for a person already on a call JOINS that call, whatever channel you asked for, so several arrive as one call."
|
|
61
61
|
),
|
|
62
|
-
options: z2.array(OptionInputSchema).min(
|
|
62
|
+
options: z2.array(OptionInputSchema).min(1).max(6).optional()
|
|
63
63
|
}).strict();
|
|
64
64
|
var StartContactSchema = z2.object({
|
|
65
65
|
asks: z2.array(AskInputSchema).min(1).describe("The questions to pose, one per object. An ask with a parentId is filed on that Goal as it is; only an ask naming no Goal is placed in the tree by Paigy."),
|
|
66
|
-
waiting: z2.enum(["none", "hard"]).default("none"),
|
|
66
|
+
waiting: z2.enum(["none", "hard"]).default("none").describe("hard requests a call even when channel is notification; user permissions and ring cooldowns still apply."),
|
|
67
67
|
channel: z2.enum(["notification", "call"]).default("notification")
|
|
68
68
|
}).strict();
|
|
69
69
|
var ContactSchema = z2.union([StartContactSchema, z2.object({ deliveryId: z2.string().uuid() }).strict()]);
|
|
70
70
|
var CONTACT_SCHEMA = { type: "object", ...mcpInputSchema(ContactSchema) };
|
|
71
|
-
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}. One question per 'ask'; several questions are several objects in 'asks'. A bundled ask is taken apart into its own cards by Paigy's one intake read
|
|
71
|
+
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}. One question per 'ask'; several questions are several objects in 'asks'. A bundled ask is taken apart into its own cards by Paigy's one intake read, every one on the Goal the ask lands on; separate pieces of work are separate asks. An ask with no options that is not blocking is a report, and a report is an UPDATE, never a claim on them: it reaches them and is listed apart from what waits on them, so no answer is owed and none should be awaited. On a Goal whose report card is still open it is added to that card, with no new push; one that only says where your work stands while under way is recorded as the Goal's progress, not sent (the result says so). Send options (or waiting:'hard') when you actually need an answer. If the person is already on a call, your contact joins that call automatically \u2014 whatever channel you asked for, with no ring \u2014 and the Delivery it returns IS that call: reread it with contact({deliveryId}) to see everything answered on it so far, and contact again while it is live to add information or a further question to the same call.";
|
|
72
72
|
var CreateGoalSchema = z3.object({
|
|
73
73
|
outcome: z3.string().trim().min(1).max(1e4),
|
|
74
74
|
/** The work's NAME (#2115) — one to five words, how a person refers to it out loud ("the night
|
|
@@ -106,7 +106,11 @@ var UpdateGoalSchema = z3.object({
|
|
|
106
106
|
state: z3.enum(["active", "done", "cancelled"]).optional(),
|
|
107
107
|
progress: z3.string().trim().min(1).max(1e4).optional(),
|
|
108
108
|
reviewed: z3.literal(true).optional(),
|
|
109
|
-
dueAt: z3.string().datetime({ offset: true }).nullable().optional()
|
|
109
|
+
dueAt: z3.string().datetime({ offset: true }).nullable().optional(),
|
|
110
|
+
/** WITHDRAW YOUR OWN QUESTION (#2777, owner 2026-09-30). The question's id as every read shows it
|
|
111
|
+
* (the conversation's `id`, eight characters, or the whole request Entry id), on THIS Goal, asked
|
|
112
|
+
* by you and still open. It is cancelled, not answered: its cards close and nothing rings for it. */
|
|
113
|
+
withdraw: z3.array(z3.string().trim().regex(/^[0-9a-fA-F-]{8,36}$/)).min(1).max(10).optional()
|
|
110
114
|
}).strict().refine((v) => Object.keys(v).length > 0),
|
|
111
115
|
reason: z3.string().trim().min(1).max(2e3),
|
|
112
116
|
operationId: z3.string().uuid().optional()
|
|
@@ -117,10 +121,14 @@ var GetGoalSchema = z3.object({
|
|
|
117
121
|
goalId: z3.string().uuid(),
|
|
118
122
|
/** Every entry in full. Without it the read carries the person's words, open questions and your
|
|
119
123
|
* newest entry, and counts what it left out (`apps/api/src/goal/collapse.ts`). */
|
|
120
|
-
history: z3.boolean().optional()
|
|
124
|
+
history: z3.boolean().optional(),
|
|
125
|
+
/** WHEN A READ HAS CONFUSED YOU. Adds `diagnosis`: every reader that already answers a question
|
|
126
|
+
* about this work, each answer attributed to the reader that gave it, and every disagreement
|
|
127
|
+
* between two of them named. Off by default; `apps/api/src/goal/diagnose-design.md`. */
|
|
128
|
+
diagnose: z3.boolean().optional()
|
|
121
129
|
}).strict();
|
|
122
|
-
var GET_GOAL_DESCRIPTION = "Read one Goal without claiming it: its outcome, state, revision, progress, blockers, the conversation on it (each question with its options and what was decided), `next`, the one step to take, and `more`, where to read further. The conversation carries everything the person said, every open question and your newest entry; your older entries are left out and counted \u2014 history: true reads every entry in full. Another account's Goals, and another agent's Goal that is not below one of yours, are not disclosed.";
|
|
123
|
-
var UPDATE_GOAL_DESCRIPTION = `Update an owned Goal at an exact revision. State, ownership, dependencies, children, progress, title, and review acknowledgement are explicit; stale revisions are rejected. title is the work's name in one to five words, as a person would refer to it out loud (it is spoken on a call and heads every list); null clears it. reviewed: true acknowledges new evidence and closes the Deliveries addressed to you on that Goal, never over an open decision. dueAt (an ISO instant, or null) makes the Goal wait until then; when it passes you are woken for it \u2014 use it for a promise to follow up later. state: done means the work was accomplished, and it can be reopened: when the person says it is not done ("it's not working"), set state: active on that same Goal instead of starting a new one; its parent reopens with it. cancelled is final. Returns the Goal as get_goal reads it, at its new revision.`;
|
|
130
|
+
var GET_GOAL_DESCRIPTION = "Read one Goal without claiming it: its outcome, state, revision, progress, blockers, the conversation on it (each question with its options and what was decided), `next`, the one step to take, and `more`, where to read further. The conversation carries everything the person said, every open question and your newest entry; your older entries are left out and counted \u2014 history: true reads every entry in full. Another account's Goals, and another agent's Goal that is not below one of yours, are not disclosed.\n\ndiagnose: true is for when a read has CONFUSED you \u2014 not for the working loop. It adds `diagnosis`, which asks every reader that already answers a question about your work and NAMES the reader behind every value, so you never guess which of two places to look: what state your work is really in (the stored `goals.state` beside the derived `goal_execution_state`, which can differ); whether anything is armed to ring and when (`ladder_candidates`, with the ladder's own last decision); whether a wake fired for you and what it did (durable `wake.*` events, beside when your process was last heard from); and what has reached you (`list_waiting` \u2014 review flags, unstarted work, open questions, the person's newest words). Read `diagnosis.disagreements` FIRST: each one is two readers giving different values for the same fact, with both values and both sources, and it never chooses between them \u2014 that is yours to do, from the Goal's own history. `diagnosis.looked` names every reader asked, including any that could not answer, so an empty answer is never confused with a broken one.";
|
|
131
|
+
var UPDATE_GOAL_DESCRIPTION = `Update an owned Goal at an exact revision. State, ownership, dependencies, children, progress, title, and review acknowledgement are explicit; stale revisions are rejected. title is the work's name in one to five words, as a person would refer to it out loud (it is spoken on a call and heads every list); null clears it. reviewed: true acknowledges new evidence and closes the Deliveries addressed to you on that Goal, never over an open decision. dueAt (an ISO instant, or null) makes the Goal wait until then; when it passes you are woken for it \u2014 use it for a promise to follow up later. withdraw: [questionId] takes back a question YOU asked on this Goal that is still open \u2014 because you acted on it yourself, it no longer matters, or you asked it wrongly (e.g. waiting: hard when nothing was blocked): it is cancelled, not answered, its card closes and it stops ringing; the id is the one the conversation shows. state: done means the work was accomplished, and it can be reopened: when the person says it is not done ("it's not working"), set state: active on that same Goal instead of starting a new one; its parent reopens with it. state: done while children are still open records your part as done: the Goal waits and closes by itself when its last open child closes. cancelled is final. Returns the Goal as get_goal reads it, at its new revision.`;
|
|
124
132
|
var CLAIM_GOAL_DESCRIPTION = "Claim the oldest runnable or review-pending Goal you own, or pass goalId to claim that Goal. Another agent's Goal that has gone quiet for 3 days (check_replies lists them as stalledOthers) is taken over when you claim it, and becomes yours to finish or cancel. Returns the Goal as get_goal reads it, and creates or renews the execution lease.";
|
|
125
133
|
var CHECK_REPLIES_DESCRIPTION = "What is waiting for you: your open Deliveries (a request the user started toward you, a handoff), one row each with its Goals, how many decisions are still open, and the newest words in brief; `assigned`, your Goals nobody has started yet, however they became yours (claim_goal({goalId}) starts one); and `review`, your Goals with something new on them \u2014 the user's answers and notes are Entries on the Goal, not Deliveries. 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 a Delivery in full with contact({deliveryId}). Once you have acted on what arrived, update_goal with reviewed: true clears the Goal from `review` and closes the Deliveries addressed to you on it.";
|
|
126
134
|
var CheckRepliesSchema = z3.object({}).strict();
|
|
@@ -133,16 +141,15 @@ var AGENT_TOOLS = [
|
|
|
133
141
|
{ name: "update_goal", description: UPDATE_GOAL_DESCRIPTION, inputSchema: mcpInputSchema(UpdateGoalToolSchema) }
|
|
134
142
|
];
|
|
135
143
|
var AGENT_TOOL_NAMES = AGENT_TOOLS.map((t) => t.name);
|
|
136
|
-
var DONE_MESSAGE = "When the work is done, send one message through contact saying what is done and anything the person needs to do or check.";
|
|
137
144
|
function serverInstructions(opts) {
|
|
138
145
|
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.";
|
|
139
|
-
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.
|
|
146
|
+
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.
|
|
140
147
|
|
|
141
148
|
HOW TO ASK:
|
|
142
149
|
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.
|
|
143
150
|
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.
|
|
144
151
|
3. \`waiting: hard\` only for a decision you are blocked on; \`waiting: none\` for a question you can keep working around.
|
|
145
|
-
4. Never hold the process open with while-loops.
|
|
152
|
+
4. Never hold the process open with while-loops. For an open Call with a pending decision, follow its \`next\` with another bounded \`contact({deliveryId})\` tool call; a returned wait window is not a completed conversation. Otherwise, yield only with a working listener or scheduled wakeup, and collect answers with \`check_replies\` or \`claim_goal\` on that wake.`;
|
|
146
153
|
}
|
|
147
154
|
function entryWords(entry) {
|
|
148
155
|
const content = entry.content;
|
|
@@ -750,18 +757,20 @@ var UserSettingsSchema = z4.object({
|
|
|
750
757
|
* clobber guard as voiceMode: absent = leave unchanged on write. */
|
|
751
758
|
broker: BrokerTuningSchema.optional()
|
|
752
759
|
});
|
|
753
|
-
var
|
|
760
|
+
var HistoryWorkSchema = z4.object({
|
|
754
761
|
id: z4.string(),
|
|
755
|
-
/** 'user' = a request you sent; 'agent' = a notification an agent sent you. */
|
|
756
|
-
initiator: z4.enum(["user", "agent"]),
|
|
757
762
|
title: z4.string(),
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
763
|
+
state: z4.enum(["done", "cancelled"]),
|
|
764
|
+
/** Who held it (`agent:<tokenId>` or `human:<userId>`). */
|
|
765
|
+
assignee: z4.string()
|
|
766
|
+
});
|
|
767
|
+
var HistoryEntrySchema = z4.union([
|
|
768
|
+
z4.object({ at: z4.string(), card: InboxItemSchema }),
|
|
769
|
+
z4.object({ at: z4.string(), work: HistoryWorkSchema })
|
|
770
|
+
]);
|
|
771
|
+
var HistoryPageSchema = z4.object({
|
|
772
|
+
entries: z4.array(HistoryEntrySchema),
|
|
773
|
+
next: z4.string().nullable()
|
|
765
774
|
});
|
|
766
775
|
var ACTIVITY_LINES = 2;
|
|
767
776
|
var ACTIVITY_LINE_MAX = 80;
|
|
@@ -945,6 +954,9 @@ var QueueItemSchema = z4.object({
|
|
|
945
954
|
progressLine: z4.string().nullable().optional(),
|
|
946
955
|
reviewPending: z4.boolean().default(false),
|
|
947
956
|
dueAt: z4.string().nullable().default(null),
|
|
957
|
+
/** WHEN ITS OWNER SAID DONE WHILE CHILDREN WERE OPEN (#2704): its own work is finished and it closes
|
|
958
|
+
* with its last open child. Null otherwise; optional, so hand-built queues need not spell it. */
|
|
959
|
+
finishedAt: z4.string().nullable().optional(),
|
|
948
960
|
/** The Goal this one was opened under; null at the root. */
|
|
949
961
|
parentGoalId: z4.string().nullable().default(null),
|
|
950
962
|
/** Goals opened under this one — only those the same list holds. */
|
|
@@ -953,8 +965,17 @@ var QueueItemSchema = z4.object({
|
|
|
953
965
|
dependencyGoalIds: z4.array(z4.string()).default([]),
|
|
954
966
|
/** True while any gate is on a Goal that is not done — the walk draws it dashed. */
|
|
955
967
|
blocked: z4.boolean().default(false),
|
|
956
|
-
/**
|
|
968
|
+
/** Its questions: every OPEN one, and at most ten settled, newest settled first
|
|
969
|
+
* (20260929133308) — the page decides which of them to show. NOT the whole set: `asked` and
|
|
970
|
+
* `answered` are, and a settled one's words are a line (280 characters), its body read when the
|
|
971
|
+
* question is opened. */
|
|
957
972
|
questions: z4.array(QueueQuestionSchema).default([]),
|
|
973
|
+
/** HOW MANY QUESTIONS THIS WORK HAS ASKED, and how many are answered — the Goal's own totals,
|
|
974
|
+
* bounded at 100 server-side. A tally counted off `questions` is a wrong number that looks
|
|
975
|
+
* right once the cap bites (`walk/trees.ts` `tallyOf`). Optional, and defaulted from the array
|
|
976
|
+
* by the projection, so hand-built queues (fixtures, the demo) need not spell them. */
|
|
977
|
+
asked: z4.number().optional(),
|
|
978
|
+
answered: z4.number().optional(),
|
|
958
979
|
/** Every note on it the person replied to (`QueueReplySchema`) — the page decides which to show.
|
|
959
980
|
* Optional, not defaulted: absent is none, and every hand-built queue (fixtures, the demo) need
|
|
960
981
|
* not spell an empty list. */
|
|
@@ -1089,6 +1110,19 @@ var DeliveryConfigSchema = z4.object({
|
|
|
1089
1110
|
* carries credentials; only a `poll` registration can come back with null here. */
|
|
1090
1111
|
realtime: z4.object({ url: z4.string(), anonKey: z4.string() }).nullable()
|
|
1091
1112
|
});
|
|
1113
|
+
var HostDecisionSchema = z4.object({
|
|
1114
|
+
/** The agent's token id: the row's `recipient`. */
|
|
1115
|
+
agent: z4.string().uuid(),
|
|
1116
|
+
decision: z4.enum(["stood_back", "took_over"]),
|
|
1117
|
+
/** The work it was about: the Goal `claim_goal` would hand that agent next. */
|
|
1118
|
+
goalId: z4.string().uuid().nullable().optional(),
|
|
1119
|
+
/** When the server last heard from the agent, as the host read it: the presence it stood back for. */
|
|
1120
|
+
seenAt: z4.string().datetime().nullable().optional(),
|
|
1121
|
+
/** When that work last moved (`claimable.since` on `check_replies`), the fact the bound is judged on. */
|
|
1122
|
+
since: z4.string().datetime().nullable().optional(),
|
|
1123
|
+
/** What the host said, in its log's own words: why it stood back, or what the take-over did. */
|
|
1124
|
+
said: z4.string().max(300).optional()
|
|
1125
|
+
});
|
|
1092
1126
|
var WakeNudgeSchema = z4.object({
|
|
1093
1127
|
kind: z4.enum(["reply", "request", "callback"]),
|
|
1094
1128
|
notificationId: z4.string().optional(),
|
|
@@ -1133,6 +1167,9 @@ var DeviceTokenSchema = z4.object({
|
|
|
1133
1167
|
* landed in the FIRST granted workspace and the agent rediscovered its own repo from
|
|
1134
1168
|
* the thread each time (host.ts, live catch 2026-08-06 — prompt-papered until now). */
|
|
1135
1169
|
workspace: z4.string().nullable().optional(),
|
|
1170
|
+
/** Local host recovery must preserve the launch's runtime and Paigy identity. */
|
|
1171
|
+
harness: z4.enum(["claude", "codex", "agy"]).optional(),
|
|
1172
|
+
session_id: z4.string().uuid().optional(),
|
|
1136
1173
|
uik_pub: z4.string().nullable().optional()
|
|
1137
1174
|
});
|
|
1138
1175
|
var SupportRequestSchema = z4.object({
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
NameTakenError,
|
|
10
10
|
NotifyRequestSchema,
|
|
11
11
|
PROTO,
|
|
12
|
+
RevokedError,
|
|
12
13
|
TOKEN_PATH,
|
|
13
14
|
UnpairedError,
|
|
14
15
|
acceptTriage,
|
|
@@ -36,6 +37,7 @@ import {
|
|
|
36
37
|
reach,
|
|
37
38
|
reachAs,
|
|
38
39
|
readToken,
|
|
40
|
+
recordDecision,
|
|
39
41
|
registerDelivery,
|
|
40
42
|
repoFromRemote,
|
|
41
43
|
requestCode,
|
|
@@ -53,7 +55,7 @@ import {
|
|
|
53
55
|
updateGoal,
|
|
54
56
|
updateSlot,
|
|
55
57
|
whoAmI
|
|
56
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-6C6CO7H3.js";
|
|
57
59
|
export {
|
|
58
60
|
AGENT_TOOLS,
|
|
59
61
|
AGENT_TOOL_NAMES,
|
|
@@ -65,6 +67,7 @@ export {
|
|
|
65
67
|
NameTakenError,
|
|
66
68
|
NotifyRequestSchema,
|
|
67
69
|
PROTO,
|
|
70
|
+
RevokedError,
|
|
68
71
|
TOKEN_PATH,
|
|
69
72
|
UnpairedError,
|
|
70
73
|
acceptTriage,
|
|
@@ -92,6 +95,7 @@ export {
|
|
|
92
95
|
reach,
|
|
93
96
|
reachAs,
|
|
94
97
|
readToken,
|
|
98
|
+
recordDecision,
|
|
95
99
|
registerDelivery,
|
|
96
100
|
repoFromRemote,
|
|
97
101
|
requestCode,
|
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-6MEUSSRH.js";
|
|
7
|
+
import "./chunk-RLN2B5IZ.js";
|
|
8
|
+
import "./chunk-6C6CO7H3.js";
|
|
9
9
|
|
|
10
10
|
// src/enable.ts
|
|
11
11
|
function main() {
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
resolvePairing,
|
|
7
7
|
startPairing,
|
|
8
8
|
suggestedAgentName
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-YNKTKLQD.js";
|
|
10
10
|
import {
|
|
11
11
|
ENABLE_COMMAND,
|
|
12
12
|
OnboardSchema,
|
|
@@ -15,11 +15,11 @@ import {
|
|
|
15
15
|
SERVER_INSTRUCTIONS,
|
|
16
16
|
TOOLS,
|
|
17
17
|
paigyToolsAllowlisted
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-6MEUSSRH.js";
|
|
19
19
|
import {
|
|
20
20
|
decideListen,
|
|
21
21
|
listenerAlive
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-RLN2B5IZ.js";
|
|
23
23
|
import {
|
|
24
24
|
clearSurface,
|
|
25
25
|
writeSurface
|
|
@@ -39,7 +39,7 @@ import {
|
|
|
39
39
|
sessionId,
|
|
40
40
|
slotName,
|
|
41
41
|
whoAmI
|
|
42
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-6C6CO7H3.js";
|
|
43
43
|
|
|
44
44
|
// src/index.ts
|
|
45
45
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
package/dist/listen.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
entryWords,
|
|
4
4
|
removeListenMark,
|
|
5
5
|
writeListenMark
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-RLN2B5IZ.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-
|
|
14
|
+
} from "./chunk-6C6CO7H3.js";
|
|
15
15
|
|
|
16
16
|
// src/listen.ts
|
|
17
17
|
import { spawn } from "child_process";
|
|
@@ -124,6 +124,7 @@ var { brief: BRIEF, release: RELEASE } = listenOptions(process.argv);
|
|
|
124
124
|
var line = (text) => void process.stdout.write(text + "\n");
|
|
125
125
|
var emit = (obj) => line(JSON.stringify(obj));
|
|
126
126
|
var listeningAs = () => slotName(agentName()) ?? agentName();
|
|
127
|
+
var SWEEP_EVERY_MS = Number(process.env.PAIGY_SWEEP_MS) || 9e4;
|
|
127
128
|
function saidIn(delivery) {
|
|
128
129
|
return ("entries" in delivery ? delivery.entries : []).filter((entry) => entry.kind === "contribution").map((entry) => entryWords(entry)).filter(Boolean).join("\n");
|
|
129
130
|
}
|
|
@@ -192,7 +193,10 @@ async function main() {
|
|
|
192
193
|
process.on("exit", () => removeListenMark(slot));
|
|
193
194
|
if (!BRIEF) emit({ type: "listening", channel: sub.channel });
|
|
194
195
|
await sweep("boot");
|
|
196
|
+
const heartbeat = setInterval(() => void sweep("timer"), SWEEP_EVERY_MS);
|
|
197
|
+
heartbeat.unref?.();
|
|
195
198
|
const shutdown = async () => {
|
|
199
|
+
clearInterval(heartbeat);
|
|
196
200
|
removeListenMark(slot);
|
|
197
201
|
await sub.close();
|
|
198
202
|
process.exit(0);
|
|
@@ -224,6 +228,7 @@ if (isEntry()) {
|
|
|
224
228
|
}
|
|
225
229
|
}
|
|
226
230
|
export {
|
|
231
|
+
SWEEP_EVERY_MS,
|
|
227
232
|
brief,
|
|
228
233
|
catchUpReason,
|
|
229
234
|
launchEnv,
|
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-YNKTKLQD.js";
|
|
7
7
|
import {
|
|
8
8
|
autoConfigureClients,
|
|
9
9
|
claudeInstallHint,
|
|
10
10
|
openBrowser
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-6MEUSSRH.js";
|
|
12
|
+
import "./chunk-RLN2B5IZ.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-6C6CO7H3.js";
|
|
24
24
|
|
|
25
25
|
// src/onboard.ts
|
|
26
26
|
function reportRegistered() {
|
package/dist/slot.js
CHANGED
package/dist/stalled.js
CHANGED
|
@@ -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 { checkReplies } = await import("./dist-
|
|
32
|
+
const { checkReplies } = await import("./dist-33DA5X2G.js");
|
|
33
33
|
const reply = stopReply((await checkReplies()).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