@hanzo/rooms 0.1.18 → 0.1.19

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/dist/Chat.js CHANGED
@@ -298,6 +298,8 @@ function Why({ text }) {
298
298
  * writes, which streams no words while it does.
299
299
  */
300
300
  const STALL = 300_000;
301
+ /** Characters of a streaming reasoning trace a turn shows: its tail. */
302
+ const THOUGHT = 320;
301
303
  /**
302
304
  * How long a send waits for a freshly attached file to have passages before it
303
305
  * goes without them. Long enough for a page or a short document to be read; a
@@ -1087,12 +1089,16 @@ function Thread({ placeholder = message(), initial, anonymous = false, heading,
1087
1089
  if (read.carried)
1088
1090
  return _jsx(Carried, { text: read.text, attached: read.carried.attached, reused: read.carried.reused });
1089
1091
  }
1090
- // WHO IS ANSWERING, while the answer has no words yet: the agents the
1091
- // question addresses, or the whole room when it names nobody.
1092
- if (turn.role === "assistant" && !said && chat.streaming && room.length) {
1092
+ // WHILE THE ANSWER HAS NO WORDS YET: who is answering (the agents the
1093
+ // question addresses, or the whole room when it names nobody), and the
1094
+ // model's reasoning as it streams (`reasoning` on the turn), dimmed and
1095
+ // cut to its last lines.
1096
+ const thought = turn.role === "assistant" && !said && chat.streaming ? (turn.reasoning ?? "").trim() : "";
1097
+ if (turn.role === "assistant" && !said && chat.streaming && (room.length || thought)) {
1093
1098
  const q = [...shown].reverse().find((one) => one.role === "user");
1094
- const whom = addressed(words(q?.content), room);
1095
- return (_jsxs(Text, { fontSize: "$2", color: "$soft", children: [join(whom), " ", whom.length > 1 ? "are" : "is", " answering\u2026"] }));
1099
+ const whom = room.length ? addressed(words(q?.content), room) : [];
1100
+ const doing = thought ? "thinking" : "answering";
1101
+ return (_jsxs(YStack, { gap: "$1", "data-slot": "thinking", children: [_jsx(Text, { fontSize: "$2", color: "$soft", children: whom.length ? `${join(whom)} ${whom.length > 1 ? "are" : "is"} ${doing}…` : "Thinking…" }), thought ? (_jsx(Text, { fontSize: "$2", color: "$soft", opacity: 0.72, "data-slot": "thought", children: thought.length > THOUGHT ? `…${thought.slice(-THOUGHT).replace(/^\S*\s/, "")}` : thought })) : null] }));
1096
1102
  }
1097
1103
  // A ROOM'S ANSWER IS SEVERAL PEOPLE'S. Each opens a line with their
1098
1104
  // name, as the brief asks, so each is drawn under their own face and
package/dist/lib/web.d.ts CHANGED
@@ -19,6 +19,11 @@
19
19
  * model is asked (`current`), and the search reads the best pages as well as
20
20
  * listing them, so the answer can quote a reading rather than a page's blurb.
21
21
  *
22
+ * Only a turn that needs the web is offered it: a question about now, or one
23
+ * that names a page. The gateway answers a request that offers tools whole,
24
+ * after checking its calls against their schemas, so its first word waits for
25
+ * its last; every other turn goes out without the tools and streams.
26
+ *
22
27
  * Bounded: at most ROUNDS rounds of lookups the model asks for, CALLS lookups in
23
28
  * a round, and every lookup on its own clock. The request after the last round
24
29
  * offers no tools, so the turn ends in words.
package/dist/lib/web.js CHANGED
@@ -19,6 +19,11 @@
19
19
  * model is asked (`current`), and the search reads the best pages as well as
20
20
  * listing them, so the answer can quote a reading rather than a page's blurb.
21
21
  *
22
+ * Only a turn that needs the web is offered it: a question about now, or one
23
+ * that names a page. The gateway answers a request that offers tools whole,
24
+ * after checking its calls against their schemas, so its first word waits for
25
+ * its last; every other turn goes out without the tools and streams.
26
+ *
22
27
  * Bounded: at most ROUNDS rounds of lookups the model asks for, CALLS lookups in
23
28
  * a round, and every lookup on its own clock. The request after the last round
24
29
  * offers no tools, so the turn ends in words.
@@ -374,6 +379,11 @@ export function researched(base, clock = () => new Date()) {
374
379
  const names = new Set((asked.tools ?? []).map((t) => t?.function?.name));
375
380
  if (!asked.stream || !Array.isArray(asked.messages) || !WEB.every((t) => names.has(t.function.name)))
376
381
  return base(input, init);
382
+ const q = opening(asked.messages);
383
+ if (!q && !named(told(textOf(asked.messages.at(-1)?.content)).text).length) {
384
+ const { tools: _tools, tool_choice: _choice, ...bare } = asked;
385
+ return base(input, { ...init, body: JSON.stringify(bare) });
386
+ }
377
387
  const now = clock();
378
388
  const headers = new Headers(init.headers);
379
389
  headers.delete('content-length');
@@ -392,7 +402,6 @@ export function researched(base, clock = () => new Date()) {
392
402
  };
393
403
  let messages = ruled(asked.messages, now);
394
404
  const seen = new Set(asked.messages.flatMap((m) => named(textOf(m.content))));
395
- const q = opening(messages);
396
405
  if (q) {
397
406
  const id = 'web_0';
398
407
  messages = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hanzo/rooms",
3
- "version": "0.1.18",
3
+ "version": "0.1.19",
4
4
  "description": "The workspace rooms — Home, Chat, Inbox, Contacts, Meet, Cal, Drive, Board, Work, Bots — and the frame that holds them, once, for every Hanzo surface.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",