@prismshadow/penguin-server 0.2.7 → 0.2.9

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.
Files changed (58) hide show
  1. package/README.md +4 -4
  2. package/dist/api/types.d.ts +528 -39
  3. package/dist/auth-token.d.ts +29 -0
  4. package/dist/auth-token.js +51 -0
  5. package/dist/auth-token.js.map +1 -0
  6. package/dist/chunk-K4ZSUT72.js +34 -0
  7. package/dist/chunk-K4ZSUT72.js.map +1 -0
  8. package/dist/chunk-OTYHSDV7.js +374 -0
  9. package/dist/chunk-OTYHSDV7.js.map +1 -0
  10. package/dist/{chunk-WKJ3ANJP.js → chunk-WL5FUO3A.js} +92 -381
  11. package/dist/chunk-WL5FUO3A.js.map +1 -0
  12. package/dist/extension/index.d.ts +212 -0
  13. package/dist/extension/index.js +1 -0
  14. package/dist/extension/index.js.map +1 -0
  15. package/dist/index.js +7337 -1774
  16. package/dist/index.js.map +1 -1
  17. package/dist/initial-password.d.ts +9 -12
  18. package/dist/initial-password.js +3 -7
  19. package/dist/install.ps1 +729 -0
  20. package/dist/install.sh +785 -0
  21. package/dist/reset-admin-password.d.ts +4 -7
  22. package/dist/reset-admin-password.js +11 -9
  23. package/dist/reset-admin-password.js.map +1 -1
  24. package/dist/secret-file.d.ts +3 -0
  25. package/dist/secret-file.js +17 -0
  26. package/dist/secret-file.js.map +1 -0
  27. package/package.json +19 -3
  28. package/web-dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  29. package/web-dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  30. package/web-dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  31. package/web-dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  32. package/web-dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  33. package/web-dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  34. package/web-dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  35. package/web-dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  36. package/web-dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  37. package/web-dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  38. package/web-dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  39. package/web-dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  40. package/web-dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  41. package/web-dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  42. package/web-dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  43. package/web-dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  44. package/web-dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  45. package/web-dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  46. package/web-dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  47. package/web-dist/assets/{addon-fit-BXTX0Xqu.js → addon-fit-BjXzaLkS.js} +1 -1
  48. package/web-dist/assets/{addon-web-links-KebkunbU.js → addon-web-links-D4HvCIde.js} +1 -1
  49. package/web-dist/assets/{highlighter-B3HctNDB.js → highlighter-Di8euoN5.js} +1 -1
  50. package/web-dist/assets/index-C6i84Esu.js +451 -0
  51. package/web-dist/assets/index-DW00p4Ny.css +1 -0
  52. package/web-dist/assets/{xterm-fEUfDV0F.js → xterm-XhYBaOEK.js} +1 -1
  53. package/web-dist/index.html +2 -2
  54. package/dist/chunk-UUJCF46V.js +0 -50
  55. package/dist/chunk-UUJCF46V.js.map +0 -1
  56. package/dist/chunk-WKJ3ANJP.js.map +0 -1
  57. package/web-dist/assets/index-BbLm3DrY.css +0 -1
  58. package/web-dist/assets/index-DwgTjTHO.js +0 -189
@@ -47,6 +47,19 @@ interface AuthLoginRequest {
47
47
  interface AuthResponse {
48
48
  user: UserInfo;
49
49
  }
50
+ /**
51
+ * GET /api/install — the identity of the data root this server is serving (install-id.ts),
52
+ * read by the web app before it mounts so state persisted against a DIFFERENT root can be
53
+ * swept. Public, like the login route it sits next to.
54
+ */
55
+ interface InstallResponse {
56
+ /**
57
+ * Opaque per-data-root id, or null when the server could not establish one (an
58
+ * unreadable or unwritable root). Null means "unknown", and a client must change
59
+ * nothing on it — never treat it as a new install.
60
+ */
61
+ installId: string | null;
62
+ }
50
63
  interface MeResponse {
51
64
  user: UserInfo;
52
65
  /**
@@ -62,18 +75,19 @@ interface MeResponse {
62
75
  /**
63
76
  * Whether this server runs in desktop mode (spawned by the desktop shell with
64
77
  * PENGUIN_DESKTOP_TOKEN). The web app then hides the logout entry, the
65
- * initial-password banner and the self-update entry, and omits the old-password
66
- * field when changing the password.
78
+ * initial-password banner and the self-update entry.
67
79
  */
68
80
  desktopMode: boolean;
69
81
  /**
70
- * How THIS session was established. Distinct from desktopMode: a browser signed into a
71
- * desktop-mode server holds a "password" session and must still provide the old
72
- * password when changing it — only "desktop" sessions (opened by the shell's one-shot
73
- * token) may omit it. "token" marks a request authenticated by the local API token's
74
- * Bearer header (the CLI and agent-driven calls).
82
+ * How THIS session was established — distinct from desktopMode, which describes the
83
+ * server: a browser signed into a desktop-mode server holds a "password" session.
84
+ * "desktop" is the shell's own window (one-shot token); "setup" was claimed through the
85
+ * first-login link on a server whose admin password has never been set. Both may set a
86
+ * password without the old one (it is random and was never shown); only "desktop" opens
87
+ * desktop-only routes. "token" marks a request authenticated by the local API token's
88
+ * Bearer header (the CLI and agent-driven calls) — no stored session at all.
75
89
  */
76
- sessionVia: "password" | "desktop" | "token";
90
+ sessionVia: "password" | "desktop" | "setup" | "token";
77
91
  /**
78
92
  * The upload limits currently in force, so the composer can refuse an oversize pick before
79
93
  * reading it and can name the real number in the message. They are admin-settable and ride
@@ -108,7 +122,7 @@ interface UploadLimits {
108
122
  attachmentLimitMaxMb: number;
109
123
  }
110
124
  interface PasswordChangeRequest {
111
- /** Omitted only by desktop-established sessions (desktop mode); required otherwise. */
125
+ /** Omitted only by a "desktop" or "setup" session (see {@link MeResponse.sessionVia}); required otherwise. */
112
126
  oldPassword?: string;
113
127
  /** At least 8 characters. */
114
128
  newPassword: string;
@@ -220,6 +234,14 @@ interface UiPrefs {
220
234
  credentialGuideSeen?: boolean;
221
235
  /** The initial-password notice banner (app layout) was permanently dismissed by the user. */
222
236
  initialPasswordBannerDismissed?: boolean;
237
+ /**
238
+ * "I have dealt with this" markers for the dismissible to-do badges, per Project id and then
239
+ * per trail (`skills` / `models` / `errors`). Each value is the SIGNATURE of what was waved
240
+ * away rather than a hidden flag, so anything new raises the dot again (web's
241
+ * `lib/todo-badges.ts`). Replaced whole on every write, like `draftShortcuts`: the merge is
242
+ * shallow, so this whole map is one field.
243
+ */
244
+ todoDismissed?: Record<string, Record<string, string>>;
223
245
  /**
224
246
  * The draft screen's user-defined shortcuts, in display order. Replaced whole on every write
225
247
  * (the merge is shallow, so the array is one field like any other) and bounded on write by
@@ -593,6 +615,13 @@ interface ModelOAuthStatusResponse {
593
615
  status: "pending" | "done" | "error";
594
616
  /** The provider group the flow mints a key for. */
595
617
  provider: string;
618
+ /**
619
+ * How many models the minted key was written to — set on the `done` answer, the way
620
+ * {@link ModelOAuthCodeResponse} sets it on a redemption. The dialog reports this number, so
621
+ * it has to be the server's own: the caller's model table can outlive a rejected save and
622
+ * would otherwise name a count the server never wrote.
623
+ */
624
+ applied?: number;
596
625
  error?: ModelOAuthErrorCode;
597
626
  }
598
627
  /**
@@ -679,6 +708,13 @@ interface VaultEntryUpdate {
679
708
  interface VaultUpdateRequest {
680
709
  entries: VaultEntryUpdate[];
681
710
  }
711
+ /** One installed Skill the library carries a higher version of (see {@link AgentSummary.skillUpdates}). */
712
+ interface SkillUpdateRef {
713
+ /** Skill directory name — the identity install / uninstall address it by. */
714
+ name: string;
715
+ /** The LIBRARY's version, i.e. what installing again would bring, not what is on disk. */
716
+ version: number;
717
+ }
682
718
  interface AgentSummary {
683
719
  agentId: string;
684
720
  name?: string;
@@ -704,6 +740,14 @@ interface AgentSummary {
704
740
  scheduleCount: number;
705
741
  /** Installed Skill count (number of agent_state/skills/<name>/ directories with a SKILL.md). */
706
742
  skillCount: number;
743
+ /**
744
+ * Installed Skills the built-in library has moved past, each with the library version on
745
+ * offer — the Skill-library update gate, riding along on the Agent list so a badge over
746
+ * that page costs no request of its own. Empty when nothing is behind. Skills that are not
747
+ * in the library (installed from a zip or a picked directory) are never listed: there is no
748
+ * library version for them to be behind.
749
+ */
750
+ skillUpdates: SkillUpdateRef[];
707
751
  /** Memory count (topic files summed over the scope directories under agent_state/memory/, independent of the memory switch). */
708
752
  memoryCount: number;
709
753
  }
@@ -1446,20 +1490,117 @@ interface SessionProcessesResponse {
1446
1490
  processes: SessionProcessInfo[];
1447
1491
  }
1448
1492
  /** Messaging channels a Session can bind to. */
1449
- type MessagingChannel = "feishu" | "telegram";
1493
+ type MessagingChannel = "feishu" | "telegram" | "qq" | "wechat";
1450
1494
  /** Event-connection runtime state of one binding (kept in memory, not persisted). */
1451
1495
  type MessagingRuntimeState = "disconnected" | "connecting" | "connected" | "error";
1496
+ /**
1497
+ * A failure that happened AFTER an inbound message was accepted — as opposed to a
1498
+ * connection failure, which `MessagingRuntimeStatus.lastError` reports.
1499
+ *
1500
+ * The two stages fail in completely different places and lead to different actions, and
1501
+ * from the chat they are indistinguishable (both produce silence), which is why the stage
1502
+ * is stated rather than folded into one message.
1503
+ */
1504
+ interface MessagingDeliveryError {
1505
+ /** ISO 8601 timestamp of the failure. */
1506
+ at: string;
1507
+ /** `inbound` — the message arrived and its Task never started; `send` — a reply never reached the chat. */
1508
+ stage: "inbound" | "send";
1509
+ /** The failure's own message, as the channel or the Session reported it. */
1510
+ detail: string;
1511
+ }
1452
1512
  interface MessagingRuntimeStatus {
1453
1513
  state: MessagingRuntimeState;
1454
1514
  /** Failure detail; present only in the `error` state. */
1455
1515
  lastError?: string;
1456
1516
  /** When the state last changed (ISO 8601); absent for a binding that never connected. */
1457
1517
  changedAt?: string;
1518
+ /**
1519
+ * When this binding last accepted an inbound message (ISO 8601).
1520
+ *
1521
+ * "Connected, and nothing has arrived" is the answer to the one question a chat cannot
1522
+ * answer for itself — whether the platform is delivering anything at all. A channel that
1523
+ * withholds messages (Telegram's group privacy, a bot that is not a member) produces
1524
+ * exactly that, with no error anywhere.
1525
+ *
1526
+ * In-process AND scoped to one connection: it starts empty on every (re)connect, and a
1527
+ * re-enable or a credential save opens a new one. So an absent field means "nothing since
1528
+ * this connection opened", never "nothing ever" — anything reporting it has to say which,
1529
+ * or it sends a reader off to fix a channel that is working.
1530
+ */
1531
+ lastInboundAt?: string;
1532
+ /**
1533
+ * The most recent post-acceptance failure; absent when none has happened since this
1534
+ * connection opened, and never cleared by a later success — an intermittent failure would
1535
+ * otherwise be erased by the next ordinary message. `at` is what says how stale it is.
1536
+ */
1537
+ lastDeliveryError?: MessagingDeliveryError;
1538
+ /**
1539
+ * The most recent CONNECTION failure, kept after the connection recovers — unlike
1540
+ * `lastError`, which belongs to the `error` state and is gone the moment the state leaves it.
1541
+ *
1542
+ * A connection that fails and recovers repeatedly (a second program polling the same bot
1543
+ * token takes turns with this one) reads as `connected` in any snapshot taken between
1544
+ * flaps, with nothing at all to show for the failures in between. This is what is left
1545
+ * behind — for the life of the connection, like the two above it.
1546
+ */
1547
+ lastConnectionError?: {
1548
+ at: string;
1549
+ detail: string;
1550
+ };
1551
+ }
1552
+ /**
1553
+ * What a messaging binding carries whatever channel it is: the connection intent, the three
1554
+ * delivery preferences, whether a chat is known, and the row's identity and timestamps.
1555
+ *
1556
+ * Split out because this is the half that grows. Three delivery preferences arrived in one
1557
+ * release, and each would otherwise have been written into three interfaces — the credential
1558
+ * slice is the only thing a channel genuinely differs in, and it is what stays per-channel.
1559
+ *
1560
+ * `channel` is NOT here: a discriminated union discriminates on a literal the member itself
1561
+ * declares, so each interface keeps its own.
1562
+ *
1563
+ * A channel may RE-DECLARE a field below when it has more to say about it — QQ does, for all
1564
+ * three preferences, because the platform's passive-reply budget and its expiring window
1565
+ * change what setting one costs there. The re-declared type must be identical, which the
1566
+ * compiler enforces, so the redeclaration can only add documentation and never a contract.
1567
+ */
1568
+ interface MessagingBindingCommon {
1569
+ sessionId: string;
1570
+ /** Connection INTENT (the state toggle's value); new bindings start disabled, and at most one of a Session's channels is enabled. */
1571
+ enabled: boolean;
1572
+ /**
1573
+ * Send each non-blank line of a relayed assistant reply as its own message instead of one
1574
+ * message per reply. Off by default; off is the original one-message-per-reply behaviour.
1575
+ */
1576
+ linePerMessage: boolean;
1577
+ /**
1578
+ * Relay only the LAST completed assistant message of a run, delivered when the run ends,
1579
+ * instead of mirroring each completed message as it completes. Off by default; off is the
1580
+ * original every-message behaviour. Independent of `linePerMessage`, which then applies to
1581
+ * that one final message. The approval notice is not a reply and is unaffected.
1582
+ */
1583
+ finalReplyOnly: boolean;
1584
+ /**
1585
+ * Render a relayed reply's Markdown in this channel's own markup instead of sending its
1586
+ * characters as written. ON by default. Each channel shows what it can — Telegram has no
1587
+ * headings, lists or tables, QQ has no code or tables, Feishu has all of them, and WeChat
1588
+ * reads Markdown itself so the render is a subtraction rather than a translation — and a
1589
+ * rendering the channel refuses falls back to the plain source, so this can cost
1590
+ * formatting and never a message.
1591
+ */
1592
+ renderMarkdown: boolean;
1593
+ /**
1594
+ * Whether an inbound chat is known (the bot has been messaged at least once). Replies and
1595
+ * test messages target that chat; until it exists nothing can be sent.
1596
+ */
1597
+ lastChatKnown: boolean;
1598
+ createdAt: string;
1599
+ updatedAt: string;
1458
1600
  }
1459
1601
  /** The stored Feishu config, secret masked (plaintext never leaves the server). */
1460
- interface FeishuBindingInfo {
1602
+ interface FeishuBindingInfo extends MessagingBindingCommon {
1461
1603
  channel: "feishu";
1462
- sessionId: string;
1463
1604
  appId: string;
1464
1605
  /**
1465
1606
  * Masked app secret (site-wide mask rule: `***`, or `first4…last4` for long values);
@@ -1468,20 +1609,10 @@ interface FeishuBindingInfo {
1468
1609
  */
1469
1610
  appSecretMasked?: string;
1470
1611
  baseDomain: string;
1471
- /** Connection INTENT (the state toggle's value); new bindings start disabled, and at most one of a Session's channels is enabled. */
1472
- enabled: boolean;
1473
- /**
1474
- * Whether an inbound Feishu chat is known (the bot has been messaged at least once).
1475
- * Replies and test messages target that chat; until it exists nothing can be sent.
1476
- */
1477
- lastChatKnown: boolean;
1478
- createdAt: string;
1479
- updatedAt: string;
1480
1612
  }
1481
1613
  /** The stored Telegram config, token masked (plaintext never leaves the server). */
1482
- interface TelegramBindingInfo {
1614
+ interface TelegramBindingInfo extends MessagingBindingCommon {
1483
1615
  channel: "telegram";
1484
- sessionId: string;
1485
1616
  /** The numeric bot id (the token's half before the colon) — the channel-scoped account identity, never secret. */
1486
1617
  botId: string;
1487
1618
  /**
@@ -1490,18 +1621,78 @@ interface TelegramBindingInfo {
1490
1621
  * is saved.
1491
1622
  */
1492
1623
  botTokenMasked?: string;
1493
- /** Connection INTENT (the state toggle's value); new bindings start disabled, and at most one of a Session's channels is enabled. */
1494
- enabled: boolean;
1624
+ }
1625
+ /**
1626
+ * The stored QQ config, secret masked (plaintext never leaves the server).
1627
+ *
1628
+ * The three preference fields are re-declared unchanged: every one of them costs something
1629
+ * different here, and the platform's reply budget is what a reader setting one needs to know.
1630
+ */
1631
+ interface QQBindingInfo extends MessagingBindingCommon {
1632
+ channel: "qq";
1633
+ /** The bot's App ID — the channel-scoped account identity, never secret. */
1634
+ appId: string;
1635
+ /**
1636
+ * Masked App Secret (site-wide mask rule: `***`, or `first4…last4` for long values);
1637
+ * absent when no secret is stored (never entered, or cleared) — the binding cannot be
1638
+ * enabled until one is saved.
1639
+ */
1640
+ appSecretMasked?: string;
1495
1641
  /**
1496
- * Whether an inbound Telegram chat is known (the bot has been messaged at least once).
1497
- * Replies and test messages target that chat; until it exists nothing can be sent.
1642
+ * Send each non-blank line of a relayed assistant reply as its own message instead of one
1643
+ * message per reply. Off by default. On QQ the split is additionally capped at the
1644
+ * platform's passive-reply budget rather than the channel-neutral ceiling, so it yields
1645
+ * far fewer messages here than on the other channels.
1646
+ */
1647
+ linePerMessage: boolean;
1648
+ /**
1649
+ * Relay only the LAST completed assistant message of a run, delivered when the run ends.
1650
+ * Off by default.
1651
+ *
1652
+ * On QQ it cuts both ways, which is worth knowing before setting it here. It spends the
1653
+ * least of the platform's passive-reply budget a run can spend — one message, where an
1654
+ * every-message relay spends one per completed message. But a passive reply is accepted
1655
+ * only for a few minutes after the inbound message that funds it, and holding the reply
1656
+ * to the run's end spends that window on the run: a run that outlives it delivers nothing
1657
+ * at all, where the every-message relay would have sent whatever completed inside it.
1658
+ */
1659
+ finalReplyOnly: boolean;
1660
+ /**
1661
+ * Render a relayed reply's Markdown in this channel's own markup. ON by default. QQ's own
1662
+ * subset is the widest for prose and the narrowest for code: headings, lists, blockquotes
1663
+ * and rules render, while inline code, fenced code and tables have no syntax at all here —
1664
+ * a code block arrives as plain escaped lines. A rendering the platform refuses falls back
1665
+ * to the plain source, at the cost of one more slot from the passive-reply budget.
1666
+ */
1667
+ renderMarkdown: boolean;
1668
+ /**
1669
+ * Whether an inbound QQ chat is known (the bot has been messaged at least once). Weaker
1670
+ * than it looks on this channel: QQ accepts only replies to a recent message, so a known
1671
+ * chat is necessary but not sufficient for anything to be deliverable right now.
1498
1672
  */
1499
1673
  lastChatKnown: boolean;
1500
- createdAt: string;
1501
- updatedAt: string;
1674
+ }
1675
+ /**
1676
+ * The stored WeChat config, token masked (plaintext never leaves the server).
1677
+ *
1678
+ * No preference field is re-declared. The three delivery preferences cost exactly what they
1679
+ * cost on Feishu and Telegram here — this channel has no reply budget and no expiring reply
1680
+ * window — and re-declaring a field to say nothing new about it would only invite the next
1681
+ * reader to look for the difference.
1682
+ */
1683
+ interface WeChatBindingInfo extends MessagingBindingCommon {
1684
+ channel: "wechat";
1685
+ /** The bot id a scan issued — the channel-scoped account identity, never secret. */
1686
+ botId: string;
1687
+ /**
1688
+ * Masked bot token (site-wide mask rule: `***`, or `first4…last4` for long values);
1689
+ * absent when none is stored (cleared, or a scan that never completed) — the binding
1690
+ * cannot be enabled until a scan saves one.
1691
+ */
1692
+ botTokenMasked?: string;
1502
1693
  }
1503
1694
  /** A Session's saved config for one messaging channel (`channel` is the discriminant). */
1504
- type MessagingBindingInfo = FeishuBindingInfo | TelegramBindingInfo;
1695
+ type MessagingBindingInfo = FeishuBindingInfo | TelegramBindingInfo | QQBindingInfo | WeChatBindingInfo;
1505
1696
  /** One saved channel config with its event-connection runtime status. */
1506
1697
  interface MessagingChannelState {
1507
1698
  binding: MessagingBindingInfo;
@@ -1526,12 +1717,37 @@ interface TelegramBindingResponse {
1526
1717
  binding: TelegramBindingInfo | null;
1527
1718
  status: MessagingRuntimeStatus;
1528
1719
  }
1720
+ /** GET / PUT …/messaging/qq response (the QQ narrowing of the same envelope). */
1721
+ interface QQBindingResponse {
1722
+ binding: QQBindingInfo | null;
1723
+ status: MessagingRuntimeStatus;
1724
+ }
1725
+ /** GET / PUT …/messaging/wechat response (the WeChat narrowing of the same envelope). */
1726
+ interface WeChatBindingResponse {
1727
+ binding: WeChatBindingInfo | null;
1728
+ status: MessagingRuntimeStatus;
1729
+ }
1529
1730
  /**
1530
1731
  * PUT …/messaging/feishu — saves credentials/config ONLY, never flipping the connection
1531
1732
  * (exception: an enabled binding's connector restarts with the new credentials so stored
1532
1733
  * config and live connection never diverge). The connection toggle is POST …/state.
1533
1734
  */
1534
- interface FeishuBindingPutRequest {
1735
+ /**
1736
+ * The delivery preferences any channel's PUT may set. Each is optional and each behaves the
1737
+ * same way on every channel: an omitted field keeps the stored value, so a client that knows
1738
+ * about one preference can save it without having to send the others back. Their meanings are
1739
+ * on {@link MessagingBindingCommon}, and where a channel charges differently for one, on that
1740
+ * channel's own `*BindingInfo`.
1741
+ *
1742
+ * The defaults a binding created without them starts from: `linePerMessage` off,
1743
+ * `finalReplyOnly` off, `renderMarkdown` ON.
1744
+ */
1745
+ interface MessagingDeliveryPatch {
1746
+ linePerMessage?: boolean;
1747
+ finalReplyOnly?: boolean;
1748
+ renderMarkdown?: boolean;
1749
+ }
1750
+ interface FeishuBindingPutRequest extends MessagingDeliveryPatch {
1535
1751
  appId: string;
1536
1752
  /** Omitted or blank keeps the stored secret (the masked value never round-trips). */
1537
1753
  appSecret?: string;
@@ -1546,9 +1762,10 @@ interface FeishuBindingPutRequest {
1546
1762
  /**
1547
1763
  * PUT …/messaging/telegram — saves the credential ONLY, same contract as the Feishu PUT
1548
1764
  * (an enabled binding's connector restarts with the new token; the connection toggle is
1549
- * POST …/state). 409 `telegram_bot_in_use` when the token's bot id is bound elsewhere.
1765
+ * POST …/state). Saving never conflicts across Sessions: the same bot may sit saved on
1766
+ * several, and only enabling it is exclusive.
1550
1767
  */
1551
- interface TelegramBindingPutRequest {
1768
+ interface TelegramBindingPutRequest extends MessagingDeliveryPatch {
1552
1769
  /** Omitted or blank keeps the stored token (the masked value never round-trips). */
1553
1770
  botToken?: string;
1554
1771
  /**
@@ -1558,11 +1775,46 @@ interface TelegramBindingPutRequest {
1558
1775
  */
1559
1776
  clearBotToken?: boolean;
1560
1777
  }
1778
+ /**
1779
+ * PUT …/messaging/qq — saves the credential pair ONLY, same contract as the Feishu PUT
1780
+ * (an enabled binding's connector restarts with the new credentials; the connection toggle
1781
+ * is POST …/state). The App ID is the account identity, so changing it rebinds the row to
1782
+ * a different bot and drops the remembered chat.
1783
+ */
1784
+ interface QQBindingPutRequest extends MessagingDeliveryPatch {
1785
+ appId: string;
1786
+ /** Omitted or blank keeps the stored secret (the masked value never round-trips). */
1787
+ appSecret?: string;
1788
+ /**
1789
+ * Drops the STORED secret (the models-page clear idiom; a typed `appSecret` wins over
1790
+ * it). Refused with 409 `messaging_disable_before_clear` while the binding is enabled.
1791
+ */
1792
+ clearAppSecret?: boolean;
1793
+ }
1794
+ /**
1795
+ * PUT …/messaging/wechat — the delivery preferences ONLY.
1796
+ *
1797
+ * The one PUT on this router that carries no credential, because there is none to carry: a
1798
+ * WeChat bot token exists only where a scan put it, and there is no console to copy one out
1799
+ * of. Saving therefore presupposes a binding — a PUT before any scan answers 400
1800
+ * `wechat_token_required` rather than creating an empty row — and the connection toggle
1801
+ * stays POST …/state, as on every channel.
1802
+ */
1803
+ interface WeChatBindingPutRequest extends MessagingDeliveryPatch {
1804
+ /**
1805
+ * Drops the STORED token (the models-page clear idiom). Refused with 409
1806
+ * `messaging_disable_before_clear` while the binding is enabled. The row and its bot
1807
+ * identity stay; only a fresh scan can make it connectable again.
1808
+ */
1809
+ clearBotToken?: boolean;
1810
+ }
1561
1811
  /**
1562
1812
  * POST …/messaging/<channel>/state — enable connects with the STORED credentials,
1563
- * disable terminates. Enabling is mutually exclusive per Session: while another channel
1564
- * is enabled it answers 409 `another_channel_enabled` (turn that one off first), and a
1565
- * config whose secret is missing answers its channel's 400 `*_required`.
1813
+ * disable terminates. Enabling is what binds the bot account to this Session, and it is
1814
+ * mutually exclusive twice over: while another channel of the same Session is enabled it
1815
+ * answers 409 `another_channel_enabled`, and while another SESSION has the same account
1816
+ * enabled it answers 409 `account_enabled_elsewhere` (both say: turn that one off first).
1817
+ * A config whose secret is missing answers its channel's 400 `*_required`.
1566
1818
  */
1567
1819
  interface MessagingBindingStateRequest {
1568
1820
  enabled: boolean;
@@ -1589,11 +1841,145 @@ interface TelegramTestResponse {
1589
1841
  latencyMs?: number;
1590
1842
  /** The bot's `@username`, when the API reports one. */
1591
1843
  botUsername?: string;
1844
+ /**
1845
+ * True when @BotFather's **Group Privacy** is ON for this bot, which is the default. In
1846
+ * every group where the bot is not an administrator it then receives only a command
1847
+ * addressed to it or a reply to one of its own messages — an ordinary sentence is never
1848
+ * delivered, so a binding that answers fine in a direct chat stays silent there. The
1849
+ * setting is account-wide and Telegram overrides it for a group the bot administers, so
1850
+ * this reports the setting and never the outcome in any particular group. Absent when the
1851
+ * API did not report the setting; never inferred.
1852
+ */
1853
+ groupPrivacy?: boolean;
1592
1854
  error?: string;
1593
1855
  }
1856
+ /** POST …/messaging/qq/test — draft values; each omitted field falls back to the stored binding. */
1857
+ interface QQTestRequest {
1858
+ appId?: string;
1859
+ appSecret?: string;
1860
+ }
1861
+ /**
1862
+ * QQ credential-test outcome. There is no account label: the platform's only credential
1863
+ * call is the access-token exchange, which identifies nothing beyond the App ID that was
1864
+ * sent to it.
1865
+ */
1866
+ interface QQTestResponse {
1867
+ ok: boolean;
1868
+ latencyMs?: number;
1869
+ error?: string;
1870
+ }
1871
+ /**
1872
+ * POST …/messaging/qq/scan — starts a scan-to-connect flow: the server registers a bind
1873
+ * task under a fresh AES key it keeps to itself, and answers with what the browser may
1874
+ * know. The key is absent from this type on purpose — it decrypts the App Secret, so it
1875
+ * never leaves the server (the same rule that keeps a stored secret from round-tripping).
1876
+ */
1877
+ interface QQScanStartResponse {
1878
+ /** Opaque bind-task handle, passed back to the poll endpoint. */
1879
+ taskId: string;
1880
+ /** The URL to ENCODE into a QR code. It is opened by the QQ app, never fetched by the browser. */
1881
+ qrUrl: string;
1882
+ /** How often to poll, in milliseconds (the interval the protocol is designed around). */
1883
+ pollMs: number;
1884
+ }
1885
+ /**
1886
+ * POST …/messaging/qq/scan/poll — one step of the scan. `pending` means keep polling,
1887
+ * `expired` means start a new task and show a new QR, and `completed` means the server has
1888
+ * already decrypted the App Secret and SAVED the binding: `appId` names the bot that landed.
1889
+ * Saving is all it does — enabling the connection stays the separate, exclusive act it is on
1890
+ * every channel. A task id that is unknown, belongs to another Session, was already
1891
+ * resolved, or is being resolved by a poll still in flight answers 404
1892
+ * `qq_scan_task_unknown`: the task is claimed by one poll, so a client whose interval fires
1893
+ * before the previous request came back binds once rather than once per overlapping poll.
1894
+ */
1895
+ interface QQScanPollResponse {
1896
+ status: "none" | "pending" | "completed" | "expired";
1897
+ /** The bound bot's App ID; present only on `completed`. Never the secret. */
1898
+ appId?: string;
1899
+ /** The saved binding, present on `completed` so the editor refreshes without a second GET. */
1900
+ binding?: QQBindingInfo;
1901
+ }
1902
+ /**
1903
+ * WeChat credential-test outcome. There is no request body and no draft to probe: this
1904
+ * channel's credential exists only where a scan put it, so the test always probes the STORED
1905
+ * binding. It answers 400 `wechat_token_required` when there is none.
1906
+ *
1907
+ * No account label, for the same reason QQ has none: the probe (`getconfig`) reports the
1908
+ * bot's settings and names neither the bot nor the person.
1909
+ */
1910
+ interface WeChatTestResponse {
1911
+ ok: boolean;
1912
+ latencyMs?: number;
1913
+ error?: string;
1914
+ }
1915
+ /**
1916
+ * POST …/messaging/wechat/scan — starts a scan-to-connect flow, which on this channel is the
1917
+ * ONLY way to bind: the bot token has no console to be copied out of.
1918
+ *
1919
+ * The server registers a code and answers with what the browser may know. The platform's own
1920
+ * poll handle is absent from this type on purpose — it is what collects the bot token, so it
1921
+ * never leaves the server, and `taskId` is a handle this server mints in its place.
1922
+ */
1923
+ interface WeChatScanStartResponse {
1924
+ /** Opaque scan handle, passed back to the poll, verify and cancel endpoints. */
1925
+ taskId: string;
1926
+ /** The URL to ENCODE into a QR code. It is opened by WeChat, never fetched by the browser. */
1927
+ qrUrl: string;
1928
+ /** How often to poll, in milliseconds. */
1929
+ pollMs: number;
1930
+ }
1931
+ /**
1932
+ * Where a WeChat scan stands. Richer than QQ's four states because the flow is: WeChat
1933
+ * separates scanning from confirming, and may interpose a pairing code shown on the phone.
1934
+ *
1935
+ * - `pending` — the code is up and nothing has happened; keep polling.
1936
+ * - `scanned` — scanned; the phone is showing the confirmation prompt.
1937
+ * - `need_verify_code` — the phone is showing digits that must be sent to the verify
1938
+ * endpoint before the bind proceeds.
1939
+ * - `blocked` — too many wrong pairing codes; the code is spent and a new scan is needed.
1940
+ * - `expired` — the code lapsed before it was used; show a new one.
1941
+ * - `already_bound` — this bot is already bound to this server, so no new credentials were
1942
+ * issued and nothing was saved. Not a failure: the existing binding still works.
1943
+ * - `completed` — the server has already SAVED the binding; `botId` names the bot.
1944
+ */
1945
+ type WeChatScanStatus = "pending" | "scanned" | "need_verify_code" | "blocked" | "expired" | "already_bound" | "completed";
1946
+ /**
1947
+ * POST …/messaging/wechat/scan/poll — one step of the scan.
1948
+ *
1949
+ * `completed` means the server has decrypted nothing and stored everything: the credentials
1950
+ * went from the platform into storage without passing through the browser. Saving is all it
1951
+ * does — enabling the connection stays the separate, exclusive act it is on every channel. A
1952
+ * task id that is unknown, belongs to another Session, or was already resolved answers 404
1953
+ * `wechat_scan_task_unknown`.
1954
+ *
1955
+ * Unlike QQ's poll, an overlapping request answers `pending` rather than 404: the upstream
1956
+ * call is a LONG poll, so one of them spans several of the client's intervals, and that
1957
+ * overlap is the normal rhythm rather than a replay.
1958
+ */
1959
+ interface WeChatScanPollResponse {
1960
+ status: WeChatScanStatus;
1961
+ /** The bound bot's id; present only on `completed`. Never the token. */
1962
+ botId?: string;
1963
+ /** The saved binding, present on `completed` so the editor refreshes without a second GET. */
1964
+ binding?: WeChatBindingInfo;
1965
+ }
1966
+ /**
1967
+ * POST …/messaging/wechat/scan/verify — the digits WeChat showed on the phone.
1968
+ *
1969
+ * They ride the NEXT poll rather than a request of their own, because the platform takes the
1970
+ * pairing code as a parameter of the status call: this endpoint records them and answers
1971
+ * 204. A wrong code is not reported here — the next poll asks for one again, which is how
1972
+ * the platform reports it.
1973
+ */
1974
+ interface WeChatScanVerifyRequest {
1975
+ taskId: string;
1976
+ verifyCode: string;
1977
+ }
1594
1978
  /**
1595
1979
  * POST …/messaging/<channel>/test-message — sent to the last known chat (409
1596
- * `feishu_no_chat` / `telegram_no_chat` before one exists).
1980
+ * `feishu_no_chat` / `telegram_no_chat` / `qq_no_chat` before one exists). On QQ this can
1981
+ * still fail with 502 afterwards: the platform accepts only replies to a message sent from
1982
+ * QQ minutes earlier, so a known chat does not mean a deliverable one.
1597
1983
  */
1598
1984
  interface MessagingTestMessageResponse {
1599
1985
  ok: true;
@@ -2144,6 +2530,29 @@ interface UsageModelSeries extends UsageEntitySeriesCounts {
2144
2530
  provider: string;
2145
2531
  modelId: string;
2146
2532
  }
2533
+ /**
2534
+ * Lifetime Token total for one Model, keyed by the (provider, modelId) pair. Deliberately
2535
+ * unfiltered — no date range, no Agent: it answers "how much has this model been used", a
2536
+ * question with no window attached, and the models page that shows it carries no filters of its
2537
+ * own to honour. Models never used are absent rather than zero.
2538
+ */
2539
+ interface UsageModelTotal {
2540
+ provider: string;
2541
+ modelId: string;
2542
+ /** The three buckets summed (cache read + cache write + output), matching the cost center's Token figure. */
2543
+ tokens: number;
2544
+ requests: number;
2545
+ }
2546
+ /** Response of `GET /usage/model-totals`. */
2547
+ interface UsageModelTotals {
2548
+ totals: UsageModelTotal[];
2549
+ }
2550
+ /**
2551
+ * The two categories an error record is filed under: `unexpected` is a 500 or an unforeseen
2552
+ * runtime exception, `expected` an HttpError / business 4xx. The panel separates them by
2553
+ * colour, and `GET /usage/errors` takes one of them as its `kind` filter.
2554
+ */
2555
+ type UsageErrorKind = "unexpected" | "expected";
2147
2556
  /** Occurrence count of an error for a given source · code (the "most common" metric in the stats center's error panel). */
2148
2557
  interface UsageErrorCount {
2149
2558
  source: string;
@@ -2169,6 +2578,15 @@ interface UsageErrorItem {
2169
2578
  */
2170
2579
  interface UsageErrors {
2171
2580
  total: number;
2581
+ /**
2582
+ * How many of {@link total} a clear would actually take (see {@link UsageErrorsClearResponse}).
2583
+ *
2584
+ * The same as `total` for an ordinary member, and smaller for an admin, whose reads include
2585
+ * unattributed rows that no Project-scoped clear removes. The confirmation is the only place
2586
+ * this matters, and it is the place it matters most: an irreversible delete has to name the
2587
+ * number that will really go, not the number on screen.
2588
+ */
2589
+ clearable: number;
2172
2590
  /** Count of unexpected ones (500 / runtime exceptions) among them — the part the frontend highlights. */
2173
2591
  unexpected: number;
2174
2592
  /** The most frequent source · code (null when there are no errors). */
@@ -2180,13 +2598,28 @@ interface UsageErrors {
2180
2598
  * GET /api/projects/:projectId/usage/errors — one page of the error detail table, newest
2181
2599
  * first. The dashboard response above already carries the first page; this exists so
2182
2600
  * "show me earlier ones" does not have to refetch the whole aggregate. It takes the same
2183
- * date/agent filter as the dashboard, so a page never widens what the summary counted.
2601
+ * date/agent filter as the dashboard, so a page never widens what the summary counted, plus
2602
+ * an optional `kind` ({@link UsageErrorKind}) narrowing to one of the two categories — which
2603
+ * is how the cost-center badge asks "are there unexpected errors, and how new is the newest"
2604
+ * with `limit=1` instead of pulling the whole dashboard aggregate.
2184
2605
  */
2185
2606
  interface UsageErrorsPage {
2186
2607
  items: UsageErrorItem[];
2187
2608
  /** Filtered row count, so the caller knows when it has reached the end. */
2188
2609
  total: number;
2189
2610
  }
2611
+ /**
2612
+ * DELETE /api/projects/:projectId/usage/errors — empties the error table for the filter the
2613
+ * panel is showing (its date range and Agent), Project owner only.
2614
+ *
2615
+ * Scoped to the filter rather than the Project's whole history, so a clear takes exactly the
2616
+ * rows on screen. Errors with no Project attribution are never included, whoever asks: they
2617
+ * belong to no Project and are surfaced in every Project's admin view.
2618
+ */
2619
+ interface UsageErrorsClearResponse {
2620
+ /** How many rows were deleted, so the caller can say what went instead of guessing. */
2621
+ deleted: number;
2622
+ }
2190
2623
  interface UsageResponse {
2191
2624
  summary: {
2192
2625
  today: UsageBucket;
@@ -2491,5 +2924,61 @@ interface UpdateRunResponse {
2491
2924
  /** True when the install changed (or was already current): restart the service to run the new version. */
2492
2925
  needsRestart: boolean;
2493
2926
  }
2927
+ /** One `Host` entry of the server's `~/.ssh/config`, as the Machines page lists it. */
2928
+ interface MachineInfo {
2929
+ /** `ssh:<alias>` — the id the install route is asked for. */
2930
+ id: string;
2931
+ /**
2932
+ * The alias exactly as written in the config. The list is the config text and nothing
2933
+ * else — no `ssh -G`, no processes, no network — so a config declaring hundreds of hosts
2934
+ * costs one file read; an alias is resolved only when it is actually installed to.
2935
+ */
2936
+ alias: string;
2937
+ /**
2938
+ * The last install THIS server carried out there, remembered on disk so it survives a
2939
+ * restart, a hot push, and installing on some other machine. Null when this server has
2940
+ * never installed there.
2941
+ *
2942
+ * A record of what was done, not a survey of the far side: a machine wiped by hand still
2943
+ * reads as installed until the next install probes it and corrects the record. Asking the
2944
+ * remote instead would cost an ssh round trip per host at page load, which is the price
2945
+ * the config-text list exists to avoid.
2946
+ */
2947
+ installed: {
2948
+ version: string;
2949
+ at: string;
2950
+ } | null;
2951
+ }
2952
+ /**
2953
+ * The running or last install, polled by GET /api/machines while one runs. `log` carries the
2954
+ * far side's own words where there are any: ssh's diagnostics and the remote installer's
2955
+ * output say more about a refused key or an unusable Node than a paraphrase would.
2956
+ */
2957
+ interface MachineInstallJob {
2958
+ machineId: string;
2959
+ alias: string;
2960
+ running: boolean;
2961
+ log: string[];
2962
+ result: null | {
2963
+ ok: true;
2964
+ kind: "installed" | "already-installed";
2965
+ version: string | null;
2966
+ } | {
2967
+ ok: false;
2968
+ step: string;
2969
+ message: string;
2970
+ };
2971
+ }
2972
+ /** GET /api/machines, and the 202 body of POST /api/machines/:machineId/install. */
2973
+ interface MachinesResponse {
2974
+ machines: MachineInfo[];
2975
+ /**
2976
+ * The version an install would leave on the remote — the base release, plus a `+hmr.<sha>`
2977
+ * suffix when this server carries a pushed version to replicate. Null for a development
2978
+ * checkout, which stands on no release the remote could download.
2979
+ */
2980
+ imageVersion: string | null;
2981
+ job: MachineInstallJob | null;
2982
+ }
2494
2983
 
2495
- export type { AdminPasswordResetRequest, AdminUserCreateRequest, AdminUserCreateResponse, AdminUsersResponse, AgentCompactionConfigDto, AgentConfigDto, AgentConfigResponse, AgentConfigUpdateRequest, AgentCreateRequest, AgentCreateResponse, AgentImportRequest, AgentImportResponse, AgentKernelUpdateResponse, AgentMemoryConfigDto, AgentModelConfigDto, AgentSchedulesConfigDto, AgentSkillsConfigDto, AgentSkillsResponse, AgentSummary, AgentTraceDateGroup, AgentTraceFileRef, AgentTraceSessionEntry, AgentTraceSessionFile, AgentTraceSessionGroup, AgentTracesResponse, AgentVaultConfigDto, AgentsResponse, ApprovalDecisionRequest, ApprovalMode, AuthLoginRequest, AuthResponse, BenchmarkCaseScore, BenchmarkCaseSummary, BenchmarkCasesResponse, BenchmarkEvaluation, BenchmarkRunScore, BenchmarkSummary, BenchmarksResponse, CaseMaterial, ChatDefaultsDto, CommandPolicyDto, CommandPolicyRuleDto, ContextToolShare, CredentialInfo, DefaultModelResponse, DefaultModelUpdateRequest, DesktopUpdateStatus, DesktopUpdateStatusResponse, DesktopUpdaterCommandMessage, DesktopUpdaterStatusMessage, DirEntryInfo, DirListResponse, DirectorySkillItem, DirectorySkillsResponse, DraftShortcut, EndpointModelListRequest, EndpointModelListResponse, ErrorBody, FeishuBindingInfo, FeishuBindingPutRequest, FeishuBindingResponse, FeishuTestRequest, FeishuTestResponse, FilesStatRequest, FilesStatResponse, GoalResponse, GoalServerEvent, GoalStateView, HistoryMessage, McpServerTestResponse, MeResponse, MemberAddRequest, MemberAddResponse, MemberInfo, MembersResponse, MemoryFileInfo, MemoryFileResponse, MemoryFilesResponse, MemoryImportMode, MemoryImportRequest, MemoryImportResponse, MemoryOverviewResponse, MemoryScopeExport, MemoryScopeInfo, MemoryTransferFile, MessagesLiveTail, MessagesPageInfo, MessagesResponse, MessagingBindingInfo, MessagingBindingStateRequest, MessagingBindingsResponse, MessagingChannel, MessagingChannelState, MessagingRuntimeState, MessagingRuntimeStatus, MessagingTestMessageResponse, ModelInfo, ModelOAuthCodeRequest, ModelOAuthCodeResponse, ModelOAuthErrorCode, ModelOAuthMode, ModelOAuthStartRequest, ModelOAuthStartResponse, ModelOAuthStatusResponse, ModelPricingDto, ModelProtocolDetectRequest, ModelProtocolDetectResponse, ModelProtocolProbeDto, ModelRefDto, ModelTestRequest, ModelTestResponse, ModelUpdateEntry, ModelVisionDetectRequest, ModelVisionDetectResponse, ModelVisionOutcome, ModelsResponse, ModelsUpdateRequest, PasswordChangeRequest, PendingFollowUpInfo, PendingSteeringInfo, PrefsResponse, ProjectCreateRequest, ProjectCreateResponse, ProjectRole, ProjectSummary, ProjectUpdateRequest, ProjectUpdateResponse, ProjectsResponse, ProtocolProbeOutcome, RecalledMessageResponse, RequestSpan, RetryNowResponse, ScheduleItem, ScheduleServerEvent, ScheduleStatus, ScheduleUpsertRequest, SchedulesResponse, ServerEvent, ServerSettings, ServerSettingsResponse, ServerSettingsUpdateRequest, SessionCategory, SessionCategoryCounts, SessionContextParts, SessionContextResponse, SessionCreateRequest, SessionCreateResponse, SessionForkRequest, SessionForkResponse, SessionInfo, SessionPatchRequest, SessionProcessInfo, SessionProcessesResponse, SessionResponse, SessionSource, SessionStatus, SessionTracesResponse, SessionsResponse, SkillArchiveInstallRequest, SkillGroupItem, SkillInstallRequest, SkillLibraryResponse, SkillMetadataItem, SteerRequest, SubagentMessageResponse, SubagentRuntimeInfo, TaskCreateRequest, TaskCreateResponse, TaskInputPart, TelegramBindingInfo, TelegramBindingPutRequest, TelegramBindingResponse, TelegramTestRequest, TelegramTestResponse, ToolCallSpan, TraceAnalysisResponse, TraceEventsResponse, TraceFileInfo, TraceImportRequest, TraceImportResponse, TraceModelSegment, TraceOtherSpan, TracePosition, TraceTaskStats, TraceToolSpan, UiPrefs, UpdateCheckResponse, UpdateRunResponse, UploadLimits, UsageAgentSeries, UsageBucket, UsageEntitySeriesCounts, UsageErrorCount, UsageErrorItem, UsageErrors, UsageErrorsPage, UsageGranularity, UsageGroupBy, UsageGroupRow, UsageModelSeries, UsageResponse, UsageSeriesPoint, UsageTrendPointInTrace, UserInfo, VaultEntryInfo, VaultEntryUpdate, VaultResponse, VaultUpdateRequest, VersionResponse, WorkspaceFileEntry, WorkspaceFilesResponse };
2984
+ export type { AdminPasswordResetRequest, AdminUserCreateRequest, AdminUserCreateResponse, AdminUsersResponse, AgentCompactionConfigDto, AgentConfigDto, AgentConfigResponse, AgentConfigUpdateRequest, AgentCreateRequest, AgentCreateResponse, AgentImportRequest, AgentImportResponse, AgentKernelUpdateResponse, AgentMemoryConfigDto, AgentModelConfigDto, AgentSchedulesConfigDto, AgentSkillsConfigDto, AgentSkillsResponse, AgentSummary, AgentTraceDateGroup, AgentTraceFileRef, AgentTraceSessionEntry, AgentTraceSessionFile, AgentTraceSessionGroup, AgentTracesResponse, AgentVaultConfigDto, AgentsResponse, ApprovalDecisionRequest, ApprovalMode, AuthLoginRequest, AuthResponse, BenchmarkCaseScore, BenchmarkCaseSummary, BenchmarkCasesResponse, BenchmarkEvaluation, BenchmarkRunScore, BenchmarkSummary, BenchmarksResponse, CaseMaterial, ChatDefaultsDto, CommandPolicyDto, CommandPolicyRuleDto, ContextToolShare, CredentialInfo, DefaultModelResponse, DefaultModelUpdateRequest, DesktopUpdateStatus, DesktopUpdateStatusResponse, DesktopUpdaterCommandMessage, DesktopUpdaterStatusMessage, DirEntryInfo, DirListResponse, DirectorySkillItem, DirectorySkillsResponse, DraftShortcut, EndpointModelListRequest, EndpointModelListResponse, ErrorBody, FeishuBindingInfo, FeishuBindingPutRequest, FeishuBindingResponse, FeishuTestRequest, FeishuTestResponse, FilesStatRequest, FilesStatResponse, GoalResponse, GoalServerEvent, GoalStateView, HistoryMessage, InstallResponse, MachineInfo, MachineInstallJob, MachinesResponse, McpServerTestResponse, MeResponse, MemberAddRequest, MemberAddResponse, MemberInfo, MembersResponse, MemoryFileInfo, MemoryFileResponse, MemoryFilesResponse, MemoryImportMode, MemoryImportRequest, MemoryImportResponse, MemoryOverviewResponse, MemoryScopeExport, MemoryScopeInfo, MemoryTransferFile, MessagesLiveTail, MessagesPageInfo, MessagesResponse, MessagingBindingCommon, MessagingBindingInfo, MessagingBindingStateRequest, MessagingBindingsResponse, MessagingChannel, MessagingChannelState, MessagingDeliveryError, MessagingDeliveryPatch, MessagingRuntimeState, MessagingRuntimeStatus, MessagingTestMessageResponse, ModelInfo, ModelOAuthCodeRequest, ModelOAuthCodeResponse, ModelOAuthErrorCode, ModelOAuthMode, ModelOAuthStartRequest, ModelOAuthStartResponse, ModelOAuthStatusResponse, ModelPricingDto, ModelProtocolDetectRequest, ModelProtocolDetectResponse, ModelProtocolProbeDto, ModelRefDto, ModelTestRequest, ModelTestResponse, ModelUpdateEntry, ModelVisionDetectRequest, ModelVisionDetectResponse, ModelVisionOutcome, ModelsResponse, ModelsUpdateRequest, PasswordChangeRequest, PendingFollowUpInfo, PendingSteeringInfo, PrefsResponse, ProjectCreateRequest, ProjectCreateResponse, ProjectRole, ProjectSummary, ProjectUpdateRequest, ProjectUpdateResponse, ProjectsResponse, ProtocolProbeOutcome, QQBindingInfo, QQBindingPutRequest, QQBindingResponse, QQScanPollResponse, QQScanStartResponse, QQTestRequest, QQTestResponse, RecalledMessageResponse, RequestSpan, RetryNowResponse, ScheduleItem, ScheduleServerEvent, ScheduleStatus, ScheduleUpsertRequest, SchedulesResponse, ServerEvent, ServerSettings, ServerSettingsResponse, ServerSettingsUpdateRequest, SessionCategory, SessionCategoryCounts, SessionContextParts, SessionContextResponse, SessionCreateRequest, SessionCreateResponse, SessionForkRequest, SessionForkResponse, SessionInfo, SessionPatchRequest, SessionProcessInfo, SessionProcessesResponse, SessionResponse, SessionSource, SessionStatus, SessionTracesResponse, SessionsResponse, SkillArchiveInstallRequest, SkillGroupItem, SkillInstallRequest, SkillLibraryResponse, SkillMetadataItem, SkillUpdateRef, SteerRequest, SubagentMessageResponse, SubagentRuntimeInfo, TaskCreateRequest, TaskCreateResponse, TaskInputPart, TelegramBindingInfo, TelegramBindingPutRequest, TelegramBindingResponse, TelegramTestRequest, TelegramTestResponse, ToolCallSpan, TraceAnalysisResponse, TraceEventsResponse, TraceFileInfo, TraceImportRequest, TraceImportResponse, TraceModelSegment, TraceOtherSpan, TracePosition, TraceTaskStats, TraceToolSpan, UiPrefs, UpdateCheckResponse, UpdateRunResponse, UploadLimits, UsageAgentSeries, UsageBucket, UsageEntitySeriesCounts, UsageErrorCount, UsageErrorItem, UsageErrorKind, UsageErrors, UsageErrorsClearResponse, UsageErrorsPage, UsageGranularity, UsageGroupBy, UsageGroupRow, UsageModelSeries, UsageModelTotal, UsageModelTotals, UsageResponse, UsageSeriesPoint, UsageTrendPointInTrace, UserInfo, VaultEntryInfo, VaultEntryUpdate, VaultResponse, VaultUpdateRequest, VersionResponse, WeChatBindingInfo, WeChatBindingPutRequest, WeChatBindingResponse, WeChatScanPollResponse, WeChatScanStartResponse, WeChatScanStatus, WeChatScanVerifyRequest, WeChatTestResponse, WorkspaceFileEntry, WorkspaceFilesResponse };