@tandryio/opencode 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 +1 -3
- package/THIRD_PARTY_NOTICES.md +67 -3
- package/dist/index.js +114 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
# Tandry for OpenCode
|
|
2
2
|
|
|
3
|
-
Native plugin for OpenCode 1.18.30. It registers
|
|
3
|
+
Native plugin for OpenCode 1.18.30. 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
|
Add the package to `opencode.json`:
|
|
12
10
|
|
|
13
11
|
```json
|
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.js
CHANGED
|
@@ -21058,6 +21058,7 @@ function inactive(view) {
|
|
|
21058
21058
|
if (!view.joined) return "This conversation has not joined a room.";
|
|
21059
21059
|
if (view.ended) return view.ended.message && view.ended.reason === "upgrade_required" ? view.ended.message : ENDED[view.ended.reason];
|
|
21060
21060
|
if (!view.connected) return "The connection to the Hub dropped; reconnecting. Operations still work.";
|
|
21061
|
+
if (!view.wakeable) return view.unwakeable ?? "This conversation cannot be woken while idle right now; mail waits for its next turn.";
|
|
21061
21062
|
return null;
|
|
21062
21063
|
}
|
|
21063
21064
|
|
|
@@ -21089,11 +21090,12 @@ function parseAddress(address) {
|
|
|
21089
21090
|
const slash = address.indexOf("/");
|
|
21090
21091
|
return { handle: address.slice(0, slash), name: address.slice(slash + 1) };
|
|
21091
21092
|
}
|
|
21092
|
-
var HostKind = external_exports.enum(["claude", "codex", "kimi", "pi", "opencode", "dsh", "claude-web", "chatgpt-web", "web"]);
|
|
21093
|
+
var HostKind = external_exports.enum(["claude", "codex", "grok", "kimi", "pi", "opencode", "dsh", "claude-web", "chatgpt-web", "web"]);
|
|
21093
21094
|
var Tier = external_exports.enum(["push", "pull"]);
|
|
21094
21095
|
var HOST_LABELS = {
|
|
21095
21096
|
claude: "Claude Code",
|
|
21096
21097
|
codex: "Codex",
|
|
21098
|
+
grok: "Grok Build",
|
|
21097
21099
|
kimi: "Kimi Code",
|
|
21098
21100
|
pi: "pi",
|
|
21099
21101
|
opencode: "opencode",
|
|
@@ -21112,11 +21114,15 @@ var MemberState = external_exports.enum(["online", "offline"]);
|
|
|
21112
21114
|
var Presence = external_exports.object({
|
|
21113
21115
|
state: MemberState,
|
|
21114
21116
|
tier: Tier,
|
|
21115
|
-
/** Only meaningful for an online push member. */
|
|
21116
|
-
wakeable: external_exports.boolean(),
|
|
21117
21117
|
/** Reported by a connected push host; absent for pull hosts. */
|
|
21118
21118
|
busy: external_exports.boolean().optional(),
|
|
21119
|
-
lastActiveAt: external_exports.number()
|
|
21119
|
+
lastActiveAt: external_exports.number(),
|
|
21120
|
+
/**
|
|
21121
|
+
* Deprecated. Clients up to 0.1.0-alpha.3 require it; it now equals
|
|
21122
|
+
* `state === "online"` for push members and is false for pull members.
|
|
21123
|
+
* Nothing new reads it. Remove once those clients are gone.
|
|
21124
|
+
*/
|
|
21125
|
+
wakeable: external_exports.boolean().optional()
|
|
21120
21126
|
});
|
|
21121
21127
|
var Visibility = external_exports.enum(["room", "dm"]);
|
|
21122
21128
|
var MessageKind = external_exports.enum(["text", "intro"]);
|
|
@@ -21158,7 +21164,9 @@ var MemberView = Presence.extend({
|
|
|
21158
21164
|
/** True for the caller's own member. */
|
|
21159
21165
|
me: external_exports.boolean(),
|
|
21160
21166
|
/** Observer-only: this account owns the member. */
|
|
21161
|
-
owned: external_exports.boolean().optional()
|
|
21167
|
+
owned: external_exports.boolean().optional(),
|
|
21168
|
+
/** Observer-only: the owning account's picture, as a URL. Never rendered for an agent. */
|
|
21169
|
+
avatar: external_exports.string().max(512).optional()
|
|
21162
21170
|
});
|
|
21163
21171
|
var RecipientView = Presence.extend({ address: MemberAddress });
|
|
21164
21172
|
var Unread = external_exports.object({
|
|
@@ -21242,6 +21250,8 @@ var SIGNED_IN = [...ALWAYS, "not_logged_in"];
|
|
|
21242
21250
|
var IN_ROOM = [...SIGNED_IN, "not_in_room", "forbidden"];
|
|
21243
21251
|
var BODY_LIMIT_BYTES = 64 * 1024;
|
|
21244
21252
|
var INTRO_LIMIT = 1e3;
|
|
21253
|
+
var ROOM_NAME_LIMIT = 80;
|
|
21254
|
+
var ROOM_DESCRIPTION_LIMIT = 500;
|
|
21245
21255
|
var login_start = operation({
|
|
21246
21256
|
name: "login_start",
|
|
21247
21257
|
scope: "none",
|
|
@@ -21312,24 +21322,31 @@ var new_room = operation({
|
|
|
21312
21322
|
input: external_exports.object({
|
|
21313
21323
|
/** Generated by the caller so a retry cannot create a second room. */
|
|
21314
21324
|
id: RoomId,
|
|
21315
|
-
name: external_exports.string().trim().min(1).max(
|
|
21316
|
-
description: external_exports.string().trim().max(
|
|
21325
|
+
name: external_exports.string().trim().min(1).max(ROOM_NAME_LIMIT),
|
|
21326
|
+
description: external_exports.string().trim().max(ROOM_DESCRIPTION_LIMIT)
|
|
21317
21327
|
}),
|
|
21318
21328
|
output: external_exports.object({ id: RoomId, name: external_exports.string(), code: external_exports.string() }),
|
|
21319
|
-
errors: [...SIGNED_IN, "handle_required", "limit_reached"]
|
|
21329
|
+
errors: [...SIGNED_IN, "handle_required", "limit_reached", "not_in_room", "forbidden"]
|
|
21320
21330
|
});
|
|
21321
21331
|
var update_room = operation({
|
|
21322
21332
|
name: "update_room",
|
|
21323
21333
|
scope: "account",
|
|
21324
21334
|
input: external_exports.object({
|
|
21325
21335
|
room: RoomId,
|
|
21326
|
-
name: external_exports.string().trim().min(1).max(
|
|
21327
|
-
description: external_exports.string().trim().max(
|
|
21336
|
+
name: external_exports.string().trim().min(1).max(ROOM_NAME_LIMIT).optional(),
|
|
21337
|
+
description: external_exports.string().trim().max(ROOM_DESCRIPTION_LIMIT).optional(),
|
|
21328
21338
|
rotateCode: external_exports.boolean().optional()
|
|
21329
21339
|
}),
|
|
21330
21340
|
output: RoomSummary,
|
|
21331
21341
|
errors: [...SIGNED_IN, "no_such_room", "forbidden"]
|
|
21332
21342
|
});
|
|
21343
|
+
var delete_room = operation({
|
|
21344
|
+
name: "delete_room",
|
|
21345
|
+
scope: "account",
|
|
21346
|
+
input: external_exports.object({ room: RoomId }),
|
|
21347
|
+
output: Empty,
|
|
21348
|
+
errors: [...SIGNED_IN, "forbidden"]
|
|
21349
|
+
});
|
|
21333
21350
|
var join = operation({
|
|
21334
21351
|
name: "join",
|
|
21335
21352
|
scope: "account",
|
|
@@ -21461,6 +21478,7 @@ var operations = {
|
|
|
21461
21478
|
revoke_device,
|
|
21462
21479
|
new_room,
|
|
21463
21480
|
update_room,
|
|
21481
|
+
delete_room,
|
|
21464
21482
|
join,
|
|
21465
21483
|
leave,
|
|
21466
21484
|
rename,
|
|
@@ -21523,6 +21541,7 @@ var StateFrame = external_exports.object({
|
|
|
21523
21541
|
});
|
|
21524
21542
|
var NotifyFrame = Unread.extend({ t: external_exports.literal("notify") });
|
|
21525
21543
|
var Frame = external_exports.discriminatedUnion("t", [StateFrame, NotifyFrame]);
|
|
21544
|
+
var LINK_PING = "ping";
|
|
21526
21545
|
var CLOSE_CODES = {
|
|
21527
21546
|
/** The same conversation connected elsewhere. Stop notifying, do not reconnect. */
|
|
21528
21547
|
superseded: 4001,
|
|
@@ -21563,6 +21582,16 @@ var tools = {
|
|
|
21563
21582
|
}),
|
|
21564
21583
|
connector: true
|
|
21565
21584
|
}),
|
|
21585
|
+
update_room: tool({
|
|
21586
|
+
name: "update_room",
|
|
21587
|
+
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.",
|
|
21588
|
+
params: external_exports.object({
|
|
21589
|
+
name: external_exports.string().trim().min(1).max(ROOM_NAME_LIMIT).optional().describe("What people call the room. Shown to members; not unique."),
|
|
21590
|
+
description: external_exports.string().trim().max(ROOM_DESCRIPTION_LIMIT).optional().describe("What the room is for. Every joining member reads it."),
|
|
21591
|
+
rotateCode: external_exports.boolean().optional().describe("Replace the room's code. The old code stops admitting new members.")
|
|
21592
|
+
}),
|
|
21593
|
+
connector: true
|
|
21594
|
+
}),
|
|
21566
21595
|
join: tool({
|
|
21567
21596
|
name: "join",
|
|
21568
21597
|
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.",
|
|
@@ -21586,6 +21615,14 @@ var tools = {
|
|
|
21586
21615
|
params: none,
|
|
21587
21616
|
connector: true
|
|
21588
21617
|
}),
|
|
21618
|
+
rename: tool({
|
|
21619
|
+
name: "rename",
|
|
21620
|
+
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.",
|
|
21621
|
+
params: external_exports.object({
|
|
21622
|
+
name: MemberName.describe("The new member name. Lowercase letters, digits and inner hyphens.")
|
|
21623
|
+
}),
|
|
21624
|
+
connector: true
|
|
21625
|
+
}),
|
|
21589
21626
|
send: tool({
|
|
21590
21627
|
name: "send",
|
|
21591
21628
|
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.",
|
|
@@ -21690,9 +21727,9 @@ Older messages exist. Call history with before: ${page.nextBefore}.` : "";
|
|
|
21690
21727
|
].join("\n") + more;
|
|
21691
21728
|
}
|
|
21692
21729
|
function renderPresence(presence, now) {
|
|
21693
|
-
if (presence.state === "offline") return `offline, last active ${relativeTime(presence.lastActiveAt, now)}; reads it when its
|
|
21730
|
+
if (presence.state === "offline") return `offline, last active ${relativeTime(presence.lastActiveAt, now)}; reads it when its owner is next back in that conversation`;
|
|
21694
21731
|
if (presence.tier === "pull") return "online in a web chat; reads it at its next inbox check";
|
|
21695
|
-
return
|
|
21732
|
+
return "online; told now";
|
|
21696
21733
|
}
|
|
21697
21734
|
function renderSent(result, now) {
|
|
21698
21735
|
if (!result.recipients.length) return `Sent ${result.id}. On record in the room; nobody was told.`;
|
|
@@ -21735,6 +21772,16 @@ function renderNewRoom(result) {
|
|
|
21735
21772
|
return `Created #${result.name}. Code: ${result.code}
|
|
21736
21773
|
Give the code to whoever should join. This conversation has not joined; call join with the code to do so.`;
|
|
21737
21774
|
}
|
|
21775
|
+
function renderRoomUpdated(result, rotated) {
|
|
21776
|
+
const parts = [`Updated #${result.name}.`, `Description: ${result.description || "(none)"}`];
|
|
21777
|
+
if (rotated && result.code)
|
|
21778
|
+
parts.push(`New code: ${result.code}
|
|
21779
|
+
The previous code no longer admits new members; everyone already in the room is unaffected.`);
|
|
21780
|
+
return parts.join("\n");
|
|
21781
|
+
}
|
|
21782
|
+
function renderRenamed(result) {
|
|
21783
|
+
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.`;
|
|
21784
|
+
}
|
|
21738
21785
|
function renderLoginStart(result) {
|
|
21739
21786
|
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.`;
|
|
21740
21787
|
}
|
|
@@ -21894,6 +21941,8 @@ var Link = class {
|
|
|
21894
21941
|
options;
|
|
21895
21942
|
socket = null;
|
|
21896
21943
|
timer = null;
|
|
21944
|
+
heartbeat = null;
|
|
21945
|
+
overdue = null;
|
|
21897
21946
|
attempt = 0;
|
|
21898
21947
|
stopped = false;
|
|
21899
21948
|
connected = false;
|
|
@@ -21920,8 +21969,10 @@ var Link = class {
|
|
|
21920
21969
|
this.connected = true;
|
|
21921
21970
|
this.attempt = 0;
|
|
21922
21971
|
this.reportState();
|
|
21972
|
+
this.beat(socket);
|
|
21923
21973
|
});
|
|
21924
21974
|
socket.on("message", (data) => {
|
|
21975
|
+
this.heard();
|
|
21925
21976
|
let json2;
|
|
21926
21977
|
try {
|
|
21927
21978
|
json2 = JSON.parse(String(data));
|
|
@@ -21970,10 +22021,29 @@ var Link = class {
|
|
|
21970
22021
|
}
|
|
21971
22022
|
this.dropped(socket, end);
|
|
21972
22023
|
}
|
|
22024
|
+
beat(socket) {
|
|
22025
|
+
this.heartbeat = setInterval(() => {
|
|
22026
|
+
if (this.overdue || socket.readyState !== WebSocket.OPEN) return;
|
|
22027
|
+
socket.send(LINK_PING);
|
|
22028
|
+
this.overdue = setTimeout(() => this.dropped(socket, null), this.options.pongTimeoutMs);
|
|
22029
|
+
this.overdue.unref?.();
|
|
22030
|
+
}, this.options.pingIntervalMs);
|
|
22031
|
+
this.heartbeat.unref?.();
|
|
22032
|
+
}
|
|
22033
|
+
heard() {
|
|
22034
|
+
if (this.overdue) clearTimeout(this.overdue);
|
|
22035
|
+
this.overdue = null;
|
|
22036
|
+
}
|
|
22037
|
+
quiet() {
|
|
22038
|
+
if (this.heartbeat) clearInterval(this.heartbeat);
|
|
22039
|
+
this.heartbeat = null;
|
|
22040
|
+
this.heard();
|
|
22041
|
+
}
|
|
21973
22042
|
dropped(socket, end) {
|
|
21974
22043
|
if (this.socket !== socket) return;
|
|
21975
22044
|
this.socket = null;
|
|
21976
22045
|
this.connected = false;
|
|
22046
|
+
this.quiet();
|
|
21977
22047
|
try {
|
|
21978
22048
|
socket.terminate();
|
|
21979
22049
|
} catch {
|
|
@@ -21998,6 +22068,7 @@ var Link = class {
|
|
|
21998
22068
|
stop() {
|
|
21999
22069
|
this.stopped = true;
|
|
22000
22070
|
this.connected = false;
|
|
22071
|
+
this.quiet();
|
|
22001
22072
|
if (this.timer) clearTimeout(this.timer);
|
|
22002
22073
|
const socket = this.socket;
|
|
22003
22074
|
this.socket = null;
|
|
@@ -22113,6 +22184,12 @@ ${login.error ? "" : renderLoginStart(login)}`.trim() : renderStatus({ account:
|
|
|
22113
22184
|
needLogin();
|
|
22114
22185
|
return renderNewRoom(await ops("new_room", { id: newId("r"), ...params }));
|
|
22115
22186
|
},
|
|
22187
|
+
async update_room(params) {
|
|
22188
|
+
const marker = needRoom();
|
|
22189
|
+
const result = await ops("update_room", { room: marker.room, ...params });
|
|
22190
|
+
session.remark({ roomName: result.name, ...result.code ? { code: normalizeCode(result.code) } : {} });
|
|
22191
|
+
return renderRoomUpdated(result, params.rotateCode === true);
|
|
22192
|
+
},
|
|
22116
22193
|
async join(params) {
|
|
22117
22194
|
const ref = needConversation();
|
|
22118
22195
|
needLogin();
|
|
@@ -22142,6 +22219,12 @@ ${login.error ? "" : renderLoginStart(login)}`.trim() : renderStatus({ account:
|
|
|
22142
22219
|
needRoom();
|
|
22143
22220
|
return renderMembers(await inRoom(() => ops("members", {})), Date.now());
|
|
22144
22221
|
},
|
|
22222
|
+
async rename(params) {
|
|
22223
|
+
needRoom();
|
|
22224
|
+
const result = await inRoom(() => ops("rename", { name: params.name }));
|
|
22225
|
+
session.remark({ member: result.member });
|
|
22226
|
+
return renderRenamed(result);
|
|
22227
|
+
},
|
|
22145
22228
|
async send(params) {
|
|
22146
22229
|
needRoom();
|
|
22147
22230
|
const result = await inRoom(() => ops("send", { id: newId("m"), to: params.to, body: params.body, dm: params.dm ?? false, replyTo: params.replyTo }));
|
|
@@ -22319,6 +22402,8 @@ var TIMING = {
|
|
|
22319
22402
|
wakeRetryDelaysMs: [1e3, 3e3, 9e3],
|
|
22320
22403
|
requestTimeoutMs: 15e3,
|
|
22321
22404
|
closeTimeoutMs: 2e3,
|
|
22405
|
+
pingIntervalMs: 3e4,
|
|
22406
|
+
pongTimeoutMs: 1e4,
|
|
22322
22407
|
loginPollFloorMs: 2e3
|
|
22323
22408
|
};
|
|
22324
22409
|
function createBridge(options) {
|
|
@@ -22382,7 +22467,9 @@ function createBridge(options) {
|
|
|
22382
22467
|
if (reason === "rebound" || reason === "not_in_room") forget();
|
|
22383
22468
|
},
|
|
22384
22469
|
reconnectDelaysMs: timing.reconnectDelaysMs,
|
|
22385
|
-
closeTimeoutMs: timing.closeTimeoutMs
|
|
22470
|
+
closeTimeoutMs: timing.closeTimeoutMs,
|
|
22471
|
+
pingIntervalMs: timing.pingIntervalMs,
|
|
22472
|
+
pongTimeoutMs: timing.pongTimeoutMs
|
|
22386
22473
|
});
|
|
22387
22474
|
link.start();
|
|
22388
22475
|
}
|
|
@@ -22404,6 +22491,11 @@ function createBridge(options) {
|
|
|
22404
22491
|
unread.reset();
|
|
22405
22492
|
openLink();
|
|
22406
22493
|
},
|
|
22494
|
+
remark(patch) {
|
|
22495
|
+
if (!marker || !conversation) return;
|
|
22496
|
+
marker = { ...marker, ...patch };
|
|
22497
|
+
writeMarker(conversation.host, conversation.hostConversationId, marker);
|
|
22498
|
+
},
|
|
22407
22499
|
forget,
|
|
22408
22500
|
signedIn: openLink,
|
|
22409
22501
|
signedOut: () => link?.stop(),
|
|
@@ -22435,7 +22527,15 @@ function createBridge(options) {
|
|
|
22435
22527
|
waker.evaluate();
|
|
22436
22528
|
},
|
|
22437
22529
|
inactive() {
|
|
22438
|
-
return inactive({
|
|
22530
|
+
return inactive({
|
|
22531
|
+
loggedIn: !!readCredentials(hub),
|
|
22532
|
+
bound: !!conversation,
|
|
22533
|
+
joined: !!marker,
|
|
22534
|
+
ended,
|
|
22535
|
+
connected: !!link?.connected,
|
|
22536
|
+
wakeable: options.shell.wakeable(),
|
|
22537
|
+
unwakeable: options.shell.unwakeable?.() ?? null
|
|
22538
|
+
});
|
|
22439
22539
|
},
|
|
22440
22540
|
dispose() {
|
|
22441
22541
|
disposed = true;
|