pi-roundtable-webchat 0.9.13 → 0.11.0

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/CHANGELOG.md CHANGED
@@ -5,6 +5,14 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.11.0] - 2026-10-13
9
+
10
+ - Release in lockstep with pi-roundtable 0.11.0; no package-specific behavior changes. The core peer range moves to `>=0.11.0 <0.12.0`.
11
+
12
+ ## [0.10.0] - 2026-10-13
13
+
14
+ - Release in lockstep with pi-roundtable 0.10.0; no package-specific behavior changes. The core peer range moves to `>=0.10.0 <0.11.0`.
15
+
8
16
  ## [0.9.13] - 2026-10-13
9
17
 
10
18
  - Release in lockstep with pi-roundtable 0.9.13; no package-specific behavior changes.
package/README.md CHANGED
@@ -21,7 +21,7 @@ It needs no Discord: a host whose `roundtable.config.ts` has no `discord` key an
21
21
 
22
22
  ## Requirements
23
23
 
24
- - Bun 1.3 or later, and pi-roundtable `>=0.9.0 <0.10.0` as a peer dependency. Uploading files needs `context.attachments`, which pi-roundtable added in 0.9.2: the plugin refuses to set up on an earlier core and names the version to install.
24
+ - Bun 1.3 or later, and pi-roundtable `>=0.11.0 <0.12.0` as a peer dependency. Uploading files needs `context.attachments`, which pi-roundtable added in 0.9.2: the plugin refuses to set up on an earlier core and names the version to install.
25
25
  - An HTTP listener on the host (`http` in the configuration), behind a reverse proxy that serves it over HTTPS.
26
26
  - An OpenID Connect provider that issues access tokens for this API, with signing keys published as a JWKS.
27
27
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-roundtable-webchat",
3
- "version": "0.9.13",
3
+ "version": "0.11.0",
4
4
  "description": "A WebSocket chat adapter for pi-roundtable: private web conversations for people an OpenID Connect provider signs in, with live progress and approval cards",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -36,14 +36,14 @@
36
36
  "jose": "6.2.12"
37
37
  },
38
38
  "peerDependencies": {
39
- "pi-roundtable": ">=0.9.0 <0.10.0"
39
+ "pi-roundtable": ">=0.11.0 <0.12.0"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@biomejs/biome": "2.5.15",
43
43
  "@earendil-works/pi-ai": ">=1.0.0 <2",
44
44
  "@earendil-works/pi-coding-agent": ">=1.0.0 <2",
45
45
  "@types/bun": "1.4.2",
46
- "pi-roundtable": "0.9.13",
46
+ "pi-roundtable": "0.11.0",
47
47
  "typebox": "1.3.34",
48
48
  "typescript": "7.0.2"
49
49
  }
package/src/prompts.ts CHANGED
@@ -184,12 +184,27 @@ type ApprovalFrame = NonNullable<
184
184
  * The approval as the frame carries it: whole while its JSON is within `APPROVAL_MAX_BYTES`.
185
185
  * Over that, each string value of the input is cut to the most code points that fit, marked
186
186
  * `… [N chars]`, and `truncated` is set; an input that does not fit even then is sent as `{}`
187
- * with no files. The card's `message` text always accompanies it.
187
+ * with no files. The copy text is only informational, so it is carried after the input is
188
+ * settled and only if it fits then, never at the input's cost. The card's `message` text always
189
+ * accompanies it.
188
190
  */
189
191
  function boundedApproval(details: ApprovalDetails): ApprovalFrame {
190
192
  const size = (value: unknown) =>
191
193
  new TextEncoder().encode(JSON.stringify(value)).length;
192
194
  if (size(details) <= APPROVAL_MAX_BYTES) return details;
195
+ const { copy, ...withoutCopy } = details;
196
+ const bounded = boundedWithoutCopy(withoutCopy, size);
197
+ if (!copy) return bounded;
198
+ const candidate: ApprovalFrame = { ...bounded, copy };
199
+ return size(candidate) <= APPROVAL_MAX_BYTES ? candidate : bounded;
200
+ }
201
+
202
+ /** `boundedApproval` for details without a copy text. */
203
+ function boundedWithoutCopy(
204
+ details: Omit<ApprovalDetails, "copy">,
205
+ size: (value: unknown) => number,
206
+ ): ApprovalFrame {
207
+ if (size(details) <= APPROVAL_MAX_BYTES) return details;
193
208
  const { files: _files, ...base } = details;
194
209
  const fits = (limit: number): ApprovalFrame | undefined => {
195
210
  const candidate: ApprovalFrame = {
package/src/protocol.ts CHANGED
@@ -57,6 +57,7 @@ export type PromptFrame =
57
57
  * (absent when unreadable). A client shows this when it knows it, and `message` otherwise.
58
58
  * When the serialized details would pass `APPROVAL_MAX_BYTES`, each long string value of
59
59
  * `input` is cut to its start plus `… [N chars]` (N in code points) and `truncated` is true.
60
+ * The informational `copy` text is kept only if it still fits then, never at the cost of `input`.
60
61
  */
61
62
  approval?: ApprovalDetails & { truncated?: true };
62
63
  }