@paigy/mcp 0.40.21 → 0.40.23
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-LRN27BMO.js → chunk-BNMMRKEY.js} +1 -1
- package/dist/{chunk-B7SEHASI.js → chunk-HKODQKUV.js} +4 -2
- package/dist/{chunk-OW65TWMX.js → chunk-JLRBZZNT.js} +43 -21
- package/dist/{chunk-2UEIJRRC.js → chunk-PR7ROBN4.js} +111 -32
- package/dist/{dist-VVU24KB2.js → dist-B7AOS5TG.js} +13 -3
- package/dist/enable.js +3 -3
- package/dist/index.js +4 -4
- package/dist/listen.js +2 -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
|
@@ -4,10 +4,11 @@ import {
|
|
|
4
4
|
serverInstructions,
|
|
5
5
|
sessionStartHook,
|
|
6
6
|
withSessionStartHook
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-JLRBZZNT.js";
|
|
8
8
|
import {
|
|
9
|
+
CODEX_ENV,
|
|
9
10
|
agentName
|
|
10
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-PR7ROBN4.js";
|
|
11
12
|
|
|
12
13
|
// src/toolset.ts
|
|
13
14
|
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.";
|
|
@@ -94,6 +95,7 @@ function withPaigyMcpToml(existing, agent) {
|
|
|
94
95
|
"[mcp_servers.paigy]",
|
|
95
96
|
'command = "npx"',
|
|
96
97
|
'args = ["-y", "@paigy/mcp@latest"]',
|
|
98
|
+
`env_vars = [${CODEX_ENV.map((name) => JSON.stringify(name)).join(", ")}]`,
|
|
97
99
|
`env = { PAIGY_AGENT = "${agent}" }`,
|
|
98
100
|
""
|
|
99
101
|
].join("\n");
|
|
@@ -59,7 +59,18 @@ var AskInputSchema = z2.object({
|
|
|
59
59
|
ask: z2.string().trim().min(1).max(1e4).describe(
|
|
60
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(1).max(6).optional()
|
|
62
|
+
options: z2.array(OptionInputSchema).min(1).max(6).optional(),
|
|
63
|
+
// YOUR VIEW OF ONE OR MANY, A HINT TO PAIGY'S READ (owner, 2026-10-02: "one and many makes sense...
|
|
64
|
+
// make sure the brain that formats is aware of how it should work"). Three independent fixes went
|
|
65
|
+
// out as "All three / 1 and 3 only / Just log it" because every card was pick-one. #2943 made this
|
|
66
|
+
// field override the read; no agent sent it, so nothing changed. The read now decides each card's
|
|
67
|
+
// shape (`goal/intake.ts` `answerOf`), and this reaches it as the agent's view, weighed, not obeyed.
|
|
68
|
+
select: z2.enum(["one", "many"]).optional().describe(
|
|
69
|
+
`Your view of how the options are answered: "one" to pick one, "many" to tick any number of them. A hint: Paigy's read decides each card's shape, a checklist when the options can all be wanted at once, a pick when choosing one rules out the others. The person can always answer in their own words as well. Ignored without options.`
|
|
70
|
+
),
|
|
71
|
+
answers: z2.string().trim().regex(/^[0-9a-fA-F-]{8,36}$/).optional().describe(
|
|
72
|
+
"Your reply answers a question the person asked you: the id the conversation shows for it (8 characters or whole). Their question closes with this reply as its answer, and any decision of yours it was holding back goes back to them. Needs parentId: the Goal the question is on. The reply is sent to them as it is; to also ask something new, send that as its own ask."
|
|
73
|
+
)
|
|
63
74
|
}).strict();
|
|
64
75
|
var StartContactSchema = z2.object({
|
|
65
76
|
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."),
|
|
@@ -68,7 +79,7 @@ var StartContactSchema = z2.object({
|
|
|
68
79
|
}).strict();
|
|
69
80
|
var ContactSchema = z2.union([StartContactSchema, z2.object({ deliveryId: z2.string().uuid() }).strict()]);
|
|
70
81
|
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, 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.";
|
|
82
|
+
var CONTACT_DESCRIPTION = "Contact the user with one or more asks/questions. Pass an array of asks (each with 'ask', optional 'options', 'select', '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. Each option's label must stand on its own \u2014 the person may see only the labels \u2014 so never a label that points into your text ('All three', 'Option 2', '1 and 3 only'). Whether a card is a checklist or a pick is decided by Paigy's read: independent options they may want several of become a checklist, alternatives a pick. select:'many' or select:'one' tells it your view, a hint it weighs. The person can always answer in their own words, so never add an 'Other' option. 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
83
|
var CreateGoalSchema = z3.object({
|
|
73
84
|
outcome: z3.string().trim().min(1).max(1e4),
|
|
74
85
|
/** The work's NAME (#2115) — one to five words, how a person refers to it out loud ("the night
|
|
@@ -91,7 +102,7 @@ var CreateGoalSchema = z3.object({
|
|
|
91
102
|
var CreateGoalToolSchema = CreateGoalSchema.extend({
|
|
92
103
|
idempotencyKey: CreateGoalSchema.shape.idempotencyKey.optional().describe("Optional. One is minted per call; pass your own only so a retry lands on the same Goal.")
|
|
93
104
|
}).strict();
|
|
94
|
-
var CREATE_GOAL_DESCRIPTION = 'Create a durable Goal for an outcome. Without parentGoalId it is placed against your open Goals: if one already IS this work, that Goal comes back (existing: true) and nothing new is created \u2014 continue it; if the work belongs under one, it is created there (parentGoalId in the receipt); otherwise it is a root. Pass parentGoalId yourself to put it under a specific Goal. Pass repo to anchor the work to a specific repository ("owner/repo" or repo name); delegated children inherit it. Pass title to name it in one to five words, as a person would refer to it out loud ("the night rings") \u2014 it heads every list and is spoken on a call; without one the brain writes it. Admission only:
|
|
105
|
+
var CREATE_GOAL_DESCRIPTION = 'Create a durable Goal for an outcome. Without parentGoalId it is placed against your open Goals: if one already IS this work, that Goal comes back (existing: true) and nothing new is created \u2014 continue it; if the work belongs under one, it is created there (parentGoalId in the receipt); otherwise it is a root. Pass parentGoalId yourself to put it under a specific Goal. Pass repo to anchor the work to a specific repository ("owner/repo" or repo name); delegated children inherit it. Pass title to name it in one to five words, as a person would refer to it out loud ("the night rings") \u2014 it heads every list and is spoken on a call; without one the brain writes it. Admission only: claim it before doing work, then update it as it advances. Returns an admission receipt with goalId, current state, revision, ownerParticipant, and the next step; no Goal content or execution lease.';
|
|
95
106
|
var UpdateGoalSchema = z3.object({
|
|
96
107
|
revision: z3.number().int().positive(),
|
|
97
108
|
changes: z3.object({
|
|
@@ -127,12 +138,13 @@ var GetGoalSchema = z3.object({
|
|
|
127
138
|
* between two of them named. Off by default; `docs/model/goal/diagnose-design.md`. */
|
|
128
139
|
diagnose: z3.boolean().optional()
|
|
129
140
|
}).strict();
|
|
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.
|
|
131
|
-
var UPDATE_GOAL_DESCRIPTION = `Update
|
|
132
|
-
var CLAIM_GOAL_DESCRIPTION = "Claim the oldest runnable or review-pending Goal you own
|
|
141
|
+
var GET_GOAL_DESCRIPTION = "Read one Goal without claiming it, including others (the ten most recent other contributors, with names, latest entry headlines and times): 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. A question in that conversation reads `open` (nothing yet), `answered` (a choice was made, and `answer` carries it), `replied` (they said something and the read settled the question on their words \u2014 NO option of yours was chosen, and the words are the reply line beside it, so read that before you act), or `closed`. 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. Every Goal of your person is readable, whichever of their agents owns it; another account's Goals 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.";
|
|
142
|
+
var UPDATE_GOAL_DESCRIPTION = `Update a Goal you are on at an exact revision. You are on a Goal you own, or one you have written on (an update with progress, or a contact on it); any of your person's agents may write on any of their Goals, and one that never touched a Goal is refused (409 goal_not_joined). State, ownership, dependencies, children, progress, title, and review acknowledgement are explicit; stale revisions are rejected. A CONTACT ON THIS GOAL MOVES ITS REVISION: a question filed on a Goal is a change to it, so an update prepared before a contact and sent after it is refused as stale (409 goal_revision_conflict) \u2014 re-read the Goal, then write. 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.`;
|
|
143
|
+
var CLAIM_GOAL_DESCRIPTION = "Claim a pending answer to your question or the oldest runnable or review-pending Goal you own. Pass goalId to join any Goal of your person; its assignment stays unchanged. Read others before overlapping another agent\u2019s work. Joining lets you contribute and change its state; use update_goal with ownerParticipant when the assignment itself should change. Returns the Goal as get_goal reads it, and marks you as on it, which never shuts another agent out: other agents of your person may write on it and change it too, and two changes at once are told apart by revision (409 goal_revision_conflict).";
|
|
133
144
|
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.";
|
|
134
145
|
var CheckRepliesSchema = z3.object({}).strict();
|
|
135
146
|
var AGENT_TOOLS = [
|
|
147
|
+
{ name: "who_is_working", description: "Read your person's agents that contributed in the last 24 hours, newest first: at most 30 agents and their five most recently touched Goals, with their latest entry headline and time. Use get_goal to read a Goal and its other contributors before starting overlapping work. Read-only; no arguments.", inputSchema: mcpInputSchema(CheckRepliesSchema) },
|
|
136
148
|
{ name: "contact", description: CONTACT_DESCRIPTION, inputSchema: CONTACT_SCHEMA },
|
|
137
149
|
{ name: "check_replies", description: CHECK_REPLIES_DESCRIPTION, inputSchema: mcpInputSchema(CheckRepliesSchema) },
|
|
138
150
|
{ name: "create_goal", description: CREATE_GOAL_DESCRIPTION, inputSchema: mcpInputSchema(CreateGoalToolSchema) },
|
|
@@ -143,16 +155,16 @@ var AGENT_TOOLS = [
|
|
|
143
155
|
var AGENT_TOOL_NAMES = AGENT_TOOLS.map((t) => t.name);
|
|
144
156
|
function serverInstructions(opts) {
|
|
145
157
|
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.";
|
|
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.
|
|
158
|
+
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 Goal of your person is open to you, whichever of their agents owns it: read it with get_goal, write on it (contact with its id as parentId, or update_goal progress), and once you have written on it you may change it too. 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.
|
|
147
159
|
|
|
148
160
|
HOW TO ASK:
|
|
149
161
|
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.
|
|
150
162
|
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.
|
|
151
163
|
3. \`waiting: hard\` only for a decision you are blocked on; \`waiting: none\` for a question you can keep working around.
|
|
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.
|
|
164
|
+
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. STOP REREADING when a window comes back with nothing new said \u2014 they are not typing, the question stays open, and its answer reaches you on the Goal. Otherwise, yield only with a working listener or scheduled wakeup, and collect answers with \`check_replies\` or \`claim_goal\` on that wake.
|
|
153
165
|
5. One ask, one row. Never restate a question that is still waiting inside a new contact: keep waiting on the original, or the answer lands on one copy and the other stays open.
|
|
154
|
-
6. Read the Goal's conversation before asking. Never ask again what was answered or already shipped.
|
|
155
|
-
7. A question carries its options. Without them it reaches the person as a bare title nobody can answer.
|
|
166
|
+
6. Read the Goal's conversation before asking. Never ask again what was answered or already shipped \u2014 and tell its states apart: \`answered\` carries the choice in \`answer\`, while \`replied\` means they said something and chose none of your options, so that question is still yours to settle and their words are the line beside it.
|
|
167
|
+
7. A question carries its options. Without them it reaches the person as a bare title nobody can answer. Each option names its choice in full -- never \`All three\` or \`Option 2\`. Paigy's read decides whether a card is a checklist (options they may want several of) or a pick (one rules out the others); \`select: "many"\` or \`"one"\` is your view, a hint it weighs. They can always answer in their own words, so no "Other" option.
|
|
156
168
|
8. A diagnosis says when, why and how it happens, then proposes one fix. Never options first.`;
|
|
157
169
|
}
|
|
158
170
|
function entryWords(entry) {
|
|
@@ -171,7 +183,7 @@ function entryWords(entry) {
|
|
|
171
183
|
return entry.sources.map((source) => source.text).join("\n");
|
|
172
184
|
}
|
|
173
185
|
var LIVE_MS = 3 * 6e4;
|
|
174
|
-
var WORKING_MS =
|
|
186
|
+
var WORKING_MS = 60 * 6e4;
|
|
175
187
|
var ContextSchema = z4.object({
|
|
176
188
|
title: z4.string().min(1).describe("One-line headline of what you need (required, non-empty)."),
|
|
177
189
|
description: z4.array(z4.string().min(1)).describe(
|
|
@@ -523,7 +535,13 @@ var AgendaTurnSchema = z4.object({
|
|
|
523
535
|
/** Whether the walk WAITS for an answer before moving on. Absent = derived as today
|
|
524
536
|
* (a question blocks, context flows). blocking:false on a question = ask and move
|
|
525
537
|
* on, the claim stays pending; blocking:true on context = hold for a reply. */
|
|
526
|
-
blocking: z4.boolean().optional()
|
|
538
|
+
blocking: z4.boolean().optional(),
|
|
539
|
+
/** SPOKEN ONLY IF THEY SAY NOTHING (owner, 2026-10-01, call 812de935: "you're gonna re-ask, but it
|
|
540
|
+
* shouldn't be the same words … more like, hey, are you still there, or are you able to answer, or
|
|
541
|
+
* would you need more information"). The walk holds this turn out of its queue; at the queue's end it
|
|
542
|
+
* listens for the last word, and only if that listen is silent is this turn said and asked. If they
|
|
543
|
+
* speak, it is dropped and their words are taken like any reply. */
|
|
544
|
+
ifSilent: z4.boolean().optional()
|
|
527
545
|
});
|
|
528
546
|
var CLAIM_STALE_MS = 30 * 6e4;
|
|
529
547
|
var InboxItemSchema = z4.object({
|
|
@@ -724,12 +742,13 @@ var UserSettingsSchema = z4.object({
|
|
|
724
742
|
* they are an enum on a live column across every account, and the rename is a rename of
|
|
725
743
|
* what people read (owner, 2026-09-30). */
|
|
726
744
|
sessionMode: z4.enum(["default", "all_calls", "silent"]),
|
|
727
|
-
/**
|
|
728
|
-
*
|
|
729
|
-
*
|
|
730
|
-
* wanting
|
|
731
|
-
*
|
|
732
|
-
silentPush
|
|
745
|
+
/** `silentPush` lived here until #2813 and is now GONE, field and column both. It was kept as an
|
|
746
|
+
* optional long after DateNight stopped reading it, on the theory that a phone on an older
|
|
747
|
+
* bundle PATCHing the whole settings object would be REFUSED for sending a key we had stopped
|
|
748
|
+
* wanting. That theory was wrong about this schema: these are plain `z.object`s with no
|
|
749
|
+
* `.strict()` anywhere in this file, and zod STRIPS unknown keys rather than rejecting them, so
|
|
750
|
+
* an old bundle's `silentPush` is accepted and ignored. Worth remembering before keeping the
|
|
751
|
+
* next dead field for the same reason. */
|
|
733
752
|
/** Opt-in (default false) to using your content to improve Paigy and train models. */
|
|
734
753
|
improveConsent: z4.boolean(),
|
|
735
754
|
missedCall: MissedCallSchema.default("backoff_standard"),
|
|
@@ -863,7 +882,8 @@ var ConnectionSummarySchema = z4.object({
|
|
|
863
882
|
});
|
|
864
883
|
var LedgerItemSchema = z4.object({ id: z4.string(), parentId: z4.string(), title: z4.string(), createdAt: z4.string() });
|
|
865
884
|
var AgentLedgerSchema = z4.object({
|
|
866
|
-
agent
|
|
885
|
+
/** Null when the agent has not named itself yet — never a placeholder (owner, 2026-10-01). */
|
|
886
|
+
agent: z4.object({ id: z4.string(), name: z4.string().nullable(), revokedAt: z4.string().nullable() }),
|
|
867
887
|
/** Its own questions you have not answered. */
|
|
868
888
|
asks: z4.array(LedgerItemSchema),
|
|
869
889
|
/** Its questions you answered that nobody acted on — still owed to somebody. */
|
|
@@ -1030,7 +1050,7 @@ var QueueItemSchema = z4.object({
|
|
|
1030
1050
|
* the newest Entry on the Goal they wrote, of any kind — a line they added, a reply to a note, an
|
|
1031
1051
|
* answer to a question, a voice note filed as work. Null when the only hands on it have been its
|
|
1032
1052
|
* agent's; optional, so a hand-built queue (fixtures, the demo) and a door older than
|
|
1033
|
-
*
|
|
1053
|
+
* 20261001030911 need not spell it — `work/list.ts`'s `yoursAt` keeps its other sources, so the
|
|
1034
1054
|
* Work tab orders as it did before the migration rather than throwing on the missing key.
|
|
1035
1055
|
*
|
|
1036
1056
|
* It is a FACT, not a reconstruction: `latest` holds one Entry, so an agent's progress note a
|
|
@@ -1345,7 +1365,9 @@ var CallRecapSchema = z4.object({
|
|
|
1345
1365
|
* summarized like a pre-made option is"), so the row scans like a chosen option and their
|
|
1346
1366
|
* own words stay under it. Absent on every line stored before the read wrote them, and on
|
|
1347
1367
|
* anything that is not an answer. */
|
|
1348
|
-
|
|
1368
|
+
/** `about` is the request the line answered (its question), null for words that answered none —
|
|
1369
|
+
* the key the screen groups on, so one question is one row however many times it was answered. */
|
|
1370
|
+
lines: z4.array(z4.object({ entryId: z4.string().uuid(), words: z4.string(), headline: z4.string().optional(), about: z4.string().nullable().optional() }))
|
|
1349
1371
|
})),
|
|
1350
1372
|
unfiled: z4.array(z4.object({ lineId: z4.string().uuid(), words: z4.string(), atMs: z4.number() })),
|
|
1351
1373
|
more: z4.object({ lines: z4.number(), entries: z4.number(), topics: z4.number() })
|
|
@@ -22,6 +22,7 @@ import { execFileSync as execFileSync2 } from "child_process";
|
|
|
22
22
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
23
23
|
import { WebSocket } from "undici";
|
|
24
24
|
var require2 = __sdkCreateRequire(import.meta.url);
|
|
25
|
+
var CODEX_ENV = ["CODEX_THREAD_ID", "CODEX_SESSION_ID", "PAIGY_TOKEN", "PAIGY_SESSION_ID", "PAIGY_HARNESS", "PAIGY_INSTANCE_ID"];
|
|
25
26
|
var BACKEND_URL = process.env.PAIGY_BACKEND_URL ?? "https://paigy.ai";
|
|
26
27
|
var NETWORK_MSG = `Can't reach ${BACKEND_URL} \u2014 the connection was blocked or dropped before an HTTP response. If this agent runs in a sandboxed environment with a network allowlist (e.g. Claude Code on the web, CI), ask the user to add the Paigy domain (paigy.ai) to the environment's allowed domains, then retry.`;
|
|
27
28
|
var PROXY_ENV = ["HTTPS_PROXY", "https_proxy", "HTTP_PROXY", "http_proxy"];
|
|
@@ -79,14 +80,14 @@ function isNetworkError(e) {
|
|
|
79
80
|
async function reach(url, init) {
|
|
80
81
|
return send(url, init, sessionId());
|
|
81
82
|
}
|
|
82
|
-
function reachAs(session) {
|
|
83
|
-
return (url, init) => send(url, init, session);
|
|
83
|
+
function reachAs(session, instance) {
|
|
84
|
+
return (url, init) => send(url, init, session, instance);
|
|
84
85
|
}
|
|
85
|
-
async function send(url, init, session) {
|
|
86
|
+
async function send(url, init, session, instance = envSession("PAIGY_INSTANCE_ID") ?? INSTANCE_ID) {
|
|
86
87
|
try {
|
|
87
88
|
const headers = {
|
|
88
89
|
...init?.headers,
|
|
89
|
-
"x-paigy-instance":
|
|
90
|
+
"x-paigy-instance": instance,
|
|
90
91
|
"x-paigy-session": session
|
|
91
92
|
};
|
|
92
93
|
return await fetch(url, { ...init, headers, dispatcher: await proxy() });
|
|
@@ -1527,7 +1528,18 @@ var AskInputSchema = z2.object({
|
|
|
1527
1528
|
ask: z2.string().trim().min(1).max(1e4).describe(
|
|
1528
1529
|
"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
1530
|
),
|
|
1530
|
-
options: z2.array(OptionInputSchema).min(1).max(6).optional()
|
|
1531
|
+
options: z2.array(OptionInputSchema).min(1).max(6).optional(),
|
|
1532
|
+
// YOUR VIEW OF ONE OR MANY, A HINT TO PAIGY'S READ (owner, 2026-10-02: "one and many makes sense...
|
|
1533
|
+
// make sure the brain that formats is aware of how it should work"). Three independent fixes went
|
|
1534
|
+
// out as "All three / 1 and 3 only / Just log it" because every card was pick-one. #2943 made this
|
|
1535
|
+
// field override the read; no agent sent it, so nothing changed. The read now decides each card's
|
|
1536
|
+
// shape (`goal/intake.ts` `answerOf`), and this reaches it as the agent's view, weighed, not obeyed.
|
|
1537
|
+
select: z2.enum(["one", "many"]).optional().describe(
|
|
1538
|
+
`Your view of how the options are answered: "one" to pick one, "many" to tick any number of them. A hint: Paigy's read decides each card's shape, a checklist when the options can all be wanted at once, a pick when choosing one rules out the others. The person can always answer in their own words as well. Ignored without options.`
|
|
1539
|
+
),
|
|
1540
|
+
answers: z2.string().trim().regex(/^[0-9a-fA-F-]{8,36}$/).optional().describe(
|
|
1541
|
+
"Your reply answers a question the person asked you: the id the conversation shows for it (8 characters or whole). Their question closes with this reply as its answer, and any decision of yours it was holding back goes back to them. Needs parentId: the Goal the question is on. The reply is sent to them as it is; to also ask something new, send that as its own ask."
|
|
1542
|
+
)
|
|
1531
1543
|
}).strict();
|
|
1532
1544
|
var StartContactSchema = z2.object({
|
|
1533
1545
|
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."),
|
|
@@ -1536,7 +1548,7 @@ var StartContactSchema = z2.object({
|
|
|
1536
1548
|
}).strict();
|
|
1537
1549
|
var ContactSchema = z2.union([StartContactSchema, z2.object({ deliveryId: z2.string().uuid() }).strict()]);
|
|
1538
1550
|
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, 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.";
|
|
1551
|
+
var CONTACT_DESCRIPTION = "Contact the user with one or more asks/questions. Pass an array of asks (each with 'ask', optional 'options', 'select', '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. Each option's label must stand on its own \u2014 the person may see only the labels \u2014 so never a label that points into your text ('All three', 'Option 2', '1 and 3 only'). Whether a card is a checklist or a pick is decided by Paigy's read: independent options they may want several of become a checklist, alternatives a pick. select:'many' or select:'one' tells it your view, a hint it weighs. The person can always answer in their own words, so never add an 'Other' option. 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
1552
|
var CreateGoalSchema = z3.object({
|
|
1541
1553
|
outcome: z3.string().trim().min(1).max(1e4),
|
|
1542
1554
|
/** The work's NAME (#2115) — one to five words, how a person refers to it out loud ("the night
|
|
@@ -1559,7 +1571,7 @@ var CreateGoalSchema = z3.object({
|
|
|
1559
1571
|
var CreateGoalToolSchema = CreateGoalSchema.extend({
|
|
1560
1572
|
idempotencyKey: CreateGoalSchema.shape.idempotencyKey.optional().describe("Optional. One is minted per call; pass your own only so a retry lands on the same Goal.")
|
|
1561
1573
|
}).strict();
|
|
1562
|
-
var CREATE_GOAL_DESCRIPTION = 'Create a durable Goal for an outcome. Without parentGoalId it is placed against your open Goals: if one already IS this work, that Goal comes back (existing: true) and nothing new is created \u2014 continue it; if the work belongs under one, it is created there (parentGoalId in the receipt); otherwise it is a root. Pass parentGoalId yourself to put it under a specific Goal. Pass repo to anchor the work to a specific repository ("owner/repo" or repo name); delegated children inherit it. Pass title to name it in one to five words, as a person would refer to it out loud ("the night rings") \u2014 it heads every list and is spoken on a call; without one the brain writes it. Admission only:
|
|
1574
|
+
var CREATE_GOAL_DESCRIPTION = 'Create a durable Goal for an outcome. Without parentGoalId it is placed against your open Goals: if one already IS this work, that Goal comes back (existing: true) and nothing new is created \u2014 continue it; if the work belongs under one, it is created there (parentGoalId in the receipt); otherwise it is a root. Pass parentGoalId yourself to put it under a specific Goal. Pass repo to anchor the work to a specific repository ("owner/repo" or repo name); delegated children inherit it. Pass title to name it in one to five words, as a person would refer to it out loud ("the night rings") \u2014 it heads every list and is spoken on a call; without one the brain writes it. Admission only: claim it before doing work, then update it as it advances. Returns an admission receipt with goalId, current state, revision, ownerParticipant, and the next step; no Goal content or execution lease.';
|
|
1563
1575
|
var UpdateGoalSchema = z3.object({
|
|
1564
1576
|
revision: z3.number().int().positive(),
|
|
1565
1577
|
changes: z3.object({
|
|
@@ -1595,12 +1607,13 @@ var GetGoalSchema = z3.object({
|
|
|
1595
1607
|
* between two of them named. Off by default; `docs/model/goal/diagnose-design.md`. */
|
|
1596
1608
|
diagnose: z3.boolean().optional()
|
|
1597
1609
|
}).strict();
|
|
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.
|
|
1599
|
-
var UPDATE_GOAL_DESCRIPTION = `Update
|
|
1600
|
-
var CLAIM_GOAL_DESCRIPTION = "Claim the oldest runnable or review-pending Goal you own
|
|
1610
|
+
var GET_GOAL_DESCRIPTION = "Read one Goal without claiming it, including others (the ten most recent other contributors, with names, latest entry headlines and times): 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. A question in that conversation reads `open` (nothing yet), `answered` (a choice was made, and `answer` carries it), `replied` (they said something and the read settled the question on their words \u2014 NO option of yours was chosen, and the words are the reply line beside it, so read that before you act), or `closed`. 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. Every Goal of your person is readable, whichever of their agents owns it; another account's Goals 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.";
|
|
1611
|
+
var UPDATE_GOAL_DESCRIPTION = `Update a Goal you are on at an exact revision. You are on a Goal you own, or one you have written on (an update with progress, or a contact on it); any of your person's agents may write on any of their Goals, and one that never touched a Goal is refused (409 goal_not_joined). State, ownership, dependencies, children, progress, title, and review acknowledgement are explicit; stale revisions are rejected. A CONTACT ON THIS GOAL MOVES ITS REVISION: a question filed on a Goal is a change to it, so an update prepared before a contact and sent after it is refused as stale (409 goal_revision_conflict) \u2014 re-read the Goal, then write. 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.`;
|
|
1612
|
+
var CLAIM_GOAL_DESCRIPTION = "Claim a pending answer to your question or the oldest runnable or review-pending Goal you own. Pass goalId to join any Goal of your person; its assignment stays unchanged. Read others before overlapping another agent\u2019s work. Joining lets you contribute and change its state; use update_goal with ownerParticipant when the assignment itself should change. Returns the Goal as get_goal reads it, and marks you as on it, which never shuts another agent out: other agents of your person may write on it and change it too, and two changes at once are told apart by revision (409 goal_revision_conflict).";
|
|
1601
1613
|
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.";
|
|
1602
1614
|
var CheckRepliesSchema = z3.object({}).strict();
|
|
1603
1615
|
var AGENT_TOOLS = [
|
|
1616
|
+
{ name: "who_is_working", description: "Read your person's agents that contributed in the last 24 hours, newest first: at most 30 agents and their five most recently touched Goals, with their latest entry headline and time. Use get_goal to read a Goal and its other contributors before starting overlapping work. Read-only; no arguments.", inputSchema: mcpInputSchema(CheckRepliesSchema) },
|
|
1604
1617
|
{ name: "contact", description: CONTACT_DESCRIPTION, inputSchema: CONTACT_SCHEMA },
|
|
1605
1618
|
{ name: "check_replies", description: CHECK_REPLIES_DESCRIPTION, inputSchema: mcpInputSchema(CheckRepliesSchema) },
|
|
1606
1619
|
{ name: "create_goal", description: CREATE_GOAL_DESCRIPTION, inputSchema: mcpInputSchema(CreateGoalToolSchema) },
|
|
@@ -1625,7 +1638,7 @@ function entryWords(entry) {
|
|
|
1625
1638
|
return entry.sources.map((source) => source.text).join("\n");
|
|
1626
1639
|
}
|
|
1627
1640
|
var LIVE_MS = 3 * 6e4;
|
|
1628
|
-
var WORKING_MS =
|
|
1641
|
+
var WORKING_MS = 60 * 6e4;
|
|
1629
1642
|
var ContextSchema = z4.object({
|
|
1630
1643
|
title: z4.string().min(1).describe("One-line headline of what you need (required, non-empty)."),
|
|
1631
1644
|
description: z4.array(z4.string().min(1)).describe(
|
|
@@ -1652,6 +1665,13 @@ var TransformSchema = z4.enum([
|
|
|
1652
1665
|
"summarize"
|
|
1653
1666
|
// reduce volume, keep decision value — 30-turn cap, spoken briefing
|
|
1654
1667
|
]);
|
|
1668
|
+
function participantRef(p) {
|
|
1669
|
+
return `${p.kind}:${p.id}`;
|
|
1670
|
+
}
|
|
1671
|
+
var PAIGY_SELF = { kind: "agent", id: "paigy" };
|
|
1672
|
+
function isPaigy(ref) {
|
|
1673
|
+
return ref === participantRef(PAIGY_SELF);
|
|
1674
|
+
}
|
|
1655
1675
|
var VisualSchema = z4.object({
|
|
1656
1676
|
url: z4.string().url(),
|
|
1657
1677
|
label: z4.string().optional()
|
|
@@ -1977,7 +1997,13 @@ var AgendaTurnSchema = z4.object({
|
|
|
1977
1997
|
/** Whether the walk WAITS for an answer before moving on. Absent = derived as today
|
|
1978
1998
|
* (a question blocks, context flows). blocking:false on a question = ask and move
|
|
1979
1999
|
* on, the claim stays pending; blocking:true on context = hold for a reply. */
|
|
1980
|
-
blocking: z4.boolean().optional()
|
|
2000
|
+
blocking: z4.boolean().optional(),
|
|
2001
|
+
/** SPOKEN ONLY IF THEY SAY NOTHING (owner, 2026-10-01, call 812de935: "you're gonna re-ask, but it
|
|
2002
|
+
* shouldn't be the same words … more like, hey, are you still there, or are you able to answer, or
|
|
2003
|
+
* would you need more information"). The walk holds this turn out of its queue; at the queue's end it
|
|
2004
|
+
* listens for the last word, and only if that listen is silent is this turn said and asked. If they
|
|
2005
|
+
* speak, it is dropped and their words are taken like any reply. */
|
|
2006
|
+
ifSilent: z4.boolean().optional()
|
|
1981
2007
|
});
|
|
1982
2008
|
var CLAIM_STALE_MS = 30 * 6e4;
|
|
1983
2009
|
var InboxItemSchema = z4.object({
|
|
@@ -2178,12 +2204,13 @@ var UserSettingsSchema = z4.object({
|
|
|
2178
2204
|
* they are an enum on a live column across every account, and the rename is a rename of
|
|
2179
2205
|
* what people read (owner, 2026-09-30). */
|
|
2180
2206
|
sessionMode: z4.enum(["default", "all_calls", "silent"]),
|
|
2181
|
-
/**
|
|
2182
|
-
*
|
|
2183
|
-
*
|
|
2184
|
-
* wanting
|
|
2185
|
-
*
|
|
2186
|
-
silentPush
|
|
2207
|
+
/** `silentPush` lived here until #2813 and is now GONE, field and column both. It was kept as an
|
|
2208
|
+
* optional long after DateNight stopped reading it, on the theory that a phone on an older
|
|
2209
|
+
* bundle PATCHing the whole settings object would be REFUSED for sending a key we had stopped
|
|
2210
|
+
* wanting. That theory was wrong about this schema: these are plain `z.object`s with no
|
|
2211
|
+
* `.strict()` anywhere in this file, and zod STRIPS unknown keys rather than rejecting them, so
|
|
2212
|
+
* an old bundle's `silentPush` is accepted and ignored. Worth remembering before keeping the
|
|
2213
|
+
* next dead field for the same reason. */
|
|
2187
2214
|
/** Opt-in (default false) to using your content to improve Paigy and train models. */
|
|
2188
2215
|
improveConsent: z4.boolean(),
|
|
2189
2216
|
missedCall: MissedCallSchema.default("backoff_standard"),
|
|
@@ -2317,7 +2344,8 @@ var ConnectionSummarySchema = z4.object({
|
|
|
2317
2344
|
});
|
|
2318
2345
|
var LedgerItemSchema = z4.object({ id: z4.string(), parentId: z4.string(), title: z4.string(), createdAt: z4.string() });
|
|
2319
2346
|
var AgentLedgerSchema = z4.object({
|
|
2320
|
-
agent
|
|
2347
|
+
/** Null when the agent has not named itself yet — never a placeholder (owner, 2026-10-01). */
|
|
2348
|
+
agent: z4.object({ id: z4.string(), name: z4.string().nullable(), revokedAt: z4.string().nullable() }),
|
|
2321
2349
|
/** Its own questions you have not answered. */
|
|
2322
2350
|
asks: z4.array(LedgerItemSchema),
|
|
2323
2351
|
/** Its questions you answered that nobody acted on — still owed to somebody. */
|
|
@@ -2484,7 +2512,7 @@ var QueueItemSchema = z4.object({
|
|
|
2484
2512
|
* the newest Entry on the Goal they wrote, of any kind — a line they added, a reply to a note, an
|
|
2485
2513
|
* answer to a question, a voice note filed as work. Null when the only hands on it have been its
|
|
2486
2514
|
* agent's; optional, so a hand-built queue (fixtures, the demo) and a door older than
|
|
2487
|
-
*
|
|
2515
|
+
* 20261001030911 need not spell it — `work/list.ts`'s `yoursAt` keeps its other sources, so the
|
|
2488
2516
|
* Work tab orders as it did before the migration rather than throwing on the missing key.
|
|
2489
2517
|
*
|
|
2490
2518
|
* It is a FACT, not a reconstruction: `latest` holds one Entry, so an agent's progress note a
|
|
@@ -2801,7 +2829,9 @@ var CallRecapSchema = z4.object({
|
|
|
2801
2829
|
* summarized like a pre-made option is"), so the row scans like a chosen option and their
|
|
2802
2830
|
* own words stay under it. Absent on every line stored before the read wrote them, and on
|
|
2803
2831
|
* anything that is not an answer. */
|
|
2804
|
-
|
|
2832
|
+
/** `about` is the request the line answered (its question), null for words that answered none —
|
|
2833
|
+
* the key the screen groups on, so one question is one row however many times it was answered. */
|
|
2834
|
+
lines: z4.array(z4.object({ entryId: z4.string().uuid(), words: z4.string(), headline: z4.string().optional(), about: z4.string().nullable().optional() }))
|
|
2805
2835
|
})),
|
|
2806
2836
|
unfiled: z4.array(z4.object({ lineId: z4.string().uuid(), words: z4.string(), atMs: z4.number() })),
|
|
2807
2837
|
more: z4.object({ lines: z4.number(), entries: z4.number(), topics: z4.number() })
|
|
@@ -2873,6 +2903,9 @@ function readToken(agent2 = agentName()) {
|
|
|
2873
2903
|
if (process.env.PAIGY_TOKEN) return process.env.PAIGY_TOKEN;
|
|
2874
2904
|
return readTokenFile()[agent2]?.access_token ?? "";
|
|
2875
2905
|
}
|
|
2906
|
+
function readSlot(agent2) {
|
|
2907
|
+
return readTokenFile()[agent2]?.access_token ?? "";
|
|
2908
|
+
}
|
|
2876
2909
|
function listSlots() {
|
|
2877
2910
|
return Object.keys(readTokenFile());
|
|
2878
2911
|
}
|
|
@@ -3003,11 +3036,16 @@ async function updateGoal(goalId, input, opts = {}) {
|
|
|
3003
3036
|
return await res.json();
|
|
3004
3037
|
}
|
|
3005
3038
|
var AWAIT_WINDOW_MS = 45e3;
|
|
3006
|
-
async function hatch(name, voice = null) {
|
|
3007
|
-
const res = await ensureAuthed(await reach(`${BACKEND_URL}/api/hatch`, {
|
|
3039
|
+
async function hatch(name, voice = null, opts = {}) {
|
|
3040
|
+
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/hatch`, {
|
|
3008
3041
|
method: "POST",
|
|
3009
3042
|
headers: { "content-type": "application/json", authorization: `Bearer ${authToken()}` },
|
|
3010
|
-
body: JSON.stringify({
|
|
3043
|
+
body: JSON.stringify({
|
|
3044
|
+
name,
|
|
3045
|
+
voice,
|
|
3046
|
+
...opts.brief ? { brief: opts.brief } : {},
|
|
3047
|
+
...opts.parentGoalId ? { parentGoalId: opts.parentGoalId } : {}
|
|
3048
|
+
})
|
|
3011
3049
|
}));
|
|
3012
3050
|
if (!res.ok) throw new Error(`hatch failed: ${res.status} ${await res.text()}`);
|
|
3013
3051
|
return await res.json();
|
|
@@ -3053,6 +3091,22 @@ async function claimSessions(opts = {}) {
|
|
|
3053
3091
|
if (!res.ok) throw new Error(`claim_sessions failed: ${res.status}`);
|
|
3054
3092
|
return (await res.json()).sessions;
|
|
3055
3093
|
}
|
|
3094
|
+
async function claimSessionEnds(opts = {}) {
|
|
3095
|
+
const res = await ensureAuthed(await reach(`${BACKEND_URL}/api/sessions/ends/claim`, {
|
|
3096
|
+
headers: { authorization: `Bearer ${authToken(opts.token)}` }
|
|
3097
|
+
// the HOST's identity
|
|
3098
|
+
}));
|
|
3099
|
+
if (!res.ok) throw new Error(`claim_session_ends failed: ${res.status}`);
|
|
3100
|
+
return (await res.json()).ends ?? [];
|
|
3101
|
+
}
|
|
3102
|
+
async function finishSessionEnd(endId, result, opts = {}) {
|
|
3103
|
+
const res = await ensureAuthed(await reach(`${BACKEND_URL}/api/sessions/ends/${encodeURIComponent(endId)}`, {
|
|
3104
|
+
method: "POST",
|
|
3105
|
+
headers: { "content-type": "application/json", authorization: `Bearer ${authToken(opts.token)}` },
|
|
3106
|
+
body: JSON.stringify({ result })
|
|
3107
|
+
}));
|
|
3108
|
+
if (!res.ok) await fail("finish_session_end", res);
|
|
3109
|
+
}
|
|
3056
3110
|
async function recordDecision(decision, opts = {}) {
|
|
3057
3111
|
const res = await ensureAuthed(await reach(`${BACKEND_URL}/api/host/decisions`, {
|
|
3058
3112
|
method: "POST",
|
|
@@ -3129,6 +3183,13 @@ async function dismissTriage(proposalId, opts = {}) {
|
|
|
3129
3183
|
if (!res.ok) throw new Error(`dismiss_triage failed: ${res.status} ${await res.text()}`);
|
|
3130
3184
|
return await res.json();
|
|
3131
3185
|
}
|
|
3186
|
+
async function whoIsWorking(opts = {}) {
|
|
3187
|
+
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/agents/working`, {
|
|
3188
|
+
headers: { authorization: `Bearer ${authToken(opts.token) ?? ""}`, "x-paigy-model": "goal-entry-v1" }
|
|
3189
|
+
}));
|
|
3190
|
+
if (!res.ok) await fail("who_is_working", res);
|
|
3191
|
+
return await res.json();
|
|
3192
|
+
}
|
|
3132
3193
|
function repoFromRemote(url) {
|
|
3133
3194
|
const said = (url ?? "").trim();
|
|
3134
3195
|
if (!said) return null;
|
|
@@ -3176,7 +3237,9 @@ async function contact(input, opts = {}) {
|
|
|
3176
3237
|
// this cannot see.
|
|
3177
3238
|
repo: repoFromRemote(a.repo) ?? a.repo ?? currentRepo() ?? void 0,
|
|
3178
3239
|
ask: a.ask,
|
|
3179
|
-
options: a.options ?? []
|
|
3240
|
+
options: a.options ?? [],
|
|
3241
|
+
...a.select ? { select: a.select } : {},
|
|
3242
|
+
...a.answers ? { answers: a.answers } : {}
|
|
3180
3243
|
}));
|
|
3181
3244
|
const res = await ensureAuthed(await send2(`${BACKEND_URL}/api/goals/contact`, {
|
|
3182
3245
|
method: "POST",
|
|
@@ -3241,7 +3304,7 @@ async function checkReplies(opts = {}) {
|
|
|
3241
3304
|
function compact(o) {
|
|
3242
3305
|
return Object.fromEntries(Object.entries(o).filter(([, v]) => v !== void 0 && v !== null && v !== "" && !(Array.isArray(v) && v.length === 0)));
|
|
3243
3306
|
}
|
|
3244
|
-
var who = (participant) => participant.startsWith("human:") ? "person" : participant.startsWith("agent:") ? "agent" : participant;
|
|
3307
|
+
var who = (participant) => participant.startsWith("human:") ? "person" : isPaigy(participant) ? "paigy" : participant.startsWith("agent:") ? "agent" : participant;
|
|
3245
3308
|
var at = (iso) => {
|
|
3246
3309
|
const t = Date.parse(iso);
|
|
3247
3310
|
return Number.isFinite(t) ? new Date(t).toISOString().replace(/\.\d{3}Z$/, "Z") : iso;
|
|
@@ -3261,6 +3324,9 @@ function decided(result) {
|
|
|
3261
3324
|
return void 0;
|
|
3262
3325
|
}
|
|
3263
3326
|
}
|
|
3327
|
+
function stateOf(state, answer, decided2) {
|
|
3328
|
+
return state === "answered" && answer && decided2 === void 0 ? "replied" : state;
|
|
3329
|
+
}
|
|
3264
3330
|
var handle = (entryId) => entryId.slice(0, 8);
|
|
3265
3331
|
function conversation(e) {
|
|
3266
3332
|
const answers = new Map((e.answers ?? []).map((a) => [a.decisionNeedId, a]));
|
|
@@ -3273,14 +3339,15 @@ function conversation(e) {
|
|
|
3273
3339
|
const need = (e.decisionNeeds ?? []).find((n) => n.requestEntryId === entry.entryId);
|
|
3274
3340
|
const answer = need ? answers.get(need.decisionNeedId) : void 0;
|
|
3275
3341
|
const decision = answer ? decided(answer.result) : void 0;
|
|
3342
|
+
const owed = need?.state === "open" && entry.authorParticipant.startsWith("human:");
|
|
3276
3343
|
return compact({
|
|
3277
|
-
id: repliedTo.has(entry.entryId) ? handle(entry.entryId) : void 0,
|
|
3344
|
+
id: repliedTo.has(entry.entryId) || owed ? handle(entry.entryId) : void 0,
|
|
3278
3345
|
from: who(entry.authorParticipant),
|
|
3279
3346
|
at: at(entry.createdAt),
|
|
3280
3347
|
said: sealed ? "[encrypted]" : entryWords(entry).trim(),
|
|
3281
3348
|
re: entry.aboutId && shown.has(entry.aboutId) ? handle(entry.aboutId) : void 0,
|
|
3282
3349
|
options,
|
|
3283
|
-
decision: need ? compact({ state: need.state, answer: decision }) : void 0
|
|
3350
|
+
decision: need ? compact({ state: stateOf(need.state, answer, decision), answer: decision }) : void 0
|
|
3284
3351
|
});
|
|
3285
3352
|
});
|
|
3286
3353
|
}
|
|
@@ -3296,7 +3363,9 @@ function more(g) {
|
|
|
3296
3363
|
function goalView(g) {
|
|
3297
3364
|
if (!g.goalId) return compact({ state: g.state, next: g.message });
|
|
3298
3365
|
const lines2 = conversation(g);
|
|
3299
|
-
const
|
|
3366
|
+
const owed = lines2.filter((l) => l.from === "person" && l.decision?.state === "open" && l.id);
|
|
3367
|
+
const owes = owed.length ? `The person asked you ${owed.length === 1 ? "a question" : `${owed.length} questions`} (${owed.map((l) => `id ${l.id}: "${l.said.slice(0, 80)}"`).join("; ")}) \u2014 answer with contact({ asks: [{ ask: <your answer>, parentId: "${g.goalId}", answers: "<id>" }] }). ` : "";
|
|
3368
|
+
const newest = [...lines2].reverse().find((l) => l.from === "agent");
|
|
3300
3369
|
return compact({
|
|
3301
3370
|
goalId: g.goalId,
|
|
3302
3371
|
revision: g.revision,
|
|
@@ -3304,7 +3373,9 @@ function goalView(g) {
|
|
|
3304
3373
|
outcome: g.outcome,
|
|
3305
3374
|
progress: g.progress && g.progress.trim() !== newest?.said ? g.progress : void 0,
|
|
3306
3375
|
reviewPending: g.reviewPending || void 0,
|
|
3376
|
+
reviewSince: g.reviewSince,
|
|
3307
3377
|
owner: g.ownerParticipant,
|
|
3378
|
+
others: g.others,
|
|
3308
3379
|
parentGoalId: g.parentGoalId,
|
|
3309
3380
|
// Every child is in the subtree below, with its goalId: listed again, it was said twice.
|
|
3310
3381
|
childGoalIds: g.subtree?.length ? void 0 : g.childGoalIds,
|
|
@@ -3320,7 +3391,7 @@ function goalView(g) {
|
|
|
3320
3391
|
dueAt: g.dueAt,
|
|
3321
3392
|
leaseExpiresAt: g.leaseExpiresAt,
|
|
3322
3393
|
conversation: lines2,
|
|
3323
|
-
next: g.message,
|
|
3394
|
+
next: owes ? `${owes}${g.message ?? ""}`.trim() : g.message,
|
|
3324
3395
|
more: more(g)
|
|
3325
3396
|
});
|
|
3326
3397
|
}
|
|
@@ -3340,7 +3411,7 @@ function deliveryView(d) {
|
|
|
3340
3411
|
notSent: d.notSent,
|
|
3341
3412
|
joinedCard: d.joinedCard,
|
|
3342
3413
|
joinedCall: d.joinedCall,
|
|
3343
|
-
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 })})
|
|
3414
|
+
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 })}) to continue this same Call \u2014 each call is ONE bounded window, and never resend the ask. When a window comes back with nothing new said, they are not typing: stop rereading, leave the question open, and collect the answer with check_replies or claim_goal on your next wake. ${d.message ?? ""}`.trim() : d.message
|
|
3344
3415
|
});
|
|
3345
3416
|
}
|
|
3346
3417
|
function repliesView(r) {
|
|
@@ -3381,7 +3452,7 @@ function repliesView(r) {
|
|
|
3381
3452
|
// sentence names the person and quotes the freshest one, because a count is not a message.
|
|
3382
3453
|
...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.`] : [],
|
|
3383
3454
|
...stalled.length ? [`${stalled.length} of your Goals have had no progress for 3 days: update_goal each with progress, finish it, or cancel it.`] : [],
|
|
3384
|
-
...others.length ? [`${others.length} of other agents' Goals have gone quiet for 3 days: claim_goal({goalId})
|
|
3455
|
+
...others.length ? [`${others.length} of other agents' Goals have gone quiet for 3 days: claim_goal({goalId}) joins one without changing its owner, then finish or cancel it with update_goal.`] : [],
|
|
3385
3456
|
// No name of its own (#2525): the API's ask, verbatim.
|
|
3386
3457
|
...r.unnamed ? [r.unnamed] : []
|
|
3387
3458
|
].join(" ")
|
|
@@ -3402,6 +3473,9 @@ async function runTool(name, args, opts) {
|
|
|
3402
3473
|
const sent = await contact(input, { ...client, signal, waits });
|
|
3403
3474
|
return "sent" in sent ? sent : deliveryView(sent);
|
|
3404
3475
|
}
|
|
3476
|
+
case "who_is_working":
|
|
3477
|
+
CheckRepliesSchema.parse(input);
|
|
3478
|
+
return whoIsWorking(client);
|
|
3405
3479
|
case "check_replies":
|
|
3406
3480
|
CheckRepliesSchema.parse(input);
|
|
3407
3481
|
return repliesView(await checkReplies(client));
|
|
@@ -3607,6 +3681,7 @@ function machineZone() {
|
|
|
3607
3681
|
}
|
|
3608
3682
|
|
|
3609
3683
|
export {
|
|
3684
|
+
CODEX_ENV,
|
|
3610
3685
|
BACKEND_URL,
|
|
3611
3686
|
NETWORK_MSG,
|
|
3612
3687
|
sessionId,
|
|
@@ -3626,6 +3701,7 @@ export {
|
|
|
3626
3701
|
slotIdentity,
|
|
3627
3702
|
sleep,
|
|
3628
3703
|
readToken,
|
|
3704
|
+
readSlot,
|
|
3629
3705
|
listSlots,
|
|
3630
3706
|
slotName,
|
|
3631
3707
|
deleteToken,
|
|
@@ -3647,6 +3723,8 @@ export {
|
|
|
3647
3723
|
NameTakenError,
|
|
3648
3724
|
setIdentity,
|
|
3649
3725
|
claimSessions,
|
|
3726
|
+
claimSessionEnds,
|
|
3727
|
+
finishSessionEnd,
|
|
3650
3728
|
recordDecision,
|
|
3651
3729
|
heartbeat,
|
|
3652
3730
|
registerDelivery,
|
|
@@ -3656,6 +3734,7 @@ export {
|
|
|
3656
3734
|
getTriage,
|
|
3657
3735
|
acceptTriage,
|
|
3658
3736
|
dismissTriage,
|
|
3737
|
+
whoIsWorking,
|
|
3659
3738
|
repoFromRemote,
|
|
3660
3739
|
currentRepo,
|
|
3661
3740
|
contact,
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
AWAIT_WINDOW_MS,
|
|
5
5
|
ApiError,
|
|
6
6
|
BACKEND_URL,
|
|
7
|
+
CODEX_ENV,
|
|
7
8
|
KEY_PATH,
|
|
8
9
|
NETWORK_MSG,
|
|
9
10
|
NameTakenError,
|
|
@@ -17,12 +18,14 @@ import {
|
|
|
17
18
|
authToken,
|
|
18
19
|
checkReplies,
|
|
19
20
|
claimGoal,
|
|
21
|
+
claimSessionEnds,
|
|
20
22
|
claimSessions,
|
|
21
23
|
contact,
|
|
22
24
|
createGoal,
|
|
23
25
|
currentRepo,
|
|
24
26
|
deleteToken,
|
|
25
27
|
dismissTriage,
|
|
28
|
+
finishSessionEnd,
|
|
26
29
|
getGoal,
|
|
27
30
|
getTriage,
|
|
28
31
|
hatch,
|
|
@@ -36,6 +39,7 @@ import {
|
|
|
36
39
|
pollToken,
|
|
37
40
|
reach,
|
|
38
41
|
reachAs,
|
|
42
|
+
readSlot,
|
|
39
43
|
readToken,
|
|
40
44
|
recordDecision,
|
|
41
45
|
registerDelivery,
|
|
@@ -54,14 +58,16 @@ import {
|
|
|
54
58
|
subscribeWake,
|
|
55
59
|
updateGoal,
|
|
56
60
|
updateSlot,
|
|
57
|
-
whoAmI
|
|
58
|
-
|
|
61
|
+
whoAmI,
|
|
62
|
+
whoIsWorking
|
|
63
|
+
} from "./chunk-PR7ROBN4.js";
|
|
59
64
|
export {
|
|
60
65
|
AGENT_TOOLS,
|
|
61
66
|
AGENT_TOOL_NAMES,
|
|
62
67
|
AWAIT_WINDOW_MS,
|
|
63
68
|
ApiError,
|
|
64
69
|
BACKEND_URL,
|
|
70
|
+
CODEX_ENV,
|
|
65
71
|
KEY_PATH,
|
|
66
72
|
NETWORK_MSG,
|
|
67
73
|
NameTakenError,
|
|
@@ -75,12 +81,14 @@ export {
|
|
|
75
81
|
authToken,
|
|
76
82
|
checkReplies,
|
|
77
83
|
claimGoal,
|
|
84
|
+
claimSessionEnds,
|
|
78
85
|
claimSessions,
|
|
79
86
|
contact,
|
|
80
87
|
createGoal,
|
|
81
88
|
currentRepo,
|
|
82
89
|
deleteToken,
|
|
83
90
|
dismissTriage,
|
|
91
|
+
finishSessionEnd,
|
|
84
92
|
getGoal,
|
|
85
93
|
getTriage,
|
|
86
94
|
hatch,
|
|
@@ -94,6 +102,7 @@ export {
|
|
|
94
102
|
pollToken,
|
|
95
103
|
reach,
|
|
96
104
|
reachAs,
|
|
105
|
+
readSlot,
|
|
97
106
|
readToken,
|
|
98
107
|
recordDecision,
|
|
99
108
|
registerDelivery,
|
|
@@ -112,5 +121,6 @@ export {
|
|
|
112
121
|
subscribeWake,
|
|
113
122
|
updateGoal,
|
|
114
123
|
updateSlot,
|
|
115
|
-
whoAmI
|
|
124
|
+
whoAmI,
|
|
125
|
+
whoIsWorking
|
|
116
126
|
};
|
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-HKODQKUV.js";
|
|
7
|
+
import "./chunk-JLRBZZNT.js";
|
|
8
|
+
import "./chunk-PR7ROBN4.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-BNMMRKEY.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-HKODQKUV.js";
|
|
19
19
|
import {
|
|
20
20
|
decideListen,
|
|
21
21
|
listenerAlive
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-JLRBZZNT.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-PR7ROBN4.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-JLRBZZNT.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-PR7ROBN4.js";
|
|
15
15
|
|
|
16
16
|
// src/listen.ts
|
|
17
17
|
import { spawn } from "child_process";
|
package/dist/onboard.js
CHANGED
|
@@ -3,13 +3,13 @@ import {
|
|
|
3
3
|
resolvePairing,
|
|
4
4
|
startPairing,
|
|
5
5
|
suggestedAgentName
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-BNMMRKEY.js";
|
|
7
7
|
import {
|
|
8
8
|
autoConfigureClients,
|
|
9
9
|
claudeInstallHint,
|
|
10
10
|
openBrowser
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-HKODQKUV.js";
|
|
12
|
+
import "./chunk-JLRBZZNT.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-PR7ROBN4.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-B7AOS5TG.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