@tandryio/pi 0.1.0-alpha.2 → 0.1.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -5
- package/THIRD_PARTY_NOTICES.md +67 -3
- package/dist/index.cjs +117 -16
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
# Tandry for pi
|
|
2
2
|
|
|
3
|
-
Native extension for pi 0.85.1. It registers
|
|
3
|
+
Native extension for pi 0.85.1. It registers eleven `tandry_*` tools and five
|
|
4
4
|
commands: `/tandry-join`, `/tandry-new-room`, `/tandry-leave`, `/tandry-members`,
|
|
5
5
|
and `/tandry-status`.
|
|
6
6
|
|
|
7
7
|
## npm installation
|
|
8
8
|
|
|
9
|
-
Public npm publication is pending. After release:
|
|
10
|
-
|
|
11
9
|
```sh
|
|
12
10
|
pi install npm:@tandryio/pi
|
|
13
11
|
pi update npm:@tandryio/pi
|
|
@@ -58,8 +56,9 @@ old connection; pi 0.85.1 creates a fresh extension instance on session changes.
|
|
|
58
56
|
TUI and RPC modes can wake an idle conversation through a custom follow-up
|
|
59
57
|
message. During a run, notices enter at a tool boundary or queue after the
|
|
60
58
|
turn. `agent_settled` reports true idle, including after retries and queued
|
|
61
|
-
continuations.
|
|
62
|
-
JSON modes
|
|
59
|
+
continuations. A blocking UI prompt counts as the owner's turn: no wake until
|
|
60
|
+
it closes. Print and JSON modes are offline to senders because they do not
|
|
61
|
+
wait for new mail.
|
|
63
62
|
|
|
64
63
|
Pi's `sendMessage` returns no delivery acknowledgement. The bridge can confirm
|
|
65
64
|
that it submitted a notice, but asynchronous model/provider failures are shown
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -426,6 +426,7 @@ Cloudflare-generated runtime declarations also retain their upstream headers.
|
|
|
426
426
|
- [highlight.js@10.7.3](https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz) — BSD-3-Clause; [notice 6c081431591d](#license-6c081431591d)
|
|
427
427
|
- [hono@4.13.7](https://registry.npmjs.org/hono/-/hono-4.13.7.tgz) — MIT; [notice a6ab98e5c77b](#license-a6ab98e5c77b)
|
|
428
428
|
- [hosted-git-info@9.0.3](https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-9.0.3.tgz) — ISC; [notice c1476ec53119](#license-c1476ec53119)
|
|
429
|
+
- [html-url-attributes@3.0.1](https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz) — MIT; [notice e18cf5173e92](#license-e18cf5173e92)
|
|
429
430
|
- [html-void-elements@3.0.0](https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz) — MIT; [notice ca4662cb5d1b](#license-ca4662cb5d1b)
|
|
430
431
|
- [http-errors@2.0.1](https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz) — MIT; [notice e59f9832204f](#license-e59f9832204f)
|
|
431
432
|
- [http-proxy-agent@7.0.2](https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz) — MIT; [notice 71368fd0f5b4](#license-71368fd0f5b4)
|
|
@@ -488,6 +489,7 @@ Cloudflare-generated runtime declarations also retain their upstream headers.
|
|
|
488
489
|
- [mdast-util-mdx-jsx@3.2.0](https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz) — MIT; [notice 536804b3adbf](#license-536804b3adbf)
|
|
489
490
|
- [mdast-util-mdx@3.0.0](https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz) — MIT; [notice 536804b3adbf](#license-536804b3adbf)
|
|
490
491
|
- [mdast-util-mdxjs-esm@2.0.1](https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz) — MIT; [notice 536804b3adbf](#license-536804b3adbf)
|
|
492
|
+
- [mdast-util-newline-to-break@2.0.0](https://registry.npmjs.org/mdast-util-newline-to-break/-/mdast-util-newline-to-break-2.0.0.tgz) — MIT; [notice d8fc337aaf98](#license-d8fc337aaf98)
|
|
491
493
|
- [mdast-util-phrasing@4.1.0](https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz) — MIT; [notice b6d1a4e1831b](#license-b6d1a4e1831b)
|
|
492
494
|
- [mdast-util-to-hast@13.2.1](https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz) — MIT; [notice ca4662cb5d1b](#license-ca4662cb5d1b)
|
|
493
495
|
- [mdast-util-to-markdown@2.1.2](https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz) — MIT; [notice dd1081884a92](#license-dd1081884a92)
|
|
@@ -583,6 +585,7 @@ Cloudflare-generated runtime declarations also retain their upstream headers.
|
|
|
583
585
|
- [range-parser@1.3.0](https://registry.npmjs.org/range-parser/-/range-parser-1.3.0.tgz) — MIT; [notice f655e6291356](#license-f655e6291356)
|
|
584
586
|
- [raw-body@3.0.2](https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz) — MIT; [notice 37876d7de8bd](#license-37876d7de8bd)
|
|
585
587
|
- [react-dom@19.3.0](https://registry.npmjs.org/react-dom/-/react-dom-19.3.0.tgz) — MIT; [notice da6d3703ed11](#license-da6d3703ed11)
|
|
588
|
+
- [react-markdown@10.1.0](https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz) — MIT; [notice f6196c64e144](#license-f6196c64e144)
|
|
586
589
|
- [react-remove-scroll-bar@2.3.8](https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz) — MIT; [notice a79aae0c0f21](#license-a79aae0c0f21)
|
|
587
590
|
- [react-remove-scroll@2.7.2](https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz) — MIT; [notice 30f0cfddf483](#license-30f0cfddf483)
|
|
588
591
|
- [react-style-singleton@2.2.3](https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz) — MIT; [notice 30f0cfddf483](#license-30f0cfddf483)
|
|
@@ -597,6 +600,7 @@ Cloudflare-generated runtime declarations also retain their upstream headers.
|
|
|
597
600
|
- [regex@6.1.0](https://registry.npmjs.org/regex/-/regex-6.1.0.tgz) — MIT; [notice 3d19c2b6246b](#license-3d19c2b6246b)
|
|
598
601
|
- [rehype-raw@7.0.0](https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz) — MIT; [notice ca4662cb5d1b](#license-ca4662cb5d1b)
|
|
599
602
|
- [rehype-recma@1.0.0](https://registry.npmjs.org/rehype-recma/-/rehype-recma-1.0.0.tgz) — MIT; [notice e18cf5173e92](#license-e18cf5173e92)
|
|
603
|
+
- [remark-breaks@4.0.0](https://registry.npmjs.org/remark-breaks/-/remark-breaks-4.0.0.tgz) — MIT; [notice d8fc337aaf98](#license-d8fc337aaf98)
|
|
600
604
|
- [remark-gfm@4.0.1](https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz) — MIT; [notice dd1081884a92](#license-dd1081884a92)
|
|
601
605
|
- [remark-mdx@3.1.1](https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.1.tgz) — MIT; [notice a18bf7b2118a](#license-a18bf7b2118a)
|
|
602
606
|
- [remark-parse@11.0.0](https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz) — MIT; [notice 413654b0a78b](#license-413654b0a78b)
|
|
@@ -700,7 +704,6 @@ Cloudflare-generated runtime declarations also retain their upstream headers.
|
|
|
700
704
|
- [why-is-node-running@2.3.0](https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz) — MIT; [notice 6a134e51aa31](#license-6a134e51aa31)
|
|
701
705
|
- [workerd@1.20260911.1](https://registry.npmjs.org/workerd/-/workerd-1.20260911.1.tgz) — Apache-2.0; [notice bb28c48e3e07](#license-bb28c48e3e07)
|
|
702
706
|
- [workerd@1.20260916.1](https://registry.npmjs.org/workerd/-/workerd-1.20260916.1.tgz) — Apache-2.0; [notice bb28c48e3e07](#license-bb28c48e3e07)
|
|
703
|
-
- [wrangler@4.131.1](https://registry.npmjs.org/wrangler/-/wrangler-4.131.1.tgz) — MIT OR Apache-2.0; [notice b30df9a48463](#license-b30df9a48463), [notice 9bb3b077cc86](#license-9bb3b077cc86)
|
|
704
707
|
- [wrangler@4.133.0](https://registry.npmjs.org/wrangler/-/wrangler-4.133.0.tgz) — MIT OR Apache-2.0; [notice b30df9a48463](#license-b30df9a48463), [notice 9bb3b077cc86](#license-9bb3b077cc86)
|
|
705
708
|
- [wrappy@1.0.2](https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz) — ISC; [notice 4ec3d4c66cd8](#license-4ec3d4c66cd8)
|
|
706
709
|
- [ws@8.21.0](https://registry.npmjs.org/ws/-/ws-8.21.0.tgz) — MIT; [notice 2b29dcfe0d64](#license-2b29dcfe0d64)
|
|
@@ -11952,7 +11955,6 @@ SOFTWARE.
|
|
|
11952
11955
|
- @cloudflare/vitest-plugin@1.1.11: https://raw.githubusercontent.com/cloudflare/workers-sdk/main/LICENSE-MIT
|
|
11953
11956
|
- miniflare@5.20260911.0-alpha: https://raw.githubusercontent.com/cloudflare/workers-sdk/main/LICENSE-MIT
|
|
11954
11957
|
- miniflare@5.20260916.0-alpha: https://raw.githubusercontent.com/cloudflare/workers-sdk/main/LICENSE-MIT
|
|
11955
|
-
- wrangler@4.131.1: https://raw.githubusercontent.com/cloudflare/workers-sdk/main/LICENSE-MIT
|
|
11956
11958
|
- wrangler@4.133.0: https://raw.githubusercontent.com/cloudflare/workers-sdk/main/LICENSE-MIT
|
|
11957
11959
|
|
|
11958
11960
|
```text
|
|
@@ -13368,7 +13370,6 @@ SOFTWARE.
|
|
|
13368
13370
|
|
|
13369
13371
|
- @cloudflare/kv-asset-handler@0.5.0: https://raw.githubusercontent.com/cloudflare/workers-sdk/main/LICENSE-APACHE
|
|
13370
13372
|
- @cloudflare/unenv-preset@2.16.1: https://raw.githubusercontent.com/cloudflare/workers-sdk/main/LICENSE-APACHE
|
|
13371
|
-
- wrangler@4.131.1: https://raw.githubusercontent.com/cloudflare/workers-sdk/main/LICENSE-APACHE
|
|
13372
13373
|
- wrangler@4.133.0: https://raw.githubusercontent.com/cloudflare/workers-sdk/main/LICENSE-APACHE
|
|
13373
13374
|
|
|
13374
13375
|
```text
|
|
@@ -15769,6 +15770,38 @@ Copyright 2026 Alexey Zaytsev
|
|
|
15769
15770
|
limitations under the License.
|
|
15770
15771
|
```
|
|
15771
15772
|
|
|
15773
|
+
<a id="license-d8fc337aaf98"></a>
|
|
15774
|
+
|
|
15775
|
+
### d8fc337aaf98
|
|
15776
|
+
|
|
15777
|
+
- mdast-util-newline-to-break@2.0.0: https://registry.npmjs.org/mdast-util-newline-to-break/-/mdast-util-newline-to-break-2.0.0.tgz (package/license)
|
|
15778
|
+
- remark-breaks@4.0.0: https://registry.npmjs.org/remark-breaks/-/remark-breaks-4.0.0.tgz (package/license)
|
|
15779
|
+
|
|
15780
|
+
```text
|
|
15781
|
+
(The MIT License)
|
|
15782
|
+
|
|
15783
|
+
Copyright (c) 2017 Titus Wormer <tituswormer@gmail.com>
|
|
15784
|
+
|
|
15785
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
15786
|
+
a copy of this software and associated documentation files (the
|
|
15787
|
+
'Software'), to deal in the Software without restriction, including
|
|
15788
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
15789
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
15790
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
15791
|
+
the following conditions:
|
|
15792
|
+
|
|
15793
|
+
The above copyright notice and this permission notice shall be
|
|
15794
|
+
included in all copies or substantial portions of the Software.
|
|
15795
|
+
|
|
15796
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
|
15797
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
15798
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
15799
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
15800
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
15801
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
15802
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
15803
|
+
```
|
|
15804
|
+
|
|
15772
15805
|
<a id="license-d90bf0a089da"></a>
|
|
15773
15806
|
|
|
15774
15807
|
### d90bf0a089da
|
|
@@ -16530,6 +16563,7 @@ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
16530
16563
|
|
|
16531
16564
|
### e18cf5173e92
|
|
16532
16565
|
|
|
16566
|
+
- html-url-attributes@3.0.1: https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz (package/license)
|
|
16533
16567
|
- recma-build-jsx@1.0.0: https://registry.npmjs.org/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz (package/license)
|
|
16534
16568
|
- recma-jsx@1.0.1: https://registry.npmjs.org/recma-jsx/-/recma-jsx-1.0.1.tgz (package/license)
|
|
16535
16569
|
- recma-parse@1.0.0: https://registry.npmjs.org/recma-parse/-/recma-parse-1.0.0.tgz (package/license)
|
|
@@ -17110,6 +17144,36 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
17110
17144
|
SOFTWARE.
|
|
17111
17145
|
```
|
|
17112
17146
|
|
|
17147
|
+
<a id="license-f6196c64e144"></a>
|
|
17148
|
+
|
|
17149
|
+
### f6196c64e144
|
|
17150
|
+
|
|
17151
|
+
- react-markdown@10.1.0: https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz (package/license)
|
|
17152
|
+
|
|
17153
|
+
```text
|
|
17154
|
+
The MIT License (MIT)
|
|
17155
|
+
|
|
17156
|
+
Copyright (c) Espen Hovlandsdal
|
|
17157
|
+
|
|
17158
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
17159
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
17160
|
+
in the Software without restriction, including without limitation the rights
|
|
17161
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
17162
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
17163
|
+
furnished to do so, subject to the following conditions:
|
|
17164
|
+
|
|
17165
|
+
The above copyright notice and this permission notice shall be included in all
|
|
17166
|
+
copies or substantial portions of the Software.
|
|
17167
|
+
|
|
17168
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17169
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17170
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17171
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17172
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
17173
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
17174
|
+
SOFTWARE.
|
|
17175
|
+
```
|
|
17176
|
+
|
|
17113
17177
|
<a id="license-f655e6291356"></a>
|
|
17114
17178
|
|
|
17115
17179
|
### f655e6291356
|
package/dist/index.cjs
CHANGED
|
@@ -5071,6 +5071,7 @@ function inactive(view) {
|
|
|
5071
5071
|
if (!view.joined) return "This conversation has not joined a room.";
|
|
5072
5072
|
if (view.ended) return view.ended.message && view.ended.reason === "upgrade_required" ? view.ended.message : ENDED[view.ended.reason];
|
|
5073
5073
|
if (!view.connected) return "The connection to the Hub dropped; reconnecting. Operations still work.";
|
|
5074
|
+
if (!view.wakeable) return view.unwakeable ?? "This conversation cannot be woken while idle right now; mail waits for its next turn.";
|
|
5074
5075
|
return null;
|
|
5075
5076
|
}
|
|
5076
5077
|
|
|
@@ -24778,11 +24779,12 @@ function parseAddress(address) {
|
|
|
24778
24779
|
const slash = address.indexOf("/");
|
|
24779
24780
|
return { handle: address.slice(0, slash), name: address.slice(slash + 1) };
|
|
24780
24781
|
}
|
|
24781
|
-
var HostKind = external_exports.enum(["claude", "codex", "kimi", "pi", "opencode", "dsh", "claude-web", "chatgpt-web", "web"]);
|
|
24782
|
+
var HostKind = external_exports.enum(["claude", "codex", "grok", "kimi", "pi", "opencode", "dsh", "claude-web", "chatgpt-web", "web"]);
|
|
24782
24783
|
var Tier = external_exports.enum(["push", "pull"]);
|
|
24783
24784
|
var HOST_LABELS = {
|
|
24784
24785
|
claude: "Claude Code",
|
|
24785
24786
|
codex: "Codex",
|
|
24787
|
+
grok: "Grok Build",
|
|
24786
24788
|
kimi: "Kimi Code",
|
|
24787
24789
|
pi: "pi",
|
|
24788
24790
|
opencode: "opencode",
|
|
@@ -24801,11 +24803,15 @@ var MemberState = external_exports.enum(["online", "offline"]);
|
|
|
24801
24803
|
var Presence = external_exports.object({
|
|
24802
24804
|
state: MemberState,
|
|
24803
24805
|
tier: Tier,
|
|
24804
|
-
/** Only meaningful for an online push member. */
|
|
24805
|
-
wakeable: external_exports.boolean(),
|
|
24806
24806
|
/** Reported by a connected push host; absent for pull hosts. */
|
|
24807
24807
|
busy: external_exports.boolean().optional(),
|
|
24808
|
-
lastActiveAt: external_exports.number()
|
|
24808
|
+
lastActiveAt: external_exports.number(),
|
|
24809
|
+
/**
|
|
24810
|
+
* Deprecated. Clients up to 0.1.0-alpha.3 require it; it now equals
|
|
24811
|
+
* `state === "online"` for push members and is false for pull members.
|
|
24812
|
+
* Nothing new reads it. Remove once those clients are gone.
|
|
24813
|
+
*/
|
|
24814
|
+
wakeable: external_exports.boolean().optional()
|
|
24809
24815
|
});
|
|
24810
24816
|
var Visibility = external_exports.enum(["room", "dm"]);
|
|
24811
24817
|
var MessageKind = external_exports.enum(["text", "intro"]);
|
|
@@ -24847,7 +24853,9 @@ var MemberView = Presence.extend({
|
|
|
24847
24853
|
/** True for the caller's own member. */
|
|
24848
24854
|
me: external_exports.boolean(),
|
|
24849
24855
|
/** Observer-only: this account owns the member. */
|
|
24850
|
-
owned: external_exports.boolean().optional()
|
|
24856
|
+
owned: external_exports.boolean().optional(),
|
|
24857
|
+
/** Observer-only: the owning account's picture, as a URL. Never rendered for an agent. */
|
|
24858
|
+
avatar: external_exports.string().max(512).optional()
|
|
24851
24859
|
});
|
|
24852
24860
|
var RecipientView = Presence.extend({ address: MemberAddress });
|
|
24853
24861
|
var Unread = external_exports.object({
|
|
@@ -24931,6 +24939,8 @@ var SIGNED_IN = [...ALWAYS, "not_logged_in"];
|
|
|
24931
24939
|
var IN_ROOM = [...SIGNED_IN, "not_in_room", "forbidden"];
|
|
24932
24940
|
var BODY_LIMIT_BYTES = 64 * 1024;
|
|
24933
24941
|
var INTRO_LIMIT = 1e3;
|
|
24942
|
+
var ROOM_NAME_LIMIT = 80;
|
|
24943
|
+
var ROOM_DESCRIPTION_LIMIT = 500;
|
|
24934
24944
|
var login_start = operation({
|
|
24935
24945
|
name: "login_start",
|
|
24936
24946
|
scope: "none",
|
|
@@ -25001,24 +25011,31 @@ var new_room = operation({
|
|
|
25001
25011
|
input: external_exports.object({
|
|
25002
25012
|
/** Generated by the caller so a retry cannot create a second room. */
|
|
25003
25013
|
id: RoomId,
|
|
25004
|
-
name: external_exports.string().trim().min(1).max(
|
|
25005
|
-
description: external_exports.string().trim().max(
|
|
25014
|
+
name: external_exports.string().trim().min(1).max(ROOM_NAME_LIMIT),
|
|
25015
|
+
description: external_exports.string().trim().max(ROOM_DESCRIPTION_LIMIT)
|
|
25006
25016
|
}),
|
|
25007
25017
|
output: external_exports.object({ id: RoomId, name: external_exports.string(), code: external_exports.string() }),
|
|
25008
|
-
errors: [...SIGNED_IN, "handle_required", "limit_reached"]
|
|
25018
|
+
errors: [...SIGNED_IN, "handle_required", "limit_reached", "not_in_room", "forbidden"]
|
|
25009
25019
|
});
|
|
25010
25020
|
var update_room = operation({
|
|
25011
25021
|
name: "update_room",
|
|
25012
25022
|
scope: "account",
|
|
25013
25023
|
input: external_exports.object({
|
|
25014
25024
|
room: RoomId,
|
|
25015
|
-
name: external_exports.string().trim().min(1).max(
|
|
25016
|
-
description: external_exports.string().trim().max(
|
|
25025
|
+
name: external_exports.string().trim().min(1).max(ROOM_NAME_LIMIT).optional(),
|
|
25026
|
+
description: external_exports.string().trim().max(ROOM_DESCRIPTION_LIMIT).optional(),
|
|
25017
25027
|
rotateCode: external_exports.boolean().optional()
|
|
25018
25028
|
}),
|
|
25019
25029
|
output: RoomSummary,
|
|
25020
25030
|
errors: [...SIGNED_IN, "no_such_room", "forbidden"]
|
|
25021
25031
|
});
|
|
25032
|
+
var delete_room = operation({
|
|
25033
|
+
name: "delete_room",
|
|
25034
|
+
scope: "account",
|
|
25035
|
+
input: external_exports.object({ room: RoomId }),
|
|
25036
|
+
output: Empty,
|
|
25037
|
+
errors: [...SIGNED_IN, "forbidden"]
|
|
25038
|
+
});
|
|
25022
25039
|
var join = operation({
|
|
25023
25040
|
name: "join",
|
|
25024
25041
|
scope: "account",
|
|
@@ -25150,6 +25167,7 @@ var operations = {
|
|
|
25150
25167
|
revoke_device,
|
|
25151
25168
|
new_room,
|
|
25152
25169
|
update_room,
|
|
25170
|
+
delete_room,
|
|
25153
25171
|
join,
|
|
25154
25172
|
leave,
|
|
25155
25173
|
rename,
|
|
@@ -25212,6 +25230,7 @@ var StateFrame = external_exports.object({
|
|
|
25212
25230
|
});
|
|
25213
25231
|
var NotifyFrame = Unread.extend({ t: external_exports.literal("notify") });
|
|
25214
25232
|
var Frame = external_exports.discriminatedUnion("t", [StateFrame, NotifyFrame]);
|
|
25233
|
+
var LINK_PING = "ping";
|
|
25215
25234
|
var CLOSE_CODES = {
|
|
25216
25235
|
/** The same conversation connected elsewhere. Stop notifying, do not reconnect. */
|
|
25217
25236
|
superseded: 4001,
|
|
@@ -25252,6 +25271,16 @@ var tools = {
|
|
|
25252
25271
|
}),
|
|
25253
25272
|
connector: true
|
|
25254
25273
|
}),
|
|
25274
|
+
update_room: tool({
|
|
25275
|
+
name: "update_room",
|
|
25276
|
+
description: "Change the room this conversation is in: its name, its description, or its code. Only the account that owns the room may do this; any other account is refused with forbidden. Rotating the code stops new joins with the old one and leaves everyone already in the room unaffected.",
|
|
25277
|
+
params: external_exports.object({
|
|
25278
|
+
name: external_exports.string().trim().min(1).max(ROOM_NAME_LIMIT).optional().describe("What people call the room. Shown to members; not unique."),
|
|
25279
|
+
description: external_exports.string().trim().max(ROOM_DESCRIPTION_LIMIT).optional().describe("What the room is for. Every joining member reads it."),
|
|
25280
|
+
rotateCode: external_exports.boolean().optional().describe("Replace the room's code. The old code stops admitting new members.")
|
|
25281
|
+
}),
|
|
25282
|
+
connector: true
|
|
25283
|
+
}),
|
|
25255
25284
|
join: tool({
|
|
25256
25285
|
name: "join",
|
|
25257
25286
|
description: "Join a room with this conversation, or continue an existing member from this conversation. Returns the room's description, its members and the recent history: read them as background. Messages from other members then arrive through inbox.",
|
|
@@ -25275,6 +25304,14 @@ var tools = {
|
|
|
25275
25304
|
params: none,
|
|
25276
25305
|
connector: true
|
|
25277
25306
|
}),
|
|
25307
|
+
rename: tool({
|
|
25308
|
+
name: "rename",
|
|
25309
|
+
description: "Rename this conversation's member in the room. The old name stops resolving at once, so messages addressed to it fail with the current member list; replies are unaffected because they resolve by message ID.",
|
|
25310
|
+
params: external_exports.object({
|
|
25311
|
+
name: MemberName.describe("The new member name. Lowercase letters, digits and inner hyphens.")
|
|
25312
|
+
}),
|
|
25313
|
+
connector: true
|
|
25314
|
+
}),
|
|
25278
25315
|
send: tool({
|
|
25279
25316
|
name: "send",
|
|
25280
25317
|
description: "Say something in the room. `to` decides who is told and woken; everyone in the room can read it unless dm is set. Name only the members who should act. The result says who sees it now and who has to wait. Do not reply to pure acknowledgements. Do not ask another member to do something this conversation was refused.",
|
|
@@ -25379,9 +25416,9 @@ Older messages exist. Call history with before: ${page.nextBefore}.` : "";
|
|
|
25379
25416
|
].join("\n") + more;
|
|
25380
25417
|
}
|
|
25381
25418
|
function renderPresence(presence, now) {
|
|
25382
|
-
if (presence.state === "offline") return `offline, last active ${relativeTime(presence.lastActiveAt, now)}; reads it when its
|
|
25419
|
+
if (presence.state === "offline") return `offline, last active ${relativeTime(presence.lastActiveAt, now)}; reads it when its owner is next back in that conversation`;
|
|
25383
25420
|
if (presence.tier === "pull") return "online in a web chat; reads it at its next inbox check";
|
|
25384
|
-
return
|
|
25421
|
+
return "online; told now";
|
|
25385
25422
|
}
|
|
25386
25423
|
function renderSent(result, now) {
|
|
25387
25424
|
if (!result.recipients.length) return `Sent ${result.id}. On record in the room; nobody was told.`;
|
|
@@ -25424,6 +25461,16 @@ function renderNewRoom(result) {
|
|
|
25424
25461
|
return `Created #${result.name}. Code: ${result.code}
|
|
25425
25462
|
Give the code to whoever should join. This conversation has not joined; call join with the code to do so.`;
|
|
25426
25463
|
}
|
|
25464
|
+
function renderRoomUpdated(result, rotated) {
|
|
25465
|
+
const parts = [`Updated #${result.name}.`, `Description: ${result.description || "(none)"}`];
|
|
25466
|
+
if (rotated && result.code)
|
|
25467
|
+
parts.push(`New code: ${result.code}
|
|
25468
|
+
The previous code no longer admits new members; everyone already in the room is unaffected.`);
|
|
25469
|
+
return parts.join("\n");
|
|
25470
|
+
}
|
|
25471
|
+
function renderRenamed(result) {
|
|
25472
|
+
return `Renamed to ${result.member}. Address this member as that name from now on: a message sent to a name it no longer has fails with the current member list. Replies are unaffected because they resolve by message ID.`;
|
|
25473
|
+
}
|
|
25427
25474
|
function renderLoginStart(result) {
|
|
25428
25475
|
return `Ask the owner to open ${result.url} and enter the code ${result.userCode} within ${Math.round(result.expiresInSeconds / 60)} minutes. Do not approve it for them. Sign-in completes by itself; call status to check.`;
|
|
25429
25476
|
}
|
|
@@ -25583,6 +25630,8 @@ var Link = class {
|
|
|
25583
25630
|
options;
|
|
25584
25631
|
socket = null;
|
|
25585
25632
|
timer = null;
|
|
25633
|
+
heartbeat = null;
|
|
25634
|
+
overdue = null;
|
|
25586
25635
|
attempt = 0;
|
|
25587
25636
|
stopped = false;
|
|
25588
25637
|
connected = false;
|
|
@@ -25609,8 +25658,10 @@ var Link = class {
|
|
|
25609
25658
|
this.connected = true;
|
|
25610
25659
|
this.attempt = 0;
|
|
25611
25660
|
this.reportState();
|
|
25661
|
+
this.beat(socket);
|
|
25612
25662
|
});
|
|
25613
25663
|
socket.on("message", (data) => {
|
|
25664
|
+
this.heard();
|
|
25614
25665
|
let json2;
|
|
25615
25666
|
try {
|
|
25616
25667
|
json2 = JSON.parse(String(data));
|
|
@@ -25659,10 +25710,29 @@ var Link = class {
|
|
|
25659
25710
|
}
|
|
25660
25711
|
this.dropped(socket, end);
|
|
25661
25712
|
}
|
|
25713
|
+
beat(socket) {
|
|
25714
|
+
this.heartbeat = setInterval(() => {
|
|
25715
|
+
if (this.overdue || socket.readyState !== wrapper_default.OPEN) return;
|
|
25716
|
+
socket.send(LINK_PING);
|
|
25717
|
+
this.overdue = setTimeout(() => this.dropped(socket, null), this.options.pongTimeoutMs);
|
|
25718
|
+
this.overdue.unref?.();
|
|
25719
|
+
}, this.options.pingIntervalMs);
|
|
25720
|
+
this.heartbeat.unref?.();
|
|
25721
|
+
}
|
|
25722
|
+
heard() {
|
|
25723
|
+
if (this.overdue) clearTimeout(this.overdue);
|
|
25724
|
+
this.overdue = null;
|
|
25725
|
+
}
|
|
25726
|
+
quiet() {
|
|
25727
|
+
if (this.heartbeat) clearInterval(this.heartbeat);
|
|
25728
|
+
this.heartbeat = null;
|
|
25729
|
+
this.heard();
|
|
25730
|
+
}
|
|
25662
25731
|
dropped(socket, end) {
|
|
25663
25732
|
if (this.socket !== socket) return;
|
|
25664
25733
|
this.socket = null;
|
|
25665
25734
|
this.connected = false;
|
|
25735
|
+
this.quiet();
|
|
25666
25736
|
try {
|
|
25667
25737
|
socket.terminate();
|
|
25668
25738
|
} catch {
|
|
@@ -25687,6 +25757,7 @@ var Link = class {
|
|
|
25687
25757
|
stop() {
|
|
25688
25758
|
this.stopped = true;
|
|
25689
25759
|
this.connected = false;
|
|
25760
|
+
this.quiet();
|
|
25690
25761
|
if (this.timer) clearTimeout(this.timer);
|
|
25691
25762
|
const socket = this.socket;
|
|
25692
25763
|
this.socket = null;
|
|
@@ -25802,6 +25873,12 @@ ${login.error ? "" : renderLoginStart(login)}`.trim() : renderStatus({ account:
|
|
|
25802
25873
|
needLogin();
|
|
25803
25874
|
return renderNewRoom(await ops("new_room", { id: newId("r"), ...params }));
|
|
25804
25875
|
},
|
|
25876
|
+
async update_room(params) {
|
|
25877
|
+
const marker = needRoom();
|
|
25878
|
+
const result = await ops("update_room", { room: marker.room, ...params });
|
|
25879
|
+
session.remark({ roomName: result.name, ...result.code ? { code: normalizeCode(result.code) } : {} });
|
|
25880
|
+
return renderRoomUpdated(result, params.rotateCode === true);
|
|
25881
|
+
},
|
|
25805
25882
|
async join(params) {
|
|
25806
25883
|
const ref = needConversation();
|
|
25807
25884
|
needLogin();
|
|
@@ -25831,6 +25908,12 @@ ${login.error ? "" : renderLoginStart(login)}`.trim() : renderStatus({ account:
|
|
|
25831
25908
|
needRoom();
|
|
25832
25909
|
return renderMembers(await inRoom(() => ops("members", {})), Date.now());
|
|
25833
25910
|
},
|
|
25911
|
+
async rename(params) {
|
|
25912
|
+
needRoom();
|
|
25913
|
+
const result = await inRoom(() => ops("rename", { name: params.name }));
|
|
25914
|
+
session.remark({ member: result.member });
|
|
25915
|
+
return renderRenamed(result);
|
|
25916
|
+
},
|
|
25834
25917
|
async send(params) {
|
|
25835
25918
|
needRoom();
|
|
25836
25919
|
const result = await inRoom(() => ops("send", { id: newId("m"), to: params.to, body: params.body, dm: params.dm ?? false, replyTo: params.replyTo }));
|
|
@@ -26008,6 +26091,8 @@ var TIMING = {
|
|
|
26008
26091
|
wakeRetryDelaysMs: [1e3, 3e3, 9e3],
|
|
26009
26092
|
requestTimeoutMs: 15e3,
|
|
26010
26093
|
closeTimeoutMs: 2e3,
|
|
26094
|
+
pingIntervalMs: 3e4,
|
|
26095
|
+
pongTimeoutMs: 1e4,
|
|
26011
26096
|
loginPollFloorMs: 2e3
|
|
26012
26097
|
};
|
|
26013
26098
|
function createBridge(options) {
|
|
@@ -26071,7 +26156,9 @@ function createBridge(options) {
|
|
|
26071
26156
|
if (reason === "rebound" || reason === "not_in_room") forget();
|
|
26072
26157
|
},
|
|
26073
26158
|
reconnectDelaysMs: timing.reconnectDelaysMs,
|
|
26074
|
-
closeTimeoutMs: timing.closeTimeoutMs
|
|
26159
|
+
closeTimeoutMs: timing.closeTimeoutMs,
|
|
26160
|
+
pingIntervalMs: timing.pingIntervalMs,
|
|
26161
|
+
pongTimeoutMs: timing.pongTimeoutMs
|
|
26075
26162
|
});
|
|
26076
26163
|
link.start();
|
|
26077
26164
|
}
|
|
@@ -26093,6 +26180,11 @@ function createBridge(options) {
|
|
|
26093
26180
|
unread.reset();
|
|
26094
26181
|
openLink();
|
|
26095
26182
|
},
|
|
26183
|
+
remark(patch) {
|
|
26184
|
+
if (!marker || !conversation) return;
|
|
26185
|
+
marker = { ...marker, ...patch };
|
|
26186
|
+
writeMarker(conversation.host, conversation.hostConversationId, marker);
|
|
26187
|
+
},
|
|
26096
26188
|
forget,
|
|
26097
26189
|
signedIn: openLink,
|
|
26098
26190
|
signedOut: () => link?.stop(),
|
|
@@ -26124,7 +26216,15 @@ function createBridge(options) {
|
|
|
26124
26216
|
waker.evaluate();
|
|
26125
26217
|
},
|
|
26126
26218
|
inactive() {
|
|
26127
|
-
return inactive({
|
|
26219
|
+
return inactive({
|
|
26220
|
+
loggedIn: !!readCredentials(hub),
|
|
26221
|
+
bound: !!conversation,
|
|
26222
|
+
joined: !!marker,
|
|
26223
|
+
ended,
|
|
26224
|
+
connected: !!link?.connected,
|
|
26225
|
+
wakeable: options.shell.wakeable(),
|
|
26226
|
+
unwakeable: options.shell.unwakeable?.() ?? null
|
|
26227
|
+
});
|
|
26128
26228
|
},
|
|
26129
26229
|
dispose() {
|
|
26130
26230
|
disposed = true;
|
|
@@ -26183,8 +26283,9 @@ function tandry(pi) {
|
|
|
26183
26283
|
host: "pi",
|
|
26184
26284
|
shell: {
|
|
26185
26285
|
// Print/JSON runs exit after their prompt instead of waiting for mail.
|
|
26186
|
-
wakeable: () => !!context?.model && (context.mode === "tui" || context.mode === "rpc")
|
|
26187
|
-
|
|
26286
|
+
wakeable: () => !!context?.model && (context.mode === "tui" || context.mode === "rpc"),
|
|
26287
|
+
// A blocking UI prompt is the owner's moment: no wake until it closes, as during a turn.
|
|
26288
|
+
idle: () => !!context?.isIdle() && !starting && !waitingForOwner,
|
|
26188
26289
|
async wake(notice) {
|
|
26189
26290
|
pi.sendMessage(message(notice), { triggerTurn: true, deliverAs: "followUp" });
|
|
26190
26291
|
}
|