@paigy/mcp 0.40.38 → 0.40.40

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.
@@ -1,4 +1,4 @@
1
- // ../../../../../../private/tmp/paigy-draft-reaches/packages/sdk/dist/index.js
1
+ // ../../packages/sdk/dist/index.js
2
2
  import { createRequire as __sdkCreateRequire } from "module";
3
3
  import { execFileSync } from "child_process";
4
4
  import { createHash, randomUUID } from "crypto";
@@ -59,6 +59,24 @@ function parentOf(pid) {
59
59
  return void 0;
60
60
  }
61
61
  }
62
+ var CODEX_PARENT = /(^|\/)\.codex\/|CodexCLI\.app|(^|[\/\s])codex(\s|$)/;
63
+ var codexParent;
64
+ function underCodex() {
65
+ if (codexParent !== void 0) return codexParent;
66
+ codexParent = false;
67
+ if (process.platform === "win32") return codexParent;
68
+ for (const pid of ancestors()) {
69
+ try {
70
+ const command = execFileSync("ps", ["-o", "command=", "-p", String(pid)], { encoding: "utf8", timeout: 1e3 });
71
+ if (CODEX_PARENT.test(command)) {
72
+ codexParent = true;
73
+ break;
74
+ }
75
+ } catch {
76
+ }
77
+ }
78
+ return codexParent;
79
+ }
62
80
  var lineage;
63
81
  function ancestors() {
64
82
  if (lineage) return lineage;
@@ -116,7 +134,8 @@ function parseSessionRecord(text) {
116
134
  return void 0;
117
135
  }
118
136
  function sessionId() {
119
- return envSession("PAIGY_SESSION_ID") ?? claudeConversation() ?? envSession("CLAUDE_CODE_SESSION_ID") ?? envSession("CODEX_THREAD_ID") ?? envSession("CODEX_SESSION_ID") ?? WORKSPACE_ID;
137
+ return envSession("PAIGY_SESSION_ID") ?? claudeConversation() ?? envSession("CLAUDE_CODE_SESSION_ID") ?? envSession("CODEX_THREAD_ID") ?? envSession("CODEX_SESSION_ID") ?? // A Codex thread that was handed no id is its own agent, not the folder's (`underCodex`).
138
+ (underCodex() ? INSTANCE_ID : WORKSPACE_ID);
120
139
  }
121
140
  function isNetworkError(e) {
122
141
  return e instanceof Error && e.message.startsWith(NETWORK_MSG);
@@ -1498,16 +1517,16 @@ function parseWhen(said2, tz, nowMs, read22 = "earliest") {
1498
1517
  let hour = null;
1499
1518
  let minute = 0;
1500
1519
  const spoken = new RegExp(`\\bat\\s+(${Object.keys(SPOKEN_HOUR).join("|")})\\b`, "i").exec(text);
1501
- const clock3 = CLOCK.exec(text);
1520
+ const clock2 = CLOCK.exec(text);
1502
1521
  if (spoken) {
1503
1522
  hour = SPOKEN_HOUR[spoken[1].toLowerCase()];
1504
- } else if (clock3 && (clock3[3] || /\bat\s/i.test(clock3[0]))) {
1505
- hour = Number(clock3[1]);
1506
- minute = clock3[2] ? Number(clock3[2]) : 0;
1523
+ } else if (clock2 && (clock2[3] || /\bat\s/i.test(clock2[0]))) {
1524
+ hour = Number(clock2[1]);
1525
+ minute = clock2[2] ? Number(clock2[2]) : 0;
1507
1526
  if (hour > 23 || minute > 59) return null;
1508
1527
  }
1509
1528
  if (hour !== null) {
1510
- const mer = clock3?.[3]?.toLowerCase().replace(/\./g, "") ?? "";
1529
+ const mer = clock2?.[3]?.toLowerCase().replace(/\./g, "") ?? "";
1511
1530
  const pmWord = /\b(p\.?m\.?|afternoon|evening|tonight|at night)\b/i.test(text);
1512
1531
  const amWord = /\b(a\.?m\.?|morning)\b/i.test(text);
1513
1532
  if (mer.startsWith("p") || pmWord && !amWord) {
@@ -1551,7 +1570,7 @@ function parseDelay(said2, tz, nowMs, read22 = "earliest") {
1551
1570
  return Math.max(0, Math.round((Date.parse(at2) - nowMs) / 1e3));
1552
1571
  }
1553
1572
  var NIGHT = { from: 23, to: 7 };
1554
- var ASK_MAX = 250;
1573
+ var ASK_MAX = 80;
1555
1574
  var UNITS_MAX = 12;
1556
1575
  var UNIT_TITLE_MAX = 50;
1557
1576
  var UNIT_BODY_MAX = 200;
@@ -1616,15 +1635,15 @@ var CompletionSchema = z3.object({
1616
1635
  }).strict();
1617
1636
  var CompleteChangeSchema = CompletionSchema.extend({ kind: z3.literal("complete") });
1618
1637
  var ASKING_RULES = `HOW TO ASK:
1619
- 1. Write one question per object. Five questions are five objects in \`questions\`, in one contact, so each can be answered on its own; one question with five parts settles nothing until all five are answered.
1620
- 2. Name the Goal you are working on as the question's \`goalId\`: the question goes onto that Goal and its answer comes back there. It must exist: create it with manage_goals first.
1621
- 3. \`workItBlocks\` only for work you are truly blocked on (it asks for a call); leave it out for a question you can keep working around.
1622
- 4. Never hold the process open with while-loops. A wait that comes back \`expired\` is not a finished conversation: wait again with contact({wait:true}) only while you have nothing else to do. While a Call you placed is open, keep receiving window after window until it ends, even when a window is empty: the person may give follow-ups or instructions. With no open Call, STOP WAITING when a window comes back with nothing new \u2014 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 \`contact({wait:false})\` or \`get_goals\` on that wake.
1623
- 5. One question, 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. Take back one that no longer matters with \`withdrawQuestionIds\`.
1624
- 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.
1625
- 7. A question carries its options when you have them; a free-text question may omit them. Each option\u2019s label must stand on its own and name its choice in full -- never \`All three\` or \`Option 2\`. \`pickMode: "many"\` makes the card a checklist (options they may want several of); \`"one"\`, the default, a pick (one rules out the others); \`"rank"\` an ordering. Each question is sent exactly as written, with no reading in between. They can always answer in their own words, so never add an 'Other' option.
1626
- 8. A diagnosis says when, why and how it happens, then proposes one fix. Never options first.
1627
- 9. GIVE A REPORT ITS REPLY: an update takes \`reply\` too, one line the person can tap instead of typing, written in THEIR voice for THAT report ("Sounds good, I'll test later") \u2014 the same care you give a question's options. What they tap is what you read back, which tells you whether they verified your work or only received it. One line, because a report has one way to close, and it may not change what happens next: a reply that would is a question. Requested delivery and completed-Goal reports require a reply (reply_required); ordinary progress may omit it.`;
1638
+ 1. One question per object in \`questions\`, so each is answered on its own.
1639
+ 2. \`goalId\` names the existing Goal it is about (create one with manage_goals first); the answer comes back there.
1640
+ 3. \`workItBlocks\` only when you are truly blocked: it asks for a call.
1641
+ 4. No while-loops. While any Call is open, even one your question joined from their items, keep receiving through empty windows; otherwise stop at one: the answer reaches you on the Goal. Yield only with a listener or wakeup.
1642
+ 5. One question, one row: never re-send one still waiting; take back one that no longer matters with \`withdrawQuestionIds\`.
1643
+ 6. Read the Goal before asking; never re-ask what was answered or shipped. \`replied\` means they chose no option: it is still yours to settle.
1644
+ 7. Give options when you have them. Each label names its choice in full (never "Option 2"); never add "Other". \`pickMode\`: one (default), many, rank.
1645
+ 8. A diagnosis says when, why and how it happens, then proposes one fix.
1646
+ 9. Give a report its \`reply\`: one line in THEIR voice for THAT report, so you learn whether they verified it or only received it. Required when it reaches them or completes a Goal.`;
1628
1647
  function draft2020(node) {
1629
1648
  if (Array.isArray(node)) return node.map(draft2020);
1630
1649
  if (node && typeof node === "object") {
@@ -1667,7 +1686,7 @@ var userExplicitlyRequested = z4.enum(["any", "call"]).optional().describe(
1667
1686
  `Only what the person said about THIS message, in so many words: "any" when they asked you to send it to them ("send it to my phone", "message me the result"), "call" when they asked to be called about it. It is then delivered (a call rings for the whole contact, and carries everything waiting on them); omitted, an update is only recorded as the Goal's progress unless the person needs it. Never set it to make a message louder.`
1668
1687
  );
1669
1688
  var units = z4.array(UnitInputSchema).optional().describe(
1670
- `The context this message needs, as up to ${UNITS_MAX} units in reading order, each {title, body}: a title of at most ${UNIT_TITLE_MAX} characters and a body of at most ${UNIT_BODY_MAX}. One idea per unit. Leave it out when the main text says it all.`
1689
+ `The context this message needs, as up to ${UNITS_MAX} units in reading order, each {title, body}: a title of at most ${UNIT_TITLE_MAX} characters and a body of at most ${UNIT_BODY_MAX}. One idea per unit. Leave it out when the main text says it all. Over a cap is refused by name (ask_too_long, too_many_units, unit_title_too_long, unit_body_too_long) and nothing is sent.`
1671
1690
  );
1672
1691
  var UpdateInputSchema = z4.object({
1673
1692
  message: z4.string().trim().min(1).describe(`The one point, at most ${ASK_MAX} characters; the context goes in units.`),
@@ -1722,7 +1741,7 @@ var questionFields = {
1722
1741
  ),
1723
1742
  goalId: z4.string().uuid().describe("The Goal the question is about, which must exist (create it with manage_goals first). Its answer comes back there."),
1724
1743
  units,
1725
- options: z4.array(OptionInputSchema).min(1).max(6).optional().describe("The choices, when you have them. Each label stands on its own, at most 50 characters; a hint, at most 200."),
1744
+ options: z4.array(OptionInputSchema).min(1).max(6).optional().describe("The choices, when you have them. Each label stands on its own, at most 50 characters; a hint, at most 200. They can always answer in their own words, so no 'Other' or 'None of these'."),
1726
1745
  // HOW THE OPTIONS ARE ANSWERED, SAID BY THE AGENT (owner, 2026-10-02: "one and many makes sense";
1727
1746
  // brain_prompts.md §1: structured agent questions need no model). The app draws all three.
1728
1747
  pickMode: z4.enum(["one", "many", "rank"]).optional().describe(
@@ -1764,7 +1783,9 @@ var QuestionDependencySchema = z4.object({
1764
1783
  reason: reason.optional()
1765
1784
  }).strict().refine(actionFits, ACTION_FITS);
1766
1785
  var sendFields = {
1767
- completions: z4.array(CompletionSchema).min(1).max(20).optional().describe("Close existing Goals and deliver their completion reports atomically. Ordinary updates never close work."),
1786
+ completions: z4.array(CompletionSchema).min(1).max(20).optional().describe(
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
+ ),
1768
1789
  updates: z4.array(UpdateInputSchema).min(1).max(20).optional().describe(
1769
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 and nobody is notified."
1770
1791
  ),
@@ -1778,7 +1799,7 @@ var sendFields = {
1778
1799
  };
1779
1800
  var ContactSchema = z4.object({
1780
1801
  ...sendFields,
1781
- questions: z4.array(QuestionInputSchema).min(1).max(20).optional().describe("Questions for the person, one per object."),
1802
+ questions: z4.array(QuestionInputSchema).min(1).max(20).optional().describe("Questions for the person, one per object, each sent exactly as written, with no reading in between."),
1782
1803
  /** RECEIVING (2I, I2; brain_prompts.md §2.2): the events this agent handled. */
1783
1804
  ackEventIds: z4.array(z4.string().uuid()).min(1).max(100).optional().describe(
1784
1805
  "The exact eventIds of the events you have handled: an acknowledgment (ACK). Reading alone acknowledges nothing, so an event comes back until you acknowledge it; after that the next batch can come. Each recipient acknowledges separately, for itself only. A Question you owe is answered (answers), never acknowledged away."
@@ -1794,15 +1815,13 @@ var ContactWireSchema = z4.object({
1794
1815
  questions: z4.array(QuestionWireSchema).min(1).max(20).optional()
1795
1816
  }).strict().refine(sendsAnything, "a contact sends at least one update, question, answer, withdrawal or question dependency");
1796
1817
  var CONTACT_SCHEMA = { type: "object", ...mcpInputSchema(ContactSchema) };
1797
- var CONTACT_DESCRIPTION = "Send to and receive from the person: completions, updates, questions, answers to questions addressed to you, withdrawals of your own questions, and what a question holds up. Every Goal you name must already exist: create it with manage_goals first; an unknown Goal is refused and nothing is sent. Every item applies on its own: read `results`, where a failed item names why while the rest still apply.\n\n" + ASKING_RULES + `
1798
-
1799
- CUT A LONG MESSAGE BEFORE YOU SEND IT: a question, an update's message or an answer is the one point, in at most ${ASK_MAX} characters; everything else it needs goes in 'units', up to ${UNITS_MAX} {title, body} in reading order, one idea each, every title at most ${UNIT_TITLE_MAX} characters and every body at most ${UNIT_BODY_MAX}. The person sees the main text and the titles, and opens a unit to read its body. Over a cap is refused by name (ask_too_long, too_many_units, unit_title_too_long, unit_body_too_long) and nothing is sent.
1818
+ var CONTACT_DESCRIPTION = "Send to and receive from the person: completions, updates, questions, answers to questions addressed to you, withdrawals, and what a question holds up. Every Goal named must exist: an unknown one refuses the whole contact. Each item applies on its own: read `results`, where a failed one names why.\n\n" + ASKING_RULES + `
1800
1819
 
1801
- UPDATES ask nothing, so no answer is owed and none should be awaited. An update reaches the person only when they asked you for it (userExplicitlyRequested), when it answers something they said, or once its Goal is done; any other is recorded as the Goal's progress and nobody is notified. Ordinary updates never close a Goal. On a Goal whose report card is still open, an update that reaches them is added to that card, with no new push. If the person is already on a call, anything that reaches them joins that call, with no ring.
1820
+ LENGTH: the question, message or answer is the one point, at most ${ASK_MAX} characters; the rest goes in \`units\`, one idea each. Over a cap is refused by name and nothing is sent. Several results are several updates.
1802
1821
 
1803
- COMPLETIONS close and report in one operation: completions:[{goalId,message,units?,reply,options?}]. The same contract works in manage_goals changes with kind:complete. message is at most 50 characters; use units when useful for initial state, changes, current state (verification and limits), and next steps / leftover work with its owner. reply is one acknowledgement in the person's voice. Optional options:[{label,hint}] suggest next steps: a tap acknowledges the report and requests that step from its author. It never reopens the completed Goal; follow-up work needs a new Goal. Closure and the report commit together or neither does. Required children and dependencies must already be finished. No Reviewer rejudges your completion; say only what your evidence supports.
1822
+ UPDATES ask nothing. One reaches the person only when they asked for it, it answers something they said, or its Goal is done; else it is kept as progress. One that reaches them joins an open report card or a live call.
1804
1823
 
1805
- RECEIVING: a contact that sends nothing returns \`events\`, a limited batch of what is addressed to you (not a history page): \`question\`, a Question you owe (answer it in answers, with its questionId); \`update\`, something new on one of your Goals (a reply, an answer: read it with get_goals); \`instruction\`, a request or note sent to you. \`hasMore\` says more are waiting. Reading acknowledges nothing: once you have handled events, confirm their eventIds with contact({ackEventIds}), and the next batch can come. contact({}) waits up to about 45 seconds for something to arrive; contact({wait:false}) returns at once. It also lists work given to you that nobody has started (\`assigned\`; your first write to it starts it) and your work gone quiet (\`stalled\`).`;
1824
+ RECEIVING: contact({}) waits ~45 s; contact({wait:false}) returns \`events\` at once. Confirm the ones you handled with contact({ackEventIds}).`;
1806
1825
  var CreateGoalSchema = z5.object({
1807
1826
  outcome: z5.string().trim().min(1).max(1e4),
1808
1827
  /** The work's NAME (#2115) — one to five words, how a person refers to it out loud ("the night
@@ -2017,11 +2036,28 @@ var messageBase = {
2017
2036
  obligationIds: z6.array(id)
2018
2037
  };
2019
2038
  var BrainMessageSchema = z6.union([
2020
- z6.object({ ...messageBase, to: z6.object({ kind: z6.literal("user") }).strict() }).strict(),
2039
+ // A MESSAGE TO THE PERSON KEEPS ITS SENTENCES (turns.md): the talker writes them one by one, and each is
2040
+ // its own unit of speech (`<cycle>:<key>:<n>`). `text` is the same words joined, for every reader of a
2041
+ // message's words. Absent on results written before sentences.
2042
+ z6.object({
2043
+ ...messageBase,
2044
+ to: z6.object({ kind: z6.literal("user") }).strict(),
2045
+ sentences: z6.array(z6.string().min(1)).min(1).optional(),
2046
+ // THE REPORTS IT TELLS, BY THEIR OWN IDENTITY (call 9d1c096c, 2026-10-15): the talker's message names the report
2047
+ // Entries it speaks of, so the plan's line names that report rather than re-finding it by its Goal. Absent on
2048
+ // results written before it.
2049
+ tells: z6.array(z6.object({ id }).strict()).optional()
2050
+ }).strict(),
2021
2051
  z6.object({
2022
2052
  ...messageBase,
2023
2053
  to: z6.object({ kind: z6.literal("agent"), agentId: z6.string().regex(/^agent:(?!paigy$)\S+$/) }).strict(),
2024
- call: z6.object({ callId: id, listen: z6.literal(true) }).strict().optional()
2054
+ call: z6.object({ callId: id, listen: z6.literal(true) }).strict().optional(),
2055
+ // WHAT IT ASKS THE AGENT, IN UNDER TEN WORDS (owner, 2026-10-15: "Yes, add the summary"): the talker's own, stored
2056
+ // as the sent Entry's summary, which the recap's "Sent to <agent>: …" row shows. Absent on results written before it.
2057
+ summary: z6.string().optional(),
2058
+ // THE PERSON ASKED TO BE CALLED BACK ONCE THIS AGENT'S WORK IS DONE (turns.md, step 0): the agent owes
2059
+ // the call, and its next contact about it rings them (`public.callbacks`).
2060
+ callback: z6.literal(true).optional()
2025
2061
  }).strict()
2026
2062
  ]);
2027
2063
  var BrainSearchSchema = z6.object({
@@ -2045,92 +2081,97 @@ var BrainResultSchema = z6.object({
2045
2081
  next: BrainNextSchema,
2046
2082
  search: BrainSearchSchema.optional()
2047
2083
  }).strict();
2048
- var str = z6.string();
2084
+ var str2 = z6.string();
2049
2085
  var strs = z6.array(z6.string());
2050
2086
  var CompactResultSchema = z6.object({
2051
- next: z6.object({ say: strs, then: z6.enum(["listen", "hold", "end", "none"]), waitFor: strs, reason: str, instructions: strs }).strict(),
2052
- messages: z6.array(z6.object({ key: str, to: str, text: str, about: strs, entries: strs, owed: strs, inviteToCall: z6.boolean() }).strict()),
2053
- entries: z6.array(z6.object({ key: str, from: str, on: strs }).strict()),
2054
- answers: z6.array(z6.object({ question: str, entries: strs, summary: str, picked: strs }).strict()),
2087
+ next: z6.object({ say: strs, then: z6.enum(["listen", "hold", "end", "none"]), waitFor: strs, reason: str2, instructions: strs }).strict(),
2088
+ messages: z6.array(z6.object({ key: str2, to: str2, text: str2, about: strs, entries: strs, owed: strs, inviteToCall: z6.boolean() }).strict()),
2089
+ entries: z6.array(z6.object({ key: str2, from: str2, on: strs }).strict()),
2090
+ answers: z6.array(z6.object({ question: str2, entries: strs, summary: str2, picked: strs }).strict()),
2055
2091
  changes: z6.array(z6.object({
2056
- key: str,
2092
+ key: str2,
2057
2093
  what: z6.enum(["goal", "question", "lesson"]),
2058
2094
  op: z6.enum(["create", "edit", "assign", "open", "complete", "cancel", "defer", "move", "block", "unblock", "withdraw", "remember", "revise"]),
2059
- id: str,
2060
- text: str,
2061
- title: str,
2062
- who: str,
2063
- under: str,
2095
+ id: str2,
2096
+ text: str2,
2097
+ title: str2,
2098
+ who: str2,
2099
+ under: str2,
2064
2100
  gate: z6.enum(["start", "complete", "answer", "none"]),
2065
- options: z6.array(z6.object({ id: str, label: str }).strict()),
2101
+ options: z6.array(z6.object({ id: str2, label: str2 }).strict()),
2066
2102
  pick: z6.enum(["one", "many", "rank", "words"]),
2067
2103
  entries: strs
2068
2104
  }).strict()),
2069
2105
  feedback: z6.array(strs),
2070
- search: z6.object({ query: str, within: strs, goal: str }).strict()
2106
+ search: z6.object({ query: str2, within: strs, goal: str2 }).strict()
2071
2107
  }).strict();
2072
2108
  var COMPACT_RESULT_JSON_SCHEMA = (({ $schema: _, ...rest }) => rest)(
2073
2109
  zodToJsonSchema(CompactResultSchema, { $refStrategy: "none" })
2074
2110
  );
2075
- var str2 = z7.string();
2111
+ var str3 = z7.string();
2076
2112
  var strs2 = z7.array(z7.string());
2077
2113
  var TalkerReplySchema = z7.object({
2078
2114
  /** What to say and send, messages to the person first: spoken in the order written. `to` is "user"
2079
- * or an agent's handle; `about` names handles; `blocks` is the item a question to an agent must be
2080
- * answered before ("" for none). */
2081
- messages: z7.array(z7.object({ key: str2, to: str2, text: str2, about: strs2, blocks: str2 }).strict()),
2115
+ * or an agent's handle; `sentences` is what a message to the person says, one short sentence each
2116
+ * ([] to an agent); `text` is what a message to an agent says ("" to the person); `summary` is what it
2117
+ * asks the agent, in under ten words, as the person would put it ("" to the person; owner, 2026-10-15:
2118
+ * "Yes, add the summary"), which the recap's "Sent to <agent>: …" row shows; `about` names
2119
+ * handles; `blocks` is the item a question to an agent must be answered before ("" for none);
2120
+ * `callback` is true on a message to the agent doing work the person asked to be called back about
2121
+ * once it is done (false otherwise): that agent then owes the call (turns.md, step 0). */
2122
+ messages: z7.array(z7.object({ key: str3, to: str3, sentences: strs2, text: str3, summary: str3, about: strs2, blocks: str3, callback: z7.boolean() }).strict()),
2082
2123
  /** What the call does next: listen, hold (the person asked for a moment) or end (they asked to). */
2083
2124
  then: z7.enum(["listen", "hold", "end"]),
2084
2125
  /** The person's replies to items (replies, owner 2026-10-07): the item's handle, the chosen option
2085
2126
  * IDs, the line handles, how they replied in under ten words (keeping any condition), and `defer`:
2086
2127
  * "" when their words settle the item, else what a reply that puts it off waits for -- "call" (the
2087
2128
  * end of this call), a question's handle (that question's answer) or an ISO time. */
2088
- replies: z7.array(z7.object({ item: str2, options: strs2, lines: strs2, summary: str2, defer: str2 }).strict()),
2129
+ replies: z7.array(z7.object({ item: str3, options: strs2, lines: strs2, summary: str3, defer: str3 }).strict()),
2089
2130
  /** The line handles that tell the talker how to run this call; they last until it ends and reach no agent. */
2090
2131
  instruction: strs2,
2091
2132
  /** The line handles the filer acts on, and the only ones it reads (3e): new work, a change to existing
2092
2133
  * work, feedback on Paigy, anything said to an agent, and any rule meant to outlast the call. */
2093
2134
  file: strs2,
2094
2135
  /** Evidence to fetch for a second round: a search, an item's full text, or an agent by name. */
2095
- need: z7.object({ kind: z7.enum(["search", "item", "agent", ""]), text: str2 }).strict(),
2136
+ need: z7.object({ kind: z7.enum(["search", "item", "agent", ""]), text: str3 }).strict(),
2096
2137
  /** The handle of the item to explain ("" for none). */
2097
- explain: str2
2138
+ explain: str3
2098
2139
  }).strict();
2099
2140
  var TALKER_REPLY_JSON_SCHEMA = (({ $schema: _, ...rest }) => rest)(
2100
2141
  zodToJsonSchema(TalkerReplySchema, { $refStrategy: "none" })
2101
2142
  );
2102
- var str3 = z8.string();
2143
+ var str4 = z8.string();
2103
2144
  var strs3 = z8.array(z8.string());
2104
2145
  var FilerReplySchema = z8.object({
2105
2146
  /** Which Goals each new line goes on: a line's handle, Goal handles (or keys of new Goals), and what
2106
2147
  * the line says in at most ten words. */
2107
- filed: z8.array(z8.object({ line: str3, goals: strs3, summary: str3 }).strict()),
2148
+ filed: z8.array(z8.object({ line: str4, goals: strs3, summary: str4 }).strict()),
2108
2149
  goals: z8.array(z8.object({
2109
2150
  op: z8.enum(["create", "edit", "complete", "cancel", "reopen", "assign", "defer", "move", "block", "unblock"]),
2110
- key: str3,
2111
- goal: str3,
2112
- title: str3,
2113
- outcome: str3,
2114
- owner: str3,
2115
- under: str3,
2116
- until: str3,
2117
- on: str3,
2151
+ key: str4,
2152
+ goal: str4,
2153
+ title: str4,
2154
+ outcome: str4,
2155
+ owner: str4,
2156
+ under: str4,
2157
+ until: str4,
2158
+ on: str4,
2118
2159
  gate: z8.enum(["start", "complete", "answer", ""]),
2119
- why: str3
2160
+ why: str4
2120
2161
  }).strict()),
2121
2162
  questions: z8.array(z8.object({
2122
2163
  op: z8.enum(["create", "edit", "assign", "withdraw"]),
2123
- key: str3,
2124
- question: str3,
2125
- text: str3,
2126
- summary: str3,
2127
- to: str3,
2128
- goal: str3,
2129
- options: z8.array(z8.object({ id: str3, label: str3 }).strict()),
2164
+ key: str4,
2165
+ question: str4,
2166
+ text: str4,
2167
+ summary: str4,
2168
+ to: str4,
2169
+ goal: str4,
2170
+ options: z8.array(z8.object({ id: str4, label: str4 }).strict()),
2130
2171
  pick: z8.enum(["one", "many", "rank", "words", ""]),
2131
- blocks: str3
2172
+ blocks: str4
2132
2173
  }).strict()),
2133
- lessons: z8.array(z8.object({ op: z8.enum(["remember", "revise", "withdraw"]), lesson: str3, text: str3, scope: str3 }).strict()),
2174
+ lessons: z8.array(z8.object({ op: z8.enum(["remember", "revise", "withdraw"]), lesson: str4, text: str4, scope: str4 }).strict()),
2134
2175
  /** Line handles whose words comment on Paigy itself. */
2135
2176
  feedback: strs3
2136
2177
  }).strict();
@@ -2191,6 +2232,27 @@ var TidyReplySchema = z10.object({
2191
2232
  var TIDY_REPLY_JSON_SCHEMA = (({ $schema: _, ...rest }) => rest)(
2192
2233
  zodToJsonSchema(TidyReplySchema, { $refStrategy: "none" })
2193
2234
  );
2235
+ var HandoutReplySchema = z11.object({
2236
+ assign: z11.array(z11.object({
2237
+ /** The Goal's handle (G). */
2238
+ goal: z11.string(),
2239
+ /** The agent's handle (A). */
2240
+ to: z11.string(),
2241
+ /** At most ten words, naming the Goal of theirs it is most like: the reason the hand-out records. */
2242
+ why: z11.string()
2243
+ }).strict()),
2244
+ /** The Goals no listed agent's work is even loosely like: Paigy starts a session for them (owner, 2026-10-24,
2245
+ * Goal 37603006, "One per family of related Goals"). */
2246
+ new: z11.array(z11.object({
2247
+ /** The Goal's handle (G). */
2248
+ goal: z11.string(),
2249
+ /** At most ten words: why nothing active fits it. */
2250
+ why: z11.string()
2251
+ }).strict())
2252
+ }).strict();
2253
+ var HANDOUT_REPLY_JSON_SCHEMA = (({ $schema: _, ...rest }) => rest)(
2254
+ zodToJsonSchema(HandoutReplySchema, { $refStrategy: "none" })
2255
+ );
2194
2256
  function entryWords(entry) {
2195
2257
  const content = entry.content;
2196
2258
  if (content && "sealed" in content) return "";
@@ -2226,42 +2288,6 @@ var LIVE_MS = 3 * 6e4;
2226
2288
  var WORKING_MS = 60 * 6e4;
2227
2289
  var WORKING_TIER_MS = 2 * 60 * 6e4;
2228
2290
  var RECENT_TIER_MS = 24 * 60 * 6e4;
2229
- var json = z11.lazy(() => z11.union([
2230
- z11.string(),
2231
- z11.number().finite(),
2232
- z11.boolean(),
2233
- z11.null(),
2234
- z11.array(json),
2235
- z11.record(json)
2236
- ]));
2237
- var clock = z11.number().int().nonnegative().safe();
2238
- var HeardEventSchema = z11.object({
2239
- eventId: z11.string().uuid(),
2240
- source: z11.enum(["phone", "bot"]),
2241
- sequence: clock,
2242
- kind: z11.string().min(1),
2243
- phoneAtMs: clock.optional(),
2244
- botAtMs: clock.optional(),
2245
- payload: z11.record(json)
2246
- }).strict();
2247
- var HeardCursorSchema = HeardEventSchema.pick({ source: true, sequence: true, eventId: true });
2248
- var HeardPageSchema = z11.object({
2249
- events: z11.array(HeardEventSchema).max(200),
2250
- next: HeardCursorSchema.nullable()
2251
- }).strict();
2252
- var MAX_EVENTS = 50;
2253
- var MAX_BYTES = 8e4;
2254
- var batchBytes = (events) => {
2255
- let bytes = 0;
2256
- for (const char of JSON.stringify({ events })) {
2257
- const point = char.codePointAt(0);
2258
- bytes += point < 128 ? 1 : point < 2048 ? 2 : point < 65536 ? 3 : 4;
2259
- }
2260
- return bytes;
2261
- };
2262
- var HeardBatchSchema = z11.object({
2263
- events: z11.array(HeardEventSchema).min(1).max(MAX_EVENTS)
2264
- }).strict().refine((value) => batchBytes(value.events) <= MAX_BYTES, "heard_batch_too_large");
2265
2291
  var ContextSchema = z12.object({
2266
2292
  title: z12.string().min(1).describe("One-line headline of what you need (required, non-empty)."),
2267
2293
  description: z12.array(z12.string().min(1)).describe(
@@ -2593,6 +2619,10 @@ var AgendaTurnSchema = z12.object({
2593
2619
  /** The spoken sentences of the turn, in order. No count: how long a turn is is the brain's call
2594
2620
  * (owner, 2026-09-25), and a count here refused whole plans. */
2595
2621
  info: z12.array(z12.string().min(1)).default([]),
2622
+ /** THE ID OF EACH SENTENCE, when the plan names them (turns.md): a talker message's sentences are its
2623
+ * `info`, one piece each, and `units[i]` is the id the bot's line receipt carries for `info[i]`
2624
+ * (`<cycle>:<key>:<n>`), so what was heard is known per sentence. Absent on every other turn. */
2625
+ units: z12.array(z12.string().min(1)).optional(),
2596
2626
  question: z12.string().min(1).nullable(),
2597
2627
  /** True on the one turn carrying the agent's own declared question. */
2598
2628
  asks: z12.boolean().optional(),
@@ -2617,6 +2647,21 @@ var AgendaTurnSchema = z12.object({
2617
2647
  * the phone (`asking`, so the agenda goes gold and its options show) without treating the line as a
2618
2648
  * question turn — the talker owns re-asking and the waits, so `question` stays null. */
2619
2649
  onTable: z12.boolean().optional(),
2650
+ /** THE CARRIED ITEM THIS LINE TELLS (Goal 2a1e50eb, owner 2026-10-14: "Build the whole design") — a
2651
+ * request the Call carries that asks NOTHING: a report, a progress note, another agent's waiting news.
2652
+ * Its request Entry id, so the phone can make that agenda row the current one while it is read
2653
+ * (`telling` on the `turn` topic, `docs/clients/app/walk/design.md` §11).
2654
+ *
2655
+ * A FIELD OF ITS OWN, NEVER `claimId`: the claim is the RETURN identity — answers route by it and the
2656
+ * record tags the line with it (`workId`) — and an answer must never route to an Entry that asks
2657
+ * nothing. Absent on a turn speaking for a question (`claimId` says that) and on one speaking for no
2658
+ * carried item at all (an opener, a sign-off, Paigy's own line). */
2659
+ telling: z12.string().optional(),
2660
+ /** PAIGY'S OWN LINE (owner, 2026-10-15; calls ed2cbdce, ad50ad25): a turn that speaks for no item -- an
2661
+ * opener, a sign-off, a reply about nothing an agent asked or told -- is recorded as Paigy's, not as the
2662
+ * agent that rang. Absent on every turn that speaks for an item (`agentId` names whose), and on plans
2663
+ * from before it: a bot that does not know it records the ringing agent, as before. */
2664
+ speaksFor: z12.literal("paigy").optional(),
2620
2665
  select: SelectShapeSchema.optional(),
2621
2666
  options: z12.array(OptionSchema.omit({ id: true })).optional(),
2622
2667
  /* `pace` STOOD HERE (#826). A turn could carry seconds and the model chose them. The walk
@@ -2705,7 +2750,7 @@ var InboxItemSchema = z12.object({
2705
2750
  questions: z12.array(CallQuestionSchema).optional(),
2706
2751
  /** The same call carrying order, including request Entries with no DecisionNeed as reports.
2707
2752
  * Additive: questions stays decision-only for every other surface and older bundles. */
2708
- callItems: z12.array(CallQuestionSchema.extend({ state: z12.enum(["open", "answered", "report"]) })).optional(),
2753
+ callItems: z12.array(CallQuestionSchema.extend({ state: z12.enum(["open", "answered", "report"]), acknowledged: z12.boolean().optional() })).optional(),
2709
2754
  visuals: z12.array(VisualSchema).optional(),
2710
2755
  /** The connected agent's name (the single pairing name — user-typed, or the
2711
2756
  * agent's suggestion, or a default silly name). */
@@ -2770,6 +2815,21 @@ var InboxItemSchema = z12.object({
2770
2815
  * urgency (see the main README's "premier use case" + docs/delivery/notify/states.md). Drives the
2771
2816
  * inbox's blocking badge and the extra confirm step before dismissing it. */
2772
2817
  blocking: z12.boolean().default(false),
2818
+ /** WHAT FREED THIS QUESTION (owner, 2026-10-16, Goal 2383ef14: "we don't really show the question
2819
+ * at the top until the question it could reply to with is resolved. And then we show it again
2820
+ * with the context of the other thing that was resolved"; asked how it should carry that, "The
2821
+ * answer above it"). A question they answered with a question of their own waits for theirs
2822
+ * (`private.ask_back`) and drops out of the front while it waits; when it comes back, the card
2823
+ * draws their question and the answer it got ABOVE the ask, as one card. Absent on a question
2824
+ * nothing ever held back. */
2825
+ freedBy: z12.object({
2826
+ questionId: z12.string(),
2827
+ asked: z12.string(),
2828
+ answer: z12.string(),
2829
+ answeredAt: z12.string(),
2830
+ /** The answer in ten words, when the talker wrote one beside it. */
2831
+ summary: z12.string().optional()
2832
+ }).optional(),
2773
2833
  /** The user's locked-in answer; present only for replied items (GET /api/replied/:id). */
2774
2834
  answer: UserAnswerSchema.optional(),
2775
2835
  /** THE TARGET FACTS A CARD RENDERS (#1796 point 5, 2026-09-11): the Delivery it is a view of,
@@ -2829,8 +2889,8 @@ var MissedCallSchema = z12.enum([
2829
2889
  "inbox",
2830
2890
  "dismiss"
2831
2891
  ]);
2832
- var clock2 = (h) => h === 0 ? "midnight" : h === 12 ? "noon" : h < 12 ? `${h} am` : `${h - 12} pm`;
2833
- var QUIET = ` Nothing rings from ${clock2(NIGHT.from)} to ${clock2(NIGHT.to)} your time; the count waits for morning.`;
2892
+ var clock = (h) => h === 0 ? "midnight" : h === 12 ? "noon" : h < 12 ? `${h} am` : `${h - 12} pm`;
2893
+ var QUIET = ` Nothing rings from ${clock(NIGHT.from)} to ${clock(NIGHT.to)} your time; the count waits for morning.`;
2834
2894
  var BrokerTuningSchema = z12.object({
2835
2895
  /** 'none' = skip the spoken ack after a mapped answer (power users find it slow). */
2836
2896
  ackVerbosity: z12.enum(["normal", "none"]).optional(),
@@ -3167,6 +3227,13 @@ var QueueItemSchema = z12.object({
3167
3227
  * can see (`replies`, `questions[].answeredAt`) miss a spontaneous note entirely — a `request`
3168
3228
  * Entry with no `about_id` is in neither. */
3169
3229
  lastPersonAt: z12.string().nullable().optional(),
3230
+ /** EACH SIDE'S NEWEST WORD IN THE LAST DAY (owner, 2026-10-13, the Work tab's order): the person's
3231
+ * (`yours`) and the agents' (`theirs`), each null when that side wrote nothing on it in 24 hours.
3232
+ * `latest` holds one Entry, so whichever side wrote first is hidden there; Work orders a Goal by
3233
+ * these two and draws the side it was placed by under its title. Optional, so hand-built queues
3234
+ * and a door older than 20261013045542 need not spell them. */
3235
+ yours: GoalLatestSchema.nullable().optional(),
3236
+ theirs: GoalLatestSchema.nullable().optional(),
3170
3237
  /** WHAT THIS ROW IS, IN TWELVE CHARACTERS (#2928) — the hash of every other field on it, stamped
3171
3238
  * by the one projection that builds the row (`apps/api/src/goal/queue.ts`). It is how the
3172
3239
  * incremental read knows a row has not moved: the phone echoes back the revs it holds
@@ -3440,10 +3507,20 @@ var CallRecapSchema = z12.object({
3440
3507
  title: z12.string(),
3441
3508
  owner: z12.string(),
3442
3509
  state: z12.string(),
3510
+ /** Presented Entry content and its author, separately from the current Goal owner. */
3511
+ items: z12.array(z12.object({ entryId: z12.string(), author: z12.string(), text: z12.string(), summary: z12.string().nullable(), acknowledged: z12.boolean().optional() })).optional(),
3443
3512
  /** Whether the call put it to the person. An item it carried and never said has no row on the
3444
3513
  * review (owner, 2026-10-08: "why do we get the third one when it didn't happen in the call?"). */
3445
3514
  presented: z12.boolean(),
3446
- questions: z12.array(z12.object({ id: z12.string().uuid(), state: z12.string(), title: z12.string() })),
3515
+ /** Whether THIS call created it — the third way a call touches work, beside carrying a request
3516
+ * there and filing words there (owner, 2026-10-08, Goal `5b4b1a0a`: "Show the new work, keep my
3517
+ * words under it"). Created work is never carried, so it is never `presented`; without this the
3518
+ * row is dropped by the "only what happened on the call" filter. False on a database before
3519
+ * 20261013080133. */
3520
+ created: z12.boolean(),
3521
+ /** `request` is the Entry that asked it — what a line's `about` names when the line answered or put
3522
+ * it off. Optional: an older API sent none. */
3523
+ questions: z12.array(z12.object({ id: z12.string().uuid(), state: z12.string(), title: z12.string(), request: z12.string().optional() })),
3447
3524
  /** `words` is always what they SAID, verbatim — the record, never replaced. `summary` is what
3448
3525
  * the line says in ten words (owner, 2026-10-07): the filer's, or the talker's for the answer it
3449
3526
  * gave, so the row scans like a chosen option and their own words stay under it. Absent when
@@ -3479,7 +3556,44 @@ var CallRecapSchema = z12.object({
3479
3556
  })),
3480
3557
  more: z12.object({ lines: z12.number(), entries: z12.number(), topics: z12.number() }),
3481
3558
  /** Last stored position on this page when another exists; absent before paging shipped. */
3482
- next: z12.number().int().nonnegative().nullable().optional()
3559
+ next: z12.number().int().nonnegative().nullable().optional(),
3560
+ /** THE CALL AS ONE LIST OF ROWS (owner, 2026-10-14: "we only really want a thing like transcript but
3561
+ * built from the summaries", then "the transcript tabs should show the same but with full words").
3562
+ * Both tabs draw these rows, in this order: Summary from `summary`, Transcript from `words`.
3563
+ * - `put`: an item put to the person, at the first agent line that voiced it. Paigy's sentences
3564
+ * that voiced it are folded into `spoken`, never rows of their own.
3565
+ * - `said`: the person's words, one row per reply or per filed line no reply covers.
3566
+ * - `did`: what Paigy did ("Sent to Mouth: …", "Recorded: …", "Filed on …").
3567
+ * `by` is the row's real author, never inferred from `kind`: a relay Paigy sent to an agent is
3568
+ * Paigy's, not the person's. Optional and additive (owner: "make sure whatever you do is backward
3569
+ * compatible"): an API before it sends none, and the screen falls back to `topics` and `said`. */
3570
+ timeline: z12.array(z12.object({
3571
+ id: z12.string(),
3572
+ position: z12.number(),
3573
+ atMs: z12.number(),
3574
+ kind: z12.enum(["put", "said", "did"]),
3575
+ by: z12.object({ participant: z12.string().nullable(), agentId: z12.string().nullable(), name: z12.string().nullable() }),
3576
+ goalId: z12.string().uuid().nullable(),
3577
+ requestId: z12.string().nullable(),
3578
+ summary: z12.string().nullable(),
3579
+ words: z12.string(),
3580
+ /** Paigy's sentences folded into this row: on a `put` row, what it said putting the item to the
3581
+ * person (before their next row); on a `said` row, what it said in reply (until their next row).
3582
+ * `atMs` is when each was said; optional, absent before 2026-10-14's fix. */
3583
+ spoken: z12.array(z12.object({ lineId: z12.string(), words: z12.string(), atMs: z12.number().optional() })),
3584
+ /** On a `said` row: the work these words were filed on, and whether they answered (recorded) a
3585
+ * question. They replace the "Filed on ..." and "Recorded: ..." rows that repeated the person's own
3586
+ * summary (Brain, 2026-10-14). Optional: absent from an API before it. */
3587
+ filedOn: z12.array(z12.object({ goalId: z12.string().uuid(), title: z12.string() })).optional(),
3588
+ recorded: z12.boolean().optional(),
3589
+ settled: z12.object({ requestId: z12.string(), answer: z12.string() }).nullable().optional(),
3590
+ acknowledged: z12.boolean().optional(),
3591
+ /** On a `put` row: still waiting for the person's answer (not settled, not answered, not put off).
3592
+ * The server's judgement; the screen draws "Still waiting for your answer" from it. Optional: absent
3593
+ * from an API before it, where the screen falls back to its own reading. */
3594
+ waiting: z12.boolean().optional(),
3595
+ lineIds: z12.array(z12.string())
3596
+ })).optional()
3483
3597
  });
3484
3598
  function sessionSlot(sessionId2) {
3485
3599
  const id2 = sessionId2 ?? sessionId();
@@ -3586,6 +3700,14 @@ async function requestCode(suggestedName = agentName(), device) {
3586
3700
  if (!res.ok) throw new Error(`/api/device/code failed: ${res.status} ${await res.text()}`);
3587
3701
  return await res.json();
3588
3702
  }
3703
+ var ServerFault = class extends Error {
3704
+ constructor(status) {
3705
+ super(`Paigy's server failed (HTTP ${status}) while checking the code.`);
3706
+ this.status = status;
3707
+ this.name = "ServerFault";
3708
+ }
3709
+ status;
3710
+ };
3589
3711
  async function pollToken(deviceCode) {
3590
3712
  const res = await reach(`${BACKEND_URL}/api/device/token`, {
3591
3713
  method: "POST",
@@ -3593,6 +3715,7 @@ async function pollToken(deviceCode) {
3593
3715
  body: JSON.stringify({ device_code: deviceCode })
3594
3716
  });
3595
3717
  if (res.ok) return await res.json();
3718
+ if (res.status >= 500) throw new ServerFault(res.status);
3596
3719
  const body = await res.json().catch(() => ({ error: "unknown" }));
3597
3720
  const err = body.error ?? "unknown";
3598
3721
  if (err === "authorization_pending") return null;
@@ -3954,6 +4077,9 @@ async function receiveContact(input, opts = {}) {
3954
4077
  throw error;
3955
4078
  }
3956
4079
  }
4080
+ function viaLine(via) {
4081
+ return via ? `a card they shared by link${via.decidedBy ? `, decided by ${via.decidedBy}` : ""}` : void 0;
4082
+ }
3957
4083
  function compact(o) {
3958
4084
  return Object.fromEntries(Object.entries(o).filter(([, v]) => v !== void 0 && v !== null && v !== "" && !(Array.isArray(v) && v.length === 0)));
3959
4085
  }
@@ -3977,7 +4103,8 @@ function decided(result) {
3977
4103
  return void 0;
3978
4104
  }
3979
4105
  }
3980
- function stateOf(state, answer, decided2) {
4106
+ function stateOf(state, answer, decided2, withdrawn) {
4107
+ if (withdrawn && state === "answered") return "closed";
3981
4108
  return state === "answered" && answer && decided2 === void 0 ? "replied" : state;
3982
4109
  }
3983
4110
  var handle = (entryId) => entryId.slice(0, 8);
@@ -4006,10 +4133,11 @@ function conversation(e) {
4006
4133
  at: at(entry.createdAt),
4007
4134
  said: sealed ? "[encrypted]" : entryWords(entry).trim(),
4008
4135
  caveat: entry.callOngoing ? "Call ongoing; what the person decides may change." : void 0,
4136
+ via: viaLine(entry.via),
4009
4137
  units: askUnits(entry, e.entries ?? []).map((u) => `${u.title}: ${u.body}`),
4010
4138
  re: re ? handle(re) : void 0,
4011
4139
  options,
4012
- decision: need ? compact({ state: stateOf(need.state, answer, decision), answer: decision }) : void 0
4140
+ decision: need ? compact({ state: stateOf(need.state, answer, decision, need.withdrawn), answer: decision, via: viaLine(answer?.via) }) : void 0
4013
4141
  });
4014
4142
  });
4015
4143
  }
@@ -4177,7 +4305,7 @@ function receivedView(r, now = Date.now()) {
4177
4305
  ...rings.map((r2) => rerings(r2, now)),
4178
4306
  ...assigned.length ? [`${assigned.length} of your Goals are assigned to you and not started (assigned): read one with get_goals({goalIds:[goalId]}); your first write to it starts it.`] : [],
4179
4307
  ...w.claimable && !assigned.length ? [`Next waiting on you: ${w.claimable.title ?? w.claimable.goalId} (get_goals({ goalIds: ["${w.claimable.goalId}"] })).`] : [],
4180
- ...stalled.length ? [`${stalled.length} of your Goals have had no progress${stalled.length === 1 ? " " : ""}${quietFor(stalled, now)}: report on each with a contact update, or finish or cancel it with manage_goals.`] : [],
4308
+ ...stalled.length ? [`${stalled.length} of your Goals have had no progress${stalled.length === 1 ? " " : ""}${quietFor(stalled, now)}: report on each with a contact update, or finish, cancel or defer it with manage_goals.`] : [],
4181
4309
  // The COUNT, oldest three, and where to read them (owner, 2026-10-08): it was 34 rows of
4182
4310
  // other agents' work on every window, ahead of this agent's own next step.
4183
4311
  ...others ? [`${others.count} of other agents' Goals have gone quiet${others.count === 1 ? " " : ""}${quietFor([{ since: others.oldestSince }], now, others.count)}: The oldest three are in others.goals: get_goals({goalIds:[goalId]}) reads one in full. A write to it puts you on it without changing its owner.`] : [],
@@ -4522,6 +4650,7 @@ export {
4522
4650
  deleteToken,
4523
4651
  revokeToken,
4524
4652
  requestCode,
4653
+ ServerFault,
4525
4654
  pollToken,
4526
4655
  UnpairedError,
4527
4656
  RevokedError,