@paigy/mcp 0.40.40 → 0.40.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -14
- package/dist/{chunk-6FG3PZR2.js → chunk-AX55W57P.js} +1 -1
- package/dist/{chunk-V4OVLFMP.js → chunk-CPDYOHSY.js} +94 -25
- package/dist/{chunk-H2EBILBE.js → chunk-NYSDESST.js} +55 -13
- package/dist/{chunk-PKJJSHLW.js → chunk-UVVW32KH.js} +2 -2
- package/dist/{dist-EJWDUF5J.js → dist-VYRT3PHE.js} +1 -1
- package/dist/enable.js +3 -3
- package/dist/index.js +5 -5
- package/dist/listen.js +4 -4
- 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 +2 -1
package/README.md
CHANGED
|
@@ -109,19 +109,20 @@ Or add the entry to `~/.gemini/settings.json`:
|
|
|
109
109
|
|
|
110
110
|
Then pair: `PAIGY_AGENT=gemini npx -p @paigy/mcp@latest paigy-mcp-onboard`.
|
|
111
111
|
|
|
112
|
-
> `PAIGY_AGENT` names the agent AND keys its token slot
|
|
113
|
-
> `mcp-agent`
|
|
114
|
-
> `PAIGY_AGENT` the client's config uses
|
|
115
|
-
>
|
|
112
|
+
> `PAIGY_AGENT` names the agent AND keys its token slot. Without it, each session gets a private slot
|
|
113
|
+
> (`session:<id>`); the shared `mcp-agent` default went on 2026-08-07. Each client reads only its own slot, so pair with the same
|
|
114
|
+
> `PAIGY_AGENT` the client's config uses. A fixed `PAIGY_AGENT` makes every session of that client one agent: two running at once
|
|
115
|
+
> collide, and the copy set aside is refused `holder_conflict` when it acts (#2933). `paigy-harness setup` wires clients without it,
|
|
116
|
+
> so each session hatches its own identity.
|
|
116
117
|
|
|
117
118
|
## Tools
|
|
118
119
|
|
|
119
120
|
One catalog, on every transport (2026-09-11): the agent tools are `AGENT_TOOLS` in
|
|
120
|
-
`packages/schema/src/tools.ts`
|
|
121
|
-
send_feedback
|
|
121
|
+
`packages/schema/src/tools.ts` (configure, contact, manage_goals, get_delivery, get_goals, search, check_activity,
|
|
122
|
+
send_feedback), and both this server and the hosted MCP
|
|
122
123
|
(`apps/api/src/mcp`) publish that list and dispatch it through the SDK's one `runTool`.
|
|
123
|
-
This server
|
|
124
|
-
renames and logs this agent out (`logOut: true`) over the token file this machine holds
|
|
124
|
+
This server extends `configure`, the one identity tool, which on the hosted MCP only reports who you are: here it also pairs,
|
|
125
|
+
renames and logs this agent out (`logOut: true`) over the token file this machine holds. It adds `listen`.
|
|
125
126
|
`onboard` is now `configure`; `pair` and `unpair` are folded into it (2026-10-07). See the [SDK contract](../../packages/sdk/README.md) for the
|
|
126
127
|
contact shape. Sending returns immediately unless it asks to `wait`: `wait: true` holds one
|
|
127
128
|
cancellable ~45-second window here for a response to what was sent (the hosted transport
|
|
@@ -145,9 +146,8 @@ time. Bookkeeping (`operationId`, the manage request id, the revision an edit wa
|
|
|
145
146
|
minted here, never asked of the model. Retired
|
|
146
147
|
reply-lease/ACK/work/callback tools and hidden notification aliases are rejected.
|
|
147
148
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
not a compatibility fallback for target MCP tools.
|
|
149
|
+
Until 2026-09-13 the standalone listener below was a legacy host with its own reply intake. Since #1957 it reads
|
|
150
|
+
the same `receive` as `contact({})`, as the next section says.
|
|
151
151
|
|
|
152
152
|
## Configuration
|
|
153
153
|
|
|
@@ -305,12 +305,12 @@ machine is paired and this session's identity is minted by its first tool call;
|
|
|
305
305
|
|
|
306
306
|
## Publishing (maintainers)
|
|
307
307
|
|
|
308
|
-
Tool input schemas are generated from zod
|
|
308
|
+
Tool input schemas are generated from zod by `mcpInputSchema` (`packages/schema/src/mcp-schema.ts`) as draft-2020-12 JSON
|
|
309
309
|
Schema, and `src/schema.test.ts` guards that every tool stays valid (strict clients
|
|
310
310
|
like the Anthropic API reject anything else). **A schema fix only reaches agents once
|
|
311
311
|
a new version is published to npm** — 0.8.0 once shipped *without* a committed fix and
|
|
312
|
-
400'd strict clients for weeks. So after any change
|
|
313
|
-
definitions: **bump the version
|
|
312
|
+
400'd strict clients for weeks. So after any change to the tool schemas (`packages/schema`) or the tool
|
|
313
|
+
definitions: **bump the version in `apps/mcp/package.json`**; publishing is `pnpm release` from the repo root, which the owner runs (`docs/infra/releasing.md`). Don't rely on the commit alone.
|
|
314
314
|
Install recipes pin `@paigy/mcp@latest` so a fresh `npx` picks up the new version; if a
|
|
315
315
|
stale one sticks, `rm -rf ~/.npm/_npx` and restart the client.
|
|
316
316
|
|
|
@@ -1517,16 +1517,16 @@ function parseWhen(said2, tz, nowMs, read22 = "earliest") {
|
|
|
1517
1517
|
let hour = null;
|
|
1518
1518
|
let minute = 0;
|
|
1519
1519
|
const spoken = new RegExp(`\\bat\\s+(${Object.keys(SPOKEN_HOUR).join("|")})\\b`, "i").exec(text);
|
|
1520
|
-
const
|
|
1520
|
+
const clock22 = CLOCK.exec(text);
|
|
1521
1521
|
if (spoken) {
|
|
1522
1522
|
hour = SPOKEN_HOUR[spoken[1].toLowerCase()];
|
|
1523
|
-
} else if (
|
|
1524
|
-
hour = Number(
|
|
1525
|
-
minute =
|
|
1523
|
+
} else if (clock22 && (clock22[3] || /\bat\s/i.test(clock22[0]))) {
|
|
1524
|
+
hour = Number(clock22[1]);
|
|
1525
|
+
minute = clock22[2] ? Number(clock22[2]) : 0;
|
|
1526
1526
|
if (hour > 23 || minute > 59) return null;
|
|
1527
1527
|
}
|
|
1528
1528
|
if (hour !== null) {
|
|
1529
|
-
const mer =
|
|
1529
|
+
const mer = clock22?.[3]?.toLowerCase().replace(/\./g, "") ?? "";
|
|
1530
1530
|
const pmWord = /\b(p\.?m\.?|afternoon|evening|tonight|at night)\b/i.test(text);
|
|
1531
1531
|
const amWord = /\b(a\.?m\.?|morning)\b/i.test(text);
|
|
1532
1532
|
if (mer.startsWith("p") || pmWord && !amWord) {
|
|
@@ -1787,7 +1787,7 @@ var sendFields = {
|
|
|
1787
1787
|
"COMPLETIONS close and report in one operation, the same contract as manage_goals kind:complete: closure and the report commit together or neither does. Required children and dependencies must already be finished. options suggest next steps: a tap acknowledges the report and requests that step, and never reopens the Goal (follow-up work needs a new one). No reviewer rejudges it: say only what your evidence supports. Ordinary updates never close a Goal."
|
|
1788
1788
|
),
|
|
1789
1789
|
updates: z4.array(UpdateInputSchema).min(1).max(20).optional().describe(
|
|
1790
|
-
"News: progress, findings, a result. An update asks nothing. It reaches the person only when they asked for it (userExplicitlyRequested), when it answers something they said, or once its Goal is done; otherwise it is recorded as the Goal's progress
|
|
1790
|
+
"News: progress, findings, a result. An update asks nothing. It reaches the person only when they asked for it (userExplicitlyRequested), when it answers something they said, or once its Goal is done; otherwise it is recorded as the Goal's progress, which the person is not told. Every update reaches the other agents that wrote on its Goal in the last hour: to tell another agent something, write it as an update on that agent's Goal."
|
|
1791
1791
|
),
|
|
1792
1792
|
answers: z4.array(AnswerInputSchema).min(1).max(20).optional().describe("Answers to Questions addressed to you."),
|
|
1793
1793
|
withdrawQuestionIds: z4.array(questionHandle).min(1).max(10).optional().describe(
|
|
@@ -1922,9 +1922,12 @@ var GetGoalsSchema = z5.object({
|
|
|
1922
1922
|
history: z5.boolean().optional()
|
|
1923
1923
|
}).strict();
|
|
1924
1924
|
var GetDeliverySchema = z5.object({
|
|
1925
|
-
deliveryId: z5.string().uuid().describe("The Delivery id returned by contact or receive.")
|
|
1925
|
+
deliveryId: z5.string().uuid().describe("The Delivery id returned by contact or receive."),
|
|
1926
|
+
// WHAT WAS SAID ON A CALL (owner, 2026-10-26, Goal c743f4a4: "A flag on get_delivery", "Any of my agents").
|
|
1927
|
+
transcript: z5.boolean().optional().describe("For a Call: also return what was said on it, one page of spoken lines."),
|
|
1928
|
+
after: z5.string().max(40).optional().describe("With transcript: the next value the previous page returned, to read the next page.")
|
|
1926
1929
|
}).strict();
|
|
1927
|
-
var GET_DELIVERY_DESCRIPTION = "Read a Delivery in full: its whole ask, units, options and answers, plus current callState and callOutcome for a Call. Any agent of the same account may read it; another account is not disclosed. Reading never acknowledges or resends anything. Use this after a call or when receive names a Call you are waiting on.";
|
|
1930
|
+
var GET_DELIVERY_DESCRIPTION = "Read a Delivery in full: its whole ask, units, options and answers, plus current callState and callOutcome for a Call. For a Call, transcript: true adds what was said: each spoken line in order, who said it, and when from pickup, a page at a time. A line from the room, not the person, is marked room. Any agent of the same account may read it; another account is not disclosed. Reading never acknowledges or resends anything. Use this after a call or when receive names a Call you are waiting on.";
|
|
1928
1931
|
var GET_GOALS_DESCRIPTION = "Read one to ten Goals by goalIds, returned in the same order under goals (a read never puts you on them). history applies to every requested Goal. A refused read fails the call with its original refusal; no partial result is presented as complete. Each Goal includes its ten most recent other contributors (names, latest entry headlines and times), 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.";
|
|
1929
1932
|
var SearchToolSchema = z5.object({
|
|
1930
1933
|
query: z5.string().trim().min(1).max(500),
|
|
@@ -2143,8 +2146,9 @@ var TALKER_REPLY_JSON_SCHEMA = (({ $schema: _, ...rest }) => rest)(
|
|
|
2143
2146
|
var str4 = z8.string();
|
|
2144
2147
|
var strs3 = z8.array(z8.string());
|
|
2145
2148
|
var FilerReplySchema = z8.object({
|
|
2146
|
-
/** Which Goals each new line goes on: a line's handle, Goal handles (or keys of new Goals
|
|
2147
|
-
* the line says in at most
|
|
2149
|
+
/** Which Goals each new line goes on: a line's handle, Goal handles (or keys of new Goals: a line that asks
|
|
2150
|
+
* for new work goes on the Goal it creates, owner 2026-10-26), and what the line says in at most twenty
|
|
2151
|
+
* words (owner, 2026-10-26: "bump it from 10 to 20 words"). */
|
|
2148
2152
|
filed: z8.array(z8.object({ line: str4, goals: strs3, summary: str4 }).strict()),
|
|
2149
2153
|
goals: z8.array(z8.object({
|
|
2150
2154
|
op: z8.enum(["create", "edit", "complete", "cancel", "reopen", "assign", "defer", "move", "block", "unblock"]),
|
|
@@ -2419,7 +2423,7 @@ var NotifyRequestFields = z12.object({
|
|
|
2419
2423
|
* derive agent-side before sealing, so the server only ever shapes plaintext). */
|
|
2420
2424
|
// 10k, not a sentence budget. What the human hears is bounded by the BROKER — it splits
|
|
2421
2425
|
// the ask into topics and gives each one at most three sentences and one question
|
|
2422
|
-
// (docs/
|
|
2426
|
+
// (docs/history/agenda-design.md) — not by a wire cap the agent has to pre-summarize under.
|
|
2423
2427
|
// Owner, 2026-07-28: "our actual limitation on how long something is to the user should
|
|
2424
2428
|
// come from the broker splitting and summarizing." The cap that remains is a size guard.
|
|
2425
2429
|
ask: z12.string().min(1).max(1e4).optional().describe(
|
|
@@ -2496,7 +2500,7 @@ var UserAnswerSchema = z12.discriminatedUnion("kind", [
|
|
|
2496
2500
|
z12.object({ kind: z12.literal("clarify"), chunks: z12.array(z12.string()).min(1) }),
|
|
2497
2501
|
z12.object({ kind: z12.literal("confirm"), approved: z12.boolean() }),
|
|
2498
2502
|
z12.object({ kind: z12.literal("turns"), turns: z12.array(TurnSchema).min(1) }),
|
|
2499
|
-
/** An auto-answer derived from the user's PAST decisions (docs/
|
|
2503
|
+
/** An auto-answer derived from the user's PAST decisions (docs/history/precedent-design.md §2):
|
|
2500
2504
|
* delivered through the same settle/await path as a human answer, carrying the judge's
|
|
2501
2505
|
* derivation and the precedent ids it grew from. Always paired with a visible trail
|
|
2502
2506
|
* card the user can reply to — the broker never overrides the user. */
|
|
@@ -2812,7 +2816,7 @@ var InboxItemSchema = z12.object({
|
|
|
2812
2816
|
"Labels for a select:'confirm' paige \u2014 'yesno' (Yes/No) or 'approve' (Approve/Deny). Ignored unless select is 'confirm'."
|
|
2813
2817
|
),
|
|
2814
2818
|
/** Real downstream work is stuck behind this one — set by the agent, independent of
|
|
2815
|
-
* urgency (see the main README's "premier use case" + docs/
|
|
2819
|
+
* urgency (see the main README's "premier use case" + docs/history/notify-states.md). Drives the
|
|
2816
2820
|
* inbox's blocking badge and the extra confirm step before dismissing it. */
|
|
2817
2821
|
blocking: z12.boolean().default(false),
|
|
2818
2822
|
/** WHAT FREED THIS QUESTION (owner, 2026-10-16, Goal 2383ef14: "we don't really show the question
|
|
@@ -2830,6 +2834,12 @@ var InboxItemSchema = z12.object({
|
|
|
2830
2834
|
/** The answer in ten words, when the talker wrote one beside it. */
|
|
2831
2835
|
summary: z12.string().optional()
|
|
2832
2836
|
}).optional(),
|
|
2837
|
+
/** WHAT THIS CARD ANSWERS (owner, 2026-10-27, Goal 81b6a9d6: "this reads very clearly as an answer to
|
|
2838
|
+
* something I asked, but I don't see the question… To show the question near the top of the card").
|
|
2839
|
+
* An agent's card that is its answer to one of the person's own questions carries that question's
|
|
2840
|
+
* words, drawn above it as "You asked" (`public.questions_answered_by`, read beside the card read).
|
|
2841
|
+
* Absent on every card that answers nothing of theirs, and on a held question, which has `freedBy`. */
|
|
2842
|
+
answering: z12.object({ asked: z12.string() }).optional(),
|
|
2833
2843
|
/** The user's locked-in answer; present only for replied items (GET /api/replied/:id). */
|
|
2834
2844
|
answer: UserAnswerSchema.optional(),
|
|
2835
2845
|
/** THE TARGET FACTS A CARD RENDERS (#1796 point 5, 2026-09-11): the Delivery it is a view of,
|
|
@@ -2891,6 +2901,7 @@ var MissedCallSchema = z12.enum([
|
|
|
2891
2901
|
]);
|
|
2892
2902
|
var clock = (h) => h === 0 ? "midnight" : h === 12 ? "noon" : h < 12 ? `${h} am` : `${h - 12} pm`;
|
|
2893
2903
|
var QUIET = ` Nothing rings from ${clock(NIGHT.from)} to ${clock(NIGHT.to)} your time; the count waits for morning.`;
|
|
2904
|
+
var THEIR_QUIET = ` Nothing rings from ${clock(NIGHT.from)} to ${clock(NIGHT.to)} their time; the count waits for morning.`;
|
|
2894
2905
|
var BrokerTuningSchema = z12.object({
|
|
2895
2906
|
/** 'none' = skip the spoken ack after a mapped answer (power users find it slow). */
|
|
2896
2907
|
ackVerbosity: z12.enum(["normal", "none"]).optional(),
|
|
@@ -3015,7 +3026,8 @@ var ConnectionSummarySchema = z12.object({
|
|
|
3015
3026
|
kind: z12.enum(["device", "agent"]).optional(),
|
|
3016
3027
|
/** For an agent, the token id of the DEVICE that minted it — so agents group under their
|
|
3017
3028
|
* machine, and revoking a device cascades to them. Null on devices, and on unlinked
|
|
3018
|
-
* agents (
|
|
3029
|
+
* agents (provider-managed, hatched by another agent, or minted before the link existed);
|
|
3030
|
+
* a phone-launched agent is linked to the computer it runs on since #1602. */
|
|
3019
3031
|
mintedByDevice: z12.string().nullable().optional(),
|
|
3020
3032
|
device: z12.string().nullable(),
|
|
3021
3033
|
/** The agent's display name (the single pairing name). */
|
|
@@ -3029,7 +3041,7 @@ var ConnectionSummarySchema = z12.object({
|
|
|
3029
3041
|
* user on the agent's own page. null = no ceiling (today's behaviour for every
|
|
3030
3042
|
* connection). Android binds importance to a relationship rather than to each message,
|
|
3031
3043
|
* and that is the thing our roster could not say: "Marlow may always call me; Otto
|
|
3032
|
-
* never may" (docs/
|
|
3044
|
+
* never may" (docs/history/party-navigation-design.md, gap 2). Clamped in `arbitrateLevel`, so it binds
|
|
3033
3045
|
* every surface at once and outranks even `sessionMode: all_calls` — a mode the user
|
|
3034
3046
|
* set once must not overrule a rule they set about one agent. */
|
|
3035
3047
|
reach: NotifyLevelSchema.nullable().optional(),
|
|
@@ -3188,12 +3200,14 @@ var QueueItemSchema = z12.object({
|
|
|
3188
3200
|
/** Its questions: every OPEN one, and at most ten settled, newest settled first
|
|
3189
3201
|
* (20260929133308) — the page decides which of them to show. NOT the whole set: `asked` and
|
|
3190
3202
|
* `answered` are, and a settled one's words are a line (280 characters), its body read when the
|
|
3191
|
-
* question is opened.
|
|
3203
|
+
* question is opened. Never a CANCELLED one (withdrawn, dismissed, or its Goal or call ended): it
|
|
3204
|
+
* asks nothing of anyone (#3723). */
|
|
3192
3205
|
questions: z12.array(QueueQuestionSchema).default([]),
|
|
3193
3206
|
/** HOW MANY QUESTIONS THIS WORK HAS ASKED, and how many are answered — the Goal's own totals,
|
|
3194
3207
|
* bounded at 100 server-side. A tally counted off `questions` is a wrong number that looks
|
|
3195
3208
|
* right once the cap bites (`walk/trees.ts` `tallyOf`). Optional, and defaulted from the array
|
|
3196
|
-
* by the projection, so hand-built queues (fixtures, the demo) need not spell them.
|
|
3209
|
+
* by the projection, so hand-built queues (fixtures, the demo) need not spell them. A cancelled
|
|
3210
|
+
* question is not asked (#3725). */
|
|
3197
3211
|
asked: z12.number().optional(),
|
|
3198
3212
|
answered: z12.number().optional(),
|
|
3199
3213
|
/** Every note on it the person replied to (`QueueReplySchema`) — the page decides which to show.
|
|
@@ -3208,6 +3222,10 @@ var QueueItemSchema = z12.object({
|
|
|
3208
3222
|
* as progress). `updatedAt` moves for reasons nobody chose — a
|
|
3209
3223
|
* state recomputed, a review flag — so it cannot tell work in hand from work gone quiet. */
|
|
3210
3224
|
lastProgressAt: z12.string().nullable().optional(),
|
|
3225
|
+
/** WHEN AN AGENT LAST ACTED ON IT (owner, 2026-10-27: "Move it now", Goal 567258dc): its newest agent write, an
|
|
3226
|
+
* Entry or a Goal change, Paigy's excluded (`goals.worked_at`). What keeps work an agent is writing on from
|
|
3227
|
+
* reading as gone quiet (`coldSince`); absent on a door that does not carry it. */
|
|
3228
|
+
workedAt: z12.string().nullable().optional(),
|
|
3211
3229
|
/** THE GOAL'S NEWEST WORD, FROM EITHER SIDE (owner, 2026-09-27): the newest Entry on it, of any
|
|
3212
3230
|
* kind — what the person added ("Add to this"), their reply, the agent's ask or its progress
|
|
3213
3231
|
* note. A progress note is an Entry, so this is already the newer of the two: the person's note
|
|
@@ -3500,6 +3518,11 @@ var CallRecapSchema = z12.object({
|
|
|
3500
3518
|
durationMs: z12.number().nullable(),
|
|
3501
3519
|
/** Bot-clock pickup offset; absent before the timestamp release, null before its report lands. */
|
|
3502
3520
|
pickupMs: z12.number().nullable().optional(),
|
|
3521
|
+
/** STILL FILING (20261026182117): the call has not ended on the server, or it has and a brain cycle on it is
|
|
3522
|
+
* still pending, the next writer, which may still settle, file or start something. What the close itself
|
|
3523
|
+
* waits for (`private.close_call`). `status` cannot say it: nothing writes "finalizing", and a call reads
|
|
3524
|
+
* "open" until the sweep closes it, after nothing is pending. Absent from an API before it. */
|
|
3525
|
+
filing: z12.boolean().optional(),
|
|
3503
3526
|
agents: z12.array(z12.object({ id: z12.string(), name: z12.string().nullable() }))
|
|
3504
3527
|
}),
|
|
3505
3528
|
topics: z12.array(z12.object({
|
|
@@ -3554,7 +3577,8 @@ var CallRecapSchema = z12.object({
|
|
|
3554
3577
|
words: z12.string(),
|
|
3555
3578
|
atMs: z12.number()
|
|
3556
3579
|
})),
|
|
3557
|
-
|
|
3580
|
+
/** What did not fit, counted. `settles` counts items past the recap's 100; absent before 20261026165518. */
|
|
3581
|
+
more: z12.object({ lines: z12.number(), entries: z12.number(), topics: z12.number(), settles: z12.number().optional() }),
|
|
3558
3582
|
/** Last stored position on this page when another exists; absent before paging shipped. */
|
|
3559
3583
|
next: z12.number().int().nonnegative().nullable().optional(),
|
|
3560
3584
|
/** THE CALL AS ONE LIST OF ROWS (owner, 2026-10-14: "we only really want a thing like transcript but
|
|
@@ -3593,6 +3617,24 @@ var CallRecapSchema = z12.object({
|
|
|
3593
3617
|
* from an API before it, where the screen falls back to its own reading. */
|
|
3594
3618
|
waiting: z12.boolean().optional(),
|
|
3595
3619
|
lineIds: z12.array(z12.string())
|
|
3620
|
+
})).optional(),
|
|
3621
|
+
/** THE RECAP (owner, 2026-10-26: "the transcript should just be the entries that settled or
|
|
3622
|
+
* acknowledged the items; that's it"). Each item the person's words settled on this call, in the
|
|
3623
|
+
* order they said them: who asked it (`by`), the item in its agent's words (`title`), and only the
|
|
3624
|
+
* words of theirs that settled it (`lines`: each line once, verbatim, with when it was said on the
|
|
3625
|
+
* bot clock like `said[].atMs`). Built from their replies, not from what the call put, so an item
|
|
3626
|
+
* settled without being put is still here. Beside them (owner: "List them too, with the words that
|
|
3627
|
+
* said them"), each Goal his words told something (`kind` "told") or the call started ("started"),
|
|
3628
|
+
* with `requestId` null and the Goal's name as `title`; a started Goal may have no `lines` yet. `kind`
|
|
3629
|
+
* is a string, not an enum, so a later kind never fails an older build's parse; `requestId` is the
|
|
3630
|
+
* request the words settled. On the first page only; absent from an API before it. */
|
|
3631
|
+
settles: z12.array(z12.object({
|
|
3632
|
+
requestId: z12.string().nullable(),
|
|
3633
|
+
kind: z12.string(),
|
|
3634
|
+
by: z12.object({ participant: z12.string(), agentId: z12.string().nullable(), name: z12.string() }),
|
|
3635
|
+
goalId: z12.string().uuid().nullable(),
|
|
3636
|
+
title: z12.string(),
|
|
3637
|
+
lines: z12.array(z12.object({ lineId: z12.string(), words: z12.string(), atMs: z12.number() }))
|
|
3596
3638
|
})).optional()
|
|
3597
3639
|
});
|
|
3598
3640
|
function sessionSlot(sessionId2) {
|
|
@@ -3936,11 +3978,12 @@ async function checkActivity(opts = {}) {
|
|
|
3936
3978
|
if (!res.ok) await fail("check_activity", res);
|
|
3937
3979
|
return await res.json();
|
|
3938
3980
|
}
|
|
3939
|
-
var NOT_SENT = `Recorded as the Goal's progress, not sent
|
|
3981
|
+
var NOT_SENT = `Recorded as the Goal's progress, not sent to the person; the other agents that wrote on the Goal in the last hour are told. The person is told only a question, an answer to one they asked you, and what you say once the Goal is done. To close the work, send contact.completions or manage_goals kind:complete with the shared completion report, closing and reporting together. If the person asked you, in so many words, to send them this, send it again with userExplicitlyRequested: "any" on that update.`;
|
|
3940
3982
|
var APPLIED = "Applied; nothing was sent to the person.";
|
|
3941
3983
|
var DEMOTED = "Delivered as a card, not a call: the person's settings do not allow a call right now (silent, quiet hours, or a mode). It has reached them; do not send it again.";
|
|
3942
3984
|
async function readDelivery(deliveryId, opts = {}) {
|
|
3943
|
-
const
|
|
3985
|
+
const query = opts.transcript ? `?transcript=1${opts.after ? `&after=${encodeURIComponent(opts.after)}` : ""}` : "";
|
|
3986
|
+
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/deliveries/${encodeURIComponent(deliveryId)}${query}`, {
|
|
3944
3987
|
headers: { authorization: `Bearer ${authToken(opts.token) ?? ""}` },
|
|
3945
3988
|
signal: opts.signal
|
|
3946
3989
|
}));
|
|
@@ -4177,7 +4220,11 @@ function goalView(g) {
|
|
|
4177
4220
|
subtree: g.subtree?.length ? g.subtree.map((c) => compact({
|
|
4178
4221
|
goal: `${" ".repeat(c.depth - 1)}${c.title} (${c.state})`,
|
|
4179
4222
|
goalId: c.goalId,
|
|
4180
|
-
|
|
4223
|
+
// AN ANSWERED QUESTION NEVER READS OPEN (2026-10-27, Goal b5f1fc27): an answer given on a call,
|
|
4224
|
+
// an option pick or a spoken reply, has an instant on the list's row and no words there, and
|
|
4225
|
+
// it read "(open)". Seven answered questions read that way, and an agent reading them would
|
|
4226
|
+
// ask the owner again. The words are on the Goal's own read.
|
|
4227
|
+
questions: c.questions.length ? c.questions.map((q) => `${q.question} \u2192 ${q.answer || (q.answeredAt ? "(answered: read this Goal for the answer)" : "(open)")}`) : void 0
|
|
4181
4228
|
})) : void 0,
|
|
4182
4229
|
blockedBy: g.blockedDependencyGoalIds,
|
|
4183
4230
|
dueAt: g.dueAt,
|
|
@@ -4205,7 +4252,8 @@ var itemsView = (results) => (results ?? []).map((r) => compact({
|
|
|
4205
4252
|
error: r.error,
|
|
4206
4253
|
detail: r.detail
|
|
4207
4254
|
}));
|
|
4208
|
-
function deliveryReadView(d) {
|
|
4255
|
+
function deliveryReadView(d, asked2 = {}) {
|
|
4256
|
+
const t = d.transcript;
|
|
4209
4257
|
return compact({
|
|
4210
4258
|
deliveryId: d.deliveryId,
|
|
4211
4259
|
kind: d.kind,
|
|
@@ -4214,9 +4262,20 @@ function deliveryReadView(d) {
|
|
|
4214
4262
|
conversation: conversation(d),
|
|
4215
4263
|
callState: d.callState,
|
|
4216
4264
|
callOutcome: d.callOutcome ?? (d.kind === "call" ? d.message : void 0),
|
|
4217
|
-
|
|
4265
|
+
// WHAT WAS SAID (owner, 2026-10-26): each line as "m:ss", who said it, and the words; `for` and `room` only
|
|
4266
|
+
// when they are true of the line, so a short call reads as the call did.
|
|
4267
|
+
transcript: t ? compact({
|
|
4268
|
+
timedFrom: t.pickupKnown ? "pickup" : "the call's start",
|
|
4269
|
+
lines: t.lines.map((l) => compact({ at: clock2(l.atMs), by: l.by, for: l.for ?? void 0, room: l.room || void 0, words: l.words })),
|
|
4270
|
+
next: t.next ?? void 0
|
|
4271
|
+
}) : void 0,
|
|
4272
|
+
next: t?.next ? `Read the next page of the transcript with get_delivery({deliveryId: "${d.deliveryId}", transcript: true, after: "${t.next}"}).` : asked2.transcript && !t ? d.kind === "call" ? "This API sent no transcript: it is older than the transcript, or the call has none it can show." : "Only a Call has a transcript." : d.callState && d.callState !== "ended" ? "Keep receiving with contact({wait:true}) while this Call is open, even after an empty window. Do not resend the ask." : "Answers and follow-ups are on their Goals; receive on your next wake. This read acknowledges nothing."
|
|
4218
4273
|
});
|
|
4219
4274
|
}
|
|
4275
|
+
function clock2(ms) {
|
|
4276
|
+
const s = Math.max(0, Math.floor(ms / 1e3));
|
|
4277
|
+
return `${Math.floor(s / 60)}:${String(s % 60).padStart(2, "0")}`;
|
|
4278
|
+
}
|
|
4220
4279
|
function deliveryView(d) {
|
|
4221
4280
|
const answers = "Answers land on the Goal: collect them with contact({wait:true}) or get_goals. Do not resend it.";
|
|
4222
4281
|
const pending = d.state === "open" && d.decisionNeeds.some((n) => n.state === "open");
|
|
@@ -4296,6 +4355,8 @@ function receivedView(r, now = Date.now()) {
|
|
|
4296
4355
|
// on startup and after a wake (contact({wait:false}), and every hosted receive), never on a window of a
|
|
4297
4356
|
// held wait, which would repeat them window after window.
|
|
4298
4357
|
houseRules: r.waitOutcome === "not_waited" ? w.houseRules : void 0,
|
|
4358
|
+
// THEIR RING POLICY, ONE FOR EVERY AGENT (owner, 2026-10-27, Goal 6faa6a51), on the same reads as the house rules.
|
|
4359
|
+
ringPolicy: r.waitOutcome === "not_waited" ? w.ringPolicy : void 0,
|
|
4299
4360
|
next: [
|
|
4300
4361
|
r.events.length ? `Handle each event, then acknowledge the ones you handled: contact({ ackEventIds: [${r.events.filter((e) => e.kind !== "question").map((e) => `"${e.eventId}"`).join(", ")}] }).` : w.claimable || assigned.length || rings.length || w.calls?.some((c) => c.callState !== "ended") ? "No messages." : "Nothing is waiting.",
|
|
4301
4362
|
...owed.length ? [`You owe ${owed.length === 1 ? "an answer" : `${owed.length} answers`}: contact({ answers: [{ questionId: "<questionId>", answer: { text: <your answer> } }] }) for each question; a question is answered, never acknowledged.`] : [],
|
|
@@ -4380,8 +4441,16 @@ async function runTool(name, args, opts) {
|
|
|
4380
4441
|
for (const g of managed.goals ?? []) remember(client.token, g.goalId, g.revision);
|
|
4381
4442
|
return managedView(managed, changes);
|
|
4382
4443
|
}
|
|
4383
|
-
case "get_delivery":
|
|
4384
|
-
|
|
4444
|
+
case "get_delivery": {
|
|
4445
|
+
const asked2 = GetDeliverySchema.parse(input);
|
|
4446
|
+
return deliveryReadView(
|
|
4447
|
+
await readDelivery(
|
|
4448
|
+
asked2.deliveryId,
|
|
4449
|
+
{ ...client, signal, ...asked2.transcript ? { transcript: true, ...asked2.after ? { after: asked2.after } : {} } : {} }
|
|
4450
|
+
),
|
|
4451
|
+
{ transcript: asked2.transcript === true }
|
|
4452
|
+
);
|
|
4453
|
+
}
|
|
4385
4454
|
case "get_goals": {
|
|
4386
4455
|
const { goalIds, history } = GetGoalsSchema.parse(input);
|
|
4387
4456
|
const rows = await getGoals(goalIds, client, { history });
|
|
@@ -264,7 +264,7 @@ var sendFields = {
|
|
|
264
264
|
"COMPLETIONS close and report in one operation, the same contract as manage_goals kind:complete: closure and the report commit together or neither does. Required children and dependencies must already be finished. options suggest next steps: a tap acknowledges the report and requests that step, and never reopens the Goal (follow-up work needs a new one). No reviewer rejudges it: say only what your evidence supports. Ordinary updates never close a Goal."
|
|
265
265
|
),
|
|
266
266
|
updates: z4.array(UpdateInputSchema).min(1).max(20).optional().describe(
|
|
267
|
-
"News: progress, findings, a result. An update asks nothing. It reaches the person only when they asked for it (userExplicitlyRequested), when it answers something they said, or once its Goal is done; otherwise it is recorded as the Goal's progress
|
|
267
|
+
"News: progress, findings, a result. An update asks nothing. It reaches the person only when they asked for it (userExplicitlyRequested), when it answers something they said, or once its Goal is done; otherwise it is recorded as the Goal's progress, which the person is not told. Every update reaches the other agents that wrote on its Goal in the last hour: to tell another agent something, write it as an update on that agent's Goal."
|
|
268
268
|
),
|
|
269
269
|
answers: z4.array(AnswerInputSchema).min(1).max(20).optional().describe("Answers to Questions addressed to you."),
|
|
270
270
|
withdrawQuestionIds: z4.array(questionHandle).min(1).max(10).optional().describe(
|
|
@@ -399,9 +399,12 @@ var GetGoalsSchema = z5.object({
|
|
|
399
399
|
history: z5.boolean().optional()
|
|
400
400
|
}).strict();
|
|
401
401
|
var GetDeliverySchema = z5.object({
|
|
402
|
-
deliveryId: z5.string().uuid().describe("The Delivery id returned by contact or receive.")
|
|
402
|
+
deliveryId: z5.string().uuid().describe("The Delivery id returned by contact or receive."),
|
|
403
|
+
// WHAT WAS SAID ON A CALL (owner, 2026-10-26, Goal c743f4a4: "A flag on get_delivery", "Any of my agents").
|
|
404
|
+
transcript: z5.boolean().optional().describe("For a Call: also return what was said on it, one page of spoken lines."),
|
|
405
|
+
after: z5.string().max(40).optional().describe("With transcript: the next value the previous page returned, to read the next page.")
|
|
403
406
|
}).strict();
|
|
404
|
-
var GET_DELIVERY_DESCRIPTION = "Read a Delivery in full: its whole ask, units, options and answers, plus current callState and callOutcome for a Call. Any agent of the same account may read it; another account is not disclosed. Reading never acknowledges or resends anything. Use this after a call or when receive names a Call you are waiting on.";
|
|
407
|
+
var GET_DELIVERY_DESCRIPTION = "Read a Delivery in full: its whole ask, units, options and answers, plus current callState and callOutcome for a Call. For a Call, transcript: true adds what was said: each spoken line in order, who said it, and when from pickup, a page at a time. A line from the room, not the person, is marked room. Any agent of the same account may read it; another account is not disclosed. Reading never acknowledges or resends anything. Use this after a call or when receive names a Call you are waiting on.";
|
|
405
408
|
var GET_GOALS_DESCRIPTION = "Read one to ten Goals by goalIds, returned in the same order under goals (a read never puts you on them). history applies to every requested Goal. A refused read fails the call with its original refusal; no partial result is presented as complete. Each Goal includes its ten most recent other contributors (names, latest entry headlines and times), 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.";
|
|
406
409
|
var SearchToolSchema = z5.object({
|
|
407
410
|
query: z5.string().trim().min(1).max(500),
|
|
@@ -626,8 +629,9 @@ var TALKER_REPLY_JSON_SCHEMA = (({ $schema: _, ...rest }) => rest)(
|
|
|
626
629
|
var str4 = z8.string();
|
|
627
630
|
var strs3 = z8.array(z8.string());
|
|
628
631
|
var FilerReplySchema = z8.object({
|
|
629
|
-
/** Which Goals each new line goes on: a line's handle, Goal handles (or keys of new Goals
|
|
630
|
-
* the line says in at most
|
|
632
|
+
/** Which Goals each new line goes on: a line's handle, Goal handles (or keys of new Goals: a line that asks
|
|
633
|
+
* for new work goes on the Goal it creates, owner 2026-10-26), and what the line says in at most twenty
|
|
634
|
+
* words (owner, 2026-10-26: "bump it from 10 to 20 words"). */
|
|
631
635
|
filed: z8.array(z8.object({ line: str4, goals: strs3, summary: str4 }).strict()),
|
|
632
636
|
goals: z8.array(z8.object({
|
|
633
637
|
op: z8.enum(["create", "edit", "complete", "cancel", "reopen", "assign", "defer", "move", "block", "unblock"]),
|
|
@@ -888,7 +892,7 @@ var NotifyRequestFields = z12.object({
|
|
|
888
892
|
* derive agent-side before sealing, so the server only ever shapes plaintext). */
|
|
889
893
|
// 10k, not a sentence budget. What the human hears is bounded by the BROKER — it splits
|
|
890
894
|
// the ask into topics and gives each one at most three sentences and one question
|
|
891
|
-
// (docs/
|
|
895
|
+
// (docs/history/agenda-design.md) — not by a wire cap the agent has to pre-summarize under.
|
|
892
896
|
// Owner, 2026-07-28: "our actual limitation on how long something is to the user should
|
|
893
897
|
// come from the broker splitting and summarizing." The cap that remains is a size guard.
|
|
894
898
|
ask: z12.string().min(1).max(1e4).optional().describe(
|
|
@@ -965,7 +969,7 @@ var UserAnswerSchema = z12.discriminatedUnion("kind", [
|
|
|
965
969
|
z12.object({ kind: z12.literal("clarify"), chunks: z12.array(z12.string()).min(1) }),
|
|
966
970
|
z12.object({ kind: z12.literal("confirm"), approved: z12.boolean() }),
|
|
967
971
|
z12.object({ kind: z12.literal("turns"), turns: z12.array(TurnSchema).min(1) }),
|
|
968
|
-
/** An auto-answer derived from the user's PAST decisions (docs/
|
|
972
|
+
/** An auto-answer derived from the user's PAST decisions (docs/history/precedent-design.md §2):
|
|
969
973
|
* delivered through the same settle/await path as a human answer, carrying the judge's
|
|
970
974
|
* derivation and the precedent ids it grew from. Always paired with a visible trail
|
|
971
975
|
* card the user can reply to — the broker never overrides the user. */
|
|
@@ -1281,7 +1285,7 @@ var InboxItemSchema = z12.object({
|
|
|
1281
1285
|
"Labels for a select:'confirm' paige \u2014 'yesno' (Yes/No) or 'approve' (Approve/Deny). Ignored unless select is 'confirm'."
|
|
1282
1286
|
),
|
|
1283
1287
|
/** Real downstream work is stuck behind this one — set by the agent, independent of
|
|
1284
|
-
* urgency (see the main README's "premier use case" + docs/
|
|
1288
|
+
* urgency (see the main README's "premier use case" + docs/history/notify-states.md). Drives the
|
|
1285
1289
|
* inbox's blocking badge and the extra confirm step before dismissing it. */
|
|
1286
1290
|
blocking: z12.boolean().default(false),
|
|
1287
1291
|
/** WHAT FREED THIS QUESTION (owner, 2026-10-16, Goal 2383ef14: "we don't really show the question
|
|
@@ -1299,6 +1303,12 @@ var InboxItemSchema = z12.object({
|
|
|
1299
1303
|
/** The answer in ten words, when the talker wrote one beside it. */
|
|
1300
1304
|
summary: z12.string().optional()
|
|
1301
1305
|
}).optional(),
|
|
1306
|
+
/** WHAT THIS CARD ANSWERS (owner, 2026-10-27, Goal 81b6a9d6: "this reads very clearly as an answer to
|
|
1307
|
+
* something I asked, but I don't see the question… To show the question near the top of the card").
|
|
1308
|
+
* An agent's card that is its answer to one of the person's own questions carries that question's
|
|
1309
|
+
* words, drawn above it as "You asked" (`public.questions_answered_by`, read beside the card read).
|
|
1310
|
+
* Absent on every card that answers nothing of theirs, and on a held question, which has `freedBy`. */
|
|
1311
|
+
answering: z12.object({ asked: z12.string() }).optional(),
|
|
1302
1312
|
/** The user's locked-in answer; present only for replied items (GET /api/replied/:id). */
|
|
1303
1313
|
answer: UserAnswerSchema.optional(),
|
|
1304
1314
|
/** THE TARGET FACTS A CARD RENDERS (#1796 point 5, 2026-09-11): the Delivery it is a view of,
|
|
@@ -1360,6 +1370,7 @@ var MissedCallSchema = z12.enum([
|
|
|
1360
1370
|
]);
|
|
1361
1371
|
var clock = (h) => h === 0 ? "midnight" : h === 12 ? "noon" : h < 12 ? `${h} am` : `${h - 12} pm`;
|
|
1362
1372
|
var QUIET = ` Nothing rings from ${clock(NIGHT.from)} to ${clock(NIGHT.to)} your time; the count waits for morning.`;
|
|
1373
|
+
var THEIR_QUIET = ` Nothing rings from ${clock(NIGHT.from)} to ${clock(NIGHT.to)} their time; the count waits for morning.`;
|
|
1363
1374
|
var BrokerTuningSchema = z12.object({
|
|
1364
1375
|
/** 'none' = skip the spoken ack after a mapped answer (power users find it slow). */
|
|
1365
1376
|
ackVerbosity: z12.enum(["normal", "none"]).optional(),
|
|
@@ -1484,7 +1495,8 @@ var ConnectionSummarySchema = z12.object({
|
|
|
1484
1495
|
kind: z12.enum(["device", "agent"]).optional(),
|
|
1485
1496
|
/** For an agent, the token id of the DEVICE that minted it — so agents group under their
|
|
1486
1497
|
* machine, and revoking a device cascades to them. Null on devices, and on unlinked
|
|
1487
|
-
* agents (
|
|
1498
|
+
* agents (provider-managed, hatched by another agent, or minted before the link existed);
|
|
1499
|
+
* a phone-launched agent is linked to the computer it runs on since #1602. */
|
|
1488
1500
|
mintedByDevice: z12.string().nullable().optional(),
|
|
1489
1501
|
device: z12.string().nullable(),
|
|
1490
1502
|
/** The agent's display name (the single pairing name). */
|
|
@@ -1498,7 +1510,7 @@ var ConnectionSummarySchema = z12.object({
|
|
|
1498
1510
|
* user on the agent's own page. null = no ceiling (today's behaviour for every
|
|
1499
1511
|
* connection). Android binds importance to a relationship rather than to each message,
|
|
1500
1512
|
* and that is the thing our roster could not say: "Marlow may always call me; Otto
|
|
1501
|
-
* never may" (docs/
|
|
1513
|
+
* never may" (docs/history/party-navigation-design.md, gap 2). Clamped in `arbitrateLevel`, so it binds
|
|
1502
1514
|
* every surface at once and outranks even `sessionMode: all_calls` — a mode the user
|
|
1503
1515
|
* set once must not overrule a rule they set about one agent. */
|
|
1504
1516
|
reach: NotifyLevelSchema.nullable().optional(),
|
|
@@ -1657,12 +1669,14 @@ var QueueItemSchema = z12.object({
|
|
|
1657
1669
|
/** Its questions: every OPEN one, and at most ten settled, newest settled first
|
|
1658
1670
|
* (20260929133308) — the page decides which of them to show. NOT the whole set: `asked` and
|
|
1659
1671
|
* `answered` are, and a settled one's words are a line (280 characters), its body read when the
|
|
1660
|
-
* question is opened.
|
|
1672
|
+
* question is opened. Never a CANCELLED one (withdrawn, dismissed, or its Goal or call ended): it
|
|
1673
|
+
* asks nothing of anyone (#3723). */
|
|
1661
1674
|
questions: z12.array(QueueQuestionSchema).default([]),
|
|
1662
1675
|
/** HOW MANY QUESTIONS THIS WORK HAS ASKED, and how many are answered — the Goal's own totals,
|
|
1663
1676
|
* bounded at 100 server-side. A tally counted off `questions` is a wrong number that looks
|
|
1664
1677
|
* right once the cap bites (`walk/trees.ts` `tallyOf`). Optional, and defaulted from the array
|
|
1665
|
-
* by the projection, so hand-built queues (fixtures, the demo) need not spell them.
|
|
1678
|
+
* by the projection, so hand-built queues (fixtures, the demo) need not spell them. A cancelled
|
|
1679
|
+
* question is not asked (#3725). */
|
|
1666
1680
|
asked: z12.number().optional(),
|
|
1667
1681
|
answered: z12.number().optional(),
|
|
1668
1682
|
/** Every note on it the person replied to (`QueueReplySchema`) — the page decides which to show.
|
|
@@ -1677,6 +1691,10 @@ var QueueItemSchema = z12.object({
|
|
|
1677
1691
|
* as progress). `updatedAt` moves for reasons nobody chose — a
|
|
1678
1692
|
* state recomputed, a review flag — so it cannot tell work in hand from work gone quiet. */
|
|
1679
1693
|
lastProgressAt: z12.string().nullable().optional(),
|
|
1694
|
+
/** WHEN AN AGENT LAST ACTED ON IT (owner, 2026-10-27: "Move it now", Goal 567258dc): its newest agent write, an
|
|
1695
|
+
* Entry or a Goal change, Paigy's excluded (`goals.worked_at`). What keeps work an agent is writing on from
|
|
1696
|
+
* reading as gone quiet (`coldSince`); absent on a door that does not carry it. */
|
|
1697
|
+
workedAt: z12.string().nullable().optional(),
|
|
1680
1698
|
/** THE GOAL'S NEWEST WORD, FROM EITHER SIDE (owner, 2026-09-27): the newest Entry on it, of any
|
|
1681
1699
|
* kind — what the person added ("Add to this"), their reply, the agent's ask or its progress
|
|
1682
1700
|
* note. A progress note is an Entry, so this is already the newer of the two: the person's note
|
|
@@ -1967,6 +1985,11 @@ var CallRecapSchema = z12.object({
|
|
|
1967
1985
|
durationMs: z12.number().nullable(),
|
|
1968
1986
|
/** Bot-clock pickup offset; absent before the timestamp release, null before its report lands. */
|
|
1969
1987
|
pickupMs: z12.number().nullable().optional(),
|
|
1988
|
+
/** STILL FILING (20261026182117): the call has not ended on the server, or it has and a brain cycle on it is
|
|
1989
|
+
* still pending, the next writer, which may still settle, file or start something. What the close itself
|
|
1990
|
+
* waits for (`private.close_call`). `status` cannot say it: nothing writes "finalizing", and a call reads
|
|
1991
|
+
* "open" until the sweep closes it, after nothing is pending. Absent from an API before it. */
|
|
1992
|
+
filing: z12.boolean().optional(),
|
|
1970
1993
|
agents: z12.array(z12.object({ id: z12.string(), name: z12.string().nullable() }))
|
|
1971
1994
|
}),
|
|
1972
1995
|
topics: z12.array(z12.object({
|
|
@@ -2021,7 +2044,8 @@ var CallRecapSchema = z12.object({
|
|
|
2021
2044
|
words: z12.string(),
|
|
2022
2045
|
atMs: z12.number()
|
|
2023
2046
|
})),
|
|
2024
|
-
|
|
2047
|
+
/** What did not fit, counted. `settles` counts items past the recap's 100; absent before 20261026165518. */
|
|
2048
|
+
more: z12.object({ lines: z12.number(), entries: z12.number(), topics: z12.number(), settles: z12.number().optional() }),
|
|
2025
2049
|
/** Last stored position on this page when another exists; absent before paging shipped. */
|
|
2026
2050
|
next: z12.number().int().nonnegative().nullable().optional(),
|
|
2027
2051
|
/** THE CALL AS ONE LIST OF ROWS (owner, 2026-10-14: "we only really want a thing like transcript but
|
|
@@ -2060,6 +2084,24 @@ var CallRecapSchema = z12.object({
|
|
|
2060
2084
|
* from an API before it, where the screen falls back to its own reading. */
|
|
2061
2085
|
waiting: z12.boolean().optional(),
|
|
2062
2086
|
lineIds: z12.array(z12.string())
|
|
2087
|
+
})).optional(),
|
|
2088
|
+
/** THE RECAP (owner, 2026-10-26: "the transcript should just be the entries that settled or
|
|
2089
|
+
* acknowledged the items; that's it"). Each item the person's words settled on this call, in the
|
|
2090
|
+
* order they said them: who asked it (`by`), the item in its agent's words (`title`), and only the
|
|
2091
|
+
* words of theirs that settled it (`lines`: each line once, verbatim, with when it was said on the
|
|
2092
|
+
* bot clock like `said[].atMs`). Built from their replies, not from what the call put, so an item
|
|
2093
|
+
* settled without being put is still here. Beside them (owner: "List them too, with the words that
|
|
2094
|
+
* said them"), each Goal his words told something (`kind` "told") or the call started ("started"),
|
|
2095
|
+
* with `requestId` null and the Goal's name as `title`; a started Goal may have no `lines` yet. `kind`
|
|
2096
|
+
* is a string, not an enum, so a later kind never fails an older build's parse; `requestId` is the
|
|
2097
|
+
* request the words settled. On the first page only; absent from an API before it. */
|
|
2098
|
+
settles: z12.array(z12.object({
|
|
2099
|
+
requestId: z12.string().nullable(),
|
|
2100
|
+
kind: z12.string(),
|
|
2101
|
+
by: z12.object({ participant: z12.string(), agentId: z12.string().nullable(), name: z12.string() }),
|
|
2102
|
+
goalId: z12.string().uuid().nullable(),
|
|
2103
|
+
title: z12.string(),
|
|
2104
|
+
lines: z12.array(z12.object({ lineId: z12.string(), words: z12.string(), atMs: z12.number() }))
|
|
2063
2105
|
})).optional()
|
|
2064
2106
|
});
|
|
2065
2107
|
|
|
@@ -5,12 +5,12 @@ import {
|
|
|
5
5
|
serverInstructions,
|
|
6
6
|
sessionStartHook,
|
|
7
7
|
withSessionStartHook
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-NYSDESST.js";
|
|
9
9
|
import {
|
|
10
10
|
CODEX_ENV,
|
|
11
11
|
agentName,
|
|
12
12
|
withCodexEnv
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-CPDYOHSY.js";
|
|
14
14
|
|
|
15
15
|
// src/toolset.ts
|
|
16
16
|
var CONFIGURE_DESCRIPTION = "Set this agent up with Paigy \u2014 call it FIRST, before contact, and any time you're unsure who you are. One call does whatever the situation needs: NOT SET UP \u2192 if this machine holds a device credential (the user ran the Paigy desktop app or harness) it hatches an identity INSTANTLY, no code and no approval; otherwise it starts the code ceremony. ALREADY SET UP \u2192 returns your current identity and the two things left to decide, renaming it or logging out. 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 (pick your own; voices: rachel, george, jessica, brian, lily). Safe to call any time: idempotent, and it never writes settings.\n\nTHE CODE CEREMONY does not open a browser; the user enters the code in the Paigy app (or scans `qr`). A result with { user_code, device_code, qr, user_message } has already started polling for approval in the background: you MUST immediately print the `user_message` (the bare code) to the user, AND in that same turn call configure again with that `device_code` to collect the result. It returns the moment the user approves; on { status:'pending' } call again to keep waiting; on { status:'awaiting_confirmation' } (E2EE) show the bare `user_message` verify code and call again to finish. Every result's first text block states the code plainly.\n\nOn { status:'paired' }, or whenever it returns `enable_command`, ALWAYS follow the `enable_prompt`: PRINT that command for the user to run, so Paigy's tools stop prompting each time. 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.\n\nLOG OUT with { logOut: true }: it logs out THIS agent only \u2014 its token is revoked server-side and its local entry removed. Other agents and this device's credential are untouched, and a later configure re-hatches instantly while the device credential exists. Disconnecting the device itself is not an agent tool.";
|
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-UVVW32KH.js";
|
|
7
|
+
import "./chunk-NYSDESST.js";
|
|
8
|
+
import "./chunk-CPDYOHSY.js";
|
|
9
9
|
|
|
10
10
|
// src/enable.ts
|
|
11
11
|
function main() {
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
resolvePairing,
|
|
11
11
|
startPairing,
|
|
12
12
|
suggestedAgentName
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-AX55W57P.js";
|
|
14
14
|
import {
|
|
15
15
|
ConfigureSchema,
|
|
16
16
|
ENABLE_COMMAND,
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
SERVER_INSTRUCTIONS,
|
|
19
19
|
TOOLS,
|
|
20
20
|
paigyToolsAllowlisted
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-UVVW32KH.js";
|
|
22
22
|
import {
|
|
23
23
|
ReachTeller,
|
|
24
24
|
decideListen,
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
listenerKey,
|
|
30
30
|
wakeStatusPath,
|
|
31
31
|
withReach
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-NYSDESST.js";
|
|
33
33
|
import {
|
|
34
34
|
clearSurface,
|
|
35
35
|
writeSurface
|
|
@@ -50,7 +50,7 @@ import {
|
|
|
50
50
|
setClient,
|
|
51
51
|
slotName,
|
|
52
52
|
whoAmI
|
|
53
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-CPDYOHSY.js";
|
|
54
54
|
|
|
55
55
|
// src/index.ts
|
|
56
56
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -199,7 +199,7 @@ function pairStartResult(start, loggedOut) {
|
|
|
199
199
|
qr.make();
|
|
200
200
|
const link = start.verificationUri;
|
|
201
201
|
const ascii = qr.createASCII(1, 2);
|
|
202
|
-
const door = "in Paigy \u2192
|
|
202
|
+
const door = "in Paigy \u2192 You \u203A Computers \u2192 Connect a computer";
|
|
203
203
|
const userMessage = loggedOut ? `**Your machine was logged out.** Reconnect and every agent here pairs itself again \u2014 no more codes.
|
|
204
204
|
|
|
205
205
|
**[Reconnect this machine](${link})**
|
package/dist/listen.js
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
removeListenMark,
|
|
12
12
|
wakeStatusPath,
|
|
13
13
|
writeListenMark
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-NYSDESST.js";
|
|
15
15
|
import {
|
|
16
16
|
agentName,
|
|
17
17
|
getGoals,
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
receive,
|
|
21
21
|
slotName,
|
|
22
22
|
subscribeWake
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-CPDYOHSY.js";
|
|
24
24
|
|
|
25
25
|
// src/listen.ts
|
|
26
26
|
import { createHash } from "crypto";
|
|
@@ -174,8 +174,8 @@ function brief(waiting, reason, as, goalId) {
|
|
|
174
174
|
const said = newestSaid(lead) || ("about" in lead ? lead.about : "");
|
|
175
175
|
const shown = said.length > 160 ? `${said.slice(0, 160)}\u2026` : said;
|
|
176
176
|
const goal = waiting.goal?.goalId ?? lead.goalIds[0];
|
|
177
|
-
const act = ` \xB7 get_goals({goalIds:["${goal}"]}) to read it in full, then contact to answer; nothing is acknowledged until contact({ackEventIds})
|
|
178
|
-
return `Paigy \xB7 ${reason} \xB7 ${waiting.deliveries.length} waiting \xB7 lead ${lead.deliveryId} on Goal ${goal}: "${shown}"${mine}${fresh}${stalled}${act}`;
|
|
177
|
+
const act = goal ? ` \xB7 get_goals({goalIds:["${goal}"]}) to read it in full, then contact to answer; nothing is acknowledged until contact({ackEventIds})` : " \xB7 nothing is acknowledged until contact({ackEventIds})";
|
|
178
|
+
return `Paigy \xB7 ${reason} \xB7 ${waiting.deliveries.length} waiting \xB7 lead ${lead.deliveryId}${goal ? ` on Goal ${goal}` : ""}: "${shown}"${mine}${fresh}${stalled}${act}`;
|
|
179
179
|
}
|
|
180
180
|
function launchEnv(waiting, reason, goalId) {
|
|
181
181
|
const env = { PAIGY_WORK: JSON.stringify(waiting), PAIGY_EVENT: reason };
|
package/dist/onboard.js
CHANGED
|
@@ -3,14 +3,14 @@ import {
|
|
|
3
3
|
resolvePairing,
|
|
4
4
|
startPairing,
|
|
5
5
|
suggestedAgentName
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-AX55W57P.js";
|
|
7
7
|
import {
|
|
8
8
|
autoConfigureClients,
|
|
9
9
|
claudeInstallHint,
|
|
10
10
|
openBrowser,
|
|
11
11
|
removeOldGeminiHooks
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-UVVW32KH.js";
|
|
13
|
+
import "./chunk-NYSDESST.js";
|
|
14
14
|
import {
|
|
15
15
|
TOKEN_PATH,
|
|
16
16
|
agentName,
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
saveToken,
|
|
22
22
|
setIdentity,
|
|
23
23
|
whoAmI
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-CPDYOHSY.js";
|
|
25
25
|
|
|
26
26
|
// src/onboard.ts
|
|
27
27
|
function reportRegistered() {
|
package/dist/slot.js
CHANGED
package/dist/stalled.js
CHANGED
|
@@ -33,7 +33,7 @@ async function main() {
|
|
|
33
33
|
const dir = join(homedir(), ".paigy", "stalled-reminded");
|
|
34
34
|
const mark = join(dir, `${session || "session"}-${day}`);
|
|
35
35
|
if (existsSync(mark)) return;
|
|
36
|
-
const { receive } = await import("./dist-
|
|
36
|
+
const { receive } = await import("./dist-VYRT3PHE.js");
|
|
37
37
|
const reply = stopReply((await receive()).stalled ?? []);
|
|
38
38
|
if (!reply) return;
|
|
39
39
|
mkdirSync(dir, { recursive: true });
|
package/dist/statusline.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paigy/mcp",
|
|
3
|
-
"
|
|
3
|
+
"mcpName": "io.github.paigy-ai/mcp",
|
|
4
|
+
"version": "0.40.41",
|
|
4
5
|
"description": "Paigy MCP server — the AI agent harness that calls you. Lets an agent notify a user and await their reply.",
|
|
5
6
|
"license": "MIT",
|
|
6
7
|
"type": "module",
|